Skip to content

Commit

Permalink
Nightvision hard prototype (#366)
Browse files Browse the repository at this point in the history
* Nightvision hard prototype

* fixes night vision

* Adds toggles to masks

* fixes night vision

* adds nightvision UV green shading

* Applies SWSL with Vertex calc and applies it as texture for id nightvision

* adds a overlay to night vision

adds a overlay to night vision and changes some file locations for better organization

---------

Co-authored-by: ScyronX <[email protected]>
  • Loading branch information
BlueHNT and ScyronX authored Jul 28, 2024
1 parent bef5ec0 commit 4858ed8
Show file tree
Hide file tree
Showing 28 changed files with 672 additions and 11 deletions.
45 changes: 45 additions & 0 deletions Content.Client/_N14/NightVision/GreenVisionOverlay.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Content.Shared.Abilities;
using Content.Shared._N14.NightVision;

namespace Content.Client._N14.NightVision;

public sealed partial class GreenVisionOverlay : Overlay
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] IEntityManager _entityManager = default!;


public override bool RequestScreenTexture => true;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _greenVisionShader;

public GreenVisionOverlay()
{
IoCManager.InjectDependencies(this);
_greenVisionShader = _prototypeManager.Index<ShaderPrototype>("GreenVision").Instance().Duplicate();
}

protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
return;
if (_playerManager.LocalPlayer?.ControlledEntity is not {Valid: true} player)
return;
if (!_entityManager.HasComponent<GreenVisionComponent>(player))
return;

_greenVisionShader?.SetParameter("SCREEN_TEXTURE", ScreenTexture);


var worldHandle = args.WorldHandle;
var viewport = args.WorldBounds;
worldHandle.SetTransform(Matrix3.Identity);
worldHandle.UseShader(_greenVisionShader);
worldHandle.DrawRect(viewport, Color.White);
}
}
39 changes: 39 additions & 0 deletions Content.Client/_N14/NightVision/GreenVisionSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Content.Shared.Abilities;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Content.Shared._N14.NightVision;

namespace Content.Client._N14.NightVision;

public sealed partial class GreenVisionSystem : EntitySystem
{
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IOverlayManager _overlayMan = default!;

private GreenVisionOverlay _overlay = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<GreenVisionComponent, ComponentInit>(OnGreenVisionInit);
SubscribeLocalEvent<GreenVisionComponent, ComponentShutdown>(OnGreenVisionShutdown);

_overlay = new();
}

private void OnGreenVisionInit(EntityUid uid, GreenVisionComponent component, ComponentInit args)
{
if (_player.LocalPlayer?.ControlledEntity == uid)
_overlayMan.AddOverlay(_overlay);
}

private void OnGreenVisionShutdown(EntityUid uid, GreenVisionComponent component, ComponentShutdown args)
{
if (_player.LocalPlayer?.ControlledEntity == uid)
{
_overlayMan.RemoveOverlay(_overlay);
}
}
}
96 changes: 96 additions & 0 deletions Content.Client/_N14/NightVision/NightVisionOverlay.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System.Numerics;
using Content.Shared._N14.NightVision;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.Map;
using Content.Shared.Mobs.Components;

namespace Content.Client._N14.NightVision;

public sealed class NightVisionOverlay : Overlay
{
[Dependency] private readonly IEntityManager _entity = default!;
[Dependency] private readonly IPlayerManager _players = default!;

private readonly ContainerSystem _container;
private readonly TransformSystem _transform;

public override OverlaySpace Space => OverlaySpace.WorldSpace;

private readonly List<NightVisionRenderEntry> _entries = new();

public NightVisionOverlay()
{
IoCManager.InjectDependencies(this);

_container = _entity.System<ContainerSystem>();
_transform = _entity.System<TransformSystem>();
}

protected override void Draw(in OverlayDrawArgs args)
{
if (!_entity.TryGetComponent(_players.LocalEntity, out NightVisionComponent? nightVision) ||
nightVision.State == NightVisionState.Off)
{
return;
}

var handle = args.WorldHandle;
var eye = args.Viewport.Eye;
var eyeRot = eye?.Rotation ?? default;

_entries.Clear();
var entities = _entity.EntityQueryEnumerator<MobStateComponent, SpriteComponent, TransformComponent>();
while (entities.MoveNext(out var uid, out var visible, out var sprite, out var xform))
{
_entries.Add(new NightVisionRenderEntry((uid, sprite, xform),
eye?.Position.MapId,
eyeRot,
nightVision.SeeThroughContainers,
0));
}

_entries.Sort(SortPriority);

foreach (var entry in _entries)
{
Render(entry.Ent, entry.Map, handle, entry.EyeRot, entry.NightVisionSeeThroughContainers);
}

//handle.SetTransform(Matrix3x2.Identity);
}

private static int SortPriority(NightVisionRenderEntry x, NightVisionRenderEntry y)
{
return x.Priority.CompareTo(y.Priority);
}

private void Render(Entity<SpriteComponent, TransformComponent> ent,
MapId? map,
DrawingHandleWorld handle,
Angle eyeRot,
bool seeThroughContainers)
{
var (uid, sprite, xform) = ent;
if (xform.MapID != map)
return;

var seeThrough = seeThroughContainers;
if (!seeThrough && _container.IsEntityOrParentInContainer(uid))
return;

var position = _transform.GetWorldPosition(xform);
var rotation = _transform.GetWorldRotation(xform);

//sprite.Render(handle, eyeRot, rotation, position: position);
}
}

public record struct NightVisionRenderEntry(
(EntityUid, SpriteComponent, TransformComponent) Ent,
MapId? Map,
Angle EyeRot,
bool NightVisionSeeThroughContainers,
int Priority);
82 changes: 82 additions & 0 deletions Content.Client/_N14/NightVision/NightVisionSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using Content.Shared._N14.NightVision;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Player;

namespace Content.Client._N14.NightVision;

public sealed class NightVisionSystem : SharedNightVisionSystem
{
[Dependency] private readonly ILightManager _light = default!;
[Dependency] private readonly IOverlayManager _overlay = default!;
[Dependency] private readonly IPlayerManager _player = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<NightVisionComponent, LocalPlayerAttachedEvent>(OnNightVisionAttached);
SubscribeLocalEvent<NightVisionComponent, LocalPlayerDetachedEvent>(OnNightVisionDetached);
}

private void OnNightVisionAttached(Entity<NightVisionComponent> ent, ref LocalPlayerAttachedEvent args)
{
NightVisionChanged(ent);
}

private void OnNightVisionDetached(Entity<NightVisionComponent> ent, ref LocalPlayerDetachedEvent args)
{
Off();
}

protected override void NightVisionChanged(Entity<NightVisionComponent> ent)
{
if (ent != _player.LocalEntity)
return;

switch (ent.Comp.State)
{
case NightVisionState.Off:
Off();
break;
case NightVisionState.Half:
Half(ent);
break;
case NightVisionState.Full:
Full(ent);
break;
default:
throw new ArgumentOutOfRangeException();
}
}

protected override void NightVisionRemoved(Entity<NightVisionComponent> ent)
{
if (ent != _player.LocalEntity)
return;

Off();
}

private void Off()
{
_overlay.RemoveOverlay(new NightVisionOverlay());
_light.DrawLighting = true;
}

private void Half(Entity<NightVisionComponent> ent)
{
if (ent.Comp.Overlay)
_overlay.AddOverlay(new NightVisionOverlay());

_light.DrawLighting = true;
}

private void Full(Entity<NightVisionComponent> ent)
{
if (ent.Comp.Overlay)
_overlay.AddOverlay(new NightVisionOverlay());

_light.DrawLighting = false;
}
}
5 changes: 5 additions & 0 deletions Content.Server/_N14/NightVision/NightVisionSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Content.Shared._N14.NightVision;

namespace Content.Server._N14.NightVision;

public sealed class NightVisionSystem : SharedNightVisionSystem;
1 change: 1 addition & 0 deletions Content.Shared/Alert/AlertType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public enum AlertType : byte
BorgCrit,
BorgDead,
Offer,
NightVision
}

}
9 changes: 9 additions & 0 deletions Content.Shared/_N14/NightVision/GreenVisionComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Robust.Shared.GameStates;

namespace Content.Shared._N14.NightVision;

[RegisterComponent]
[NetworkedComponent]

public sealed partial class GreenVisionComponent : Component
{}
34 changes: 34 additions & 0 deletions Content.Shared/_N14/NightVision/NightVisionComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Content.Shared.Alert;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;

namespace Content.Shared._N14.NightVision;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
[Access(typeof(SharedNightVisionSystem))]
public sealed partial class NightVisionComponent : Component
{
[DataField]
public ProtoId<AlertPrototype>? Alert;

[DataField, AutoNetworkedField]
public NightVisionState State = NightVisionState.Full;

[DataField, AutoNetworkedField]
public bool Overlay;

[DataField, AutoNetworkedField]
public bool Innate;

[DataField, AutoNetworkedField]
public bool SeeThroughContainers;
}

[Serializable, NetSerializable]
public enum NightVisionState
{
Off,
Half,
Full
}
21 changes: 21 additions & 0 deletions Content.Shared/_N14/NightVision/NightVisionItemComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared._N14.NightVision;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedNightVisionSystem))]
public sealed partial class NightVisionItemComponent : Component
{
[DataField, AutoNetworkedField]
public EntProtoId ActionId = "ActionToggleNightVision";

[DataField, AutoNetworkedField]
public EntityUid? Action;

[DataField, AutoNetworkedField]
public EntityUid? User;

[DataField, AutoNetworkedField]
public bool Toggleable = true;
}
9 changes: 9 additions & 0 deletions Content.Shared/_N14/NightVision/NightVisionItemVisuals.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Robust.Shared.Serialization;

namespace Content.Shared._N14.NightVision;

[Serializable, NetSerializable]
public enum NightVisionItemVisuals
{
Active,
}
17 changes: 17 additions & 0 deletions Content.Shared/_N14/NightVision/RMCNightVisionVisibleComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Robust.Shared.GameStates;

namespace Content.Shared._N14.NightVision;

/// <summary>
/// For rendering sprites on top of FOV when the user has a <see cref="NightVisionComponent"/>.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class RMCNightVisionVisibleComponent : Component
{
/// <summary>
/// Priority for rendering order.
/// Rendered from lowest to highest, which means higher numbers will be rendered above lower numbers.
/// </summary>
[DataField, AutoNetworkedField]
public int Priority = 0;
}
Loading

0 comments on commit 4858ed8

Please sign in to comment.