Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions Content.Server/_Scp/Other/ScpClog/ScpClogSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using Content.Shared.Popups;
using Content.Shared._Scp.Other.ScpClog;
using Content.Shared._Scp.Watching;
using Content.Shared.Storage.Components;
using Content.Shared.Whitelist;
using Robust.Server.Containers;
using Content.Server.Popups;
using Content.Server.Fluids.EntitySystems;
using Robust.Server.Audio;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Chemistry.Components;
using Content.Shared._Scp.Helpers;
using Content.Shared._Scp.Proximity;
using System.Linq;
using Content.Server.Examine;
using Content.Shared.Doors.Components;
using Content.Server.Doors.Systems;
using Content.Shared.Lock;
using Content.Shared._Scp.Other.BunkerMarker;
using Content.Server.Explosion.EntitySystems;
using Robust.Server.GameObjects;
using Content.Shared.Explosion.EntitySystems;

namespace Content.Server._Scp.Other.ScpClog;

public sealed class ScpClogSystem : EntitySystem
{
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly EyeWatchingSystem _watching = default!;
[Dependency] private readonly ContainerSystem _containerSystem = default!;
[Dependency] private readonly PuddleSystem _puddle = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly ExamineSystem _examine = default!;
[Dependency] private readonly ExplosionSystem _explosion = default!;
[Dependency] private readonly DoorSystem _door = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly ScpHelpers _helpers = default!;
[Dependency] private readonly LockSystem _lock = default!;

private EntityQuery<InsideEntityStorageComponent> _insideQuery;
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<ScpClogComponent, ScpClogActionEvent>(OnClog);

_insideQuery = GetEntityQuery<InsideEntityStorageComponent>();
}

private void OnClog(Entity<ScpClogComponent> ent, ref ScpClogActionEvent args)
{
if (args.Handled)
return;

if (IsInContainer(ent, out var storage))
{
var message = Loc.GetString("scp-cage-suppress-ability", ("container", Name(storage.Value)));
_popup.PopupEntity(message, ent, ent, PopupType.LargeCaution);

return;
}

if (_watching.IsWatchedByAny(ent))
{
var message = Loc.GetString("scp173-fast-movement-too-many-watchers");
_popup.PopupEntity(message, ent, ent, PopupType.LargeCaution);
return;
}

var coords = Transform(ent).Coordinates;

var tempSol = new Solution();
tempSol.AddReagent(ent.Comp.Reagent, 25);
_puddle.TrySpillAt(coords, tempSol, out _, false);

_audio.PlayPvs(ent.Comp.ClogSound, ent);

var total = _helpers.GetAroundSolutionVolume(ent, ent.Comp.Reagent, LineOfSightBlockerLevel.None);

if (total >= ent.Comp.MinTotalSolutionVolume)
{
var lookup = _lookup.GetEntitiesInRange(coords, ent.Comp.ClogDeconstructEffectRadius, flags: LookupFlags.Dynamic | LookupFlags.Static)
.Where(target => _examine.InRangeUnOccluded(ent, target, ent.Comp.ClogDeconstructEffectRadius));

foreach (var target in lookup)
{
if (TryComp<DoorBoltComponent>(target, out var doorBoltComp) && doorBoltComp.BoltsDown)
_door.SetBoltsDown((target, doorBoltComp), false, predicted: true);

if (TryComp<LockComponent>(target, out var lockComp) && lockComp.Locked)
_lock.Unlock(target, args.Performer, lockComp);

if (TryComp<DoorComponent>(target, out var doorComp) && doorComp.State is not DoorState.Open && !HasComp<BunkerMarkerComponent>(target))
_door.StartOpening(target);
}
}
if (total >= ent.Comp.ExtraMinTotalSolutionVolume)
{
_explosion.QueueExplosion(_transform.GetMapCoordinates(ent), SharedExplosionSystem.DefaultExplosionPrototypeId, 300f, 0.6f, 50f, ent);
}

args.Handled = true;
}

public bool IsInContainer(Entity<ScpClogComponent> ent, [NotNullWhen(true)] out EntityUid? storage)
{
storage = null;

if (!_insideQuery.TryComp(ent, out var insideEntityStorageComponent))
return false;

if (!_containerSystem.TryGetContainingContainer(ent.Owner, out var container))
return false;

if (!_whitelist.CheckBoth(container.Owner, ent.Comp.InContainersClogBlacklist, ent.Comp.InContainersClogWhitelist))
return false;

storage = insideEntityStorageComponent.Storage;
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
using Content.Server._Scp.Scp173;
using Content.Shared._Scp.Other.ScpBlind;
using Content.Shared.Xenoarchaeology.Artifact;
using Content.Shared.Xenoarchaeology.Artifact.XAE;

namespace Content.Server._Scp.Research.Artifacts.Effects._ScpSpecific.Scp173.Blind;

public sealed class ArtifactScp173BlindEveryoneInRangeSystem : BaseXAESystem<ArtifactScp173BlindEveryoneInRangeComponent>
{
[Dependency] private readonly Scp173System _scp173 = default!;
[Dependency] private readonly SharedScpBlindSystem _scpBlind = default!;

protected override void OnActivated(Entity<ArtifactScp173BlindEveryoneInRangeComponent> ent, ref XenoArtifactNodeActivatedEvent args)
{
_scp173.BlindEveryoneInRange(ent, ent.Comp.Time, false);
_scpBlind.BlindEveryoneInRange(ent, ent.Comp.Time, false);
}
}
66 changes: 1 addition & 65 deletions Content.Server/_Scp/Scp173/Scp173System.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
using System.Linq;
using System.Numerics;
using Content.Server.Doors.Systems;
using Content.Server.Examine;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Fluids.EntitySystems;
using Content.Server.Ghost;
using Content.Server.Interaction;
using Content.Server.Popups;
Expand All @@ -14,13 +11,11 @@
using Content.Shared._Scp.Other.DamageOnCollide;
using Content.Shared._Scp.Proximity;
using Content.Shared._Scp.Scp173;
using Content.Shared.Chemistry.Components;
using Content.Shared.Coordinates.Helpers;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Doors.Components;
using Content.Shared.Examine;
using Content.Shared.Explosion.EntitySystems;
using Content.Shared.Light.Components;
using Content.Shared.Lock;
using Content.Shared.Physics;
Expand All @@ -43,20 +38,16 @@ public sealed partial class Scp173System : SharedScp173System
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly PuddleSystem _puddle = default!;
[Dependency] private readonly LockSystem _lock = default!;
[Dependency] private readonly DoorSystem _door = default!;
[Dependency] private readonly ExamineSystem _examine = default!;
[Dependency] private readonly InteractionSystem _interaction = default!;
[Dependency] private readonly PhysicsSystem _physics = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly AudioSystem _audio= default!;
[Dependency] private readonly ExplosionSystem _explosion = default!;
[Dependency] private readonly ScpHelpers _helpers = default!;
[Dependency] private readonly ScpDamageOnCollideSystem _damageOnCollide = default!;

private readonly SoundSpecifier _storageOpenSound = new SoundCollectionSpecifier("MetalBreak");
private readonly SoundSpecifier _clogSound = new SoundPathSpecifier("/Audio/_Scp/Scp173/clog.ogg");

private const float ToggleDoorStuffChance = 0.35f;

Expand All @@ -67,7 +58,7 @@ public override void Initialize()
base.Initialize();

SubscribeLocalEvent<Scp173Component, Scp173DamageStructureAction>(OnStructureDamage);
SubscribeLocalEvent<Scp173Component, Scp173ClogAction>(OnClog);

SubscribeLocalEvent<Scp173Component, Scp173FastMovementAction>(OnFastMovement);
}

Expand Down Expand Up @@ -173,61 +164,6 @@ private void OnStructureDamage(Entity<Scp173Component> uid, ref Scp173DamageStru
args.Handled = true;
}

private void OnClog(Entity<Scp173Component> ent, ref Scp173ClogAction args)
{
if (args.Handled)
return;

if (IsInScpCage(ent, out var storage))
{
var message = Loc.GetString("scp-cage-suppress-ability", ("container", Name(storage.Value)));
_popup.PopupEntity(message, ent, ent, PopupType.LargeCaution);

return;
}

if (Watching.IsWatchedByAny(ent))
{
var message = Loc.GetString("scp173-fast-movement-too-many-watchers");
_popup.PopupEntity(message, ent, ent, PopupType.LargeCaution);
return;
}

var coords = Transform(ent).Coordinates;

var tempSol = new Solution();
tempSol.AddReagent(Scp173Component.Reagent, 25);
_puddle.TrySpillAt(coords, tempSol, out _, false);

_audio.PlayPvs(_clogSound, ent);

var total = _helpers.GetAroundSolutionVolume(ent, Scp173Component.Reagent, LineOfSightBlockerLevel.None);

if (total >= Scp173Component.MinTotalSolutionVolume)
{
var lookup = _lookup.GetEntitiesInRange(coords, ContainmentRoomSearchRadius, flags: LookupFlags.Dynamic | LookupFlags.Static)
.Where(target => _examine.InRangeUnOccluded(ent, target, ContainmentRoomSearchRadius));

foreach (var target in lookup)
{
if (TryComp<DoorBoltComponent>(target, out var doorBoltComp) && doorBoltComp.BoltsDown)
_door.SetBoltsDown((target, doorBoltComp), false, predicted: true);

if (TryComp<LockComponent>(target, out var lockComp) && lockComp.Locked)
_lock.Unlock(target, args.Performer, lockComp);

if (TryComp<DoorComponent>(target, out var doorComp) && doorComp.State is not DoorState.Open && !HasComp<BunkerMarkerComponent>(target))
_door.StartOpening(target);
}
}
if (total >= Scp173Component.ExtraMinTotalSolutionVolume)
{
_explosion.QueueExplosion(_transform.GetMapCoordinates(ent), SharedExplosionSystem.DefaultExplosionPrototypeId, 300f, 0.6f, 50f, ent);
}

args.Handled = true;
}

/// <summary>
/// Обработчик способности быстрого перемещения (прыжка) SCP-173.
/// Проверяет все условия, запрещающие прыжок, рассчитывает конечную позицию
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Content.Shared.Actions;
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;

namespace Content.Shared._Scp.Other.ScpBlind;

public sealed partial class ScpBlindActionEvent : InstantActionEvent;

[Serializable, NetSerializable]
public sealed partial class ScpActionStartBlind : SimpleDoAfterEvent;
10 changes: 10 additions & 0 deletions Content.Shared/_Scp/Other/ScpBlind/ScpBlindAllowerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

using Robust.Shared.GameStates;

namespace Content.Shared._Scp.Other.ScpBlind;

[RegisterComponent, NetworkedComponent]
public sealed partial class ScpBlindAllowerComponent : Component
{

}
10 changes: 10 additions & 0 deletions Content.Shared/_Scp/Other/ScpBlind/ScpBlindBlockerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

using Robust.Shared.GameStates;

namespace Content.Shared._Scp.Other.ScpBlind;

[RegisterComponent, NetworkedComponent]
public sealed partial class ScpBlindBlockerComponent : Component
{

}
50 changes: 50 additions & 0 deletions Content.Shared/_Scp/Other/ScpBlind/ScpBlindComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

using Content.Shared.Actions.Components;
using Content.Shared.Whitelist;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared._Scp.Other.ScpBlind;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class ScpBlindComponent : Component
{
[DataField]
public EntProtoId<ActionComponent> ActionProto = "Scp173Blind";

/// <summary>
/// Время, через которое начнется ослепление после активации способности
/// </summary>
[DataField]
public TimeSpan StartBlindTime = TimeSpan.FromSeconds(12f);

/// <summary>
/// Время ослепления после успешного применения способности
/// </summary>
[DataField]
public TimeSpan BlindnessTime = TimeSpan.FromSeconds(7);

[DataField]
public float? MinWatchersToBlind;

[DataField]
public float SearchAllowerRadius = 8f;

[DataField]
public float SearchBlockerRadius = 8f;

[DataField]
public bool MustBeAllowedToBlind = false;

[DataField]
public bool IgnoreBlockers = false;

[DataField]
public EntityWhitelist? InContainersBlindWhitelist;

[DataField]
public EntityWhitelist? InContainersBlindBlacklist;

[ViewVariables, AutoNetworkedField]
public EntityUid? ActionEnt;
}
Loading
Loading