[Fix] Исправлен фастмердж #600 (#606)

* commit

* fix
This commit is contained in:
Spatison
2025-06-19 19:46:24 +03:00
committed by GitHub
parent a621ca1d5f
commit 876a48458e
17 changed files with 89 additions and 105 deletions

View File

@@ -44,7 +44,7 @@ public sealed class CombatModeIndicatorsOverlay : Overlay
_eye = eye;
_combat = combatSys;
_hands = hands;
ZIndex = 100;
ZIndex = 100; // WD EDIT
var spriteSys = _entMan.EntitySysManager.GetEntitySystem<SpriteSystem>();
_gunSight = spriteSys.Frame0(new SpriteSpecifier.Rsi(new ResPath("/Textures/Interface/Misc/crosshair_pointers.rsi"),

View File

@@ -128,10 +128,12 @@ namespace Content.Client.Entry
_prototypeManager.RegisterIgnore("stationGoal");
_prototypeManager.RegisterIgnore("ghostRoleRaffleDecider");
// WD EDIT START
// Vision effects
_componentFactory.RegisterIgnore("UltraVisionComponent");
_componentFactory.RegisterIgnore("DogVisionComponent");
_componentFactory.RegisterIgnore("CRTVisionComponent");
// WD EDIT END
_componentFactory.GenerateNetIds();
_adminManager.Initialize();

View File

@@ -1,12 +1,13 @@
using Content.Shared._White.Overlays;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Content.Shared._White.Traits.Assorted.Components;
using Robust.Shared.Timing;
namespace Content.Client.Overlays;
namespace Content.Client._White.Overlays;
// ReSharper disable once InconsistentNaming
public sealed class CRTVisionOverlay : Overlay
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -38,13 +39,13 @@ public sealed class CRTVisionOverlay : Overlay
// Effect parameters
private float _healthPercentage = 1.0f;
private float _glitchIntensity = 0.0f;
private float _glitchIntensity;
// Temporary glitch effect parameters
private float _temporaryGlitchIntensity = 0.0f;
private float _temporaryGlitchDuration = 0.0f;
private float _temporaryGlitchTimer = 0.0f;
private bool _hasTemporaryGlitch = false;
private float _temporaryGlitchIntensity;
private float _temporaryGlitchDuration;
private float _temporaryGlitchTimer;
private bool _hasTemporaryGlitch;
public CRTVisionOverlay()
{
@@ -58,8 +59,8 @@ public sealed class CRTVisionOverlay : Overlay
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (_playerManager.LocalEntity is not { Valid: true } player
|| !_entityManager.HasComponent<CRTVisionComponent>(player))
if (_playerManager.LocalEntity is not { Valid: true, } player
|| !_entityManager.HasComponent<CRTVisionOverlayComponent>(player))
return false;
return base.BeforeDraw(in args);
@@ -95,11 +96,11 @@ public sealed class CRTVisionOverlay : Overlay
_crtVisionShader.SetParameter("TIME", _currentTime);
// Apply temporary glitch effect if active
float effectiveGlitchIntensity = _glitchIntensity;
var effectiveGlitchIntensity = _glitchIntensity;
if (_hasTemporaryGlitch && _temporaryGlitchDuration > 0f)
{
float remainingFactor = 1.0f - (_temporaryGlitchTimer / _temporaryGlitchDuration);
float tempIntensity = _temporaryGlitchIntensity * remainingFactor;
var remainingFactor = 1.0f - (_temporaryGlitchTimer / _temporaryGlitchDuration);
var tempIntensity = _temporaryGlitchIntensity * remainingFactor;
effectiveGlitchIntensity = Math.Max(effectiveGlitchIntensity, tempIntensity);
}
@@ -131,7 +132,7 @@ public sealed class CRTVisionOverlay : Overlay
if (_healthPercentage < GlitchHealthThreshold)
{
// Normalize scale from threshold to 0.0 into range from 0.0 to 1.0
float normalizedHealth = 1.0f - (_healthPercentage / GlitchHealthThreshold);
var normalizedHealth = 1.0f - (_healthPercentage / GlitchHealthThreshold);
// Quadratic function for smooth effect increase
_glitchIntensity = normalizedHealth * normalizedHealth * GlitchIntensityMultiplier;
@@ -146,8 +147,8 @@ public sealed class CRTVisionOverlay : Overlay
// At low charge enhance effects
if (_healthPercentage < LowHealthThreshold)
{
float lowChargeFactor = 1.0f - (_healthPercentage / LowHealthThreshold);
float pulsation = (float)Math.Sin(_currentTime * LowHealthPulsationFrequency) * LowHealthPulsationAmplitude;
var lowChargeFactor = 1.0f - (_healthPercentage / LowHealthThreshold);
var pulsation = (float)Math.Sin(_currentTime * LowHealthPulsationFrequency) * LowHealthPulsationAmplitude;
_glitchIntensity = Math.Max(_glitchIntensity, lowChargeFactor * LowHealthIntensityFactor + pulsation);
}
_glitchIntensity = Math.Max(0f, _glitchIntensity);

View File

@@ -1,25 +1,23 @@
using Content.Shared._White.Traits.Assorted.Components;
using Content.Shared._White.Overlays;
using Content.Shared.CCVar;
using Content.Shared.Damage;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Stunnable;
using Content.Shared.Weapons.Melee.Events;
using Robust.Client.Graphics;
using Robust.Shared.Configuration;
using Robust.Shared.Player;
using Content.Shared.Damage;
using Robust.Shared.Timing;
using System;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Stunnable;
using Content.Shared.Mobs.Systems;
namespace Content.Client.Overlays;
namespace Content.Client._White.Overlays;
public sealed partial class CRTVisionSystem : EntitySystem
// ReSharper disable once InconsistentNaming
public sealed class CRTVisionSystem : EntitySystem
{
[Dependency] private readonly IOverlayManager _overlayMan = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly ISharedPlayerManager _playerMan = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
private CRTVisionOverlay _overlay = default!;
@@ -31,35 +29,44 @@ public sealed partial class CRTVisionSystem : EntitySystem
private const float StudioVisorGlitchReduction = 0.7f; // Reduce glitch intensity by 70% with studio visor
private const float StudioVisorLowHealthThreshold = 0.3f;
private bool _noVisionFilters;
public override void Initialize()
{
base.Initialize();
_overlay = new();
SubscribeLocalEvent<CRTVisionComponent, ComponentInit>(OnComponentChange);
SubscribeLocalEvent<CRTVisionComponent, ComponentShutdown>(OnComponentChange);
SubscribeLocalEvent<CRTVisionComponent, LocalPlayerAttachedEvent>(OnPlayerStateChange);
SubscribeLocalEvent<CRTVisionComponent, LocalPlayerDetachedEvent>(OnPlayerStateChange);
SubscribeLocalEvent<CRTVisionOverlayComponent, ComponentInit>(OnComponentChange);
SubscribeLocalEvent<CRTVisionOverlayComponent, ComponentShutdown>(OnComponentChange);
SubscribeLocalEvent<CRTVisionOverlayComponent, LocalPlayerAttachedEvent>(OnPlayerStateChange);
SubscribeLocalEvent<CRTVisionOverlayComponent, LocalPlayerDetachedEvent>(OnPlayerStateChange);
// Subscribe to studio visor events
SubscribeLocalEvent<StudioVisorComponent, ComponentInit>(OnComponentChange);
SubscribeLocalEvent<StudioVisorComponent, ComponentShutdown>(OnComponentChange);
SubscribeLocalEvent<StudioVisorOverlayComponent, ComponentInit>(OnComponentChange);
SubscribeLocalEvent<StudioVisorOverlayComponent, ComponentShutdown>(OnComponentChange);
// Subscribe to damage events
SubscribeLocalEvent<CRTVisionComponent, DamageChangedEvent>(OnDamageChanged);
SubscribeLocalEvent<CRTVisionOverlayComponent, DamageChangedEvent>(OnDamageChanged);
// Subscribe to mob state change events
SubscribeLocalEvent<CRTVisionComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<CRTVisionOverlayComponent, MobStateChangedEvent>(OnMobStateChanged);
// Subscribe to health threshold events
SubscribeLocalEvent<CRTVisionComponent, MobThresholdChecked>(OnThresholdChecked);
SubscribeLocalEvent<CRTVisionOverlayComponent, MobThresholdChecked>(OnThresholdChecked);
// Subscribe to attack and stun events
SubscribeLocalEvent<CRTVisionComponent, AttackedEvent>(OnAttacked);
SubscribeLocalEvent<CRTVisionComponent, StunnedEvent>(OnStunned);
SubscribeLocalEvent<CRTVisionOverlayComponent, AttackedEvent>(OnAttacked);
SubscribeLocalEvent<CRTVisionOverlayComponent, StunnedEvent>(OnStunned);
Subs.CVar(_cfg, CCVars.NoVisionFilters, OnNoVisionFiltersChanged);
Subs.CVar(
_cfg,
CCVars.NoVisionFilters,
v =>
{
_noVisionFilters = v;
UpdateOverlayState();
});
}
private void OnComponentChange<T>(EntityUid uid, T component, EntityEventArgs args) where T: IComponent
@@ -68,7 +75,7 @@ public sealed partial class CRTVisionSystem : EntitySystem
UpdateOverlayState();
}
private void OnPlayerStateChange<T>(EntityUid uid, CRTVisionComponent component, T args)
private void OnPlayerStateChange<T>(EntityUid uid, CRTVisionOverlayComponent component, T args)
{
UpdateOverlayState();
}
@@ -76,46 +83,40 @@ public sealed partial class CRTVisionSystem : EntitySystem
private void UpdateOverlayState()
{
var player = _playerMan.LocalEntity;
if (player == null || !EntityManager.HasComponent<CRTVisionComponent>(player))
{
if (player == null || !EntityManager.HasComponent<CRTVisionOverlayComponent>(player))
{
_overlayMan.RemoveOverlay(_overlay);
return;
}
UpdateHealthPercentage(player.Value);
var hasStudioVisor = _entityManager.HasComponent<StudioVisorComponent>(player.Value);
var noVisionFilters = _cfg.GetCVar(CCVars.NoVisionFilters);
var hasStudioVisor = _entityManager.HasComponent<StudioVisorOverlayComponent>(player.Value);
// The overlay is active if filters are enabled, and the user either doesn't have a studio visor,
// or has one but is at low health.
bool shouldShowOverlay = !noVisionFilters && (!hasStudioVisor || _healthPercentage < StudioVisorLowHealthThreshold);
var shouldShowOverlay = !_noVisionFilters && (!hasStudioVisor || _healthPercentage < StudioVisorLowHealthThreshold);
if (shouldShowOverlay)
{
if (!_overlayMan.HasOverlay<CRTVisionOverlay>())
_overlayMan.AddOverlay(_overlay);
_overlayMan.AddOverlay(_overlay);
}
else
{
if (_overlayMan.HasOverlay<CRTVisionOverlay>())
_overlayMan.RemoveOverlay(_overlay);
{
if (_overlayMan.HasOverlay<CRTVisionOverlay>())
_overlayMan.RemoveOverlay(_overlay);
}
}
private void OnNoVisionFiltersChanged(bool enabled)
{
UpdateOverlayState();
}
// Process damage event
private void OnDamageChanged(EntityUid uid, CRTVisionComponent component, DamageChangedEvent args)
private void OnDamageChanged(EntityUid uid, CRTVisionOverlayComponent component, DamageChangedEvent args)
{
if (uid != _playerMan.LocalEntity)
return;
// Check if it was damage and not healing
if (args.DamageIncreased && args.DamageDelta != null)
if (args is { DamageIncreased: true, DamageDelta: not null, })
{
var damageAmount = (float) args.DamageDelta.GetTotal();
TriggerImpactEffect(damageAmount);
@@ -129,7 +130,7 @@ public sealed partial class CRTVisionSystem : EntitySystem
private void UpdateHealthPercentage(EntityUid uid)
{
if (!_entityManager.TryGetComponent<DamageableComponent>(uid, out var damageable) ||
!_entityManager.TryGetComponent<MobThresholdsComponent>(uid, out var thresholds))
!_entityManager.HasComponent<MobThresholdsComponent>(uid))
return;
// Get critical threshold
@@ -145,29 +146,25 @@ public sealed partial class CRTVisionSystem : EntitySystem
}
// Handle mob state change (e.g., transition from Normal to Critical)
private void OnMobStateChanged(EntityUid uid, CRTVisionComponent component, MobStateChangedEvent args)
private void OnMobStateChanged(EntityUid uid, CRTVisionOverlayComponent component, MobStateChangedEvent args)
{
if (uid != _playerMan.LocalEntity)
return;
// If state worsened, show impact effect
if (args.NewMobState > args.OldMobState)
{
TriggerImpactEffect(20.0f); // Stronger effect on state change
}
// Trigger a strong glitch effect when entering critical state
if (args.NewMobState == MobState.Critical)
{
_overlay.SetTemporaryGlitchEffect(1.5f, 0.5f);
}
// Update health percentage for glitch effects
UpdateOverlayState();
}
// Handle health threshold check
private void OnThresholdChecked(EntityUid uid, CRTVisionComponent component, MobThresholdChecked args)
private void OnThresholdChecked(EntityUid uid, CRTVisionOverlayComponent component, MobThresholdChecked args)
{
if (uid != _playerMan.LocalEntity)
return;
@@ -183,7 +180,7 @@ public sealed partial class CRTVisionSystem : EntitySystem
}
// Handle attack on player
private void OnAttacked(EntityUid uid, CRTVisionComponent component, AttackedEvent args)
private void OnAttacked(EntityUid uid, CRTVisionOverlayComponent component, AttackedEvent args)
{
if (uid != _playerMan.LocalEntity)
return;
@@ -193,7 +190,7 @@ public sealed partial class CRTVisionSystem : EntitySystem
}
// Handle stun event
private void OnStunned(EntityUid uid, CRTVisionComponent component, StunnedEvent args)
private void OnStunned(EntityUid uid, CRTVisionOverlayComponent component, StunnedEvent args)
{
if (uid != _playerMan.LocalEntity)
return;
@@ -210,11 +207,11 @@ public sealed partial class CRTVisionSystem : EntitySystem
// Reduce impact effect intensity if player has studio visor
var effectiveIntensity = intensity;
if (_entityManager.HasComponent<StudioVisorComponent>(player.Value))
if (_entityManager.HasComponent<StudioVisorOverlayComponent>(player.Value))
effectiveIntensity *= (1.0f - StudioVisorGlitchReduction);
// Trigger a temporary glitch effect proportional to damage
float glitchIntensity = Math.Min(effectiveIntensity / 50.0f, 1.0f);
var glitchIntensity = Math.Min(effectiveIntensity / 50.0f, 1.0f);
_overlay.SetTemporaryGlitchEffect(glitchIntensity * 0.8f, 0.4f);
}
}

View File

@@ -1,11 +1,10 @@
using Robust.Shared.GameStates;
namespace Content.Shared._White.Traits.Assorted.Components;
namespace Content.Shared._White.Overlays;
/// <summary>
/// This is used for adding CRT vision effects to IPCs.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class CRTVisionComponent : Component
{
}
// ReSharper disable once InconsistentNaming
public sealed partial class CRTVisionOverlayComponent : Component;

View File

@@ -1,11 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared._White.Traits.Assorted.Components;
namespace Content.Shared._White.Overlays;
/// <summary>
/// This is used for IPCs with studio visor that reduces CRT vision effects.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class StudioVisorComponent : Component
{
}
public sealed partial class StudioVisorOverlayComponent : Component;

View File

@@ -3,3 +3,6 @@ trait-description-Deaf = You can not hear anything anyone says! Luckily, you see
trait-name-Contract = Contract
trait-description-Contract = You signed paper with your own blood, what could go wrong?
trait-name-StudioVisor = Studio Visor
trait-description-StudioVisor = A studio-grade visor is installed in your vision sensors, which significantly reduces the intensity of CRT-like visual effects and glitches caused by damage or low health.

View File

@@ -665,6 +665,3 @@ trait-description-IPCFragileCircuits =
Your chassis is particularly bad at handling electric discharges.
You immediately shut down any time you take [color=orange]Shock[/color] damage and must be rebooted.
fragileCircuits-kill-popup = {$name}'s circuits shut down from short-circuiting!
trait-name-StudioVisor = Studio Visor
trait-description-StudioVisor = A studio-grade visor is installed in your vision sensors, which significantly reduces the intensity of CRT-like visual effects and glitches caused by damage or low health.

View File

@@ -3,3 +3,6 @@ trait-description-Deaf = Вы совершенно ничего не слыши
trait-name-Contract = Контракт
trait-description-Contract = Вы подписали какую-то бумажку своей кровью, что может пойти не так?
trait-name-StudioVisor = Студийный визор
trait-description-StudioVisor = В ваши оптические сенсоры встроен визор студийного класса, который значительно снижает интенсивность визуальных ЭЛТ-эффектов и глитчей, вызванных повреждениями или низким уровнем заряда.

View File

@@ -590,6 +590,3 @@ trait-name-IPCFragileCircuits = Хрупкие Микросхемы
trait-description-IPCFragileCircuits =
Ваша система не переносит электрических перегрузок. Любой [color=orange]шоковый[/color] урон моментально отключает вас.
fragileCircuits-kill-popup = {$name} отключился из-за короткого замыкания!
trait-name-StudioVisor = Студийный визор
trait-description-StudioVisor = В ваши оптические сенсоры встроен визор студийного класса, который значительно снижает интенсивность визуальных ЭЛТ-эффектов и глитчей, вызванных повреждениями или низким уровнем заряда.

View File

@@ -2,7 +2,6 @@
id: BorgChassisSelectable
parent: BaseBorgChassisNT
components:
- type: CRTVision
- type: Sprite
layers:
- state: robot
@@ -37,6 +36,7 @@
- type: SurgerySpeedModifier
speedModifier: 1.5
- type: Sanitized
- type: CRTVisionOverlay # WD EDIT
- type: entity
id: BorgChassisGeneric

View File

@@ -4,7 +4,6 @@
name: Urist McPositronic
description: A positronic brain in a metal body.
components:
- type: CRTVision
- type: PowerCellSlot
cellSlotId: cell_slot
fitsInCharger: true
@@ -137,6 +136,7 @@
- DoorBumpOpener
- SiliconEmotes
- SiliconMob
- type: CRTVisionOverlay # WD EDIT
- type: entity
save: false

View File

@@ -1,14 +0,0 @@
- type: entity
id: MobIPCSpecies
parent: BaseMob
name: ipc
description: A synthetic man-made lifeform.
components:
- type: CRTVision
- type: Respirator
damage:
excess: 0
damageRecovery:
types:
Asphyxiation: -1.0

View File

@@ -1,5 +1,5 @@
- type: entity
parent: [BaseWeaponBallisticTurret, BaseTurret3D] # wwdp edit
parent: [BaseTurret3D, BaseWeaponBallisticTurret] # wwdp edit
id: WeaponTurretSyndicate
suffix: Syndicate
components:
@@ -8,7 +8,7 @@
- Syndicate
- type: entity
parent: [BaseWeaponBallisticTurret, BaseTurret3D] # wwdp edit
parent: [BaseTurret3D, BaseWeaponBallisticTurret] # wwdp edit
id: WeaponTurretSAN
suffix: Sol Alliance Navy
description: A turret designed to provide protection for Sol Marines during combat drops. It menaces targets with a twin-linked C-20r, although its cheap fire controller lends to poor accuracy.
@@ -28,7 +28,7 @@
capacity: 200
- type: entity
parent: [BaseWeaponBallisticTurret, BaseTurret3D] # wwdp edit
parent: [BaseTurret3D, BaseWeaponBallisticTurret] # wwdp edit
name: disposable ballistic turret
id: WeaponTurretSyndicateDisposable
suffix: Syndicate, Disposable
@@ -62,7 +62,7 @@
canCreateVacuum: false
- type: entity
parent: [BaseWeaponBallisticTurret, BaseTurret3D] # wwdp edit
parent: [BaseTurret3D, BaseWeaponBallisticTurret] # wwdp edit
id: WeaponTurretNanoTrasen
suffix: NanoTrasen
components:
@@ -71,7 +71,7 @@
- NanoTrasen
- type: entity
parent: [BaseWeaponBallisticTurret, BaseTurret3D] # wwdp edit
parent: [BaseTurret3D, BaseWeaponBallisticTurret] # wwdp edit
id: WeaponTurretHostile
suffix: Hostile
components:

View File

@@ -37,7 +37,7 @@
capacity: 200
- type: entity
parent: [BaseWeaponBallisticTurret, BaseTurret3D] # wwdp edit
parent: BaseWeaponBallisticTurret
id: BaseWeaponTurretMinigun
name: minigun turret
abstract: true

View File

@@ -82,6 +82,7 @@
components:
- type: Sprite
noRot: true
sprite: Objects/Weapons/Guns/Turrets/turrets.rsi
drawdepth: Mobs
layers:
- state: syndie_base

View File

@@ -9,4 +9,4 @@
functions:
- !type:TraitAddComponent
components:
- type: StudioVisor
- type: StudioVisorOverlay