Рабочие термальные очки
This commit is contained in:
parent
6feef16ffd
commit
dce3d63d67
11 changed files with 347 additions and 1 deletions
|
|
@ -0,0 +1,61 @@
|
|||
using Content.Shared._Sunrise.ThermalVision;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._Sunrise.ThermalVision;
|
||||
|
||||
public sealed class ThermalVisionOverlay : Overlay
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
private readonly TransformSystem _transform;
|
||||
public override bool RequestScreenTexture => true;
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
private readonly ShaderInstance _screenShader;
|
||||
public ThermalVisionOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_screenShader = _prototypeManager.Index<ShaderPrototype>("ThermalVisionScreenShader").InstanceUnique();
|
||||
_transform = _entityManager.System<TransformSystem>();
|
||||
ZIndex = 10000;
|
||||
}
|
||||
|
||||
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (!_entityManager.TryGetComponent(_playerManager.LocalSession?.AttachedEntity, out EyeComponent? eyeComp))
|
||||
return false;
|
||||
|
||||
if (args.Viewport.Eye != eyeComp.Eye)
|
||||
return false;
|
||||
|
||||
var playerEntity = _playerManager.LocalSession?.AttachedEntity;
|
||||
|
||||
if (playerEntity == null)
|
||||
return false;
|
||||
|
||||
if (!_entityManager.TryGetComponent<ThermalVisionComponent>(playerEntity, out var blurComp))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (ScreenTexture == null)
|
||||
return;
|
||||
|
||||
var worldHandle = args.WorldHandle;
|
||||
var viewport = args.WorldBounds;
|
||||
var eyeRotation = args.Viewport.Eye?.Rotation ?? Angle.Zero;
|
||||
|
||||
_screenShader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
|
||||
|
||||
worldHandle.UseShader(_screenShader);
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
worldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
83
Content.Client/_Sunrise/ThermalVision/ThermalVisionSystem.cs
Normal file
83
Content.Client/_Sunrise/ThermalVision/ThermalVisionSystem.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
using Content.Shared._Sunrise.ThermalVision;
|
||||
using Content.Shared.Eye.Blinding.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._Sunrise.ThermalVision;
|
||||
|
||||
public sealed class ThermalVisionSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||
[Dependency] private readonly TransformSystem _xformSys = default!;
|
||||
private ThroughWallsVisionOverlay _throughWallsOverlay = default!;
|
||||
private ThermalVisionOverlay _overlay = default!;
|
||||
|
||||
private EntityUid? _effect = null;
|
||||
private readonly EntProtoId _effectPrototype = "EffectThermalVision";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ThermalVisionComponent, ComponentInit>(OnVisionInit);
|
||||
SubscribeLocalEvent<ThermalVisionComponent, ComponentShutdown>(OnVisionShutdown);
|
||||
|
||||
SubscribeLocalEvent<ThermalVisionComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<ThermalVisionComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
||||
|
||||
_throughWallsOverlay = new();
|
||||
_overlay = new();
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(Entity<ThermalVisionComponent> ent, ref LocalPlayerAttachedEvent args)
|
||||
{
|
||||
if (_effect == null)
|
||||
AddNightVision(ent.Owner);
|
||||
else if (HasComp<EyeProtectionComponent>(ent.Owner))
|
||||
RemoveNightVision();
|
||||
}
|
||||
|
||||
private void OnPlayerDetached(Entity<ThermalVisionComponent> ent, ref LocalPlayerDetachedEvent args)
|
||||
{
|
||||
RemoveNightVision();
|
||||
}
|
||||
|
||||
private void OnVisionInit(Entity<ThermalVisionComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
if (_player.LocalEntity != ent.Owner)
|
||||
return;
|
||||
|
||||
if (_effect == null)
|
||||
AddNightVision(ent.Owner);
|
||||
else if (HasComp<EyeProtectionComponent>(ent.Owner))
|
||||
RemoveNightVision();
|
||||
}
|
||||
|
||||
private void OnVisionShutdown(Entity<ThermalVisionComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
if (_player.LocalEntity != ent.Owner) return;
|
||||
|
||||
RemoveNightVision();
|
||||
}
|
||||
|
||||
private void AddNightVision(EntityUid uid)
|
||||
{
|
||||
if (HasComp<EyeProtectionComponent>(uid)) return;
|
||||
|
||||
_overlayMan.AddOverlay(_throughWallsOverlay);
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
_effect = SpawnAttachedTo(_effectPrototype, Transform(uid).Coordinates);
|
||||
_xformSys.SetParent(_effect.Value, uid);
|
||||
}
|
||||
private void RemoveNightVision()
|
||||
{
|
||||
_overlayMan.RemoveOverlay(_throughWallsOverlay);
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
Del(_effect);
|
||||
_effect = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
using Content.Shared._Sunrise.ThermalVision;
|
||||
using Content.Shared.Body.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._Sunrise.ThermalVision;
|
||||
|
||||
public sealed class ThroughWallsVisionOverlay : Overlay
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
private readonly ContainerSystem _containerSystem;
|
||||
private readonly TransformSystem _transform;
|
||||
private readonly ShaderInstance _shader;
|
||||
|
||||
public override bool RequestScreenTexture => true;
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
public ThroughWallsVisionOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_transform = _entityManager.System<TransformSystem>();
|
||||
_containerSystem = _entityManager.System<ContainerSystem>();
|
||||
|
||||
_shader = _prototypeManager.Index<ShaderPrototype>("BrightnessShader").InstanceUnique();
|
||||
}
|
||||
|
||||
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (!_entityManager.TryGetComponent(_playerManager.LocalSession?.AttachedEntity, out EyeComponent? eyeComp))
|
||||
return false;
|
||||
|
||||
if (args.Viewport.Eye != eyeComp.Eye)
|
||||
return false;
|
||||
|
||||
var playerEntity = _playerManager.LocalSession?.AttachedEntity;
|
||||
|
||||
if (playerEntity == null)
|
||||
return false;
|
||||
|
||||
if (!_entityManager.TryGetComponent<ThermalVisionComponent>(playerEntity, out var blurComp))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (ScreenTexture == null)
|
||||
return;
|
||||
|
||||
var worldHandle = args.WorldHandle;
|
||||
var viewport = args.WorldBounds;
|
||||
var eyeRotation = args.Viewport.Eye?.Rotation ?? Angle.Zero;
|
||||
|
||||
worldHandle.UseShader(_shader);
|
||||
var query = _entityManager.EntityQueryEnumerator<BodyComponent, MetaDataComponent, SpriteComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var uid, out _, out var meta, out var sprite, out var xform))
|
||||
{
|
||||
if (xform.MapID != args.MapId || _containerSystem.IsEntityInContainer(uid, meta)) continue;
|
||||
var (position, rotation) = _transform.GetWorldPositionRotation(xform);
|
||||
|
||||
sprite.Render(worldHandle, eyeRotation, rotation, null, position);
|
||||
}
|
||||
|
||||
worldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._Sunrise.ThermalVision;
|
||||
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent]
|
||||
public sealed partial class ThermalVisionComponent : Component
|
||||
{
|
||||
}
|
||||
|
|
@ -12015,3 +12015,14 @@
|
|||
type: Fix
|
||||
id: 827
|
||||
time: '2025-02-10T01:32:35.194700+00:00'
|
||||
- author: VigersRay
|
||||
changes:
|
||||
- message: "\u0422\u0435\u0440\u043C\u0430\u043B\u044C\u043D\u044B\u0435 \u043E\u0447\
|
||||
\u043A\u0438 \u0442\u0435\u043F\u0435\u0440\u044C \u0440\u0430\u0431\u043E\u0442\
|
||||
\u0430\u044E\u0442 \u0438 \u043F\u043E\u0437\u0432\u043E\u043B\u044F\u044E\u0442\
|
||||
\ \u0432\u0438\u0434\u0435\u0442\u044C \u0441\u0443\u0449\u0435\u0441\u0442\u0432\
|
||||
\ \u0437\u0430 \u0441\u0442\u0435\u043D\u0430\u043C\u0438 \u0430 \u0442\u0430\
|
||||
\u043A \u0436\u0435 \u043D\u0435\u0432\u0438\u0434\u0438\u043C\u043E\u043A."
|
||||
type: Tweak
|
||||
id: 828
|
||||
time: '2025-02-10T04:43:25.594250+00:00'
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@
|
|||
|
||||
#Make a scanner category when these actually function and we get the trayson
|
||||
- type: entity
|
||||
parent: ClothingEyesBase
|
||||
parent: [ClothingEyesBase, BaseToggleClothing]
|
||||
id: ClothingEyesGlassesThermal
|
||||
name: optical thermal scanner
|
||||
description: Thermals in the shape of glasses.
|
||||
|
|
@ -239,6 +239,15 @@
|
|||
- type: GroupExamine
|
||||
- type: IdentityBlocker
|
||||
coverage: EYES
|
||||
# Sunrise-Start
|
||||
- type: ToggleClothing
|
||||
action: ActionToggleThermalVision
|
||||
disableOnUnequip: true
|
||||
- type: ComponentToggler
|
||||
parent: true
|
||||
components:
|
||||
- type: ThermalVision
|
||||
# Sunrise-End
|
||||
|
||||
- type: entity
|
||||
parent: ClothingEyesBase
|
||||
|
|
|
|||
9
Resources/Prototypes/_Sunrise/Actions/thermal.yml
Normal file
9
Resources/Prototypes/_Sunrise/Actions/thermal.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
- type: entity
|
||||
id: ActionToggleThermalVision
|
||||
name: toggle thermal vision
|
||||
description: Toggle thermal vision on or off.
|
||||
components:
|
||||
- type: InstantAction
|
||||
useDelay: 5
|
||||
priority: -9
|
||||
event: !type:ToggleActionEvent
|
||||
|
|
@ -10,3 +10,18 @@
|
|||
id: NoMirageStealth
|
||||
kind: source
|
||||
path: "/Textures/_Sunrise/Shaders/no_mirage_stealth.swsl"
|
||||
|
||||
- type: shader
|
||||
id: ThermalVisionScreenShader
|
||||
kind: source
|
||||
path: "/Textures/_Sunrise/Shaders/thermal_screen.swsl"
|
||||
params:
|
||||
ThermalBoost: 1.5
|
||||
ThermalIntensity: 1
|
||||
|
||||
- type: shader
|
||||
id: BrightnessShader
|
||||
kind: source
|
||||
path: "/Textures/_Sunrise/Shaders/brightness.swsl"
|
||||
params:
|
||||
brightness: 1.5
|
||||
|
|
|
|||
10
Resources/Prototypes/_Sunrise/ThermalVision/light.yml
Normal file
10
Resources/Prototypes/_Sunrise/ThermalVision/light.yml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
- type: entity
|
||||
id: EffectThermalVision
|
||||
categories: [ HideSpawnMenu ]
|
||||
name: thermal vision
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#FFE4D6"
|
||||
energy: 1.8
|
||||
radius: 20
|
||||
softness: 20
|
||||
8
Resources/Textures/_Sunrise/Shaders/brightness.swsl
Normal file
8
Resources/Textures/_Sunrise/Shaders/brightness.swsl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
uniform highp float brightness;
|
||||
|
||||
void fragment() {
|
||||
highp vec4 col = zTexture(UV);
|
||||
col.rgb *= brightness;
|
||||
COLOR = col;
|
||||
lightSample = vec3(1.0);
|
||||
}
|
||||
60
Resources/Textures/_Sunrise/Shaders/thermal_screen.swsl
Normal file
60
Resources/Textures/_Sunrise/Shaders/thermal_screen.swsl
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
uniform sampler2D SCREEN_TEXTURE;
|
||||
|
||||
uniform highp float ThermalBoost;
|
||||
uniform highp float ThermalIntensity;
|
||||
|
||||
const highp vec3 cBlack = vec3(0.00, 0.00, 0.00);
|
||||
const highp vec3 cBlue = vec3(0.00, 0.00, 0.65);
|
||||
const highp vec3 cGreen = vec3(0.00, 0.65, 0.00);
|
||||
const highp vec3 cYellow = vec3(0.65, 0.65, 0.00);
|
||||
const highp vec3 cRed = vec3(0.65, 0.00, 0.00);
|
||||
const highp vec3 cWhite = vec3(0.65, 0.65, 0.65);
|
||||
|
||||
highp vec3 getThermalColor(in highp float t)
|
||||
{
|
||||
// 0.0..0.2: black -> blue
|
||||
// 0.2..0.4: blue -> green
|
||||
// 0.4..0.6: green -> yellow
|
||||
// 0.6..0.8: yellow-> red
|
||||
// 0.8..1.0: red -> white
|
||||
|
||||
if (t < 0.2)
|
||||
{
|
||||
highp float alpha = t / 0.2;
|
||||
return mix(cBlack, cBlue, alpha);
|
||||
}
|
||||
else if (t < 0.4)
|
||||
{
|
||||
highp float alpha = (t - 0.2) / 0.2;
|
||||
return mix(cBlue, cGreen, alpha);
|
||||
}
|
||||
else if (t < 0.6)
|
||||
{
|
||||
highp float alpha = (t - 0.4) / 0.2;
|
||||
return mix(cGreen, cYellow, alpha);
|
||||
}
|
||||
else if (t < 0.8)
|
||||
{
|
||||
highp float alpha = (t - 0.6) / 0.2;
|
||||
return mix(cYellow, cRed, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
highp float alpha = (t - 0.8) / 0.2;
|
||||
return mix(cRed, cWhite, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void fragment()
|
||||
{
|
||||
COLOR = zTextureSpec(SCREEN_TEXTURE, Pos);
|
||||
|
||||
highp float lum = dot(COLOR.rgb, vec3(0.299, 0.587, 0.114));
|
||||
|
||||
lum *= ThermalBoost;
|
||||
lum = clamp(lum, 0.0, 1.0);
|
||||
|
||||
highp vec3 thermalColor = getThermalColor(lum);
|
||||
|
||||
COLOR.rgb = mix(COLOR.rgb, thermalColor, ThermalIntensity);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue