From 12947097993df8dc093738b4aa412feab6e98175 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 30 Jul 2023 12:53:17 -0400 Subject: [PATCH 1/5] EMP effect for Silicons Some mild cleanup, made Parkstation markers consistent, added IPC damage container, and added a screen static overlay for when IPCs are EMP'd --- .../Overlays/Shaders/StaticOverlay.cs | 92 +++++++++++++++++++ .../Silicon/Systems/SeeingStaticSystem.cs | 57 ++++++++++++ .../Commands/SetOutfitCommand.cs | 4 +- Content.Server/Emp/EmpSystem.cs | 4 +- .../Silicon/Systems/SiliconEmpSystem.cs | 68 ++++++++++++++ .../Silicon/Systems/SiliconMiscSystem.cs | 2 +- .../Station/Systems/StationSpawningSystem.cs | 4 +- .../Temperature/Systems/TemperatureSystem.cs | 4 +- .../Zombies/ZombifyOnDeathSystem.cs | 4 +- Content.Shared/Humanoid/NamingSystem.cs | 4 +- Content.Shared/Humanoid/SkinColor.cs | 8 +- .../EncryptionKeyHolderComponent.cs | 4 +- .../EntitySystems/EncryptionKeySystem.cs | 4 +- .../Components/SeeingStaticComponent.cs | 9 ++ .../Silicon/Systems/SeeingStaticSystem.cs | 6 ++ .../SimpleStation14/Damage/containers.yml | 6 ++ .../Entities/Mobs/Player/silicon_base.yml | 13 ++- .../SimpleStation14/Shaders/shaders.yml | 5 + .../SimpleStation14/status_effects.yml | 2 + .../Shaders/seeing_static.swsl | 43 +++++++++ 20 files changed, 317 insertions(+), 26 deletions(-) create mode 100644 Content.Client/SimpleStation14/Overlays/Shaders/StaticOverlay.cs create mode 100644 Content.Client/SimpleStation14/Silicon/Systems/SeeingStaticSystem.cs create mode 100644 Content.Server/SimpleStation14/Silicon/Systems/SiliconEmpSystem.cs create mode 100644 Content.Shared/SimpleStation14/Silicon/Components/SeeingStaticComponent.cs create mode 100644 Content.Shared/SimpleStation14/Silicon/Systems/SeeingStaticSystem.cs create mode 100644 Resources/Prototypes/SimpleStation14/status_effects.yml create mode 100644 Resources/Textures/SimpleStation14/Shaders/seeing_static.swsl diff --git a/Content.Client/SimpleStation14/Overlays/Shaders/StaticOverlay.cs b/Content.Client/SimpleStation14/Overlays/Shaders/StaticOverlay.cs new file mode 100644 index 0000000000..2c299f792f --- /dev/null +++ b/Content.Client/SimpleStation14/Overlays/Shaders/StaticOverlay.cs @@ -0,0 +1,92 @@ +using Content.Shared.SimpleStation14.Silicon.Components; +using Content.Shared.SimpleStation14.Silicon.Systems; +using Content.Shared.StatusEffect; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.Player; +using Robust.Shared.Enums; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; + +namespace Content.Client.SimpleStation14.Overlays.Shaders; + +public sealed class StaticOverlay : Overlay +{ + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + + public override OverlaySpace Space => OverlaySpace.WorldSpace; + public override bool RequestScreenTexture => true; + private readonly ShaderInstance _staticShader; + + private (TimeSpan, TimeSpan)? _time; + private float? _fullTimeLeft; + private float? _curTimeLeft; + + public float MixAmount = 0; + + public StaticOverlay() + { + IoCManager.InjectDependencies(this); + _staticShader = _prototypeManager.Index("SeeingStatic").InstanceUnique(); + } + + protected override void FrameUpdate(FrameEventArgs args) + { + var playerEntity = _playerManager.LocalPlayer?.ControlledEntity; + + if (playerEntity == null) + return; + + if (!_entityManager.HasComponent(playerEntity) + || !_entityManager.TryGetComponent(playerEntity, out var statusComp)) + return; + + var status = _entityManager.EntitySysManager.GetEntitySystem(); + + if (playerEntity == null || statusComp == null) + return; + + if (!status.TryGetTime(playerEntity.Value, SeeingStaticSystem.StaticKey, out var timeTemp, statusComp)) + return; + + if (_time != timeTemp) // Resets the shader if the times change. This should factor in wheather it's a reset, or a increase, but I have a lot of cough syrup in me, so TODO. + { + _time = timeTemp; + _fullTimeLeft = null; + _curTimeLeft = null; + } + + _fullTimeLeft ??= (float) (timeTemp.Value.Item2 - timeTemp.Value.Item1).TotalSeconds; + _curTimeLeft ??= _fullTimeLeft; + + _curTimeLeft -= args.DeltaSeconds; + + MixAmount = Math.Clamp(_curTimeLeft.Value / _fullTimeLeft.Value, 0, 1); + } + + protected override bool BeforeDraw(in OverlayDrawArgs args) + { + if (!_entityManager.TryGetComponent(_playerManager.LocalPlayer?.ControlledEntity, out EyeComponent? eyeComp)) + return false; + + if (args.Viewport.Eye != eyeComp.Eye) + return false; + + return MixAmount > 0; + } + + protected override void Draw(in OverlayDrawArgs args) + { + if (ScreenTexture == null) + return; + + var handle = args.WorldHandle; + _staticShader.SetParameter("SCREEN_TEXTURE", ScreenTexture); + _staticShader.SetParameter("mixAmount", MixAmount); + handle.UseShader(_staticShader); + handle.DrawRect(args.WorldBounds, Color.White); + handle.UseShader(null); + } +} diff --git a/Content.Client/SimpleStation14/Silicon/Systems/SeeingStaticSystem.cs b/Content.Client/SimpleStation14/Silicon/Systems/SeeingStaticSystem.cs new file mode 100644 index 0000000000..dbb333ebab --- /dev/null +++ b/Content.Client/SimpleStation14/Silicon/Systems/SeeingStaticSystem.cs @@ -0,0 +1,57 @@ +using Content.Client.SimpleStation14.Overlays.Shaders; +using Content.Shared.SimpleStation14.Silicon.Components; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.Player; + +namespace Content.Client.SimpleStation14.Silicon.Systems; + +/// +/// System to handle the SeeingStatic overlay. +/// +public sealed class SeeingStaticSystem : EntitySystem +{ + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IOverlayManager _overlayMan = default!; + + private StaticOverlay _overlay = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnShutdown); + + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + + _overlay = new(); + } + + private void OnPlayerAttached(EntityUid uid, SeeingStaticComponent component, PlayerAttachedEvent args) + { + _overlayMan.AddOverlay(_overlay); + } + + private void OnPlayerDetached(EntityUid uid, SeeingStaticComponent component, PlayerDetachedEvent args) + { + _overlay.MixAmount = 0; + _overlayMan.RemoveOverlay(_overlay); + } + + private void OnInit(EntityUid uid, SeeingStaticComponent component, ComponentInit args) + { + if (_player.LocalPlayer?.ControlledEntity == uid) + _overlayMan.AddOverlay(_overlay); + } + + private void OnShutdown(EntityUid uid, SeeingStaticComponent component, ComponentShutdown args) + { + if (_player.LocalPlayer?.ControlledEntity == uid) + { + _overlay.MixAmount = 0; + _overlayMan.RemoveOverlay(_overlay); + } + } +} diff --git a/Content.Server/Administration/Commands/SetOutfitCommand.cs b/Content.Server/Administration/Commands/SetOutfitCommand.cs index 762d9234b9..4a77948047 100644 --- a/Content.Server/Administration/Commands/SetOutfitCommand.cs +++ b/Content.Server/Administration/Commands/SetOutfitCommand.cs @@ -131,7 +131,7 @@ public static bool SetOutfit(EntityUid target, string gear, IEntityManager entit } } - // Parkstation-IPC-Start + // Parkstation-Ipc-Start // Pretty much copied from StationSpawningSystem.SpawnStartingGear if (entityManager.TryGetComponent(target, out var keyHolderComp)) { @@ -158,7 +158,7 @@ public static bool SetOutfit(EntityUid target, string gear, IEntityManager entit entityManager.QueueDeleteEntity(earEntity); } } - // Parkstation-IPC-End + // Parkstation-Ipc-End return true; } diff --git a/Content.Server/Emp/EmpSystem.cs b/Content.Server/Emp/EmpSystem.cs index b327f086db..b384a23979 100644 --- a/Content.Server/Emp/EmpSystem.cs +++ b/Content.Server/Emp/EmpSystem.cs @@ -31,7 +31,7 @@ public void EmpPulse(MapCoordinates coordinates, float range, float energyConsum { foreach (var uid in _lookup.GetEntitiesInRange(coordinates, range)) { - var ev = new EmpPulseEvent(energyConsumption, false, false); + var ev = new EmpPulseEvent(energyConsumption, false, false, TimeSpan.FromSeconds(duration)); RaiseLocalEvent(uid, ref ev); if (ev.Affected) { @@ -101,7 +101,7 @@ private void OnCameraSetActive(EntityUid uid, EmpDisabledComponent component, re } [ByRefEvent] -public record struct EmpPulseEvent(float EnergyConsumption, bool Affected, bool Disabled); +public record struct EmpPulseEvent(float EnergyConsumption, bool Affected, bool Disabled, TimeSpan Duration); [ByRefEvent] public record struct EmpDisabledRemoved(); diff --git a/Content.Server/SimpleStation14/Silicon/Systems/SiliconEmpSystem.cs b/Content.Server/SimpleStation14/Silicon/Systems/SiliconEmpSystem.cs new file mode 100644 index 0000000000..5fb42ddabe --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Systems/SiliconEmpSystem.cs @@ -0,0 +1,68 @@ +using Content.Server.Emp; +using Content.Server.Speech.Muting; +using Content.Server.Stunnable; +using Content.Shared.CombatMode.Pacification; +using Content.Shared.Eye.Blinding.Components; +using Content.Shared.Eye.Blinding.Systems; +using Content.Shared.SimpleStation14.Silicon.Components; +using Content.Shared.SimpleStation14.Silicon.Systems; +using Content.Shared.Speech.EntitySystems; +using Content.Shared.StatusEffect; +using Robust.Shared.Random; + +namespace Content.Server.SimpleStation14.Silicon.Systems; + +public sealed class SiliconEmpSystem : EntitySystem +{ + [Dependency] private readonly StatusEffectsSystem _status = default!; + [Dependency] private readonly StunSystem _stun = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedStutteringSystem _stuttering = default!; + [Dependency] private readonly SharedSlurredSystem _slurredSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnEmpPulse); + } + + private void OnEmpPulse(EntityUid uid, SiliconComponent component, ref EmpPulseEvent args) + { + args.EnergyConsumption *= 0.25f; // EMPs drain a lot of freakin power. + + if (!TryComp(uid, out var statusComp)) // We check for this now, since we use it so many times. + return; + + args.Affected = true; + args.Disabled = true; + + var duration = args.Duration / 1.5; // We divide the duration since EMPs are balanced for structures, not people. + + if (duration.TotalSeconds * 0.25 >= 3) // If the EMP blast is strong enough, we stun them. + // This is mostly to prevent flickering in/out of being stunned. We also cap how long they can be stunned for. + { + _stun.TryParalyze(uid, TimeSpan.FromSeconds(Math.Min(duration.TotalSeconds * 0.25f, 15f)), true, statusComp); + } + + _stun.TrySlowdown(uid, duration, true, _random.NextFloat(0.50f, 0.70f), _random.NextFloat(0.35f, 0.70f), statusComp); + + _status.TryAddStatusEffect(uid, SeeingStaticSystem.StaticKey, duration, true, statusComp); + + if (_random.Prob(0.60f)) + _stuttering.DoStutter(uid, duration * 2, false, statusComp); + else if (_random.Prob(0.80f)) + _slurredSystem.DoSlur(uid, duration * 2, statusComp); + + if (_random.Prob(0.02f)) + _status.TryAddStatusEffect(uid, "Muted", duration * 0.5, true, statusComp); + + if (_random.Prob(0.02f)) + _status.TryAddStatusEffect(uid, TemporaryBlindnessSystem.BlindingStatusEffect, duration * 0.5, true, statusComp); + + if (_random.Prob(0.08f)) + _status.TryAddStatusEffect(uid, "Pacified", duration * 0.5, true, statusComp); + + args.EnergyConsumption = 0; + } +} diff --git a/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs b/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs index d331d8908e..2cc91df177 100644 --- a/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs @@ -1,7 +1,7 @@ using Content.Shared.SimpleStation14.Silicon.Components; using Content.Shared.Bed.Sleep; -namespace Content.Server.SimpleStation14.Silicon.Misc; +namespace Content.Server.SimpleStation14.Silicon.Sytstems; // This entire thing is fucking stupid and I hate it. public sealed class SiliconMiscSystem : EntitySystem diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index 42c753fc65..04d6118228 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -190,7 +190,7 @@ public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGe } } - // Parkstation-IPC-Start + // Parkstation-Ipc-Start // This is kinda gross, and weird, and very hardcoded, but it's the best way I could think of to do it. // This is replicated in SetOutfitCommand.SetOutfit. // If they have an EncryptionKeyHolderComponent, spawn in their headset, find the @@ -221,7 +221,7 @@ public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGe EntityManager.QueueDeleteEntity(earEntity); } } - // Parkstation-IPC-End + // Parkstation-Ipc-End if (!TryComp(entity, out HandsComponent? handsComponent)) return; diff --git a/Content.Server/Temperature/Systems/TemperatureSystem.cs b/Content.Server/Temperature/Systems/TemperatureSystem.cs index 0a79643123..54f26d902e 100644 --- a/Content.Server/Temperature/Systems/TemperatureSystem.cs +++ b/Content.Server/Temperature/Systems/TemperatureSystem.cs @@ -168,7 +168,7 @@ private void ServerAlert(EntityUid uid, AlertsComponent status, OnTemperatureCha } } - // Parkstation-IPCs-Start + // Parkstation-Ipc-Start /// /// Finds the TemperatureComponent and the ThermalRegulatorComponent, and uses _alertsSystem to set the alert level based on the range of temperatures as allowed by those components. /// Does some math to determine the alert level based on the current temperature and the range of temperatures allowed by the ThermalRegulatorComponent. @@ -241,7 +241,7 @@ private void ServerAlertNotDumb(EntityUid uid, AlertsComponent status, OnTempera return; } } - /// Parkstation-IPCs-End + /// Parkstation-Ipc-End private void EnqueueDamage(EntityUid uid, TemperatureComponent component, OnTemperatureChangeEvent args) { diff --git a/Content.Server/Zombies/ZombifyOnDeathSystem.cs b/Content.Server/Zombies/ZombifyOnDeathSystem.cs index 45a90eac73..841a714511 100644 --- a/Content.Server/Zombies/ZombifyOnDeathSystem.cs +++ b/Content.Server/Zombies/ZombifyOnDeathSystem.cs @@ -102,10 +102,10 @@ public void ZombifyEntity(EntityUid target, MobStateComponent? mobState = null) if (HasComp(target)) return; - // Parkstation-IPC-Start + // Parkstation-Ipc-Start if (HasComp(target)) return; - // Parkstation-IPC-End + // Parkstation-Ipc-End if (!Resolve(target, ref mobState, logMissing: false)) return; diff --git a/Content.Shared/Humanoid/NamingSystem.cs b/Content.Shared/Humanoid/NamingSystem.cs index 221bdb89d8..b6b6ae0f56 100644 --- a/Content.Shared/Humanoid/NamingSystem.cs +++ b/Content.Shared/Humanoid/NamingSystem.cs @@ -38,11 +38,11 @@ public string GetName(string species, Gender? gender = null) case SpeciesNaming.XnoY: return Loc.GetString("namepreset-x-no-y", ("first", GetFirstName(speciesProto, gender)), ("last", GetLastName(speciesProto))); - // Parkstation-IPC-Start + // Parkstation-Ipc-Start case SpeciesNaming.FirstDashLast: return Loc.GetString("namepreset-firstdashlast", ("first", GetFirstName(speciesProto, gender)), ("last", GetLastName(speciesProto))); - // Parkstation-IPC-End + // Parkstation-Ipc-End case SpeciesNaming.FirstLast: default: return Loc.GetString("namepreset-firstlast", diff --git a/Content.Shared/Humanoid/SkinColor.cs b/Content.Shared/Humanoid/SkinColor.cs index 6e6fc543b1..1e152a0456 100644 --- a/Content.Shared/Humanoid/SkinColor.cs +++ b/Content.Shared/Humanoid/SkinColor.cs @@ -117,7 +117,7 @@ public static bool VerifyHumanSkinTone(Color color) /// Tinted hue color public static Color TintedHues(Color color) { - // Parkstation-IPC-Start + // Parkstation-Ipc-Start var hsv = Color.ToHsv(color); hsv.Y = Math.Min(hsv.Y, 0.6f); @@ -125,7 +125,7 @@ public static Color TintedHues(Color color) hsv.Z = Math.Max(hsv.Z, 0.25f); return Color.FromHsv(hsv); - // Parkstation-IPC-End + // Parkstation-Ipc-End } /// @@ -135,11 +135,11 @@ public static Color TintedHues(Color color) /// True if valid, false otherwise public static bool VerifyTintedHues(Color color) { - // Parkstation-IPC-Start + // Parkstation-Ipc-Start var hsv = Color.ToHsv(color); return hsv.Y <= 0.6 && hsv.Z >= 0.25; - // Parkstation-IPC-End + // Parkstation-Ipc-End } public static bool VerifySkinColor(HumanoidSkinColor type, Color color) diff --git a/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs b/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs index 81ddb23a00..79548e4cb9 100644 --- a/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs +++ b/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs @@ -42,14 +42,14 @@ public sealed class EncryptionKeyHolderComponent : Component public Container KeyContainer = default!; public const string KeyContainerName = "key_slots"; - // Parkstation-IPC-Start + // Parkstation-Ipc-Start /// /// Whether or not the headset can be examined to see the encryption keys while the keys aren't accessible. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("examineWhileLocked")] public bool ExamineWhileLocked = true; - // Parkstation-IPC-End + // Parkstation-Ipc-End /// /// Combined set of radio channels provided by all contained keys. diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index 47b829b32a..921fb5262c 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -175,13 +175,13 @@ private void OnHolderExamined(EntityUid uid, EncryptionKeyHolderComponent compon if (!args.IsInDetailsRange) return; - // Parkstation-IPC-Start + // Parkstation-Ipc-Start if (!component.ExamineWhileLocked && !component.KeysUnlocked) return; if (!component.ExamineWhileLocked && TryComp(uid, out var panel) && !panel.Open) return; - // Parkstation-IPC-End + // Parkstation-Ipc-End if (component.KeyContainer.ContainedEntities.Count == 0) { diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SeeingStaticComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SeeingStaticComponent.cs new file mode 100644 index 0000000000..dfc58105d3 --- /dev/null +++ b/Content.Shared/SimpleStation14/Silicon/Components/SeeingStaticComponent.cs @@ -0,0 +1,9 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.SimpleStation14.Silicon.Components; + +/// +/// Exists for use as a status effect. Adds a tv static shader to the client. +/// +[RegisterComponent, NetworkedComponent] +public sealed class SeeingStaticComponent : Component { } diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SeeingStaticSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SeeingStaticSystem.cs new file mode 100644 index 0000000000..9032163607 --- /dev/null +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SeeingStaticSystem.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.SimpleStation14.Silicon.Systems; + +public sealed class SeeingStaticSystem : EntitySystem +{ + public const string StaticKey = "SeeingStatic"; +} diff --git a/Resources/Prototypes/SimpleStation14/Damage/containers.yml b/Resources/Prototypes/SimpleStation14/Damage/containers.yml index d7e93239b7..c1c4c59404 100644 --- a/Resources/Prototypes/SimpleStation14/Damage/containers.yml +++ b/Resources/Prototypes/SimpleStation14/Damage/containers.yml @@ -8,3 +8,9 @@ # - Genetic # supportedTypes: # - Bloodloss + +- type: damageContainer + id: Silicon + supportedGroups: + - Brute + - Burn diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 703db6b958..d029a14d30 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -18,7 +18,7 @@ path: /Audio/Effects/hit_kick.ogg - type: Clickable - type: Damageable - damageContainer: Inorganic + damageContainer: Inorganic # Note that for dumb reasons, this essentially makes them a wall. # - type: Bloodstream # This is left commented out because it's not necessary for a robot, but you may want it. # bloodReagent: MotorOil # bloodlossDamage: @@ -82,10 +82,10 @@ specificHeat: 24 coldDamage: types: - Cold: 0.1 #per second, scales with temperature & other constants + Cold: 0.1 # Per second, scales with temperature & other constants. heatDamage: types: - Heat: 0.25 #per second, scales with temperature & other constants + Heat: 0.25 # Per second, scales with temperature & other constants. atmosTemperatureTransferEfficiency: 0.05 - type: ThermalRegulator metabolismHeat: 600 @@ -109,6 +109,8 @@ thresholds: 0: Alive 165: Dead + - type: Damageable + damageContainer: Silicon # Not a wall. - type: Destructible thresholds: - trigger: !type:DamageTrigger @@ -253,7 +255,7 @@ - type: GenericVisualizer visuals: enum.CreamPiedVisuals.Creamed: - clownedon: # Not 'creampied' bc I can already see Skyrat complaining about conflicts. + clownedon: True: { visible: true } False: { visible: false } - type: RotationVisuals @@ -362,11 +364,12 @@ - Electrocution # - Drunk - SlurredSpeech - - PressureImmunity + # - PressureImmunity - Muted # - ForcedSleep - TemporaryBlindness - Pacified # - PsionicsDisabled # - PsionicallyInsulated + - SeeingStatic - type: Blindable diff --git a/Resources/Prototypes/SimpleStation14/Shaders/shaders.yml b/Resources/Prototypes/SimpleStation14/Shaders/shaders.yml index b394e308c7..ee9c1b2f6a 100644 --- a/Resources/Prototypes/SimpleStation14/Shaders/shaders.yml +++ b/Resources/Prototypes/SimpleStation14/Shaders/shaders.yml @@ -7,3 +7,8 @@ id: Ethereal kind: source path: "/Textures/SimpleStation14/Shaders/ethereal.swsl" + +- type: shader + id: SeeingStatic + kind: source + path: "/Textures/SimpleStation14/Shaders/seeing_static.swsl" diff --git a/Resources/Prototypes/SimpleStation14/status_effects.yml b/Resources/Prototypes/SimpleStation14/status_effects.yml new file mode 100644 index 0000000000..de4048f912 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/status_effects.yml @@ -0,0 +1,2 @@ +- type: statusEffect + id: SeeingStatic diff --git a/Resources/Textures/SimpleStation14/Shaders/seeing_static.swsl b/Resources/Textures/SimpleStation14/Shaders/seeing_static.swsl new file mode 100644 index 0000000000..765cb94f71 --- /dev/null +++ b/Resources/Textures/SimpleStation14/Shaders/seeing_static.swsl @@ -0,0 +1,43 @@ +// Credited to PelicanPolice on Shadertoy +// Free for any purpose, commercial or otherwise. +// But do post here so I can see where it got used! +// If using on shadertoy, do link to this project on yours :) + +// A copy of the camera static shader, but takes a screen texture, and an amount to mix by. + +uniform sampler2D SCREEN_TEXTURE; +uniform highp float mixAmount; + +highp float noise(highp vec2 pos, highp float evolve) { + + // Loop the evolution (over a very long period of time). + highp float e = fract((evolve*0.01)); + + // Coordinates + highp float cx = pos.x*e; + highp float cy = sin(pos.y*e * 376.0); // is this close enough to a 60hz interference? :smol: + + highp float v2_2 = cx*2.4/cy*23.0+pow(abs(cy/22.4),3.3); + highp float v2_1 = fract(fract(v2_2)); + highp float v2 = fract(2.0/v2_1); + highp float v3 = fract(cx*evolve/pow(abs(cy),0.050)); + + // Generate a "random" black or white value + return fract(0.1*v2*v3); +} + + +void fragment() { + highp vec4 color = zTextureSpec(SCREEN_TEXTURE, UV); + highp vec2 coords = FRAGCOORD.xy; + + highp vec3 staticAmount; + for (int i = 0; i < 1; i++) + { + // Generate a black to white pixel + staticAmount = vec3(noise(coords,TIME)); + } + + // Output to screen + COLOR = mix(color, vec4(staticAmount, 1.0), mixAmount); +} From 2e48a58adb55897cad8930928236c7a21ac1c106 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 30 Jul 2023 15:58:35 -0400 Subject: [PATCH 2/5] Adds Silicons to the SolarFlareRule --- .../Overlays/Shaders/StaticOverlay.cs | 4 +-- .../Silicon/Systems/SiliconEmpSystem.cs | 2 +- .../Components/SolarFlareRuleComponent.cs | 15 ++++++++++ .../StationEvents/Events/SolarFlareRule.cs | 30 +++++++++++++++++++ .../Components/SeeingStaticComponent.cs | 13 ++++++-- Resources/Prototypes/GameRules/events.yml | 2 ++ 6 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Content.Client/SimpleStation14/Overlays/Shaders/StaticOverlay.cs b/Content.Client/SimpleStation14/Overlays/Shaders/StaticOverlay.cs index 2c299f792f..151d3ef8a9 100644 --- a/Content.Client/SimpleStation14/Overlays/Shaders/StaticOverlay.cs +++ b/Content.Client/SimpleStation14/Overlays/Shaders/StaticOverlay.cs @@ -39,7 +39,7 @@ protected override void FrameUpdate(FrameEventArgs args) if (playerEntity == null) return; - if (!_entityManager.HasComponent(playerEntity) + if (!_entityManager.TryGetComponent(playerEntity, out var staticComp) || !_entityManager.TryGetComponent(playerEntity, out var statusComp)) return; @@ -63,7 +63,7 @@ protected override void FrameUpdate(FrameEventArgs args) _curTimeLeft -= args.DeltaSeconds; - MixAmount = Math.Clamp(_curTimeLeft.Value / _fullTimeLeft.Value, 0, 1); + MixAmount = Math.Clamp(_curTimeLeft.Value / _fullTimeLeft.Value * staticComp.Multiplier, 0, 1); } protected override bool BeforeDraw(in OverlayDrawArgs args) diff --git a/Content.Server/SimpleStation14/Silicon/Systems/SiliconEmpSystem.cs b/Content.Server/SimpleStation14/Silicon/Systems/SiliconEmpSystem.cs index 5fb42ddabe..20af4c252b 100644 --- a/Content.Server/SimpleStation14/Silicon/Systems/SiliconEmpSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Systems/SiliconEmpSystem.cs @@ -31,7 +31,7 @@ private void OnEmpPulse(EntityUid uid, SiliconComponent component, ref EmpPulseE { args.EnergyConsumption *= 0.25f; // EMPs drain a lot of freakin power. - if (!TryComp(uid, out var statusComp)) // We check for this now, since we use it so many times. + if (!TryComp(uid, out var statusComp)) return; args.Affected = true; diff --git a/Content.Server/StationEvents/Components/SolarFlareRuleComponent.cs b/Content.Server/StationEvents/Components/SolarFlareRuleComponent.cs index 92a3b43375..cc7d3bf0f9 100644 --- a/Content.Server/StationEvents/Components/SolarFlareRuleComponent.cs +++ b/Content.Server/StationEvents/Components/SolarFlareRuleComponent.cs @@ -1,3 +1,4 @@ +using System.Numerics; using Content.Server.StationEvents.Events; using Content.Shared.Radio; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; @@ -33,4 +34,18 @@ public sealed class SolarFlareRuleComponent : Component /// [DataField("doorToggleChancePerSecond")] public float DoorToggleChancePerSecond; + + // Parkstation-Ipc-Start + /// + /// Chance that Silicons will get static vision per second during event + /// + [DataField("siliconStaticChancePerSecond")] + public float SiliconStaticChancePerSecond; + + /// + /// How long Silicons will get static vision for + /// + [DataField("siliconStaticDuration")] + public Vector2 SiliconStaticDuration; + // Parkstation-Ipc-End } diff --git a/Content.Server/StationEvents/Events/SolarFlareRule.cs b/Content.Server/StationEvents/Events/SolarFlareRule.cs index 206a8ca685..f5585ace6f 100644 --- a/Content.Server/StationEvents/Events/SolarFlareRule.cs +++ b/Content.Server/StationEvents/Events/SolarFlareRule.cs @@ -7,6 +7,9 @@ using Content.Shared.Radio.Components; using Content.Shared.Doors.Components; using Content.Shared.Doors.Systems; +using Content.Shared.SimpleStation14.Silicon.Components; +using Content.Shared.StatusEffect; // Parkstation-Ipc +using Content.Shared.SimpleStation14.Silicon.Systems; // Parkstation-Ipc namespace Content.Server.StationEvents.Events; @@ -14,6 +17,7 @@ public sealed class SolarFlareRule : StationEventSystem { [Dependency] private readonly PoweredLightSystem _poweredLight = default!; [Dependency] private readonly SharedDoorSystem _door = default!; + [Dependency] private readonly StatusEffectsSystem _status = default!; // Parkstation-Ipc private float _effectTimer = 0; @@ -43,6 +47,32 @@ protected override void ActiveTick(EntityUid uid, SolarFlareRuleComponent compon if (airlock.AutoClose && RobustRandom.Prob(component.DoorToggleChancePerSecond)) _door.TryToggleDoor(airlockEnt, door); } + // Parkstation-Ipc-Start // Makes Silicons respond to Solar Flares. + var siliconQuery = EntityQueryEnumerator(); + while (siliconQuery.MoveNext(out var siliconEnt, out _)) + { + if (HasComp(siliconEnt)) + continue; // So we don't mess with any ongoing effects. + + if (RobustRandom.Prob(component.DoorToggleChancePerSecond)) + { + _status.TryAddStatusEffect + ( + siliconEnt, + SeeingStaticSystem.StaticKey, + TimeSpan.FromSeconds(RobustRandom.NextFloat(component.SiliconStaticDuration.X, component.SiliconStaticDuration.Y)), + true, + null + ); + + if (TryComp(siliconEnt, out var staticComp)) + { + staticComp.Multiplier = 0.80f; + Dirty(staticComp); + } + } + } + // Parkstation-Ipc-End } } diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SeeingStaticComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SeeingStaticComponent.cs index dfc58105d3..657be40066 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SeeingStaticComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SeeingStaticComponent.cs @@ -5,5 +5,14 @@ namespace Content.Shared.SimpleStation14.Silicon.Components; /// /// Exists for use as a status effect. Adds a tv static shader to the client. /// -[RegisterComponent, NetworkedComponent] -public sealed class SeeingStaticComponent : Component { } +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SeeingStaticComponent : Component +{ + /// + /// The multiplier applied to the effect. + /// Setting this to 0.5 will halve the effect throughout its entire duration, meaning it will never be fully opaque. + /// Setting this to 2 will double the effect throughout its entire duration, meaning it will be fully opaque for twice as long. + /// + [AutoNetworkedField] + public float Multiplier = 1f; +} diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index c0dcfa3688..f6b7139781 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -206,6 +206,8 @@ - Service lightBreakChancePerSecond: 0.00003 doorToggleChancePerSecond: 0.0001 + siliconStaticChancePerSecond: 0.00024 + siliconStaticDuration: 3, 8 # - type: entity # id: VentClog From 003b9cc0528be72b508736fcca2d550bc16ba118 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sat, 23 Sep 2023 07:07:09 -0400 Subject: [PATCH 3/5] IPCs can be now be cured of bleeding, and are affected by Solar Flares with an EMP. --- .../Silicon/Systems/SiliconMiscSystem.cs | 25 ++++++++++++++++++- .../StationEvents/Events/SolarFlareRule.cs | 24 +++++------------- .../Repairable/SharedRepairableSystem.cs | 2 +- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs b/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs index 2cc91df177..717cf4ca45 100644 --- a/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs @@ -1,20 +1,43 @@ using Content.Shared.SimpleStation14.Silicon.Components; using Content.Shared.Bed.Sleep; +using static Content.Shared.Repairable.SharedRepairableSystem; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; namespace Content.Server.SimpleStation14.Silicon.Sytstems; -// This entire thing is fucking stupid and I hate it. public sealed class SiliconMiscSystem : EntitySystem { + [Dependency] private readonly BloodstreamSystem _blood = default!; + public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnTryingToSleep); + SubscribeLocalEvent(OnRepairFinished); } + /// + /// Stops Silicons from being capable of sleeping. + /// + /// + /// This is stupid. + /// private void OnTryingToSleep(EntityUid uid, SiliconComponent component, ref TryingToSleepEvent args) { args.Cancelled = true; } + + /// + /// Ensure Silicons stop bleeding when repaired, if they can bleed. + /// + private void OnRepairFinished(EntityUid uid, SiliconComponent component, RepairFinishedEvent args) + { + if (TryComp(uid, out var bloodComp)) + { + _blood.TryModifyBleedAmount(uid, -bloodComp.BleedAmount, bloodComp); + } + } + } diff --git a/Content.Server/StationEvents/Events/SolarFlareRule.cs b/Content.Server/StationEvents/Events/SolarFlareRule.cs index f5585ace6f..f4708d977d 100644 --- a/Content.Server/StationEvents/Events/SolarFlareRule.cs +++ b/Content.Server/StationEvents/Events/SolarFlareRule.cs @@ -7,9 +7,10 @@ using Content.Shared.Radio.Components; using Content.Shared.Doors.Components; using Content.Shared.Doors.Systems; -using Content.Shared.SimpleStation14.Silicon.Components; -using Content.Shared.StatusEffect; // Parkstation-Ipc -using Content.Shared.SimpleStation14.Silicon.Systems; // Parkstation-Ipc +using Content.Shared.SimpleStation14.Silicon.Components; // Parkstation-Ipc +using Content.Shared.Emp; // Parkstation-Ipc +using Content.Server.Emp; // Parkstation-Ipc +using Content.Shared.Coordinates; // Parkstation-Ipc namespace Content.Server.StationEvents.Events; @@ -17,7 +18,7 @@ public sealed class SolarFlareRule : StationEventSystem { [Dependency] private readonly PoweredLightSystem _poweredLight = default!; [Dependency] private readonly SharedDoorSystem _door = default!; - [Dependency] private readonly StatusEffectsSystem _status = default!; // Parkstation-Ipc + [Dependency] private readonly EmpSystem _emp = default!; // Parkstation-Ipc private float _effectTimer = 0; @@ -56,20 +57,7 @@ protected override void ActiveTick(EntityUid uid, SolarFlareRuleComponent compon if (RobustRandom.Prob(component.DoorToggleChancePerSecond)) { - _status.TryAddStatusEffect - ( - siliconEnt, - SeeingStaticSystem.StaticKey, - TimeSpan.FromSeconds(RobustRandom.NextFloat(component.SiliconStaticDuration.X, component.SiliconStaticDuration.Y)), - true, - null - ); - - if (TryComp(siliconEnt, out var staticComp)) - { - staticComp.Multiplier = 0.80f; - Dirty(staticComp); - } + _emp.EmpPulse(Transform(siliconEnt).MapPosition, 0.5f, 40, RobustRandom.NextFloat(2, 20)); } } // Parkstation-Ipc-End diff --git a/Content.Shared/Repairable/SharedRepairableSystem.cs b/Content.Shared/Repairable/SharedRepairableSystem.cs index ec59a60a8f..3cfc8de258 100644 --- a/Content.Shared/Repairable/SharedRepairableSystem.cs +++ b/Content.Shared/Repairable/SharedRepairableSystem.cs @@ -6,7 +6,7 @@ namespace Content.Shared.Repairable; public abstract class SharedRepairableSystem : EntitySystem { [Serializable, NetSerializable] - protected sealed class RepairFinishedEvent : SimpleDoAfterEvent + public sealed class RepairFinishedEvent : SimpleDoAfterEvent // Parkstation-IPC // Protected? PROTECTED?? The absolute gall! { } } From a63ba8850aaa7fffc7b578a6ca6e0b5c950fb4ec Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:43:40 -0400 Subject: [PATCH 4/5] TODO comment --- Content.Server/StationEvents/Events/SolarFlareRule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/StationEvents/Events/SolarFlareRule.cs b/Content.Server/StationEvents/Events/SolarFlareRule.cs index f4708d977d..1ee1464842 100644 --- a/Content.Server/StationEvents/Events/SolarFlareRule.cs +++ b/Content.Server/StationEvents/Events/SolarFlareRule.cs @@ -57,7 +57,7 @@ protected override void ActiveTick(EntityUid uid, SolarFlareRuleComponent compon if (RobustRandom.Prob(component.DoorToggleChancePerSecond)) { - _emp.EmpPulse(Transform(siliconEnt).MapPosition, 0.5f, 40, RobustRandom.NextFloat(2, 20)); + _emp.EmpPulse(Transform(siliconEnt).MapPosition, 0.5f, 40, RobustRandom.NextFloat(2, 20)); //TODO: Make this targets individual Silicons once Wizden merge. } } // Parkstation-Ipc-End From fcb10ce36b648824f07d30e96006fb85c6661de0 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:48:33 -0400 Subject: [PATCH 5/5] Apply suggestions from code review --- Content.Server/Emp/EmpSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Server/Emp/EmpSystem.cs b/Content.Server/Emp/EmpSystem.cs index b384a23979..96185e1644 100644 --- a/Content.Server/Emp/EmpSystem.cs +++ b/Content.Server/Emp/EmpSystem.cs @@ -31,7 +31,7 @@ public void EmpPulse(MapCoordinates coordinates, float range, float energyConsum { foreach (var uid in _lookup.GetEntitiesInRange(coordinates, range)) { - var ev = new EmpPulseEvent(energyConsumption, false, false, TimeSpan.FromSeconds(duration)); + var ev = new EmpPulseEvent(energyConsumption, false, false, TimeSpan.FromSeconds(duration)); // Parkstation-IPCs RaiseLocalEvent(uid, ref ev); if (ev.Affected) { @@ -101,7 +101,7 @@ private void OnCameraSetActive(EntityUid uid, EmpDisabledComponent component, re } [ByRefEvent] -public record struct EmpPulseEvent(float EnergyConsumption, bool Affected, bool Disabled, TimeSpan Duration); +public record struct EmpPulseEvent(float EnergyConsumption, bool Affected, bool Disabled, TimeSpan Duration); // Parkstation-IPCs [ByRefEvent] public record struct EmpDisabledRemoved();