Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Content.Server/Radio/EntitySystems/RadioSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
using Robust.Shared.Random;
using Robust.Shared.Replays;
using Robust.Shared.Utility;
// ES START
using Content.Server._ES.Radio;
// ES END

namespace Content.Server.Radio.EntitySystems;

Expand All @@ -28,6 +31,9 @@ public sealed class RadioSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ChatSystem _chat = default!;
// ES START
[Dependency] private readonly ESRadioSystem _esRadio = default!;
// ES END

// set used to prevent radio feedback loops.
private readonly HashSet<string> _messages = new();
Expand Down Expand Up @@ -145,6 +151,26 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann
RaiseLocalEvent(receiver, ref attemptEv);
if (attemptEv.Cancelled)
continue;
// ES START
var distortedMessage = _esRadio.DistortMessage(radioSource, receiver, FormattedMessage.EscapeText(message));
var distortedWrappedMessage = Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap",
("color", channel.Color),
("fontType", speech.FontId),
("fontSize", speech.FontSize),
("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))),
("channel", $"\\[{channel.LocalizedName}\\]"),
("name", name),
("message", distortedMessage));

chat = new ChatMessage(
ChatChannel.Radio,
distortedMessage,
distortedWrappedMessage,
NetEntity.Invalid,
null);
chatMsg = new MsgChatMessage { Message = chat };
ev = new RadioReceiveEvent(message, messageSource, channel, radioSource, chatMsg);
// ES END

// send the message
RaiseLocalEvent(receiver, ref ev);
Expand Down
18 changes: 18 additions & 0 deletions Content.Server/_ES/Radio/Components/ESRadioFalloffComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Content.Shared.Dataset;
using Robust.Shared.Prototypes;

namespace Content.Server._ES.Radio.Components;

[RegisterComponent]
[Access(typeof(ESRadioSystem))]
public sealed partial class ESRadioFalloffComponent : Component
{
[DataField]
public float MaxClearSendDistance = 15f;

[DataField]
public float MaxSendDistance = 50f;

[DataField]
public ProtoId<LocalizedDatasetPrototype> FalloffInterjectionDataset = "ESRadioFalloffInterjections";
}
85 changes: 85 additions & 0 deletions Content.Server/_ES/Radio/ESRadioSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System.Text;
using Content.Server._ES.Radio.Components;
using Content.Server.Radio;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;

namespace Content.Server._ES.Radio;

public sealed class ESRadioSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly TransformSystem _transform = default!;

/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<ESRadioFalloffComponent, RadioReceiveAttemptEvent>(OnFalloffReceiveAttempt);
}

private void OnFalloffReceiveAttempt(Entity<ESRadioFalloffComponent> ent, ref RadioReceiveAttemptEvent args)
{
if (args.Cancelled)
return;

if (_transform.InRange(args.RadioSource, args.RadioReceiver, ent.Comp.MaxSendDistance))
return;
args.Cancelled = true;
}

public string DistortMessage(Entity<ESRadioFalloffComponent?> receiver, EntityUid sender, string message)
{
var msg = message;

if (!Resolve(receiver, ref receiver.Comp, false))
return msg;

var receiverXform = Transform(receiver);
var senderXform = Transform(sender);

if (!receiverXform.Coordinates.TryDistance(EntityManager, _transform, senderXform.Coordinates, out var distance))
return msg;

var distortion = (distance - receiver.Comp.MaxClearSendDistance) / (receiver.Comp.MaxSendDistance - receiver.Comp.MaxClearSendDistance);
if (distortion < 0) // only distort if we're in the range.
return msg;

var muffleChance = MathHelper.Lerp(0.05f, 0.4f, distortion);

var outputMsg = new StringBuilder();
foreach (var letter in msg.AsSpan())
{
if (!char.IsLetterOrDigit(letter))
{
outputMsg.Append(letter);
continue;
}

if (_random.Prob(muffleChance))
outputMsg.Append('~');
else
outputMsg.Append(letter);
}

msg = outputMsg.ToString();
outputMsg.Clear();

var interjectionChance = Math.Clamp(MathHelper.Lerp(-0.1f, 0.5f, distortion), 0, 1);
var interjection = _prototypeManager.Index(receiver.Comp.FalloffInterjectionDataset);
foreach (var word in msg.Split(' '))
{
if (_random.Prob(interjectionChance))
{
outputMsg.Append(Loc.GetString(_random.Pick(interjection.Values)));
outputMsg.Append(' ');
}

outputMsg.Append(word);
outputMsg.Append(' ');
}

return outputMsg.ToString().TrimEnd();
}
}
5 changes: 5 additions & 0 deletions Resources/Locale/en-US/_ES/radio/falloff.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
es-radio-falloff-interjection-1 = [italic]--BZZT--[/italic]
es-radio-falloff-interjection-2 = [italic]--KRSSH--[/italic]
es-radio-falloff-interjection-3 = [italic]--CRACKLE--[/italic]
es-radio-falloff-interjection-4 = [italic]--PSSSHT--[/italic]
es-radio-falloff-interjection-5 = [italic]--PZZAT--[/italic]
3 changes: 3 additions & 0 deletions Resources/Prototypes/Entities/Clothing/Ears/headsets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
- type: GuideHelp
guides:
- Radio
# ES START
- type: ESRadioFalloff
# ES END

- type: entity
parent: ClothingHeadset
Expand Down
5 changes: 5 additions & 0 deletions Resources/Prototypes/_ES/Datasets/radio.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- type: localizedDataset
id: ESRadioFalloffInterjections
values:
prefix: es-radio-falloff-interjection-
count: 5
Loading