Skip to content

feat(radio): add AN/PRC-117G comms system#1306

Open
rokudara-sen wants to merge 1 commit into
AU-14:masterfrom
rokudara-sen:feature/new-comms-system
Open

feat(radio): add AN/PRC-117G comms system#1306
rokudara-sen wants to merge 1 commit into
AU-14:masterfrom
rokudara-sen:feature/new-comms-system

Conversation

@rokudara-sen

Copy link
Copy Markdown

About the PR

This PR adds the AN/PRC-117G manpack radio for Radio Telephone Operators, a tunable direct-frequency layer for all headsets, and tiered radio jamming.

The goal is to make ground comms more interesting than a simple "tower works / tower does not work" check. RTOs now have a real field role: keeping squads connected, managing secure nets, handling intercepts, and reacting to jamming.

The AN/PRC-117G is worn on the back and can only be operated by RTO-qualified personnel. It supports up to four programmable preset nets, either selected from the faction net list or entered manually as raw frequencies. The active AN/PRC net is transmitted on with :r.

While worn and powered, the radio acts as a relay anchor. Friendly headset traffic on nets loaded into the AN/PRC works without a communications tower within 30 tiles at full signal, and out to 45 tiles with degraded signal.

The radio has four operating modes:

  • FH: Frequency Hopping
  • SC: Single Channel
  • CT: Cipher Text
  • PT: Plain Text

It also has monitor mode, scan mode, a 0–5 squelch noise gate, an operator callsign, and a 50-entry net log.

COMSEC is handled through physical fill cards. Faction fill cards are inserted into the radio and secure faction-net traffic in every mode except PT. Secured transmissions are pure static to any AN/PRC without the matching fill. The fill slot also accepts captured enemy cards, which is how hostile secured traffic can be decoded.

Tuning an enemy net's frequency shows their traffic as red intercept text. A ZEROIZE button ejects the inserted fill card.

All headsets also get one tunable direct frequency, from 30.000 to 87.999 MHz, transmitted with :x. Direct frequencies work peer-to-peer without towers, keys, or relays, and can be bridged over distance by an AN/PRC carrying the same frequency.

Radio jammers now interact with these systems. Standard radios are still hard-blocked when transmitting from inside a jam field, but AN/PRC transmissions degrade instead with mode-dependent garble. FH is more resistant, PT is more vulnerable, and direct frequencies can be jammed too.

GOVFOR, OPFOR, and CLF all get their own AN/PRC variants and fill cards. RTOs, squad sergeants, and commanders receive the new equipment through faction loadouts

Two new guidebook pages cover the AN/PRC-117G and field headset systems.

Why / Balance

This gives the RTO role something important to actively manage during a round. Squads benefit from staying near their RTO, losing the RTO can hurt a whole element's communications, and capturing a radio or fill card can provide real intelligence value. (This could also be used as an intel objective)

The COMSEC loop (fill, intercept, zeroize, capture) gives faction RTOs something to play around without changing how regular soldiers use their normal headset encryption keys.

The scope is intentionally contained. The relay only ever carries the operator faction's own nets. Colony and third-party channels still route the way they did before: tower-dependent and unaffected by an RTO simply tuning to them.

Colonist and third-party gameplay should remain unchanged unless someone brings a jammer into play, which affects everyone equally.

Please test this yourself

Please do not just review the code and assume this is fine. This touches a lot of radio behavior, and I would really appreciate people testing it ingame with weird setups.

Good things to try:

  • Use two or more RTOs on the same faction net.
  • Put different faction RTOs close to each other and check what does and does not relay.
  • Try using the AN/PRC while moving between grids, maps, dropships, shuttles, or teleports.
  • Kill, crit, cuff, strip, disconnect, or move the RTO and check whether relay behavior stops correctly.
  • Put the radio in containers, drop it, turn it off, delete it, or move it away from the operator.
  • Try friendly fill, enemy fill, no fill, and zeroized fill.
  • Put jammers near the sender, receiver, relay, or all of them at once.
  • Try direct-frequency headset comms between hostile groups using the same frequency.
  • Check implants, accessory earpieces, headset encryption keys, muted channels, ghosts, and admin observing.
  • Spam several relays, several jammers, and many different direct frequencies to see if anything breaks.

If you can think of an edge case that is not listed here, please reply with it. I would rather have too many strange test cases than miss one obvious exploit.

Ingame testing performed

The following has already been tested ingame:

  • AN/PRC-117G can be equipped on the back slot.
  • Only RTO-qualified operators can operate the AN/PRC-117G.
  • Radio presets can be configured from faction nets.
  • Radio presets can be configured through raw frequency entry.
  • :r transmits on the selected active AN/PRC net.
  • Friendly headset traffic is relayed by a worn, powered AN/PRC.
  • Relay coverage works without a communications tower within the intended relay range.
  • Tower-gating exemptions work for relay-covered traffic.
  • Relay-covered traffic degrades outside the full-signal range.
  • The relay only carries the operator faction's own nets.
  • Tuning enemy, colony, or third-party frequencies does not reroute those channels for uninvolved players.
  • Direct headset frequency tuning works within the 30.000–87.999 MHz range.
  • :x transmits on the headset's tuned direct frequency.
  • Direct-frequency headset traffic works peer-to-peer without towers.
  • AN/PRC bridging works for headsets using the same direct frequency.
  • Matching COMSEC fill allows secured faction-net traffic to be decoded.
  • Missing or incorrect COMSEC fill turns secured AN/PRC traffic into static.
  • Captured enemy fill cards can be inserted and used to decode hostile secured traffic.
  • Enemy-net intercept traffic appears as red intercept text.
  • ZEROIZE ejects the inserted fill card.
  • Jammers hard-block standard radio transmissions from inside a jam field.
  • Jammers degrade AN/PRC transmissions instead of hard-blocking them.
  • FH and PT modes apply their intended jamming resistance/susceptibility behavior.
  • Direct frequencies are affected by jamming.
  • GOVFOR and CLF variants spawn with their expected faction equipment.
  • Guidebook pages open and display for both the AN/PRC-117G and field headset systems.

Outstanding before merge

  • OPFOR loadout wiring still needs to be completed/verified.

Merge warning

Warning

Do not merge this PR until it has been tested heavily

This touches radio routing, tower gating, jamming, faction encryption, item slots, headset behavior, and intercept logic. There are probably edge cases I have not thought of yet.

Edge cases reviewers should think about

Please reply to this PR with any abuse cases, edge cases, or strange interaction ideas you can think of, especially around:

  • Multiple RTOs relaying the same net on the same map.
  • Multiple RTOs from different factions relaying near each other.
  • AN/PRC relay behavior across grids, maps, shuttles, dropships, and FTL/teleport movement.
  • Radio behavior when the RTO dies, disconnects, is crit, is cuffed, is stripped, or drops the radio.
  • Relay behavior when the AN/PRC is powered off, unworn, deleted, gibbed, EMPed, or moved into containers.
  • Captured radios with friendly fill, enemy fill, no fill, or zeroized fill.
  • Jamming behavior when the transmitter, receiver, relay, or all three are inside different jam fields.
  • Direct-frequency abuse cases, especially shared frequencies between hostile groups.
  • Interaction with implants, accessory earpieces, headset encryption keys, channel mutes, and ghost/admin observing.
  • UI desyncs between the radio panel, headset tuning window, item slot, and net log.
  • Roundstart loadouts, latejoin loadouts, role changes, respawns, and admin-spawned equipment.
  • Performance with many players, many direct frequencies, several jammers, and multiple active relays.
  • System ordering: ANPRCRangeSystem relies on after: constraints against RMCTelephoneSystem / JammerSystem. If upstream ever renames those systems, this fails loudly at server startup rather than silently.
  • Engine subscription constraints: only one system may subscribe a given (component, event) pair. If upstream ever subscribes <HeadsetComponent, MapInitEvent> itself, the server should fail loudly at startup with a Duplicate Subscriptions exception instead of silently changing behavior.

Technical details

  • ANPRCRangeSystem subscribes to RadioSendAttemptEvent / RadioReceiveAttemptEvent after RMCTelephoneSystem and JammerSystem, then overrides their verdict for relay-covered traffic and AN/PRC :r transmissions. Conditions that must stay cancelled, such as muted channels via RMCRadioFilter and jammed non-ANPRC senders, are checked again before anything is un-cancelled

  • ANPRCGarbleSystem subscribes to RadioReceiveEvent on TunableHeadsetComponent before HeadsetSystem. The by-ref event carries the garbled message into the normal relay-to-chat path

  • TunableFrequencySystem injects TunableHeadsetComponent and registers its BUI on every headset at map-init through SharedUserInterfaceSystem.SetUi(), instead of editing the upstream CMHeadset prototype

  • Engine constraint: only one system may subscribe a given (component, event) pair. Our _AU14 systems therefore hook TunableHeadsetComponent for receive-garbling and <HeadsetComponent, MapInitEvent> for component injection. If upstream ever subscribes <HeadsetComponent, MapInitEvent> itself, the server will probably fail at startup with a Duplicate Subscriptions exception. The fix would be retargeting our subscription:

    • ANPRCRadioSystem: presets, transmit, receive/intercept, and net log
    • ANPRCCryptoSystem: fill card item slot
    • ANPRCGarbleSystem: jam, range, COMSEC garble tiers, and squelch
    • ANPRCRangeSystem: per-map relay range gating
    • TunableFrequencySystem: direct-frequency routing and relay bridging
  • The radio item carries its own ActiveRadioComponent, like a headset, instead of granting channels to the wearer. This avoids collisions with accessory earpieces or radio implants that put IntrinsicRadioReceiverComponent on the player

  • Added a new BUI and XAML window for the radio panel

  • Added a small frequency-tuning window for headsets

  • Added prototypes for:

    • Faction-specific AN/PRC variants.
    • Faction fill cards.
    • Frequency card.
    • Sentinel radio channels for :r and :x routing.
  • Added guidebook XML and guide entries.

  • Added FTL locale files.

Media

TODO, will update once I have more time.

Requirements

  • I have read and am following the Pull Request and Changelog Guidelines.
  • I have added media to this PR or it does not require an ingame showcase.
  • By submitting this code and/or assets, I confirm that I either own them or have provided the correct necessary licenses to use and distribute them. I agree to be fully responsible for any legal claims or issues arising from the use of these materials.

Changelog

🆑

  • add: Added the AN/PRC-117G manpack radio for Radio Telephone Operators, with up to four programmable preset nets and :r transmission.
  • add: Added relay-based ground comms. Headset traffic on nets loaded in a worn AN/PRC works without a comms tower within 30 tiles at full signal and 45 tiles with degraded signal.
  • add: Added AN/PRC operating modes: Frequency Hopping, Single Channel, Cipher Text, and Plain Text, each with different jamming resistance and security tradeoffs.
  • add: Added physical COMSEC fill cards for GOVFOR, OPFOR, and CLF. Secured faction-net traffic is pure static to radios without the matching fill, and captured enemy cards can be loaded to decode hostile traffic.
  • add: Added signal interception. Tuning an enemy net's frequency on the AN/PRC delivers their traffic as red intercept text and records it in the net log.
  • add: Added monitor mode, scan mode, squelch noise gate, operator callsigns, and a 50-entry net log to the AN/PRC.
  • add: Added a tunable direct frequency, from 30.000 to 87.999 MHz, to all headsets. It transmits with :x, requires no tower or encryption key, and can be bridged by an AN/PRC.
  • add: Added GOVFOR, OPFOR, and CLF AN/PRC radio variants and matching fill cards, with faction loadout wiring where currently implemented.
  • add: Added guidebook pages for the AN/PRC-117G and field headsets under the Communications Reference.
  • tweak: Radio jammers now degrade AN/PRC transmissions with mode-dependent garble instead of blocking them, jam both endpoints of a transmission, and affect direct frequencies.
  • tweak: Transmitting on a faction net without COMSEC fill now warns the operator on every transmission.
  • tweak: RTOs broadcasting in Frequency Hopping mode cause light interference for listeners on standard headsets. Switch to Single Channel when addressing regular troops.

Add the AN/PRC-117G manpack radio for RTO-qualified operators,
including programmable nets, relay support, COMSEC fills, intercept
behavior, and jamming-aware transmission modes.

The AN/PRC-117G supports up to four labeled preset nets, faction-net
selection, raw frequency tuning, and `:r` transmission on the active net.
When worn by an eligible operator, it can relay loaded faction nets for
nearby headset traffic without requiring a comms tower.

Add radio operating modes with different security and jamming behavior:
FH, SC, CT, and PT. Add monitor mode, scan mode, squelch control,
callsign prefixes, and a local net log.

Add physical COMSEC fill cards with a dedicated slot and zeroize support.
Valid fill secures faction nets outside PT mode, while captured enemy fill
cards allow operators to decode secured enemy traffic.

Add tiered radio jamming. Standard radios are blocked when transmitting
inside jam fields, while AN/PRC-117G traffic degrades based on operating
mode. Receiver proximity to jammers now applies additional garbling, and
degraded messages always corrupt at least one word.

Add one tunable direct frequency to standard ship headsets. Direct
headset traffic uses `:x`, operates peer-to-peer over short range, can be
bridged by an AN/PRC-117G on the same frequency, and remains vulnerable
to jamming.

Add GOVFOR, OPFOR, and CLF radio variants with matching fill cards.
Issue the new equipment to RTOs, squad sergeants, and commanders. Add
guidebook documentation and relay exemptions for tower and telephone
gating.

# Conflicts:
#	Resources/Prototypes/_AU14/Roles/Jobs/Military/Base/commanderBase.yml
@github-actions github-actions Bot added the L Large pull request. label Jun 13, 2026
@rokudara-sen rokudara-sen marked this pull request as draft June 13, 2026 07:22
@github-actions github-actions Bot added Changes: UI Changes UI/XAML files. Changes: Translations Changes localization files. labels Jun 13, 2026
@rokudara-sen rokudara-sen marked this pull request as ready for review June 13, 2026 07:22
- AU14TabletGovfor
- AU14TabletGovfor
- ANPRCFillCardGOVFOR
- ANPRCFillCardGOVFOR

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rank chevron is spawned and equipped into a free hand. Current implementation causes the Captain's chevron to be yoinked by anyone that spawns next to them.

Move this to pocket2 or the back storage (marines spawn with a satchel which isn't listed here)

- type: ClothingSpeedModifier
walkModifier: 0.95
sprintModifier: 0.95

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with all the newlines here in this prototype?

@troytroy400

Copy link
Copy Markdown
Contributor

Media is gonna be required for this one when you get the chance. Otherwise this looks really cool, RTO can probably make a comeback as a dedicated role once more.

@TheHellFireo TheHellFireo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other then stuff i found, i really don't know how this would be good for gameplay
This could have just been a fun little minigame for RTO, where they exist as a limited ranged radio tower ie
,
if the radio tower is down on the map, the RTO has to adjust signals and manage channels every few odd minutes to be able to have players in like a 15 tile radius be able to hear and transmit radio messages like normally

if (radio.FrequencyOverrides.TryGetValue(radio.ActiveSlot, out var dynFreq))
{
args.Channel = null;
_tunable.BroadcastOnFrequency(args.Source, dynFreq, outMessage);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This in not good. you are just making a new chat system which has none of the systems the current one has like admin logging, metadata, observer checks etc etc.

return null;
}

private void SendToEntity(EntityUid sender, EntityUid receiver, string message, int frequency)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here


// :x intercept

private void OnSpoke(Entity<TunedFrequencyComponent> ent, ref EntitySpokeEvent args)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only checks for the radio component and doesn't checkj if the headset is broken or disabled etc

private void UpdateBuiState(Entity<ANPRCRadioComponent> ent)
{
_ui.SetUiState(ent.Owner, ANPRCRadioUI.Key, new ANPRCRadioState(
new Dictionary<int, ProtoId<RadioChannelPrototype>>(ent.Comp.Presets),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You rebuild the UI even when its not open

var channelId = args.Channel.ID;

// Same map-local rule as OnSendAttempt.
if (!AnyAnchorCoversChannel(channelId, Transform(args.RadioReceiver).MapID))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already scan for anchors in line 127, this just doubles the work

@maertayn

Copy link
Copy Markdown
Contributor

Dropped a banger and then went completely dark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Changes: Translations Changes localization files. Changes: UI Changes UI/XAML files. L Large pull request.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants