Skip to content

Commit 9bf2770

Browse files
authored
Radio Host Job and Equipment (#5288)
## Short description <!-- What do you propose to change with your PR? --> Mirror of my [Moffstation PR](moff-station/moff-station-14#1471) porting Goobstation's Radio Host job and equipment. Since the code originates from Goobstation which is an AGPL licensed work, it is required to be relicensed to MIT. You can see screenshots of messages from JohnJohn, Rouden, loltart and H20we (jvne) giving MIT approval in the above link. Each have contributed majorly or in part to the ported code and thus each were reached out for approval which was received. This adds Station Radio equipment consisting of... - Station Radio Server - Station Radio Rig - Vinyl Player - Tape Deck - Station Radio Receivers These machines will need to eventually be incorporated into mapping along with Job spawn markers for the Radio Host. Station Radio Server, Rig, Vinyl Player and the Tape deck should ideally be mapped in a closed secure room to avoid access from random persons. A new access was added called "Journalism" which is intended for the Radio Host and Reporter. Locking other service workers from accessing the equipment. Appropriate Journalist Access Doors have been added for mapping. Station Radio Receivers will need to be placed around stations and on some shuttles like the Cargo Shuttle. A new research is added for creating circuit boards for the Server, Rig, Vinyl player and Tape Deck. The Station Radio Receiver board can be created straight from the autolathe with no research required. A large selection of songs and ads have been added. These can be inserted into Vinyl Players to play said audio tracks. Vinyls and CDs have a chance to spawn in Maintenance. You can also purchase a crate of Vinyls or ADs through cargo. Syndicate Agents can purchase a new Disruptive CD called Numbers. Which when inserted into a Vinyl player and broadcasted across station, it will summon a random threat upon completion. The Vinyl player must be connected to a Station Rig which must also be connected to a server in order for the CD to work. Nukies can find a collection of joke CDs from their uplinks. ## Current Issues ~~I am having issues with getting Journalist access to appear in ID computers.~~ No way to test to see how TTS will work with this. If they broadcast over the radio or not. ~~Unsure if there are enough mapping assets included (doors, etc). I don't know mapping so I don't know what else might be required.~~ ~~Whatever the rabbit thinks of the code.~~ ## Why we need to add this <!-- What is the reason for adding these changes? Please post links to Discussions as well as Bug Reports here. Please describe how this will change the game balance. --> The Radio Host is a person whose whole purpose is to maintain and run the Station's radio. Playing songs, advertisements as well as hosting interviews live on air. A fun service role which adds variety to the game. Plus more things to do on high pop. ## Test plan <!-- Describe how you tested the pull request, and how someone reviewing this PR can test it themselves. --> Load Branch Add Testing YAML from below. ### Testing Radio Host Equipment 1. Spawn in CrateRadioHostFIlled. 2. Activate all 4 flat packs. 3. Link the Vinyl Player to the Station Radio Rig, and the Station Radio Rig to the Station Radio Server. 4. Spawn in CrateRadioHostVinyls and CrateRadioHostADs. 5. Open and observe random selection of Vinyls and CDs. 6. Spawn StationRadioReceiver away from the Vinyl Player. 7. Insert a Vinyl or CD into the Vinyl player. 8. Listen to Music/AD. 9. Walk to the StationRadioReceiver and here same Music/AD playing. 10. Press E on StationRadioReceiver to turn on and off. 11. Alt Click StationRadioReceiver to turn volume down/up. 12. Right Click StationRadioReceiver and select to Lower or Increase Volume. 13. Unanchor/Mess with power to StationRadioReceiver. 14. Load a second game client. 15. Position the second client in another room with a StationRadioReceiver. 16. On the first client, spawn a tape recorder and record you saying some things. 17. Rewind tape and insert it into your Tape Deck. 18. Turn on the station Radio Server by pressing E on it. 19. Say words, and observe them be transmitted through the radio on the second client. 20. Turn the radio receiver volume down, and observe the sounds coming through as whispers. 21. Play the tape on the Tape Deck, and observe it playing through the station. ### Testing Acquiring Radio Host Gear 1. Traverse through the R&D portal on Dev Map. 2. Check the Autolathe and see Station Radio Machine Board available for printing. 3. Insert the Debug Research Disk into the Research Server 4. Research the Civilian Tree until Radio Music Communications appears. 5. Spawn a Circuit Imprinter and observer no Radio Host Equipment Available. 6. Unlock Radio Music Communications. 7. Observe Radio Host Gear now an option. 8. Print and build all pieces of Radio Equipment. Radio Receiver, Tape Deck, Vinyl Player, Radio Rig and Radio Server. 9. Observe construction graphs working. 10. Spawn in Cargo Request Computer. 11. Observe Vinyls Crate and ADs Crate as purchase options. 12. Spawn a Cargo Telepad and link to the Cargo Request Computer. 13. Spawn in some spesos and add to Cargo Request Computer. 14. Purchase a vinyls and ads crate. 20. Open crates and observe random selection of Vinyls. ### Testing Numbers CD calling in Threat. 1. Spawn in a Vinyl Player. 2. Spawn in CDNumbers. 3. Attempt to insert CD and see it fail to play. 4. Spawn in a Radio Rig and Radio Server. 5. Link three machines together. 6. Insert Numbers CD and observe it playing. 7. Eject the Numbers CD, and spawn in CDNumbersQuickAdmin (CD: Nmbrz) 8. Insert and wait 15 seconds for CD to finish playing. 9. Observe a threat is called via Central Command Announcement and the CD is destroyed after completion. ### Threat Table Chances for Numbers CD ``` Threat Chances 20% Major Threat - 8% Lone Op - 6% Dragon - 4% Colossus - 2% Wizard 60% Moderate Threat - 18% Ninja - 16% Eeplet - 12% Rod (8% fast Rod, 4% slow Rod) - 10% Revenant - 4% Pirate 20% Minor Threat - 8% Clown Trio - 12% Dead Drop ``` ## Media (Video/Screenshots) <!-- Attach media if the PR makes in-game changes (clothing, items, features, etc). --> **FULL DEMONSTATION HERE** https://youtu.be/4D5zqJWV-IY <img width="1024" height="514" alt="image" src="https://github.com/user-attachments/assets/c04ed5a3-dee1-4723-adfd-79dd307150f4" /> <img width="775" height="618" alt="image" src="https://github.com/user-attachments/assets/a106cb94-afe8-4898-b924-3908b410986f" /> <img width="488" height="224" alt="image" src="https://github.com/user-attachments/assets/a1c1f6e9-0a35-42a9-8945-68528a563b6c" /> ## Checks <!-- check boxes for faster reviewing of your PR --> - [X] I do not require assistance to complete the PR. - [X] Before posting/requesting review of a PR, I have verified that the changes work. - [X] I have added screenshots/videos of the changes, or this PR does not change in-game mechanics. - [X] I affirm that my changes are licensed under the [MIT License](https://github.com/ss14Starlight/space-station-14/blob/Starlight/LICENSE.TXT) and grant permission for use in this repository under its conditions. **Changelog** :cl: JohnJJohn, Rouden, H20we, loltart - add: Radio Host equipment has found it's way into the sector. - add: Syndicate agents can find illegal CDs in their uplinks.
1 parent ff5aa75 commit 9bf2770

314 files changed

Lines changed: 4765 additions & 55 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Content.Shared.Speech;
1414
using Content.Shared.Speech.Components;
1515
using Robust.Shared.Prototypes;
16+
using Content.Shared.Power.EntitySystems; // Goobstation - Radio Host
1617

1718
#region Starlight
1819
using Content.Server._Starlight.Language;
@@ -32,6 +33,8 @@ public sealed partial class RadioDeviceSystem : SharedRadioDeviceSystem
3233
[Dependency] private InteractionSystem _interaction = default!;
3334
[Dependency] private SharedAppearanceSystem _appearance = default!;
3435

36+
[Dependency] private SharedPowerReceiverSystem _power = default!; // Goobstation - Radio Host
37+
3538
// Used to prevent a shitter from using a bunch of radios to spam chat.
3639
private HashSet<(string, EntityUid, string)> _recentlySent = new(); // Starlight edit
3740

@@ -192,7 +195,7 @@ private void OnAttemptListen(EntityUid uid, RadioMicrophoneComponent component,
192195

193196
private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref RadioReceiveEvent args)
194197
{
195-
if (uid == args.RadioSource)
198+
if (uid == args.RadioSource || component.PowerRequired && !_power.IsPowered(uid)) // Goobstation - Radio Host - Powered required
196199
return;
197200

198201
var nameEv = new TransformSpeakerNameEvent(args.MessageSource, Name(args.MessageSource));
@@ -204,8 +207,9 @@ private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref
204207

205208
// log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios
206209
var message = args.OriginalChatMsg.Message; // Starlight-edit: The chat system will handle the rest and re-obfuscate if needed.
207-
_chat.TrySendInGameICMessage(uid, message, InGameICChatType.Whisper, ChatTransmitRange.GhostRangeLimit,
208-
nameOverride: name, checkRadioPrefix: false, languageOverride: args.Language); // Starlight
210+
_chat.TrySendInGameICMessage(uid, message, InGameICChatType.Whisper, ChatTransmitRange.GhostRangeLimit, nameOverride: name,
211+
checkRadioPrefix: component.ParseRadioPrefix, // Starlight - Radio Host, change LouderSpeech to ParseRadioPrefix
212+
languageOverride: args.Language); // Starlight
209213
}
210214

211215
private void OnIntercomEncryptionChannelsChanged(Entity<IntercomComponent> ent, ref EncryptionChannelsChangedEvent args)
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
using Content.Shared._Goobstation.StationRadio.Components; // Starlight - _Goob -> _Goobstation
2+
using Content.Shared._Goobstation.StationRadio.Events; // Starlight - _Goob -> _Goobstation
3+
using Content.Server.GameTicking;
4+
using Content.Server.Station.Systems;
5+
using Content.Shared.Communications;
6+
using Content.Shared.Containers.ItemSlots;
7+
using Content.Shared.Popups;
8+
using Content.Shared.Power.EntitySystems;
9+
using Content.Shared.Random;
10+
using Content.Shared.Random.Helpers;
11+
using Robust.Shared.Audio;
12+
using Robust.Shared.Audio.Systems;
13+
using Robust.Shared.Containers;
14+
using Robust.Shared.Prototypes;
15+
using Robust.Shared.Random;
16+
using Robust.Shared.Timing;
17+
using System.Linq;
18+
using Content.Shared.Radio.Components;
19+
using Content.Server.Chat.Systems;
20+
using Content.Shared._Goobstation.StationRadio.Systems; // Starlight - Station Radio Check oved to StationRadioReceiverSystem
21+
22+
namespace Content.Server._Goobstation.StationRadio; // Starlight - _Goob -> _Goobstation
23+
24+
/// <summary>
25+
/// System that handles spawning game rules when vinyl disks finish playing.
26+
/// </summary>
27+
public sealed partial class VinylSummonRuleSystem : EntitySystem
28+
{
29+
[Dependency] private IGameTiming _timing = default!;
30+
[Dependency] private SharedAudioSystem _audio = default!;
31+
[Dependency] private GameTicker _gameTicker = default!;
32+
[Dependency] private SharedContainerSystem _containers = default!;
33+
[Dependency] private IPrototypeManager _prototypeManager = default!;
34+
[Dependency] private IRobustRandom _random = default!;
35+
[Dependency] private StationSystem _stationSystem = default!;
36+
[Dependency] private SharedPowerReceiverSystem _power = default!;
37+
[Dependency] private ItemSlotsSystem _itemSlots = default!;
38+
[Dependency] private SharedPopupSystem _popups = default!;
39+
[Dependency] private ChatSystem _chat = default!;
40+
[Dependency] private readonly StationRadioReceiverSystem _stationRadio = default!; // Starlight - Station Radio Check oved to StationRadioReceiverSystem
41+
42+
private record struct TrackingData(EntityUid VinylPlayerUid, TimeSpan EndTime);
43+
private readonly Dictionary<EntityUid, TrackingData> _trackingVinyls = new();
44+
45+
public override void Initialize()
46+
{
47+
base.Initialize();
48+
49+
SubscribeLocalEvent<VinylPlayerComponent, VinylInsertedEvent>(OnVinylInserted);
50+
SubscribeLocalEvent<VinylPlayerComponent, VinylRemovedEvent>(OnVinylRemoved);
51+
}
52+
53+
private void OnVinylInserted(EntityUid uid, VinylPlayerComponent player, ref VinylInsertedEvent args)
54+
{
55+
var playerUid = uid;
56+
var vinylUid = args.Vinyl;
57+
58+
// Check if the inserted entity has the summon rule component / A song
59+
if (!TryComp<VinylSummonRuleComponent>(vinylUid, out _)
60+
|| !TryComp<VinylComponent>(vinylUid, out var vinylComp)
61+
|| vinylComp.Song == null)
62+
return;
63+
64+
void QueueSafeEject()
65+
{
66+
Timer.Spawn(0, () => EjectVinyl(playerUid, vinylUid));
67+
}
68+
69+
// Check if vinyl player is on a station
70+
if (_stationSystem.GetOwningStation(playerUid) == null)
71+
{
72+
_popups.PopupPredicted(Loc.GetString("vinyl-popout-no-station"), playerUid, null, PopupType.Medium);
73+
QueueSafeEject();
74+
return;
75+
}
76+
77+
// Check if vinyl player is powered
78+
if (!_power.IsPowered(playerUid))
79+
{
80+
_popups.PopupPredicted(Loc.GetString("vinyl-popout-no-power"), playerUid, null, PopupType.Medium);
81+
QueueSafeEject();
82+
return;
83+
}
84+
85+
// Check if vinyl player is connected to the radio system
86+
if (!_stationRadio.TryGetLinkedPoweredServer(playerUid, out _)) // Starlight - Station Radio Check oved to StationRadioReceiverSystem
87+
{
88+
_popups.PopupPredicted(Loc.GetString("vinyl-popout-no-radio-connection"), playerUid, null, PopupType.Medium);
89+
QueueSafeEject();
90+
return;
91+
}
92+
93+
// Get the audio length
94+
var resolved = _audio.ResolveSound(vinylComp.Song);
95+
var audioLength = _audio.GetAudioLength(resolved);
96+
var endTime = _timing.CurTime + audioLength;
97+
98+
// Track this vinyl with its player
99+
_trackingVinyls[vinylUid] = new TrackingData(playerUid, endTime);
100+
}
101+
102+
private void OnVinylRemoved(EntityUid uid, VinylPlayerComponent player, ref VinylRemovedEvent args)
103+
{
104+
// Stop tracking if the vinyl is removed
105+
_trackingVinyls.Remove(args.Vinyl);
106+
}
107+
108+
public override void Update(float frameTime)
109+
{
110+
base.Update(frameTime);
111+
112+
var currentTime = _timing.CurTime;
113+
114+
foreach (var (vinylUid, data) in _trackingVinyls.ToList())
115+
{
116+
// Check if the vinyl still exists
117+
if (!Exists(vinylUid)
118+
|| !Exists(data.VinylPlayerUid))
119+
{
120+
_trackingVinyls.Remove(vinylUid);
121+
continue;
122+
}
123+
124+
// Check if vinyl player is still on a station
125+
if (_stationSystem.GetOwningStation(data.VinylPlayerUid) == null)
126+
{
127+
_trackingVinyls.Remove(vinylUid);
128+
_popups.PopupPredicted(Loc.GetString("vinyl-popout-no-station"), data.VinylPlayerUid, null, PopupType.Medium);
129+
EjectVinyl(data.VinylPlayerUid, vinylUid);
130+
continue;
131+
}
132+
133+
// Check if vinyl player is still powered
134+
if (!_power.IsPowered(data.VinylPlayerUid))
135+
{
136+
_trackingVinyls.Remove(vinylUid);
137+
_popups.PopupPredicted(Loc.GetString("vinyl-popout-no-power"), data.VinylPlayerUid, null, PopupType.Medium);
138+
EjectVinyl(data.VinylPlayerUid, vinylUid);
139+
continue;
140+
}
141+
142+
// Check if vinyl player is still connected to the radio system
143+
if (!_stationRadio.TryGetLinkedPoweredServer(data.VinylPlayerUid, out _)) // Starlight - Station Radio Check oved to StationRadioReceiverSystem
144+
{
145+
_trackingVinyls.Remove(vinylUid);
146+
_popups.PopupPredicted(Loc.GetString("vinyl-popout-no-radio-connection"), data.VinylPlayerUid, null, PopupType.Medium);
147+
EjectVinyl(data.VinylPlayerUid, vinylUid);
148+
continue;
149+
}
150+
151+
// Check if playback has finished
152+
if (currentTime >= data.EndTime)
153+
{
154+
HandleVinylFinished(vinylUid);
155+
_trackingVinyls.Remove(vinylUid);
156+
}
157+
}
158+
}
159+
160+
private void EjectVinyl(EntityUid playerUid, EntityUid vinylUid)
161+
{
162+
if (!Exists(vinylUid)
163+
|| !Exists(playerUid)
164+
|| !TryComp<ItemSlotsComponent>(playerUid, out var itemSlots))
165+
return;
166+
167+
// Find the slot containing the vinyl
168+
foreach (var (_, slot) in itemSlots.Slots)
169+
if (slot.Item == vinylUid)
170+
{
171+
_itemSlots.TryEject(playerUid, slot, null, out _);
172+
return;
173+
}
174+
}
175+
176+
private void HandleVinylFinished(EntityUid vinylUid)
177+
{
178+
if (!TryComp<VinylSummonRuleComponent>(vinylUid, out var summonComp))
179+
return;
180+
181+
// Resolve the game rule ID and get the threat prototype if available
182+
var ruleId = ResolveGameRule(summonComp.GameRule, out var threat);
183+
184+
if (ruleId != null)
185+
{
186+
_gameTicker.StartGameRule(ruleId, out _);
187+
188+
// If we have a threat prototype with an announcement, send it
189+
if (threat != null)
190+
_chat.DispatchGlobalAnnouncement(Loc.GetString(threat.Announcement), playSound: true, colorOverride: Color.Red);
191+
}
192+
193+
var vinylXform = Transform(vinylUid);
194+
var vinylCoords = vinylXform.Coordinates;
195+
196+
// Remove from container
197+
if (_containers.TryGetContainingContainer((vinylUid, vinylXform, null), out var container))
198+
_containers.Remove(vinylUid, container);
199+
200+
// Play sound effect
201+
_audio.PlayPvs(summonComp.BurnSound, vinylCoords, summonComp.BurnSoundParams); // Starlight - Dehardcode BurnSoundParams
202+
203+
// Spawn ash at the vinyl's location
204+
Spawn(summonComp.AshPrototype, vinylCoords); // Starlight - Dehardcode ash prototype
205+
206+
// Delete the vinyl
207+
QueueDel(vinylUid);
208+
}
209+
210+
private string? ResolveGameRule(string gameRuleIdentifier, out NinjaHackingThreatPrototype? threat)
211+
{
212+
threat = null;
213+
214+
// Check if it's a weighted random pool
215+
if (_prototypeManager.TryIndex<WeightedRandomPrototype>(gameRuleIdentifier, out var weightedPool))
216+
{
217+
// Pick a random threat ID from the weighted pool
218+
var threatId = weightedPool.Pick(_random);
219+
220+
// Look up the threat prototype to get the actual game rule ID
221+
if (_prototypeManager.TryIndex<NinjaHackingThreatPrototype>(threatId, out threat))
222+
return threat.Rule;
223+
224+
return null;
225+
}
226+
227+
// Assume it's a direct game rule entity ID
228+
return gameRuleIdentifier;
229+
}
230+
}

Content.Shared/Radio/Components/RadioSpeakerComponent.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
using Content.Shared.Chat;
33
using Robust.Shared.GameStates;
44
using Robust.Shared.Prototypes;
5+
using Content.Shared._Goobstation.StationRadio.Systems; // Starlight - Radio Host _Goob -> _Goobstation
56

67
namespace Content.Shared.Radio.Components;
78

89
/// <summary>
910
/// Listens for radio messages and relays them to local chat.
1011
/// </summary>
1112
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
12-
[Access(typeof(SharedRadioDeviceSystem))]
13+
[Access(typeof(SharedRadioDeviceSystem), typeof(StationRadioReceiverSystem))] // Goobstation - Add StationRadioReceiverSystem access.
1314
public sealed partial class RadioSpeakerComponent : Component
1415
{
1516
/// <summary>
@@ -24,4 +25,20 @@ public sealed partial class RadioSpeakerComponent : Component
2425

2526
[DataField, AutoNetworkedField]
2627
public bool Enabled;
28+
29+
// Starlight - Radio Host LouderSpeech -> ParseRadioPrefix.
30+
/// <summary>
31+
/// Whether or not a message is parsed through the radio when when sent in local chat.
32+
/// </summary>
33+
[DataField, AutoNetworkedField]
34+
public bool ParseRadioPrefix;
35+
// Starlight - End
36+
37+
// Goobstation - Radio Host
38+
/// <summary>
39+
/// Does the radio need to be on a power grid to work?
40+
/// </summary>
41+
[DataField]
42+
public bool PowerRequired;
43+
// Goobstation - End
2744
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using Robust.Shared.GameStates;
2+
3+
namespace Content.Shared._Goobstation.StationRadio.Components; // Starlight - _Goob -> _Goobstation
4+
5+
[RegisterComponent, NetworkedComponent]
6+
public sealed partial class RadioRigComponent : Component;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using Robust.Shared.Audio;
2+
using Robust.Shared.GameStates;
3+
4+
namespace Content.Shared._Goobstation.StationRadio.Components; // Starlight - _Goob -> _Goobstation
5+
6+
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
7+
public sealed partial class StationRadioReceiverComponent : Component
8+
{
9+
/// <summary>
10+
/// The sound entity being played
11+
/// </summary>
12+
[DataField, AutoNetworkedField]
13+
public EntityUid? SoundEntity;
14+
15+
/// <summary>
16+
/// Is the radio turned on
17+
/// </summary>
18+
[DataField, AutoNetworkedField]
19+
public bool Active = true;
20+
21+
/// <summary>
22+
/// Default audio params for the played audio.
23+
/// </summary>
24+
[DataField, AutoNetworkedField]
25+
public AudioParams DefaultParams = AudioParams.Default.WithVolume(3.5f).WithMaxDistance(8f); // 8 is just the edge of the screen usually
26+
27+
// Moffstation - Add Low Volume mode
28+
/// <summary>
29+
/// Is Radio is playing at full or low volume.
30+
/// </summary>
31+
[DataField, AutoNetworkedField]
32+
public bool LowVolume;
33+
// Moffstation - End
34+
35+
// Starlight - Dehardcode LowVolume mode's gain.
36+
/// <summary>
37+
/// How quiet the low volume setting on a Station Radio is. Default is 10%.
38+
/// </summary>
39+
[DataField, AutoNetworkedField]
40+
public float LowVolumeGain = 0.1f;
41+
// Starlight - End
42+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using Robust.Shared.GameStates;
2+
using Robust.Shared.Audio; // Starlight - Add Station Radio Resume Play
3+
4+
namespace Content.Shared._Goobstation.StationRadio.Components; // Starlight - _Goob -> _Goobstation
5+
6+
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
7+
public sealed partial class StationRadioServerComponent : Component
8+
// Starlight - Add the ability for Station Radios to resume play.
9+
{
10+
/// <summary>
11+
/// The song currently being broadcasted.
12+
/// Null if nothing is playing.
13+
/// </summary>
14+
[DataField, AutoNetworkedField]
15+
public SoundPathSpecifier? CurrentSong;
16+
17+
/// <summary>
18+
/// For determining where the sound should resume.
19+
/// </summary>
20+
[DataField, AutoNetworkedField]
21+
public TimeSpan? PlaybackStartTime;
22+
}
23+
// Starlight - End
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Robust.Shared.Audio;
2+
using Robust.Shared.GameStates;
3+
4+
namespace Content.Shared._Goobstation.StationRadio.Components; // Starlight - _Goob -> _Goobstation
5+
6+
[RegisterComponent, NetworkedComponent]
7+
public sealed partial class VinylComponent : Component
8+
{
9+
/// <summary>
10+
/// What song should be played when the vinyl is played
11+
/// </summary>
12+
[DataField] public SoundPathSpecifier? Song;
13+
}

0 commit comments

Comments
 (0)