Compare commits

..

2 Commits

Author SHA1 Message Date
comasqw
a20f2ba6a3 refactor Prototype class init 2024-11-19 17:12:42 +04:00
comasqw
c00de7fd09 refactor 2024-11-19 17:09:14 +04:00
2332 changed files with 25783 additions and 354131 deletions

2
.github/labeler.yml vendored
View File

@@ -16,7 +16,7 @@
- changed-files:
- any-glob-to-any-file: '**/*.swsl'
"Changes: No C#":
"No C#":
- changed-files:
# Equiv to any-glob-to-all as long as this has one matcher. If ALL changed files are not C# files, then apply label.
- all-globs-to-all-files: "!**/*.cs"

View File

@@ -16,6 +16,6 @@ jobs:
- name: Check for Merge Conflicts
uses: eps1lon/actions-label-merge-conflict@v3.0.0
with:
dirtyLabel: "S: Merge Conflict"
dirtyLabel: "Merge Conflict"
repoToken: "${{ secrets.GITHUB_TOKEN }}"
commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request."

View File

@@ -10,7 +10,7 @@ jobs:
steps:
- uses: actions-ecosystem/action-add-labels@v1
with:
labels: "S: Needs Review"
labels: "Status: Needs Review"
- uses: actions-ecosystem/action-remove-labels@v1
with:
labels: "S: Awaiting Changes"
labels: "Status: Awaiting Changes"

View File

@@ -1,23 +0,0 @@
name: "Labels: Approved"
on:
pull_request_review:
types: [submitted]
jobs:
add_label:
# Change the repository name after you've made sure the team name is correct for your fork!
if: ${{ (github.repository == 'space-wizards/space-station-14') && (github.event.review.state == 'APPROVED') }}
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: tspascoal/get-user-teams-membership@v3
id: checkUserMember
with:
username: ${{ github.actor }}
team: "content-maintainers,junior-maintainers"
GITHUB_TOKEN: ${{ secrets.LABELER_PAT }}
- if: ${{ steps.checkUserMember.outputs.isTeamMember == 'true' }}
uses: actions-ecosystem/action-add-labels@v1
with:
labels: "S: Approved"

View File

@@ -1,20 +0,0 @@
name: "Labels: Size"
on: pull_request_target
jobs:
size-label:
runs-on: ubuntu-latest
steps:
- name: size-label
uses: "pascalgn/size-label-action@v0.5.5"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
with:
# Custom size configuration
sizes: >
{
"0": "XS",
"10": "S",
"30": "M",
"100": "L",
"1000": "XL"
}

View File

@@ -1,16 +0,0 @@
name: "Labels: Branch stable"
on:
pull_request_target:
types:
- opened
branches:
- 'stable'
jobs:
add_label:
runs-on: ubuntu-latest
steps:
- uses: actions-ecosystem/action-add-labels@v1
with:
labels: "Branch: Stable"

View File

@@ -1,16 +0,0 @@
name: "Labels: Branch staging"
on:
pull_request_target:
types:
- opened
branches:
- 'staging'
jobs:
add_label:
runs-on: ubuntu-latest
steps:
- uses: actions-ecosystem/action-add-labels@v1
with:
labels: "Branch: Staging"

View File

@@ -3,8 +3,6 @@
on:
issues:
types: [opened]
pull_request_target:
types: [opened]
jobs:
add_label:
@@ -13,4 +11,4 @@ jobs:
- uses: actions-ecosystem/action-add-labels@v1
if: join(github.event.issue.labels) == ''
with:
labels: "S: Untriaged"
labels: "Status: Untriaged"

View File

@@ -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()

View File

@@ -22,11 +22,11 @@ namespace Content.Client.Administration.UI.BanPanel;
[GenerateTypedNameReferences]
public sealed partial class BanPanel : DefaultWindow
{
public event Action<string?, (IPAddress, int)?, bool, ImmutableTypedHwid?, bool, uint, string, NoteSeverity, string[]?, bool>? BanSubmitted;
public event Action<string?, (IPAddress, int)?, bool, byte[]?, bool, uint, string, NoteSeverity, string[]?, bool>? BanSubmitted;
public event Action<string>? PlayerChanged;
private string? PlayerUsername { get; set; }
private (IPAddress, int)? IpAddress { get; set; }
private ImmutableTypedHwid? Hwid { get; set; }
private byte[]? Hwid { get; set; }
private double TimeEntered { get; set; }
private uint Multiplier { get; set; }
private bool HasBanFlag { get; set; }
@@ -371,8 +371,9 @@ public sealed partial class BanPanel : DefaultWindow
private void OnHwidChanged()
{
var hwidString = HwidLine.Text;
ImmutableTypedHwid? hwid = null;
if (HwidCheckbox.Pressed && !(string.IsNullOrEmpty(hwidString) && LastConnCheckbox.Pressed) && !ImmutableTypedHwid.TryParse(hwidString, out hwid))
var length = 3 * (hwidString.Length / 4) - hwidString.TakeLast(2).Count(c => c == '=');
Hwid = new byte[length];
if (HwidCheckbox.Pressed && !(string.IsNullOrEmpty(hwidString) && LastConnCheckbox.Pressed) && !Convert.TryFromBase64String(hwidString, Hwid, out _))
{
ErrorLevel |= ErrorLevelEnum.Hwid;
HwidLine.ModulateSelfOverride = Color.Red;
@@ -389,7 +390,7 @@ public sealed partial class BanPanel : DefaultWindow
Hwid = null;
return;
}
Hwid = hwid;
Hwid = Convert.FromHexString(hwidString);
}
private void OnTypeChanged()

View File

@@ -8,7 +8,6 @@
<Label Name="ExpiryLabel" Text="{Loc admin-note-editor-expiry-label}" Visible="False" />
<HistoryLineEdit Name="ExpiryLineEdit" PlaceHolder="{Loc admin-note-editor-expiry-placeholder}"
Visible="False" HorizontalExpand="True" />
<OptionButton Name="ExpiryLengthDropdown" Visible="False" />
</BoxContainer>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<OptionButton Name="TypeOption" HorizontalAlignment="Center" />

View File

@@ -17,17 +17,6 @@ public sealed partial class NoteEdit : FancyWindow
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IClientConsoleHost _console = default!;
private enum Multipliers
{
Minutes,
Hours,
Days,
Weeks,
Months,
Years,
Centuries
}
public event Action<int, NoteType, string, NoteSeverity?, bool, DateTime?>? SubmitPressed;
public NoteEdit(SharedAdminNote? note, string playerName, bool canCreate, bool canEdit)
@@ -42,20 +31,6 @@ public sealed partial class NoteEdit : FancyWindow
ResetSubmitButton();
// It's weird to use minutes as the IDs, but it works and makes sense kind of :)
ExpiryLengthDropdown.AddItem(Loc.GetString("admin-note-button-minutes"), (int) Multipliers.Minutes);
ExpiryLengthDropdown.AddItem(Loc.GetString("admin-note-button-hours"), (int) Multipliers.Hours);
ExpiryLengthDropdown.AddItem(Loc.GetString("admin-note-button-days"), (int) Multipliers.Days);
ExpiryLengthDropdown.AddItem(Loc.GetString("admin-note-button-weeks"), (int) Multipliers.Weeks);
ExpiryLengthDropdown.AddItem(Loc.GetString("admin-note-button-months"), (int) Multipliers.Months);
ExpiryLengthDropdown.AddItem(Loc.GetString("admin-note-button-years"), (int) Multipliers.Years);
ExpiryLengthDropdown.AddItem(Loc.GetString("admin-note-button-centuries"), (int) Multipliers.Centuries);
ExpiryLengthDropdown.OnItemSelected += OnLengthChanged;
ExpiryLengthDropdown.SelectId((int) Multipliers.Weeks);
ExpiryLineEdit.OnTextChanged += OnTextChanged;
TypeOption.AddItem(Loc.GetString("admin-note-editor-type-note"), (int) NoteType.Note);
TypeOption.AddItem(Loc.GetString("admin-note-editor-type-message"), (int) NoteType.Message);
TypeOption.AddItem(Loc.GetString("admin-note-editor-type-watchlist"), (int) NoteType.Watchlist);
@@ -159,7 +134,6 @@ 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
@@ -198,9 +172,8 @@ public sealed partial class NoteEdit : FancyWindow
{
ExpiryLabel.Visible = !PermanentCheckBox.Pressed;
ExpiryLineEdit.Visible = !PermanentCheckBox.Pressed;
ExpiryLengthDropdown.Visible = !PermanentCheckBox.Pressed;
ExpiryLineEdit.Text = !PermanentCheckBox.Pressed ? 1.ToString() : string.Empty;
ExpiryLineEdit.Text = !PermanentCheckBox.Pressed ? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") : string.Empty;
}
private void OnSecretPressed(BaseButton.ButtonEventArgs _)
@@ -214,16 +187,6 @@ public sealed partial class NoteEdit : FancyWindow
SeverityOption.SelectId(args.Id);
}
private void OnLengthChanged(OptionButton.ItemSelectedEventArgs args)
{
ExpiryLengthDropdown.SelectId(args.Id);
}
private void OnTextChanged(HistoryLineEdit.LineEditEventArgs args)
{
ParseExpiryTime();
}
private void OnSubmitButtonPressed(BaseButton.ButtonEventArgs args)
{
if (!ParseExpiryTime())
@@ -300,24 +263,13 @@ public sealed partial class NoteEdit : FancyWindow
return true;
}
if (string.IsNullOrWhiteSpace(ExpiryLineEdit.Text) || !uint.TryParse(ExpiryLineEdit.Text, out var inputInt))
if (string.IsNullOrWhiteSpace(ExpiryLineEdit.Text) || !DateTime.TryParse(ExpiryLineEdit.Text, out var result) || DateTime.UtcNow > result)
{
ExpiryLineEdit.ModulateSelfOverride = Color.Red;
return false;
}
var mult = ExpiryLengthDropdown.SelectedId switch
{
(int) Multipliers.Minutes => TimeSpan.FromMinutes(1).TotalMinutes,
(int) Multipliers.Hours => TimeSpan.FromHours(1).TotalMinutes,
(int) Multipliers.Days => TimeSpan.FromDays(1).TotalMinutes,
(int) Multipliers.Weeks => TimeSpan.FromDays(7).TotalMinutes,
(int) Multipliers.Months => TimeSpan.FromDays(30).TotalMinutes,
(int) Multipliers.Years => TimeSpan.FromDays(365).TotalMinutes,
(int) Multipliers.Centuries => TimeSpan.FromDays(36525).TotalMinutes,
_ => throw new ArgumentOutOfRangeException(nameof(ExpiryLengthDropdown.SelectedId), "Multiplier out of range :(")
};
ExpiryTime = DateTime.UtcNow.AddMinutes(inputInt * mult);
ExpiryTime = result.ToUniversalTime();
ExpiryLineEdit.ModulateSelfOverride = null;
return true;
}

View File

@@ -2,7 +2,6 @@ using System.Linq;
using Content.Shared.Alert;
using JetBrains.Annotations;
using Robust.Client.Player;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
@@ -25,7 +24,8 @@ public sealed class ClientAlertsSystem : AlertsSystem
SubscribeLocalEvent<AlertsComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<AlertsComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<AlertsComponent, ComponentHandleState>(OnHandleState);
SubscribeLocalEvent<AlertsComponent, AfterAutoHandleStateEvent>(ClientAlertsHandleState);
}
protected override void LoadPrototypes()
{
@@ -47,16 +47,6 @@ public sealed class ClientAlertsSystem : AlertsSystem
}
}
private void OnHandleState(Entity<AlertsComponent> alerts, ref ComponentHandleState args)
{
if (args.Current is not AlertComponentState cast)
return;
alerts.Comp.Alerts = cast.Alerts;
UpdateHud(alerts);
}
protected override void AfterShowAlert(Entity<AlertsComponent> alerts)
{
UpdateHud(alerts);
@@ -67,6 +57,11 @@ public sealed class ClientAlertsSystem : AlertsSystem
UpdateHud(alerts);
}
private void ClientAlertsHandleState(Entity<AlertsComponent> alerts, ref AfterAutoHandleStateEvent args)
{
UpdateHud(alerts);
}
private void UpdateHud(Entity<AlertsComponent> entity)
{
if (_playerManager.LocalEntity == entity.Owner)

View File

@@ -1,4 +1,8 @@
using Robust.Shared.GameObjects;
namespace Content.Client.Atmos.Components;
[RegisterComponent]
public sealed partial class PipeColorVisualsComponent : Component;
public sealed partial class PipeColorVisualsComponent : Component
{
}

View File

@@ -1,5 +1,6 @@
<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">
@@ -61,7 +62,7 @@
</PanelContainer>
</BoxContainer>
<!-- If the alarm is inactive, this is label is displayed instead -->
<!-- If the alarm is inactive, this is label is diplayed 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 -->

View File

@@ -136,9 +136,8 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
GasGridContainer.RemoveAllChildren();
var gasData = focusData.Value.GasData.Where(g => g.Key != Gas.Oxygen);
var keyValuePairs = gasData.ToList();
if (keyValuePairs.Count == 0)
if (gasData.Count() == 0)
{
// No other gases
var gasLabel = new Label()
@@ -159,11 +158,13 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
else
{
// Add an entry for each gas
foreach ((var gas, (var mol, var percent, var alert)) in keyValuePairs)
foreach ((var gas, (var mol, var percent, var alert)) in gasData)
{
FixedPoint2 gasPercent = percent * 100f;
var gasPercent = (FixedPoint2)0f;
gasPercent = percent * 100f;
var gasShorthand = _gasShorthands.GetValueOrDefault(gas, "X");
if (!_gasShorthands.TryGetValue(gas, out var gasShorthand))
gasShorthand = "X";
var gasLabel = new Label()
{

View File

@@ -14,6 +14,8 @@ 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)
@@ -22,6 +24,9 @@ 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);
}

View File

@@ -1,6 +1,7 @@
<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"

View File

@@ -4,6 +4,8 @@ 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;
@@ -17,7 +19,7 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<PipeAppearanceComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: [typeof(SubFloorHideSystem)]);
SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: new[] { typeof(SubFloorHideSystem) });
}
private void OnInit(EntityUid uid, PipeAppearanceComponent component, ComponentInit args)
@@ -82,8 +84,7 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
layer.Visible &= visible;
if (!visible)
continue;
if (!visible) continue;
layer.Color = color;
}

View File

@@ -1,7 +1,12 @@
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;
@@ -22,7 +27,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
foreach (var visLayer in component.HideOnDepowered)
{
if (args.Sprite.LayerMapTryGet(visLayer, out var powerVisibilityLayer))
if (args.Sprite.LayerMapTryGet(visLayer, out int powerVisibilityLayer))
args.Sprite.LayerSetVisible(powerVisibilityLayer, powered);
}
}
@@ -31,7 +36,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
foreach (var (setLayer, powerState) in component.SetOnDepowered)
{
if (args.Sprite.LayerMapTryGet(setLayer, out var setStateLayer))
if (args.Sprite.LayerMapTryGet(setLayer, out int setStateLayer))
args.Sprite.LayerSetState(setStateLayer, new RSI.StateId(powerState));
}
}

View File

@@ -1,7 +1,11 @@
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;
@@ -74,7 +78,6 @@ public sealed class AirAlarmBoundUserInterface : BoundUserInterface
{
base.Dispose(disposing);
if (disposing)
_window?.Dispose();
if (disposing) _window?.Dispose();
}
}

View File

@@ -8,6 +8,7 @@ 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;
@@ -58,7 +59,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));
}
@@ -69,7 +70,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
AirAlarmModeChanged!.Invoke((AirAlarmMode) args.Id);
};
_autoMode.OnToggled += _ =>
_autoMode.OnToggled += args =>
{
AutoModeChanged!.Invoke(_autoMode.Pressed);
};
@@ -175,18 +176,22 @@ public sealed partial class AirAlarmWindow : FancyWindow
public static Color ColorForThreshold(float amount, AtmosAlarmThreshold threshold)
{
threshold.CheckThreshold(amount, out var curAlarm);
threshold.CheckThreshold(amount, out AtmosAlarmType curAlarm);
return ColorForAlarm(curAlarm);
}
public static Color ColorForAlarm(AtmosAlarmType curAlarm)
{
return curAlarm switch
if(curAlarm == AtmosAlarmType.Danger)
{
AtmosAlarmType.Danger => StyleNano.DangerousRedFore,
AtmosAlarmType.Warning => StyleNano.ConcerningOrangeFore,
_ => StyleNano.GoodGreenFore,
};
return StyleNano.DangerousRedFore;
}
else if(curAlarm == AtmosAlarmType.Warning)
{
return StyleNano.ConcerningOrangeFore;
}
return StyleNano.GoodGreenFore;
}

View File

@@ -1,8 +1,12 @@
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;
@@ -21,7 +25,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)
{
@@ -82,7 +86,7 @@ public sealed partial class PumpControl : BoxContainer
_data.PressureChecks = (VentPressureBound) args.Id;
PumpDataChanged?.Invoke(_address, _data);
};
_copySettings.OnPressed += _ =>
{
PumpDataCopied?.Invoke(_data);

View File

@@ -1,9 +1,15 @@
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;
@@ -21,7 +27,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();
@@ -71,7 +77,7 @@ public sealed partial class ScrubberControl : BoxContainer
_data.PumpDirection = (ScrubberPumpDirection) args.Id;
ScrubberDataChanged?.Invoke(_address, _data);
};
_copySettings.OnPressed += _ =>
{
ScrubberDataCopied?.Invoke(_data);

View File

@@ -43,8 +43,7 @@ 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.##}")));
@@ -54,9 +53,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, alarmThreshold, arg3) =>
gasThresholdControl.ThresholdDataChanged += (type, threshold, arg3) =>
{
OnThresholdUpdate!(_address, type, alarmThreshold, arg3);
OnThresholdUpdate!(_address, type, threshold, arg3);
};
_gasThresholds.Add(gas, gasThresholdControl);
@@ -65,8 +64,7 @@ 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);
@@ -105,8 +103,7 @@ 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.##}")));

View File

@@ -1,4 +1,7 @@
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;

View File

@@ -1,8 +1,12 @@
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
@@ -111,38 +115,29 @@ 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 var alarm, out var bound);
threshold.CheckThreshold(currentAmount, out AtmosAlarmType alarm, out AtmosMonitorThresholdBound which);
var upperDangerState = AtmosAlarmType.Normal;
var lowerDangerState = AtmosAlarmType.Normal;
var upperWarningState = AtmosAlarmType.Normal;
var lowerWarningState = AtmosAlarmType.Normal;
switch (alarm)
if(alarm == AtmosAlarmType.Danger)
{
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;
}
if(which == AtmosMonitorThresholdBound.Upper) upperDangerState = alarm;
else lowerDangerState = alarm;
}
else if(alarm == AtmosAlarmType.Warning)
{
if(which == AtmosMonitorThresholdBound.Upper) upperWarningState = alarm;
else lowerWarningState = alarm;
}
_upperBoundControl.SetValue(threshold.UpperBound.Value);

View File

@@ -1,4 +1,3 @@
using System.Globalization;
using System.Linq;
using System.Numerics;
using Content.Client.Atmos.EntitySystems;
@@ -102,9 +101,14 @@ public sealed class AtmosDebugOverlay : Overlay
else
{
// Red-Green-Blue interpolation
res = interp < 0.5f
? Color.InterpolateBetween(Color.Red, Color.LimeGreen, interp * 2)
: Color.InterpolateBetween(Color.LimeGreen, Color.Blue, (interp - 0.5f) * 2);
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 = res.WithAlpha(0.75f);
@@ -177,10 +181,7 @@ 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))
@@ -242,7 +243,7 @@ public sealed class AtmosDebugOverlay : Overlay
var moles = data.Moles == null
? "No Air"
: data.Moles.Sum().ToString(CultureInfo.InvariantCulture);
: data.Moles.Sum().ToString();
handle.DrawString(_font, pos, $"Moles: {moles}");
pos += offset;
@@ -262,12 +263,7 @@ 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))

View File

@@ -30,7 +30,7 @@ public sealed class ClientClothingSystem : ClothingSystem
/// For some context, im currently refactoring inventory. Part of that is slots not being indexed by a massive enum anymore, but by strings.
/// Problem here: Every rsi-state is using the old enum-names in their state. I already used the new inventoryslots ALOT. tldr: its this or another week of renaming files.
/// </summary>
public static readonly Dictionary<string, string> TemporarySlotMap = new() //CP14 Public
private static readonly Dictionary<string, string> TemporarySlotMap = new()
{
{"head", "HELMET"},
{"eyes", "EYES"},
@@ -65,7 +65,6 @@ public sealed class ClientClothingSystem : ClothingSystem
base.Initialize();
SubscribeLocalEvent<ClothingComponent, GetEquipmentVisualsEvent>(OnGetVisuals);
SubscribeLocalEvent<ClothingComponent, InventoryTemplateUpdated>(OnInventoryTemplateUpdated);
SubscribeLocalEvent<InventoryComponent, VisualsChangedEvent>(OnVisualsChanged);
SubscribeLocalEvent<SpriteComponent, DidUnequipEvent>(OnDidUnequip);
@@ -78,7 +77,11 @@ public sealed class ClientClothingSystem : ClothingSystem
if (args.Sprite == null)
return;
UpdateAllSlots(uid, component);
var enumerator = _inventorySystem.GetSlotEnumerator((uid, component));
while (enumerator.NextItem(out var item, out var slot))
{
RenderEquipment(uid, item, slot.Name, component);
}
// No clothing equipped -> make sure the layer is hidden, though this should already be handled by on-unequip.
if (args.Sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var layer))
@@ -88,23 +91,6 @@ public sealed class ClientClothingSystem : ClothingSystem
}
}
private void OnInventoryTemplateUpdated(Entity<ClothingComponent> ent, ref InventoryTemplateUpdated args)
{
UpdateAllSlots(ent.Owner, clothing: ent.Comp);
}
private void UpdateAllSlots(
EntityUid uid,
InventoryComponent? inventoryComponent = null,
ClothingComponent? clothing = null)
{
var enumerator = _inventorySystem.GetSlotEnumerator((uid, inventoryComponent));
while (enumerator.NextItem(out var item, out var slot))
{
RenderEquipment(uid, item, slot.Name, inventoryComponent, clothingComponent: clothing);
}
}
private void OnGetVisuals(EntityUid uid, ClothingComponent item, GetEquipmentVisualsEvent args)
{
if (!TryComp(args.Equipee, out InventoryComponent? inventory))

View File

@@ -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!;

View File

@@ -1,20 +1,15 @@
<DefaultWindow xmlns="https://spacestation14.io">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<BoxContainer Orientation="Vertical" MinWidth="243" Margin="0 0 5 0">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4" Margin="0 0 5 0">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 0 0 5">
<LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True"/>
<OptionButton Name="OptionCategories" Access="Public" MinSize="130 0"/>
</BoxContainer>
<ItemList Name="Recipes" Access="Public" SelectMode="Single" VerticalExpand="True"/>
<ScrollContainer Name="RecipesGridScrollContainer" VerticalExpand="True" Access="Public" Visible="False">
<GridContainer Name="RecipesGrid" Columns="5" Access="Public"/>
</ScrollContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<BoxContainer Orientation="Horizontal">
<Button Name="MenuGridViewButton" ToggleMode="True" Text="{Loc construction-menu-grid-view}"/>
<Button Name="FavoriteButton" Visible="false"/>
</BoxContainer>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.6">
<Button Name="FavoriteButton" Visible="false" HorizontalExpand="False"
HorizontalAlignment="Right" Margin="0 0 0 15"/>
<Control>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="0 0 0 5">
<BoxContainer Orientation="Horizontal" Align="Center">

View File

@@ -25,16 +25,11 @@ namespace Content.Client.Construction.UI
OptionButton OptionCategories { get; }
bool EraseButtonPressed { get; set; }
bool GridViewButtonPressed { get; set; }
bool BuildButtonPressed { get; set; }
ItemList Recipes { get; }
ItemList RecipeStepList { get; }
ScrollContainer RecipesGridScrollContainer { get; }
GridContainer RecipesGrid { get; }
event EventHandler<(string search, string catagory)> PopulateRecipes;
event EventHandler<ItemList.Item?> RecipeSelected;
event EventHandler RecipeFavorited;
@@ -77,16 +72,9 @@ namespace Content.Client.Construction.UI
set => EraseButton.Pressed = value;
}
public bool GridViewButtonPressed
{
get => MenuGridViewButton.Pressed;
set => MenuGridViewButton.Pressed = value;
}
public ConstructionMenu()
{
SetSize = new Vector2(560, 450);
MinSize = new Vector2(560, 320);
SetSize = MinSize = new Vector2(720, 320);
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
@@ -114,9 +102,6 @@ namespace Content.Client.Construction.UI
EraseButton.OnToggled += args => EraseButtonToggled?.Invoke(this, args.Pressed);
FavoriteButton.OnPressed += args => RecipeFavorited?.Invoke(this, EventArgs.Empty);
MenuGridViewButton.OnPressed += _ =>
PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[OptionCategories.SelectedId]));
}
public event EventHandler? ClearAllGhosts;

View File

@@ -1,8 +1,7 @@
using System.Linq;
using System.Numerics;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Systems.MenuBar.Widgets;
using Content.Shared.Construction.Prototypes;
using Content.Shared.Tag;
using Content.Shared.Whitelist;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
@@ -12,6 +11,7 @@ using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.Utility;
using Robust.Shared.Enums;
using Robust.Shared.Graphics;
using Robust.Shared.Prototypes;
using static Robust.Client.UserInterface.Controls.BaseButton;
@@ -33,12 +33,10 @@ namespace Content.Client.Construction.UI
private readonly IConstructionMenuView _constructionView;
private readonly EntityWhitelistSystem _whitelistSystem;
private readonly SpriteSystem _spriteSystem;
private ConstructionSystem? _constructionSystem;
private ConstructionPrototype? _selected;
private List<ConstructionPrototype> _favoritedRecipes = [];
private Dictionary<string, TextureButton> _recipeButtons = new();
private string _selectedCategory = string.Empty;
private string _favoriteCatName = "construction-category-favorites";
private string _forAllCategoryName = "construction-category-all";
@@ -87,7 +85,6 @@ namespace Content.Client.Construction.UI
IoCManager.InjectDependencies(this);
_constructionView = new ConstructionMenu();
_whitelistSystem = _entManager.System<EntityWhitelistSystem>();
_spriteSystem = _entManager.System<SpriteSystem>();
// This is required so that if we load after the system is initialized, we can bind to it immediately
if (_systemManager.TryGetEntitySystem<ConstructionSystem>(out var constructionSystem))
@@ -153,24 +150,12 @@ namespace Content.Client.Construction.UI
PopulateInfo(_selected);
}
private void OnGridViewRecipeSelected(object? sender, ConstructionPrototype? recipe)
{
if (recipe is null)
{
_selected = null;
_constructionView.ClearRecipeInfo();
return;
}
_selected = recipe;
if (_placementManager.IsActive && !_placementManager.Eraser) UpdateGhostPlacement();
PopulateInfo(_selected);
}
private void OnViewPopulateRecipes(object? sender, (string search, string catagory) args)
{
var (search, category) = args;
var recipesList = _constructionView.Recipes;
recipesList.Clear();
var recipes = new List<ConstructionPrototype>();
var isEmptyCategory = string.IsNullOrEmpty(category) || category == _forAllCategoryName;
@@ -185,7 +170,7 @@ namespace Content.Client.Construction.UI
if (recipe.Hide)
continue;
if (!recipe.CrystallPunkAllowed) //CrystallEdge clearing recipes
if (!recipe.CrystallPunkAllowed) //CrystallPunk clearing recipes
continue;
if (_playerManager.LocalSession == null
@@ -219,73 +204,12 @@ namespace Content.Client.Construction.UI
recipes.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.InvariantCulture));
var recipesList = _constructionView.Recipes;
recipesList.Clear();
var recipesGrid = _constructionView.RecipesGrid;
recipesGrid.RemoveAllChildren();
_constructionView.RecipesGridScrollContainer.Visible = _constructionView.GridViewButtonPressed;
_constructionView.Recipes.Visible = !_constructionView.GridViewButtonPressed;
if (_constructionView.GridViewButtonPressed)
foreach (var recipe in recipes)
{
foreach (var recipe in recipes)
{
var itemButton = new TextureButton
{
TextureNormal = _spriteSystem.Frame0(recipe.Icon),
VerticalAlignment = Control.VAlignment.Center,
Name = recipe.Name,
ToolTip = recipe.Name,
Scale = new Vector2(1.35f),
ToggleMode = true,
};
var itemButtonPanelContainer = new PanelContainer
{
PanelOverride = new StyleBoxFlat { BackgroundColor = StyleNano.ButtonColorDefault },
Children = { itemButton },
};
itemButton.OnToggled += buttonToggledEventArgs =>
{
SelectGridButton(itemButton, buttonToggledEventArgs.Pressed);
if (buttonToggledEventArgs.Pressed &&
_selected != null &&
_recipeButtons.TryGetValue(_selected.Name, out var oldButton))
{
oldButton.Pressed = false;
SelectGridButton(oldButton, false);
}
OnGridViewRecipeSelected(this, buttonToggledEventArgs.Pressed ? recipe : null);
};
recipesGrid.AddChild(itemButtonPanelContainer);
_recipeButtons[recipe.Name] = itemButton;
var isCurrentButtonSelected = _selected == recipe;
itemButton.Pressed = isCurrentButtonSelected;
SelectGridButton(itemButton, isCurrentButtonSelected);
}
recipesList.Add(GetItem(recipe, recipesList));
}
else
{
foreach (var recipe in recipes)
{
recipesList.Add(GetItem(recipe, recipesList));
}
}
}
private void SelectGridButton(TextureButton button, bool select)
{
if (button.Parent is not PanelContainer buttonPanel)
return;
button.Modulate = select ? Color.Green : Color.White;
var buttonColor = select ? StyleNano.ButtonColorDefault : Color.Transparent;
buttonPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = buttonColor };
// There is apparently no way to set which
}
private void PopulateCategories(string? selectCategory = null)
@@ -336,10 +260,11 @@ namespace Content.Client.Construction.UI
private void PopulateInfo(ConstructionPrototype prototype)
{
var spriteSys = _systemManager.GetEntitySystem<SpriteSystem>();
_constructionView.ClearRecipeInfo();
_constructionView.SetRecipeInfo(
prototype.Name, prototype.Description, _spriteSystem.Frame0(prototype.Icon),
prototype.Name, prototype.Description, spriteSys.Frame0(prototype.Icon),
prototype.Type != ConstructionType.Item,
!_favoritedRecipes.Contains(prototype));
@@ -352,6 +277,7 @@ namespace Content.Client.Construction.UI
if (_constructionSystem?.GetGuide(prototype) is not { } guide)
return;
var spriteSys = _systemManager.GetEntitySystem<SpriteSystem>();
foreach (var entry in guide.Entries)
{
@@ -367,20 +293,20 @@ namespace Content.Client.Construction.UI
// The padding needs to be applied regardless of text length... (See PadLeft documentation)
text = text.PadLeft(text.Length + entry.Padding);
var icon = entry.Icon != null ? _spriteSystem.Frame0(entry.Icon) : Texture.Transparent;
var icon = entry.Icon != null ? spriteSys.Frame0(entry.Icon) : Texture.Transparent;
stepList.AddItem(text, icon, false);
}
}
private ItemList.Item GetItem(ConstructionPrototype recipe, ItemList itemList)
private static ItemList.Item GetItem(ConstructionPrototype recipe, ItemList itemList)
{
return new(itemList)
{
Metadata = recipe,
Text = recipe.Name,
Icon = _spriteSystem.Frame0(recipe.Icon),
Icon = recipe.Icon.Frame0(),
TooltipEnabled = true,
TooltipText = recipe.Description,
TooltipText = recipe.Description
};
}

View File

@@ -31,7 +31,7 @@ namespace Content.Client.Crayon.UI
private void PopulateCrayons()
{
var crayonDecals = _protoManager.EnumeratePrototypes<DecalPrototype>().Where(x => x.Tags.Contains("crayon"));
_menu?.Populate(crayonDecals.ToList());
_menu?.Populate(crayonDecals);
}
public override void OnProtoReload(PrototypesReloadedEventArgs args)
@@ -44,16 +44,6 @@ namespace Content.Client.Crayon.UI
PopulateCrayons();
}
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
{
base.ReceiveMessage(message);
if (_menu is null || message is not CrayonUsedMessage crayonMessage)
return;
_menu.AdvanceState(crayonMessage.DrawnDecal);
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);

View File

@@ -1,13 +1,14 @@
<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'crayon-window-title'}"
MinSize="450 500"
SetSize="450 500">
MinSize="250 300"
SetSize="250 300">
<BoxContainer Orientation="Vertical">
<ColorSelectorSliders Name="ColorSelector" Visible="False" />
<LineEdit Name="Search" Margin="0 0 0 8" PlaceHolder="{Loc 'crayon-window-placeholder'}" />
<LineEdit Name="Search" />
<ScrollContainer VerticalExpand="True">
<BoxContainer Name="Grids" Orientation="Vertical">
</BoxContainer>
<GridContainer Name="Grid" Columns="6">
<!-- Crayon decals get added here by code -->
</GridContainer>
</ScrollContainer>
</BoxContainer>
</DefaultWindow>

View File

@@ -1,10 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using Content.Client.Stylesheets;
using Content.Shared.Crayon;
using Content.Shared.Decals;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
@@ -20,12 +18,7 @@ namespace Content.Client.Crayon.UI
[GenerateTypedNameReferences]
public sealed partial class CrayonWindow : DefaultWindow
{
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
private readonly SpriteSystem _spriteSystem = default!;
private Dictionary<string, List<(string Name, Texture Texture)>>? _decals;
private List<string>? _allDecals;
private string? _autoSelected;
private Dictionary<string, Texture>? _decals;
private string? _selected;
private Color _color;
@@ -35,10 +28,8 @@ namespace Content.Client.Crayon.UI
public CrayonWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>();
Search.OnTextChanged += SearchChanged;
Search.OnTextChanged += _ => RefreshList();
ColorSelector.OnColorChanged += SelectColor;
}
@@ -53,94 +44,51 @@ namespace Content.Client.Crayon.UI
private void RefreshList()
{
// Clear
Grids.DisposeAllChildren();
if (_decals == null || _allDecals == null)
Grid.DisposeAllChildren();
if (_decals == null)
return;
var filter = Search.Text;
var comma = filter.IndexOf(',');
var first = (comma == -1 ? filter : filter[..comma]).Trim();
var names = _decals.Keys.ToList();
names.Sort((a, b) => a == "random" ? 1 : b == "random" ? -1 : a.CompareTo(b));
if (_autoSelected != null && first != _autoSelected && _allDecals.Contains(first))
foreach (var (decal, tex) in _decals)
{
_selected = first;
_autoSelected = _selected;
OnSelected?.Invoke(_selected);
}
foreach (var categoryName in names)
{
var locName = Loc.GetString("crayon-category-" + categoryName);
var category = _decals[categoryName].Where(d => locName.Contains(first) || d.Name.Contains(first)).ToList();
if (category.Count == 0)
if (!decal.Contains(filter))
continue;
var label = new Label
var button = new TextureButton()
{
Text = locName
TextureNormal = tex,
Name = decal,
ToolTip = decal,
Modulate = _color,
};
var grid = new GridContainer
button.OnPressed += ButtonOnPressed;
if (_selected == decal)
{
Columns = 6,
Margin = new Thickness(0, 0, 0, 16)
};
Grids.AddChild(label);
Grids.AddChild(grid);
foreach (var (name, texture) in category)
{
var button = new TextureButton()
var panelContainer = new PanelContainer()
{
TextureNormal = texture,
Name = name,
ToolTip = name,
Modulate = _color,
Scale = new System.Numerics.Vector2(2, 2)
};
button.OnPressed += ButtonOnPressed;
if (_selected == name)
{
var panelContainer = new PanelContainer()
PanelOverride = new StyleBoxFlat()
{
PanelOverride = new StyleBoxFlat()
{
BackgroundColor = StyleNano.ButtonColorDefault,
},
Children =
{
button,
},
};
grid.AddChild(panelContainer);
}
else
{
grid.AddChild(button);
}
BackgroundColor = StyleNano.ButtonColorDefault,
},
Children =
{
button,
},
};
Grid.AddChild(panelContainer);
}
else
{
Grid.AddChild(button);
}
}
}
private void SearchChanged(LineEdit.LineEditEventArgs obj)
{
_autoSelected = ""; // Placeholder to kick off the auto-select in refreshlist()
RefreshList();
}
private void ButtonOnPressed(ButtonEventArgs obj)
{
if (obj.Button.Name == null) return;
_selected = obj.Button.Name;
_autoSelected = null;
OnSelected?.Invoke(_selected);
RefreshList();
}
@@ -159,38 +107,12 @@ namespace Content.Client.Crayon.UI
RefreshList();
}
public void AdvanceState(string drawnDecal)
public void Populate(IEnumerable<DecalPrototype> prototypes)
{
var filter = Search.Text;
if (!filter.Contains(',') || !filter.Contains(drawnDecal))
return;
var first = filter[..filter.IndexOf(',')].Trim();
if (first.Equals(drawnDecal, StringComparison.InvariantCultureIgnoreCase))
{
Search.Text = filter[(filter.IndexOf(',') + 1)..].Trim();
_autoSelected = first;
}
RefreshList();
}
public void Populate(List<DecalPrototype> prototypes)
{
_decals = [];
_allDecals = [];
prototypes.Sort((a, b) => a.ID.CompareTo(b.ID));
_decals = new Dictionary<string, Texture>();
foreach (var decalPrototype in prototypes)
{
var category = "random";
if (decalPrototype.Tags.Count > 1 && decalPrototype.Tags[1].StartsWith("crayon-"))
category = decalPrototype.Tags[1].Replace("crayon-", "");
var list = _decals.GetOrNew(category);
list.Add((decalPrototype.ID, _spriteSystem.Frame0(decalPrototype.Sprite)));
_allDecals.Add(decalPrototype.ID);
_decals.Add(decalPrototype.ID, decalPrototype.Sprite.Frame0());
}
RefreshList();

View File

@@ -124,10 +124,6 @@ public sealed class ColorFlashEffectSystem : SharedColorFlashEffectSystem
continue;
}
var targetEv = new GetFlashEffectTargetEvent(ent);
RaiseLocalEvent(ent, ref targetEv);
ent = targetEv.Target;
EnsureComp<ColorFlashEffectComponent>(ent, out comp);
comp.NetSyncEnabled = false;
comp.Color = sprite.Color;
@@ -136,9 +132,3 @@ public sealed class ColorFlashEffectSystem : SharedColorFlashEffectSystem
}
}
}
/// <summary>
/// Raised on an entity to change the target for a color flash effect.
/// </summary>
[ByRefEvent]
public record struct GetFlashEffectTargetEvent(EntityUid Target);

View File

@@ -1,95 +0,0 @@
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);
}
}

View File

@@ -165,7 +165,7 @@ namespace Content.Client.Entry
_clientPreferencesManager.Initialize();
_euiManager.Initialize();
_voteManager.Initialize();
_userInterfaceManager.SetDefaultTheme("SS14DefaultTheme");
_userInterfaceManager.SetDefaultTheme(_configManager.GetCVar(CCVars.UIDefaultInterfaceTheme));
_userInterfaceManager.SetActiveTheme(_configManager.GetCVar(CVars.InterfaceTheme));
_documentParsingManager.Initialize();
_titleWindowManager.Initialize();

View File

@@ -55,7 +55,7 @@ namespace Content.Client.Eui
/// </summary>
protected void SendMessage(EuiMessageBase msg)
{
var netMsg = new MsgEuiMessage();
var netMsg = _netManager.CreateNetMessage<MsgEuiMessage>();
netMsg.Id = Id;
netMsg.Message = msg;

View File

@@ -112,12 +112,7 @@ namespace Content.Client.Ghost
_actions.RemoveAction(uid, component.ToggleLightingActionEntity);
_actions.RemoveAction(uid, component.ToggleFoVActionEntity);
_actions.RemoveAction(uid, component.ToggleGhostsActionEntity);
//_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity); //Dont need in CP14
//CP14
_actions.RemoveAction(uid, component.CP14ZLevelUpActionEntity);
_actions.RemoveAction(uid, component.CP14ZLevelDownActionEntity);
_actions.RemoveAction(uid, component.CP14ToggleRoofActionEntity);
//CP14 end
_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity);
if (uid != _playerManager.LocalEntity)
return;

View File

@@ -168,8 +168,8 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
var parent = forcedRoot == null ? null : AddEntry(forcedRoot.Value, null, addedEntries);
foreach (var entry in GetSortedEntries(roots))
{
if (!entry.CrystallPunkAllowed) continue; //CrystallEdge guidebook filter
if (entry.LocFilter is not null && entry.LocFilter != ContentLocalizationManager.Culture) continue; //CrystallEdge guidebook filter
if (!entry.CrystallPunkAllowed) continue; //CrystallPunk guidebook filter
if (entry.LocFilter is not null && entry.LocFilter != ContentLocalizationManager.Culture) continue; //CrystallPunk guidebook filter
AddEntry(entry.Id, parent, addedEntries);
}

View File

@@ -32,7 +32,7 @@ public sealed class GuidebookSystem : EntitySystem
[Dependency] private readonly RgbLightControllerSystem _rgbLightControllerSystem = default!;
[Dependency] private readonly SharedPointLightSystem _pointLightSystem = default!;
[Dependency] private readonly TagSystem _tags = default!;
[Dependency] private readonly IPrototypeManager _proto = default!; //CrystallEdge guidebook filter
[Dependency] private readonly IPrototypeManager _proto = default!; //CrystallPunk guidebook filter
public event Action<List<ProtoId<GuideEntryPrototype>>,
List<ProtoId<GuideEntryPrototype>>?,
@@ -47,7 +47,7 @@ public sealed class GuidebookSystem : EntitySystem
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<GuideHelpComponent, MapInitEvent>(OnCrystallEdgeMapInit); //CrystallEdge guidebook filter
SubscribeLocalEvent<GuideHelpComponent, MapInitEvent>(OnCrystallPunkMapInit); //CrystallPunk guidebook filter
SubscribeLocalEvent<GuideHelpComponent, GetVerbsEvent<ExamineVerb>>(OnGetVerbs);
SubscribeLocalEvent<GuideHelpComponent, ActivateInWorldEvent>(OnInteract);
@@ -57,12 +57,12 @@ public sealed class GuidebookSystem : EntitySystem
OnGuidebookControlsTestGetAlternateVerbs);
}
//CrystallEdge guidebook filter
private void OnCrystallEdgeMapInit(Entity<GuideHelpComponent> ent, ref MapInitEvent args)
//CrystallPunk guidebook filter
private void OnCrystallPunkMapInit(Entity<GuideHelpComponent> ent, ref MapInitEvent args)
{
foreach (var guide in ent.Comp.Guides)
{
var guideProto = _proto.Index(guide);
var guideProto = _proto.Index<GuideEntryPrototype>(guide);
if (!guideProto.CrystallPunkAllowed) //REMOVE unnecessary guidebook
{
RemComp<GuideHelpComponent>(ent);
@@ -70,7 +70,7 @@ public sealed class GuidebookSystem : EntitySystem
}
}
}
//CrystallEdge guidebook filter end
//CrystallPunk guidebook filter end
/// <summary>
/// Gets a user entity to use for verbs and examinations. If the player has no attached entity, this will use a

View File

@@ -34,7 +34,6 @@ namespace Content.Client.Info
AddInfoButton("server-info-website-button", CCVars.InfoLinksWebsite);
AddInfoButton("server-info-wiki-button", CCVars.InfoLinksWiki);
AddInfoButton("server-info-forum-button", CCVars.InfoLinksForum);
AddInfoButton("server-info-telegram-button", CCVars.InfoLinksTelegram);
var guidebookController = UserInterfaceManager.GetUIController<GuidebookUIController>();
var guidebookButton = new Button() { Text = Loc.GetString("server-info-guidebook-button") };

View File

@@ -235,23 +235,9 @@ namespace Content.Client.Inventory
EntityManager.RaisePredictiveEvent(new InteractInventorySlotEvent(GetNetEntity(item.Value), altInteract: true));
}
protected override void UpdateInventoryTemplate(Entity<InventoryComponent> ent)
{
base.UpdateInventoryTemplate(ent);
if (TryComp(ent, out InventorySlotsComponent? inventorySlots))
{
foreach (var slot in ent.Comp.Slots)
{
if (inventorySlots.SlotData.TryGetValue(slot.Name, out var slotData))
slotData.SlotDef = slot;
}
}
}
public sealed class SlotData
{
public SlotDefinition SlotDef;
public readonly SlotDefinition SlotDef;
public EntityUid? HeldEntity => Container?.ContainedEntity;
public bool Blocked;
public bool Highlighted;

View File

@@ -17,7 +17,6 @@ using Content.Shared.Inventory.VirtualItem;
using Content.Shared.Strip.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input;
@@ -30,13 +29,10 @@ namespace Content.Client.Inventory
[UsedImplicitly]
public sealed class StrippableBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IUserInterfaceManager _ui = default!;
private readonly ExamineSystem _examine;
private readonly InventorySystem _inv;
private readonly SharedCuffableSystem _cuffable;
private readonly StrippableSystem _strippable;
[ViewVariables]
private const int ButtonSeparation = 4;
@@ -55,8 +51,6 @@ namespace Content.Client.Inventory
_examine = EntMan.System<ExamineSystem>();
_inv = EntMan.System<InventorySystem>();
_cuffable = EntMan.System<SharedCuffableSystem>();
_strippable = EntMan.System<StrippableSystem>();
_virtualHiddenEntity = EntMan.SpawnEntity(HiddenPocketEntityId, MapCoordinates.Nullspace);
}
@@ -191,15 +185,9 @@ 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)
@@ -210,8 +198,7 @@ namespace Content.Client.Inventory
var entity = container.ContainedEntity;
// If this is a full pocket, obscure the real entity
// this does not work for modified clients because they are still sent the real entity
if (entity != null && _strippable.IsStripHidden(slotDef, _player.LocalEntity))
if (entity != null && slotDef.StripHidden)
entity = _virtualHiddenEntity;
var button = new SlotButton(new SlotData(slotDef, container));

View File

@@ -21,22 +21,6 @@ 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))

View File

@@ -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,10 +136,6 @@ 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}";

View File

@@ -279,7 +279,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
_profileEditor.OnOpenGuidebook += _guide.OpenHelp;
_characterSetup = new CharacterSetupGui(_profileEditor);
_characterSetup = new CharacterSetupGui(EntityManager, _prototypeManager, _resourceCache, _preferencesManager, _profileEditor);
_characterSetup.CloseButton.OnPressed += _ =>
{

View File

@@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:style="clr-namespace:Content.Client.Stylesheets"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
VerticalExpand="True">
<Control>
<PanelContainer Name="BackgroundPanel" />
@@ -11,15 +10,10 @@
<Label Text="{Loc 'character-setup-gui-character-setup-label'}"
Margin="8 0 0 0" VAlign="Center"
StyleClasses="LabelHeadingBigger" />
<Button Name="StatsButton" HorizontalExpand="True"
Text="{Loc 'character-setup-gui-character-setup-stats-button'}"
StyleClasses="ButtonBig"
HorizontalAlignment="Right" />
<cc:CommandButton Name="AdminRemarksButton"
Command="adminremarks"
Text="{Loc 'character-setup-gui-character-setup-adminremarks-button'}"
StyleClasses="ButtonBig" />
<Button Name="RulesButton"
Text="{Loc 'character-setup-gui-character-setup-rules-button'}"
StyleClasses="ButtonBig"/>

View File

@@ -1,7 +1,6 @@
using Content.Client.Info;
using Content.Client.Info.PlaytimeStats;
using Content.Client.Resources;
using Content.Shared.CCVar;
using Content.Shared.Preferences;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
@@ -9,7 +8,6 @@ using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
namespace Content.Client.Lobby.UI
@@ -20,23 +18,28 @@ namespace Content.Client.Lobby.UI
[GenerateTypedNameReferences]
public sealed partial class CharacterSetupGui : Control
{
[Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPrototypeManager _protomanager = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private readonly IClientPreferencesManager _preferencesManager;
private readonly IEntityManager _entManager;
private readonly IPrototypeManager _protomanager;
private readonly Button _createNewCharacterButton;
public event Action<int>? SelectCharacter;
public event Action<int>? DeleteCharacter;
public CharacterSetupGui(HumanoidProfileEditor profileEditor)
public CharacterSetupGui(
IEntityManager entManager,
IPrototypeManager protoManager,
IResourceCache resourceCache,
IClientPreferencesManager preferencesManager,
HumanoidProfileEditor profileEditor)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_preferencesManager = preferencesManager;
_entManager = entManager;
_protomanager = protoManager;
var panelTex = _resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
var back = new StyleBoxTexture
{
Texture = panelTex,
@@ -53,7 +56,7 @@ namespace Content.Client.Lobby.UI
_createNewCharacterButton.OnPressed += args =>
{
_preferencesManager.CreateCharacter(HumanoidCharacterProfile.Random());
preferencesManager.CreateCharacter(HumanoidCharacterProfile.Random());
ReloadCharacterPickers();
args.Event.Handle();
};
@@ -62,8 +65,6 @@ namespace Content.Client.Lobby.UI
RulesButton.OnPressed += _ => new RulesAndInfoWindow().Open();
StatsButton.OnPressed += _ => new PlaytimeStatsWindow().OpenCentered();
_cfg.OnValueChanged(CCVars.SeeOwnNotes, p => AdminRemarksButton.Visible = p, true);
}
/// <summary>

View File

@@ -36,18 +36,17 @@ public sealed partial class LoadoutContainer : BoxContainer
if (_protoManager.TryIndex(proto, out var loadProto))
{
var ent = loadProto.DummyEntity ?? _entManager.System<LoadoutSystem>().GetFirstOrNull(loadProto);
var ent = _entManager.System<LoadoutSystem>().GetFirstOrNull(loadProto);
if (ent == null)
return;
if (ent != null)
{
_entity = _entManager.SpawnEntity(ent, MapCoordinates.Nullspace);
Sprite.SetEntity(_entity);
_entity = _entManager.SpawnEntity(ent, MapCoordinates.Nullspace);
Sprite.SetEntity(_entity);
var spriteTooltip = new Tooltip();
spriteTooltip.SetMessage(FormattedMessage.FromUnformatted(_entManager.GetComponent<MetaDataComponent>(_entity.Value).EntityDescription));
TooltipSupplier = _ => spriteTooltip;
var spriteTooltip = new Tooltip();
spriteTooltip.SetMessage(FormattedMessage.FromUnformatted(_entManager.GetComponent<MetaDataComponent>(_entity.Value).EntityDescription));
TooltipSupplier = _ => spriteTooltip;
}
}
}

View File

@@ -2,6 +2,7 @@ using Content.Client.Message;
using Content.Client.UserInterface.Systems.EscapeMenu;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.State;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;

View File

@@ -14,7 +14,6 @@ public abstract class EquipmentHudSystem<T> : EntitySystem where T : IComponent
{
[Dependency] private readonly IPlayerManager _player = default!;
[ViewVariables]
protected bool IsActive;
protected virtual SlotFlags TargetSlots => ~SlotFlags.POCKET;
@@ -103,7 +102,7 @@ public abstract class EquipmentHudSystem<T> : EntitySystem where T : IComponent
args.Components.Add(component);
}
protected void RefreshOverlay(EntityUid uid)
private void RefreshOverlay(EntityUid uid)
{
if (uid != _player.LocalSession?.AttachedEntity)
return;

View File

@@ -21,16 +21,9 @@ public sealed class ShowHealthBarsSystem : EquipmentHudSystem<ShowHealthBarsComp
{
base.Initialize();
SubscribeLocalEvent<ShowHealthBarsComponent, AfterAutoHandleStateEvent>(OnHandleState);
_overlay = new(EntityManager, _prototype);
}
private void OnHandleState(Entity<ShowHealthBarsComponent> ent, ref AfterAutoHandleStateEvent args)
{
RefreshOverlay(ent);
}
protected override void UpdateInternal(RefreshEquipmentHudEvent<ShowHealthBarsComponent> component)
{
base.UpdateInternal(component);

View File

@@ -17,7 +17,6 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem<ShowHealthIconsCo
{
[Dependency] private readonly IPrototypeManager _prototypeMan = default!;
[ViewVariables]
public HashSet<string> DamageContainers = new();
public override void Initialize()
@@ -25,7 +24,6 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem<ShowHealthIconsCo
base.Initialize();
SubscribeLocalEvent<DamageableComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
SubscribeLocalEvent<ShowHealthIconsComponent, AfterAutoHandleStateEvent>(OnHandleState);
}
protected override void UpdateInternal(RefreshEquipmentHudEvent<ShowHealthIconsComponent> component)
@@ -45,11 +43,6 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem<ShowHealthIconsCo
DamageContainers.Clear();
}
private void OnHandleState(Entity<ShowHealthIconsComponent> ent, ref AfterAutoHandleStateEvent args)
{
RefreshOverlay(ent);
}
private void OnGetStatusIconsEvent(Entity<DamageableComponent> entity, ref GetStatusIconsEvent args)
{
if (!IsActive)

View File

@@ -35,7 +35,7 @@ public sealed partial class StencilOverlay
var matty = Matrix3x2.Multiply(matrix, invMatrix);
worldHandle.SetTransform(matty);
foreach (var tile in _map.GetTilesIntersecting(grid.Owner, grid, worldAABB))
foreach (var tile in grid.Comp.GetTilesIntersecting(worldAABB))
{
// Ignored tiles for stencil
if (_weather.CanWeatherAffect(grid.Owner, grid, tile))

View File

@@ -26,7 +26,6 @@ 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;
@@ -36,12 +35,11 @@ public sealed partial class StencilOverlay : Overlay
private readonly ShaderInstance _shader;
public StencilOverlay(ParallaxSystem parallax, SharedTransformSystem transform, SharedMapSystem map, SpriteSystem sprite, WeatherSystem weather)
public StencilOverlay(ParallaxSystem parallax, SharedTransformSystem transform, SpriteSystem sprite, WeatherSystem weather)
{
ZIndex = ParallaxSystem.ParallaxZIndex + 1;
_parallax = parallax;
_transform = transform;
_map = map;
_sprite = sprite;
_weather = weather;
IoCManager.InjectDependencies(this);

View File

@@ -10,14 +10,13 @@ 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, _map, _sprite, _weather));
_overlay.AddOverlay(new StencilOverlay(_parallax, _transform, _sprite, _weather));
}
public override void Shutdown()

View File

@@ -1,12 +1,9 @@
using Content.Shared.Alert;
using Content.Shared.CCVar;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Systems;
using Robust.Client.GameObjects;
using Robust.Client.Physics;
using Robust.Client.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Physics.Components;
using Robust.Shared.Player;
using Robust.Shared.Timing;
@@ -17,8 +14,6 @@ public sealed class MoverController : SharedMoverController
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
public override void Initialize()
{
@@ -140,15 +135,4 @@ public sealed class MoverController : SharedMoverController
{
return _timing is { IsFirstTimePredicted: true, InSimulation: true };
}
public override void SetSprinting(Entity<InputMoverComponent> entity, ushort subTick, bool walking)
{
// Logger.Info($"[{_gameTiming.CurTick}/{subTick}] Sprint: {enabled}");
base.SetSprinting(entity, subTick, walking);
if (walking && _cfg.GetCVar(CCVars.ToggleWalk))
_alerts.ShowAlert(entity, WalkingAlert, showCooldown: false, autoRemove: false);
else
_alerts.ClearAlert(entity, WalkingAlert);
}
}

View File

@@ -1,10 +1,7 @@
using Content.Client.Effects;
using Content.Client.Smoking;
using Content.Shared.Chemistry.Components;
using Content.Shared.Polymorph.Components;
using Content.Shared.Polymorph.Systems;
using Robust.Client.GameObjects;
using Robust.Shared.Player;
namespace Content.Client.Polymorph.Systems;
@@ -13,20 +10,14 @@ public sealed class ChameleonProjectorSystem : SharedChameleonProjectorSystem
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
private EntityQuery<AppearanceComponent> _appearanceQuery;
private EntityQuery<SpriteComponent> _spriteQuery;
public override void Initialize()
{
base.Initialize();
_appearanceQuery = GetEntityQuery<AppearanceComponent>();
_spriteQuery = GetEntityQuery<SpriteComponent>();
SubscribeLocalEvent<ChameleonDisguiseComponent, AfterAutoHandleStateEvent>(OnHandleState);
SubscribeLocalEvent<ChameleonDisguisedComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<ChameleonDisguisedComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<ChameleonDisguisedComponent, GetFlashEffectTargetEvent>(OnGetFlashEffectTargetEvent);
}
private void OnHandleState(Entity<ChameleonDisguiseComponent> ent, ref AfterAutoHandleStateEvent args)
@@ -34,30 +25,9 @@ public sealed class ChameleonProjectorSystem : SharedChameleonProjectorSystem
CopyComp<SpriteComponent>(ent);
CopyComp<GenericVisualizerComponent>(ent);
CopyComp<SolutionContainerVisualsComponent>(ent);
CopyComp<BurnStateVisualsComponent>(ent);
// reload appearance to hopefully prevent any invisible layers
if (_appearanceQuery.TryComp(ent, out var appearance))
_appearance.QueueUpdate(ent, appearance);
}
private void OnStartup(Entity<ChameleonDisguisedComponent> ent, ref ComponentStartup args)
{
if (!_spriteQuery.TryComp(ent, out var sprite))
return;
ent.Comp.WasVisible = sprite.Visible;
sprite.Visible = false;
}
private void OnShutdown(Entity<ChameleonDisguisedComponent> ent, ref ComponentShutdown args)
{
if (_spriteQuery.TryComp(ent, out var sprite))
sprite.Visible = ent.Comp.WasVisible;
}
private void OnGetFlashEffectTargetEvent(Entity<ChameleonDisguisedComponent> ent, ref GetFlashEffectTargetEvent args)
{
args.Target = ent.Comp.Disguise;
}
}

View File

@@ -116,7 +116,7 @@ public partial class BaseShuttleControl : MapGridControl
}
}
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 gridToView, Entity<MapGridComponent> grid, Color color, float alpha = 0.01f)
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 matrix, 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 = gridToView;
_drawJob.Matrix = matrix;
_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 => 64;
public int BatchSize => 16;
public float MinimapScale;
public Vector2 MidPoint;
@@ -297,7 +297,12 @@ public partial class BaseShuttleControl : MapGridControl
public void Execute(int index)
{
ScaledVertices[index] = Vector2.Transform(Vertices[index], Matrix);
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;
}
}
}

View File

@@ -15,7 +15,6 @@ 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()
@@ -36,12 +35,6 @@ 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;

View File

@@ -138,7 +138,6 @@ 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);

View File

@@ -107,19 +107,16 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
DrawCircles(handle);
var gridNent = EntManager.GetNetEntity(GridEntity);
var mapPos = _xformSystem.ToMapCoordinates(_coordinates.Value);
var ourGridToWorld = _xformSystem.GetWorldMatrix(GridEntity.Value);
var selectedDockToOurGrid = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero);
var selectedDockToWorld = Matrix3x2.Multiply(selectedDockToOurGrid, ourGridToWorld);
var ourGridMatrix = _xformSystem.GetWorldMatrix(GridEntity.Value);
var dockMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero);
var worldFromDock = Matrix3x2.Multiply(dockMatrix, ourGridMatrix);
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);
Matrix3x2.Invert(worldFromDock, out var offsetMatrix);
// Draw nearby grids
var controlBounds = PixelSizeBox;
_grids.Clear();
_mapManager.FindGridsIntersecting(gridXform.MapID, viewBoundsWorld, ref _grids);
_mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(mapPos.Position - WorldRangeVector, mapPos.Position + WorldRangeVector), ref _grids);
// offset the dotted-line position to the bounds.
Vector2? viewedDockPos = _viewedState != null ? MidPointVector : null;
@@ -139,11 +136,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
if (grid.Owner != GridEntity && !_shuttles.CanDraw(grid.Owner, iffComp: iffComp))
continue;
var curGridToWorld = _xformSystem.GetWorldMatrix(grid.Owner);
var curGridToView = curGridToWorld * worldToSelectedDock * selectedDockToView;
var gridMatrix = _xformSystem.GetWorldMatrix(grid.Owner);
var matty = Matrix3x2.Multiply(gridMatrix, offsetMatrix);
var color = _shuttles.GetIFFColor(grid.Owner, grid.Owner == GridEntity, component: iffComp);
DrawGrid(handle, curGridToView, grid, color);
DrawGrid(handle, matty, grid, color);
// Draw any docks on that grid
if (!DockState.Docks.TryGetValue(EntManager.GetNetEntity(grid), out var gridDocks))
@@ -154,24 +151,23 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
if (ViewedDock == dock.Entity)
continue;
var otherDockRotation = Matrix3Helpers.CreateRotation(dock.Angle);
var position = Vector2.Transform(dock.Coordinates.Position, matty);
// 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))
var otherDockRotation = Matrix3Helpers.CreateRotation(dock.Angle);
var scaledPos = ScalePosition(position with {Y = -position.Y});
if (!controlBounds.Contains(scaledPos.Floored()))
continue;
// Draw the dock's collision
var collisionBL = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), curGridToView);
Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), matty);
var collisionBR = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), curGridToView);
Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), matty);
var collisionTR = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), curGridToView);
Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), matty);
var collisionTL = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), curGridToView);
Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), matty);
var verts = new[]
{
@@ -185,6 +181,13 @@ 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);
@@ -192,10 +195,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), 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);
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);
verts = new[]
{
@@ -209,6 +212,13 @@ 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)
@@ -243,11 +253,9 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
collisionCenter /= 4;
var range = viewedDockPos.Value - collisionCenter;
var maxRange = SharedDockingSystem.DockingHiglightRange * MinimapScale;
var maxRangeSq = maxRange * maxRange;
if (range.LengthSquared() < maxRangeSq)
if (range.Length() < SharedDockingSystem.DockingHiglightRange * MinimapScale)
{
if (dock.GridDockedWith == null)
if (_viewedState?.GridDockedWith == null)
{
var coordsOne = EntManager.GetCoordinates(_viewedState!.Coordinates);
var coordsTwo = EntManager.GetCoordinates(dock.Coordinates);
@@ -257,11 +265,10 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
var rotA = _xformSystem.GetWorldRotation(coordsOne.EntityId) + _viewedState!.Angle;
var rotB = _xformSystem.GetWorldRotation(coordsTwo.EntityId) + dock.Angle;
var distanceSq = (mapOne.Position - mapTwo.Position).LengthSquared();
var distance = (mapOne.Position - mapTwo.Position).Length();
var inAlignment = _dockSystem.InAlignment(mapOne, rotA, mapTwo, rotB);
var maxDockDistSq = SharedDockingSystem.DockRange * SharedDockingSystem.DockRange;
var canDock = distanceSq < maxDockDistSq && inAlignment;
var canDock = distance < SharedDockingSystem.DockRange && inAlignment;
if (dockButton != null)
dockButton.Disabled = !canDock || !canDockChange;
@@ -290,8 +297,7 @@ 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 dockPositionInView = Vector2.Transform(dock.Coordinates.Position, curGridToView);
var containerPos = dockPositionInView / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale;
var containerPos = scaledPos / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale;
SetPosition(container, containerPos);
}

View File

@@ -29,11 +29,6 @@ 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();
@@ -62,11 +57,6 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
_rotation = angle;
}
public void SetConsole(EntityUid? consoleEntity)
{
_consoleEntity = consoleEntity;
}
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
{
base.KeyBindUp(args);
@@ -149,35 +139,40 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
}
var mapPos = _transform.ToMapCoordinates(_coordinates.Value);
var posMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, _rotation.Value);
var offset = _coordinates.Value.Position;
var posMatrix = Matrix3Helpers.CreateTransform(offset, _rotation.Value);
var ourEntRot = RotateWithEntity ? _transform.GetWorldRotation(xform) : _rotation.Value;
var ourEntMatrix = Matrix3Helpers.CreateTransform(_transform.GetWorldPosition(xform), ourEntRot);
var shuttleToWorld = Matrix3x2.Multiply(posMatrix, ourEntMatrix);
Matrix3x2.Invert(shuttleToWorld, out var worldToShuttle);
var shuttleToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector);
var ourWorldMatrix = Matrix3x2.Multiply(posMatrix, ourEntMatrix);
Matrix3x2.Invert(ourWorldMatrix, out var ourWorldMatrixInvert);
// Draw our grid in detail
var ourGridId = xform.GridUid;
if (EntManager.TryGetComponent<MapGridComponent>(ourGridId, out var ourGrid) &&
fixturesQuery.HasComponent(ourGridId.Value))
{
var ourGridToWorld = _transform.GetWorldMatrix(ourGridId.Value);
var ourGridToShuttle = Matrix3x2.Multiply(ourGridToWorld, worldToShuttle);
var ourGridToView = ourGridToShuttle * shuttleToView;
var ourGridMatrix = _transform.GetWorldMatrix(ourGridId.Value);
var matrix = Matrix3x2.Multiply(ourGridMatrix, ourWorldMatrixInvert);
var color = _shuttles.GetIFFColor(ourGridId.Value, self: true);
DrawGrid(handle, ourGridToView, (ourGridId.Value, ourGrid), color);
DrawDocks(handle, ourGridId.Value, ourGridToView);
DrawGrid(handle, matrix, (ourGridId.Value, ourGrid), color);
DrawDocks(handle, ourGridId.Value, matrix);
}
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(new Vector2(0f, -radarVertRadius)),
ScalePosition(new Vector2(radarVertRadius / 2f, 0f)),
ScalePosition(new Vector2(0f, radarVertRadius)),
ScalePosition(new Vector2(radarVertRadius / -2f, 0f)),
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)),
};
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, radarPosVerts, Color.Lime);
@@ -202,8 +197,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
if (!_shuttles.CanDraw(gUid, gridBody, iff))
continue;
var curGridToWorld = _transform.GetWorldMatrix(gUid);
var curGridToView = curGridToWorld * worldToShuttle * shuttleToView;
var gridMatrix = _transform.GetWorldMatrix(gUid);
var matty = Matrix3x2.Multiply(gridMatrix, ourWorldMatrixInvert);
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);
@@ -218,7 +213,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
{
var gridBounds = grid.Comp.LocalAABB;
var gridCentre = Vector2.Transform(gridBody.LocalCenter, curGridToView);
var gridCentre = Vector2.Transform(gridBody.LocalCenter, matty);
gridCentre.Y = -gridCentre.Y;
var distance = gridCentre.Length();
var labelText = Loc.GetString("shuttle-console-iff-label", ("name", labelName),
@@ -234,8 +230,9 @@ 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.
var gridScaledPosition = gridCentre - new Vector2(0, -yOffset);
// 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);
// 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
@@ -267,32 +264,18 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
}
// Detailed view
var gridAABB = curGridToWorld.TransformBox(grid.Comp.LocalAABB);
var gridAABB = gridMatrix.TransformBox(grid.Comp.LocalAABB);
// Skip drawing if it's out of range.
if (!gridAABB.Intersects(viewAABB))
continue;
DrawGrid(handle, curGridToView, grid, labelColor);
DrawDocks(handle, gUid, curGridToView);
DrawGrid(handle, matty, grid, labelColor);
DrawDocks(handle, gUid, matty);
}
// 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 gridToView)
private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 matrix)
{
if (!ShowDocks)
return;
@@ -300,32 +283,33 @@ 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);
var positionInView = Vector2.Transform(position, gridToView);
if (!viewBounds.Contains(positionInView))
{
if (uiPosition.Length() > (WorldRange * 2f) - DockScale)
continue;
}
var color = Color.ToSrgb(Color.Magenta);
var verts = new[]
{
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),
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),
};
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);
}

View File

@@ -131,8 +131,7 @@ public sealed partial class BorgMenu : FancyWindow
_modules.Clear();
foreach (var module in chassis.ModuleContainer.ContainedEntities)
{
var moduleComponent = _entity.GetComponent<BorgModuleComponent>(module);
var control = new BorgModuleControl(module, _entity, !moduleComponent.DefaultModule);
var control = new BorgModuleControl(module, _entity);
control.RemoveButtonPressed += () =>
{
RemoveModuleButtonPressed?.Invoke(module);

View File

@@ -9,7 +9,7 @@ public sealed partial class BorgModuleControl : PanelContainer
{
public Action? RemoveButtonPressed;
public BorgModuleControl(EntityUid entity, IEntityManager entityManager, bool canRemove)
public BorgModuleControl(EntityUid entity, IEntityManager entityManager)
{
RobustXamlLoader.Load(this);
@@ -20,7 +20,6 @@ public sealed partial class BorgModuleControl : PanelContainer
{
RemoveButtonPressed?.Invoke();
};
RemoveButton.Visible = canRemove;
}
}

View File

@@ -1,43 +0,0 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc 'borg-select-type-menu-title'}"
SetSize="550 300">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal" VerticalExpand="True">
<!-- Left pane: selection of borg type -->
<BoxContainer Orientation="Vertical" MinWidth="200" Margin="2 0">
<Label Text="{Loc 'borg-select-type-menu-available'}" StyleClasses="LabelHeading" />
<ScrollContainer HScrollEnabled="False" VerticalExpand="True">
<BoxContainer Name="SelectionsContainer" Orientation="Vertical" />
</ScrollContainer>
</BoxContainer>
<customControls:VSeparator />
<!-- Right pane: information about selected borg module, confirm button. -->
<BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="2 0">
<Label Text="{Loc 'borg-select-type-menu-information'}" StyleClasses="LabelHeading" />
<Control VerticalExpand="True">
<controls:Placeholder Name="InfoPlaceholder" PlaceholderText="{Loc 'borg-select-type-menu-select-type'}" />
<BoxContainer Name="InfoContents" Orientation="Vertical" Visible="False">
<BoxContainer Orientation="Horizontal" Margin="0 0 0 4">
<EntityPrototypeView Name="ChassisView" Scale="2,2" />
<Label Name="NameLabel" HorizontalExpand="True" />
</BoxContainer>
<RichTextLabel Name="DescriptionLabel" VerticalExpand="True" VerticalAlignment="Top" />
</BoxContainer>
</Control>
<controls:ConfirmButton Name="ConfirmTypeButton" Text="{Loc 'borg-select-type-menu-confirm'}"
Disabled="True" HorizontalAlignment="Right"
MinWidth="200" />
</BoxContainer>
</BoxContainer>
<controls:StripeBack Margin="0 0 0 4">
<Label Text="{Loc 'borg-select-type-menu-bottom-text'}" HorizontalAlignment="Center" StyleClasses="LabelSubText" Margin="4 4 0 4"/>
</controls:StripeBack>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -1,81 +0,0 @@
using System.Linq;
using Content.Client.UserInterface.Controls;
using Content.Client.UserInterface.Systems.Guidebook;
using Content.Shared.Guidebook;
using Content.Shared.Silicons.Borgs;
using Content.Shared.Silicons.Borgs.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client.Silicons.Borgs;
/// <summary>
/// Menu used by borgs to select their type.
/// </summary>
/// <seealso cref="BorgSelectTypeUserInterface"/>
/// <seealso cref="BorgSwitchableTypeComponent"/>
[GenerateTypedNameReferences]
public sealed partial class BorgSelectTypeMenu : FancyWindow
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private BorgTypePrototype? _selectedBorgType;
public event Action<ProtoId<BorgTypePrototype>>? ConfirmedBorgType;
[ValidatePrototypeId<GuideEntryPrototype>]
private static readonly List<ProtoId<GuideEntryPrototype>> GuidebookEntries = new() { "Cyborgs", "Robotics" };
public BorgSelectTypeMenu()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
var group = new ButtonGroup();
foreach (var borgType in _prototypeManager.EnumeratePrototypes<BorgTypePrototype>().OrderBy(PrototypeName))
{
var button = new Button
{
Text = PrototypeName(borgType),
Group = group,
};
button.OnPressed += _ =>
{
_selectedBorgType = borgType;
UpdateInformation(borgType);
};
SelectionsContainer.AddChild(button);
}
ConfirmTypeButton.OnPressed += ConfirmButtonPressed;
HelpGuidebookIds = GuidebookEntries;
}
private void UpdateInformation(BorgTypePrototype prototype)
{
_selectedBorgType = prototype;
InfoContents.Visible = true;
InfoPlaceholder.Visible = false;
ConfirmTypeButton.Disabled = false;
NameLabel.Text = PrototypeName(prototype);
DescriptionLabel.Text = Loc.GetString($"borg-type-{prototype.ID}-desc");
ChassisView.SetPrototype(prototype.DummyPrototype);
}
private void ConfirmButtonPressed(BaseButton.ButtonEventArgs obj)
{
if (_selectedBorgType == null)
return;
ConfirmedBorgType?.Invoke(_selectedBorgType);
}
private static string PrototypeName(BorgTypePrototype prototype)
{
return Loc.GetString($"borg-type-{prototype.ID}-name");
}
}

View File

@@ -1,30 +0,0 @@
using Content.Shared.Silicons.Borgs.Components;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
namespace Content.Client.Silicons.Borgs;
/// <summary>
/// User interface used by borgs to select their type.
/// </summary>
/// <seealso cref="BorgSelectTypeMenu"/>
/// <seealso cref="BorgSwitchableTypeComponent"/>
/// <seealso cref="BorgSwitchableTypeUiKey"/>
[UsedImplicitly]
public sealed class BorgSelectTypeUserInterface : BoundUserInterface
{
[ViewVariables]
private BorgSelectTypeMenu? _menu;
public BorgSelectTypeUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_menu = this.CreateWindow<BorgSelectTypeMenu>();
_menu.ConfirmedBorgType += prototype => SendMessage(new BorgSelectTypeMessage(prototype));
}
}

View File

@@ -1,81 +0,0 @@
using Content.Shared.Movement.Components;
using Content.Shared.Silicons.Borgs;
using Content.Shared.Silicons.Borgs.Components;
using Robust.Client.GameObjects;
namespace Content.Client.Silicons.Borgs;
/// <summary>
/// Client side logic for borg type switching. Sets up primarily client-side visual information.
/// </summary>
/// <seealso cref="SharedBorgSwitchableTypeSystem"/>
/// <seealso cref="BorgSwitchableTypeComponent"/>
public sealed class BorgSwitchableTypeSystem : SharedBorgSwitchableTypeSystem
{
[Dependency] private readonly BorgSystem _borgSystem = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BorgSwitchableTypeComponent, AfterAutoHandleStateEvent>(AfterStateHandler);
SubscribeLocalEvent<BorgSwitchableTypeComponent, ComponentStartup>(OnComponentStartup);
}
private void OnComponentStartup(Entity<BorgSwitchableTypeComponent> ent, ref ComponentStartup args)
{
UpdateEntityAppearance(ent);
}
private void AfterStateHandler(Entity<BorgSwitchableTypeComponent> ent, ref AfterAutoHandleStateEvent args)
{
UpdateEntityAppearance(ent);
}
protected override void UpdateEntityAppearance(
Entity<BorgSwitchableTypeComponent> entity,
BorgTypePrototype prototype)
{
if (TryComp(entity, out SpriteComponent? sprite))
{
sprite.LayerSetState(BorgVisualLayers.Body, prototype.SpriteBodyState);
sprite.LayerSetState(BorgVisualLayers.LightStatus, prototype.SpriteToggleLightState);
}
if (TryComp(entity, out BorgChassisComponent? chassis))
{
_borgSystem.SetMindStates(
(entity.Owner, chassis),
prototype.SpriteHasMindState,
prototype.SpriteNoMindState);
if (TryComp(entity, out AppearanceComponent? appearance))
{
// Queue update so state changes apply.
_appearance.QueueUpdate(entity, appearance);
}
}
if (prototype.SpriteBodyMovementState is { } movementState)
{
var spriteMovement = EnsureComp<SpriteMovementComponent>(entity);
spriteMovement.NoMovementLayers.Clear();
spriteMovement.NoMovementLayers["movement"] = new PrototypeLayerData
{
State = prototype.SpriteBodyState,
};
spriteMovement.MovementLayers.Clear();
spriteMovement.MovementLayers["movement"] = new PrototypeLayerData
{
State = movementState,
};
}
else
{
RemComp<SpriteMovementComponent>(entity);
}
base.UpdateEntityAppearance(entity, prototype);
}
}

View File

@@ -92,18 +92,4 @@ public sealed class BorgSystem : SharedBorgSystem
sprite.LayerSetState(MMIVisualLayers.Base, state);
}
}
/// <summary>
/// Sets the sprite states used for the borg "is there a mind or not" indication.
/// </summary>
/// <param name="borg">The entity and component to modify.</param>
/// <param name="hasMindState">The state to use if the borg has a mind.</param>
/// <param name="noMindState">The state to use if the borg has no mind.</param>
/// <seealso cref="BorgChassisComponent.HasMindState"/>
/// <seealso cref="BorgChassisComponent.NoMindState"/>
public void SetMindStates(Entity<BorgChassisComponent> borg, string hasMindState, string noMindState)
{
borg.Comp.HasMindState = hasMindState;
borg.Comp.NoMindState = noMindState;
}
}

View File

@@ -9,7 +9,6 @@ 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;
@@ -19,13 +18,8 @@ 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);
@@ -53,12 +47,9 @@ 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);
@@ -80,8 +71,6 @@ public sealed partial class LawDisplay : Control
MinWidth = 75,
};
_nextAllowedPress[radioChannelButton] = TimeSpan.Zero;
radioChannelButton.OnPressed += _ =>
{
switch (radioChannel)
@@ -91,21 +80,9 @@ 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;
}
}
}

View File

@@ -1,7 +1,7 @@
using Content.Shared.Singularity.EntitySystems;
using Content.Shared.Singularity.Components;
namespace Content.Client.Singularity.Systems;
namespace Content.Client.Singularity.EntitySystems;
/// <summary>
/// The client-side version of <see cref="SharedEventHorizonSystem"/>.

View File

@@ -1,12 +0,0 @@
using Content.Shared.Singularity.EntitySystems;
using Content.Shared.Singularity.Components;
namespace Content.Client.Singularity.Systems;
/// <summary>
/// The client-side version of <see cref="SharedSingularityGeneratorSystem"/>.
/// Manages <see cref="SingularityGeneratorComponent"/>s.
/// Exists to make relevant signal handlers (ie: <see cref="SharedSingularityGeneratorSystem.OnEmagged"/>) work on the client.
/// </summary>
public sealed class SingularityGeneratorSystem : SharedSingularityGeneratorSystem
{}

View File

@@ -5,7 +5,7 @@ using Robust.Client.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.Utility;
namespace Content.Client.Singularity.Systems;
namespace Content.Client.Singularity.EntitySystems;
/// <summary>
/// The client-side version of <see cref="SharedSingularitySystem"/>.

View File

@@ -1,6 +1,6 @@
<widgets:AlertsUI xmlns="https://spacestation14.io"
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Alerts.Widgets"
MinSize="96 96">
MinSize="64 64">
<PanelContainer HorizontalAlignment="Right" VerticalAlignment="Top">
<BoxContainer Name="AlertContainer" Access="Public" Orientation="Vertical" />
</PanelContainer>

View File

@@ -16,8 +16,9 @@ using static Robust.Client.UserInterface.Controls.LineEdit;
namespace Content.Client.UserInterface.Systems.Chat.Widgets;
[GenerateTypedNameReferences]
[Virtual]
#pragma warning disable RA0003
public partial class ChatBox : UIWidget
#pragma warning restore RA0003
{
private readonly ChatUIController _controller;
private readonly IEntityManager _entManager;

View File

@@ -71,7 +71,6 @@ 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
{

View File

@@ -83,27 +83,22 @@ 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();
}
}

View File

@@ -160,9 +160,8 @@ public sealed class ItemGridPiece : Control, IEntityControl
}
// typically you'd divide by two, but since the textures are half a tile, this is done implicitly
var iconPosition = new Vector2(
(boundingGrid.Width + 1) * size.X + Location.Rotation.RotateVec(itemComponent.StoredOffset).X * 2,
(boundingGrid.Height + 1) * size.Y + Location.Rotation.RotateVec(itemComponent.StoredOffset).Y * 2);
var iconPosition = new Vector2((boundingGrid.Width + 1) * size.X + itemComponent.StoredOffset.X * 2,
(boundingGrid.Height + 1) * size.Y + itemComponent.StoredOffset.Y * 2);
var iconRotation = Location.Rotation + Angle.FromDegrees(itemComponent.StoredRotation);
if (itemComponent.StoredSprite is { } storageSprite)

View File

@@ -307,6 +307,12 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
_entity.GetNetEntity(storageEnt),
new ItemStorageLocation(DraggingRotation, position)));
}
else
{
_entity.RaisePredictiveEvent(new StorageRemoveItemEvent(
_entity.GetNetEntity(draggingGhost.Entity),
_entity.GetNetEntity(storageEnt)));
}
_menuDragHelper.EndDrag();
_container?.BuildItemPieces();

View File

@@ -20,7 +20,7 @@ public enum WeaponArcAnimation : byte
None,
Thrust,
Slash,
//CrystallEdge Melee upgrade
//CrystallPunk Melee upgrade
CPSlash,
CPThrust
}

View File

@@ -43,8 +43,8 @@ public sealed partial class MeleeWeaponSystem
return;
}
var length = 1f; //CrystallEdgeMelee upgrade
var offset = -1f; //CrystallEdge Melee upgrade
var length = 1f; //CrystallPunk Melee upgrade
var offset = -1f; //CrystallPunk Melee upgrade
var spriteRotation = Angle.Zero;
if (arcComponent.Animation != WeaponArcAnimation.None
@@ -59,8 +59,8 @@ public sealed partial class MeleeWeaponSystem
if (meleeWeaponComponent.SwingLeft)
angle *= -1;
length = meleeWeaponComponent.CPAnimationLength; //CrystallEdge Melee upgrade
offset = meleeWeaponComponent.CPAnimationOffset; //CrystallEdge Melee upgrade
length = meleeWeaponComponent.CPAnimationLength; //CrystallPunk Melee upgrade
offset = meleeWeaponComponent.CPAnimationOffset; //CrystallPunk Melee upgrade
}
sprite.Rotation = localPos.ToWorldAngle();
var distance = Math.Clamp(localPos.Length() / 2f, 0.2f, 1f);
@@ -92,7 +92,7 @@ public sealed partial class MeleeWeaponSystem
if (arcComponent.Fadeout)
_animation.Play(animationUid, GetFadeAnimation(sprite, 0f, 0.15f), FadeAnimationKey);
break;
//CrystallEdge MeleeUpgrade
//CrystallPunk MeleeUpgrade
case WeaponArcAnimation.CPSlash:
track = EnsureComp<TrackUserComponent>(animationUid);
track.User = user;
@@ -107,7 +107,7 @@ public sealed partial class MeleeWeaponSystem
if (arcComponent.Fadeout)
_animation.Play(animationUid, GetFadeAnimation(sprite, 0f, 0.15f), FadeAnimationKey);
break;
//CrystallEdge MeleeUpgrade end
//CrystallPunk MeleeUpgrade end
}
}
@@ -207,7 +207,7 @@ public sealed partial class MeleeWeaponSystem
/// </summary>
private Animation GetLungeAnimation(Vector2 direction)
{
const float length = 0.2f; // 0.1 original, CrystallEdge update
const float length = 0.2f; // 0.1 original, CrystallPunk update
return new Animation
{
@@ -221,9 +221,9 @@ public sealed partial class MeleeWeaponSystem
InterpolationMode = AnimationInterpolationMode.Linear,
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(Vector2.Zero, 0f), //CrystallEdge MeleeUpgrade
new AnimationTrackProperty.KeyFrame(direction.Normalized() * 0.15f, length*0.4f), //CrystallEdge MeleeUpgrade
new AnimationTrackProperty.KeyFrame(Vector2.Zero, length*0.6f) //CrystallEdge MeleeUpgrade
new AnimationTrackProperty.KeyFrame(Vector2.Zero, 0f), //CrystallPunk MeleeUpgrade
new AnimationTrackProperty.KeyFrame(direction.Normalized() * 0.15f, length*0.4f), //CrystallPunk MeleeUpgrade
new AnimationTrackProperty.KeyFrame(Vector2.Zero, length*0.6f) //CrystallPunk MeleeUpgrade
}
}
}
@@ -253,7 +253,7 @@ public sealed partial class MeleeWeaponSystem
}
}
//CrystallEdge MeleeUpgrade start
//CrystallPunk MeleeUpgrade start
private Animation CPGetSlashAnimation(SpriteComponent sprite, Angle arc, Angle spriteRotation, float length, float offset = -1f)
{
var startRotation = sprite.Rotation + (arc * 0.5f);
@@ -324,6 +324,6 @@ public sealed partial class MeleeWeaponSystem
};
}
//CrystallEdge MeleeUpgrade end
//CrystallPunk MeleeUpgrade end
}

View File

@@ -157,7 +157,7 @@ public sealed partial class GunSystem : SharedGunSystem
var useKey = gun.UseKey ? EngineKeyFunctions.Use : EngineKeyFunctions.UseSecondary;
if (_inputSystem.CmdStates.GetState(useKey) != BoundKeyState.Down && !gun.BurstActivated)
if (_inputSystem.CmdStates.GetState(useKey) != BoundKeyState.Down)
{
if (gun.ShotCounter != 0)
EntityManager.RaisePredictiveEvent(new RequestStopShootEvent { Gun = GetNetEntity(gunUid) });

View File

@@ -206,7 +206,8 @@ namespace Content.Client.Wires.UI
(_statusContainer = new GridContainer
{
Margin = new Thickness(8, 4),
Rows = 2
// TODO: automatically change columns count.
Columns = 3
})
}
}
@@ -226,8 +227,7 @@ namespace Content.Client.Wires.UI
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#525252ff")}
});
CloseButton.OnPressed += _ => Close();
SetHeight = 200;
MinWidth = 320;
SetSize = new Vector2(320, 200);
}
@@ -503,8 +503,6 @@ 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);

View File

@@ -1,213 +0,0 @@
using Content.Client.Clothing;
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared.Clothing;
using Content.Shared.Hands;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Wieldable.Components;
using Robust.Client.GameObjects;
using Robust.Client.ResourceManagement;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations;
namespace Content.Client._CP14.ModularCraft;
public sealed class CP14ClientModularCraftSystem : CP14SharedModularCraftSystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IResourceCache _resCache = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, GetInhandVisualsEvent>(OnGetInhandVisuals);
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, GetEquipmentVisualsEvent>(OnGetEquipmentVisuals);
}
private void OnAfterHandleState(Entity<CP14ModularCraftStartPointComponent> start,
ref AfterAutoHandleStateEvent args)
{
if (!TryComp<SpriteComponent>(start, out var sprite))
return;
UpdateIcon(start, sprite);
}
private void UpdateIcon(Entity<CP14ModularCraftStartPointComponent> start, SpriteComponent? sprite = null)
{
if (!Resolve(start, ref sprite, false))
return;
//Remove old layers
foreach (var key in start.Comp.RevealedLayers)
{
sprite.RemoveLayer(key);
}
start.Comp.RevealedLayers.Clear();
//Add new layers
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
if (indexedPart.IconSprite is null)
{
//Try get default sprite
if (indexedPart.RsiPath is null)
continue;
var state = $"icon";
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var keyCode = $"cp14-modular-icon-layer-{counterPart}-default";
start.Comp.RevealedLayers.Add(keyCode);
var index = sprite.AddLayer(defaultLayer);
sprite.LayerMapSet(keyCode, index);
}
else
{
var counter = 0;
foreach (var layer in indexedPart.IconSprite)
{
var keyCode = $"cp14-modular-icon-layer-{counterPart}-{counter}";
start.Comp.RevealedLayers.Add(keyCode);
var index = sprite.AddLayer(layer);
sprite.LayerMapSet(keyCode, index);
counter++;
}
}
counterPart++;
}
}
private void OnGetInhandVisuals(Entity<CP14ModularCraftStartPointComponent> start, ref GetInhandVisualsEvent args)
{
var defaultKey = $"cp14-modular-inhand-layer-{args.Location.ToString().ToLowerInvariant()}";
if (!TryComp<ItemComponent>(start, out var item))
return;
var wielded = item.HeldPrefix == "wielded"; //SHITCOOOOOOODE
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
var targetLayers =
wielded ? indexedPart.WieldedInhandVisuals : indexedPart.InhandVisuals;
if (targetLayers is not null && targetLayers.TryGetValue(args.Location, out var layers))
{
var i = 0;
foreach (var layer in layers)
{
var key = $"{defaultKey}-{counterPart}-{i}";
args.Layers.Add((key, layer));
i++;
}
}
else
{
//Try get default visuals
if (indexedPart.RsiPath is null)
continue;
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
var state = $"inhand-{args.Location.ToString().ToLowerInvariant()}";
if (wielded)
state = $"wielded-{state}";
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var key = $"{defaultKey}-{counterPart}-default";
args.Layers.Add((key, defaultLayer));
}
counterPart++;
}
}
private void OnGetEquipmentVisuals(Entity<CP14ModularCraftStartPointComponent> start,
ref GetEquipmentVisualsEvent args)
{
if (!TryComp(args.Equipee, out InventoryComponent? inventory))
return;
var defaultKey = $"cp14-modular-clothing-layer-{args.Slot}";
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
if (indexedPart.ClothingVisuals is not null && indexedPart.ClothingVisuals.TryGetValue(args.Slot, out var layers))
{
var i = 0;
foreach (var layer in layers)
{
var key = $"{defaultKey}-{counterPart}-{i}";
args.Layers.Add((key, layer));
i++;
}
}
else
{
//Try get default sprites
if (indexedPart.RsiPath is null)
continue;
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
if (!ClientClothingSystem.TemporarySlotMap.TryGetValue(args.Slot, out var correctedSlot))
continue;
var state = $"equipped-{correctedSlot}";
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var key = $"{defaultKey}-{counterPart}-default";
args.Layers.Add((key, defaultLayer));
}
}
}
}

View File

@@ -1,127 +0,0 @@
using Content.Shared._CP14.Roof;
using Content.Shared.Ghost;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Console;
using Robust.Shared.Map.Components;
namespace Content.Client._CP14.Roof;
public sealed class CP14RoofSystem : EntitySystem
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
private bool _roofVisible = true;
public bool DisabledByCommand = false;
private EntityQuery<GhostComponent> _ghostQuery;
private EntityQuery<TransformComponent> _xformQuery;
public bool RoofVisibility
{
get => _roofVisible && !DisabledByCommand;
set
{
_roofVisible = value;
UpdateRoofVisibilityAll();
}
}
public override void Initialize()
{
base.Initialize();
_ghostQuery = GetEntityQuery<GhostComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
SubscribeLocalEvent<CP14RoofComponent, ComponentStartup>(RoofStartup);
SubscribeLocalEvent<GhostComponent, CP14ToggleRoofVisibilityAction>(OnToggleRoof);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var player = _playerManager.LocalEntity;
if (_ghostQuery.HasComp(player))
return;
if (_xformQuery.TryComp(player, out var playerXform))
{
var grid = playerXform.GridUid;
if (grid == null || !TryComp<MapGridComponent>(grid, out var gridComp))
return;
var roofQuery = GetEntityQuery<CP14RoofComponent>();
var anchored = _map.GetAnchoredEntities(grid.Value, gridComp, playerXform.Coordinates);
var underRoof = false;
foreach (var ent in anchored)
{
if (!roofQuery.HasComp(ent))
continue;
underRoof = true;
}
if (underRoof && _roofVisible)
{
RoofVisibility = false;
}
if (!underRoof && !_roofVisible)
{
RoofVisibility = true;
}
}
}
private void OnToggleRoof(Entity<GhostComponent> ent, ref CP14ToggleRoofVisibilityAction args)
{
if (args.Handled)
return;
DisabledByCommand = !DisabledByCommand;
UpdateRoofVisibilityAll();
args.Handled = true;
}
private void RoofStartup(Entity<CP14RoofComponent> ent, ref ComponentStartup args)
{
if (!TryComp<SpriteComponent>(ent, out var sprite))
return;
UpdateVisibility(ent, sprite);
}
private void UpdateVisibility(Entity<CP14RoofComponent> ent, SpriteComponent sprite)
{
sprite.Visible = RoofVisibility;
}
public void UpdateRoofVisibilityAll()
{
var query = EntityQueryEnumerator<CP14RoofComponent, SpriteComponent>();
while (query.MoveNext(out var uid, out var marker, out var sprite))
{
UpdateVisibility((uid, marker), sprite);
}
}
}
internal sealed class ShowRoof : LocalizedCommands
{
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
public override string Command => "cp14_toggleroof";
public override string Help => "Toggle roof visibility";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var roofSystem = _entitySystemManager.GetEntitySystem<CP14RoofSystem>();
roofSystem.DisabledByCommand = !roofSystem.DisabledByCommand;
roofSystem.UpdateRoofVisibilityAll();
}
}

View File

@@ -1,7 +0,0 @@
using Content.Shared._CP14.Temperature;
namespace Content.Client._CP14.Temperature;
public sealed partial class CP14ClientFireSpreadSystem : CP14SharedFireSpreadSystem
{
}

View File

@@ -12,7 +12,6 @@ namespace Content.IntegrationTests.Tests.Access
[TestOf(typeof(AccessReaderComponent))]
public sealed class AccessReaderTest
{
/*
[Test]
public async Task TestProtoTags()
{
@@ -124,6 +123,6 @@ namespace Content.IntegrationTests.Tests.Access
});
await pair.CleanReturnAsync();
}
*/
}
}

View File

@@ -6,7 +6,7 @@ namespace Content.IntegrationTests.Tests.Atmos
[TestFixture]
[TestOf(typeof(AtmosAlarmThreshold))]
public sealed class AlarmThresholdTest
{/*
{
[TestPrototypes]
private const string Prototypes = @"
- type: alarmThreshold
@@ -135,6 +135,6 @@ namespace Content.IntegrationTests.Tests.Atmos
}
});
await pair.CleanReturnAsync();
}*/
}
}
}

View File

@@ -8,7 +8,7 @@ namespace Content.IntegrationTests.Tests.Atmos
[TestFixture]
[TestOf(typeof(Atmospherics))]
public sealed class ConstantsTest
{/*
{
[Test]
public async Task TotalGasesTest()
{
@@ -27,6 +27,6 @@ namespace Content.IntegrationTests.Tests.Atmos
});
});
await pair.CleanReturnAsync();
}*/
}
}
}

View File

@@ -8,7 +8,7 @@ namespace Content.IntegrationTests.Tests.Atmos
[TestFixture]
[TestOf(typeof(GasMixture))]
public sealed class GasMixtureTest
{/*
{
[Test]
public async Task TestMerge()
{
@@ -105,6 +105,6 @@ namespace Content.IntegrationTests.Tests.Atmos
});
await pair.CleanReturnAsync();
}*/
}
}
}

View File

@@ -8,7 +8,7 @@ namespace Content.IntegrationTests.Tests.Atmos;
[TestFixture]
public sealed class GridJoinTest
{/*
{
private const string CanisterProtoId = "AirCanister";
[Test]
@@ -49,5 +49,5 @@ public sealed class GridJoinTest
});
await pair.CleanReturnAsync();
}*/
}
}

View File

@@ -18,7 +18,7 @@ namespace Content.IntegrationTests.Tests;
[TestFixture]
public sealed class CargoTest
{/*
{
private static readonly HashSet<ProtoId<CargoProductPrototype>> Ignored =
[
// This is ignored because it is explicitly intended to be able to sell for more than it costs.
@@ -265,5 +265,5 @@ public sealed class CargoTest
});
await pair.CleanReturnAsync();
}*/
}
}

View File

@@ -32,9 +32,9 @@ namespace Content.IntegrationTests.Tests.Commands
// No bans on record
Assert.Multiple(async () =>
{
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null);
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null);
Assert.That(await sDatabase.GetServerBanAsync(1), Is.Null);
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Is.Empty);
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Is.Empty);
});
// Try to pardon a ban that does not exist
@@ -43,9 +43,9 @@ namespace Content.IntegrationTests.Tests.Commands
// Still no bans on record
Assert.Multiple(async () =>
{
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null);
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null);
Assert.That(await sDatabase.GetServerBanAsync(1), Is.Null);
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Is.Empty);
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Is.Empty);
});
var banReason = "test";
@@ -57,9 +57,9 @@ namespace Content.IntegrationTests.Tests.Commands
// Should have one ban on record now
Assert.Multiple(async () =>
{
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Not.Null);
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Not.Null);
Assert.That(await sDatabase.GetServerBanAsync(1), Is.Not.Null);
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1));
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1));
});
await pair.RunTicksSync(5);
@@ -70,13 +70,13 @@ namespace Content.IntegrationTests.Tests.Commands
await server.WaitPost(() => sConsole.ExecuteCommand("pardon 2"));
// The existing ban is unaffected
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Not.Null);
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Not.Null);
var ban = await sDatabase.GetServerBanAsync(1);
Assert.Multiple(async () =>
{
Assert.That(ban, Is.Not.Null);
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1));
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1));
// Check that it matches
Assert.That(ban.Id, Is.EqualTo(1));
@@ -95,7 +95,7 @@ namespace Content.IntegrationTests.Tests.Commands
await server.WaitPost(() => sConsole.ExecuteCommand("pardon 1"));
// No bans should be returned
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null);
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null);
// Direct id lookup returns a pardoned ban
var pardonedBan = await sDatabase.GetServerBanAsync(1);
@@ -105,7 +105,7 @@ namespace Content.IntegrationTests.Tests.Commands
Assert.That(pardonedBan, Is.Not.Null);
// The list is still returned since that ignores pardons
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1));
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1));
Assert.That(pardonedBan.Id, Is.EqualTo(1));
Assert.That(pardonedBan.UserId, Is.EqualTo(clientId));
@@ -133,13 +133,13 @@ namespace Content.IntegrationTests.Tests.Commands
Assert.Multiple(async () =>
{
// No bans should be returned
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null);
Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null);
// Direct id lookup returns a pardoned ban
Assert.That(await sDatabase.GetServerBanAsync(1), Is.Not.Null);
// The list is still returned since that ignores pardons
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1));
Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1));
});
// Reconnect client. Slightly faster than dirtying the pair.

View File

@@ -18,7 +18,7 @@ namespace Content.IntegrationTests.Tests.Disposal
[TestOf(typeof(DisposalEntryComponent))]
[TestOf(typeof(DisposalUnitComponent))]
public sealed class DisposalUnitTest
{/*
{
[Reflect(false)]
private sealed class DisposalUnitTestSystem : EntitySystem
{
@@ -242,6 +242,6 @@ namespace Content.IntegrationTests.Tests.Disposal
});
await pair.CleanReturnAsync();
}*/
}
}
}

View File

@@ -6,7 +6,7 @@ using Content.Shared.Wires;
namespace Content.IntegrationTests.Tests.EncryptionKeys;
public sealed class RemoveEncryptionKeys : InteractionTest
{/*
{
[Test]
public async Task HeadsetKeys()
{
@@ -108,5 +108,5 @@ public sealed class RemoveEncryptionKeys : InteractionTest
AssertPrototype("TelecomServerFilled");
await InteractUsing(Pry);
AssertPrototype("MachineFrame");
}*/
}
}

View File

@@ -8,7 +8,7 @@ namespace Content.IntegrationTests.Tests.Internals;
[TestFixture]
[TestOf(typeof(InternalsSystem))]
public sealed class AutoInternalsTests
{/*
{
[Test]
public async Task TestInternalsAutoActivateInSpaceForStationSpawn()
{
@@ -81,5 +81,5 @@ public sealed class AutoInternalsTests
components:
- type: Loadout
prototypes: [InternalsDummyGear]
";*/
";
}

Some files were not shown because too many files have changed in this diff Show More