mirror of
https://github.com/corvax-team/ss14-wl.git
synced 2026-02-15 03:31:38 +01:00
Merge remote-tracking branch 'refs/remotes/wizards/master' into upstream-sync
# Conflicts: # Content.Server/Connection/ConnectionManager.cs # Resources/Prototypes/Catalog/Fills/Lockers/heads.yml # Resources/Prototypes/Entities/Stations/base.yml
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using Content.Shared.Administration.Notes;
|
||||
using Content.Shared.Administration.Notes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
@@ -13,7 +13,7 @@ public sealed partial class AdminMessagePopupMessage : Control
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
Admin.SetMessage(FormattedMessage.FromMarkup(Loc.GetString(
|
||||
Admin.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString(
|
||||
"admin-notes-message-admin",
|
||||
("admin", message.AdminName),
|
||||
("date", message.AddedOn.ToLocalTime()))));
|
||||
|
||||
@@ -49,7 +49,7 @@ public sealed partial class AdminMessagePopupWindow : Control
|
||||
MessageContainer.AddChild(new AdminMessagePopupMessage(message));
|
||||
}
|
||||
|
||||
Description.SetMessage(FormattedMessage.FromMarkup(Loc.GetString("admin-notes-message-desc", ("count", state.Messages.Length))));
|
||||
Description.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString("admin-notes-message-desc", ("count", state.Messages.Length))));
|
||||
}
|
||||
|
||||
private void OnDismissButtonPressed(BaseButton.ButtonEventArgs obj)
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
Unread++;
|
||||
|
||||
var formatted = new FormattedMessage(1);
|
||||
formatted.AddMarkup($"[color=gray]{message.SentAt.ToShortTimeString()}[/color] {message.Text}");
|
||||
formatted.AddMarkupOrThrow($"[color=gray]{message.SentAt.ToShortTimeString()}[/color] {message.Text}");
|
||||
TextOutput.AddMessage(formatted);
|
||||
LastMessage = message.SentAt;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Content.Shared.Anomaly;
|
||||
using Content.Shared.Gravity;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.Anomaly.Ui;
|
||||
|
||||
@@ -131,13 +131,13 @@ public sealed partial class ChangelogTab : Control
|
||||
Margin = new Thickness(6, 0, 0, 0),
|
||||
};
|
||||
authorLabel.SetMessage(
|
||||
FormattedMessage.FromMarkup(Loc.GetString("changelog-author-changed", ("author", author))));
|
||||
FormattedMessage.FromMarkupOrThrow(Loc.GetString("changelog-author-changed", ("author", author))));
|
||||
ChangelogBody.AddChild(authorLabel);
|
||||
|
||||
foreach (var change in groupedEntry.SelectMany(c => c.Changes))
|
||||
{
|
||||
var text = new RichTextLabel();
|
||||
text.SetMessage(FormattedMessage.FromMarkup(change.Message));
|
||||
text.SetMessage(FormattedMessage.FromMarkupOrThrow(change.Message));
|
||||
ChangelogBody.AddChild(new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Content.Client.Chat.UI
|
||||
var msg = new FormattedMessage();
|
||||
if (fontColor != null)
|
||||
msg.PushColor(fontColor.Value);
|
||||
msg.AddMarkup(message);
|
||||
msg.AddMarkupOrThrow(message);
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Content.Client.Actions;
|
||||
using Content.Client.Actions;
|
||||
using Content.Client.Mapping;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace Content.Client.Credits
|
||||
var text = _resourceManager.ContentFileReadAllText($"/Credits/{path}");
|
||||
if (markup)
|
||||
{
|
||||
label.SetMessage(FormattedMessage.FromMarkup(text.Trim()));
|
||||
label.SetMessage(FormattedMessage.FromMarkupOrThrow(text.Trim()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -227,7 +227,7 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
||||
StatusOptionButton.SelectId((int) criminalRecord.Status);
|
||||
if (criminalRecord.Reason is {} reason)
|
||||
{
|
||||
var message = FormattedMessage.FromMarkup(Loc.GetString("criminal-records-console-wanted-reason"));
|
||||
var message = FormattedMessage.FromMarkupOrThrow(Loc.GetString("criminal-records-console-wanted-reason"));
|
||||
message.AddText($": {reason}");
|
||||
WantedReason.SetMessage(message);
|
||||
WantedReason.Visible = true;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Gravity;
|
||||
using Content.Shared.Power;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Gravity;
|
||||
@@ -21,7 +22,7 @@ public sealed partial class GravitySystem : SharedGravitySystem
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (_appearanceSystem.TryGetData<GravityGeneratorStatus>(uid, GravityGeneratorVisuals.State, out var state, args.Component))
|
||||
if (_appearanceSystem.TryGetData<PowerChargeStatus>(uid, PowerChargeVisuals.State, out var state, args.Component))
|
||||
{
|
||||
if (comp.SpriteMap.TryGetValue(state, out var spriteState))
|
||||
{
|
||||
@@ -30,7 +31,7 @@ public sealed partial class GravitySystem : SharedGravitySystem
|
||||
}
|
||||
}
|
||||
|
||||
if (_appearanceSystem.TryGetData<float>(uid, GravityGeneratorVisuals.Charge, out var charge, args.Component))
|
||||
if (_appearanceSystem.TryGetData<float>(uid, PowerChargeVisuals.Charge, out var charge, args.Component))
|
||||
{
|
||||
var layer = args.Sprite.LayerMapGet(GravityGeneratorVisualLayers.Core);
|
||||
switch (charge)
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
using Content.Shared.Gravity;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.Gravity.UI
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class GravityGeneratorBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[ViewVariables]
|
||||
private GravityGeneratorWindow? _window;
|
||||
|
||||
public GravityGeneratorBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = this.CreateWindow<GravityGeneratorWindow>();
|
||||
_window.SetEntity(Owner);
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
var castState = (SharedGravityGeneratorComponent.GeneratorState) state;
|
||||
_window?.UpdateState(castState);
|
||||
}
|
||||
|
||||
public void SetPowerSwitch(bool on)
|
||||
{
|
||||
SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(on));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
using Content.Shared.Gravity;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow;
|
||||
|
||||
namespace Content.Client.Gravity.UI
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GravityGeneratorWindow : FancyWindow
|
||||
{
|
||||
private readonly ButtonGroup _buttonGroup = new();
|
||||
|
||||
public event Action<bool>? OnPowerSwitch;
|
||||
|
||||
public GravityGeneratorWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
OnButton.Group = _buttonGroup;
|
||||
OffButton.Group = _buttonGroup;
|
||||
|
||||
OnButton.OnPressed += _ => OnPowerSwitch?.Invoke(true);
|
||||
OffButton.OnPressed += _ => OnPowerSwitch?.Invoke(false);
|
||||
}
|
||||
|
||||
public void SetEntity(EntityUid uid)
|
||||
{
|
||||
EntityView.SetEntity(uid);
|
||||
}
|
||||
|
||||
public void UpdateState(SharedGravityGeneratorComponent.GeneratorState state)
|
||||
{
|
||||
if (state.On)
|
||||
OnButton.Pressed = true;
|
||||
else
|
||||
OffButton.Pressed = true;
|
||||
|
||||
PowerLabel.Text = Loc.GetString(
|
||||
"gravity-generator-window-power-label",
|
||||
("draw", state.PowerDraw),
|
||||
("max", state.PowerDrawMax));
|
||||
|
||||
PowerLabel.SetOnlyStyleClass(MathHelper.CloseTo(state.PowerDraw, state.PowerDrawMax) ? "Good" : "Caution");
|
||||
|
||||
ChargeBar.Value = state.Charge;
|
||||
ChargeText.Text = (state.Charge / 255f).ToString("P0");
|
||||
StatusLabel.Text = Loc.GetString(state.PowerStatus switch
|
||||
{
|
||||
GravityGeneratorPowerStatus.Off => "gravity-generator-window-status-off",
|
||||
GravityGeneratorPowerStatus.Discharging => "gravity-generator-window-status-discharging",
|
||||
GravityGeneratorPowerStatus.Charging => "gravity-generator-window-status-charging",
|
||||
GravityGeneratorPowerStatus.FullyCharged => "gravity-generator-window-status-fully-charged",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
});
|
||||
|
||||
StatusLabel.SetOnlyStyleClass(state.PowerStatus switch
|
||||
{
|
||||
GravityGeneratorPowerStatus.Off => "Danger",
|
||||
GravityGeneratorPowerStatus.Discharging => "Caution",
|
||||
GravityGeneratorPowerStatus.Charging => "Caution",
|
||||
GravityGeneratorPowerStatus.FullyCharged => "Good",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
});
|
||||
|
||||
EtaLabel.Text = state.EtaSeconds >= 0
|
||||
? Loc.GetString("gravity-generator-window-eta-value", ("left", TimeSpan.FromSeconds(state.EtaSeconds)))
|
||||
: Loc.GetString("gravity-generator-window-eta-none");
|
||||
|
||||
EtaLabel.SetOnlyStyleClass(state.EtaSeconds >= 0 ? "Caution" : "Disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
||||
var i = 0;
|
||||
foreach (var effectString in effect.EffectDescriptions)
|
||||
{
|
||||
descMsg.AddMarkup(effectString);
|
||||
descMsg.AddMarkupOrThrow(effectString);
|
||||
i++;
|
||||
if (i < descriptionsCount)
|
||||
descMsg.PushNewline();
|
||||
@@ -174,7 +174,7 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
||||
var i = 0;
|
||||
foreach (var effectString in guideEntryRegistryPlant.PlantMetabolisms)
|
||||
{
|
||||
descMsg.AddMarkup(effectString);
|
||||
descMsg.AddMarkupOrThrow(effectString);
|
||||
i++;
|
||||
if (i < descriptionsCount)
|
||||
descMsg.PushNewline();
|
||||
@@ -195,7 +195,7 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
||||
FormattedMessage description = new();
|
||||
description.AddText(reagent.LocalizedDescription);
|
||||
description.PushNewline();
|
||||
description.AddMarkup(Loc.GetString("guidebook-reagent-physical-description",
|
||||
description.AddMarkupOrThrow(Loc.GetString("guidebook-reagent-physical-description",
|
||||
("description", reagent.LocalizedPhysicalDescription)));
|
||||
ReagentDescription.SetMessage(description);
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ public sealed partial class GuideReagentReaction : BoxContainer, ISearchableCont
|
||||
var i = 0;
|
||||
foreach (var (product, amount) in reagents.OrderByDescending(p => p.Value))
|
||||
{
|
||||
msg.AddMarkup(Loc.GetString("guidebook-reagent-recipes-reagent-display",
|
||||
msg.AddMarkupOrThrow(Loc.GetString("guidebook-reagent-recipes-reagent-display",
|
||||
("reagent", protoMan.Index<ReagentPrototype>(product).LocalizedName), ("ratio", amount)));
|
||||
i++;
|
||||
if (i < reagentCount)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -18,7 +18,7 @@ public sealed partial class InfoSection : BoxContainer
|
||||
{
|
||||
TitleLabel.Text = title;
|
||||
if (markup)
|
||||
Content.SetMessage(FormattedMessage.FromMarkup(text.Trim()));
|
||||
Content.SetMessage(FormattedMessage.FromMarkupOrThrow(text.Trim()));
|
||||
else
|
||||
Content.SetMessage(text);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Content.Client.Info
|
||||
}
|
||||
public void SetInfoBlob(string markup)
|
||||
{
|
||||
_richTextLabel.SetMessage(FormattedMessage.FromMarkup(markup));
|
||||
_richTextLabel.SetMessage(FormattedMessage.FromMarkupOrThrow(markup));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public static class RichTextLabelExt
|
||||
/// </remarks>
|
||||
public static RichTextLabel SetMarkup(this RichTextLabel label, string markup)
|
||||
{
|
||||
label.SetMessage(FormattedMessage.FromMarkup(markup));
|
||||
label.SetMessage(FormattedMessage.FromMarkupOrThrow(markup));
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Client.Lobby;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Players;
|
||||
@@ -133,7 +133,7 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
|
||||
reasons.Add(jobReason.ToMarkup());
|
||||
}
|
||||
|
||||
reason = reasons.Count == 0 ? null : FormattedMessage.FromMarkup(string.Join('\n', reasons));
|
||||
reason = reasons.Count == 0 ? null : FormattedMessage.FromMarkupOrThrow(string.Join('\n', reasons));
|
||||
return reason == null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using Content.Shared.Power;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.Power.PowerCharge;
|
||||
|
||||
public sealed class PowerChargeBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[ViewVariables]
|
||||
private PowerChargeWindow? _window;
|
||||
|
||||
public PowerChargeBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetPowerSwitch(bool on)
|
||||
{
|
||||
SendMessage(new SwitchChargingMachineMessage(on));
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
if (!EntMan.TryGetComponent(Owner, out PowerChargeComponent? component))
|
||||
return;
|
||||
|
||||
_window = this.CreateWindow<PowerChargeWindow>();
|
||||
_window.UpdateWindow(this, Loc.GetString(component.WindowTitle));
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
if (state is not PowerChargeState chargeState)
|
||||
return;
|
||||
|
||||
_window?.UpdateState(chargeState);
|
||||
}
|
||||
}
|
||||
10
Content.Client/Power/PowerCharge/PowerChargeComponent.cs
Normal file
10
Content.Client/Power/PowerCharge/PowerChargeComponent.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using Content.Shared.Power;
|
||||
|
||||
namespace Content.Client.Power.PowerCharge;
|
||||
|
||||
/// <inheritdoc cref="Content.Shared.Power.SharedPowerChargeComponent" />
|
||||
[RegisterComponent]
|
||||
public sealed partial class PowerChargeComponent : SharedPowerChargeComponent
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,27 +1,26 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc 'gravity-generator-window-title'}"
|
||||
MinSize="270 130"
|
||||
SetSize="360 180">
|
||||
<BoxContainer Margin="4 0" Orientation="Horizontal">
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<GridContainer Margin="2 0 0 0" Columns="2">
|
||||
<!-- Power -->
|
||||
<Label Text="{Loc 'gravity-generator-window-power'}" HorizontalExpand="True" StyleClasses="StatusFieldTitle" />
|
||||
<Label Text="{Loc 'power-charge-window-power'}" HorizontalExpand="True" StyleClasses="StatusFieldTitle" />
|
||||
<BoxContainer Orientation="Horizontal" MinWidth="120">
|
||||
<Button Name="OnButton" Text="{Loc 'gravity-generator-window-power-on'}" StyleClasses="OpenRight" />
|
||||
<Button Name="OffButton" Text="{Loc 'gravity-generator-window-power-off'}" StyleClasses="OpenLeft" />
|
||||
<Button Name="OnButton" Text="{Loc 'power-charge-window-power-on'}" StyleClasses="OpenRight" />
|
||||
<Button Name="OffButton" Text="{Loc 'power-charge-window-power-off'}" StyleClasses="OpenLeft" />
|
||||
</BoxContainer>
|
||||
<Control /> <!-- Empty control to act as a spacer in the grid. -->
|
||||
<Label Name="PowerLabel" Text="0 / 0 W" />
|
||||
<!-- Status -->
|
||||
<Label Text="{Loc 'gravity-generator-window-status'}" StyleClasses="StatusFieldTitle" />
|
||||
<Label Name="StatusLabel" Text="{Loc 'gravity-generator-window-status-fully-charged'}" />
|
||||
<Label Text="{Loc 'power-charge-window-status'}" StyleClasses="StatusFieldTitle" />
|
||||
<Label Name="StatusLabel" Text="{Loc 'power-charge-window-status-fully-charged'}" />
|
||||
<!-- ETA -->
|
||||
<Label Text="{Loc 'gravity-generator-window-eta'}" StyleClasses="StatusFieldTitle" />
|
||||
<Label Text="{Loc 'power-charge-window-eta'}" StyleClasses="StatusFieldTitle" />
|
||||
<Label Name="EtaLabel" Text="N/A" />
|
||||
<!-- Charge -->
|
||||
<Label Text="{Loc 'gravity-generator-window-charge'}" StyleClasses="StatusFieldTitle" />
|
||||
<Label Text="{Loc 'power-charge-window-charge'}" StyleClasses="StatusFieldTitle" />
|
||||
<ProgressBar Name="ChargeBar" MaxValue="255">
|
||||
<Label Name="ChargeText" Margin="4 0" Text="0 %" />
|
||||
</ProgressBar>
|
||||
@@ -31,5 +30,4 @@
|
||||
<SpriteView Name="EntityView" SetSize="96 96" OverrideDirection="South" />
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
</controls:FancyWindow>
|
||||
72
Content.Client/Power/PowerCharge/PowerChargeWindow.xaml.cs
Normal file
72
Content.Client/Power/PowerCharge/PowerChargeWindow.xaml.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Power;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Power.PowerCharge;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class PowerChargeWindow : FancyWindow
|
||||
{
|
||||
private readonly ButtonGroup _buttonGroup = new();
|
||||
|
||||
public PowerChargeWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
OnButton.Group = _buttonGroup;
|
||||
OffButton.Group = _buttonGroup;
|
||||
}
|
||||
|
||||
public void UpdateWindow(PowerChargeBoundUserInterface bui, string title)
|
||||
{
|
||||
Title = title;
|
||||
|
||||
OnButton.OnPressed += _ => bui.SetPowerSwitch(true);
|
||||
OffButton.OnPressed += _ => bui.SetPowerSwitch(false);
|
||||
|
||||
EntityView.SetEntity(bui.Owner);
|
||||
}
|
||||
|
||||
public void UpdateState(PowerChargeState state)
|
||||
{
|
||||
if (state.On)
|
||||
OnButton.Pressed = true;
|
||||
else
|
||||
OffButton.Pressed = true;
|
||||
|
||||
PowerLabel.Text = Loc.GetString(
|
||||
"power-charge-window-power-label",
|
||||
("draw", state.PowerDraw),
|
||||
("max", state.PowerDrawMax));
|
||||
|
||||
PowerLabel.SetOnlyStyleClass(MathHelper.CloseTo(state.PowerDraw, state.PowerDrawMax) ? "Good" : "Caution");
|
||||
|
||||
ChargeBar.Value = state.Charge;
|
||||
ChargeText.Text = (state.Charge / 255f).ToString("P0");
|
||||
StatusLabel.Text = Loc.GetString(state.PowerStatus switch
|
||||
{
|
||||
PowerChargePowerStatus.Off => "power-charge-window-status-off",
|
||||
PowerChargePowerStatus.Discharging => "power-charge-window-status-discharging",
|
||||
PowerChargePowerStatus.Charging => "power-charge-window-status-charging",
|
||||
PowerChargePowerStatus.FullyCharged => "power-charge-window-status-fully-charged",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
});
|
||||
|
||||
StatusLabel.SetOnlyStyleClass(state.PowerStatus switch
|
||||
{
|
||||
PowerChargePowerStatus.Off => "Danger",
|
||||
PowerChargePowerStatus.Discharging => "Caution",
|
||||
PowerChargePowerStatus.Charging => "Caution",
|
||||
PowerChargePowerStatus.FullyCharged => "Good",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
});
|
||||
|
||||
EtaLabel.Text = state.EtaSeconds >= 0
|
||||
? Loc.GetString("power-charge-window-eta-value", ("left", TimeSpan.FromSeconds(state.EtaSeconds)))
|
||||
: Loc.GetString("power-charge-window-eta-none");
|
||||
|
||||
EtaLabel.SetOnlyStyleClass(state.EtaSeconds >= 0 ? "Caution" : "Disabled");
|
||||
}
|
||||
}
|
||||
@@ -309,7 +309,7 @@ public sealed partial class PowerMonitoringWindow
|
||||
BorderThickness = new Thickness(2),
|
||||
};
|
||||
|
||||
msg.AddMarkup(Loc.GetString("power-monitoring-window-rogue-power-consumer"));
|
||||
msg.AddMarkupOrThrow(Loc.GetString("power-monitoring-window-rogue-power-consumer"));
|
||||
SystemWarningPanel.Visible = true;
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ public sealed partial class PowerMonitoringWindow
|
||||
BorderThickness = new Thickness(2),
|
||||
};
|
||||
|
||||
msg.AddMarkup(Loc.GetString("power-monitoring-window-power-net-abnormalities"));
|
||||
msg.AddMarkupOrThrow(Loc.GetString("power-monitoring-window-power-net-abnormalities"));
|
||||
SystemWarningPanel.Visible = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -128,12 +128,12 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow
|
||||
};
|
||||
|
||||
var text = new FormattedMessage();
|
||||
text.PushMarkup(Loc.GetString("robotics-console-model", ("name", model)));
|
||||
text.AddMarkup(Loc.GetString("robotics-console-designation"));
|
||||
text.AddMarkupOrThrow($"{Loc.GetString("robotics-console-model", ("name", model))}\n");
|
||||
text.AddMarkupOrThrow(Loc.GetString("robotics-console-designation"));
|
||||
text.AddText($" {data.Name}\n"); // prevent players trolling by naming borg [color=red]satan[/color]
|
||||
text.PushMarkup(Loc.GetString("robotics-console-battery", ("charge", (int) (data.Charge * 100f)), ("color", batteryColor)));
|
||||
text.PushMarkup(Loc.GetString("robotics-console-brain", ("brain", data.HasBrain)));
|
||||
text.AddMarkup(Loc.GetString("robotics-console-modules", ("count", data.ModuleCount)));
|
||||
text.AddMarkupOrThrow($"{Loc.GetString("robotics-console-battery", ("charge", (int)(data.Charge * 100f)), ("color", batteryColor))}\n");
|
||||
text.AddMarkupOrThrow($"{Loc.GetString("robotics-console-brain", ("brain", data.HasBrain))}\n");
|
||||
text.AddMarkupOrThrow(Loc.GetString("robotics-console-modules", ("count", data.ModuleCount)));
|
||||
BorgInfo.SetMessage(text);
|
||||
|
||||
// how the turntables
|
||||
|
||||
@@ -61,9 +61,9 @@ namespace Content.Client.RoundEnd
|
||||
//Gamemode Name
|
||||
var gamemodeLabel = new RichTextLabel();
|
||||
var gamemodeMessage = new FormattedMessage();
|
||||
gamemodeMessage.AddMarkup(Loc.GetString("round-end-summary-window-round-id-label", ("roundId", roundId)));
|
||||
gamemodeMessage.AddMarkupOrThrow(Loc.GetString("round-end-summary-window-round-id-label", ("roundId", roundId)));
|
||||
gamemodeMessage.AddText(" ");
|
||||
gamemodeMessage.AddMarkup(Loc.GetString("round-end-summary-window-gamemode-name-label", ("gamemode", gamemode)));
|
||||
gamemodeMessage.AddMarkupOrThrow(Loc.GetString("round-end-summary-window-gamemode-name-label", ("gamemode", gamemode)));
|
||||
gamemodeLabel.SetMessage(gamemodeMessage);
|
||||
roundEndSummaryContainer.AddChild(gamemodeLabel);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Numerics;
|
||||
using System.Numerics;
|
||||
using Content.Client.Actions.UI;
|
||||
using Content.Client.Cooldown;
|
||||
using Content.Shared.Alert;
|
||||
@@ -69,8 +69,8 @@ namespace Content.Client.UserInterface.Systems.Alerts.Controls
|
||||
|
||||
private Control SupplyTooltip(Control? sender)
|
||||
{
|
||||
var msg = FormattedMessage.FromMarkup(Loc.GetString(Alert.Name));
|
||||
var desc = FormattedMessage.FromMarkup(Loc.GetString(Alert.Description));
|
||||
var msg = FormattedMessage.FromMarkupOrThrow(Loc.GetString(Alert.Name));
|
||||
var desc = FormattedMessage.FromMarkupOrThrow(Loc.GetString(Alert.Description));
|
||||
return new ActionAlertTooltip(msg, desc) {Cooldown = Cooldown};
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ public partial class ChatBox : UIWidget
|
||||
{
|
||||
var formatted = new FormattedMessage(3);
|
||||
formatted.PushColor(color);
|
||||
formatted.AddMarkup(message);
|
||||
formatted.AddMarkupOrThrow(message);
|
||||
formatted.Pop();
|
||||
Contents.AddMessage(formatted);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ using Content.Client.UserInterface.Controls;
|
||||
using Content.Client.VendingMachines.UI;
|
||||
using Content.Shared.VendingMachines;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Input;
|
||||
using System.Linq;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.VendingMachines
|
||||
{
|
||||
|
||||
@@ -139,11 +139,11 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow
|
||||
{
|
||||
if (state.Paused)
|
||||
{
|
||||
message.AddMarkup(Loc.GetString("analysis-console-info-scanner-paused"));
|
||||
message.AddMarkupOrThrow(Loc.GetString("analysis-console-info-scanner-paused"));
|
||||
}
|
||||
else
|
||||
{
|
||||
message.AddMarkup(Loc.GetString("analysis-console-info-scanner"));
|
||||
message.AddMarkupOrThrow(Loc.GetString("analysis-console-info-scanner"));
|
||||
}
|
||||
Information.SetMessage(message);
|
||||
UpdateArtifactIcon(null); //set it to blank
|
||||
@@ -155,11 +155,11 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow
|
||||
if (state.ScanReport == null)
|
||||
{
|
||||
if (!state.AnalyzerConnected) //no analyzer connected
|
||||
message.AddMarkup(Loc.GetString("analysis-console-info-no-scanner"));
|
||||
message.AddMarkupOrThrow(Loc.GetString("analysis-console-info-no-scanner"));
|
||||
else if (!state.CanScan) //no artifact
|
||||
message.AddMarkup(Loc.GetString("analysis-console-info-no-artifact"));
|
||||
message.AddMarkupOrThrow(Loc.GetString("analysis-console-info-no-artifact"));
|
||||
else if (state.Artifact == null) //ready to go
|
||||
message.AddMarkup(Loc.GetString("analysis-console-info-ready"));
|
||||
message.AddMarkupOrThrow(Loc.GetString("analysis-console-info-ready"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
8
Content.IntegrationTests/AssemblyInfo.cs
Normal file
8
Content.IntegrationTests/AssemblyInfo.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
[assembly: Parallelizable(ParallelScope.Children)]
|
||||
|
||||
// I don't know why this parallelism limit was originally put here.
|
||||
// I *do* know that I tried removing it, and ran into the following .NET runtime problem:
|
||||
// https://github.com/dotnet/runtime/issues/107197
|
||||
// So we can't really parallelize integration tests harder either until the runtime fixes that,
|
||||
// *or* we fix serv3 to not spam expression trees.
|
||||
[assembly: LevelOfParallelism(3)]
|
||||
@@ -23,8 +23,6 @@ using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.UnitTesting;
|
||||
|
||||
[assembly: LevelOfParallelism(3)]
|
||||
|
||||
namespace Content.IntegrationTests;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
|
||||
[assembly: Parallelizable(ParallelScope.Children)]
|
||||
|
||||
namespace Content.IntegrationTests;
|
||||
namespace Content.IntegrationTests;
|
||||
|
||||
[SetUpFixture]
|
||||
public sealed class PoolManagerTestEventHandler
|
||||
|
||||
@@ -25,6 +25,9 @@ namespace Content.IntegrationTests.Tests.Gravity
|
||||
id: WeightlessGravityGeneratorDummy
|
||||
components:
|
||||
- type: GravityGenerator
|
||||
- type: PowerCharge
|
||||
windowTitle: gravity-generator-window-title
|
||||
idlePower: 50
|
||||
chargeRate: 1000000000 # Set this really high so it discharges in a single tick.
|
||||
activePower: 500
|
||||
- type: ApcPowerReceiver
|
||||
|
||||
@@ -21,6 +21,9 @@ namespace Content.IntegrationTests.Tests
|
||||
id: GridGravityGeneratorDummy
|
||||
components:
|
||||
- type: GravityGenerator
|
||||
- type: PowerCharge
|
||||
windowTitle: gravity-generator-window-title
|
||||
idlePower: 50
|
||||
chargeRate: 1000000000 # Set this really high so it discharges in a single tick.
|
||||
activePower: 500
|
||||
- type: ApcPowerReceiver
|
||||
|
||||
@@ -658,7 +658,7 @@ public record struct CommandPermissionsUnassignedError(CommandSpec Command) : IC
|
||||
{
|
||||
public FormattedMessage DescribeInner()
|
||||
{
|
||||
return FormattedMessage.FromMarkup($"The command {Command.FullName()} is missing permission flags and cannot be executed.");
|
||||
return FormattedMessage.FromMarkupOrThrow($"The command {Command.FullName()} is missing permission flags and cannot be executed.");
|
||||
}
|
||||
|
||||
public string? Expression { get; set; }
|
||||
@@ -671,7 +671,7 @@ public record struct NoPermissionError(CommandSpec Command) : IConError
|
||||
{
|
||||
public FormattedMessage DescribeInner()
|
||||
{
|
||||
return FormattedMessage.FromMarkup($"You do not have permission to execute {Command.FullName()}");
|
||||
return FormattedMessage.FromMarkupOrThrow($"You do not have permission to execute {Command.FullName()}");
|
||||
}
|
||||
|
||||
public string? Expression { get; set; }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Anomaly.Components;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Shared.Anomaly;
|
||||
@@ -11,10 +10,7 @@ using Content.Shared.Physics;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Map;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Power;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
namespace Content.Server.Anomaly;
|
||||
|
||||
@@ -115,7 +111,7 @@ public sealed partial class AnomalySystem
|
||||
var valid = true;
|
||||
|
||||
// TODO: This should be using static lookup.
|
||||
foreach (var ent in gridComp.GetAnchoredEntities(tile))
|
||||
foreach (var ent in _mapSystem.GetAnchoredEntities(grid, gridComp, tile))
|
||||
{
|
||||
if (!physQuery.TryGetComponent(ent, out var body))
|
||||
continue;
|
||||
@@ -131,10 +127,10 @@ public sealed partial class AnomalySystem
|
||||
continue;
|
||||
|
||||
var pos = _mapSystem.GridTileToLocal(grid, gridComp, tile);
|
||||
var mapPos = pos.ToMap(EntityManager, _transform);
|
||||
var mapPos = _transform.ToMapCoordinates(pos);
|
||||
// don't spawn in AntiAnomalyZones
|
||||
var antiAnomalyZonesQueue = AllEntityQuery<AntiAnomalyZoneComponent, TransformComponent>();
|
||||
while (antiAnomalyZonesQueue.MoveNext(out var uid, out var zone, out var antiXform))
|
||||
while (antiAnomalyZonesQueue.MoveNext(out _, out var zone, out var antiXform))
|
||||
{
|
||||
if (antiXform.MapID != mapPos.MapId)
|
||||
continue;
|
||||
|
||||
@@ -119,12 +119,12 @@ public sealed partial class CargoSystem
|
||||
msg.PushNewline();
|
||||
foreach (var entry in prototype.Entries)
|
||||
{
|
||||
msg.AddMarkup($"- {Loc.GetString("bounty-console-manifest-entry",
|
||||
msg.AddMarkupOrThrow($"- {Loc.GetString("bounty-console-manifest-entry",
|
||||
("amount", entry.Amount),
|
||||
("item", Loc.GetString(entry.Name)))}");
|
||||
msg.PushNewline();
|
||||
}
|
||||
msg.AddMarkup(Loc.GetString("bounty-console-manifest-reward", ("reward", prototype.Reward)));
|
||||
msg.AddMarkupOrThrow(Loc.GetString("bounty-console-manifest-reward", ("reward", prototype.Reward)));
|
||||
_paperSystem.SetContent((uid, paper), msg.ToMarkup());
|
||||
}
|
||||
|
||||
|
||||
@@ -67,11 +67,6 @@ public sealed partial class CargoSystem
|
||||
|
||||
private void OnPalletUIOpen(EntityUid uid, CargoPalletConsoleComponent component, BoundUIOpenedEvent args)
|
||||
{
|
||||
var player = args.Actor;
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
UpdatePalletConsoleInterface(uid);
|
||||
}
|
||||
|
||||
@@ -85,11 +80,6 @@ public sealed partial class CargoSystem
|
||||
|
||||
private void OnPalletAppraise(EntityUid uid, CargoPalletConsoleComponent component, CargoPalletAppraiseMessage args)
|
||||
{
|
||||
var player = args.Actor;
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
UpdatePalletConsoleInterface(uid);
|
||||
}
|
||||
|
||||
@@ -313,11 +303,6 @@ public sealed partial class CargoSystem
|
||||
|
||||
private void OnPalletSale(EntityUid uid, CargoPalletConsoleComponent component, CargoPalletSellMessage args)
|
||||
{
|
||||
var player = args.Actor;
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
var xform = Transform(uid);
|
||||
|
||||
if (xform.GridUid is not EntityUid gridUid)
|
||||
|
||||
@@ -499,7 +499,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
||||
if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker)
|
||||
return;
|
||||
|
||||
var message = TransformSpeech(source, FormattedMessage.RemoveMarkup(originalMessage));
|
||||
var message = TransformSpeech(source, FormattedMessage.RemoveMarkupOrThrow(originalMessage));
|
||||
if (message.Length == 0)
|
||||
return;
|
||||
|
||||
@@ -597,7 +597,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
||||
var wrappedMessage = Loc.GetString("chat-manager-entity-me-wrap-message",
|
||||
("entityName", name),
|
||||
("entity", ent),
|
||||
("message", FormattedMessage.RemoveMarkup(action)));
|
||||
("message", FormattedMessage.RemoveMarkupOrThrow(action)));
|
||||
|
||||
if (checkEmote)
|
||||
TryEmoteChatInput(source, action);
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Connection.Whitelist;
|
||||
using Content.Server.Connection.Whitelist.Conditions;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Corvax.Interfaces.Server;
|
||||
using Content.Corvax.Interfaces.Shared;
|
||||
using Content.Server.Chat.Managers;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -28,7 +28,7 @@ namespace Content.Server.DetailExaminable
|
||||
Act = () =>
|
||||
{
|
||||
var markup = new FormattedMessage();
|
||||
markup.AddMarkup(component.Content);
|
||||
markup.AddMarkupOrThrow(component.Content);
|
||||
_examineSystem.SendExamineTooltip(args.User, uid, markup, false, false);
|
||||
},
|
||||
Text = Loc.GetString("detail-examinable-verb-text"),
|
||||
|
||||
@@ -71,7 +71,7 @@ public sealed class DragonRiftSystem : EntitySystem
|
||||
Dirty(uid, comp);
|
||||
|
||||
var msg = Loc.GetString("carp-rift-warning",
|
||||
("location", FormattedMessage.RemoveMarkup(_navMap.GetNearestBeaconString((uid, xform)))));
|
||||
("location", FormattedMessage.RemoveMarkupOrThrow(_navMap.GetNearestBeaconString((uid, xform)))));
|
||||
_chat.DispatchGlobalAnnouncement(msg, playSound: false, colorOverride: Color.Red);
|
||||
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
||||
_navMap.SetBeaconEnabled(uid, true);
|
||||
|
||||
@@ -2,7 +2,6 @@ using Content.Server.Body.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.EntityEffects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.EntityEffects;
|
||||
|
||||
namespace Content.Server.EntityEffects.Effects;
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ using Content.Shared.EntityEffects;
|
||||
using Content.Shared.Polymorph;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Content.Shared.EntityEffects;
|
||||
|
||||
namespace Content.Server.EntityEffects.Effects;
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace Content.Server.Explosion.EntitySystems
|
||||
return;
|
||||
|
||||
// Gets location of the implant
|
||||
var posText = FormattedMessage.RemoveMarkup(_navMap.GetNearestBeaconString(uid));
|
||||
var posText = FormattedMessage.RemoveMarkupOrThrow(_navMap.GetNearestBeaconString(uid));
|
||||
var critMessage = Loc.GetString(component.CritMessage, ("user", implanted.ImplantedEntity.Value), ("position", posText));
|
||||
var deathMessage = Loc.GetString(component.DeathMessage, ("user", implanted.ImplantedEntity.Value), ("position", posText));
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ public sealed class GatewayGeneratorSystem : EntitySystem
|
||||
// Create the gateway.
|
||||
var gatewayUid = SpawnAtPosition(generator.Proto, originCoords);
|
||||
var gatewayComp = Comp<GatewayComponent>(gatewayUid);
|
||||
_gateway.SetDestinationName(gatewayUid, FormattedMessage.FromMarkup($"[color=#D381C996]{gatewayName}[/color]"), gatewayComp);
|
||||
_gateway.SetDestinationName(gatewayUid, FormattedMessage.FromMarkupOrThrow($"[color=#D381C996]{gatewayName}[/color]"), gatewayComp);
|
||||
_gateway.SetEnabled(gatewayUid, true, gatewayComp);
|
||||
generator.Generated.Add(mapUid);
|
||||
}
|
||||
|
||||
@@ -8,42 +8,13 @@ namespace Content.Server.Gravity
|
||||
[Access(typeof(GravityGeneratorSystem))]
|
||||
public sealed partial class GravityGeneratorComponent : SharedGravityGeneratorComponent
|
||||
{
|
||||
// 1% charge per second.
|
||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("chargeRate")] public float ChargeRate { get; set; } = 0.01f;
|
||||
// The gravity generator has two power values.
|
||||
// Idle power is assumed to be the power needed to run the control systems and interface.
|
||||
[DataField("idlePower")] public float IdlePowerUse { get; set; }
|
||||
// Active power is the power needed to keep the gravity field stable.
|
||||
[DataField("activePower")] public float ActivePowerUse { get; set; }
|
||||
[DataField("lightRadiusMin")] public float LightRadiusMin { get; set; }
|
||||
[DataField("lightRadiusMax")] public float LightRadiusMax { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is the power switch on?
|
||||
/// </summary>
|
||||
[DataField("switchedOn")]
|
||||
public bool SwitchedOn { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Is the gravity generator intact?
|
||||
/// </summary>
|
||||
[DataField("intact")]
|
||||
public bool Intact { get; set; } = true;
|
||||
|
||||
[DataField("maxCharge")]
|
||||
public float MaxCharge { get; set; } = 1;
|
||||
|
||||
// 0 -> 1
|
||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("charge")] public float Charge { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Is the gravity generator currently "producing" gravity?
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public bool GravityActive { get; set; } = false;
|
||||
|
||||
// Do we need a UI update even if the charge doesn't change? Used by power button.
|
||||
[ViewVariables] public bool NeedUIUpdate { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,290 +1,63 @@
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Audio;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Gravity;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Gravity
|
||||
namespace Content.Server.Gravity;
|
||||
|
||||
public sealed class GravityGeneratorSystem : EntitySystem
|
||||
{
|
||||
public sealed class GravityGeneratorSystem : EntitySystem
|
||||
[Dependency] private readonly GravitySystem _gravitySystem = default!;
|
||||
[Dependency] private readonly SharedPointLightSystem _lights = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly AmbientSoundSystem _ambientSoundSystem = default!;
|
||||
[Dependency] private readonly GravitySystem _gravitySystem = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SharedPointLightSystem _lights = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
base.Initialize();
|
||||
|
||||
public override void Initialize()
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, EntParentChangedMessage>(OnParentChanged);
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, ChargedMachineActivatedEvent>(OnActivated);
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, ChargedMachineDeactivatedEvent>(OnDeactivated);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
var query = EntityQueryEnumerator<GravityGeneratorComponent, PowerChargeComponent>();
|
||||
while (query.MoveNext(out var uid, out var grav, out var charge))
|
||||
{
|
||||
base.Initialize();
|
||||
if (!_lights.TryGetLight(uid, out var pointLight))
|
||||
continue;
|
||||
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, ComponentInit>(OnCompInit);
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, EntParentChangedMessage>(OnParentChanged); // Or just anchor changed?
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, InteractHandEvent>(OnInteractHand);
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, SharedGravityGeneratorComponent.SwitchGeneratorMessage>(
|
||||
OnSwitchGenerator);
|
||||
_lights.SetEnabled(uid, charge.Charge > 0, pointLight);
|
||||
_lights.SetRadius(uid, MathHelper.Lerp(grav.LightRadiusMin, grav.LightRadiusMax, charge.Charge),
|
||||
pointLight);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnParentChanged(EntityUid uid, GravityGeneratorComponent component, ref EntParentChangedMessage args)
|
||||
private void OnActivated(Entity<GravityGeneratorComponent> ent, ref ChargedMachineActivatedEvent args)
|
||||
{
|
||||
ent.Comp.GravityActive = true;
|
||||
if (TryComp<TransformComponent>(ent, out var xform) &&
|
||||
TryComp(xform.ParentUid, out GravityComponent? gravity))
|
||||
{
|
||||
if (component.GravityActive && TryComp(args.OldParent, out GravityComponent? gravity))
|
||||
{
|
||||
_gravitySystem.RefreshGravity(args.OldParent.Value, gravity);
|
||||
}
|
||||
_gravitySystem.EnableGravity(xform.ParentUid, gravity);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnComponentShutdown(EntityUid uid, GravityGeneratorComponent component, ComponentShutdown args)
|
||||
private void OnDeactivated(Entity<GravityGeneratorComponent> ent, ref ChargedMachineDeactivatedEvent args)
|
||||
{
|
||||
ent.Comp.GravityActive = false;
|
||||
if (TryComp<TransformComponent>(ent, out var xform) &&
|
||||
TryComp(xform.ParentUid, out GravityComponent? gravity))
|
||||
{
|
||||
if (component.GravityActive &&
|
||||
TryComp(uid, out TransformComponent? xform) &&
|
||||
TryComp(xform.ParentUid, out GravityComponent? gravity))
|
||||
{
|
||||
component.GravityActive = false;
|
||||
_gravitySystem.RefreshGravity(xform.ParentUid, gravity);
|
||||
}
|
||||
_gravitySystem.RefreshGravity(xform.ParentUid, gravity);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
private void OnParentChanged(EntityUid uid, GravityGeneratorComponent component, ref EntParentChangedMessage args)
|
||||
{
|
||||
if (component.GravityActive && TryComp(args.OldParent, out GravityComponent? gravity))
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<GravityGeneratorComponent, ApcPowerReceiverComponent>();
|
||||
while (query.MoveNext(out var uid, out var gravGen, out var powerReceiver))
|
||||
{
|
||||
var ent = (uid, gravGen, powerReceiver);
|
||||
if (!gravGen.Intact)
|
||||
continue;
|
||||
|
||||
// Calculate charge rate based on power state and such.
|
||||
// Negative charge rate means discharging.
|
||||
float chargeRate;
|
||||
if (gravGen.SwitchedOn)
|
||||
{
|
||||
if (powerReceiver.Powered)
|
||||
{
|
||||
chargeRate = gravGen.ChargeRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scale discharge rate such that if we're at 25% active power we discharge at 75% rate.
|
||||
var receiving = powerReceiver.PowerReceived;
|
||||
var mainSystemPower = Math.Max(0, receiving - gravGen.IdlePowerUse);
|
||||
var ratio = 1 - mainSystemPower / (gravGen.ActivePowerUse - gravGen.IdlePowerUse);
|
||||
chargeRate = -(ratio * gravGen.ChargeRate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chargeRate = -gravGen.ChargeRate;
|
||||
}
|
||||
|
||||
var active = gravGen.GravityActive;
|
||||
var lastCharge = gravGen.Charge;
|
||||
gravGen.Charge = Math.Clamp(gravGen.Charge + frameTime * chargeRate, 0, gravGen.MaxCharge);
|
||||
if (chargeRate > 0)
|
||||
{
|
||||
// Charging.
|
||||
if (MathHelper.CloseTo(gravGen.Charge, gravGen.MaxCharge) && !gravGen.GravityActive)
|
||||
{
|
||||
gravGen.GravityActive = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Discharging
|
||||
if (MathHelper.CloseTo(gravGen.Charge, 0) && gravGen.GravityActive)
|
||||
{
|
||||
gravGen.GravityActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
var updateUI = gravGen.NeedUIUpdate;
|
||||
if (!MathHelper.CloseTo(lastCharge, gravGen.Charge))
|
||||
{
|
||||
UpdateState(ent);
|
||||
updateUI = true;
|
||||
}
|
||||
|
||||
if (updateUI)
|
||||
UpdateUI(ent, chargeRate);
|
||||
|
||||
if (active != gravGen.GravityActive &&
|
||||
TryComp(uid, out TransformComponent? xform) &&
|
||||
TryComp<GravityComponent>(xform.ParentUid, out var gravity))
|
||||
{
|
||||
// Force it on in the faster path.
|
||||
if (gravGen.GravityActive)
|
||||
{
|
||||
_gravitySystem.EnableGravity(xform.ParentUid, gravity);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gravitySystem.RefreshGravity(xform.ParentUid, gravity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetSwitchedOn(EntityUid uid, GravityGeneratorComponent component, bool on,
|
||||
ApcPowerReceiverComponent? powerReceiver = null, EntityUid? user = null)
|
||||
{
|
||||
if (!Resolve(uid, ref powerReceiver))
|
||||
return;
|
||||
|
||||
if (user != null)
|
||||
_adminLogger.Add(LogType.Action, on ? LogImpact.Medium : LogImpact.High, $"{ToPrettyString(user)} set ${ToPrettyString(uid):target} to {(on ? "on" : "off")}");
|
||||
|
||||
component.SwitchedOn = on;
|
||||
UpdatePowerState(component, powerReceiver);
|
||||
component.NeedUIUpdate = true;
|
||||
}
|
||||
|
||||
private static void UpdatePowerState(
|
||||
GravityGeneratorComponent component,
|
||||
ApcPowerReceiverComponent powerReceiver)
|
||||
{
|
||||
powerReceiver.Load = component.SwitchedOn ? component.ActivePowerUse : component.IdlePowerUse;
|
||||
}
|
||||
|
||||
private void UpdateUI(Entity<GravityGeneratorComponent, ApcPowerReceiverComponent> ent, float chargeRate)
|
||||
{
|
||||
var (_, component, powerReceiver) = ent;
|
||||
if (!_uiSystem.IsUiOpen(ent.Owner, SharedGravityGeneratorComponent.GravityGeneratorUiKey.Key))
|
||||
return;
|
||||
|
||||
var chargeTarget = chargeRate < 0 ? 0 : component.MaxCharge;
|
||||
short chargeEta;
|
||||
var atTarget = false;
|
||||
if (MathHelper.CloseTo(component.Charge, chargeTarget))
|
||||
{
|
||||
chargeEta = short.MinValue; // N/A
|
||||
atTarget = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var diff = chargeTarget - component.Charge;
|
||||
chargeEta = (short) Math.Abs(diff / chargeRate);
|
||||
}
|
||||
|
||||
var status = chargeRate switch
|
||||
{
|
||||
> 0 when atTarget => GravityGeneratorPowerStatus.FullyCharged,
|
||||
< 0 when atTarget => GravityGeneratorPowerStatus.Off,
|
||||
> 0 => GravityGeneratorPowerStatus.Charging,
|
||||
< 0 => GravityGeneratorPowerStatus.Discharging,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
var state = new SharedGravityGeneratorComponent.GeneratorState(
|
||||
component.SwitchedOn,
|
||||
(byte) (component.Charge * 255),
|
||||
status,
|
||||
(short) Math.Round(powerReceiver.PowerReceived),
|
||||
(short) Math.Round(powerReceiver.Load),
|
||||
chargeEta
|
||||
);
|
||||
|
||||
_uiSystem.SetUiState(
|
||||
ent.Owner,
|
||||
SharedGravityGeneratorComponent.GravityGeneratorUiKey.Key,
|
||||
state);
|
||||
|
||||
component.NeedUIUpdate = false;
|
||||
}
|
||||
|
||||
private void OnCompInit(Entity<GravityGeneratorComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
ApcPowerReceiverComponent? powerReceiver = null;
|
||||
if (!Resolve(ent, ref powerReceiver, false))
|
||||
return;
|
||||
|
||||
UpdatePowerState(ent, powerReceiver);
|
||||
UpdateState((ent, ent.Comp, powerReceiver));
|
||||
}
|
||||
|
||||
private void OnInteractHand(EntityUid uid, GravityGeneratorComponent component, InteractHandEvent args)
|
||||
{
|
||||
ApcPowerReceiverComponent? powerReceiver = default!;
|
||||
if (!Resolve(uid, ref powerReceiver))
|
||||
return;
|
||||
|
||||
// Do not allow opening UI if broken or unpowered.
|
||||
if (!component.Intact || powerReceiver.PowerReceived < component.IdlePowerUse)
|
||||
return;
|
||||
|
||||
_uiSystem.OpenUi(uid, SharedGravityGeneratorComponent.GravityGeneratorUiKey.Key, args.User);
|
||||
component.NeedUIUpdate = true;
|
||||
}
|
||||
|
||||
public void UpdateState(Entity<GravityGeneratorComponent, ApcPowerReceiverComponent> ent)
|
||||
{
|
||||
var (uid, grav, powerReceiver) = ent;
|
||||
var appearance = EntityManager.GetComponentOrNull<AppearanceComponent>(uid);
|
||||
_appearance.SetData(uid, GravityGeneratorVisuals.Charge, grav.Charge, appearance);
|
||||
|
||||
if (_lights.TryGetLight(uid, out var pointLight))
|
||||
{
|
||||
_lights.SetEnabled(uid, grav.Charge > 0, pointLight);
|
||||
_lights.SetRadius(uid, MathHelper.Lerp(grav.LightRadiusMin, grav.LightRadiusMax, grav.Charge), pointLight);
|
||||
}
|
||||
|
||||
if (!grav.Intact)
|
||||
{
|
||||
MakeBroken((uid, grav), appearance);
|
||||
}
|
||||
else if (powerReceiver.PowerReceived < grav.IdlePowerUse)
|
||||
{
|
||||
MakeUnpowered((uid, grav), appearance);
|
||||
}
|
||||
else if (!grav.SwitchedOn)
|
||||
{
|
||||
MakeOff((uid, grav), appearance);
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeOn((uid, grav), appearance);
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeBroken(Entity<GravityGeneratorComponent> ent, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(ent, false);
|
||||
|
||||
_appearance.SetData(ent, GravityGeneratorVisuals.State, GravityGeneratorStatus.Broken);
|
||||
}
|
||||
|
||||
private void MakeUnpowered(Entity<GravityGeneratorComponent> ent, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(ent, false);
|
||||
|
||||
_appearance.SetData(ent, GravityGeneratorVisuals.State, GravityGeneratorStatus.Unpowered, appearance);
|
||||
}
|
||||
|
||||
private void MakeOff(Entity<GravityGeneratorComponent> ent, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(ent, false);
|
||||
|
||||
_appearance.SetData(ent, GravityGeneratorVisuals.State, GravityGeneratorStatus.Off, appearance);
|
||||
}
|
||||
|
||||
private void MakeOn(Entity<GravityGeneratorComponent> ent, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(ent, true);
|
||||
|
||||
_appearance.SetData(ent, GravityGeneratorVisuals.State, GravityGeneratorStatus.On, appearance);
|
||||
}
|
||||
|
||||
private void OnSwitchGenerator(
|
||||
EntityUid uid,
|
||||
GravityGeneratorComponent component,
|
||||
SharedGravityGeneratorComponent.SwitchGeneratorMessage args)
|
||||
{
|
||||
SetSwitchedOn(uid, component, args.On, user: args.Actor);
|
||||
_gravitySystem.RefreshGravity(args.OldParent.Value, gravity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace Content.Server.Nuke
|
||||
}
|
||||
|
||||
codesMessage.PushNewline();
|
||||
codesMessage.AddMarkup(Loc.GetString("nuke-codes-list", ("name", MetaData(nukeUid).EntityName), ("code", nuke.Code)));
|
||||
codesMessage.AddMarkupOrThrow(Loc.GetString("nuke-codes-list", ("name", MetaData(nukeUid).EntityName), ("code", nuke.Code)));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -461,7 +461,7 @@ public sealed class NukeSystem : EntitySystem
|
||||
// warn a crew
|
||||
var announcement = Loc.GetString("nuke-component-announcement-armed",
|
||||
("time", (int) component.RemainingTime),
|
||||
("location", FormattedMessage.RemoveMarkup(_navMap.GetNearestBeaconString((uid, nukeXform)))));
|
||||
("location", FormattedMessage.RemoveMarkupOrThrow(_navMap.GetNearestBeaconString((uid, nukeXform)))));
|
||||
var sender = Loc.GetString("nuke-component-announcement-sender");
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid ?? uid, announcement, sender, false, null, Color.Red);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Points;
|
||||
using JetBrains.Annotations;
|
||||
@@ -76,7 +76,7 @@ public sealed class PointSystem : SharedPointSystem
|
||||
if (!_player.TryGetPlayerData(id, out var data))
|
||||
continue;
|
||||
|
||||
msg.AddMarkup(Loc.GetString("point-scoreboard-list",
|
||||
msg.AddMarkupOrThrow(Loc.GetString("point-scoreboard-list",
|
||||
("place", place),
|
||||
("name", data.UserName),
|
||||
("points", points.Int())));
|
||||
|
||||
66
Content.Server/Power/Components/PowerChargeComponent.cs
Normal file
66
Content.Server/Power/Components/PowerChargeComponent.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Power;
|
||||
|
||||
namespace Content.Server.Power.Components;
|
||||
|
||||
/// <inheritdoc cref="Content.Shared.Power.SharedPowerChargeComponent" />
|
||||
[RegisterComponent]
|
||||
[Access(typeof(PowerChargeSystem))]
|
||||
public sealed partial class PowerChargeComponent : SharedPowerChargeComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Change in charge per second.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float ChargeRate { get; set; } = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// Baseline power that this machine consumes.
|
||||
/// </summary>
|
||||
[DataField("idlePower")]
|
||||
public float IdlePowerUse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Power consumed when <see cref="SwitchedOn"/> is true.
|
||||
/// </summary>
|
||||
[DataField("activePower")]
|
||||
public float ActivePowerUse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the gravity generator intact?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool Intact { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Is the power switch on?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool SwitchedOn { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the power is switched on and the entity has charged up.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool Active { get; set; }
|
||||
|
||||
[DataField]
|
||||
public float MaxCharge { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The UI key of the UI that's used with this machine.<br/>
|
||||
/// This is used to allow machine power charging to be integrated into any ui
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public Enum UiKey { get; set; } = PowerChargeUiKey.Key;
|
||||
|
||||
/// <summary>
|
||||
/// Current charge value.
|
||||
/// Goes from 0 to 1.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float Charge { get; set; } = 1;
|
||||
|
||||
[ViewVariables]
|
||||
public bool NeedUIUpdate { get; set; }
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace Content.Server.Power.EntitySystems
|
||||
if (args.Handled || args.Target == null || !args.CanReach || !_toolSystem.HasQuality(args.Used, SharedToolSystem.PulseQuality))
|
||||
return;
|
||||
|
||||
var markup = FormattedMessage.FromMarkup(GenerateCableMarkup(uid));
|
||||
var markup = FormattedMessage.FromMarkupOrThrow(GenerateCableMarkup(uid));
|
||||
_examineSystem.SendExamineTooltip(args.User, uid, markup, false, false);
|
||||
args.Handled = true;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ namespace Content.Server.Power.EntitySystems
|
||||
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/zap.svg.192dpi.png")),
|
||||
Act = () =>
|
||||
{
|
||||
var markup = FormattedMessage.FromMarkup(GenerateCableMarkup(uid));
|
||||
var markup = FormattedMessage.FromMarkupOrThrow(GenerateCableMarkup(uid));
|
||||
_examineSystem.SendExamineTooltip(args.User, uid, markup, false, false);
|
||||
}
|
||||
};
|
||||
|
||||
283
Content.Server/Power/EntitySystems/PowerChargeSystem.cs
Normal file
283
Content.Server/Power/EntitySystems/PowerChargeSystem.cs
Normal file
@@ -0,0 +1,283 @@
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Audio;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Power;
|
||||
using Content.Shared.UserInterface;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Power.EntitySystems;
|
||||
|
||||
public sealed class PowerChargeSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly AmbientSoundSystem _ambientSoundSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PowerChargeComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<PowerChargeComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
SubscribeLocalEvent<PowerChargeComponent, ActivatableUIOpenAttemptEvent>(OnUIOpenAttempt);
|
||||
SubscribeLocalEvent<PowerChargeComponent, AfterActivatableUIOpenEvent>(OnAfterUiOpened);
|
||||
SubscribeLocalEvent<PowerChargeComponent, AnchorStateChangedEvent>(OnAnchorStateChange);
|
||||
|
||||
// This needs to be ui key agnostic
|
||||
SubscribeLocalEvent<PowerChargeComponent, SwitchChargingMachineMessage>(OnSwitchGenerator);
|
||||
}
|
||||
|
||||
private void OnAnchorStateChange(EntityUid uid, PowerChargeComponent component, AnchorStateChangedEvent args)
|
||||
{
|
||||
if (args.Anchored || !TryComp<ApcPowerReceiverComponent>(uid, out var powerReceiverComponent))
|
||||
return;
|
||||
|
||||
component.Active = false;
|
||||
component.Charge = 0;
|
||||
UpdateState(new Entity<PowerChargeComponent, ApcPowerReceiverComponent>(uid, component, powerReceiverComponent));
|
||||
}
|
||||
|
||||
private void OnAfterUiOpened(EntityUid uid, PowerChargeComponent component, AfterActivatableUIOpenEvent args)
|
||||
{
|
||||
if (!TryComp<ApcPowerReceiverComponent>(uid, out var apcPowerReceiver))
|
||||
return;
|
||||
|
||||
UpdateUI((uid, component, apcPowerReceiver), component.ChargeRate);
|
||||
}
|
||||
|
||||
private void OnSwitchGenerator(EntityUid uid, PowerChargeComponent component, SwitchChargingMachineMessage args)
|
||||
{
|
||||
SetSwitchedOn(uid, component, args.On, user: args.Actor);
|
||||
}
|
||||
|
||||
private void OnUIOpenAttempt(EntityUid uid, PowerChargeComponent component, ActivatableUIOpenAttemptEvent args)
|
||||
{
|
||||
if (!component.Intact)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnComponentShutdown(EntityUid uid, PowerChargeComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (!component.Active)
|
||||
return;
|
||||
|
||||
component.Active = false;
|
||||
|
||||
var eventArgs = new ChargedMachineDeactivatedEvent();
|
||||
RaiseLocalEvent(uid, ref eventArgs);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<PowerChargeComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
ApcPowerReceiverComponent? powerReceiver = null;
|
||||
if (!Resolve(ent, ref powerReceiver, false))
|
||||
return;
|
||||
|
||||
UpdatePowerState(ent, powerReceiver);
|
||||
UpdateState((ent, ent.Comp, powerReceiver));
|
||||
}
|
||||
|
||||
private void SetSwitchedOn(EntityUid uid, PowerChargeComponent component, bool on,
|
||||
ApcPowerReceiverComponent? powerReceiver = null, EntityUid? user = null)
|
||||
{
|
||||
if (!Resolve(uid, ref powerReceiver))
|
||||
return;
|
||||
|
||||
if (user is { } )
|
||||
_adminLogger.Add(LogType.Action, on ? LogImpact.Medium : LogImpact.High, $"{ToPrettyString(user):player} set ${ToPrettyString(uid):target} to {(on ? "on" : "off")}");
|
||||
|
||||
component.SwitchedOn = on;
|
||||
UpdatePowerState(component, powerReceiver);
|
||||
component.NeedUIUpdate = true;
|
||||
}
|
||||
|
||||
private static void UpdatePowerState(PowerChargeComponent component, ApcPowerReceiverComponent powerReceiver)
|
||||
{
|
||||
powerReceiver.Load = component.SwitchedOn ? component.ActivePowerUse : component.IdlePowerUse;
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<PowerChargeComponent, ApcPowerReceiverComponent>();
|
||||
while (query.MoveNext(out var uid, out var chargingMachine, out var powerReceiver))
|
||||
{
|
||||
var ent = (uid, gravGen: chargingMachine, powerReceiver);
|
||||
if (!chargingMachine.Intact)
|
||||
continue;
|
||||
|
||||
// Calculate charge rate based on power state and such.
|
||||
// Negative charge rate means discharging.
|
||||
float chargeRate;
|
||||
if (chargingMachine.SwitchedOn)
|
||||
{
|
||||
if (powerReceiver.Powered)
|
||||
{
|
||||
chargeRate = chargingMachine.ChargeRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scale discharge rate such that if we're at 25% active power we discharge at 75% rate.
|
||||
var receiving = powerReceiver.PowerReceived;
|
||||
var mainSystemPower = Math.Max(0, receiving - chargingMachine.IdlePowerUse);
|
||||
var ratio = 1 - mainSystemPower / (chargingMachine.ActivePowerUse - chargingMachine.IdlePowerUse);
|
||||
chargeRate = -(ratio * chargingMachine.ChargeRate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chargeRate = -chargingMachine.ChargeRate;
|
||||
}
|
||||
|
||||
var active = chargingMachine.Active;
|
||||
var lastCharge = chargingMachine.Charge;
|
||||
chargingMachine.Charge = Math.Clamp(chargingMachine.Charge + frameTime * chargeRate, 0, chargingMachine.MaxCharge);
|
||||
if (chargeRate > 0)
|
||||
{
|
||||
// Charging.
|
||||
if (MathHelper.CloseTo(chargingMachine.Charge, chargingMachine.MaxCharge) && !chargingMachine.Active)
|
||||
{
|
||||
chargingMachine.Active = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Discharging
|
||||
if (MathHelper.CloseTo(chargingMachine.Charge, 0) && chargingMachine.Active)
|
||||
{
|
||||
chargingMachine.Active = false;
|
||||
}
|
||||
}
|
||||
|
||||
var updateUI = chargingMachine.NeedUIUpdate;
|
||||
if (!MathHelper.CloseTo(lastCharge, chargingMachine.Charge))
|
||||
{
|
||||
UpdateState(ent);
|
||||
updateUI = true;
|
||||
}
|
||||
|
||||
if (updateUI)
|
||||
UpdateUI(ent, chargeRate);
|
||||
|
||||
if (active == chargingMachine.Active)
|
||||
continue;
|
||||
|
||||
if (chargingMachine.Active)
|
||||
{
|
||||
var eventArgs = new ChargedMachineActivatedEvent();
|
||||
RaiseLocalEvent(uid, ref eventArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
var eventArgs = new ChargedMachineDeactivatedEvent();
|
||||
RaiseLocalEvent(uid, ref eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateUI(Entity<PowerChargeComponent, ApcPowerReceiverComponent> ent, float chargeRate)
|
||||
{
|
||||
var (_, component, powerReceiver) = ent;
|
||||
if (!_uiSystem.IsUiOpen(ent.Owner, component.UiKey))
|
||||
return;
|
||||
|
||||
var chargeTarget = chargeRate < 0 ? 0 : component.MaxCharge;
|
||||
short chargeEta;
|
||||
var atTarget = false;
|
||||
if (MathHelper.CloseTo(component.Charge, chargeTarget))
|
||||
{
|
||||
chargeEta = short.MinValue; // N/A
|
||||
atTarget = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var diff = chargeTarget - component.Charge;
|
||||
chargeEta = (short) Math.Abs(diff / chargeRate);
|
||||
}
|
||||
|
||||
var status = chargeRate switch
|
||||
{
|
||||
> 0 when atTarget => PowerChargePowerStatus.FullyCharged,
|
||||
< 0 when atTarget => PowerChargePowerStatus.Off,
|
||||
> 0 => PowerChargePowerStatus.Charging,
|
||||
< 0 => PowerChargePowerStatus.Discharging,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
var state = new PowerChargeState(
|
||||
component.SwitchedOn,
|
||||
(byte) (component.Charge * 255),
|
||||
status,
|
||||
(short) Math.Round(powerReceiver.PowerReceived),
|
||||
(short) Math.Round(powerReceiver.Load),
|
||||
chargeEta
|
||||
);
|
||||
|
||||
_uiSystem.SetUiState(
|
||||
ent.Owner,
|
||||
component.UiKey,
|
||||
state);
|
||||
|
||||
component.NeedUIUpdate = false;
|
||||
}
|
||||
|
||||
private void UpdateState(Entity<PowerChargeComponent, ApcPowerReceiverComponent> ent)
|
||||
{
|
||||
var (uid, machine, powerReceiver) = ent;
|
||||
var appearance = EntityManager.GetComponentOrNull<AppearanceComponent>(uid);
|
||||
_appearance.SetData(uid, PowerChargeVisuals.Charge, machine.Charge, appearance);
|
||||
_appearance.SetData(uid, PowerChargeVisuals.Active, machine.Active);
|
||||
|
||||
|
||||
if (!machine.Intact)
|
||||
{
|
||||
MakeBroken((uid, machine), appearance);
|
||||
}
|
||||
else if (powerReceiver.PowerReceived < machine.IdlePowerUse)
|
||||
{
|
||||
MakeUnpowered((uid, machine), appearance);
|
||||
}
|
||||
else if (!machine.SwitchedOn)
|
||||
{
|
||||
MakeOff((uid, machine), appearance);
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeOn((uid, machine), appearance);
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeBroken(Entity<PowerChargeComponent> ent, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(ent, false);
|
||||
|
||||
_appearance.SetData(ent, PowerChargeVisuals.State, PowerChargeStatus.Broken, appearance);
|
||||
}
|
||||
|
||||
private void MakeUnpowered(Entity<PowerChargeComponent> ent, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(ent, false);
|
||||
|
||||
_appearance.SetData(ent, PowerChargeVisuals.State, PowerChargeStatus.Unpowered, appearance);
|
||||
}
|
||||
|
||||
private void MakeOff(Entity<PowerChargeComponent> ent, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(ent, false);
|
||||
|
||||
_appearance.SetData(ent, PowerChargeVisuals.State, PowerChargeStatus.Off, appearance);
|
||||
}
|
||||
|
||||
private void MakeOn(Entity<PowerChargeComponent> ent, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(ent, true);
|
||||
|
||||
_appearance.SetData(ent, PowerChargeVisuals.State, PowerChargeStatus.On, appearance);
|
||||
}
|
||||
}
|
||||
|
||||
[ByRefEvent] public record struct ChargedMachineActivatedEvent;
|
||||
[ByRefEvent] public record struct ChargedMachineDeactivatedEvent;
|
||||
11
Content.Server/Shuttles/Components/StationAnchorComponent.cs
Normal file
11
Content.Server/Shuttles/Components/StationAnchorComponent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Content.Server.Shuttles.Systems;
|
||||
|
||||
namespace Content.Server.Shuttles.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(StationAnchorSystem))]
|
||||
public sealed partial class StationAnchorComponent : Component
|
||||
{
|
||||
[DataField("switchedOn")]
|
||||
public bool SwitchedOn { get; set; } = true;
|
||||
}
|
||||
86
Content.Server/Shuttles/Systems/StationAnchorSystem.cs
Normal file
86
Content.Server/Shuttles/Systems/StationAnchorSystem.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Shared.Construction.Components;
|
||||
using Content.Shared.Popups;
|
||||
|
||||
namespace Content.Server.Shuttles.Systems;
|
||||
|
||||
public sealed class StationAnchorSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ShuttleSystem _shuttleSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<StationAnchorComponent, UnanchorAttemptEvent>(OnUnanchorAttempt);
|
||||
SubscribeLocalEvent<StationAnchorComponent, AnchorStateChangedEvent>(OnAnchorStationChange);
|
||||
|
||||
SubscribeLocalEvent<StationAnchorComponent, ChargedMachineActivatedEvent>(OnActivated);
|
||||
SubscribeLocalEvent<StationAnchorComponent, ChargedMachineDeactivatedEvent>(OnDeactivated);
|
||||
|
||||
SubscribeLocalEvent<StationAnchorComponent, MapInitEvent>(OnMapInit);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<StationAnchorComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
if (!ent.Comp.SwitchedOn)
|
||||
return;
|
||||
|
||||
SetStatus(ent, true);
|
||||
}
|
||||
|
||||
private void OnActivated(Entity<StationAnchorComponent> ent, ref ChargedMachineActivatedEvent args)
|
||||
{
|
||||
SetStatus(ent, true);
|
||||
}
|
||||
|
||||
private void OnDeactivated(Entity<StationAnchorComponent> ent, ref ChargedMachineDeactivatedEvent args)
|
||||
{
|
||||
SetStatus(ent, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prevent unanchoring when anchor is active
|
||||
/// </summary>
|
||||
private void OnUnanchorAttempt(Entity<StationAnchorComponent> ent, ref UnanchorAttemptEvent args)
|
||||
{
|
||||
if (!ent.Comp.SwitchedOn)
|
||||
return;
|
||||
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("station-anchor-unanchoring-failed"),
|
||||
ent,
|
||||
args.User,
|
||||
PopupType.Medium);
|
||||
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnAnchorStationChange(Entity<StationAnchorComponent> ent, ref AnchorStateChangedEvent args)
|
||||
{
|
||||
if (!args.Anchored)
|
||||
SetStatus(ent, false);
|
||||
}
|
||||
|
||||
private void SetStatus(Entity<StationAnchorComponent> ent, bool enabled, ShuttleComponent? shuttleComponent = default)
|
||||
{
|
||||
var transform = Transform(ent);
|
||||
var grid = transform.GridUid;
|
||||
if (!grid.HasValue || !transform.Anchored && enabled || !Resolve(grid.Value, ref shuttleComponent))
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
_shuttleSystem.Disable(grid.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_shuttleSystem.Enable(grid.Value);
|
||||
}
|
||||
|
||||
shuttleComponent.Enabled = !enabled;
|
||||
ent.Comp.SwitchedOn = enabled;
|
||||
}
|
||||
}
|
||||
@@ -100,19 +100,55 @@ namespace Content.Server.Stack
|
||||
/// </summary>
|
||||
public List<EntityUid> SpawnMultiple(string entityPrototype, int amount, EntityCoordinates spawnPosition)
|
||||
{
|
||||
var proto = _prototypeManager.Index<EntityPrototype>(entityPrototype);
|
||||
proto.TryGetComponent<StackComponent>(out var stack);
|
||||
var maxCountPerStack = GetMaxCount(stack);
|
||||
var spawns = CalculateSpawns(entityPrototype, amount);
|
||||
|
||||
var spawnedEnts = new List<EntityUid>();
|
||||
foreach (var count in spawns)
|
||||
{
|
||||
var entity = SpawnAtPosition(entityPrototype, spawnPosition);
|
||||
spawnedEnts.Add(entity);
|
||||
SetCount(entity, count);
|
||||
}
|
||||
|
||||
return spawnedEnts;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SpawnMultiple(string,int,EntityCoordinates)"/>
|
||||
public List<EntityUid> SpawnMultiple(string entityPrototype, int amount, EntityUid target)
|
||||
{
|
||||
var spawns = CalculateSpawns(entityPrototype, amount);
|
||||
|
||||
var spawnedEnts = new List<EntityUid>();
|
||||
foreach (var count in spawns)
|
||||
{
|
||||
var entity = SpawnNextToOrDrop(entityPrototype, target);
|
||||
spawnedEnts.Add(entity);
|
||||
SetCount(entity, count);
|
||||
}
|
||||
|
||||
return spawnedEnts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates how many stacks to spawn that total up to <paramref name="amount"/>.
|
||||
/// </summary>
|
||||
/// <param name="entityPrototype">The stack to spawn.</param>
|
||||
/// <param name="amount">The amount of pieces across all stacks.</param>
|
||||
/// <returns>The list of stack counts per entity.</returns>
|
||||
private List<int> CalculateSpawns(string entityPrototype, int amount)
|
||||
{
|
||||
var proto = _prototypeManager.Index<EntityPrototype>(entityPrototype);
|
||||
proto.TryGetComponent<StackComponent>(out var stack, EntityManager.ComponentFactory);
|
||||
var maxCountPerStack = GetMaxCount(stack);
|
||||
var amounts = new List<int>();
|
||||
while (amount > 0)
|
||||
{
|
||||
var entity = Spawn(entityPrototype, spawnPosition);
|
||||
spawnedEnts.Add(entity);
|
||||
var countAmount = Math.Min(maxCountPerStack, amount);
|
||||
SetCount(entity, countAmount);
|
||||
amount -= countAmount;
|
||||
amounts.Add(countAmount);
|
||||
}
|
||||
return spawnedEnts;
|
||||
|
||||
return amounts;
|
||||
}
|
||||
|
||||
private void OnStackAlternativeInteract(EntityUid uid, StackComponent stack, GetVerbsEvent<AlternativeVerb> args)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Cargo.Systems;
|
||||
@@ -128,7 +128,7 @@ public record struct OnlyOneStationsError : IConError
|
||||
{
|
||||
public FormattedMessage DescribeInner()
|
||||
{
|
||||
return FormattedMessage.FromMarkup("This command doesn't function if there is more than one or no stations, explicitly specify a station with the ent command or similar.");
|
||||
return FormattedMessage.FromMarkupOrThrow("This command doesn't function if there is more than one or no stations, explicitly specify a station with the ent command or similar.");
|
||||
}
|
||||
|
||||
public string? Expression { get; set; }
|
||||
|
||||
@@ -79,7 +79,7 @@ public sealed class TraitorCodePaperSystem : EntitySystem
|
||||
break;
|
||||
|
||||
codesMessage.PushNewline();
|
||||
codesMessage.AddMarkup(code);
|
||||
codesMessage.AddMarkupOrThrow(code);
|
||||
}
|
||||
|
||||
if (!codesMessage.IsEmpty)
|
||||
|
||||
@@ -387,11 +387,7 @@ public sealed class WiresSystem : SharedWiresSystem
|
||||
|
||||
private void OnWiresActionMessage(EntityUid uid, WiresComponent component, WiresActionMessage args)
|
||||
{
|
||||
if (args.Actor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var player = (EntityUid) args.Actor;
|
||||
var player = args.Actor;
|
||||
|
||||
if (!EntityManager.TryGetComponent(player, out HandsComponent? handsComponent))
|
||||
{
|
||||
|
||||
@@ -304,15 +304,15 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
|
||||
|
||||
var n = component.LastAnalyzedNode;
|
||||
|
||||
msg.AddMarkup(Loc.GetString("analysis-console-info-id", ("id", n.Id)));
|
||||
msg.AddMarkupOrThrow(Loc.GetString("analysis-console-info-id", ("id", n.Id)));
|
||||
msg.PushNewline();
|
||||
msg.AddMarkup(Loc.GetString("analysis-console-info-depth", ("depth", n.Depth)));
|
||||
msg.AddMarkupOrThrow(Loc.GetString("analysis-console-info-depth", ("depth", n.Depth)));
|
||||
msg.PushNewline();
|
||||
|
||||
var activated = n.Triggered
|
||||
? "analysis-console-info-triggered-true"
|
||||
: "analysis-console-info-triggered-false";
|
||||
msg.AddMarkup(Loc.GetString(activated));
|
||||
msg.AddMarkupOrThrow(Loc.GetString(activated));
|
||||
msg.PushNewline();
|
||||
|
||||
msg.PushNewline();
|
||||
@@ -321,7 +321,7 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
|
||||
var triggerProto = _prototype.Index<ArtifactTriggerPrototype>(n.Trigger);
|
||||
if (triggerProto.TriggerHint != null)
|
||||
{
|
||||
msg.AddMarkup(Loc.GetString("analysis-console-info-trigger",
|
||||
msg.AddMarkupOrThrow(Loc.GetString("analysis-console-info-trigger",
|
||||
("trigger", Loc.GetString(triggerProto.TriggerHint))) + "\n");
|
||||
needSecondNewline = true;
|
||||
}
|
||||
@@ -329,7 +329,7 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
|
||||
var effectproto = _prototype.Index<ArtifactEffectPrototype>(n.Effect);
|
||||
if (effectproto.EffectHint != null)
|
||||
{
|
||||
msg.AddMarkup(Loc.GetString("analysis-console-info-effect",
|
||||
msg.AddMarkupOrThrow(Loc.GetString("analysis-console-info-effect",
|
||||
("effect", Loc.GetString(effectproto.EffectHint))) + "\n");
|
||||
needSecondNewline = true;
|
||||
}
|
||||
@@ -337,11 +337,11 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
|
||||
if (needSecondNewline)
|
||||
msg.PushNewline();
|
||||
|
||||
msg.AddMarkup(Loc.GetString("analysis-console-info-edges", ("edges", n.Edges.Count)));
|
||||
msg.AddMarkupOrThrow(Loc.GetString("analysis-console-info-edges", ("edges", n.Edges.Count)));
|
||||
msg.PushNewline();
|
||||
|
||||
if (component.LastAnalyzerPointValue != null)
|
||||
msg.AddMarkup(Loc.GetString("analysis-console-info-value", ("value", component.LastAnalyzerPointValue)));
|
||||
msg.AddMarkupOrThrow(Loc.GetString("analysis-console-info-value", ("value", component.LastAnalyzerPointValue)));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Content.Shared.Examine
|
||||
|
||||
if (group.Title != null)
|
||||
{
|
||||
message.AddMarkup(Loc.GetString(group.Title));
|
||||
message.AddMarkupOrThrow(Loc.GetString(group.Title));
|
||||
message.PushNewline();
|
||||
}
|
||||
message.AddMessage(GetFormattedMessageFromExamineEntries(group.Entries));
|
||||
|
||||
@@ -447,7 +447,7 @@ namespace Content.Shared.Examine
|
||||
/// <seealso cref="PushMessage"/>
|
||||
public void PushMarkup(string markup, int priority=0)
|
||||
{
|
||||
PushMessage(FormattedMessage.FromMarkup(markup), priority);
|
||||
PushMessage(FormattedMessage.FromMarkupOrThrow(markup), priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -495,7 +495,7 @@ namespace Content.Shared.Examine
|
||||
/// <seealso cref="AddMessage"/>
|
||||
public void AddMarkup(string markup, int priority=0)
|
||||
{
|
||||
AddMessage(FormattedMessage.FromMarkup(markup), priority);
|
||||
AddMessage(FormattedMessage.FromMarkupOrThrow(markup), priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,118 +1,44 @@
|
||||
using Content.Shared.Power;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Gravity
|
||||
namespace Content.Shared.Gravity;
|
||||
|
||||
[NetworkedComponent()]
|
||||
[Virtual]
|
||||
public partial class SharedGravityGeneratorComponent : Component
|
||||
{
|
||||
[NetworkedComponent()]
|
||||
[Virtual]
|
||||
public partial class SharedGravityGeneratorComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// A map of the sprites used by the gravity generator given its status.
|
||||
/// </summary>
|
||||
[DataField("spriteMap")]
|
||||
[Access(typeof(SharedGravitySystem))]
|
||||
public Dictionary<GravityGeneratorStatus, string> SpriteMap = new();
|
||||
/// <summary>
|
||||
/// A map of the sprites used by the gravity generator given its status.
|
||||
/// </summary>
|
||||
[DataField("spriteMap")]
|
||||
[Access(typeof(SharedGravitySystem))]
|
||||
public Dictionary<PowerChargeStatus, string> SpriteMap = new();
|
||||
|
||||
/// <summary>
|
||||
/// The sprite used by the core of the gravity generator when the gravity generator is starting up.
|
||||
/// </summary>
|
||||
[DataField("coreStartupState")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CoreStartupState = "startup";
|
||||
/// <summary>
|
||||
/// The sprite used by the core of the gravity generator when the gravity generator is starting up.
|
||||
/// </summary>
|
||||
[DataField("coreStartupState")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CoreStartupState = "startup";
|
||||
|
||||
/// <summary>
|
||||
/// The sprite used by the core of the gravity generator when the gravity generator is idle.
|
||||
/// </summary>
|
||||
[DataField("coreIdleState")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CoreIdleState = "idle";
|
||||
/// <summary>
|
||||
/// The sprite used by the core of the gravity generator when the gravity generator is idle.
|
||||
/// </summary>
|
||||
[DataField("coreIdleState")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CoreIdleState = "idle";
|
||||
|
||||
/// <summary>
|
||||
/// The sprite used by the core of the gravity generator when the gravity generator is activating.
|
||||
/// </summary>
|
||||
[DataField("coreActivatingState")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CoreActivatingState = "activating";
|
||||
/// <summary>
|
||||
/// The sprite used by the core of the gravity generator when the gravity generator is activating.
|
||||
/// </summary>
|
||||
[DataField("coreActivatingState")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CoreActivatingState = "activating";
|
||||
|
||||
/// <summary>
|
||||
/// The sprite used by the core of the gravity generator when the gravity generator is active.
|
||||
/// </summary>
|
||||
[DataField("coreActivatedState")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CoreActivatedState = "activated";
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the server to set whether the generator should be on or off
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SwitchGeneratorMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public bool On;
|
||||
|
||||
public SwitchGeneratorMessage(bool on)
|
||||
{
|
||||
On = on;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class GeneratorState : BoundUserInterfaceState
|
||||
{
|
||||
public bool On;
|
||||
// 0 -> 255
|
||||
public byte Charge;
|
||||
public GravityGeneratorPowerStatus PowerStatus;
|
||||
public short PowerDraw;
|
||||
public short PowerDrawMax;
|
||||
public short EtaSeconds;
|
||||
|
||||
public GeneratorState(
|
||||
bool on,
|
||||
byte charge,
|
||||
GravityGeneratorPowerStatus powerStatus,
|
||||
short powerDraw,
|
||||
short powerDrawMax,
|
||||
short etaSeconds)
|
||||
{
|
||||
On = on;
|
||||
Charge = charge;
|
||||
PowerStatus = powerStatus;
|
||||
PowerDraw = powerDraw;
|
||||
PowerDrawMax = powerDrawMax;
|
||||
EtaSeconds = etaSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum GravityGeneratorUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum GravityGeneratorVisuals
|
||||
{
|
||||
State,
|
||||
Charge
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum GravityGeneratorStatus
|
||||
{
|
||||
Broken,
|
||||
Unpowered,
|
||||
Off,
|
||||
On
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum GravityGeneratorPowerStatus : byte
|
||||
{
|
||||
Off,
|
||||
Discharging,
|
||||
Charging,
|
||||
FullyCharged
|
||||
}
|
||||
/// <summary>
|
||||
/// The sprite used by the core of the gravity generator when the gravity generator is active.
|
||||
/// </summary>
|
||||
[DataField("coreActivatedState")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CoreActivatedState = "activated";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.IdentityManagement;
|
||||
@@ -85,12 +85,12 @@ public sealed class HealthExaminableSystem : EntitySystem
|
||||
{
|
||||
first = false;
|
||||
}
|
||||
msg.AddMarkup(chosenLocStr);
|
||||
msg.AddMarkupOrThrow(chosenLocStr);
|
||||
}
|
||||
|
||||
if (msg.IsEmpty)
|
||||
{
|
||||
msg.AddMarkup(Loc.GetString($"health-examinable-{component.LocPrefix}-none"));
|
||||
msg.AddMarkupOrThrow(Loc.GetString($"health-examinable-{component.LocPrefix}-none"));
|
||||
}
|
||||
|
||||
// Anything else want to add on to this?
|
||||
|
||||
77
Content.Shared/Power/SharedPowerCharge.cs
Normal file
77
Content.Shared/Power/SharedPowerCharge.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Power;
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the server to set whether the machine should be on or off
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SwitchChargingMachineMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public bool On;
|
||||
|
||||
public SwitchChargingMachineMessage(bool on)
|
||||
{
|
||||
On = on;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class PowerChargeState : BoundUserInterfaceState
|
||||
{
|
||||
public bool On;
|
||||
// 0 -> 255
|
||||
public byte Charge;
|
||||
public PowerChargePowerStatus PowerStatus;
|
||||
public short PowerDraw;
|
||||
public short PowerDrawMax;
|
||||
public short EtaSeconds;
|
||||
|
||||
public PowerChargeState(
|
||||
bool on,
|
||||
byte charge,
|
||||
PowerChargePowerStatus powerStatus,
|
||||
short powerDraw,
|
||||
short powerDrawMax,
|
||||
short etaSeconds)
|
||||
{
|
||||
On = on;
|
||||
Charge = charge;
|
||||
PowerStatus = powerStatus;
|
||||
PowerDraw = powerDraw;
|
||||
PowerDrawMax = powerDrawMax;
|
||||
EtaSeconds = etaSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum PowerChargeUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum PowerChargeVisuals
|
||||
{
|
||||
State,
|
||||
Charge,
|
||||
Active
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum PowerChargeStatus
|
||||
{
|
||||
Broken,
|
||||
Unpowered,
|
||||
Off,
|
||||
On
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum PowerChargePowerStatus : byte
|
||||
{
|
||||
Off,
|
||||
Discharging,
|
||||
Charging,
|
||||
FullyCharged
|
||||
}
|
||||
14
Content.Shared/Power/SharedPowerChargeComponent.cs
Normal file
14
Content.Shared/Power/SharedPowerChargeComponent.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Content.Shared.Power;
|
||||
|
||||
/// <summary>
|
||||
/// Component for a powered machine that slowly powers on and off over a period of time.
|
||||
/// </summary>
|
||||
public abstract partial class SharedPowerChargeComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The title used for the default charged machine window if used
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId WindowTitle { get; set; } = string.Empty;
|
||||
|
||||
}
|
||||
@@ -570,11 +570,11 @@ namespace Content.Shared.Preferences
|
||||
string flavortext;
|
||||
if (FlavorText.Length > MaxDescLength)
|
||||
{
|
||||
flavortext = FormattedMessage.RemoveMarkup(FlavorText)[..MaxDescLength];
|
||||
flavortext = FormattedMessage.RemoveMarkupOrThrow(FlavorText)[..MaxDescLength];
|
||||
}
|
||||
else
|
||||
{
|
||||
flavortext = FormattedMessage.RemoveMarkup(FlavorText);
|
||||
flavortext = FormattedMessage.RemoveMarkupOrThrow(FlavorText);
|
||||
}
|
||||
|
||||
var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species, Sex, sponsorPrototypes);
|
||||
|
||||
@@ -26,7 +26,7 @@ public sealed partial class GroupLoadoutEffect : LoadoutEffect
|
||||
reasons.Add(reason.ToMarkup());
|
||||
}
|
||||
|
||||
reason = reasons.Count == 0 ? null : FormattedMessage.FromMarkup(string.Join('\n', reasons));
|
||||
reason = reasons.Count == 0 ? null : FormattedMessage.FromMarkupOrThrow(string.Join('\n', reasons));
|
||||
return reason == null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ public sealed partial class RoleLoadout : IEquatable<RoleLoadout>
|
||||
if (!protoManager.TryIndex(loadout, out var loadoutProto))
|
||||
{
|
||||
// Uhh
|
||||
reason = FormattedMessage.FromMarkup("");
|
||||
reason = FormattedMessage.FromMarkupOrThrow("");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Components;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
@@ -157,42 +157,42 @@ public abstract class SharedResearchSystem : EntitySystem
|
||||
if (includeTier)
|
||||
{
|
||||
disciplinePrototype ??= PrototypeManager.Index(technology.Discipline);
|
||||
description.AddMarkup(Loc.GetString("research-console-tier-discipline-info",
|
||||
description.AddMarkupOrThrow(Loc.GetString("research-console-tier-discipline-info",
|
||||
("tier", technology.Tier), ("color", disciplinePrototype.Color), ("discipline", Loc.GetString(disciplinePrototype.Name))));
|
||||
description.PushNewline();
|
||||
}
|
||||
|
||||
if (includeCost)
|
||||
{
|
||||
description.AddMarkup(Loc.GetString("research-console-cost", ("amount", technology.Cost)));
|
||||
description.AddMarkupOrThrow(Loc.GetString("research-console-cost", ("amount", technology.Cost)));
|
||||
description.PushNewline();
|
||||
}
|
||||
|
||||
if (includePrereqs && technology.TechnologyPrerequisites.Any())
|
||||
{
|
||||
description.AddMarkup(Loc.GetString("research-console-prereqs-list-start"));
|
||||
description.AddMarkupOrThrow(Loc.GetString("research-console-prereqs-list-start"));
|
||||
foreach (var recipe in technology.TechnologyPrerequisites)
|
||||
{
|
||||
var techProto = PrototypeManager.Index(recipe);
|
||||
description.PushNewline();
|
||||
description.AddMarkup(Loc.GetString("research-console-prereqs-list-entry",
|
||||
description.AddMarkupOrThrow(Loc.GetString("research-console-prereqs-list-entry",
|
||||
("text", Loc.GetString(techProto.Name))));
|
||||
}
|
||||
description.PushNewline();
|
||||
}
|
||||
|
||||
description.AddMarkup(Loc.GetString("research-console-unlocks-list-start"));
|
||||
description.AddMarkupOrThrow(Loc.GetString("research-console-unlocks-list-start"));
|
||||
foreach (var recipe in technology.RecipeUnlocks)
|
||||
{
|
||||
var recipeProto = PrototypeManager.Index(recipe);
|
||||
description.PushNewline();
|
||||
description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry",
|
||||
description.AddMarkupOrThrow(Loc.GetString("research-console-unlocks-list-entry",
|
||||
("name", _lathe.GetRecipeName(recipeProto))));
|
||||
}
|
||||
foreach (var generic in technology.GenericUnlocks)
|
||||
{
|
||||
description.PushNewline();
|
||||
description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry-generic",
|
||||
description.AddMarkupOrThrow(Loc.GetString("research-console-unlocks-list-entry-generic",
|
||||
("text", Loc.GetString(generic.UnlockDescription))));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Shared.Shuttles.UI.MapObjects;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Physics.Components;
|
||||
|
||||
@@ -125,7 +126,7 @@ public abstract partial class SharedShuttleSystem : EntitySystem
|
||||
if (!Resolve(gridUid, ref physics))
|
||||
return true;
|
||||
|
||||
if (physics.Mass < 10f)
|
||||
if (physics.BodyType != BodyType.Static && physics.Mass < 10f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
3
Content.Tests/AssemblyInfo.cs
Normal file
3
Content.Tests/AssemblyInfo.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
[assembly: Parallelizable(ParallelScope.Fixtures)]
|
||||
@@ -1,41 +1,4 @@
|
||||
Entries:
|
||||
- author: Keer-Sar
|
||||
changes:
|
||||
- message: Non-humanoids' names are now capitalized when inserting materials into
|
||||
machines.
|
||||
type: Fix
|
||||
id: 6755
|
||||
time: '2024-06-16T02:06:12.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/29071
|
||||
- author: EmoGarbage404
|
||||
changes:
|
||||
- message: Magboots no longer work when off-grid.
|
||||
type: Fix
|
||||
id: 6756
|
||||
time: '2024-06-16T03:38:18.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/29034
|
||||
- author: deltanedas
|
||||
changes:
|
||||
- message: Tarantulas now use Mechanotoxin, a venom that slows you down over time.
|
||||
type: Tweak
|
||||
id: 6757
|
||||
time: '2024-06-16T11:26:59.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/29066
|
||||
- author: Cojoke-dot
|
||||
changes:
|
||||
- message: Musicians can now select instruments in their loadout
|
||||
type: Add
|
||||
id: 6758
|
||||
time: '2024-06-16T11:27:35.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/29059
|
||||
- author: ElectroJr
|
||||
changes:
|
||||
- message: Fixed pianos, office chairs & other objects not rotating while being
|
||||
pulled.
|
||||
type: Fix
|
||||
id: 6759
|
||||
time: '2024-06-16T11:30:36.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/29032
|
||||
- author: deltanedas
|
||||
changes:
|
||||
- message: Added the Carp Hardsuit to the uplink which is spaceproof and makes carp
|
||||
@@ -3842,3 +3805,44 @@
|
||||
id: 7254
|
||||
time: '2024-08-31T08:28:36.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/31655
|
||||
- author: juliangiebel
|
||||
changes:
|
||||
- message: Adds the station anchor. It anchors stations in space and prevents them
|
||||
from moving.
|
||||
type: Add
|
||||
id: 7255
|
||||
time: '2024-08-31T14:40:28.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/26098
|
||||
- author: Moomoobeef
|
||||
changes:
|
||||
- message: medibelts are found in the medidrobe instead of in lockers.
|
||||
type: Tweak
|
||||
id: 7256
|
||||
time: '2024-08-31T23:22:06.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/31470
|
||||
- author: EmoGarbage404
|
||||
changes:
|
||||
- message: Removed the reclaimer shuttle.
|
||||
type: Remove
|
||||
- message: Removed fultons and fulton beacons from the autolathe
|
||||
type: Remove
|
||||
- message: Adjusted equipment inside salvage lockers and vendors.
|
||||
type: Tweak
|
||||
id: 7257
|
||||
time: '2024-08-31T23:39:32.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/31333
|
||||
- author: Moomoobeef
|
||||
changes:
|
||||
- message: Added flavors to an array of previously indescribable things.
|
||||
type: Add
|
||||
id: 7258
|
||||
time: '2024-09-01T00:03:30.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/31685
|
||||
- author: Ilya246
|
||||
changes:
|
||||
- message: Fixed tip 26 being misinformation about the tesla. It now displays truthful
|
||||
information.
|
||||
type: Fix
|
||||
id: 7259
|
||||
time: '2024-09-01T11:03:23.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/31705
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
station-anchor-unanchoring-failed = Can't unanchor an active station anchor
|
||||
station-anchor-window-title = Station Anchor
|
||||
@@ -50,6 +50,7 @@ flavor-base-horrible = horrible
|
||||
# lmao
|
||||
flavor-base-terrible = terrible
|
||||
flavor-base-mindful = mindful
|
||||
flavor-base-chewy = chewy
|
||||
|
||||
# Complex flavors. Put a flavor here when you want something that's more
|
||||
# specific.
|
||||
@@ -173,6 +174,8 @@ flavor-complex-violets = like violets
|
||||
flavor-complex-pyrotton = like a burning mouth
|
||||
flavor-complex-mothballs = like mothballs
|
||||
flavor-complex-paint-thinner = like paint thinner
|
||||
flavor-complex-paper = like mushy pulp
|
||||
flavor-complex-compressed-meat = like compressed meat
|
||||
|
||||
# Drink-specific flavors.
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
## UI field names
|
||||
|
||||
power-charge-window-status = Status:
|
||||
power-charge-window-power = Power:
|
||||
power-charge-window-eta = ETA:
|
||||
power-charge-window-charge = Charge:
|
||||
|
||||
## UI statuses
|
||||
power-charge-window-status-fully-charged = Fully Charged
|
||||
power-charge-window-status-off = Off
|
||||
power-charge-window-status-charging = Charging
|
||||
power-charge-window-status-discharging = Discharging
|
||||
|
||||
## UI Power Buttons
|
||||
power-charge-window-power-on = On
|
||||
power-charge-window-power-off = Off
|
||||
power-charge-window-power-label = { $draw } / { $max } W
|
||||
|
||||
## UI ETA label
|
||||
|
||||
power-charge-window-eta-none = N/A
|
||||
power-charge-window-eta-value = { TOSTRING($left, "m\\:ss") }
|
||||
@@ -23,7 +23,7 @@ tips-dataset-22 = You can hold SPACE by default to slow the movement of the shut
|
||||
tips-dataset-23 = Dexalin, Dexalin Plus, and Epinephrine will all purge heartbreaker toxin from your bloodstream while metabolizing.
|
||||
tips-dataset-24 = Every crewmember comes with an emergency medipen in their survival box containing epinephrine and tranexamic acid.
|
||||
tips-dataset-25 = The AME is a high-priority target and is easily sabotaged. Make sure to set up the Singularity or Solars so that you don't run out of power if it blows.
|
||||
tips-dataset-26 = During a teslaloose, make sure to get rid of all electronic items so you don't become a target.
|
||||
tips-dataset-26 = If the tesla is loose, it will chase any people, stationary machines and computers. Turning off your electronics does not make you less of a target. Your best bet is not being close to it.
|
||||
tips-dataset-27 = You can add labels to any item, including food or pill canisters, using a hand labeller.
|
||||
tips-dataset-28 = Riot armor is significantly more powerful against opponents that aren't using guns compared to regular armor.
|
||||
tips-dataset-29 = As a ghost, you can use the Verb Menu to orbit around and follow any entity in game automatically.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -127,28 +127,6 @@
|
||||
- id: MagazineLightRifleBox
|
||||
amount: 2
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffel
|
||||
id: ClothingBackpackDuffelSyndicateCostumeCentcom
|
||||
name: CentComm official costume duffel bag
|
||||
description: "Contains a full CentComm Official uniform set, headset and clipboard included. Encryption keys and ID access are not included."
|
||||
suffix: DO NOT MAP
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: ClothingOuterArmorBasic
|
||||
- id: ClothingHeadHatCentcom
|
||||
- id: ClothingEyesGlassesSunglasses
|
||||
- id: ClothingUniformJumpsuitCentcomOfficial
|
||||
- id: ClothingShoesBootsJack
|
||||
- id: ClothingHandsGlovesColorBlack
|
||||
- id: ClothingHeadsetAltCentComFake
|
||||
- id: Paper
|
||||
- id: Pen
|
||||
- id: CentcomPDAFake
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelClown
|
||||
id: ClothingBackpackDuffelSyndicateCostumeClown
|
||||
|
||||
@@ -1,48 +1,47 @@
|
||||
- type: entityTable
|
||||
id: FillSalvageSpecialistHardsuitSpatio
|
||||
table: !type:AllSelector
|
||||
children:
|
||||
- id: OxygenTankFilled
|
||||
- id: ClothingShoesBootsMag
|
||||
- id: ClothingOuterHardsuitSpatio
|
||||
- id: ClothingMaskGasExplorer
|
||||
|
||||
- type: entityTable
|
||||
id: LockerFillSalvageSpecialist
|
||||
table: !type:AllSelector
|
||||
children:
|
||||
- id: ClothingBeltUtilityFilled
|
||||
- id: SurvivalKnife
|
||||
- id: HandheldGPSBasic
|
||||
- id: RadioHandheld
|
||||
- id: AppraisalTool
|
||||
- id: FireExtinguisher
|
||||
- id: Flare
|
||||
prob: 0.3
|
||||
rolls: !type:ConstantNumberSelector
|
||||
value: 3
|
||||
|
||||
- type: entity
|
||||
id: LockerSalvageSpecialistFilledHardsuit
|
||||
suffix: Filled, Hardsuit
|
||||
parent: LockerSalvageSpecialist
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: ClothingOuterHardsuitSpatio
|
||||
- id: ClothingShoesBootsMag
|
||||
- id: ClothingMaskGasExplorer
|
||||
- id: ClothingBeltUtilityFilled
|
||||
- id: SurvivalKnife
|
||||
- id: HandheldGPSBasic
|
||||
- id: RadioHandheld
|
||||
- id: SeismicCharge
|
||||
amount: 2
|
||||
- id: OreBag
|
||||
prob: 0.5
|
||||
- id: Flare
|
||||
prob: 0.3
|
||||
- id: Flare
|
||||
prob: 0.3
|
||||
- id: Flare
|
||||
prob: 0.3
|
||||
- type: EntityTableContainerFill
|
||||
containers:
|
||||
entity_storage: !type:AllSelector
|
||||
children:
|
||||
- !type:NestedSelector
|
||||
tableId: FillSalvageSpecialistHardsuitSpatio
|
||||
- !type:NestedSelector
|
||||
tableId: LockerFillSalvageSpecialist
|
||||
|
||||
- type: entity
|
||||
id: LockerSalvageSpecialistFilled
|
||||
suffix: Filled
|
||||
parent: LockerSalvageSpecialist
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
# Currently do not function as 'true' mesons, so they're useless for salvagers.
|
||||
# - id: ClothingEyesGlassesMeson
|
||||
- id: ClothingBeltUtilityFilled
|
||||
- id: SurvivalKnife
|
||||
- id: HandheldGPSBasic
|
||||
- id: RadioHandheld
|
||||
- id: SeismicCharge
|
||||
amount: 2
|
||||
- id: OreBag
|
||||
prob: 0.5
|
||||
- id: Flare
|
||||
prob: 0.3
|
||||
- id: Flare
|
||||
prob: 0.3
|
||||
- id: Flare
|
||||
prob: 0.3
|
||||
- type: EntityTableContainerFill
|
||||
containers:
|
||||
entity_storage: !type:NestedSelector
|
||||
tableId: LockerFillSalvageSpecialist
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
- id: RubberStampApproved
|
||||
- id: RubberStampDenied
|
||||
- id: RubberStampQm
|
||||
- id: SalvageShuttleConsoleCircuitboard
|
||||
- id: PrinterDocFlatpack # Corvax-Printer
|
||||
|
||||
- type: entity
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
- id: ClothingHandsGlovesLatex
|
||||
- id: ClothingHeadsetMedical
|
||||
- id: ClothingEyesHudMedical
|
||||
- id: ClothingBeltMedical
|
||||
- id: ClothingHeadHatSurgcapGreen
|
||||
prob: 0.1
|
||||
orGroup: Surgcaps
|
||||
@@ -84,7 +83,6 @@
|
||||
- id: ClothingHandsGlovesLatex
|
||||
- id: ClothingHeadsetMedical
|
||||
- id: ClothingEyesHudMedical
|
||||
- id: ClothingBeltMedical
|
||||
- id: ClothingHeadHatSurgcapGreen
|
||||
prob: 0.1
|
||||
orGroup: Surgcaps
|
||||
|
||||
@@ -229,12 +229,10 @@
|
||||
parent: SuitStorageBase
|
||||
suffix: Salvage
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: OxygenTankFilled
|
||||
- id: ClothingShoesBootsMag
|
||||
- id: ClothingOuterHardsuitSpatio
|
||||
- id: ClothingMaskGasExplorer
|
||||
- type: EntityTableContainerFill
|
||||
containers:
|
||||
entity_storage: !type:NestedSelector
|
||||
tableId: FillSalvageSpecialistHardsuitSpatio
|
||||
- type: AccessReader
|
||||
access: [["Salvage"]]
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
ClothingBackpackSatchelMedical: 4
|
||||
ClothingUniformJumpsuitMedicalDoctor: 4
|
||||
ClothingUniformJumpskirtMedicalDoctor: 4
|
||||
ClothingBeltMedical: 4
|
||||
ClothingHeadHatBeretMedic: 4
|
||||
ClothingHeadNurseHat: 4
|
||||
ClothingOuterCoatLab: 4
|
||||
|
||||
@@ -3,13 +3,9 @@
|
||||
startingInventory:
|
||||
Crowbar: 2
|
||||
Pickaxe: 4
|
||||
OreBag: 4
|
||||
OreBag: 2
|
||||
Flare: 4
|
||||
FlashlightLantern: 2
|
||||
Floodlight: 2
|
||||
HandheldGPSBasic: 2
|
||||
RadioHandheld: 2
|
||||
WeaponProtoKineticAccelerator: 4
|
||||
SeismicCharge: 2
|
||||
FultonBeacon: 1
|
||||
Fulton: 2
|
||||
|
||||
@@ -41,16 +41,6 @@
|
||||
- type: Clothing
|
||||
sprite: Clothing/Ears/Headsets/centcom.rsi
|
||||
|
||||
- type: entity
|
||||
parent: ClothingHeadsetAltCentCom
|
||||
id: ClothingHeadsetAltCentComFake
|
||||
suffix: Fake
|
||||
components:
|
||||
- type: ContainerFill
|
||||
containers:
|
||||
key_slots:
|
||||
- EncryptionKeyCommon
|
||||
|
||||
- type: entity
|
||||
parent: [ClothingHeadsetAlt, BaseCommandContraband]
|
||||
id: ClothingHeadsetAltCommand
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
- WhitelistChameleon
|
||||
- type: StaticPrice
|
||||
price: 10
|
||||
- type: FlavorProfile #yes not every peice of clothing is edible, but this way every edible piece of clothing should have the flavor without me having to track down what specific clothing can and cannot be eaten.
|
||||
flavors:
|
||||
- fiber
|
||||
|
||||
- type: entity
|
||||
abstract: true
|
||||
|
||||
@@ -197,6 +197,7 @@
|
||||
- id: PowerCellHighPrinted
|
||||
- id: RadioHandheld
|
||||
- id: ClothingBeltUtility
|
||||
- id: Floodlight
|
||||
- id: WeaponProtoKineticAccelerator
|
||||
weight: 0.5
|
||||
- id: OxygenTankFilled
|
||||
|
||||
@@ -347,6 +347,11 @@
|
||||
bloodReagent: InsectBlood
|
||||
bloodMaxVolume: 20
|
||||
- type: Food
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- horrible
|
||||
- terrible
|
||||
- chewy
|
||||
- type: Hunger
|
||||
baseDecayRate: 0.25
|
||||
- type: Extractable
|
||||
@@ -957,6 +962,9 @@
|
||||
requiresSpecialDigestion: true
|
||||
# Wooly prevents eating wool deleting the goat so its fine
|
||||
requireDead: false
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- fiber
|
||||
- type: Butcherable
|
||||
spawned:
|
||||
- id: FoodMeat
|
||||
@@ -1635,6 +1643,9 @@
|
||||
Dead:
|
||||
Base: splat-0
|
||||
- type: Food
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- meaty
|
||||
- type: Thirst
|
||||
startingThirst: 25 # spawn with Okay thirst state
|
||||
thresholds:
|
||||
@@ -3179,6 +3190,9 @@
|
||||
Dead:
|
||||
Base: splat-0
|
||||
- type: Food
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- meaty
|
||||
- type: Hunger
|
||||
baseDecayRate: 0.3
|
||||
- type: Extractable
|
||||
|
||||
@@ -585,6 +585,10 @@
|
||||
- Hamster
|
||||
- VimPilot
|
||||
- ChefPilot
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- meaty
|
||||
- sadness
|
||||
|
||||
- type: entity
|
||||
name: Shiva
|
||||
|
||||
@@ -1214,6 +1214,22 @@
|
||||
CableHV: 5
|
||||
Uranium: 2
|
||||
|
||||
- type: entity
|
||||
parent: BaseMachineCircuitboard
|
||||
id: StationAnchorCircuitboard
|
||||
name: station anchor machine board
|
||||
description: A machine printed circuit board for a station anchor.
|
||||
components:
|
||||
- type: MachineBoard
|
||||
prototype: StationAnchor
|
||||
stackRequirements:
|
||||
Capacitor: 4
|
||||
MatterBin: 3
|
||||
Steel: 10
|
||||
Glass: 5
|
||||
CableHV: 8
|
||||
Uranium: 2
|
||||
|
||||
- type: entity
|
||||
parent: BaseMachineCircuitboard
|
||||
id: ReagentGrinderIndustrialMachineCircuitboard
|
||||
|
||||
@@ -142,17 +142,6 @@
|
||||
- type: StealTarget
|
||||
stealGroup: CargoShuttleConsoleCircuitboard
|
||||
|
||||
- type: entity
|
||||
parent: BaseComputerCircuitboard
|
||||
id: SalvageShuttleConsoleCircuitboard
|
||||
name: salvage shuttle console board
|
||||
description: A computer printed circuit board for a salvage shuttle console.
|
||||
components:
|
||||
- type: ComputerBoard
|
||||
prototype: ComputerShuttleSalvage
|
||||
- type: StealTarget
|
||||
stealGroup: SalvageShuttleConsoleCircuitboard
|
||||
|
||||
- type: entity
|
||||
parent: BaseComputerCircuitboard
|
||||
id: SurveillanceCameraMonitorCircuitboard
|
||||
|
||||
@@ -689,14 +689,6 @@
|
||||
- NewsReaderCartridge
|
||||
- LogProbeCartridge
|
||||
|
||||
- type: entity
|
||||
parent: CentcomPDA
|
||||
id: CentcomPDAFake
|
||||
suffix: Fake
|
||||
components:
|
||||
- type: Pda
|
||||
id: CentcomIDCardSyndie
|
||||
|
||||
- type: entity
|
||||
parent: CentcomPDA
|
||||
id: DeathsquadPDA
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
- type: Crayon
|
||||
capacity: 15
|
||||
- type: Food
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- chewy
|
||||
- bitter
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
|
||||
@@ -117,6 +117,9 @@
|
||||
- type: Appearance
|
||||
- type: Food
|
||||
requiresSpecialDigestion: true
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- fiber
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
@@ -405,6 +408,9 @@
|
||||
- type: Appearance
|
||||
- type: Food
|
||||
requiresSpecialDigestion: true
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- fiber
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
|
||||
@@ -539,24 +539,6 @@
|
||||
- type: IdCard
|
||||
jobTitle: ERT Field Officer
|
||||
|
||||
- type: entity
|
||||
parent: IDCardStandard
|
||||
id: CentcomIDCardSyndie
|
||||
name: command officer ID card
|
||||
suffix: Fake
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: centcom
|
||||
- state: idcentcom
|
||||
- type: Item
|
||||
heldPrefix: blue
|
||||
- type: IdCard
|
||||
jobTitle: Central Commander
|
||||
- type: Access
|
||||
tags:
|
||||
- Maintenance
|
||||
|
||||
- type: entity
|
||||
parent: IDCardStandard
|
||||
id: MusicianIDCard
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
solution: food
|
||||
delay: 7
|
||||
forceFeedDelay: 7
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- paper
|
||||
- type: BadFood
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user