Adds blinding + blindfolds (#8688)
* Adds blinding + blindfolds * Don't break examining lol * moment * fix toggle lights behavior * move checks around * Sloth review * Added a salvage funny * review * woops * Switch circle shader Co-authored-by: wrexbe <wrexbe@protonmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@ using Content.Client.CharacterInterface;
|
|||||||
using Content.Client.Chat.Managers;
|
using Content.Client.Chat.Managers;
|
||||||
using Content.Client.EscapeMenu;
|
using Content.Client.EscapeMenu;
|
||||||
using Content.Client.Eui;
|
using Content.Client.Eui;
|
||||||
|
using Content.Client.Eye.Blinding;
|
||||||
using Content.Client.Flash;
|
using Content.Client.Flash;
|
||||||
using Content.Client.GhostKick;
|
using Content.Client.GhostKick;
|
||||||
using Content.Client.HUD;
|
using Content.Client.HUD;
|
||||||
|
|||||||
80
Content.Client/Eye/Blinding/BlindOverlay.cs
Normal file
80
Content.Client/Eye/Blinding/BlindOverlay.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.Player;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Content.Shared.Eye.Blinding;
|
||||||
|
|
||||||
|
namespace Content.Client.Eye.Blinding
|
||||||
|
{
|
||||||
|
public sealed class BlindOverlay : Overlay
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
|
[Dependency] IEntityManager _entityManager = default!;
|
||||||
|
[Dependency] ILightManager _lightManager = default!;
|
||||||
|
|
||||||
|
|
||||||
|
public override bool RequestScreenTexture => true;
|
||||||
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
|
private readonly ShaderInstance _greyscaleShader;
|
||||||
|
private readonly ShaderInstance _circleMaskShader;
|
||||||
|
|
||||||
|
private BlindableComponent _blindableComponent = default!;
|
||||||
|
|
||||||
|
public BlindOverlay()
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
_greyscaleShader = _prototypeManager.Index<ShaderPrototype>("GreyscaleFullscreen").InstanceUnique();
|
||||||
|
_circleMaskShader = _prototypeManager.Index<ShaderPrototype>("CircleMask").InstanceUnique();
|
||||||
|
}
|
||||||
|
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||||
|
{
|
||||||
|
var playerEntity = _playerManager.LocalPlayer?.ControlledEntity;
|
||||||
|
|
||||||
|
if (playerEntity == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_entityManager.TryGetComponent<BlindableComponent>(playerEntity, out var blindComp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_blindableComponent = blindComp;
|
||||||
|
|
||||||
|
var blind = _blindableComponent.Sources > 0;
|
||||||
|
|
||||||
|
if (!blind && _blindableComponent.LightSetup) // Turn FOV back on if we can see again
|
||||||
|
{
|
||||||
|
_lightManager.Enabled = true;
|
||||||
|
_blindableComponent.LightSetup = false;
|
||||||
|
_blindableComponent.GraceFrame = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return blind;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(in OverlayDrawArgs args)
|
||||||
|
{
|
||||||
|
if (ScreenTexture == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_blindableComponent.GraceFrame)
|
||||||
|
{
|
||||||
|
_blindableComponent.LightSetup = true; // Ok we touched the lights
|
||||||
|
_lightManager.Enabled = false;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
_blindableComponent.GraceFrame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_greyscaleShader?.SetParameter("SCREEN_TEXTURE", ScreenTexture);
|
||||||
|
|
||||||
|
var worldHandle = args.WorldHandle;
|
||||||
|
var viewport = args.WorldBounds;
|
||||||
|
worldHandle.SetTransform(Matrix3.Identity);
|
||||||
|
worldHandle.UseShader(_greyscaleShader);
|
||||||
|
worldHandle.DrawRect(viewport, Color.White);
|
||||||
|
worldHandle.UseShader(_circleMaskShader);
|
||||||
|
worldHandle.DrawRect(viewport, Color.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
Content.Client/Eye/Blinding/BlindingSystem.cs
Normal file
51
Content.Client/Eye/Blinding/BlindingSystem.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using Content.Shared.Eye.Blinding;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.Player;
|
||||||
|
|
||||||
|
namespace Content.Client.Eye.Blinding;
|
||||||
|
|
||||||
|
public sealed class BlindingSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
|
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||||
|
|
||||||
|
private BlindOverlay _overlay = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<BlindableComponent, ComponentInit>(OnBlindInit);
|
||||||
|
SubscribeLocalEvent<BlindableComponent, ComponentShutdown>(OnBlindShutdown);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<BlindableComponent, PlayerAttachedEvent>(OnPlayerAttached);
|
||||||
|
SubscribeLocalEvent<BlindableComponent, PlayerDetachedEvent>(OnPlayerDetached);
|
||||||
|
|
||||||
|
_overlay = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayerAttached(EntityUid uid, BlindableComponent component, PlayerAttachedEvent args)
|
||||||
|
{
|
||||||
|
_overlayMan.AddOverlay(_overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayerDetached(EntityUid uid, BlindableComponent component, PlayerDetachedEvent args)
|
||||||
|
{
|
||||||
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBlindInit(EntityUid uid, BlindableComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
if (_player.LocalPlayer?.ControlledEntity == uid)
|
||||||
|
_overlayMan.AddOverlay(_overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBlindShutdown(EntityUid uid, BlindableComponent component, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
if (_player.LocalPlayer?.ControlledEntity == uid)
|
||||||
|
{
|
||||||
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ using System.Linq;
|
|||||||
using Content.Shared.DragDrop;
|
using Content.Shared.DragDrop;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.MobState.Components;
|
using Content.Shared.MobState.Components;
|
||||||
|
using Content.Shared.Eye.Blinding;
|
||||||
using Content.Shared.MobState.EntitySystems;
|
using Content.Shared.MobState.EntitySystems;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
@@ -98,7 +99,7 @@ namespace Content.Shared.Examine
|
|||||||
{
|
{
|
||||||
if (MobStateSystem.IsDead(examiner, mobState))
|
if (MobStateSystem.IsDead(examiner, mobState))
|
||||||
return DeadExamineRange;
|
return DeadExamineRange;
|
||||||
else if (MobStateSystem.IsCritical(examiner, mobState))
|
else if (MobStateSystem.IsCritical(examiner, mobState) || (TryComp<BlindableComponent>(examiner, out var blind) && blind.Sources > 0))
|
||||||
return CritExamineRange;
|
return CritExamineRange;
|
||||||
}
|
}
|
||||||
return ExamineRange;
|
return ExamineRange;
|
||||||
|
|||||||
26
Content.Shared/Eye/Blinding/BlindableComponent.cs
Normal file
26
Content.Shared/Eye/Blinding/BlindableComponent.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Eye.Blinding
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
[NetworkedComponent]
|
||||||
|
public sealed class BlindableComponent : Component
|
||||||
|
{
|
||||||
|
/// <description>
|
||||||
|
/// How many sources of blindness are affecting us?
|
||||||
|
/// </description>
|
||||||
|
[DataField("sources")]
|
||||||
|
public int Sources = 0;
|
||||||
|
|
||||||
|
/// <description>
|
||||||
|
/// Used to ensure that this doesn't break with sandbox or admin tools.
|
||||||
|
/// This is not "enabled/disabled".
|
||||||
|
/// </description>
|
||||||
|
public bool LightSetup = false;
|
||||||
|
|
||||||
|
/// <description>
|
||||||
|
/// Gives an extra frame of blindness to reenable light manager during
|
||||||
|
/// </description>
|
||||||
|
public bool GraceFrame = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Content.Shared/Eye/Blinding/BlindfoldComponent.cs
Normal file
12
Content.Shared/Eye/Blinding/BlindfoldComponent.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Eye.Blinding
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
[NetworkedComponent]
|
||||||
|
public sealed class BlindfoldComponent : Component
|
||||||
|
{
|
||||||
|
[ViewVariables]
|
||||||
|
public bool IsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Content.Shared/Eye/Blinding/SharedBlindingSystem.cs
Normal file
40
Content.Shared/Eye/Blinding/SharedBlindingSystem.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using Content.Shared.Inventory.Events;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
|
using Content.Shared.Item;
|
||||||
|
|
||||||
|
namespace Content.Shared.Eye.Blinding
|
||||||
|
{
|
||||||
|
public sealed class SharedBlindingSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<BlindfoldComponent, GotEquippedEvent>(OnEquipped);
|
||||||
|
SubscribeLocalEvent<BlindfoldComponent, GotUnequippedEvent>(OnUnequipped);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEquipped(EntityUid uid, BlindfoldComponent component, GotEquippedEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp<SharedItemComponent>(uid, out var clothing) || clothing.SlotFlags == SlotFlags.PREVENTEQUIP) // we live in a society
|
||||||
|
return;
|
||||||
|
// Is the clothing in its actual slot?
|
||||||
|
if (!clothing.SlotFlags.HasFlag(args.SlotFlags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.IsActive = true;
|
||||||
|
if (!TryComp<BlindableComponent>(args.Equipee, out var blindComp))
|
||||||
|
return;
|
||||||
|
blindComp.Sources++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnequipped(EntityUid uid, BlindfoldComponent component, GotUnequippedEvent args)
|
||||||
|
{
|
||||||
|
if (!component.IsActive)
|
||||||
|
return;
|
||||||
|
component.IsActive = false;
|
||||||
|
if (!TryComp<BlindableComponent>(args.Equipee, out var blindComp))
|
||||||
|
return;
|
||||||
|
blindComp.Sources--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,6 +74,8 @@
|
|||||||
prob: 0.001
|
prob: 0.001
|
||||||
- id: WeaponRevolverInspector
|
- id: WeaponRevolverInspector
|
||||||
prob: 0.001
|
prob: 0.001
|
||||||
|
- id: ClothingShoesBootsMagBlinding
|
||||||
|
prob: 0.001
|
||||||
# - Skub
|
# - Skub
|
||||||
- id: Skub
|
- id: Skub
|
||||||
prob: 0.001
|
prob: 0.001
|
||||||
|
|||||||
@@ -17,3 +17,4 @@
|
|||||||
ClothingUniformJumpsuitSecBlue: 3
|
ClothingUniformJumpsuitSecBlue: 3
|
||||||
ClothingHeadsetSecurity: 3
|
ClothingHeadsetSecurity: 3
|
||||||
ClothingOuterWinterSec: 2
|
ClothingOuterWinterSec: 2
|
||||||
|
ClothingEyesBlindfold: 1
|
||||||
|
|||||||
@@ -26,5 +26,6 @@
|
|||||||
Gohei: 2
|
Gohei: 2
|
||||||
ClothingHeadPaperSack: 2
|
ClothingHeadPaperSack: 2
|
||||||
ClothingHeadPaperSackSmile: 2
|
ClothingHeadPaperSackSmile: 2
|
||||||
|
ClothingEyesBlindfold: 1
|
||||||
emaggedInventory:
|
emaggedInventory:
|
||||||
ClothingShoesBling: 1
|
ClothingShoesBling: 1
|
||||||
|
|||||||
@@ -8,3 +8,18 @@
|
|||||||
sprite: Clothing/Eyes/Misc/eyepatch.rsi
|
sprite: Clothing/Eyes/Misc/eyepatch.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Eyes/Misc/eyepatch.rsi
|
sprite: Clothing/Eyes/Misc/eyepatch.rsi
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: ClothingEyesBase
|
||||||
|
id: ClothingEyesBlindfold
|
||||||
|
name: blindfold
|
||||||
|
description: The bind leading the blind.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Clothing/Eyes/Misc/blindfold.rsi
|
||||||
|
- type: Clothing
|
||||||
|
sprite: Clothing/Eyes/Misc/blindfold.rsi
|
||||||
|
- type: Blindfold
|
||||||
|
- type: Construction
|
||||||
|
graph: Blindfold
|
||||||
|
node: blindfold
|
||||||
|
|||||||
@@ -49,6 +49,20 @@
|
|||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 750
|
price: 750
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: ClothingShoesBootsMag
|
||||||
|
id: ClothingShoesBootsMagBlinding
|
||||||
|
name: magboots of blinding speed
|
||||||
|
description: These would look fetching on a fetcher like you.
|
||||||
|
components:
|
||||||
|
- type: ClothingSpeedModifier
|
||||||
|
walkModifier: 2.5 #PVS isn't too much of an issue when you are blind...
|
||||||
|
sprintModifier: 2.5
|
||||||
|
enabled: false
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 3000
|
||||||
|
- type: Blindfold
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingShoesBase
|
parent: ClothingShoesBase
|
||||||
id: ClothingShoesBootsMagSyndie
|
id: ClothingShoesBootsMagSyndie
|
||||||
|
|||||||
@@ -103,5 +103,6 @@
|
|||||||
- WeaponFlareGun
|
- WeaponFlareGun
|
||||||
- Spear
|
- Spear
|
||||||
- LidSalami
|
- LidSalami
|
||||||
|
- ClothingEyesBlindfold
|
||||||
chance: 0.6
|
chance: 0.6
|
||||||
offset: 0.0
|
offset: 0.0
|
||||||
|
|||||||
@@ -82,6 +82,7 @@
|
|||||||
- PressureImmunity
|
- PressureImmunity
|
||||||
- Muted
|
- Muted
|
||||||
- type: DiseaseCarrier
|
- type: DiseaseCarrier
|
||||||
|
- type: Blindable
|
||||||
# Other
|
# Other
|
||||||
- type: Inventory
|
- type: Inventory
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
- type: constructionGraph
|
||||||
|
id: Blindfold
|
||||||
|
start: start
|
||||||
|
graph:
|
||||||
|
- node: start
|
||||||
|
edges:
|
||||||
|
- to: blindfold
|
||||||
|
steps:
|
||||||
|
- material: Cloth
|
||||||
|
amount: 3
|
||||||
|
doAfter: 10
|
||||||
|
- node: blindfold
|
||||||
|
entity: ClothingEyesBlindfold
|
||||||
@@ -47,3 +47,16 @@
|
|||||||
icon:
|
icon:
|
||||||
sprite: Objects/Specific/Medical/medical.rsi
|
sprite: Objects/Specific/Medical/medical.rsi
|
||||||
state: gauze
|
state: gauze
|
||||||
|
|
||||||
|
- type: construction
|
||||||
|
name: blindfold
|
||||||
|
id: blindfold
|
||||||
|
graph: Blindfold
|
||||||
|
startNode: start
|
||||||
|
targetNode: blindfold
|
||||||
|
category: Tools
|
||||||
|
objectType: Item
|
||||||
|
description: Better hope everyone turns a blind eye to you crafting this sussy item...
|
||||||
|
icon:
|
||||||
|
sprite: Clothing/Eyes/Misc/blindfold.rsi
|
||||||
|
state: icon
|
||||||
|
|||||||
@@ -2,3 +2,8 @@
|
|||||||
id: Greyscale
|
id: Greyscale
|
||||||
kind: source
|
kind: source
|
||||||
path: "/Textures/Shaders/greyscale.swsl"
|
path: "/Textures/Shaders/greyscale.swsl"
|
||||||
|
|
||||||
|
- type: shader
|
||||||
|
id: GreyscaleFullscreen
|
||||||
|
kind: source
|
||||||
|
path: "/Textures/Shaders/greyscale_fullscreen.swsl"
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 347 B |
BIN
Resources/Textures/Clothing/Eyes/Misc/blindfold.rsi/icon.png
Normal file
BIN
Resources/Textures/Clothing/Eyes/Misc/blindfold.rsi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 269 B |
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/40d89d11ea4a5cb81d61dc1018b46f4e7d32c62a",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "equipped-EYES",
|
||||||
|
"directions": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
9
Resources/Textures/Shaders/greyscale_fullscreen.swsl
Normal file
9
Resources/Textures/Shaders/greyscale_fullscreen.swsl
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
uniform sampler2D SCREEN_TEXTURE;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
highp vec4 color = zTextureSpec(SCREEN_TEXTURE, UV);
|
||||||
|
|
||||||
|
highp float grey = dot(color.rgb, vec3(0.299, 0.587, 0.114));
|
||||||
|
|
||||||
|
COLOR = vec4(vec3(grey), color.a);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user