From d090e98bd4916f8d4d0e402a3852a39c708258b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?=
<6766154+Zumorica@users.noreply.github.com>
Date: Thu, 28 Mar 2019 14:31:49 +0100
Subject: [PATCH] [Ready] SoundComponent (#164)
Requires https://github.com/space-wizards/space-station-14/pull/768
- [x] Play sounds
- [x] SoundSchedules actually work
- [x] Send sound to specific users
- [x] Make existing components use SoundComponent
- [x] Add ScheduledSounds from prototypes
- [x] Add Play methods equivalent to those of AudioSystem.
- [x] Document most code.
---
Content.Client/Content.Client.csproj | 1 +
Content.Client/EntryPoint.cs | 2 +
.../Components/Sound/SoundComponent.cs | 109 +++++++++++++++
Content.Server/Content.Server.csproj | 1 +
Content.Server/EntryPoint.cs | 2 +
.../Construction/ConstructionComponent.cs | 23 ++--
.../Construction/ConstructorComponent.cs | 4 +-
.../Components/Power/ApcComponent.cs | 6 +-
.../Components/Power/PoweredLightComponent.cs | 4 +-
.../Components/Sound/SoundComponent.cs | 72 ++++++++++
.../Ranged/Hitscan/HitscanWeaponComponent.cs | 5 +-
.../BallisticMagazineWeaponComponent.cs | 12 +-
.../Projectile/BallisticWeaponComponent.cs | 4 +-
.../Ranged/Projectile/ProjectileWeapon.cs | 3 +-
Content.Shared/Content.Shared.csproj | 3 +-
.../Components/Sound/SharedSoundComponent.cs | 125 ++++++++++++++++++
Content.Shared/GameObjects/ContentNetIDs.cs | 1 +
Resources/Prototypes/Entities/Lights.yml | 1 +
Resources/Prototypes/Entities/Power.yml | 1 +
Resources/Prototypes/Entities/Weapons.yml | 1 +
.../Prototypes/Entities/weapons/guns.yml | 1 +
21 files changed, 350 insertions(+), 31 deletions(-)
create mode 100644 Content.Client/GameObjects/Components/Sound/SoundComponent.cs
create mode 100644 Content.Server/GameObjects/Components/Sound/SoundComponent.cs
create mode 100644 Content.Shared/GameObjects/Components/Sound/SharedSoundComponent.cs
diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj
index 7e484e6eee..81c68a9997 100644
--- a/Content.Client/Content.Client.csproj
+++ b/Content.Client/Content.Client.csproj
@@ -84,6 +84,7 @@
+
diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs
index ac22770bb2..cb53bb6d8a 100644
--- a/Content.Client/EntryPoint.cs
+++ b/Content.Client/EntryPoint.cs
@@ -26,6 +26,7 @@ using SS14.Shared.IoC;
using SS14.Shared.Prototypes;
using System;
using Content.Client.GameObjects.Components.Mobs;
+using Content.Client.GameObjects.Components.Sound;
using Content.Client.UserInterface;
using Content.Shared.GameObjects.Components.Markers;
using Content.Shared.GameObjects.Components.Mobs;
@@ -82,6 +83,7 @@ namespace Content.Client
factory.Register();
factory.Register();
factory.Register();
+ factory.Register();
factory.RegisterReference();
diff --git a/Content.Client/GameObjects/Components/Sound/SoundComponent.cs b/Content.Client/GameObjects/Components/Sound/SoundComponent.cs
new file mode 100644
index 0000000000..6dc1d362bb
--- /dev/null
+++ b/Content.Client/GameObjects/Components/Sound/SoundComponent.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using Content.Shared.GameObjects.Components.Sound;
+using SS14.Client.GameObjects.EntitySystems;
+using SS14.Shared.GameObjects;
+using SS14.Shared.Interfaces.GameObjects;
+using SS14.Shared.Interfaces.Network;
+using SS14.Shared.Interfaces.Timers;
+using SS14.Shared.IoC;
+using SS14.Shared.Log;
+using SS14.Shared.Serialization;
+using SS14.Shared.Timers;
+
+namespace Content.Client.GameObjects.Components.Sound
+{
+ public class SoundComponent : SharedSoundComponent
+ {
+ private readonly List _schedules = new List();
+ private AudioSystem _audioSystem;
+ private Random Random;
+
+ public override void StopAllSounds()
+ {
+ foreach (var schedule in _schedules)
+ {
+ schedule.Play = false;
+ }
+ _schedules.Clear();
+ }
+
+ public override void StopScheduledSound(string filename)
+ {
+ foreach (var schedule in _schedules.ToArray())
+ {
+ if (schedule.Filename != filename) continue;
+ schedule.Play = false;
+ _schedules.Remove(schedule);
+ }
+ }
+
+ public override void AddScheduledSound(ScheduledSound schedule)
+ {
+ _schedules.Add(schedule);
+ Play(schedule);
+ }
+
+ public void Play(ScheduledSound schedule)
+ {
+ if (!schedule.Play) return;
+ if (Random == null) Random = new Random(Owner.Uid.GetHashCode() ^ DateTime.Now.GetHashCode());
+
+ Timer.Spawn((int) schedule.Delay + (Random.Next((int) schedule.RandomDelay)),() =>
+ {
+ if (!schedule.Play) return; // We make sure this hasn't changed.
+ if (_audioSystem == null) _audioSystem = IoCManager.Resolve().GetEntitySystem();
+ _audioSystem.Play(schedule.Filename, Owner, schedule.AudioParams);
+
+ if (schedule.Times == 0)
+ {
+ _schedules.Remove(schedule);
+ return;
+ }
+
+ if (schedule.Times > 0)
+ schedule.Times--;
+
+ Play(schedule);
+ });
+ }
+
+ public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null)
+ {
+ base.HandleMessage(message, netChannel, component);
+ switch (message)
+ {
+ case ScheduledSoundMessage msg:
+ AddScheduledSound(msg.Schedule);
+ break;
+
+ case StopSoundScheduleMessage msg:
+ StopScheduledSound(msg.Filename);
+ break;
+
+ case StopAllSoundsMessage msg:
+ StopAllSounds();
+ break;
+ }
+ }
+
+ public override void Initialize()
+ {
+ base.Initialize();
+ IoCManager.Resolve().TryGetEntitySystem(out _audioSystem);
+ }
+
+ public override void ExposeData(ObjectSerializer serializer)
+ {
+ base.ExposeData(serializer);
+ if (serializer.Writing) return;
+ serializer.TryReadDataField("schedules", out List schedules);
+ if (schedules == null) return;
+ foreach (var schedule in schedules)
+ {
+ if (schedule == null) continue;
+ AddScheduledSound(schedule);
+ }
+ }
+ }
+}
diff --git a/Content.Server/Content.Server.csproj b/Content.Server/Content.Server.csproj
index 1896fea3d9..aa5e33e006 100644
--- a/Content.Server/Content.Server.csproj
+++ b/Content.Server/Content.Server.csproj
@@ -99,6 +99,7 @@
+
diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs
index ad1855b06e..96c671a4b3 100644
--- a/Content.Server/EntryPoint.cs
+++ b/Content.Server/EntryPoint.cs
@@ -35,6 +35,7 @@ using Content.Server.Mobs;
using Content.Server.Players;
using Content.Server.GameObjects.Components.Interactable;
using Content.Server.GameObjects.Components.Markers;
+using Content.Server.GameObjects.Components.Sound;
using Content.Server.GameObjects.Components.Weapon.Ranged;
using Content.Server.GameTicking;
using Content.Server.Interfaces;
@@ -107,6 +108,7 @@ namespace Content.Server
factory.Register();
factory.Register();
+ factory.Register();
factory.Register();
diff --git a/Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs b/Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs
index 0118f01143..8ea9badc00 100644
--- a/Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs
+++ b/Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Interactable.Tools;
+using Content.Server.GameObjects.Components.Sound;
using Content.Server.GameObjects.Components.Stack;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Construction;
@@ -28,7 +29,6 @@ namespace Content.Server.GameObjects.Components.Construction
SpriteComponent Sprite;
ITransformComponent Transform;
- AudioSystem AudioSystem;
Random random;
public override void Initialize()
@@ -38,7 +38,6 @@ namespace Content.Server.GameObjects.Components.Construction
Sprite = Owner.GetComponent();
Transform = Owner.GetComponent();
var systemman = IoCManager.Resolve();
- AudioSystem = systemman.GetEntitySystem();
random = new Random();
}
@@ -95,6 +94,8 @@ namespace Content.Server.GameObjects.Components.Construction
bool TryProcessStep(ConstructionStep step, IEntity slapped)
{
+ var sound = IoCManager.Resolve().GetEntitySystem();
+
switch (step)
{
case ConstructionStepMaterial matStep:
@@ -105,9 +106,9 @@ namespace Content.Server.GameObjects.Components.Construction
return false;
}
if (matStep.Material == MaterialType.Cable)
- AudioSystem.Play("/Audio/items/zip.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/zip.ogg", Transform.GridPosition);
else
- AudioSystem.Play("/Audio/items/deconstruct.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/deconstruct.ogg", Transform.GridPosition);
return true;
case ConstructionStepTool toolStep:
switch (toolStep.Tool)
@@ -115,7 +116,7 @@ namespace Content.Server.GameObjects.Components.Construction
case ToolType.Crowbar:
if (slapped.HasComponent())
{
- AudioSystem.Play("/Audio/items/crowbar.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/crowbar.ogg", Transform.GridPosition);
return true;
}
return false;
@@ -123,16 +124,16 @@ namespace Content.Server.GameObjects.Components.Construction
if (slapped.TryGetComponent(out WelderComponent welder) && welder.TryUse(toolStep.Amount))
{
if (random.NextDouble() > 0.5)
- AudioSystem.Play("/Audio/items/welder.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/welder.ogg", Transform.GridPosition);
else
- AudioSystem.Play("/Audio/items/welder2.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/welder2.ogg", Transform.GridPosition);
return true;
}
return false;
case ToolType.Wrench:
if (slapped.HasComponent())
{
- AudioSystem.Play("/Audio/items/ratchet.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/ratchet.ogg", Transform.GridPosition);
return true;
}
return false;
@@ -140,16 +141,16 @@ namespace Content.Server.GameObjects.Components.Construction
if (slapped.HasComponent())
{
if (random.NextDouble() > 0.5)
- AudioSystem.Play("/Audio/items/screwdriver.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/screwdriver.ogg", Transform.GridPosition);
else
- AudioSystem.Play("/Audio/items/screwdriver2.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/screwdriver2.ogg", Transform.GridPosition);
return true;
}
return false;
case ToolType.Wirecutters:
if (slapped.HasComponent())
{
- AudioSystem.Play("/Audio/items/wirecutter.ogg", Transform.GridPosition);
+ sound.Play("/Audio/items/wirecutter.ogg", Transform.GridPosition);
return true;
}
return false;
diff --git a/Content.Server/GameObjects/Components/Construction/ConstructorComponent.cs b/Content.Server/GameObjects/Components/Construction/ConstructorComponent.cs
index f074411855..824994ed42 100644
--- a/Content.Server/GameObjects/Components/Construction/ConstructorComponent.cs
+++ b/Content.Server/GameObjects/Components/Construction/ConstructorComponent.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Materials;
+using Content.Server.GameObjects.Components.Sound;
using Content.Server.GameObjects.Components.Stack;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Construction;
@@ -75,8 +76,7 @@ namespace Content.Server.GameObjects.Components.Construction
// OK WE'RE GOOD CONSTRUCTION STARTED.
var entMgr = IoCManager.Resolve();
- var AudioSystem = IoCManager.Resolve().GetEntitySystem();
- AudioSystem.Play("/Audio/items/deconstruct.ogg", loc);
+ IoCManager.Resolve().GetEntitySystem().Play("/Audio/items/deconstruct.ogg", loc);
if (prototype.Stages.Count == 2)
{
// Exactly 2 stages, so don't make an intermediate frame.
diff --git a/Content.Server/GameObjects/Components/Power/ApcComponent.cs b/Content.Server/GameObjects/Components/Power/ApcComponent.cs
index 2cc349714c..e8d32c9279 100644
--- a/Content.Server/GameObjects/Components/Power/ApcComponent.cs
+++ b/Content.Server/GameObjects/Components/Power/ApcComponent.cs
@@ -1,4 +1,5 @@
-using Content.Server.GameObjects.EntitySystems;
+using Content.Server.GameObjects.Components.Sound;
+using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Components.Power;
using SS14.Server.GameObjects;
using SS14.Server.GameObjects.Components.UserInterface;
@@ -118,8 +119,7 @@ namespace Content.Server.GameObjects.Components.Power
private void _clickSound()
{
- IoCManager.Resolve().GetEntitySystem()
- .Play("/Audio/machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f));
+ Owner.GetComponent().Play("/Audio/machines/machine_switch.ogg", AudioParams.Default.WithVolume(-2f));
}
}
}
diff --git a/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs b/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs
index 8fa309f15d..74e168398a 100644
--- a/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs
+++ b/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs
@@ -1,4 +1,5 @@
using System;
+using Content.Server.GameObjects.Components.Sound;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces.GameObjects;
using Content.Shared.GameObjects;
@@ -150,8 +151,7 @@ namespace Content.Server.GameObjects.Components.Power
if (time > _lastThunk + _thunkDelay)
{
_lastThunk = time;
- IoCManager.Resolve().GetEntitySystem()
- .Play("/Audio/machines/light_tube_on.ogg", Owner, AudioParams.Default.WithVolume(-10f));
+ Owner.GetComponent().Play("/Audio/machines/light_tube_on.ogg", AudioParams.Default.WithVolume(-10f));
}
}
else
diff --git a/Content.Server/GameObjects/Components/Sound/SoundComponent.cs b/Content.Server/GameObjects/Components/Sound/SoundComponent.cs
new file mode 100644
index 0000000000..5045dbe48d
--- /dev/null
+++ b/Content.Server/GameObjects/Components/Sound/SoundComponent.cs
@@ -0,0 +1,72 @@
+using System.Collections.Generic;
+using Content.Shared.GameObjects.Components.Sound;
+using SS14.Server.GameObjects.EntitySystems;
+using SS14.Shared.Audio;
+using SS14.Shared.GameObjects;
+using SS14.Shared.Interfaces.GameObjects;
+using SS14.Shared.Interfaces.Network;
+using SS14.Shared.Log;
+using SS14.Shared.Map;
+using SS14.Shared.Serialization;
+
+namespace Content.Server.GameObjects.Components.Sound
+{
+ public class SoundComponent : SharedSoundComponent
+ {
+ ///
+ /// Stops all sounds.
+ ///
+ /// User that will be affected.
+ public void StopAllSounds(INetChannel channel)
+ {
+ SendNetworkMessage(new StopAllSoundsMessage(), channel);
+ }
+
+ ///
+ /// Stops a certain scheduled sound from playing.
+ ///
+ /// User that will be affected.
+ public void StopScheduledSound(string filename, INetChannel channel)
+ {
+ SendNetworkMessage(new StopSoundScheduleMessage(){Filename = filename}, channel);
+ }
+
+ ///
+ /// Adds an scheduled sound to be played.
+ ///
+ /// User that will be affected.
+ public void AddScheduledSound(ScheduledSound schedule, INetChannel channel)
+ {
+ SendNetworkMessage(new ScheduledSoundMessage() {Schedule = schedule}, channel);
+ }
+
+ public override void StopAllSounds()
+ {
+ StopAllSounds(null);
+ }
+
+ public override void StopScheduledSound(string filename)
+ {
+ StopScheduledSound(filename, null);
+ }
+
+ public override void AddScheduledSound(ScheduledSound schedule)
+ {
+ AddScheduledSound(schedule, null);
+ }
+
+ ///
+ /// Play an audio file following the entity.
+ ///
+ /// The resource path to the OGG Vorbis file to play.
+ /// User that will be affected.
+ public void Play(string filename, AudioParams? audioParams = null, INetChannel channel = null)
+ {
+ AddScheduledSound(new ScheduledSound()
+ {
+ Filename = filename,
+ AudioParams = audioParams,
+ }, channel);
+ }
+ }
+}
diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs
index 2fa08b8f28..b876d4e08c 100644
--- a/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs
+++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs
@@ -12,7 +12,8 @@ using SS14.Shared.Maths;
using SS14.Shared.Physics;
using SS14.Shared.Serialization;
using System;
-using SS14.Shared.GameObjects;
+ using Content.Server.GameObjects.Components.Sound;
+ using SS14.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Hitscan
{
@@ -81,7 +82,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Hitscan
};
var mgr = IoCManager.Resolve();
mgr.GetEntitySystem().CreateParticle(message);
- mgr.GetEntitySystem().Play("/Audio/laser.ogg", Owner, AudioParams.Default.WithVolume(-5));
+ Owner.GetComponent().Play("/Audio/laser.ogg", AudioParams.Default.WithVolume(-5));
}
}
}
diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BallisticMagazineWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BallisticMagazineWeaponComponent.cs
index 497bc80434..e319ae3d75 100644
--- a/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BallisticMagazineWeaponComponent.cs
+++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BallisticMagazineWeaponComponent.cs
@@ -1,4 +1,5 @@
using System;
+using Content.Server.GameObjects.Components.Sound;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Weapons.Ranged;
@@ -110,8 +111,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
if (_magInSound != null)
{
- var audioSystem = IoCManager.Resolve().GetEntitySystem();
- audioSystem.Play(_magInSound, Owner);
+ Owner.GetComponent().Play(_magInSound);
}
component.OnAmmoCountChanged += _magazineAmmoCountChanged;
@@ -142,8 +142,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
entity.Transform.GridPosition = Owner.Transform.GridPosition;
if (_magOutSound != null)
{
- var audioSystem = IoCManager.Resolve().GetEntitySystem();
- audioSystem.Play(_magOutSound, Owner);
+ Owner.GetComponent().Play(_magOutSound);
}
_updateAppearance();
@@ -163,9 +162,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
var entity = RemoveFromChamber(chamber);
entity.Transform.GridPosition = Owner.Transform.GridPosition;
entity.Transform.LocalRotation = _bulletDropRandom.Pick(_randomBulletDirs).ToAngle();
- var audioSystem = IoCManager.Resolve().GetEntitySystem();
var effect = $"/Audio/items/weapons/casingfall{_bulletDropRandom.Next(1, 4)}.ogg";
- audioSystem.Play(effect, entity, AudioParams.Default.WithVolume(-3));
+ Owner.GetComponent().Play(effect, AudioParams.Default.WithVolume(-3));
if (Magazine != null)
{
@@ -181,7 +179,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
EjectMagazine();
if (_autoEjectSound != null)
{
- audioSystem.Play(_autoEjectSound, Owner, AudioParams.Default.WithVolume(-5));
+ Owner.GetComponent().Play(_autoEjectSound, AudioParams.Default.WithVolume(-5));
}
}
}
diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BallisticWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BallisticWeaponComponent.cs
index cb23dd4e0e..2c1c9fa3c6 100644
--- a/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BallisticWeaponComponent.cs
+++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BallisticWeaponComponent.cs
@@ -1,5 +1,6 @@
using System;
using Content.Server.GameObjects.Components.Interactable;
+using Content.Server.GameObjects.Components.Sound;
using Content.Shared.GameObjects;
using SS14.Server.Chat;
using SS14.Server.GameObjects.Components.Container;
@@ -69,8 +70,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
{
if (_soundGunEmpty != null)
{
- var audioSystem = IoCManager.Resolve().GetEntitySystem();
- audioSystem.Play(_soundGunEmpty, Owner);
+ Owner.GetComponent().Play(_soundGunEmpty);
}
}
var chambered = GetChambered(0);
diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/ProjectileWeapon.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/ProjectileWeapon.cs
index 9fa5d127f4..0e1de9a103 100644
--- a/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/ProjectileWeapon.cs
+++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/ProjectileWeapon.cs
@@ -1,6 +1,7 @@
using System;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Projectiles;
+using Content.Server.GameObjects.Components.Sound;
using SS14.Server.GameObjects;
using SS14.Server.GameObjects.EntitySystems;
using SS14.Server.Interfaces.GameObjects;
@@ -90,7 +91,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
projectile.Transform.LocalRotation = angle.Theta;
// Sound!
- IoCManager.Resolve().GetEntitySystem().Play("/Audio/gunshot_c20.ogg", user);
+ Owner.GetComponent().Play("/Audio/gunshot_c20.ogg");
}
///
diff --git a/Content.Shared/Content.Shared.csproj b/Content.Shared/Content.Shared.csproj
index 93f267c422..c8c3c80e4e 100644
--- a/Content.Shared/Content.Shared.csproj
+++ b/Content.Shared/Content.Shared.csproj
@@ -72,6 +72,7 @@
+
@@ -126,4 +127,4 @@
-
+
\ No newline at end of file
diff --git a/Content.Shared/GameObjects/Components/Sound/SharedSoundComponent.cs b/Content.Shared/GameObjects/Components/Sound/SharedSoundComponent.cs
new file mode 100644
index 0000000000..67b9b9fe8e
--- /dev/null
+++ b/Content.Shared/GameObjects/Components/Sound/SharedSoundComponent.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Content.Shared.GameObjects;
+using SS14.Shared.Audio;
+using SS14.Shared.GameObjects;
+using SS14.Shared.Interfaces.GameObjects;
+using SS14.Shared.Interfaces.Serialization;
+using SS14.Shared.IoC;
+using SS14.Shared.Map;
+using SS14.Shared.Serialization;
+using SS14.Shared.Timers;
+
+namespace Content.Shared.GameObjects.Components.Sound
+{
+ public class SharedSoundComponent : Component
+ {
+ public override string Name => "Sound";
+ public override uint? NetID => ContentNetIDs.SOUND;
+
+ ///
+ /// Stops all sounds.
+ ///
+ public virtual void StopAllSounds()
+ {}
+
+ ///
+ /// Stops a certain scheduled sound from playing.
+ ///
+ public virtual void StopScheduledSound(string filename)
+ {}
+
+ ///
+ /// Adds an scheduled sound to be played.
+ ///
+ public virtual void AddScheduledSound(ScheduledSound scheduledSound)
+ {}
+
+ ///
+ /// Play an audio file following the entity.
+ ///
+ /// The resource path to the OGG Vorbis file to play.
+ public void Play(string filename, AudioParams? audioParams = null)
+ {
+ AddScheduledSound(new ScheduledSound()
+ {
+ Filename = filename,
+ AudioParams = audioParams,
+ });
+ }
+ }
+
+ [NetSerializable, Serializable]
+ public class ScheduledSoundMessage : ComponentMessage
+ {
+ public ScheduledSound Schedule;
+ public ScheduledSoundMessage()
+ {
+ Directed = true;
+ }
+ }
+
+ [NetSerializable, Serializable]
+ public class StopSoundScheduleMessage : ComponentMessage
+ {
+ public string Filename;
+ public StopSoundScheduleMessage()
+ {
+ Directed = true;
+ }
+ }
+
+ [NetSerializable, Serializable]
+ public class StopAllSoundsMessage : ComponentMessage
+ {
+ public StopAllSoundsMessage()
+ {
+ Directed = true;
+ }
+ }
+
+ [Serializable, NetSerializable]
+ public class ScheduledSound : IExposeData
+ {
+ public string Filename = "";
+
+ ///
+ /// The parameters to play the sound with.
+ ///
+ public AudioParams? AudioParams;
+
+ ///
+ /// Delay in milliseconds before playing the sound,
+ /// and delay between repetitions if Times is not 0.
+ ///
+ public uint Delay = 0;
+
+ ///
+ /// Maximum number of milliseconds to add to the delay randomly.
+ /// Useful for random ambience noises. Generated value differs from client to client.
+ ///
+ public uint RandomDelay = 0;
+
+ ///
+ /// How many times to repeat the sound. If it's 0, it will play the sound once.
+ /// If it's less than 0, it will repeat the sound indefinitely.
+ /// If it's greater than 0, it will play the sound n+1 times.
+ ///
+ public int Times = 0;
+
+ ///
+ /// Whether the sound will play or not.
+ ///
+ public bool Play = true;
+
+ public void ExposeData(ObjectSerializer serializer)
+ {
+ Filename = serializer.ReadDataField("filename", "");
+ Delay = serializer.ReadDataField("delay", 0u);
+ RandomDelay = serializer.ReadDataField("randomdelay", 0u);
+ Times = serializer.ReadDataField("times", 0);
+ AudioParams = serializer.ReadDataField("audioparams", SS14.Shared.Audio.AudioParams.Default);
+ }
+ }
+}
diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs
index 14871ceb3f..cffb1f54b4 100644
--- a/Content.Shared/GameObjects/ContentNetIDs.cs
+++ b/Content.Shared/GameObjects/ContentNetIDs.cs
@@ -14,5 +14,6 @@
public const uint SPECIES = 1009;
public const uint RANGED_WEAPON = 1010;
public const uint CAMERA_RECOIL = 1011;
+ public const uint SOUND = 1012;
}
}
diff --git a/Resources/Prototypes/Entities/Lights.yml b/Resources/Prototypes/Entities/Lights.yml
index fbcf4e8ac2..7a94c3f73d 100644
--- a/Resources/Prototypes/Entities/Lights.yml
+++ b/Resources/Prototypes/Entities/Lights.yml
@@ -4,6 +4,7 @@
components:
- type: Clickable
- type: BoundingBox
+ - type: Sound
- type: Sprite
sprite: Buildings/light_tube.rsi
state: on
diff --git a/Resources/Prototypes/Entities/Power.yml b/Resources/Prototypes/Entities/Power.yml
index 7487ddadd2..94dc3a0533 100644
--- a/Resources/Prototypes/Entities/Power.yml
+++ b/Resources/Prototypes/Entities/Power.yml
@@ -95,6 +95,7 @@
type: ApcBoundUserInterface
- type: BoundingBox
aabb: -0.25, -0.25, 0.25, 0.3
+ - type: Sound
- type: entity
id: SMES
diff --git a/Resources/Prototypes/Entities/Weapons.yml b/Resources/Prototypes/Entities/Weapons.yml
index fe9adcf64d..e7432c623b 100644
--- a/Resources/Prototypes/Entities/Weapons.yml
+++ b/Resources/Prototypes/Entities/Weapons.yml
@@ -18,6 +18,7 @@
Size: 24
sprite: Objects/laser_retro.rsi
prefix: 100
+ - type: Sound
- type: entity
name: Spear
diff --git a/Resources/Prototypes/Entities/weapons/guns.yml b/Resources/Prototypes/Entities/weapons/guns.yml
index fc9f855527..686ade94a9 100644
--- a/Resources/Prototypes/Entities/weapons/guns.yml
+++ b/Resources/Prototypes/Entities/weapons/guns.yml
@@ -11,6 +11,7 @@
- type: Icon
sprite: Objects/c20r.rsi
state: c20r-5
+ - type: Sound
- type: RangedWeapon
automatic: true
firerate: 8