Intercoms [crappy radios] (#12898)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Radio.EntitySystems;
|
||||
using Content.Shared.Radio;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Server.Radio.Components;
|
||||
|
||||
@@ -15,10 +16,23 @@ public sealed class RadioMicrophoneComponent : Component
|
||||
[DataField("broadcastChannel", customTypeSerializer: typeof(PrototypeIdSerializer<RadioChannelPrototype>))]
|
||||
public string BroadcastChannel = "Common";
|
||||
|
||||
[ViewVariables, DataField("supportedChannels", customTypeSerializer: typeof(PrototypeIdListSerializer<RadioChannelPrototype>))]
|
||||
public List<string>? SupportedChannels;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("listenRange")]
|
||||
public int ListenRange = 4;
|
||||
|
||||
[DataField("enabled")]
|
||||
public bool Enabled = false;
|
||||
|
||||
[DataField("powerRequired")]
|
||||
public bool PowerRequired = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the speaker must have an
|
||||
/// unobstructed path to the radio to speak
|
||||
/// </summary>
|
||||
[DataField("unobstructedRequired")]
|
||||
public bool UnobstructedRequired = false;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Interaction;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.Radio.Components;
|
||||
using Content.Server.Speech;
|
||||
using Content.Server.Speech.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Radio;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -20,6 +23,7 @@ public sealed class RadioDeviceSystem : EntitySystem
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
[Dependency] private readonly RadioSystem _radio = default!;
|
||||
[Dependency] private readonly InteractionSystem _interaction = default!;
|
||||
|
||||
// Used to prevent a shitter from using a bunch of radios to spam chat.
|
||||
private HashSet<(string, EntityUid)> _recentlySent = new();
|
||||
@@ -31,6 +35,8 @@ public sealed class RadioDeviceSystem : EntitySystem
|
||||
SubscribeLocalEvent<RadioMicrophoneComponent, ExaminedEvent>(OnExamine);
|
||||
SubscribeLocalEvent<RadioMicrophoneComponent, ActivateInWorldEvent>(OnActivateMicrophone);
|
||||
SubscribeLocalEvent<RadioMicrophoneComponent, ListenEvent>(OnListen);
|
||||
SubscribeLocalEvent<RadioMicrophoneComponent, ListenAttemptEvent>(OnAttemptListen);
|
||||
SubscribeLocalEvent<RadioMicrophoneComponent, GetVerbsEvent<Verb>>(OnGetVerbs);
|
||||
|
||||
SubscribeLocalEvent<RadioSpeakerComponent, ComponentInit>(OnSpeakerInit);
|
||||
SubscribeLocalEvent<RadioSpeakerComponent, ActivateInWorldEvent>(OnActivateSpeaker);
|
||||
@@ -80,6 +86,9 @@ public sealed class RadioDeviceSystem : EntitySystem
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
if (component.PowerRequired && !this.IsPowered(uid, EntityManager))
|
||||
return;
|
||||
|
||||
component.Enabled = !component.Enabled;
|
||||
|
||||
if (!quiet)
|
||||
@@ -95,6 +104,39 @@ public sealed class RadioDeviceSystem : EntitySystem
|
||||
RemCompDeferred<ActiveListenerComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnGetVerbs(EntityUid uid, RadioMicrophoneComponent component, GetVerbsEvent<Verb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || args.Hands == null)
|
||||
return;
|
||||
|
||||
if (component.SupportedChannels == null || component.SupportedChannels.Count <= 1)
|
||||
return;
|
||||
|
||||
if (component.PowerRequired && !this.IsPowered(uid, EntityManager))
|
||||
return;
|
||||
|
||||
foreach (var channel in component.SupportedChannels)
|
||||
{
|
||||
var proto = _protoMan.Index<RadioChannelPrototype>(channel);
|
||||
|
||||
var v = new Verb
|
||||
{
|
||||
Text = proto.LocalizedName,
|
||||
Priority = 1,
|
||||
Category = VerbCategory.ChannelSelect,
|
||||
Disabled = component.BroadcastChannel == channel,
|
||||
DoContactInteraction = true,
|
||||
Act = () =>
|
||||
{
|
||||
component.BroadcastChannel = channel;
|
||||
_popup.PopupEntity(Loc.GetString("handheld-radio-component-channel-set",
|
||||
("channel", channel)), uid, Filter.Entities(args.User));
|
||||
}
|
||||
};
|
||||
args.Verbs.Add(v);
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleRadioSpeaker(EntityUid uid, EntityUid user, bool quiet = false, RadioSpeakerComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
@@ -121,8 +163,9 @@ public sealed class RadioDeviceSystem : EntitySystem
|
||||
if (!args.IsInDetailsRange)
|
||||
return;
|
||||
|
||||
var freq = _protoMan.Index<RadioChannelPrototype>(component.BroadcastChannel).Frequency;
|
||||
args.PushMarkup(Loc.GetString("handheld-radio-component-on-examine", ("frequency", freq)));
|
||||
var proto = _protoMan.Index<RadioChannelPrototype>(component.BroadcastChannel);
|
||||
args.PushMarkup(Loc.GetString("handheld-radio-component-on-examine", ("frequency", proto.Frequency)));
|
||||
args.PushMarkup(Loc.GetString("handheld-radio-component-chennel-examine", ("channel", proto.LocalizedName)));
|
||||
}
|
||||
|
||||
private void OnListen(EntityUid uid, RadioMicrophoneComponent component, ListenEvent args)
|
||||
@@ -134,6 +177,15 @@ public sealed class RadioDeviceSystem : EntitySystem
|
||||
_radio.SendRadioMessage(args.Source, args.Message, _protoMan.Index<RadioChannelPrototype>(component.BroadcastChannel));
|
||||
}
|
||||
|
||||
private void OnAttemptListen(EntityUid uid, RadioMicrophoneComponent component, ListenAttemptEvent args)
|
||||
{
|
||||
if (component.PowerRequired && !this.IsPowered(uid, EntityManager)
|
||||
|| component.UnobstructedRequired && !_interaction.InRangeUnobstructed(args.Source, uid, 0))
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, RadioReceiveEvent args)
|
||||
{
|
||||
var nameEv = new TransformSpeakerNameEvent(args.Source, Name(args.Source));
|
||||
|
||||
@@ -76,6 +76,8 @@ namespace Content.Shared.Verbs
|
||||
public static readonly VerbCategory InstrumentStyle =
|
||||
new("verb-categories-instrument-style", null);
|
||||
|
||||
public static readonly VerbCategory ChannelSelect = new("verb-categories-channel-select", null);
|
||||
|
||||
public static readonly VerbCategory SetSensor = new("verb-categories-set-sensor", null);
|
||||
|
||||
public static readonly VerbCategory Lever = new("verb-categories-lever", null);
|
||||
|
||||
@@ -2,3 +2,5 @@ handheld-radio-component-on-use = The radio is now {$radioState}.
|
||||
handheld-radio-component-on-examine = It's set to broadcast over the {$frequency} frequency.
|
||||
handheld-radio-component-on-state = on
|
||||
handheld-radio-component-off-state = off
|
||||
handheld-radio-component-channel-set = Channel set to {$channel}
|
||||
handheld-radio-component-chennel-examine = The current channel is {$channel}.
|
||||
@@ -22,6 +22,7 @@ verb-categories-tricks = Tricks
|
||||
verb-categories-transfer = Set Transfer Amount
|
||||
verb-categories-split = Split
|
||||
verb-categories-instrument-style = Instrument Style
|
||||
verb-categories-channel-select = Channels
|
||||
verb-categories-set-sensor = Sensor
|
||||
verb-categories-timer = Set Delay
|
||||
verb-categories-lever = Lever
|
||||
|
||||
@@ -292,6 +292,7 @@
|
||||
requiredTechnologies:
|
||||
- BasicResearch
|
||||
unlockedRecipes:
|
||||
- IntercomElectronics
|
||||
- ConveyorBeltAssembly
|
||||
- FlashlightLantern
|
||||
- FireExtinguisher
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
- type: entity
|
||||
id: IntercomElectronics
|
||||
parent: BaseElectronics
|
||||
name: intercom electronics
|
||||
description: An electronics board used in intercoms
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/module.rsi
|
||||
state: id_mod
|
||||
- type: Tag
|
||||
tags:
|
||||
- DroneUsable
|
||||
- IntercomElectronics
|
||||
|
||||
@@ -205,6 +205,7 @@
|
||||
- APCElectronics
|
||||
- AirAlarmElectronics
|
||||
- FireAlarmElectronics
|
||||
- IntercomElectronics
|
||||
- MailingUnitElectronics
|
||||
- Bucket
|
||||
- MopItem
|
||||
@@ -256,6 +257,7 @@
|
||||
- AirAlarmElectronics
|
||||
- FireAlarmElectronics
|
||||
- MailingUnitElectronics
|
||||
- IntercomElectronics
|
||||
- SMESMachineCircuitboard
|
||||
- SubstationMachineCircuitboard
|
||||
- ThermomachineFreezerMachineCircuitBoard
|
||||
|
||||
189
Resources/Prototypes/Entities/Structures/Wallmounts/intercom.yml
Normal file
189
Resources/Prototypes/Entities/Structures/Wallmounts/intercom.yml
Normal file
@@ -0,0 +1,189 @@
|
||||
- type: entity
|
||||
id: Intercom
|
||||
name: intercom
|
||||
description: An intercom. For when the station just needs to know something.
|
||||
components:
|
||||
- type: WallMount
|
||||
- type: ApcPowerReceiver
|
||||
- type: Electrified
|
||||
enabled: false
|
||||
usesApcPower: true
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
- type: ExtensionCableReceiver
|
||||
- type: Clickable
|
||||
- type: InteractionOutline
|
||||
- type: Appearance
|
||||
- type: Sprite
|
||||
sprite: Structures/Wallmounts/intercom.rsi
|
||||
layers:
|
||||
- state: base
|
||||
- state: unshaded
|
||||
map: ["enum.PowerDeviceVisualLayers.Powered"]
|
||||
shader: unshaded
|
||||
- type: Transform
|
||||
noRot: true
|
||||
anchored: true
|
||||
- type: Wires
|
||||
BoardName: "Intercom"
|
||||
LayoutId: Intercom
|
||||
- type: Construction
|
||||
graph: Intercom
|
||||
node: intercom
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
damageModifierSet: Metallic
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 100
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
- !type:PlaySoundBehavior
|
||||
sound:
|
||||
path: /Audio/Effects/metalbreak.ogg
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.PowerDeviceVisuals.Powered:
|
||||
enum.PowerDeviceVisualLayers.Powered:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
snap:
|
||||
- Wallmount
|
||||
|
||||
- type: entity
|
||||
id: IntercomAssesmbly
|
||||
name: intercom assembly
|
||||
description: An intercom. It doesn't seem very helpful right now.
|
||||
components:
|
||||
- type: WallMount
|
||||
- type: Clickable
|
||||
- type: InteractionOutline
|
||||
- type: Sprite
|
||||
sprite: Structures/Wallmounts/intercom.rsi
|
||||
state: build
|
||||
- type: Construction
|
||||
graph: Intercom
|
||||
node: assembly
|
||||
- type: Transform
|
||||
anchored: true
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
snap:
|
||||
- Wallmount
|
||||
|
||||
- type: entity
|
||||
id: IntercomCommand
|
||||
parent: Intercom
|
||||
suffix: Command
|
||||
components:
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
supportedChannels:
|
||||
- Common
|
||||
- Command
|
||||
|
||||
- type: entity
|
||||
id: IntercomEngineering
|
||||
parent: Intercom
|
||||
suffix: Engineering
|
||||
components:
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
supportedChannels:
|
||||
- Common
|
||||
- Engineering
|
||||
|
||||
- type: entity
|
||||
id: IntercomMedical
|
||||
parent: Intercom
|
||||
suffix: Medical
|
||||
components:
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
supportedChannels:
|
||||
- Common
|
||||
- Medical
|
||||
|
||||
- type: entity
|
||||
id: IntercomScience
|
||||
parent: Intercom
|
||||
suffix: Science
|
||||
components:
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
supportedChannels:
|
||||
- Common
|
||||
- Science
|
||||
|
||||
- type: entity
|
||||
id: IntercomSecurity
|
||||
parent: Intercom
|
||||
suffix: Security
|
||||
components:
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
supportedChannels:
|
||||
- Common
|
||||
- Security
|
||||
|
||||
- type: entity
|
||||
id: IntercomService
|
||||
parent: Intercom
|
||||
suffix: Service
|
||||
components:
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
supportedChannels:
|
||||
- Common
|
||||
- Service
|
||||
|
||||
- type: entity
|
||||
id: IntercomSupply
|
||||
parent: Intercom
|
||||
suffix: Supply
|
||||
components:
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
supportedChannels:
|
||||
- Common
|
||||
- Supply
|
||||
|
||||
- type: entity
|
||||
id: IntercomAll
|
||||
parent: Intercom
|
||||
suffix: All
|
||||
components:
|
||||
- type: RadioMicrophone
|
||||
powerRequired: true
|
||||
unobstructedRequired: true
|
||||
listenRange: 2
|
||||
supportedChannels:
|
||||
- Common
|
||||
- Command
|
||||
- Engineering
|
||||
- Medical
|
||||
- Science
|
||||
- Security
|
||||
- Service
|
||||
- Supply
|
||||
@@ -0,0 +1,72 @@
|
||||
- type: constructionGraph
|
||||
id: Intercom
|
||||
start: start
|
||||
graph:
|
||||
- node: start
|
||||
edges:
|
||||
- to: assembly
|
||||
steps:
|
||||
- material: Steel
|
||||
amount: 2
|
||||
doAfter: 2.0
|
||||
|
||||
- node: assembly
|
||||
entity: IntercomAssesmbly
|
||||
edges:
|
||||
- to: wired
|
||||
steps:
|
||||
- material: Cable
|
||||
amount: 2
|
||||
doAfter: 1
|
||||
- to: start
|
||||
completed:
|
||||
- !type:GivePrototype
|
||||
prototype: SheetSteel1
|
||||
amount: 2
|
||||
- !type:DeleteEntity {}
|
||||
steps:
|
||||
- tool: Welding
|
||||
doAfter: 2
|
||||
|
||||
- node: wired
|
||||
entity: IntercomAssesmbly
|
||||
edges:
|
||||
- to: electronics
|
||||
steps:
|
||||
- tag: IntercomElectronics
|
||||
store: board
|
||||
name: "intercom electronics"
|
||||
icon:
|
||||
sprite: "Objects/Misc/module.rsi"
|
||||
state: "id_mod"
|
||||
doAfter: 1
|
||||
- to: assembly
|
||||
completed:
|
||||
- !type:GivePrototype
|
||||
prototype: CableApcStack1
|
||||
amount: 2
|
||||
steps:
|
||||
- tool: Cutting
|
||||
doAfter: 1
|
||||
|
||||
- node: electronics
|
||||
edges:
|
||||
- to: intercom
|
||||
steps:
|
||||
- tool: Screwing
|
||||
doAfter: 2
|
||||
|
||||
- node: intercom
|
||||
entity: Intercom #TODO: make this work with encryption keys
|
||||
edges:
|
||||
- to: wired
|
||||
conditions:
|
||||
- !type:AllWiresCut {}
|
||||
- !type:WirePanel {}
|
||||
- !type:ContainerNotEmpty
|
||||
container: board
|
||||
completed:
|
||||
- !type:EmptyAllContainers {}
|
||||
steps:
|
||||
- tool: Prying
|
||||
doAfter: 1
|
||||
@@ -580,3 +580,22 @@
|
||||
state: off
|
||||
conditions:
|
||||
- !type:TileNotBlocked {}
|
||||
|
||||
# INTERCOM
|
||||
- type: construction
|
||||
name: intercom
|
||||
id: IntercomAssesmbly
|
||||
graph: Intercom
|
||||
startNode: start
|
||||
targetNode: intercom
|
||||
category: construction-category-structures
|
||||
description: An intercom. For when the station just needs to know something.
|
||||
icon:
|
||||
sprite: Structures/Wallmounts/intercom.rsi
|
||||
state: base
|
||||
placementMode: SnapgridCenter
|
||||
objectType: Structure
|
||||
canRotate: true
|
||||
canBuildInImpassable: true
|
||||
conditions:
|
||||
- !type:WallmountCondition {}
|
||||
@@ -34,6 +34,15 @@
|
||||
Steel: 50
|
||||
Plastic: 50
|
||||
|
||||
- type: latheRecipe
|
||||
id: IntercomElectronics
|
||||
icon: { sprite: Objects/Misc/module.rsi, state: id_mod }
|
||||
result: IntercomElectronics
|
||||
completetime: 2
|
||||
materials:
|
||||
Steel: 50
|
||||
Plastic: 50
|
||||
|
||||
- type: latheRecipe
|
||||
id: FireAlarmElectronics
|
||||
icon: { sprite: Objects/Misc/module.rsi, state: door_electronics }
|
||||
|
||||
@@ -291,6 +291,9 @@
|
||||
- type: Tag
|
||||
id: Ingot
|
||||
|
||||
- type: Tag
|
||||
id: IntercomElectronics
|
||||
|
||||
- type: Tag
|
||||
id: JawsOfLife
|
||||
|
||||
|
||||
BIN
Resources/Textures/Structures/Wallmounts/intercom.rsi/base.png
Normal file
BIN
Resources/Textures/Structures/Wallmounts/intercom.rsi/base.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Resources/Textures/Structures/Wallmounts/intercom.rsi/build.png
Normal file
BIN
Resources/Textures/Structures/Wallmounts/intercom.rsi/build.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from /tg/station at https://github.com/tgstation/tgstation/commit/6bfe3b2e4fcbcdac9159dc4f0327a82ddf05ba7bi",
|
||||
"states": [
|
||||
{
|
||||
"name": "base",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "build",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "unshaded",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 382 B |
Reference in New Issue
Block a user