Add voice mask implant (#41551)
* Add voice mask implant * Remove voice mask * Voice mask implant now overrides your identity * voice mask implant can now be extracted, when taking out the voice mask implant it now updates your name proplery * Simplify logic
This commit is contained in:
parent
7c7ab40ae3
commit
3720601121
|
|
@ -26,6 +26,12 @@ public sealed partial class VoiceMaskComponent : Component
|
|||
[DataField]
|
||||
public ProtoId<SpeechVerbPrototype>? VoiceMaskSpeechVerb;
|
||||
|
||||
/// <summary>
|
||||
/// If true will override the users identity with whatever <see cref="VoiceMaskName"/> is.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool OverrideIdentity;
|
||||
|
||||
/// <summary>
|
||||
/// The action that gets displayed when the voice mask is equipped.
|
||||
/// </summary>
|
||||
|
|
@ -38,3 +44,4 @@ public sealed partial class VoiceMaskComponent : Component
|
|||
[DataField]
|
||||
public EntityUid? ActionEntity;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ using Content.Shared.CCVar;
|
|||
using Content.Shared.Chat;
|
||||
using Content.Shared.Clothing;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.IdentityManagement.Components;
|
||||
using Content.Shared.Implants;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Lock;
|
||||
|
|
@ -27,6 +29,7 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
|||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||
[Dependency] private readonly LockSystem _lock = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly IdentitySystem _identity = default!;
|
||||
|
||||
// CCVar.
|
||||
private int _maxNameLength;
|
||||
|
|
@ -34,8 +37,11 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
|||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<VoiceMaskComponent, InventoryRelayedEvent<TransformSpeakerNameEvent>>(OnTransformSpeakerName);
|
||||
SubscribeLocalEvent<VoiceMaskComponent, InventoryRelayedEvent<TransformSpeakerNameEvent>>(OnTransformSpeakerNameInventory);
|
||||
SubscribeLocalEvent<VoiceMaskComponent, ImplantRelayEvent<TransformSpeakerNameEvent>>(OnTransformSpeakerNameImplant);
|
||||
SubscribeLocalEvent<VoiceMaskComponent, ImplantRelayEvent<SeeIdentityAttemptEvent>>(OnSeeIdentityAttemptEvent);
|
||||
SubscribeLocalEvent<VoiceMaskComponent, ImplantImplantedEvent>(OnImplantImplantedEvent);
|
||||
SubscribeLocalEvent<VoiceMaskComponent, ImplantRemovedEvent>(OnImplantRemovedEventEvent);
|
||||
SubscribeLocalEvent<VoiceMaskComponent, LockToggledEvent>(OnLockToggled);
|
||||
SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskChangeNameMessage>(OnChangeName);
|
||||
SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskChangeVerbMessage>(OnChangeVerb);
|
||||
|
|
@ -45,19 +51,31 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
|||
Subs.CVar(_cfgManager, CCVars.MaxNameLength, value => _maxNameLength = value, true);
|
||||
}
|
||||
|
||||
private void OnTransformSpeakerName(Entity<VoiceMaskComponent> entity, ref InventoryRelayedEvent<TransformSpeakerNameEvent> args)
|
||||
private void OnTransformSpeakerNameInventory(Entity<VoiceMaskComponent> entity, ref InventoryRelayedEvent<TransformSpeakerNameEvent> args)
|
||||
{
|
||||
args.Args.VoiceName = GetCurrentVoiceName(entity);
|
||||
args.Args.SpeechVerb = entity.Comp.VoiceMaskSpeechVerb ?? args.Args.SpeechVerb;
|
||||
TransformVoice(entity, args.Args);
|
||||
}
|
||||
|
||||
// DeltaV - specific for implants
|
||||
private void OnTransformSpeakerNameImplant(Entity<VoiceMaskComponent> entity, ref ImplantRelayEvent<TransformSpeakerNameEvent> args)
|
||||
{
|
||||
args.Event.VoiceName = GetCurrentVoiceName(entity);
|
||||
args.Event.SpeechVerb = entity.Comp.VoiceMaskSpeechVerb ?? args.Event.SpeechVerb;
|
||||
TransformVoice(entity, args.Event);
|
||||
}
|
||||
|
||||
private void OnSeeIdentityAttemptEvent(Entity<VoiceMaskComponent> entity, ref ImplantRelayEvent<SeeIdentityAttemptEvent> args)
|
||||
{
|
||||
if (entity.Comp.OverrideIdentity)
|
||||
args.Event.NameOverride = GetCurrentVoiceName(entity);
|
||||
}
|
||||
|
||||
private void OnImplantImplantedEvent(Entity<VoiceMaskComponent> entity, ref ImplantImplantedEvent ev)
|
||||
{
|
||||
_identity.QueueIdentityUpdate(ev.Implanted);
|
||||
}
|
||||
|
||||
private void OnImplantRemovedEventEvent(Entity<VoiceMaskComponent> entity, ref ImplantRemovedEvent ev)
|
||||
{
|
||||
_identity.QueueIdentityUpdate(ev.Implanted);
|
||||
}
|
||||
// END DeltaV
|
||||
|
||||
private void OnLockToggled(Entity<VoiceMaskComponent> ent, ref LockToggledEvent args)
|
||||
{
|
||||
|
|
@ -89,6 +107,9 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
|||
return;
|
||||
}
|
||||
|
||||
var nameUpdatedEvent = new VoiceMaskNameUpdatedEvent(entity, entity.Comp.VoiceMaskName, message.Name);
|
||||
RaiseLocalEvent(message.Actor, ref nameUpdatedEvent);
|
||||
|
||||
entity.Comp.VoiceMaskName = message.Name;
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(message.Actor):player} set voice of {ToPrettyString(entity):mask}: {entity.Comp.VoiceMaskName}");
|
||||
|
||||
|
|
@ -133,5 +154,11 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
|||
{
|
||||
return entity.Comp.VoiceMaskName ?? Loc.GetString("voice-mask-default-name-override");
|
||||
}
|
||||
|
||||
private void TransformVoice(Entity<VoiceMaskComponent> entity, TransformSpeakerNameEvent args)
|
||||
{
|
||||
args.VoiceName = GetCurrentVoiceName(entity);
|
||||
args.SpeechVerb = entity.Comp.VoiceMaskSpeechVerb ?? args.SpeechVerb;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
using Content.Server.VoiceMask;
|
||||
using Content.Shared.Implants;
|
||||
|
||||
namespace Content.Server.DV.Implants;
|
||||
|
||||
public sealed class SubdermalBionicSyrinxImplantSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<VoiceMaskComponent, ImplantImplantedEvent>(OnInsert);
|
||||
}
|
||||
|
||||
private void OnInsert(Entity<VoiceMaskComponent> ent, ref ImplantImplantedEvent args)
|
||||
{
|
||||
// Update the name so it's the entities default name. You can't take it off like a voice mask so it's important!
|
||||
ent.Comp.VoiceMaskName = Name(args.Implanted);
|
||||
}
|
||||
}
|
||||
|
|
@ -37,4 +37,9 @@ public sealed class SeeIdentityAttemptEvent : CancellableEntityEventArgs, IInven
|
|||
|
||||
// cumulative coverage from each relayed slot
|
||||
public IdentityBlockerCoverage TotalCoverage = IdentityBlockerCoverage.NONE;
|
||||
|
||||
/// <summary>
|
||||
/// A specific name to override your identiy with.
|
||||
/// </summary>
|
||||
public string? NameOverride = null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,10 +47,16 @@ public sealed class IdentityRepresentation
|
|||
PresumedName = presumedName;
|
||||
}
|
||||
|
||||
public string ToStringKnown(bool trueName)
|
||||
/// <summary>
|
||||
/// Get this identity as a string
|
||||
/// </summary>
|
||||
/// <param name="trueName">Should we show their "true" name or hide it?</param>
|
||||
/// <param name="nameOverride">A "true name" override</param>
|
||||
/// <returns></returns>
|
||||
public string ToStringKnown(bool trueName, string? nameOverride)
|
||||
{
|
||||
return trueName
|
||||
? TrueName
|
||||
? nameOverride ?? TrueName
|
||||
: PresumedName ?? ToStringUnknown();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using Content.Shared.Humanoid;
|
|||
using Content.Shared.IdentityManagement.Components;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.VoiceMask;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects.Components.Localization;
|
||||
|
|
@ -53,6 +54,7 @@ public sealed class IdentitySystem : EntitySystem
|
|||
SubscribeLocalEvent<IdentityComponent, DidUnequipHandEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
||||
SubscribeLocalEvent<IdentityComponent, WearerMaskToggledEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
||||
SubscribeLocalEvent<IdentityComponent, EntityRenamedEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
||||
SubscribeLocalEvent<IdentityComponent, VoiceMaskNameUpdatedEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -197,7 +199,7 @@ public sealed class IdentitySystem : EntitySystem
|
|||
var ev = new SeeIdentityAttemptEvent();
|
||||
|
||||
RaiseLocalEvent(target, ev);
|
||||
return representation.ToStringKnown(!ev.Cancelled);
|
||||
return representation.ToStringKnown(!ev.Cancelled, ev.NameOverride);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Shared.Chat; // DeltaV
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.IdentityManagement.Components;
|
||||
using Content.Shared.Implants.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
|
|
@ -13,7 +14,8 @@ public abstract partial class SharedSubdermalImplantSystem
|
|||
SubscribeLocalEvent<ImplantedComponent, MobStateChangedEvent>(RelayToImplantEvent);
|
||||
SubscribeLocalEvent<ImplantedComponent, AfterInteractUsingEvent>(RelayToImplantEvent);
|
||||
SubscribeLocalEvent<ImplantedComponent, SuicideEvent>(RelayToImplantEvent);
|
||||
SubscribeLocalEvent<ImplantedComponent, TransformSpeakerNameEvent>(RelayToImplantEvent); // DeltaV
|
||||
SubscribeLocalEvent<ImplantedComponent, TransformSpeakerNameEvent>(RelayToImplantEvent);
|
||||
SubscribeLocalEvent<ImplantedComponent, SeeIdentityAttemptEvent>(RelayToImplantEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -180,7 +180,14 @@ public abstract partial class SharedSubdermalImplantSystem : EntitySystem
|
|||
[ByRefEvent]
|
||||
public readonly record struct ImplantImplantedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// The implant itself
|
||||
/// </summary>
|
||||
public readonly EntityUid Implant;
|
||||
|
||||
/// <summary>
|
||||
/// The entity getting implanted
|
||||
/// </summary>
|
||||
public readonly EntityUid Implanted;
|
||||
|
||||
public ImplantImplantedEvent(EntityUid implant, EntityUid implanted)
|
||||
|
|
|
|||
|
|
@ -6,3 +6,11 @@ public sealed partial class VoiceMaskSetNameEvent : InstantActionEvent
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised on an entity when their voice masks name is updated
|
||||
/// </summary>
|
||||
/// <param name="VoiceMaskUid">Uid of the voice mask</param>
|
||||
/// <param name="OldName">The old name</param>
|
||||
/// <param name="NewName">The new name</param>
|
||||
[ByRefEvent]
|
||||
public readonly record struct VoiceMaskNameUpdatedEvent(EntityUid VoiceMaskUid, string? OldName, string NewName);
|
||||
|
|
|
|||
|
|
@ -173,9 +173,6 @@ uplink-binary-translator-key-desc = Lets you tap into the silicons' binary chann
|
|||
uplink-hypopen-name = Hypopen
|
||||
uplink-hypopen-desc = A chemical hypospray disguised as a pen, capable of instantly injecting up to 10u of reagents. Starts empty.
|
||||
|
||||
uplink-voice-mask-name = Voice Mask
|
||||
uplink-voice-mask-desc = A gas mask that lets you adjust your voice to whoever you can think of. Also utilizes cutting-edge chameleon technology.
|
||||
|
||||
uplink-clothing-eyes-hud-syndicate-name = Syndicate Visor
|
||||
uplink-clothing-eyes-hud-syndicate-desc = The syndicate's professional head-up display, designed for better detection of humanoids and their subsequent elimination.
|
||||
|
||||
|
|
@ -228,6 +225,9 @@ uplink-micro-bomb-implanter-desc = Explode on death or manual activation with th
|
|||
uplink-radio-implanter-name = Radio Implanter
|
||||
uplink-radio-implanter-desc = Implants a Syndicate radio, allowing covert communication without a headset.
|
||||
|
||||
uplink-voice-mask-implanter-name = Voice Mask Implanter
|
||||
uplink-voice-mask-implanter-desc = Modifies your vocal cords to be able to sound like anyone you could imagine.
|
||||
|
||||
# Bundles
|
||||
uplink-observation-kit-name = Observation Kit
|
||||
uplink-observation-kit-desc = Includes surveillance camera monitor board and security hud disguised as sunglasses.
|
||||
|
|
|
|||
|
|
@ -477,3 +477,11 @@
|
|||
icon: Interface/Actions/shop.png
|
||||
- type: InstantAction
|
||||
event: !type:IntrinsicStoreActionEvent
|
||||
|
||||
- type: entity
|
||||
parent: ActionChangeVoiceMask
|
||||
id: ActionChangeVoiceMaskImplant
|
||||
components:
|
||||
- type: Action
|
||||
icon: { sprite: Interface/Actions/voice-mask.rsi, state: icon }
|
||||
itemIconStyle: BigAction
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@
|
|||
- CyberPen
|
||||
- SpyCrewMonitor
|
||||
- BriefcaseThiefBribingBundleFilled
|
||||
- ClothingMaskGasVoiceChameleon
|
||||
- VoiceMaskImplanter
|
||||
#- todo Chameleon Stamp
|
||||
|
||||
- type: thiefBackpackSet
|
||||
|
|
|
|||
|
|
@ -1579,6 +1579,21 @@
|
|||
categories:
|
||||
- UplinkImplants
|
||||
|
||||
- type: listing
|
||||
id: UplinkVoiceMaskImplant
|
||||
name: uplink-voice-mask-implanter-name
|
||||
description: uplink-voice-mask-implanter-desc
|
||||
icon: { sprite: Interface/Actions/voice-mask.rsi, state: icon }
|
||||
productEntity: VoiceMaskImplanter
|
||||
# Begin DeltaV Removals
|
||||
# discountCategory: usualDiscounts
|
||||
# discountDownTo:
|
||||
# Telecrystal: 1
|
||||
# End DeltaV Removals
|
||||
cost:
|
||||
Telecrystal: 1 # DeltaV - was 2
|
||||
categories:
|
||||
- UplinkImplants
|
||||
|
||||
# Wearables
|
||||
|
||||
|
|
@ -1595,21 +1610,6 @@
|
|||
categories:
|
||||
- UplinkWearables
|
||||
|
||||
- type: listing
|
||||
id: UplinkVoiceMask
|
||||
name: uplink-voice-mask-name
|
||||
description: uplink-voice-mask-desc
|
||||
productEntity: ClothingMaskGasVoiceChameleon
|
||||
# Begin DeltaV Removals
|
||||
# discountCategory: usualDiscounts
|
||||
# discountDownTo:
|
||||
# Telecrystal: 1
|
||||
# End DeltaV Removals
|
||||
cost:
|
||||
Telecrystal: 1 # DeltaV - was 2
|
||||
categories:
|
||||
- UplinkWearables
|
||||
|
||||
- type: listing
|
||||
id: UplinkHolster
|
||||
name: uplink-holster-name
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
- FakeMindShieldImplant
|
||||
- RadioSyndicateImplant
|
||||
- ChameleonControllerImplant
|
||||
- VoiceMaskImplant
|
||||
deimplantFailureDamage:
|
||||
types:
|
||||
Cellular: 50
|
||||
|
|
@ -258,6 +259,14 @@
|
|||
- type: Implanter
|
||||
implant: ChameleonControllerImplant
|
||||
|
||||
- type: entity
|
||||
id: VoiceMaskImplanter
|
||||
name: voice mask implanter
|
||||
parent: BaseImplantOnlyImplanterSyndi
|
||||
components:
|
||||
- type: Implanter
|
||||
implant: VoiceMaskImplant
|
||||
|
||||
#Nuclear Operative/Special implanters
|
||||
|
||||
- type: entity
|
||||
|
|
|
|||
|
|
@ -251,6 +251,25 @@
|
|||
enum.ChameleonControllerKey.Key:
|
||||
type: ChameleonControllerBoundUserInterface
|
||||
|
||||
- type: entity
|
||||
parent: BaseSubdermalImplant
|
||||
id: VoiceMaskImplant
|
||||
name: voice mask implant
|
||||
description: This implant allows you to change your voice at will.
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: SubdermalImplant
|
||||
implantAction: ActionChangeVoiceMaskImplant
|
||||
- type: VoiceMask
|
||||
overrideIdentity: true
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
enum.VoiceMaskUIKey.Key:
|
||||
type: VoiceMaskBoundUserInterface
|
||||
- type: Tag
|
||||
tags:
|
||||
- SubdermalImplant
|
||||
|
||||
#Nuclear Operative/Special Exclusive implants
|
||||
|
||||
- type: entity
|
||||
|
|
|
|||
Loading…
Reference in New Issue