Get rid of the OverlayEffectsComponent stuff (#3010)

* Get rid of the OverlayEffectsComponent stuff because it just ended up creating workarounds for it's bugs, without removing any functionality

* Flashes and Flashbangs use the same code now (the Flashable path because it's better)
This commit is contained in:
20kdc
2021-01-24 08:17:45 +00:00
committed by GitHub
parent 329d599107
commit e53ae365a3
21 changed files with 65 additions and 659 deletions

View File

@@ -13,6 +13,7 @@ using Content.Client.StationEvents;
using Content.Client.UserInterface;
using Content.Client.UserInterface.AdminMenu;
using Content.Client.UserInterface.Stylesheets;
using Content.Client.Graphics.Overlays;
using Content.Shared.Actions;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.Components.Cargo;
@@ -149,7 +150,12 @@ namespace Content.Client
IoCManager.Resolve<IGameHud>().Initialize();
IoCManager.Resolve<IClientNotifyManager>().Initialize();
IoCManager.Resolve<IClientGameTicker>().Initialize();
IoCManager.Resolve<IOverlayManager>().AddOverlay(new ParallaxOverlay());
var overlayMgr = IoCManager.Resolve<IOverlayManager>();
overlayMgr.AddOverlay(new ParallaxOverlay());
overlayMgr.AddOverlay(new GradientCircleMaskOverlay());
overlayMgr.AddOverlay(new CircleMaskOverlay());
overlayMgr.AddOverlay(new FlashOverlay());
overlayMgr.AddOverlay(new RadiationPulseOverlay());
IoCManager.Resolve<IChatManager>().Initialize();
IoCManager.Resolve<ISandboxManager>().Initialize();
IoCManager.Resolve<IClientPreferencesManager>().Initialize();

View File

@@ -1,169 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.Interfaces;
using Robust.Client.GameObjects;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Interfaces.Graphics.Overlays;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Players;
using Robust.Shared.ViewVariables;
namespace Content.Client.GameObjects.Components.Mobs
{
/// <summary>
/// A character UI component which shows the current damage state of the mob (living/dead)
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(SharedOverlayEffectsComponent))]
public sealed class ClientOverlayEffectsComponent : SharedOverlayEffectsComponent//, ICharacterUI
{
[Dependency] private readonly IOverlayManager _overlayManager = default!;
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
[Dependency] private readonly IClientNetManager _netManager = default!;
/// <summary>
/// A list of overlay containers representing the current overlays applied
/// </summary>
private List<OverlayContainer> _currentEffects = new();
[ViewVariables(VVAccess.ReadOnly)]
public List<OverlayContainer> ActiveOverlays
{
get => _currentEffects;
set => SetEffects(value);
}
public override void Initialize()
{
base.Initialize();
UpdateOverlays();
}
public override void HandleMessage(ComponentMessage message, IComponent component)
{
switch (message)
{
case PlayerAttachedMsg _:
UpdateOverlays();
break;
case PlayerDetachedMsg _:
ActiveOverlays.ForEach(o => _overlayManager.RemoveOverlay(o.ID));
break;
}
}
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
{
base.HandleNetworkMessage(message, netChannel, session);
if (message is OverlayEffectComponentMessage overlayMessage)
{
SetEffects(overlayMessage.Overlays);
}
}
private void UpdateOverlays()
{
_currentEffects = _overlayManager.AllOverlays
.Where(overlay => Enum.IsDefined(typeof(SharedOverlayID), overlay.ID))
.Select(overlay => new OverlayContainer(overlay.ID))
.ToList();
foreach (var overlayContainer in ActiveOverlays)
{
if (!_overlayManager.HasOverlay(overlayContainer.ID))
{
if (TryCreateOverlay(overlayContainer, out var overlay))
{
_overlayManager.AddOverlay(overlay);
}
}
}
SendNetworkMessage(new ResendOverlaysMessage(), _netManager.ServerChannel);
}
private void SetEffects(List<OverlayContainer> newOverlays)
{
foreach (var container in ActiveOverlays.ToArray())
{
if (!newOverlays.Contains(container))
{
RemoveOverlay(container);
}
}
foreach (var container in newOverlays)
{
if (!ActiveOverlays.Contains(container))
{
AddOverlay(container);
}
else
{
UpdateOverlayConfiguration(container, _overlayManager.GetOverlay(container.ID));
}
}
_currentEffects = newOverlays;
}
private void RemoveOverlay(OverlayContainer container)
{
ActiveOverlays.Remove(container);
_overlayManager.RemoveOverlay(container.ID);
}
private void AddOverlay(OverlayContainer container)
{
if (_overlayManager.HasOverlay(container.ID))
{
return;
}
ActiveOverlays.Add(container);
if (TryCreateOverlay(container, out var overlay))
{
_overlayManager.AddOverlay(overlay);
}
else
{
Logger.ErrorS("overlay", $"Could not add overlay {container.ID}");
}
}
private void UpdateOverlayConfiguration(OverlayContainer container, Overlay overlay)
{
if (overlay is IConfigurableOverlay configurable)
{
foreach (var param in container.Parameters)
{
configurable.Configure(param);
}
}
}
private bool TryCreateOverlay(OverlayContainer container, out Overlay overlay)
{
var overlayTypes = _reflectionManager.GetAllChildren<Overlay>();
var overlayType = overlayTypes.FirstOrDefault(t => t.Name == container.ID);
if (overlayType != null)
{
overlay = IoCManager.Resolve<IDynamicTypeFactory>().CreateInstance<Overlay>(overlayType);
UpdateOverlayConfiguration(container, overlay);
return true;
}
overlay = default;
return false;
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Threading;
using Content.Client.Graphics.Overlays;
using Content.Shared.GameObjects.Components.Weapons;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays;
@@ -19,10 +20,8 @@ namespace Content.Client.GameObjects.Components.Weapons
[RegisterComponent]
public sealed class FlashableComponent : SharedFlashableComponent
{
private CancellationTokenSource _cancelToken;
private TimeSpan _startTime;
private double _duration;
private FlashOverlay _overlay;
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
{
@@ -57,94 +56,15 @@ namespace Content.Client.GameObjects.Components.Weapons
if (currentTime > newEndTime)
{
DisableOverlay();
return;
}
_startTime = newState.Time;
_duration = newState.Duration;
EnableOverlay(newEndTime - currentTime);
}
private void EnableOverlay(double duration)
{
// If the timer gets reset
if (_overlay != null)
{
_overlay.Duration = _duration;
_overlay.StartTime = _startTime;
_cancelToken.Cancel();
}
else
{
var overlayManager = IoCManager.Resolve<IOverlayManager>();
_overlay = new FlashOverlay(_duration);
overlayManager.AddOverlay(_overlay);
}
_cancelToken = new CancellationTokenSource();
Owner.SpawnTimer((int) duration * 1000, DisableOverlay, _cancelToken.Token);
}
private void DisableOverlay()
{
if (_overlay == null)
{
return;
}
var overlayManager = IoCManager.Resolve<IOverlayManager>();
overlayManager.RemoveOverlay(_overlay.ID);
_overlay = null;
_cancelToken.Cancel();
_cancelToken = null;
}
}
public sealed class FlashOverlay : Overlay
{
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
private readonly IGameTiming _timer;
private readonly IClyde _displayManager;
public TimeSpan StartTime { get; set; }
public double Duration { get; set; }
public FlashOverlay(double duration) : base(nameof(FlashOverlay))
{
_timer = IoCManager.Resolve<IGameTiming>();
_displayManager = IoCManager.Resolve<IClyde>();
StartTime = _timer.CurTime;
Duration = duration;
}
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{
var elapsedTime = (_timer.CurTime - StartTime).TotalSeconds;
if (elapsedTime > Duration)
{
return;
}
var screenHandle = (DrawingHandleScreen) handle;
screenHandle.DrawRect(
new UIBox2(0.0f, 0.0f, _displayManager.ScreenSize.X, _displayManager.ScreenSize.Y),
Color.White.WithAlpha(GetAlpha(elapsedTime / Duration))
);
}
private float GetAlpha(double ratio)
{
// Ideally you just want a smooth slope to finish it so it's not jarring at the end
// By all means put in a better curve
const float slope = -9.0f;
const float exponent = 0.1f;
const float yOffset = 9.0f;
const float xOffset = 0.0f;
// Overkill but easy to adjust if you want to mess around with the design
var result = (float) MathHelper.Clamp(slope * (float) Math.Pow(ratio - xOffset, exponent) + yOffset, 0.0, 1.0);
DebugTools.Assert(!float.IsNaN(result));
return result;
var overlay = overlayManager.GetOverlay<FlashOverlay>(nameof(FlashOverlay));
overlay.ReceiveFlash(_duration);
}
}
}

View File

@@ -3,6 +3,7 @@ using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Graphics.Shaders;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Player;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
@@ -13,11 +14,12 @@ namespace Content.Client.Graphics.Overlays
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _shader;
public CircleMaskOverlay() : base(nameof(SharedOverlayID.CircleMaskOverlay))
public CircleMaskOverlay() : base(nameof(CircleMaskOverlay))
{
IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("CircleMask").Instance();
@@ -25,6 +27,8 @@ namespace Content.Client.Graphics.Overlays
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{
if (!GradientCircleMaskOverlay.LocalPlayerHasState(_playerManager, false, true))
return;
handle.UseShader(_shader);
var worldHandle = (DrawingHandleWorld)handle;
var viewport = _eyeManager.GetWorldViewport();

View File

@@ -1,5 +1,6 @@
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.Interfaces;
using Content.Shared.Network.NetMessages;
using Robust.Client.Graphics;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays;
@@ -14,7 +15,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace Content.Client.Graphics.Overlays
{
public class FlashOverlay : Overlay, IConfigurableOverlay
public class FlashOverlay : Overlay
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IClyde _displayManager = default!;
@@ -22,27 +23,33 @@ namespace Content.Client.Graphics.Overlays
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
private readonly ShaderInstance _shader;
private readonly double _startTime;
private int _lastsFor = 5000;
private double _startTime = -1;
private double _lastsFor = 1;
private Texture _screenshotTexture;
public FlashOverlay() : base(nameof(SharedOverlayID.FlashOverlay))
public FlashOverlay() : base(nameof(FlashOverlay))
{
IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").Instance().Duplicate();
}
_startTime = _gameTiming.CurTime.TotalMilliseconds;
public void ReceiveFlash(double duration)
{
_displayManager.Screenshot(ScreenshotType.BeforeUI, image =>
{
var rgba32Image = image.CloneAs<Rgba32>(Configuration.Default);
_screenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image);
});
_startTime = _gameTiming.CurTime.TotalSeconds;
_lastsFor = duration;
}
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{
var percentComplete = (float) ((_gameTiming.CurTime.TotalSeconds - _startTime) / _lastsFor);
if (percentComplete >= 1.0f)
return;
handle.UseShader(_shader);
var percentComplete = (float) ((_gameTiming.CurTime.TotalMilliseconds - _startTime) / _lastsFor);
_shader?.SetParameter("percentComplete", percentComplete);
var screenSpaceHandle = handle as DrawingHandleScreen;
@@ -60,13 +67,5 @@ namespace Content.Client.Graphics.Overlays
_screenshotTexture = null;
}
public void Configure(OverlayParameter parameters)
{
if (parameters is TimedOverlayParameter timedParams)
{
_lastsFor = timedParams.Length;
}
}
}
}

View File

@@ -1,8 +1,10 @@
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Mobs.State;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Graphics.Shaders;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Player;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
@@ -13,18 +15,43 @@ namespace Content.Client.Graphics.Overlays
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _shader;
public GradientCircleMaskOverlay() : base(nameof(SharedOverlayID.GradientCircleMaskOverlay))
public GradientCircleMaskOverlay() : base(nameof(GradientCircleMaskOverlay))
{
IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("GradientCircleMask").Instance();
}
public static bool LocalPlayerHasState(IPlayerManager pm, bool critical, bool dead) {
var playerEntity = pm.LocalPlayer?.ControlledEntity;
if (playerEntity == null)
{
return false;
}
if (playerEntity.TryGetComponent<IMobStateComponent>(out var mobState))
{
if (critical)
if (mobState.IsCritical())
return true;
if (dead)
if (mobState.IsDead())
return true;
}
return false;
}
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{
if (!LocalPlayerHasState(_playerManager, true, false))
return;
handle.UseShader(_shader);
var worldHandle = (DrawingHandleWorld)handle;
var viewport = _eyeManager.GetWorldViewport();

View File

@@ -47,7 +47,7 @@ namespace Content.Client.StationEvents
// TODO: When worldHandle can do DrawCircle change this.
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
public RadiationPulseOverlay() : base(nameof(SharedOverlayID.RadiationPulseOverlay))
public RadiationPulseOverlay() : base(nameof(RadiationPulseOverlay))
{
IoCManager.InjectDependencies(this);
_lastTick = _gameTiming.CurTime;

View File

@@ -1,33 +0,0 @@
using Content.Server.Administration;
using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player;
namespace Content.Server.Commands.Mobs
{
[AdminCommand(AdminFlags.Debug)]
public class AddOverlayCommand : IClientCommand
{
public string Command => "addoverlay";
public string Description => "Adds an overlay by its ID";
public string Help => "addoverlay <id>";
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args)
{
if (args.Length != 1)
{
shell.SendText(player, "Expected 1 argument.");
return;
}
if (player?.AttachedEntity != null)
{
if (player.AttachedEntity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent))
{
overlayEffectsComponent.AddOverlay(args[0]);
}
}
}
}
}

View File

@@ -1,33 +0,0 @@
using Content.Server.Administration;
using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player;
namespace Content.Server.Commands.Mobs
{
[AdminCommand(AdminFlags.Debug)]
public class RemoveOverlayCommand : IClientCommand
{
public string Command => "rmoverlay";
public string Description => "Removes an overlay by its ID";
public string Help => "rmoverlay <id>";
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args)
{
if (args.Length != 1)
{
shell.SendText(player, "Expected 1 argument.");
return;
}
if (player?.AttachedEntity != null)
{
if (player.AttachedEntity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent))
{
overlayEffectsComponent.RemoveOverlay(args[0]);
}
}
}
}
}

View File

@@ -1,95 +0,0 @@
using System;
using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Mobs;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Players;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Mobs
{
[RegisterComponent]
[ComponentReference(typeof(SharedOverlayEffectsComponent))]
public sealed class ServerOverlayEffectsComponent : SharedOverlayEffectsComponent
{
public ServerOverlayEffectsComponent()
{
NetSyncEnabled = false;
}
[ViewVariables(VVAccess.ReadWrite)]
public List<OverlayContainer> ActiveOverlays { get; } = new();
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
{
if (Owner.TryGetComponent(out IActorComponent actor) && message is ResendOverlaysMessage)
{
if (actor.playerSession.ConnectedClient == netChannel)
{
SyncClient();
}
}
}
public void AddOverlay(string id) => AddOverlay(new OverlayContainer(id));
public void AddOverlay(SharedOverlayID id) => AddOverlay(new OverlayContainer(id));
public void AddOverlay(OverlayContainer container)
{
if (!ActiveOverlays.Contains(container))
{
ActiveOverlays.Add(container);
SyncClient();
}
}
public void RemoveOverlay(SharedOverlayID id) => RemoveOverlay(id.ToString());
public void RemoveOverlay(string id) => RemoveOverlay(new OverlayContainer(id));
public void RemoveOverlay(OverlayContainer container)
{
if (ActiveOverlays.Remove(container))
{
SyncClient();
}
}
public bool TryModifyOverlay(string id, Action<OverlayContainer> modifications)
{
var overlay = ActiveOverlays.Find(c => c.ID == id);
if (overlay == null)
{
return false;
}
modifications(overlay);
SyncClient();
return true;
}
public void ClearOverlays()
{
if (ActiveOverlays.Count == 0)
{
return;
}
ActiveOverlays.Clear();
SyncClient();
}
private void SyncClient()
{
if (Owner.TryGetComponent(out IActorComponent actor))
{
if (actor.playerSession.ConnectedClient.IsConnected)
{
SendNetworkMessage(new OverlayEffectComponentMessage(ActiveOverlays), actor.playerSession.ConnectedClient);
}
}
}
}
}

View File

@@ -20,11 +20,6 @@ namespace Content.Server.GameObjects.Components.Mobs.State
appearance.SetData(DamageStateVisuals.State, DamageState.Critical);
}
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay))
{
overlay.AddOverlay(SharedOverlayID.GradientCircleMaskOverlay);
}
if (entity.TryGetComponent(out StunnableComponent stun))
{
stun.CancelAll();
@@ -36,11 +31,6 @@ namespace Content.Server.GameObjects.Components.Mobs.State
public override void ExitState(IEntity entity)
{
base.ExitState(entity);
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay))
{
overlay.ClearOverlays();
}
}
}
}

View File

@@ -26,11 +26,6 @@ namespace Content.Server.GameObjects.Components.Mobs.State
status.ShowAlert(AlertType.HumanDead);
}
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlayComponent))
{
overlayComponent.AddOverlay(SharedOverlayID.CircleMaskOverlay);
}
if (entity.TryGetComponent(out StunnableComponent stun))
{
stun.CancelAll();
@@ -52,11 +47,6 @@ namespace Content.Server.GameObjects.Components.Mobs.State
{
physics.CanCollide = true;
}
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay))
{
overlay.ClearOverlays();
}
}
}
}

View File

@@ -8,15 +8,5 @@ namespace Content.Server.GameObjects.Components.Mobs.State
[ComponentReference(typeof(IMobStateComponent))]
public class MobStateComponent : SharedMobStateComponent
{
public override void OnRemove()
{
// TODO: Might want to add an OnRemove() to IMobState since those are where these components are being used
if (Owner.TryGetComponent(out ServerOverlayEffectsComponent overlay))
{
overlay.ClearOverlays();
}
base.OnRemove();
}
}
}

View File

@@ -4,13 +4,17 @@ using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Network.NetMessages;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.Player;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Timers;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
@@ -128,22 +132,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
}
// TODO: Check if target can be flashed (e.g. things like sunglasses would block a flash)
// TODO: Merge with the code in FlashableComponent
private void Flash(IEntity entity, IEntity user, int flashDuration)
{
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent))
if (entity.TryGetComponent(out FlashableComponent flashable))
{
if (!overlayEffectsComponent.TryModifyOverlay(nameof(SharedOverlayID.FlashOverlay),
overlay =>
{
if (overlay.TryGetOverlayParameter<TimedOverlayParameter>(out var timed))
{
timed.Length += flashDuration;
}
}))
{
var container = new OverlayContainer(SharedOverlayID.FlashOverlay, new TimedOverlayParameter(flashDuration));
overlayEffectsComponent.AddOverlay(container);
}
flashable.Flash(flashDuration / 1000d);
}
if (entity.TryGetComponent(out StunnableComponent stunnableComponent))

View File

@@ -1,35 +0,0 @@
using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Mobs;
using JetBrains.Annotations;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
namespace Content.Server.GameObjects.EntitySystems
{
[UsedImplicitly]
internal sealed class TimedOverlayRemovalSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var component in ComponentManager.EntityQuery<ServerOverlayEffectsComponent>())
{
foreach (var overlay in component.ActiveOverlays.ToArray())
{
if (overlay.TryGetOverlayParameter<TimedOverlayParameter>(out var parameter))
{
if (parameter.StartedAt + parameter.Length <= _gameTiming.CurTime.TotalMilliseconds)
{
component.RemoveOverlay(overlay);
}
}
}
}
}
}
}

View File

@@ -85,12 +85,6 @@ namespace Content.Server.GameTicking
var ghostComponent = ghost.GetComponent<GhostComponent>();
ghostComponent.CanReturnToBody = canReturn;
if (playerEntity != null &&
playerEntity.TryGetComponent(out ServerOverlayEffectsComponent? overlayComponent))
{
overlayComponent.RemoveOverlay(SharedOverlayID.CircleMaskOverlay);
}
if (canReturn)
mind.Visit(ghost);
else

View File

@@ -1,6 +1,7 @@
using Content.Server.Administration;
using Content.Server.Interfaces;
using Content.Shared;
using Content.Shared.Network.NetMessages;
using Content.Shared.Administration;
using Content.Shared.Interfaces;
using Robust.Server.Interfaces.Console;

View File

@@ -51,25 +51,11 @@ namespace Content.Server.StationEvents
public override void Startup()
{
ResetTimeUntilPulse();
var componentManager = IoCManager.Resolve<IComponentManager>();
foreach (var overlay in componentManager.EntityQuery<ServerOverlayEffectsComponent>())
{
overlay.AddOverlay(SharedOverlayID.RadiationPulseOverlay);
}
base.Startup();
}
public override void Shutdown()
{
var componentManager = IoCManager.Resolve<IComponentManager>();
foreach (var overlay in componentManager.EntityQuery<ServerOverlayEffectsComponent>())
{
overlay.RemoveOverlay(SharedOverlayID.RadiationPulseOverlay);
}
base.Shutdown();
}

View File

@@ -1,120 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Mobs
{
/// <summary>
/// Full screen overlays; Blindness, death, flash, alcohol etc.
/// </summary>
public abstract class SharedOverlayEffectsComponent : Component
{
public override string Name => "OverlayEffectsUI";
public sealed override uint? NetID => ContentNetIDs.OVERLAYEFFECTS;
}
[Serializable, NetSerializable]
public class OverlayContainer : IEquatable<string>, IEquatable<OverlayContainer>
{
[ViewVariables(VVAccess.ReadOnly)]
public string ID { get; }
[ViewVariables(VVAccess.ReadWrite)]
public List<OverlayParameter> Parameters { get; } = new();
public OverlayContainer([NotNull] string id)
{
ID = id;
}
public OverlayContainer(SharedOverlayID id) : this(id.ToString())
{
}
public OverlayContainer(SharedOverlayID id, params OverlayParameter[] parameters) : this(id)
{
Parameters.AddRange(parameters);
}
public bool TryGetOverlayParameter<T>(out T parameter) where T : OverlayParameter
{
var found = Parameters.FirstOrDefault(p => p is T);
if (found != null)
{
parameter = found as T;
return true;
}
parameter = default;
return false;
}
public bool Equals(string other)
{
return ID == other;
}
public bool Equals(OverlayContainer other)
{
return ID == other?.ID;
}
public override int GetHashCode()
{
return ID != null ? ID.GetHashCode() : 0;
}
}
[Serializable, NetSerializable]
public class OverlayEffectComponentMessage : ComponentMessage
{
public List<OverlayContainer> Overlays;
public OverlayEffectComponentMessage(List<OverlayContainer> overlays)
{
Directed = true;
Overlays = overlays;
}
}
[Serializable, NetSerializable]
public class ResendOverlaysMessage : ComponentMessage
{
}
[Serializable, NetSerializable]
public abstract class OverlayParameter
{
}
[Serializable, NetSerializable]
public class TimedOverlayParameter : OverlayParameter
{
[ViewVariables(VVAccess.ReadOnly)]
public int Length { get; set; }
public double StartedAt { get; private set; }
public TimedOverlayParameter(int length)
{
Length = length;
StartedAt = IoCManager.Resolve<IGameTiming>().CurTime.TotalMilliseconds;
}
}
public enum SharedOverlayID
{
GradientCircleMaskOverlay,
CircleMaskOverlay,
FlashOverlay,
RadiationPulseOverlay,
}
}

View File

@@ -1,9 +0,0 @@
using Content.Shared.GameObjects.Components.Mobs;
namespace Content.Shared.Interfaces
{
public interface IConfigurableOverlay
{
void Configure(OverlayParameter parameter);
}
}

View File

@@ -15,7 +15,6 @@
innateActions:
- HumanScream
- Disarm
- type: OverlayEffectsUI
- type: Eye
zoom: 0.5, 0.5
- type: CameraRecoil