OverlayManager 2 Electric Boogaloo (#1410)

This commit is contained in:
R. Neuser
2020-07-19 10:32:26 -05:00
committed by GitHub
parent 0d03aeff37
commit 86c318cc74
10 changed files with 264 additions and 97 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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:

View File

@@ -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);
}
}
} }
} }
} }

View File

@@ -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)
)
);
} }
} }
} }

View File

@@ -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);
}
}
}
}
}
}
}

View File

@@ -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,

View File

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