using System; using System.Collections.Generic; using Robust.Client.GameObjects; using Robust.Shared.Audio; using Robust.Shared.GameObjects; using Robust.Shared.Player; namespace Robust.Client.Animations { /// /// An animation track that plays a sound as keyframes. /// public sealed class AnimationTrackPlaySound : AnimationTrack { /// /// A list of key frames for when to fire flicks. /// public List KeyFrames { get; private set; } = new(); public override (int KeyFrameIndex, float FramePlayingTime) InitPlayback() { return (-1, 0); } public override (int KeyFrameIndex, float FramePlayingTime) AdvancePlayback(object context, int prevKeyFrameIndex, float prevPlayingTime, float frameTime) { var entity = (IEntity) context; var playingTime = prevPlayingTime + frameTime; var keyFrameIndex = prevKeyFrameIndex; // Advance to the correct key frame. while (keyFrameIndex != KeyFrames.Count - 1 && KeyFrames[keyFrameIndex + 1].KeyTime < playingTime) { playingTime -= KeyFrames[keyFrameIndex + 1].KeyTime; keyFrameIndex += 1; var keyFrame = KeyFrames[keyFrameIndex]; SoundSystem.Play(Filter.Local(), keyFrame.Resource, entity, keyFrame.AudioParamsFunc.Invoke()); } return (keyFrameIndex, playingTime); } public struct KeyFrame { /// /// The RSI state to play when this keyframe gets triggered. /// public readonly string Resource; /// /// A function that returns the audio parameter to be used. /// The reason this is a function is so that this can return /// an AudioParam with different parameters each time, such as random pitch. /// public readonly Func AudioParamsFunc; /// /// The time between this keyframe and the last. /// public readonly float KeyTime; public KeyFrame(string resource, float keyTime, Func? audioParams = null) { Resource = resource; KeyTime = keyTime; AudioParamsFunc = audioParams ?? (() => AudioParams.Default); } } } }