OverlayManager 2 Electric Boogaloo (#1410)
This commit is contained in:
@@ -10,9 +10,11 @@ using Robust.Client.Interfaces.Graphics.Overlays;
|
|||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Network;
|
||||||
using Robust.Shared.Interfaces.Reflection;
|
using Robust.Shared.Interfaces.Reflection;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Log;
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Players;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
public sealed class ClientOverlayEffectsComponent : SharedOverlayEffectsComponent//, ICharacterUI
|
public sealed class ClientOverlayEffectsComponent : SharedOverlayEffectsComponent//, ICharacterUI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An enum representing the current state being applied to the user
|
/// A list of overlay containers representing the current overlays applied
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<OverlayContainer> _currentEffects = new List<OverlayContainer>();
|
private List<OverlayContainer> _currentEffects = new List<OverlayContainer>();
|
||||||
|
|
||||||
@@ -41,43 +43,57 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
// Required dependencies
|
// Required dependencies
|
||||||
[Dependency] private readonly IOverlayManager _overlayManager;
|
[Dependency] private readonly IOverlayManager _overlayManager;
|
||||||
[Dependency] private readonly IReflectionManager _reflectionManager;
|
[Dependency] private readonly IReflectionManager _reflectionManager;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager;
|
[Dependency] private readonly IClientNetManager _netManager;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
UpdateOverlays();
|
||||||
|
}
|
||||||
|
|
||||||
public override void HandleMessage(ComponentMessage message, IComponent component)
|
public override void HandleMessage(ComponentMessage message, IComponent component)
|
||||||
{
|
{
|
||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
case PlayerAttachedMsg _:
|
case PlayerAttachedMsg _:
|
||||||
var overlays = new List<OverlayContainer>(_currentEffects);
|
UpdateOverlays();
|
||||||
_currentEffects.Clear();
|
|
||||||
SetEffects(overlays);
|
|
||||||
break;
|
break;
|
||||||
case PlayerDetachedMsg _:
|
case PlayerDetachedMsg _:
|
||||||
ActiveOverlays = new List<OverlayContainer>();
|
ActiveOverlays.ForEach(o => _overlayManager.RemoveOverlay(o.ID));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
|
||||||
{
|
{
|
||||||
base.HandleComponentState(curState, nextState);
|
base.HandleNetworkMessage(message, netChannel, session);
|
||||||
|
if (message is OverlayEffectComponentMessage overlayMessage)
|
||||||
if (!(curState is OverlayEffectComponentState state))
|
|
||||||
{
|
{
|
||||||
return;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_playerManager?.LocalPlayer != null && _playerManager.LocalPlayer.ControlledEntity != Owner)
|
SendNetworkMessage(new ResendOverlaysMessage(), _netManager.ServerChannel);
|
||||||
{
|
|
||||||
_currentEffects = state.Overlays;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ActiveOverlays.Equals(state.Overlays))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ActiveOverlays = state.Overlays;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetEffects(List<OverlayContainer> newOverlays)
|
private void SetEffects(List<OverlayContainer> newOverlays)
|
||||||
@@ -96,7 +112,13 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
{
|
{
|
||||||
AddOverlay(container);
|
AddOverlay(container);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateOverlayConfiguration(container, _overlayManager.GetOverlay(container.ID));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_currentEffects = newOverlays;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveOverlay(OverlayContainer container)
|
private void RemoveOverlay(OverlayContainer container)
|
||||||
@@ -107,6 +129,11 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
|
|
||||||
private void AddOverlay(OverlayContainer container)
|
private void AddOverlay(OverlayContainer container)
|
||||||
{
|
{
|
||||||
|
if (_overlayManager.HasOverlay(container.ID))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ActiveOverlays.Add(container);
|
ActiveOverlays.Add(container);
|
||||||
if (TryCreateOverlay(container, out var overlay))
|
if (TryCreateOverlay(container, out var overlay))
|
||||||
{
|
{
|
||||||
@@ -118,26 +145,38 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateOverlayConfiguration(OverlayContainer container, Overlay overlay)
|
||||||
|
{
|
||||||
|
var configurableTypes = overlay.GetType()
|
||||||
|
.GetInterfaces()
|
||||||
|
.Where(type =>
|
||||||
|
type.IsGenericType
|
||||||
|
&& type.GetGenericTypeDefinition() == typeof(IConfigurable<>)
|
||||||
|
&& container.Parameters.Exists(p => p.GetType() == type.GenericTypeArguments.First()))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (configurableTypes.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var type in configurableTypes)
|
||||||
|
{
|
||||||
|
var method = type.GetMethod(nameof(IConfigurable<object>.Configure));
|
||||||
|
var parameter = container.Parameters
|
||||||
|
.First(p => p.GetType() == type.GenericTypeArguments.First());
|
||||||
|
|
||||||
|
method!.Invoke(overlay, new []{ parameter });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryCreateOverlay(OverlayContainer container, out Overlay overlay)
|
private bool TryCreateOverlay(OverlayContainer container, out Overlay overlay)
|
||||||
{
|
{
|
||||||
var overlayTypes = _reflectionManager.GetAllChildren<Overlay>();
|
var overlayTypes = _reflectionManager.GetAllChildren<Overlay>();
|
||||||
var foundType = overlayTypes.FirstOrDefault(t => t.Name == container.ID);
|
var overlayType = overlayTypes.FirstOrDefault(t => t.Name == container.ID);
|
||||||
|
|
||||||
if (foundType != null)
|
if (overlayType != null)
|
||||||
{
|
{
|
||||||
overlay = Activator.CreateInstance(foundType) as Overlay;
|
overlay = Activator.CreateInstance(overlayType) as Overlay;
|
||||||
var configurable = foundType
|
UpdateOverlayConfiguration(container, overlay);
|
||||||
.GetInterfaces()
|
|
||||||
.FirstOrDefault(type =>
|
|
||||||
type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IConfigurable<>)
|
|
||||||
&& type.GenericTypeArguments.First() == container.GetType());
|
|
||||||
|
|
||||||
if (configurable != null)
|
|
||||||
{
|
|
||||||
var method = overlay?.GetType().GetMethod("Configure");
|
|
||||||
method?.Invoke(overlay, new []{ container });
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Content.Client.Graphics.Overlays
|
|||||||
|
|
||||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
|
|
||||||
public CircleMaskOverlay() : base(nameof(OverlayType.CircleMaskOverlay))
|
public CircleMaskOverlay() : base(nameof(SharedOverlayID.CircleMaskOverlay))
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
Shader = _prototypeManager.Index<ShaderPrototype>("CircleMask").Instance();
|
Shader = _prototypeManager.Index<ShaderPrototype>("CircleMask").Instance();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ using Color = Robust.Shared.Maths.Color;
|
|||||||
|
|
||||||
namespace Content.Client.Graphics.Overlays
|
namespace Content.Client.Graphics.Overlays
|
||||||
{
|
{
|
||||||
public class FlashOverlay : Overlay, IConfigurable<TimedOverlayContainer>
|
public class FlashOverlay : Overlay, IConfigurable<TimedOverlayParameter>
|
||||||
{
|
{
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||||
@@ -31,7 +31,7 @@ namespace Content.Client.Graphics.Overlays
|
|||||||
private int lastsFor = 5000;
|
private int lastsFor = 5000;
|
||||||
private Texture _screenshotTexture;
|
private Texture _screenshotTexture;
|
||||||
|
|
||||||
public FlashOverlay() : base(nameof(OverlayType.FlashOverlay))
|
public FlashOverlay() : base(nameof(SharedOverlayID.FlashOverlay))
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
Shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").Instance().Duplicate();
|
Shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").Instance().Duplicate();
|
||||||
@@ -65,7 +65,7 @@ namespace Content.Client.Graphics.Overlays
|
|||||||
_screenshotTexture = null;
|
_screenshotTexture = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(TimedOverlayContainer parameters)
|
public void Configure(TimedOverlayParameter parameters)
|
||||||
{
|
{
|
||||||
lastsFor = parameters.Length;
|
lastsFor = parameters.Length;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Content.Client.Graphics.Overlays
|
|||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
|
|
||||||
public GradientCircleMaskOverlay() : base(nameof(OverlayType.GradientCircleMaskOverlay))
|
public GradientCircleMaskOverlay() : base(nameof(SharedOverlayID.GradientCircleMaskOverlay))
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
Shader = _prototypeManager.Index<ShaderPrototype>("GradientCircleMask").Instance();
|
Shader = _prototypeManager.Index<ShaderPrototype>("GradientCircleMask").Instance();
|
||||||
|
|||||||
@@ -69,24 +69,24 @@ namespace Content.Server.GameObjects
|
|||||||
statusEffectsComponent?.ChangeStatusEffectIcon(StatusEffect.Health,
|
statusEffectsComponent?.ChangeStatusEffectIcon(StatusEffect.Health,
|
||||||
"/Textures/Interface/StatusEffects/Human/human" + modifier + ".png");
|
"/Textures/Interface/StatusEffects/Human/human" + modifier + ".png");
|
||||||
|
|
||||||
overlayComponent?.RemoveOverlay(OverlayType.GradientCircleMaskOverlay);
|
overlayComponent?.RemoveOverlay(SharedOverlayID.GradientCircleMaskOverlay);
|
||||||
overlayComponent?.RemoveOverlay(OverlayType.CircleMaskOverlay);
|
overlayComponent?.RemoveOverlay(SharedOverlayID.CircleMaskOverlay);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case ThresholdType.Critical:
|
case ThresholdType.Critical:
|
||||||
statusEffectsComponent?.ChangeStatusEffectIcon(
|
statusEffectsComponent?.ChangeStatusEffectIcon(
|
||||||
StatusEffect.Health,
|
StatusEffect.Health,
|
||||||
"/Textures/Interface/StatusEffects/Human/humancrit-0.png");
|
"/Textures/Interface/StatusEffects/Human/humancrit-0.png");
|
||||||
overlayComponent?.ClearOverlays();
|
overlayComponent?.AddOverlay(SharedOverlayID.GradientCircleMaskOverlay);
|
||||||
overlayComponent?.AddOverlay(OverlayType.GradientCircleMaskOverlay);
|
overlayComponent?.RemoveOverlay(SharedOverlayID.CircleMaskOverlay);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case ThresholdType.Death:
|
case ThresholdType.Death:
|
||||||
statusEffectsComponent?.ChangeStatusEffectIcon(
|
statusEffectsComponent?.ChangeStatusEffectIcon(
|
||||||
StatusEffect.Health,
|
StatusEffect.Health,
|
||||||
"/Textures/Interface/StatusEffects/Human/humandead.png");
|
"/Textures/Interface/StatusEffects/Human/humandead.png");
|
||||||
overlayComponent?.ClearOverlays();
|
overlayComponent?.RemoveOverlay(SharedOverlayID.GradientCircleMaskOverlay);
|
||||||
overlayComponent?.AddOverlay(OverlayType.CircleMaskOverlay);
|
overlayComponent?.AddOverlay(SharedOverlayID.CircleMaskOverlay);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Network;
|
||||||
|
using Robust.Shared.Players;
|
||||||
using Robust.Shared.Timers;
|
using Robust.Shared.Timers;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
@@ -12,50 +17,83 @@ namespace Content.Server.GameObjects.Components.Mobs
|
|||||||
[ComponentReference(typeof(SharedOverlayEffectsComponent))]
|
[ComponentReference(typeof(SharedOverlayEffectsComponent))]
|
||||||
public sealed class ServerOverlayEffectsComponent : SharedOverlayEffectsComponent
|
public sealed class ServerOverlayEffectsComponent : SharedOverlayEffectsComponent
|
||||||
{
|
{
|
||||||
private readonly List<OverlayContainer> _currentOverlays = new List<OverlayContainer>();
|
public ServerOverlayEffectsComponent()
|
||||||
|
{
|
||||||
|
NetSyncEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
private List<OverlayContainer> ActiveOverlays => _currentOverlays;
|
public List<OverlayContainer> ActiveOverlays { get; } = new List<OverlayContainer>();
|
||||||
|
|
||||||
public override ComponentState GetComponentState()
|
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
|
||||||
{
|
{
|
||||||
return new OverlayEffectComponentState(_currentOverlays);
|
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)
|
public void AddOverlay(OverlayContainer container)
|
||||||
{
|
{
|
||||||
if (!ActiveOverlays.Contains(container))
|
if (!ActiveOverlays.Contains(container))
|
||||||
{
|
{
|
||||||
ActiveOverlays.Add(container);
|
ActiveOverlays.Add(container);
|
||||||
Dirty();
|
SyncClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddOverlay(string id) => AddOverlay(new OverlayContainer(id));
|
public void RemoveOverlay(SharedOverlayID id) => RemoveOverlay(id.ToString());
|
||||||
public void AddOverlay(OverlayType type) => AddOverlay(new OverlayContainer(type));
|
|
||||||
|
public void RemoveOverlay(string id) => RemoveOverlay(new OverlayContainer(id));
|
||||||
|
|
||||||
public void RemoveOverlay(OverlayContainer container)
|
public void RemoveOverlay(OverlayContainer container)
|
||||||
{
|
{
|
||||||
if (ActiveOverlays.RemoveAll(c => c.Equals(container)) > 0)
|
if (ActiveOverlays.Remove(container))
|
||||||
{
|
{
|
||||||
Dirty();
|
SyncClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveOverlay(string id)
|
public bool TryModifyOverlay(string id, Action<OverlayContainer> modifications)
|
||||||
{
|
{
|
||||||
if (ActiveOverlays.RemoveAll(container => container.ID == id) > 0)
|
var overlay = ActiveOverlays.Find(c => c.ID == id);
|
||||||
|
if (overlay == null)
|
||||||
{
|
{
|
||||||
Dirty();
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveOverlay(OverlayType type) => RemoveOverlay(type.ToString());
|
modifications(overlay);
|
||||||
|
SyncClient();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void ClearOverlays()
|
public void ClearOverlays()
|
||||||
{
|
{
|
||||||
|
if (ActiveOverlays.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ActiveOverlays.Clear();
|
ActiveOverlays.Clear();
|
||||||
Dirty();
|
SyncClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncClient()
|
||||||
|
{
|
||||||
|
if (Owner.TryGetComponent(out IActorComponent actor))
|
||||||
|
{
|
||||||
|
if (actor.playerSession.ConnectedClient.IsConnected)
|
||||||
|
{
|
||||||
|
SendNetworkMessage(new OverlayEffectComponentMessage(ActiveOverlays), actor.playerSession.ConnectedClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
|
|||||||
public override string Name => "Flash";
|
public override string Name => "Flash";
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)] private int _flashDuration = 5000;
|
[ViewVariables(VVAccess.ReadWrite)] private int _flashDuration = 5000;
|
||||||
[ViewVariables(VVAccess.ReadWrite)] private float _flashFalloffExp = 8f;
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)] private int _uses = 5;
|
[ViewVariables(VVAccess.ReadWrite)] private int _uses = 5;
|
||||||
[ViewVariables(VVAccess.ReadWrite)] private float _range = 3f;
|
[ViewVariables(VVAccess.ReadWrite)] private float _range = 3f;
|
||||||
[ViewVariables(VVAccess.ReadWrite)] private int _aoeFlashDuration = 5000 / 3;
|
[ViewVariables(VVAccess.ReadWrite)] private int _aoeFlashDuration = 5000 / 3;
|
||||||
@@ -55,9 +54,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
|
|||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
serializer.DataField(ref _flashDuration, "duration", 5000);
|
serializer.DataField(ref _flashDuration, "duration", 5000);
|
||||||
serializer.DataField(ref _flashFalloffExp, "flashFalloffExp", 8f);
|
|
||||||
serializer.DataField(ref _uses, "uses", 5);
|
serializer.DataField(ref _uses, "uses", 5);
|
||||||
serializer.DataField(ref _range, "range", 3f);
|
serializer.DataField(ref _range, "range", 7f);
|
||||||
serializer.DataField(ref _aoeFlashDuration, "aoeFlashDuration", _flashDuration / 3);
|
serializer.DataField(ref _aoeFlashDuration, "aoeFlashDuration", _flashDuration / 3);
|
||||||
serializer.DataField(ref _slowTo, "slowTo", 0.75f);
|
serializer.DataField(ref _slowTo, "slowTo", 0.75f);
|
||||||
}
|
}
|
||||||
@@ -139,9 +137,18 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
|
|||||||
{
|
{
|
||||||
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent))
|
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent))
|
||||||
{
|
{
|
||||||
var container = new TimedOverlayContainer(nameof(OverlayType.FlashOverlay), flashDuration);
|
if (!overlayEffectsComponent.TryModifyOverlay(nameof(SharedOverlayID.FlashOverlay),
|
||||||
overlayEffectsComponent.AddOverlay(container);
|
overlay =>
|
||||||
container.StartTimer(() => overlayEffectsComponent.RemoveOverlay(container));
|
{
|
||||||
|
if (overlay.TryGetOverlayParameter<TimedOverlayParameter>(out var timed))
|
||||||
|
{
|
||||||
|
timed.Length += flashDuration;
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
var container = new OverlayContainer(SharedOverlayID.FlashOverlay, new TimedOverlayParameter(flashDuration));
|
||||||
|
overlayEffectsComponent.AddOverlay(container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out StunnableComponent stunnableComponent))
|
if (entity.TryGetComponent(out StunnableComponent stunnableComponent))
|
||||||
@@ -165,8 +172,13 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
|
|||||||
|
|
||||||
if (inDetailsRange)
|
if (inDetailsRange)
|
||||||
{
|
{
|
||||||
message.AddMarkup(_localizationManager.GetString(
|
message.AddMarkup(
|
||||||
"The flash has [color=green]{0}[/color] uses remaining.", Uses));
|
_localizationManager.GetString(
|
||||||
|
"The flash has [color=green]{0}[/color] {1} remaining.",
|
||||||
|
Uses,
|
||||||
|
_localizationManager.GetPluralString("use", "uses", Uses)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.Timing;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.EntitySystems
|
||||||
|
{
|
||||||
|
[UsedImplicitly]
|
||||||
|
public class TimedOverlayRemovalSystem : EntitySystem
|
||||||
|
{
|
||||||
|
#pragma warning disable 649
|
||||||
|
[Dependency] private readonly IGameTiming _gameTiming;
|
||||||
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
EntityQuery = new TypeEntityQuery(typeof(ServerOverlayEffectsComponent));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
|
||||||
|
foreach (var entity in RelevantEntities)
|
||||||
|
{
|
||||||
|
var effectsComponent = entity.GetComponent<ServerOverlayEffectsComponent>();
|
||||||
|
foreach (var overlay in effectsComponent.ActiveOverlays.ToArray())
|
||||||
|
{
|
||||||
|
if (overlay.TryGetOverlayParameter<TimedOverlayParameter>(out var parameter))
|
||||||
|
{
|
||||||
|
if (parameter.StartedAt + parameter.Length <= _gameTiming.CurTime.TotalMilliseconds)
|
||||||
|
{
|
||||||
|
effectsComponent.RemoveOverlay(overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Timers;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Timing;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Timers;
|
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
using YamlDotNet.RepresentationModel;
|
using YamlDotNet.RepresentationModel;
|
||||||
using Component = Robust.Shared.GameObjects.Component;
|
using Component = Robust.Shared.GameObjects.Component;
|
||||||
@@ -18,72 +23,101 @@ namespace Content.Shared.GameObjects.Components.Mobs
|
|||||||
public abstract class SharedOverlayEffectsComponent : Component
|
public abstract class SharedOverlayEffectsComponent : Component
|
||||||
{
|
{
|
||||||
public override string Name => "OverlayEffectsUI";
|
public override string Name => "OverlayEffectsUI";
|
||||||
|
|
||||||
public sealed override uint? NetID => ContentNetIDs.OVERLAYEFFECTS;
|
public sealed override uint? NetID => ContentNetIDs.OVERLAYEFFECTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public class OverlayContainer
|
public class OverlayContainer : IEquatable<string>, IEquatable<OverlayContainer>
|
||||||
{
|
{
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
public string ID { get; }
|
public string ID { get; }
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public List<OverlayParameter> Parameters { get; } = new List<OverlayParameter>();
|
||||||
|
|
||||||
public OverlayContainer([NotNull] string id)
|
public OverlayContainer([NotNull] string id)
|
||||||
{
|
{
|
||||||
ID = id;
|
ID = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OverlayContainer(OverlayType type) : this(type.ToString())
|
public OverlayContainer(SharedOverlayID id) : this(id.ToString())
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public OverlayContainer(SharedOverlayID id, params OverlayParameter[] parameters) : this(id)
|
||||||
{
|
{
|
||||||
if (obj is OverlayContainer container)
|
Parameters.AddRange(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetOverlayParameter<T>(out T parameter) where T : OverlayParameter
|
||||||
|
{
|
||||||
|
var found = Parameters.FirstOrDefault(p => p is T);
|
||||||
|
if (found != null)
|
||||||
{
|
{
|
||||||
return container.ID == ID;
|
parameter = found as T;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj is string idString)
|
parameter = default;
|
||||||
{
|
return false;
|
||||||
return idString == ID;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return base.Equals(obj);
|
public bool Equals(string other)
|
||||||
|
{
|
||||||
|
return ID == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(OverlayContainer other)
|
||||||
|
{
|
||||||
|
return ID == other?.ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return (ID != null ? ID.GetHashCode() : 0);
|
return ID != null ? ID.GetHashCode() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public class OverlayEffectComponentState : ComponentState
|
public class OverlayEffectComponentMessage : ComponentMessage
|
||||||
{
|
{
|
||||||
public List<OverlayContainer> Overlays;
|
public List<OverlayContainer> Overlays;
|
||||||
|
|
||||||
public OverlayEffectComponentState(List<OverlayContainer> overlays) : base(ContentNetIDs.OVERLAYEFFECTS)
|
public OverlayEffectComponentMessage(List<OverlayContainer> overlays)
|
||||||
{
|
{
|
||||||
|
Directed = true;
|
||||||
Overlays = overlays;
|
Overlays = overlays;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public class TimedOverlayContainer : OverlayContainer
|
public class ResendOverlaysMessage : ComponentMessage
|
||||||
{
|
{
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
|
||||||
public int Length { get; }
|
|
||||||
|
|
||||||
public TimedOverlayContainer(string id, int length) : base(id)
|
|
||||||
{
|
|
||||||
Length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StartTimer(Action finished) => Timer.Spawn(Length, finished);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum OverlayType
|
[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,
|
GradientCircleMaskOverlay,
|
||||||
CircleMaskOverlay,
|
CircleMaskOverlay,
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
cooldownTime: 1
|
cooldownTime: 1
|
||||||
arc: smash
|
arc: smash
|
||||||
hitSound: /Audio/Weapons/flash.ogg
|
hitSound: /Audio/Weapons/flash.ogg
|
||||||
slowTo: 0.7
|
|
||||||
|
|
||||||
- type: Item
|
- type: Item
|
||||||
Size: 2
|
Size: 2
|
||||||
|
|||||||
Reference in New Issue
Block a user