106 lines
3.5 KiB
C#
106 lines
3.5 KiB
C#
using Content.Server.Actions;
|
|
using Content.Server.Chat.Systems;
|
|
using Content.Server.Humanoid;
|
|
using Content.Server.Speech.Components;
|
|
using Content.Shared.Actions.ActionTypes;
|
|
using Content.Shared.Chat.Prototypes;
|
|
using Content.Shared.Humanoid;
|
|
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!;
|
|
[Dependency] private readonly ActionsSystem _actions = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<VocalComponent, MapInitEvent>(OnMapInit);
|
|
SubscribeLocalEvent<VocalComponent, ComponentShutdown>(OnShutdown);
|
|
SubscribeLocalEvent<VocalComponent, SexChangedEvent>(OnSexChanged);
|
|
SubscribeLocalEvent<VocalComponent, EmoteEvent>(OnEmote);
|
|
SubscribeLocalEvent<VocalComponent, ScreamActionEvent>(OnScreamAction);
|
|
}
|
|
|
|
private void OnMapInit(EntityUid uid, VocalComponent component, MapInitEvent args)
|
|
{
|
|
// try to add scream action when vocal comp added
|
|
if (_proto.TryIndex(component.ScreamActionId, out InstantActionPrototype? proto))
|
|
{
|
|
component.ScreamAction = new InstantAction(proto);
|
|
_actions.AddAction(uid, component.ScreamAction, null);
|
|
}
|
|
|
|
LoadSounds(uid, component);
|
|
}
|
|
|
|
private void OnShutdown(EntityUid uid, VocalComponent component, ComponentShutdown args)
|
|
{
|
|
// remove scream action when component removed
|
|
if (component.ScreamAction != null)
|
|
{
|
|
_actions.RemoveAction(uid, component.ScreamAction);
|
|
}
|
|
}
|
|
|
|
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 void OnScreamAction(EntityUid uid, VocalComponent component, ScreamActionEvent args)
|
|
{
|
|
if (args.Handled)
|
|
return;
|
|
|
|
_chat.TryEmoteWithChat(uid, component.ScreamActionId);
|
|
args.Handled = true;
|
|
}
|
|
|
|
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<HumanoidAppearanceComponent>(uid)?.Sex ?? Sex.Unsexed;
|
|
|
|
if (!component.Sounds.TryGetValue(sex.Value, out var protoId))
|
|
return;
|
|
_proto.TryIndex(protoId, out component.EmoteSounds);
|
|
}
|
|
}
|