Skip to content

Commit

Permalink
Merge branch 'master' into add-premade-mercenery-loadouts
Browse files Browse the repository at this point in the history
  • Loading branch information
Tryded authored May 30, 2024
2 parents 30dc710 + a7cece8 commit e62c507
Show file tree
Hide file tree
Showing 19 changed files with 76,033 additions and 104 deletions.
8 changes: 8 additions & 0 deletions Content.Client/DeltaV/Implants/Radio/RadioImplantSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Content.Shared.DeltaV.Implants.Radio;

namespace Content.Client.DeltaV.Implants.Radio;

/// <inheritdoc />
public sealed class RadioImplantSystem : SharedRadioImplantSystem
{
}
3 changes: 2 additions & 1 deletion Content.IntegrationTests/Tests/PostMapInitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public sealed class PostMapInitTest
"TheHive", //DeltaV
"Hammurabi", //DeltaV
"Lighthouse", //DeltaV
"Submarine" //DeltaV
"Submarine", //DeltaV
"Micro" //DeltaV
};

/// <summary>
Expand Down
126 changes: 126 additions & 0 deletions Content.Server/DeltaV/Implants/Radio/RadioImplantSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using Content.Server.Chat.Systems;
using Content.Server.Radio;
using Content.Server.Radio.Components;
using Content.Server.Radio.EntitySystems;
using Content.Shared.DeltaV.Implants.Radio;
using Content.Shared.Radio.Components;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Player;

namespace Content.Server.DeltaV.Implants.Radio;

/// <inheritdoc />
public sealed class RadioImplantSystem : SharedRadioImplantSystem
{
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly RadioSystem _radioSystem = default!;

private EntityQuery<ActorComponent> _actorQuery;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RadioImplantComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<RadioImplantComponent, EntInsertedIntoContainerMessage>(OnInsertEncryptionKey);
SubscribeLocalEvent<RadioImplantComponent, EntRemovedFromContainerMessage>(OnRemoveEncryptionKey);
SubscribeLocalEvent<RadioImplantComponent, RadioReceiveEvent>(OnRadioReceive);
SubscribeLocalEvent<HasRadioImplantComponent, EntitySpokeEvent>(OnSpeak);
_actorQuery = GetEntityQuery<ActorComponent>();
}

/// <summary>
/// Ensures implants with fixed channels work.
/// </summary>
private void OnMapInit(Entity<RadioImplantComponent> ent, ref MapInitEvent args)
{
UpdateRadioReception(ent);
}

/// <summary>
/// Handles the implantee's speech being forwarded onto the radio channel of the implant.
/// </summary>
private void OnSpeak(Entity<HasRadioImplantComponent> ent, ref EntitySpokeEvent args)
{
// not a radio message, or already handled by another radio
if (args.Channel is null)
return;

// does the implant have access to the channel the implantee is trying to speak on?
if (ent.Comp.Implant is {} implant
&& TryComp<RadioImplantComponent>(implant, out var radioImplantComponent)
&& radioImplantComponent.Channels.Contains(args.Channel.ID))
{
_radioSystem.SendRadioMessage(ent, args.Message, args.Channel.ID, implant);
// prevent other radios they might be wearing from sending the message again
args.Channel = null;
}
}

/// <summary>
/// Handles receiving radio messages and forwarding them to the implantee.
/// </summary>
private void OnRadioReceive(EntityUid uid, RadioImplantComponent component, ref RadioReceiveEvent args)
{
if (_actorQuery.TryComp(component.Implantee, out var actorComponent))
_netManager.ServerSendMessage(args.ChatMsg, actorComponent.PlayerSession.Channel);
}

/// <summary>
/// Handles the addition of an encryption key to the implant's storage.
/// </summary>
private void OnInsertEncryptionKey(Entity<RadioImplantComponent> ent, ref EntInsertedIntoContainerMessage args)
{
// check if the insertion is actually something getting inserted into the radio implant storage, since
// this evt also fires when the radio implant is being inserted into a person.
if (ent.Owner != args.Container.Owner
|| !TryComp<EncryptionKeyComponent>(args.Entity, out var encryptionKeyComponent))
return;

// copy over the radio channels that can be accessed
ent.Comp.Channels.Clear();
foreach (var channel in encryptionKeyComponent.Channels)
{
ent.Comp.Channels.Add(channel);
}
Dirty(ent);
UpdateRadioReception(ent);
}

/// <summary>
/// Handles the removal of an encryption key from the implant's storage.
/// </summary>
private void OnRemoveEncryptionKey(Entity<RadioImplantComponent> ent, ref EntRemovedFromContainerMessage args)
{
// check if the insertion is actually something getting inserted into the radio implant storage, since
// this evt also fires when the radio implant is being inserted into a person.
if (ent.Owner != args.Container.Owner
|| !HasComp<EncryptionKeyComponent>(args.Entity))
return;

// clear the radio channels since there's no encryption key inserted anymore.
ent.Comp.Channels.Clear();
Dirty(ent);
UpdateRadioReception(ent);
}

/// <summary>
/// Ensures that this thing can actually hear radio messages from channels the key provides.
/// </summary>
private void UpdateRadioReception(Entity<RadioImplantComponent> ent)
{
if (ent.Comp.Channels.Count != 0)
{
// we need to add this comp to actually receive radio events.
var channels = EnsureComp<ActiveRadioComponent>(ent).Channels;
foreach (var channel in ent.Comp.Channels)
{
channels.Add(channel);
}
}
else
{
RemComp<ActiveRadioComponent>(ent);
}
}
}
16 changes: 16 additions & 0 deletions Content.Shared/DeltaV/Implants/Radio/HasRadioImplantComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Robust.Shared.GameStates;

namespace Content.Shared.DeltaV.Implants.Radio;

/// <summary>
/// This indicates this entity has a radio implant implanted into themselves.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedRadioImplantSystem))]
public sealed partial class HasRadioImplantComponent : Component
{
/// <summary>
/// The radio implant. We need this to be able to determine encryption keys.
/// </summary>
[DataField, AutoNetworkedField]
public EntityUid? Implant;
}
24 changes: 24 additions & 0 deletions Content.Shared/DeltaV/Implants/Radio/RadioImplantComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Content.Shared.Radio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared.DeltaV.Implants.Radio;

/// <summary>
/// This is for radio implants. Might be Syndie, might not be Syndie, but either way, it's an implant.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedRadioImplantSystem))]
public sealed partial class RadioImplantComponent : Component
{
/// <summary>
/// The entity this implant got added to.
/// </summary>
[DataField, AutoNetworkedField]
public EntityUid? Implantee;

/// <summary>
/// The channels this implant can talk on.
/// </summary>
[DataField, AutoNetworkedField]
public HashSet<ProtoId<RadioChannelPrototype>> Channels = new();
}
56 changes: 56 additions & 0 deletions Content.Shared/DeltaV/Implants/Radio/SharedRadioImplantSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Content.Shared.Actions;
using Content.Shared.Implants;
using Content.Shared.Storage;
using Content.Shared.Storage.EntitySystems;
using Robust.Shared.Containers;

namespace Content.Shared.DeltaV.Implants.Radio;

/// <summary>
/// This handles radio implants, which you can implant to get access to a radio channel.
/// </summary>
public abstract class SharedRadioImplantSystem : EntitySystem
{
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<RadioImplantComponent, ImplantImplantedEvent>(OnImplanted);
SubscribeLocalEvent<RadioImplantComponent, EntGotRemovedFromContainerMessage>(OnPossiblyUnimplanted);
}

/// <summary>
/// Handles implantation of the implant.
/// </summary>
private void OnImplanted(EntityUid uid, RadioImplantComponent component, ImplantImplantedEvent args)
{
if (args.Implanted is not { Valid: true })
return;

component.Implantee = args.Implanted.Value;
Dirty(uid, component);

// make sure the person entity gets slapped with a component so it can react to it talking.
var hasRadioImplantComponent = EnsureComp<HasRadioImplantComponent>(args.Implanted.Value);
hasRadioImplantComponent.Implant = uid;
Dirty(component.Implantee.Value, hasRadioImplantComponent);
}


/// <summary>
/// Handles removal of the implant from its containing mob.
/// </summary>
/// <remarks>Done via <see cref="EntGotRemovedFromContainerMessage"/> because there is no specific event for an implant being removed.</remarks>
private void OnPossiblyUnimplanted(EntityUid uid, RadioImplantComponent component, EntGotRemovedFromContainerMessage args)
{
if (Terminating(uid))
return;

// this gets fired if it gets removed from ANY container but really, we just want to know if it was removed from its owner...
// so check if the ent we got implanted into matches the container's owner (here, the container's owner is the entity)
if (component.Implantee is not null && component.Implantee == args.Container.Owner)
{
RemComp<HasRadioImplantComponent>(component.Implantee.Value);
component.Implantee = null;
}
}
}
29 changes: 29 additions & 0 deletions Resources/Changelog/DeltaVChangelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2483,3 +2483,32 @@
id: 366
time: '2024-05-26T18:33:15.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/1260
- author: pissdemon
changes:
- message: Syndicate encryption keys can no longer be purchased.
type: Remove
- message: Syndicate radio implants are now available in uplinks. After implanting,
you can use it to speak on the Syndicate frequency like you would on a headset
(":t Hi!"). No headset needed!
type: Add
- message: Generic radio implants are now available in uplinks. After implanting,
you can insert an encryption key into its bluespace storage space, and use it
like you would use a headset.
type: Add
id: 367
time: '2024-05-27T15:24:53.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/1262
- author: deltanedas
changes:
- message: Fixed submarine's TEG being broken.
type: Fix
id: 368
time: '2024-05-28T00:18:36.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/1265
- author: Colin-Tel
changes:
- message: Added Micro station! It can appear in lobbies no larger than 35.
type: Add
id: 369
time: '2024-05-29T04:10:40.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/1251
9 changes: 9 additions & 0 deletions Resources/Locale/en-US/deltav/store/uplink-catalog.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,12 @@ uplink-reinforcement-radio-nukie-mouse-desc = Calls in a specially trained mouse
# Implants
uplink-bionic-syrinx-implanter-name = Bionic Syrinx Implanter
uplink-bionic-syrinx-implanter-desc = An implant that enhances a harpy's natural talent for mimicry to let you adjust your voice to whoever you can think of.
uplink-syndicate-radio-implanter-name = Syndicate Radio Implanter
uplink-syndicate-radio-implanter-desc = A cranial implant that lets you talk on the Syndicate radio channel (use :t).
uplink-syndicate-radio-implanter-bundle-name = Syndicate Radio Implanter Bundle
uplink-syndicate-radio-implanter-bundle-desc = Two implanters for the price of one and a half! Share one with your Syndicate friend.
uplink-generic-radio-implanter-name = Generic Radio Implanter
uplink-generic-radio-implanter-desc = A cranial implant with a bluespace compartment for a single encryption key (not included). Put in a key of your choice, and you can talk using it like you would with any headset.
Loading

0 comments on commit e62c507

Please sign in to comment.