diff --git a/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs b/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs index 368e465c74..626da3a2e1 100644 --- a/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs +++ b/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs @@ -18,7 +18,7 @@ namespace Content.Client.Light.Visualizers { [DataField("minBlinkingTime")] private float _minBlinkingTime = 0.5f; [DataField("maxBlinkingTime")] private float _maxBlinkingTime = 2; - [DataField("blinkingSound", required: true)] private SoundSpecifier _blinkingSound = default!; + [DataField("blinkingSound")] private SoundSpecifier? _blinkingSound = default; private bool _wasBlinking; @@ -125,13 +125,16 @@ namespace Content.Client.Light.Visualizers } }; - blinkingAnim.AnimationTracks.Add(new AnimationTrackPlaySound() + if (_blinkingSound != null) { - KeyFrames = + blinkingAnim.AnimationTracks.Add(new AnimationTrackPlaySound() + { + KeyFrames = { new AnimationTrackPlaySound.KeyFrame(_blinkingSound.GetSound(), 0.5f) } - }); + }); + } return blinkingAnim; } diff --git a/Content.Server/Actions/Actions/GhostBoo.cs b/Content.Server/Actions/Actions/GhostBoo.cs index 4edc86b1ce..ee6b8260cb 100644 --- a/Content.Server/Actions/Actions/GhostBoo.cs +++ b/Content.Server/Actions/Actions/GhostBoo.cs @@ -31,12 +31,11 @@ namespace Content.Server.Actions.Actions var booCounter = 0; foreach (var ent in ents) { - var boos = ent.GetAllComponents().ToList(); - foreach (var boo in boos) - { - if (boo.AffectedByGhostBoo(args)) - booCounter++; - } + var ghostBoo = new GhostBooEvent(); + ent.EntityManager.EventBus.RaiseLocalEvent(ent.Uid, ghostBoo); + + if (ghostBoo.Handled) + booCounter++; if (booCounter >= _maxTargets) break; diff --git a/Content.Server/Ghost/GhostBooEvent.cs b/Content.Server/Ghost/GhostBooEvent.cs new file mode 100644 index 0000000000..17ee1e7803 --- /dev/null +++ b/Content.Server/Ghost/GhostBooEvent.cs @@ -0,0 +1,9 @@ +using Robust.Shared.GameObjects; + +namespace Content.Server.Ghost +{ + public class GhostBooEvent : HandledEntityEventArgs + { + + } +} diff --git a/Content.Server/Ghost/IGhostBooAffected.cs b/Content.Server/Ghost/IGhostBooAffected.cs deleted file mode 100644 index e797f4b0a7..0000000000 --- a/Content.Server/Ghost/IGhostBooAffected.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Content.Shared.Actions.Behaviors; - -namespace Content.Server.Ghost -{ - /// - /// Allow ghost to interact with object by boo action - /// - public interface IGhostBooAffected - { - /// - /// Invokes when ghost used boo action near entity. - /// Use it to blink lights or make something spooky. - /// - /// Boo action details - /// Returns true if object was affected - bool AffectedByGhostBoo(InstantActionEventArgs args); - } -} diff --git a/Content.Server/Light/Components/PoweredLightComponent.cs b/Content.Server/Light/Components/PoweredLightComponent.cs index a942b6fcd9..46a7d60408 100644 --- a/Content.Server/Light/Components/PoweredLightComponent.cs +++ b/Content.Server/Light/Components/PoweredLightComponent.cs @@ -1,11 +1,9 @@ using System; using System.Threading.Tasks; -using Content.Server.Ghost; using Content.Server.Hands.Components; using Content.Server.Items; using Content.Server.Power.Components; using Content.Server.Temperature.Components; -using Content.Shared.Actions.Behaviors; using Content.Shared.Damage; using Content.Shared.Damage.Components; using Content.Shared.Interaction; @@ -30,22 +28,19 @@ namespace Content.Server.Light.Components /// Component that represents a wall light. It has a light bulb that can be replaced when broken. /// [RegisterComponent] - public class PoweredLightComponent : Component, IInteractHand, IInteractUsing, IMapInit, IGhostBooAffected + public class PoweredLightComponent : Component, IInteractHand, IInteractUsing, IMapInit { [Dependency] private readonly IGameTiming _gameTiming = default!; public override string Name => "PoweredLight"; private static readonly TimeSpan _thunkDelay = TimeSpan.FromSeconds(2); - // time to blink light when ghost made boo nearby - private static readonly TimeSpan ghostBlinkingTime = TimeSpan.FromSeconds(10); - private static readonly TimeSpan ghostBlinkingCooldown = TimeSpan.FromSeconds(60); [ComponentDependency] private readonly AppearanceComponent? _appearance; private TimeSpan _lastThunk; - private TimeSpan? _lastGhostBlink; + public TimeSpan? LastGhostBlink; [DataField("burnHandSound")] private SoundSpecifier _burnHandSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg"); @@ -64,11 +59,20 @@ namespace Content.Server.Light.Components private bool _currentLit; [ViewVariables] - private bool _isBlinking; + public bool IsBlinking; [ViewVariables] [DataField("ignoreGhostsBoo")] - private bool _ignoreGhostsBoo; + public bool IgnoreGhostsBoo; + + [ViewVariables] + [DataField("ghostBlinkingTime")] + public TimeSpan GhostBlinkingTime = TimeSpan.FromSeconds(10); + + [ViewVariables] + [DataField("ghostBlinkingCooldown")] + public TimeSpan GhostBlinkingCooldown = TimeSpan.FromSeconds(60); + [DataField("bulb")] private LightBulbType _bulbType = LightBulbType.Tube; public LightBulbType BulbType => _bulbType; @@ -312,36 +316,6 @@ namespace Content.Server.Light.Components UpdateLight(); } - public void ToggleBlinkingLight(bool isNowBlinking) - { - if (_isBlinking == isNowBlinking) - return; - - _isBlinking = isNowBlinking; - _appearance?.SetData(PoweredLightVisuals.Blinking, _isBlinking); - } - - public bool AffectedByGhostBoo(InstantActionEventArgs args) - { - if (_ignoreGhostsBoo) - return false; - - // check cooldown first to prevent abuse - var time = _gameTiming.CurTime; - if (_lastGhostBlink != null) - { - if (time <= _lastGhostBlink + ghostBlinkingCooldown) - return false; - } - _lastGhostBlink = time; - - ToggleBlinkingLight(true); - Owner.SpawnTimer(ghostBlinkingTime, () => - { - ToggleBlinkingLight(false); - }); - - return true; - } + } } diff --git a/Content.Server/Light/EntitySystems/PoweredLightSystem.cs b/Content.Server/Light/EntitySystems/PoweredLightSystem.cs index 9318882b93..96c4dbb908 100644 --- a/Content.Server/Light/EntitySystems/PoweredLightSystem.cs +++ b/Content.Server/Light/EntitySystems/PoweredLightSystem.cs @@ -1,3 +1,11 @@ +using System; +using Content.Server.Ghost; +using Content.Server.Light.Components; +using Content.Shared.Light; +using Robust.Server.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Timing; using Content.Server.Light.Components; using Content.Server.MachineLinking.Events; using Robust.Shared.GameObjects; @@ -6,13 +14,51 @@ namespace Content.Server.Light.EntitySystems { public class PoweredLightSystem : EntitySystem { + [Dependency] private readonly IGameTiming _gameTiming = default!; + public override void Initialize() { base.Initialize(); - + SubscribeLocalEvent(OnGhostBoo); SubscribeLocalEvent(OnSignalReceived); } + private void OnGhostBoo(EntityUid uid, PoweredLightComponent light, GhostBooEvent args) + { + if (light.IgnoreGhostsBoo) + return; + + // check cooldown first to prevent abuse + var time = _gameTiming.CurTime; + if (light.LastGhostBlink != null) + { + if (time <= light.LastGhostBlink + light.GhostBlinkingCooldown) + return; + } + + light.LastGhostBlink = time; + + ToggleBlinkingLight(light, true); + light.Owner.SpawnTimer(light.GhostBlinkingTime, () => + { + ToggleBlinkingLight(light, false); + }); + + args.Handled = true; + } + + public void ToggleBlinkingLight(PoweredLightComponent light, bool isNowBlinking) + { + if (light.IsBlinking == isNowBlinking) + return; + + light.IsBlinking = isNowBlinking; + + if (!light.Owner.TryGetComponent(out AppearanceComponent? appearance)) + return; + appearance.SetData(PoweredLightVisuals.Blinking, isNowBlinking); + } + private void OnSignalReceived(EntityUid uid, PoweredLightComponent component, SignalReceivedEvent args) { switch (args.Port)