Add voice trigger for modular grenades (#11449)

This commit is contained in:
themias
2022-10-16 13:44:50 -04:00
committed by GitHub
parent 6e108bd400
commit b567c34e92
10 changed files with 191 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
using Content.Shared.Interaction;
using Content.Server.Radio.Components;
using Content.Shared.Radio;
using System.Text.RegularExpressions;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Radio.EntitySystems;
using System;
namespace Content.Server.Explosion.Components
{
/// <summary>
/// Sends a trigger when the keyphrase is heard
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(IListen))]
public sealed class TriggerOnVoiceComponent : Component, IListen
{
private SharedInteractionSystem _sharedInteractionSystem = default!;
private TriggerSystem _triggerSystem = default!;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("keyPhrase")]
public string? KeyPhrase;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("listenRange")]
public int ListenRange { get; private set; } = 4;
[ViewVariables]
public bool IsRecording = false;
[ViewVariables]
[DataField("minLength")]
public int MinLength = 3;
[ViewVariables]
[DataField("maxLength")]
public int MaxLength = 50;
/// <summary>
/// Displays 'recorded' popup only for the one who activated
/// it in order to allow for stealthily recording others
/// </summary>
[ViewVariables]
public EntityUid Activator;
protected override void Initialize()
{
base.Initialize();
_sharedInteractionSystem = EntitySystem.Get<SharedInteractionSystem>();
_triggerSystem = EntitySystem.Get<TriggerSystem>();
}
bool IListen.CanListen(string message, EntityUid source, RadioChannelPrototype? channelPrototype)
{
//will hear standard speech and radio messages originating nearby but not independant whispers
return _sharedInteractionSystem.InRangeUnobstructed(Owner, source, range: ListenRange);
}
void IListen.Listen(string message, EntityUid speaker, RadioChannelPrototype? channel)
{
message = message.Trim();
if (IsRecording && message.Length >= MinLength && message.Length <= MaxLength)
{
KeyPhrase = message;
_triggerSystem.ToggleRecord(this, Activator, true);
}
else if (KeyPhrase != null && message.Contains(KeyPhrase, StringComparison.InvariantCultureIgnoreCase))
{
_triggerSystem.Trigger(Owner, speaker);
}
}
}
}

View File

@@ -0,0 +1,61 @@
using Content.Server.Explosion.Components;
using Content.Server.Nutrition.Components;
using Content.Shared.Examine;
using Content.Shared.Interaction.Events;
using Content.Shared.Popups;
using Content.Shared.Verbs;
using Microsoft.CodeAnalysis.Options;
using Robust.Shared.GameObjects;
using Robust.Shared.Physics.Events;
using Robust.Shared.Player;
using Robust.Shared.Utility;
namespace Content.Server.Explosion.EntitySystems
{
public sealed partial class TriggerSystem
{
private void InitializeVoice()
{
SubscribeLocalEvent<TriggerOnVoiceComponent, ExaminedEvent>(OnVoiceExamine);
SubscribeLocalEvent<TriggerOnVoiceComponent, GetVerbsEvent<AlternativeVerb>>(OnVoiceGetAltVerbs);
}
private void OnVoiceGetAltVerbs(EntityUid uid, TriggerOnVoiceComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
args.Verbs.Add(new AlternativeVerb()
{
Text = Loc.GetString("verb-trigger-voice-record"),
Act = () => ToggleRecord(component, args.User),
Priority = 1
});
}
public void ToggleRecord(TriggerOnVoiceComponent component, EntityUid user, bool recorded = false)
{
component.IsRecording ^= true;
if (recorded) //recording success popup
{
_popupSystem.PopupEntity(Loc.GetString("popup-trigger-voice-recorded"), component.Owner, Filter.Entities(user));
}
else if (component.IsRecording) //recording start popup
{
component.Activator = user;
_popupSystem.PopupEntity(Loc.GetString("popup-trigger-voice-start-recording"), component.Owner, Filter.Entities(user));
}
else //recording stopped manually popup
{
_popupSystem.PopupEntity(Loc.GetString("popup-trigger-voice-stop-recording"), component.Owner, Filter.Entities(user));
}
}
private void OnVoiceExamine(EntityUid uid, TriggerOnVoiceComponent component, ExaminedEvent args)
{
if (args.IsInDetailsRange)
args.PushText(Loc.GetString("examine-trigger-voice", ("keyphrase", component.KeyPhrase?? Loc.GetString("trigger-voice-uninitialized"))));
}
}
}

View File

@@ -57,6 +57,7 @@ namespace Content.Server.Explosion.EntitySystems
InitializeOnUse();
InitializeSignal();
InitializeTimedCollide();
InitializeVoice();
SubscribeLocalEvent<TriggerOnCollideComponent, StartCollideEvent>(OnTriggerCollide);
SubscribeLocalEvent<TriggerOnActivateComponent, ActivateInWorldEvent>(OnActivate);

View File

@@ -0,0 +1,8 @@
examine-trigger-voice = The display reads "{$keyphrase}"
trigger-voice-uninitialized = Uninitialized...
verb-trigger-voice-record = Record
popup-trigger-voice-start-recording = Started recording
popup-trigger-voice-stop-recording = Stopped recording
popup-trigger-voice-recorded = Recorded

View File

@@ -319,6 +319,7 @@
- GeneratorPlasmaMachineCircuitboard
- Signaller
- SignalTrigger
- VoiceTrigger
- type: technology
name: technologies-compact-power-technology

View File

@@ -43,3 +43,18 @@
- type: SignalReceiver
- type: StaticPrice
price: 40
- type: entity
parent: BaseItem
id: VoiceTrigger
name: voice trigger
description: Adds a machine link that is triggered by vocal keywords
components:
- type: Sprite
sprite: Objects/Devices/voice.rsi
state: voice
- type: PayloadTrigger
components:
- type: TriggerOnVoice
- type: StaticPrice
price: 40

View File

@@ -217,6 +217,7 @@
- FlashPayload
- Signaller
- SignalTrigger
- VoiceTrigger
- PowerCellSmall
- PowerCellMedium
- PowerCellHigh

View File

@@ -20,6 +20,17 @@
Steel: 300
Plastic: 200
- type: latheRecipe
id: VoiceTrigger
icon:
sprite: Objects/Devices/voice.rsi
state: voice
result: VoiceTrigger
completetime: 2
materials:
Steel: 300
Plastic: 200
- type: latheRecipe
id: ChemicalPayload
icon:

View File

@@ -0,0 +1,17 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c71e03214013191760284361aaff7af90505aaab",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "voice",
"directions": 1
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B