Merge remote-tracking branch 'upstream/stable' into ed-11-12-2024-upstream
# Conflicts: # Content.IntegrationTests/Tests/PostMapInitTest.cs # Content.Shared/Lock/LockSystem.cs # Resources/Maps/oasis.yml # Resources/Prototypes/Maps/Pools/default.yml # Resources/Prototypes/audio.yml
This commit is contained in:
@@ -258,13 +258,13 @@ namespace Content.Client.Actions
|
||||
|
||||
public void LinkAllActions(ActionsComponent? actions = null)
|
||||
{
|
||||
if (_playerManager.LocalEntity is not { } user ||
|
||||
!Resolve(user, ref actions, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_playerManager.LocalEntity is not { } user ||
|
||||
!Resolve(user, ref actions, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LinkActions?.Invoke(actions);
|
||||
LinkActions?.Invoke(actions);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
|
||||
@@ -159,6 +159,7 @@ public sealed partial class NoteEdit : FancyWindow
|
||||
SecretCheckBox.Pressed = false;
|
||||
SeverityOption.Disabled = false;
|
||||
PermanentCheckBox.Pressed = true;
|
||||
SubmitButton.Disabled = true;
|
||||
UpdatePermanentCheckboxFields();
|
||||
break;
|
||||
case (int) NoteType.Message: // Message: these are shown to the player when they log on
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.Atmos.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class PipeColorVisualsComponent : Component
|
||||
{
|
||||
}
|
||||
public sealed partial class PipeColorVisualsComponent : Component;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<BoxContainer xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:Content.Client.Stylesheets"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Orientation="Vertical" HorizontalExpand ="True" Margin="0 0 0 3">
|
||||
@@ -62,7 +61,7 @@
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- If the alarm is inactive, this is label is diplayed instead -->
|
||||
<!-- If the alarm is inactive, this is label is displayed instead -->
|
||||
<Label Name="NoDataLabel" Text="{Loc 'atmos-alerts-window-no-data-available'}" HorizontalAlignment="Center" Margin="0 15" FontColorOverride="#a9a9a9" ReservesSpace="False" Visible="False"></Label>
|
||||
|
||||
<!-- Silencing progress bar -->
|
||||
|
||||
@@ -136,8 +136,9 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
|
||||
GasGridContainer.RemoveAllChildren();
|
||||
|
||||
var gasData = focusData.Value.GasData.Where(g => g.Key != Gas.Oxygen);
|
||||
var keyValuePairs = gasData.ToList();
|
||||
|
||||
if (gasData.Count() == 0)
|
||||
if (keyValuePairs.Count == 0)
|
||||
{
|
||||
// No other gases
|
||||
var gasLabel = new Label()
|
||||
@@ -158,13 +159,11 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
|
||||
else
|
||||
{
|
||||
// Add an entry for each gas
|
||||
foreach ((var gas, (var mol, var percent, var alert)) in gasData)
|
||||
foreach ((var gas, (var mol, var percent, var alert)) in keyValuePairs)
|
||||
{
|
||||
var gasPercent = (FixedPoint2)0f;
|
||||
gasPercent = percent * 100f;
|
||||
FixedPoint2 gasPercent = percent * 100f;
|
||||
|
||||
if (!_gasShorthands.TryGetValue(gas, out var gasShorthand))
|
||||
gasShorthand = "X";
|
||||
var gasShorthand = _gasShorthands.GetValueOrDefault(gas, "X");
|
||||
|
||||
var gasLabel = new Label()
|
||||
{
|
||||
|
||||
@@ -14,8 +14,6 @@ public sealed class AtmosAlertsComputerBoundUserInterface : BoundUserInterface
|
||||
_menu = new AtmosAlertsComputerWindow(this, Owner);
|
||||
_menu.OpenCentered();
|
||||
_menu.OnClose += Close;
|
||||
|
||||
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
@@ -24,9 +22,6 @@ public sealed class AtmosAlertsComputerBoundUserInterface : BoundUserInterface
|
||||
|
||||
var castState = (AtmosAlertsComputerBoundInterfaceState) state;
|
||||
|
||||
if (castState == null)
|
||||
return;
|
||||
|
||||
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
|
||||
_menu?.UpdateUI(xform?.Coordinates, castState.AirAlarms, castState.FireAlarms, castState.FocusData);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:ui="clr-namespace:Content.Client.Pinpointer.UI"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
Title="{Loc 'atmos-alerts-window-title'}"
|
||||
Resizable="False"
|
||||
SetSize="1120 750"
|
||||
|
||||
@@ -4,8 +4,6 @@ using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Atmos.Piping;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
|
||||
namespace Content.Client.Atmos.EntitySystems;
|
||||
|
||||
@@ -19,7 +17,7 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PipeAppearanceComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: new[] { typeof(SubFloorHideSystem) });
|
||||
SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: [typeof(SubFloorHideSystem)]);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, PipeAppearanceComponent component, ComponentInit args)
|
||||
@@ -84,7 +82,8 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
|
||||
|
||||
layer.Visible &= visible;
|
||||
|
||||
if (!visible) continue;
|
||||
if (!visible)
|
||||
continue;
|
||||
|
||||
layer.Color = color;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Power;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.Client.Atmos.Monitor;
|
||||
|
||||
@@ -27,7 +22,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
|
||||
{
|
||||
foreach (var visLayer in component.HideOnDepowered)
|
||||
{
|
||||
if (args.Sprite.LayerMapTryGet(visLayer, out int powerVisibilityLayer))
|
||||
if (args.Sprite.LayerMapTryGet(visLayer, out var powerVisibilityLayer))
|
||||
args.Sprite.LayerSetVisible(powerVisibilityLayer, powered);
|
||||
}
|
||||
}
|
||||
@@ -36,7 +31,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
|
||||
{
|
||||
foreach (var (setLayer, powerState) in component.SetOnDepowered)
|
||||
{
|
||||
if (args.Sprite.LayerMapTryGet(setLayer, out int setStateLayer))
|
||||
if (args.Sprite.LayerMapTryGet(setLayer, out var setStateLayer))
|
||||
args.Sprite.LayerSetState(setStateLayer, new RSI.StateId(powerState));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Atmos.Monitor.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
|
||||
namespace Content.Client.Atmos.Monitor.UI;
|
||||
|
||||
@@ -78,6 +74,7 @@ public sealed class AirAlarmBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing) _window?.Dispose();
|
||||
if (disposing)
|
||||
_window?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using Content.Shared.Atmos.Monitor.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Temperature;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
@@ -59,7 +58,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
|
||||
AirAlarmMode.Fill => "air-alarm-ui-mode-fill",
|
||||
AirAlarmMode.Panic => "air-alarm-ui-mode-panic",
|
||||
AirAlarmMode.None => "air-alarm-ui-mode-none",
|
||||
_ => "error"
|
||||
_ => "error",
|
||||
};
|
||||
_modes.AddItem(Loc.GetString(text));
|
||||
}
|
||||
@@ -70,7 +69,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
|
||||
AirAlarmModeChanged!.Invoke((AirAlarmMode) args.Id);
|
||||
};
|
||||
|
||||
_autoMode.OnToggled += args =>
|
||||
_autoMode.OnToggled += _ =>
|
||||
{
|
||||
AutoModeChanged!.Invoke(_autoMode.Pressed);
|
||||
};
|
||||
@@ -176,22 +175,18 @@ public sealed partial class AirAlarmWindow : FancyWindow
|
||||
|
||||
public static Color ColorForThreshold(float amount, AtmosAlarmThreshold threshold)
|
||||
{
|
||||
threshold.CheckThreshold(amount, out AtmosAlarmType curAlarm);
|
||||
threshold.CheckThreshold(amount, out var curAlarm);
|
||||
return ColorForAlarm(curAlarm);
|
||||
}
|
||||
|
||||
public static Color ColorForAlarm(AtmosAlarmType curAlarm)
|
||||
{
|
||||
if(curAlarm == AtmosAlarmType.Danger)
|
||||
return curAlarm switch
|
||||
{
|
||||
return StyleNano.DangerousRedFore;
|
||||
}
|
||||
else if(curAlarm == AtmosAlarmType.Warning)
|
||||
{
|
||||
return StyleNano.ConcerningOrangeFore;
|
||||
}
|
||||
|
||||
return StyleNano.GoodGreenFore;
|
||||
AtmosAlarmType.Danger => StyleNano.DangerousRedFore,
|
||||
AtmosAlarmType.Warning => StyleNano.ConcerningOrangeFore,
|
||||
_ => StyleNano.GoodGreenFore,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
using System;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Atmos.Monitor.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Client.Atmos.Monitor.UI.Widgets;
|
||||
|
||||
@@ -25,7 +21,7 @@ public sealed partial class PumpControl : BoxContainer
|
||||
private OptionButton _pressureCheck => CPressureCheck;
|
||||
private FloatSpinBox _externalBound => CExternalBound;
|
||||
private FloatSpinBox _internalBound => CInternalBound;
|
||||
private Button _copySettings => CCopySettings;
|
||||
private Button _copySettings => CCopySettings;
|
||||
|
||||
public PumpControl(GasVentPumpData data, string address)
|
||||
{
|
||||
@@ -86,7 +82,7 @@ public sealed partial class PumpControl : BoxContainer
|
||||
_data.PressureChecks = (VentPressureBound) args.Id;
|
||||
PumpDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
|
||||
_copySettings.OnPressed += _ =>
|
||||
{
|
||||
PumpDataCopied?.Invoke(_data);
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Atmos.Monitor.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Client.Atmos.Monitor.UI.Widgets;
|
||||
|
||||
@@ -27,7 +21,7 @@ public sealed partial class ScrubberControl : BoxContainer
|
||||
private OptionButton _pumpDirection => CPumpDirection;
|
||||
private FloatSpinBox _volumeRate => CVolumeRate;
|
||||
private CheckBox _wideNet => CWideNet;
|
||||
private Button _copySettings => CCopySettings;
|
||||
private Button _copySettings => CCopySettings;
|
||||
|
||||
private GridContainer _gases => CGasContainer;
|
||||
private Dictionary<Gas, Button> _gasControls = new();
|
||||
@@ -77,7 +71,7 @@ public sealed partial class ScrubberControl : BoxContainer
|
||||
_data.PumpDirection = (ScrubberPumpDirection) args.Id;
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
|
||||
_copySettings.OnPressed += _ =>
|
||||
{
|
||||
ScrubberDataCopied?.Invoke(_data);
|
||||
|
||||
@@ -43,7 +43,8 @@ public sealed partial class SensorInfo : BoxContainer
|
||||
var label = new RichTextLabel();
|
||||
|
||||
var fractionGas = amount / data.TotalMoles;
|
||||
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator", ("gas", $"{gas}"),
|
||||
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
|
||||
("gas", $"{gas}"),
|
||||
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
|
||||
("amount", $"{amount:0.####}"),
|
||||
("percentage", $"{(100 * fractionGas):0.##}")));
|
||||
@@ -53,9 +54,9 @@ public sealed partial class SensorInfo : BoxContainer
|
||||
var threshold = data.GasThresholds[gas];
|
||||
var gasThresholdControl = new ThresholdControl(Loc.GetString($"air-alarm-ui-thresholds-gas-title", ("gas", $"{gas}")), threshold, AtmosMonitorThresholdType.Gas, gas, 100);
|
||||
gasThresholdControl.Margin = new Thickness(20, 2, 2, 2);
|
||||
gasThresholdControl.ThresholdDataChanged += (type, threshold, arg3) =>
|
||||
gasThresholdControl.ThresholdDataChanged += (type, alarmThreshold, arg3) =>
|
||||
{
|
||||
OnThresholdUpdate!(_address, type, threshold, arg3);
|
||||
OnThresholdUpdate!(_address, type, alarmThreshold, arg3);
|
||||
};
|
||||
|
||||
_gasThresholds.Add(gas, gasThresholdControl);
|
||||
@@ -64,7 +65,8 @@ public sealed partial class SensorInfo : BoxContainer
|
||||
|
||||
_pressureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-pressure-title"), data.PressureThreshold, AtmosMonitorThresholdType.Pressure);
|
||||
PressureThresholdContainer.AddChild(_pressureThreshold);
|
||||
_temperatureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-temperature-title"), data.TemperatureThreshold,
|
||||
_temperatureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-temperature-title"),
|
||||
data.TemperatureThreshold,
|
||||
AtmosMonitorThresholdType.Temperature);
|
||||
TemperatureThresholdContainer.AddChild(_temperatureThreshold);
|
||||
|
||||
@@ -103,7 +105,8 @@ public sealed partial class SensorInfo : BoxContainer
|
||||
}
|
||||
|
||||
var fractionGas = amount / data.TotalMoles;
|
||||
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator", ("gas", $"{gas}"),
|
||||
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
|
||||
("gas", $"{gas}"),
|
||||
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
|
||||
("amount", $"{amount:0.####}"),
|
||||
("percentage", $"{(100 * fractionGas):0.##}")));
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using Content.Client.Message;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Temperature;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
using System;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Atmos.Monitor.Components;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
// holy FUCK
|
||||
// this technically works because some of this you can *not* do in XAML but holy FUCK
|
||||
@@ -115,29 +111,38 @@ public sealed partial class ThresholdControl : BoxContainer
|
||||
_enabled.Pressed = !_threshold.Ignore;
|
||||
}
|
||||
|
||||
private String LabelForBound(string boundType) //<todo.eoin Replace this with enums
|
||||
private string LabelForBound(string boundType) //<todo.eoin Replace this with enums
|
||||
{
|
||||
return Loc.GetString($"air-alarm-ui-thresholds-{boundType}");
|
||||
}
|
||||
|
||||
public void UpdateThresholdData(AtmosAlarmThreshold threshold, float currentAmount)
|
||||
{
|
||||
threshold.CheckThreshold(currentAmount, out AtmosAlarmType alarm, out AtmosMonitorThresholdBound which);
|
||||
threshold.CheckThreshold(currentAmount, out var alarm, out var bound);
|
||||
|
||||
var upperDangerState = AtmosAlarmType.Normal;
|
||||
var lowerDangerState = AtmosAlarmType.Normal;
|
||||
var upperWarningState = AtmosAlarmType.Normal;
|
||||
var lowerWarningState = AtmosAlarmType.Normal;
|
||||
|
||||
if(alarm == AtmosAlarmType.Danger)
|
||||
switch (alarm)
|
||||
{
|
||||
if(which == AtmosMonitorThresholdBound.Upper) upperDangerState = alarm;
|
||||
else lowerDangerState = alarm;
|
||||
}
|
||||
else if(alarm == AtmosAlarmType.Warning)
|
||||
{
|
||||
if(which == AtmosMonitorThresholdBound.Upper) upperWarningState = alarm;
|
||||
else lowerWarningState = alarm;
|
||||
case AtmosAlarmType.Danger:
|
||||
{
|
||||
if (bound == AtmosMonitorThresholdBound.Upper)
|
||||
upperDangerState = alarm;
|
||||
else
|
||||
lowerDangerState = alarm;
|
||||
break;
|
||||
}
|
||||
case AtmosAlarmType.Warning:
|
||||
{
|
||||
if (bound == AtmosMonitorThresholdBound.Upper)
|
||||
upperWarningState = alarm;
|
||||
else
|
||||
lowerWarningState = alarm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_upperBoundControl.SetValue(threshold.UpperBound.Value);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Atmos.EntitySystems;
|
||||
@@ -101,14 +102,9 @@ public sealed class AtmosDebugOverlay : Overlay
|
||||
else
|
||||
{
|
||||
// Red-Green-Blue interpolation
|
||||
if (interp < 0.5f)
|
||||
{
|
||||
res = Color.InterpolateBetween(Color.Red, Color.LimeGreen, interp * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = Color.InterpolateBetween(Color.LimeGreen, Color.Blue, (interp - 0.5f) * 2);
|
||||
}
|
||||
res = interp < 0.5f
|
||||
? Color.InterpolateBetween(Color.Red, Color.LimeGreen, interp * 2)
|
||||
: Color.InterpolateBetween(Color.LimeGreen, Color.Blue, (interp - 0.5f) * 2);
|
||||
}
|
||||
|
||||
res = res.WithAlpha(0.75f);
|
||||
@@ -181,7 +177,10 @@ public sealed class AtmosDebugOverlay : Overlay
|
||||
handle.DrawCircle(tileCentre, 0.05f, Color.Black);
|
||||
}
|
||||
|
||||
private void CheckAndShowBlockDir(AtmosDebugOverlayData data, DrawingHandleWorld handle, AtmosDirection dir,
|
||||
private void CheckAndShowBlockDir(
|
||||
AtmosDebugOverlayData data,
|
||||
DrawingHandleWorld handle,
|
||||
AtmosDirection dir,
|
||||
Vector2 tileCentre)
|
||||
{
|
||||
if (!data.BlockDirection.HasFlag(dir))
|
||||
@@ -243,7 +242,7 @@ public sealed class AtmosDebugOverlay : Overlay
|
||||
|
||||
var moles = data.Moles == null
|
||||
? "No Air"
|
||||
: data.Moles.Sum().ToString();
|
||||
: data.Moles.Sum().ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
handle.DrawString(_font, pos, $"Moles: {moles}");
|
||||
pos += offset;
|
||||
@@ -263,7 +262,12 @@ public sealed class AtmosDebugOverlay : Overlay
|
||||
private void GetGrids(MapId mapId, Box2Rotated box)
|
||||
{
|
||||
_grids.Clear();
|
||||
_mapManager.FindGridsIntersecting(mapId, box, ref _grids, (EntityUid uid, MapGridComponent grid,
|
||||
_mapManager.FindGridsIntersecting(
|
||||
mapId,
|
||||
box,
|
||||
ref _grids,
|
||||
(EntityUid uid,
|
||||
MapGridComponent grid,
|
||||
ref List<(Entity<MapGridComponent>, DebugMessage)> state) =>
|
||||
{
|
||||
if (_system.TileData.TryGetValue(uid, out var data))
|
||||
|
||||
@@ -7,7 +7,7 @@ using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Clothing;
|
||||
|
||||
public sealed class FlippableClothingVisualizerSystem : VisualizerSystem<FlippableClothingVisualsComponent>
|
||||
public sealed class FlippableClothingVisualizerSystem : VisualizerSystem<FlippableClothingVisualsComponent>
|
||||
{
|
||||
[Dependency] private readonly SharedItemSystem _itemSys = default!;
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
using Content.Shared.Electrocution;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Client.Electrocution;
|
||||
|
||||
/// <summary>
|
||||
/// Shows the Electrocution HUD to entities with the ShowElectrocutionHUDComponent.
|
||||
/// </summary>
|
||||
public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<ElectrocutionHUDVisualsComponent>
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerMan = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ShowElectrocutionHUDComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<ShowElectrocutionHUDComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<ShowElectrocutionHUDComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<ShowElectrocutionHUDComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(Entity<ShowElectrocutionHUDComponent> ent, ref LocalPlayerAttachedEvent args)
|
||||
{
|
||||
ShowHUD();
|
||||
}
|
||||
|
||||
private void OnPlayerDetached(Entity<ShowElectrocutionHUDComponent> ent, ref LocalPlayerDetachedEvent args)
|
||||
{
|
||||
RemoveHUD();
|
||||
}
|
||||
|
||||
private void OnInit(Entity<ShowElectrocutionHUDComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
if (_playerMan.LocalEntity == ent)
|
||||
{
|
||||
ShowHUD();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnShutdown(Entity<ShowElectrocutionHUDComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
if (_playerMan.LocalEntity == ent)
|
||||
{
|
||||
RemoveHUD();
|
||||
}
|
||||
}
|
||||
|
||||
// Show the HUD to the client.
|
||||
// We have to look for all current entities that can be electrified and toggle the HUD layer on if they are.
|
||||
private void ShowHUD()
|
||||
{
|
||||
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
|
||||
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
|
||||
{
|
||||
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp))
|
||||
continue;
|
||||
|
||||
if (electrified)
|
||||
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, true);
|
||||
else
|
||||
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the HUD from the client.
|
||||
// Find all current entities that can be electrified and hide the HUD layer.
|
||||
private void RemoveHUD()
|
||||
{
|
||||
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
|
||||
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
|
||||
{
|
||||
|
||||
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle the HUD layer if an entity becomes (de-)electrified
|
||||
protected override void OnAppearanceChange(EntityUid uid, ElectrocutionHUDVisualsComponent comp, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component))
|
||||
return;
|
||||
|
||||
var player = _playerMan.LocalEntity;
|
||||
if (electrified && HasComp<ShowElectrocutionHUDComponent>(player))
|
||||
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, true);
|
||||
else
|
||||
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, false);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ namespace Content.Client.Eui
|
||||
/// </summary>
|
||||
protected void SendMessage(EuiMessageBase msg)
|
||||
{
|
||||
var netMsg = _netManager.CreateNetMessage<MsgEuiMessage>();
|
||||
var netMsg = new MsgEuiMessage();
|
||||
netMsg.Id = Id;
|
||||
netMsg.Message = msg;
|
||||
|
||||
|
||||
@@ -191,9 +191,15 @@ namespace Content.Client.Inventory
|
||||
return;
|
||||
|
||||
if (ev.Function == ContentKeyFunctions.ExamineEntity)
|
||||
{
|
||||
_examine.DoExamine(slot.Entity.Value);
|
||||
ev.Handle();
|
||||
}
|
||||
else if (ev.Function == EngineKeyFunctions.UseSecondary)
|
||||
{
|
||||
_ui.GetUIController<VerbMenuUIController>().OpenVerbMenu(slot.Entity.Value);
|
||||
ev.Handle();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddInventoryButton(EntityUid invUid, string slotId, InventoryComponent inv)
|
||||
|
||||
@@ -21,6 +21,22 @@ public sealed class HandheldLightSystem : SharedHandheldLightSystem
|
||||
SubscribeLocalEvent<HandheldLightComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// TODO: Not properly predicted yet. Don't call this function if you want a the actual return value!
|
||||
/// </remarks>
|
||||
public override bool TurnOff(Entity<HandheldLightComponent> ent, bool makeNoise = true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// TODO: Not properly predicted yet. Don't call this function if you want a the actual return value!
|
||||
/// </remarks>
|
||||
public override bool TurnOn(EntityUid user, Entity<HandheldLightComponent> uid)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, HandheldLightComponent? component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Content.Client.Lobby
|
||||
return;
|
||||
}
|
||||
|
||||
Lobby!.StationTime.Text = Loc.GetString("lobby-state-player-status-round-not-started");
|
||||
Lobby!.StationTime.Text = Loc.GetString("lobby-state-player-status-round-not-started");
|
||||
string text;
|
||||
|
||||
if (_gameTicker.Paused)
|
||||
@@ -136,6 +136,10 @@ namespace Content.Client.Lobby
|
||||
{
|
||||
text = Loc.GetString(seconds < -5 ? "lobby-state-right-now-question" : "lobby-state-right-now-confirmation");
|
||||
}
|
||||
else if (difference.TotalHours >= 1)
|
||||
{
|
||||
text = $"{Math.Floor(difference.TotalHours)}:{difference.Minutes:D2}:{difference.Seconds:D2}";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = $"{difference.Minutes}:{difference.Seconds:D2}";
|
||||
|
||||
@@ -35,7 +35,7 @@ public sealed partial class StencilOverlay
|
||||
var matty = Matrix3x2.Multiply(matrix, invMatrix);
|
||||
worldHandle.SetTransform(matty);
|
||||
|
||||
foreach (var tile in grid.Comp.GetTilesIntersecting(worldAABB))
|
||||
foreach (var tile in _map.GetTilesIntersecting(grid.Owner, grid, worldAABB))
|
||||
{
|
||||
// Ignored tiles for stencil
|
||||
if (_weather.CanWeatherAffect(grid.Owner, grid, tile))
|
||||
|
||||
@@ -26,6 +26,7 @@ public sealed partial class StencilOverlay : Overlay
|
||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||
private readonly ParallaxSystem _parallax;
|
||||
private readonly SharedTransformSystem _transform;
|
||||
private readonly SharedMapSystem _map;
|
||||
private readonly SpriteSystem _sprite;
|
||||
private readonly WeatherSystem _weather;
|
||||
|
||||
@@ -35,11 +36,12 @@ public sealed partial class StencilOverlay : Overlay
|
||||
|
||||
private readonly ShaderInstance _shader;
|
||||
|
||||
public StencilOverlay(ParallaxSystem parallax, SharedTransformSystem transform, SpriteSystem sprite, WeatherSystem weather)
|
||||
public StencilOverlay(ParallaxSystem parallax, SharedTransformSystem transform, SharedMapSystem map, SpriteSystem sprite, WeatherSystem weather)
|
||||
{
|
||||
ZIndex = ParallaxSystem.ParallaxZIndex + 1;
|
||||
_parallax = parallax;
|
||||
_transform = transform;
|
||||
_map = map;
|
||||
_sprite = sprite;
|
||||
_weather = weather;
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
@@ -10,13 +10,14 @@ public sealed class StencilOverlaySystem : EntitySystem
|
||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||
[Dependency] private readonly ParallaxSystem _parallax = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
[Dependency] private readonly WeatherSystem _weather = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_overlay.AddOverlay(new StencilOverlay(_parallax, _transform, _sprite, _weather));
|
||||
_overlay.AddOverlay(new StencilOverlay(_parallax, _transform, _map, _sprite, _weather));
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
|
||||
@@ -116,7 +116,7 @@ public partial class BaseShuttleControl : MapGridControl
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 matrix, Entity<MapGridComponent> grid, Color color, float alpha = 0.01f)
|
||||
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 gridToView, Entity<MapGridComponent> grid, Color color, float alpha = 0.01f)
|
||||
{
|
||||
var rator = Maps.GetAllTilesEnumerator(grid.Owner, grid.Comp);
|
||||
var minimapScale = MinimapScale;
|
||||
@@ -264,7 +264,7 @@ public partial class BaseShuttleControl : MapGridControl
|
||||
Extensions.EnsureLength(ref _allVertices, totalData);
|
||||
|
||||
_drawJob.MidPoint = midpoint;
|
||||
_drawJob.Matrix = matrix;
|
||||
_drawJob.Matrix = gridToView;
|
||||
_drawJob.MinimapScale = minimapScale;
|
||||
_drawJob.Vertices = gridData.Vertices;
|
||||
_drawJob.ScaledVertices = _allVertices;
|
||||
@@ -286,7 +286,7 @@ public partial class BaseShuttleControl : MapGridControl
|
||||
|
||||
private record struct GridDrawJob : IParallelRobustJob
|
||||
{
|
||||
public int BatchSize => 16;
|
||||
public int BatchSize => 64;
|
||||
|
||||
public float MinimapScale;
|
||||
public Vector2 MidPoint;
|
||||
@@ -297,12 +297,7 @@ public partial class BaseShuttleControl : MapGridControl
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var vert = Vertices[index];
|
||||
var adjustedVert = Vector2.Transform(vert, Matrix);
|
||||
adjustedVert = adjustedVert with { Y = -adjustedVert.Y };
|
||||
|
||||
var scaledVert = ScalePosition(adjustedVert, MinimapScale, MidPoint);
|
||||
ScaledVertices[index] = scaledVert;
|
||||
ScaledVertices[index] = Vector2.Transform(Vertices[index], Matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public sealed partial class NavScreen : BoxContainer
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
private SharedTransformSystem _xformSystem;
|
||||
|
||||
private EntityUid? _consoleEntity; // Entity of controlling console
|
||||
private EntityUid? _shuttleEntity;
|
||||
|
||||
public NavScreen()
|
||||
@@ -35,6 +36,12 @@ public sealed partial class NavScreen : BoxContainer
|
||||
_shuttleEntity = shuttle;
|
||||
}
|
||||
|
||||
public void SetConsole(EntityUid? console)
|
||||
{
|
||||
_consoleEntity = console;
|
||||
NavRadar.SetConsole(console);
|
||||
}
|
||||
|
||||
private void OnIFFTogglePressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
NavRadar.ShowIFF ^= true;
|
||||
|
||||
@@ -138,6 +138,7 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
|
||||
{
|
||||
var coordinates = _entManager.GetCoordinates(cState.NavState.Coordinates);
|
||||
NavContainer.SetShuttle(coordinates?.EntityId);
|
||||
NavContainer.SetConsole(owner);
|
||||
MapContainer.SetShuttle(coordinates?.EntityId);
|
||||
MapContainer.SetConsole(owner);
|
||||
|
||||
|
||||
@@ -107,16 +107,19 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
DrawCircles(handle);
|
||||
var gridNent = EntManager.GetNetEntity(GridEntity);
|
||||
var mapPos = _xformSystem.ToMapCoordinates(_coordinates.Value);
|
||||
var ourGridMatrix = _xformSystem.GetWorldMatrix(GridEntity.Value);
|
||||
var dockMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero);
|
||||
var worldFromDock = Matrix3x2.Multiply(dockMatrix, ourGridMatrix);
|
||||
var ourGridToWorld = _xformSystem.GetWorldMatrix(GridEntity.Value);
|
||||
var selectedDockToOurGrid = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero);
|
||||
var selectedDockToWorld = Matrix3x2.Multiply(selectedDockToOurGrid, ourGridToWorld);
|
||||
|
||||
Matrix3x2.Invert(worldFromDock, out var offsetMatrix);
|
||||
Box2 viewBoundsWorld = Matrix3Helpers.TransformBox(selectedDockToWorld, new Box2(-WorldRangeVector, WorldRangeVector));
|
||||
|
||||
Matrix3x2.Invert(selectedDockToWorld, out var worldToSelectedDock);
|
||||
var selectedDockToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector);
|
||||
|
||||
// Draw nearby grids
|
||||
var controlBounds = PixelSizeBox;
|
||||
_grids.Clear();
|
||||
_mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(mapPos.Position - WorldRangeVector, mapPos.Position + WorldRangeVector), ref _grids);
|
||||
_mapManager.FindGridsIntersecting(gridXform.MapID, viewBoundsWorld, ref _grids);
|
||||
|
||||
// offset the dotted-line position to the bounds.
|
||||
Vector2? viewedDockPos = _viewedState != null ? MidPointVector : null;
|
||||
@@ -136,11 +139,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
if (grid.Owner != GridEntity && !_shuttles.CanDraw(grid.Owner, iffComp: iffComp))
|
||||
continue;
|
||||
|
||||
var gridMatrix = _xformSystem.GetWorldMatrix(grid.Owner);
|
||||
var matty = Matrix3x2.Multiply(gridMatrix, offsetMatrix);
|
||||
var curGridToWorld = _xformSystem.GetWorldMatrix(grid.Owner);
|
||||
var curGridToView = curGridToWorld * worldToSelectedDock * selectedDockToView;
|
||||
var color = _shuttles.GetIFFColor(grid.Owner, grid.Owner == GridEntity, component: iffComp);
|
||||
|
||||
DrawGrid(handle, matty, grid, color);
|
||||
DrawGrid(handle, curGridToView, grid, color);
|
||||
|
||||
// Draw any docks on that grid
|
||||
if (!DockState.Docks.TryGetValue(EntManager.GetNetEntity(grid), out var gridDocks))
|
||||
@@ -151,23 +154,24 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
if (ViewedDock == dock.Entity)
|
||||
continue;
|
||||
|
||||
var position = Vector2.Transform(dock.Coordinates.Position, matty);
|
||||
|
||||
var otherDockRotation = Matrix3Helpers.CreateRotation(dock.Angle);
|
||||
var scaledPos = ScalePosition(position with {Y = -position.Y});
|
||||
|
||||
if (!controlBounds.Contains(scaledPos.Floored()))
|
||||
// This box is the AABB of all the vertices we draw below.
|
||||
var dockRenderBoundsLocal = new Box2(-0.5f, -0.7f, 0.5f, 0.5f);
|
||||
var currentDockToCurGrid = Matrix3Helpers.CreateTransform(dock.Coordinates.Position, dock.Angle);
|
||||
var currentDockToWorld = Matrix3x2.Multiply(currentDockToCurGrid, curGridToWorld);
|
||||
var dockRenderBoundsWorld = Matrix3Helpers.TransformBox(currentDockToWorld, dockRenderBoundsLocal);
|
||||
if (!viewBoundsWorld.Intersects(dockRenderBoundsWorld))
|
||||
continue;
|
||||
|
||||
// Draw the dock's collision
|
||||
var collisionBL = Vector2.Transform(dock.Coordinates.Position +
|
||||
Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), matty);
|
||||
Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), curGridToView);
|
||||
var collisionBR = Vector2.Transform(dock.Coordinates.Position +
|
||||
Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), matty);
|
||||
Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), curGridToView);
|
||||
var collisionTR = Vector2.Transform(dock.Coordinates.Position +
|
||||
Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), matty);
|
||||
Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), curGridToView);
|
||||
var collisionTL = Vector2.Transform(dock.Coordinates.Position +
|
||||
Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), matty);
|
||||
Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), curGridToView);
|
||||
|
||||
var verts = new[]
|
||||
{
|
||||
@@ -181,13 +185,6 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
collisionBL,
|
||||
};
|
||||
|
||||
for (var i = 0; i < verts.Length; i++)
|
||||
{
|
||||
var vert = verts[i];
|
||||
vert.Y = -vert.Y;
|
||||
verts[i] = ScalePosition(vert);
|
||||
}
|
||||
|
||||
var collisionCenter = verts[0] + verts[1] + verts[3] + verts[5];
|
||||
|
||||
var otherDockConnection = Color.ToSrgb(Color.Pink);
|
||||
@@ -195,10 +192,10 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, verts, otherDockConnection);
|
||||
|
||||
// Draw the dock itself
|
||||
var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), matty);
|
||||
var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), matty);
|
||||
var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), matty);
|
||||
var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), matty);
|
||||
var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), curGridToView);
|
||||
var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), curGridToView);
|
||||
var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), curGridToView);
|
||||
var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), curGridToView);
|
||||
|
||||
verts = new[]
|
||||
{
|
||||
@@ -212,13 +209,6 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
dockBL
|
||||
};
|
||||
|
||||
for (var i = 0; i < verts.Length; i++)
|
||||
{
|
||||
var vert = verts[i];
|
||||
vert.Y = -vert.Y;
|
||||
verts[i] = ScalePosition(vert);
|
||||
}
|
||||
|
||||
Color otherDockColor;
|
||||
|
||||
if (HighlightedDock == dock.Entity)
|
||||
@@ -253,9 +243,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
collisionCenter /= 4;
|
||||
var range = viewedDockPos.Value - collisionCenter;
|
||||
|
||||
if (range.Length() < SharedDockingSystem.DockingHiglightRange * MinimapScale)
|
||||
var maxRange = SharedDockingSystem.DockingHiglightRange * MinimapScale;
|
||||
var maxRangeSq = maxRange * maxRange;
|
||||
if (range.LengthSquared() < maxRangeSq)
|
||||
{
|
||||
if (_viewedState?.GridDockedWith == null)
|
||||
if (dock.GridDockedWith == null)
|
||||
{
|
||||
var coordsOne = EntManager.GetCoordinates(_viewedState!.Coordinates);
|
||||
var coordsTwo = EntManager.GetCoordinates(dock.Coordinates);
|
||||
@@ -265,10 +257,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
var rotA = _xformSystem.GetWorldRotation(coordsOne.EntityId) + _viewedState!.Angle;
|
||||
var rotB = _xformSystem.GetWorldRotation(coordsTwo.EntityId) + dock.Angle;
|
||||
|
||||
var distance = (mapOne.Position - mapTwo.Position).Length();
|
||||
var distanceSq = (mapOne.Position - mapTwo.Position).LengthSquared();
|
||||
|
||||
var inAlignment = _dockSystem.InAlignment(mapOne, rotA, mapTwo, rotB);
|
||||
var canDock = distance < SharedDockingSystem.DockRange && inAlignment;
|
||||
var maxDockDistSq = SharedDockingSystem.DockRange * SharedDockingSystem.DockRange;
|
||||
var canDock = distanceSq < maxDockDistSq && inAlignment;
|
||||
|
||||
if (dockButton != null)
|
||||
dockButton.Disabled = !canDock || !canDockChange;
|
||||
@@ -297,7 +290,8 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
|
||||
{
|
||||
// Because it's being layed out top-down we have to arrange for first frame.
|
||||
container.Arrange(PixelRect);
|
||||
var containerPos = scaledPos / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale;
|
||||
var dockPositionInView = Vector2.Transform(dock.Coordinates.Position, curGridToView);
|
||||
var containerPos = dockPositionInView / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale;
|
||||
SetPosition(container, containerPos);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
|
||||
/// </summary>
|
||||
private EntityCoordinates? _coordinates;
|
||||
|
||||
/// <summary>
|
||||
/// Entity of controlling console
|
||||
/// </summary>
|
||||
private EntityUid? _consoleEntity;
|
||||
|
||||
private Angle? _rotation;
|
||||
|
||||
private Dictionary<NetEntity, List<DockingPortState>> _docks = new();
|
||||
@@ -57,6 +62,11 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
|
||||
_rotation = angle;
|
||||
}
|
||||
|
||||
public void SetConsole(EntityUid? consoleEntity)
|
||||
{
|
||||
_consoleEntity = consoleEntity;
|
||||
}
|
||||
|
||||
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
base.KeyBindUp(args);
|
||||
@@ -139,40 +149,35 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
|
||||
}
|
||||
|
||||
var mapPos = _transform.ToMapCoordinates(_coordinates.Value);
|
||||
var offset = _coordinates.Value.Position;
|
||||
var posMatrix = Matrix3Helpers.CreateTransform(offset, _rotation.Value);
|
||||
var posMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, _rotation.Value);
|
||||
var ourEntRot = RotateWithEntity ? _transform.GetWorldRotation(xform) : _rotation.Value;
|
||||
var ourEntMatrix = Matrix3Helpers.CreateTransform(_transform.GetWorldPosition(xform), ourEntRot);
|
||||
var ourWorldMatrix = Matrix3x2.Multiply(posMatrix, ourEntMatrix);
|
||||
Matrix3x2.Invert(ourWorldMatrix, out var ourWorldMatrixInvert);
|
||||
var shuttleToWorld = Matrix3x2.Multiply(posMatrix, ourEntMatrix);
|
||||
Matrix3x2.Invert(shuttleToWorld, out var worldToShuttle);
|
||||
var shuttleToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector);
|
||||
|
||||
// Draw our grid in detail
|
||||
var ourGridId = xform.GridUid;
|
||||
if (EntManager.TryGetComponent<MapGridComponent>(ourGridId, out var ourGrid) &&
|
||||
fixturesQuery.HasComponent(ourGridId.Value))
|
||||
{
|
||||
var ourGridMatrix = _transform.GetWorldMatrix(ourGridId.Value);
|
||||
var matrix = Matrix3x2.Multiply(ourGridMatrix, ourWorldMatrixInvert);
|
||||
var ourGridToWorld = _transform.GetWorldMatrix(ourGridId.Value);
|
||||
var ourGridToShuttle = Matrix3x2.Multiply(ourGridToWorld, worldToShuttle);
|
||||
var ourGridToView = ourGridToShuttle * shuttleToView;
|
||||
var color = _shuttles.GetIFFColor(ourGridId.Value, self: true);
|
||||
|
||||
DrawGrid(handle, matrix, (ourGridId.Value, ourGrid), color);
|
||||
DrawDocks(handle, ourGridId.Value, matrix);
|
||||
DrawGrid(handle, ourGridToView, (ourGridId.Value, ourGrid), color);
|
||||
DrawDocks(handle, ourGridId.Value, ourGridToView);
|
||||
}
|
||||
|
||||
var invertedPosition = _coordinates.Value.Position - offset;
|
||||
invertedPosition.Y = -invertedPosition.Y;
|
||||
// Don't need to transform the InvWorldMatrix again as it's already offset to its position.
|
||||
|
||||
// Draw radar position on the station
|
||||
var radarPos = invertedPosition;
|
||||
const float radarVertRadius = 2f;
|
||||
|
||||
var radarPosVerts = new Vector2[]
|
||||
{
|
||||
ScalePosition(radarPos + new Vector2(0f, -radarVertRadius)),
|
||||
ScalePosition(radarPos + new Vector2(radarVertRadius / 2f, 0f)),
|
||||
ScalePosition(radarPos + new Vector2(0f, radarVertRadius)),
|
||||
ScalePosition(radarPos + new Vector2(radarVertRadius / -2f, 0f)),
|
||||
ScalePosition(new Vector2(0f, -radarVertRadius)),
|
||||
ScalePosition(new Vector2(radarVertRadius / 2f, 0f)),
|
||||
ScalePosition(new Vector2(0f, radarVertRadius)),
|
||||
ScalePosition(new Vector2(radarVertRadius / -2f, 0f)),
|
||||
};
|
||||
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, radarPosVerts, Color.Lime);
|
||||
@@ -197,8 +202,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
|
||||
if (!_shuttles.CanDraw(gUid, gridBody, iff))
|
||||
continue;
|
||||
|
||||
var gridMatrix = _transform.GetWorldMatrix(gUid);
|
||||
var matty = Matrix3x2.Multiply(gridMatrix, ourWorldMatrixInvert);
|
||||
var curGridToWorld = _transform.GetWorldMatrix(gUid);
|
||||
var curGridToView = curGridToWorld * worldToShuttle * shuttleToView;
|
||||
|
||||
var labelColor = _shuttles.GetIFFColor(grid, self: false, iff);
|
||||
var coordColor = new Color(labelColor.R * 0.8f, labelColor.G * 0.8f, labelColor.B * 0.8f, 0.5f);
|
||||
@@ -213,8 +218,7 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
|
||||
{
|
||||
var gridBounds = grid.Comp.LocalAABB;
|
||||
|
||||
var gridCentre = Vector2.Transform(gridBody.LocalCenter, matty);
|
||||
gridCentre.Y = -gridCentre.Y;
|
||||
var gridCentre = Vector2.Transform(gridBody.LocalCenter, curGridToView);
|
||||
|
||||
var distance = gridCentre.Length();
|
||||
var labelText = Loc.GetString("shuttle-console-iff-label", ("name", labelName),
|
||||
@@ -230,9 +234,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
|
||||
// y-offset the control to always render below the grid (vertically)
|
||||
var yOffset = Math.Max(gridBounds.Height, gridBounds.Width) * MinimapScale / 1.8f;
|
||||
|
||||
// The actual position in the UI. We centre the label by offsetting the matrix position
|
||||
// by half the label's width, plus the y-offset
|
||||
var gridScaledPosition = ScalePosition(gridCentre) - new Vector2(0, -yOffset);
|
||||
// The actual position in the UI.
|
||||
var gridScaledPosition = gridCentre - new Vector2(0, -yOffset);
|
||||
|
||||
// Normalize the grid position if it exceeds the viewport bounds
|
||||
// normalizing it instead of clamping it preserves the direction of the vector and prevents corner-hugging
|
||||
@@ -264,18 +267,32 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
|
||||
}
|
||||
|
||||
// Detailed view
|
||||
var gridAABB = gridMatrix.TransformBox(grid.Comp.LocalAABB);
|
||||
var gridAABB = curGridToWorld.TransformBox(grid.Comp.LocalAABB);
|
||||
|
||||
// Skip drawing if it's out of range.
|
||||
if (!gridAABB.Intersects(viewAABB))
|
||||
continue;
|
||||
|
||||
DrawGrid(handle, matty, grid, labelColor);
|
||||
DrawDocks(handle, gUid, matty);
|
||||
DrawGrid(handle, curGridToView, grid, labelColor);
|
||||
DrawDocks(handle, gUid, curGridToView);
|
||||
}
|
||||
|
||||
// If we've set the controlling console, and it's on a different grid
|
||||
// to the shuttle itself, then draw an additional marker to help the
|
||||
// player determine where they are relative to the shuttle.
|
||||
if (_consoleEntity != null && xformQuery.TryGetComponent(_consoleEntity, out var consoleXform))
|
||||
{
|
||||
if (consoleXform.ParentUid != _coordinates.Value.EntityId)
|
||||
{
|
||||
var consolePositionWorld = _transform.GetWorldPosition((EntityUid)_consoleEntity);
|
||||
var p = Vector2.Transform(consolePositionWorld, worldToShuttle * shuttleToView);
|
||||
handle.DrawCircle(p, 5, Color.ToSrgb(Color.Cyan), true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 matrix)
|
||||
private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 gridToView)
|
||||
{
|
||||
if (!ShowDocks)
|
||||
return;
|
||||
@@ -283,33 +300,32 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
|
||||
const float DockScale = 0.6f;
|
||||
var nent = EntManager.GetNetEntity(uid);
|
||||
|
||||
const float sqrt2 = 1.41421356f;
|
||||
const float dockRadius = DockScale * sqrt2;
|
||||
// Worst-case bounds used to cull a dock:
|
||||
Box2 viewBounds = new Box2(-dockRadius, -dockRadius, Size.X + dockRadius, Size.Y + dockRadius);
|
||||
if (_docks.TryGetValue(nent, out var docks))
|
||||
{
|
||||
foreach (var state in docks)
|
||||
{
|
||||
var position = state.Coordinates.Position;
|
||||
var uiPosition = Vector2.Transform(position, matrix);
|
||||
|
||||
if (uiPosition.Length() > (WorldRange * 2f) - DockScale)
|
||||
var positionInView = Vector2.Transform(position, gridToView);
|
||||
if (!viewBounds.Contains(positionInView))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var color = Color.ToSrgb(Color.Magenta);
|
||||
|
||||
var verts = new[]
|
||||
{
|
||||
Vector2.Transform(position + new Vector2(-DockScale, -DockScale), matrix),
|
||||
Vector2.Transform(position + new Vector2(DockScale, -DockScale), matrix),
|
||||
Vector2.Transform(position + new Vector2(DockScale, DockScale), matrix),
|
||||
Vector2.Transform(position + new Vector2(-DockScale, DockScale), matrix),
|
||||
Vector2.Transform(position + new Vector2(-DockScale, -DockScale), gridToView),
|
||||
Vector2.Transform(position + new Vector2(DockScale, -DockScale), gridToView),
|
||||
Vector2.Transform(position + new Vector2(DockScale, DockScale), gridToView),
|
||||
Vector2.Transform(position + new Vector2(-DockScale, DockScale), gridToView),
|
||||
};
|
||||
|
||||
for (var i = 0; i < verts.Length; i++)
|
||||
{
|
||||
var vert = verts[i];
|
||||
vert.Y = -vert.Y;
|
||||
verts[i] = ScalePosition(vert);
|
||||
}
|
||||
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts, color.WithAlpha(0.8f));
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.LineStrip, verts, color);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Silicons.Laws.Ui;
|
||||
@@ -18,8 +19,13 @@ public sealed partial class LawDisplay : Control
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly EntityManager _entityManager = default!;
|
||||
|
||||
private static readonly TimeSpan PressCooldown = TimeSpan.FromSeconds(3);
|
||||
|
||||
private readonly Dictionary<Button, TimeSpan> _nextAllowedPress = new();
|
||||
|
||||
public LawDisplay(EntityUid uid, SiliconLaw law, HashSet<string>? radioChannels)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
@@ -47,9 +53,12 @@ public sealed partial class LawDisplay : Control
|
||||
MinWidth = 75,
|
||||
};
|
||||
|
||||
_nextAllowedPress[localButton] = TimeSpan.Zero;
|
||||
|
||||
localButton.OnPressed += _ =>
|
||||
{
|
||||
_chatManager.SendMessage($"{lawIdentifierPlaintext}: {lawDescriptionPlaintext}", ChatSelectChannel.Local);
|
||||
_nextAllowedPress[localButton] = _timing.CurTime + PressCooldown;
|
||||
};
|
||||
|
||||
LawAnnouncementButtons.AddChild(localButton);
|
||||
@@ -71,6 +80,8 @@ public sealed partial class LawDisplay : Control
|
||||
MinWidth = 75,
|
||||
};
|
||||
|
||||
_nextAllowedPress[radioChannelButton] = TimeSpan.Zero;
|
||||
|
||||
radioChannelButton.OnPressed += _ =>
|
||||
{
|
||||
switch (radioChannel)
|
||||
@@ -80,9 +91,21 @@ public sealed partial class LawDisplay : Control
|
||||
default:
|
||||
_chatManager.SendMessage($"{SharedChatSystem.RadioChannelPrefix}{radioChannelProto.KeyCode} {lawIdentifierPlaintext}: {lawDescriptionPlaintext}", ChatSelectChannel.Radio); break;
|
||||
}
|
||||
_nextAllowedPress[radioChannelButton] = _timing.CurTime + PressCooldown;
|
||||
};
|
||||
|
||||
LawAnnouncementButtons.AddChild(radioChannelButton);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
var curTime = _timing.CurTime;
|
||||
foreach (var (button, nextPress) in _nextAllowedPress)
|
||||
{
|
||||
button.Disabled = curTime < nextPress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,8 @@ using static Robust.Client.UserInterface.Controls.LineEdit;
|
||||
namespace Content.Client.UserInterface.Systems.Chat.Widgets;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
#pragma warning disable RA0003
|
||||
[Virtual]
|
||||
public partial class ChatBox : UIWidget
|
||||
#pragma warning restore RA0003
|
||||
{
|
||||
private readonly ChatUIController _controller;
|
||||
private readonly IEntityManager _entManager;
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
|
||||
buttonHeading.AddStyleClass(ContainerButton.StyleClassButton);
|
||||
buttonHeading.Label.HorizontalAlignment = HAlignment.Center;
|
||||
buttonHeading.Label.HorizontalExpand = true;
|
||||
buttonHeading.Margin = new Thickness(8, 0, 8, 2);
|
||||
|
||||
var body = new CollapsibleBody
|
||||
{
|
||||
|
||||
@@ -83,22 +83,27 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
if (args.Function == EngineKeyFunctions.UIClick)
|
||||
{
|
||||
_handsSystem.UIHandClick(_playerHandsComponent, hand.SlotName);
|
||||
args.Handle();
|
||||
}
|
||||
else if (args.Function == EngineKeyFunctions.UseSecondary)
|
||||
{
|
||||
_handsSystem.UIHandOpenContextMenu(hand.SlotName);
|
||||
args.Handle();
|
||||
}
|
||||
else if (args.Function == ContentKeyFunctions.ActivateItemInWorld)
|
||||
{
|
||||
_handsSystem.UIHandActivate(hand.SlotName);
|
||||
args.Handle();
|
||||
}
|
||||
else if (args.Function == ContentKeyFunctions.AltActivateItemInWorld)
|
||||
{
|
||||
_handsSystem.UIHandAltActivateItem(hand.SlotName);
|
||||
args.Handle();
|
||||
}
|
||||
else if (args.Function == ContentKeyFunctions.ExamineEntity)
|
||||
{
|
||||
_handsSystem.UIInventoryExamine(hand.SlotName);
|
||||
args.Handle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -206,8 +206,7 @@ namespace Content.Client.Wires.UI
|
||||
(_statusContainer = new GridContainer
|
||||
{
|
||||
Margin = new Thickness(8, 4),
|
||||
// TODO: automatically change columns count.
|
||||
Columns = 3
|
||||
Rows = 2
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -227,7 +226,8 @@ namespace Content.Client.Wires.UI
|
||||
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#525252ff")}
|
||||
});
|
||||
CloseButton.OnPressed += _ => Close();
|
||||
SetSize = new Vector2(320, 200);
|
||||
SetHeight = 200;
|
||||
MinWidth = 320;
|
||||
}
|
||||
|
||||
|
||||
@@ -503,6 +503,8 @@ namespace Content.Client.Wires.UI
|
||||
|
||||
public StatusLight(StatusLightData data, IResourceCache resourceCache)
|
||||
{
|
||||
HorizontalAlignment = HAlignment.Right;
|
||||
|
||||
var hsv = Color.ToHsv(data.Color);
|
||||
hsv.Z /= 2;
|
||||
var dimColor = Color.FromHsv(hsv);
|
||||
|
||||
Reference in New Issue
Block a user