Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EMP effect for Silicons #190

Merged
merged 8 commits into from
Oct 28, 2023
Original file line number Diff line number Diff line change
@@ -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<ShaderPrototype>("SeeingStatic").InstanceUnique();
}

protected override void FrameUpdate(FrameEventArgs args)
{
var playerEntity = _playerManager.LocalPlayer?.ControlledEntity;

if (playerEntity == null)
return;

if (!_entityManager.TryGetComponent<SeeingStaticComponent>(playerEntity, out var staticComp)
|| !_entityManager.TryGetComponent<StatusEffectsComponent>(playerEntity, out var statusComp))
return;

var status = _entityManager.EntitySysManager.GetEntitySystem<StatusEffectsSystem>();

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 * staticComp.Multiplier, 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);
}
}
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// System to handle the SeeingStatic overlay.
/// </summary>
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<SeeingStaticComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<SeeingStaticComponent, ComponentShutdown>(OnShutdown);

SubscribeLocalEvent<SeeingStaticComponent, PlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<SeeingStaticComponent, PlayerDetachedEvent>(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);
}
}
}
4 changes: 2 additions & 2 deletions Content.Server/Administration/Commands/SetOutfitCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,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<EncryptionKeyHolderComponent>(target, out var keyHolderComp))
{
Expand All @@ -159,7 +159,7 @@ public static bool SetOutfit(EntityUid target, string gear, IEntityManager entit
entityManager.QueueDeleteEntity(earEntity);
}
}
// Parkstation-IPC-End
// Parkstation-Ipc-End

return true;
}
Expand Down
4 changes: 2 additions & 2 deletions Content.Server/Emp/EmpSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)); // Parkstation-IPCs
RaiseLocalEvent(uid, ref ev);
if (ev.Affected)
{
Expand Down Expand Up @@ -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); // Parkstation-IPCs

[ByRefEvent]
public record struct EmpDisabledRemoved();
Original file line number Diff line number Diff line change
@@ -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<SiliconComponent, EmpPulseEvent>(OnEmpPulse);
}

private void OnEmpPulse(EntityUid uid, SiliconComponent component, ref EmpPulseEvent args)
{
args.EnergyConsumption *= 0.25f; // EMPs drain a lot of freakin power.

if (!TryComp<StatusEffectsComponent>(uid, out var statusComp))
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<SeeingStaticComponent>(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<MutedComponent>(uid, "Muted", duration * 0.5, true, statusComp);

if (_random.Prob(0.02f))
_status.TryAddStatusEffect<TemporaryBlindnessComponent>(uid, TemporaryBlindnessSystem.BlindingStatusEffect, duration * 0.5, true, statusComp);

if (_random.Prob(0.08f))
_status.TryAddStatusEffect<PacifiedComponent>(uid, "Pacified", duration * 0.5, true, statusComp);

args.EnergyConsumption = 0;
}
}
Original file line number Diff line number Diff line change
@@ -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.Misc;
namespace Content.Server.SimpleStation14.Silicon.Sytstems;
Pspritechologist marked this conversation as resolved.
Show resolved Hide resolved

// 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<SiliconComponent, TryingToSleepEvent>(OnTryingToSleep);
SubscribeLocalEvent<SiliconComponent, RepairFinishedEvent>(OnRepairFinished);
}

/// <summary>
/// Stops Silicons from being capable of sleeping.
/// </summary>
/// <remarks>
/// This is stupid.
/// </remarks>
private void OnTryingToSleep(EntityUid uid, SiliconComponent component, ref TryingToSleepEvent args)
{
args.Cancelled = true;
}

/// <summary>
/// Ensure Silicons stop bleeding when repaired, if they can bleed.
/// </summary>
private void OnRepairFinished(EntityUid uid, SiliconComponent component, RepairFinishedEvent args)
{
if (TryComp<BloodstreamComponent>(uid, out var bloodComp))
{
_blood.TryModifyBleedAmount(uid, -bloodComp.BleedAmount, bloodComp);
}
}

}
4 changes: 2 additions & 2 deletions Content.Server/Station/Systems/StationSpawningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,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
Expand Down Expand Up @@ -219,7 +219,7 @@ public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGe
EntityManager.QueueDeleteEntity(earEntity);
}
}
// Parkstation-IPC-End
// Parkstation-Ipc-End

if (!TryComp(entity, out HandsComponent? handsComponent))
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Numerics;
Pspritechologist marked this conversation as resolved.
Show resolved Hide resolved
using Content.Server.StationEvents.Events;
using Content.Shared.Radio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
Expand Down Expand Up @@ -33,4 +34,18 @@ public sealed class SolarFlareRuleComponent : Component
/// </summary>
[DataField("doorToggleChancePerSecond")]
public float DoorToggleChancePerSecond;

// Parkstation-Ipc-Start
/// <summary>
/// Chance that Silicons will get static vision per second during event
/// </summary>
[DataField("siliconStaticChancePerSecond")]
public float SiliconStaticChancePerSecond;

/// <summary>
/// How long Silicons will get static vision for
/// </summary>
[DataField("siliconStaticDuration")]
public Vector2 SiliconStaticDuration;
// Parkstation-Ipc-End
}
18 changes: 18 additions & 0 deletions Content.Server/StationEvents/Events/SolarFlareRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@
using Content.Shared.Radio.Components;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
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;

public sealed class SolarFlareRule : StationEventSystem<SolarFlareRuleComponent>
{
[Dependency] private readonly PoweredLightSystem _poweredLight = default!;
[Dependency] private readonly SharedDoorSystem _door = default!;
[Dependency] private readonly EmpSystem _emp = default!; // Parkstation-Ipc

private float _effectTimer = 0;

Expand Down Expand Up @@ -43,6 +48,19 @@ 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<SiliconComponent>();
while (siliconQuery.MoveNext(out var siliconEnt, out _))
{
if (HasComp<SeeingStaticComponent>(siliconEnt))
continue; // So we don't mess with any ongoing effects.

if (RobustRandom.Prob(component.DoorToggleChancePerSecond))
{
_emp.EmpPulse(Transform(siliconEnt).MapPosition, 0.5f, 40, RobustRandom.NextFloat(2, 20)); //TODO: Make this targets individual Silicons once Wizden merge.
}
}
// Parkstation-Ipc-End
}
}

Expand Down
Loading
Loading