Skip to content

Commit

Permalink
Merge EE 11/10/24 (Grimbly-Station#131)
Browse files Browse the repository at this point in the history
<!--
This is a semi-strict format, you can add/remove sections as needed but
the order/format should be kept the same
Remove these comments before submitting
-->

# Description

<!--
Explain this PR in as much detail as applicable

Some example prompts to consider:
How might this affect the game? The codebase?
What might be some alternatives to this?
How/Who does this benefit/hurt [the game/codebase]?
-->

Merges EE, do not merge.
  • Loading branch information
sleepyyapril authored Nov 10, 2024
2 parents 6056aba + d9c1ea9 commit 8ad0edb
Show file tree
Hide file tree
Showing 191 changed files with 28,432 additions and 21,112 deletions.
65 changes: 65 additions & 0 deletions Content.Client/FootPrint/FootPrintsVisualizerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Content.Shared.FootPrint;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Random;

namespace Content.Client.FootPrint;

public sealed class FootPrintsVisualizerSystem : VisualizerSystem<FootPrintComponent>
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly IRobustRandom _random = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<FootPrintComponent, ComponentInit>(OnInitialized);
SubscribeLocalEvent<FootPrintComponent, ComponentShutdown>(OnShutdown);
}

private void OnInitialized(EntityUid uid, FootPrintComponent comp, ComponentInit args)
{
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;

sprite.LayerMapReserveBlank(FootPrintVisualLayers.Print);
UpdateAppearance(uid, comp, sprite);
}

private void OnShutdown(EntityUid uid, FootPrintComponent comp, ComponentShutdown args)
{
if (TryComp<SpriteComponent>(uid, out var sprite)
&& sprite.LayerMapTryGet(FootPrintVisualLayers.Print, out var layer))
sprite.RemoveLayer(layer);
}

private void UpdateAppearance(EntityUid uid, FootPrintComponent component, SpriteComponent sprite)
{
if (!sprite.LayerMapTryGet(FootPrintVisualLayers.Print, out var layer)
|| !TryComp<FootPrintsComponent>(component.PrintOwner, out var printsComponent)
|| !TryComp<AppearanceComponent>(uid, out var appearance)
|| !_appearance.TryGetData<FootPrintVisuals>(uid, FootPrintVisualState.State, out var printVisuals, appearance))
return;

sprite.LayerSetState(layer, new RSI.StateId(printVisuals switch
{
FootPrintVisuals.BareFootPrint => printsComponent.RightStep ? printsComponent.RightBarePrint : printsComponent.LeftBarePrint,
FootPrintVisuals.ShoesPrint => printsComponent.ShoesPrint,
FootPrintVisuals.SuitPrint => printsComponent.SuitPrint,
FootPrintVisuals.Dragging => _random.Pick(printsComponent.DraggingPrint),
_ => throw new ArgumentOutOfRangeException($"Unknown {printVisuals} parameter.")
}), printsComponent.RsiPath);

if (_appearance.TryGetData<Color>(uid, FootPrintVisualState.Color, out var printColor, appearance))
sprite.LayerSetColor(layer, printColor);
}

protected override void OnAppearanceChange (EntityUid uid, FootPrintComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite is not { } sprite)
return;

UpdateAppearance(uid, component, sprite);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Trinary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos.Piping;
Expand All @@ -13,7 +11,6 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
[UsedImplicitly]
public sealed class PressureControlledValveSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
Expand All @@ -40,39 +37,26 @@ private void OnUpdate(EntityUid uid, PressureControlledValveComponent comp, ref
return;
}

// If output is higher than input, flip input/output to enable bidirectional flow.
if (outletNode.Air.Pressure > inletNode.Air.Pressure)
{
PipeNode temp = outletNode;
outletNode = inletNode;
inletNode = temp;
}

float control = (controlNode.Air.Pressure - outletNode.Air.Pressure) - comp.Threshold;
float transferRate;
if (control < 0)
{
comp.Enabled = false;
transferRate = 0;
}
else
// If the pressure in either inlet or outlet exceeds the side pressure, act as an open pipe.
if (!comp.Enabled && (controlNode.Air.Pressure < inletNode.Air.Pressure
|| controlNode.Air.Pressure < outletNode.Air.Pressure))
{
inletNode.AddAlwaysReachable(outletNode);
outletNode.AddAlwaysReachable(inletNode);
comp.Enabled = true;
transferRate = Math.Min(control * comp.Gain, comp.MaxTransferRate * _atmosphereSystem.PumpSpeedup());
UpdateAppearance(uid, comp);
_ambientSoundSystem.SetAmbience(uid, true);
return;
}
UpdateAppearance(uid, comp);

// We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters.
var transferVolume = transferRate * args.dt;
if (transferVolume <= 0)
{
_ambientSoundSystem.SetAmbience(uid, false);
if (!comp.Enabled)
return;
}

_ambientSoundSystem.SetAmbience(uid, true);
var removed = inletNode.Air.RemoveVolume(transferVolume);
_atmosphereSystem.Merge(outletNode.Air, removed);
inletNode.RemoveAlwaysReachable(outletNode);
outletNode.RemoveAlwaysReachable(inletNode);
comp.Enabled = false;
UpdateAppearance(uid, comp);
_ambientSoundSystem.SetAmbience(uid, false);
}

private void OnFilterLeaveAtmosphere(EntityUid uid, PressureControlledValveComponent comp, ref AtmosDeviceDisabledEvent args)
Expand Down
4 changes: 2 additions & 2 deletions Content.Server/Chat/Systems/ChatSystem.Emote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private void CacheEmotes()
/// <param name="emoteId">The id of emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param>
/// <param name="hideLog">Whether or not this message should appear in the adminlog window</param>
/// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerSpeechEvent"/>. If this is set, the event will not get raised.</param>
public void TryEmoteWithChat(
EntityUid source,
string emoteId,
Expand All @@ -74,7 +74,7 @@ public void TryEmoteWithChat(
/// <param name="hideLog">Whether or not this message should appear in the adminlog window</param>
/// <param name="hideChat">Whether or not this message should appear in the chat window</param>
/// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerSpeechEvent"/>. If this is set, the event will not get raised.</param>
public void TryEmoteWithChat(
EntityUid source,
EmotePrototype emote,
Expand Down
29 changes: 7 additions & 22 deletions Content.Server/Chat/Systems/ChatSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Content.Server.Language;
using Content.Server.Speech.Components;
using Content.Server.Speech.EntitySystems;
using Content.Server.Chat;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.ActionBlocker;
Expand Down Expand Up @@ -147,7 +146,7 @@ private void OnGameChange(GameRunLevelChangedEvent ev)
/// <param name="hideLog">Whether or not this message should appear in the adminlog window</param>
/// <param name="shell"></param>
/// <param name="player">The player doing the speaking</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerSpeechEvent"/>. If this is set, the event will not get raised.</param>
public void TrySendInGameICMessage(
EntityUid source,
string message,
Expand All @@ -170,7 +169,7 @@ public void TrySendInGameICMessage(
/// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param>
/// <param name="shell"></param>
/// <param name="player">The player doing the speaking</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerSpeechEvent"/>. If this is set, the event will not get raised.</param>
/// <param name="ignoreActionBlocker">If set to true, action blocker will not be considered for whether an entity can send this message.</param>
public void TrySendInGameICMessage(
EntityUid source,
Expand Down Expand Up @@ -421,11 +420,11 @@ private void SendEntitySpeak(
}
else
{
var nameEv = new TransformSpeakerNameEvent(source, Name(source));
var nameEv = new TransformSpeakerSpeechEvent(source, Name(source));
RaiseLocalEvent(source, nameEv);
name = nameEv.Name;
name = nameEv.VoiceName ?? Name(source);
// Check for a speech verb override
if (nameEv.SpeechVerb != null && _prototypeManager.TryIndex<SpeechVerbPrototype>(nameEv.SpeechVerb, out var proto))
if (nameEv.SpeechVerb != null && _prototypeManager.TryIndex(nameEv.SpeechVerb, out var proto))
speech = proto;
}

Expand Down Expand Up @@ -493,9 +492,9 @@ private void SendEntityWhisper(
}
else
{
var nameEv = new TransformSpeakerNameEvent(source, Name(source));
var nameEv = new TransformSpeakerSpeechEvent(source, Name(source));
RaiseLocalEvent(source, nameEv);
name = nameEv.Name;
name = nameEv.VoiceName ?? Name(source);
}
name = FormattedMessage.EscapeText(name);

Expand Down Expand Up @@ -994,20 +993,6 @@ public record ExpandICChatRecipientstEvent(EntityUid Source, float VoiceRange, D
{
}

public sealed class TransformSpeakerNameEvent : EntityEventArgs
{
public EntityUid Sender;
public string Name;
public string? SpeechVerb;

public TransformSpeakerNameEvent(EntityUid sender, string name, string? speechVerb = null)
{
Sender = sender;
Name = name;
SpeechVerb = speechVerb;
}
}

/// <summary>
/// Raised broadcast in order to transform speech.transmit
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,110 +1,30 @@
using Content.Server.Administration.Logs;
using Content.Server.Chat.Systems;
using Content.Server.Popups;
using Content.Server.VoiceMask;
using Content.Shared.Database;
using Content.Server.VoiceMask;
using Content.Shared.Implants;
using Content.Shared.Implants.Components;
using Content.Shared.Popups;
using Content.Shared.Preferences;
using Content.Shared.Tag;
using Content.Shared.VoiceMask;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;

namespace Content.Server.Implants;

public sealed class SubdermalBionicSyrinxImplantSystem : EntitySystem
{
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly TagSystem _tag = default!;

[ValidatePrototypeId<TagPrototype>]
public const string BionicSyrinxImplant = "BionicSyrinxImplant";

private const string BionicSyrinxImplant = "BionicSyrinxImplant";

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<VoiceMaskerComponent, ImplantImplantedEvent>(OnInsert);
SubscribeLocalEvent<SyrinxVoiceMaskComponent, TransformSpeakerNameEvent>(OnSpeakerNameTransform);
SubscribeLocalEvent<SyrinxVoiceMaskComponent, VoiceMaskChangeNameMessage>(OnChangeName);
// We need to remove the SyrinxVoiceMaskComponent from the owner before the implant
// is removed, so we need to execute before the SubdermalImplantSystem.
SubscribeLocalEvent<VoiceMaskerComponent, EntGotRemovedFromContainerMessage>(OnRemove, before: new[] { typeof(SubdermalImplantSystem) });
SubscribeLocalEvent<VoiceMaskComponent, ImplantImplantedEvent>(OnInsert);
}

private void OnInsert(EntityUid uid, VoiceMaskerComponent component, ImplantImplantedEvent args)
private void OnInsert(EntityUid uid, VoiceMaskComponent component, ImplantImplantedEvent args)
{
if (!args.Implanted.HasValue ||
!_tag.HasTag(args.Implant, BionicSyrinxImplant))
return;

var voicemask = EnsureComp<SyrinxVoiceMaskComponent>(args.Implanted.Value);
voicemask.VoiceName = MetaData(args.Implanted.Value).EntityName;
Dirty(args.Implanted.Value, voicemask);
}

private void OnRemove(EntityUid uid, VoiceMaskerComponent component, EntGotRemovedFromContainerMessage args)
{
if (!TryComp<SubdermalImplantComponent>(uid, out var implanted) || implanted.ImplantedEntity == null)
return;

RemComp<SyrinxVoiceMaskComponent>(implanted.ImplantedEntity.Value);
}

/// <summary>
/// Copy from VoiceMaskSystem, adapted to work with SyrinxVoiceMaskComponent.
/// </summary>
private void OnChangeName(EntityUid uid, SyrinxVoiceMaskComponent component, VoiceMaskChangeNameMessage message)
{
if (message.Name.Length > HumanoidCharacterProfile.MaxNameLength || message.Name.Length <= 0)
{
_popupSystem.PopupEntity(Loc.GetString("voice-mask-popup-failure"), uid, message.Actor, PopupType.SmallCaution);
return;
}

component.VoiceName = message.Name;
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(message.Actor):player} set voice of {ToPrettyString(uid):mask}: {component.VoiceName}");

_popupSystem.PopupEntity(Loc.GetString("voice-mask-popup-success"), uid, message.Actor);
TrySetLastKnownName(uid, message.Name);
UpdateUI(uid, component);
}

/// <summary>
/// Copy from VoiceMaskSystem, adapted to work with SyrinxVoiceMaskComponent.
/// </summary>
private void TrySetLastKnownName(EntityUid implanted, string lastName)
{
if (!HasComp<VoiceMaskComponent>(implanted)
|| !TryComp<VoiceMaskerComponent>(implanted, out var maskComp))
return;

maskComp.LastSetName = lastName;
}

/// <summary>
/// Copy from VoiceMaskSystem, adapted to work with SyrinxVoiceMaskComponent.
/// </summary>
private void UpdateUI(EntityUid owner, SyrinxVoiceMaskComponent? component = null)
{
if (!Resolve(owner, ref component, logMissing: false))
return;

if (_uiSystem.TryGetOpenUi(owner, VoiceMaskUIKey.Key, out _))
_uiSystem.SetUiState(new(owner, null), VoiceMaskUIKey.Key, new VoiceMaskBuiState(component.VoiceName, null));
}

/// <summary>
/// Copy from VoiceMaskSystem, adapted to work with SyrinxVoiceMaskComponent.
/// </summary>
private void OnSpeakerNameTransform(EntityUid uid, SyrinxVoiceMaskComponent component, TransformSpeakerNameEvent args)
{
if (component.Enabled)
args.Name = component.VoiceName;
// Update the name so it's the entities default name. You can't take it off like a voice mask so it's important!
component.VoiceMaskName = Name(args.Implanted.Value);
}
}
9 changes: 0 additions & 9 deletions Content.Server/DeltaV/VoiceMask/SyrinxVoiceMaskComponent.cs

This file was deleted.

Loading

0 comments on commit 8ad0edb

Please sign in to comment.