mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
commit
7ee42055d0
1274 changed files with 19843 additions and 19283 deletions
|
|
@ -6,6 +6,9 @@ labels: autogenerated
|
|||
|
||||
A test failure has been detected on the main branch. This should never occur.
|
||||
|
||||
Commit under test: {{ env.GITHUB_SHA }}
|
||||
[Link to failing run]({{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }})
|
||||
|
||||
> [!NOTE]
|
||||
> This issue is automatically generated by a github action and will be updated when this failure reoccurs.
|
||||
> Do not edit the body of this issue.
|
||||
|
|
|
|||
6
.github/workflows/heisendetector.yml
vendored
6
.github/workflows/heisendetector.yml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- name: Checkout Master
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
|
|
@ -81,6 +81,10 @@ jobs:
|
|||
FULLNAME: ${{ matrix.value.fullname }}
|
||||
OUTPUT: ${{ matrix.value.output }}
|
||||
FAILURE: ${{ matrix.value.failure }}
|
||||
GITHUB_SERVER_URL: ${{ vars.GITHUB_SERVER_URL }}
|
||||
GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }}
|
||||
GITHUB_RUN_ID: ${{ vars.GITHUB_RUN_ID }}
|
||||
GITHUB_SHA: ${{ vars.GITHUB_SHA }}
|
||||
with:
|
||||
filename: .github/ISSUE_TEMPLATE/heisentest_template.md
|
||||
update_existing: true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Text;
|
||||
using Content.Client.Resources;
|
||||
using Content.Shared.Access.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Enums;
|
||||
|
|
@ -13,12 +14,12 @@ public sealed class AccessOverlay : Overlay
|
|||
private const int TextFontSize = 12;
|
||||
|
||||
private readonly IEntityManager _entityManager;
|
||||
private readonly SharedTransformSystem _transformSystem;
|
||||
private readonly TransformSystem _transformSystem;
|
||||
private readonly Font _font;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||
|
||||
public AccessOverlay(IEntityManager entityManager, IResourceCache resourceCache, SharedTransformSystem transformSystem)
|
||||
public AccessOverlay(IEntityManager entityManager, IResourceCache resourceCache, TransformSystem transformSystem)
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
_transformSystem = transformSystem;
|
||||
|
|
@ -87,7 +88,7 @@ public sealed class AccessOverlay : Overlay
|
|||
}
|
||||
|
||||
var accessInfoText = textBuffer.ToString();
|
||||
var screenPos = args.ViewportControl.WorldToScreen(_transformSystem.GetWorldPosition(transform));
|
||||
var screenPos = args.ViewportControl.WorldToScreen(_transformSystem.GetRenderWorldPosition((uid, transform)));
|
||||
args.ScreenHandle.DrawString(_font, screenPos, accessInfoText, 1, Color.Gold, TextOutline.Default);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Console;
|
||||
|
|
@ -8,7 +9,7 @@ public sealed partial class ShowAccessReadersCommand : LocalizedEntityCommands
|
|||
{
|
||||
[Dependency] private IOverlayManager _overlay = default!;
|
||||
[Dependency] private IResourceCache _cache = default!;
|
||||
[Dependency] private SharedTransformSystem _xform = default!;
|
||||
[Dependency] private TransformSystem _xform = default!;
|
||||
|
||||
public override string Command => "showaccessreaders";
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@ namespace Content.Client.Actions;
|
|||
|
||||
public sealed partial class ActionIconVisualsSystem : VisualizerSystem<ActionComponent>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override void OnAppearanceChange(EntityUid uid, ActionComponent comp, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (AppearanceSystem.TryGetData<SpriteSpecifier>(uid, ActionState.DynamicIcon, out var icon, args.Component))
|
||||
if (args.TryGetData<SpriteSpecifier>(ActionState.DynamicIcon, out var icon))
|
||||
{
|
||||
if (icon is SpriteSpecifier.EntityPrototype)
|
||||
SpriteSystem.LayerSetTexture((uid, args.Sprite), ActionVisuals.Icon, SpriteSystem.Frame0(icon));
|
||||
|
|
@ -20,7 +21,7 @@ public sealed partial class ActionIconVisualsSystem : VisualizerSystem<ActionCom
|
|||
SpriteSystem.LayerSetSprite((uid, args.Sprite), ActionVisuals.Icon, icon);
|
||||
}
|
||||
|
||||
if (AppearanceSystem.TryGetData<Color>(uid, ActionState.Color, out var color, args.Component))
|
||||
if (args.TryGetData<Color>(ActionState.Color, out var color))
|
||||
{
|
||||
SpriteSystem.LayerSetColor((uid, args.Sprite), ActionVisuals.Icon, color);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public sealed partial class AdminMessagePopupWindow : Control
|
|||
|
||||
public void SetState(AdminMessageEuiState state)
|
||||
{
|
||||
Timer = (float) state.Time.TotalSeconds;
|
||||
Timer = (float)state.Time.TotalSeconds;
|
||||
|
||||
MessageContainer.RemoveAllChildren();
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ public sealed partial class AdminMessagePopupWindow : Control
|
|||
}
|
||||
|
||||
Description.SetMessage(
|
||||
FormattedMessage.FromMarkup(Loc.GetString("admin-notes-message-desc", ("count", state.Messages.Length))));
|
||||
FormattedMessage.FromMarkupOrThrow(Loc.GetString("admin-notes-message-desc", ("count", state.Messages.Length))));
|
||||
}
|
||||
|
||||
private void OnDismissButtonPressed(BaseButton.ButtonEventArgs obj)
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ public sealed partial class ExplosionDebugOverlay : Overlay
|
|||
handle.SetTransform(SpaceMatrix);
|
||||
|
||||
DrawTiles(handle, gridBounds, SpaceTiles, SpaceTileSize);
|
||||
handle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
private void DrawTiles(
|
||||
|
|
|
|||
|
|
@ -8,23 +8,19 @@ namespace Content.Client.AlertLevel;
|
|||
public sealed partial class AlertLevelDisplaySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
[Dependency] private SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(EntityUid uid, AlertLevelDisplayComponent alertLevelDisplay, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var layer = _sprite.LayerMapReserve((uid, args.Sprite), AlertLevelDisplay.Layer);
|
||||
|
||||
if (_appearance.TryGetData<bool>(uid, AlertLevelDisplay.Powered, out var powered, component: args.Component))
|
||||
{
|
||||
if (args.TryGetData<bool>(AlertLevelDisplay.Powered, out var powered))
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), layer, powered);
|
||||
}
|
||||
|
||||
if (!_appearance.TryGetData<ProtoId<AlertLevelPrototype>>(uid, AlertLevelDisplay.CurrentLevel, out var level, component: args.Component))
|
||||
if (!args.TryGetData<ProtoId<AlertLevelPrototype>>(AlertLevelDisplay.CurrentLevel, out var level))
|
||||
{
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public sealed partial class AnomalyScannerSystem : SharedAnomalyScannerSystem
|
|||
|
||||
private void OnComponentInit(Entity<AnomalyScannerScreenComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
if(!_sprite.TryGetLayer(ent.Owner, AnomalyScannerVisualLayers.Base, out var layer, true))
|
||||
if (!_sprite.TryGetLayer(ent.Owner, AnomalyScannerVisualLayers.Base, out var layer, true))
|
||||
return;
|
||||
|
||||
// Allocate the OwnedTexture
|
||||
|
|
@ -70,9 +70,8 @@ public sealed partial class AnomalyScannerSystem : SharedAnomalyScannerSystem
|
|||
if (args.Sprite is null || ent.Comp.ScreenTexture is null || ent.Comp.BarBuf is null)
|
||||
return;
|
||||
|
||||
args.AppearanceData.TryGetValue(AnomalyScannerVisuals.AnomalySeverity, out var severityObj);
|
||||
if (severityObj is not float severity)
|
||||
severity = 0;
|
||||
if (!args.TryGetData<float>(AnomalyScannerVisuals.AnomalySeverity, out var severity))
|
||||
severity = 0.0f;
|
||||
|
||||
// Get the bar length
|
||||
var barLength = (int)(severity * ent.Comp.Size.X);
|
||||
|
|
@ -80,16 +79,16 @@ public sealed partial class AnomalyScannerSystem : SharedAnomalyScannerSystem
|
|||
// Calculate the bar color
|
||||
// Hue "angle" of two colors to interpolate between depending on severity
|
||||
// Just a lerp from Green hue at severity = 0.5 to Red hue at 1.0
|
||||
var hue = Math.Clamp(2*GreenHue * (1 - severity), RedHue, GreenHue);
|
||||
var hue = Math.Clamp(2 * GreenHue * (1 - severity), RedHue, GreenHue);
|
||||
var color = new Rgba32(Color.FromHsv(new Vector4(hue, 1f, 1f, 1f)).RGBA);
|
||||
|
||||
var transparent = new Rgba32(0, 0, 0, 255);
|
||||
|
||||
for(var y = 0; y < ent.Comp.Size.Y; y++)
|
||||
for (var y = 0; y < ent.Comp.Size.Y; y++)
|
||||
{
|
||||
for (var x = 0; x < ent.Comp.Size.X; x++)
|
||||
{
|
||||
ent.Comp.BarBuf[y*ent.Comp.Size.X + x] = x < barLength ? color : transparent;
|
||||
ent.Comp.BarBuf[y * ent.Comp.Size.X + x] = x < barLength ? color : transparent;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,10 +46,10 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
|
|||
if (args.Sprite is not { } sprite)
|
||||
return;
|
||||
|
||||
if (!Appearance.TryGetData<bool>(uid, AnomalyVisuals.IsPulsing, out var pulsing, args.Component))
|
||||
if (!args.TryGetData<bool>(AnomalyVisuals.IsPulsing, out var pulsing))
|
||||
pulsing = false;
|
||||
|
||||
if (Appearance.TryGetData<bool>(uid, AnomalyVisuals.Supercritical, out var super, args.Component) && super)
|
||||
if (args.TryGetData<bool>(AnomalyVisuals.Supercritical, out var super) && super)
|
||||
pulsing = super;
|
||||
|
||||
if (HasComp<AnomalySupercriticalComponent>(uid))
|
||||
|
|
|
|||
|
|
@ -75,13 +75,13 @@ public sealed partial class AtmosPipeAppearanceSystem : SharedAtmosPipeAppearanc
|
|||
|
||||
var numberOfPipeLayers = GetNumberOfPipeLayers(uid, out var atmosPipeLayers);
|
||||
|
||||
if (!_appearance.TryGetData<int>(uid, PipeVisuals.VisualState, out var worldConnectedDirections, args.Component))
|
||||
if (!args.TryGetData<int>(PipeVisuals.VisualState, out var worldConnectedDirections))
|
||||
{
|
||||
HideAllPipeConnection((uid, args.Sprite), atmosPipeLayers, numberOfPipeLayers);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_appearance.TryGetData<Color>(uid, PipeColorVisuals.Color, out var color, args.Component))
|
||||
if (!args.TryGetData<Color>(PipeColorVisuals.Color, out var color))
|
||||
color = Color.White;
|
||||
|
||||
for (byte i = 0; i < numberOfPipeLayers; i++)
|
||||
|
|
|
|||
|
|
@ -14,30 +14,23 @@ namespace Content.Client.Atmos.EntitySystems;
|
|||
/// </summary>
|
||||
public sealed partial class AtmosPipeLayersSystem : SharedAtmosPipeLayersSystem
|
||||
{
|
||||
[Dependency] private SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private IReflectionManager _reflection = default!;
|
||||
[Dependency] private IResourceCache _resourceCache = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<AtmosPipeLayersComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(Entity<AtmosPipeLayersComponent> ent, ref AppearanceChangeEvent ev)
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(Entity<AtmosPipeLayersComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
if (_appearance.TryGetData<string>(ent, AtmosPipeLayerVisuals.Sprite, out var spriteRsi) &&
|
||||
if (args.TryGetData<string>(AtmosPipeLayerVisuals.Sprite, out var spriteRsi) &&
|
||||
_resourceCache.TryGetResource(SpriteSpecifierSerializer.TextureRoot / spriteRsi, out RSIResource? resource))
|
||||
{
|
||||
_sprite.SetBaseRsi((ent, sprite), resource.RSI);
|
||||
}
|
||||
|
||||
if (_appearance.TryGetData<Dictionary<string, string>>(ent, AtmosPipeLayerVisuals.SpriteLayers, out var pipeState))
|
||||
if (args.TryGetData<Dictionary<string, string>>(AtmosPipeLayerVisuals.SpriteLayers, out var pipeState))
|
||||
{
|
||||
foreach (var (layerKey, rsiPath) in pipeState)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ using Robust.Client.GameObjects;
|
|||
namespace Content.Client.Atmos.EntitySystems;
|
||||
|
||||
/// <summary>
|
||||
/// Used to change the appearance of gas canisters.
|
||||
/// Used to change the appearance of gas canisters when painted.
|
||||
/// </summary>
|
||||
public sealed partial class GasCanisterAppearanceSystem : VisualizerSystem<GasCanisterComponent>
|
||||
{
|
||||
protected override void OnAppearanceChange(EntityUid uid, GasCanisterComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!AppearanceSystem.TryGetData<string>(uid, PaintableVisuals.Prototype, out var protoName, args.Component) || args.Sprite is not { } old)
|
||||
if (!args.TryGetData<string>(PaintableVisuals.Prototype, out var protoName) || args.Sprite is null)
|
||||
return;
|
||||
|
||||
if (!ProtoMan.HasIndex(protoName))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
using Content.Client.Atmos.Overlays;
|
||||
using Content.Shared.CCVar;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Client.Atmos.EntitySystems;
|
||||
|
||||
/// <summary>
|
||||
/// System responsible for rendering vacuum effects using <see cref="GasTileVacuumOverlay"/>.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed partial class GasTileVacuumOverlaySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private IOverlayManager _overlayMan = default!;
|
||||
[Dependency] private IConfigurationManager _cfgManager = default!;
|
||||
|
||||
private GasTileVacuumOverlay? _gasTileVacuumOverlay;
|
||||
private bool _vacuumOverlayEnabledDueToCvar; // due to CVar being enabled
|
||||
private bool _vacuumOverlayEnabledIntensity; // due to non zero intensity in setting
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_cfgManager.OnValueChanged(CCVars.VacuumOverlay, OnVacuumOverlayChanged, true);
|
||||
_cfgManager.OnValueChanged(CCVars.VacuumOverlayIntensity, OnVacuumOverlayIntensityChanged, true);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
_cfgManager.UnsubValueChanged(CCVars.VacuumOverlay, OnVacuumOverlayChanged);
|
||||
_cfgManager.UnsubValueChanged(CCVars.VacuumOverlayIntensity, OnVacuumOverlayIntensityChanged);
|
||||
_overlayMan.RemoveOverlay<GasTileVacuumOverlay>();
|
||||
}
|
||||
|
||||
private void OnVacuumOverlayChanged(bool enabled)
|
||||
{
|
||||
_vacuumOverlayEnabledDueToCvar = enabled;
|
||||
UpdateOverlay();
|
||||
}
|
||||
|
||||
private void OnVacuumOverlayIntensityChanged(float intensity)
|
||||
{
|
||||
_vacuumOverlayEnabledIntensity = intensity > 0f;
|
||||
UpdateOverlay();
|
||||
}
|
||||
|
||||
private void UpdateOverlay()
|
||||
{
|
||||
if (_vacuumOverlayEnabledDueToCvar && _vacuumOverlayEnabledIntensity)
|
||||
{
|
||||
_gasTileVacuumOverlay ??= new GasTileVacuumOverlay();
|
||||
|
||||
if (!_overlayMan.HasOverlay<GasTileVacuumOverlay>())
|
||||
_overlayMan.AddOverlay(_gasTileVacuumOverlay);
|
||||
}
|
||||
else
|
||||
{
|
||||
_overlayMan.RemoveOverlay<GasTileVacuumOverlay>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,13 +14,7 @@ public sealed partial class MaxPressureVisualsSystem : EntitySystem
|
|||
{
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<MaxPressureVisualsComponent, ComponentInit>(OnMaxPressureInit);
|
||||
SubscribeLocalEvent<MaxPressureVisualsComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnMaxPressureInit(Entity<MaxPressureVisualsComponent> entity, ref ComponentInit args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(entity, out var sprite))
|
||||
|
|
@ -28,28 +22,27 @@ public sealed partial class MaxPressureVisualsSystem : EntitySystem
|
|||
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(entity.Comp.IntegritySteps);
|
||||
|
||||
if (_sprite.LayerMapTryGet((entity, sprite), MaxPressureVisualLayers.Base, out _, false))
|
||||
if (_sprite.LayerMapTryGet((entity, sprite), MaxPressureVisualLayers.Base, out var layerIndex, false))
|
||||
{
|
||||
_sprite.LayerSetRsiState((entity, sprite), MaxPressureVisualLayers.Base, $"{entity.Comp.IntegrityMask}");
|
||||
_sprite.LayerSetVisible((entity, sprite), MaxPressureVisualLayers.Base, false);
|
||||
_sprite.LayerSetRsiState((entity, sprite), layerIndex, $"{entity.Comp.IntegrityMask}");
|
||||
_sprite.LayerSetVisible((entity, sprite), layerIndex, false);
|
||||
}
|
||||
|
||||
if (_sprite.LayerMapTryGet((entity, sprite), MaxPressureVisualLayers.BaseUnshaded, out _, false))
|
||||
if (_sprite.LayerMapTryGet((entity, sprite), MaxPressureVisualLayers.BaseUnshaded, out layerIndex, false))
|
||||
{
|
||||
_sprite.LayerSetRsiState((entity, sprite), MaxPressureVisualLayers.BaseUnshaded, $"{entity.Comp.IntegrityState}-unshaded-0");
|
||||
_sprite.LayerSetVisible((entity, sprite), MaxPressureVisualLayers.BaseUnshaded, false);
|
||||
_sprite.LayerSetRsiState((entity, sprite), layerIndex, $"{entity.Comp.IntegrityState}-unshaded-0");
|
||||
_sprite.LayerSetVisible((entity, sprite), layerIndex, false);
|
||||
}
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(Entity<MaxPressureVisualsComponent> entity, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite is not { } sprite)
|
||||
return;
|
||||
|
||||
if (!args.AppearanceData.TryGetValue(GasIntegrity.Integrity, out var obj) || obj is not float integrity)
|
||||
return;
|
||||
|
||||
if (!args.AppearanceData.TryGetValue(GasIntegrity.MaxIntegrity, out obj) || obj is not float maxIntegrity)
|
||||
if (!args.TryGetData<float>(GasIntegrity.Integrity, out var integrity)
|
||||
|| !args.TryGetData<float>(GasIntegrity.MaxIntegrity, out var maxIntegrity))
|
||||
return;
|
||||
|
||||
// We don't want visuals at max integrity, so we return if we're at max.
|
||||
|
|
|
|||
|
|
@ -8,13 +8,15 @@ public sealed partial class PipeColorVisualizerSystem : VisualizerSystem<PipeCol
|
|||
{
|
||||
protected override void OnAppearanceChange(EntityUid uid, PipeColorVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (TryComp<SpriteComponent>(uid, out var sprite)
|
||||
&& AppearanceSystem.TryGetData<Color>(uid, PipeColorVisuals.Color, out var color, args.Component))
|
||||
{
|
||||
// T-ray scanner / sub floor runs after this visualizer. Lets not bulldoze transparency.
|
||||
var layer = sprite[PipeVisualLayers.Pipe];
|
||||
layer.Color = color.WithAlpha(layer.Color.A);
|
||||
}
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!args.TryGetData<Color>(PipeColorVisuals.Color, out var color))
|
||||
return;
|
||||
|
||||
// T-ray scanner / sub floor runs after this visualizer. Lets not bulldoze transparency.
|
||||
var layer = args.Sprite[PipeVisualLayers.Pipe];
|
||||
layer.Color = color.WithAlpha(layer.Color.A);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,8 @@ public sealed partial class AtmosAlarmableVisualsSystem : VisualizerSystem<Atmos
|
|||
if (args.Sprite == null || !SpriteSystem.LayerMapTryGet((uid, args.Sprite), component.LayerMap, out var layer, false))
|
||||
return;
|
||||
|
||||
if (!args.AppearanceData.TryGetValue(PowerDeviceVisuals.Powered, out var poweredObject) ||
|
||||
poweredObject is not bool powered)
|
||||
{
|
||||
if (!args.TryGetData<bool>(PowerDeviceVisuals.Powered, out var powered))
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.HideOnDepowered != null)
|
||||
{
|
||||
|
|
@ -36,8 +33,7 @@ public sealed partial class AtmosAlarmableVisualsSystem : VisualizerSystem<Atmos
|
|||
}
|
||||
}
|
||||
|
||||
if (args.AppearanceData.TryGetValue(AtmosMonitorVisuals.AlarmType, out var alarmTypeObject)
|
||||
&& alarmTypeObject is AtmosAlarmType alarmType
|
||||
if (args.TryGetData<AtmosAlarmType>(AtmosMonitorVisuals.AlarmType, out var alarmType)
|
||||
&& powered
|
||||
&& component.AlarmStates.TryGetValue(alarmType, out var state))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,8 +65,6 @@ public sealed partial class AtmosDebugOverlay : Overlay
|
|||
handle.SetTransform(_transform.GetWorldMatrix(grid));
|
||||
DrawData(msg, handle);
|
||||
}
|
||||
|
||||
handle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
private void DrawData(DebugMessage msg,
|
||||
|
|
|
|||
|
|
@ -222,8 +222,6 @@ public sealed partial class GasTileDangerousTemperatureOverlay : Overlay
|
|||
},
|
||||
new Color(0, 0, 0, 0));
|
||||
|
||||
drawHandle.SetTransform(Matrix3x2.Identity);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +231,6 @@ public sealed partial class GasTileDangerousTemperatureOverlay : Overlay
|
|||
|
||||
if (res.TemperatureTarget != null)
|
||||
args.WorldHandle.DrawTextureRect(res.TemperatureTarget.Texture, args.WorldBounds);
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
|
|
|
|||
|
|
@ -164,8 +164,5 @@ public sealed partial class GasTileFireOverlay : Overlay
|
|||
|
||||
return true;
|
||||
});
|
||||
|
||||
drawHandle.UseShader(null);
|
||||
drawHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,8 +198,6 @@ public sealed partial class GasTileHeatBlurOverlay : Overlay
|
|||
// no distortion, no need to render
|
||||
if (!anyDistortion)
|
||||
{
|
||||
args.WorldHandle.UseShader(null);
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -218,9 +216,6 @@ public sealed partial class GasTileHeatBlurOverlay : Overlay
|
|||
|
||||
args.WorldHandle.UseShader(_shader);
|
||||
args.WorldHandle.DrawTextureRect(res.HeatTarget.Texture, args.WorldBounds);
|
||||
|
||||
args.WorldHandle.UseShader(null);
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
|
|
|
|||
196
Content.Client/Atmos/Overlays/GasTileVacuumOverlay.cs
Normal file
196
Content.Client/Atmos/Overlays/GasTileVacuumOverlay.cs
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Atmos.EntitySystems;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Color = Robust.Shared.Maths.Color;
|
||||
|
||||
namespace Content.Client.Atmos.Overlays;
|
||||
|
||||
/// <summary>
|
||||
/// Overlay responsible for rendering vacuum overlay.
|
||||
/// </summary>
|
||||
public sealed partial class GasTileVacuumOverlay : Overlay
|
||||
{
|
||||
public override bool RequestScreenTexture { get; set; } = true;
|
||||
private static readonly ProtoId<ShaderPrototype> UnshadedShader = "unshaded";
|
||||
private static readonly ProtoId<ShaderPrototype> VacuumOverlayShader = "VacuumDesaturation";
|
||||
private static readonly Color EmptyColor = new(0, 0, 0, 0);
|
||||
private static readonly Color MarkerColor = new(255f, 0, 0);
|
||||
|
||||
[Dependency] private IEntityManager _entManager = default!;
|
||||
[Dependency] private IPrototypeManager _proto = default!;
|
||||
[Dependency] private IClyde _clyde = default!;
|
||||
[Dependency] private IConfigurationManager _configManager = default!;
|
||||
|
||||
private readonly SharedMapSystem _maps;
|
||||
private readonly SharedTransformSystem _xformSys;
|
||||
private readonly ShaderInstance _unshader;
|
||||
private readonly ShaderInstance _shader;
|
||||
|
||||
private List<Entity<MapGridComponent>> _intersectingGrids = new();
|
||||
private readonly OverlayResourceCache<CachedResources> _resources = new();
|
||||
|
||||
// Overlay settings
|
||||
private float _intensity; // overlay intensity. 0.0f = turned off, 1.0f = full grayscale
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
public GasTileVacuumOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_maps = _entManager.System<SharedMapSystem>();
|
||||
_xformSys = _entManager.System<SharedTransformSystem>();
|
||||
|
||||
_unshader = _proto.Index(UnshadedShader).Instance();
|
||||
_shader = _proto.Index(VacuumOverlayShader).InstanceUnique();
|
||||
_configManager.OnValueChanged(CCVars.VacuumOverlayIntensity, SetVacuumOverlayIntensity, invokeImmediately: true);
|
||||
}
|
||||
|
||||
private void SetVacuumOverlayIntensity(float intensity)
|
||||
{
|
||||
_intensity = MathHelper.Clamp(intensity, 0f, 1f);
|
||||
_shader.SetParameter("intensity", _intensity);
|
||||
}
|
||||
|
||||
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (args.MapId == MapId.Nullspace)
|
||||
return false;
|
||||
|
||||
var res = _resources.GetForViewport(args.Viewport, static _ => new CachedResources());
|
||||
|
||||
var target = args.Viewport.RenderTarget;
|
||||
|
||||
// Probably the resolution of the game window changed, remake the textures.
|
||||
if (res.VacuumTarget?.Texture.Size != target.Size)
|
||||
{
|
||||
res.VacuumTarget?.Dispose();
|
||||
res.VacuumTarget = _clyde.CreateRenderTarget(
|
||||
target.Size,
|
||||
new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb),
|
||||
name: $"{nameof(GasTileVacuumOverlay)}-blur");
|
||||
}
|
||||
|
||||
var overlayQuery = _entManager.GetEntityQuery<GasTileOverlayComponent>();
|
||||
|
||||
args.WorldHandle.UseShader(_unshader);
|
||||
|
||||
var mapId = args.MapId;
|
||||
var worldAABB = args.WorldAABB;
|
||||
var worldBounds = args.WorldBounds;
|
||||
var worldHandle = args.WorldHandle;
|
||||
var worldToViewportLocal = args.Viewport.GetWorldToLocalMatrix();
|
||||
|
||||
// If there is no Vacuum after checking all visible tiles, we can bail early
|
||||
var anyVacuum = false;
|
||||
|
||||
// We're rendering in the context of the vacuum target texture, which will encode data as to where vacuum effect will be
|
||||
args.WorldHandle.RenderInRenderTarget(res.VacuumTarget,
|
||||
() =>
|
||||
{
|
||||
_intersectingGrids.Clear();
|
||||
_maps.FindGridsIntersecting(mapId, worldAABB, ref _intersectingGrids);
|
||||
foreach (var grid in _intersectingGrids)
|
||||
{
|
||||
if (!overlayQuery.TryGetComponent(grid.Owner, out var comp))
|
||||
continue;
|
||||
|
||||
var (_, _, gridEntToWorld, worldToGridLocal) = _xformSys.GetWorldPositionRotationMatrixWithInv(grid.Owner);
|
||||
var gridEntToViewportLocal = gridEntToWorld * worldToViewportLocal;
|
||||
|
||||
if (!Matrix3x2.Invert(gridEntToViewportLocal, out _))
|
||||
continue;
|
||||
|
||||
// Draw commands (like DrawRect) will be using grid coordinates from here
|
||||
worldHandle.SetTransform(gridEntToViewportLocal);
|
||||
|
||||
// We only care about tiles that fit in these bounds
|
||||
var floatBounds = worldToGridLocal.TransformBox(worldBounds).Enlarged(grid.Comp.TileSize);
|
||||
|
||||
var localBounds = new Box2i(
|
||||
(int)MathF.Floor(floatBounds.Left),
|
||||
(int)MathF.Floor(floatBounds.Bottom),
|
||||
(int)MathF.Ceiling(floatBounds.Right),
|
||||
(int)MathF.Ceiling(floatBounds.Top));
|
||||
|
||||
// for each tile and its gas --->
|
||||
foreach (var chunk in comp.Chunks.Values)
|
||||
{
|
||||
var enumerator = new GasChunkEnumerator(chunk);
|
||||
|
||||
while (enumerator.MoveNext(out var tileGas))
|
||||
{
|
||||
// Check and make sure the tile is within the viewport/screen
|
||||
var tilePosition = chunk.Origin + (enumerator.X, enumerator.Y);
|
||||
if (!localBounds.Contains(tilePosition))
|
||||
continue;
|
||||
|
||||
if (tileGas.ByteGasTemperature.Value != ThermalByte.StateVacuum)
|
||||
continue;
|
||||
|
||||
// Encode the strength in the red channel
|
||||
// alpha set to 1 as tile is active
|
||||
worldHandle.DrawRect(Box2.CenteredAround(tilePosition + grid.Comp.TileSizeHalfVector,
|
||||
grid.Comp.TileSizeVector),
|
||||
MarkerColor);
|
||||
anyVacuum = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// This clears the buffer to all zero first...
|
||||
EmptyColor);
|
||||
|
||||
// no distortion, no need to render
|
||||
if (!anyVacuum)
|
||||
{
|
||||
args.WorldHandle.UseShader(null);
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var res = _resources.GetForViewport(args.Viewport, static _ => new CachedResources());
|
||||
|
||||
if (ScreenTexture is null || res.VacuumTarget is null)
|
||||
return;
|
||||
|
||||
_shader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
|
||||
|
||||
args.WorldHandle.UseShader(_shader);
|
||||
args.WorldHandle.DrawTextureRect(res.VacuumTarget.Texture, args.WorldBounds);
|
||||
|
||||
args.WorldHandle.UseShader(null);
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
{
|
||||
_resources.Dispose();
|
||||
|
||||
_configManager.UnsubValueChanged(CCVars.VacuumOverlayIntensity, SetVacuumOverlayIntensity);
|
||||
base.DisposeBehavior();
|
||||
}
|
||||
|
||||
internal sealed class CachedResources : IDisposable
|
||||
{
|
||||
public IRenderTexture? VacuumTarget;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
VacuumTarget?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -204,9 +204,6 @@ public sealed partial class GasTileVisibleGasOverlay : Overlay
|
|||
|
||||
return true;
|
||||
});
|
||||
|
||||
drawHandle.UseShader(null);
|
||||
drawHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
private void DrawMapOverlay(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="270 420"
|
||||
SetSize="360 420" Title="{Loc 'gas-analyzer-window-name'}">
|
||||
<BoxContainer Orientation="Vertical" Margin="5 5 5 5">
|
||||
<BoxContainer Orientation="Vertical" Margin="10">
|
||||
<BoxContainer Name="CTopBox" Orientation="Horizontal"/>
|
||||
<!-- Gas Mix Data, Populated by function -->
|
||||
<TabContainer Name="CTabContainer" VerticalExpand="True" Margin="1 1 1 2">
|
||||
|
|
@ -43,4 +44,4 @@
|
|||
</ScrollContainer>
|
||||
</TabContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
</controls:FancyWindow>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ using Direction = Robust.Shared.Maths.Direction;
|
|||
namespace Content.Client.Atmos.UI
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GasAnalyzerWindow : DefaultWindow
|
||||
public sealed partial class GasAnalyzerWindow : FancyWindow
|
||||
{
|
||||
private readonly SharedAtmosphereSystem _atmosphere;
|
||||
private NetEntity _currentEntity = NetEntity.Invalid;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:Content.Client.Stylesheets"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="480 400" Title="Canister">
|
||||
<BoxContainer Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
<BoxContainer Orientation="Vertical" Margin="10" SeparationOverride="10">
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||
<Label Text="{Loc comp-gas-canister-ui-canister-status}" StyleClasses="LabelHeading"/>
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
|
|
@ -49,4 +50,4 @@
|
|||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
</controls:FancyWindow>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
|
@ -13,7 +14,7 @@ namespace Content.Client.Atmos.UI
|
|||
/// Client-side UI used to control a canister.
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GasCanisterWindow : DefaultWindow
|
||||
public sealed partial class GasCanisterWindow : FancyWindow
|
||||
{
|
||||
private readonly ButtonGroup _buttonGroup = new();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="480 400" Title="Filter">
|
||||
<BoxContainer Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
<BoxContainer Orientation="Vertical" Margin="10" SeparationOverride="10">
|
||||
<controls:SwitchButton
|
||||
Name="ToggleStatusButton"
|
||||
HorizontalAlignment="Left"
|
||||
|
|
@ -25,4 +25,4 @@
|
|||
<Button Name="SelectGasButton" Text="{Loc comp-gas-filter-ui-filter-gas-confirm}" HorizontalExpand="True" Disabled="True" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
</controls:FancyWindow>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Atmos.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
|
@ -14,7 +15,7 @@ namespace Content.Client.Atmos.UI
|
|||
/// Client-side UI used to control a gas filter.
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GasFilterWindow : DefaultWindow
|
||||
public sealed partial class GasFilterWindow : FancyWindow
|
||||
{
|
||||
private readonly ButtonGroup _buttonGroup = new();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="200 200" Title="Gas Mixer">
|
||||
<BoxContainer Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
Resizable="False" Title="Gas Mixer">
|
||||
<BoxContainer Orientation="Vertical" Margin="10" SeparationOverride="10">
|
||||
<controls:SwitchButton
|
||||
Name="ToggleStatusButton"
|
||||
HorizontalAlignment="Left"
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<Label Text="{Loc comp-gas-mixer-ui-mixer-output-pressure}"/>
|
||||
<Control MinSize="5 0" />
|
||||
<LineEdit Name="MixerPressureOutputInput" MinSize="70 0" />
|
||||
<LineEdit Name="MixerPressureOutputInput" MinSize="80 0" />
|
||||
<Control MinSize="5 0" />
|
||||
<Button Name="SetMaxPressureButton" Text="{Loc comp-gas-mixer-ui-mixer-max}" />
|
||||
<Control MinSize="5 0" />
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<Control MinSize="0 5" />
|
||||
<Label Text="{Loc comp-gas-mixer-ui-mixer-node-primary}"/>
|
||||
<Label Text="{Loc comp-gas-mixer-ui-mixer-node-back}"/>
|
||||
<Control MinSize="5 0" />
|
||||
<LineEdit Name="MixerNodeOneInput" MinSize="60 0" />
|
||||
<Label Text=" %"/>
|
||||
|
|
@ -34,4 +34,4 @@
|
|||
<Button Name="SetMixerPercentageButton" Text="{Loc comp-gas-mixer-ui-mixer-set}" HorizontalAlignment="Right" Disabled="True"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
</controls:FancyWindow>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Content.Client.Atmos.EntitySystems;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
|
|
@ -19,7 +20,7 @@ namespace Content.Client.Atmos.UI
|
|||
/// Client-side UI used to control a gas mixer.
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GasMixerWindow : DefaultWindow
|
||||
public sealed partial class GasMixerWindow : FancyWindow
|
||||
{
|
||||
public event Action<bool>? ToggleStatusButtonPressed;
|
||||
public event Action<string>? MixerOutputPressureChanged;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
SetSize="340 110" MinSize="340 110" Title="Pressure Pump">
|
||||
<BoxContainer Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
MinSize="50 50" Resizable="False" Title="Pressure Pump">
|
||||
<BoxContainer Orientation="Vertical" Margin="10" SeparationOverride="10">
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<controls:SwitchButton
|
||||
Name="ToggleStatusButton"
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<Label Text="{Loc comp-gas-pump-ui-pump-output-pressure}"/>
|
||||
<FloatSpinBox HorizontalExpand="True" Name="PumpPressureOutputInput" MinSize="70 0" />
|
||||
<FloatSpinBox HorizontalExpand="True" Name="PumpPressureOutputInput" MinSize="155 0" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="300 120" Title="{Loc comp-gas-thermomachine-ui-title-freezer}">
|
||||
<BoxContainer Name="VboxContainer" Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
<BoxContainer Name="VboxContainer" Orientation="Vertical" Margin="10" SeparationOverride="10">
|
||||
<controls:SwitchButton
|
||||
Name="ToggleStatusButton"
|
||||
HorizontalAlignment="Left"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="200 120" Title="Volume Pump">
|
||||
<BoxContainer Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
MinSize="50 50" Resizable="False" Title="Volume Pump">
|
||||
<BoxContainer Orientation="Vertical" Margin="10" SeparationOverride="10">
|
||||
<controls:SwitchButton
|
||||
Name="ToggleStatusButton"
|
||||
HorizontalAlignment="Left"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="280 160" Title="{Loc comp-space-heater-ui-title}">
|
||||
MinSize="50 50" Resizable="False" Title="{Loc comp-space-heater-ui-title}">
|
||||
|
||||
<BoxContainer Name="VboxContainer" Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
<BoxContainer Name="VboxContainer" Orientation="Vertical" Margin="10" SeparationOverride="10">
|
||||
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<controls:SwitchButton
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" HorizontalAlignment="Right">
|
||||
<Button Text="{Loc comp-space-heater-ui-decrease-temperature-range}" Access="Public" Name="DecreaseTempRange" StyleClasses="OpenRight"/>
|
||||
<LineEdit Name ="Thermostat" MinSize="55 0"></LineEdit>
|
||||
<LineEdit Name ="Thermostat" MinSize="55 0" CanKeyboardFocus="False"></LineEdit>
|
||||
<Button Text="{Loc comp-space-heater-ui-increase-temperature-range}" Access="Public" Name="IncreaseTempRange" StyleClasses="OpenLeft"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
|
@ -33,4 +33,4 @@
|
|||
</BoxContainer>
|
||||
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
</controls:FancyWindow>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
|
|
@ -11,7 +12,7 @@ namespace Content.Client.Atmos.UI;
|
|||
/// Client-side UI used to control a space heater.
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class SpaceHeaterWindow : DefaultWindow
|
||||
public sealed partial class SpaceHeaterWindow : FancyWindow
|
||||
{
|
||||
// To account for a minimum delta temperature for atmos equalization to trigger we use a fixed step for target temperature increment/decrement
|
||||
public int TemperatureChangeDelta = 5;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ public sealed partial class PortableScrubberSystem : VisualizerSystem<PortableSc
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsFull, out var isFull, args.Component)
|
||||
&& AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsRunning, out var isRunning, args.Component))
|
||||
if (args.TryGetData<bool>(PortableScrubberVisuals.IsFull, out var isFull)
|
||||
&& args.TryGetData<bool>(PortableScrubberVisuals.IsRunning, out var isRunning))
|
||||
{
|
||||
var runningState = isRunning ? component.RunningState : component.IdleState;
|
||||
SpriteSystem.LayerSetRsiState((uid, args.Sprite), PortableScrubberVisualLayers.IsRunning, runningState);
|
||||
|
|
@ -24,7 +24,7 @@ public sealed partial class PortableScrubberSystem : VisualizerSystem<PortableSc
|
|||
SpriteSystem.LayerSetRsiState((uid, args.Sprite), PowerDeviceVisualLayers.Powered, fullState);
|
||||
}
|
||||
|
||||
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsDraining, out var isDraining, args.Component))
|
||||
if (args.TryGetData<bool>(PortableScrubberVisuals.IsDraining, out var isDraining))
|
||||
{
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), PortableScrubberVisualLayers.IsDraining, isDraining);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,11 +72,8 @@ public sealed partial class JukeboxSystem : SharedJukeboxSystem
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!args.AppearanceData.TryGetValue(JukeboxVisuals.VisualState, out var visualStateObject) ||
|
||||
visualStateObject is not JukeboxVisualState visualState)
|
||||
{
|
||||
if (!args.TryGetData<JukeboxVisualState>(JukeboxVisuals.VisualState, out var visualState))
|
||||
visualState = JukeboxVisualState.On;
|
||||
}
|
||||
|
||||
UpdateAppearance((uid, args.Sprite), visualState, component);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ public sealed partial class BarSignVisualizerSystem : VisualizerSystem<BarSignCo
|
|||
{
|
||||
protected override void OnAppearanceChange(EntityUid uid, BarSignComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
AppearanceSystem.TryGetData<bool>(uid, PowerDeviceVisuals.Powered, out var powered, args.Component);
|
||||
AppearanceSystem.TryGetData<string>(uid, BarSignVisuals.BarSignPrototype, out var currentSign, args.Component);
|
||||
args.TryGetData<bool>(PowerDeviceVisuals.Powered, out var powered);
|
||||
args.TryGetData<string>(BarSignVisuals.BarSignPrototype, out var currentSign);
|
||||
|
||||
if (powered
|
||||
&& currentSign != null
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ public sealed partial class PotencyVisualsSystem : VisualizerSystem<PotencyVisua
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (AppearanceSystem.TryGetData<float>(uid, ProduceVisuals.Potency, out var potency, args.Component))
|
||||
{
|
||||
var potencyRatio = Math.Clamp(potency / 100f, 0f, 1f);
|
||||
var scale = MathHelper.Lerp(component.MinimumScale, component.MaximumScale, potencyRatio);
|
||||
SpriteSystem.SetScale((uid, args.Sprite), new Vector2(scale, scale));
|
||||
}
|
||||
if (!args.TryGetData<float>(ProduceVisuals.Potency, out var potency))
|
||||
return;
|
||||
|
||||
var potencyRatio = Math.Clamp(potency / 100f, 0f, 1f);
|
||||
var scale = MathHelper.Lerp(component.MinimumScale, component.MaximumScale, potencyRatio);
|
||||
SpriteSystem.SetScale((uid, args.Sprite), new Vector2(scale, scale));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,13 +12,22 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
|
|||
{
|
||||
[Dependency] private RotationVisualizerSystem _rotationVisualizerSystem = default!;
|
||||
[Dependency] private IEyeManager _eye = default!;
|
||||
[Dependency] private SharedTransformSystem _xformSystem = default!;
|
||||
[Dependency] private TransformSystem _xformSystem = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
[Dependency] private EntityQuery<SpriteComponent> _spriteQuery = default!;
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
protected override void AfterBuckleParentChanged(Entity<BuckleComponent> ent, ref EntParentChangedMessage args)
|
||||
{
|
||||
if (HasComp<StrapComponent>(args.Transform.ParentUid) ||
|
||||
args.OldParent is { } oldParent && HasComp<StrapComponent>(oldParent))
|
||||
{
|
||||
_xformSystem.SnapRenderTransformAfterParentChange(ent, true);
|
||||
}
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnStrapMoveEvent(Entity<StrapComponent> ent, ref MoveEvent args)
|
||||
{
|
||||
|
|
@ -90,6 +99,8 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
|
|||
[SubscribeLocalEvent]
|
||||
private void OnBuckledEvent(Entity<BuckleComponent> ent, ref BuckledEvent args)
|
||||
{
|
||||
_xformSystem.SnapRenderTransform(ent, true);
|
||||
|
||||
if (!args.Strap.Comp.ModifyBuckleDrawDepth)
|
||||
return;
|
||||
|
||||
|
|
@ -114,6 +125,8 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
|
|||
[SubscribeLocalEvent]
|
||||
private void OnUnbuckledEvent(Entity<BuckleComponent> ent, ref UnbuckledEvent args)
|
||||
{
|
||||
_xformSystem.SnapRenderTransform(ent, true);
|
||||
|
||||
if (!args.Strap.Comp.ModifyBuckleDrawDepth)
|
||||
return;
|
||||
|
||||
|
|
@ -133,7 +146,7 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
|
|||
if (!TryComp<RotationVisualsComponent>(ent, out var rotVisuals))
|
||||
return;
|
||||
|
||||
if (!Appearance.TryGetData<bool>(ent, BuckleVisuals.Buckled, out var buckled, args.Component) ||
|
||||
if (!args.TryGetData<bool>(BuckleVisuals.Buckled, out var buckled) ||
|
||||
!buckled ||
|
||||
args.Sprite == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ public sealed partial class TypingIndicatorVisualizerSystem : VisualizerSystem<T
|
|||
args.Sprite.LayerSetShader(layer, proto.Shader);
|
||||
SpriteSystem.LayerSetOffset((uid, args.Sprite), layer, proto.Offset);
|
||||
|
||||
AppearanceSystem.TryGetData<TypingIndicatorState>(uid, TypingIndicatorVisuals.State, out var state);
|
||||
args.TryGetData<TypingIndicatorState>(TypingIndicatorVisuals.State, out var state);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), layer, state != TypingIndicatorState.None);
|
||||
switch (state)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using Content.Shared.CCVar;
|
|||
using Content.Shared.Chat;
|
||||
using Content.Shared.Speech;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Configuration;
|
||||
|
|
@ -18,7 +19,7 @@ namespace Content.Client.Chat.UI
|
|||
[Dependency] private IEyeManager _eyeManager = default!;
|
||||
[Dependency] private IEntityManager _entityManager = default!;
|
||||
[Dependency] protected IConfigurationManager ConfigManager = default!;
|
||||
private readonly SharedTransformSystem _transformSystem;
|
||||
private readonly TransformSystem _transformSystem;
|
||||
|
||||
public enum SpeechType : byte
|
||||
{
|
||||
|
|
@ -89,7 +90,7 @@ namespace Content.Client.Chat.UI
|
|||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_senderEntity = senderEntity;
|
||||
_transformSystem = _entityManager.System<SharedTransformSystem>();
|
||||
_transformSystem = _entityManager.System<TransformSystem>();
|
||||
|
||||
// Use text clipping so new messages don't overlap old ones being pushed up.
|
||||
RectClipContent = true;
|
||||
|
|
@ -153,7 +154,7 @@ namespace Content.Client.Chat.UI
|
|||
baseOffset = speech.SpeechBubbleOffset;
|
||||
|
||||
var offset = (-_eyeManager.CurrentEye.Rotation).ToWorldVec() * -(EntityVerticalOffset + baseOffset);
|
||||
var worldPos = _transformSystem.GetWorldPosition(xform) + offset;
|
||||
var worldPos = _transformSystem.GetRenderWorldPosition((_senderEntity, xform)) + offset;
|
||||
|
||||
var lowerCenter = _eyeManager.WorldToScreen(worldPos) / UIScale;
|
||||
var screenPos = lowerCenter - new Vector2(ContentSize.X / 2, ContentSize.Y + _verticalOffsetAchieved);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public sealed partial class SmokeVisualizerSystem : VisualizerSystem<SmokeVisual
|
|||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
if (!AppearanceSystem.TryGetData<Color>(uid, SmokeVisuals.Color, out var color))
|
||||
if (!args.TryGetData<Color>(SmokeVisuals.Color, out var color))
|
||||
return;
|
||||
SpriteSystem.SetColor((uid, args.Sprite), color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,14 +35,11 @@ public sealed partial class SolutionContainerVisualsSystem : VisualizerSystem<So
|
|||
|
||||
// Check if the solution that was updated is the one set as represented
|
||||
if (!string.IsNullOrEmpty(component.SolutionName)
|
||||
&& AppearanceSystem.TryGetData(uid, SolutionContainerVisuals.SolutionName, out string name, args.Component)
|
||||
&& args.TryGetData<string>(SolutionContainerVisuals.SolutionName, out var name)
|
||||
&& name != component.SolutionName)
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData(uid,
|
||||
SolutionContainerVisuals.FillFraction,
|
||||
out float fraction,
|
||||
args.Component))
|
||||
if (!args.TryGetData<float>(SolutionContainerVisuals.FillFraction, out var fraction))
|
||||
return;
|
||||
|
||||
// C# moment; setting it as nullable (even though it's not) avoids a
|
||||
|
|
@ -100,8 +97,7 @@ public sealed partial class SolutionContainerVisualsSystem : VisualizerSystem<So
|
|||
|
||||
SpriteSystem.LayerSetRsiState(ent, fillLayer, fillBaseName + closestFillSprite);
|
||||
|
||||
if (changeColor
|
||||
&& AppearanceSystem.TryGetData(uid, SolutionContainerVisuals.Color, out Color color, args.Component))
|
||||
if (changeColor && args.TryGetData<Color>(SolutionContainerVisuals.Color, out var color))
|
||||
SpriteSystem.LayerSetColor(ent, fillLayer, color);
|
||||
else
|
||||
SpriteSystem.LayerSetColor(ent, fillLayer, Color.White);
|
||||
|
|
@ -127,10 +123,7 @@ public sealed partial class SolutionContainerVisualsSystem : VisualizerSystem<So
|
|||
Entity<SpriteComponent?> ent,
|
||||
int fillLayer)
|
||||
{
|
||||
if (!AppearanceSystem.TryGetData(uid,
|
||||
SolutionContainerVisuals.BaseOverride,
|
||||
out string baseOverride,
|
||||
args.Component))
|
||||
if (!args.TryGetData<string>(SolutionContainerVisuals.BaseOverride, out var baseOverride))
|
||||
return null;
|
||||
|
||||
var reagentProto = ProtoMan.Index<ReagentPrototype>(baseOverride);
|
||||
|
|
|
|||
|
|
@ -50,10 +50,8 @@ public sealed partial class VaporVisualizerSystem : VisualizerSystem<VaporVisual
|
|||
/// </summary>
|
||||
protected override void OnAppearanceChange(EntityUid uid, VaporVisualsComponent comp, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (AppearanceSystem.TryGetData<Color>(uid, VaporVisuals.Color, out var color, args.Component) && args.Sprite != null)
|
||||
{
|
||||
if (args.Sprite != null && args.TryGetData<Color>(VaporVisuals.Color, out var color))
|
||||
SpriteSystem.SetColor((uid, args.Sprite), color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
using Content.Client.Clothing.Systems;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
|
|
@ -54,7 +52,8 @@ public sealed partial class ChameleonBoundUserInterface : BoundUserInterface
|
|||
newTargets.Add(target);
|
||||
}
|
||||
_menu?.UpdateState(newTargets, st.SelectedId);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
_menu?.UpdateState(targets, st.SelectedId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ namespace Content.Client.CombatMode
|
|||
worldHandle.UseShader(_shader);
|
||||
var viewport = args.WorldAABB;
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
worldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,13 @@ public sealed partial class CommunicationsConsoleBoundUserInterface(EntityUid ow
|
|||
[Dependency] private StationSystem _station = default!;
|
||||
[Dependency] private AlertLevelSystem _alertLevel = default!;
|
||||
|
||||
[Dependency] private EntityQuery<AlertLevelComponent> _alertLevelQuery;
|
||||
|
||||
[ViewVariables]
|
||||
private CommunicationsConsoleMenu? _menu;
|
||||
|
||||
private static readonly EntProtoId FallbackScreen = "Screen";
|
||||
private static readonly ProtoId<AlertLevelPrototype> UnknownAlertLevel = "Unknown";
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Open()
|
||||
|
|
@ -81,21 +84,30 @@ public sealed partial class CommunicationsConsoleBoundUserInterface(EntityUid ow
|
|||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (_menu == null)
|
||||
return;
|
||||
|
||||
if (state is not CommunicationsConsoleInterfaceState commsState)
|
||||
return;
|
||||
|
||||
var stationUid = _station.GetOwningStation(Owner);
|
||||
|
||||
if (!EntMan.TryGetComponent<AlertLevelComponent>(stationUid, out var alertComp))
|
||||
return;
|
||||
|
||||
if (_menu != null)
|
||||
ProtoId<AlertLevelPrototype> currentAlertLevel;
|
||||
List<ProtoId<AlertLevelPrototype>> selectableAlertLevels;
|
||||
bool canChangeAlertLevel;
|
||||
if (_alertLevelQuery.TryGetComponent(stationUid, out var alertComp))
|
||||
{
|
||||
var currentAlertLevel = alertComp.CurrentAlertLevel;
|
||||
var selectableAlertLevels = _alertLevel.GetSelectableAlertLevels((stationUid.Value, alertComp));
|
||||
var canChangeAlertLevel = _alertLevel.CanChangeAlertLevel((stationUid.Value, alertComp));
|
||||
|
||||
_menu.UpdateState(commsState, currentAlertLevel, selectableAlertLevels, canChangeAlertLevel);
|
||||
currentAlertLevel = alertComp.CurrentAlertLevel;
|
||||
selectableAlertLevels = _alertLevel.GetSelectableAlertLevels((stationUid.Value, alertComp));
|
||||
canChangeAlertLevel = _alertLevel.CanChangeAlertLevel((stationUid.Value, alertComp));
|
||||
}
|
||||
else
|
||||
{
|
||||
currentAlertLevel = UnknownAlertLevel;
|
||||
selectableAlertLevels = new() { UnknownAlertLevel };
|
||||
canChangeAlertLevel = false;
|
||||
}
|
||||
|
||||
_menu.UpdateState(commsState, currentAlertLevel, selectableAlertLevels, canChangeAlertLevel);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public sealed partial class FlatpackSystem : SharedFlatpackSystem
|
|||
private void OnAppearanceChange(Entity<FlatpackComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
var (_, comp) = ent;
|
||||
if (!_appearance.TryGetData<string>(ent, FlatpackVisuals.Machine, out var machineBoardId) || args.Sprite == null)
|
||||
if (args.Sprite == null || !args.TryGetData<string>(FlatpackVisuals.Machine, out var machineBoardId))
|
||||
return;
|
||||
|
||||
if (!ProtoMan.TryIndex<EntityPrototype>(machineBoardId, out var machineBoardPrototype))
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ public sealed partial class EntityScreenshotGenerator
|
|||
|
||||
try
|
||||
{
|
||||
if (proto.HasComponent<SpriteComponent>(_entityManager.ComponentFactory))
|
||||
if (proto.HasComp<SpriteComponent>(_entityManager.ComponentFactory))
|
||||
{
|
||||
entity = _entityManager.SpawnEntity(proto.ID, new EntityCoordinates(previewGrid.Owner, default));
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ public sealed partial class EntityScreenshotGenerator
|
|||
|
||||
private bool HasExportableSprite(EntityPrototype prototype)
|
||||
{
|
||||
if (prototype.HasComponent<SpriteComponent>(_entityManager.ComponentFactory))
|
||||
if (prototype.HasComp<SpriteComponent>(_entityManager.ComponentFactory))
|
||||
return true;
|
||||
|
||||
return TryGetPrototypeIcon(prototype, out _);
|
||||
|
|
|
|||
|
|
@ -13,20 +13,20 @@ using Robust.Shared.Utility;
|
|||
namespace Content.Client.Damage;
|
||||
|
||||
/// <summary>
|
||||
/// A simple visualizer for any entity with a DamageableComponent
|
||||
/// to display the status of how damaged it is.
|
||||
/// A simple visualizer for any entity with a DamageableComponent
|
||||
/// to display the status of how damaged it is.
|
||||
///
|
||||
/// Can either be an overlay for an entity, or target multiple
|
||||
/// layers on the same entity.
|
||||
/// Can either be an overlay for an entity, or target multiple
|
||||
/// layers on the same entity.
|
||||
///
|
||||
/// This can be disabled dynamically by passing into SetData,
|
||||
/// key DamageVisualizerKeys.Disabled, value bool
|
||||
/// (DamageVisualizerKeys lives in Content.Shared.Damage)
|
||||
/// This can be disabled dynamically by passing into SetData,
|
||||
/// key DamageVisualizerKeys.Disabled, value bool
|
||||
/// (DamageVisualizerKeys lives in Content.Shared.Damage)
|
||||
///
|
||||
/// Damage layers, if targeting layers, can also be dynamically
|
||||
/// disabled if needed by passing into SetData, the name/enum
|
||||
/// of the sprite layer, and then passing in a bool value
|
||||
/// (true to enable, false to disable).
|
||||
/// Damage layers, if targeting layers, can also be dynamically
|
||||
/// disabled if needed by passing into SetData, the name/enum
|
||||
/// of the sprite layer, and then passing in a bool value
|
||||
/// (true to enable, false to disable).
|
||||
/// </summary>
|
||||
public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponent>
|
||||
{
|
||||
|
|
@ -325,7 +325,7 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a damage tracking layer to a given sprite component.
|
||||
/// Adds a damage tracking layer to a given sprite component.
|
||||
/// </summary>
|
||||
private void AddDamageLayerToSprite(Entity<SpriteComponent?> spriteEnt, DamageVisualizerSprite sprite, string state, string mapKey, int? index = null)
|
||||
{
|
||||
|
|
@ -355,35 +355,34 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
// If this was passed into the component, we update
|
||||
// the data to ensure that the current disabled
|
||||
// bool matches.
|
||||
if (AppearanceSystem.TryGetData<bool>(uid, DamageVisualizerKeys.Disabled, out var disabledStatus, args.Component))
|
||||
if (args.TryGetData<bool>(DamageVisualizerKeys.Disabled, out var disabledStatus))
|
||||
damageVisComp.Disabled = disabledStatus;
|
||||
|
||||
if (damageVisComp.Disabled)
|
||||
return;
|
||||
|
||||
if (AppearanceSystem.TryGetData<string>(uid, DamageVisualizerKeys.Displacement, out var displacement, args.Component) &&
|
||||
if (args.TryGetData<string>(DamageVisualizerKeys.Displacement, out var displacement) &&
|
||||
ProtoMan.Resolve<DisplacementDataPrototype>(displacement, out var displacementProto))
|
||||
damageVisComp.Displacement = displacementProto.Displacement;
|
||||
else
|
||||
damageVisComp.Displacement = null;
|
||||
|
||||
HandleDamage(uid, args.Component, damageVisComp);
|
||||
HandleDamage(uid, args, damageVisComp);
|
||||
}
|
||||
|
||||
private void HandleDamage(EntityUid uid, AppearanceComponent component, DamageVisualsComponent damageVisComp)
|
||||
private void HandleDamage(EntityUid uid, AppearanceChangeEvent args, DamageVisualsComponent damageVisComp)
|
||||
{
|
||||
if (!TryComp(uid, out SpriteComponent? spriteComponent)
|
||||
|| !TryComp(uid, out DamageableComponent? damageComponent))
|
||||
return;
|
||||
|
||||
if (damageVisComp.TargetLayers != null && damageVisComp.DamageOverlayGroups != null)
|
||||
UpdateDisabledLayers(uid, spriteComponent, component, damageVisComp);
|
||||
UpdateDisabledLayers(uid, spriteComponent, args, damageVisComp);
|
||||
|
||||
if (damageVisComp.Overlay && damageVisComp.TargetLayers == null)
|
||||
CheckOverlayOrdering((uid, spriteComponent), damageVisComp);
|
||||
|
||||
if (AppearanceSystem.TryGetData<bool>(uid, DamageVisualizerKeys.ForceUpdate, out var update, component)
|
||||
&& update)
|
||||
if (args.TryGetData<bool>(DamageVisualizerKeys.ForceUpdate, out var update) && update)
|
||||
{
|
||||
ForceUpdateLayers((uid, damageComponent, spriteComponent, damageVisComp));
|
||||
return;
|
||||
|
|
@ -395,8 +394,7 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
return;
|
||||
}
|
||||
|
||||
if (!AppearanceSystem.TryGetData<DamageVisualizerGroupData>(uid, DamageVisualizerKeys.DamageUpdateGroups,
|
||||
out var data, component))
|
||||
if (!args.TryGetData<DamageVisualizerGroupData>(DamageVisualizerKeys.DamageUpdateGroups, out var data))
|
||||
{
|
||||
data = new DamageVisualizerGroupData(_damageable.GetDamagePerGroup(uid).Keys.ToList());
|
||||
}
|
||||
|
|
@ -405,18 +403,18 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any layers were disabled in the last
|
||||
/// data update. Disabled layers mean that the
|
||||
/// layer will no longer be visible, or obtain
|
||||
/// any damage updates.
|
||||
/// Checks if any layers were disabled in the last
|
||||
/// data update. Disabled layers mean that the
|
||||
/// layer will no longer be visible, or obtain
|
||||
/// any damage updates.
|
||||
/// </summary>
|
||||
private void UpdateDisabledLayers(EntityUid uid, SpriteComponent spriteComponent, AppearanceComponent component, DamageVisualsComponent damageVisComp)
|
||||
private void UpdateDisabledLayers(EntityUid uid, SpriteComponent spriteComponent, AppearanceChangeEvent args, DamageVisualsComponent damageVisComp)
|
||||
{
|
||||
foreach (var layer in damageVisComp.TargetLayerMapKeys)
|
||||
{
|
||||
// I assume this gets set by something like body system if limbs are missing???
|
||||
// TODO is this actually used by anything anywhere?
|
||||
AppearanceSystem.TryGetData(uid, layer, out bool disabled, component);
|
||||
args.TryGetData(layer, out bool disabled);
|
||||
|
||||
if (damageVisComp.DisabledLayers[layer] == disabled)
|
||||
continue;
|
||||
|
|
@ -439,11 +437,11 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the overlay ordering on the current
|
||||
/// sprite component, compared to the
|
||||
/// data for the visualizer. If the top
|
||||
/// most layer doesn't match, the sprite
|
||||
/// layers are recreated and placed on top.
|
||||
/// Checks the overlay ordering on the current
|
||||
/// sprite component, compared to the
|
||||
/// data for the visualizer. If the top
|
||||
/// most layer doesn't match, the sprite
|
||||
/// layers are recreated and placed on top.
|
||||
/// </summary>
|
||||
private void CheckOverlayOrdering(Entity<SpriteComponent> spriteEnt, DamageVisualsComponent damageVisComp)
|
||||
{
|
||||
|
|
@ -494,8 +492,8 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates damage visuals without tracking
|
||||
/// any damage groups.
|
||||
/// Updates damage visuals without tracking
|
||||
/// any damage groups.
|
||||
/// </summary>
|
||||
private void UpdateDamageVisuals(Entity<DamageableComponent, SpriteComponent, DamageVisualsComponent> entity)
|
||||
{
|
||||
|
|
@ -521,9 +519,9 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates damage visuals by damage group,
|
||||
/// according to the list of damage groups
|
||||
/// passed into it.
|
||||
/// Updates damage visuals by damage group,
|
||||
/// according to the list of damage groups
|
||||
/// passed into it.
|
||||
/// </summary>
|
||||
private void UpdateDamageVisuals(List<ProtoId<DamageGroupPrototype>> delta, Entity<DamageableComponent, SpriteComponent, DamageVisualsComponent> entity)
|
||||
{
|
||||
|
|
@ -562,7 +560,7 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a threshold boundary was passed.
|
||||
/// Checks if a threshold boundary was passed.
|
||||
/// </summary>
|
||||
private bool CheckThresholdBoundary(FixedPoint2 damageTotal, FixedPoint2 lastThreshold, DamageVisualsComponent damageVisComp, out FixedPoint2 threshold)
|
||||
{
|
||||
|
|
@ -587,10 +585,10 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the entry point for
|
||||
/// forcing an update on all damage layers.
|
||||
/// Does different things depending on
|
||||
/// the configuration of the visualizer.
|
||||
/// This is the entry point for
|
||||
/// forcing an update on all damage layers.
|
||||
/// Does different things depending on
|
||||
/// the configuration of the visualizer.
|
||||
/// </summary>
|
||||
private void ForceUpdateLayers(Entity<DamageableComponent, SpriteComponent, DamageVisualsComponent> entity)
|
||||
{
|
||||
|
|
@ -611,9 +609,9 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a target layer. Without a damage group passed in,
|
||||
/// it assumes you're updating a layer that is tracking all
|
||||
/// damage.
|
||||
/// Updates a target layer. Without a damage group passed in,
|
||||
/// it assumes you're updating a layer that is tracking all
|
||||
/// damage.
|
||||
/// </summary>
|
||||
private void UpdateTargetLayer(Entity<SpriteComponent> spriteEnt, DamageVisualsComponent damageVisComp, object layerMapKey, FixedPoint2 threshold)
|
||||
{
|
||||
|
|
@ -647,7 +645,7 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a target layer by damage group.
|
||||
/// Updates a target layer by damage group.
|
||||
/// </summary>
|
||||
private void UpdateTargetLayer(Entity<SpriteComponent, DamageVisualsComponent> entity, object layerMapKey, string damageGroup, FixedPoint2 threshold)
|
||||
{
|
||||
|
|
@ -686,7 +684,7 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an overlay that is tracking all damage.
|
||||
/// Updates an overlay that is tracking all damage.
|
||||
/// </summary>
|
||||
private void UpdateOverlay(Entity<SpriteComponent> spriteEnt, FixedPoint2 threshold, DisplacementData? displacement = null)
|
||||
{
|
||||
|
|
@ -701,7 +699,7 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an overlay based on damage group.
|
||||
/// Updates an overlay based on damage group.
|
||||
/// </summary>
|
||||
private void UpdateOverlay(Entity<SpriteComponent, DamageVisualsComponent> entity, string damageGroup, FixedPoint2 threshold, DisplacementData? displacement = null)
|
||||
{
|
||||
|
|
@ -726,10 +724,10 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem<DamageVisuals
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a layer on the sprite by what
|
||||
/// prefix it has (calculated by whatever
|
||||
/// function calls it), and what threshold
|
||||
/// was passed into it.
|
||||
/// Updates a layer on the sprite by what
|
||||
/// prefix it has (calculated by whatever
|
||||
/// function calls it), and what threshold
|
||||
/// was passed into it.
|
||||
/// </summary>
|
||||
private void UpdateDamageLayerState(Entity<SpriteComponent> spriteEnt, int spriteLayer, string statePrefix, FixedPoint2 threshold, string layerKey, DisplacementData? displacement)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -254,8 +254,6 @@ public sealed partial class DamageOverlay : Overlay
|
|||
handle.UseShader(_critShader);
|
||||
handle.DrawRect(viewport, Color.White);
|
||||
}
|
||||
|
||||
handle.UseShader(null);
|
||||
}
|
||||
|
||||
private float GetDiff(float value, float lastFrameTime)
|
||||
|
|
|
|||
|
|
@ -10,31 +10,27 @@ public sealed partial class DamageStateVisualizerSystem : VisualizerSystem<Damag
|
|||
{
|
||||
var sprite = args.Sprite;
|
||||
|
||||
if (sprite == null || !AppearanceSystem.TryGetData<MobState>(uid, MobStateVisuals.State, out var data, args.Component))
|
||||
{
|
||||
if (sprite == null || !args.TryGetData<MobState>(MobStateVisuals.State, out var data))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!component.States.TryGetValue(data, out var layers))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Brain no worky rn so this was just easier.
|
||||
foreach (var key in new[] { DamageStateVisualLayers.Base, DamageStateVisualLayers.BaseUnshaded })
|
||||
{
|
||||
if (!SpriteSystem.LayerMapTryGet((uid, sprite), key, out _, false)) continue;
|
||||
if (!SpriteSystem.LayerMapTryGet((uid, sprite), key, out var layerIndex, false)) continue;
|
||||
|
||||
SpriteSystem.LayerSetVisible((uid, sprite), key, false);
|
||||
SpriteSystem.LayerSetVisible((uid, sprite), layerIndex, false);
|
||||
}
|
||||
|
||||
foreach (var (key, state) in layers)
|
||||
{
|
||||
// Inheritance moment.
|
||||
if (!SpriteSystem.LayerMapTryGet((uid, sprite), key, out _, false)) continue;
|
||||
if (!SpriteSystem.LayerMapTryGet((uid, sprite), key, out var layerIndex, false)) continue;
|
||||
|
||||
SpriteSystem.LayerSetVisible((uid, sprite), key, true);
|
||||
SpriteSystem.LayerSetRsiState((uid, sprite), key, state);
|
||||
SpriteSystem.LayerSetVisible((uid, sprite), layerIndex, true);
|
||||
SpriteSystem.LayerSetRsiState((uid, sprite), layerIndex, state);
|
||||
}
|
||||
|
||||
// So they don't draw over mobs anymore
|
||||
|
|
|
|||
|
|
@ -115,8 +115,6 @@ namespace Content.Client.Decals.Overlays
|
|||
else
|
||||
handle.DrawTexture(cache.Texture, decal.Coordinates, angle, decal.Color);
|
||||
}
|
||||
|
||||
handle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
private static int CompareDecalIndex(DecalIndex x, DecalIndex y)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,5 @@ public sealed partial class DecalPlacementOverlay : Overlay
|
|||
var box = new Box2Rotated(aabb, rotation, localPos);
|
||||
|
||||
handle.DrawTextureRect(_sprite.Frame0(decal.Sprite), box, color);
|
||||
handle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ namespace Content.Client.Delivery;
|
|||
|
||||
public sealed partial class DeliveryVisualizerSystem : VisualizerSystem<DeliveryComponent>
|
||||
{
|
||||
[Dependency] private SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
private static readonly ProtoId<JobIconPrototype> UnknownIcon = "JobIconUnknown";
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, DeliveryComponent component, ref AppearanceChangeEvent args)
|
||||
|
|
@ -16,7 +14,7 @@ public sealed partial class DeliveryVisualizerSystem : VisualizerSystem<Delivery
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
_appearance.TryGetData(uid, DeliveryVisuals.JobIcon, out string job, args.Component);
|
||||
args.TryGetData<string>(DeliveryVisuals.JobIcon, out var job);
|
||||
|
||||
if (string.IsNullOrEmpty(job))
|
||||
job = UnknownIcon;
|
||||
|
|
|
|||
|
|
@ -15,14 +15,6 @@ public sealed partial class DisposalUnitSystem : SharedDisposalUnitSystem
|
|||
|
||||
private const string AnimationKey = "disposal_unit_animation";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DisposalUnitComponent, AfterAutoHandleStateEvent>(OnHandleState);
|
||||
SubscribeLocalEvent<DisposalUnitComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
protected override void OnComponentInit(Entity<DisposalUnitComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
base.OnComponentInit(ent, ref args);
|
||||
|
|
@ -55,28 +47,19 @@ public sealed partial class DisposalUnitSystem : SharedDisposalUnitSystem
|
|||
ent.Comp.FlushingAnimation = anim;
|
||||
}
|
||||
|
||||
private void OnHandleState(EntityUid uid, DisposalUnitComponent component, ref AfterAutoHandleStateEvent args)
|
||||
[SubscribeLocalEvent]
|
||||
private void OnHandleState(Entity<DisposalUnitComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
UpdateUI((uid, component));
|
||||
UpdateUI(ent);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(Entity<DisposalUnitComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
UpdateState(ent, args.Sprite, args.Component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the animation of a disposal unit.
|
||||
/// </summary>
|
||||
/// <param name="ent">The disposal unit.</param>
|
||||
/// <param name="sprite">The disposal unit's sprite.</param>
|
||||
/// <param name="appearance">The disposal unit's appearance.</param>
|
||||
private void UpdateState(Entity<DisposalUnitComponent> ent, SpriteComponent sprite, AppearanceComponent appearance)
|
||||
{
|
||||
if (!_appearanceSystem.TryGetData<bool>(ent, DisposalUnitVisuals.IsFlushing, out var isFlushing, appearance))
|
||||
if (!args.TryGetData<bool>(DisposalUnitVisuals.IsFlushing, out var isFlushing))
|
||||
return;
|
||||
|
||||
// This is a transient state so not too worried about replaying in range.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public sealed class DoAfterOverlay : Overlay
|
|||
private readonly IEntityManager _entManager;
|
||||
private readonly IGameTiming _timing;
|
||||
private readonly IPlayerManager _player;
|
||||
private readonly SharedTransformSystem _transform;
|
||||
private readonly TransformSystem _transform;
|
||||
private readonly MetaDataSystem _meta;
|
||||
private readonly ProgressColorSystem _progressColor;
|
||||
private readonly SharedContainerSystem _container;
|
||||
|
|
@ -53,7 +53,7 @@ public sealed class DoAfterOverlay : Overlay
|
|||
_entManager = entManager;
|
||||
_timing = timing;
|
||||
_player = player;
|
||||
_transform = _entManager.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
|
||||
_transform = _entManager.EntitySysManager.GetEntitySystem<TransformSystem>();
|
||||
_meta = _entManager.EntitySysManager.GetEntitySystem<MetaDataSystem>();
|
||||
_container = _entManager.EntitySysManager.GetEntitySystem<SharedContainerSystem>();
|
||||
_progressColor = _entManager.System<ProgressColorSystem>();
|
||||
|
|
@ -68,8 +68,6 @@ public sealed class DoAfterOverlay : Overlay
|
|||
{
|
||||
var handle = args.WorldHandle;
|
||||
var rotation = args.Viewport.Eye?.Rotation ?? Angle.Zero;
|
||||
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
// If you use the display UI scale then need to set max(1f, displayscale) because 0 is valid.
|
||||
const float scale = 1f;
|
||||
var scaleMatrix = Matrix3Helpers.CreateScale(new Vector2(scale, scale));
|
||||
|
|
@ -90,7 +88,7 @@ public sealed class DoAfterOverlay : Overlay
|
|||
if (comp.DoAfters.Count == 0)
|
||||
continue;
|
||||
|
||||
var worldPosition = _transform.GetWorldPosition(xform, xformQuery);
|
||||
var worldPosition = _transform.GetRenderWorldPosition((uid, xform));
|
||||
if (!bounds.Contains(worldPosition))
|
||||
continue;
|
||||
|
||||
|
|
@ -176,9 +174,6 @@ public sealed class DoAfterOverlay : Overlay
|
|||
offset += _barTexture.Height / scale;
|
||||
}
|
||||
}
|
||||
|
||||
handle.UseShader(null);
|
||||
handle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
public Color GetProgressColor(float progress, float alpha = 1f)
|
||||
|
|
|
|||
|
|
@ -7,87 +7,82 @@ using Robust.Client.GameObjects;
|
|||
|
||||
namespace Content.Client.Doors;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed partial class AirlockSystem : SharedAirlockSystem
|
||||
{
|
||||
[Dependency] private AppearanceSystem _appearanceSystem = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<AirlockComponent, ComponentStartup>(OnComponentStartup);
|
||||
SubscribeLocalEvent<AirlockComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
[Dependency] private EntityQuery<DoorComponent> _doorQuery;
|
||||
|
||||
private void OnComponentStartup(EntityUid uid, AirlockComponent comp, ComponentStartup args)
|
||||
[SubscribeLocalEvent]
|
||||
private void OnComponentStartup(Entity<AirlockComponent> ent, ref ComponentStartup args)
|
||||
{
|
||||
// Has to be on component startup because we don't know what order components initialize in and running this before DoorComponent inits _will_ crash.
|
||||
if (!TryComp<DoorComponent>(uid, out var door))
|
||||
if (!_doorQuery.TryComp(ent, out var door))
|
||||
return;
|
||||
|
||||
if (comp.OpenUnlitVisible) // Otherwise there are flashes of the fallback sprite between clicking on the door and the door closing animation starting.
|
||||
if (ent.Comp.OpenUnlitVisible) // Otherwise there are flashes of the fallback sprite between clicking on the door and the door closing animation starting.
|
||||
{
|
||||
door.OpenSpriteStates.Add((DoorVisualLayers.BaseUnlit, comp.OpenSpriteState));
|
||||
door.ClosedSpriteStates.Add((DoorVisualLayers.BaseUnlit, comp.ClosedSpriteState));
|
||||
door.OpenSpriteStates.Add((DoorVisualLayers.BaseUnlit, ent.Comp.OpenSpriteState));
|
||||
door.ClosedSpriteStates.Add((DoorVisualLayers.BaseUnlit, ent.Comp.ClosedSpriteState));
|
||||
}
|
||||
|
||||
((Animation)door.OpeningAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick()
|
||||
((Animation)door.OpeningAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = DoorVisualLayers.BaseUnlit,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.OpeningSpriteState, 0f) },
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.OpeningSpriteState, 0f) },
|
||||
}
|
||||
);
|
||||
|
||||
((Animation)door.ClosingAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick()
|
||||
((Animation)door.ClosingAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = DoorVisualLayers.BaseUnlit,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.ClosingSpriteState, 0f) },
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.ClosingSpriteState, 0f) },
|
||||
}
|
||||
);
|
||||
|
||||
door.DenyingAnimation = new Animation()
|
||||
door.DenyingAnimation = new Animation
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(comp.DenyAnimationTime),
|
||||
Length = TimeSpan.FromSeconds(ent.Comp.DenyAnimationTime),
|
||||
AnimationTracks =
|
||||
{
|
||||
new AnimationTrackSpriteFlick()
|
||||
new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = DoorVisualLayers.BaseUnlit,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.DenySpriteState, 0f) },
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.DenySpriteState, 0f) },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!comp.AnimatePanel)
|
||||
if (!ent.Comp.AnimatePanel)
|
||||
return;
|
||||
|
||||
// For some reason the open panel sprite is used for both open and
|
||||
// closed sprites. I really don't get it.
|
||||
door.OpenSpriteStates.Add((WiresVisualLayers.MaintenancePanel, comp.OpenPanelSpriteState));
|
||||
door.ClosedSpriteStates.Add((WiresVisualLayers.MaintenancePanel, comp.OpenPanelSpriteState));
|
||||
door.OpenSpriteStates.Add((WiresVisualLayers.MaintenancePanel, null));
|
||||
door.ClosedSpriteStates.Add((WiresVisualLayers.MaintenancePanel, ent.Comp.OpenPanelSpriteState));
|
||||
|
||||
((Animation)door.OpeningAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick()
|
||||
((Animation)door.OpeningAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = WiresVisualLayers.MaintenancePanel,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.OpeningPanelSpriteState, 0f) },
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.OpeningPanelSpriteState, 0f) },
|
||||
});
|
||||
|
||||
((Animation)door.ClosingAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = WiresVisualLayers.MaintenancePanel,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.ClosingPanelSpriteState, 0f) },
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.ClosingPanelSpriteState, 0f) },
|
||||
});
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, AirlockComponent comp, ref AppearanceChangeEvent args)
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(Entity<AirlockComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!_appearanceSystem.TryGetData<DoorState>(uid, DoorVisuals.State, out var state, args.Component))
|
||||
if (!args.TryGetData<DoorState>(DoorVisuals.State, out var state))
|
||||
state = DoorState.Closed;
|
||||
|
||||
_appearanceSystem.TryGetData<bool>(uid, PowerDeviceVisuals.Powered, out var hasPower, args.Component);
|
||||
args.TryGetData<bool>(PowerDeviceVisuals.Powered, out var hasPower);
|
||||
|
||||
var showBaseUnlit = false;
|
||||
var showBolted = false;
|
||||
|
|
@ -95,10 +90,10 @@ public sealed partial class AirlockSystem : SharedAirlockSystem
|
|||
|
||||
if (hasPower)
|
||||
{
|
||||
_appearanceSystem.TryGetData<bool>(uid, DoorVisuals.BoltLights, out var boltedVisible, args.Component);
|
||||
args.TryGetData<bool>(DoorVisuals.BoltLights, out var boltedVisible);
|
||||
showBolted = boltedVisible && (state == DoorState.Closed || state == DoorState.Welded);
|
||||
|
||||
_appearanceSystem.TryGetData<bool>(uid, DoorVisuals.EmergencyLights, out var emergencyVisible, args.Component);
|
||||
args.TryGetData<bool>(DoorVisuals.EmergencyLights, out var emergencyVisible);
|
||||
showEmergency = emergencyVisible;
|
||||
|
||||
if (!showBolted && !showEmergency)
|
||||
|
|
@ -106,33 +101,33 @@ public sealed partial class AirlockSystem : SharedAirlockSystem
|
|||
if (state == DoorState.Closing || state == DoorState.Opening || state == DoorState.Denying || state == DoorState.Closed)
|
||||
showBaseUnlit = true;
|
||||
|
||||
if (state == DoorState.Open && comp.OpenUnlitVisible)
|
||||
if (state == DoorState.Open && ent.Comp.OpenUnlitVisible)
|
||||
showBaseUnlit = true;
|
||||
|
||||
_appearanceSystem.TryGetData<bool>(uid, DoorVisuals.ClosedLights, out var closedLightsVisible, args.Component);
|
||||
args.TryGetData<bool>(DoorVisuals.ClosedLights, out var closedLightsVisible);
|
||||
if (state == DoorState.Closed && closedLightsVisible)
|
||||
showBaseUnlit = true;
|
||||
}
|
||||
}
|
||||
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseUnlit, showBaseUnlit);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseBolted, showBolted);
|
||||
if (comp.EmergencyAccessLayer)
|
||||
_sprite.LayerSetVisible((ent, args.Sprite), DoorVisualLayers.BaseUnlit, showBaseUnlit);
|
||||
_sprite.LayerSetVisible((ent, args.Sprite), DoorVisualLayers.BaseBolted, showBolted);
|
||||
if (ent.Comp.EmergencyAccessLayer)
|
||||
{
|
||||
var isDoorIdle = state != DoorState.Open && state != DoorState.Opening && state != DoorState.Closing;
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseEmergencyAccess,
|
||||
_sprite.LayerSetVisible((ent, args.Sprite), DoorVisualLayers.BaseEmergencyAccess,
|
||||
showEmergency && isDoorIdle && !showBolted);
|
||||
}
|
||||
|
||||
if (comp.OpenUnlitVisible)
|
||||
if (ent.Comp.OpenUnlitVisible)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case DoorState.Open:
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), DoorVisualLayers.BaseUnlit, comp.OpenSpriteState);
|
||||
_sprite.LayerSetRsiState((ent, args.Sprite), DoorVisualLayers.BaseUnlit, ent.Comp.OpenSpriteState);
|
||||
break;
|
||||
case DoorState.Closed:
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), DoorVisualLayers.BaseUnlit, comp.ClosedSpriteState);
|
||||
_sprite.LayerSetRsiState((ent, args.Sprite), DoorVisualLayers.BaseUnlit, ent.Comp.ClosedSpriteState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,23 +6,19 @@ using Robust.Client.GameObjects;
|
|||
|
||||
namespace Content.Client.Doors;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed partial class DoorSystem : SharedDoorSystem
|
||||
{
|
||||
[Dependency] private AnimationPlayerSystem _animationSystem = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<DoorComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
SubscribeLocalEvent<DoorComponent, AnimationCompletedEvent>(OnAnimationCompleted);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnComponentInit(Entity<DoorComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
// Base call deferred until end of function.
|
||||
var comp = ent.Comp;
|
||||
comp.OpenSpriteStates = new List<(Enum, string)>(2);
|
||||
comp.ClosedSpriteStates = new List<(Enum, string)>(2);
|
||||
comp.OpenSpriteStates = new(2);
|
||||
comp.ClosedSpriteStates = new(2);
|
||||
|
||||
comp.OpenSpriteStates.Add((DoorVisualLayers.Base, comp.OpenSpriteState));
|
||||
comp.ClosedSpriteStates.Add((DoorVisualLayers.Base, comp.ClosedSpriteState));
|
||||
|
|
@ -74,8 +70,11 @@ public sealed partial class DoorSystem : SharedDoorSystem
|
|||
},
|
||||
},
|
||||
};
|
||||
|
||||
base.OnComponentInit(ent, ref args);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAnimationCompleted(Entity<DoorComponent> ent, ref AnimationCompletedEvent args)
|
||||
{
|
||||
if (args.Key != DoorComponent.OpenKey && args.Key != DoorComponent.CloseKey)
|
||||
|
|
@ -105,20 +104,20 @@ public sealed partial class DoorSystem : SharedDoorSystem
|
|||
}
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(Entity<DoorComponent> entity, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<DoorState>(entity, DoorVisuals.State, out var state, args.Component))
|
||||
if (!args.TryGetData<DoorState>(DoorVisuals.State, out var state))
|
||||
state = DoorState.Closed;
|
||||
|
||||
if (AppearanceSystem.TryGetData<string>(entity, PaintableVisuals.Prototype, out var prototype, args.Component))
|
||||
if (args.TryGetData<string>(PaintableVisuals.Prototype, out var prototype))
|
||||
UpdateSpriteLayers((entity.Owner, args.Sprite), prototype);
|
||||
|
||||
// We are checking beforehand since some doors may not have an emagging visual layer, and we don't want LayerSetVisible to throw an error.
|
||||
if (_sprite.TryGetLayer(entity.Owner, DoorVisualLayers.BaseEmagging, out var _, false))
|
||||
_sprite.LayerSetVisible(entity.Owner, DoorVisualLayers.BaseEmagging, state == DoorState.Emagging);
|
||||
if (_sprite.LayerMapTryGet(entity.Owner, DoorVisualLayers.BaseEmagging, out var emaggingLayer, logMissing: false))
|
||||
_sprite.LayerSetVisible(entity.Owner, emaggingLayer, state == DoorState.Emagging);
|
||||
|
||||
UpdateAppearanceForDoorState(entity, args.Sprite, state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Client.Wires.Visualizers;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Doors.Systems;
|
||||
using Robust.Client.Animations;
|
||||
|
|
@ -5,60 +6,103 @@ using Robust.Client.GameObjects;
|
|||
|
||||
namespace Content.Client.Doors;
|
||||
|
||||
// TODO: Consolidate redundant code from the AirlockSystem.
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed partial class FirelockSystem : SharedFirelockSystem
|
||||
{
|
||||
[Dependency] private SharedAppearanceSystem _appearanceSystem = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<FirelockComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
[Dependency] private EntityQuery<DoorComponent> _doorQuery;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnComponentStartup(Entity<FirelockComponent> ent, ref ComponentStartup args)
|
||||
{
|
||||
base.OnComponentStartup(ent, ref args);
|
||||
if (!TryComp<DoorComponent>(ent.Owner, out var door))
|
||||
if (!_doorQuery.TryComp(ent.Owner, out var door))
|
||||
return;
|
||||
|
||||
door.ClosedSpriteStates.Add((DoorVisualLayers.BaseUnlit, ent.Comp.WarningLightSpriteState));
|
||||
door.OpenSpriteStates.Add((DoorVisualLayers.BaseUnlit, ent.Comp.WarningLightSpriteState));
|
||||
// Add animations if we have an unlit layer.
|
||||
if (_sprite.LayerMapTryGet(ent.Owner, DoorVisualLayers.BaseUnlit, out _, logMissing: false))
|
||||
{
|
||||
door.ClosedSpriteStates.Add((DoorVisualLayers.BaseUnlit, ent.Comp.WarningLightSpriteState));
|
||||
door.OpenSpriteStates.Add((DoorVisualLayers.BaseUnlit, ent.Comp.WarningLightSpriteState));
|
||||
|
||||
((Animation)door.OpeningAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick()
|
||||
{
|
||||
LayerKey = DoorVisualLayers.BaseUnlit,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.OpeningLightSpriteState, 0f) },
|
||||
}
|
||||
);
|
||||
((Animation)door.OpeningAnimation).AnimationTracks.Add(
|
||||
new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = DoorVisualLayers.BaseUnlit,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.OpeningLightSpriteState, 0f) },
|
||||
}
|
||||
);
|
||||
|
||||
((Animation)door.ClosingAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick()
|
||||
{
|
||||
LayerKey = DoorVisualLayers.BaseUnlit,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.ClosingLightSpriteState, 0f) },
|
||||
}
|
||||
);
|
||||
((Animation)door.ClosingAnimation).AnimationTracks.Add(
|
||||
new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = DoorVisualLayers.BaseUnlit,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.ClosingLightSpriteState, 0f) },
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!ent.Comp.AnimatePanel)
|
||||
return;
|
||||
|
||||
door.OpenSpriteStates.Add((WiresVisualLayers.MaintenancePanel, null));
|
||||
door.ClosedSpriteStates.Add((WiresVisualLayers.MaintenancePanel, ent.Comp.OpenPanelSpriteState));
|
||||
|
||||
((Animation)door.OpeningAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = WiresVisualLayers.MaintenancePanel,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.OpeningPanelSpriteState, 0f) },
|
||||
});
|
||||
|
||||
((Animation)door.ClosingAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = WiresVisualLayers.MaintenancePanel,
|
||||
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.ClosingPanelSpriteState, 0f) },
|
||||
});
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, FirelockComponent comp, ref AppearanceChangeEvent args)
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(Entity<FirelockComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
var boltedVisible = false;
|
||||
var unlitVisible = false;
|
||||
|
||||
if (!_appearanceSystem.TryGetData<DoorState>(uid, DoorVisuals.State, out var state, args.Component))
|
||||
if (!args.TryGetData<DoorState>(DoorVisuals.State, out var state))
|
||||
state = DoorState.Closed;
|
||||
|
||||
boltedVisible = _appearanceSystem.TryGetData<bool>(uid, DoorVisuals.BoltLights, out var lights, args.Component) && lights;
|
||||
unlitVisible =
|
||||
var boltedVisible = args.TryGetData<bool>(DoorVisuals.BoltLights, out var lights) && lights;
|
||||
var unlitVisible =
|
||||
state == DoorState.Closing
|
||||
|| state == DoorState.Opening
|
||||
|| state == DoorState.Denying
|
||||
|| (_appearanceSystem.TryGetData<bool>(uid, DoorVisuals.ClosedLights, out var closedLights, args.Component) && closedLights);
|
||||
|| state == DoorState.Opening
|
||||
|| state == DoorState.Denying
|
||||
|| args.TryGetData<bool>(DoorVisuals.ClosedLights, out var closedLights) && closedLights;
|
||||
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseUnlit, unlitVisible && !boltedVisible);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseBolted, boltedVisible);
|
||||
if (_sprite.LayerMapTryGet((ent, args.Sprite), DoorVisualLayers.BaseUnlit, out var unlitLayer, logMissing: false))
|
||||
_sprite.LayerSetVisible((ent, args.Sprite), unlitLayer, unlitVisible && !boltedVisible);
|
||||
|
||||
if (_sprite.LayerMapTryGet((ent, args.Sprite), DoorVisualLayers.BaseBolted, out var boltedLayer, logMissing: false))
|
||||
_sprite.LayerSetVisible((ent, args.Sprite), boltedLayer, boltedVisible);
|
||||
|
||||
var warningLightsVisible =
|
||||
state == DoorState.Closed
|
||||
|| state == DoorState.Welded
|
||||
|| state == DoorState.Denying;
|
||||
|
||||
if (_sprite.LayerMapTryGet((ent, args.Sprite), FirelockVisualLayersPressure.Base, out var pressureLayerIndex, logMissing: false))
|
||||
{
|
||||
if (!args.TryGetData<bool>(FirelockVisuals.PressureWarning, out var pressure))
|
||||
pressure = false;
|
||||
_sprite.LayerSetVisible((ent, args.Sprite), pressureLayerIndex, pressure && warningLightsVisible);
|
||||
}
|
||||
|
||||
if (_sprite.LayerMapTryGet((ent, args.Sprite), FirelockVisualLayersTemperature.Base, out var tempLayerIndex, logMissing: false))
|
||||
{
|
||||
if (!args.TryGetData<bool>(FirelockVisuals.TemperatureWarning, out var temp))
|
||||
temp = false;
|
||||
_sprite.LayerSetVisible((ent, args.Sprite), tempLayerIndex, temp && warningLightsVisible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,5 @@ public sealed partial class DrowsinessOverlay : Overlay
|
|||
_drowsinessShader.SetParameter("Strength", _visualScale * Intensity);
|
||||
handle.UseShader(_drowsinessShader);
|
||||
handle.DrawRect(args.WorldBounds, Color.White);
|
||||
handle.UseShader(null);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,5 @@ public sealed partial class RainbowOverlay : Overlay
|
|||
_rainbowShader.SetParameter("phase", Phase);
|
||||
handle.UseShader(_rainbowShader);
|
||||
handle.DrawRect(args.WorldBounds, Color.White);
|
||||
handle.UseShader(null);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,6 @@ public sealed partial class DrunkOverlay : Overlay
|
|||
_drunkShader.SetParameter("phase", Phase);
|
||||
handle.UseShader(_drunkShader);
|
||||
handle.DrawRect(args.WorldBounds, Color.White);
|
||||
handle.UseShader(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public sealed partial class ElectrocutionHUDVisualizerSystem : VisualizerSystem<
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component))
|
||||
if (!args.TryGetData<bool>(ElectrifiedVisuals.IsElectrified, out var electrified))
|
||||
return;
|
||||
|
||||
var player = _playerMan.LocalEntity;
|
||||
|
|
|
|||
|
|
@ -30,18 +30,18 @@ public sealed partial class EnsnareableSystem : SharedEnsnareableSystem
|
|||
|
||||
private void OnAppearanceChange(EntityUid uid, EnsnareableComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (component.Sprite == null)
|
||||
return;
|
||||
|
||||
if (args.Sprite == null || !_sprite.LayerMapTryGet((uid, args.Sprite), EnsnaredVisualLayers.Ensnared, out var layer, false))
|
||||
return;
|
||||
|
||||
if (_appearance.TryGetData<bool>(uid, EnsnareableVisuals.IsEnsnared, out var isEnsnared, args.Component))
|
||||
{
|
||||
if (component.Sprite != null)
|
||||
{
|
||||
_sprite.LayerSetRsi((uid, args.Sprite), layer, new ResPath(component.Sprite));
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, component.State);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), layer, isEnsnared);
|
||||
}
|
||||
}
|
||||
if (!args.TryGetData<bool>(EnsnareableVisuals.IsEnsnared, out var isEnsnared))
|
||||
return;
|
||||
|
||||
_sprite.LayerSetRsi((uid, args.Sprite), layer, new ResPath(component.Sprite));
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, component.State);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), layer, isEnsnared);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using Content.Shared.Explosion;
|
||||
using Content.Shared.Explosion.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
|
|
@ -11,7 +10,7 @@ public sealed partial class ClusterGrenadeVisualizerSystem : VisualizerSystem<Cl
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (AppearanceSystem.TryGetData<int>(uid, ClusterGrenadeVisuals.GrenadesCounter, out var grenadesCounter, args.Component))
|
||||
if (args.TryGetData<int>(ClusterGrenadeVisuals.GrenadesCounter, out var grenadesCounter))
|
||||
SpriteSystem.LayerSetRsiState((uid, args.Sprite), 0, $"{comp.State}-{grenadesCounter}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,9 +52,6 @@ public sealed partial class ExplosionOverlay : Overlay
|
|||
index = Math.Min(index, visuals.Intensity.Count - 1);
|
||||
DrawExplosion(drawHandle, args.WorldBounds, visuals, index, xforms, textures);
|
||||
}
|
||||
|
||||
drawHandle.SetTransform(Matrix3x2.Identity);
|
||||
drawHandle.UseShader(null);
|
||||
}
|
||||
|
||||
private void DrawExplosion(
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ namespace Content.Client.Eye.Blinding
|
|||
worldHandle.DrawRect(viewport, Color.White);
|
||||
worldHandle.UseShader(_circleMaskShader);
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
worldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ namespace Content.Client.Eye.Blinding
|
|||
|
||||
worldHandle.UseShader(_circleMaskShader);
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
worldHandle.UseShader(null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +113,6 @@ namespace Content.Client.Eye.Blinding
|
|||
|
||||
worldHandle.UseShader(_cataractsShader);
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
worldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,15 +11,8 @@ namespace Content.Client.Fax.System;
|
|||
public sealed partial class FaxVisualsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private AnimationPlayerSystem _player = default!;
|
||||
[Dependency] private SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FaxMachineComponent, AppearanceChangeEvent>(OnAppearanceChanged);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChanged(EntityUid uid, FaxMachineComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
|
|
@ -28,26 +21,26 @@ public sealed partial class FaxVisualsSystem : EntitySystem
|
|||
if (_player.HasRunningAnimation(uid, "faxecute"))
|
||||
return;
|
||||
|
||||
if (_appearance.TryGetData(uid, FaxMachineVisuals.VisualState, out FaxMachineVisualState visuals) &&
|
||||
visuals == FaxMachineVisualState.Inserting)
|
||||
{
|
||||
_player.Play(uid,
|
||||
new Animation()
|
||||
if (!args.TryGetData(FaxMachineVisuals.VisualState, out FaxMachineVisualState visuals)
|
||||
|| visuals != FaxMachineVisualState.Inserting)
|
||||
return;
|
||||
|
||||
_player.Play(uid,
|
||||
new Animation()
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(2.4),
|
||||
AnimationTracks =
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(2.4),
|
||||
AnimationTracks =
|
||||
new AnimationTrackSpriteFlick()
|
||||
{
|
||||
new AnimationTrackSpriteFlick()
|
||||
LayerKey = FaxMachineVisuals.VisualState,
|
||||
KeyFrames =
|
||||
{
|
||||
LayerKey = FaxMachineVisuals.VisualState,
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackSpriteFlick.KeyFrame(component.InsertingState, 0f)
|
||||
},
|
||||
new AnimationTrackSpriteFlick.KeyFrame(component.InsertingState, 0f)
|
||||
},
|
||||
},
|
||||
},
|
||||
"faxecute");
|
||||
}
|
||||
},
|
||||
"faxecute");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ public sealed partial class FlashOverlay : Overlay
|
|||
_shader.SetParameter("percentComplete", PercentComplete);
|
||||
worldHandle.UseShader(_shader);
|
||||
worldHandle.DrawTextureRectRegion(ScreenshotTexture, args.WorldBounds);
|
||||
worldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,8 +75,6 @@ public sealed partial class PuddleOverlay : Overlay
|
|||
drawHandle.DrawRect(box, ColorMap(debugOverlayData.CurrentVolume));
|
||||
}
|
||||
}
|
||||
|
||||
drawHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
private void DrawScreen(in OverlayDrawArgs args)
|
||||
|
|
|
|||
|
|
@ -24,12 +24,8 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
var volume = 1f;
|
||||
|
||||
if (args.AppearanceData.TryGetValue(PuddleVisuals.CurrentVolume, out var volumeObj))
|
||||
{
|
||||
volume = (float)volumeObj;
|
||||
}
|
||||
if (!args.TryGetData<float>(PuddleVisuals.CurrentVolume, out var volume))
|
||||
volume = 1.0f;
|
||||
|
||||
// Update smoothing and sprite based on volume.
|
||||
if (TryComp<IconSmoothComponent>(uid, out var smooth))
|
||||
|
|
@ -57,15 +53,10 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
|||
|
||||
var baseColor = Color.White;
|
||||
|
||||
if (args.AppearanceData.TryGetValue(PuddleVisuals.SolutionColor, out var colorObj))
|
||||
{
|
||||
var color = (Color)colorObj;
|
||||
_sprite.SetColor((uid, args.Sprite), color * baseColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sprite.SetColor((uid, args.Sprite), args.Sprite.Color * baseColor);
|
||||
}
|
||||
if (!args.TryGetData<Color>(PuddleVisuals.SolutionColor, out var color))
|
||||
color = args.Sprite.Color;
|
||||
|
||||
_sprite.SetColor((uid, args.Sprite), color * baseColor);
|
||||
}
|
||||
|
||||
#region Spill
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public sealed partial class GravitySystem : SharedGravitySystem
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (_appearanceSystem.TryGetData<PowerChargeStatus>(uid, PowerChargeVisuals.State, out var state, args.Component))
|
||||
if (args.TryGetData<PowerChargeStatus>(PowerChargeVisuals.State, out var state))
|
||||
{
|
||||
if (comp.SpriteMap.TryGetValue(state, out var spriteState))
|
||||
{
|
||||
|
|
@ -33,7 +33,7 @@ public sealed partial class GravitySystem : SharedGravitySystem
|
|||
}
|
||||
}
|
||||
|
||||
if (_appearanceSystem.TryGetData<float>(uid, PowerChargeVisuals.Charge, out var charge, args.Component))
|
||||
if (args.TryGetData<float>(PowerChargeVisuals.Charge, out var charge))
|
||||
{
|
||||
var layer = _sprite.LayerMapGet((uid, args.Sprite), GravityGeneratorVisualLayers.Core);
|
||||
switch (charge)
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
|
|||
|
||||
public GuideMicrowaveEmbed(string recipe) : this()
|
||||
{
|
||||
GenerateControl(_prototype.Index<FoodRecipePrototype>(recipe));
|
||||
GenerateControl(_prototype.Index<MicrowaveMealRecipePrototype>(recipe));
|
||||
}
|
||||
|
||||
public GuideMicrowaveEmbed(FoodRecipePrototype recipe) : this()
|
||||
public GuideMicrowaveEmbed(MicrowaveMealRecipePrototype recipe) : this()
|
||||
{
|
||||
GenerateControl(recipe);
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!_prototype.TryIndex<FoodRecipePrototype>(id, out var recipe))
|
||||
if (!_prototype.TryIndex<MicrowaveMealRecipePrototype>(id, out var recipe))
|
||||
{
|
||||
_sawmill.Error($"Specified recipe prototype \"{id}\" is not a valid recipe prototype");
|
||||
return false;
|
||||
|
|
@ -78,7 +78,7 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
|
|||
return true;
|
||||
}
|
||||
|
||||
private void GenerateHeader(FoodRecipePrototype recipe)
|
||||
private void GenerateHeader(MicrowaveMealRecipePrototype recipe)
|
||||
{
|
||||
var entity = _prototype.Index<EntityPrototype>(recipe.Result);
|
||||
|
||||
|
|
@ -89,9 +89,9 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
|
|||
ResultDescription.SetMarkup(entity.Description);
|
||||
}
|
||||
|
||||
private void GenerateSolidIngredients(FoodRecipePrototype recipe)
|
||||
private void GenerateSolidIngredients(MicrowaveMealRecipePrototype recipe)
|
||||
{
|
||||
foreach (var (product, amount) in recipe.IngredientsSolids.OrderByDescending(p => p.Value))
|
||||
foreach (var (product, amount) in recipe.Ingredients.Solids.OrderByDescending(p => p.Value))
|
||||
{
|
||||
var ingredient = _prototype.Index<EntityPrototype>(product);
|
||||
|
||||
|
|
@ -122,9 +122,9 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
|
|||
}
|
||||
}
|
||||
|
||||
private void GenerateLiquidIngredients(FoodRecipePrototype recipe)
|
||||
private void GenerateLiquidIngredients(MicrowaveMealRecipePrototype recipe)
|
||||
{
|
||||
foreach (var (product, amount) in recipe.IngredientsReagents.OrderByDescending(p => p.Value))
|
||||
foreach (var (product, amount) in recipe.Ingredients.Reagents.OrderByDescending(p => p.Value))
|
||||
{
|
||||
var reagent = _prototype.Index<ReagentPrototype>(product);
|
||||
|
||||
|
|
@ -165,22 +165,58 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
|
|||
}
|
||||
}
|
||||
|
||||
private void GenerateIngredients(FoodRecipePrototype recipe)
|
||||
private void GenerateStackIngredients(MicrowaveMealRecipePrototype recipe)
|
||||
{
|
||||
foreach (var (product, amount) in recipe.Ingredients.Stacks.OrderByDescending(p => p.Value))
|
||||
{
|
||||
var stack = _prototype.Index(product);
|
||||
|
||||
// stack icon
|
||||
|
||||
IngredientsGrid.AddChild(new GuideEntityEmbed(stack.Spawn, false, false));
|
||||
|
||||
// stack name
|
||||
|
||||
var stackName = Loc.GetString(stack.Name);
|
||||
var stackNameMsg = new FormattedMessage();
|
||||
stackNameMsg.AddMarkupOrThrow(Loc.GetString("guidebook-microwave-stack-name-display", ("stack", stackName)));
|
||||
stackNameMsg.Pop();
|
||||
|
||||
var stackNameLabel = new RichTextLabel();
|
||||
stackNameLabel.SetMessage(stackNameMsg);
|
||||
|
||||
IngredientsGrid.AddChild(stackNameLabel);
|
||||
|
||||
// stack quantity
|
||||
|
||||
var stackQuantityMsg = new FormattedMessage();
|
||||
stackQuantityMsg.AddMarkupOrThrow(Loc.GetString("guidebook-microwave-stack-quantity-display", ("amount", amount)));
|
||||
stackQuantityMsg.Pop();
|
||||
|
||||
var stackQuantityLabel = new RichTextLabel();
|
||||
stackQuantityLabel.SetMessage(stackQuantityMsg);
|
||||
|
||||
IngredientsGrid.AddChild(stackQuantityLabel);
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateIngredients(MicrowaveMealRecipePrototype recipe)
|
||||
{
|
||||
GenerateLiquidIngredients(recipe);
|
||||
GenerateStackIngredients(recipe);
|
||||
GenerateSolidIngredients(recipe);
|
||||
}
|
||||
|
||||
private void GenerateCookTime(FoodRecipePrototype recipe)
|
||||
private void GenerateCookTime(MicrowaveMealRecipePrototype recipe)
|
||||
{
|
||||
var msg = new FormattedMessage();
|
||||
msg.AddMarkupOrThrow(Loc.GetString("guidebook-microwave-cook-time", ("time", recipe.CookTime)));
|
||||
msg.AddMarkupOrThrow(Loc.GetString("guidebook-microwave-cook-time", ("time", recipe.Time)));
|
||||
msg.Pop();
|
||||
|
||||
CookTimeLabel.SetMessage(msg);
|
||||
}
|
||||
|
||||
private void GenerateControl(FoodRecipePrototype recipe)
|
||||
private void GenerateControl(MicrowaveMealRecipePrototype recipe)
|
||||
{
|
||||
GenerateHeader(recipe);
|
||||
GenerateIngredients(recipe);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public sealed partial class GuideMicrowaveGroupEmbed : BoxContainer, IDocumentTa
|
|||
|
||||
private void CreateEntries(string group)
|
||||
{
|
||||
var prototypes = _prototype.EnumeratePrototypes<FoodRecipePrototype>()
|
||||
var prototypes = _prototype.EnumeratePrototypes<MicrowaveMealRecipePrototype>()
|
||||
.Where(p => p.Group.Equals(group))
|
||||
.OrderBy(p => p.Name);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace Content.Client.Hands.Systems
|
|||
|
||||
[Dependency] private StrippableSystem _stripSys = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
[Dependency] private TransformSystem _renderTransforms = default!;
|
||||
[Dependency] private ExamineSystem _examine = default!;
|
||||
[Dependency] private DisplacementMapSystem _displacement = default!;
|
||||
|
||||
|
|
@ -112,9 +113,15 @@ namespace Content.Client.Hands.Systems
|
|||
EntityCoordinates? targetDropLocation = null
|
||||
)
|
||||
{
|
||||
TryGetHeldItem(ent, handId, out var held);
|
||||
base.DoDrop(ent, handId, doDropInteraction, log, targetDropLocation);
|
||||
|
||||
if (TryGetHeldItem(ent, handId, out var held) && TryComp(held, out SpriteComponent? sprite))
|
||||
if (held == null || IsHolding(ent, held.Value))
|
||||
return;
|
||||
|
||||
_renderTransforms.SnapRenderTransform(held.Value, true);
|
||||
|
||||
if (TryComp(held, out SpriteComponent? sprite))
|
||||
sprite.RenderOrder = EntityManager.CurrentTick.Value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public sealed partial class HolidaySystem : EntitySystem
|
|||
|
||||
private void OnAppearanceChange(Entity<HolidayRsiSwapComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!_appearance.TryGetData<string>(ent, HolidayVisuals.Holiday, out var data, args.Component))
|
||||
if (!args.TryGetData<string>(HolidayVisuals.Holiday, out var data))
|
||||
return;
|
||||
|
||||
var comp = ent.Comp;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
using System.Linq;
|
||||
using Content.Shared.Body;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
|
@ -14,9 +12,7 @@ namespace Content.Client.Humanoid;
|
|||
public sealed partial class OrganMarkingPicker : Control
|
||||
{
|
||||
[Dependency] private MarkingManager _marking = default!;
|
||||
[Dependency] private IEntityManager _entity = default!;
|
||||
|
||||
private readonly SpriteSystem _sprite;
|
||||
[Dependency] private ILocalizationManager _loc = default!;
|
||||
|
||||
private readonly MarkingsViewModel _markingsModel;
|
||||
private readonly HashSet<HumanoidVisualLayers> _layers;
|
||||
|
|
@ -33,8 +29,6 @@ public sealed partial class OrganMarkingPicker : Control
|
|||
_group = group;
|
||||
_organ = organ;
|
||||
|
||||
_sprite = _entity.System<SpriteSystem>();
|
||||
|
||||
UpdateMarkings();
|
||||
}
|
||||
|
||||
|
|
@ -79,10 +73,10 @@ public sealed partial class OrganMarkingPicker : Control
|
|||
|
||||
var control = new LayerMarkingPicker(_markingsModel, _organ, layer, allMarkings);
|
||||
LayerTabs.AddChild(control);
|
||||
if (Loc.TryGetString($"markings-layer-{layer}-{_group.Id}", out var layerTitle))
|
||||
if (_loc.TryGetString($"markings-layer-{layer}-{_group.Id}", out var layerTitle))
|
||||
LayerTabs.SetTabTitle(i, layerTitle);
|
||||
else
|
||||
LayerTabs.SetTabTitle(i, Loc.GetString($"markings-layer-{layer}"));
|
||||
LayerTabs.SetTabTitle(i, _loc.GetString($"markings-layer-{layer}"));
|
||||
i++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,21 +6,14 @@ namespace Content.Client.IconSmoothing;
|
|||
public sealed partial class ClientRandomIconSmoothSystem : SharedRandomIconSmoothSystem
|
||||
{
|
||||
[Dependency] private IconSmoothSystem _iconSmooth = default!;
|
||||
[Dependency] private AppearanceSystem _appearance = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<RandomIconSmoothComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(Entity<RandomIconSmoothComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!TryComp<IconSmoothComponent>(ent, out var smooth))
|
||||
return;
|
||||
|
||||
if (!_appearance.TryGetData<string>(ent, RandomIconSmoothState.State, out var state, args.Component))
|
||||
if (!args.TryGetData<string>(RandomIconSmoothState.State, out var state))
|
||||
return;
|
||||
|
||||
smooth.StateBase = state;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,24 @@
|
|||
using System.Numerics;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Storage;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Client.Interactable
|
||||
{
|
||||
// TODO Remove Shared prefix
|
||||
public sealed partial class InteractionSystem : SharedInteractionSystem;
|
||||
public sealed partial class InteractionSystem : SharedInteractionSystem
|
||||
{
|
||||
[Dependency] private TransformSystem _clientTransform = default!;
|
||||
|
||||
protected override bool TryFaceInteraction(EntityUid user, Vector2 coordinates)
|
||||
{
|
||||
var faced = base.TryFaceInteraction(user, coordinates);
|
||||
|
||||
if (faced)
|
||||
_clientTransform.SnapRenderRotation(user);
|
||||
|
||||
return faced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
using Content.Shared.Kitchen.Components;
|
||||
using Content.Shared.Kitchen.EntitySystems;
|
||||
using Robust.Client.Player;
|
||||
|
||||
namespace Content.Client.Kitchen.EntitySystems;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed partial class ClientMicrowaveSystem : MicrowaveSystem
|
||||
{
|
||||
[Dependency] private IPlayerManager _player = default!;
|
||||
[Dependency] private SharedUserInterfaceSystem _userInterface = default!;
|
||||
|
||||
public override void UpdateUI(Entity<MicrowaveComponent?> microwave)
|
||||
{
|
||||
base.UpdateUI(microwave);
|
||||
|
||||
if (!MicrowaveQuery.Resolve(microwave.Owner, ref microwave.Comp))
|
||||
return;
|
||||
|
||||
if (_userInterface.TryGetOpenUi(microwave.Owner, MicrowaveUiKey.Key, out var bui))
|
||||
bui.Update();
|
||||
}
|
||||
|
||||
protected override void ActivateMicrowaveCycle(Entity<MicrowaveComponent> ent)
|
||||
{
|
||||
base.ActivateMicrowaveCycle(ent);
|
||||
|
||||
if (!Timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
var audioParams = ent.Comp.LoopingSound.Params;
|
||||
audioParams = audioParams.WithLoop(true).WithMaxDistance(5);
|
||||
|
||||
ent.Comp.PlayingStream ??= Audio.PlayLocal(ent.Comp.LoopingSound, ent, _player.LocalEntity, audioParams)?.Entity;
|
||||
}
|
||||
|
||||
protected override void DeactivateMicrowaveCycle(Entity<MicrowaveComponent> ent)
|
||||
{
|
||||
base.DeactivateMicrowaveCycle(ent);
|
||||
|
||||
// We have this check here so Audio.Stop doesn't mistakenly tell us that the entity has been deleted when it hasn't been!!!
|
||||
if (!Timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
ent.Comp.PlayingStream = Audio.Stop(ent.Comp.PlayingStream);
|
||||
|
||||
foreach (var solid in GetMicrowaveContents(ent.AsNullable()))
|
||||
{
|
||||
RemComp<ActivelyMicrowavedComponent>(solid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,151 +1,128 @@
|
|||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Kitchen.Components;
|
||||
using Content.Shared.Kitchen.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Kitchen.UI
|
||||
namespace Content.Client.Kitchen.UI;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed partial class MicrowaveBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class MicrowaveBoundUserInterface : BoundUserInterface
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
[Dependency] private MicrowaveSystem _microwave = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private MicrowaveMenu? _menu;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly Dictionary<int, EntityUid> _solids = new();
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
[ViewVariables]
|
||||
private MicrowaveMenu? _menu;
|
||||
base.Open();
|
||||
|
||||
[ViewVariables]
|
||||
private readonly Dictionary<int, EntityUid> _solids = new();
|
||||
|
||||
[ViewVariables]
|
||||
private readonly Dictionary<int, ReagentQuantity> _reagents = new();
|
||||
|
||||
public MicrowaveBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
_menu = this.CreateWindow<MicrowaveMenu>();
|
||||
_menu.StartButton.OnPressed += _ => SendPredictedMessage(new MicrowaveStartCookMessage());
|
||||
_menu.EjectButton.OnPressed += _ => SendPredictedMessage(new MicrowaveEjectMessage());
|
||||
_menu.IngredientsList.OnItemSelected += args =>
|
||||
{
|
||||
}
|
||||
SendPredictedMessage(new MicrowaveEjectSolidIndexedMessage(EntMan.GetNetEntity(_solids[args.ItemIndex])));
|
||||
};
|
||||
|
||||
protected override void Open()
|
||||
_menu.OnCookTimeSelected += (name, index, cookTime) =>
|
||||
{
|
||||
base.Open();
|
||||
_menu = this.CreateWindow<MicrowaveMenu>();
|
||||
_menu.StartButton.OnPressed += _ => SendPredictedMessage(new MicrowaveStartCookMessage());
|
||||
_menu.EjectButton.OnPressed += _ => SendPredictedMessage(new MicrowaveEjectMessage());
|
||||
_menu.IngredientsList.OnItemSelected += args =>
|
||||
{
|
||||
SendPredictedMessage(new MicrowaveEjectSolidIndexedMessage(EntMan.GetNetEntity(_solids[args.ItemIndex])));
|
||||
};
|
||||
|
||||
_menu.OnCookTimeSelected += (args, buttonIndex) =>
|
||||
{
|
||||
var selectedCookTime = (uint) 0;
|
||||
|
||||
if (args.Button is MicrowaveMenu.MicrowaveCookTimeButton microwaveCookTimeButton)
|
||||
{
|
||||
// args.Button is a MicrowaveCookTimeButton
|
||||
var actualButton = (MicrowaveMenu.MicrowaveCookTimeButton) args.Button;
|
||||
selectedCookTime = actualButton.CookTime == 0 ? 0 : actualButton.CookTime;
|
||||
// SendMessage(new MicrowaveSelectCookTimeMessage((int) selectedCookTime / 5, actualButton.CookTime));
|
||||
SendPredictedMessage(new MicrowaveSelectCookTimeMessage((int) selectedCookTime / 5, actualButton.CookTime));
|
||||
|
||||
_menu.CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
|
||||
("time", selectedCookTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
// args.Button is a normal button aka instant cook button
|
||||
SendPredictedMessage(new MicrowaveSelectCookTimeMessage((int) selectedCookTime, 0));
|
||||
|
||||
_menu.CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
|
||||
("time", Loc.GetString("microwave-menu-instant-button")));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
if (state is not MicrowaveUpdateUserInterfaceState cState || _menu == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_menu.IsBusy = cState.IsMicrowaveBusy;
|
||||
_menu.CurrentCooktimeEnd = cState.CurrentCookTimeEnd;
|
||||
|
||||
_menu.ToggleBusyDisableOverlayPanel(cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0);
|
||||
// TODO move this to a component state and ensure the net ids.
|
||||
RefreshContentsDisplay(EntMan.GetEntityArray(cState.ContainedSolids));
|
||||
|
||||
//Set the cook time info label
|
||||
var cookTime = cState.ActiveButtonIndex == 0
|
||||
? Loc.GetString("microwave-menu-instant-button")
|
||||
: cState.CurrentCookTime.ToString();
|
||||
|
||||
|
||||
SendPredictedMessage(new MicrowaveSelectCookTimeMessage(index, cookTime));
|
||||
_menu.CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
|
||||
("time", cookTime));
|
||||
_menu.StartButton.Disabled = cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0;
|
||||
_menu.EjectButton.Disabled = cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0;
|
||||
("time", name));
|
||||
};
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
//Set the correct button active button
|
||||
if (cState.ActiveButtonIndex == 0)
|
||||
{
|
||||
_menu.InstantCookButton.Pressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var currentlySelectedTimeButton = (Button) _menu.CookTimeButtonVbox.GetChild(cState.ActiveButtonIndex - 1);
|
||||
currentlySelectedTimeButton.Pressed = true;
|
||||
}
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
//Set the "micowave light" ui color to indicate if the microwave is busy or not
|
||||
if (cState.IsMicrowaveBusy && cState.ContainedSolids.Length > 0)
|
||||
{
|
||||
_menu.IngredientsPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#947300") };
|
||||
}
|
||||
else
|
||||
{
|
||||
_menu.IngredientsPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#1B1B1E") };
|
||||
}
|
||||
}
|
||||
if (_menu is null || !EntMan.TryGetComponent<MicrowaveComponent>(Owner, out var comp))
|
||||
return;
|
||||
|
||||
private void RefreshContentsDisplay(EntityUid[] containedSolids)
|
||||
RefreshContentsDisplay();
|
||||
UpdateActiveDisplay(comp);
|
||||
|
||||
// Update the currently-selected cook time label and button
|
||||
var buttonIndex = comp.CurrentCookTimeButtonIndex;
|
||||
if (_menu.TryGetCookTimeButton(buttonIndex, out var button))
|
||||
button.Pressed = true;
|
||||
|
||||
var timeLabel = buttonIndex == 0
|
||||
? Loc.GetString("microwave-menu-instant-button")
|
||||
: comp.CurrentCookTimerTime.ToString();
|
||||
|
||||
_menu.CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
|
||||
("time", timeLabel));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the state of various controls in this menu based on the active / empty status of the microwave.
|
||||
/// </summary>
|
||||
private void UpdateActiveDisplay(MicrowaveComponent? comp)
|
||||
{
|
||||
if (_menu is null)
|
||||
return;
|
||||
|
||||
// Disable various UI controls if the microwave is active or empty
|
||||
var isActive = EntMan.TryGetComponent<ActiveMicrowaveComponent>(Owner, out var activeComp);
|
||||
var isEmpty = !_microwave.HasContents((Owner, comp));
|
||||
_menu.IsBusy = isActive;
|
||||
_menu.ToggleBusyDisableOverlayPanel(isActive);
|
||||
_menu.StartButton.Disabled = isActive || isEmpty;
|
||||
_menu.EjectButton.Disabled = isActive || isEmpty;
|
||||
|
||||
if (activeComp != null)
|
||||
_menu.CurrentCooktimeEnd = activeComp.CookTimeEnd;
|
||||
|
||||
// Set the "microwave light" panel color
|
||||
_menu.SetIngredientPanelLight(isActive && !isEmpty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the panel containing all of the microwave's contents.
|
||||
/// </summary>
|
||||
private void RefreshContentsDisplay()
|
||||
{
|
||||
if (_menu == null)
|
||||
return;
|
||||
|
||||
_solids.Clear();
|
||||
_menu.IngredientsList.Clear();
|
||||
foreach (var entity in _microwave.GetMicrowaveContents(Owner))
|
||||
{
|
||||
_reagents.Clear();
|
||||
if (EntMan.Deleted(entity))
|
||||
continue;
|
||||
|
||||
if (_menu == null) return;
|
||||
|
||||
_solids.Clear();
|
||||
_menu.IngredientsList.Clear();
|
||||
foreach (var entity in containedSolids)
|
||||
{
|
||||
if (EntMan.Deleted(entity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO just use sprite view
|
||||
|
||||
Texture? texture;
|
||||
if (EntMan.TryGetComponent<IconComponent>(entity, out var iconComponent))
|
||||
{
|
||||
texture = EntMan.System<SpriteSystem>().GetIcon(iconComponent);
|
||||
}
|
||||
else if (EntMan.TryGetComponent<SpriteComponent>(entity, out var spriteComponent))
|
||||
{
|
||||
texture = spriteComponent.Icon?.Default;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var solidItem = _menu.IngredientsList.AddItem(EntMan.GetComponent<MetaDataComponent>(entity).EntityName, texture);
|
||||
var solidIndex = _menu.IngredientsList.IndexOf(solidItem);
|
||||
_solids.Add(solidIndex, entity);
|
||||
}
|
||||
// TODO just use sprite view
|
||||
var itemIcon = GetEntityIcon(entity);
|
||||
var itemName = EntMan.GetComponent<MetaDataComponent>(entity).EntityName;
|
||||
var solidItem = _menu.IngredientsList.AddItem(itemName, itemIcon);
|
||||
var solidIndex = _menu.IngredientsList.IndexOf(solidItem);
|
||||
_solids.Add(solidIndex, entity);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the texture associated with an ingredient.
|
||||
/// </summary>
|
||||
/// <param name="uid">The ingredient entity.</param>
|
||||
private Texture? GetEntityIcon(EntityUid uid)
|
||||
{
|
||||
if (EntMan.TryGetComponent<IconComponent>(uid, out var icon))
|
||||
return _sprite.GetIcon(icon);
|
||||
|
||||
if (EntMan.TryGetComponent<SpriteComponent>(uid, out var sprite))
|
||||
return sprite.Icon?.Default;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
9
Content.Client/Kitchen/UI/MicrowaveCookTimeButton.xaml
Normal file
9
Content.Client/Kitchen/UI/MicrowaveCookTimeButton.xaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<Button xmlns="https://spacestation14.io"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
TextAlign="Center"
|
||||
ToggleMode="True"
|
||||
HorizontalExpand="True">
|
||||
<Button.StyleClasses>
|
||||
<system:String>OpenBoth</system:String>
|
||||
</Button.StyleClasses>
|
||||
</Button>
|
||||
39
Content.Client/Kitchen/UI/MicrowaveCookTimeButton.xaml.cs
Normal file
39
Content.Client/Kitchen/UI/MicrowaveCookTimeButton.xaml.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Kitchen.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class MicrowaveCookTimeButton : Button
|
||||
{
|
||||
public event Action<string, uint>? OnCookTimeSelected;
|
||||
private uint _cookTime = 0;
|
||||
|
||||
public uint CookTime
|
||||
{
|
||||
get => _cookTime;
|
||||
set
|
||||
{
|
||||
_cookTime = value;
|
||||
UpdateLabel();
|
||||
}
|
||||
}
|
||||
|
||||
public MicrowaveCookTimeButton()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
UpdateLabel();
|
||||
|
||||
OnPressed += _ => OnCookTimeSelected?.Invoke(Text ?? string.Empty, _cookTime);
|
||||
}
|
||||
|
||||
private void UpdateLabel()
|
||||
{
|
||||
var labelText = _cookTime == 0
|
||||
? Loc.GetString("microwave-menu-instant-button")
|
||||
: _cookTime.ToString();
|
||||
|
||||
Text = labelText;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:kitchen="clr-namespace:Content.Client.Kitchen.UI"
|
||||
Title="{Loc 'microwave-menu-title'}"
|
||||
MinWidth="512"
|
||||
MinSize="512 256">
|
||||
|
|
@ -49,15 +50,11 @@
|
|||
Align="Center"
|
||||
Modulate="#FFFFFF"
|
||||
VAlign="Center" />
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<Button
|
||||
<BoxContainer Orientation="Vertical" SeparationOverride="1">
|
||||
<kitchen:MicrowaveCookTimeButton
|
||||
Name="InstantCookButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'microwave-menu-instant-button'}"
|
||||
StyleClasses="OpenLeft"
|
||||
ToggleMode="True"
|
||||
Margin="0 0 2 0"
|
||||
TextAlign="Center" />
|
||||
CookTime="0"
|
||||
StyleClasses="OpenBoth"/>
|
||||
<GridContainer
|
||||
Name="CookTimeButtonVbox"
|
||||
HSeparationOverride="1"
|
||||
|
|
@ -71,6 +68,7 @@
|
|||
<BoxContainer
|
||||
Orientation="Vertical"
|
||||
Align="Center"
|
||||
SeparationOverride="1"
|
||||
SizeFlagsStretchRatio="3">
|
||||
<Control MinSize="0 15" />
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -1,83 +1,118 @@
|
|||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Kitchen.UI
|
||||
namespace Content.Client.Kitchen.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class MicrowaveMenu : FancyWindow
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class MicrowaveMenu : FancyWindow
|
||||
[Dependency] private IGameTiming _timing = default!;
|
||||
|
||||
public event Action<string, int, uint>? OnCookTimeSelected;
|
||||
|
||||
public ButtonGroup CookTimeButtonGroup { get; }
|
||||
public bool IsBusy;
|
||||
public TimeSpan CurrentCooktimeEnd;
|
||||
|
||||
private readonly StyleBoxFlat _ingredientsStylebox = new();
|
||||
|
||||
public MicrowaveMenu()
|
||||
{
|
||||
[Dependency] private IGameTiming _timing = default!;
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
public event Action<BaseButton.ButtonEventArgs, int>? OnCookTimeSelected;
|
||||
IngredientsPanel.PanelOverride = _ingredientsStylebox;
|
||||
|
||||
public ButtonGroup CookTimeButtonGroup { get; }
|
||||
CookTimeButtonGroup = new ButtonGroup();
|
||||
InstantCookButton.Group = CookTimeButtonGroup;
|
||||
InstantCookButton.OnCookTimeSelected += (name, cookTime) => OnCookTimeButtonPressed(name, 0, cookTime);
|
||||
|
||||
public bool IsBusy;
|
||||
public TimeSpan CurrentCooktimeEnd;
|
||||
|
||||
public MicrowaveMenu()
|
||||
for (var i = 1; i <= 6; i++)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
CookTimeButtonGroup = new ButtonGroup();
|
||||
InstantCookButton.Group = CookTimeButtonGroup;
|
||||
InstantCookButton.OnPressed += args =>
|
||||
var cookTime = i * 5;
|
||||
var newButton = new MicrowaveCookTimeButton
|
||||
{
|
||||
OnCookTimeSelected?.Invoke(args, 0);
|
||||
CookTime = (uint)cookTime,
|
||||
Group = CookTimeButtonGroup
|
||||
};
|
||||
|
||||
for (var i = 1; i <= 6; i++)
|
||||
{
|
||||
var newButton = new MicrowaveCookTimeButton
|
||||
{
|
||||
Text = (i * 5).ToString(),
|
||||
TextAlign = Label.AlignMode.Center,
|
||||
ToggleMode = true,
|
||||
CookTime = (uint) (i * 5),
|
||||
Group = CookTimeButtonGroup,
|
||||
HorizontalExpand = true,
|
||||
};
|
||||
if (i == 4)
|
||||
{
|
||||
newButton.StyleClasses.Add("OpenRight");
|
||||
}
|
||||
else
|
||||
{
|
||||
newButton.StyleClasses.Add("OpenBoth");
|
||||
}
|
||||
CookTimeButtonVbox.AddChild(newButton);
|
||||
newButton.OnPressed += args =>
|
||||
{
|
||||
OnCookTimeSelected?.Invoke(args, i);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleBusyDisableOverlayPanel(bool shouldDisable)
|
||||
{
|
||||
DisableCookingPanelOverlay.Visible = shouldDisable;
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (!IsBusy)
|
||||
return;
|
||||
|
||||
if (CurrentCooktimeEnd > _timing.CurTime)
|
||||
{
|
||||
CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
|
||||
("time", CurrentCooktimeEnd.Subtract(_timing.CurTime).Seconds));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MicrowaveCookTimeButton : Button
|
||||
{
|
||||
public uint CookTime;
|
||||
newButton.OnCookTimeSelected += (name, cookTime) => OnCookTimeButtonPressed(name, i, cookTime);
|
||||
CookTimeButtonVbox.AddChild(newButton);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCookTimeButtonPressed(string name, int index, uint cookTime)
|
||||
{
|
||||
OnCookTimeSelected?.Invoke(name, index, cookTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the visibility of the "busy overlay panel" over the microwave's ingredients,
|
||||
/// indicating to the player that the ingredients list cannot be interacted with
|
||||
/// (namely while the microwave is active.)
|
||||
/// </summary>
|
||||
/// <param name="shouldDisable">Whether or not this microwave is "busy".</param>
|
||||
public void ToggleBusyDisableOverlayPanel(bool shouldDisable)
|
||||
{
|
||||
DisableCookingPanelOverlay.Visible = shouldDisable;
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (!IsBusy)
|
||||
return;
|
||||
|
||||
var remaining = CurrentCooktimeEnd - _timing.CurTime;
|
||||
if (remaining > TimeSpan.Zero)
|
||||
{
|
||||
CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
|
||||
("time", Math.Ceiling(remaining.TotalSeconds)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the "color light" state of the ingredient panel's ingredient box.
|
||||
/// </summary>
|
||||
/// <param name="value">Wheether or not the panel is "lit" (yellow) or "unlit" (gray).</param>
|
||||
public void SetIngredientPanelLight(bool value)
|
||||
{
|
||||
var panelColor = value
|
||||
? Color.DarkGoldenrod
|
||||
: Color.FromHex("#1B1B1E");
|
||||
|
||||
_ingredientsStylebox.BackgroundColor = panelColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get the cook time button at the given index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index to select.</param>
|
||||
/// <param name="button">The cook time button, if found.</param>
|
||||
/// <returns>Whether or not this operation was successful.</returns>
|
||||
public bool TryGetCookTimeButton(int index,
|
||||
[NotNullWhen(true)] out Button? button)
|
||||
{
|
||||
button = null;
|
||||
|
||||
if (index == 0)
|
||||
button = InstantCookButton;
|
||||
else
|
||||
{
|
||||
if (index <= CookTimeButtonVbox.ChildCount)
|
||||
{
|
||||
var control = CookTimeButtonVbox.GetChild(index - 1);
|
||||
if (control is Button timeButton)
|
||||
button = timeButton;
|
||||
}
|
||||
}
|
||||
|
||||
return button != null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,12 @@ public sealed partial class KudzuVisualsSystem : VisualizerSystem<KudzuVisualsCo
|
|||
{
|
||||
protected override void OnAppearanceChange(EntityUid uid, KudzuVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
|
||||
if (args.Sprite == null)
|
||||
if (args.Sprite == null
|
||||
|| !args.TryGetData<int>(KudzuVisuals.Variant, out var variant)
|
||||
|| !args.TryGetData<int>(KudzuVisuals.GrowthLevel, out var level))
|
||||
return;
|
||||
if (AppearanceSystem.TryGetData<int>(uid, KudzuVisuals.Variant, out var var, args.Component)
|
||||
&& AppearanceSystem.TryGetData<int>(uid, KudzuVisuals.GrowthLevel, out var level, args.Component))
|
||||
{
|
||||
var index = SpriteSystem.LayerMapReserve((uid, args.Sprite), $"{component.Layer}");
|
||||
SpriteSystem.LayerSetRsiState((uid, args.Sprite), index, $"kudzu_{level}{var}");
|
||||
}
|
||||
|
||||
var index = SpriteSystem.LayerMapReserve((uid, args.Sprite), $"{component.Layer}");
|
||||
SpriteSystem.LayerSetRsiState((uid, args.Sprite), index, $"kudzu_{level}{variant}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public sealed partial class LatheSystem : SharedLatheSystem
|
|||
return;
|
||||
|
||||
// Lathe specific stuff
|
||||
if (_appearance.TryGetData<bool>(uid, LatheVisuals.IsRunning, out var isRunning, args.Component))
|
||||
if (args.TryGetData<bool>(LatheVisuals.IsRunning, out var isRunning))
|
||||
{
|
||||
if (_sprite.LayerMapTryGet((uid, args.Sprite), LatheVisualLayers.IsRunning, out var runningLayer, false) &&
|
||||
component.RunningState != null &&
|
||||
|
|
@ -35,7 +35,7 @@ public sealed partial class LatheSystem : SharedLatheSystem
|
|||
}
|
||||
}
|
||||
|
||||
if (_appearance.TryGetData<bool>(uid, PowerDeviceVisuals.Powered, out var powered, args.Component) &&
|
||||
if (args.TryGetData<bool>(PowerDeviceVisuals.Powered, out var powered) &&
|
||||
_sprite.LayerMapTryGet((uid, args.Sprite), PowerDeviceVisualLayers.Powered, out var powerLayer, false))
|
||||
{
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), powerLayer, powered);
|
||||
|
|
|
|||
|
|
@ -127,9 +127,6 @@ public sealed partial class AmbientOcclusionOverlay : Overlay
|
|||
|
||||
worldHandle.UseShader(_proto.Index(StencilEqualDrawShader).Instance());
|
||||
worldHandle.DrawTextureRect(res.AOTarget!.Texture, worldBounds, color);
|
||||
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
args.WorldHandle.UseShader(null);
|
||||
}
|
||||
|
||||
private void OnColorChanged(string value)
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ public sealed partial class EmergencyLightSystem : VisualizerSystem<EmergencyLig
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<bool>(uid, EmergencyLightVisuals.On, out var on, args.Component))
|
||||
if (!args.TryGetData<bool>(EmergencyLightVisuals.On, out var on))
|
||||
on = false;
|
||||
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), EmergencyLightVisualLayers.LightOff, !on);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), EmergencyLightVisualLayers.LightOn, on);
|
||||
|
||||
if (AppearanceSystem.TryGetData<Color>(uid, EmergencyLightVisuals.Color, out var color, args.Component))
|
||||
if (args.TryGetData<Color>(EmergencyLightVisuals.Color, out var color))
|
||||
{
|
||||
SpriteSystem.LayerSetColor((uid, args.Sprite), EmergencyLightVisualLayers.LightOn, color);
|
||||
SpriteSystem.LayerSetColor((uid, args.Sprite), EmergencyLightVisualLayers.LightOff, color);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public sealed partial class ExpendableLightSystem : VisualizerSystem<ExpendableL
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (AppearanceSystem.TryGetData<string>(uid, ExpendableLightVisuals.Behavior, out var lightBehaviourID, args.Component)
|
||||
if (args.TryGetData<string>(ExpendableLightVisuals.Behavior, out var lightBehaviourID)
|
||||
&& TryComp<LightBehaviourComponent>(uid, out var lightBehaviour))
|
||||
{
|
||||
_lightBehavior.StopLightBehaviour((uid, lightBehaviour));
|
||||
|
|
@ -43,7 +43,7 @@ public sealed partial class ExpendableLightSystem : VisualizerSystem<ExpendableL
|
|||
}
|
||||
}
|
||||
|
||||
if (!AppearanceSystem.TryGetData<ExpendableLightState>(uid, ExpendableLightVisuals.State, out var state, args.Component))
|
||||
if (!args.TryGetData<ExpendableLightState>(ExpendableLightVisuals.State, out var state))
|
||||
return;
|
||||
|
||||
switch (state)
|
||||
|
|
|
|||
|
|
@ -6,41 +6,35 @@ namespace Content.Client.Light.EntitySystems;
|
|||
|
||||
public sealed partial class LightBulbSystem : SharedLightBulbSystem
|
||||
{
|
||||
[Dependency] private AppearanceSystem _appearance = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<LightBulbComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, LightBulbComponent comp, ref AppearanceChangeEvent args)
|
||||
[SubscribeLocalEvent]
|
||||
private void OnAppearanceChange(Entity<LightBulbComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
// update sprite state
|
||||
if (_appearance.TryGetData<LightBulbState>(uid, LightBulbVisuals.State, out var state, args.Component))
|
||||
if (args.TryGetData<LightBulbState>(LightBulbVisuals.State, out var state))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case LightBulbState.Normal:
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.NormalSpriteState);
|
||||
_sprite.LayerSetRsiState((ent, args.Sprite), LightBulbVisualLayers.Base, ent.Comp.NormalSpriteState);
|
||||
break;
|
||||
case LightBulbState.Broken:
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.BrokenSpriteState);
|
||||
_sprite.LayerSetRsiState((ent, args.Sprite), LightBulbVisualLayers.Base, ent.Comp.BrokenSpriteState);
|
||||
break;
|
||||
case LightBulbState.Burned:
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.BurnedSpriteState);
|
||||
_sprite.LayerSetRsiState((ent, args.Sprite), LightBulbVisualLayers.Base, ent.Comp.BurnedSpriteState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// also update sprites color
|
||||
if (_appearance.TryGetData<Color>(uid, LightBulbVisuals.Color, out var color, args.Component))
|
||||
if (args.TryGetData<Color>(LightBulbVisuals.Color, out var color))
|
||||
{
|
||||
_sprite.SetColor((uid, args.Sprite), color);
|
||||
_sprite.SetColor((ent, args.Sprite), color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,9 +39,7 @@ public sealed partial class PlanetLightSystem : EntitySystem
|
|||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GetClearColorEvent>(OnClearColor);
|
||||
|
||||
_cfgManager.OnValueChanged(CCVars.AmbientOcclusion, val =>
|
||||
Subs.CVar(_cfgManager, CCVars.AmbientOcclusion, val =>
|
||||
{
|
||||
AmbientOcclusion = val;
|
||||
}, true);
|
||||
|
|
@ -54,11 +52,6 @@ public sealed partial class PlanetLightSystem : EntitySystem
|
|||
_overlayMan.AddOverlay(new AfterLightTargetOverlay());
|
||||
}
|
||||
|
||||
private void OnClearColor(ref GetClearColorEvent ev)
|
||||
{
|
||||
ev.Color = Color.Transparent;
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
|
@ -70,4 +63,10 @@ public sealed partial class PlanetLightSystem : EntitySystem
|
|||
_overlayMan.RemoveOverlay<AfterLightTargetOverlay>();
|
||||
_overlayMan.RemoveOverlay<AmbientOcclusionOverlay>();
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnClearColor(ref GetClearColorEvent ev)
|
||||
{
|
||||
ev.Color = Color.Transparent;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,40 +39,34 @@ public sealed partial class HandheldLightSystem : SharedHandheldLightSystem
|
|||
|
||||
private void OnAppearanceChange(EntityUid uid, HandheldLightComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!_appearance.TryGetData<bool>(uid, ToggleableVisuals.Enabled, out var enabled, args.Component))
|
||||
{
|
||||
if (!args.TryGetData<bool>(ToggleableVisuals.Enabled, out var enabled))
|
||||
return;
|
||||
|
||||
if (!args.TryGetData<HandheldLightPowerStates>(HandheldLightVisuals.Power, out var state))
|
||||
return;
|
||||
|
||||
if (!TryComp<LightBehaviourComponent>(uid, out var lightBehaviour))
|
||||
return;
|
||||
|
||||
// Reset any running behaviour to reset the animated properties back to the original value, to avoid conflicts between resets
|
||||
if (_lightBehavior.HasRunningBehaviours((uid, lightBehaviour)))
|
||||
{
|
||||
_lightBehavior.StopLightBehaviour((uid, lightBehaviour), resetToOriginalSettings: true);
|
||||
}
|
||||
|
||||
if (!_appearance.TryGetData<HandheldLightPowerStates>(uid, HandheldLightVisuals.Power, out var state, args.Component))
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp<LightBehaviourComponent>(uid, out var lightBehaviour))
|
||||
switch (state)
|
||||
{
|
||||
// Reset any running behaviour to reset the animated properties back to the original value, to avoid conflicts between resets
|
||||
if (_lightBehavior.HasRunningBehaviours((uid, lightBehaviour)))
|
||||
{
|
||||
_lightBehavior.StopLightBehaviour((uid, lightBehaviour), resetToOriginalSettings: true);
|
||||
}
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case HandheldLightPowerStates.FullPower:
|
||||
break; // We just needed to reset all behaviours
|
||||
case HandheldLightPowerStates.LowPower:
|
||||
_lightBehavior.StartLightBehaviour((uid, lightBehaviour), component.RadiatingBehaviourId);
|
||||
break;
|
||||
case HandheldLightPowerStates.Dying:
|
||||
_lightBehavior.StartLightBehaviour((uid, lightBehaviour), component.BlinkingBehaviourId);
|
||||
break;
|
||||
}
|
||||
case HandheldLightPowerStates.FullPower:
|
||||
break; // We just needed to reset all behaviours
|
||||
case HandheldLightPowerStates.LowPower:
|
||||
_lightBehavior.StartLightBehaviour((uid, lightBehaviour), component.RadiatingBehaviourId);
|
||||
break;
|
||||
case HandheldLightPowerStates.Dying:
|
||||
_lightBehavior.StartLightBehaviour((uid, lightBehaviour), component.BlinkingBehaviourId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,5 @@ public sealed partial class RoofOverlay : Overlay
|
|||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
worldHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Shared.Light.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
|
|
@ -21,7 +22,7 @@ public sealed partial class SunShadowOverlay : Overlay
|
|||
[Dependency] private IPrototypeManager _protoManager = default!;
|
||||
private readonly EntityLookupSystem _lookup;
|
||||
private readonly SharedMapSystem _mapSys;
|
||||
private readonly SharedTransformSystem _xformSys;
|
||||
private readonly TransformSystem _xformSys;
|
||||
|
||||
private readonly HashSet<Entity<SunShadowCastComponent>> _shadows = new();
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ public sealed partial class SunShadowOverlay : Overlay
|
|||
public SunShadowOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_xformSys = _entManager.System<SharedTransformSystem>();
|
||||
_xformSys = _entManager.System<TransformSystem>();
|
||||
_mapSys = _entManager.System<SharedMapSystem>();
|
||||
_lookup = _entManager.System<EntityLookupSystem>();
|
||||
ZIndex = AfterLightTargetOverlay.ContentZIndex + 1;
|
||||
|
|
@ -119,7 +120,7 @@ public sealed partial class SunShadowOverlay : Overlay
|
|||
foreach (var ent in _shadows)
|
||||
{
|
||||
var xform = _entManager.GetComponent<TransformComponent>(ent.Owner);
|
||||
var (worldPos, worldRot) = _xformSys.GetWorldPositionRotation(xform);
|
||||
var (worldPos, worldRot) = _xformSys.GetRenderWorldPositionRotation((ent.Owner, xform));
|
||||
// Need no rotation on matrix as sun shadow direction doesn't care.
|
||||
var worldMatrix = Matrix3x2.CreateTranslation(worldPos);
|
||||
var renderMatrix = Matrix3x2.Multiply(worldMatrix, invMatrix);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public sealed partial class PoweredLightVisualizerSystem : VisualizerSystem<Powe
|
|||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<PoweredLightState>(uid, PoweredLightVisuals.BulbState, out var state, args.Component))
|
||||
if (!args.TryGetData<PoweredLightState>(PoweredLightVisuals.BulbState, out var state))
|
||||
return;
|
||||
|
||||
if (comp.SpriteStateMap.TryGetValue(state, out var spriteState))
|
||||
|
|
@ -42,7 +42,7 @@ public sealed partial class PoweredLightVisualizerSystem : VisualizerSystem<Powe
|
|||
SetBlinkingAnimation(
|
||||
uid,
|
||||
state == PoweredLightState.On
|
||||
&& (AppearanceSystem.TryGetData<bool>(uid, PoweredLightVisuals.Blinking, out var isBlinking, args.Component) && isBlinking),
|
||||
&& (args.TryGetData<bool>(PoweredLightVisuals.Blinking, out var isBlinking) && isBlinking),
|
||||
comp
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue