diff --git a/Content.Server/Instruments/SwappableInstrumentComponent.cs b/Content.Server/Instruments/SwappableInstrumentComponent.cs
new file mode 100644
index 0000000000..bfe8b5c3a6
--- /dev/null
+++ b/Content.Server/Instruments/SwappableInstrumentComponent.cs
@@ -0,0 +1,14 @@
+namespace Content.Server.Instruments;
+
+[RegisterComponent]
+public sealed class SwappableInstrumentComponent : Component
+{
+ ///
+ /// Used to store the different instruments that can be swapped between.
+ /// string = display name of the instrument
+ /// byte 1 = instrument midi program
+ /// byte 2 = instrument midi bank
+ ///
+ [DataField("instrumentList", required: true)]
+ public Dictionary InstrumentList = new();
+}
diff --git a/Content.Server/Instruments/SwappableInstrumentSystem.cs b/Content.Server/Instruments/SwappableInstrumentSystem.cs
new file mode 100644
index 0000000000..1f64a0c7c7
--- /dev/null
+++ b/Content.Server/Instruments/SwappableInstrumentSystem.cs
@@ -0,0 +1,51 @@
+using Content.Shared.Instruments;
+using Content.Shared.Popups;
+using Content.Shared.Verbs;
+using Robust.Shared.Player;
+
+namespace Content.Server.Instruments;
+
+public sealed class SwappableInstrumentSystem : EntitySystem
+{
+ [Dependency] private readonly SharedInstrumentSystem _sharedInstrument = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent>(AddStyleVerb);
+ }
+
+ private void AddStyleVerb(EntityUid uid, SwappableInstrumentComponent component, GetVerbsEvent args)
+ {
+ if (!args.CanInteract || !args.CanAccess || component.InstrumentList.Count <= 1)
+ return;
+
+ if (!TryComp(uid, out var instrument))
+ return;
+
+ if (instrument.Playing) //no changing while playing
+ return;
+
+ var priority = 0;
+ foreach (var entry in component.InstrumentList)
+ {
+ AlternativeVerb selection = new()
+ {
+ Text = entry.Key,
+ Category = VerbCategory.InstrumentStyle,
+ Priority = priority,
+ Act = () =>
+ {
+ _sharedInstrument.SetInstrumentProgram(instrument, entry.Value.Item1, entry.Value.Item2);
+ _popup.PopupEntity(Loc.GetString("swappable-instrument-component-style-set", ("style", entry.Key)),
+ args.User, Filter.Entities(args.User));
+ }
+ };
+
+ priority--;
+ args.Verbs.Add(selection);
+ }
+ }
+}
diff --git a/Content.Shared/Instruments/SharedInstrumentSystem.cs b/Content.Shared/Instruments/SharedInstrumentSystem.cs
index f356b722b4..767738f175 100644
--- a/Content.Shared/Instruments/SharedInstrumentSystem.cs
+++ b/Content.Shared/Instruments/SharedInstrumentSystem.cs
@@ -18,6 +18,12 @@ public abstract class SharedInstrumentSystem : EntitySystem
public virtual void EndRenderer(EntityUid uid, bool fromStateChange, SharedInstrumentComponent? instrument = null)
{ }
+ public void SetInstrumentProgram(SharedInstrumentComponent component, byte program, byte bank)
+ {
+ component.InstrumentProgram = program;
+ component.InstrumentBank = bank;
+ }
+
private void OnGetState(EntityUid uid, SharedInstrumentComponent instrument, ref ComponentGetState args)
{
args.State =
diff --git a/Content.Shared/Verbs/VerbCategory.cs b/Content.Shared/Verbs/VerbCategory.cs
index 66b0e39055..53a05cacc5 100644
--- a/Content.Shared/Verbs/VerbCategory.cs
+++ b/Content.Shared/Verbs/VerbCategory.cs
@@ -68,6 +68,9 @@ namespace Content.Shared.Verbs
public static readonly VerbCategory Split =
new("verb-categories-split", null);
+ public static readonly VerbCategory InstrumentStyle =
+ new("verb-categories-instrument-style", null);
+
public static readonly VerbCategory SetSensor = new("verb-categories-set-sensor", null);
}
}
diff --git a/Resources/Locale/en-US/instruments/instruments-component.ftl b/Resources/Locale/en-US/instruments/instruments-component.ftl
index db412a9342..cbbe835140 100644
--- a/Resources/Locale/en-US/instruments/instruments-component.ftl
+++ b/Resources/Locale/en-US/instruments/instruments-component.ftl
@@ -8,3 +8,6 @@ instruments-component-menu-no-midi-support = MIDI support is currently not
FluidSynth or a development package
for FluidSynth.
+# SwappableInstrumentComponent
+swappable-instrument-component-style-set = Style set to "{$style}"
+
diff --git a/Resources/Locale/en-US/verbs/verb-system.ftl b/Resources/Locale/en-US/verbs/verb-system.ftl
index c4fdaed060..27d4da4985 100644
--- a/Resources/Locale/en-US/verbs/verb-system.ftl
+++ b/Resources/Locale/en-US/verbs/verb-system.ftl
@@ -20,6 +20,7 @@ verb-categories-rotate = Rotate
verb-categories-smite = Smite
verb-categories-transfer = Set Transfer Amount
verb-categories-split = Split
+verb-categories-instrument-style = Instrument Style
verb-categories-set-sensor = Sensor
verb-categories-timer = Set Delay
diff --git a/Resources/Prototypes/Entities/Objects/Fun/instruments.yml b/Resources/Prototypes/Entities/Objects/Fun/instruments.yml
index 957ea64dba..7dd8b43082 100644
--- a/Resources/Prototypes/Entities/Objects/Fun/instruments.yml
+++ b/Resources/Prototypes/Entities/Objects/Fun/instruments.yml
@@ -26,6 +26,10 @@
components:
- type: Instrument
program: 62
+ - type: SwappableInstrument
+ instrumentList:
+ "Electro": {62: 0} #i needed generic sounding synth presets, sue me
+ "Bubbles": {63: 0}
- type: Sprite
sprite: Objects/Fun/Instruments/h_synthesizer.rsi
state: icon
@@ -43,7 +47,11 @@
description: Anyway, here's Wonderwall.
components:
- type: Instrument
- program: 25
+ program: 24
+ - type: SwappableInstrument
+ instrumentList:
+ "Nylon": {24: 0}
+ "Steel": {25: 0}
- type: Sprite
sprite: Objects/Fun/Instruments/guitar.rsi
state: icon
@@ -82,6 +90,10 @@
components:
- type: Instrument
program: 56
+ - type: SwappableInstrument
+ instrumentList:
+ "Standard": {56: 0}
+ "Muted": {59: 0}
- type: Sprite
sprite: Objects/Fun/Instruments/trumpet.rsi
state: icon
@@ -117,6 +129,11 @@
components:
- type: Instrument
program: 27
+ - type: SwappableInstrument
+ instrumentList:
+ "Clean": {27: 0}
+ "Jazz": {25: 0}
+ "Muted": {28: 0}
- type: Sprite
sprite: Objects/Fun/Instruments/eguitar.rsi
state: icon
@@ -134,6 +151,10 @@
components:
- type: Instrument
program: 21
+ - type: SwappableInstrument
+ instrumentList:
+ "Standard": {21: 0}
+ "Tango": {23: 0}
- type: Sprite
sprite: Objects/Fun/Instruments/accordion.rsi
state: icon
@@ -240,7 +261,13 @@
description: An instrument. You could probably grind this into raw jazz.
components:
- type: Instrument
- program: 67
+ program: 66
+ - type: SwappableInstrument
+ instrumentList:
+ "Soprano": {64: 0}
+ "Alto": {65: 0}
+ "Tenor": {66: 0}
+ "Baritone": {67: 0}
- type: Sprite
sprite: Objects/Fun/Instruments/saxophone.rsi
state: icon