Реворк сварочной маски. Порт PR визардов 31999 (#1623)

This commit is contained in:
banumbas 2025-04-03 00:10:28 +03:00 committed by GitHub
parent 0a2ef6ec2b
commit 57578360e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 443 additions and 11 deletions

View file

@ -0,0 +1,63 @@
using Robust.Client.Graphics;
using Robust.Shared.Player;
using Robust.Client.Player;
using Content.Client.Overlays;
using Content.Shared.Eye;
using Content.Client.Eye;
using Content.Client.Sunrise.Overlays;
using Content.Client.Sunrise.Eye;
using Content.Shared.Sunrise.Eye;
namespace Content.Client.Sunrise.Eye;
public sealed class DarkenedVisionSystem : SharedDarkenedVisionSystem
{
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IOverlayManager _overlayMan = default!;
private DarkenedVisionOverlay _overlay = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DarkenedVisionComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<DarkenedVisionComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<DarkenedVisionComponent, LocalPlayerAttachedEvent>(OnAttached);
SubscribeLocalEvent<DarkenedVisionComponent, LocalPlayerDetachedEvent>(OnDetached);
_overlay = new();
}
private void OnAttached(Entity<DarkenedVisionComponent> ent, ref LocalPlayerAttachedEvent args)
{
_overlayMan.AddOverlay(_overlay);
_overlay.DarkenedVision = ent.Comp;
}
private void OnDetached(Entity<DarkenedVisionComponent> ent, ref LocalPlayerDetachedEvent args)
{
_overlayMan.RemoveOverlay(_overlay);
_overlay.DarkenedVision = null;
}
private void OnStartup(Entity<DarkenedVisionComponent> ent, ref ComponentStartup args)
{
if (_player.LocalEntity == ent.Owner)
{
_overlayMan.AddOverlay(_overlay);
_overlay.DarkenedVision = ent.Comp;
}
}
private void OnShutdown(Entity<DarkenedVisionComponent> ent, ref ComponentShutdown args)
{
if (_player.LocalEntity == ent.Owner)
{
_overlayMan.RemoveOverlay(_overlay);
_overlay.DarkenedVision = null;
}
}
}

View file

@ -0,0 +1,75 @@
using Content.Client.Movement.Systems;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Content.Shared.Eye.Blinding;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Eye;
using Content.Client.Overlays;
using Content.Shared.Sunrise.Eye;
using Content.Client.Sunrise.Overlays;
namespace Content.Client.Sunrise.Overlays;
public sealed class DarkenedVisionOverlay : Overlay
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
public override bool RequestScreenTexture => true;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _circleMaskShader;
public DarkenedVisionComponent? DarkenedVision;
public DarkenedVisionOverlay()
{
IoCManager.InjectDependencies(this);
_circleMaskShader = _prototypeManager.Index<ShaderPrototype>("CircleMask").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;
return DarkenedVision != null && DarkenedVision.Strength < DarkenedVision.BlindTreshold && DarkenedVision.Strength > 0;
}
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
return;
var playerEntity = _playerManager.LocalSession?.AttachedEntity;
if (playerEntity == null)
return;
if (_entityManager.TryGetComponent<EyeComponent>(playerEntity, out var content))
{
_circleMaskShader?.SetParameter("Zoom", content.Zoom.X);
}
_circleMaskShader?.SetParameter("CirclePow", 1f);
_circleMaskShader?.SetParameter("CircleRadius", (10 - DarkenedVision!.Strength) * 32f);
var worldHandle = args.WorldHandle;
var viewport = args.WorldBounds;
worldHandle.UseShader(_circleMaskShader);
worldHandle.DrawRect(viewport, Color.White);
worldHandle.UseShader(null);
}
}

View file

@ -0,0 +1,15 @@
using Content.Shared.Clothing;
using Content.Shared.Clothing.Components;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Inventory;
using Content.Shared.Tag;
using Content.Shared.Eye;
using Content.Shared.Sunrise.Eye;
using Content.Shared.Sunrise.Clothing.EntitySystems;
using Content.Shared.Sunrise.Clothing.Components;
namespace Content.Server.Sunrise.Eye;
public sealed class DarkenedVisionSystem : SharedDarkenedVisionSystem {}

View file

@ -0,0 +1,13 @@
using Robust.Shared.GameStates;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Clothing.Components;
using Content.Shared.Sunrise.Clothing.EntitySystems;
using Content.Shared.Sunrise.Clothing.Components;
using Content.Shared.Clothing;
namespace Content.Shared.Sunrise.Clothing.Components;
[RegisterComponent, NetworkedComponent, Access(typeof(WeldingMaskSystem))]
public sealed partial class WeldingMaskComponent : Component
{
}

View file

@ -0,0 +1,36 @@
using Content.Shared.Clothing.Components;
using Content.Shared.Eye;
using Content.Shared.Item;
using Content.Shared.Item.ItemToggle.Components;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Sunrise.Eye;
using Content.Shared.Sunrise.Clothing.EntitySystems;
using Content.Shared.Sunrise.Clothing.Components;
using Content.Shared.Clothing;
namespace Content.Shared.Sunrise.Clothing.EntitySystems;
public sealed class WeldingMaskSystem : EntitySystem
{
[Dependency] private readonly ClothingSystem _clothing = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
[Dependency] private readonly SharedDarkenedVisionSystem _darkenedVision = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<WeldingMaskComponent, ItemToggledEvent>(OnToggle);
}
private void OnToggle(Entity<WeldingMaskComponent> ent, ref ItemToggledEvent args)
{
var prefix = args.Activated ? null : "up";
_clothing.SetEquippedPrefix(ent, prefix);
_item.SetHeldPrefix(ent, prefix);
if (args.User is not { } user) return;
_darkenedVision.UpdateVisionDarkening(user);
}
}

View file

@ -0,0 +1,27 @@
using Robust.Shared.GameStates;
using Content.Shared.Sunrise.Eye;
using Content.Shared.Sunrise.Clothing.EntitySystems;
using Content.Shared.Sunrise.Clothing.Components;
using Content.Shared.Clothing;
namespace Content.Shared.Sunrise.Eye;
/// <summary>
/// Adds overlay for client that darkness vision
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedDarkenedVisionSystem))]
public sealed partial class DarkenedVisionComponent : Component
{
/// <summary>
/// How much is vision darkened (in tiles from screen edge)
/// </summary>
[DataField, AutoNetworkedField]
public float Strength = 0;
/// <summary>
/// If strength is higher than this value users goes blind
/// </summary>
[DataField]
public float BlindTreshold = 8;
}

View file

@ -0,0 +1,54 @@
using Content.Shared.Clothing;
using Content.Shared.Clothing.Components;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Inventory;
using Content.Shared.Tag;
using Content.Shared.Eye;
using Content.Shared.Sunrise.Eye;
using Content.Shared.Sunrise.Clothing.Components;
namespace Content.Shared.Sunrise.Eye;
public abstract class SharedDarkenedVisionSystem : EntitySystem
{
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly BlindableSystem _blinding = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DarkenedVisionComponent, CanSeeAttemptEvent>(OnTrySee);
}
public void UpdateVisionDarkening(Entity<DarkenedVisionComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp, false))
return;
var ev = new GetVisionDarkeningEvent();
RaiseLocalEvent(ent, ev);
if (TryComp<InventoryComponent>(ent, out var inventory))
_inventory.RelayEvent((ent.Owner, inventory), ref ev);
ent.Comp.Strength = ev.Strength;
Dirty(ent);
_blinding.UpdateIsBlind(ent.Owner);
}
private void OnTrySee(Entity<DarkenedVisionComponent> ent, ref CanSeeAttemptEvent args)
{
if (ent.Comp.Strength >= ent.Comp.BlindTreshold) args.Cancel();
}
}
/// <summary>
/// Event to get total vision darkening
/// </summary>
public sealed class GetVisionDarkeningEvent : EntityEventArgs, IInventoryRelayEvent
{
public SlotFlags TargetSlots => SlotFlags.EYES | SlotFlags.MASK | SlotFlags.HEAD;
public float Strength = 0f;
}

View file

@ -0,0 +1,14 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Sunrise.Eye;
/// <summary>
/// Piece of gear that darkens the user vision
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(VisionDarkenerSystem))]
public sealed partial class VisionDarkenerComponent : Component
{
[DataField, AutoNetworkedField]
public float Strength = 0;
}

View file

@ -0,0 +1,46 @@
using Content.Shared.Clothing;
using Content.Shared.Clothing.Components;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Inventory;
using Content.Shared.Tag;
using Content.Shared.Eye;
using Content.Shared.Sunrise.Eye;
using Content.Shared.Sunrise.Clothing.Components;
namespace Content.Shared.Sunrise.Eye;
public sealed class VisionDarkenerSystem : EntitySystem
{
[Dependency] private readonly SharedDarkenedVisionSystem _darkenedVision = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<VisionDarkenerComponent, GetVisionDarkeningEvent>(OnGetVisionDarkening);
SubscribeLocalEvent<VisionDarkenerComponent, InventoryRelayedEvent<GetVisionDarkeningEvent>>(OnGetVisionDarkening);
SubscribeLocalEvent<VisionDarkenerComponent, ClothingGotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<VisionDarkenerComponent, ClothingGotUnequippedEvent>(OnGotUnquipped);
}
private void OnGetVisionDarkening(Entity<VisionDarkenerComponent> ent, ref GetVisionDarkeningEvent args)
{
args.Strength += ent.Comp.Strength;
}
private void OnGetVisionDarkening(Entity<VisionDarkenerComponent> ent, ref InventoryRelayedEvent<GetVisionDarkeningEvent> args)
{
args.Args.Strength += ent.Comp.Strength;
}
private void OnGotEquipped(Entity<VisionDarkenerComponent> ent, ref ClothingGotEquippedEvent args)
{
_darkenedVision.UpdateVisionDarkening(args.Wearer);
}
private void OnGotUnquipped(Entity<VisionDarkenerComponent> ent, ref ClothingGotUnequippedEvent args)
{
_darkenedVision.UpdateVisionDarkening(args.Wearer);
}
}

View file

@ -1,6 +1,6 @@
- type: entity
parent: ClothingHeadBase
id: WeldingMaskBase
id: WeldingMaskBase # Left for the guys made by the greatest prototypers of Sunrise.
name: welding mask
abstract: true
components:
@ -25,15 +25,56 @@
- Snout
- type: entity
parent: WeldingMaskBase
id: ClothingHeadHatWelding
parent: [ClothingHeadBase, BaseToggleClothing] # Sunrise-Edit
id: ClothingHeadHatWelding # Sunrise-Edit
name: welding mask
# Sunrise-Start
# abstract: true
description: A head-mounted face cover designed to protect the wearer completely from space-arc eye.
components:
- type: Sprite
sprite: Clothing/Head/Welding/welding.rsi
layers:
- state: icon
map: [ "enum.ToggleVisuals.Layer" ]
- type: Clothing
sprite: Clothing/Head/Welding/welding.rsi
# Sunrise End
- type: Item
storedRotation: 0
- type: ItemToggle # Welding mask starts in an activated state
activated: true
- type: ToggleClothing
action: ActionToggleWeldingMask
- type: HideLayerClothing
slots:
- Snout
hideOnToggle: true
- type: Appearance
- type: WeldingMask
- type: GenericVisualizer
visuals:
enum.ToggleVisuals.Toggled:
enum.ToggleVisuals.Layer:
True: {state: icon}
False: {state: icon-up}
# Sunrise-End
- type: PhysicalComposition
materialComposition:
Steel: 200
Glass: 100
- type: StaticPrice
price: 50
# Sunrise-Start
- type: ComponentToggler
components:
- type: IngestionBlocker
- type: FlashImmunity
- type: IdentityBlocker
- type: EyeProtection
- type: VisionDarkener
strength: 6
# Sunrise-End
- type: Tag
tags:
- HamsterWearable
@ -41,34 +82,79 @@
- WeldingMask
- type: entity
parent: WeldingMaskBase
parent: ClothingHeadHatWelding # Sunrise-Edit
id: ClothingHeadHatWeldingMaskFlame
name: flame welding mask
description: A painted welding helmet, this one has flames on it.
components:
- type: Sprite
sprite: Clothing/Head/Welding/flame_welding_mask.rsi
# Sunrise-Start
layers:
- state: icon
map: [ "enum.ToggleVisuals.Layer" ]
# Sunrise-End
- type: Clothing
sprite: Clothing/Head/Welding/flame_welding_mask.rsi
# Sunrise-Start
- type: Tag
tags:
- WhitelistChameleon
- WeldingMask
# Sunrise-End
- type: entity
parent: WeldingMaskBase
parent: ClothingHeadHatWelding # Sunrise-Edit
id: ClothingHeadHatWeldingMaskFlameBlue
name: blue-flame welding mask
description: A painted welding helmet, this one has blue flames on it.
components:
- type: Sprite
sprite: Clothing/Head/Welding/blue_flame_welding_mask.rsi
# Sunrise-Start
layers:
- state: icon
map: [ "enum.ToggleVisuals.Layer" ]
# Sunrise-End
- type: Clothing
sprite: Clothing/Head/Welding/blue_flame_welding_mask.rsi
# Sunrise-Start
- type: Tag
tags:
- WhitelistChameleon
- WeldingMask
# Sunrise-End
- type: entity
parent: WeldingMaskBase
parent: ClothingHeadHatWelding # Sunrise-Edit
id: ClothingHeadHatWeldingMaskPainted
name: painted welding mask
description: A welding helmet, painted in crimson.
components:
- type: Sprite
sprite: Clothing/Head/Welding/paintedwelding.rsi
# Sunrise-Start
layers:
- state: icon
map: [ "enum.ToggleVisuals.Layer" ]
# Sunrise-End
- type: Clothing
sprite: Clothing/Head/Welding/paintedwelding.rsi
# Sunrise-Start
- type: Tag
tags:
- WhitelistChameleon
- WeldingMask
# Sunrise-End
# Sunrise-Start
- type: entity
id: ActionToggleWeldingMask
name: Adjust Welding Mask
description: Covers or reveals your face.
components:
- type: InstantAction
useDelay: 1
itemIconStyle: BigItem
event: !type:ToggleActionEvent
# Sunrise-End

View file

@ -267,6 +267,7 @@
abstract: true
components:
# Sunrise-Start
- type: DarkenedVision
- type: CanEscapeInventory
- type: Mood
- type: CritHeartbeat

View file

@ -56,12 +56,14 @@
sprite: _Sunrise/Clothing/Eyes/Glasses/weldglasses.rsi
- type: Clothing
sprite: _Sunrise/Clothing/Eyes/Glasses/weldglasses.rsi
#- type: FlashImmunity
- type: IdentityBlocker
coverage: EYES
- type: FlashImmunity
- type: EyeProtection
- type: Tag
tags:
- HamsterWearable
- WhitelistChameleon
- type: VisionDarkener
strength: 3
- type: StaticPrice
price: 8
- type: entity
parent: ClothingEyesBase