From 9cd0c118703bb4b0ae9fb90f67845e666a2e239a Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Tue, 17 Jan 2023 00:05:20 -0500 Subject: [PATCH] Anomalies (#13371) --- Content.Client/Anomaly/AnomalySystem.cs | 59 ++++ .../Anomaly/Effects/GravityAnomalySystem.cs | 8 + .../Ui/AnomalyGeneratorBoundUserInterface.cs | 54 +++ .../Anomaly/Ui/AnomalyGeneratorWindow.xaml | 48 +++ .../Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs | 80 +++++ .../Ui/AnomalyScannerBoundUserInterface.cs | 48 +++ .../Anomaly/Ui/AnomalyScannerMenu.xaml | 12 + .../Anomaly/Ui/AnomalyScannerMenu.xaml.cs | 47 +++ .../Anomaly/AnomalySystem.Generator.cs | 114 +++++++ .../Anomaly/AnomalySystem.Scanner.cs | 169 ++++++++++ .../Anomaly/AnomalySystem.Vessel.cs | 129 +++++++ Content.Server/Anomaly/AnomalySystem.cs | 127 +++++++ .../Components/AnomalousParticleComponent.cs | 23 ++ .../Components/AnomalyGeneratorComponent.cs | 44 +++ .../Components/AnomalyScannerComponent.cs | 49 +++ .../Components/AnomalyVesselComponent.cs | 40 +++ .../Effects/ElectricityAnomalySystem.cs | 61 ++++ .../Anomaly/Effects/GravityAnomalySystem.cs | 39 +++ .../Effects/PyroclasticAnomalySystem.cs | 100 ++++++ Content.Server/Beam/BeamSystem.cs | 89 +++-- .../EntitySystems/EmitterSystem.cs | 91 ++++- Content.Shared.Database/LogType.cs | 1 + .../Anomaly/Components/AnomalyComponent.cs | 268 +++++++++++++++ .../Components/AnomalyPulsingComponent.cs | 22 ++ .../AnomalySupercriticalComponent.cs | 37 ++ .../Components/ElectricityAnomalyComponent.cs | 14 + .../Components/GravityAnomalyComponent.cs | 53 +++ .../Components/PyroclasticAnomalyComponent.cs | 54 +++ .../Effects/SharedGravityAnomalySystem.cs | 65 ++++ Content.Shared/Anomaly/SharedAnomaly.cs | 97 ++++++ Content.Shared/Anomaly/SharedAnomalySystem.cs | 319 ++++++++++++++++++ .../Components/SharedEmitterComponent.cs | 7 +- Content.Shared/Verbs/VerbCategory.cs | 2 + .../Ambience/Objects/anomaly_generator.ogg | Bin 0 -> 39601 bytes .../Audio/Ambience/Objects/attributions.yml | 4 + Resources/Audio/Ambience/anomaly_drone.ogg | Bin 0 -> 75985 bytes Resources/Audio/Ambience/attributions.yml | 4 + Resources/Audio/Items/attributions.yml | 5 + Resources/Audio/Items/beep.ogg | Bin 0 -> 5488 bytes Resources/Locale/en-US/anomaly/anomaly.ftl | 30 ++ .../catalog/research/technologies.ftl | 3 + .../components/emitter-component.ftl | 3 + Resources/Locale/en-US/verbs/verb-system.ftl | 1 + .../Catalog/Fills/Lockers/science.yml | 6 + .../Catalog/Research/technologies.yml | 15 + .../Markers/Spawners/Random/anomaly.yml | 16 + .../Circuitboards/Machine/production.yml | 32 ++ .../Objects/Specific/Research/anomaly.yml | 19 ++ .../Weapons/Guns/Projectiles/projectiles.yml | 52 +++ .../Structures/Machines/anomaly_equipment.yml | 240 +++++++++++++ .../Entities/Structures/Machines/lathe.yml | 3 + .../Structures/Specific/anomalies.yml | 104 ++++++ .../Structures/Wallmounts/Signs/signs.yml | 13 +- .../Prototypes/Recipes/Lathes/devices.yml | 8 + .../Prototypes/Recipes/Lathes/electronics.yml | 16 + .../Research/anomalyscanner.rsi/icon.png | Bin 0 -> 942 bytes .../Research/anomalyscanner.rsi/meta.json | 14 + .../Anomaly/anomaly_generator.rsi/base.png | Bin 0 -> 3857 bytes .../anomaly_generator.rsi/inserting.png | Bin 0 -> 609 bytes .../Anomaly/anomaly_generator.rsi/meta.json | 47 +++ .../Anomaly/anomaly_generator.rsi/panel.png | Bin 0 -> 347 bytes .../anomaly_generator.rsi/unshaded.png | Bin 0 -> 1830 bytes .../Anomaly/anomaly_vessel.rsi/anomaly.png | Bin 0 -> 283 bytes .../Anomaly/anomaly_vessel.rsi/base.png | Bin 0 -> 615 bytes .../Anomaly/anomaly_vessel.rsi/meta.json | 23 ++ .../Anomaly/anomaly_vessel.rsi/panel.png | Bin 0 -> 228 bytes .../Anomaly/anomaly_vessel.rsi/powered.png | Bin 0 -> 133 bytes .../Machines/Anomaly/ape.rsi/base.png | Bin 0 -> 1651 bytes .../Machines/Anomaly/ape.rsi/firing.png | Bin 0 -> 306 bytes .../Machines/Anomaly/ape.rsi/locked.png | Bin 0 -> 142 bytes .../Machines/Anomaly/ape.rsi/meta.json | 35 ++ .../Machines/Anomaly/ape.rsi/panel.png | Bin 0 -> 289 bytes .../Machines/Anomaly/ape.rsi/underpowered.png | Bin 0 -> 172 bytes .../Machines/Anomaly/ape.rsi/unshaded.png | Bin 0 -> 283 bytes .../Specific/anomaly.rsi/anom1-pulse.png | Bin 0 -> 2701 bytes .../Structures/Specific/anomaly.rsi/anom1.png | Bin 0 -> 663 bytes .../Specific/anomaly.rsi/anom2-pulse.png | Bin 0 -> 2283 bytes .../Structures/Specific/anomaly.rsi/anom2.png | Bin 0 -> 379 bytes .../Specific/anomaly.rsi/anom3-pulse.png | Bin 0 -> 4167 bytes .../Structures/Specific/anomaly.rsi/anom3.png | Bin 0 -> 658 bytes .../Specific/anomaly.rsi/anom4-pulse.png | Bin 0 -> 1788 bytes .../Structures/Specific/anomaly.rsi/anom4.png | Bin 0 -> 1525 bytes .../Structures/Specific/anomaly.rsi/meta.json | 97 ++++++ .../Wallmounts/signs.rsi/anomaly2.png | Bin 0 -> 454 bytes .../Structures/Wallmounts/signs.rsi/meta.json | 3 + 85 files changed, 3109 insertions(+), 54 deletions(-) create mode 100644 Content.Client/Anomaly/AnomalySystem.cs create mode 100644 Content.Client/Anomaly/Effects/GravityAnomalySystem.cs create mode 100644 Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs create mode 100644 Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml create mode 100644 Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs create mode 100644 Content.Client/Anomaly/Ui/AnomalyScannerBoundUserInterface.cs create mode 100644 Content.Client/Anomaly/Ui/AnomalyScannerMenu.xaml create mode 100644 Content.Client/Anomaly/Ui/AnomalyScannerMenu.xaml.cs create mode 100644 Content.Server/Anomaly/AnomalySystem.Generator.cs create mode 100644 Content.Server/Anomaly/AnomalySystem.Scanner.cs create mode 100644 Content.Server/Anomaly/AnomalySystem.Vessel.cs create mode 100644 Content.Server/Anomaly/AnomalySystem.cs create mode 100644 Content.Server/Anomaly/Components/AnomalousParticleComponent.cs create mode 100644 Content.Server/Anomaly/Components/AnomalyGeneratorComponent.cs create mode 100644 Content.Server/Anomaly/Components/AnomalyScannerComponent.cs create mode 100644 Content.Server/Anomaly/Components/AnomalyVesselComponent.cs create mode 100644 Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs create mode 100644 Content.Server/Anomaly/Effects/GravityAnomalySystem.cs create mode 100644 Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs create mode 100644 Content.Shared/Anomaly/Components/AnomalyComponent.cs create mode 100644 Content.Shared/Anomaly/Components/AnomalyPulsingComponent.cs create mode 100644 Content.Shared/Anomaly/Components/AnomalySupercriticalComponent.cs create mode 100644 Content.Shared/Anomaly/Effects/Components/ElectricityAnomalyComponent.cs create mode 100644 Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs create mode 100644 Content.Shared/Anomaly/Effects/Components/PyroclasticAnomalyComponent.cs create mode 100644 Content.Shared/Anomaly/Effects/SharedGravityAnomalySystem.cs create mode 100644 Content.Shared/Anomaly/SharedAnomaly.cs create mode 100644 Content.Shared/Anomaly/SharedAnomalySystem.cs create mode 100644 Resources/Audio/Ambience/Objects/anomaly_generator.ogg create mode 100644 Resources/Audio/Ambience/Objects/attributions.yml create mode 100644 Resources/Audio/Ambience/anomaly_drone.ogg create mode 100644 Resources/Audio/Ambience/attributions.yml create mode 100644 Resources/Audio/Items/beep.ogg create mode 100644 Resources/Locale/en-US/anomaly/anomaly.ftl create mode 100644 Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml create mode 100644 Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml create mode 100644 Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml create mode 100644 Resources/Prototypes/Entities/Structures/Specific/anomalies.yml create mode 100644 Resources/Textures/Objects/Specific/Research/anomalyscanner.rsi/icon.png create mode 100644 Resources/Textures/Objects/Specific/Research/anomalyscanner.rsi/meta.json create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/base.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/inserting.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/meta.json create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/panel.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/unshaded.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/anomaly.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/base.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/meta.json create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/panel.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/powered.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/ape.rsi/base.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/ape.rsi/firing.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/ape.rsi/locked.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/ape.rsi/meta.json create mode 100644 Resources/Textures/Structures/Machines/Anomaly/ape.rsi/panel.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/ape.rsi/underpowered.png create mode 100644 Resources/Textures/Structures/Machines/Anomaly/ape.rsi/unshaded.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/anom1-pulse.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/anom1.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/anom2-pulse.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/anom2.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/anom3-pulse.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/anom3.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/anom4-pulse.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/anom4.png create mode 100644 Resources/Textures/Structures/Specific/anomaly.rsi/meta.json create mode 100644 Resources/Textures/Structures/Wallmounts/signs.rsi/anomaly2.png diff --git a/Content.Client/Anomaly/AnomalySystem.cs b/Content.Client/Anomaly/AnomalySystem.cs new file mode 100644 index 0000000000..3f42a3e5f7 --- /dev/null +++ b/Content.Client/Anomaly/AnomalySystem.cs @@ -0,0 +1,59 @@ +using Content.Shared.Anomaly; +using Content.Shared.Anomaly.Components; +using Robust.Client.GameObjects; +using Robust.Shared.Timing; + +namespace Content.Client.Anomaly; + +public sealed class AnomalySystem : SharedAnomalySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAppearanceChanged); + } + + private void OnAppearanceChanged(EntityUid uid, AnomalyComponent component, ref AppearanceChangeEvent args) + { + if (args.Sprite is not { } sprite) + return; + + if (!Appearance.TryGetData(uid, AnomalyVisuals.IsPulsing, out bool pulsing, args.Component)) + pulsing = false; + + if (Appearance.TryGetData(uid, AnomalyVisuals.IsPulsing, out bool super, args.Component) && super) + pulsing = super; + + if (HasComp(uid)) + pulsing = true; + + if (!sprite.LayerMapTryGet(AnomalyVisualLayers.Base, out var layer) || + !sprite.LayerMapTryGet(AnomalyVisualLayers.Animated, out var animatedLayer)) + return; + + sprite.LayerSetVisible(layer, !pulsing); + sprite.LayerSetVisible(animatedLayer, pulsing); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var (super, sprite) in EntityQuery()) + { + var completion = 1f - (float) ((super.EndTime - _timing.CurTime) / super.SupercriticalDuration); + var scale = completion * (super.MaxScaleAmount - 1f) + 1f; + sprite.Scale = new Vector2(scale, scale); + + var transparency = (byte) (65 * (1f - completion) + 190); + if (transparency < sprite.Color.AByte) + { + sprite.Color = sprite.Color.WithAlpha(transparency); + } + } + } +} diff --git a/Content.Client/Anomaly/Effects/GravityAnomalySystem.cs b/Content.Client/Anomaly/Effects/GravityAnomalySystem.cs new file mode 100644 index 0000000000..444e57b3f4 --- /dev/null +++ b/Content.Client/Anomaly/Effects/GravityAnomalySystem.cs @@ -0,0 +1,8 @@ +using Content.Shared.Anomaly.Effects; + +namespace Content.Client.Anomaly.Effects; + +public sealed class GravityAnomalySystem : SharedGravityAnomalySystem +{ + // this is not the system you are looking for +} diff --git a/Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs b/Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs new file mode 100644 index 0000000000..9d8923a2e1 --- /dev/null +++ b/Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs @@ -0,0 +1,54 @@ +using Content.Shared.Anomaly; +using Content.Shared.Gravity; +using JetBrains.Annotations; +using Robust.Client.GameObjects; + +namespace Content.Client. Anomaly.Ui; + +[UsedImplicitly] +public sealed class AnomalyGeneratorBoundUserInterface : BoundUserInterface +{ + private AnomalyGeneratorWindow? _window; + + public AnomalyGeneratorBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base (owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _window = new (Owner.Owner); + + _window.OpenCentered(); + _window.OnClose += Close; + + _window.OnGenerateButtonPressed += () => + { + SendMessage(new AnomalyGeneratorGenerateButtonPressedEvent()); + }; + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not AnomalyGeneratorUserInterfaceState msg) + return; + _window?.UpdateState(msg); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + + _window?.Dispose(); + } + + public void SetPowerSwitch(bool on) + { + SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(on)); + } +} + diff --git a/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml b/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml new file mode 100644 index 0000000000..c818d263f6 --- /dev/null +++ b/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs b/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs new file mode 100644 index 0000000000..cf46f0f8fd --- /dev/null +++ b/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs @@ -0,0 +1,80 @@ +using Content.Client.Message; +using Content.Shared.Anomaly; +using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Timing; +using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow; + +namespace Content.Client.Anomaly.Ui; + +[GenerateTypedNameReferences] +public sealed partial class AnomalyGeneratorWindow : FancyWindow +{ + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + private TimeSpan _cooldownEnd = TimeSpan.Zero; + private bool _hasEnoughFuel; + + public Action? OnGenerateButtonPressed; + + public AnomalyGeneratorWindow(EntityUid gen) + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + EntityView.Sprite = _entityManager.GetComponent(gen); + + GenerateButton.OnPressed += _ => OnGenerateButtonPressed?.Invoke(); + } + + public void UpdateState(AnomalyGeneratorUserInterfaceState state) + { + _cooldownEnd = state.CooldownEndTime; + _hasEnoughFuel = state.FuelCost <= state.FuelAmount; + + var fuelCompletion = Math.Clamp((float) state.FuelAmount / state.FuelCost, 0f, 1f); + + FuelBar.Value = fuelCompletion; + FuelText.Text = $"{fuelCompletion:P}"; + + UpdateTimer(); + UpdateReady(); // yes this can trigger twice. no i don't care + } + + public void UpdateTimer() + { + if (_timing.CurTime > _cooldownEnd) + { + CooldownLabel.SetMarkup(Loc.GetString("anomaly-generator-no-cooldown")); + } + else + { + var timeLeft = _cooldownEnd - _timing.CurTime; + var timeString = $"{timeLeft.Minutes:0}:{timeLeft.Seconds:00}"; + CooldownLabel.SetMarkup(Loc.GetString("anomaly-generator-cooldown", ("time", timeString))); + UpdateReady(); + } + } + + public void UpdateReady() + { + var ready = _hasEnoughFuel && _timing.CurTime > _cooldownEnd; + + var msg = ready + ? Loc.GetString("anomaly-generator-yes-fire") + : Loc.GetString("anomaly-generator-no-fire"); + ReadyLabel.SetMarkup(msg); + + GenerateButton.Disabled = !ready; + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + UpdateTimer(); + } +} + diff --git a/Content.Client/Anomaly/Ui/AnomalyScannerBoundUserInterface.cs b/Content.Client/Anomaly/Ui/AnomalyScannerBoundUserInterface.cs new file mode 100644 index 0000000000..64f66818eb --- /dev/null +++ b/Content.Client/Anomaly/Ui/AnomalyScannerBoundUserInterface.cs @@ -0,0 +1,48 @@ +using Content.Shared.Anomaly; +using JetBrains.Annotations; +using Robust.Client.GameObjects; + +namespace Content.Client.Anomaly.Ui; + +[UsedImplicitly] +public sealed class AnomalyScannerBoundUserInterface : BoundUserInterface +{ + private AnomalyScannerMenu? _menu; + + public AnomalyScannerBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey) + { + + } + + protected override void Open() + { + base.Open(); + + _menu = new AnomalyScannerMenu(); + _menu.OpenCentered(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not AnomalyScannerUserInterfaceState msg) + return; + + if (_menu == null) + return; + + _menu.LastMessage = msg.Message; + _menu.NextPulseTime = msg.NextPulseTime; + _menu.UpdateMenu(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Dispose(); + } +} + diff --git a/Content.Client/Anomaly/Ui/AnomalyScannerMenu.xaml b/Content.Client/Anomaly/Ui/AnomalyScannerMenu.xaml new file mode 100644 index 0000000000..ac4adf7e0e --- /dev/null +++ b/Content.Client/Anomaly/Ui/AnomalyScannerMenu.xaml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/Content.Client/Anomaly/Ui/AnomalyScannerMenu.xaml.cs b/Content.Client/Anomaly/Ui/AnomalyScannerMenu.xaml.cs new file mode 100644 index 0000000000..14726952d1 --- /dev/null +++ b/Content.Client/Anomaly/Ui/AnomalyScannerMenu.xaml.cs @@ -0,0 +1,47 @@ +using Content.Client.Message; +using Content.Client.UserInterface.Controls; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Timing; +using Robust.Shared.Utility; + +namespace Content.Client.Anomaly.Ui; + +[GenerateTypedNameReferences] +public sealed partial class AnomalyScannerMenu : FancyWindow +{ + [Dependency] private readonly IGameTiming _timing = default!; + + public FormattedMessage LastMessage = new(); + public TimeSpan? NextPulseTime; + + public AnomalyScannerMenu() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + } + + public void UpdateMenu() + { + var msg = new FormattedMessage(LastMessage); + + if (NextPulseTime != null) + { + msg.PushNewline(); + msg.PushNewline(); + var time = NextPulseTime.Value - _timing.CurTime; + var timestring = $"{time.Minutes:00}:{time.Seconds:00}"; + msg.AddMarkup(Loc.GetString("anomaly-scanner-pulse-timer", ("time", timestring))); + } + + TextDisplay.SetMarkup(msg.ToMarkup()); + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + if (NextPulseTime != null) + UpdateMenu(); + } +} diff --git a/Content.Server/Anomaly/AnomalySystem.Generator.cs b/Content.Server/Anomaly/AnomalySystem.Generator.cs new file mode 100644 index 0000000000..cd37280270 --- /dev/null +++ b/Content.Server/Anomaly/AnomalySystem.Generator.cs @@ -0,0 +1,114 @@ +using Content.Server.Anomaly.Components; +using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; +using Content.Shared.Anomaly; +using Content.Shared.Materials; +using Robust.Shared.Map.Components; + +namespace Content.Server.Anomaly; + +/// +/// This handles anomalous vessel as well as +/// the calculations for how many points they +/// should produce. +/// +public sealed partial class AnomalySystem +{ + /// + /// A multiplier applied to the grid bounds + /// to make the likelihood of it spawning outside + /// of the main station less likely. + /// + /// tl;dr anomalies only generate on the inner __% of the station. + /// + public const float GridBoundsMultiplier = 0.6f; + + private void InitializeGenerator() + { + SubscribeLocalEvent(OnGeneratorBUIOpened); + SubscribeLocalEvent(OnGeneratorMaterialAmountChanged); + SubscribeLocalEvent(OnGenerateButtonPressed); + SubscribeLocalEvent(OnGeneratorPowerChanged); + } + + private void OnGeneratorPowerChanged(EntityUid uid, AnomalyGeneratorComponent component, ref PowerChangedEvent args) + { + _ambient.SetAmbience(uid, args.Powered); + } + + private void OnGeneratorBUIOpened(EntityUid uid, AnomalyGeneratorComponent component, BoundUIOpenedEvent args) + { + UpdateGeneratorUi(uid, component); + } + + private void OnGeneratorMaterialAmountChanged(EntityUid uid, AnomalyGeneratorComponent component, ref MaterialAmountChangedEvent args) + { + UpdateGeneratorUi(uid, component); + } + + private void OnGenerateButtonPressed(EntityUid uid, AnomalyGeneratorComponent component, AnomalyGeneratorGenerateButtonPressedEvent args) + { + TryGeneratorCreateAnomaly(uid, component); + } + + public void UpdateGeneratorUi(EntityUid uid, AnomalyGeneratorComponent component) + { + var materialAmount = _material.GetMaterialAmount(uid, component.RequiredMaterial); + + var state = new AnomalyGeneratorUserInterfaceState(component.CooldownEndTime, materialAmount, component.MaterialPerAnomaly); + _ui.TrySetUiState(uid, AnomalyGeneratorUiKey.Key, state); + } + + public void TryGeneratorCreateAnomaly(EntityUid uid, AnomalyGeneratorComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + if (!this.IsPowered(uid, EntityManager)) + return; + + if (Timing.CurTime < component.CooldownEndTime) + return; + + var grid = Transform(uid).GridUid; + if (grid == null) + return; + + if (!_material.TryChangeMaterialAmount(uid, component.RequiredMaterial, -component.MaterialPerAnomaly)) + return; + + SpawnOnRandomGridLocation(grid.Value, component.SpawnerPrototype); + component.CooldownEndTime = Timing.CurTime + component.CooldownLength; + UpdateGeneratorUi(uid, component); + } + + private void SpawnOnRandomGridLocation(EntityUid grid, string toSpawn) + { + if (!TryComp(grid, out var gridComp)) + return; + + var xform = Transform(grid); + + var targetCoords = xform.Coordinates; + var (gridPos, _, gridMatrix) = _transform.GetWorldPositionRotationMatrix(xform); + var gridBounds = gridMatrix.TransformBox(gridComp.LocalAABB); + + for (var i = 0; i < 25; i++) + { + var randomX = Random.Next((int) (gridBounds.Left * GridBoundsMultiplier), (int) (gridBounds.Right * GridBoundsMultiplier)); + var randomY = Random.Next((int) (gridBounds.Bottom * GridBoundsMultiplier), (int) (gridBounds.Top * GridBoundsMultiplier)); + + var tile = new Vector2i(randomX - (int) gridPos.X, randomY - (int) gridPos.Y); + if (_atmosphere.IsTileSpace(grid, Transform(grid).MapUid, tile, + mapGridComp: gridComp) || _atmosphere.IsTileAirBlocked(grid, tile, mapGridComp: gridComp)) + { + continue; + } + + targetCoords = gridComp.GridTileToLocal(tile); + break; + } + + Spawn(toSpawn, targetCoords); + } +} diff --git a/Content.Server/Anomaly/AnomalySystem.Scanner.cs b/Content.Server/Anomaly/AnomalySystem.Scanner.cs new file mode 100644 index 0000000000..8c70810682 --- /dev/null +++ b/Content.Server/Anomaly/AnomalySystem.Scanner.cs @@ -0,0 +1,169 @@ +using Content.Server.Anomaly.Components; +using Content.Server.DoAfter; +using Content.Shared.Anomaly; +using Content.Shared.Anomaly.Components; +using Content.Shared.Interaction; +using Robust.Server.GameObjects; +using Robust.Shared.Utility; + +namespace Content.Server.Anomaly; + +/// +/// This handles the anomaly scanner and it's UI updates. +/// +public sealed partial class AnomalySystem +{ + private void InitializeScanner() + { + SubscribeLocalEvent(OnScannerUiOpened); + SubscribeLocalEvent(OnScannerAfterInteract); + SubscribeLocalEvent(OnScannerDoAfterFinished); + SubscribeLocalEvent(OnScannerDoAfterCancelled); + + SubscribeLocalEvent(OnScannerAnomalyShutdown); + SubscribeLocalEvent(OnScannerAnomalySeverityChanged); + SubscribeLocalEvent(OnScannerAnomalyStabilityChanged); + SubscribeLocalEvent(OnScannerAnomalyHealthChanged); + } + + private void OnScannerAnomalyShutdown(ref AnomalyShutdownEvent args) + { + foreach (var component in EntityQuery()) + { + if (component.ScannedAnomaly != args.Anomaly) + continue; + _ui.TryCloseAll(component.Owner, AnomalyScannerUiKey.Key); + } + } + + private void OnScannerAnomalySeverityChanged(ref AnomalySeverityChangedEvent args) + { + foreach (var component in EntityQuery()) + { + if (component.ScannedAnomaly != args.Anomaly) + continue; + UpdateScannerUi(component.Owner, component); + } + } + + private void OnScannerAnomalyStabilityChanged(ref AnomalyStabilityChangedEvent args) + { + foreach (var component in EntityQuery()) + { + if (component.ScannedAnomaly != args.Anomaly) + continue; + UpdateScannerUi(component.Owner, component); + } + } + + private void OnScannerAnomalyHealthChanged(ref AnomalyHealthChangedEvent args) + { + foreach (var component in EntityQuery()) + { + if (component.ScannedAnomaly != args.Anomaly) + continue; + UpdateScannerUi(component.Owner, component); + } + } + + private void OnScannerUiOpened(EntityUid uid, AnomalyScannerComponent component, BoundUIOpenedEvent args) + { + UpdateScannerUi(uid, component); + } + + private void OnScannerAfterInteract(EntityUid uid, AnomalyScannerComponent component, AfterInteractEvent args) + { + if (component.TokenSource != null) + return; + + if (args.Target is not { } target) + return; + if (!HasComp(target)) + return; + + component.TokenSource = new(); + _doAfter.DoAfter(new DoAfterEventArgs(args.User, component.ScanDoAfterDuration, component.TokenSource.Token, target, uid) + { + DistanceThreshold = 2f, + UsedFinishedEvent = new AnomalyScanFinishedEvent(target, args.User), + UsedCancelledEvent = new AnomalyScanCancelledEvent() + }); + } + + private void OnScannerDoAfterFinished(EntityUid uid, AnomalyScannerComponent component, AnomalyScanFinishedEvent args) + { + component.TokenSource = null; + + Audio.PlayPvs(component.CompleteSound, uid); + _popup.PopupEntity(Loc.GetString("anomaly-scanner-component-scan-complete"), uid); + UpdateScannerWithNewAnomaly(uid, args.Anomaly, component); + + if (TryComp(args.User, out var actor)) + _ui.TryOpen(uid, AnomalyScannerUiKey.Key, actor.PlayerSession); + } + + private void OnScannerDoAfterCancelled(EntityUid uid, AnomalyScannerComponent component, AnomalyScanCancelledEvent args) + { + component.TokenSource = null; + } + + public void UpdateScannerUi(EntityUid uid, AnomalyScannerComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + TimeSpan? nextPulse = null; + if (TryComp(component.ScannedAnomaly, out var anomalyComponent)) + nextPulse = anomalyComponent.NextPulseTime; + + var state = new AnomalyScannerUserInterfaceState(GetScannerMessage(component), nextPulse); + _ui.TrySetUiState(uid, AnomalyScannerUiKey.Key, state); + } + + public void UpdateScannerWithNewAnomaly(EntityUid scanner, EntityUid anomaly, AnomalyScannerComponent? scannerComp = null, AnomalyComponent? anomalyComp = null) + { + if (!Resolve(scanner, ref scannerComp) || !Resolve(anomaly, ref anomalyComp)) + return; + + scannerComp.ScannedAnomaly = anomaly; + UpdateScannerUi(scanner, scannerComp); + } + + public FormattedMessage GetScannerMessage(AnomalyScannerComponent component) + { + var msg = new FormattedMessage(); + if (component.ScannedAnomaly is not { } anomaly || !TryComp(anomaly, out var anomalyComp)) + { + msg.AddMarkup(Loc.GetString("anomaly-scanner-no-anomaly")); + return msg; + } + + msg.AddMarkup(Loc.GetString("anomaly-scanner-severity-percentage", ("percent", anomalyComp.Severity.ToString("P")))); + msg.PushNewline(); + string stateLoc; + if (anomalyComp.Stability < anomalyComp.DecayThreshold) + stateLoc = Loc.GetString("anomaly-scanner-stability-low"); + else if (anomalyComp.Stability > anomalyComp.GrowthThreshold) + stateLoc = Loc.GetString("anomaly-scanner-stability-high"); + else + stateLoc = Loc.GetString("anomaly-scanner-stability-medium"); + msg.AddMarkup(stateLoc); + msg.PushNewline(); + + var points = GetAnomalyPointValue(anomaly, anomalyComp) / 10 * 10; //round to tens place + msg.AddMarkup(Loc.GetString("anomaly-scanner-point-output", ("point", points))); + msg.PushNewline(); + msg.PushNewline(); + + msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-readout")); + msg.PushNewline(); + msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-danger", ("type", GetParticleLocale(anomalyComp.SeverityParticleType)))); + msg.PushNewline(); + msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-unstable", ("type", GetParticleLocale(anomalyComp.DestabilizingParticleType)))); + msg.PushNewline(); + msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-containment", ("type", GetParticleLocale(anomalyComp.WeakeningParticleType)))); + + //The timer at the end here is actually added in the ui itself. + return msg; + } +} diff --git a/Content.Server/Anomaly/AnomalySystem.Vessel.cs b/Content.Server/Anomaly/AnomalySystem.Vessel.cs new file mode 100644 index 0000000000..dabd2528fb --- /dev/null +++ b/Content.Server/Anomaly/AnomalySystem.Vessel.cs @@ -0,0 +1,129 @@ +using Content.Server.Anomaly.Components; +using Content.Server.Construction; +using Content.Server.Power.EntitySystems; +using Content.Shared.Anomaly; +using Content.Shared.Anomaly.Components; +using Content.Shared.Examine; +using Content.Shared.Interaction; +using Content.Shared.Research.Components; + +namespace Content.Server.Anomaly; + +/// +/// This handles anomalous vessel as well as +/// the calculations for how many points they +/// should produce. +/// +public sealed partial class AnomalySystem +{ + private void InitializeVessel() + { + SubscribeLocalEvent(OnVesselShutdown); + SubscribeLocalEvent(OnVesselMapInit); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnVesselInteractUsing); + SubscribeLocalEvent(OnExamined); + SubscribeLocalEvent(OnVesselGetPointsPerSecond); + SubscribeLocalEvent(OnVesselAnomalyShutdown); + } + + private void OnExamined(EntityUid uid, AnomalyVesselComponent component, ExaminedEvent args) + { + if (!args.IsInDetailsRange) + return; + + args.PushText(component.Anomaly == null + ? Loc.GetString("anomaly-vessel-component-not-assigned") + : Loc.GetString("anomaly-vessel-component-assigned")); + } + + private void OnVesselShutdown(EntityUid uid, AnomalyVesselComponent component, ComponentShutdown args) + { + if (component.Anomaly is not { } anomaly) + return; + + if (!TryComp(anomaly, out var anomalyComp)) + return; + + anomalyComp.ConnectedVessel = null; + } + + private void OnVesselMapInit(EntityUid uid, AnomalyVesselComponent component, MapInitEvent args) + { + UpdateVesselAppearance(uid, component); + } + + private void OnRefreshParts(EntityUid uid, AnomalyVesselComponent component, RefreshPartsEvent args) + { + var modifierRating = args.PartRatings[component.MachinePartPointModifier] - 1; + component.PointMultiplier = MathF.Pow(component.PartRatingPointModifier, modifierRating); + } + + private void OnVesselInteractUsing(EntityUid uid, AnomalyVesselComponent component, InteractUsingEvent args) + { + if (component.Anomaly != null || + !TryComp(args.Used, out var scanner) || + scanner.ScannedAnomaly is not {} anomaly) + { + return; + } + + if (!TryComp(anomaly, out var anomalyComponent) || anomalyComponent.ConnectedVessel != null) + return; + + component.Anomaly = scanner.ScannedAnomaly; + anomalyComponent.ConnectedVessel = uid; + UpdateVesselAppearance(uid, component); + _popup.PopupEntity(Loc.GetString("anomaly-vessel-component-anomaly-assigned"), uid); + } + + private void OnVesselGetPointsPerSecond(EntityUid uid, AnomalyVesselComponent component, ref ResearchServerGetPointsPerSecondEvent args) + { + if (!this.IsPowered(uid, EntityManager) || component.Anomaly is not {} anomaly) + { + args.Points = 0; + return; + } + + args.Points += (int) (GetAnomalyPointValue(anomaly) * component.PointMultiplier); + } + + private void OnVesselAnomalyShutdown(ref AnomalyShutdownEvent args) + { + foreach (var component in EntityQuery()) + { + var ent = component.Owner; + + if (args.Anomaly != component.Anomaly) + continue; + + component.Anomaly = null; + UpdateVesselAppearance(ent, component); + + if (!args.Supercritical) + continue; + _explosion.TriggerExplosive(ent); + } + } + + /// + /// Updates the appearance of an anomaly vessel + /// based on whether or not it has an anomaly + /// + /// + /// + public void UpdateVesselAppearance(EntityUid uid, AnomalyVesselComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + var on = component.Anomaly != null; + + Appearance.SetData(uid, AnomalyVesselVisuals.HasAnomaly, on); + if (TryComp(uid, out var pointLightComponent)) + { + pointLightComponent.Enabled = on; + } + _ambient.SetAmbience(uid, on); + } +} diff --git a/Content.Server/Anomaly/AnomalySystem.cs b/Content.Server/Anomaly/AnomalySystem.cs new file mode 100644 index 0000000000..ed31ab7510 --- /dev/null +++ b/Content.Server/Anomaly/AnomalySystem.cs @@ -0,0 +1,127 @@ +using Content.Server.Anomaly.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Audio; +using Content.Server.DoAfter; +using Content.Server.Explosion.EntitySystems; +using Content.Server.Materials; +using Content.Server.Popups; +using Content.Shared.Anomaly; +using Content.Shared.Anomaly.Components; +using Robust.Server.GameObjects; +using Robust.Shared.Physics.Events; +using Robust.Shared.Random; +namespace Content.Server.Anomaly; + +/// +/// This handles logic and interactions relating to +/// +public sealed partial class AnomalySystem : SharedAnomalySystem +{ + [Dependency] private readonly AmbientSoundSystem _ambient = default!; + [Dependency] private readonly AtmosphereSystem _atmosphere = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + [Dependency] private readonly ExplosionSystem _explosion = default!; + [Dependency] private readonly MaterialStorageSystem _material = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly UserInterfaceSystem _ui = default!; + + public const float MinParticleVariation = 0.8f; + public const float MaxParticleVariation = 1.2f; + + /// + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnStartCollide); + + InitializeGenerator(); + InitializeScanner(); + InitializeVessel(); + } + + private void OnMapInit(EntityUid uid, AnomalyComponent component, MapInitEvent args) + { + component.NextPulseTime = Timing.CurTime + GetPulseLength(component) * 3; // longer the first time + ChangeAnomalyStability(uid, Random.NextFloat(component.InitialStabilityRange.Item1 , component.InitialStabilityRange.Item2), component); + ChangeAnomalySeverity(uid, Random.NextFloat(component.InitialSeverityRange.Item1, component.InitialSeverityRange.Item2), component); + + var particles = new List + { AnomalousParticleType.Delta, AnomalousParticleType.Epsilon, AnomalousParticleType.Zeta }; + component.SeverityParticleType = Random.PickAndTake(particles); + component.DestabilizingParticleType = Random.PickAndTake(particles); + component.WeakeningParticleType = Random.PickAndTake(particles); + } + + private void OnShutdown(EntityUid uid, AnomalyComponent component, ComponentShutdown args) + { + EndAnomaly(uid, component); + } + + private void OnStartCollide(EntityUid uid, AnomalyComponent component, ref StartCollideEvent args) + { + if (!TryComp(args.OtherFixture.Body.Owner, out var particleComponent)) + return; + + if (args.OtherFixture.ID != particleComponent.FixtureId) + return; + + // small function to randomize because it's easier to read like this + float VaryValue(float v) => v * Random.NextFloat(MinParticleVariation, MaxParticleVariation); + + if (particleComponent.ParticleType == component.DestabilizingParticleType) + { + ChangeAnomalyStability(uid, VaryValue(component.StabilityPerDestabilizingHit), component); + } + else if (particleComponent.ParticleType == component.SeverityParticleType) + { + ChangeAnomalySeverity(uid, VaryValue(component.SeverityPerSeverityHit), component); + } + else if (particleComponent.ParticleType == component.WeakeningParticleType) + { + ChangeAnomalyHealth(uid, VaryValue(component.HealthPerWeakeningeHit), component); + ChangeAnomalyStability(uid, VaryValue(component.StabilityPerWeakeningeHit), component); + } + } + + /// + /// Gets the amount of research points generated per second for an anomaly. + /// + /// + /// + /// The amount of points + public int GetAnomalyPointValue(EntityUid anomaly, AnomalyComponent? component = null) + { + if (!Resolve(anomaly, ref component, false)) + return 0; + + var multiplier = 1f; + if (component.Stability > component.GrowthThreshold) + multiplier = 1.25f; //more points for unstable + else if (component.Stability < component.DecayThreshold) + multiplier = 0.75f; //less points if it's dying + + //penalty of up to 50% based on health + multiplier *= MathF.Pow(1.5f, component.Health) - 0.5f; + + return (int) ((component.MaxPointsPerSecond - component.MinPointsPerSecond) * component.Severity * multiplier); + } + + /// + /// Gets the localized name of a particle. + /// + /// + /// + public string GetParticleLocale(AnomalousParticleType type) + { + return type switch + { + AnomalousParticleType.Delta => Loc.GetString("anomaly-particles-delta"), + AnomalousParticleType.Epsilon => Loc.GetString("anomaly-particles-epsilon"), + AnomalousParticleType.Zeta => Loc.GetString("anomaly-particles-zeta"), + _ => throw new ArgumentOutOfRangeException() + }; + } +} diff --git a/Content.Server/Anomaly/Components/AnomalousParticleComponent.cs b/Content.Server/Anomaly/Components/AnomalousParticleComponent.cs new file mode 100644 index 0000000000..195fe5a941 --- /dev/null +++ b/Content.Server/Anomaly/Components/AnomalousParticleComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.Anomaly; + +namespace Content.Server.Anomaly.Components; + +/// +/// This is used for projectiles which affect anomalies through colliding with them. +/// +[RegisterComponent] +public sealed class AnomalousParticleComponent : Component +{ + /// + /// The type of particle that the projectile + /// imbues onto the anomaly on contact. + /// + [DataField("particleType", required: true)] + public AnomalousParticleType ParticleType; + + /// + /// The fixture that's checked on collision. + /// + [DataField("fixtureId")] + public string FixtureId = "projectile"; +} diff --git a/Content.Server/Anomaly/Components/AnomalyGeneratorComponent.cs b/Content.Server/Anomaly/Components/AnomalyGeneratorComponent.cs new file mode 100644 index 0000000000..4c9fc39442 --- /dev/null +++ b/Content.Server/Anomaly/Components/AnomalyGeneratorComponent.cs @@ -0,0 +1,44 @@ +using Content.Shared.Materials; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Anomaly.Components; + +/// +/// This is used for a machine that is able to generate +/// anomalies randomly on the station. +/// +[RegisterComponent] +public sealed class AnomalyGeneratorComponent : Component +{ + /// + /// The time at which the cooldown for generating another anomaly will be over + /// + [DataField("cooldownEndTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan CooldownEndTime = TimeSpan.Zero; + + /// + /// The cooldown between generating anomalies. + /// + [DataField("cooldownLength"), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan CooldownLength = TimeSpan.FromMinutes(5); + + /// + /// The material needed to generate an anomaly + /// + [DataField("requiredMaterial", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + public string RequiredMaterial = "Plasma"; + + /// + /// The amount of material needed to generate a single anomaly + /// + [DataField("materialPerAnomaly"), ViewVariables(VVAccess.ReadWrite)] + public int MaterialPerAnomaly = 1500; // a bit less than a stack of plasma + + /// + /// The random anomaly spawner entity + /// + [DataField("spawnerPrototype", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + public string SpawnerPrototype = "RandomAnomalySpawner"; +} diff --git a/Content.Server/Anomaly/Components/AnomalyScannerComponent.cs b/Content.Server/Anomaly/Components/AnomalyScannerComponent.cs new file mode 100644 index 0000000000..6fd8c1787d --- /dev/null +++ b/Content.Server/Anomaly/Components/AnomalyScannerComponent.cs @@ -0,0 +1,49 @@ +using System.Threading; +using Robust.Shared.Audio; + +namespace Content.Server.Anomaly.Components; + +/// +/// This is used for scanning anomalies and +/// displaying information about them in the ui +/// +[RegisterComponent] +public sealed class AnomalyScannerComponent : Component +{ + /// + /// The anomaly that was last scanned by this scanner. + /// + [ViewVariables] + public EntityUid? ScannedAnomaly; + + /// + /// How long the scan takes + /// + [DataField("scanDoAfterDuration")] + public float ScanDoAfterDuration = 5; + + public CancellationTokenSource? TokenSource; + + /// + /// The sound plays when the scan finished + /// + [DataField("completeSound")] + public SoundSpecifier? CompleteSound = new SoundPathSpecifier("/Audio/Items/beep.ogg"); +} + +public sealed class AnomalyScanFinishedEvent : EntityEventArgs +{ + public EntityUid Anomaly; + + public EntityUid User; + + public AnomalyScanFinishedEvent(EntityUid anomaly, EntityUid user) + { + Anomaly = anomaly; + User = user; + } +} + +public sealed class AnomalyScanCancelledEvent : EntityEventArgs +{ +} diff --git a/Content.Server/Anomaly/Components/AnomalyVesselComponent.cs b/Content.Server/Anomaly/Components/AnomalyVesselComponent.cs new file mode 100644 index 0000000000..c833cf636b --- /dev/null +++ b/Content.Server/Anomaly/Components/AnomalyVesselComponent.cs @@ -0,0 +1,40 @@ +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Anomaly.Components; + +/// +/// Anomaly Vessels can have an anomaly "stored" in them +/// by interacting on them with an anomaly scanner. Then, +/// they generate points for the selected server based on +/// the anomaly's stability and severity. +/// +[RegisterComponent] +public sealed class AnomalyVesselComponent : Component +{ + /// + /// The anomaly that the vessel is storing. + /// Can be null. + /// + [ViewVariables] + public EntityUid? Anomaly; + + /// + /// A multiplier applied to the amount of points generated. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float PointMultiplier = 1; + + /// + /// The machine part that affects the point multiplier of the vessel + /// + [DataField("machinePartPointModifier", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartPointModifier = "ScanningModule"; + + /// + /// A value used to scale the point multiplier + /// with the corresponding part rating. + /// + [DataField("partRatingPointModifier")] + public float PartRatingPointModifier = 1.5f; +} diff --git a/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs b/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs new file mode 100644 index 0000000000..55c7b1bfa5 --- /dev/null +++ b/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs @@ -0,0 +1,61 @@ +using Content.Server.Electrocution; +using Content.Server.Lightning; +using Content.Server.Power.Components; +using Content.Shared.Anomaly.Components; +using Content.Shared.Anomaly.Effects.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.StatusEffect; +using Robust.Shared.Random; + +namespace Content.Server.Anomaly.Effects; + +public sealed class ElectricityAnomalySystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly LightningSystem _lightning = default!; + [Dependency] private readonly ElectrocutionSystem _electrocution = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnPulse); + SubscribeLocalEvent(OnSupercritical); + } + + private void OnPulse(EntityUid uid, ElectricityAnomalyComponent component, ref AnomalyPulseEvent args) + { + var range = component.MaxElectrocuteRange * args.Stabiltiy; + var damage = (int) (component.MaxElectrocuteDamage * args.Severity); + var duration = component.MaxElectrocuteDuration * args.Severity; + + var xform = Transform(uid); + foreach (var comp in _lookup.GetComponentsInRange(xform.MapPosition, range)) + { + var ent = comp.Owner; + + _electrocution.TryDoElectrocution(ent, uid, damage, duration, true, statusEffects: comp, ignoreInsulation: true); + } + } + + private void OnSupercritical(EntityUid uid, ElectricityAnomalyComponent component, ref AnomalySupercriticalEvent args) + { + var poweredQuery = GetEntityQuery(); + var mobQuery = GetEntityQuery(); + var validEnts = new HashSet(); + foreach (var ent in _lookup.GetEntitiesInRange(uid, component.MaxElectrocuteRange * 2)) + { + if (mobQuery.HasComponent(ent)) + validEnts.Add(ent); + + if (_random.Prob(0.1f) && poweredQuery.HasComponent(ent)) + validEnts.Add(ent); + } + + // goodbye, sweet perf + foreach (var ent in validEnts) + { + _lightning.ShootLightning(uid, ent); + } + } +} diff --git a/Content.Server/Anomaly/Effects/GravityAnomalySystem.cs b/Content.Server/Anomaly/Effects/GravityAnomalySystem.cs new file mode 100644 index 0000000000..a928add35b --- /dev/null +++ b/Content.Server/Anomaly/Effects/GravityAnomalySystem.cs @@ -0,0 +1,39 @@ +using Content.Server.Singularity.Components; +using Content.Shared.Anomaly.Components; +using Content.Shared.Anomaly.Effects; +using Content.Shared.Anomaly.Effects.Components; +using Content.Shared.Radiation.Components; + +namespace Content.Server.Anomaly.Effects; + +/// +/// This handles logic and events relating to and +/// +public sealed class GravityAnomalySystem : SharedGravityAnomalySystem +{ + /// + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnSeverityChanged); + SubscribeLocalEvent(OnStabilityChanged); + } + + private void OnSeverityChanged(EntityUid uid, GravityAnomalyComponent component, ref AnomalySeverityChangedEvent args) + { + if (TryComp(uid, out var radSource)) + radSource.Intensity = component.MaxRadiationIntensity * args.Severity; + + if (!TryComp(uid, out var gravityWell)) + return; + var accel = (component.MaxAccel - component.MinAccel) * args.Severity + component.MinAccel; + gravityWell.BaseRadialAcceleration = accel; + gravityWell.BaseTangentialAcceleration = accel * 0.2f; + } + + private void OnStabilityChanged(EntityUid uid, GravityAnomalyComponent component, ref AnomalyStabilityChangedEvent args) + { + if (TryComp(uid, out var gravityWell)) + gravityWell.MaxRange = component.MaxGravityWellRange * args.Stability; + } +} diff --git a/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs b/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs new file mode 100644 index 0000000000..87508802a4 --- /dev/null +++ b/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs @@ -0,0 +1,100 @@ +using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Interaction; +using Content.Shared.Anomaly.Components; +using Content.Shared.Anomaly.Effects.Components; +using Robust.Server.GameObjects; +using Robust.Shared.Map; + +namespace Content.Server.Anomaly.Effects; + +/// +/// This handles and the events from +/// +public sealed class PyroclasticAnomalySystem : EntitySystem +{ + [Dependency] private readonly AtmosphereSystem _atmosphere = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly FlammableSystem _flammable = default!; + [Dependency] private readonly InteractionSystem _interaction = default!; + [Dependency] private readonly TransformSystem _xform = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnPulse); + SubscribeLocalEvent(OnSupercritical); + } + + private void OnPulse(EntityUid uid, PyroclasticAnomalyComponent component, ref AnomalyPulseEvent args) + { + var xform = Transform(uid); + var ignitionRadius = component.MaximumIgnitionRadius * args.Stabiltiy; + IgniteNearby(xform.Coordinates, args.Severity, ignitionRadius); + } + + private void OnSupercritical(EntityUid uid, PyroclasticAnomalyComponent component, ref AnomalySupercriticalEvent args) + { + var xform = Transform(uid); + var grid = xform.GridUid; + var map = xform.MapUid; + + var indices = _xform.GetGridOrMapTilePosition(uid, xform); + var mixture = _atmosphere.GetTileMixture(grid, map, indices, true); + + if (mixture == null) + return; + mixture.AdjustMoles(component.SupercriticalGas, component.SupercriticalMoleAmount); + if (grid is { }) + { + foreach (var ind in _atmosphere.GetAdjacentTiles(grid.Value, indices)) + { + var mix = _atmosphere.GetTileMixture(grid, map, indices, true); + if (mix is not {}) + continue; + mix.AdjustMoles(component.SupercriticalGas, component.SupercriticalMoleAmount); + mix.Temperature += component.HotspotExposeTemperature; + _atmosphere.HotspotExpose(grid.Value, indices, component.HotspotExposeTemperature, mix?.Volume ?? component.SupercriticalMoleAmount, true); + } + } + IgniteNearby(xform.Coordinates, 1, component.MaximumIgnitionRadius * 2); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var (pyro, anom, xform) in EntityQuery()) + { + var ent = pyro.Owner; + + var grid = xform.GridUid; + var map = xform.MapUid; + var indices = _xform.GetGridOrMapTilePosition(ent, xform); + var mixture = _atmosphere.GetTileMixture(grid, map, indices, true); + if (mixture is { }) + { + mixture.Temperature += pyro.HeatPerSecond * anom.Severity * frameTime; + } + + if (grid != null && anom.Severity > pyro.AnomalyHotspotThreshold) + { + _atmosphere.HotspotExpose(grid.Value, indices, pyro.HotspotExposeTemperature, pyro.HotspotExposeVolume, true); + } + } + } + + public void IgniteNearby(EntityCoordinates coordinates, float severity, float radius) + { + foreach (var flammable in _lookup.GetComponentsInRange(coordinates, radius)) + { + var ent = flammable.Owner; + if (!_interaction.InRangeUnobstructed(coordinates.ToMap(EntityManager), ent, -1)) + continue; + + var stackAmount = 1 + (int) (severity / 0.25f); + _flammable.AdjustFireStacks(ent, stackAmount, flammable); + _flammable.Ignite(ent, flammable); + } + } +} diff --git a/Content.Server/Beam/BeamSystem.cs b/Content.Server/Beam/BeamSystem.cs index dd2fb798b8..0f0cf6fac3 100644 --- a/Content.Server/Beam/BeamSystem.cs +++ b/Content.Server/Beam/BeamSystem.cs @@ -1,14 +1,11 @@ using Content.Server.Beam.Components; -using Content.Server.Lightning; using Content.Shared.Beam; using Content.Shared.Beam.Components; -using Content.Shared.Interaction; using Content.Shared.Physics; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Physics.Components; -using Robust.Shared.Physics.Dynamics; using Robust.Shared.Physics.Systems; namespace Content.Server.Beam; @@ -17,8 +14,8 @@ public sealed class BeamSystem : SharedBeamSystem { [Dependency] private readonly FixtureSystem _fixture = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedBroadphaseSystem _broadphase = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; - [Dependency] private readonly SharedTransformSystem _transformSystem = default!; public override void Initialize() { @@ -79,52 +76,52 @@ public sealed class BeamSystem : SharedBeamSystem var shape = new EdgeShape(distanceCorrection, new Vector2(0,0)); var distanceLength = distanceCorrection.Length; - if (TryComp(ent, out var physics) && TryComp(ent, out var beam)) + if (!TryComp(ent, out var physics) || !TryComp(ent, out var beam)) + return; + FixturesComponent? manager = null; + _fixture.TryCreateFixture( + ent, + shape, + "BeamBody", + hard: false, + collisionMask: (int)CollisionGroup.ItemMask, + collisionLayer: (int)CollisionGroup.MobLayer, + manager: manager, + body: physics); + + _physics.SetBodyType(ent, BodyType.Dynamic, manager: manager, body: physics); + _physics.SetCanCollide(ent, true, manager: manager, body: physics); + _broadphase.RegenerateContacts(physics, manager); + + var beamVisualizerEvent = new BeamVisualizerEvent(ent, distanceLength, userAngle, bodyState, shader); + RaiseNetworkEvent(beamVisualizerEvent); + + if (controller != null) + beam.VirtualBeamController = controller; + + else { - FixturesComponent? manager = null; - _fixture.TryCreateFixture( - ent, - shape, - "BeamBody", - hard: false, - collisionMask: (int)CollisionGroup.ItemMask, - collisionLayer: (int)CollisionGroup.MobLayer, - manager: manager, - body: physics); + var controllerEnt = Spawn("VirtualBeamEntityController", beamSpawnPos); + beam.VirtualBeamController = controllerEnt; - _physics.SetBodyType(ent, BodyType.Dynamic, manager: manager, body: physics); - _physics.SetCanCollide(ent, true, manager: manager, body: physics); + _audio.PlayPvs(beam.Sound, beam.Owner); - var beamVisualizerEvent = new BeamVisualizerEvent(ent, distanceLength, userAngle, bodyState, shader); - RaiseNetworkEvent(beamVisualizerEvent); - - if (controller != null) - beam.VirtualBeamController = controller; - - else - { - var controllerEnt = Spawn("VirtualBeamEntityController", beamSpawnPos); - beam.VirtualBeamController = controllerEnt; - - _audio.PlayPvs(beam.Sound, beam.Owner); - - var beamControllerCreatedEvent = new BeamControllerCreatedEvent(ent, controllerEnt); - RaiseLocalEvent(controllerEnt, beamControllerCreatedEvent); - } - - //Create the rest of the beam, sprites handled through the BeamVisualizerEvent - for (int i = 0; i < distanceLength-1; i++) - { - beamSpawnPos = beamSpawnPos.Offset(calculatedDistance.Normalized); - var newEnt = Spawn(prototype, beamSpawnPos); - - var ev = new BeamVisualizerEvent(newEnt, distanceLength, userAngle, bodyState, shader); - RaiseNetworkEvent(ev); - } - - var beamFiredEvent = new BeamFiredEvent(ent); - RaiseLocalEvent(beam.VirtualBeamController.Value, beamFiredEvent); + var beamControllerCreatedEvent = new BeamControllerCreatedEvent(ent, controllerEnt); + RaiseLocalEvent(controllerEnt, beamControllerCreatedEvent); } + + //Create the rest of the beam, sprites handled through the BeamVisualizerEvent + for (var i = 0; i < distanceLength-1; i++) + { + beamSpawnPos = beamSpawnPos.Offset(calculatedDistance.Normalized); + var newEnt = Spawn(prototype, beamSpawnPos); + + var ev = new BeamVisualizerEvent(newEnt, distanceLength, userAngle, bodyState, shader); + RaiseNetworkEvent(ev); + } + + var beamFiredEvent = new BeamFiredEvent(ent); + RaiseLocalEvent(beam.VirtualBeamController.Value, beamFiredEvent); } /// diff --git a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs index 44986ab518..6393df7ee6 100644 --- a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs +++ b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs @@ -7,16 +7,19 @@ using Content.Server.Projectiles; using Content.Server.Storage.Components; using Content.Server.Weapons.Ranged.Systems; using Content.Shared.Database; +using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Projectiles; using Content.Shared.Singularity.Components; using Content.Shared.Singularity.EntitySystems; +using Content.Shared.Verbs; using Content.Shared.Weapons.Ranged.Components; using JetBrains.Annotations; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; +using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; using Timer = Robust.Shared.Timing.Timer; @@ -27,6 +30,7 @@ namespace Content.Server.Singularity.EntitySystems public sealed class EmitterSystem : SharedEmitterSystem { [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; @@ -38,14 +42,28 @@ namespace Content.Server.Singularity.EntitySystems base.Initialize(); SubscribeLocalEvent(ReceivedChanged); + SubscribeLocalEvent(OnApcChanged); SubscribeLocalEvent(OnInteractHand); + SubscribeLocalEvent>(OnGetVerb); + SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(OnRefreshParts); SubscribeLocalEvent(OnUpgradeExamine); + SubscribeLocalEvent(OnAnchorStateChanged); + } + + private void OnAnchorStateChanged(EntityUid uid, EmitterComponent component, ref AnchorStateChangedEvent args) + { + if (args.Anchored) + return; + + SwitchOff(component); } private void OnInteractHand(EntityUid uid, EmitterComponent component, InteractHandEvent args) { - args.Handled = true; + if (args.Handled) + return; + if (EntityManager.TryGetComponent(uid, out LockComponent? lockComp) && lockComp.Locked) { _popup.PopupEntity(Loc.GetString("comp-emitter-access-locked", @@ -71,6 +89,7 @@ namespace Content.Server.Singularity.EntitySystems _adminLogger.Add(LogType.Emitter, component.IsOn ? LogImpact.Medium : LogImpact.High, $"{ToPrettyString(args.User):player} toggled {ToPrettyString(uid):emitter}"); + args.Handled = true; } else { @@ -79,6 +98,47 @@ namespace Content.Server.Singularity.EntitySystems } } + private void OnGetVerb(EntityUid uid, EmitterComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract || args.Hands == null) + return; + + if (TryComp(uid, out var lockComp) && lockComp.Locked) + return; + + if (component.SelectableTypes.Count < 2) + return; + + foreach (var type in component.SelectableTypes) + { + var proto = _prototype.Index(type); + + var v = new Verb + { + Priority = 1, + Category = VerbCategory.SelectType, + Text = proto.Name, + Disabled = type == component.BoltType, + Impact = LogImpact.Medium, + DoContactInteraction = true, + Act = () => + { + component.BoltType = type; + _popup.PopupEntity(Loc.GetString("emitter-component-type-set", ("type", proto.Name)), uid); + } + }; + args.Verbs.Add(v); + } + } + + private void OnExamined(EntityUid uid, EmitterComponent component, ExaminedEvent args) + { + if (component.SelectableTypes.Count < 2) + return; + var proto = _prototype.Index(component.BoltType); + args.Message.AddText(Loc.GetString("emitter-component-current-type", ("type", proto.Name))); + } + private void ReceivedChanged( EntityUid uid, EmitterComponent component, @@ -99,6 +159,23 @@ namespace Content.Server.Singularity.EntitySystems } } + private void OnApcChanged(EntityUid uid, EmitterComponent component, ref PowerChangedEvent args) + { + if (!component.IsOn) + { + return; + } + + if (!args.Powered) + { + PowerOff(component); + } + else + { + PowerOn(component); + } + } + private void OnRefreshParts(EntityUid uid, EmitterComponent component, RefreshPartsEvent args) { var powerUseRating = args.PartRatings[component.MachinePartPowerUse]; @@ -122,7 +199,9 @@ namespace Content.Server.Singularity.EntitySystems { component.IsOn = false; if (TryComp(component.Owner, out var powerConsumer)) - powerConsumer.DrawRate = 0; + powerConsumer.DrawRate = 1; // this needs to be not 0 so that the visuals still work. + if (TryComp(component.Owner, out var apcReceiever)) + apcReceiever.Load = 1; PowerOff(component); UpdateAppearance(component); } @@ -132,6 +211,11 @@ namespace Content.Server.Singularity.EntitySystems component.IsOn = true; if (TryComp(component.Owner, out var powerConsumer)) powerConsumer.DrawRate = component.PowerUseActive; + if (TryComp(component.Owner, out var apcReceiever)) + { + apcReceiever.Load = component.PowerUseActive; + PowerOn(component); + } // Do not directly PowerOn(). // OnReceivedPowerChanged will get fired due to DrawRate change which will turn it on. UpdateAppearance(component); @@ -179,9 +263,6 @@ namespace Content.Server.Singularity.EntitySystems // and thus not firing DebugTools.Assert(component.IsPowered); DebugTools.Assert(component.IsOn); - DebugTools.Assert(TryComp(component.Owner, out var powerConsumer) && - (powerConsumer.DrawRate <= powerConsumer.ReceivedPower || - MathHelper.CloseTo(powerConsumer.DrawRate, powerConsumer.ReceivedPower, 0.0001f))); Fire(component); diff --git a/Content.Shared.Database/LogType.cs b/Content.Shared.Database/LogType.cs index 77d77747e4..ad6e6ac2e9 100644 --- a/Content.Shared.Database/LogType.cs +++ b/Content.Shared.Database/LogType.cs @@ -81,4 +81,5 @@ public enum LogType Stamina = 76, EntitySpawn = 77, AdminMessage = 78, + Anomaly = 79 } diff --git a/Content.Shared/Anomaly/Components/AnomalyComponent.cs b/Content.Shared/Anomaly/Components/AnomalyComponent.cs new file mode 100644 index 0000000000..d19616323d --- /dev/null +++ b/Content.Shared/Anomaly/Components/AnomalyComponent.cs @@ -0,0 +1,268 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Anomaly.Components; + +/// +/// This is used for tracking the general behavior of anomalies. +/// This doesn't contain the specific implementations for what +/// they do, just the generic behaviors associated with them. +/// +/// Anomalies and their related components were designed here: https://hackmd.io/@ss14-design/r1sQbkJOs +/// +[RegisterComponent, NetworkedComponent] +public sealed class AnomalyComponent : Component +{ + /// + /// How likely an anomaly is to grow more dangerous. Moves both up and down. + /// Ranges from 0 to 1. + /// Values less than 0.5 indicate stability, whereas values greater + /// than 0.5 indicate instability, which causes increases in severity. + /// + /// + /// Note that this doesn't refer to stability as a percentage: This is an arbitrary + /// value that only matters in relation to the and + /// + [ViewVariables(VVAccess.ReadWrite)] + public float Stability = 0f; + + /// + /// How severe the effects of an anomaly are. Moves only upwards. + /// Ranges from 0 to 1. + /// A value of 0 indicates effects of extrememly minimal severity, whereas greater + /// values indicate effects of linearly increasing severity. + /// + /// + /// Wacky-Stability scale lives on in my heart. - emo + /// + [ViewVariables(VVAccess.ReadWrite)] + public float Severity = 0f; + + #region Health + /// + /// The internal "health" of an anomaly. + /// Ranges from 0 to 1. + /// When the health of an anomaly reaches 0, it is destroyed without ever + /// reaching a supercritical point. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float Health = 1f; + + /// + /// If the of the anomaly exceeds this value, it + /// becomes too unstable to support itself and starts decreasing in . + /// + [DataField("decayhreshold"), ViewVariables(VVAccess.ReadWrite)] + public float DecayThreshold = 0.15f; + + /// + /// The amount of health lost when the stability is below the + /// + [DataField("healthChangePerSecond"), ViewVariables(VVAccess.ReadWrite)] + public float HealthChangePerSecond = -0.05f; + #endregion + + #region Growth + /// + /// If the of the anomaly exceeds this value, it + /// becomes unstable and starts increasing in . + /// + [DataField("growthThreshold"), ViewVariables(VVAccess.ReadWrite)] + public float GrowthThreshold = 0.5f; + + /// + /// A coefficient used for calculating the increase in severity when above the GrowthThreshold + /// + [DataField("severityGrowthCoefficient"), ViewVariables(VVAccess.ReadWrite)] + public float SeverityGrowthCoefficient = 0.07f; + #endregion + + #region Pulse + /// + /// The time at which the next artifact pulse will occur. + /// + [DataField("nextPulseTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan NextPulseTime = TimeSpan.MaxValue; + + /// + /// The minimum interval between pulses. + /// + [DataField("minPulseLength")] + public TimeSpan MinPulseLength = TimeSpan.FromMinutes(1); + + /// + /// The maximum interval between pulses. + /// + [DataField("maxPulseLength")] + public TimeSpan MaxPulseLength = TimeSpan.FromMinutes(2); + + /// + /// A percentage by which the length of a pulse might vary. + /// + [DataField("pulseVariation")] + public float PulseVariation = .1f; + + /// + /// The sound played when an anomaly pulses + /// + [DataField("pulseSound")] + public SoundSpecifier? PulseSound = new SoundCollectionSpecifier("RadiationPulse"); + + /// + /// The sound plays when an anomaly goes supercritical + /// + [DataField("supercriticalSound")] + public SoundSpecifier? SupercriticalSound = new SoundCollectionSpecifier("explosion"); + #endregion + + /// + /// The range of initial values for stability + /// + /// + /// +/- 0.2 from perfect stability (0.5) + /// + [DataField("initialStabilityRange")] + public (float, float) InitialStabilityRange = (0.4f, 0.6f); + + /// + /// The range of initial values for severity + /// + /// + /// Between 0 and 0.5, which should be all mild effects + /// + [DataField("initialSeverityRange")] + public (float, float) InitialSeverityRange = (0.1f, 0.5f); + + /// + /// The particle type that increases the severity of the anomaly. + /// + [DataField("severityParticleType")] + public AnomalousParticleType SeverityParticleType; + + /// + /// The amount that the increases by when hit + /// of an anomalous particle of . + /// + [DataField("severityPerSeverityHit")] + public float SeverityPerSeverityHit = 0.025f; + + /// + /// The particle type that destabilizes the anomaly. + /// + [DataField("destabilizingParticleType")] + public AnomalousParticleType DestabilizingParticleType; + + /// + /// The amount that the increases by when hit + /// of an anomalous particle of . + /// + [DataField("stabilityPerDestabilizingHit")] + public float StabilityPerDestabilizingHit = 0.04f; + + /// + /// The particle type that weakens the anomalys health. + /// + [DataField("weakeningParticleType")] + public AnomalousParticleType WeakeningParticleType; + + /// + /// The amount that the increases by when hit + /// of an anomalous particle of . + /// + [DataField("healthPerWeakeningeHit")] + public float HealthPerWeakeningeHit = -0.05f; + + /// + /// The amount that the increases by when hit + /// of an anomalous particle of . + /// + [DataField("stabilityPerWeakeningeHit")] + public float StabilityPerWeakeningeHit = -0.02f; + + #region Points and Vessels + /// + /// The vessel that the anomaly is connceted to. Stored so that multiple + /// vessels cannot connect to the same anomaly. + /// + [ViewVariables(VVAccess.ReadWrite)] + public EntityUid? ConnectedVessel; + + /// + /// The minimum amount of research points generated per second + /// + [DataField("minPointsPerSecond")] + public int MinPointsPerSecond; + + /// + /// The maximum amount of research points generated per second + /// This doesn't include the point bonus for being unstable. + /// + [DataField("maxPointsPerSecond")] + public int MaxPointsPerSecond = 100; + #endregion +} + +[Serializable, NetSerializable] +public sealed class AnomalyComponentState : ComponentState +{ + public float Severity; + public float Stability; + public float Health; + public TimeSpan NextPulseTime; + + public AnomalyComponentState(float severity, float stability, float health, TimeSpan nextPulseTime) + { + Severity = severity; + Stability = stability; + Health = health; + NextPulseTime = nextPulseTime; + } +} + +/// +/// Event raised at regular intervals on an anomaly to do whatever its effect is. +/// +/// +/// +[ByRefEvent] +public readonly record struct AnomalyPulseEvent(float Stabiltiy, float Severity) +{ + public readonly float Stabiltiy = Stabiltiy; + public readonly float Severity = Severity; +} + +/// +/// Event raised on an anomaly when it reaches a supercritical point. +/// +[ByRefEvent] +public readonly record struct AnomalySupercriticalEvent; + +/// +/// Event broadcast after an anomaly goes supercritical +/// +/// The anomaly being shut down. +/// Whether or not the anomaly shut down passively or via a supercritical event. +[ByRefEvent] +public readonly record struct AnomalyShutdownEvent(EntityUid Anomaly, bool Supercritical); + +/// +/// Event broadcast when an anomaly's severity is changed. +/// +/// The anomaly being changed +[ByRefEvent] +public readonly record struct AnomalySeverityChangedEvent(EntityUid Anomaly, float Severity); + +/// +/// Event broadcast when an anomaly's stability is changed. +/// +[ByRefEvent] +public readonly record struct AnomalyStabilityChangedEvent(EntityUid Anomaly, float Stability); + +/// +/// Event broadcast when an anomaly's health is changed. +/// +/// The anomaly being changed +[ByRefEvent] +public readonly record struct AnomalyHealthChangedEvent(EntityUid Anomaly, float Health); diff --git a/Content.Shared/Anomaly/Components/AnomalyPulsingComponent.cs b/Content.Shared/Anomaly/Components/AnomalyPulsingComponent.cs new file mode 100644 index 0000000000..9c12ec11c8 --- /dev/null +++ b/Content.Shared/Anomaly/Components/AnomalyPulsingComponent.cs @@ -0,0 +1,22 @@ +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Anomaly.Components; + +/// +/// This component tracks anomalies that are currently pulsing +/// +[RegisterComponent] +public sealed class AnomalyPulsingComponent : Component +{ + /// + /// The time at which the pulse will be over. + /// + [DataField("endTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan EndTime = TimeSpan.MaxValue; + + /// + /// How long the pulse visual lasts + /// + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan PulseDuration = TimeSpan.FromSeconds(5); +} diff --git a/Content.Shared/Anomaly/Components/AnomalySupercriticalComponent.cs b/Content.Shared/Anomaly/Components/AnomalySupercriticalComponent.cs new file mode 100644 index 0000000000..bc5bb381ef --- /dev/null +++ b/Content.Shared/Anomaly/Components/AnomalySupercriticalComponent.cs @@ -0,0 +1,37 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Anomaly.Components; + +/// +/// Tracks anomalies going supercritical +/// +[RegisterComponent, NetworkedComponent] +public sealed class AnomalySupercriticalComponent : Component +{ + /// + /// The time when the supercritical animation ends and it does whatever effect. + /// + [DataField("endTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan EndTime = TimeSpan.MaxValue; + + /// + /// The length of the animation before it goes supercritical. + /// + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan SupercriticalDuration = TimeSpan.FromSeconds(10); + + /// + /// The maximum size the anomaly scales to while going supercritical + /// + [DataField("maxScaleAmount")] + public float MaxScaleAmount = 3; +} + +[Serializable, NetSerializable] +public sealed class AnomalySupercriticalComponentState : ComponentState +{ + public TimeSpan EndTime; + public TimeSpan Duration; +} diff --git a/Content.Shared/Anomaly/Effects/Components/ElectricityAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/ElectricityAnomalyComponent.cs new file mode 100644 index 0000000000..fc430127ef --- /dev/null +++ b/Content.Shared/Anomaly/Effects/Components/ElectricityAnomalyComponent.cs @@ -0,0 +1,14 @@ +namespace Content.Shared.Anomaly.Effects.Components; + +[RegisterComponent] +public sealed class ElectricityAnomalyComponent : Component +{ + [DataField("maxElectrocutionRange"), ViewVariables(VVAccess.ReadWrite)] + public float MaxElectrocuteRange = 6f; + + [DataField("maxElectrocuteDamage"), ViewVariables(VVAccess.ReadWrite)] + public float MaxElectrocuteDamage = 20f; + + [DataField("maxElectrocuteDuration"), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan MaxElectrocuteDuration = TimeSpan.FromSeconds(8); +} diff --git a/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs new file mode 100644 index 0000000000..a6f80aeda0 --- /dev/null +++ b/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs @@ -0,0 +1,53 @@ +namespace Content.Shared.Anomaly.Effects.Components; + +[RegisterComponent] +public sealed class GravityAnomalyComponent : Component +{ + /// + /// The maximumum size the GravityWellComponent MaxRange can be. + /// Is scaled linearly with stability. + /// + [DataField("maxGravityWellRange"), ViewVariables(VVAccess.ReadWrite)] + public float MaxGravityWellRange = 8f; + + /// + /// The maximum distance from which the anomaly + /// can throw you via a pulse. + /// + [DataField("maxThrowRange"), ViewVariables(VVAccess.ReadWrite)] + public float MaxThrowRange = 5f; + + /// + /// The maximum strength the anomaly + /// can throw you via a pulse + /// + [DataField("maxThrowStrength"), ViewVariables(VVAccess.ReadWrite)] + public float MaxThrowStrength = 10; + + /// + /// The maximum Intensity of the RadiationSourceComponent. + /// Is scaled linearly with stability. + /// + [DataField("maxRadiationIntensity"), ViewVariables(VVAccess.ReadWrite)] + public float MaxRadiationIntensity = 3f; + + /// + /// The minimum acceleration value for GravityWellComponent + /// Is scaled linearly with stability. + /// + [DataField("minAccel"), ViewVariables(VVAccess.ReadWrite)] + public float MinAccel = 1f; + + /// + /// The maximum acceleration value for GravityWellComponent + /// Is scaled linearly with stability. + /// + [DataField("maxAccel"), ViewVariables(VVAccess.ReadWrite)] + public float MaxAccel = 5f; + + /// + /// The range around the anomaly that will be spaced on supercritical. + /// + [DataField("spaceRange"), ViewVariables(VVAccess.ReadWrite)] + public float SpaceRange = 3f; +} diff --git a/Content.Shared/Anomaly/Effects/Components/PyroclasticAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/PyroclasticAnomalyComponent.cs new file mode 100644 index 0000000000..5f3c1c2595 --- /dev/null +++ b/Content.Shared/Anomaly/Effects/Components/PyroclasticAnomalyComponent.cs @@ -0,0 +1,54 @@ +using Content.Shared.Atmos; + +namespace Content.Shared.Anomaly.Effects.Components; + +[RegisterComponent] +public sealed class PyroclasticAnomalyComponent : Component +{ + /// + /// The MAXIMUM amount of heat released per second. + /// This is scaled linearly with the Severity of the anomaly. + /// + /// + /// I have no clue if this is balanced. + /// + [DataField("heatPerSecond")] + public float HeatPerSecond = 50; + + /// + /// The maximum distance from which you can be ignited by the anomaly. + /// + [DataField("maximumIgnitionRadius")] + public float MaximumIgnitionRadius = 8f; + + /// + /// The minimum amount of severity required + /// before the anomaly becomes a hotspot. + /// + [DataField("anomalyHotspotThreshold")] + public float AnomalyHotspotThreshold = 0.6f; + + /// + /// The temperature of the hotspot where the anomaly is + /// + [DataField("hotspotExposeTemperature")] + public float HotspotExposeTemperature = 1000; + + /// + /// The volume of the hotspot where the anomaly is. + /// + [DataField("hotspotExposeVolume")] + public float HotspotExposeVolume = 50; + + /// + /// Gas released when the anomaly goes supercritical. + /// + [DataField("supercriticalGas")] + public Gas SupercriticalGas = Gas.Plasma; + + /// + /// The amount of gas released when the anomaly goes supercritical + /// + [DataField("supercriticalMoleAmount")] + public float SupercriticalMoleAmount = 50f; +} diff --git a/Content.Shared/Anomaly/Effects/SharedGravityAnomalySystem.cs b/Content.Shared/Anomaly/Effects/SharedGravityAnomalySystem.cs new file mode 100644 index 0000000000..8cb1714afb --- /dev/null +++ b/Content.Shared/Anomaly/Effects/SharedGravityAnomalySystem.cs @@ -0,0 +1,65 @@ +using System.Linq; +using Content.Shared.Anomaly.Components; +using Content.Shared.Anomaly.Effects.Components; +using Content.Shared.Construction.Components; +using Content.Shared.Construction.EntitySystems; +using Content.Shared.Throwing; +using Robust.Shared.Map; + +namespace Content.Shared.Anomaly.Effects; + +public abstract class SharedGravityAnomalySystem : EntitySystem +{ + [Dependency] private readonly IMapManager _map = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly SharedAnchorableSystem _anchorable = default!; + [Dependency] private readonly ThrowingSystem _throwing = default!; + [Dependency] private readonly SharedTransformSystem _xform = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnAnomalyPulse); + SubscribeLocalEvent(OnSupercritical); + } + + private void OnAnomalyPulse(EntityUid uid, GravityAnomalyComponent component, ref AnomalyPulseEvent args) + { + var xform = Transform(uid); + var range = component.MaxThrowRange * args.Severity; + var strength = component.MaxThrowStrength * args.Severity; + var lookup = _lookup.GetEntitiesInRange(uid, range, LookupFlags.Dynamic | LookupFlags.Sundries); + foreach (var ent in lookup) + { + var tempXform = Transform(ent); + + var foo = tempXform.MapPosition.Position - xform.MapPosition.Position; + _throwing.TryThrow(ent, foo.Normalized * 10, strength, uid, 0); + } + } + + private void OnSupercritical(EntityUid uid, GravityAnomalyComponent component, ref AnomalySupercriticalEvent args) + { + var xform = Transform(uid); + if (!_map.TryGetGrid(xform.GridUid, out var grid)) + return; + + var worldPos = _xform.GetWorldPosition(xform); + var tileref = grid.GetTilesIntersecting(new Circle(worldPos, component.SpaceRange)).ToArray(); + var tiles = tileref.Select(t => (t.GridIndices, Tile.Empty)).ToList(); + grid.SetTiles(tiles); + + var range = component.MaxThrowRange * 2; + var strength = component.MaxThrowStrength * 2; + var lookup = _lookup.GetEntitiesInRange(uid, range, LookupFlags.Dynamic | LookupFlags.Sundries); + foreach (var ent in lookup) + { + var tempXform = Transform(ent); + + var foo = tempXform.MapPosition.Position - xform.MapPosition.Position; + Logger.Debug($"{ToPrettyString(ent)}: {foo}: {foo.Normalized}: {foo.Normalized * 10}"); + _throwing.TryThrow(ent, foo * 5, strength, uid, 0); + } + } +} + diff --git a/Content.Shared/Anomaly/SharedAnomaly.cs b/Content.Shared/Anomaly/SharedAnomaly.cs new file mode 100644 index 0000000000..fe93cff117 --- /dev/null +++ b/Content.Shared/Anomaly/SharedAnomaly.cs @@ -0,0 +1,97 @@ +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Shared.Anomaly; + +[Serializable, NetSerializable] +public enum AnomalyVisuals : byte +{ + IsPulsing, + Supercritical +} + +[Serializable, NetSerializable] +public enum AnomalyVisualLayers : byte +{ + Base, + Animated +} + +/// +/// The types of anomalous particles used +/// for interfacing with anomalies. +/// +/// +/// The only thought behind these names is that +/// they're a continuation of radioactive particles. +/// Yes i know detla+ waves exist, but they're not +/// common enough for me to care. +/// +[Serializable, NetSerializable] +public enum AnomalousParticleType : byte +{ + Delta, + Epsilon, + Zeta +} + +[Serializable, NetSerializable] +public enum AnomalyVesselVisuals : byte +{ + HasAnomaly +} + +[Serializable, NetSerializable] +public enum AnomalyVesselVisualLayers : byte +{ + Base +} + +[Serializable, NetSerializable] +public enum AnomalyScannerUiKey : byte +{ + Key +} + +[Serializable, NetSerializable] +public sealed class AnomalyScannerUserInterfaceState : BoundUserInterfaceState +{ + public FormattedMessage Message; + + public TimeSpan? NextPulseTime; + + public AnomalyScannerUserInterfaceState(FormattedMessage message, TimeSpan? nextPulseTime) + { + Message = message; + NextPulseTime = nextPulseTime; + } +} + +[Serializable, NetSerializable] +public enum AnomalyGeneratorUiKey : byte +{ + Key +} + +[Serializable, NetSerializable] +public sealed class AnomalyGeneratorUserInterfaceState : BoundUserInterfaceState +{ + public TimeSpan CooldownEndTime; + + public int FuelAmount; + + public int FuelCost; + + public AnomalyGeneratorUserInterfaceState(TimeSpan cooldownEndTime, int fuelAmount, int fuelCost) + { + CooldownEndTime = cooldownEndTime; + FuelAmount = fuelAmount; + FuelCost = fuelCost; + } +} + +[Serializable, NetSerializable] +public sealed class AnomalyGeneratorGenerateButtonPressedEvent : BoundUserInterfaceMessage +{ + +} diff --git a/Content.Shared/Anomaly/SharedAnomalySystem.cs b/Content.Shared/Anomaly/SharedAnomalySystem.cs new file mode 100644 index 0000000000..6d954dcc82 --- /dev/null +++ b/Content.Shared/Anomaly/SharedAnomalySystem.cs @@ -0,0 +1,319 @@ +using Content.Shared.Administration.Logs; +using Content.Shared.Anomaly.Components; +using Content.Shared.Database; +using Robust.Shared.GameStates; +using Robust.Shared.Network; +using Robust.Shared.Random; +using Robust.Shared.Timing; +using Robust.Shared.Utility; + +namespace Content.Shared.Anomaly; + +public abstract class SharedAnomalySystem : EntitySystem +{ + [Dependency] protected readonly IGameTiming Timing = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] protected readonly IRobustRandom Random = default!; + [Dependency] protected readonly ISharedAdminLogManager Log = default!; + [Dependency] protected readonly SharedAudioSystem Audio = default!; + [Dependency] protected readonly SharedAppearanceSystem Appearance = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAnomalyGetState); + SubscribeLocalEvent(OnAnomalyHandleState); + SubscribeLocalEvent(OnSupercriticalGetState); + SubscribeLocalEvent(OnSupercriticalHandleState); + + SubscribeLocalEvent(OnAnomalyUnpause); + SubscribeLocalEvent(OnPulsingUnpause); + SubscribeLocalEvent(OnSupercriticalUnpause); + } + + private void OnAnomalyGetState(EntityUid uid, AnomalyComponent component, ref ComponentGetState args) + { + args.State = new AnomalyComponentState( + component.Severity, + component.Stability, + component.Health, + component.NextPulseTime); + } + + private void OnAnomalyHandleState(EntityUid uid, AnomalyComponent component, ref ComponentHandleState args) + { + if (args.Current is not AnomalyComponentState state) + return; + component.Severity = state.Severity; + component.Stability = state.Stability; + component.Health = state.Health; + component.NextPulseTime = state.NextPulseTime; + } + + private void OnSupercriticalGetState(EntityUid uid, AnomalySupercriticalComponent component, ref ComponentGetState args) + { + args.State = new AnomalySupercriticalComponentState + { + EndTime = component.EndTime, + Duration = component.SupercriticalDuration + }; + } + + private void OnSupercriticalHandleState(EntityUid uid, AnomalySupercriticalComponent component, ref ComponentHandleState args) + { + if (args.Current is not AnomalySupercriticalComponentState state) + return; + + component.EndTime = state.EndTime; + component.SupercriticalDuration = state.Duration; + } + + private void OnAnomalyUnpause(EntityUid uid, AnomalyComponent component, ref EntityUnpausedEvent args) + { + component.NextPulseTime += args.PausedTime; + Dirty(component); + } + + private void OnPulsingUnpause(EntityUid uid, AnomalyPulsingComponent component, ref EntityUnpausedEvent args) + { + component.EndTime += args.PausedTime; + } + + private void OnSupercriticalUnpause(EntityUid uid, AnomalySupercriticalComponent component, ref EntityUnpausedEvent args) + { + component.EndTime += args.PausedTime; + Dirty(component); + } + + public void DoAnomalyPulse(EntityUid uid, AnomalyComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + var variation = Random.NextFloat(-component.PulseVariation, component.PulseVariation) + 1; + component.NextPulseTime = Timing.CurTime + GetPulseLength(component) * variation; + + // if we are above the growth threshold, then grow before the pulse + if (component.Stability > component.GrowthThreshold) + { + ChangeAnomalySeverity(uid, GetSeverityIncreaseFromGrowth(component), component); + } + else + { + // just doing this to update the scanner ui + // as they hook into these events + ChangeAnomalySeverity(uid, 0); + } + + Log.Add(LogType.Anomaly, LogImpact.Medium, $"Anomaly {ToPrettyString(uid)} pulsed with severity {component.Severity}."); + Audio.PlayPvs(component.PulseSound, uid); + + var pulse = EnsureComp(uid); + pulse.EndTime = Timing.CurTime + pulse.PulseDuration; + Appearance.SetData(uid, AnomalyVisuals.IsPulsing, true); + + var ev = new AnomalyPulseEvent(component.Stability, component.Severity); + RaiseLocalEvent(uid, ref ev); + } + + /// + /// Begins the animation for going supercritical + /// + /// + public void StartSupercriticalEvent(EntityUid uid) + { + // don't restart it if it's already begun + if (HasComp(uid)) + return; + + Log.Add(LogType.Anomaly, LogImpact.High, $"Anomaly {ToPrettyString(uid)} began to go supercritical."); + + var super = EnsureComp(uid); + super.EndTime = Timing.CurTime + super.SupercriticalDuration; + Appearance.SetData(uid, AnomalyVisuals.Supercritical, true); + Dirty(super); + } + + /// + /// Does the supercritical event for the anomaly. + /// This isn't called once the anomaly reaches the point, but + /// after the animation for it going supercritical + /// + /// + /// + public void DoAnomalySupercriticalEvent(EntityUid uid, AnomalyComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + Audio.PlayPvs(component.SupercriticalSound, uid); + + var ev = new AnomalySupercriticalEvent(); + RaiseLocalEvent(uid, ref ev); + + EndAnomaly(uid, component, true); + } + + /// + /// Ends an anomaly, cleaning up all entities that may be associated with it. + /// + /// The anomaly being shut down + /// + /// Whether or not the anomaly ended via supercritical event + public void EndAnomaly(EntityUid uid, AnomalyComponent? component = null, bool supercritical = false) + { + if (!Resolve(uid, ref component)) + return; + + var ev = new AnomalyShutdownEvent(uid, supercritical); + RaiseLocalEvent(uid, ref ev, true); + + Log.Add(LogType.Anomaly, LogImpact.Extreme, $"Anomaly {ToPrettyString(uid)} went supercritical."); + + if (Terminating(uid) || _net.IsClient) + return; + Del(uid); + } + + /// + /// Changes the stability of the anomaly. + /// + /// + /// + /// + public void ChangeAnomalyStability(EntityUid uid, float change, AnomalyComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + var newVal = component.Stability + change; + + component.Stability = Math.Clamp(newVal, 0, 1); + Dirty(component); + + var ev = new AnomalyStabilityChangedEvent(uid, component.Stability); + RaiseLocalEvent(uid, ref ev, true); + } + + /// + /// Changes the severity of an anomaly, going supercritical if it exceeds 1. + /// + /// + /// + /// + public void ChangeAnomalySeverity(EntityUid uid, float change, AnomalyComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + var newVal = component.Severity + change; + + if (newVal >= 1) + StartSupercriticalEvent(uid); + + component.Severity = Math.Clamp(newVal, 0, 1); + Dirty(component); + + var ev = new AnomalySeverityChangedEvent(uid, component.Severity); + RaiseLocalEvent(uid, ref ev, true); + } + + /// + /// Changes the health of an anomaly, ending it if it's less than 0. + /// + /// + /// + /// + public void ChangeAnomalyHealth(EntityUid uid, float change, AnomalyComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + var newVal = component.Health + change; + + if (newVal < 0) + { + EndAnomaly(uid, component); + return; + } + + component.Health = Math.Clamp(newVal, 0, 1); + Dirty(component); + + var ev = new AnomalyHealthChangedEvent(uid, component.Health); + RaiseLocalEvent(uid, ref ev, true); + } + + /// + /// Gets the length of time between each pulse + /// for an anomaly based on its current stability. + /// + /// + /// For anomalies under the instability theshold, this will return the maximum length. + /// For those over the theshold, they will return an amount between the maximum and + /// minium value based on a linear relationship with the stability. + /// + /// + /// The length of time as a TimeSpan, not including random variation. + public TimeSpan GetPulseLength(AnomalyComponent component) + { + DebugTools.Assert(component.MaxPulseLength > component.MinPulseLength); + var modifier = Math.Clamp((component.Stability - component.GrowthThreshold) / component.GrowthThreshold, 0, 1); + return (component.MaxPulseLength - component.MinPulseLength) * modifier + component.MinPulseLength; + } + + /// + /// Gets the increase in an anomaly's severity due + /// to being above its growth threshold + /// + /// + /// The increase in severity for this anomaly + private float GetSeverityIncreaseFromGrowth(AnomalyComponent component) + { + var score = 1 + Math.Max(component.Stability - component.GrowthThreshold, 0) * 10; + return score * component.SeverityGrowthCoefficient; + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var anomaly in EntityQuery()) + { + var ent = anomaly.Owner; + + // if the stability is under the death threshold, + // update it every second to start killing it slowly. + if (anomaly.Stability < anomaly.DecayThreshold) + { + ChangeAnomalyHealth(ent, anomaly.HealthChangePerSecond * frameTime, anomaly); + } + + if (Timing.CurTime > anomaly.NextPulseTime) + { + DoAnomalyPulse(ent, anomaly); + } + } + + foreach (var pulse in EntityQuery()) + { + var ent = pulse.Owner; + + if (Timing.CurTime > pulse.EndTime) + { + Appearance.SetData(ent, AnomalyVisuals.IsPulsing, false); + RemComp(ent, pulse); + } + } + + foreach (var (super, anom) in EntityQuery()) + { + var ent = anom.Owner; + + if (Timing.CurTime <= super.EndTime) + continue; + DoAnomalySupercriticalEvent(ent, anom); + RemComp(ent, super); + } + } +} diff --git a/Content.Shared/Singularity/Components/SharedEmitterComponent.cs b/Content.Shared/Singularity/Components/SharedEmitterComponent.cs index f2362cae85..7579823246 100644 --- a/Content.Shared/Singularity/Components/SharedEmitterComponent.cs +++ b/Content.Shared/Singularity/Components/SharedEmitterComponent.cs @@ -1,8 +1,10 @@ using System.Threading; using Content.Shared.Construction.Prototypes; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; namespace Content.Shared.Singularity.Components; @@ -25,9 +27,12 @@ public sealed class EmitterComponent : Component /// /// The entity that is spawned when the emitter fires. /// - [DataField("boltType")] + [DataField("boltType", customTypeSerializer: typeof(PrototypeIdSerializer))] public string BoltType = "EmitterBolt"; + [DataField("selectableTypes", customTypeSerializer: typeof(PrototypeIdListSerializer))] + public List SelectableTypes = new(); + /// /// The current amount of power being used. /// diff --git a/Content.Shared/Verbs/VerbCategory.cs b/Content.Shared/Verbs/VerbCategory.cs index 1f63f3d106..63a1cbced6 100644 --- a/Content.Shared/Verbs/VerbCategory.cs +++ b/Content.Shared/Verbs/VerbCategory.cs @@ -81,5 +81,7 @@ namespace Content.Shared.Verbs public static readonly VerbCategory SetSensor = new("verb-categories-set-sensor", null); public static readonly VerbCategory Lever = new("verb-categories-lever", null); + + public static readonly VerbCategory SelectType = new("verb-categories-select-type", null); } } diff --git a/Resources/Audio/Ambience/Objects/anomaly_generator.ogg b/Resources/Audio/Ambience/Objects/anomaly_generator.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7b28e732a55d770d3ce41d8488bd89a7cbe6a9c1 GIT binary patch literal 39601 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 HSjw~rE7#UR literal 0 HcmV?d00001 diff --git a/Resources/Audio/Ambience/attributions.yml b/Resources/Audio/Ambience/attributions.yml new file mode 100644 index 0000000000..e6979603be --- /dev/null +++ b/Resources/Audio/Ambience/attributions.yml @@ -0,0 +1,4 @@ +- files: ["anomaly_drone.ogg"] + license: "CC0-1.0" + copyright: "Created by Joao_Janz, edited and converted to Mono by EmoGarbage" + source: "https://freesound.org/people/Joao_Janz/sounds/478472/" \ No newline at end of file diff --git a/Resources/Audio/Items/attributions.yml b/Resources/Audio/Items/attributions.yml index 92bce1cd2d..aee30635ab 100644 --- a/Resources/Audio/Items/attributions.yml +++ b/Resources/Audio/Items/attributions.yml @@ -1,3 +1,8 @@ +- files: ["beep.ogg"] + license: "CC0-1.0" + copyright: "Created by Pól, converted to OGG and Mono by EmoGarbage" + source: "https://freesound.org/people/P%C3%B3l/sounds/385927/" + - files: ["trayhit1.ogg"] license: "CC-BY-SA-3.0" copyright: "Time immemorial" diff --git a/Resources/Audio/Items/beep.ogg b/Resources/Audio/Items/beep.ogg new file mode 100644 index 0000000000000000000000000000000000000000..65abe4208ccfae0008c79cea70c8b9fc658c7075 GIT binary patch literal 5488 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 QlmGw#07*qoM6N<$f~!QgWB>pF literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Research/anomalyscanner.rsi/meta.json b/Resources/Textures/Objects/Specific/Research/anomalyscanner.rsi/meta.json new file mode 100644 index 0000000000..76eff64a56 --- /dev/null +++ b/Resources/Textures/Objects/Specific/Research/anomalyscanner.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC0-1.0", + "copyright": "Created by EmoGarbage", + "states": [ + { + "name": "icon" + } + ] +} diff --git a/Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/base.png b/Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/base.png new file mode 100644 index 0000000000000000000000000000000000000000..b53ee643c1a77ec059c20e2d1f32a6ebbb0a1611 GIT binary patch literal 3857 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 T)Wcf100000NkvXXu0mjf99LWU literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/inserting.png b/Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/inserting.png new file mode 100644 index 0000000000000000000000000000000000000000..aeb74f2c8652509e88be0cd5451461aea0ce8dca GIT binary patch literal 609 zcmeAS@N?(olHy`uVBq!ia0y~yU~B-g4{)%7L|$x32U3j1LGDfr>(0r%WME*D_H=O! zshIQjmSNXn1A(@{)VXf%20Q;>Z2DzlsHYaaG&+J^M6K%{bF=nmyRv+-lTKlwafBN|ulNg-qnGP7RSoAa0t1~k22|loS&-KB7 zJwM|IyRFyW-4|&P*Ev1OmT`eJqlJdjscpHcN}HDZcsDH6XH4K=n&aQFzn_8OztDr4 z_Z%A-7;1Kuvqms5sHrmO-}r7@edx*^`{}=*7uD0+i-gU8AUt;yd(Wb+-zxU4fBh=& zz=t{@cgeL`wuw<|w;um|@}AM^*I!?Ki+5v?Xk&1WXJRnWWMr5zg<(%Z3#lj0kC&MGAd=X~S5Hz`5#u;9TL zCj=!;Dm1y+o11>s7QV077t22A2Q(ZP_&2k0)qzKsPF)V~e)m2%^xD&-384?N9x0}- zpI^0kT6^>3EmFNU=X{sF`MTN0Zf@Ckm9J^K(#olM>$-b-`cmuPt4IBp))Ei+_A7FB zq(`90&2xp5QeM1Ja`r5`8&b;MszD_=uI_b&FuXf9q-@gY68zA@~ZNq#Z V)NT6DT>*PQd{0+Dmvv4FO#qBulYIaH literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/unshaded.png b/Resources/Textures/Structures/Machines/Anomaly/anomaly_generator.rsi/unshaded.png new file mode 100644 index 0000000000000000000000000000000000000000..6608244157412d33df71875e2f8201d1e1b11c82 GIT binary patch literal 1830 zcmds$do+}39LHZjQF>oTHrHY{5%nc0}ks6jW1E{dulJKoa$(N)`+%BG?Fj%t4IL!eoQTSwd233>_-VAx zmA9qtG2Z0Am20@|ijPTBERdOC74=CyWb5(rozKv9>L4`%lDG7w6_t{UH1Kz>Uw6Em zt){K;`(c|cf&6=+H;#4|=+I}E-8&EL8eK$UV=iTfr$}mkwK2+d;j8|7o*dy9(%9e{ zFue*VN6k$sSFiBjxEr6I`wAJZ#?6WRqkE4}szG6FZv?|vz11tdG->t5E`J)xU496^WZi)? z;z!x;$f*K3Qf%DjppnS|JJDD-q3;fZik(gD&6jKX05;tHlu^^}>s^rpKV0BMxFTI> z1iKi_(`;Q@3RY3M*ieAKko1`^oH%SdLY6QpB zsYNcFCA3Q#K@nv7JRRtniBCLZCW}@v<%d%2-U+VJf_ErFMvj!E#M?3}Ts$GGRc&JW zAnVyi;iErVz>(O^Wty_0>Wh)6kMee>hG#lDI)1XY&X~JE!YhN&?tRj>RhEEcYgM78 zWqQmpHQNAjv4NiW6VC2)h-psMny&evlu}HKW9p6!l<&e>1l^JvQA+sB!ydk;;Adw_ zTT#H1de?JnphZp@ShGXxM9fw0YYY8DUM_CFNAi5JTrVV0GUUt_J`^1P6E z(!I(maiD{J$Xl>XXixP5{n?yel+5p@C9kKFga@g4bt_OPi8PHYnD%0`J6qs(0wdoQ zH!fA2v*;BqHr)sk9#%U*?hJtBA@4wYhbC*c!o{1G@53M$9WV`n#qP)z&t7nN zwqPE;?R=ywlJ%tP5sbU1Z&H0fy_CU=Y`7FP#lHL_+i(gI&_Vkom|;?Zgd7fItt#t^ zx4#QlG1#-ck>wVF`qrssJ=5Baf->2jDcbd>S@q&g3r3K^6fiGIU0>^#%zW@$N|AkH2SYWr;AfK3m{ph;As^ev-ook&cPx#)k#D_R9J=W)KLn8Fc=5$e|^0yAsL9!H9AK(=>j{#o`Vh&bPlf(h%pw}o>o1i zA(p0MFZKOiMCP{t_TdLG#u#Jl-%Z*EFT2AMKwP}W09MX>eKltUkyOrm4FG~j<(bh_ zxqu*201^OcF)y8O*2ktjWNtCBA1(8%k0!;f(aNg@Y zGg=TSYb>m>&l1!_b-^Xz614V#u1?$it@!_eM-Kox_JQ6dc&D;?DXl#ljS`?D`TWWE h0=!)Ph-u literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/base.png b/Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/base.png new file mode 100644 index 0000000000000000000000000000000000000000..e292496fbe13a51a8530f1105b55f5ade12b67fb GIT binary patch literal 615 zcmV-t0+{`YP)Px%AxT6*R9J=OmrrXGK^Vp#rAM7NmUN(nl1oD^2oW}*9<++IJqz|Oeg{8=A3<7r zPoZZc^>0Ci1lm(tiw6(w;<(h#`T^>p>@vGE@9reo;K2vNY~Goj=g0fb%=F5!dRNj1L_36lUg(_EVaNj{(mKZbcb!U& zA3jhMCTep_1ej;Jj`rG#}tjE<- z!~$)1cCg*q8E1;&*MOPcqy%Q4Yo%8PV5T2%mq6=yCh%%(0?I z8FTI&aFvEF!D4d}N5@BL+YTD+BRX&BIzKqE0M|tW?VtewY5S(TYmFl!{EP;fSpGi| zUmEsl=&RJ{?rl%+RZTS1_%<}xF`U}=Mz;rD?esur<002ovPDHLkV1oP) BBVhml literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/meta.json b/Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/meta.json new file mode 100644 index 0000000000..1a9a61933d --- /dev/null +++ b/Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/meta.json @@ -0,0 +1,23 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by EmoGarbage404", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "anomaly" + }, + { + "name": "base" + }, + { + "name": "panel" + }, + { + "name": "powered" + } + ] +} diff --git a/Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/panel.png b/Resources/Textures/Structures/Machines/Anomaly/anomaly_vessel.rsi/panel.png new file mode 100644 index 0000000000000000000000000000000000000000..b350a504157a00bad5f1e5ac9b308ca8b45b0905 GIT binary patch literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}^E_P~Ln2y} z6C_v{Cy4Yk1sZU<9rR%D`JtkILND5%*PBbuo%PYAWW^;jT^l}18%{e>8(!V(`{&;I z*`I!VF%(R;*f~v@S)+_Wbz1Nn2B&GoMumTu&17DYXnB)w!L+A5JT6a~?B)LzFYLaX ze8A_X*PB=To?GWEVE*tlK7~PB-(%~X#zwE36Jk!Ue8o`2c+kW_XUDIPx*ElET{RCt{2T1{&kM;Lw-N+D{{C`FY>K*$g)_JTn%iHQP93>Ma*sDx7bbu-DK zho1c_a_*srl-!cEloD!sNKnCczz(i)6%6ad30R2QXtQlR!d0M$st0AJv#b4>9qmeS z$OB?`N2B*^-kDj=^Tu#U@$n~Lb?j|F{rGJxsGPt*V3@l)-(!G?o8MhmmaVE&MgKeM z<^Y8=1*Frdo_519F?V&o6J`+RuFiL6%Ox(~4T3#V`U3@^c;SL&1nkZ;!<>Q=CerB? z*48$#|Kcy+mOTDGrluwX%aRU&O!`IbID=uB$mO!g<+45PL2U?>0W1XpU~O#!_wQBt zv+4+_U?>?NBFqsOwtl4mggFAk)_*8706>qkhGANEhb{eql$=AC0bV;z?e`kLKWMk5 zUaA7Puhg0O+wcA zM+f0JLn28)X^T7G52Q1IQVL32Xqq~J^Lzvt*bdM%^;ZT`7fEVh`Uy!$^leG&S3VF) zpFHXL92LYl9|i)Q*kngWIsiZj!G|Bs^?d)!&o_DG8#_CpABi#jGLY3D*vRb2Naysa z;;X4(MJA=;$+Oi+oVV+L@@y3V;B+5Ef1pKhqEO(>%tkpux z1SkDXQ%8QZi0!AVmbM`Jl@`Hj^>&OIl}Hj0LM&}6GFA0^waGwg3OGgI4Pw8rf)S;D z-wa^N0lb>)w_~N!7aahWg^;yXtG8p>k&#X&)inkMbo!YJQS0{&K=%ctyUMbK$14Se zexZzh)cSn`;I*YtO3~VUVJ+AKotRf=>wnw>AM63$<yv;Dc%sVy0W7FCg_K? zwGHHQSv@SOsL5d8D< zC4YYR=urT`QuTYBNPq3CU`v01_u@JJ%vdEST%Nv!g}V#!g+b|v}S$fA^$izBDUH4 zGF+a%#N}45RJeTB4gh2MF+ARWjIsQfl=FbZF5rf9XUqIPKU&1z?jul2ksmGMkG(z1 z*`1h*hR2p?00}7%aE>?#B~KoC$h!acur4lK-F1i1&c?yv_|y zeb}K#*nFS}Ps4(6ac=1MlqPB$q>W>ooFAg(2BWY+i5>Pr)aPy4$20pe}i^* zHdE3%PQ)Zs>T^kUl4N6A84&40fV8a`M{{Wxvprr*&Z6yEz002ovPDHLkV1lhI7F+-T literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/firing.png b/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/firing.png new file mode 100644 index 0000000000000000000000000000000000000000..20c993ec3926d734e24c19b704b352ec8beb7e3e GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|-gvq=hE&XX zd()7w$v~vx;qtR=>0Gj)BAD_OyWa{>K*Ma>vY8b>k8+Fc2 vE&t^5gTe~DWM4fD!qEj literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/locked.png b/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/locked.png new file mode 100644 index 0000000000000000000000000000000000000000..fa85ff1d523d1a3cc5c232427d316c7ede627b7f GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|JUm?-Ln`LH zy}6N>L4k*PL)U-td9R|Mva$&TZPY&@py{mCken8FX3cd&hK$pffEs|H!1J?o)*ikC gzS3{6LPQ=&b4SJSaTW_J-USJGy85}Sb4q9e0GUN7>;M1& literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/meta.json b/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/meta.json new file mode 100644 index 0000000000..2a826897e4 --- /dev/null +++ b/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/meta.json @@ -0,0 +1,35 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by EmoGarbage404", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "base", + "directions": 4 + }, + { + "name": "firing", + "directions": 4 + }, + { + "name": "locked", + "directions": 4 + }, + { + "name": "panel", + "directions": 4 + }, + { + "name": "underpowered", + "directions": 4 + }, + { + "name": "unshaded", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/panel.png b/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/panel.png new file mode 100644 index 0000000000000000000000000000000000000000..dd170d14cd9e5034aab7e233a4e34f9e753a2939 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|ZhN{ohE&XX zd()Qdkb%UpkH`BRKk~SKV9=90crY^N&9i5$EFXp5>D_bK(-p4KdPYlxE9lj_j@Dz# zO#k1PICOe;`;%BDMuvZvOLm>v|28xHqQ_jphSzK{pY0l)x_Blp`}B`Z0Kx~_1p)_* zb+7Y^7{;%$|K~l&zuj#Pql4{KIR#(&fV-Pm-(8>Gl=xwroO|KTOH)7m%Rcj)Va=Y4 zC-bH*_f+$I#cOq|C!Oo?hHvlVH_TQrJicZJ$)CCx8ItPC-3kbtMFpUXO@geCxNA$4v5 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/underpowered.png b/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/underpowered.png new file mode 100644 index 0000000000000000000000000000000000000000..9cc2d9d5a2faeb4a4b489684e4114b3ca79ab888 GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|(mY)pLn`LH zy|IzE!GMS5z=15DgJvQ*hXu~C#kz2AoWk*QUH{XFP2Kve3=9ejH9!5ZI=5CVYP#(` zzAw}2SZA?+_*0|%?XcpR#nKYGe?itVFzjq`y10E`%krkM7pHhZ0u3>Ff+rO?oxXi= P2XQ@J{an^LB{Ts51%EqB literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/unshaded.png b/Resources/Textures/Structures/Machines/Anomaly/ape.rsi/unshaded.png new file mode 100644 index 0000000000000000000000000000000000000000..b5fb9bb69ebd1df94ce9c6263de5385e7c14bb9f GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|u6nvShE&XX zd()At$w8v+;d;G?F-rUbJ65}vYrJ4^N*AlxHjl)Zj%zN4zwBmD zbZq-s$JY8&6=(=Uu*vW5Y<7ir?=N~*SsRn8mt7g&U{#ahdpEYrp#1)&_Yn^-S7}WZ zxuyOnHcs?_&}&h z%DYWpKdJ3Jz2H~}r%(2gj-FQ*+9$O|XKv|Oa=0kK?0;3WXWUk|XyJVeB3U5XODdSA W>FM`+xp(z}1Uy~+T-G@yGywn@<8A=} literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom1-pulse.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom1-pulse.png new file mode 100644 index 0000000000000000000000000000000000000000..3ea4f894bf49922ba7728fbed020f31fffa3ab26 GIT binary patch literal 2701 zcmV;83Uc*{P)Px2EJr3&A|L~W|H z3NGS8<;5w58@X0^!30-PQ1c-7MunP-Fjkq?_ZB|0o}HcZvC^*1i*}mCtE2Oq^Reg5 z8J!uRl1eIBU3v7-3RIF`u8;eB+VhR0=EuBsEj0nYyn6pP0Q~y@T@Sx&_%Qr#5qtnW zQ-9mTZv(*T;Q`gLRQspn82}^$+d4UGc=!#@r}lq&_1?<2D)r^n`@eVgH!+|7z;ryr zn~Tr*&%d81pV!xKQssy9wdDW*{oe)NK7WQNu3hx7q6_+CuMvxbddU%v^~iy4R+!_Zm7n~TpW2w!&U>o?fh-^9-TX68A`aK45& z7oVL<=HZ9xuneDD`x-xw4w7#>zl+ZkYv0A^y!!f0X#2ON4(bHBKJM?ePR@pM&*9MF zd<~<)1f#(uQBsxxZkMCh$=T4?c)@?&IyvjgWiM0*E{5Nw6GWgiTPJ62$q&^*;kRK< z5P|Zdb#m6w_?$VMuX$er!*9TxAfz~L011U?q-?NOrbzMWK%G&B4z%Qk=ulSsdEKdh z2a}8*p^~uyLiT>HP@Zxjwt#K#*E&|?yUO`&0o&eB6HC73lJ6_$vITs5zgD-)_OS3X zwm@d&==c%EHS69^e@AgGQ%;tpay$E*DZhYC$jQU&)wUKJU+WCU@4_SG4;a58>q+$%oqaW!R_S{580*nv?_iPa>~Bg3OG<2fAbp&1@#%9- ze0#docSzL!AraB4dE_%?e)dkKO!jXdYsWzN2u4CiZ@j%Pu8oNEFut3#+1 z&89j-+n-0*RLNg||LxJp7!+LO0MOs_>5s%yB|p=Y@Oi{+e5zOKqwxXz1oZKvxK_9E zf%KkhFoFSNLV4mO!}-=WD1NU$uG~ zF!JHs60DE{tNmOAzh^CY z$3GtpCJoM)ZF05W!#|gwXTG^{)chF5wYug&(HtEvM-9oFi_gK{z>TBkyC|-8Bww4| zl5g9G4d3exH2U?UxYm<=ZDr$p`F8ShhVS$Sn&)2ue2U`QxyI-1OdU%dIx@cM4fJjn ze_hWKsAgJG zQt`{@J68buzjh^zW)}(FS^5GzrRdgyhtLzxa)Kp z{1^cE;FGXP0NhOkS`ii+jQenf=G5a}UBQYTg}cJl3BZFx03-w3Iyu_~f_{v+G|zTf z9l2b^_w{2)ApfC%3@Yu%Ff}p=z&6dY0^`#=2wVy7Gd|uXtCF7}bt6bx*JZ?~Umy4P zLI+|M;`1Mxuhp^*U@MAim;COTCawSoes|4mAzQE?9}}S!D2i+6KE6u_!9Rx*8tu{{ zifg?PzD)_;{L* zf^W^0!*oz{18G5*3-GciNHsJpG?4WkRFXN<;GlxRezB@{HKxvqNGYetbTK3?Ig z`2m3JAS{rdAS6FPCO?9#)5e#5r0_G7e+@{*rhf-8j^f&-&4Hj9eH`wHPq&@`gbvpD zc;nS_@-=bA$16HG^8?6d+y`N^%0u!4FdfwV2-;DTx1Yq(|LV`h-i<;FO_oNV4PHik zJ|6^W6y674t~T5ncYU`AK0D5(__m3+aDD&)9aI$EoL*fwf^*`XqPXKpjp+{MW)6OumIc6&SK-_&;}G2$w1}?B|p!IJA;VR$2Z5-G`u7Rmkqb00000NkvXX Hu0mjfF^OAe literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom1.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom1.png new file mode 100644 index 0000000000000000000000000000000000000000..0075a07a5128c71ff4c7e6848a623442dfffe313 GIT binary patch literal 663 zcmV;I0%-k-P)Px%QAtEWR9J=WRxxYaKp1^;+aVabC=DWu3ZgA^F(_jR6uf!R>?NQ-ke^^^=}*uf z2z2q3!GktU#-jp;E{PFA1YBXPWHOoJ>kvNm?sRu@oq#FiO{cr>zW46Fr@I4Q@INCB zBbJ5{+Zj1Kj~P3UpCrQCmfR0Kq3>dp;ppu2pYy#okx-iw_q=}9SLUnQ92$?ap{2{Q zu>b(@0}o}sLK;SFFrMJ+=VJgsQUcv+A;czSs~QKuejI;++i_sKZCs2pEr(G6ze+B7 zMX1AL?7Egi1!K)<3w2~&duN;#(Th3dXAn(*i4 z0*CvKR{bU>oG%NUd^)HWD35DTsGiqn9}hkV0=o8kBggYG^JRgn#jLuZWHfqUzAUQ5 zsy{>Jc@t<0M*qSXG1H_ xhDgJRPx-rAb6VRCt{2TwQBZNf>@zmNl!TCu*ZhKVmt-UUyy~pSjdg&RfN_qve3dJrQ6a{dY80KP12$!)pOFQu{Z8T&zrtyGIP$Hk91cv z4;0$dIp>+o^SqOpcV-TNf`WpAf`URj;((W%q6a&tc-IS`s$>4DBZujm_dfHkk3N3r z>GQb7{d3pzyz39|E*K!mU-77t<0Zs`z%)tCK8@StBiocCo-vN-v86_c9sgx3T`4f;n=M&Jl<%OA86 zSm6_y)FQ83I-VQ`2;K;+@J1UBNk z;`eF-8}X(1Wliv{L|rT&9)&-tb#W^)yRq7+gn6&QE9U~-#y{UZc!U<3+gy7`%Cwvx z076W;x`5voY{a+aPh?Vy)C3}Mqk=?#llUn7&!>Ovr1y+x7pedNFO5pg>~4Vm@$p58OJx%Scg6@_T(l4W}VjDCUm ztne%>{Kzfp1!Q^v0FL;-PW@pi@MP?E=XiFZie;Fdz%QD_Pj4()44CLSTg~g`o%7v; zM@$pYNDPD@i1>fM-|V6VE_V-BOcR7)SA>@F0|3;uP#-N2GU`QAMwJ7j* zAQG9>;?}4qgJO$p9QQqMwS-LesQ{2~KKV zI96~Pu*jeh{ZxD&KbnAy4+7%{fDjd*$4^WUV(txuA7D>>9zQXGG{1}i9I?H<9mHc4 z|9`+AhyfJ7T=+J?m+XGUFK2+-?8fT*mqw*Fo?WOu8M_UoQVF)Vw=Lv`VZhUCcVRrc zP!&uCy`l!NJH5;6<()*&*{X>D&ftY=UN7$mrh>ls0iZs&x%Tn$;qHov|H{z;oC!2d z1%u!R*d6VQ__g}yA}uS!-(&zXSLY^B#*bw0gBPkSKZ-Bnm(2q_n143#e06yp^Xe?-HrGC0IXX~b`HA>VaFYjkv@(AtufM6; z)j_L&F0%YYd@i@&JV4Ey*TYGztHU&bn?#Ub)BvDkZgcJ3`R>6ZXaZWmArTY^KkP+n=URYh z0Y;RHweY*m0wNr;fl~ZV(GMWk0~oL;LZc^O;j|d!0~UTT8-Wp=Vqf^d+TbnY$FBm@ z1k(I6>i__1IoK9$y&Q~C8$#N6LkL1`32WmmVH9dpXq#>dWudl(e?8m66%-T{6ciK` z6ciK`6ciNN2VZ0&Nbv{9?RiA<`9CIDy}9C`v3AM3#KGX`W$AO!dQ0G#Nzz|Hw|fZbl;Qs3z=nRzTP z`u+0bv)u55&4}AAKR)aK$ZvZ#kQe=K&Zj3bsT@06cLQGZ%km>PJ6&`GUi8cGCo-wx zjo9$fsCF#OP8Z#RjeaM71}AH@{;Z z03*;GiA$eP40jzKXy1z=eLq%SD|kUSsnCi*FV^kC=IOet5uIXq(mAwO$8H_^}X134OQ zeieX>03-_t;NkrUJbr2d%7?(~9Pw@W9eaR+QK?L>EHw^35&^j9(|L5XY<0+Wv`fM_wu4?i#_pnM3Y#UK&XaC@8cc{sqVs%GQa?M_vE`002ovPDHLk FV1lRbH8lVL literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom2.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom2.png new file mode 100644 index 0000000000000000000000000000000000000000..91b21edf71e4bffe4517f2d617b127193c97cd28 GIT binary patch literal 379 zcmV->0fhdEP)Px$HAzH4R9J=WmQ7B>Kn#UnQ6*-9@G8r27f#My=v-i$F5DF?T7)yP$0idbB=V#v zO61A=?09~FUH@H&HG^IrpWn3i@7MF|uL4-cJs=?f#h8rH@>38Opfb0NO%M;F3E-GN zRnM0-5GFvwyf&^SL0pIj=VLANR9#w(`^(e{i0n1{}re(qgSFWz0+%`#RZr(Ac9=Dnv1M zBNUP9t1`?CLy;L1GsEEL`Tq6$~@gK#L??!qk)NObUDz{T34av%_tV{diVGofPbVq&!CjLd$7 z1kN18YoeZuHJtz9!8+|-TtY~k#S6q8p;=FPP-L&OttkMv_3q)6?) z|J05I`JMKP0j)LcPB`BPZm#)VQ{^owskqd(`=K-cdlHE@_jU|59?F{Q?(DhsfmONw zkhp&O5!is?bzO*l;eT_?8@!^LsD5ODWRPgu=>9@T3|rw`3)R}X=RNPc;DeLU(Ncul zRI;m7>J+wJHtgPIUrSImW{c~9J9H9s=GPi2m1MK$LZobNxi{#ZHb$IdsI0VkU3u!~ z$+JY&qz8ia-+e6HxRGd>HbA?|4@%a%1Sa zQjT$q?P9MXCHZIl@Br`O*2xrWi-spO9#@cjEwh&Q>3OT1s6mCUbM_U74d~Ow#OSX_ zezCKx^DJXTB%{?IlBGQ{NQy1h(dN6#<3RmN!&(pZ8n~cd-3|P`PspDax6cSN+#MWx z-JTA-))cqZG*CLNtK!IxXwqI`rXA*<=;U3Y$>tGpH z<7#w0h})(AFjo|-tN`UEGq7Dx_G3+CHCbg~N_Ms5-V|FTB~0;e<4o|XG8Y?4j91#P z_jeU^CG9x~V|0|x&E})T7wApY*lOi2Iq7ApbZeqhJh<*cc46@To?Nl{6KeBf(H+I3XntAWrRry$8$JA5juheCB|1KH?7A(ZcJs9! zPz5|BJx6M`McxGjxwnICTEJm_eH{hM)(zJBlNo5WSoNRFq#I4Y)KJrZW{hqI1qN`z zTMApuU2668pCV@;dNVc9tv_`wuk2YWrwjh%#ktm%lc6wWH`_!0D+zTW9ydIbwF&g2 zmH8h#UsYr3Rx_PPc$WK|O}wY>2tVr=mA@3V03(og{LK(Ftu~hZ6;xWo=a&emCt@!+V`gxX{Yw4gAA)5>%)N9!%A;0lvwC;($ z{=OY8OcG}BkY?;Thf66nn|{O36l1)=cc+VmfRNg?2;0_V!w0M|AK6liEprUP+y8%)+z zk9C*hcOP%mURj-(P~OrJfRv*7V17_wkPTZ7b#dVNefO!VbsZzDE7icrM>k_*NPsIl zG5QX`wpH{^#7`UWX`3m2P&ivbvZE!7G@Nr_1sNo@m*nCRVXW#xeCju~NLd#7PPlUL ziTUY|YBsi&d87RQO=;*So%`aupaI~Se$+O>D`Rp9qCru6qMFhe#>MtirnXQ3(!3(7 zu(d#OgDJ_4d~ix-&+jV$!_S{YRgocN9p`nyzW=aF@p``Diy1D0o=EeY2=9ycdbnJL zE{y(*)XANx8b-LO)nf|^lDZaozj!_mSO9U zJ*czj|6*}v)SM{L$Yr~PEpyrV(UKn;KHuRv99^&9Fh7@5S=7w`hhp=UN_#7X7i(mL zu=ssnet-b=2^L1#u5B<|*`Sx=I}C8lmRxv!e|C^)H^|Q|1AicSN_&}MPdAwGMbZ;C zs8~D-@hy`Ln`gd?~!|w!vM$4l1&Iz3TY>Wv22d+x)wWS07?nr%8PHQ8}K|! zx8!5XA`}Pz1_)ZQ3Y}>_h52~svz+Yn^5q|WOtr8;{PqOn;|nJfpa=S^fI85D_5a)^ z7XI^4?!(9#5HcTHP{W{L<;vc>)HVE28(AW1XiaCw0189Cm576NW!v3R0p=XQ%e;Ex z^&Uld^d$hs?vqFDwc#89o8!?wzPQ0~ch#hP=;YI?@<5&PAn0WvQjLXspP%0XIZs6N z#hzE{TfExziVdn<`Ha1K7KK8Po=SNh2lmx|@_jk|i%&qq%$!0DR7siRr5^zZ>9P;y zIyKqzbY|jzJe-9|;sgx_*apQ7IFoO1ULB?EC-x=1Yo3-}cy2c-2#a6e2szh6hRjuu zc3X)uj?Jux%b30rc9R(*n*f2@dCN#D`6zJZZqD}J~kwU%4-^uW}3U;kuD8+o`t zzXDasjOHPMKQAAJBF$Y7F3piQ7~qpA*zbXWaBLZ~Icsxgclb2{-Rl-7CjL7L*&EZ1 z2GL$$(p4a$#VrfSkbdIW9$1d9nKqe{QFZk+jp#QV{{X*kNN8h&hVPyjj8dmR7r4BS zIo4~4K(z3?%!{BP7xu_Os|Z&(dx;D|rCt1*viT?4ZP9;`Sl-VnILJkJiPoBP#oPZEGRn5B16tlX*;=rCT8ZhyV`>h-P6AqCMXbPdzZ5X zU8W#b7+_fM1WS(OkL-;&e|F|cZa_av@g3R?hX6+Bz#R`kwhXWWlX)1g%zjhmDEQq2{V*WNezXCKN&Q9H}Se?|K^auGT%ZfB2bTm zbMX02eIsHl+#|&0P0SK%Ezf%r>hec@byzU5{5tt_7dr-3nd7oN4?kZwsTpBAwgW>1 z>15P!xfWbDiEJ!?CB3OY;+i;Kj$C=Av(`k#Wl|n{o1s~>)tZdfIIhV0Y^D3E(sRt4 zHsnK=v;wPYVk_f(T(ta<<|k*XmF#Ma0J9GYMI`KErS${nXs?~E#w^@F$BVo(@MwXO z`+j%Le=E6W;G;Y{-p_c9N+4XvEn1VsgafON0s*P2Fbc6WV|u1t=A=aO<^+<IY&K)x3rH+-x;^SwQQU!v>7aNKE=gGv<(S&MJZkD*?q&bC_-5pW% z_+d8Qx)i@1i8orkgTzFxY~Q&Of>Rp7?>QT_uP4sH!h}v&XKFX!(n2V3&tvZ${cPUMM~mANH~tZPT(0 zi0R<>Z6bI5sp&AjnVUawvicvwnzVYunjHA*?iatRiuXEJ zg{wOT6QjnV+dXr6{u)N%45U5dPUeMncBj{ux`#5rCDLKBGW!Yn(2R|2)9+nMAO^Ue z&Cr`Seo<|C;LbV269?uy18!zFl`m|(f%mN^lYlF(pNZ^a=#fY7G} zkXqbJ3{a>FQ;a^_ec||HeY4(?d_-6jg~+vEo&Qx>bgQ8`Iurj~67puz%wUPb(P#5$ zo?AMW3q7$x38N1shyXRiBzYG$M>rudfZLYvcNEg1=*PY0o7G=dX5VawmUq|A;AjYJ5!sxR2KhF?oFIzdc;A`rTlu zBOX|WAdSUkWg^QR?T)d3MT_=#c|C(Csl^ria2oi!DwTtbxFU)Y1};dsdkqVOFe$XQ z!uraM&Mq!{Cc&M6c=HafTCesM#s>_eur_-ay7HW^Bl~Zr4m<*{J>pr1{$lSomD}4x zDbAgD6JbLF)J5V%v-U{7^mZO&eV|kGYYZx-jz}BSxIMY;|C2@IbSg5 zaGV5uE`=BY05IyqZ*10g7YPcEFO(o#a~QTVGGclN04+auh&7PRManTDeY3zpRT?sT z7N$3zpU-H^cm>Cp+`bwgJ+1?wPgb%DH(?aow*?sAm3@o_H(|K_og6UXf&QG{TmQsg?K;5}`8fe6^;cKgNLqb><&zE}&{{N?(4 z7jl=b1E;ABY0$;?Qbmlk5rq5Lp|Lk;j5pnw_s8nyPI+i@T9wzkxVdU?Hy;*svQ81$ zmy9bALc2CxGJZ2SEJCjLJB9S2Knh4cVS|E#y{o&BRGnI8X<@IugX_Z%>eis0D1ZjG zE@`d1qrLxqbZ;x?#r)Wd-vPy2gtlHQTe!0{_M!KW66sg&GF)!j_-#AvmzXc=mmJ7% zRhO;|o@2W%D$HHmLOsG=9LUl-Gjcd{O8@c|AwavJR{q?QYn_SR+o7<*4XY9Aeb-|B pvhE{}46s2=;N!G1uci$&XHUiNFUP;c4}Jzf_SVi;&n$wH{|9;8C4B$@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom3.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom3.png new file mode 100644 index 0000000000000000000000000000000000000000..b35962c9debd5253848a1ed07c979395cd802ea0 GIT binary patch literal 658 zcmV;D0&V??P)Px%Oi4sRR9J=W*3FL_MGyt>-*~6#c$Vi18oX=E1|OD-{~vAc|PSns@N(}eAivrm>_51vdg!edZbnBqbpTlB0?m19T=E+kXQH6F>X zCA0c}s$^g;c_rS+$VMqm_qPc2$w=1JJri8Xu6*s0>>24Zd{o{%e#TE|v^uOLORW2_ zJ$5sWWuV7Ms`byNk}KI$(wE$Pg-@~M_PHG2U@coIy>MBx*Ev##QzdAq-Cu6Ng!GJ? zFQoK2`3Y?&ZYJFRO8g>usWq-~BPSYtbZpTn`A$urWJJi!w@th+~MQ0*8V_zC){DFXu>}u(1dNDHT8{(%I(D`ew5=6(v0Y| z?(tHXYb^>c>*n@fAn+E6ohn||=W>hUjXqgpGX#7v0rrDwN95h_fkI-d{SUqe spb33n05=Z5dw$vi`VjE5o$YM!8oDa>p+eLG0ssI207*qoM6N<$f|ZdtAOHXW literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom4-pulse.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom4-pulse.png new file mode 100644 index 0000000000000000000000000000000000000000..488dd67f1f72d0c4187861ea0b2be0761fafc40b GIT binary patch literal 1788 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 bI2Zl_TvO|WqLMOX00000NkvXXu0mjfBk0Q8 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/meta.json b/Resources/Textures/Structures/Specific/anomaly.rsi/meta.json new file mode 100644 index 0000000000..f9d4be792f --- /dev/null +++ b/Resources/Textures/Structures/Specific/anomaly.rsi/meta.json @@ -0,0 +1,97 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by EmoGarbage; anom3, anom3-pulse, anom4, anom4-pulse are CC-BY-SA-3.0 at https://github.com/ParadiseSS13/Paradise/blob/master/icons/effects/effects.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "anom1" + }, + { + "name": "anom1-pulse", + "delays": [ + [ + 0.15625, + 0.15625, + 0.15625, + 0.15625, + 0.15625, + 0.15625, + 0.15625, + 0.15625 + ] + ] + }, + { + "name": "anom2" + }, + { + "name": "anom2-pulse", + "delays": [ + [ + 0.15625, + 0.15625, + 0.15625, + 0.15625, + 0.15625, + 0.15625, + 0.15625, + 0.15625 + ] + ] + }, + { + "name": "anom3" + }, + { + "name": "anom3-pulse", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "anom4", + "delays": [ + [ + 0.3, + 0.3, + 0.3, + 0.3, + 0.3, + 0.3, + 0.3 + ] + ] + }, + { + "name": "anom4-pulse", + "delays": [ + [ + 0.15, + 0.15, + 0.15, + 0.15, + 0.15, + 0.15, + 0.15 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Structures/Wallmounts/signs.rsi/anomaly2.png b/Resources/Textures/Structures/Wallmounts/signs.rsi/anomaly2.png new file mode 100644 index 0000000000000000000000000000000000000000..73d94ac95e45de566b4003a5605a00de2f3c55ea GIT binary patch literal 454 zcmV;%0XhDOP)Px$fJsC_R9J=WmN9C>FcgOWmMq;1p`albkdW!nGuTk5x804vB49G9BuFQ4~G&e^1hr3=I13x@iiS%@+p~gSXe0T94Yn z*?e)hUw$J`vrgt*3hbtLwGgAGN%Azq^GDbTAn_wSOrL6F8UZe8A8#*D7L2v$(gIM8 zi%n4(V-73FbwIRNfQ+x53+6Db`EJ_=s@dmh1~>G;r2v-#Zs=8ju5FPK0C3En%+)O@ zHbn_>zBN_>R72pn+_dDn#zp`()d@h&T3wCa0hq(UrNBB`RScQKu#Q&XQfPy;F2hkU zE>AZ>kn%JGm!cAD9e{K#!>(JP1wfhY1hL}J9EFU!J2X6PK{}4FVF#rGn07*qoM6N<$g2_n27ytkO literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Wallmounts/signs.rsi/meta.json b/Resources/Textures/Structures/Wallmounts/signs.rsi/meta.json index 7fb0e4a735..209c9c7d75 100644 --- a/Resources/Textures/Structures/Wallmounts/signs.rsi/meta.json +++ b/Resources/Textures/Structures/Wallmounts/signs.rsi/meta.json @@ -23,6 +23,9 @@ ] ] }, + { + "name": "anomaly2" + }, { "name": "armory", "delays": [