mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 05:27:38 +03:00
Port Supermatter Updates From Impstation (#1719)
# Description Yea it turns out ImpStation made a shitton of updates to Supermatter that were never upstreamed, including making a fancy new Supermatter Monitoring Console, which needs to be mapped. Technically this is a DeltaV PR, but out of pure spite I ported the entirety of this completely by hand. <details><summary><h1>Media</h1></summary> <p>  </p> </details> # Changelog 🆑 - add: Added Supermatter Monitoring Console. (cherry picked from commit 541f1695d0f9e03afb26f847f3e8fd1462c5ed14)
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
using Content.Shared._EE.Supermatter.Components;
|
||||
|
||||
namespace Content.Client._EE.Supermatter.Consoles;
|
||||
|
||||
public sealed class SupermatterConsoleBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[ViewVariables]
|
||||
private SupermatterConsoleWindow? _menu;
|
||||
|
||||
public SupermatterConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { }
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
_menu = new SupermatterConsoleWindow(this, Owner);
|
||||
_menu.OpenCentered();
|
||||
_menu.OnClose += Close;
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
var castState = (SupermatterConsoleBoundInterfaceState)state;
|
||||
_menu?.UpdateUI(castState.Supermatters, castState.FocusData);
|
||||
}
|
||||
|
||||
public void SendFocusChangeMessage(NetEntity? netEntity)
|
||||
{
|
||||
SendMessage(new SupermatterConsoleFocusChangeMessage(netEntity));
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (!disposing)
|
||||
return;
|
||||
|
||||
_menu?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:ui="clr-namespace:Content.Client.Pinpointer.UI"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc 'supermatter-console-window-title'}"
|
||||
Resizable="True"
|
||||
SetSize="700 400"
|
||||
MinSize="700 400">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<!-- Main display -->
|
||||
<BoxContainer Orientation="Horizontal" VerticalExpand="True" HorizontalExpand="True">
|
||||
<!-- Supermatter list -->
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" Margin="10 0 10 10">
|
||||
<!-- Supermatters (entries added by C# code) -->
|
||||
<BoxContainer VerticalExpand="True" HorizontalExpand="True" Margin="0 10 0 0">
|
||||
<ScrollContainer HorizontalExpand="True">
|
||||
<BoxContainer Name="SupermattersTable" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" Margin="0 0 0 10" />
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Footer -->
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<PanelContainer StyleClasses="LowDivider" />
|
||||
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
|
||||
<Label Text="{Loc 'supermatter-console-window-flavor-left'}" StyleClasses="WindowFooterText" />
|
||||
<Label Text="{Loc 'supermatter-console-window-flavor-right'}" StyleClasses="WindowFooterText"
|
||||
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
|
||||
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
@@ -0,0 +1,258 @@
|
||||
using Content.Client.Message;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared._EE.Supermatter.Components;
|
||||
using Content.Shared._EE.Supermatter.Monitor;
|
||||
using Content.Shared.Pinpointer;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Client._EE.Supermatter.Consoles;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class SupermatterConsoleWindow : FancyWindow
|
||||
{
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly SpriteSystem _spriteSystem;
|
||||
private readonly SharedNavMapSystem _navMapSystem;
|
||||
|
||||
private EntityUid? _owner;
|
||||
private NetEntity? _trackedEntity;
|
||||
|
||||
private SupermatterConsoleEntry[]? _supermatters = null;
|
||||
private IEnumerable<SupermatterConsoleEntry>? _activeAlerts = null;
|
||||
|
||||
public event Action<NetEntity?>? SendFocusChangeMessageAction;
|
||||
|
||||
private bool _autoScrollActive = false;
|
||||
private bool _autoScrollAwaitsUpdate = false;
|
||||
|
||||
// Colors
|
||||
private Color _wallColor = new Color(64, 64, 64);
|
||||
private Color _tileColor = new Color(28, 28, 28);
|
||||
private Color _monitorBlipColor = Color.Cyan;
|
||||
private Color _untrackedEntColor = Color.DimGray;
|
||||
private Color _regionBaseColor = new Color(154, 154, 154);
|
||||
private Color _inactiveColor = StyleNano.DisabledFore;
|
||||
private Color _statusTextColor = StyleNano.GoodGreenFore;
|
||||
private Color _goodColor = Color.LimeGreen;
|
||||
private Color _warningColor = new Color(255, 182, 72);
|
||||
private Color _dangerColor = new Color(255, 67, 67);
|
||||
|
||||
public SupermatterConsoleWindow(SupermatterConsoleBoundUserInterface userInterface, EntityUid? owner)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
_entManager = IoCManager.Resolve<IEntityManager>();
|
||||
_spriteSystem = _entManager.System<SpriteSystem>();
|
||||
_navMapSystem = _entManager.System<SharedNavMapSystem>();
|
||||
|
||||
// Pass the owner to nav map
|
||||
_owner = owner;
|
||||
|
||||
// Set supermatter monitoring message action
|
||||
SendFocusChangeMessageAction += userInterface.SendFocusChangeMessage;
|
||||
}
|
||||
|
||||
public void UpdateUI(SupermatterConsoleEntry[] supermatters, SupermatterFocusData? focusData)
|
||||
{
|
||||
if (_owner == null)
|
||||
return;
|
||||
|
||||
if (!_entManager.TryGetComponent<SupermatterConsoleComponent>(_owner.Value, out var console))
|
||||
return;
|
||||
|
||||
if (_trackedEntity != focusData?.NetEntity)
|
||||
{
|
||||
SendFocusChangeMessageAction?.Invoke(_trackedEntity);
|
||||
focusData = null;
|
||||
}
|
||||
|
||||
// Retain supermatter data for use inbetween updates
|
||||
_supermatters = supermatters;
|
||||
|
||||
// Clear excess children from the tables
|
||||
var supermattersCount = _supermatters.Count();
|
||||
|
||||
while (SupermattersTable.ChildCount > supermattersCount)
|
||||
SupermattersTable.RemoveChild(SupermattersTable.GetChild(SupermattersTable.ChildCount - 1));
|
||||
|
||||
// Update all entries in each table
|
||||
for (int index = 0; index < _supermatters.Count(); index++)
|
||||
{
|
||||
var entry = _supermatters.ElementAt(index);
|
||||
UpdateUIEntry(entry, index, SupermattersTable, console, focusData);
|
||||
}
|
||||
|
||||
// If no alerts are active, display a message
|
||||
if (supermattersCount == 0)
|
||||
{
|
||||
var label = new RichTextLabel()
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
VerticalExpand = true,
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
};
|
||||
|
||||
label.SetMarkup(Loc.GetString("supermatter-console-window-no-supermatters"));
|
||||
|
||||
SupermattersTable.AddChild(label);
|
||||
}
|
||||
|
||||
// Auto-scroll re-enable
|
||||
if (_autoScrollAwaitsUpdate)
|
||||
{
|
||||
_autoScrollActive = true;
|
||||
_autoScrollAwaitsUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateUIEntry(SupermatterConsoleEntry entry, int index, Control table, SupermatterConsoleComponent console, SupermatterFocusData? focusData = null)
|
||||
{
|
||||
// Make new UI entry if required
|
||||
if (index >= table.ChildCount)
|
||||
{
|
||||
var newEntryContainer = new SupermatterEntryContainer(entry.NetEntity);
|
||||
|
||||
// On click
|
||||
newEntryContainer.FocusButton.OnButtonUp += args =>
|
||||
{
|
||||
if (_trackedEntity == newEntryContainer.NetEntity)
|
||||
{
|
||||
_trackedEntity = null;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_trackedEntity = newEntryContainer.NetEntity;
|
||||
}
|
||||
|
||||
// Send message to console that the focus has changed
|
||||
SendFocusChangeMessageAction?.Invoke(_trackedEntity);
|
||||
};
|
||||
|
||||
// Add the entry to the current table
|
||||
table.AddChild(newEntryContainer);
|
||||
}
|
||||
|
||||
// Update values and UI elements
|
||||
var tableChild = table.GetChild(index);
|
||||
|
||||
if (tableChild is not SupermatterEntryContainer)
|
||||
{
|
||||
table.RemoveChild(tableChild);
|
||||
UpdateUIEntry(entry, index, table, console, focusData);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var entryContainer = (SupermatterEntryContainer)tableChild;
|
||||
|
||||
entryContainer.UpdateEntry(entry, entry.NetEntity == _trackedEntity, focusData);
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
AutoScrollToFocus();
|
||||
}
|
||||
|
||||
private void ActivateAutoScrollToFocus()
|
||||
{
|
||||
_autoScrollActive = false;
|
||||
_autoScrollAwaitsUpdate = true;
|
||||
}
|
||||
|
||||
private void AutoScrollToFocus()
|
||||
{
|
||||
if (!_autoScrollActive)
|
||||
return;
|
||||
|
||||
var scroll = SupermattersTable.Parent as ScrollContainer;
|
||||
if (scroll == null)
|
||||
return;
|
||||
|
||||
if (!TryGetVerticalScrollbar(scroll, out var vScrollbar))
|
||||
return;
|
||||
|
||||
if (!TryGetNextScrollPosition(out float? nextScrollPosition))
|
||||
return;
|
||||
|
||||
vScrollbar.ValueTarget = nextScrollPosition.Value;
|
||||
|
||||
if (MathHelper.CloseToPercent(vScrollbar.Value, vScrollbar.ValueTarget))
|
||||
_autoScrollActive = false;
|
||||
}
|
||||
|
||||
private bool TryGetVerticalScrollbar(ScrollContainer scroll, [NotNullWhen(true)] out VScrollBar? vScrollBar)
|
||||
{
|
||||
vScrollBar = null;
|
||||
|
||||
foreach (var child in scroll.Children)
|
||||
{
|
||||
if (child is not VScrollBar)
|
||||
continue;
|
||||
|
||||
var castChild = child as VScrollBar;
|
||||
|
||||
if (castChild != null)
|
||||
{
|
||||
vScrollBar = castChild;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryGetNextScrollPosition([NotNullWhen(true)] out float? nextScrollPosition)
|
||||
{
|
||||
nextScrollPosition = null;
|
||||
|
||||
var scroll = SupermattersTable.Parent as ScrollContainer;
|
||||
if (scroll == null)
|
||||
return false;
|
||||
|
||||
var container = scroll.Children.ElementAt(0) as BoxContainer;
|
||||
if (container == null || container.Children.Count() == 0)
|
||||
return false;
|
||||
|
||||
// Exit if the heights of the children haven't been initialized yet
|
||||
if (!container.Children.Any(x => x.Height > 0))
|
||||
return false;
|
||||
|
||||
nextScrollPosition = 0;
|
||||
|
||||
foreach (var control in container.Children)
|
||||
{
|
||||
if (control == null || control is not SupermatterEntryContainer)
|
||||
continue;
|
||||
|
||||
if (((SupermatterEntryContainer)control).NetEntity == _trackedEntity)
|
||||
return true;
|
||||
|
||||
nextScrollPosition += control.Height;
|
||||
}
|
||||
|
||||
// Failed to find control
|
||||
nextScrollPosition = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private SupermatterStatusType GetStatus(NetEntity netEntity)
|
||||
{
|
||||
var status = _supermatters?.FirstOrNull(x => x.NetEntity == netEntity)?.EntityStatus;
|
||||
|
||||
if (status == null)
|
||||
return SupermatterStatusType.Error;
|
||||
|
||||
return status.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<BoxContainer xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Orientation="Vertical" HorizontalExpand ="True" Margin="0 0 0 3">
|
||||
|
||||
<Button Name="FocusButton" VerticalExpand="True" HorizontalExpand="True" StyleClasses="OpenLeft" Access="Public">
|
||||
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Horizontal">
|
||||
<!-- Supermatter sprite -->
|
||||
<TextureRect Name="SupermatterSprite" SetWidth="32" SetHeight="48" TexturePath="/Textures/_EE/Interface/Supermatter/supermatter.png" Margin="6 2" />
|
||||
|
||||
<!-- Supermatter name -->
|
||||
<Label Name="SupermatterNameLabel" Text="???" HorizontalExpand="True" HorizontalAlignment="Left" Margin="5 0" />
|
||||
|
||||
<!-- Supermatter status -->
|
||||
<Label Name="SupermatterStatusLabel" Text="{Loc 'supermatter-console-window-error-status'}" HorizontalExpand="True" HorizontalAlignment="Right" Margin="5 0" />
|
||||
</BoxContainer>
|
||||
</Button>
|
||||
|
||||
<!-- Panel that appears on selecting the device -->
|
||||
<PanelContainer Name="FocusContainer" HorizontalExpand="True" Margin="1 -1 1 0" ReservesSpace="False" Visible="False" Access="Public">
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="#25252a"/>
|
||||
</PanelContainer.PanelOverride>
|
||||
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Horizontal" Margin="6 3">
|
||||
|
||||
<!-- Engine details -->
|
||||
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical" Margin="0 0 6 0">
|
||||
<!-- Integrity display -->
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="IntegrityLabel" Text="{Loc 'supermatter-console-window-label-integrity'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<PanelContainer Name="IntegrityBarBorder" SetWidth="150" SetHeight="24">
|
||||
<ProgressBar Name="IntegrityBar" MinValue="0" MaxValue="100" HorizontalExpand="True" VerticalExpand="True" Margin="1">
|
||||
<Label Name="IntegrityBarLabel" HorizontalAlignment="Right" Margin="0 0 4 0" />
|
||||
</ProgressBar>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Internal energy display -->
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="PowerLabel" Text="{Loc 'supermatter-console-window-label-power'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<PanelContainer Name="PowerBarBorder" SetWidth="150" SetHeight="24">
|
||||
<ProgressBar Name="PowerBar" MinValue="0" MaxValue="5000" HorizontalExpand="True" VerticalExpand="True" Margin="1">
|
||||
<Label Name="PowerBarLabel" HorizontalAlignment="Right" Margin="0 0 4 0" />
|
||||
</ProgressBar>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Radiation display -->
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="RadiationLabel" Text="{Loc 'supermatter-console-window-label-radiation'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<PanelContainer Name="RadiationBarBorder" SetWidth="150" SetHeight="24">
|
||||
<ProgressBar Name="RadiationBar" MinValue="0" MaxValue="30" HorizontalExpand="True" VerticalExpand="True" Margin="1">
|
||||
<Label Name="RadiationBarLabel" HorizontalAlignment="Right" Margin="0 0 4 0" />
|
||||
</ProgressBar>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Absorbed moles display -->
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="MolesLabel" Text="{Loc 'supermatter-console-window-label-moles'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<PanelContainer Name="MolesBarBorder" SetWidth="150" SetHeight="24">
|
||||
<ProgressBar Name="MolesBar" MinValue="0" MaxValue="100" HorizontalExpand="True" VerticalExpand="True" Margin="1">
|
||||
<Label Name="MolesBarLabel" HorizontalAlignment="Right" Margin="0 0 4 0" />
|
||||
</ProgressBar>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Temperature display -->
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="TemperatureLabel" Text="{Loc 'supermatter-console-window-label-temperature'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<PanelContainer Name="TemperatureBarBorder" SetWidth="150" SetHeight="24">
|
||||
<ProgressBar Name="TemperatureBar" MinValue="0" MaxValue="1000" HorizontalExpand="True" VerticalExpand="True" Margin="1">
|
||||
<Label Name="TemperatureBarLabel" HorizontalAlignment="Right" Margin="0 0 4 0" />
|
||||
</ProgressBar>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Temperature limit display -->
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="TemperatureLimitLabel" Text="{Loc 'supermatter-console-window-label-temperature-limit'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<Label Name="TemperatureLimitBarLabel" HorizontalAlignment="Left" SetWidth="150" />
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Waste multiplier display -->
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="WasteLabel" Text="{Loc 'supermatter-console-window-label-waste'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<PanelContainer Name="WasteBarBorder" SetWidth="150" SetHeight="24">
|
||||
<ProgressBar Name="WasteBar" MinValue="0" MaxValue="10" HorizontalExpand="True" VerticalExpand="True" Margin="1">
|
||||
<Label Name="WasteBarLabel" HorizontalAlignment="Right" Margin="0 0 4 0" />
|
||||
</ProgressBar>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Absorption ratio display -->
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="AbsorptionLabel" Text="{Loc 'supermatter-console-window-label-absorption'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<Label Name="AbsorptionBarLabel" HorizontalAlignment="Left" SetWidth="150" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Gas details (entries added by C# code) -->
|
||||
<BoxContainer Name="GasTable" HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical" Margin="6 0 0 0" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
</BoxContainer>
|
||||
@@ -0,0 +1,285 @@
|
||||
using Content.Client.Atmos.EntitySystems;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Shared._EE.Supermatter.Components;
|
||||
using Content.Shared._EE.Supermatter.Monitor;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Client._EE.Supermatter.Consoles;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class SupermatterEntryContainer : BoxContainer
|
||||
{
|
||||
public NetEntity NetEntity;
|
||||
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly IResourceCache _cache;
|
||||
|
||||
private Dictionary<SupermatterStatusType, string> _statusStrings = new()
|
||||
{
|
||||
[SupermatterStatusType.Inactive] = "supermatter-console-window-inactive-status",
|
||||
[SupermatterStatusType.Normal] = "supermatter-console-window-normal-status",
|
||||
[SupermatterStatusType.Caution] = "supermatter-console-window-caution-status",
|
||||
[SupermatterStatusType.Warning] = "supermatter-console-window-warning-status",
|
||||
[SupermatterStatusType.Danger] = "supermatter-console-window-danger-status",
|
||||
[SupermatterStatusType.Emergency] = "supermatter-console-window-emergency-status",
|
||||
[SupermatterStatusType.Delaminating] = "supermatter-console-window-delaminating-status"
|
||||
};
|
||||
|
||||
public SupermatterEntryContainer(NetEntity uid)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
_entManager = IoCManager.Resolve<IEntityManager>();
|
||||
_cache = IoCManager.Resolve<IResourceCache>();
|
||||
|
||||
NetEntity = uid;
|
||||
|
||||
// Load fonts
|
||||
var headerFont = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Bold.ttf"), 11);
|
||||
var normalFont = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSansDisplay/NotoSansDisplay-Regular.ttf"), 11);
|
||||
var monoFont = new VectorFont(_cache.GetResource<FontResource>("/EngineFonts/NotoSans/NotoSansMono-Regular.ttf"), 10);
|
||||
|
||||
// Set fonts
|
||||
SupermatterNameLabel.FontOverride = headerFont;
|
||||
|
||||
SupermatterStatusLabel.FontOverride = normalFont;
|
||||
|
||||
IntegrityLabel.FontOverride = normalFont;
|
||||
PowerLabel.FontOverride = normalFont;
|
||||
RadiationLabel.FontOverride = normalFont;
|
||||
MolesLabel.FontOverride = normalFont;
|
||||
TemperatureLabel.FontOverride = normalFont;
|
||||
TemperatureLimitLabel.FontOverride = normalFont;
|
||||
WasteLabel.FontOverride = normalFont;
|
||||
AbsorptionLabel.FontOverride = normalFont;
|
||||
|
||||
IntegrityBarLabel.FontOverride = monoFont;
|
||||
PowerBarLabel.FontOverride = monoFont;
|
||||
RadiationBarLabel.FontOverride = monoFont;
|
||||
MolesBarLabel.FontOverride = monoFont;
|
||||
TemperatureBarLabel.FontOverride = monoFont;
|
||||
TemperatureLimitBarLabel.FontOverride = monoFont;
|
||||
WasteBarLabel.FontOverride = monoFont;
|
||||
AbsorptionBarLabel.FontOverride = monoFont;
|
||||
}
|
||||
|
||||
public void UpdateEntry(SupermatterConsoleEntry entry, bool isFocus, SupermatterFocusData? focusData = null)
|
||||
{
|
||||
NetEntity = entry.NetEntity;
|
||||
|
||||
// Load fonts
|
||||
var normalFont = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSansDisplay/NotoSansDisplay-Regular.ttf"), 11);
|
||||
|
||||
// Update supermatter name
|
||||
SupermatterNameLabel.Text = Loc.GetString("supermatter-console-window-label-sm", ("name", entry.EntityName));
|
||||
|
||||
// Update supermatter status
|
||||
SupermatterStatusLabel.Text = Loc.GetString(GetStatusLabel(entry.EntityStatus));
|
||||
SupermatterStatusLabel.FontColorOverride = GetStatusColor(entry.EntityStatus);
|
||||
|
||||
// Focus updates
|
||||
FocusContainer.Visible = isFocus;
|
||||
|
||||
if (isFocus)
|
||||
{
|
||||
if (focusData != null)
|
||||
{
|
||||
var red = StyleNano.DangerousRedFore;
|
||||
var orange = StyleNano.ConcerningOrangeFore;
|
||||
var green = StyleNano.GoodGreenFore;
|
||||
var turqoise = Color.FromHex("#009893");
|
||||
|
||||
// TODO: please don't define this dictionary every update you animal
|
||||
var engineDictionary = new Dictionary<string, (Label label, ProgressBar bar, PanelContainer border, float value, float leftSize, float rightSize, Color leftColor, Color middleColor, Color rightColor)>()
|
||||
{
|
||||
{ "integrity", (IntegrityBarLabel, IntegrityBar, IntegrityBarBorder, focusData.Value.Integrity, 0.9f, 0.1f, red, orange, green) },
|
||||
{ "power", (PowerBarLabel, PowerBar, PowerBarBorder, focusData.Value.Power, 0.9f, 0.1f, green, orange, red ) },
|
||||
{ "radiation", (RadiationBarLabel, RadiationBar, RadiationBarBorder, focusData.Value.Radiation, 0.1f, 0.9f, green, orange, red ) },
|
||||
{ "moles", (MolesBarLabel, MolesBar, MolesBarBorder, focusData.Value.AbsorbedMoles, 0.5f, 0.5f, green, orange, red ) },
|
||||
{ "temperature", (TemperatureBarLabel, TemperatureBar, TemperatureBarBorder, focusData.Value.Temperature, 0.5f, 0.5f, turqoise, green, red ) },
|
||||
{ "waste", (WasteBarLabel, WasteBar, WasteBarBorder, focusData.Value.WasteMultiplier, 0.5f, 0.5f, green, orange, red ) }
|
||||
};
|
||||
|
||||
// Special cases
|
||||
var powerBar = engineDictionary["power"];
|
||||
var powerPrefix = powerBar.value switch { >= 1000 => "G", >= 1 => "M", _ => "" };
|
||||
var powerMultiplier = powerBar.value switch { >= 1000 => 0.001, >= 1 => 1, _ => 1000 };
|
||||
powerBar.label.Text = Loc.GetString("supermatter-console-window-label-power-bar", ("power", (powerBar.value * powerMultiplier).ToString("0.000")), ("prefix", powerPrefix));
|
||||
|
||||
var temperatureLimit = focusData.Value.TemperatureLimit;
|
||||
TemperatureBar.MaxValue = temperatureLimit;
|
||||
TemperatureLimitBarLabel.Text = Loc.GetString("supermatter-console-window-label-temperature-bar", ("temperature", temperatureLimit.ToString("0.00")));
|
||||
|
||||
var absorptionRatio = focusData.Value.AbsorptionRatio;
|
||||
AbsorptionBarLabel.Text = Loc.GetString("supermatter-console-window-label-absorption-bar", ("absorption", absorptionRatio.ToString("0")));
|
||||
|
||||
// Update engine bars
|
||||
foreach (var bar in engineDictionary)
|
||||
{
|
||||
var current = bar.Value;
|
||||
UpdateEngineBar(current.bar, current.border, current.value, current.leftSize, current.rightSize, current.leftColor, current.middleColor, current.rightColor);
|
||||
|
||||
if (bar.Key == "power")
|
||||
continue;
|
||||
|
||||
current.label.Text = Loc.GetString("supermatter-console-window-label-" + bar.Key + "-bar", (bar.Key, current.value.ToString("0.00")));
|
||||
}
|
||||
|
||||
// Update gas bars
|
||||
var atmosphereSystem = _entManager.System<AtmosphereSystem>();
|
||||
var gases = atmosphereSystem.Gases.OrderByDescending(gas => GetStoredGas(gas, focusData));
|
||||
var index = 0;
|
||||
|
||||
foreach (var gas in gases)
|
||||
{
|
||||
var name = gas.Name;
|
||||
var color = Color.FromHex("#" + gas.Color);
|
||||
var value = GetStoredGas(gas, focusData) / focusData.Value.AbsorbedMoles * 100;
|
||||
|
||||
UpdateGasBar(index, GasTable, name, color, value);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetStatusLabel(SupermatterStatusType status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case SupermatterStatusType.Inactive:
|
||||
return "supermatter-console-window-inactive-status";
|
||||
|
||||
case SupermatterStatusType.Normal:
|
||||
return "supermatter-console-window-normal-status";
|
||||
|
||||
case SupermatterStatusType.Caution:
|
||||
return "supermatter-console-window-caution-status";
|
||||
|
||||
case SupermatterStatusType.Warning:
|
||||
return "supermatter-console-window-warning-status";
|
||||
|
||||
case SupermatterStatusType.Danger:
|
||||
return "supermatter-console-window-danger-status";
|
||||
|
||||
case SupermatterStatusType.Emergency:
|
||||
return "supermatter-console-window-emergency-status";
|
||||
|
||||
case SupermatterStatusType.Delaminating:
|
||||
return "supermatter-console-window-delaminating-status";
|
||||
}
|
||||
|
||||
return "supermatter-console-window-error-status";
|
||||
}
|
||||
|
||||
private Color GetStatusColor(SupermatterStatusType status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case SupermatterStatusType.Inactive:
|
||||
return Color.DarkGray;
|
||||
|
||||
case SupermatterStatusType.Normal:
|
||||
return StyleNano.GoodGreenFore;
|
||||
|
||||
case SupermatterStatusType.Caution:
|
||||
case SupermatterStatusType.Warning:
|
||||
return StyleNano.ConcerningOrangeFore;
|
||||
|
||||
case SupermatterStatusType.Danger:
|
||||
case SupermatterStatusType.Emergency:
|
||||
case SupermatterStatusType.Delaminating:
|
||||
return StyleNano.DangerousRedFore;
|
||||
}
|
||||
|
||||
return StyleNano.DisabledFore;
|
||||
}
|
||||
|
||||
private float GetStoredGas(GasPrototype gas, SupermatterFocusData? focusData)
|
||||
{
|
||||
var id = int.Parse(gas.ID);
|
||||
|
||||
if (focusData == null)
|
||||
return 0;
|
||||
|
||||
return focusData.Value.GasStorage[(Gas)id];
|
||||
}
|
||||
|
||||
private void UpdateEngineBar(ProgressBar bar, PanelContainer border, float value, float leftSize, float rightSize, Color leftColor, Color middleColor, Color rightColor)
|
||||
{
|
||||
var clamped = Math.Clamp(value, bar.MinValue, bar.MaxValue);
|
||||
|
||||
var normalized = clamped / bar.MaxValue;
|
||||
var leftHsv = Color.ToHsv(leftColor);
|
||||
var middleHsv = Color.ToHsv(middleColor);
|
||||
var rightHsv = Color.ToHsv(rightColor);
|
||||
|
||||
// Ensure leftSize and rightSize add up to 1.0 or the transition won't be smooth
|
||||
var minColor = new Vector4(0, 0, 0, 0);
|
||||
var maxColor = new Vector4(1, 1, 1, 1);
|
||||
Color finalColor;
|
||||
|
||||
if (normalized <= leftSize)
|
||||
{
|
||||
normalized /= leftSize; // Adjust range to 0.0 to 1.0
|
||||
var calcColor = Vector4.Lerp(leftHsv, middleHsv, normalized);
|
||||
var clampedColor = Vector4.Clamp(calcColor, minColor, maxColor);
|
||||
finalColor = Color.FromHsv(clampedColor);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
normalized = (normalized - leftSize) / rightSize; // Adjust range to 0.0 to 1.0
|
||||
var calcColor = Vector4.Lerp(middleHsv, rightHsv, normalized);
|
||||
var clampedColor = Vector4.Clamp(calcColor, minColor, maxColor);
|
||||
finalColor = Color.FromHsv(clampedColor);
|
||||
}
|
||||
|
||||
// Check if null first to avoid repeatedly creating this.
|
||||
bar.ForegroundStyleBoxOverride ??= new StyleBoxFlat();
|
||||
border.PanelOverride ??= new StyleBoxFlat();
|
||||
|
||||
var barOverride = (StyleBoxFlat)bar.ForegroundStyleBoxOverride;
|
||||
barOverride.BackgroundColor = finalColor;
|
||||
|
||||
var panelOverride = (StyleBoxFlat)border.PanelOverride;
|
||||
panelOverride.BackgroundColor = finalColor;
|
||||
|
||||
bar.Value = clamped;
|
||||
}
|
||||
|
||||
private void UpdateGasBar(int index, Control table, string name, Color color, float value)
|
||||
{
|
||||
// Make new UI entry if required
|
||||
if (index >= table.ChildCount)
|
||||
{
|
||||
var newEntryContainer = new SupermatterGasBarContainer();
|
||||
|
||||
// Add the entry to the current table
|
||||
table.AddChild(newEntryContainer);
|
||||
}
|
||||
|
||||
// Update values and UI elements
|
||||
var tableChild = table.GetChild(index);
|
||||
|
||||
if (tableChild is not SupermatterGasBarContainer)
|
||||
{
|
||||
table.RemoveChild(tableChild);
|
||||
UpdateGasBar(index, table, name, color, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var entryContainer = (SupermatterGasBarContainer)tableChild;
|
||||
|
||||
entryContainer.UpdateEntry(name, color, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<BoxContainer xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Orientation="Vertical" HorizontalExpand ="True">
|
||||
|
||||
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="0 1">
|
||||
<Label Name="GasLabel" Text="{Loc 'supermatter-console-window-label-gas'}" HorizontalExpand="True" HorizontalAlignment="Left" />
|
||||
<PanelContainer Name="GasBarBorder" SetWidth="150" SetHeight="24">
|
||||
<ProgressBar Name="GasBar" MinValue="0" MaxValue="100" HorizontalExpand="True" VerticalExpand="True" Margin="1">
|
||||
<Label Name="GasBarLabel" HorizontalAlignment="Right" Margin="0 0 4 0" />
|
||||
</ProgressBar>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
</BoxContainer>
|
||||
@@ -0,0 +1,47 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client._EE.Supermatter.Consoles;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class SupermatterGasBarContainer : BoxContainer
|
||||
{
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly IResourceCache _cache;
|
||||
|
||||
public SupermatterGasBarContainer()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
_entManager = IoCManager.Resolve<IEntityManager>();
|
||||
_cache = IoCManager.Resolve<IResourceCache>();
|
||||
|
||||
// Load fonts
|
||||
var normalFont = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSansDisplay/NotoSansDisplay-Regular.ttf"), 11);
|
||||
var monoFont = new VectorFont(_cache.GetResource<FontResource>("/EngineFonts/NotoSans/NotoSansMono-Regular.ttf"), 10);
|
||||
|
||||
// Set fonts
|
||||
GasLabel.FontOverride = normalFont;
|
||||
GasBarLabel.FontOverride = monoFont;
|
||||
}
|
||||
|
||||
public void UpdateEntry(string name, Color color, float value)
|
||||
{
|
||||
GasBar.Value = value;
|
||||
GasLabel.Text = Loc.GetString(name) + ":";
|
||||
GasBarLabel.Text = Loc.GetString("supermatter-console-window-label-gas-bar", ("gas", value.ToString("0.00")));
|
||||
|
||||
// Check if null first to avoid repeatedly creating this.
|
||||
GasBar.ForegroundStyleBoxOverride ??= new StyleBoxFlat();
|
||||
GasBarBorder.PanelOverride ??= new StyleBoxFlat();
|
||||
|
||||
var barOverride = (StyleBoxFlat)GasBar.ForegroundStyleBoxOverride;
|
||||
barOverride.BackgroundColor = color;
|
||||
|
||||
var borderOverride = (StyleBoxFlat)GasBarBorder.PanelOverride;
|
||||
borderOverride.BackgroundColor = color;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using System.Numerics;
|
||||
using System.Numerics;
|
||||
using Content.Server.Beam.Components;
|
||||
using Content.Shared.Beam;
|
||||
using Content.Shared.Beam.Components;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics;
|
||||
@@ -83,6 +82,11 @@ public sealed class BeamSystem : SharedBeamSystem
|
||||
if (!TryComp<PhysicsComponent>(ent, out var physics) || !TryComp<BeamComponent>(ent, out var beam))
|
||||
return;
|
||||
|
||||
// imp - start non-randomized lightning sprites
|
||||
if (!beam.AllowSpriteOverwrite)
|
||||
bodyState = null;
|
||||
// imp - end non-randomized lightning sprites
|
||||
|
||||
FixturesComponent? manager = null;
|
||||
_fixture.TryCreateFixture(
|
||||
ent,
|
||||
@@ -146,21 +150,8 @@ public sealed class BeamSystem : SharedBeamSystem
|
||||
if (Deleted(user) || Deleted(target))
|
||||
return;
|
||||
|
||||
var userMapPos = _transform.GetMapCoordinates(user);
|
||||
var targetMapPos = _transform.GetMapCoordinates(target);
|
||||
|
||||
//The distance between the target and the user.
|
||||
var calculatedDistance = targetMapPos.Position - userMapPos.Position;
|
||||
var userAngle = calculatedDistance.ToWorldAngle();
|
||||
|
||||
if (userMapPos.MapId != targetMapPos.MapId)
|
||||
return;
|
||||
|
||||
//Where the start of the beam will spawn
|
||||
var beamStartPos = userMapPos.Offset(calculatedDistance.Normalized());
|
||||
|
||||
//Don't divide by zero
|
||||
if (calculatedDistance.Length() == 0)
|
||||
// imp - Beam creation was changed to a coordinate-to-coordinate method to allow for more flexibility.
|
||||
if (!TryCreateBeam(_transform.GetMapCoordinates(user), _transform.GetMapCoordinates(target), bodyPrototype, bodyState, shader, controller))
|
||||
return;
|
||||
|
||||
if (controller != null && TryComp<BeamComponent>(controller, out var controllerBeamComp))
|
||||
@@ -169,11 +160,95 @@ public sealed class BeamSystem : SharedBeamSystem
|
||||
controllerBeamComp.HitTargets.Add(target);
|
||||
}
|
||||
|
||||
var distanceCorrection = calculatedDistance - calculatedDistance.Normalized();
|
||||
|
||||
CreateBeam(bodyPrototype, userAngle, calculatedDistance, beamStartPos, distanceCorrection, controller, bodyState, shader);
|
||||
|
||||
var ev = new CreateBeamSuccessEvent(user, target);
|
||||
RaiseLocalEvent(user, ev);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called where you want an entity to create a beam from one set of coordinates to another.
|
||||
/// Tries to create the beam and does calculations like the distance, angle, and offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ported from imp
|
||||
/// </remarks>
|
||||
/// <param name="coordinates">The coordinates that the beam is being fired from</param>
|
||||
/// <param name="targetCoordinates">The coordinates that are being targeted</param>
|
||||
/// <param name="bodyPrototype">The prototype spawned when this beam is created</param>
|
||||
/// <param name="bodyState">Optional sprite state for the <see cref="bodyPrototype"/> if a default one is not given</param>
|
||||
/// <param name="shader">Optional shader for the <see cref="bodyPrototype"/> if a default one is not given</param>
|
||||
/// <param name="controller"></param>
|
||||
public bool TryCreateBeam(MapCoordinates coordinates, MapCoordinates targetCoordinates, string bodyPrototype, string? bodyState = null, string shader = "unshaded", EntityUid? controller = null)
|
||||
{
|
||||
//The distance between the target and the user.
|
||||
var calculatedDistance = targetCoordinates.Position - coordinates.Position;
|
||||
var userAngle = calculatedDistance.ToWorldAngle();
|
||||
|
||||
if (coordinates.MapId != targetCoordinates.MapId)
|
||||
return false;
|
||||
|
||||
//Where the start of the beam will spawn
|
||||
var beamStartPos = coordinates.Offset(calculatedDistance.Normalized());
|
||||
|
||||
//Don't divide by zero
|
||||
if (calculatedDistance.Length() == 0)
|
||||
return false;
|
||||
|
||||
var distanceCorrection = calculatedDistance - calculatedDistance.Normalized();
|
||||
|
||||
CreateBeam(bodyPrototype, userAngle, calculatedDistance, beamStartPos, distanceCorrection, controller, bodyState, shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called where you want an entity to create a beam from a set of coordinates to an entity.
|
||||
/// Tries to create the beam and does calculations like the distance, angle, and offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ported from imp
|
||||
/// </remarks>
|
||||
/// <param name="coordinates">The coordinates that the beam is being fired from</param>
|
||||
/// <param name="target">The entity that's being targeted by the user</param>
|
||||
/// <param name="bodyPrototype">The prototype spawned when this beam is created</param>
|
||||
/// <param name="bodyState">Optional sprite state for the <see cref="bodyPrototype"/> if a default one is not given</param>
|
||||
/// <param name="shader">Optional shader for the <see cref="bodyPrototype"/> if a default one is not given</param>
|
||||
/// <param name="controller"></param>
|
||||
public void TryCreateBeam(MapCoordinates coordinates, EntityUid target, string bodyPrototype, string? bodyState = null, string shader = "unshaded", EntityUid? controller = null)
|
||||
{
|
||||
if (Deleted(target))
|
||||
return;
|
||||
|
||||
if (TryCreateBeam(coordinates, _transform.GetMapCoordinates(target), bodyPrototype, bodyState, shader, controller))
|
||||
{
|
||||
if (controller != null && TryComp<BeamComponent>(controller, out var controllerBeamComp))
|
||||
controllerBeamComp.HitTargets.Add(target);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called where you want an entity to create a beam from an entity to a set of coordinates.
|
||||
/// Tries to create the beam and does calculations like the distance, angle, and offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ported from imp
|
||||
/// </remarks>
|
||||
/// <param name="user">The entity that's firing off the beam</param>
|
||||
/// <param name="targetCoordinates">The coordinates that are being targeted</param>
|
||||
/// <param name="bodyPrototype">The prototype spawned when this beam is created</param>
|
||||
/// <param name="bodyState">Optional sprite state for the <see cref="bodyPrototype"/> if a default one is not given</param>
|
||||
/// <param name="shader">Optional shader for the <see cref="bodyPrototype"/> if a default one is not given</param>
|
||||
/// <param name="controller"></param>
|
||||
public void TryCreateBeam(EntityUid user, MapCoordinates targetCoordinates, string bodyPrototype, string? bodyState = null, string shader = "unshaded", EntityUid? controller = null)
|
||||
{
|
||||
if (Deleted(user))
|
||||
return;
|
||||
|
||||
if (TryCreateBeam(_transform.GetMapCoordinates(user), targetCoordinates, bodyPrototype, bodyState, shader, controller))
|
||||
{
|
||||
if (controller != null && TryComp<BeamComponent>(controller, out var controllerBeamComp))
|
||||
controllerBeamComp.HitTargets.Add(user);
|
||||
|
||||
var ev = new CreateBeamSuccessEvent(user, targetCoordinates);
|
||||
RaiseLocalEvent(user, ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Server.Beam.Components;
|
||||
using Content.Server.Lightning.Components;
|
||||
using Content.Shared.Lightning;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Lightning;
|
||||
@@ -21,7 +22,7 @@ public sealed class LightningSystem : SharedLightningSystem
|
||||
[Dependency] private readonly BeamSystem _beam = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -59,6 +60,134 @@ public sealed class LightningSystem : SharedLightningSystem
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires lightning from user to coordinates
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ported from imp
|
||||
/// </remarks>
|
||||
/// <param name="user">Where the lightning fires from</param>
|
||||
/// <param name="targetCoordinates">Where the lightning fires to</param>
|
||||
/// <param name="lightningPrototype">The prototype for the lightning to be created</param>
|
||||
/// <param name="triggerLightningEvents">if the lightnings being fired should trigger lightning events.</param>
|
||||
public void ShootLightning(EntityUid user, MapCoordinates targetCoordinates, string lightningPrototype = "Lightning", bool triggerLightningEvents = true)
|
||||
{
|
||||
var spriteState = LightningRandomizer();
|
||||
_beam.TryCreateBeam(user, targetCoordinates, lightningPrototype, spriteState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires lightning from coordinates to target
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ported from imp
|
||||
/// </remarks>
|
||||
/// <param name="coordinates">Where the lightning fires from</param>
|
||||
/// <param name="target">Where the lightning fires to</param>
|
||||
/// <param name="lightningPrototype">The prototype for the lightning to be created</param>
|
||||
/// <param name="triggerLightningEvents">if the lightnings being fired should trigger lightning events.</param>
|
||||
public void ShootLightning(MapCoordinates coordinates, EntityUid target, string lightningPrototype = "Lightning", bool triggerLightningEvents = true)
|
||||
{
|
||||
var spriteState = LightningRandomizer();
|
||||
_beam.TryCreateBeam(coordinates, target, lightningPrototype, spriteState);
|
||||
|
||||
if (triggerLightningEvents) // we don't want certain prototypes to trigger lightning level events
|
||||
{
|
||||
var ev = new HitByLightningEvent(null, target);
|
||||
RaiseLocalEvent(target, ref ev);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires lightning from coordinates to other coordinates
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ported from imp
|
||||
/// </remarks>
|
||||
/// <param name="coordinates">Where the lightning fires from</param>
|
||||
/// <param name="targetCoordinates">Where the lightning fires to</param>
|
||||
/// <param name="lightningPrototype">The prototype for the lightning to be created</param>
|
||||
/// <param name="triggerLightningEvents">if the lightnings being fired should trigger lightning events.</param>
|
||||
public void ShootLightning(MapCoordinates coordinates, MapCoordinates targetCoordinates, string lightningPrototype = "Lightning", bool triggerLightningEvents = true)
|
||||
{
|
||||
var spriteState = LightningRandomizer();
|
||||
_beam.TryCreateBeam(coordinates, targetCoordinates, lightningPrototype, spriteState);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Looks for objects with a LightningTarget component in the radius, prioritizes them, and hits the highest priority targets with lightning.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ported from imp.
|
||||
/// </remarks>
|
||||
/// <param name="coordinates">Where the lightning fires from</param>
|
||||
/// <param name="range">Targets selection radius</param>
|
||||
/// <param name="boltCount">Number of lightning bolts</param>
|
||||
/// <param name="lightningPrototype">The prototype for the lightning to be created</param>
|
||||
/// <param name="arcDepth">how many times to recursively fire lightning bolts from the target points of the first shot.</param>
|
||||
/// <param name="triggerLightningEvents">if the lightnings being fired should trigger lightning events.</param>
|
||||
/// <param name="hitCoordsChance">Chance for lightning to strike random coordinates instead of an entity.</param>
|
||||
public void ShootRandomLightnings(MapCoordinates coordinates, float range, int boltCount, string lightningPrototype = "Lightning", int arcDepth = 0, bool triggerLightningEvents = true, float hitCoordsChance = 0f, EntityUid? user = null)
|
||||
{
|
||||
//TODO: add support to different priority target tablem for different lightning types
|
||||
//TODO: Remove Hardcode LightningTargetComponent (this should be a parameter of the SharedLightningComponent)
|
||||
//TODO: This is still pretty bad for perf but better than before and at least it doesn't re-allocate
|
||||
// several hashsets every time
|
||||
|
||||
var targets = _lookup.GetEntitiesInRange<LightningTargetComponent>(coordinates, range).ToList();
|
||||
_random.Shuffle(targets);
|
||||
targets.Sort((x, y) => y.Comp.Priority.CompareTo(x.Comp.Priority));
|
||||
|
||||
int shootedCount = 0;
|
||||
int count = -1;
|
||||
int mobLightningResistance = 2; // imp - If the target has a lightning resistance less than or equal to this, the lightning can hit random coordinates instead.
|
||||
while (shootedCount < boltCount)
|
||||
{
|
||||
count++;
|
||||
|
||||
// imp - random coordinate lightning start
|
||||
var outOfRange = count >= targets.Count;
|
||||
var targetLightningResistance = outOfRange ? 0 : targets[count].Comp.LightningResistance;
|
||||
|
||||
if (hitCoordsChance > 0 && targetLightningResistance <= mobLightningResistance && _random.Prob(hitCoordsChance))
|
||||
{
|
||||
var targetCoordinate = coordinates.Offset(_random.NextVector2(range, range));
|
||||
|
||||
if (user != null)
|
||||
ShootLightning(user.Value, targetCoordinate, lightningPrototype, triggerLightningEvents);
|
||||
else
|
||||
ShootLightning(coordinates, targetCoordinate, lightningPrototype, triggerLightningEvents);
|
||||
|
||||
if (arcDepth > 0)
|
||||
{
|
||||
ShootRandomLightnings(targetCoordinate, range, 1, lightningPrototype, arcDepth - 1, triggerLightningEvents, hitCoordsChance, user);
|
||||
}
|
||||
|
||||
shootedCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outOfRange) { break; }
|
||||
// imp - random coordinate lightning end
|
||||
|
||||
var curTarget = targets[count];
|
||||
if (!_random.Prob(curTarget.Comp.HitProbability)) //Chance to ignore target
|
||||
continue;
|
||||
|
||||
// imp - use correct shoot lightning method based on whether this is coordinates-based or entity-based
|
||||
if (user != null)
|
||||
ShootLightning(user.Value, targets[count].Owner, lightningPrototype, triggerLightningEvents);
|
||||
else
|
||||
ShootLightning(coordinates, targets[count].Owner, lightningPrototype, triggerLightningEvents);
|
||||
|
||||
if (arcDepth - targetLightningResistance > 0)
|
||||
{
|
||||
ShootRandomLightnings(targets[count].Owner, range, 1, lightningPrototype, arcDepth - targetLightningResistance, triggerLightningEvents, hitCoordsChance);
|
||||
}
|
||||
shootedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks for objects with a LightningTarget component in the radius, prioritizes them, and hits the highest priority targets with lightning.
|
||||
@@ -69,45 +198,18 @@ public sealed class LightningSystem : SharedLightningSystem
|
||||
/// <param name="lightningPrototype">The prototype for the lightning to be created</param>
|
||||
/// <param name="arcDepth">how many times to recursively fire lightning bolts from the target points of the first shot.</param>
|
||||
/// <param name="triggerLightningEvents">if the lightnings being fired should trigger lightning events.</param>
|
||||
public void ShootRandomLightnings(EntityUid user, float range, int boltCount, string lightningPrototype = "Lightning", int arcDepth = 0, bool triggerLightningEvents = true)
|
||||
/// <param name="hitCoordsChance">Chance for lightning to strike random coordinates instead of an entity.</param>
|
||||
public void ShootRandomLightnings(EntityUid user, float range, int boltCount, string lightningPrototype = "Lightning", int arcDepth = 0, bool triggerLightningEvents = true, float hitCoordsChance = 0f)
|
||||
{
|
||||
//To Do: add support to different priority target tablem for different lightning types
|
||||
//To Do: Remove Hardcode LightningTargetComponent (this should be a parameter of the SharedLightningComponent)
|
||||
//To Do: This is still pretty bad for perf but better than before and at least it doesn't re-allocate
|
||||
// several hashsets every time
|
||||
var mapCoords = _transform.GetMapCoordinates(user);
|
||||
var targets = _lookup.GetEntitiesInRange<LightningTargetComponent>(mapCoords, range).ToList();
|
||||
_random.Shuffle(targets);
|
||||
targets.Sort((x, y) => y.Comp.Priority.CompareTo(x.Comp.Priority));
|
||||
|
||||
int shotCount = 0;
|
||||
int count = -1;
|
||||
|
||||
while (shotCount < boltCount)
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count >= targets.Count) { break; }
|
||||
var curTarget = targets[count];
|
||||
|
||||
// Chance to ignore target
|
||||
if (!_random.Prob(curTarget.Comp.HitProbability))
|
||||
continue;
|
||||
|
||||
ShootLightning(user, targets[count].Owner, lightningPrototype, triggerLightningEvents);
|
||||
|
||||
if (arcDepth - targets[count].Comp.LightningResistance > 0)
|
||||
ShootRandomLightnings(targets[count].Owner, range, 1, lightningPrototype, arcDepth - targets[count].Comp.LightningResistance, triggerLightningEvents);
|
||||
|
||||
shotCount++;
|
||||
}
|
||||
// imp - Redirect to the other function for compatibility
|
||||
ShootRandomLightnings(_transform.GetMapCoordinates(user), range, boltCount, lightningPrototype, arcDepth, triggerLightningEvents, hitCoordsChance, user);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on the target when an entity becomes the target of a lightning strike (not when touched)
|
||||
/// </summary>
|
||||
/// <param name="Source">The entity that created the lightning</param>
|
||||
/// <param name="Source">The entity that created the lightning. May be null if the lightning came from coordinates rather than an entity.</param>
|
||||
/// <param name="Target">The entity that was struck by lightning.</param>
|
||||
[ByRefEvent]
|
||||
public readonly record struct HitByLightningEvent(EntityUid Source, EntityUid Target);
|
||||
public readonly record struct HitByLightningEvent(EntityUid? Source, EntityUid Target); // imp - Lightning might come from coordinates instead of an entity, so Source can be null
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
using Content.Server.Pinpointer;
|
||||
using Content.Shared._EE.Supermatter.Components;
|
||||
using Content.Shared._EE.Supermatter.Consoles;
|
||||
using Content.Shared._EE.Supermatter.Monitor;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Pinpointer;
|
||||
using Content.Shared.Radiation.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Map.Components;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server._EE.Supermatter.Console.Systems;
|
||||
|
||||
public sealed class SupermatterConsoleSystem : SharedSupermatterConsoleSystem
|
||||
{
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly NavMapSystem _navMapSystem = default!;
|
||||
|
||||
private const float UpdateTime = 1.0f;
|
||||
|
||||
// Note: this data does not need to be saved
|
||||
private float _updateTimer = 1.0f;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
// Console events
|
||||
SubscribeLocalEvent<SupermatterConsoleComponent, ComponentInit>(OnConsoleInit);
|
||||
SubscribeLocalEvent<SupermatterConsoleComponent, EntParentChangedMessage>(OnConsoleParentChanged);
|
||||
SubscribeLocalEvent<SupermatterConsoleComponent, SupermatterConsoleFocusChangeMessage>(OnFocusChangedMessage);
|
||||
|
||||
// Grid events
|
||||
SubscribeLocalEvent<GridSplitEvent>(OnGridSplit);
|
||||
}
|
||||
|
||||
#region Event handling
|
||||
|
||||
private void OnConsoleInit(EntityUid uid, SupermatterConsoleComponent component, ComponentInit args)
|
||||
{
|
||||
InitalizeConsole(uid, component);
|
||||
}
|
||||
|
||||
private void OnConsoleParentChanged(EntityUid uid, SupermatterConsoleComponent component, EntParentChangedMessage args)
|
||||
{
|
||||
InitalizeConsole(uid, component);
|
||||
}
|
||||
|
||||
private void OnFocusChangedMessage(EntityUid uid, SupermatterConsoleComponent component, SupermatterConsoleFocusChangeMessage args)
|
||||
{
|
||||
component.FocusSupermatter = args.FocusSupermatter;
|
||||
}
|
||||
|
||||
private void OnGridSplit(ref GridSplitEvent args)
|
||||
{
|
||||
// Collect grids
|
||||
var allGrids = args.NewGrids.ToList();
|
||||
|
||||
if (!allGrids.Contains(args.Grid))
|
||||
allGrids.Add(args.Grid);
|
||||
|
||||
// Update supermatter monitoring consoles that stand upon an updated grid
|
||||
var query = AllEntityQuery<SupermatterConsoleComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var ent, out var entConsole, out var entXform))
|
||||
{
|
||||
if (entXform.GridUid == null)
|
||||
continue;
|
||||
|
||||
if (!allGrids.Contains(entXform.GridUid.Value))
|
||||
continue;
|
||||
|
||||
InitalizeConsole(ent, entConsole);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
// Keep a list of UI entries for each gridUid, in case multiple consoles stand on the same grid
|
||||
var supermatterEntriesForEachGrid = new Dictionary<EntityUid, SupermatterConsoleEntry[]>();
|
||||
|
||||
var query = AllEntityQuery<SupermatterConsoleComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var ent, out var entConsole, out var entXform))
|
||||
{
|
||||
if (entXform?.GridUid == null)
|
||||
continue;
|
||||
|
||||
// Make a list of alarm state data for all the supermatters on the grid
|
||||
if (!supermatterEntriesForEachGrid.TryGetValue(entXform.GridUid.Value, out var supermatterEntries))
|
||||
{
|
||||
supermatterEntries = GetSupermatterStateData(entXform.GridUid.Value).ToArray();
|
||||
supermatterEntriesForEachGrid[entXform.GridUid.Value] = supermatterEntries;
|
||||
}
|
||||
|
||||
// Determine the highest level of status for the console
|
||||
var highestStatus = SupermatterStatusType.Inactive;
|
||||
|
||||
foreach (var entry in supermatterEntries)
|
||||
{
|
||||
var status = entry.EntityStatus;
|
||||
|
||||
if (status > highestStatus)
|
||||
highestStatus = status;
|
||||
}
|
||||
|
||||
// Update the appearance of the console based on the highest recorded level of alert
|
||||
if (TryComp<AppearanceComponent>(ent, out var entAppearance))
|
||||
_appearance.SetData(ent, SupermatterConsoleVisuals.ComputerLayerScreen, (int)highestStatus, entAppearance);
|
||||
|
||||
// If the console UI is open, send UI data to each subscribed session
|
||||
UpdateUIState(ent, supermatterEntries, entConsole, entXform);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateUIState
|
||||
(EntityUid uid,
|
||||
SupermatterConsoleEntry[] supermatterStateData,
|
||||
SupermatterConsoleComponent component,
|
||||
TransformComponent xform)
|
||||
{
|
||||
if (!_userInterfaceSystem.IsUiOpen(uid, SupermatterConsoleUiKey.Key))
|
||||
return;
|
||||
|
||||
var gridUid = xform.GridUid!.Value;
|
||||
|
||||
// Gathering remaining data to be send to the client
|
||||
var focusSupermatterData = GetFocusSupermatterData(uid, GetEntity(component.FocusSupermatter), gridUid);
|
||||
|
||||
// Set the UI state
|
||||
_userInterfaceSystem.SetUiState(uid, SupermatterConsoleUiKey.Key,
|
||||
new SupermatterConsoleBoundInterfaceState(supermatterStateData, focusSupermatterData));
|
||||
}
|
||||
|
||||
private List<SupermatterConsoleEntry> GetSupermatterStateData(EntityUid gridUid)
|
||||
{
|
||||
var supermatterStateData = new List<SupermatterConsoleEntry>();
|
||||
|
||||
var querySupermatters = AllEntityQuery<SupermatterComponent, TransformComponent>();
|
||||
while (querySupermatters.MoveNext(out var ent, out var entSupermatter, out var entXform))
|
||||
{
|
||||
if (entXform.GridUid != gridUid)
|
||||
continue;
|
||||
|
||||
if (!entXform.Anchored)
|
||||
continue;
|
||||
|
||||
// Create entry
|
||||
var netEnt = GetNetEntity(ent);
|
||||
|
||||
var entry = new SupermatterConsoleEntry
|
||||
(netEnt,
|
||||
MetaData(ent).EntityName,
|
||||
entSupermatter.Status);
|
||||
|
||||
supermatterStateData.Add(entry);
|
||||
}
|
||||
|
||||
return supermatterStateData;
|
||||
}
|
||||
|
||||
private SupermatterFocusData? GetFocusSupermatterData(EntityUid uid, EntityUid? focusSupermatter, EntityUid gridUid)
|
||||
{
|
||||
if (focusSupermatter == null)
|
||||
return null;
|
||||
|
||||
var focusSupermatterXform = Transform(focusSupermatter.Value);
|
||||
|
||||
if (!focusSupermatterXform.Anchored ||
|
||||
focusSupermatterXform.GridUid != gridUid ||
|
||||
!TryComp<SupermatterComponent>(focusSupermatter.Value, out var focusComp))
|
||||
return null;
|
||||
|
||||
if (!TryComp<SupermatterComponent>(focusSupermatter.Value, out var sm))
|
||||
return null;
|
||||
|
||||
if (!TryComp<RadiationSourceComponent>(focusSupermatter.Value, out var radiationComp))
|
||||
return null;
|
||||
|
||||
var gases = sm.GasStorage;
|
||||
var tempThreshold = Atmospherics.T0C + sm.HeatPenaltyThreshold;
|
||||
|
||||
return new SupermatterFocusData(
|
||||
GetNetEntity(focusSupermatter.Value),
|
||||
GetIntegrity(sm),
|
||||
sm.Power,
|
||||
radiationComp.Intensity,
|
||||
gases.Sum(gas => gases[gas.Key]),
|
||||
sm.Temperature,
|
||||
tempThreshold * sm.DynamicHeatResistance,
|
||||
sm.WasteMultiplier,
|
||||
sm.GasEfficiency * 100,
|
||||
sm.GasStorage);
|
||||
}
|
||||
|
||||
public float GetIntegrity(SupermatterComponent sm)
|
||||
{
|
||||
var integrity = sm.Damage / sm.DamageDelaminationPoint;
|
||||
integrity = (float)Math.Round(100 - integrity * 100, 2);
|
||||
integrity = integrity < 0 ? 0 : integrity;
|
||||
return integrity;
|
||||
}
|
||||
|
||||
private void InitalizeConsole(EntityUid uid, SupermatterConsoleComponent component)
|
||||
{
|
||||
var xform = Transform(uid);
|
||||
|
||||
if (xform.GridUid == null)
|
||||
return;
|
||||
|
||||
Dirty(uid, component);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,25 @@
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Radiation.Components;
|
||||
using Content.Shared.Supermatter.Components;
|
||||
using System.Text;
|
||||
using Content.Shared.Chat;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Sound.Components;
|
||||
using Content.Shared._EE.CCVars;
|
||||
using Content.Shared._EE.Supermatter.Components;
|
||||
using Content.Shared._EE.Supermatter.Monitor;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Radiation.Components;
|
||||
using Content.Shared.Speech;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Supermatter.Systems;
|
||||
namespace Content.Server._EE.Supermatter.Systems;
|
||||
|
||||
public sealed partial class SupermatterSystem
|
||||
{
|
||||
@@ -97,11 +109,16 @@ public sealed partial class SupermatterSystem
|
||||
|
||||
// Irradiate stuff
|
||||
if (TryComp<RadiationSourceComponent>(uid, out var rad))
|
||||
{
|
||||
rad.Intensity =
|
||||
sm.Power
|
||||
_config.GetCVar(ECCVars.SupermatterRadsBase) +
|
||||
(sm.Power
|
||||
* Math.Max(0, 1f + transmissionBonus / 10f)
|
||||
* 0.003f
|
||||
* _config.GetCVar(CCVars.SupermatterRadsModifier);
|
||||
* _config.GetCVar(ECCVars.SupermatterRadsModifier));
|
||||
|
||||
rad.Slope = Math.Clamp(rad.Intensity / 15, 0.2f, 1f);
|
||||
}
|
||||
|
||||
// Power * 0.55 * 0.8~1
|
||||
// This has to be differentiated with respect to time, since its going to be interacting with systems
|
||||
@@ -126,6 +143,14 @@ public sealed partial class SupermatterSystem
|
||||
// After this point power is lowered
|
||||
// This wraps around to the begining of the function
|
||||
sm.Power = Math.Max(sm.Power - Math.Min(powerReduction * powerlossInhibitor, sm.Power * 0.83f * powerlossInhibitor), 0f);
|
||||
|
||||
// Save values to the supermatter
|
||||
sm.GasStorage = sm.GasStorage.ToDictionary(
|
||||
gas => gas.Key,
|
||||
gas => absorbedGas.GetMoles(gas.Key)
|
||||
);
|
||||
sm.Temperature = absorbedGas.Temperature;
|
||||
sm.WasteMultiplier = heatModifier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -133,10 +158,35 @@ public sealed partial class SupermatterSystem
|
||||
/// </summary>
|
||||
private void SupermatterZap(EntityUid uid, SupermatterComponent sm)
|
||||
{
|
||||
// Divide power by its' threshold to get a value from 0-1, then multiply by the amount of possible lightnings
|
||||
var zapPower = sm.Power / sm.PowerPenaltyThreshold * sm.LightningPrototypes.Length;
|
||||
var zapPowerNorm = (int) Math.Clamp(zapPower, 0, sm.LightningPrototypes.Length - 1);
|
||||
_lightning.ShootRandomLightnings(uid, 3.5f, sm.Power > sm.PowerPenaltyThreshold ? 3 : 1, sm.LightningPrototypes[zapPowerNorm]);
|
||||
var zapPower = 0;
|
||||
var zapCount = 0;
|
||||
var zapRange = Math.Clamp(sm.Power / 1000, 2, 7);
|
||||
|
||||
// fuck this
|
||||
if (_random.Prob(0.05f))
|
||||
{
|
||||
zapCount += 1;
|
||||
}
|
||||
|
||||
if (sm.Power >= sm.PowerPenaltyThreshold)
|
||||
{
|
||||
zapCount += 2;
|
||||
}
|
||||
|
||||
if (sm.Power >= sm.SeverePowerPenaltyThreshold)
|
||||
{
|
||||
zapPower = 1;
|
||||
zapCount++;
|
||||
}
|
||||
|
||||
if (sm.Power >= sm.CriticalPowerPenaltyThreshold)
|
||||
{
|
||||
zapPower = 2;
|
||||
zapCount++;
|
||||
}
|
||||
|
||||
if (zapCount >= 1)
|
||||
_lightning.ShootRandomLightnings(uid, zapRange, zapCount, sm.LightningPrototypes[zapPower], hitCoordsChance: sm.ZapHitCoordinatesChance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -184,20 +234,16 @@ public sealed partial class SupermatterSystem
|
||||
totalDamage += powerDamage;
|
||||
|
||||
// Mol count only starts affecting damage when it is above 1800
|
||||
var moleDamage = Math.Max(moles - sm.MolePenaltyThreshold, 0) / 80 * sm.DamageIncreaseMultiplier;
|
||||
var moleDamage = Math.Max(moles - sm.MolePenaltyThreshold, 0f) / 80 * sm.DamageIncreaseMultiplier;
|
||||
totalDamage += moleDamage;
|
||||
|
||||
// Healing damage
|
||||
if (moles < sm.MolePenaltyThreshold)
|
||||
{
|
||||
// There's a very small float so that it doesn't divide by 0
|
||||
var healHeatDamage = Math.Min(absorbedGas.Temperature - tempThreshold, 0.001f) / 150;
|
||||
var healHeatDamage = Math.Min(absorbedGas.Temperature - tempThreshold, 0f) / 150;
|
||||
totalDamage += healHeatDamage;
|
||||
}
|
||||
|
||||
// Return the manipulated gas back to the mix
|
||||
_atmosphere.Merge(mix, absorbedGas);
|
||||
|
||||
// Check for space tiles next to SM
|
||||
//TODO: Change moles out for checking if adjacent tiles exist
|
||||
var enumerator = _atmosphere.GetAdjacentTileMixtures(xform.GridUid.Value, indices, false, false);
|
||||
@@ -217,12 +263,12 @@ public sealed partial class SupermatterSystem
|
||||
_ => 0f
|
||||
};
|
||||
|
||||
totalDamage += Math.Clamp(sm.Power * factor * sm.DamageIncreaseMultiplier, 0, sm.MaxSpaceExposureDamage);
|
||||
totalDamage += Math.Clamp(sm.Power * factor * sm.DamageIncreaseMultiplier, 0f, sm.MaxSpaceExposureDamage);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
var damage = Math.Min(sm.DamageArchived + sm.DamageHardcap * sm.DamageDelaminationPoint, totalDamage);
|
||||
var damage = Math.Min(sm.DamageArchived + sm.DamageHardcap * sm.DamageDelaminationPoint, sm.Damage + totalDamage);
|
||||
|
||||
// Prevent it from going negative
|
||||
sm.Damage = Math.Clamp(damage, 0, float.PositiveInfinity);
|
||||
@@ -233,19 +279,16 @@ public sealed partial class SupermatterSystem
|
||||
/// </summary>
|
||||
private void AnnounceCoreDamage(EntityUid uid, SupermatterComponent sm)
|
||||
{
|
||||
// If undamaged, no need to announce anything
|
||||
if (sm.Damage == 0)
|
||||
return;
|
||||
|
||||
var message = string.Empty;
|
||||
var global = false;
|
||||
|
||||
var integrity = GetIntegrity(sm).ToString("0.00");
|
||||
|
||||
// Special cases
|
||||
if (sm.Damage < sm.DamageDelaminationPoint && sm.Delamming)
|
||||
{
|
||||
message = Loc.GetString("supermatter-delam-cancel", ("integrity", integrity));
|
||||
sm.DelamAnnounced = false;
|
||||
global = true;
|
||||
}
|
||||
|
||||
// Instantly announce delamination
|
||||
if (sm.Delamming && !sm.DelamAnnounced)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
@@ -259,18 +302,73 @@ public sealed partial class SupermatterSystem
|
||||
default: loc = "supermatter-delam-explosion"; break;
|
||||
}
|
||||
|
||||
var station = _station.GetOwningStation(uid);
|
||||
if (station != null)
|
||||
_alert.SetLevel((EntityUid) station, sm.AlertCodeDeltaId, true, true, true, false);
|
||||
|
||||
sb.AppendLine(Loc.GetString(loc));
|
||||
sb.AppendLine(Loc.GetString("supermatter-seconds-before-delam", ("seconds", sm.DelamTimer)));
|
||||
sb.Append(Loc.GetString("supermatter-seconds-before-delam", ("seconds", sm.DelamTimer)));
|
||||
|
||||
message = sb.ToString();
|
||||
global = true;
|
||||
sm.DelamAnnounced = true;
|
||||
sm.YellTimer = TimeSpan.FromSeconds(sm.DelamTimer / 2);
|
||||
|
||||
SendSupermatterAnnouncement(uid, message, global);
|
||||
SendSupermatterAnnouncement(uid, sm, message, global);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only announce every YellTimer seconds
|
||||
if (_timing.CurTime < sm.YellLast + sm.YellTimer)
|
||||
return;
|
||||
|
||||
// Recovered after the delamination point
|
||||
if (sm.Damage < sm.DamageDelaminationPoint && sm.DelamAnnounced)
|
||||
{
|
||||
message = Loc.GetString("supermatter-delam-cancel", ("integrity", integrity));
|
||||
sm.DelamAnnounced = false;
|
||||
sm.YellTimer = TimeSpan.FromSeconds(_config.GetCVar(ECCVars.SupermatterYellTimer));
|
||||
global = true;
|
||||
|
||||
SendSupermatterAnnouncement(uid, sm, message, global);
|
||||
return;
|
||||
}
|
||||
|
||||
// Oh god oh fuck
|
||||
if (sm.Delamming && sm.DelamAnnounced)
|
||||
{
|
||||
var seconds = Math.Ceiling(sm.DelamEndTime.TotalSeconds - _timing.CurTime.TotalSeconds);
|
||||
|
||||
if (seconds <= 0)
|
||||
return;
|
||||
|
||||
var loc = seconds switch
|
||||
{
|
||||
> 5 => "supermatter-seconds-before-delam-countdown",
|
||||
<= 5 => "supermatter-seconds-before-delam-imminent",
|
||||
_ => String.Empty
|
||||
};
|
||||
|
||||
sm.YellTimer = seconds switch
|
||||
{
|
||||
> 30 => TimeSpan.FromSeconds(10),
|
||||
> 5 => TimeSpan.FromSeconds(5),
|
||||
<= 5 => TimeSpan.FromSeconds(1),
|
||||
_ => TimeSpan.FromSeconds(_config.GetCVar(ECCVars.SupermatterYellTimer))
|
||||
};
|
||||
|
||||
message = Loc.GetString(loc, ("seconds", seconds));
|
||||
global = true;
|
||||
|
||||
SendSupermatterAnnouncement(uid, sm, message, global);
|
||||
return;
|
||||
}
|
||||
|
||||
// We're safe
|
||||
if (sm.Damage < sm.DamageArchived && sm.Status >= SupermatterStatusType.Warning)
|
||||
{
|
||||
message = Loc.GetString("supermatter-healing", ("integrity", integrity));
|
||||
|
||||
if (sm.Status >= SupermatterStatusType.Emergency)
|
||||
global = true;
|
||||
|
||||
SendSupermatterAnnouncement(uid, sm, message, global);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -292,21 +390,27 @@ public sealed partial class SupermatterSystem
|
||||
}
|
||||
}
|
||||
|
||||
SendSupermatterAnnouncement(uid, message, global);
|
||||
SendSupermatterAnnouncement(uid, sm, message, global);
|
||||
}
|
||||
|
||||
/// <param name="global">If true, sends a station announcement</param>
|
||||
/// <param name="global">If true, sends the message to the common radio</param>
|
||||
/// <param name="customSender">Localisation string for a custom announcer name</param>
|
||||
public void SendSupermatterAnnouncement(EntityUid uid, string message, bool global = false, string? customSender = null)
|
||||
public void SendSupermatterAnnouncement(EntityUid uid, SupermatterComponent sm, string message, bool global = false)
|
||||
{
|
||||
if (global)
|
||||
{
|
||||
var sender = Loc.GetString(customSender != null ? customSender : "supermatter-announcer");
|
||||
_chat.DispatchStationAnnouncement(uid, message, sender, colorOverride: Color.Yellow);
|
||||
if (message == String.Empty)
|
||||
return;
|
||||
}
|
||||
|
||||
var channel = sm.Channel;
|
||||
|
||||
if (global)
|
||||
channel = sm.ChannelGlobal;
|
||||
|
||||
// Ensure status, otherwise the wrong speech sound may be used
|
||||
HandleStatus(uid, sm);
|
||||
|
||||
sm.YellLast = _timing.CurTime;
|
||||
_chat.TrySendInGameICMessage(uid, message, InGameICChatType.Speak, hideChat: false, checkRadioPrefix: true);
|
||||
_radio.SendRadioMessage(uid, message, channel, uid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -325,8 +429,8 @@ public sealed partial class SupermatterSystem
|
||||
/// </summary>
|
||||
public DelamType ChooseDelamType(EntityUid uid, SupermatterComponent sm)
|
||||
{
|
||||
if (_config.GetCVar(CCVars.SupermatterDoForceDelam))
|
||||
return _config.GetCVar(CCVars.SupermatterForcedDelamType);
|
||||
if (_config.GetCVar(ECCVars.SupermatterDoForceDelam))
|
||||
return _config.GetCVar(ECCVars.SupermatterForcedDelamType);
|
||||
|
||||
var mix = _atmosphere.GetContainingMixture(uid, true, true);
|
||||
|
||||
@@ -335,13 +439,13 @@ public sealed partial class SupermatterSystem
|
||||
var absorbedGas = mix.Remove(sm.GasEfficiency * mix.TotalMoles);
|
||||
var moles = absorbedGas.TotalMoles;
|
||||
|
||||
if (_config.GetCVar(CCVars.SupermatterDoSingulooseDelam)
|
||||
&& moles >= sm.MolePenaltyThreshold * _config.GetCVar(CCVars.SupermatterSingulooseMolesModifier))
|
||||
if (_config.GetCVar(ECCVars.SupermatterDoSingulooseDelam)
|
||||
&& moles >= sm.MolePenaltyThreshold * _config.GetCVar(ECCVars.SupermatterSingulooseMolesModifier))
|
||||
return DelamType.Singulo;
|
||||
}
|
||||
|
||||
if (_config.GetCVar(CCVars.SupermatterDoTeslooseDelam)
|
||||
&& sm.Power >= sm.PowerPenaltyThreshold * _config.GetCVar(CCVars.SupermatterTesloosePowerModifier))
|
||||
if (_config.GetCVar(ECCVars.SupermatterDoTeslooseDelam)
|
||||
&& sm.Power >= sm.PowerPenaltyThreshold * _config.GetCVar(ECCVars.SupermatterTesloosePowerModifier))
|
||||
return DelamType.Tesla;
|
||||
|
||||
//TODO: Add resonance cascade when there's crazy conditions or a destabilizing crystal
|
||||
@@ -361,6 +465,7 @@ public sealed partial class SupermatterSystem
|
||||
if (!sm.Delamming)
|
||||
{
|
||||
sm.Delamming = true;
|
||||
sm.DelamEndTime = _timing.CurTime + TimeSpan.FromSeconds(sm.DelamTimer);
|
||||
AnnounceCoreDamage(uid, sm);
|
||||
}
|
||||
|
||||
@@ -370,11 +475,23 @@ public sealed partial class SupermatterSystem
|
||||
AnnounceCoreDamage(uid, sm);
|
||||
}
|
||||
|
||||
sm.DelamTimerAccumulator++;
|
||||
|
||||
if (sm.DelamTimerAccumulator < sm.DelamTimer)
|
||||
if (_timing.CurTime < sm.DelamEndTime)
|
||||
return;
|
||||
|
||||
var smTransform = Transform(uid);
|
||||
|
||||
foreach (var pSession in Filter.GetAllPlayers())
|
||||
{
|
||||
var pEntity = pSession.AttachedEntity;
|
||||
|
||||
if (pEntity != null
|
||||
&& TryComp<TransformComponent>(pEntity, out var pTransform)
|
||||
&& pTransform.MapID == smTransform.MapID)
|
||||
_popup.PopupEntity(Loc.GetString("supermatter-delam-player"), pEntity.Value, pEntity.Value, PopupType.MediumCaution);
|
||||
}
|
||||
|
||||
_audio.PlayGlobal(sm.DistortSound, Filter.BroadcastMap(Transform(uid).MapID), true);
|
||||
|
||||
switch (sm.PreferredDelamType)
|
||||
{
|
||||
case DelamType.Cascade:
|
||||
@@ -395,6 +512,55 @@ public sealed partial class SupermatterSystem
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the supermatter's status and speech sound based on thresholds
|
||||
/// </summary>
|
||||
private void HandleStatus(EntityUid uid, SupermatterComponent sm)
|
||||
{
|
||||
var currentStatus = GetStatus(uid, sm);
|
||||
|
||||
if (sm.Status != currentStatus)
|
||||
{
|
||||
sm.Status = currentStatus;
|
||||
|
||||
if (!TryComp<SpeechComponent>(uid, out var speech))
|
||||
return;
|
||||
|
||||
sm.StatusCurrentSound = currentStatus switch
|
||||
{
|
||||
SupermatterStatusType.Warning => sm.StatusWarningSound,
|
||||
SupermatterStatusType.Danger => sm.StatusDangerSound,
|
||||
SupermatterStatusType.Emergency => sm.StatusEmergencySound,
|
||||
SupermatterStatusType.Delaminating => sm.StatusDelamSound,
|
||||
_ => null
|
||||
};
|
||||
|
||||
ProtoId<SpeechSoundsPrototype>? speechSound = sm.StatusCurrentSound;
|
||||
|
||||
if (currentStatus == SupermatterStatusType.Warning)
|
||||
speech.AudioParams = AudioParams.Default.AddVolume(7.5f);
|
||||
else
|
||||
speech.AudioParams = AudioParams.Default.AddVolume(10f);
|
||||
|
||||
if (currentStatus == SupermatterStatusType.Delaminating)
|
||||
speech.SoundCooldownTime = 6.8f; // approximate length of bloblarm.ogg
|
||||
else
|
||||
speech.SoundCooldownTime = 0.0f;
|
||||
|
||||
speech.SpeechSounds = speechSound;
|
||||
}
|
||||
|
||||
// Supermatter is healing, don't play any speech sounds
|
||||
if (sm.Damage < sm.DamageArchived)
|
||||
{
|
||||
if (!TryComp<SpeechComponent>(uid, out var speech))
|
||||
return;
|
||||
|
||||
sm.StatusCurrentSound = null;
|
||||
speech.SpeechSounds = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swaps out ambience sounds when the SM is delamming or not.
|
||||
/// </summary>
|
||||
@@ -405,13 +571,48 @@ public sealed partial class SupermatterSystem
|
||||
if (ambient == null)
|
||||
return;
|
||||
|
||||
if (sm.Delamming && sm.CurrentSoundLoop != sm.DelamSound)
|
||||
sm.CurrentSoundLoop = sm.DelamSound;
|
||||
var volume = (float) Math.Round(Math.Clamp((sm.Power / 50) - 5, -5, 5));
|
||||
|
||||
else if (!sm.Delamming && sm.CurrentSoundLoop != sm.CalmSound)
|
||||
sm.CurrentSoundLoop = sm.CalmSound;
|
||||
_ambient.SetVolume(uid, volume);
|
||||
|
||||
if (sm.Status >= SupermatterStatusType.Danger && sm.CurrentSoundLoop != sm.DelamLoopSound)
|
||||
sm.CurrentSoundLoop = sm.DelamLoopSound;
|
||||
|
||||
else if (sm.Status < SupermatterStatusType.Danger && sm.CurrentSoundLoop != sm.CalmLoopSound)
|
||||
sm.CurrentSoundLoop = sm.CalmLoopSound;
|
||||
|
||||
if (ambient.Sound != sm.CurrentSoundLoop)
|
||||
_ambient.SetSound(uid, sm.CurrentSoundLoop, ambient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays normal/delam sounds at a rate determined by power and damage
|
||||
/// </summary>
|
||||
private void HandleAccent(EntityUid uid, SupermatterComponent sm)
|
||||
{
|
||||
var emit = Comp<EmitSoundOnTriggerComponent>(uid);
|
||||
|
||||
if (emit == null)
|
||||
return;
|
||||
|
||||
if (sm.AccentLastTime >= _timing.CurTime || !_random.Prob(0.05f))
|
||||
return;
|
||||
|
||||
var aggression = Math.Min((sm.Damage / 800) * (sm.Power / 2500), 1) * 100;
|
||||
var nextSound = Math.Max(Math.Round((100 - aggression) * 5), sm.AccentMinCooldown);
|
||||
|
||||
if (sm.AccentLastTime + TimeSpan.FromSeconds(nextSound) > _timing.CurTime)
|
||||
return;
|
||||
|
||||
if (sm.Status >= SupermatterStatusType.Danger && emit.Sound != sm.DelamAccent)
|
||||
emit.Sound = sm.DelamAccent;
|
||||
|
||||
else if (sm.Status < SupermatterStatusType.Danger && emit.Sound != sm.CalmAccent)
|
||||
emit.Sound = sm.CalmAccent;
|
||||
|
||||
sm.AccentLastTime = _timing.CurTime;
|
||||
|
||||
var ev = new TriggerEvent(uid);
|
||||
RaiseLocalEvent(uid, ev);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,46 @@
|
||||
using Content.Server.AlertLevel;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Atmos.Piping.Components;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Decals;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Kitchen.Components;
|
||||
using Content.Server.Lightning;
|
||||
using Content.Server.Lightning.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Radio.EntitySystems;
|
||||
using Content.Server.Speech;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared._EE.CCVars;
|
||||
using Content.Shared._EE.Supermatter.Components;
|
||||
using Content.Shared._EE.Supermatter.Monitor;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Projectiles;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Server.GameObjects;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Projectiles;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Shared.Supermatter.Components;
|
||||
using Content.Server.Lightning;
|
||||
using Content.Server.AlertLevel;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.Kitchen.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Audio;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Supermatter.Systems;
|
||||
namespace Content.Server._EE.Supermatter.Systems;
|
||||
|
||||
public sealed partial class SupermatterSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
[Dependency] private readonly RadioSystem _radio = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly ExplosionSystem _explosion = default!;
|
||||
[Dependency] private readonly TransformSystem _xform = default!;
|
||||
@@ -36,10 +49,13 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
[Dependency] private readonly LightningSystem _lightning = default!;
|
||||
[Dependency] private readonly AlertLevelSystem _alert = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
[Dependency] private readonly MapSystem _map = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly IConfigurationManager _config = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
@@ -47,6 +63,7 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SupermatterComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<SupermatterComponent, AtmosDeviceUpdateEvent>(OnSupermatterUpdated);
|
||||
|
||||
SubscribeLocalEvent<SupermatterComponent, StartCollideEvent>(OnCollideEvent);
|
||||
SubscribeLocalEvent<SupermatterComponent, InteractHandEvent>(OnHandInteract);
|
||||
@@ -55,56 +72,22 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
SubscribeLocalEvent<SupermatterComponent, SupermatterDoAfterEvent>(OnGetSliver);
|
||||
}
|
||||
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
foreach (var sm in EntityManager.EntityQuery<SupermatterComponent>())
|
||||
{
|
||||
if (!sm.Activated)
|
||||
return;
|
||||
|
||||
var uid = sm.Owner;
|
||||
sm.UpdateAccumulator += frameTime;
|
||||
|
||||
if (sm.UpdateAccumulator >= sm.UpdateTimer)
|
||||
{
|
||||
sm.UpdateAccumulator -= sm.UpdateTimer;
|
||||
Cycle(uid, sm, frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Cycle(EntityUid uid, SupermatterComponent sm, float frameTime)
|
||||
{
|
||||
sm.ZapAccumulator++;
|
||||
sm.YellAccumulator++;
|
||||
|
||||
ProcessAtmos(uid, sm, frameTime);
|
||||
HandleDamage(uid, sm);
|
||||
|
||||
if (sm.Damage >= sm.DamageDelaminationPoint || sm.Delamming)
|
||||
HandleDelamination(uid, sm);
|
||||
|
||||
HandleSoundLoop(uid, sm);
|
||||
|
||||
if (sm.ZapAccumulator >= sm.ZapTimer)
|
||||
{
|
||||
sm.ZapAccumulator -= sm.ZapTimer;
|
||||
SupermatterZap(uid, sm);
|
||||
}
|
||||
|
||||
if (sm.YellAccumulator >= sm.YellTimer)
|
||||
{
|
||||
sm.YellAccumulator -= sm.YellTimer;
|
||||
AnnounceCoreDamage(uid, sm);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, SupermatterComponent sm, MapInitEvent args)
|
||||
{
|
||||
// Set the yell timer
|
||||
sm.YellTimer = TimeSpan.FromSeconds(_config.GetCVar(ECCVars.SupermatterYellTimer));
|
||||
|
||||
// Set the Sound
|
||||
_ambient.SetAmbience(uid, true);
|
||||
|
||||
@@ -113,6 +96,21 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
mix?.AdjustMoles(Gas.Oxygen, Atmospherics.OxygenMolesStandard);
|
||||
mix?.AdjustMoles(Gas.Nitrogen, Atmospherics.NitrogenMolesStandard);
|
||||
}
|
||||
public void OnSupermatterUpdated(EntityUid uid, SupermatterComponent sm, AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
ProcessAtmos(uid, sm, args.dt);
|
||||
HandleDamage(uid, sm);
|
||||
|
||||
if (sm.Damage >= sm.DamageDelaminationPoint || sm.Delamming)
|
||||
HandleDelamination(uid, sm);
|
||||
|
||||
HandleStatus(uid, sm);
|
||||
HandleSoundLoop(uid, sm);
|
||||
HandleAccent(uid, sm);
|
||||
|
||||
if (sm.Damage >= sm.DamagePenaltyPoint)
|
||||
SupermatterZap(uid, sm);
|
||||
}
|
||||
|
||||
private void OnCollideEvent(EntityUid uid, SupermatterComponent sm, ref StartCollideEvent args)
|
||||
{
|
||||
@@ -127,12 +125,26 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
|
||||
if (!HasComp<ProjectileComponent>(target))
|
||||
{
|
||||
EntityManager.SpawnEntity(sm.CollisionResultPrototype, Transform(target).Coordinates);
|
||||
_audio.PlayPvs(sm.DustSound, uid);
|
||||
var popup = "supermatter-collide";
|
||||
|
||||
if (HasComp<MobStateComponent>(target))
|
||||
{
|
||||
popup = "supermatter-collide-mob";
|
||||
EntityManager.SpawnEntity(sm.CollisionResultPrototype, Transform(target).Coordinates);
|
||||
}
|
||||
|
||||
var targetProto = MetaData(target).EntityPrototype;
|
||||
if (targetProto != null && targetProto.ID != sm.CollisionResultPrototype)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString(popup, ("sm", uid), ("target", target)), uid, PopupType.LargeCaution);
|
||||
_audio.PlayPvs(sm.DustSound, uid);
|
||||
}
|
||||
|
||||
sm.Power += args.OtherBody.Mass;
|
||||
}
|
||||
|
||||
EntityManager.QueueDeleteEntity(target);
|
||||
AddComp<SupermatterImmuneComponent>(target); // prevent spam or excess power production
|
||||
|
||||
if (TryComp<SupermatterFoodComponent>(target, out var food))
|
||||
sm.Power += food.Energy;
|
||||
@@ -157,6 +169,7 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
sm.MatterPower += 200;
|
||||
|
||||
EntityManager.SpawnEntity(sm.CollisionResultPrototype, Transform(target).Coordinates);
|
||||
_popup.PopupEntity(Loc.GetString("supermatter-collide-mob", ("sm", uid), ("target", target)), uid, PopupType.LargeCaution);
|
||||
_audio.PlayPvs(sm.DustSound, uid);
|
||||
EntityManager.QueueDeleteEntity(target);
|
||||
}
|
||||
@@ -176,7 +189,6 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnHandChange = false,
|
||||
BreakOnMove = true,
|
||||
BreakOnWeightlessMove = false,
|
||||
NeedHand = true,
|
||||
RequireCanInteract = true,
|
||||
@@ -195,7 +207,7 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
sm.Damage += sm.DamageDelaminationPoint / 10;
|
||||
|
||||
var integrity = GetIntegrity(sm).ToString("0.00");
|
||||
SendSupermatterAnnouncement(uid, Loc.GetString("supermatter-announcement-cc-tamper", ("integrity", integrity)), true, "Central Command");
|
||||
SendSupermatterAnnouncement(uid, sm, Loc.GetString("supermatter-announcement-cc-tamper", ("integrity", integrity)));
|
||||
|
||||
Spawn(sm.SliverPrototype, _transform.GetMapCoordinates(args.User));
|
||||
_popup.PopupClient(Loc.GetString("supermatter-tamper-end"), uid, args.User);
|
||||
@@ -208,4 +220,32 @@ public sealed partial class SupermatterSystem : EntitySystem
|
||||
if (args.IsInDetailsRange)
|
||||
args.PushMarkup(Loc.GetString("supermatter-examine-integrity", ("integrity", GetIntegrity(sm).ToString("0.00"))));
|
||||
}
|
||||
|
||||
private SupermatterStatusType GetStatus(EntityUid uid, SupermatterComponent sm)
|
||||
{
|
||||
var mix = _atmosphere.GetContainingMixture(uid, true, true);
|
||||
|
||||
if (mix is not { })
|
||||
return SupermatterStatusType.Error;
|
||||
|
||||
if (sm.Delamming || sm.Damage >= sm.DamageDelaminationPoint)
|
||||
return SupermatterStatusType.Delaminating;
|
||||
|
||||
if (sm.Damage >= sm.DamagePenaltyPoint)
|
||||
return SupermatterStatusType.Emergency;
|
||||
|
||||
if (sm.Damage >= sm.DamageDelamAlertPoint)
|
||||
return SupermatterStatusType.Danger;
|
||||
|
||||
if (sm.Damage >= sm.DamageWarningThreshold)
|
||||
return SupermatterStatusType.Warning;
|
||||
|
||||
if (mix.Temperature > Atmospherics.T0C + (sm.HeatPenaltyThreshold * 0.8))
|
||||
return SupermatterStatusType.Caution;
|
||||
|
||||
if (sm.Power > 5)
|
||||
return SupermatterStatusType.Normal;
|
||||
|
||||
return SupermatterStatusType.Inactive;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Beam.Components;
|
||||
@@ -44,6 +45,16 @@ public abstract partial class SharedBeamComponent : Component
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("sound")]
|
||||
public SoundSpecifier? Sound;
|
||||
|
||||
/// <summary>
|
||||
/// Allow the sprite to be randomized.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ported from imp
|
||||
/// </remarks>
|
||||
[ViewVariables]
|
||||
[DataField("allowSpriteOverwrite")]
|
||||
public bool AllowSpriteOverwrite = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,13 +79,29 @@ public sealed class BeamControllerCreatedEvent : EntityEventArgs
|
||||
public sealed class CreateBeamSuccessEvent : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid User;
|
||||
public readonly EntityUid Target;
|
||||
|
||||
/// <summary>
|
||||
/// The entity the beam targeted.
|
||||
/// Imp - This may be null if the beam targeted a map coordinate.
|
||||
/// </summary>
|
||||
public readonly EntityUid? Target;
|
||||
|
||||
/// <summary>
|
||||
/// The coordinates the beam targeted. This may be null if the beam targeted an entity.
|
||||
/// </summary>
|
||||
public readonly MapCoordinates? Coordinates;
|
||||
|
||||
public CreateBeamSuccessEvent(EntityUid user, EntityUid target)
|
||||
{
|
||||
User = user;
|
||||
Target = target;
|
||||
}
|
||||
|
||||
public CreateBeamSuccessEvent(EntityUid user, MapCoordinates coordinates)
|
||||
{
|
||||
User = user;
|
||||
Coordinates = coordinates;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using Content.Shared.Supermatter.Components;
|
||||
using Content.Shared._EE.Supermatter.Components;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Shared.CCVar;
|
||||
namespace Content.Shared._EE.CCVars;
|
||||
|
||||
public sealed partial class CCVars
|
||||
[CVarDefs]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public sealed partial class ECCVars
|
||||
{
|
||||
/// <summary>
|
||||
/// With completely default supermatter values, Singuloose delamination will occur if engineers inject at least 900 moles of coolant per tile
|
||||
@@ -44,9 +46,21 @@ public sealed partial class CCVars
|
||||
public static readonly CVarDef<DelamType> SupermatterForcedDelamType =
|
||||
CVarDef.Create("supermatter.forced_delam_type", DelamType.Singulo, CVar.SERVER);
|
||||
|
||||
/// <summary>
|
||||
/// Base amount of radiation that the supermatter emits.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<float> SupermatterRadsBase =
|
||||
CVarDef.Create("supermatter.rads_base", 3f, CVar.SERVER);
|
||||
|
||||
/// <summary>
|
||||
/// Directly multiplies the amount of rads put out by the supermatter. Be VERY conservative with this.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<float> SupermatterRadsModifier =
|
||||
CVarDef.Create("supermatter.rads_modifier", 1f, CVar.SERVER);
|
||||
|
||||
/// <summary>
|
||||
/// How often the supermatter should announce its status.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<float> SupermatterYellTimer =
|
||||
CVarDef.Create("supermatter.yell_timer", 60f, CVar.SERVER);
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Audio;
|
||||
using Content.Shared._EE.Supermatter.Monitor;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Whitelist;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Radio;
|
||||
using Content.Shared.Speech;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Supermatter.Components;
|
||||
namespace Content.Shared._EE.Supermatter.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class SupermatterComponent : Component
|
||||
@@ -16,7 +19,13 @@ public sealed partial class SupermatterComponent : Component
|
||||
/// The SM will only cycle if activated.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool Activated = false;
|
||||
public bool Activated = true;
|
||||
|
||||
/// <summary>
|
||||
/// The current status of the singularity, used for alert sounds and the monitoring console
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SupermatterStatusType Status = SupermatterStatusType.Inactive;
|
||||
|
||||
[DataField]
|
||||
public string SliverPrototype = "SupermatterSliver";
|
||||
@@ -26,14 +35,13 @@ public sealed partial class SupermatterComponent : Component
|
||||
/// If removed - delamination timer is divided by 2.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool SliverRemoved = false;
|
||||
public bool SliverRemoved;
|
||||
|
||||
public string[] LightningPrototypes =
|
||||
{
|
||||
"Lightning",
|
||||
"ChargedLightning",
|
||||
"SuperchargedLightning",
|
||||
"HyperchargedLightning"
|
||||
"SupermatterLightning",
|
||||
"SupermatterLightningCharged",
|
||||
"SupermatterLightningSupercharged"
|
||||
};
|
||||
|
||||
[DataField]
|
||||
@@ -51,17 +59,45 @@ public sealed partial class SupermatterComponent : Component
|
||||
[DataField]
|
||||
public string CollisionResultPrototype = "Ash";
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier DustSound = new SoundPathSpecifier("/Audio/Effects/Grenades/Supermatter/supermatter_start.ogg");
|
||||
#endregion
|
||||
|
||||
#region Sounds
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier CalmSound = new SoundPathSpecifier("/Audio/Supermatter/calm.ogg");
|
||||
public SoundSpecifier DustSound = new SoundPathSpecifier("/Audio/_EE/Supermatter/supermatter.ogg");
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier DelamSound = new SoundPathSpecifier("/Audio/Supermatter/delamming.ogg");
|
||||
public SoundSpecifier DistortSound = new SoundPathSpecifier("/Audio/_EE/Supermatter/distort.ogg");
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier CurrentSoundLoop = new SoundPathSpecifier("/Audio/Supermatter/calm.ogg");
|
||||
public SoundSpecifier CalmLoopSound = new SoundPathSpecifier("/Audio/_EE/Supermatter/calm.ogg");
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier DelamLoopSound = new SoundPathSpecifier("/Audio/_EE/Supermatter/delamming.ogg");
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier CurrentSoundLoop = new SoundPathSpecifier("/Audio/_EE/Supermatter/calm.ogg");
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier CalmAccent = new SoundCollectionSpecifier("SupermatterAccentNormal");
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier DelamAccent = new SoundCollectionSpecifier("SupermatterAccentDelam");
|
||||
|
||||
[DataField]
|
||||
public string StatusWarningSound = "SupermatterWarning";
|
||||
|
||||
[DataField]
|
||||
public string StatusDangerSound = "SupermatterDanger";
|
||||
|
||||
[DataField]
|
||||
public string StatusEmergencySound = "SupermatterEmergency";
|
||||
|
||||
[DataField]
|
||||
public string StatusDelamSound = "SupermatterDelaminating";
|
||||
|
||||
[DataField]
|
||||
public string? StatusCurrentSound;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -70,6 +106,12 @@ public sealed partial class SupermatterComponent : Component
|
||||
[DataField]
|
||||
public float Power;
|
||||
|
||||
[DataField]
|
||||
public float Temperature;
|
||||
|
||||
[DataField]
|
||||
public float WasteMultiplier;
|
||||
|
||||
[DataField]
|
||||
public float MatterPower;
|
||||
|
||||
@@ -134,6 +176,12 @@ public sealed partial class SupermatterComponent : Component
|
||||
[DataField]
|
||||
public float OxygenReleaseEfficiencyModifier = 0.0031f;
|
||||
|
||||
/// <summary>
|
||||
/// The chance for supermatter lightning to strike random coordinates instead of an entity
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float ZapHitCoordinatesChance = 0.75f;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Timing
|
||||
@@ -142,43 +190,40 @@ public sealed partial class SupermatterComponent : Component
|
||||
/// We yell if over 50 damage every YellTimer Seconds
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float YellTimer = 60f;
|
||||
public TimeSpan YellTimer = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Set to YellTimer at first so it doesnt yell a minute after being hit
|
||||
/// Last time the supermatter's damage was announced
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float YellAccumulator = 60f;
|
||||
public TimeSpan YellLast = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Timer for delam
|
||||
/// Time when the delamination will occuer
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float DelamTimerAccumulator;
|
||||
public TimeSpan DelamEndTime;
|
||||
|
||||
/// <summary>
|
||||
/// Time until delam
|
||||
/// How long it takes in seconds for the supermatter to delaminate after reaching zero integrity
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float DelamTimer = 120f;
|
||||
public float DelamTimer = 30f;
|
||||
|
||||
/// <summary>
|
||||
/// The message timer
|
||||
/// Last time a supermatter accent sound was triggered
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float SpeakAccumulator = 60f;
|
||||
public TimeSpan AccentLastTime = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum time in seconds between supermatter accent sounds
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float AccentMinCooldown = 2f;
|
||||
|
||||
[DataField]
|
||||
public float UpdateAccumulator = 0f;
|
||||
|
||||
[DataField]
|
||||
public float UpdateTimer = 1f;
|
||||
|
||||
[DataField]
|
||||
public float ZapAccumulator = 0f;
|
||||
|
||||
[DataField]
|
||||
public float ZapTimer = 10f;
|
||||
public TimeSpan ZapLast = TimeSpan.Zero;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -213,7 +258,7 @@ public sealed partial class SupermatterComponent : Component
|
||||
/// Above this value we can get lord singulo and independent mol damage, below it we can heal damage
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float MolePenaltyThreshold = 900f;
|
||||
public float MolePenaltyThreshold = 1800f;
|
||||
|
||||
/// <summary>
|
||||
/// More moles of gases are harder to heat than fewer, so let's scale heat damage around them
|
||||
@@ -226,7 +271,19 @@ public sealed partial class SupermatterComponent : Component
|
||||
/// and delamming into a tesla. Low chance of pyro anomalies, +2 bolts of electricity
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float PowerPenaltyThreshold = 4000f;
|
||||
public float PowerPenaltyThreshold = 5000f;
|
||||
|
||||
/// <summary>
|
||||
/// +1 bolt of electricity, TODO: anomaly spawning
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float SeverePowerPenaltyThreshold = 7000f;
|
||||
|
||||
/// <summary>
|
||||
/// +1 bolt of electricity
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float CriticalPowerPenaltyThreshold = 9000f;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum safe operational temperature in degrees Celsius.
|
||||
@@ -243,14 +300,14 @@ public sealed partial class SupermatterComponent : Component
|
||||
/// The amount of damage taken
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float Damage = 0f;
|
||||
public float Damage;
|
||||
|
||||
/// <summary>
|
||||
/// The damage from before this cycle.
|
||||
/// Used to limit the damage we can take each cycle, and for safe alert.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float DamageArchived = 0f;
|
||||
public float DamageArchived;
|
||||
|
||||
/// <summary>
|
||||
/// Is multiplied by ExplosionPoint to cap evironmental damage per cycle
|
||||
@@ -282,14 +339,26 @@ public sealed partial class SupermatterComponent : Component
|
||||
[DataField]
|
||||
public float DamageEmergencyThreshold = 500;
|
||||
|
||||
/// <summary>
|
||||
/// The point at which the SM begins shooting lightning.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int DamagePenaltyPoint = 550;
|
||||
|
||||
/// <summary>
|
||||
/// The point at which the SM begins delaminating.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int DamageDelaminationPoint = 900;
|
||||
|
||||
/// <summary>
|
||||
/// The point at which the SM begins showing warning signs.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool Delamming = false;
|
||||
public int DamageDelamAlertPoint = 300;
|
||||
|
||||
[DataField]
|
||||
public bool Delamming;
|
||||
|
||||
[DataField]
|
||||
public DelamType PreferredDelamType = DelamType.Explosion;
|
||||
@@ -299,13 +368,13 @@ public sealed partial class SupermatterComponent : Component
|
||||
#region Announcements
|
||||
|
||||
[DataField]
|
||||
public string AlertCodeYellowId = "yellow";
|
||||
public bool DelamAnnounced;
|
||||
|
||||
[DataField]
|
||||
public string AlertCodeDeltaId = "delta";
|
||||
public ProtoId<RadioChannelPrototype> Channel = "Engineering";
|
||||
|
||||
[DataField]
|
||||
public bool DelamAnnounced = false;
|
||||
public ProtoId<RadioChannelPrototype> ChannelGlobal = "Common";
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Content.Shared.Supermatter.Components;
|
||||
namespace Content.Shared._EE.Supermatter.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class SupermatterFoodComponent : Component
|
||||
@@ -1,6 +1,6 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Supermatter.Components;
|
||||
namespace Content.Shared._EE.Supermatter.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class SupermatterImmuneComponent : Component
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Content.Shared._EE.Supermatter.Consoles;
|
||||
public abstract partial class SharedSupermatterConsoleSystem : EntitySystem
|
||||
{ }
|
||||
@@ -0,0 +1,208 @@
|
||||
using Content.Shared._EE.Supermatter.Consoles;
|
||||
using Content.Shared._EE.Supermatter.Monitor;
|
||||
using Content.Shared.Atmos;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._EE.Supermatter.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[Access(typeof(SharedSupermatterConsoleSystem))]
|
||||
public sealed partial class SupermatterConsoleComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The current entity of interest (selected via the console UI)
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public NetEntity? FocusSupermatter;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public struct SupermatterNavMapData
|
||||
{
|
||||
/// <summary>
|
||||
/// The entity in question
|
||||
/// </summary>
|
||||
public NetEntity NetEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Location of the entity
|
||||
/// </summary>
|
||||
public NetCoordinates NetCoordinates;
|
||||
|
||||
/// <summary>
|
||||
/// Populate the supermatter console nav map with a single entity
|
||||
/// </summary>
|
||||
public SupermatterNavMapData(NetEntity netEntity, NetCoordinates netCoordinates)
|
||||
{
|
||||
NetEntity = netEntity;
|
||||
NetCoordinates = netCoordinates;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public struct SupermatterFocusData
|
||||
{
|
||||
/// <summary>
|
||||
/// Focus entity
|
||||
/// </summary>
|
||||
public NetEntity NetEntity;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's integrity, from 0 to 100
|
||||
/// </summary>
|
||||
public float Integrity;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's power
|
||||
/// </summary>
|
||||
public float Power;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's emitted radiation
|
||||
/// </summary>
|
||||
public float Radiation;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's total absorbed moles
|
||||
/// </summary>
|
||||
public float AbsorbedMoles;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's temperature
|
||||
/// </summary>
|
||||
public float Temperature;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's temperature limit
|
||||
/// </summary>
|
||||
public float TemperatureLimit;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's waste multiplier
|
||||
/// </summary>
|
||||
public float WasteMultiplier;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's absorption ratio
|
||||
/// </summary>
|
||||
public float AbsorptionRatio;
|
||||
|
||||
/// <summary>
|
||||
/// The supermatter's gas storage
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Dictionary<Gas, float> GasStorage;
|
||||
|
||||
/// <summary>
|
||||
/// Populates the supermatter console focus entry with supermatter data
|
||||
/// </summary>
|
||||
public SupermatterFocusData
|
||||
(NetEntity netEntity,
|
||||
float integrity,
|
||||
float power,
|
||||
float radiation,
|
||||
float absorbedMoles,
|
||||
float temperature,
|
||||
float temperatureLimit,
|
||||
float wasteMultiplier,
|
||||
float absorptionRatio,
|
||||
Dictionary<Gas, float> gasStorage)
|
||||
{
|
||||
NetEntity = netEntity;
|
||||
Integrity = integrity;
|
||||
Power = power;
|
||||
Radiation = radiation;
|
||||
AbsorbedMoles = absorbedMoles;
|
||||
Temperature = temperature;
|
||||
TemperatureLimit = temperatureLimit;
|
||||
WasteMultiplier = wasteMultiplier;
|
||||
AbsorptionRatio = absorptionRatio;
|
||||
GasStorage = gasStorage;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SupermatterConsoleBoundInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of all supermatters
|
||||
/// </summary>
|
||||
public SupermatterConsoleEntry[] Supermatters;
|
||||
|
||||
/// <summary>
|
||||
/// Data for the UI focus (if applicable)
|
||||
/// </summary>
|
||||
public SupermatterFocusData? FocusData;
|
||||
|
||||
/// <summary>
|
||||
/// Sends data from the server to the client to populate the atmos monitoring console UI
|
||||
/// </summary>
|
||||
public SupermatterConsoleBoundInterfaceState(SupermatterConsoleEntry[] supermatters, SupermatterFocusData? focusData)
|
||||
{
|
||||
Supermatters = supermatters;
|
||||
FocusData = focusData;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public struct SupermatterConsoleEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The entity in question
|
||||
/// </summary>
|
||||
public NetEntity NetEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the entity
|
||||
/// </summary>
|
||||
public string EntityName;
|
||||
|
||||
/// <summary>
|
||||
/// Current alert level
|
||||
/// </summary>
|
||||
public SupermatterStatusType EntityStatus;
|
||||
|
||||
/// <summary>
|
||||
/// Used to populate the supermatter console UI with data from a single supermatter
|
||||
/// </summary>
|
||||
public SupermatterConsoleEntry
|
||||
(NetEntity entity,
|
||||
string entityName,
|
||||
SupermatterStatusType status)
|
||||
{
|
||||
NetEntity = entity;
|
||||
EntityName = entityName;
|
||||
EntityStatus = status;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SupermatterConsoleFocusChangeMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public NetEntity? FocusSupermatter;
|
||||
|
||||
/// <summary>
|
||||
/// Used to inform the server that the specified focus for the atmos monitoring console has been changed by the client
|
||||
/// </summary>
|
||||
public SupermatterConsoleFocusChangeMessage(NetEntity? focusSupermatter)
|
||||
{
|
||||
FocusSupermatter = focusSupermatter;
|
||||
}
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public enum SupermatterConsoleVisuals
|
||||
{
|
||||
ComputerLayerScreen,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UI key associated with the supermatter monitoring console
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public enum SupermatterConsoleUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._EE.Supermatter.Monitor;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum SupermatterStatusType : sbyte
|
||||
{
|
||||
Error = -1,
|
||||
Inactive = 0,
|
||||
Normal = 1,
|
||||
Caution = 2,
|
||||
Warning = 3,
|
||||
Danger = 4,
|
||||
Emergency = 5,
|
||||
Delaminating = 6
|
||||
}
|
||||
BIN
Resources/Audio/_EE/Supermatter/accent/delam/1.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/1.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/10.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/10.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/11.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/11.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/12.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/12.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/13.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/13.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/14.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/14.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/15.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/15.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/16.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/16.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/17.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/17.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/18.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/18.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/19.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/19.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/2.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/2.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/20.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/20.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/21.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/21.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/22.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/22.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/23.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/23.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/24.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/24.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/25.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/25.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/26.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/26.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/27.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/27.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/28.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/28.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/29.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/29.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/3.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/3.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/30.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/30.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/31.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/31.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/32.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/32.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/33.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/33.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/4.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/4.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/5.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/5.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/6.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/6.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/7.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/7.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/8.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/8.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/delam/9.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/delam/9.ogg
Normal file
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
- files:
|
||||
- 1.ogg
|
||||
- 2.ogg
|
||||
- 3.ogg
|
||||
- 4.ogg
|
||||
- 5.ogg
|
||||
- 6.ogg
|
||||
- 7.ogg
|
||||
- 8.ogg
|
||||
- 9.ogg
|
||||
- 10.ogg
|
||||
- 11.ogg
|
||||
- 12.ogg
|
||||
- 13.ogg
|
||||
- 14.ogg
|
||||
- 15.ogg
|
||||
- 16.ogg
|
||||
- 17.ogg
|
||||
- 18.ogg
|
||||
- 19.ogg
|
||||
- 20.ogg
|
||||
- 21.ogg
|
||||
- 22.ogg
|
||||
- 23.ogg
|
||||
- 24.ogg
|
||||
- 25.ogg
|
||||
- 26.ogg
|
||||
- 27.ogg
|
||||
- 28.ogg
|
||||
- 29.ogg
|
||||
- 30.ogg
|
||||
- 31.ogg
|
||||
- 32.ogg
|
||||
- 33.ogg
|
||||
copyright: "Created by actioninja for tgstation13"
|
||||
license: "CC-BY-SA-3.0"
|
||||
source: "https://github.com/tgstation/tgstation/pull/45462"
|
||||
BIN
Resources/Audio/_EE/Supermatter/accent/normal/1.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/1.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/10.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/10.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/11.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/11.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/12.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/12.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/13.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/13.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/14.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/14.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/15.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/15.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/16.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/16.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/17.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/17.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/18.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/18.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/19.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/19.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/2.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/2.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/20.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/20.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/21.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/21.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/22.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/22.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/23.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/23.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/24.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/24.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/25.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/25.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/26.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/26.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/27.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/27.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/28.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/28.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/29.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/29.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/3.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/3.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/30.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/30.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/31.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/31.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/32.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/32.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/33.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/33.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/4.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/4.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/5.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/5.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/6.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/6.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/7.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/7.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/8.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/8.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/accent/normal/9.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/accent/normal/9.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/calm.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/calm.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/delamming.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/delamming.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/distort.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/distort.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/lightning.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/lightning.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/status/bloblarm.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/status/bloblarm.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/status/engine_alert1.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/status/engine_alert1.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/status/engine_alert2.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/status/engine_alert2.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/status/terminal_alert.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/status/terminal_alert.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_EE/Supermatter/supermatter.ogg
Normal file
BIN
Resources/Audio/_EE/Supermatter/supermatter.ogg
Normal file
Binary file not shown.
@@ -0,0 +1,44 @@
|
||||
supermatter-console-window-title = Supermatter Monitoring Console
|
||||
supermatter-console-window-station-name = [color=white][font size=14]{$stationName}[/font][/color]
|
||||
supermatter-console-window-unknown-location = Unknown location
|
||||
supermatter-console-window-no-supermatters = [font size=16][color=white]No supermatter detected[/font]
|
||||
|
||||
supermatter-console-window-label-sm = {CAPITALIZE($name)}
|
||||
|
||||
supermatter-console-window-label-alert-types = Supermatter status:
|
||||
supermatter-console-window-error-status = Error
|
||||
supermatter-console-window-inactive-status = Inactive
|
||||
supermatter-console-window-normal-status = Normal
|
||||
supermatter-console-window-caution-status = Caution
|
||||
supermatter-console-window-warning-status = Warning
|
||||
supermatter-console-window-danger-status = Danger
|
||||
supermatter-console-window-emergency-status = Emergency
|
||||
supermatter-console-window-delaminating-status = Delaminating
|
||||
|
||||
supermatter-console-window-label-integrity = Integrity:
|
||||
supermatter-console-window-label-integrity-bar = {$integrity}%
|
||||
|
||||
supermatter-console-window-label-power = Internal Energy:
|
||||
supermatter-console-window-label-power-bar = {$power} {$prefix}eV
|
||||
|
||||
supermatter-console-window-label-radiation = Radiation Emission:
|
||||
supermatter-console-window-label-radiation-bar = {$radiation} rads
|
||||
|
||||
supermatter-console-window-label-moles = Absorbed Moles:
|
||||
supermatter-console-window-label-moles-bar = {$moles} Moles
|
||||
|
||||
supermatter-console-window-label-temperature = Temperature:
|
||||
supermatter-console-window-label-temperature-limit = Temperature Limit:
|
||||
supermatter-console-window-label-temperature-bar = {$temperature} K
|
||||
|
||||
supermatter-console-window-label-waste = Waste Multiplier:
|
||||
supermatter-console-window-label-waste-bar = {$waste} x
|
||||
|
||||
supermatter-console-window-label-absorption = Absorption Ratio:
|
||||
supermatter-console-window-label-absorption-bar = {$absorption}%
|
||||
|
||||
supermatter-console-window-label-gas = Unknown gas
|
||||
supermatter-console-window-label-gas-bar = {$gas}%
|
||||
|
||||
supermatter-console-window-flavor-left = ⚠ Do not approach the crystal
|
||||
supermatter-console-window-flavor-right = v1.1
|
||||
@@ -1,6 +1,7 @@
|
||||
supermatter-announcer = Automatic Supermatter Engine
|
||||
supermatter-examine-integrity =
|
||||
Its' integrity is [color=yellow]{$integrity}%[/color].
|
||||
Its integrity is [color=yellow]{$integrity}%[/color].
|
||||
supermatter-healing =
|
||||
Crystalline hyperstructure returning to safe operating parameters. Integrity: {$integrity}%.
|
||||
supermatter-warning =
|
||||
Warning! Crystal hyperstructure integrity faltering! Integrity: {$integrity}%.
|
||||
supermatter-emergency =
|
||||
@@ -14,9 +15,16 @@ supermatter-delam-tesla =
|
||||
supermatter-delam-cascade =
|
||||
CRYSTAL DELAMINATION IMMINENT! Harmonic frequency limits exceeded, casualty destabilization field could not be engaged!
|
||||
supermatter-delam-cancel =
|
||||
Crystalline hyperstructure returning to safe operating parameters. Failsafe has been Disengaged. Integrity: {$integrity}%.
|
||||
Crystalline hyperstructure returning to safe operating parameters. Failsafe has been disengaged. Integrity: {$integrity}%.
|
||||
supermatter-delam-player =
|
||||
You feel reality distort for a moment...
|
||||
supermatter-seconds-before-delam =
|
||||
Estimated time before delamination: {$seconds} seconds.
|
||||
supermatter-seconds-before-delam-countdown =
|
||||
{$seconds} seconds remain before causality stabilization.
|
||||
supermatter-seconds-before-delam-imminent =
|
||||
{$seconds}...
|
||||
|
||||
supermatter-tamper-begin =
|
||||
You begin carefully cutting a piece off the supermatter crystal...
|
||||
supermatter-tamper-end =
|
||||
@@ -24,3 +32,8 @@ supermatter-tamper-end =
|
||||
supermatter-announcement-cc-tamper =
|
||||
Our automatic casualty system has detected that the supermatter crystal structural integrity was compromised by an external force.
|
||||
Engineering department, report to the supermatter engine immediately.
|
||||
|
||||
supermatter-collide =
|
||||
{CAPITALIZE(THE($target))} slams into the {$sm}!
|
||||
supermatter-collide-mob =
|
||||
{CAPITALIZE(THE($target))}'s body flashes into dust!
|
||||
@@ -170,3 +170,6 @@ chat-speech-verb-electricity-2 = buzzes
|
||||
chat-speech-verb-electricity-3 = screeches
|
||||
|
||||
chat-speech-verb-marish = Mars
|
||||
|
||||
chat-speech-verb-name-supermatter = Supermatter
|
||||
chat-speech-verb-supermatter = states
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: SupermatterSliver
|
||||
name: supermatter sliver
|
||||
description: A shard from the station's Supermatter crystal. Highly radioactive.
|
||||
components:
|
||||
- type: PointLight
|
||||
enabled: true
|
||||
radius: 3
|
||||
energy: 2
|
||||
color: "#fff633"
|
||||
- type: RadiationSource
|
||||
intensity: .75
|
||||
- type: Icon
|
||||
sprite: Supermatter/supermatter_sliver.rsi
|
||||
state: icon
|
||||
- type: Sprite
|
||||
sprite: Supermatter/supermatter_sliver.rsi
|
||||
state: icon
|
||||
- type: StealTarget
|
||||
stealGroup: SupermatterSliver
|
||||
- type: Tag
|
||||
tags:
|
||||
- HighRiskItem
|
||||
- type: SupermatterImmune
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user