CatStation/Content.Shared/Speech/EntitySystems/SpeechNoiseSystem.cs
Whatstone c89c01afc0
Bugfix: You can once again hear when you talk. (#45112)
* Unpredict your speech noise

* unpredict wilhelm
2026-08-03 15:07:50 +00:00

73 lines
2.4 KiB
C#

using Content.Shared.Chat;
using Content.Shared.Random.Helpers;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Network;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Shared.Speech.EntitySystems;
public sealed partial class SpeechSoundSystem : EntitySystem
{
[Dependency] private IGameTiming _gameTiming = default!;
[Dependency] private INetManager _net = default!;
[Dependency] private SharedAudioSystem _audio = default!;
[SubscribeLocalEvent]
private void OnEntitySpoke(Entity<SpeechComponent> ent, ref EntitySpokeEvent args)
{
if (ent.Comp.SpeechSounds == null)
return;
var currentTime = _gameTiming.CurTime;
var cooldown = TimeSpan.FromSeconds(ent.Comp.SoundCooldownTime);
// Ensure more than the cooldown time has passed since last speaking
if (currentTime - ent.Comp.LastTimeSoundPlayed < cooldown)
return;
var sound = GetSpeechSound(ent, args.Message);
ent.Comp.LastTimeSoundPlayed = currentTime;
if (_net.IsServer) // TODO: replace this call with PlayPredicted when chat is predicted.
_audio.PlayPvs(sound, ent);
}
/// <summary>
/// Gets the speech sound for a message.
/// </summary>
public SoundSpecifier? GetSpeechSound(Entity<SpeechComponent> ent, string message)
{
if (ent.Comp.SpeechSounds == null)
return null;
// Play speech sound
var prototype = ProtoMan.Index<SpeechSoundsPrototype>(ent.Comp.SpeechSounds);
// Different sounds for ask/exclaim based on last character
var contextSound = message[^1] switch
{
'?' => prototype.AskSound,
'!' => prototype.ExclaimSound,
_ => prototype.SaySound
};
// Use exclaim sound if most characters are uppercase.
var uppercaseCount = 0;
foreach (var t in message)
{
if (char.IsUpper(t))
uppercaseCount++;
}
if (uppercaseCount > message.Length / 2)
{
contextSound = prototype.ExclaimSound;
}
var random = SharedRandomExtensions.PredictedRandom(_gameTiming, GetNetEntity(ent));
var scale = (float)random.NextGaussian(1, prototype.Variation);
contextSound.Params = ent.Comp.AudioParams.WithPitchScale(scale);
return contextSound;
}
}