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]
|
[DataField]
|
||||||
public ProtoId<SpeechVerbPrototype>? VoiceMaskSpeechVerb;
|
public ProtoId<SpeechVerbPrototype>? VoiceMaskSpeechVerb;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true will override the users identity with whatever <see cref="VoiceMaskName"/> is.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool OverrideIdentity;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The action that gets displayed when the voice mask is equipped.
|
/// The action that gets displayed when the voice mask is equipped.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -38,3 +44,4 @@ public sealed partial class VoiceMaskComponent : Component
|
||||||
[DataField]
|
[DataField]
|
||||||
public EntityUid? ActionEntity;
|
public EntityUid? ActionEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ using Content.Shared.CCVar;
|
||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
using Content.Shared.Clothing;
|
using Content.Shared.Clothing;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.IdentityManagement;
|
||||||
|
using Content.Shared.IdentityManagement.Components;
|
||||||
using Content.Shared.Implants;
|
using Content.Shared.Implants;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Lock;
|
using Content.Shared.Lock;
|
||||||
|
|
@ -27,6 +29,7 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
||||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||||
[Dependency] private readonly LockSystem _lock = default!;
|
[Dependency] private readonly LockSystem _lock = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
|
[Dependency] private readonly IdentitySystem _identity = default!;
|
||||||
|
|
||||||
// CCVar.
|
// CCVar.
|
||||||
private int _maxNameLength;
|
private int _maxNameLength;
|
||||||
|
|
@ -34,8 +37,11 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<VoiceMaskComponent, InventoryRelayedEvent<TransformSpeakerNameEvent>>(OnTransformSpeakerName);
|
SubscribeLocalEvent<VoiceMaskComponent, InventoryRelayedEvent<TransformSpeakerNameEvent>>(OnTransformSpeakerNameInventory);
|
||||||
SubscribeLocalEvent<VoiceMaskComponent, ImplantRelayEvent<TransformSpeakerNameEvent>>(OnTransformSpeakerNameImplant);
|
SubscribeLocalEvent<VoiceMaskComponent, ImplantRelayEvent<TransformSpeakerNameEvent>>(OnTransformSpeakerNameImplant);
|
||||||
|
SubscribeLocalEvent<VoiceMaskComponent, ImplantRelayEvent<SeeIdentityAttemptEvent>>(OnSeeIdentityAttemptEvent);
|
||||||
|
SubscribeLocalEvent<VoiceMaskComponent, ImplantImplantedEvent>(OnImplantImplantedEvent);
|
||||||
|
SubscribeLocalEvent<VoiceMaskComponent, ImplantRemovedEvent>(OnImplantRemovedEventEvent);
|
||||||
SubscribeLocalEvent<VoiceMaskComponent, LockToggledEvent>(OnLockToggled);
|
SubscribeLocalEvent<VoiceMaskComponent, LockToggledEvent>(OnLockToggled);
|
||||||
SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskChangeNameMessage>(OnChangeName);
|
SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskChangeNameMessage>(OnChangeName);
|
||||||
SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskChangeVerbMessage>(OnChangeVerb);
|
SubscribeLocalEvent<VoiceMaskComponent, VoiceMaskChangeVerbMessage>(OnChangeVerb);
|
||||||
|
|
@ -45,19 +51,31 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
||||||
Subs.CVar(_cfgManager, CCVars.MaxNameLength, value => _maxNameLength = value, true);
|
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);
|
TransformVoice(entity, args.Args);
|
||||||
args.Args.SpeechVerb = entity.Comp.VoiceMaskSpeechVerb ?? args.Args.SpeechVerb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeltaV - specific for implants
|
|
||||||
private void OnTransformSpeakerNameImplant(Entity<VoiceMaskComponent> entity, ref ImplantRelayEvent<TransformSpeakerNameEvent> args)
|
private void OnTransformSpeakerNameImplant(Entity<VoiceMaskComponent> entity, ref ImplantRelayEvent<TransformSpeakerNameEvent> args)
|
||||||
{
|
{
|
||||||
args.Event.VoiceName = GetCurrentVoiceName(entity);
|
TransformVoice(entity, args.Event);
|
||||||
args.Event.SpeechVerb = entity.Comp.VoiceMaskSpeechVerb ?? args.Event.SpeechVerb;
|
}
|
||||||
|
|
||||||
|
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)
|
private void OnLockToggled(Entity<VoiceMaskComponent> ent, ref LockToggledEvent args)
|
||||||
{
|
{
|
||||||
|
|
@ -89,6 +107,9 @@ public sealed partial class VoiceMaskSystem : EntitySystem
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nameUpdatedEvent = new VoiceMaskNameUpdatedEvent(entity, entity.Comp.VoiceMaskName, message.Name);
|
||||||
|
RaiseLocalEvent(message.Actor, ref nameUpdatedEvent);
|
||||||
|
|
||||||
entity.Comp.VoiceMaskName = message.Name;
|
entity.Comp.VoiceMaskName = message.Name;
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(message.Actor):player} set voice of {ToPrettyString(entity):mask}: {entity.Comp.VoiceMaskName}");
|
_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");
|
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
|
#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
|
// cumulative coverage from each relayed slot
|
||||||
public IdentityBlockerCoverage TotalCoverage = IdentityBlockerCoverage.NONE;
|
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;
|
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
|
return trueName
|
||||||
? TrueName
|
? nameOverride ?? TrueName
|
||||||
: PresumedName ?? ToStringUnknown();
|
: PresumedName ?? ToStringUnknown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using Content.Shared.Humanoid;
|
||||||
using Content.Shared.IdentityManagement.Components;
|
using Content.Shared.IdentityManagement.Components;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
|
using Content.Shared.VoiceMask;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.GameObjects.Components.Localization;
|
using Robust.Shared.GameObjects.Components.Localization;
|
||||||
|
|
@ -53,6 +54,7 @@ public sealed class IdentitySystem : EntitySystem
|
||||||
SubscribeLocalEvent<IdentityComponent, DidUnequipHandEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
SubscribeLocalEvent<IdentityComponent, DidUnequipHandEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
||||||
SubscribeLocalEvent<IdentityComponent, WearerMaskToggledEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
SubscribeLocalEvent<IdentityComponent, WearerMaskToggledEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
||||||
SubscribeLocalEvent<IdentityComponent, EntityRenamedEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
SubscribeLocalEvent<IdentityComponent, EntityRenamedEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
||||||
|
SubscribeLocalEvent<IdentityComponent, VoiceMaskNameUpdatedEvent>((uid, _, _) => QueueIdentityUpdate(uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -197,7 +199,7 @@ public sealed class IdentitySystem : EntitySystem
|
||||||
var ev = new SeeIdentityAttemptEvent();
|
var ev = new SeeIdentityAttemptEvent();
|
||||||
|
|
||||||
RaiseLocalEvent(target, ev);
|
RaiseLocalEvent(target, ev);
|
||||||
return representation.ToStringKnown(!ev.Cancelled);
|
return representation.ToStringKnown(!ev.Cancelled, ev.NameOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.Implants.Components;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
|
|
@ -13,7 +14,8 @@ public abstract partial class SharedSubdermalImplantSystem
|
||||||
SubscribeLocalEvent<ImplantedComponent, MobStateChangedEvent>(RelayToImplantEvent);
|
SubscribeLocalEvent<ImplantedComponent, MobStateChangedEvent>(RelayToImplantEvent);
|
||||||
SubscribeLocalEvent<ImplantedComponent, AfterInteractUsingEvent>(RelayToImplantEvent);
|
SubscribeLocalEvent<ImplantedComponent, AfterInteractUsingEvent>(RelayToImplantEvent);
|
||||||
SubscribeLocalEvent<ImplantedComponent, SuicideEvent>(RelayToImplantEvent);
|
SubscribeLocalEvent<ImplantedComponent, SuicideEvent>(RelayToImplantEvent);
|
||||||
SubscribeLocalEvent<ImplantedComponent, TransformSpeakerNameEvent>(RelayToImplantEvent); // DeltaV
|
SubscribeLocalEvent<ImplantedComponent, TransformSpeakerNameEvent>(RelayToImplantEvent);
|
||||||
|
SubscribeLocalEvent<ImplantedComponent, SeeIdentityAttemptEvent>(RelayToImplantEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,14 @@ public abstract partial class SharedSubdermalImplantSystem : EntitySystem
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public readonly record struct ImplantImplantedEvent
|
public readonly record struct ImplantImplantedEvent
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The implant itself
|
||||||
|
/// </summary>
|
||||||
public readonly EntityUid Implant;
|
public readonly EntityUid Implant;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity getting implanted
|
||||||
|
/// </summary>
|
||||||
public readonly EntityUid Implanted;
|
public readonly EntityUid Implanted;
|
||||||
|
|
||||||
public ImplantImplantedEvent(EntityUid implant, 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-name = Hypopen
|
||||||
uplink-hypopen-desc = A chemical hypospray disguised as a pen, capable of instantly injecting up to 10u of reagents. Starts empty.
|
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-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.
|
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-name = Radio Implanter
|
||||||
uplink-radio-implanter-desc = Implants a Syndicate radio, allowing covert communication without a headset.
|
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
|
# Bundles
|
||||||
uplink-observation-kit-name = Observation Kit
|
uplink-observation-kit-name = Observation Kit
|
||||||
uplink-observation-kit-desc = Includes surveillance camera monitor board and security hud disguised as sunglasses.
|
uplink-observation-kit-desc = Includes surveillance camera monitor board and security hud disguised as sunglasses.
|
||||||
|
|
|
||||||
|
|
@ -477,3 +477,11 @@
|
||||||
icon: Interface/Actions/shop.png
|
icon: Interface/Actions/shop.png
|
||||||
- type: InstantAction
|
- type: InstantAction
|
||||||
event: !type:IntrinsicStoreActionEvent
|
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
|
- CyberPen
|
||||||
- SpyCrewMonitor
|
- SpyCrewMonitor
|
||||||
- BriefcaseThiefBribingBundleFilled
|
- BriefcaseThiefBribingBundleFilled
|
||||||
- ClothingMaskGasVoiceChameleon
|
- VoiceMaskImplanter
|
||||||
#- todo Chameleon Stamp
|
#- todo Chameleon Stamp
|
||||||
|
|
||||||
- type: thiefBackpackSet
|
- type: thiefBackpackSet
|
||||||
|
|
|
||||||
|
|
@ -1579,6 +1579,21 @@
|
||||||
categories:
|
categories:
|
||||||
- UplinkImplants
|
- 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
|
# Wearables
|
||||||
|
|
||||||
|
|
@ -1595,21 +1610,6 @@
|
||||||
categories:
|
categories:
|
||||||
- UplinkWearables
|
- 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
|
- type: listing
|
||||||
id: UplinkHolster
|
id: UplinkHolster
|
||||||
name: uplink-holster-name
|
name: uplink-holster-name
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
- FakeMindShieldImplant
|
- FakeMindShieldImplant
|
||||||
- RadioSyndicateImplant
|
- RadioSyndicateImplant
|
||||||
- ChameleonControllerImplant
|
- ChameleonControllerImplant
|
||||||
|
- VoiceMaskImplant
|
||||||
deimplantFailureDamage:
|
deimplantFailureDamage:
|
||||||
types:
|
types:
|
||||||
Cellular: 50
|
Cellular: 50
|
||||||
|
|
@ -258,6 +259,14 @@
|
||||||
- type: Implanter
|
- type: Implanter
|
||||||
implant: ChameleonControllerImplant
|
implant: ChameleonControllerImplant
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: VoiceMaskImplanter
|
||||||
|
name: voice mask implanter
|
||||||
|
parent: BaseImplantOnlyImplanterSyndi
|
||||||
|
components:
|
||||||
|
- type: Implanter
|
||||||
|
implant: VoiceMaskImplant
|
||||||
|
|
||||||
#Nuclear Operative/Special implanters
|
#Nuclear Operative/Special implanters
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,25 @@
|
||||||
enum.ChameleonControllerKey.Key:
|
enum.ChameleonControllerKey.Key:
|
||||||
type: ChameleonControllerBoundUserInterface
|
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
|
#Nuclear Operative/Special Exclusive implants
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue