Resolves TimerTriggerVisualizer is Obsolete (#13912)

This commit is contained in:
TemporalOroboros
2023-05-13 14:18:33 -07:00
committed by GitHub
parent 4770865152
commit 88063ab2be
4 changed files with 124 additions and 93 deletions

View File

@@ -1,75 +0,0 @@
using Content.Shared.Trigger;
using JetBrains.Annotations;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Serialization;
namespace Content.Client.Trigger
{
[UsedImplicitly]
public sealed class TimerTriggerVisualizer : AppearanceVisualizer, ISerializationHooks
{
private const string AnimationKey = "priming_animation";
[DataField("countdown_sound")]
private SoundSpecifier? _countdownSound;
private Animation PrimingAnimation = default!;
void ISerializationHooks.AfterDeserialization()
{
PrimingAnimation = new Animation { Length = TimeSpan.MaxValue };
{
var flick = new AnimationTrackSpriteFlick();
PrimingAnimation.AnimationTracks.Add(flick);
flick.LayerKey = TriggerVisualLayers.Base;
flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("primed", 0f));
if (_countdownSound != null)
{
var sound = new AnimationTrackPlaySound();
PrimingAnimation.AnimationTracks.Add(sound);
sound.KeyFrames.Add(new AnimationTrackPlaySound.KeyFrame(_countdownSound.GetSound(), 0));
}
}
}
[Obsolete("Subscribe to your component being initialised instead.")]
public override void InitializeEntity(EntityUid entity)
{
IoCManager.Resolve<IEntityManager>().EnsureComponent<AnimationPlayerComponent>(entity);
}
[Obsolete("Subscribe to AppearanceChangeEvent instead.")]
public override void OnChangeData(AppearanceComponent component)
{
var entMan = IoCManager.Resolve<IEntityManager>();
var sprite = entMan.GetComponent<SpriteComponent>(component.Owner);
var animPlayer = entMan.GetComponent<AnimationPlayerComponent>(component.Owner);
if (!component.TryGetData(TriggerVisuals.VisualState, out TriggerVisualState state))
{
state = TriggerVisualState.Unprimed;
}
switch (state)
{
case TriggerVisualState.Primed:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(PrimingAnimation, AnimationKey);
}
break;
case TriggerVisualState.Unprimed:
sprite.LayerSetState(0, "icon");
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
public enum TriggerVisualLayers : byte
{
Base
}
}

View File

@@ -0,0 +1,43 @@
using Robust.Client.Animations;
using Robust.Shared.Audio;
namespace Content.Client.Trigger;
[RegisterComponent]
[Access(typeof(TimerTriggerVisualizerSystem))]
public sealed class TimerTriggerVisualsComponent : Component
{
/// <summary>
/// The key used to index the priming animation.
/// </summary>
[ViewVariables]
public const string AnimationKey = "priming_animation";
/// <summary>
/// The RSI state used while the device has not been primed.
/// </summary>
[DataField("unprimedSprite")]
[ViewVariables(VVAccess.ReadWrite)]
public string UnprimedSprite = "icon";
/// <summary>
/// The RSI state used when the device is primed.
/// Not VVWrite-able because it's only used at component init to construct the priming animation.
/// </summary>
[DataField("primingSprite")]
public string PrimingSprite = "primed";
/// <summary>
/// The sound played when the device is primed.
/// Not VVWrite-able because it's only used at component init to construct the priming animation.
/// </summary>
[DataField("primingSound")]
public SoundSpecifier? PrimingSound;
/// <summary>
/// The actual priming animation.
/// Constructed at component init from the sprite and sound.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public Animation PrimingAnimation = default!;
}

View File

@@ -0,0 +1,67 @@
using Content.Shared.Trigger;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
namespace Content.Client.Trigger;
public sealed class TimerTriggerVisualizerSystem : VisualizerSystem<TimerTriggerVisualsComponent>
{
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<TimerTriggerVisualsComponent, ComponentInit>(OnComponentInit);
}
private void OnComponentInit(EntityUid uid, TimerTriggerVisualsComponent comp, ComponentInit args)
{
comp.PrimingAnimation = new Animation {
Length = TimeSpan.MaxValue,
AnimationTracks = {
new AnimationTrackSpriteFlick() {
LayerKey = TriggerVisualLayers.Base,
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.PrimingSprite, 0f) }
}
},
};
if (comp.PrimingSound != null)
{
comp.PrimingAnimation.AnimationTracks.Add(
new AnimationTrackPlaySound() {
KeyFrames = { new AnimationTrackPlaySound.KeyFrame(_audioSystem.GetSound(comp.PrimingSound), 0) }
}
);
}
}
protected override void OnAppearanceChange(EntityUid uid, TimerTriggerVisualsComponent comp, ref AppearanceChangeEvent args)
{
if (args.Sprite == null
|| !TryComp<AnimationPlayerComponent>(uid, out var animPlayer))
return;
if (!AppearanceSystem.TryGetData<TriggerVisualState>(uid, TriggerVisuals.VisualState, out var state, args.Component))
state = TriggerVisualState.Unprimed;
switch (state)
{
case TriggerVisualState.Primed:
if (!AnimationSystem.HasRunningAnimation(uid, animPlayer, TimerTriggerVisualsComponent.AnimationKey))
AnimationSystem.Play(uid, animPlayer, comp.PrimingAnimation, TimerTriggerVisualsComponent.AnimationKey);
break;
case TriggerVisualState.Unprimed:
args.Sprite.LayerSetState(TriggerVisualLayers.Base, comp.UnprimedSprite);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
public enum TriggerVisualLayers : byte
{
Base
}

View File

@@ -29,8 +29,8 @@
- !type:DoActsBehavior - !type:DoActsBehavior
acts: ["Destruction"] acts: ["Destruction"]
- type: Appearance - type: Appearance
visuals: - type: AnimationPlayer
- type: TimerTriggerVisualizer - type: TimerTriggerVisuals
- type: entity - type: entity
name: explosive grenade name: explosive grenade
@@ -70,10 +70,9 @@
- type: SpawnOnTrigger - type: SpawnOnTrigger
proto: GrenadeFlashEffect proto: GrenadeFlashEffect
- type: Appearance - type: Appearance
visuals: - type: TimerTriggerVisuals
- type: TimerTriggerVisualizer primingSound:
countdown_sound: path: /Audio/Effects/countdown.ogg
path: /Audio/Effects/countdown.ogg
- type: entity - type: entity
id: GrenadeFlashEffect id: GrenadeFlashEffect
@@ -106,10 +105,9 @@
intensitySlope: 30 #Will destroy the tile under it reliably, space 1-2 more to rods. Only does any significant damage in a 5-tile cross. intensitySlope: 30 #Will destroy the tile under it reliably, space 1-2 more to rods. Only does any significant damage in a 5-tile cross.
maxIntensity: 60 maxIntensity: 60
- type: Appearance - type: Appearance
visuals: - type: TimerTriggerVisuals
- type: TimerTriggerVisualizer primingSound:
countdown_sound: path: /Audio/Effects/minibombcountdown.ogg
path: /Audio/Effects/minibombcountdown.ogg
- type: entity - type: entity
name: the nuclear option name: the nuclear option
@@ -137,10 +135,9 @@
- !type:DoActsBehavior - !type:DoActsBehavior
acts: ["Destruction"] acts: ["Destruction"]
- type: Appearance - type: Appearance
visuals: - type: TimerTriggerVisuals
- type: TimerTriggerVisualizer primingSound:
countdown_sound: path: /Audio/Effects/countdown.ogg
path: /Audio/Effects/countdown.ogg
- type: entity - type: entity
name: modular grenade name: modular grenade
@@ -201,7 +198,6 @@
energyConsumption: 50000 energyConsumption: 50000
- type: DeleteOnTrigger - type: DeleteOnTrigger
- type: Appearance - type: Appearance
visuals: - type: TimerTriggerVisuals
- type: TimerTriggerVisualizer primingSound:
countdown_sound: path: /Audio/Effects/countdown.ogg
path: /Audio/Effects/countdown.ogg