Skip to content

Commit

Permalink
Syndicate and CentComm Radio Implanters (#33533)
Browse files Browse the repository at this point in the history
* Add Syndicate Radio Implant

* Fix description grammar

* remove unused var

* Update - Small fixes

* Un mess with imports

* Remove unused tag

* Correction

* Clear lists instead of remove

* Update 0 check

* Add Centcomm implant

* Correct centcom channel

* Correct params

* No more crying

* Update Content.Shared/Implants/Components/RadioImplantComponent.cs

* Update Content.Server/Implants/RadioImplantSystem.cs

* Update Content.Server/Implants/RadioImplantSystem.cs

---------

Co-authored-by: slarticodefast <[email protected]>
  • Loading branch information
thetolbean and slarticodefast authored Jan 30, 2025
1 parent e938512 commit 84328ee
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 0 deletions.
76 changes: 76 additions & 0 deletions Content.Server/Implants/RadioImplantSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using Content.Server.Radio.Components;
using Content.Shared.Implants;
using Content.Shared.Implants.Components;
using Robust.Shared.Containers;

namespace Content.Server.Implants;

public sealed class RadioImplantSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<RadioImplantComponent, ImplantImplantedEvent>(OnImplantImplanted);
SubscribeLocalEvent<RadioImplantComponent, EntGotRemovedFromContainerMessage>(OnRemove);
}

/// <summary>
/// If implanted with a radio implant, installs the necessary intrinsic radio components
/// </summary>
private void OnImplantImplanted(Entity<RadioImplantComponent> ent, ref ImplantImplantedEvent args)
{
if (args.Implanted == null)
return;

var activeRadio = EnsureComp<ActiveRadioComponent>(args.Implanted.Value);
foreach (var channel in ent.Comp.RadioChannels)
{
if (activeRadio.Channels.Add(channel))
ent.Comp.ActiveAddedChannels.Add(channel);
}

EnsureComp<IntrinsicRadioReceiverComponent>(args.Implanted.Value);

var intrinsicRadioTransmitter = EnsureComp<IntrinsicRadioTransmitterComponent>(args.Implanted.Value);
foreach (var channel in ent.Comp.RadioChannels)
{
if (intrinsicRadioTransmitter.Channels.Add(channel))
ent.Comp.TransmitterAddedChannels.Add(channel);
}
}

/// <summary>
/// Removes intrinsic radio components once the Radio Implant is removed
/// </summary>
private void OnRemove(Entity<RadioImplantComponent> ent, ref EntGotRemovedFromContainerMessage args)
{
if (TryComp<ActiveRadioComponent>(args.Container.Owner, out var activeRadioComponent))
{
foreach (var channel in ent.Comp.ActiveAddedChannels)
{
activeRadioComponent.Channels.Remove(channel);
}
ent.Comp.ActiveAddedChannels.Clear();

if (activeRadioComponent.Channels.Count == 0)
{
RemCompDeferred<ActiveRadioComponent>(args.Container.Owner);
}
}

if (!TryComp<IntrinsicRadioTransmitterComponent>(args.Container.Owner, out var radioTransmitterComponent))
return;

foreach (var channel in ent.Comp.TransmitterAddedChannels)
{
radioTransmitterComponent.Channels.Remove(channel);
}
ent.Comp.TransmitterAddedChannels.Clear();

if (radioTransmitterComponent.Channels.Count == 0 || activeRadioComponent?.Channels.Count == 0)
{
RemCompDeferred<IntrinsicRadioTransmitterComponent>(args.Container.Owner);
}
}
}
37 changes: 37 additions & 0 deletions Content.Shared/Implants/Components/RadioImplantComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Content.Shared.Radio;
using Robust.Shared.Prototypes;

namespace Content.Shared.Implants.Components;

/// <summary>
/// Gives the user access to a given channel without the need for a headset.
/// </summary>
[RegisterComponent]
public sealed partial class RadioImplantComponent : Component
{
/// <summary>
/// The radio channel(s) to grant access to.
/// </summary>
[DataField(required: true)]
public HashSet<ProtoId<RadioChannelPrototype>> RadioChannels = new();

/// <summary>
/// The radio channels that have been added by the implant to a user's ActiveRadioComponent.
/// Used to track which channels were successfully added (not already in user)
/// </summary>
/// <remarks>
/// Should not be modified outside RadioImplantSystem.cs
/// </remarks>
[DataField]
public HashSet<ProtoId<RadioChannelPrototype>> ActiveAddedChannels = new();

/// <summary>
/// The radio channels that have been added by the implant to a user's IntrinsicRadioTransmitterComponent.
/// Used to track which channels were successfully added (not already in user)
/// </summary>
/// <remarks>
/// Should not be modified outside RadioImplantSystem.cs
/// </remarks>
[DataField]
public HashSet<ProtoId<RadioChannelPrototype>> TransmitterAddedChannels = new();
}
3 changes: 3 additions & 0 deletions Resources/Locale/en-US/store/uplink-catalog.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ uplink-death-acidifier-implant-desc = Completely melts the user and their equipm
uplink-micro-bomb-implanter-name = Micro Bomb Implanter
uplink-micro-bomb-implanter-desc = Explode on death or manual activation with this implant. Destroys the body with all equipment.
uplink-radio-implanter-name = Radio Implanter
uplink-radio-implanter-desc = Implants a Syndicate radio, allowing covert communication without a headset.
# Bundles
uplink-observation-kit-name = Observation Kit
uplink-observation-kit-desc = Includes surveillance camera monitor board and security hud disguised as sunglasses.
Expand Down
14 changes: 14 additions & 0 deletions Resources/Prototypes/Catalog/uplink_catalog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,20 @@
categories:
- UplinkImplants

- type: listing
id: UplinkRadioImplanter
name: uplink-radio-implanter-name
description: uplink-radio-implanter-desc
icon: { sprite: /Textures/Objects/Devices/encryption_keys.rsi, state: synd_label }
productEntity: RadioImplanter
discountCategory: usualDiscounts
discountDownTo:
Telecrystal: 1
cost:
Telecrystal: 2
categories:
- UplinkImplants

- type: listing
id: UplinkMicroBombImplanter
name: uplink-micro-bomb-implanter-name
Expand Down
18 changes: 18 additions & 0 deletions Resources/Prototypes/Entities/Objects/Misc/implanters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@
- type: Implanter
implant: FreedomImplant

- type: entity
id: RadioImplanter
suffix: radio Syndicate
parent: BaseImplantOnlyImplanterSyndi
components:
- type: Implanter
implant: RadioImplant

- type: entity
id: UplinkImplanter
suffix: uplink
Expand Down Expand Up @@ -262,3 +270,13 @@
components:
- type: Implanter
implant: MindShieldImplant

# Centcomm implanters

- type: entity
id: RadioImplanterCentcomm
suffix: radio Centcomm
parent: BaseImplantOnlyImplanter
components:
- type: Implanter
implant: RadioImplantCentcomm
26 changes: 26 additions & 0 deletions Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@
components:
- Cuffable # useless if you cant be cuffed

- type: entity
parent: BaseSubdermalImplant
id: RadioImplant
name: radio implant
description: This implant grants access to the Syndicate channel without a headset.
categories: [ HideSpawnMenu ]
components:
- type: SubdermalImplant
- type: RadioImplant
radioChannels:
- Syndicate

- type: entity
parent: [ BaseSubdermalImplant, StorePresetUplink ]
id: UplinkImplant
Expand Down Expand Up @@ -336,3 +348,17 @@
- type: Tag
tags:
- MindShield

# Centcomm implants

- type: entity
parent: BaseSubdermalImplant
id: RadioImplantCentcomm
name: radio implant
description: This implant grants access to the Centcomm channel without a headset. Only authorized for Centcomm employees.
categories: [ HideSpawnMenu ]
components:
- type: SubdermalImplant
- type: RadioImplant
radioChannels:
- CentCom

0 comments on commit 84328ee

Please sign in to comment.