using Content.Server.Chat.Systems; using Content.Server.Speech.Components; using Content.Shared.Chat.Prototypes; using Content.Shared.Humanoid; using Content.Shared.Speech; using Robust.Shared.Audio.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Random; namespace Content.Server.Speech.EntitySystems; public sealed class VocalSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly ChatSystem _chat = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnSexChanged); SubscribeLocalEvent(OnEmote); } private void OnMapInit(EntityUid uid, VocalComponent component, MapInitEvent args) { LoadSounds(uid, component); } private void OnSexChanged(EntityUid uid, VocalComponent component, SexChangedEvent args) { LoadSounds(uid, component); } private void OnEmote(EntityUid uid, VocalComponent component, ref EmoteEvent args) { if (args.Handled || !args.Emote.Category.HasFlag(EmoteCategory.Vocal)) return; // snowflake case for wilhelm scream easter egg if (args.Emote.ID == component.ScreamId) { args.Handled = TryPlayScreamSound(uid, component); return; } // just play regular sound based on emote proto args.Handled = _chat.TryPlayEmoteSound(uid, component.EmoteSounds, args.Emote); } private bool TryPlayScreamSound(EntityUid uid, VocalComponent component) { if (_random.Prob(component.WilhelmProbability)) { _audio.PlayPvs(component.Wilhelm, uid, component.Wilhelm.Params); return true; } return _chat.TryPlayEmoteSound(uid, component.EmoteSounds, component.ScreamId); } private void LoadSounds(EntityUid uid, VocalComponent component, Sex? sex = null) { if (component.Sounds == null) return; sex ??= CompOrNull(uid)?.Sex ?? Sex.Unsexed; if (!component.Sounds.TryGetValue(sex.Value, out var protoId)) return; _proto.TryIndex(protoId, out component.EmoteSounds); } }