Add radio jammer (#14369)

This commit is contained in:
Slava0135
2023-04-14 22:50:19 +03:00
committed by GitHub
parent 779100484f
commit 7886d27dda
12 changed files with 214 additions and 42 deletions

View File

@@ -0,0 +1,12 @@
using Content.Server.Radio.EntitySystems;
namespace Content.Server.Radio.Components;
/// <summary>
/// Prevents all radio in range from sending messages
/// </summary>
[RegisterComponent]
[Access(typeof(JammerSystem))]
public sealed class ActiveRadioJammerComponent : Component
{
}

View File

@@ -0,0 +1,20 @@
using Content.Server.Radio.EntitySystems;
namespace Content.Server.Radio.Components;
/// <summary>
/// When activated (<see cref="ActiveRadioJammerComponent"/>) prevents from sending messages in range
/// </summary>
[RegisterComponent]
[Access(typeof(JammerSystem))]
public sealed class RadioJammerComponent : Component
{
[DataField("range"), ViewVariables(VVAccess.ReadWrite)]
public float Range = 8f;
/// <summary>
/// Power usage per second when enabled
/// </summary>
[DataField("wattage"), ViewVariables(VVAccess.ReadWrite)]
public float Wattage = 6f;
}

View File

@@ -0,0 +1,91 @@
using Content.Server.Popups;
using Content.Server.PowerCell;
using Content.Server.Radio.Components;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.PowerCell.Components;
namespace Content.Server.Radio.EntitySystems;
public sealed class JammerSystem : EntitySystem
{
[Dependency] private readonly PowerCellSystem _powerCell = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RadioJammerComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<ActiveRadioJammerComponent, PowerCellChangedEvent>(OnPowerCellChanged);
SubscribeLocalEvent<RadioJammerComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<RadioSendAttemptEvent>(OnRadioSendAttempt);
}
public override void Update(float frameTime)
{
var query = AllEntityQuery<ActiveRadioJammerComponent, RadioJammerComponent>();
while (query.MoveNext(out var uid, out var _, out var jam))
{
if (_powerCell.TryGetBatteryFromSlot(uid, out var battery) &&
!battery.TryUseCharge(jam.Wattage * frameTime))
{
RemComp<ActiveRadioJammerComponent>(uid);
}
}
}
private void OnActivate(EntityUid uid, RadioJammerComponent comp, ActivateInWorldEvent args)
{
var activated = !HasComp<ActiveRadioJammerComponent>(uid) &&
_powerCell.TryGetBatteryFromSlot(uid, out var battery) &&
battery.CurrentCharge > comp.Wattage;
if (activated)
{
EnsureComp<ActiveRadioJammerComponent>(uid);
}
else
{
RemComp<ActiveRadioJammerComponent>(uid);
}
var state = Loc.GetString(activated ? "radio-jammer-component-on-state" : "radio-jammer-component-off-state");
var message = Loc.GetString("radio-jammer-component-on-use", ("state", state));
_popup.PopupEntity(message, args.User, args.User);
args.Handled = true;
}
private void OnPowerCellChanged(EntityUid uid, ActiveRadioJammerComponent comp, PowerCellChangedEvent args)
{
if (args.Ejected)
RemComp<ActiveRadioJammerComponent>(uid);
}
private void OnExamine(EntityUid uid, RadioJammerComponent comp, ExaminedEvent args)
{
if (args.IsInDetailsRange)
{
var msg = HasComp<ActiveRadioJammerComponent>(uid)
? Loc.GetString("radio-jammer-component-examine-on-state")
: Loc.GetString("radio-jammer-component-examine-off-state");
args.PushMarkup(msg);
if (_powerCell.TryGetBatteryFromSlot(uid, out var battery))
args.PushMarkup(Loc.GetString("radio-jammer-component-charge",
("charge", (int) ((battery.CurrentCharge / battery.MaxCharge) * 100))));
}
}
private void OnRadioSendAttempt(ref RadioSendAttemptEvent args)
{
var source = Transform(args.RadioSource).Coordinates;
var query = AllEntityQuery<ActiveRadioJammerComponent, RadioJammerComponent, TransformComponent>();
while (query.MoveNext(out _, out _, out var jam, out var transform))
{
if (source.InRange(EntityManager, _transform, transform.Coordinates, jam.Range))
{
args.Cancelled = true;
return;
}
}
}
}

View File

@@ -78,6 +78,10 @@ public sealed class RadioSystem : EntitySystem
var chatMsg = new MsgChatMessage { Message = chat }; var chatMsg = new MsgChatMessage { Message = chat };
var ev = new RadioReceiveEvent(message, messageSource, channel, chatMsg); var ev = new RadioReceiveEvent(message, messageSource, channel, chatMsg);
var sendAttemptEv = new RadioSendAttemptEvent(channel, radioSource);
RaiseLocalEvent(ref sendAttemptEv);
var canSend = !sendAttemptEv.Cancelled;
var sourceMapId = Transform(radioSource).MapID; var sourceMapId = Transform(radioSource).MapID;
var hasActiveServer = HasActiveServer(sourceMapId, channel.ID); var hasActiveServer = HasActiveServer(sourceMapId, channel.ID);
var hasMicro = HasComp<RadioMicrophoneComponent>(radioSource); var hasMicro = HasComp<RadioMicrophoneComponent>(radioSource);
@@ -85,7 +89,7 @@ public sealed class RadioSystem : EntitySystem
var speakerQuery = GetEntityQuery<RadioSpeakerComponent>(); var speakerQuery = GetEntityQuery<RadioSpeakerComponent>();
var radioQuery = AllEntityQuery<ActiveRadioComponent, TransformComponent>(); var radioQuery = AllEntityQuery<ActiveRadioComponent, TransformComponent>();
var sentAtLeastOnce = false; var sentAtLeastOnce = false;
while (radioQuery.MoveNext(out var receiver, out var radio, out var transform)) while (canSend && radioQuery.MoveNext(out var receiver, out var radio, out var transform))
{ {
if (!radio.Channels.Contains(channel.ID)) if (!radio.Channels.Contains(channel.ID))
continue; continue;

View File

@@ -0,0 +1,30 @@
using Content.Shared.Chat;
using Content.Shared.Radio;
namespace Content.Server.Radio;
[ByRefEvent]
public readonly record struct RadioReceiveEvent(string Message, EntityUid MessageSource, RadioChannelPrototype Channel, MsgChatMessage ChatMsg);
/// <summary>
/// Use this event to cancel sending message per receiver
/// </summary>
[ByRefEvent]
public record struct RadioReceiveAttemptEvent(RadioChannelPrototype Channel, EntityUid RadioSource, EntityUid RadioReceiver)
{
public readonly RadioChannelPrototype Channel = Channel;
public readonly EntityUid RadioSource = RadioSource;
public readonly EntityUid RadioReceiver = RadioReceiver;
public bool Cancelled = false;
}
/// <summary>
/// Use this event to cancel sending message to every receiver
/// </summary>
[ByRefEvent]
public record struct RadioSendAttemptEvent(RadioChannelPrototype Channel, EntityUid RadioSource)
{
public readonly RadioChannelPrototype Channel = Channel;
public readonly EntityUid RadioSource = RadioSource;
public bool Cancelled = false;
}

View File

@@ -1,41 +0,0 @@
using Content.Shared.Chat;
using Content.Shared.Radio;
namespace Content.Server.Radio;
[ByRefEvent]
public struct RadioReceiveEvent
{
public readonly string Message;
public readonly EntityUid MessageSource;
public readonly RadioChannelPrototype Channel;
public readonly MsgChatMessage ChatMsg;
public RadioReceiveEvent(string message, EntityUid messageSource, RadioChannelPrototype channel, MsgChatMessage chatMsg)
{
Message = message;
MessageSource = messageSource;
Channel = channel;
ChatMsg = chatMsg;
}
}
/// <summary>
/// Use this event to cancel sending messages by doing various checks (e.g. range)
/// </summary>
[ByRefEvent]
public struct RadioReceiveAttemptEvent
{
public readonly RadioChannelPrototype Channel;
public readonly EntityUid RadioSource;
public readonly EntityUid RadioReceiver;
public bool Cancelled = false;
public RadioReceiveAttemptEvent(RadioChannelPrototype channel, EntityUid radioSource, EntityUid radioReceiver)
{
Channel = channel;
RadioSource = radioSource;
RadioReceiver = radioReceiver;
}
}

View File

@@ -0,0 +1,7 @@
radio-jammer-component-on-use = The jammer is now {$state}.
radio-jammer-component-on-state = on
radio-jammer-component-off-state = off
radio-jammer-component-examine-on-state = The light is currently [color=darkgreen]on[/color].
radio-jammer-component-examine-off-state = The light is currently [color=darkred]off[/color].
radio-jammer-component-charge = The battery is [color=yellow]{$charge}%[/color] full.

View File

@@ -93,6 +93,9 @@ uplink-hypopen-desc = A chemical hypospray disguised as a pen, capable of instan
uplink-voice-mask-name = Voice Mask 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-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-radio-jammer-name = Radio Jammer
uplink-radio-jammer-desc = This device will disrupt any nearby outgoing radio communication when activated.
# Implants # Implants
uplink-storage-implanter-name = Storage Implanter uplink-storage-implanter-name = Storage Implanter
uplink-storage-implanter-desc = Hide goodies inside of yourself with new bluespace technology! uplink-storage-implanter-desc = Hide goodies inside of yourself with new bluespace technology!

View File

@@ -332,6 +332,16 @@
categories: categories:
- UplinkUtility - UplinkUtility
- type: listing
id: UplinkRadioJammer
name: uplink-radio-jammer-name
description: uplink-radio-jammer-desc
productEntity: RadioJammer
cost:
Telecrystal: 5
categories:
- UplinkUtility
# Implants # Implants
- type: listing - type: listing

View File

@@ -0,0 +1,21 @@
- type: entity
name: radio jammer
parent: BaseItem
id: RadioJammer
description: This device will disrupt any nearby outgoing radio communication when activated.
components:
- type: Sprite
netsync: false
sprite: Objects/Devices/jammer.rsi
state: jammer
- type: RadioJammer
- type: PowerCellSlot
cellSlotId: cell_slot
- type: ContainerContainer
containers:
cell_slot: !type:ContainerSlot
- type: ItemSlots
slots:
cell_slot:
name: power-cell-slot-component-slot-name-default
startingItem: PowerCellMedium

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

View File

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