diff --git a/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxBoundUserInterface.cs b/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxBoundUserInterface.cs new file mode 100644 index 0000000000..19db0140ca --- /dev/null +++ b/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxBoundUserInterface.cs @@ -0,0 +1,63 @@ +using Content.Shared.SimpleStation14.Jukebox; +using JetBrains.Annotations; +using Robust.Client.GameObjects; + +namespace Content.Client.SimpleStation14.Jukebox.Ui; + +[UsedImplicitly] +public sealed class JukeboxBoundUserInterface : BoundUserInterface +{ + [Dependency] private readonly IEntityManager _entity = default!; + private readonly ISawmill _log = default!; + + private JukeboxWindow? _window; + + public JukeboxBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + _log = EntMan.System().Log; + } + + protected override void Open() + { + base.Open(); + + if (!_entity.TryGetComponent(Owner, out var jukeboxComp)) + { + _log.Error("No Jukebox component found for {0}!", _entity.ToPrettyString(Owner)); + return; + } + + _window = new JukeboxWindow(jukeboxComp, _log) + { + Title = _entity.GetComponent(Owner).EntityName + }; + + _window.OpenCentered(); + _window.OnClose += Close; + + _window.OnPlayButtonPressed += () => SendMessage(new JukeboxPlayButtonPressedMessage()); + + _window.OnSkipButtonPressed += () => SendMessage(new JukeboxSkipButtonPressedMessage()); + + _window.OnSongSelected += song => SendMessage(new JukeboxSongSelectedMessage(song)); + } + + protected override void ReceiveMessage(BoundUserInterfaceMessage msg) + { + base.ReceiveMessage(msg); + + if (msg is not JukeboxUpdateStateMessage jukeboxMessage) + return; + + _window?.UpdateState(jukeboxMessage.PopulateSongs); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + + _window?.Dispose(); + } +} + diff --git a/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxSystem.cs b/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxSystem.cs new file mode 100644 index 0000000000..1fa196f764 --- /dev/null +++ b/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxSystem.cs @@ -0,0 +1,20 @@ +using Content.Shared.Emag.Systems; + +namespace Content.Shared.SimpleStation14.Jukebox; + +public sealed class SharedJukeBoxSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnEmagged); + } + + /// + /// Handles setting the Jukebox's state to emagged. + /// + private void OnEmagged(EntityUid jukeBox, JukeboxComponent jukeboxComp, ref GotEmaggedEvent args) + { + args.Handled = true; + } +} diff --git a/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxWindow.xaml b/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxWindow.xaml new file mode 100644 index 0000000000..4c5f7013cf --- /dev/null +++ b/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxWindow.xaml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxWindow.xaml.cs b/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxWindow.xaml.cs new file mode 100644 index 0000000000..418464091a --- /dev/null +++ b/Content.Client/SimpleStation14/Jukebox/Ui/JukeboxWindow.xaml.cs @@ -0,0 +1,243 @@ +using Content.Shared.SimpleStation14.Jukebox; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Prototypes; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Timing; +using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow; +using Content.Shared.SimpleStation14.Prototypes; +using System.Linq; +using Content.Client.Resources; +using Content.Client.Stylesheets; +using Robust.Client.Graphics; +using Robust.Client.ResourceManagement; + +namespace Content.Client.SimpleStation14.Jukebox.Ui; + +[GenerateTypedNameReferences] +public sealed partial class JukeboxWindow : FancyWindow +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IResourceCache _resource = default!; + + private readonly ISawmill _log = default!; + + private readonly JukeboxComponent _jukeboxComp; + + private TimeSpan _timeWillFinish = TimeSpan.Zero; + + private TimeSpan _timeStopped = TimeSpan.Zero; + + private TimeSpan _songDuration = TimeSpan.Zero; + + public Action? OnPlayButtonPressed; + + public Action? OnSkipButtonPressed; + + public Action? OnSongSelected; + + + public JukeboxWindow(JukeboxComponent jukeboxComp, ISawmill log) + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + _log = log; + _jukeboxComp = jukeboxComp; + + PlayButton.OnPressed += _ => OnPlayButtonPressed?.Invoke(); + SkipButton.OnPressed += _ => OnSkipButtonPressed?.Invoke(); + + SerialTitle.SetMessage(Loc.GetString("jukebox-ui-serial-title")); + SerialNumber.Text = jukeboxComp.SerialNumber; + SkipButton.TextureNormal = _resource.GetTexture(_jukeboxComp.UiButtonSkip); + + // Sets up the custom colours of the ui. + BG_1.PanelOverride = new StyleBoxFlat { BackgroundColor = jukeboxComp.UiColorBG }; + Panel_1.PanelOverride = new StyleBoxFlat { BackgroundColor = jukeboxComp.UiColorPanel }; + Panel_2.PanelOverride = new StyleBoxFlat { BackgroundColor = jukeboxComp.UiColorPanel }; + Panel_3.PanelOverride = new StyleBoxFlat { BackgroundColor = jukeboxComp.UiColorPanel }; + // Accent_1.PanelOverride = new StyleBoxFlat { BackgroundColor = jukeboxComp.JukeboxUiColorAccent }; + // Accent_2.PanelOverride = new StyleBoxFlat { BackgroundColor = jukeboxComp.JukeboxUiColorAccent }; + Accent_3.PanelOverride = new StyleBoxFlat { BackgroundColor = jukeboxComp.UiColorAccent }; + Accent_4.PanelOverride = new StyleBoxFlat { BackgroundColor = jukeboxComp.UiColorAccent }; + + // Sets up all the fonts. + SongName.FontOverride = _resource.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 18); + SongsLabel.FontOverride = _resource.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 22); + // SerialTitle.FontOverride = _resourceCache.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 16); + SerialHeader.FontOverride = _resource.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 28); + SerialNumber.FontOverride = _resource.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 16); + + if (!jukeboxComp.DecorativeUi) // Hides the decorative portion of the UI if the Jukebox doesn't have it. + { + DecorativeBox.Visible = false; + SetHeight -= DecorativeBox.MinSize.Y; + } + + + foreach (var control in CoinLabels.Children) // Death did this and I would like to not acknowledge it. + { + if (control is Label label) + { + label.FontOverride = _resource.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 16); + label.FontColorOverride = Color.FromHex("#A5762F"); + label.HorizontalAlignment = HAlignment.Center; + label.HorizontalExpand = false; + label.VerticalAlignment = VAlignment.Center; + label.HorizontalExpand = false; + } + } + + UpdateState(true); + } + + // Updates the progress bar of the song every frame, matching to the duration, if a song is actually playing. + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + if (_jukeboxComp.CurrentlyPlayingTrack == null) + { + RunTimeBar.Value = 0f; + + return; + } + + if (_jukeboxComp.Playing) + { + RunTimeBar.Value = (float) ((float) + (_songDuration.TotalSeconds - (_timeWillFinish.TotalSeconds - _timing.CurTime.TotalSeconds)) / _songDuration.TotalSeconds); + + return; + } + + if (_jukeboxComp.StoppedTime == null) + { + _log.Error(Loc.GetString("jukebox-error-no-stopped-time"), _jukeboxComp); + + return; + } + + RunTimeBar.Value = (float) ((float) + (_songDuration.TotalSeconds - (_timeWillFinish.TotalSeconds - _timeStopped.TotalSeconds)) / _songDuration.TotalSeconds); + } + + private void PopulateSongs() + { + SongPickerBox.RemoveAllChildren(); + + if (_jukeboxComp.Emagged) // We want the emagged songs on top. + foreach (var trackId in _jukeboxComp.EmaggedSongs.OrderBy(song => song).ToList()) + GenerateSongButton(trackId, true); + + foreach (var trackId in _jukeboxComp.Songs.OrderBy(song => song).ToList()) + GenerateSongButton(trackId, false); + } + + private void GenerateSongButton(string trackId, bool illegal) + { + if (!_prototype.TryIndex(trackId, out var track)) + { + _log.Error(Loc.GetString("jukebox-error-no-prototype"), trackId); + return; + } + + var newButton = new Button + { + Text = track.Name, + TextAlign = Label.AlignMode.Left, + ClipText = true, + RectClipContent = true, + MaxWidth = 180f, + Margin = new Thickness(0, 0, 0, 4), + }; + + newButton.StyleClasses.Add(StyleBase.ButtonOpenLeft); + if (illegal) + newButton.StyleClasses.Add(StyleBase.ButtonCaution); + newButton.OnPressed += _ => OnSongSelected?.Invoke(track.ID); + + SongPickerBox.AddChild(newButton); + } + + private void PopulateQueue() + { + NextSongsBox.RemoveAllChildren(); + + if (_jukeboxComp.NextUp.Count == 0) + { + NextSongsBox.AddChild(new Label + { + Text = Loc.GetString("jukebox-ui-queue-empty"), + }); + + return; + } + + foreach (var trackId in _jukeboxComp.NextUp) + { + if (!_prototype.TryIndex(trackId, out var track)) + { + _log.Error(Loc.GetString("jukebox-error-no-prototype"), trackId); + + continue; + } + + var newLabel = new Label + { + Text = track.Name, + HorizontalAlignment = HAlignment.Center, + HorizontalExpand = false, + Margin = new Thickness(0, 2, 0, 2), + }; + + NextSongsBox.AddChild(newLabel); + } + } + + public void UpdateState(bool repopulateSongs = false) + { + if (repopulateSongs) + PopulateSongs(); + + PopulateQueue(); + + if (_jukeboxComp.CurrentlyPlayingTrack == null || !_prototype.TryIndex(_jukeboxComp.CurrentlyPlayingTrack, out var track)) + { + SongName.Text = Loc.GetString("jukebox-ui-current-empty"); + SongIcon.Texture = _resource.GetTexture(_jukeboxComp.DefaultSongArtPath); + + SkipButton.Disabled = true; + PlayButton.Disabled = true; + + _timeWillFinish = TimeSpan.Zero; + _timeStopped = TimeSpan.Zero; + + PlayButton.TextureNormal = _resource.GetTexture(_jukeboxComp.UiButtonPlay); + + PlayButton.Disabled = true; + SkipButton.Disabled = true; + + return; + } + + _timeWillFinish = _jukeboxComp.FinishPlayingTime!.Value; + + _timeStopped = _jukeboxComp.StoppedTime ?? TimeSpan.Zero; + + _songDuration = track.Duration; + + SongName.Text = track.Name; + SongIcon.Texture = _resource.GetTexture(track.ArtPath ?? _jukeboxComp.DefaultSongArtPath); + + SkipButton.Disabled = false; + PlayButton.Disabled = false; + + PlayButton.TextureNormal = _resource.GetTexture(_jukeboxComp.Playing ? _jukeboxComp.UiButtonPause : _jukeboxComp.UiButtonPlay); + + PlayButton.Disabled = false; + SkipButton.Disabled = false; + } +} diff --git a/Content.Server/SimpleStation14/Jukebox/JukeboxSystem.cs b/Content.Server/SimpleStation14/Jukebox/JukeboxSystem.cs new file mode 100644 index 0000000000..ddb0a24a5f --- /dev/null +++ b/Content.Server/SimpleStation14/Jukebox/JukeboxSystem.cs @@ -0,0 +1,352 @@ +using Content.Shared.SimpleStation14.Jukebox; +using Content.Shared.SimpleStation14.Prototypes; +using Robust.Shared.Audio; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; +using Robust.Server.GameObjects; +using Content.Server.DeviceLinking.Systems; +using Robust.Shared.Random; +using Content.Shared.Power; +using System.Linq; +using Content.Server.Power.EntitySystems; + +namespace Content.Server.SimpleStation14.Jukebox; + +public sealed partial class JukeboxSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly DeviceLinkSystem _link = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + + public const string PortSongPlayed = "Start"; + public const string PortSongStopped = "Timer"; + + public const string PortPlayRandom = "PlayRandom"; + public const string PortSkip = "Skip"; + public const string PortPause = "Pause"; + public const string PortUnPause = "Unpause"; + public const string PortTogglePuase = "TogglePause"; + + #region Public functions + + /// + /// Tries to play a song in the Jukebox using the provided ID. + /// If the Jukebox is already playing a song, the song will be added to the queue. + /// + /// The song to be queued. + public void TryQueueSong(EntityUid jukebox, string song, JukeboxComponent? jukeboxComp = null) + { + if (!Resolve(jukebox, ref jukeboxComp)) + return; + + if (!jukeboxComp.CanPlay) + return; + + if (jukeboxComp.CurrentlyPlayingTrack != null) + { + if (jukeboxComp.NextUp.Count < jukeboxComp.MaxQueued) + { + jukeboxComp.NextUp.Add(song); + } + + UpdateState(jukebox, jukeboxComp); + + return; + } + + TryPlaySong(jukebox, song, jukeboxComp); + } + + /// + /// Ends the currently playing song in the Jukebox and plays the next song in the queue, if available. + /// + public void TrySkipSong(EntityUid jukebox, JukeboxComponent? jukeboxComp = null) + { + if (!Resolve(jukebox, ref jukeboxComp)) + return; + + if (!jukeboxComp.CanPlay) + return; + + EndTrack(jukebox, jukeboxComp); + + if (jukeboxComp.NextUp.Count > 0) + { + var toPlay = jukeboxComp.NextUp[0]; // Get the first song in the queue. + jukeboxComp.NextUp.RemoveAt(0); // And remove it now so we don't need to UpdateState() twice. + + TryPlaySong(jukebox, toPlay, jukeboxComp); + + return; + } + + UpdateState(jukebox, jukeboxComp); + } + + /// + /// Pauses the currently playing song and sets the Jukebox to a paused state. + /// + /// + /// See to stop the Jukebox instead. + /// Pausing a Jukebox will allow it to remember its paused state, even if it gets stopped later. + /// + public void DoPauseSong(EntityUid jukebox, JukeboxComponent? jukeboxComp = null) + { + if (!Resolve(jukebox, ref jukeboxComp)) + return; + + if (jukeboxComp.Paused || !jukeboxComp.Playing) + return; + + jukeboxComp.Paused = true; + + StopSong(jukebox, jukeboxComp); + } + + /// + /// Unpauses the Jukebox and resumes playing the current song from where it was paused. + /// + public void TryUnPauseSong(EntityUid jukebox, JukeboxComponent? jukeboxComp = null) + { + if (!Resolve(jukebox, ref jukeboxComp)) + return; + + if (!jukeboxComp.CanPlay) + return; + + if (!jukeboxComp.Paused) + return; + + jukeboxComp.Paused = false; + + TryRestart(jukebox, jukeboxComp); + } + + /// + /// Toggles the Jukebox's paused state. + /// + public void TryTogglePause(EntityUid jukebox, JukeboxComponent? jukeboxComp = null) + { + if (!Resolve(jukebox, ref jukeboxComp)) + return; + + if (jukeboxComp.Paused) + TryUnPauseSong(jukebox, jukeboxComp); + else + DoPauseSong(jukebox, jukeboxComp); + } + + public void TryPlayRandomSong(EntityUid jukebox, JukeboxComponent? jukeboxComp = null) + { + if (!Resolve(jukebox, ref jukeboxComp)) + return; + + var potentialSongs = jukeboxComp.Songs.ToList(); + + if (jukeboxComp.Emagged) + potentialSongs.AddRange(jukeboxComp.EmaggedSongs); + + TryPlaySong(jukebox, _random.Pick(potentialSongs), jukeboxComp); + } + + /// + /// Plays a song in the Jukebox using the provided and optional offset. + /// If the Jukebox is already playing a song, it will be stopped and replaced with the new song. + /// To queue a song instead, see . + /// + /// The JukeboxTrackPrototype representing the song to be played. + /// The optional offset from the start of the song to begin playing from. + public void TryPlaySong(EntityUid jukebox, string song, JukeboxComponent? jukeboxComp = null, TimeSpan offset = new TimeSpan()) + { + if (!Resolve(jukebox, ref jukeboxComp)) + return; + + if (!_prototype.TryIndex(song, out var songPrototype)) + { + Logger.Error($"Jukebox track prototype {song} not found!"); + return; + } + + TryPlaySong(jukebox, songPrototype, jukeboxComp, offset); + } + + /// + /// + /// Directly takes a instead. + /// + public void TryPlaySong(EntityUid jukebox, JukeboxTrackPrototype song, JukeboxComponent? jukeboxComp = null, TimeSpan offset = new TimeSpan()) + { + if (!Resolve(jukebox, ref jukeboxComp)) + return; + + if (!jukeboxComp.CanPlay) + return; + + if (offset > song.Duration) // Just to make sure we don't try to play a song from the future. + offset = song.Duration - TimeSpan.FromSeconds(0.1); + + Clean(jukebox, jukeboxComp); // Clean up any currently playing song. + + jukeboxComp.Paused = false; // Unpause the Jukebox if it was paused. + + jukeboxComp.Playing = true; // Set the Jukebox to playing. + + jukeboxComp.CurrentlyPlayingTrack = song.ID; // Set the currently playing song. + + jukeboxComp.FinishPlayingTime = _timing.CurTime + song.Duration - offset; // Set the time when the song should finish. + + jukeboxComp.CurrentlyPlayingStream = _audio.Play(song.Path, Filter.Broadcast(), jukebox, true, AudioParams.Default.WithPlayOffset((float) offset.TotalSeconds)); // Play the song, with any offset, and to every player in the game. + + _link.InvokePort(jukebox, PortSongPlayed); // Invoke the Jukebox's "Start" port. + + UpdateState(jukebox, jukeboxComp); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + + // Iterate over all Jukeboxes. + while (query.MoveNext(out var jukebox, out var jukeboxComp)) + { + // If the Jukebox is playing, and the song has finished, end the song. + // This was orignially done by starting a timer, but that stopped working out of nowhere, so... + if (jukeboxComp.Playing && _timing.CurTime >= jukeboxComp.FinishPlayingTime) + { + OnSongEnd(jukebox, jukeboxComp); + } + } + } + + #endregion Public functions + #region Private functions + + /// + /// Sets the Jukebox to either a state where it can or cannot play songs. + /// + private void CheckCanPlay(EntityUid uid, JukeboxComponent component) + { + var canPlay = true; + + if (!this.IsPowered(uid, EntityManager)) + canPlay = false; + + component.CanPlay = canPlay; + + if (canPlay) + TryRestart(uid, component); + else + StopSong(uid, component); + } + + /// + /// Stops the currently playing song and sets the Jukebox to a stopped state. + /// + /// + /// This stops the song, but does not indicate that the user wants the song paused. + /// For instance, a power outage may stop the song from playing, but the user would want it to continue automatically when power comes back. + /// If the user pauses the song manually, they do not want a power outage to restart it. + /// See to pause the Jukebox instead. + /// + private void StopSong(EntityUid jukeBox, JukeboxComponent jukeboxComp) + { + if (!jukeboxComp.Playing) + return; + + jukeboxComp.StoppedTime = _timing.CurTime; + + Clean(jukeBox, jukeboxComp); + } + + /// + /// Removes the track data from the Jukebox, and stops the song from playing. + /// + private void EndTrack(EntityUid jukeBox, JukeboxComponent jukeboxComp) + { + jukeboxComp.CurrentlyPlayingTrack = null; + + jukeboxComp.FinishPlayingTime = null; + + jukeboxComp.StoppedTime = null; + + _link.InvokePort(jukeBox, PortSongStopped); // Invoke the Jukebox's "Timer" port. + + Clean(jukeBox, jukeboxComp); + } + + /// + /// Cleans up the active elements of a playing song. + /// + /// + /// Called either when a song is stopped, or when a song ends. + /// This does not modify the Jukebox's state, and should be called after the state has been updated. + /// + private void Clean(EntityUid jukebox, JukeboxComponent jukeboxComp) + { + if (jukeboxComp.CurrentlyPlayingStream != null) + { + jukeboxComp.CurrentlyPlayingStream.Stop(); + jukeboxComp.CurrentlyPlayingStream = null; + } + + jukeboxComp.Playing = false; + + UpdateState(jukebox, jukeboxComp); + } + + /// + /// Tries to restart the Jukebox and continue playing the current song from where it was stopped. + /// + /// + /// Note, this will not unpause the Jukebox itself. The Jukebox must first be unpaused, and then restarted. + /// + /// Whether or not the Jukebox is now playing. + private void TryRestart(EntityUid jukeBox, JukeboxComponent jukeboxComp) + { + if (jukeboxComp.Paused || !jukeboxComp.CanPlay) + return; + + if (jukeboxComp.CurrentlyPlayingTrack == null || + jukeboxComp.FinishPlayingTime == null || + jukeboxComp.StoppedTime == null || + !_prototype.TryIndex(jukeboxComp.CurrentlyPlayingTrack, out var trackProto)) + return; + + var timeLeftBeforeFinished = (TimeSpan) (trackProto.Duration - (jukeboxComp.FinishPlayingTime - jukeboxComp.StoppedTime)); + + jukeboxComp.StoppedTime = null; + + TryPlaySong(jukeBox, trackProto, jukeboxComp, timeLeftBeforeFinished); + + return; + } + + /// + /// Updates the Jukebox's state and ui. + /// + /// Whether or not to populate the song list in the ui. + private void UpdateState(EntityUid jukebox, JukeboxComponent jukeboxComp, bool populateSongs = false) + { + Dirty(jukeboxComp); + + _appearance.SetData(jukebox, PowerDeviceVisuals.VisualState, jukeboxComp.Playing); // Set the Jukebox's playing animation if valid. + + _ui.TrySendUiMessage(jukebox, JukeboxUiKey.Key, new JukeboxUpdateStateMessage(populateSongs)); + } + + /// + /// Event handler for the song in the Jukebox reaching its end. + /// + private void OnSongEnd(EntityUid jukebox, JukeboxComponent jukeboxComp) + { + TrySkipSong(jukebox, jukeboxComp); + } + + #endregion Private functions +} diff --git a/Content.Server/SimpleStation14/Jukebox/JukeboxSystems.Interactions.cs b/Content.Server/SimpleStation14/Jukebox/JukeboxSystems.Interactions.cs new file mode 100644 index 0000000000..1cb0fed288 --- /dev/null +++ b/Content.Server/SimpleStation14/Jukebox/JukeboxSystems.Interactions.cs @@ -0,0 +1,142 @@ +using Content.Server.Construction; +using Content.Server.DeviceLinking.Events; +using Content.Server.Power.Components; +using Content.Shared.Damage; +using Content.Shared.Emag.Systems; +using Content.Shared.SimpleStation14.Jukebox; +using Robust.Shared.Random; + +namespace Content.Server.SimpleStation14.Jukebox; + +public sealed partial class JukeboxSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnComponentInit); + SubscribeLocalEvent((ent, comp, _) => Clean(ent, comp)); + + SubscribeLocalEvent((EntityUid ent, JukeboxComponent comp, ref EntityPausedEvent _) => CheckCanPlay(ent, comp)); + SubscribeLocalEvent((EntityUid ent, JukeboxComponent comp, ref EntityUnpausedEvent _) => CheckCanPlay(ent, comp)); + SubscribeLocalEvent((EntityUid ent, JukeboxComponent comp, ref PowerChangedEvent _) => CheckCanPlay(ent, comp)); + SubscribeLocalEvent(OnEmagged); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnExamineParts); + SubscribeLocalEvent(OnDamageChanged); + SubscribeLocalEvent(OnSignalReceived); + + SubscribeLocalEvent((ent, comp, _) => TryTogglePause(ent, comp)); + SubscribeLocalEvent((ent, comp, _) => TrySkipSong(ent, comp)); + SubscribeLocalEvent((ent, comp, msg) => TryQueueSong(ent, msg.Song, comp)); + } + + /// + /// Handles setting up a Jukebox. + /// + private void OnComponentInit(EntityUid uid, JukeboxComponent component, MapInitEvent args) + { + CheckCanPlay(uid, component); + + component.SerialNumber = GenerateSerialNumber(); + + _link.EnsureSourcePorts(uid, PortSongPlayed); + _link.EnsureSourcePorts(uid, PortSongStopped); + + _link.EnsureSinkPorts(uid, PortPlayRandom); + _link.EnsureSinkPorts(uid, PortSkip); + _link.EnsureSinkPorts(uid, PortPause); + _link.EnsureSinkPorts(uid, PortUnPause); + _link.EnsureSinkPorts(uid, PortTogglePuase); + + UpdateState(uid, component); + } + + /// + /// Handles setting the Jukebox's state to emagged. + /// + private void OnEmagged(EntityUid jukeBox, JukeboxComponent jukeboxComp, ref GotEmaggedEvent args) + { + jukeboxComp.Emagged = true; + args.Handled = true; + UpdateState(jukeBox, jukeboxComp); + } + + /// + /// Generates a valid serial number for the jukeboxes. This is just goofy. + /// + public string GenerateSerialNumber() + { + var digits = new int[8]; + + digits[0] = _random.Next(1, 10); + digits[1] = _random.Next(10); + digits[2] = digits[1]; + digits[3] = digits[0]; + digits[4] = (digits[0] + digits[1]) % 10; + digits[5] = digits[2] - digits[3]; + digits[6] = digits[4] * digits[5]; + digits[7] = (digits[0] + digits[1] + digits[5] + digits[4]) % 5; + + var letter = digits[7] == 0 ? 90 : digits[7] % 2 == 0 ? (digits[7] + 65) : (90 - digits[7]); + + var serial = $"{digits[0]}{digits[1]}{digits[2]}{digits[3]}{digits[4]}{digits[Math.Abs(5)]}{digits[Math.Abs(6)]}{digits[7]}{(char) letter}"; + + return serial; + } + + private void OnRefreshParts(EntityUid uid, JukeboxComponent component, RefreshPartsEvent args) + { + if (component.QueueSizeUpgradePart == null) + { + component.MaxQueued = component.MaxQueuedDefault; + return; + } + + var queueSizeMod = (int) Math.Floor(args.PartRatings[component.QueueSizeUpgradePart]); + + component.MaxQueued = component.MaxQueuedDefault * queueSizeMod; + } + + private void OnExamineParts(EntityUid uid, JukeboxComponent component, UpgradeExamineEvent args) + { + if (component.QueueSizeUpgradePart == null) + { + return; + } + + args.AddNumberUpgrade("jukebox-maxqueued-upgrade-string", component.MaxQueued - component.MaxQueuedDefault); + } + + private void OnDamageChanged(EntityUid uid, JukeboxComponent component, DamageChangedEvent args) + { + if (args.DamageIncreased && args.DamageDelta != null && args.DamageDelta.Total < 7 && _random.Prob(0.65f)) + TryPlayRandomSong(uid, component); + } + + private void OnSignalReceived(EntityUid uid, JukeboxComponent component, ref SignalReceivedEvent args) + { + switch (args.Port) + { + case PortPlayRandom: + TryPlayRandomSong(uid, component); + break; + case PortSkip: + TrySkipSong(uid, component); + break; + case PortPause: + DoPauseSong(uid, component); + break; + case PortUnPause: + TryUnPauseSong(uid, component); + break; + case PortTogglePuase: + TryTogglePause(uid, component); + break; + default: + return; + } + } +} diff --git a/Content.Shared/SimpleStation14/Jukebox/JukeboxComponent.cs b/Content.Shared/SimpleStation14/Jukebox/JukeboxComponent.cs new file mode 100644 index 0000000000..6018d19552 --- /dev/null +++ b/Content.Shared/SimpleStation14/Jukebox/JukeboxComponent.cs @@ -0,0 +1,166 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Shared.SimpleStation14.Jukebox; + +[RegisterComponent] +[NetworkedComponent] +[AutoGenerateComponentState] +public sealed partial class JukeboxComponent : Component +{ + /// + /// The list of songs that the Jukebox has in its playlist. + /// + [AutoNetworkedField] + [DataField("songs")] + [ViewVariables(VVAccess.ReadWrite)] + public List Songs { get; set; } = new(); + + /// + /// The list of songs that the Jukebox gains access to when emagged. + /// + [AutoNetworkedField] + [DataField("emaggedSongs")] + [ViewVariables(VVAccess.ReadWrite)] + public List EmaggedSongs { get; set; } = new(); + + /// + /// The maximum number of songs that can be queued at one time by default, with the lowest tier parts. + /// + [DataField("maxQueuedDefault")] + [ViewVariables(VVAccess.ReadWrite)] + public int MaxQueuedDefault { get; set; } = 3; + + /// + /// The maximum number of songs that can be queued at one time, with upgrades. + /// + [ViewVariables(VVAccess.ReadWrite)] + public int MaxQueued { get; set; } + + /// + /// The song art to be used when no song is playing. + /// + [DataField("defaultSongArtPath")] + public ResPath DefaultSongArtPath { get; } = new("/Textures/SimpleStation14/JukeboxTracks/default.png"); + + /// + /// A colour to be used in the Jukebox's UI. + /// Should be based on the sprite. + /// + [DataField("uiColorBG")] + public Color UiColorBG { get; } = Color.FromHex("#602C00"); + + /// + [DataField("uiColorPanel")] + public Color UiColorPanel { get; } = Color.FromHex("#480F0F"); + + /// + [DataField("uiColorAccent")] + public Color UiColorAccent { get; } = Color.FromHex("#20181B"); + + [DataField("uiButtonPlay")] + public ResPath UiButtonPlay { get; } = new("/Textures/SimpleStation14/Interface/MediaControls/play.png"); + + [DataField("uiButtonPause")] + public ResPath UiButtonPause { get; } = new("/Textures/SimpleStation14/Interface/MediaControls/pause.png"); + + [DataField("uiButtonSkip")] + public ResPath UiButtonSkip { get; } = new("/Textures/SimpleStation14/Interface/MediaControls/skip.png"); + + /// + /// Whether or not to include the decorative portion of the UI + /// which contains the serial number and the 'coin' slot. + /// + [DataField("decorativeUi")] + public bool DecorativeUi { get; } = false; + + /// + /// The part to be used for upgrading the queue size. + /// + /// + /// Leave empty to disable queue size upgrades. + /// + [DataField("queueSizeUpgradePart", customTypeSerializer: typeof(PrototypeIdSerializer))] + [ViewVariables(VVAccess.ReadWrite)] + public string? QueueSizeUpgradePart { get; set; } + + /// + /// The currently playing audio stream. + /// + public IPlayingAudioStream? CurrentlyPlayingStream { get; set; } + + /// + /// The ID of the currently playing song. + /// + [AutoNetworkedField] + public string? CurrentlyPlayingTrack { get; set; } + + /// + /// The list of songs that are queued to be played. + /// + [AutoNetworkedField] + [ViewVariables(VVAccess.ReadWrite)] + public List NextUp { get; set; } = new(); + + /// + /// The time when the currently playing song should finish. + /// + [AutoNetworkedField] + [ViewVariables(VVAccess.ReadOnly)] + public TimeSpan? FinishPlayingTime { get; set; } = null; + + /// + /// The time when the currently playing song was stopped. + /// + /// + /// Used to calculate the time remaining when a song is paused, or stopped by other means. + /// + [AutoNetworkedField] + [ViewVariables(VVAccess.ReadOnly)] + public TimeSpan? StoppedTime { get; set; } = null; + + /// + /// Whether or not the Jukebox should currently be playing. + /// + [AutoNetworkedField] + [ViewVariables(VVAccess.ReadOnly)] + public bool Playing { get; set; } = false; + + /// + /// Whether or not the Jukebox is currently paused. + /// + /// + /// The Jukebox may be unpaused, but not playing if is false. + /// + [AutoNetworkedField] + [ViewVariables(VVAccess.ReadOnly)] + public bool Paused { get; set; } = false; + + /// + /// Whether or not the Jukebox is actually active. + /// + /// + /// Generally controlled server-side, for things such as power, where a function isn't appropriate. + /// To trigger a change in this value, use . + /// + [AutoNetworkedField] + [ViewVariables(VVAccess.ReadOnly)] + public bool CanPlay { get; set; } = true; + + /// + /// If the Jukebox has been emagged. + /// + [AutoNetworkedField] + [ViewVariables(VVAccess.ReadWrite)] + public bool Emagged { get; set; } = false; + + /// + /// A serial number, following convuluted rules. Just for fun :) + /// + [AutoNetworkedField] + [ViewVariables(VVAccess.ReadWrite)] + public string SerialNumber { get; set; } = "000000000"; +} diff --git a/Content.Shared/SimpleStation14/Jukebox/JukeboxSystem.cs b/Content.Shared/SimpleStation14/Jukebox/JukeboxSystem.cs new file mode 100644 index 0000000000..c5f6c28954 --- /dev/null +++ b/Content.Shared/SimpleStation14/Jukebox/JukeboxSystem.cs @@ -0,0 +1,64 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.SimpleStation14.Jukebox; + +[Serializable, NetSerializable] +public enum JukeboxUiKey : byte +{ + Key +} + +/// +/// Sent from server to client to tell the client to update the Jukebox UI based on the . +/// +/// +/// This is used instead of because the component is already networked, and contains all the data needed. +/// +[Serializable, NetSerializable] +public sealed class JukeboxUpdateStateMessage : BoundUserInterfaceMessage +{ + public bool PopulateSongs { get; } + + public JukeboxUpdateStateMessage(bool populateSongs = false) + { + PopulateSongs = populateSongs; + } +} + +/// +/// Sent from client to server when the play button is pressed. +/// +[Serializable, NetSerializable] +public sealed class JukeboxPlayButtonPressedMessage : BoundUserInterfaceMessage +{ +} + +/// +/// Sent from client to server when the skip button is pressed. +/// +[Serializable, NetSerializable] +public sealed class JukeboxSkipButtonPressedMessage : BoundUserInterfaceMessage +{ +} + +/// +/// Sent from client to server when a song is selected, containing the selected song's ID. +/// +[Serializable, NetSerializable] +public sealed class JukeboxSongSelectedMessage : BoundUserInterfaceMessage +{ + public string Song { get; } + + public JukeboxSongSelectedMessage(string song) + { + Song = song; + } +} + +[Serializable, NetSerializable] +public enum JukeboxVisualLayers +{ + Lit, + UnLit, + Player, +} diff --git a/Content.Shared/SimpleStation14/Prototypes/JukeboxTrackPrototype.cs b/Content.Shared/SimpleStation14/Prototypes/JukeboxTrackPrototype.cs new file mode 100644 index 0000000000..0aa5384ac2 --- /dev/null +++ b/Content.Shared/SimpleStation14/Prototypes/JukeboxTrackPrototype.cs @@ -0,0 +1,81 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Audio; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Shared.SimpleStation14.Prototypes; + +[Prototype("jukeboxTrack")] +[Serializable, NetSerializable] +public sealed class JukeboxTrackPrototype : IPrototype, ISerializationHooks +{ + [IdDataField] + public string ID { get; } = default!; + + /// + /// Input string for the name, pre-localization. + /// + [DataField("name")] + private string NameString { get; } = default!; + + /// + /// Actual name, localized. + /// + public string Name => Loc.GetString(NameString); + + /// + /// Path of this track's audio file. + /// + [DataField("path")] + public SoundSpecifier Path { get; } = default!; + + /// + /// Serialized as a string because TimeSpan is not serializable, and converted to a TimeSpan with . + /// + [DataField("duration")] + private string DurationString { get; } = default!; + + /// + /// Actual duration as a TimeSpan. + /// + public TimeSpan Duration = TimeSpan.Zero; + + /// + /// Path of this track's art file. + /// + [DataField("artPath")] + public ResPath? ArtPath { get; } = null; + + void ISerializationHooks.AfterDeserialization() + { + Duration = ToTimeSpan(DurationString, Name); + } + + // I know this is stupid but I don't feel learning custom type serializers right now it's old code and it scares me. + private static TimeSpan ToTimeSpan(string time, string id) + { + var split = time.Split(':'); + if (split.Length != 2) + { + Logger.Error($"Invalid time format on track '{id}': {time}"); + Logger.Debug($"Duration string should be in the format 'mm:ss'"); + throw new ArgumentException($"Invalid time format on track '{id}': {time}"); + } + + if (!int.TryParse(split[0], out var minutes)) + { + Logger.Error($"Invalid time format on track '{id}': {time}"); + Logger.Debug($"Invalid minutes: {split[0]}"); + throw new ArgumentException($"Invalid time format on track '{id}': {time}"); + } + + if (!int.TryParse(split[1], out var seconds)) + { + Logger.Error($"Invalid time format on track '{id}': {time}"); + Logger.Debug($"Invalid seconds: {split[1]}"); + throw new ArgumentException($"Invalid time format on track '{id}': {time}"); + } + + return new TimeSpan(0, minutes, seconds); + } +} diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/a_tiny_green_beetle_beat.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/a_tiny_green_beetle_beat.ogg new file mode 100644 index 0000000000..47f4180999 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/a_tiny_green_beetle_beat.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/all_access_vacation.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/all_access_vacation.ogg new file mode 100644 index 0000000000..07e4eca64d Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/all_access_vacation.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/and_the_clown_smiled_outside_the_airlock.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/and_the_clown_smiled_outside_the_airlock.ogg new file mode 100644 index 0000000000..69a812b3fc Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/and_the_clown_smiled_outside_the_airlock.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/atmospherics.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/atmospherics.ogg new file mode 100644 index 0000000000..c38bd5acd9 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/atmospherics.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/attributions.yml b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/attributions.yml new file mode 100644 index 0000000000..7011ca025b --- /dev/null +++ b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/attributions.yml @@ -0,0 +1,4 @@ +- files: [loop.ogg, and_the_clown_smiled_outside_the_airlock.ogg, atmospherics.ogg, a_tiny_green_beetle_beat.ogg, clear_choice.ogg, connect.ogg, corporate_central_command.ogg, disposal.ogg, docking.ogg, do_i_look_like_a_clown_to_you.ogg, expensive_rugs_and_cheap_caskets.ogg, figured_as_much.ogg, forget_the_station.ogg, ghost_in_the_janitors_closet.ogg, habanero_donk_pocket.ogg, hivemind_channel.ogg, its_a_wall_see.ogg, i_found_these_pills_in_maintenance.ogg, no_loose_goose_here.ogg, okay_its_loose.ogg, on_to_the_next_station.ogg, outside_in_a_firesuit.ogg, pick_a_tyre_pattern.ogg, red_shadows_fall_on_clean_floors.ogg, saw_you_just_then.ogg, should_have_filled_my_form.ogg, smells_like_something_jaunted_here.ogg, spessmen_in_a_shuttle.ogg, strangely_dark_sky.ogg, the_soap_bar.ogg, the_wanderers_sail_without_wind.ogg, wrench_the_gas_canister_down.ogg, your_stay_aboard_the_station.ogg] + license: CC0-1.0 + source: "https://github.com/unitystation/unitystation" + copyright: DSC@apelsinsaft diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/clear_choice.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/clear_choice.ogg new file mode 100644 index 0000000000..12b41c6a32 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/clear_choice.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/connect.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/connect.ogg new file mode 100644 index 0000000000..7cfec19876 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/connect.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/corporate_central_command.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/corporate_central_command.ogg new file mode 100644 index 0000000000..ba80ae459d Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/corporate_central_command.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/disposal.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/disposal.ogg new file mode 100644 index 0000000000..8a6d25bba7 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/disposal.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/do_i_look_like_a_clown_to_you.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/do_i_look_like_a_clown_to_you.ogg new file mode 100644 index 0000000000..fd420cbbd2 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/do_i_look_like_a_clown_to_you.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/docking.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/docking.ogg new file mode 100644 index 0000000000..473f1835ac Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/docking.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/expensive_rugs_and_cheap_caskets.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/expensive_rugs_and_cheap_caskets.ogg new file mode 100644 index 0000000000..90d4527fee Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/expensive_rugs_and_cheap_caskets.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/figured_as_much.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/figured_as_much.ogg new file mode 100644 index 0000000000..197262bae8 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/figured_as_much.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/forget_the_station.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/forget_the_station.ogg new file mode 100644 index 0000000000..0cc175322e Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/forget_the_station.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/ghost_in_the_janitors_closet.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/ghost_in_the_janitors_closet.ogg new file mode 100644 index 0000000000..3b3b9309eb Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/ghost_in_the_janitors_closet.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/habanero_donk_pocket.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/habanero_donk_pocket.ogg new file mode 100644 index 0000000000..800af0356e Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/habanero_donk_pocket.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/hivemind_channel.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/hivemind_channel.ogg new file mode 100644 index 0000000000..1788aee2a3 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/hivemind_channel.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/i_found_these_pills_in_maintenance.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/i_found_these_pills_in_maintenance.ogg new file mode 100644 index 0000000000..40a46fef05 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/i_found_these_pills_in_maintenance.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/its_a_wall_see.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/its_a_wall_see.ogg new file mode 100644 index 0000000000..48b52a3690 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/its_a_wall_see.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/no_loose_goose_here.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/no_loose_goose_here.ogg new file mode 100644 index 0000000000..ee41a69393 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/no_loose_goose_here.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/okay_its_loose.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/okay_its_loose.ogg new file mode 100644 index 0000000000..ad61ed052d Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/okay_its_loose.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/on_to_the_next_station.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/on_to_the_next_station.ogg new file mode 100644 index 0000000000..e69e94278b Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/on_to_the_next_station.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/outside_in_a_firesuit.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/outside_in_a_firesuit.ogg new file mode 100644 index 0000000000..53a37393c6 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/outside_in_a_firesuit.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/pick_a_tyre_pattern.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/pick_a_tyre_pattern.ogg new file mode 100644 index 0000000000..f0ffbc8f6d Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/pick_a_tyre_pattern.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/red_shadows_fall_on_clean_floors.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/red_shadows_fall_on_clean_floors.ogg new file mode 100644 index 0000000000..763a123a4e Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/red_shadows_fall_on_clean_floors.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/saw_you_just_then.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/saw_you_just_then.ogg new file mode 100644 index 0000000000..14f29e4335 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/saw_you_just_then.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/should_have_filled_my_form.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/should_have_filled_my_form.ogg new file mode 100644 index 0000000000..6b46b2b02b Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/should_have_filled_my_form.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/smells_like_something_jaunted_here.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/smells_like_something_jaunted_here.ogg new file mode 100644 index 0000000000..f09efc9d1d Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/smells_like_something_jaunted_here.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/spessmen_in_a_shuttle.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/spessmen_in_a_shuttle.ogg new file mode 100644 index 0000000000..1211509cab Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/spessmen_in_a_shuttle.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/strangely_dark_sky.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/strangely_dark_sky.ogg new file mode 100644 index 0000000000..b212b7879c Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/strangely_dark_sky.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/the_soap_bar.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/the_soap_bar.ogg new file mode 100644 index 0000000000..9a3d8e66df Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/the_soap_bar.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/the_wanderers_sail_without_wind.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/the_wanderers_sail_without_wind.ogg new file mode 100644 index 0000000000..b48a88e54e Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/the_wanderers_sail_without_wind.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/wrench_the_gas_canister_down.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/wrench_the_gas_canister_down.ogg new file mode 100644 index 0000000000..65af34fb6c Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/wrench_the_gas_canister_down.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/your_stay_aboard_the_station.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/your_stay_aboard_the_station.ogg new file mode 100644 index 0000000000..311922295d Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/your_stay_aboard_the_station.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/african_dreamland.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/african_dreamland.ogg new file mode 100644 index 0000000000..e36c2b57fc Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/african_dreamland.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/attributions.yml b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/attributions.yml new file mode 100644 index 0000000000..6a1896e815 --- /dev/null +++ b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/attributions.yml @@ -0,0 +1,4 @@ +- files: ["african_dreamland.ogg", "bangkok_taxi_drive.ogg", "berlin_through_the_night.ogg", "heading_for_bamako.ogg", "mississippi_farewell.ogg", "paris_gipsy_swing.ogg", "sicilian_sundown.ogg", "the_balkan_night_train.ogg"] + license: "CC-BY-NC-ND-4.0" + copyright: "Dieter van der Westen on the Free Music Archive." + source: "https://freemusicarchive.org/music/dieter-van-der-westen/" diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/bangkok_taxi_drive.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/bangkok_taxi_drive.ogg new file mode 100644 index 0000000000..e20c3b63ed Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/bangkok_taxi_drive.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_through_the_night.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_through_the_night.ogg new file mode 100644 index 0000000000..28ef36d25c Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_through_the_night.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/headingfor_bamako.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/headingfor_bamako.ogg new file mode 100644 index 0000000000..99b0d7d1c3 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/headingfor_bamako.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/mississippi_farewell.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/mississippi_farewell.ogg new file mode 100644 index 0000000000..d8e863b0da Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/mississippi_farewell.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/paris_gipsy_swing.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/paris_gipsy_swing.ogg new file mode 100644 index 0000000000..3a642e5fd8 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/paris_gipsy_swing.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/sicilian_sundown.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/sicilian_sundown.ogg new file mode 100644 index 0000000000..ffadf97f9e Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/sicilian_sundown.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/the_balkan_night_train.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/the_balkan_night_train.ogg new file mode 100644 index 0000000000..57e7ab2e1a Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/the_balkan_night_train.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/agartha.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/agartha.ogg new file mode 100644 index 0000000000..1e7ed7390d Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/agartha.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/attributions.yml b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/attributions.yml new file mode 100644 index 0000000000..7aa26f65ae --- /dev/null +++ b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/attributions.yml @@ -0,0 +1,4 @@ +- files: [washed_away.ogg, the_current.ogg, drift.ogg, low_tide.ogg, sha.ogg, dancers_and_floaters.ogg, agartha.ogg] + license: "CC-BY-NC-4.0" + copyright: "Jon Shuemaker on the Free Music Archive" + source: "https://freemusicarchive.org/music/jon-shuemaker/" diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/dancers_and_floaters.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/dancers_and_floaters.ogg new file mode 100644 index 0000000000..4419aaba6d Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/dancers_and_floaters.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/drift.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/drift.ogg new file mode 100644 index 0000000000..0a0ef45fe2 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/drift.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/low_tide.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/low_tide.ogg new file mode 100644 index 0000000000..248a7f63de Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/low_tide.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/sha.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/sha.ogg new file mode 100644 index 0000000000..a8b7bc57c6 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/sha.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/the_current.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/the_current.ogg new file mode 100644 index 0000000000..c5da9433b1 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/the_current.ogg differ diff --git a/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/washed_away.ogg b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/washed_away.ogg new file mode 100644 index 0000000000..46eb6a5032 Binary files /dev/null and b/Resources/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/washed_away.ogg differ diff --git a/Resources/Audio/SimpleStation14/Lobby/01 The Gamble.ogg b/Resources/Audio/SimpleStation14/Lobby/01 The Gamble.ogg deleted file mode 100644 index c1cfdd5385..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/01 The Gamble.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/02 Guilty Pleasures.ogg b/Resources/Audio/SimpleStation14/Lobby/02 Guilty Pleasures.ogg deleted file mode 100644 index 9a281d1948..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/02 Guilty Pleasures.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/03 Jazzcuzzi.ogg b/Resources/Audio/SimpleStation14/Lobby/03 Jazzcuzzi.ogg deleted file mode 100644 index 49e7a33205..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/03 Jazzcuzzi.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/04 The Walk.ogg b/Resources/Audio/SimpleStation14/Lobby/04 The Walk.ogg deleted file mode 100644 index 481b08e650..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/04 The Walk.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/05 Velvet Bossa.ogg b/Resources/Audio/SimpleStation14/Lobby/05 Velvet Bossa.ogg deleted file mode 100644 index dcb639de43..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/05 Velvet Bossa.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/06 Colors.ogg b/Resources/Audio/SimpleStation14/Lobby/06 Colors.ogg deleted file mode 100644 index 83a8d3a3ee..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/06 Colors.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/07 Midnight Jam.ogg b/Resources/Audio/SimpleStation14/Lobby/07 Midnight Jam.ogg deleted file mode 100644 index 18e4e8de8a..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/07 Midnight Jam.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/08 Miles Ahead.ogg b/Resources/Audio/SimpleStation14/Lobby/08 Miles Ahead.ogg deleted file mode 100644 index db632e7721..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/08 Miles Ahead.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/09 Moody.ogg b/Resources/Audio/SimpleStation14/Lobby/09 Moody.ogg deleted file mode 100644 index 29720317d2..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/09 Moody.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/10 Flying Away.ogg b/Resources/Audio/SimpleStation14/Lobby/10 Flying Away.ogg deleted file mode 100644 index 84bda9db8f..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/10 Flying Away.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/11 Take It Easy.ogg b/Resources/Audio/SimpleStation14/Lobby/11 Take It Easy.ogg deleted file mode 100644 index f305357554..0000000000 Binary files a/Resources/Audio/SimpleStation14/Lobby/11 Take It Easy.ogg and /dev/null differ diff --git a/Resources/Audio/SimpleStation14/Lobby/african_dreamland_stereo.ogg b/Resources/Audio/SimpleStation14/Lobby/african_dreamland_stereo.ogg new file mode 100644 index 0000000000..55f7131929 Binary files /dev/null and b/Resources/Audio/SimpleStation14/Lobby/african_dreamland_stereo.ogg differ diff --git a/Resources/Audio/SimpleStation14/Lobby/attributions.yml b/Resources/Audio/SimpleStation14/Lobby/attributions.yml index 9e777c37d1..60f04a8822 100644 --- a/Resources/Audio/SimpleStation14/Lobby/attributions.yml +++ b/Resources/Audio/SimpleStation14/Lobby/attributions.yml @@ -1,4 +1,4 @@ -- files: ["01 The Gamble.ogg", "02 Guilty Pleasures.ogg", "03 Jazzcuzzi.ogg", "04 The Walk.ogg", "05 Velvet Bossa.ogg", "06 Colors.ogg", "07 Midnight Jam.ogg", "08 Miles Ahead.ogg", "09 Moody.ogg", "10 Flying Away.ogg", "11 Take It Easy.ogg"] - license: "CC-BY-NC-SA-3.0" - copyright: "All songs used are produced by Danya Vodovoz, royalty free." - source: "https://soundcloud.com/danyavodovoz" +- files: ["african_dreamland_stereo.ogg", "bangkok_taxi_drive_stereo.ogg", "berlin_through_the_night_stereo.ogg", "heading_for_bamako_stereo.ogg", "mississippi_farewell_stereo.ogg", "paris_gipsy_swing_stereo.ogg", "sicilian_sundown_stereo.ogg", "the_balkan_night_train_stereo.ogg"] + license: "CC-BY-NC-ND-4.0" + copyright: "Dieter van der Westen on the Free Music Archive." + source: "https://freemusicarchive.org/music/dieter-van-der-westen/" diff --git a/Resources/Audio/SimpleStation14/Lobby/bangkok_taxi_drive_stereo.ogg b/Resources/Audio/SimpleStation14/Lobby/bangkok_taxi_drive_stereo.ogg new file mode 100644 index 0000000000..ce5aadda19 Binary files /dev/null and b/Resources/Audio/SimpleStation14/Lobby/bangkok_taxi_drive_stereo.ogg differ diff --git a/Resources/Audio/SimpleStation14/Lobby/berlin_through_the_night_stereo.ogg b/Resources/Audio/SimpleStation14/Lobby/berlin_through_the_night_stereo.ogg new file mode 100644 index 0000000000..0692cef220 Binary files /dev/null and b/Resources/Audio/SimpleStation14/Lobby/berlin_through_the_night_stereo.ogg differ diff --git a/Resources/Audio/SimpleStation14/Lobby/heading_for_bamako_stereo.ogg b/Resources/Audio/SimpleStation14/Lobby/heading_for_bamako_stereo.ogg new file mode 100644 index 0000000000..2c4d3a2254 Binary files /dev/null and b/Resources/Audio/SimpleStation14/Lobby/heading_for_bamako_stereo.ogg differ diff --git a/Resources/Audio/SimpleStation14/Lobby/mississippi_farewell_stereo.ogg b/Resources/Audio/SimpleStation14/Lobby/mississippi_farewell_stereo.ogg new file mode 100644 index 0000000000..124c8dd20e Binary files /dev/null and b/Resources/Audio/SimpleStation14/Lobby/mississippi_farewell_stereo.ogg differ diff --git a/Resources/Audio/SimpleStation14/Lobby/paris_gipsy_swing_stereo.ogg b/Resources/Audio/SimpleStation14/Lobby/paris_gipsy_swing_stereo.ogg new file mode 100644 index 0000000000..9eb0616221 Binary files /dev/null and b/Resources/Audio/SimpleStation14/Lobby/paris_gipsy_swing_stereo.ogg differ diff --git a/Resources/Audio/SimpleStation14/Lobby/sicilian_sundown_stereo.ogg b/Resources/Audio/SimpleStation14/Lobby/sicilian_sundown_stereo.ogg new file mode 100644 index 0000000000..2d0deeb976 Binary files /dev/null and b/Resources/Audio/SimpleStation14/Lobby/sicilian_sundown_stereo.ogg differ diff --git a/Resources/Audio/SimpleStation14/Lobby/the_balkan_night_train_stereo.ogg b/Resources/Audio/SimpleStation14/Lobby/the_balkan_night_train_stereo.ogg new file mode 100644 index 0000000000..2b22a64c83 Binary files /dev/null and b/Resources/Audio/SimpleStation14/Lobby/the_balkan_night_train_stereo.ogg differ diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Jukebox/UI.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Jukebox/UI.ftl new file mode 100644 index 0000000000..66f7cdc0bd --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/Content/Jukebox/UI.ftl @@ -0,0 +1,4 @@ +jukebox-ui-queue-empty = Queue Is Empty +jukebox-ui-current-empty = Not Playing Anything +jukebox-ui-available-songs = Songs +jukebox-ui-serial-title = NanoTrasen Crew Auditory Recreation Device diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Jukebox/jukebox.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Jukebox/jukebox.ftl new file mode 100644 index 0000000000..d79479c9b5 --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/Content/Jukebox/jukebox.ftl @@ -0,0 +1,4 @@ +jukebox-maxqueued-upgrade-string = Queue size + +jukebox-error-no-prototype = No JukeboxTrackPrototype found for {"{0}"}! +jukebox-error-no-stopped-time = Owner jukebox of {"{0}"} is stopped but has no StoppedTime! diff --git a/Resources/Locale/en-US/machine-linking/receiver_ports.ftl b/Resources/Locale/en-US/machine-linking/receiver_ports.ftl index 36c36221b6..51a3598b94 100644 --- a/Resources/Locale/en-US/machine-linking/receiver_ports.ftl +++ b/Resources/Locale/en-US/machine-linking/receiver_ports.ftl @@ -88,3 +88,18 @@ signal-port-description-unbolt = Unbolts the door. signal-port-name-togglebolt = Toggle bolt signal-port-description-togglebolt = Toggles the bolt state of the door. + +signal-port-name-playrandom = Play random +signal-port-description-playrandom = Plays a random song. + +signal-port-name-skip = Skip +signal-port-description-skip = Skips the current song. + +signal-port-name-pause = Pause +signal-port-description-pause = Pauses the current song. + +signal-port-name-unpause = Unpause +signal-port-description-unpause = Unpauses the current song. + +signal-port-name-togglepause = Toggle pause +signal-port-description-togglepause = Toggles the pause state of the current song. diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 4c521e7c92..84234b4943 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -223,6 +223,7 @@ - WallmountGeneratorAPUElectronics - WallmountGeneratorElectronics - WallmountSubstationElectronics + - JukeboxMachineCircuitboard - type: MaterialStorage whitelist: tags: diff --git a/Resources/Prototypes/Nyanotrasen/Markers/Spawners/Random/devices.yml b/Resources/Prototypes/Nyanotrasen/Markers/Spawners/Random/devices.yml index 05491ef6d3..5001cd1a69 100644 --- a/Resources/Prototypes/Nyanotrasen/Markers/Spawners/Random/devices.yml +++ b/Resources/Prototypes/Nyanotrasen/Markers/Spawners/Random/devices.yml @@ -56,6 +56,7 @@ - EmitterCircuitboard - SurveillanceCameraWirelessRouterCircuitboard - SurveillanceWirelessCameraMonitorCircuitboard + - JukeboxMachineCircuitboard chance: 0.8 rarePrototypes: - TraversalDistorterMachineCircuitboard diff --git a/Resources/Prototypes/Research/civilianservices.yml b/Resources/Prototypes/Research/civilianservices.yml index 808ecee87c..3ac02052a9 100644 --- a/Resources/Prototypes/Research/civilianservices.yml +++ b/Resources/Prototypes/Research/civilianservices.yml @@ -89,6 +89,7 @@ - SynthesizerInstrument - DawInstrumentMachineCircuitboard - MassMediaCircuitboard + - JukeboxMachineCircuitboard # Tier 2 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Circuitboards/production.yml b/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Circuitboards/production.yml new file mode 100644 index 0000000000..4592fe6c56 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Circuitboards/production.yml @@ -0,0 +1,35 @@ +- type: entity + id: JukeboxMachineCircuitboard + parent: BaseMachineCircuitboard + name: jukebox machine circuitboard + description: A jukebox machine circuitboard. + components: + - type: Sprite + state: service + - type: MachineBoard + prototype: JukeboxClassic + requirements: + Capacitor: 2 + materialRequirements: + Steel: 5 + tagRequirements: + KeyedInstrument: + Amount: 1 + DefaultPrototype: SynthesizerInstrument + ExamineName: Keyed Instrument + StringInstrument: + Amount: 1 + DefaultPrototype: AcousticGuitarInstrument + ExamineName: String Instrument + PercussionInstrument: + Amount: 1 + DefaultPrototype: GlockenspielInstrument + ExamineName: Percussion Instrument + BrassInstrument: + Amount: 1 + DefaultPrototype: TrumpetInstrument + ExamineName: Brass Instrument + WoodwindInstrument: + Amount: 1 + DefaultPrototype: SaxophoneInstrument + ExamineName: Woodwind Instrument diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/Fun/jukebox.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/Fun/jukebox.yml new file mode 100644 index 0000000000..0c96e83d75 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/Fun/jukebox.yml @@ -0,0 +1,126 @@ +- type: entity + parent: [ BaseMachinePowered, ConstructibleMachine ] + abstract: true + id: JukeboxBase + name: jukebox + description: A jukebox, capable of playing music. + components: + - type: ActivatableUI + key: enum.JukeboxUiKey.Key + - type: ActivatableUIRequiresPower + - type: UserInterface + interfaces: + - key: enum.JukeboxUiKey.Key + type: JukeboxBoundUserInterface + - type: Sprite + sprite: SimpleStation14/Structures/Machines/jukebox.rsi + layers: + - state: base + - type: ApcPowerReceiver + powerLoad: 350 + - type: Jukebox # All that's technically needed- everything else is optional. + +- type: entity + parent: JukeboxBase + id: JukeboxClassic + name: jukebox + description: An old fashioned jukebox. + components: + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.45,0.25,0.45" + mask: + - MachineMask + layer: + - MachineLayer + density: 200 + - type: Jukebox + songs: + - JonShuemakerAgartha + - JonShuemakerDancersAndFloaters + - JonShuemakerSha + - JonShuemakerLowTide + - JonShuemakerTheCurrent + - JonShuemakerDrift + - JonShuemakerWashedAway + # - ApelsinsaftAllAccessVacation # Brokey + - ApelsinsaftAndTheClownSmiledOutsideTheAirlock + - ApelsinsaftAtmospherics + - ApelsinsaftATinyGreenBeetleBeat + - ApelsinsaftClearChoice + - ApelsinsaftConnect + - ApelsinsaftCorporateCentralCommand + - ApelsinsaftDisposal + - ApelsinsaftDocking + - ApelsinsaftDoILookLikeAClownToYou + - ApelsinsaftExpensiveRugsAndCheapCaskets + - ApelsinsaftFiguredAsMuch + - ApelsinsaftForgetTheStation + - ApelsinsaftGhostInTheJanitorsCloset + - ApelsinsaftHabaneroDonkPocket + - ApelsinsaftHivemindChannel + - ApelsinsaftItsAWallSee + - ApelsinsaftIFoundThesePillsInMaintenance + - ApelsinsaftNoLooseGooseHere + - ApelsinsaftOkayItsLoose + - ApelsinsaftOnToTheNextStation + - ApelsinsaftOutsideInAFiresuit + - ApelsinsaftPickATyrePattern + - ApelsinsaftRedShadowsFallOnCleanFloors + - ApelsinsaftSawYouJustThen + - ApelsinsaftShouldHaveFilledMyForm + - ApelsinsaftSmellsLikeSomethingJauntedHere + - ApelsinsaftSpessmenInAShuttle + - ApelsinsaftStrangelyDarkSky + - ApelsinsaftTheSoapBar + - ApelsinsaftTheWanderersSailWithoutWind + - ApelsinsaftWrenchTheGasCanisterDown + - ApelsinsaftYourStayAboardTheStation + - DieterVanDerWestenAfricanDreamland + - DieterVanDerWestenBangkokTaxiDrive + - DieterVanDerWestenBerlinThroughTheNight + - DieterVanDerWestenHeadingForBamako + - DieterVanDerWestenMississippiFarewell + - DieterVanDerWestenParisGipsySwing + - DieterVanDerWestenSicilianSundown + - DieterVanDerWestenTheBalkanNightTrain + queueSizeUpgradePart: Capacitor + maxQueuedDefault: 3 + uiColorBG: "#602C00" + uiColorPanel: "#480F0F" + uiColorAccent: "#20181B" + uiButtonPlay: "/Textures/SimpleStation14/Interface/MediaControls/play.png" + uiButtonPause: "/Textures/SimpleStation14/Interface/MediaControls/pause.png" + uiButtonSkip: "/Textures/SimpleStation14/Interface/MediaControls/skip.png" + decorativeUi: true + - type: Machine + board: JukeboxMachineCircuitboard + - type: Appearance + - type: Sprite + sprite: SimpleStation14/Structures/Machines/jukebox.rsi + layers: + - state: base + - state: powered + map: ["enum.JukeboxVisualLayers.UnLit"] + - state: powered_unlit + shader: unshaded + map: ["enum.JukeboxVisualLayers.Lit"] + - state: active + map: ["enum.JukeboxVisualLayers.Player"] + - type: GenericVisualizer + visuals: + enum.PowerDeviceVisuals.VisualState: + enum.JukeboxVisualLayers.Player: + True: { visible: true} + False: { visible: false } + enum.PowerDeviceVisuals.Powered: + enum.JukeboxVisualLayers.Lit: + True: { visible: true } + False: { visible: false } + enum.JukeboxVisualLayers.UnLit: + True: { visible: true } + False: { visible: false } + diff --git a/Resources/Prototypes/SimpleStation14/JukeboxTracks/apelsinaft.yml b/Resources/Prototypes/SimpleStation14/JukeboxTracks/apelsinaft.yml new file mode 100644 index 0000000000..b48bdc4943 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/JukeboxTracks/apelsinaft.yml @@ -0,0 +1,198 @@ +# - type: jukeboxTrack +# id: ApelsinsaftAllAccessVacation +# name: "All Access Vacation" +# duration: 1:04 +# path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/all_access_vacation.ogg" # This audio is hanging the client when it gets played??? + +- type: jukeboxTrack + id: ApelsinsaftAndTheClownSmiledOutsideTheAirlock + name: "And The Clown Smiled Outside The Airlock" + duration: 2:21 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/and_the_clown_smiled_outside_the_airlock.ogg" + +- type: jukeboxTrack + id: ApelsinsaftAtmospherics + name: "Atmospherics" + duration: 2:14 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/atmospherics.ogg" + +- type: jukeboxTrack + id: ApelsinsaftATinyGreenBeetleBeat + name: "A Tiny Green Beetle Beat" + duration: 4:48 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/a_tiny_green_beetle_beat.ogg" + +- type: jukeboxTrack + id: ApelsinsaftClearChoice + name: "Clear Choice" + duration: 2:46 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/clear_choice.ogg" + +- type: jukeboxTrack + id: ApelsinsaftConnect + name: "Connect" + duration: 3:56 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/connect.ogg" + +- type: jukeboxTrack + id: ApelsinsaftCorporateCentralCommand + name: "Corporate Central Command" + duration: 3:40 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/corporate_central_command.ogg" + +- type: jukeboxTrack + id: ApelsinsaftDisposal + name: "Disposal" + duration: 2:40 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/disposal.ogg" + +- type: jukeboxTrack + id: ApelsinsaftDocking + name: "Docking" + duration: 3:13 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/docking.ogg" + +- type: jukeboxTrack + id: ApelsinsaftDoILookLikeAClownToYou + name: "Do I Look Like A Clown To You" + duration: 2:24 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/do_i_look_like_a_clown_to_you.ogg" + +- type: jukeboxTrack + id: ApelsinsaftExpensiveRugsAndCheapCaskets + name: "Expensive Rugs And Cheap Caskets" + duration: 2:18 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/expensive_rugs_and_cheap_caskets.ogg" + +- type: jukeboxTrack + id: ApelsinsaftFiguredAsMuch + name: "Figured As Much" + duration: 1:36 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/figured_as_much.ogg" + +- type: jukeboxTrack + id: ApelsinsaftForgetTheStation + name: "Forget The Station" + duration: 2:52 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/forget_the_station.ogg" + +- type: jukeboxTrack + id: ApelsinsaftGhostInTheJanitorsCloset + name: "Ghost In The Janitors Closet" + duration: 3:14 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/ghost_in_the_janitors_closet.ogg" + +- type: jukeboxTrack + id: ApelsinsaftHabaneroDonkPocket + name: "Habanero Donk Pocket" + duration: 1:13 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/habanero_donk_pocket.ogg" + +- type: jukeboxTrack + id: ApelsinsaftHivemindChannel + name: "Hivemind Channel" + duration: 3:33 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/hivemind_channel.ogg" + +- type: jukeboxTrack + id: ApelsinsaftItsAWallSee + name: "Its A Wall See" + duration: 0:42 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/its_a_wall_see.ogg" + +- type: jukeboxTrack + id: ApelsinsaftIFoundThesePillsInMaintenance + name: "I Found These Pills In Maintenance" + duration: 2:08 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/i_found_these_pills_in_maintenance.ogg" + +- type: jukeboxTrack + id: ApelsinsaftNoLooseGooseHere + name: "No Loose Goose Here" + duration: 1:57 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/no_loose_goose_here.ogg" + +- type: jukeboxTrack + id: ApelsinsaftOkayItsLoose + name: "Okay Its Loose" + duration: 2:57 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/okay_its_loose.ogg" + +- type: jukeboxTrack + id: ApelsinsaftOnToTheNextStation + name: "On To The Next Station" + duration: 5:16 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/on_to_the_next_station.ogg" + +- type: jukeboxTrack + id: ApelsinsaftOutsideInAFiresuit + name: "Outside In A Firesuit" + duration: 2:22 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/outside_in_a_firesuit.ogg" + +- type: jukeboxTrack + id: ApelsinsaftPickATyrePattern + name: "Pick A Tyre Pattern" + duration: 4:16 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/pick_a_tyre_pattern.ogg" + +- type: jukeboxTrack + id: ApelsinsaftRedShadowsFallOnCleanFloors + name: "Red Shadows Fall On Clean Floors" + duration: 3:12 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/red_shadows_fall_on_clean_floors.ogg" + +- type: jukeboxTrack + id: ApelsinsaftSawYouJustThen + name: "Saw You Just Then" + duration: 1:41 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/saw_you_just_then.ogg" + +- type: jukeboxTrack + id: ApelsinsaftShouldHaveFilledMyForm + name: "Should Have Filled My Form" + duration: 3:20 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/should_have_filled_my_form.ogg" + +- type: jukeboxTrack + id: ApelsinsaftSmellsLikeSomethingJauntedHere + name: "Smells Like Something Jaunted Here" + duration: 3:43 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/smells_like_something_jaunted_here.ogg" + +- type: jukeboxTrack + id: ApelsinsaftSpessmenInAShuttle + name: "Spessmen In A Shuttle" + duration: 5:24 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/spessmen_in_a_shuttle.ogg" + +- type: jukeboxTrack + id: ApelsinsaftStrangelyDarkSky + name: "Strangely Dark Sky" + duration: 1:28 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/strangely_dark_sky.ogg" + +- type: jukeboxTrack + id: ApelsinsaftTheSoapBar + name: "The Soap Bar" + duration: 3:37 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/the_soap_bar.ogg" + +- type: jukeboxTrack + id: ApelsinsaftTheWanderersSailWithoutWind + name: "The Wanderers Sail Without Wind" + duration: 3:44 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/the_wanderers_sail_without_wind.ogg" + +- type: jukeboxTrack + id: ApelsinsaftWrenchTheGasCanisterDown + name: "Wrench The Gas Canister Down" + duration: 2:15 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/wrench_the_gas_canister_down.ogg" + +- type: jukeboxTrack + id: ApelsinsaftYourStayAboardTheStation + name: "Your Stay Aboard The Station" + duration: 5:29 + path: "/Audio/SimpleStation14/JukeboxTracks/Apelsinsaft/your_stay_aboard_the_station.ogg" + diff --git a/Resources/Prototypes/SimpleStation14/JukeboxTracks/dieter_van_der_westen.yml b/Resources/Prototypes/SimpleStation14/JukeboxTracks/dieter_van_der_westen.yml new file mode 100644 index 0000000000..4c6bbd20af --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/JukeboxTracks/dieter_van_der_westen.yml @@ -0,0 +1,55 @@ +- type: jukeboxTrack + id: DieterVanDerWestenAfricanDreamland + name: african dreamland + path: "/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/african_dreamland.ogg" + duration: 4:32 + artPath: "/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/african_dreamland.png" + +- type: jukeboxTrack + id: DieterVanDerWestenBangkokTaxiDrive + name: bangkok taxi drive + path: "/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/bangkok_taxi_drive.ogg" + duration: 3:39 + artPath: "/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/bangkok_taxi_drive.png" + +- type: jukeboxTrack + id: DieterVanDerWestenBerlinThroughTheNight + name: berlin through the night + path: "/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_through_the_night.ogg" + duration: 3:01 + artPath: "/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_through_the_night.png" + +- type: jukeboxTrack + id: DieterVanDerWestenHeadingForBamako + name: heading for bamako + path: "/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/heading_for_bamako.ogg" + duration: 3:38 + artPath: "/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/heading_for_bamako.png" + +- type: jukeboxTrack + id: DieterVanDerWestenMississippiFarewell + name: mississippi farewell + path: "/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/mississippi_farewell.ogg" + duration: 4:05 + artPath: "/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/mississippi_farewell.png" + +- type: jukeboxTrack + id: DieterVanDerWestenParisGipsySwing + name: paris gipsy swing + path: "/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/paris_gipsy_swing.ogg" + duration: 3:27 + artPath: "/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/paris_gipsy_swing.png" + +- type: jukeboxTrack + id: DieterVanDerWestenSicilianSundown + name: sicilian sundown + path: "/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/sicilian_sundown.ogg" + duration: 2:58 + artPath: "/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/sicilian_sundown.png" + +- type: jukeboxTrack + id: DieterVanDerWestenTheBalkanNightTrain + name: the balkan night train + path: "/Audio/SimpleStation14/JukeboxTracks/DieterVanDerWesten/the_balkan_night_train.ogg" + duration: 2:52 + artPath: "/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/the_balkan_night_train.png" diff --git a/Resources/Prototypes/SimpleStation14/JukeboxTracks/jon_shuemaker.yml b/Resources/Prototypes/SimpleStation14/JukeboxTracks/jon_shuemaker.yml new file mode 100644 index 0000000000..ce897c290d --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/JukeboxTracks/jon_shuemaker.yml @@ -0,0 +1,48 @@ +- type: jukeboxTrack + id: JonShuemakerAgartha + name: "Agartha" + path: "/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/agartha.ogg" + duration: 3:16 + artPath: "/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/sha.png" + +- type: jukeboxTrack + id: JonShuemakerDancersAndFloaters + name: "Dancers And Floaters" + path: "/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/dancers_and_floaters.ogg" + duration: 3:23 + artPath: "/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/sha.png" + +- type: jukeboxTrack + id: JonShuemakerSha + name: "Sha" + path: "/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/sha.ogg" + duration: 2:26 + artPath: "/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/sha.png" + +- type: jukeboxTrack + id: JonShuemakerLowTide + name: "Low Tide" + path: "/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/low_tide.ogg" + duration: 3:42 + artPath: "/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/drift.png" + +- type: jukeboxTrack + id: JonShuemakerTheCurrent + name: "The Current" + path: "/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/the_current.ogg" + duration: 4:23 + artPath: "/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/drift.png" + +- type: jukeboxTrack + id: JonShuemakerDrift + name: "Drift" + path: "/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/drift.ogg" + duration: 4:05 + artPath: "/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/drift.png" + +- type: jukeboxTrack + id: JonShuemakerWashedAway + name: "Washed Away" + path: "/Audio/SimpleStation14/JukeboxTracks/JonShuemaker/washed_away.ogg" + duration: 5:47 + artPath: "/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/drift.png" diff --git a/Resources/Prototypes/SimpleStation14/MachineLinking/receiver_ports.yml b/Resources/Prototypes/SimpleStation14/MachineLinking/receiver_ports.yml index 768be0108a..27df8c6fd9 100644 --- a/Resources/Prototypes/SimpleStation14/MachineLinking/receiver_ports.yml +++ b/Resources/Prototypes/SimpleStation14/MachineLinking/receiver_ports.yml @@ -12,3 +12,29 @@ id: ToggleBolt name: signal-port-name-togglebolt description: signal-port-description-togglebolt + +# Jukebox signals. +- type: sinkPort + id: PlayRandom + name: signal-port-name-playrandom + description: signal-port-description-playrandom + +- type: sinkPort + id: Skip + name: signal-port-name-skip + description: signal-port-description-skip + +- type: sinkPort + id: Pause + name: signal-port-name-pause + description: signal-port-description-pause + +- type: sinkPort + id: Unpause + name: signal-port-name-unpause + description: signal-port-description-unpause + +- type: sinkPort + id: TogglePause + name: signal-port-name-togglepause + description: signal-port-description-togglepause diff --git a/Resources/Prototypes/SimpleStation14/Recipes/Lathes/electronics.yml b/Resources/Prototypes/SimpleStation14/Recipes/Lathes/electronics.yml new file mode 100644 index 0000000000..bd99ac0fe5 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Recipes/Lathes/electronics.yml @@ -0,0 +1,7 @@ +- type: latheRecipe + id: JukeboxMachineCircuitboard + result: JukeboxMachineCircuitboard + completetime: 4 + materials: + Steel: 100 + Glass: 900 diff --git a/Resources/Prototypes/SoundCollections/lobby.yml b/Resources/Prototypes/SoundCollections/lobby.yml index 0cef599033..24e6602c64 100644 --- a/Resources/Prototypes/SoundCollections/lobby.yml +++ b/Resources/Prototypes/SoundCollections/lobby.yml @@ -1,14 +1,11 @@ - type: soundCollection id: LobbyMusic files: - - /Audio/SimpleStation14/Lobby/01 The Gamble.ogg - - /Audio/SimpleStation14/Lobby/02 Guilty Pleasures.ogg - - /Audio/SimpleStation14/Lobby/03 Jazzcuzzi.ogg - - /Audio/SimpleStation14/Lobby/04 The Walk.ogg - - /Audio/SimpleStation14/Lobby/05 Velvet Bossa.ogg - - /Audio/SimpleStation14/Lobby/06 Colors.ogg - - /Audio/SimpleStation14/Lobby/07 Midnight Jam.ogg - - /Audio/SimpleStation14/Lobby/08 Miles Ahead.ogg - - /Audio/SimpleStation14/Lobby/09 Moody.ogg - - /Audio/SimpleStation14/Lobby/10 Flying Away.ogg - - /Audio/SimpleStation14/Lobby/11 Take It Easy.ogg + - /Audio/SimpleStation14/Lobby/african_dreamland_stereo.ogg + - /Audio/SimpleStation14/Lobby/bangkok_taxi_drive_stereo.ogg + - /Audio/SimpleStation14/Lobby/berlin_through_the_night_stereo.ogg + - /Audio/SimpleStation14/Lobby/heading_for_bamako_stereo.ogg + - /Audio/SimpleStation14/Lobby/mississippi_farewell_stereo.ogg + - /Audio/SimpleStation14/Lobby/paris_gipsy_swing_stereo.ogg + - /Audio/SimpleStation14/Lobby/sicilian_sundown_stereo.ogg + - /Audio/SimpleStation14/Lobby/the_balkan_night_train_stereo.ogg diff --git a/Resources/Textures/SimpleStation14/Interface/MediaControls/pause.png b/Resources/Textures/SimpleStation14/Interface/MediaControls/pause.png new file mode 100644 index 0000000000..8d768da520 Binary files /dev/null and b/Resources/Textures/SimpleStation14/Interface/MediaControls/pause.png differ diff --git a/Resources/Textures/SimpleStation14/Interface/MediaControls/pause.png.yml b/Resources/Textures/SimpleStation14/Interface/MediaControls/pause.png.yml new file mode 100644 index 0000000000..dabd6601f7 --- /dev/null +++ b/Resources/Textures/SimpleStation14/Interface/MediaControls/pause.png.yml @@ -0,0 +1,2 @@ +sample: + filter: true diff --git a/Resources/Textures/SimpleStation14/Interface/MediaControls/play.png b/Resources/Textures/SimpleStation14/Interface/MediaControls/play.png new file mode 100644 index 0000000000..a2019f63d0 Binary files /dev/null and b/Resources/Textures/SimpleStation14/Interface/MediaControls/play.png differ diff --git a/Resources/Textures/SimpleStation14/Interface/MediaControls/play.png.yml b/Resources/Textures/SimpleStation14/Interface/MediaControls/play.png.yml new file mode 100644 index 0000000000..dabd6601f7 --- /dev/null +++ b/Resources/Textures/SimpleStation14/Interface/MediaControls/play.png.yml @@ -0,0 +1,2 @@ +sample: + filter: true diff --git a/Resources/Textures/SimpleStation14/Interface/MediaControls/playpause.png b/Resources/Textures/SimpleStation14/Interface/MediaControls/playpause.png new file mode 100644 index 0000000000..06de715424 Binary files /dev/null and b/Resources/Textures/SimpleStation14/Interface/MediaControls/playpause.png differ diff --git a/Resources/Textures/SimpleStation14/Interface/MediaControls/playpause.png.yml b/Resources/Textures/SimpleStation14/Interface/MediaControls/playpause.png.yml new file mode 100644 index 0000000000..dabd6601f7 --- /dev/null +++ b/Resources/Textures/SimpleStation14/Interface/MediaControls/playpause.png.yml @@ -0,0 +1,2 @@ +sample: + filter: true diff --git a/Resources/Textures/SimpleStation14/Interface/MediaControls/skip.png b/Resources/Textures/SimpleStation14/Interface/MediaControls/skip.png new file mode 100644 index 0000000000..b0c95951f3 Binary files /dev/null and b/Resources/Textures/SimpleStation14/Interface/MediaControls/skip.png differ diff --git a/Resources/Textures/SimpleStation14/Interface/MediaControls/skip.png.yml b/Resources/Textures/SimpleStation14/Interface/MediaControls/skip.png.yml new file mode 100644 index 0000000000..dabd6601f7 --- /dev/null +++ b/Resources/Textures/SimpleStation14/Interface/MediaControls/skip.png.yml @@ -0,0 +1,2 @@ +sample: + filter: true diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/africa_dreamland.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/africa_dreamland.png new file mode 100644 index 0000000000..567aae05cd Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/africa_dreamland.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/balkan_night_train.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/balkan_night_train.png new file mode 100644 index 0000000000..504cdf2c46 Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/balkan_night_train.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/bangkok_taxi_drive.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/bangkok_taxi_drive.png new file mode 100644 index 0000000000..288148c707 Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/bangkok_taxi_drive.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_through_the_night.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_through_the_night.png new file mode 100644 index 0000000000..c67283e6a8 Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_through_the_night.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_to_bamako.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_to_bamako.png new file mode 100644 index 0000000000..1b13f4f4ce Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/berlin_to_bamako.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/heading_for_bamako.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/heading_for_bamako.png new file mode 100644 index 0000000000..7405f6a1b0 Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/heading_for_bamako.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/mississippi_farewell.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/mississippi_farewell.png new file mode 100644 index 0000000000..1cfa528f85 Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/mississippi_farewell.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/paris_gipsy_swing.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/paris_gipsy_swing.png new file mode 100644 index 0000000000..abf51c81d5 Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/paris_gipsy_swing.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/sicilian_sundown.png b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/sicilian_sundown.png new file mode 100644 index 0000000000..18cdffe4df Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/DieterVanDerWesten/sicilian_sundown.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/drift.png b/Resources/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/drift.png new file mode 100644 index 0000000000..f4413362af Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/drift.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/sha.png b/Resources/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/sha.png new file mode 100644 index 0000000000..294811798a Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/JonShuemaker/sha.png differ diff --git a/Resources/Textures/SimpleStation14/JukeboxTracks/default.png b/Resources/Textures/SimpleStation14/JukeboxTracks/default.png new file mode 100644 index 0000000000..063f341d36 Binary files /dev/null and b/Resources/Textures/SimpleStation14/JukeboxTracks/default.png differ diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/active.png b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/active.png new file mode 100644 index 0000000000..a57a117e40 Binary files /dev/null and b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/active.png differ diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/base.png b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/base.png new file mode 100644 index 0000000000..27abb5535c Binary files /dev/null and b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/base.png differ diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/meta.json b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/meta.json new file mode 100644 index 0000000000..cc1a19c095 --- /dev/null +++ b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/meta.json @@ -0,0 +1,34 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from TGStation at https://github.com/tgstation/tgstation/commit/1dd5021b2c5b64e954935bdf77bc973c34016a04", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "base" + }, + { + "name": "powered" + }, + { + "name": "powered_unlit" + }, + { + "name": "active", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.8, + 0.4, + 0.2 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/powered.png b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/powered.png new file mode 100644 index 0000000000..32c8bedba4 Binary files /dev/null and b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/powered.png differ diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/powered_unlit.png b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/powered_unlit.png new file mode 100644 index 0000000000..b40cb47c71 Binary files /dev/null and b/Resources/Textures/SimpleStation14/Structures/Machines/jukebox.rsi/powered_unlit.png differ