_window.OnNameChange += OnNameSelected;
_window.OnVerbChange += verb => SendMessage(new VoiceMaskChangeVerbMessage(verb));
+ _window.OnToggle += OnToggle;
+ _window.OnAccentToggle += OnAccentToggle;
}
private void OnNameSelected(string name)
SendMessage(new VoiceMaskChangeNameMessage(name));
}
+ private void OnToggle()
+ {
+ SendMessage(new VoiceMaskToggleMessage());
+ }
+
+ private void OnAccentToggle()
+ {
+ SendMessage(new VoiceMaskAccentToggleMessage());
+ }
+
protected override void UpdateState(BoundUserInterfaceState state)
{
if (state is not VoiceMaskBuiState cast || _window == null)
return;
}
- _window.UpdateState(cast.Name, cast.Verb);
+ _window.UpdateState(cast.Name, cast.Verb, cast.Active, cast.AccentHide);
}
protected override void Dispose(bool disposing)
<Label Text="{Loc 'voice-mask-name-change-speech-style'}" />
<OptionButton Name="SpeechVerbSelector" /> <!-- Populated in LoadVerbs -->
</BoxContainer>
+ <Button Name="ToggleAccentButton" Text="{Loc 'voice-mask-name-change-accent-toggle'}" HorizontalExpand="True" ToggleMode="True" Margin="5"/>
+ <Button Name="ToggleButton" Text="{Loc 'voice-mask-name-change-toggle'}" HorizontalExpand="True" ToggleMode="True" Margin="5"/>
</BoxContainer>
</controls:FancyWindow>
{
public Action<string>? OnNameChange;
public Action<string?>? OnVerbChange;
+ public Action? OnToggle;
+ public Action? OnAccentToggle;
private List<(string, string)> _verbs = new();
OnVerbChange?.Invoke((string?) args.Button.GetItemMetadata(args.Id));
SpeechVerbSelector.SelectId(args.Id);
};
+
+ ToggleButton.OnPressed += args => OnToggle?.Invoke();
+ ToggleAccentButton.OnPressed += args => OnAccentToggle?.Invoke();
}
public void ReloadVerbs(IPrototypeManager proto)
SpeechVerbSelector.SelectId(id);
}
- public void UpdateState(string name, string? verb)
+ public void UpdateState(string name, string? verb, bool active, bool accentHide)
{
NameSelector.Text = name;
_verb = verb;
+ ToggleButton.Pressed = active;
+ ToggleAccentButton.Pressed = accentHide;
for (int id = 0; id < SpeechVerbSelector.ItemCount; id++)
{
public string TransformSpeech(EntityUid sender, string message)
{
var ev = new TransformSpeechEvent(sender, message);
- RaiseLocalEvent(ev);
+ RaiseLocalEvent(sender, ev, true);
return ev.Message;
}
private void AccentHandler(TransformSpeechEvent args)
{
+ if (args.Cancelled)
+ return;
+
var accentEvent = new AccentGetEvent(args.Sender, args.Message);
RaiseLocalEvent(args.Sender, accentEvent, true);
/// </summary>
[DataField]
public EntityUid? ActionEntity;
+
+ /// <summary>
+ /// If user's voice is getting changed when they speak.
+ /// </summary>
+ [DataField]
+ public bool Active = true;
+
+ /// <summary>
+ /// If user's accent is getting hidden when they speak.
+ /// </summary>
+ [DataField]
+ public bool AccentHide = true;
}
+using Content.Server.Speech;
using Content.Shared.Actions;
using Content.Shared.Administration.Logs;
using Content.Shared.CCVar;
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;
SubscribeLocalEvent<VoiceMaskComponent, LockToggledEvent>(OnLockToggled);
SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskChangeNameMessage>(OnChangeName);
SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskChangeVerbMessage>(OnChangeVerb);
+ SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskToggleMessage>(OnToggle);
+ SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskAccentToggleMessage>(OnAccentToggle);
SubscribeLocalEvent<VoiceMaskComponent, ClothingGotEquippedEvent>(OnEquip);
SubscribeLocalEvent<VoiceMaskSetNameEvent>(OpenUI);
+ SubscribeLocalEvent<VoiceMaskComponent, TransformSpeechEvent>(OnTransformSpeech, before: [typeof(AccentSystem)]);
+ SubscribeLocalEvent<VoiceMaskComponent, InventoryRelayedEvent<TransformSpeechEvent>>(OnTransformSpeechInventory, before: [typeof(AccentSystem)]);
+ SubscribeLocalEvent<VoiceMaskComponent, ImplantRelayEvent<TransformSpeechEvent>>(OnTransformSpeechImplant, before: [typeof(AccentSystem)]);
Subs.CVar(_cfgManager, CCVars.MaxNameLength, value => _maxNameLength = value, true);
}
+ /// <summary>
+ /// Hides accent if the voice mask is on and the option to block accents is on
+ /// </summary>
+ private void TransformSpeech(Entity<VoiceMaskComponent> entity, TransformSpeechEvent args)
+ {
+ if (entity.Comp.AccentHide && entity.Comp.Active)
+ args.Cancel();
+ }
+
+ private void OnTransformSpeech(Entity<VoiceMaskComponent> entity, ref TransformSpeechEvent args)
+ {
+ TransformSpeech(entity, args);
+ }
+
+ private void OnTransformSpeechInventory(Entity<VoiceMaskComponent> entity, ref InventoryRelayedEvent<TransformSpeechEvent> args)
+ {
+ TransformSpeech(entity, args.Args);
+ }
+
+ private void OnTransformSpeechImplant(Entity<VoiceMaskComponent> entity, ref ImplantRelayEvent<TransformSpeechEvent> args)
+ {
+ TransformSpeech(entity, args.Event);
+ }
+
private void OnTransformSpeakerNameInventory(Entity<VoiceMaskComponent> entity, ref InventoryRelayedEvent<TransformSpeakerNameEvent> args)
{
TransformVoice(entity, args.Args);
private void OnSeeIdentityAttemptEvent(Entity<VoiceMaskComponent> entity, ref ImplantRelayEvent<SeeIdentityAttemptEvent> args)
{
- if (entity.Comp.OverrideIdentity)
- args.Event.NameOverride = GetCurrentVoiceName(entity);
+ if (!entity.Comp.OverrideIdentity || !entity.Comp.Active)
+ return;
+
+ args.Event.NameOverride = GetCurrentVoiceName(entity);
}
private void OnImplantImplantedEvent(Entity<VoiceMaskComponent> entity, ref ImplantImplantedEvent ev)
UpdateUI(entity);
}
+
+ private void OnToggle(Entity<VoiceMaskComponent> entity, ref VoiceMaskToggleMessage args)
+ {
+ _popupSystem.PopupEntity(Loc.GetString("voice-mask-popup-toggle"), entity, args.Actor);
+ entity.Comp.Active = !entity.Comp.Active;
+
+ // Update identity because of possible name override
+ _identity.QueueIdentityUpdate(args.Actor);
+ }
+
+ private void OnAccentToggle(Entity<VoiceMaskComponent> entity, ref VoiceMaskAccentToggleMessage args)
+ {
+ _popupSystem.PopupEntity(Loc.GetString("voice-mask-popup-accent-toggle"), entity, args.Actor);
+ entity.Comp.AccentHide = !entity.Comp.AccentHide;
+ }
#endregion
#region UI
private void UpdateUI(Entity<VoiceMaskComponent> entity)
{
if (_uiSystem.HasUi(entity, VoiceMaskUIKey.Key))
- _uiSystem.SetUiState(entity.Owner, VoiceMaskUIKey.Key, new VoiceMaskBuiState(GetCurrentVoiceName(entity), entity.Comp.VoiceMaskSpeechVerb));
+ _uiSystem.SetUiState(entity.Owner, VoiceMaskUIKey.Key, new VoiceMaskBuiState(GetCurrentVoiceName(entity), entity.Comp.VoiceMaskSpeechVerb, entity.Comp.Active, entity.Comp.AccentHide));
}
#endregion
private void TransformVoice(Entity<VoiceMaskComponent> entity, TransformSpeakerNameEvent args)
{
+ if (!entity.Comp.Active)
+ return;
+
args.VoiceName = GetCurrentVoiceName(entity);
args.SpeechVerb = entity.Comp.VoiceMaskSpeechVerb ?? args.SpeechVerb;
}
/// <summary>
/// Raised broadcast in order to transform speech.transmit
/// </summary>
-public sealed class TransformSpeechEvent : EntityEventArgs
+public sealed class TransformSpeechEvent : CancellableEntityEventArgs, IInventoryRelayEvent
{
+ public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET;
public EntityUid Sender;
public string Message;
SubscribeLocalEvent<ImplantedComponent, AfterInteractUsingEvent>(RelayToImplantEvent);
SubscribeLocalEvent<ImplantedComponent, SuicideEvent>(RelayToImplantEvent);
SubscribeLocalEvent<ImplantedComponent, TransformSpeakerNameEvent>(RelayToImplantEvent);
+ SubscribeLocalEvent<ImplantedComponent, TransformSpeechEvent>(RelayToImplantEvent);
SubscribeLocalEvent<ImplantedComponent, SeeIdentityAttemptEvent>(RelayToImplantEvent);
}
SubscribeLocalEvent<InventoryComponent, GetDefaultRadioChannelEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, RefreshNameModifiersEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, TransformSpeakerNameEvent>(RelayInventoryEvent);
+ SubscribeLocalEvent<InventoryComponent, TransformSpeechEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, SelfBeforeInjectEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, BeforeInjectTargetEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, SelfBeforeGunShotEvent>(RelayInventoryEvent);
{
public readonly string Name;
public readonly string? Verb;
+ public readonly bool Active;
+ public readonly bool AccentHide;
- public VoiceMaskBuiState(string name, string? verb)
+ public VoiceMaskBuiState(string name, string? verb, bool active, bool accentHide)
{
Name = name;
Verb = verb;
+ Active = active;
+ AccentHide = accentHide;
}
}
Verb = verb;
}
}
+
+/// <summary>
+/// Toggle the effects of the voice mask.
+/// </summary>
+[Serializable, NetSerializable]
+public sealed class VoiceMaskToggleMessage : BoundUserInterfaceMessage;
+
+/// <summary>
+/// Toggle the effects of accent negation.
+/// </summary>
+[Serializable, NetSerializable]
+public sealed class VoiceMaskAccentToggleMessage : BoundUserInterfaceMessage;
voice-mask-name-change-speech-style = Speech style
voice-mask-name-change-set = Set name
voice-mask-name-change-set-description = Change the name others hear to something else.
+voice-mask-name-change-toggle = Toggle voice mask
+voice-mask-name-change-accent-toggle = Block accent
+
+voice-mask-popup-toggle = Toggled voice mask.
+voice-mask-popup-accent-toggle = Toggled accent.
voice-mask-popup-success = Name set successfully.
voice-mask-popup-failure = Name could not be set.