From c13896c7671f1a9932b687297c7060386d1bd283 Mon Sep 17 00:00:00 2001
From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com>
Date: Thu, 25 May 2023 06:29:12 -0400
Subject: [PATCH 1/4] Initial push on Loudspeakers
Adds functional loudspeakers to the game with a fleshed out construction graph. Adds FilterConstructionGraphStep.cs to facilitate this, allowing you to add entities lacing a list of components, tags, and under a certain size.
Adds an audio for empty loudspeakers.
---
.../Loudspeakers/LoudSpeakerComponent.cs | 74 +++++++++++
.../Loudspeakers/LoudSpeakerSystem.cs | 113 +++++++++++++++++
.../ConstructionGraphStepTypeSerializer.cs | 8 ++
.../Steps/FilterConstructionGraphStep.cs | 46 +++++++
.../SimpleStation14/Effects/attributions.yml | 4 +
.../SimpleStation14/Effects/metaldink.ogg | Bin 0 -> 6974 bytes
.../steps/size-construction-graph-step.ftl | 3 +
.../Devices/Electronics/loud_speaker.yml | 16 +++
.../Structures/Machines/loud_speaker.yml | 100 +++++++++++++++
.../Recipes/Construction/Graphs/utilities.yml | 17 +++
.../Graphs/utilities/loud_speaker.yml | 120 ++++++++++++++++++
.../Recipes/Lathes/electronics.yml | 7 +
Resources/Prototypes/SimpleStation14/tags.yml | 3 +
13 files changed, 511 insertions(+)
create mode 100644 Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
create mode 100644 Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
create mode 100644 Content.Shared/SimpleStation14/Construction/Steps/FilterConstructionGraphStep.cs
create mode 100644 Resources/Audio/SimpleStation14/Effects/attributions.yml
create mode 100644 Resources/Audio/SimpleStation14/Effects/metaldink.ogg
create mode 100644 Resources/Locale/en-US/construction/steps/size-construction-graph-step.ftl
create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Electronics/loud_speaker.yml
create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
create mode 100644 Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities.yml
create mode 100644 Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
create mode 100644 Resources/Prototypes/SimpleStation14/Recipes/Lathes/electronics.yml
diff --git a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
new file mode 100644
index 0000000000..49a8e460b2
--- /dev/null
+++ b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
@@ -0,0 +1,74 @@
+using Content.Shared.MachineLinking;
+using Robust.Shared.Audio;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+
+namespace Content.Server.SimpleStation14.LoudSpeakers;
+
+[RegisterComponent]
+public sealed class LoudSpeakerComponent : Component
+{
+ ///
+ /// The port to look for a signal on.
+ ///
+ public string PlaySoundPort = "Trigger";
+
+ ///
+ /// Whether or not this loudspeaker has ports.
+ ///
+ [DataField("ports")]
+ public bool Ports = true;
+
+ ///
+ /// Can this loudspeaker be triggered by interacting with it?
+ ///
+ [DataField("triggerOnInteract")]
+ public bool TriggerOnInteract = false;
+
+ ///
+ /// The sound to play if no other sound is specified.
+ ///
+ [DataField("defaultSound")]
+ public SoundSpecifier DefaultSound = new SoundPathSpecifier("/Audio/SimpleStation14/Effects/metaldink.ogg");
+
+ ///
+ /// Default variance to be used, if no other variance is specified.
+ /// Is still subject to .
+ ///
+ [DataField("defaultVariance")]
+ public float DefaultVariance = 0.125f;
+
+ ///
+ /// The amount to multiply the volume by.
+ ///
+ [DataField("volumeMod")]
+ public float VolumeMod = 2f;
+
+ ///
+ /// The amount to multiply the range by.
+ ///
+ [DataField("rangeMod")]
+ public float RangeMod = 3f;
+
+ ///
+ /// The amount to multiply the rolloff by.
+ ///
+ [DataField("rolloffMod")]
+ public float RolloffMod = 0.3f;
+
+ ///
+ /// Amount to multiply the variance by, if the sound has one.
+ /// If the sound has a variance of 0, default variance is used.
+ ///
+ [DataField("varianceMod")]
+ public float VarianceMod = 1.35f;
+
+ ///
+ /// The modifier to apply to the default variance.
+
+ ///
+ /// The name of the container the payload is in.
+ /// This is specified in the construction graph.
+ ///
+ [DataField("containerSlot")]
+ public string ContainerSlot = "payload";
+}
diff --git a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
new file mode 100644
index 0000000000..bc8cf6a82a
--- /dev/null
+++ b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
@@ -0,0 +1,113 @@
+using Content.Server.MachineLinking.Events;
+using Content.Server.MachineLinking.System;
+using Content.Server.Power.Components;
+using Robust.Shared.Audio;
+using Robust.Shared.Player;
+using Robust.Shared.Containers;
+using Content.Server.Sound.Components;
+using Content.Shared.Sound.Components;
+using Content.Shared.Interaction;
+
+namespace Content.Server.SimpleStation14.LoudSpeakers;
+
+public sealed class DoorSignalControlSystem : EntitySystem
+{
+ [Dependency] private readonly SignalLinkerSystem _signal = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnInit);
+ SubscribeLocalEvent(OnSignalReceived);
+
+ SubscribeLocalEvent(OnInteractHand);
+ }
+
+ private void OnInit(EntityUid uid, LoudSpeakerComponent component, ComponentInit args)
+ {
+ if (component.Ports)
+ _signal.EnsureReceiverPorts(uid, component.PlaySoundPort);
+ }
+
+ ///
+ /// Tries to play a loudspeaker.
+ ///
+ /// The Loudspeaker to play.
+ /// The Loudspeaker component.
+ /// True if the Loudspeaker was played, false otherwise.
+ public bool TryPlayLoudSpeaker(EntityUid uid, LoudSpeakerComponent? component = null)
+ {
+ if (!Resolve(uid, ref component))
+ return false;
+
+ if (TryComp(uid, out var powerComp) && !powerComp.Powered)
+ return false;
+
+ PlayLoudSpeaker(uid, component, GetSpeakerSound(uid, component));
+
+ return true;
+ }
+
+ private void PlayLoudSpeaker(EntityUid uid, LoudSpeakerComponent component, SoundSpecifier sound)
+ {
+ var newParams = sound.Params
+ .WithVolume(sound.Params.Volume * component.VolumeMod)
+ .WithMaxDistance(sound.Params.MaxDistance * component.RangeMod)
+ .WithRolloffFactor(sound.Params.RolloffFactor * component.RolloffMod)
+ // If variance is 0 or null, use default variance.
+ .WithVariation((sound.Params.Variation !> 0 ? component.DefaultVariance : sound.Params.Variation) * component.VarianceMod);
+
+ _audio.Play(sound, Filter.Pvs(uid, component.RangeMod), uid, true, newParams);
+ }
+
+ private SoundSpecifier GetSpeakerSound(EntityUid uid, LoudSpeakerComponent component)
+ {
+ if (!TryComp(uid, out var containerManager) ||
+ !containerManager.TryGetContainer(component.ContainerSlot, out var container))
+ return component.DefaultSound;
+
+ if (container.ContainedEntities.Count == 0)
+ return component.DefaultSound;
+
+ var entity = container.ContainedEntities[0];
+
+ switch (entity)
+ {
+ case { } when TryComp(entity, out var trigger) && trigger.Sound != null:
+ return trigger.Sound;
+
+ case { } when TryComp(entity, out var use) && use.Sound != null:
+ return use.Sound;
+
+ case { } when TryComp(entity, out var drop) && drop.Sound != null:
+ return drop.Sound;
+
+ case { } when TryComp(entity, out var land) && land.Sound != null:
+ return land.Sound;
+
+ default:
+ return component.DefaultSound;
+ }
+ }
+
+ private void OnSignalReceived(EntityUid uid, LoudSpeakerComponent component, SignalReceivedEvent args)
+ {
+ if (args.Port == component.PlaySoundPort)
+ {
+ TryPlayLoudSpeaker(uid, component);
+ }
+ }
+
+ private void OnInteractHand(EntityUid uid, LoudSpeakerComponent component, InteractHandEvent args)
+ {
+ if (!component.TriggerOnInteract)
+ return;
+
+ if (!TryPlayLoudSpeaker(uid, component))
+ return;
+
+ args.Handled = true;
+ }
+}
diff --git a/Content.Shared/Construction/Steps/ConstructionGraphStepTypeSerializer.cs b/Content.Shared/Construction/Steps/ConstructionGraphStepTypeSerializer.cs
index 63e55e0d14..02993ad224 100644
--- a/Content.Shared/Construction/Steps/ConstructionGraphStepTypeSerializer.cs
+++ b/Content.Shared/Construction/Steps/ConstructionGraphStepTypeSerializer.cs
@@ -3,6 +3,7 @@
using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
+using Content.Shared.SimpleStation14.Construction.Steps; // Parkstation-LoudSpeakers
namespace Content.Shared.Construction.Steps
{
@@ -41,6 +42,13 @@ public sealed class ConstructionGraphStepTypeSerializer : ITypeReader CompBlacklist { get; } = new List();
+ [DataField("tagBlacklist")] public List TagBlacklist { get; } = new List();
+
+ public override bool EntityValid(EntityUid uid, IEntityManager entityManager, IComponentFactory compFactory)
+ {
+ if (!entityManager.TryGetComponent(uid, out var item) || item.Size > Size)
+ return false;
+
+ foreach (var component in CompBlacklist)
+ {
+ if (entityManager.HasComponent(uid, compFactory.GetComponent(component).GetType()))
+ return false;
+ }
+
+ var tagSystem = entityManager.EntitySysManager.GetEntitySystem();
+
+ if (tagSystem.HasAnyTag(uid, TagBlacklist))
+ return false;
+
+ return true;
+ }
+
+ public override void DoExamine(ExaminedEvent examinedEvent)
+ {
+ examinedEvent.Message.AddMarkup(string.IsNullOrEmpty(Name)
+ ? Loc.GetString(
+ "construction-insert-entity-below-size",
+ ("size", Size))
+ : Loc.GetString(
+ "construction-insert-exact-entity",
+ ("entityName", Name)));
+ }
+ }
+}
diff --git a/Resources/Audio/SimpleStation14/Effects/attributions.yml b/Resources/Audio/SimpleStation14/Effects/attributions.yml
new file mode 100644
index 0000000000..524ce95bb3
--- /dev/null
+++ b/Resources/Audio/SimpleStation14/Effects/attributions.yml
@@ -0,0 +1,4 @@
+- files: ["metaldink.ogg"]
+ license: "CC-BY-SA-3.0"
+ copyright: "Recorded and edited by @Pspritechologist#9442"
+ source: "Parkstation COMMIT HERE"
diff --git a/Resources/Audio/SimpleStation14/Effects/metaldink.ogg b/Resources/Audio/SimpleStation14/Effects/metaldink.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..7acfd4617f35e48a1e33c823b63d20013cfa02fb
GIT binary patch
literal 6974
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
a`gy3sT4NTu<=Uv7E2e(>h`O_^;Qs&;j_gAK
literal 0
HcmV?d00001
diff --git a/Resources/Locale/en-US/construction/steps/size-construction-graph-step.ftl b/Resources/Locale/en-US/construction/steps/size-construction-graph-step.ftl
new file mode 100644
index 0000000000..b2920740a7
--- /dev/null
+++ b/Resources/Locale/en-US/construction/steps/size-construction-graph-step.ftl
@@ -0,0 +1,3 @@
+# Parkstation
+# Shown when examining an in-construction object
+construction-insert-entity-below-size = Next, insert an entity no larger than {$size}.
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Electronics/loud_speaker.yml b/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Electronics/loud_speaker.yml
new file mode 100644
index 0000000000..a7e986b611
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Electronics/loud_speaker.yml
@@ -0,0 +1,16 @@
+- type: entity
+ id: LoudSpeakerElectronics
+ parent: BaseElectronics
+ name: loud speaker electronics
+ description: An electronics board used in loud speakers
+ components:
+ - type: Sprite
+ sprite: Objects/Misc/module.rsi
+ state: id_mod
+ - type: Tag
+ tags:
+ - DroneUsable
+ - LoudSpeakerElectronics
+ - type: ReverseEngineering
+ recipes:
+ - LoudSpeakerElectronics
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
new file mode 100644
index 0000000000..50e5886e39
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
@@ -0,0 +1,100 @@
+- type: entity
+ # parent: BaseMachine # ConstructibleMachine Work out dual inheritance
+ id: LoudSpeaker
+ name: loudspeaker
+ description: An loudspeaker. For when the station just needs to know something.
+ components:
+ - type: WallMount
+ - type: ApcPowerReceiver
+ - type: Electrified
+ enabled: false
+ usesApcPower: true
+ - type: ExtensionCableReceiver
+ - type: Clickable
+ - type: InteractionOutline
+ - type: Appearance
+ - type: Sprite
+ noRot: false
+ sprite: Structures/Wallmounts/intercom.rsi
+ layers:
+ - state: base
+ - state: unshaded
+ map: ["enum.PowerDeviceVisualLayers.Powered"]
+ # - state: broadcasting
+ # map: ["enum.RadioDeviceVisualLayers.Broadcasting"]
+ # shader: unshaded
+ # visible: false
+ - type: Transform
+ noRot: false
+ anchored: true
+ # - type: Wires
+ # BoardName: "LoudSpeaker"
+ # LayoutId: LoudSpeaker
+ - type: LoudSpeaker
+ - type: Construction
+ graph: LoudSpeaker
+ node: loudspeaker
+ - type: ContainerContainer
+ containers:
+ payload: !type:Container
+ - type: Damageable
+ damageContainer: Inorganic
+ damageModifierSet: Metallic
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 160
+ behaviors:
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]
+ - trigger:
+ !type:DamageTrigger
+ damage: 80
+ behaviors:
+ - !type:PlaySoundBehavior
+ sound:
+ path: /Audio/Effects/metalbreak.ogg
+ - !type:EmptyAllContainersBehaviour
+ - !type:SpawnEntitiesBehavior
+ spawn:
+ SheetSteel1:
+ min: 1
+ max: 2
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]
+ - type: GenericVisualizer
+ visuals:
+ enum.PowerDeviceVisuals.Powered:
+ enum.PowerDeviceVisualLayers.Powered:
+ True: { visible: true }
+ False: { visible: false }
+ # enum.RadioDeviceVisuals.Broadcasting:
+ # enum.RadioDeviceVisualLayers.Broadcasting:
+ # True: { visible: true }
+ # False: { visible: false }
+ # placement:
+ # mode: SnapgridCenter
+ # snap:
+ # - Wallmount
+
+- type: entity
+ id: LoudSpeakerAssesmbly
+ name: loudspeaker assembly
+ description: A loudspeaker. It doesn't seem very helpful right now.
+ components:
+ - type: WallMount
+ - type: Clickable
+ - type: InteractionOutline
+ - type: Sprite
+ sprite: Structures/Wallmounts/intercom.rsi
+ state: build
+ - type: Construction
+ graph: LoudSpeaker
+ node: assembly
+ - type: Transform
+ anchored: true
+ placement:
+ mode: SnapgridCenter
+ snap:
+ - Wallmount
diff --git a/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities.yml b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities.yml
new file mode 100644
index 0000000000..b693533466
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities.yml
@@ -0,0 +1,17 @@
+- type: construction
+ name: loudspeaker
+ id: LoudSpeakerAssesmbly
+ graph: LoudSpeaker
+ startNode: start
+ targetNode: loudspeaker
+ category: construction-category-structures
+ description: A loudspeaker. When you want to make sure someone's attention is always ready to be grabbed.
+ icon:
+ sprite: Structures/Wallmounts/intercom.rsi
+ state: base
+ placementMode: SnapgridCenter
+ objectType: Structure
+ canRotate: true
+ canBuildInImpassable: true
+ conditions:
+ - !type:WallmountCondition {}
diff --git a/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
new file mode 100644
index 0000000000..c28dd6d508
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
@@ -0,0 +1,120 @@
+- type: constructionGraph
+ id: LoudSpeaker
+ start: start
+ graph:
+ - node: start
+ edges:
+ - to: assembly
+ steps:
+ - material: Steel
+ amount: 2
+ doAfter: 2.0
+
+ - node: assembly
+ entity: LoudSpeakerAssesmbly
+ edges:
+ - to: wired
+ steps:
+ - material: Cable
+ amount: 2
+ doAfter: 1
+ - to: start
+ completed:
+ - !type:GivePrototype
+ prototype: SheetSteel1
+ amount: 2
+ - !type:DeleteEntity {}
+ steps:
+ - tool: Welding
+ doAfter: 2
+
+ - node: wired
+ entity: LoudSpeakerAssesmbly
+ edges:
+ - to: electronics
+ steps:
+ - tag: LoudSpeakerElectronics
+ store: board
+ name: "loudspeaker electronics"
+ icon:
+ sprite: "Objects/Misc/module.rsi"
+ state: "id_mod"
+ doAfter: 1
+ - to: assembly
+ completed:
+ - !type:GivePrototype
+ prototype: CableApcStack1
+ amount: 2
+ steps:
+ - tool: Cutting
+ doAfter: 1
+
+ - node: electronics
+ entity: LoudSpeakerAssesmbly
+ edges:
+ - to: payload
+ steps:
+ - size: 8
+ store: payload
+ name: "payload"
+ compBlacklist: [ "Tool" ]
+ - tool: Screwing
+ doAfter: 3
+ - to: payload
+ steps:
+ - tool: Screwing
+ doAfter: 2
+ - to: wired
+ completed:
+ - !type:EmptyContainer
+ container: board
+ steps:
+ - tool: Prying
+ doAfter: 1
+
+ - node: payload
+ entity: LoudSpeakerAssesmbly
+ edges:
+ - to: loudspeaker
+ steps:
+ - tool: Screwing
+ doAfter: 1
+ - to: wired
+ conditions:
+ - !type:AllWiresCut {}
+ - !type:WirePanel {}
+ - !type:ContainerNotEmpty
+ container: board
+ - !type:ContainerEmpty
+ container: payload
+ completed:
+ - !type:EmptyContainer
+ container: board
+ steps:
+ - tool: Prying
+ doAfter: 1
+ - to: electronics
+ conditions:
+ - !type:AllWiresCut {}
+ - !type:WirePanel {}
+ - !type:ContainerNotEmpty
+ container: board
+ - !type:ContainerNotEmpty
+ container: payload
+ completed:
+ - !type:EmptyContainer
+ container: payload
+ steps:
+ - tool: Prying
+ doAfter: 2
+
+ - node: loudspeaker
+ entity: LoudSpeaker
+ edges:
+ - to: payload
+ conditions:
+ - !type:AllWiresCut {}
+ - !type:WirePanel {}
+ steps:
+ - tool: Screwing
+ doAfter: 1
diff --git a/Resources/Prototypes/SimpleStation14/Recipes/Lathes/electronics.yml b/Resources/Prototypes/SimpleStation14/Recipes/Lathes/electronics.yml
new file mode 100644
index 0000000000..db40c13dfe
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Recipes/Lathes/electronics.yml
@@ -0,0 +1,7 @@
+- type: latheRecipe
+ id: LoudSpeakerElectronics
+ result: LoudSpeakerElectronics
+ completetime: 2
+ materials:
+ Steel: 40
+ Plastic: 60
diff --git a/Resources/Prototypes/SimpleStation14/tags.yml b/Resources/Prototypes/SimpleStation14/tags.yml
index ffe8954d1d..d6133a3edd 100644
--- a/Resources/Prototypes/SimpleStation14/tags.yml
+++ b/Resources/Prototypes/SimpleStation14/tags.yml
@@ -6,3 +6,6 @@
- type: Tag
id: WizardBook
+
+- type: Tag
+ id: LoudSpeakerElectronics
From fb7deb719c70d0de014cde1d0f2bcc6233306e62 Mon Sep 17 00:00:00 2001
From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com>
Date: Thu, 25 May 2023 18:24:35 -0400
Subject: [PATCH 2/4] Minor cleanup, and testing default speakers.
Removing the payload doesn't currently work.
---
.../Loudspeakers/LoudSpeakerComponent.cs | 6 +--
.../Loudspeakers/LoudSpeakerSystem.cs | 1 -
.../Structures/Machines/loud_speaker.yml | 45 ++++++++++++++++++-
.../Graphs/utilities/loud_speaker.yml | 28 ++++++------
4 files changed, 61 insertions(+), 19 deletions(-)
diff --git a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
index 49a8e460b2..cf93d97a70 100644
--- a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
+++ b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
@@ -41,13 +41,13 @@ public sealed class LoudSpeakerComponent : Component
/// The amount to multiply the volume by.
///
[DataField("volumeMod")]
- public float VolumeMod = 2f;
+ public float VolumeMod = 3.5f;
///
/// The amount to multiply the range by.
///
[DataField("rangeMod")]
- public float RangeMod = 3f;
+ public float RangeMod = 3.5f;
///
/// The amount to multiply the rolloff by.
@@ -60,7 +60,7 @@ public sealed class LoudSpeakerComponent : Component
/// If the sound has a variance of 0, default variance is used.
///
[DataField("varianceMod")]
- public float VarianceMod = 1.35f;
+ public float VarianceMod = 1.5f;
///
/// The modifier to apply to the default variance.
diff --git a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
index bc8cf6a82a..2026e9eb20 100644
--- a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
+++ b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
@@ -56,7 +56,6 @@ private void PlayLoudSpeaker(EntityUid uid, LoudSpeakerComponent component, Soun
.WithVolume(sound.Params.Volume * component.VolumeMod)
.WithMaxDistance(sound.Params.MaxDistance * component.RangeMod)
.WithRolloffFactor(sound.Params.RolloffFactor * component.RolloffMod)
- // If variance is 0 or null, use default variance.
.WithVariation((sound.Params.Variation !> 0 ? component.DefaultVariance : sound.Params.Variation) * component.VarianceMod);
_audio.Play(sound, Filter.Pvs(uid, component.RangeMod), uid, true, newParams);
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
index 50e5886e39..7d7889e564 100644
--- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
+++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
@@ -1,6 +1,6 @@
- type: entity
# parent: BaseMachine # ConstructibleMachine Work out dual inheritance
- id: LoudSpeaker
+ id: LoudSpeakerBase
name: loudspeaker
description: An loudspeaker. For when the station just needs to know something.
components:
@@ -34,6 +34,8 @@
- type: Construction
graph: LoudSpeaker
node: loudspeaker
+ containers:
+ - payload
- type: ContainerContainer
containers:
payload: !type:Container
@@ -98,3 +100,44 @@
mode: SnapgridCenter
snap:
- Wallmount
+
+- type: entity
+ parent: LoudSpeakerBase
+ id: LoudSpeakerBuzzer
+ name: buzzer
+ description: A buzzer to indicate that someone wants your attention.
+ components:
+ - type: ContainerFill
+ containers:
+ payload:
+ - BikeHorn
+ board:
+ - LoudSpeakerElectronics
+
+- type: entity
+ parent: LoudSpeakerBase
+ id: LoudSpeakerBuzzerService
+ suffix: Service
+ name: buzzer
+ description: A buzzer to indicate that someone wants your attention.
+ components:
+ - type: ContainerFill
+ containers:
+ payload:
+ - DeskBell
+ board:
+ - LoudSpeakerElectronics
+
+- type: entity
+ parent: LoudSpeakerBase
+ id: LoudSpeakerSec
+ suffix: Sec
+ name: buzzer
+ description: A buzzer to indicate that someone wants your attention.
+ components:
+ - type: ContainerFill
+ containers:
+ payload:
+ - BikeHorn
+ board:
+ - LoudSpeakerElectronics
diff --git a/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
index c28dd6d508..418a8be12e 100644
--- a/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
+++ b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
@@ -79,42 +79,42 @@
steps:
- tool: Screwing
doAfter: 1
- - to: wired
+ - to: electronics
conditions:
- - !type:AllWiresCut {}
- - !type:WirePanel {}
+ # - !type:AllWiresCut {}
+ # - !type:WirePanel {}
- !type:ContainerNotEmpty
container: board
- - !type:ContainerEmpty
+ - !type:ContainerNotEmpty
container: payload
completed:
- !type:EmptyContainer
- container: board
+ container: payload
steps:
- tool: Prying
- doAfter: 1
- - to: electronics
+ doAfter: 2
+ - to: wired
conditions:
- - !type:AllWiresCut {}
- - !type:WirePanel {}
+ # - !type:AllWiresCut {}
+ # - !type:WirePanel {}
- !type:ContainerNotEmpty
container: board
- - !type:ContainerNotEmpty
+ - !type:ContainerEmpty
container: payload
completed:
- !type:EmptyContainer
- container: payload
+ container: board
steps:
- tool: Prying
- doAfter: 2
+ doAfter: 1
- node: loudspeaker
entity: LoudSpeaker
edges:
- to: payload
conditions:
- - !type:AllWiresCut {}
- - !type:WirePanel {}
+ # - !type:AllWiresCut {}
+ # - !type:WirePanel {}
steps:
- tool: Screwing
doAfter: 1
From 5eb987c1824ba2f334da268603b9d4add55975ec Mon Sep 17 00:00:00 2001
From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com>
Date: Fri, 26 May 2023 04:27:32 -0400
Subject: [PATCH 3/4] Cleanup, and added support for
EmitSoundOnActivateComponent
---
.../Loudspeakers/LoudSpeakerSystem.cs | 3 +
.../Structures/Machines/loud_speaker.yml | 5 +
.../Graphs/utilities/loud_speaker.yml | 219 +++++++++---------
3 files changed, 116 insertions(+), 111 deletions(-)
diff --git a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
index 2026e9eb20..121ec46b39 100644
--- a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
+++ b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
@@ -77,6 +77,9 @@ private SoundSpecifier GetSpeakerSound(EntityUid uid, LoudSpeakerComponent compo
case { } when TryComp(entity, out var trigger) && trigger.Sound != null:
return trigger.Sound;
+ case { } when TryComp(entity, out var activate) && activate.Sound != null:
+ return activate.Sound;
+
case { } when TryComp(entity, out var use) && use.Sound != null:
return use.Sound;
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
index 7d7889e564..6e61764042 100644
--- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
+++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/loud_speaker.yml
@@ -35,10 +35,12 @@
graph: LoudSpeaker
node: loudspeaker
containers:
+ - board
- payload
- type: ContainerContainer
containers:
payload: !type:Container
+ board: !type:Container
- type: Damageable
damageContainer: Inorganic
damageModifierSet: Metallic
@@ -94,6 +96,9 @@
- type: Construction
graph: LoudSpeaker
node: assembly
+ containers:
+ - board
+ - payload
- type: Transform
anchored: true
placement:
diff --git a/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
index 418a8be12e..b510f7b08c 100644
--- a/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
+++ b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
@@ -2,119 +2,116 @@
id: LoudSpeaker
start: start
graph:
- - node: start
- edges:
- - to: assembly
- steps:
- - material: Steel
- amount: 2
- doAfter: 2.0
+ - node: start
+ edges:
+ - to: assembly
+ steps:
+ - material: Steel
+ amount: 2
+ doAfter: 2.0
- - node: assembly
- entity: LoudSpeakerAssesmbly
- edges:
- - to: wired
- steps:
- - material: Cable
- amount: 2
- doAfter: 1
- - to: start
- completed:
- - !type:GivePrototype
- prototype: SheetSteel1
- amount: 2
- - !type:DeleteEntity {}
- steps:
- - tool: Welding
- doAfter: 2
+ - node: assembly
+ entity: LoudSpeakerAssesmbly
+ edges:
+ - to: wired
+ steps:
+ - material: Cable
+ amount: 2
+ doAfter: 1
+ - to: start
+ completed:
+ - !type:GivePrototype
+ prototype: SheetSteel1
+ amount: 2
+ - !type:DeleteEntity {}
+ steps:
+ - tool: Welding
+ doAfter: 2
- - node: wired
- entity: LoudSpeakerAssesmbly
- edges:
- - to: electronics
- steps:
- - tag: LoudSpeakerElectronics
- store: board
- name: "loudspeaker electronics"
- icon:
- sprite: "Objects/Misc/module.rsi"
- state: "id_mod"
- doAfter: 1
- - to: assembly
- completed:
- - !type:GivePrototype
- prototype: CableApcStack1
- amount: 2
- steps:
- - tool: Cutting
- doAfter: 1
+ - node: wired
+ entity: LoudSpeakerAssesmbly
+ edges:
+ - to: electronics
+ steps:
+ - tag: LoudSpeakerElectronics
+ store: board
+ name: "loudspeaker electronics"
+ icon:
+ sprite: "Objects/Misc/module.rsi"
+ state: "id_mod"
+ doAfter: 1
+ - to: assembly
+ completed:
+ - !type:GivePrototype
+ prototype: CableApcStack1
+ amount: 2
+ steps:
+ - tool: Cutting
+ doAfter: 1
- - node: electronics
- entity: LoudSpeakerAssesmbly
- edges:
- - to: payload
- steps:
- - size: 8
- store: payload
- name: "payload"
- compBlacklist: [ "Tool" ]
- - tool: Screwing
- doAfter: 3
- - to: payload
- steps:
- - tool: Screwing
- doAfter: 2
- - to: wired
- completed:
- - !type:EmptyContainer
- container: board
- steps:
- - tool: Prying
- doAfter: 1
+ - node: electronics
+ entity: LoudSpeakerAssesmbly
+ edges:
+ - to: payload
+ steps:
+ - size: 8
+ store: payload
+ name: "payload"
+ compBlacklist: ["Tool"]
+ - tool: Screwing
+ doAfter: 3
+ - to: payload
+ steps:
+ - tool: Screwing
+ doAfter: 2
+ - to: wired
+ completed:
+ - !type:EmptyContainer
+ container: board
+ steps:
+ - tool: Prying
+ doAfter: 1
- - node: payload
- entity: LoudSpeakerAssesmbly
- edges:
- - to: loudspeaker
- steps:
- - tool: Screwing
- doAfter: 1
- - to: electronics
- conditions:
- # - !type:AllWiresCut {}
- # - !type:WirePanel {}
- - !type:ContainerNotEmpty
- container: board
- - !type:ContainerNotEmpty
- container: payload
- completed:
- - !type:EmptyContainer
- container: payload
- steps:
- - tool: Prying
- doAfter: 2
- - to: wired
- conditions:
- # - !type:AllWiresCut {}
- # - !type:WirePanel {}
- - !type:ContainerNotEmpty
- container: board
- - !type:ContainerEmpty
- container: payload
- completed:
- - !type:EmptyContainer
- container: board
- steps:
- - tool: Prying
- doAfter: 1
+ - node: payload
+ entity: LoudSpeakerAssesmbly
+ edges:
+ - to: loudspeaker
+ steps:
+ - tool: Screwing
+ doAfter: 1
+ - to: electronics
+ conditions:
+ # - !type:AllWiresCut {}
+ # - !type:WirePanel {}
+ - !type:ContainerNotEmpty
+ container: board
+ - !type:ContainerNotEmpty
+ container: payload
+ completed:
+ - !type:EmptyContainer
+ container: payload
+ steps:
+ - tool: Prying
+ doAfter: 2
+ - to: wired
+ conditions:
+ # - !type:AllWiresCut {}
+ # - !type:WirePanel {}
+ - !type:ContainerNotEmpty
+ container: board
+ - !type:ContainerEmpty
+ container: payload
+ completed:
+ - !type:EmptyContainer
+ container: board
+ steps:
+ - tool: Prying
+ doAfter: 1
- - node: loudspeaker
- entity: LoudSpeaker
- edges:
- - to: payload
- conditions:
- # - !type:AllWiresCut {}
- # - !type:WirePanel {}
- steps:
- - tool: Screwing
- doAfter: 1
+ - node: loudspeaker
+ entity: LoudSpeakerBase
+ edges:
+ - to: payload
+ steps:
+ - tool: Screwing
+ doAfter: 1
From 9ccaa307eeec078b99332638448c6024e90fe6f9 Mon Sep 17 00:00:00 2001
From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com>
Date: Sun, 28 May 2023 23:04:28 -0400
Subject: [PATCH 4/4] Soundboxes, and cleanup
Added a soundbox prototype, along with a buzzer sounds collection for standard loudspeaker audios.
Loudspeakers now cleanup after themselves when destroyed, and support for interrupting currently playing sounds when starting a new one.
---
.../Loudspeakers/LoudSpeakerComponent.cs | 40 ++++++++++++------
.../Loudspeakers/LoudSpeakerSystem.cs | 20 ++++++++-
.../SimpleStation14/Effects/attributions.yml | 5 +++
.../SimpleStation14/Effects/buzzer_one.ogg | Bin 0 -> 6324 bytes
.../SimpleStation14/Effects/buzzer_two.ogg | Bin 0 -> 6264 bytes
.../Entities/Objects/Devices/sound_boxes.yml | 27 ++++++++++++
.../Graphs/utilities/loud_speaker.yml | 4 --
.../SoundCollections/Speakers/buzzer.yml | 5 +++
Resources/Prototypes/SimpleStation14/tags.yml | 9 ++--
9 files changed, 90 insertions(+), 20 deletions(-)
create mode 100644 Resources/Audio/SimpleStation14/Effects/buzzer_one.ogg
create mode 100644 Resources/Audio/SimpleStation14/Effects/buzzer_two.ogg
create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/sound_boxes.yml
create mode 100644 Resources/Prototypes/SimpleStation14/SoundCollections/Speakers/buzzer.yml
diff --git a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
index cf93d97a70..147441412d 100644
--- a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
+++ b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerComponent.cs
@@ -1,12 +1,14 @@
-using Content.Shared.MachineLinking;
using Robust.Shared.Audio;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.SimpleStation14.LoudSpeakers;
[RegisterComponent]
public sealed class LoudSpeakerComponent : Component
{
+ public IPlayingAudioStream? CurrentPlayingSound;
+
+ public TimeSpan NextPlayTime = TimeSpan.Zero;
+
///
/// The port to look for a signal on.
///
@@ -18,12 +20,36 @@ public sealed class LoudSpeakerComponent : Component
[DataField("ports")]
public bool Ports = true;
+ ///
+ /// The name of the container the payload is in.
+ /// This is specified in the construction graph.
+ ///
+ [DataField("containerSlot")]
+ public string ContainerSlot = "payload";
+
///
/// Can this loudspeaker be triggered by interacting with it?
///
[DataField("triggerOnInteract")]
public bool TriggerOnInteract = false;
+ ///
+ /// Should this loudspeaker interrupt already playing sounds if triggered?
+ /// If false, the sounds will overlap.
+ ///
+ ///
+ /// Warning: If this is false, the speaker will not clean up after itself properly.
+ /// Since it only saves one sound at a time Use with caution.
+ ///
+ [DataField("interrupt")]
+ public bool Interrupt = true;
+
+ ///
+ /// Cool down time between playing sounds.
+ ///
+ [DataField("cooldown")]
+ public TimeSpan Cooldown = TimeSpan.FromSeconds(4);
+
///
/// The sound to play if no other sound is specified.
///
@@ -61,14 +87,4 @@ public sealed class LoudSpeakerComponent : Component
///
[DataField("varianceMod")]
public float VarianceMod = 1.5f;
-
- ///
- /// The modifier to apply to the default variance.
-
- ///
- /// The name of the container the payload is in.
- /// This is specified in the construction graph.
- ///
- [DataField("containerSlot")]
- public string ContainerSlot = "payload";
}
diff --git a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
index 121ec46b39..8d7aceb5d7 100644
--- a/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
+++ b/Content.Server/SimpleStation14/Loudspeakers/LoudSpeakerSystem.cs
@@ -7,6 +7,7 @@
using Content.Server.Sound.Components;
using Content.Shared.Sound.Components;
using Content.Shared.Interaction;
+using Robust.Shared.Timing;
namespace Content.Server.SimpleStation14.LoudSpeakers;
@@ -14,17 +15,26 @@ public sealed class DoorSignalControlSystem : EntitySystem
{
[Dependency] private readonly SignalLinkerSystem _signal = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
+ SubscribeLocalEvent(OnShutdown);
+
SubscribeLocalEvent(OnInit);
SubscribeLocalEvent(OnSignalReceived);
SubscribeLocalEvent(OnInteractHand);
}
+ private void OnShutdown(EntityUid uid, LoudSpeakerComponent component, ComponentShutdown args)
+ {
+ if (component.CurrentPlayingSound != null)
+ component.CurrentPlayingSound.Stop();
+ }
+
private void OnInit(EntityUid uid, LoudSpeakerComponent component, ComponentInit args)
{
if (component.Ports)
@@ -42,6 +52,9 @@ public bool TryPlayLoudSpeaker(EntityUid uid, LoudSpeakerComponent? component =
if (!Resolve(uid, ref component))
return false;
+ if (component.NextPlayTime > _timing.CurTime)
+ return false;
+
if (TryComp(uid, out var powerComp) && !powerComp.Powered)
return false;
@@ -58,7 +71,12 @@ private void PlayLoudSpeaker(EntityUid uid, LoudSpeakerComponent component, Soun
.WithRolloffFactor(sound.Params.RolloffFactor * component.RolloffMod)
.WithVariation((sound.Params.Variation !> 0 ? component.DefaultVariance : sound.Params.Variation) * component.VarianceMod);
- _audio.Play(sound, Filter.Pvs(uid, component.RangeMod), uid, true, newParams);
+ if (component.Interrupt && component.CurrentPlayingSound != null)
+ component.CurrentPlayingSound.Stop();
+
+ component.NextPlayTime = _timing.CurTime + component.Cooldown;
+
+ component.CurrentPlayingSound = _audio.Play(sound, Filter.Pvs(uid, component.RangeMod), uid, true, newParams);
}
private SoundSpecifier GetSpeakerSound(EntityUid uid, LoudSpeakerComponent component)
diff --git a/Resources/Audio/SimpleStation14/Effects/attributions.yml b/Resources/Audio/SimpleStation14/Effects/attributions.yml
index 524ce95bb3..6c2a4d76d0 100644
--- a/Resources/Audio/SimpleStation14/Effects/attributions.yml
+++ b/Resources/Audio/SimpleStation14/Effects/attributions.yml
@@ -2,3 +2,8 @@
license: "CC-BY-SA-3.0"
copyright: "Recorded and edited by @Pspritechologist#9442"
source: "Parkstation COMMIT HERE"
+
+- files: ["buzzer_one.ogg", "buzzer_two.ogg"]
+ license: "Pixabay Content License"
+ copyright: "By Pixabay"
+ source: "https://pixabay.com/sound-effects/buzz-buzz-95806/"
\ No newline at end of file
diff --git a/Resources/Audio/SimpleStation14/Effects/buzzer_one.ogg b/Resources/Audio/SimpleStation14/Effects/buzzer_one.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..0cdeac73b70cf12c514c653f7ffed8066454d7a1
GIT binary patch
literal 6324
zcmai22|SeB`+q0G*qRvbs8K`2Ys)aIamiB1*oRSw82irHDoa!7B3lf}Qns;W4@Dc5
zCHs;=Dk4-`uhi|f_@5cwd;8!2|MUC3pEKuk-t(OEJm-0y@AI7J9ScuSYiI-X<9R2v
zK9CGyEg`lc!UJhk?-2GB;z0F}B@qbD;2Oe$z4Pyfy^~Fu2{80P9a#Hc&wZ|SMg%}V
z>>cE#VnOr7`FT@qIqY%9I5kx@Rnjg4+w?XLJ%9*
zdBFPnZ4nS3n8BOkI_bmd6bM2=kh2UdoatcT@WYj5&6MuiL#m-2sfNRA#ja29rX{PxG+LcK`29*Q-YX(gn8c4#su|%NUSlx@k(h91HhA
zz^A%orA`{bD1^`*q6L~!=z;qT(}54BoBnbF+wBmfi^p~bWA6iNkd?=18izu(Cqm37
zfGOA(`OnWO4qkvFQUxB_K6F0ybQg|U=zuMzh;P5(x+Jh5q39VdcQ|)tfGC{1P*{o1
z8|z54$&+iX%*o?;&~H#;9{3XOz0g^BVK_Hr&{!~+xjs5BlE+(9ISS?^mhy$WBwWBc
z@6lY|%BjO(uibF&Vnr(&j1n1na?Pza>->JeqS7gUu!Hy%>_~i==i7>O1f$Px`ELf0
z?74r#M;G|bWfId>a2gk#%0opCW$nH*X#Tn?h*XUDyh8QLs4@>3gnkF^q!1#Lu4*;-wj
zVnaC;?r(QKZ2D@v<7C*(MD)x=%F$oW{2N$*M-BvnCXN%63~DmIJ3rQ3AGz+}zal3X
z-F*&w|D23Tqm0?8(!lQoixt9%sDTy1%v#KGL@aDf+}(P&dnV>qUby(8vY7v0
zk>izAo|9CbkhGMLDxa9`otRtITI|4GMlJYq#w9w%#zla(np+W$FX0Ck*THbwx3&4M5a2-*Rh
z9EVDxrRxW1ALhd^%4{qm@)X^}#FeAe1&Kn^q3L>Z+Sf9OcLi5w$?{?cOk-1I_oU*4
z?vx!dUf9bA(jGTt1wnLt5B?s8HfVgm@W3D*S-|Ka$}uxXjbY_%j5;h^CgM7uUovWZ
zzm$P7Nh&B6aZRiNn;>5B6DS%^7enZxA&4qS=7-}M-PC@_g$-BA;Yj
zFP^6$76mi0)`M_2Hm+Z9AwPClPacAB?FjJGmnXOxKqxtAHb`bDlVF0DH4!x!Lc33h
znoVR81_&BfHk3Y5%D4?>THK7%B5NjUX7<5`B5FVpql{&nQJVdS2<}rhl*i(f@fP=K
z@t8x|VKeGxcHor-s9_V?(MMVSjyXSAnV~tXc2g!=G^|1?Rup$T8;V`HyWJSOr_o+`5JMkEYiTI}rnj*^ulDkC%UglFO3Q6QRkgL38(*=hZ8ghX!OLx`QDtyn+2xmQm2GVS%Wc8^
zE&kY&s+YGE`tH>CHojeM+tm~%Wkm^l%y67P1oZGf8gbF#Q+%WUueWQy^a2K>e-MWP
zv8`a+m4K~au4_e6$7OFS(=!*Gw5ler>hf}9fa2ZiWqm73v}2b0%pOO(Ujkbsdl3+i)DqenrO=5BMUh|PN^S5wQX%G~PAtQc=OP!OBt*Yvamhz=~NaZbHJhpdAA6EG*bjD&k-accHEQmAi6x
zbm0K2`)uJH84EcK!0JM528mRYl|k;$&t$WTO(hw_Eg2+Ja4Hh1A)ajShiB!J{WQR-
z0ILj=pK_PIgK2XZ%3gqTs+wk7U!R&TAY7J-F(EZHi~9!P7q^hSYuLgoJH;JRfpBYI
zjWU)Go8aKD&B_fS)vz9rQvku$|K@mZ4hO&1vTPqf$R(d`UVIqhr}6QDeKlK#3AiCb(ppz-LDr#jLArFLdm%f8u)|g_
zfjnsJjiU7v6_EP>PfgRL
zE?-SNOU*Cv5a*3WOYCrKgmH;v%HcnWfD?e6P
zpHB=N1Kd^pM9`u10Rhx|MX{h`GDg`1GU){l%)!i1Hi1FrhaiO@P!ZKzxrLlQR|sAt(9W3
zsMQ)10L0CUxxOSo@EvG{php{dp?a>Z2D{}jNCko$M+rI(m@yfD22D-EFXiv&gFACT
zjZ=nUmmc7fW!E3cfB;^*0D-uKWq0`@ss9uv|BR6Tj}n!j&f07XZtE`0R=)MB+)#w`
z>gxBSNY7b+{i$aEr+WWSBM09a0J)z#NcT2BFSN$H)z)Y)yhT8Xts_bp6nb}az=?Sz
z3`3mG?&()1pu|QzK&t3&w&HT$WxvB#15u
zLBW$g%P^}4*O?!eZ4#GGLs3;Wlaq)>4ekdeIx*u6JQHnA_I;jDO}4Tqa3$gIRx@l#
z^5;&E(yE)o`@yFrjt^2rNvWUGMW8V~Ku{bv3>DV5595z;b3YSN;}_)bjtd#}=7Lah
zJ%Z;F4hxEiR-G!QYC?yPIQQ_<1yfR*&I&wNYv1VjC=3^e1j7{!D+joz3^oSx5MmV@Jq(8#y#J;w||vc`*cNXwy9@h?Htlg@+{Nev}BDx
zsq@us3_Tl(vM)cX{=RWwQe|?ZL|(L7$Kt9-DlQ^e8#aZ|wh{Mq8DrnJ3p+GOv;-a|
zi`*K}F&*@1EV{F-!+Z{FK5E8Bx?S2n;(@$#^5*hJ=$T911!WD{_Or(x0y>r
z)>)etrO?uC_e3rvO62{RFF)j7U$^T)$^A=F)xXix=20h%BzNW~(4D?zI>o*>|HhaL
zQqlPkp76(hX8q&sSIThCJoTsLe$C>&p`bo%d{lhXFam0CJ6*Q=dr_jpihV@GbjqJv
zJ+CiF`C8e*GLk*kyEI}XlfQ`Hx?CL^3-JtO4@u1(t1Ropf_Wj
za?tnV`5QVsZ}$!++(@k@BQ9+m4%6AyF}43#EA8s8o;1X-#k`5jZhkcT0{T0FqVcKR
z_dF1k{`4eIVL{$L&&PaTG0<+EY~^x)=8xsB3g
zX9~>rG8lqAXffLOjb4U=@s5jQdyYLs)p=XUoDW_Npx!VEOj9B5$*UXQjo{hMs~C2y
zanjZ!X8!iR@8ya4Z#$B&YagSUAL9iwci*}SKR+$^nYC?jz$$PG6T>~bEVj7?3#;-$+5N0lt@(h4
zo6--^lP6+61(DynUiKWInZmqjC%(wtog48>$y7`cDZO{6rqu9LH1h4>Mf3Q#BR49O
z(#5J@F%|5QFHK-HY3CPciO|@qrN%qoXb#q^p9uM{;}Iz2gmsjzmL
zdXlQ{^={Xvn{N<$eJ_7A_#$%q!I#XXDsD4Z@nrrW+R1XU$Az_qkJj2c-nW!}R!PF8%Womg^md_HBQH8T?v#nX0PRhIs>Or*zGm#*`9
zpZ*nv_R5;I3ARR1`zolQA&EmnPPgSitp%KCSi*Q>>ZJ@o*9R*4)_PV47`T3)n{*8P)hJLSm
z^WZs@<%Z#@+$luQu_t%`ysdXDZ;7qmHDR8Lqb~s>*6gTqOe6N+lrf%?&u*Ng`>yG^
zXhn|}Kh=r~C5>kKXn&Es-cKJx#JO?}<@9nnF^9MyH}NZbwZQeWi8@(X|Lk?%lhA-R
ztA!BS^*yibMGaeD>arCMyiOb6|fZ-U_^nQ
zwSvm)(a`i8s|`TQLBpB$+HWI)-rFu&Vz&@u4hmSkC>%B7>!Pb8=t5dkPZ6qVJV7sG
zdFU}4+}_g{fpH$)*d9Q6w3oV=^tmO-so9~$qtykz<&)SWJvDdZL{`c-%;Z9_h|HeW
zL9cF;vx38}*sOT`l>j@jXGWbz&;r)Sb}su1MGEiUqA2Q&o-MuQUcKky5pym6a-Mey
zflD{J#1;y`2_b0s$<|glI#2=pqjz!Q-fM$|F!9sy+pe!`M-=^yll8aMI$KmXgrqlx
z)$#TPhZ}7pv+@u)MS{xy+CPTm-+X)U^$SjHCG(1{&q
z(`uK&zbgAIT&~v*qq*}-(uXezId2nfdm_kaaHcDHyoV$q$nCd<(7>*8oe>{1QRK9h
zr`z`Ac|+?fOiNRF+i&k9wJf#7HIjGdhxNa6tG#~nhIO+ivZHeLarLFt_8pYv6NT=J
zAL4T^=;}li+^=nUM7-YgH7*OODkb=G2?l7J=vcVpvT`T^T=qeQE$0KzB|n+#oX+f(
zGmAH&leN$HwQsLenVD2J~fkl>OGp}gEoZr1&N^W;t`L=)0*QfpKGshxF_
z*LW9(Fl?ixs@ttOfeX4WPpfruaiu_ax+&VxV7uUl&pMuVc1nB?yCUMp(zZE?i@UfY
zpIfzmMnFw^C%t;z(Qnp1^Clt4Gio~_6yaHHE9t;*-^xS9RO7@KVzH`cZkMVmm
zUxIh!RZU1sSR!sGN+vxijL)_U^8pZ+-=dNKevyI@Bjb+
literal 0
HcmV?d00001
diff --git a/Resources/Audio/SimpleStation14/Effects/buzzer_two.ogg b/Resources/Audio/SimpleStation14/Effects/buzzer_two.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..a2a417c9a1db3306de0d86ad38e2747b6c579c2c
GIT binary patch
literal 6264
zcmai12UwHK(%t|F`FIPWQM7QCNdbXq&(bId-ekbwl
zzdEd*zbpU(fT}K>T{&kPI!FjYt7XTO5khtuRbz!RoMs5Zw?1z4i>PX;qC^bhRFSLQ
zR{>}sQyaw;84|biO;b!o!|ntorcbfDG)6?@LfLTT&T=8eyQFv
zY%Z$ZGD@_^kGuLcTod$4j2$G*m;UU8d3s>sSM>R1FQQzjHX!&NA)t$0eP;HRb5^8tUZNwC6sO1QjA+p56OhLDoB
z;JUW(yUkj6o5grbpmPPdrvYUl#Z~{O1-cgo{P$)W+@}Fdp)Gr(F}=|$RwR|)7%d^5
zh5G>XsVPaTCq~aYR^lk61Dc4q7t45!v^J_L0{tf&-9d?87__;v=u96u8a;zl?btFM&X?Ne5p8F
z-UqG=87&s7nR0`B-G__kF0{+QQ98Xut+m}{h2KwD)a)xAyh(Thcceckp|lHo!O^mR
z>6?4P+_`^;k16z<&m@|C_Bb{vThLcVu}U$2eO!)sei^&DVjBoH
z6lN>OLz77-5pm3wh=NYV`sbPn%JYIGwJ4?^R}G`$SI7OSG9;-m@=F_fhjEfpg>6Jf
z+gW!z*@e6(A>93R{KLyBUX$_D6G_t(S>9_>{~cI=M-G5NL*vCH-S;HEw={W|x$ugE
z|B9Swnch>FJEv6anpGS|weG#wb6nILk+yQub8wdR8j+2^FBjl!;B{X=;66EEJRxAJ
zEx_|~l6%|FfLRHf>52GXB8M9yN`&lZHhBX7L{6D{_EV#5W!pRz_q>gV3WL&%YtEee
zqozXS-y$bCqq-=gIxS;9En7XkFeJUWw!I>(zhR-{zqY?4$2vv@HW)cpF)F`A&J8@q
z0!CA_mc!zTj@w6|LF25}{OSMzZsdyD@$!fhNqd~6KTgsnyKMi@5d*2?dJgyXpkWID
zkOx2+I+=#bh{-jN*zShJ ~`CkU3`M$@WMx?+UYN^!YnYTK{m5xT_|XGrR@miEb6
zs)pIv)winl+RhpwVcHV_P5@BxefZnxm_ge+WtM|@;j{EUf*Lb_)E1{*h}OlaR!R9i
zE3F*0y~CiR?J~|Xr2NuZa1#)MuW0#jt}Mb-1^{0%k_aw^P8!6`<&ygGvltSQP+jUg
zNI)vk`tgEilTkP(#(5Cei=hpe&6Xw)o2dhUy@7zQxw@Xe6+o$hnJAT^d_6lERXb^`
zA(?;)X@`jdy?c84PA=rT(&TX$@nrcqn&dPhtGDu7f-Lc{$k-9JT?ZhLD@V<2Y8X<^wl%Gg6_X)nN5r?uct+qk7`THW42ib!lqA$f%1Ii;j9
zeRwL!DvubZ&GzuLZ;eNJi1JRwYIUWAve;0#Didu-Y-*LGMBwMv5<^&A;Wa&Sp4m{i
zGey6O6UrrchHvK-#}ZkbF;W&J_=R5^FFySCFU@^Jwb>kB7FW1NQ$ZdSKKH=mB!NEa
z3t8onPQo3YVeM6gp^#8a%50r`5F4idY0RUZE5i={A!2jdKf1!KL*)miRN;U!ZVKUs
ztyvmr&^81WGeFP~HXk6U)x_AF<8b5wGo)(kAOVN#;Si9jOgTFZ?H*SO4hOZ+hII!o
zYy}8l}n&|yuw0ggy|=sAgtIP7DQH$8>K;!
z$?>h%pMW54ohzmgA%SwQ9e_uxguq4qbyfyyXkiUKf1VOlEHvXue5#CZ27bQO0*UJ>
zf;CPRnp=9npDefjI0*^xlMM-kc?`EJjm`e2F!^UB{QoFX1M4hFSNOMPqt_udsH;Mh;BXK=Frw)m#51uZl7=d?kefQjJc!zmw~#86LkfjbjFHTi
zF|MddGaDR}E
z48ifu)aQ7Jf|-aYK()CTom#-SbZcaW=W9h+Y@73}&Ak|qpfAd}Xi>BzLR4`vqDX^o
zSec{c{ym2>o?n3$1l0V>I{I#N9<-3o{zdN{(2&iHJ
zL{Ek;;5dEQo>E$&9W6Ho<-19eltHj=3b2vyL66h%Oc`eq8Y4
ze(LyWOnqy@0K8gakzfl-QTLcBLI&Lj1pzPv}VfB4Q%FwAj%Qet@F&
ziJeMw6O)pzJyzjs4BYna?-QbmWo5NwioVdfvC8XFJeGzPP)zGV$mCL!r6UeLUF~?~
zrm(RUQ+(wni~#Ea$Xkt7QYt27i|0t>qE1QXN##q^A$$RtK~N=kxsX1vaL+kVV^m}pYzVoTYx&inBjN}JbvvAjRlaUxo7dt0Be
z1}&8ZJ+H>AaZ=G-vvRGv&9o##19)SVWI8jr=ji-qB
zVE19eUZJiDlg(8XqVq2nGKZ{JXEyG;U-FUeXfC?*a_sGg8m9un1gWA^cTQLL21LET
ze!k-Ti39bf>e2B2{Pb%$)ViVdi2f=VH;7?h1*7ZzVd4O98~_A1v=n}Nj07rSUVHH;|D_cH}lM6RY0ds7tlW=%q-DK@j+41C`Pz{w*^v3i%zl*CTT
zN?sXg4V(*B4~{GtbNL{))B3~Hz1vlr0)4H|T%)rYPg68bMZW}(SKXo%#4p+kJi>ao
z?jc<_$u~6ow9TO=0JS?`;60w30Kc_K!$5iI9jQF_CZu5(^J9JYtZ&EmZz>O!$}f}(
z#B0l7>1*UmyjK-tH(1IUbp^&HR_-(7`@@y?dNRIoA$|3Jq4^#Y6EI`q`hIc7#G41J
zneRUq>fq>x_vnx70y_*JBb_XfSC*fszfKsw`))Z3Som-#MUQR*BLy%dlHDXaV9MGG
zs7Lq)5dDaeRk>EcMs$Ot+q<^)CVeN?tKNJgx2_YdI-MlG00kIL_?7w?4|#*VS&5
z!e~B6p}%7G>BcI&-pBUz%;B#pRvltpFBUq77v*JzBr0A})e5blie+J=$8!kZ(|9qp
zg`mI(Qj;lCn}@0=8yn_?AU*Qi=?wk&{&g~jjh-y^BG=|}>gn7Ym#=itI(+Jwb>}Uu
zyL^M3-YuM)Ld@KE7r(KFEsk^*
z#B941b*0ZIXc?Hu)MVZeb3+(JeQ-#2m=OUgx-yu6r+w3P29g}L#8X#NHS
zaHU>1K+k}vVC+28IyIM95~
z?hfODl>6H8-{|)~#gHQGrg4Isj0-cnyros$?d>JAnpAKL&mO8Au2vjAA(988Dt8qw
zf4_b9kV5JGC(pIKlh&+vn^U$|GT|XIu_zbTEH_TK%nfOOxeF626_)mDMiZKtjz9acW2o1n_^q2`-+Zb>{(J(*r%EV7pm^h)bLNc%ndbM@m(^={KzdLw+(YsWTR{UBt#1E23S
zx9@u@qlB|$X7c+6_XO6#IMQ*smf5YLZ-ebZF78!-gBTgG4XRTRDH8w-H!0J4(p7Lq(1u7bK2&zdvNO_eS=I3mCf!l#_?OHg5Z7!_Y5Zu4g3o8sGlysH01v
zCm)4&t>w+X&R@FPkSk~!9^~lG{Rb{be*dhg1HhkaeBj^U%C-OiT&*9c*(mWHc^8yu
zF#GLbzuG%~uz#jzzu<6KnU=o3E{c+WBxb*OuIMlYP{qwLCjL*KR3F%P=+BY&!3qy&
zZWl#KkPW}?>E?S|pgnr;d1~q-9eMAIv*&}&kt#2%=D*X&jt*#ScYKz^`x8?)5%>Ys
z*m%jzH;>fxVQ=-_$G0Y)&c+fJc31`0vc^r%7>Mf4z0(l?u&0QWRWC9WTkE_HnER*i
zwlRByy%npwlNHHHWK}(u(?f&dnYU{`MBhV@KH0smykU$i5@b7Plfmsr%6@bLQ%F
zJ0*ve5YO?AS?BJwoHe+jTk%#};wDp1!hcP=Md<1yf;#Rvi-!D8&;>e6@>|vkez0n!
zq;I=6D|k^h4OOyFk%8HHxhh>daC}1y(s?A3zPIy-!-!W%<3^uxWw9NNXOBNUXwbFU
zp}Rr96Ky6MhuL)G^U))+)0$_d3_gm#UiT@9{=7u1`PjPni$k}+93hV-X$-t3rdK~k
zg3FCN>SxFDPvq=c=zR3!-5u&`ch7$S@$JrOit?Kcb@hwiZ1VWouFp45rPLz9{{Z=;Mb-cS
literal 0
HcmV?d00001
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/sound_boxes.yml b/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/sound_boxes.yml
new file mode 100644
index 0000000000..be7e04e821
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/sound_boxes.yml
@@ -0,0 +1,27 @@
+- type: entity
+ abstract: true
+ id: SoundBoxBase
+ parent: BaseItem
+ name: sound box
+ description: A small box designed to play a specific audio. It has no way to play on its own.
+ components:
+ - type: Sprite
+ sprite: Objects/Misc/module.rsi
+ state: id_mod
+ - type: Tag
+ tags:
+ - SoundBox
+ - type: EmitSoundOnTrigger
+ sound: Buzzer
+
+- type: entity
+ id: SoundBoxBuzzer
+ parent: SoundBoxBase
+ name: buzzer sound box
+ description: A sound box containing a small metal disc that vibrates when electricity is applied to it.
+ components:
+ - type: EmitSoundOnTrigger
+ sound: Buzzer
+ - type: Sprite
+ sprite: Objects/Misc/module.rsi
+ state: id_mod
diff --git a/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
index b510f7b08c..3e2428cfc0 100644
--- a/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
+++ b/Resources/Prototypes/SimpleStation14/Recipes/Construction/Graphs/utilities/loud_speaker.yml
@@ -81,8 +81,6 @@
doAfter: 1
- to: electronics
conditions:
- # - !type:AllWiresCut {}
- # - !type:WirePanel {}
- !type:ContainerNotEmpty
container: board
- !type:ContainerNotEmpty
@@ -95,8 +93,6 @@
doAfter: 2
- to: wired
conditions:
- # - !type:AllWiresCut {}
- # - !type:WirePanel {}
- !type:ContainerNotEmpty
container: board
- !type:ContainerEmpty
diff --git a/Resources/Prototypes/SimpleStation14/SoundCollections/Speakers/buzzer.yml b/Resources/Prototypes/SimpleStation14/SoundCollections/Speakers/buzzer.yml
new file mode 100644
index 0000000000..6242ee3e3d
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/SoundCollections/Speakers/buzzer.yml
@@ -0,0 +1,5 @@
+- type: soundCollection
+ id: Buzzer
+ files:
+ - /Audio/SimpleStation14/Effects/buzzer_1.ogg
+ - /Audio/SimpleStation14/Effects/buzzer_2.ogg
diff --git a/Resources/Prototypes/SimpleStation14/tags.yml b/Resources/Prototypes/SimpleStation14/tags.yml
index d6133a3edd..5452e9e3f8 100644
--- a/Resources/Prototypes/SimpleStation14/tags.yml
+++ b/Resources/Prototypes/SimpleStation14/tags.yml
@@ -1,11 +1,14 @@
+- type: Tag
+ id: SoundBox
+
- type: Tag
id: GlassesNearsight
- type: Tag
- id: Plushie
+ id: LoudSpeakerElectronics
- type: Tag
- id: WizardBook
+ id: Plushie
- type: Tag
- id: LoudSpeakerElectronics
+ id: WizardBook