using Content.Shared.Actions; using Content.Shared.Administration.Logs; using Content.Shared.CCVar; using Content.Shared.Chat; using Content.Shared.Clothing; using Content.Shared.Database; using Content.Shared.Inventory; using Content.Shared.Lock; using Content.Shared.Popups; using Content.Shared.Preferences; using Content.Shared.Speech; using Content.Shared.VoiceMask; using Robust.Shared.Configuration; using Robust.Shared.Containers; using Robust.Shared.Prototypes; namespace Content.Server.VoiceMask; public sealed partial class VoiceMaskSystem : EntitySystem { [Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly IConfigurationManager _cfgManager = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly SharedActionsSystem _actions = default!; [Dependency] private readonly LockSystem _lock = default!; [Dependency] private readonly SharedContainerSystem _container = default!; // CCVar. private int _maxNameLength; public override void Initialize() { base.Initialize(); SubscribeLocalEvent>(OnTransformSpeakerName); SubscribeLocalEvent(OnLockToggled); SubscribeLocalEvent(OnChangeName); SubscribeLocalEvent(OnChangeVerb); SubscribeLocalEvent(OnEquip); SubscribeLocalEvent(OpenUI); Subs.CVar(_cfgManager, CCVars.MaxNameLength, value => _maxNameLength = value, true); } private void OnTransformSpeakerName(Entity entity, ref InventoryRelayedEvent args) { args.Args.VoiceName = GetCurrentVoiceName(entity); args.Args.SpeechVerb = entity.Comp.VoiceMaskSpeechVerb ?? args.Args.SpeechVerb; } private void OnLockToggled(Entity ent, ref LockToggledEvent args) { if (args.Locked) _actions.RemoveAction(ent.Comp.ActionEntity); else if (_container.TryGetContainingContainer(ent.Owner, out var container)) _actions.AddAction(container.Owner, ref ent.Comp.ActionEntity, ent.Comp.Action, ent); } #region User inputs from UI private void OnChangeVerb(Entity entity, ref VoiceMaskChangeVerbMessage msg) { if (msg.Verb is { } id && !_proto.HasIndex(id)) return; entity.Comp.VoiceMaskSpeechVerb = msg.Verb; // verb is only important to metagamers so no need to log as opposed to name _popupSystem.PopupEntity(Loc.GetString("voice-mask-popup-success"), entity, msg.Actor); UpdateUI(entity); } private void OnChangeName(Entity entity, ref VoiceMaskChangeNameMessage message) { if (message.Name.Length > _maxNameLength || message.Name.Length <= 0) { _popupSystem.PopupEntity(Loc.GetString("voice-mask-popup-failure"), entity, message.Actor, PopupType.SmallCaution); return; } entity.Comp.VoiceMaskName = message.Name; _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(message.Actor):player} set voice of {ToPrettyString(entity):mask}: {entity.Comp.VoiceMaskName}"); _popupSystem.PopupEntity(Loc.GetString("voice-mask-popup-success"), entity, message.Actor); UpdateUI(entity); } #endregion #region UI private void OnEquip(EntityUid uid, VoiceMaskComponent component, ClothingGotEquippedEvent args) { if (_lock.IsLocked(uid)) return; _actions.AddAction(args.Wearer, ref component.ActionEntity, component.Action, uid); } private void OpenUI(VoiceMaskSetNameEvent ev) { var maskEntity = ev.Action.Comp.Container; if (!TryComp(maskEntity, out var voiceMaskComp)) return; if (!_uiSystem.HasUi(maskEntity.Value, VoiceMaskUIKey.Key)) return; _uiSystem.OpenUi(maskEntity.Value, VoiceMaskUIKey.Key, ev.Performer); UpdateUI((maskEntity.Value, voiceMaskComp)); } private void UpdateUI(Entity entity) { if (_uiSystem.HasUi(entity, VoiceMaskUIKey.Key)) _uiSystem.SetUiState(entity.Owner, VoiceMaskUIKey.Key, new VoiceMaskBuiState(GetCurrentVoiceName(entity), entity.Comp.VoiceMaskSpeechVerb)); } #endregion #region Helper functions private string GetCurrentVoiceName(Entity entity) { return entity.Comp.VoiceMaskName ?? Loc.GetString("voice-mask-default-name-override"); } #endregion }