diff --git a/Content.Client/GameObjects/Components/DoAfterComponent.cs b/Content.Client/GameObjects/Components/DoAfterComponent.cs index a658ca78de..23e54c217a 100644 --- a/Content.Client/GameObjects/Components/DoAfterComponent.cs +++ b/Content.Client/GameObjects/Components/DoAfterComponent.cs @@ -51,7 +51,7 @@ namespace Content.Client.GameObjects.Components /// public void Enable() { - if (Gui != null && !Gui.Disposed) + if (Gui?.Disposed == false) return; Gui = new DoAfterGui {AttachedEntity = Owner, FirstDraw = true}; @@ -70,6 +70,7 @@ namespace Content.Client.GameObjects.Components public void Disable() { Gui?.Dispose(); + Gui = null; } public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) @@ -128,8 +129,7 @@ namespace Content.Client.GameObjects.Components /// public void Remove(ClientDoAfter clientDoAfter) { - if (_doAfters.ContainsKey(clientDoAfter.ID)) - _doAfters.Remove(clientDoAfter.ID); + _doAfters.Remove(clientDoAfter.ID); var found = false; diff --git a/Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterGui.cs b/Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterGui.cs index ce588b13b1..ca3beb8a55 100644 --- a/Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterGui.cs +++ b/Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterGui.cs @@ -12,11 +12,13 @@ using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Timing; +using Robust.Shared.Utility; namespace Content.Client.GameObjects.EntitySystems.DoAfter { public sealed class DoAfterGui : VBoxContainer { + [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; @@ -106,12 +108,11 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter var control = _doAfterControls[id]; RemoveChild(control); + control.DisposeAllChildren(); _doAfterControls.Remove(id); _doAfterBars.Remove(id); - if (_cancelledDoAfters.ContainsKey(id)) - _cancelledDoAfters.Remove(id); - + _cancelledDoAfters.Remove(id); } /// @@ -124,11 +125,21 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter if (_cancelledDoAfters.ContainsKey(id)) return; - if (!_doAfterBars.TryGetValue(id, out var doAfterBar)) + DoAfterBar doAfterBar; + + if (!_doAfterControls.TryGetValue(id, out var doAfterControl)) { + doAfterControl = new PanelContainer(); + AddChild(doAfterControl); + DebugTools.Assert(!_doAfterBars.ContainsKey(id)); doAfterBar = new DoAfterBar(); + doAfterControl.AddChild(doAfterBar); _doAfterBars[id] = doAfterBar; } + else + { + doAfterBar = _doAfterBars[id]; + } doAfterBar.Cancelled = true; _cancelledDoAfters.Add(id, _gameTiming.CurTime); @@ -148,7 +159,8 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter if (doAfters.Count == 0) return; - if (_eyeManager.CurrentMap != AttachedEntity.Transform.MapID) + if (_eyeManager.CurrentMap != AttachedEntity.Transform.MapID || + !AttachedEntity.Transform.Coordinates.IsValid(_entityManager)) { Visible = false; return; @@ -172,20 +184,22 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter Visible = true; var currentTime = _gameTiming.CurTime; - var toCancel = new List(); + var toRemove = new List(); // Cleanup cancelled DoAfters foreach (var (id, cancelTime) in _cancelledDoAfters) { if ((currentTime - cancelTime).TotalSeconds > DoAfterSystem.ExcessTime) - toCancel.Add(id); + toRemove.Add(id); } - foreach (var id in toCancel) + foreach (var id in toRemove) { RemoveDoAfter(id); } + toRemove.Clear(); + // Update 0 -> 1.0f of the things foreach (var (id, message) in doAfters) { @@ -193,8 +207,20 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter continue; var doAfterBar = _doAfterBars[id]; + var ratio = (currentTime - message.StartTime).TotalSeconds; doAfterBar.Ratio = MathF.Min(1.0f, - (float) (currentTime - message.StartTime).TotalSeconds / message.Delay); + (float) ratio / message.Delay); + + // Just in case it doesn't get cleaned up by the system for whatever reason. + if (ratio > message.Delay + DoAfterSystem.ExcessTime) + { + toRemove.Add(id); + } + } + + foreach (var id in toRemove) + { + RemoveDoAfter(id); } } }