Blindness rework - damaged eyes are now a stylized simulation of legal blindness (#23212)
* blindness rework - damaged eyes now simulate legal blindness * hEY THATS FOR DEMONSTRATION PURPOSES ONLY AAA * attributions * makes eyeclosecomponent adminbus compatible * useshader(null)
This commit is contained in:
@@ -1505,6 +1505,18 @@ namespace Content.Shared.CCVar
|
||||
CVarDef.Create("ui.separated_chat_size", "0.6,0", CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
|
||||
/*
|
||||
* Accessibility
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Toggle for visual effects that may potentially cause motion sickness.
|
||||
/// Where reasonable, effects affected by this CVar should use an alternate effect.
|
||||
/// Please do not use this CVar as a bandaid for effects that could otherwise be made accessible without issue.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> ReducedMotion =
|
||||
CVarDef.Create("accessibility.reduced_motion", false, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
/*
|
||||
* CHAT
|
||||
*/
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace Content.Shared.Examine
|
||||
public const float ExamineRange = 16f;
|
||||
protected const float ExamineDetailsRange = 3f;
|
||||
|
||||
protected const float ExamineBlurrinessMult = 2.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new examine tooltip with arbitrary info.
|
||||
/// </summary>
|
||||
@@ -125,7 +127,7 @@ namespace Content.Shared.Examine
|
||||
return CritExamineRange;
|
||||
|
||||
if (TryComp<BlurryVisionComponent>(examiner, out var blurry))
|
||||
return Math.Clamp(ExamineRange - blurry.Magnitude, 2, ExamineRange);
|
||||
return Math.Clamp(ExamineRange - blurry.Magnitude * ExamineBlurrinessMult, 2, ExamineRange);
|
||||
}
|
||||
return ExamineRange;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public sealed partial class BlindableComponent : Component
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("EyeDamage"), AutoNetworkedField]
|
||||
public int EyeDamage = 0;
|
||||
|
||||
public const int MaxDamage = 3;
|
||||
public const int MaxDamage = 9;
|
||||
|
||||
/// <description>
|
||||
/// Used to ensure that this doesn't break with sandbox or admin tools.
|
||||
|
||||
@@ -17,5 +17,12 @@ public sealed partial class BlurryVisionComponent : Component
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("magnitude"), AutoNetworkedField]
|
||||
public float Magnitude;
|
||||
|
||||
public const float MaxMagnitude = 3;
|
||||
/// <summary>
|
||||
/// Exponent that controls the magnitude of the effect.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("correctionPower"), AutoNetworkedField]
|
||||
public float CorrectionPower;
|
||||
|
||||
public const float MaxMagnitude = 6;
|
||||
public const float DefaultCorrectionPower = 2f;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using Content.Shared.Eye.Blinding.Systems;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Eye.Blinding.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows mobs to toggle their eyes between being closed and being not closed.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||
public sealed partial class EyeClosingComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The prototype to grant to enable eye-toggling action.
|
||||
/// </summary>
|
||||
[DataField("eyeToggleAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string EyeToggleAction = "ActionToggleEyes";
|
||||
|
||||
/// <summary>
|
||||
/// The actual eye toggling action entity itself.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityUid? EyeToggleActionEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Path to sound to play when opening eyes
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
|
||||
public string EyeOpenSound = "/Audio/Effects/eye_open.ogg";
|
||||
|
||||
/// <summary>
|
||||
/// Path to sound to play when closing eyes
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
|
||||
public string EyeCloseSound = "/Audio/Effects/eye_close.ogg";
|
||||
|
||||
/// <summary>
|
||||
/// Toggles whether the eyes are open or closed. This is really just exactly what it says on the tin. Honest.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
|
||||
public bool EyesClosed;
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly), DataField]
|
||||
public bool PreviousEyelidPosition;
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly), DataField]
|
||||
public bool NaturallyCreated;
|
||||
}
|
||||
@@ -9,6 +9,15 @@ namespace Content.Shared.Eye.Blinding.Components;
|
||||
[NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class VisionCorrectionComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Amount of effective eye damage to add when this item is worn
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("visionBonus"), AutoNetworkedField]
|
||||
public float VisionBonus = 3f;
|
||||
public float VisionBonus = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Controls the exponent of the blur effect when worn
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("correctionPower"), AutoNetworkedField]
|
||||
public float CorrectionPower = 2f;
|
||||
}
|
||||
|
||||
@@ -7,57 +7,67 @@ namespace Content.Shared.Eye.Blinding.Systems;
|
||||
|
||||
public sealed class BlindableSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly BlurryVisionSystem _blurriness = default!;
|
||||
[Dependency] private readonly EyeClosingSystem _eyelids = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<BlindableComponent, RejuvenateEvent>(OnRejuvenate);
|
||||
SubscribeLocalEvent<BlindableComponent, EyeDamageChangedEvent>(OnDamageChanged);
|
||||
}
|
||||
|
||||
private void OnRejuvenate(EntityUid uid, BlindableComponent component, RejuvenateEvent args)
|
||||
private void OnRejuvenate(Entity<BlindableComponent> ent, ref RejuvenateEvent args)
|
||||
{
|
||||
AdjustEyeDamage(uid, -component.EyeDamage, component);
|
||||
AdjustEyeDamage((ent.Owner, ent.Comp), -ent.Comp.EyeDamage);
|
||||
}
|
||||
|
||||
private void OnDamageChanged(Entity<BlindableComponent> ent, ref EyeDamageChangedEvent args)
|
||||
{
|
||||
_blurriness.UpdateBlurMagnitude((ent.Owner, ent.Comp));
|
||||
_eyelids.UpdateEyesClosable((ent.Owner, ent.Comp));
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public void UpdateIsBlind(EntityUid uid, BlindableComponent? blindable = null)
|
||||
public void UpdateIsBlind(Entity<BlindableComponent?> blindable)
|
||||
{
|
||||
if (!Resolve(uid, ref blindable, false))
|
||||
if (!Resolve(blindable, ref blindable.Comp, false))
|
||||
return;
|
||||
|
||||
var old = blindable.IsBlind;
|
||||
var old = blindable.Comp.IsBlind;
|
||||
|
||||
// Don't bother raising an event if the eye is too damaged.
|
||||
if (blindable.EyeDamage >= BlindableComponent.MaxDamage)
|
||||
if (blindable.Comp.EyeDamage >= BlindableComponent.MaxDamage)
|
||||
{
|
||||
blindable.IsBlind = true;
|
||||
blindable.Comp.IsBlind = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ev = new CanSeeAttemptEvent();
|
||||
RaiseLocalEvent(uid, ev);
|
||||
blindable.IsBlind = ev.Blind;
|
||||
RaiseLocalEvent(blindable.Owner, ev);
|
||||
blindable.Comp.IsBlind = ev.Blind;
|
||||
}
|
||||
|
||||
if (old == blindable.IsBlind)
|
||||
if (old == blindable.Comp.IsBlind)
|
||||
return;
|
||||
|
||||
var changeEv = new BlindnessChangedEvent(blindable.IsBlind);
|
||||
RaiseLocalEvent(uid, ref changeEv);
|
||||
var changeEv = new BlindnessChangedEvent(blindable.Comp.IsBlind);
|
||||
RaiseLocalEvent(blindable.Owner, ref changeEv);
|
||||
Dirty(blindable);
|
||||
}
|
||||
|
||||
public void AdjustEyeDamage(EntityUid uid, int amount, BlindableComponent? blindable = null)
|
||||
public void AdjustEyeDamage(Entity<BlindableComponent?> blindable, int amount)
|
||||
{
|
||||
if (!Resolve(uid, ref blindable, false) || amount == 0)
|
||||
if (!Resolve(blindable, ref blindable.Comp, false) || amount == 0)
|
||||
return;
|
||||
|
||||
blindable.EyeDamage += amount;
|
||||
blindable.EyeDamage = Math.Clamp(blindable.EyeDamage, 0, BlindableComponent.MaxDamage);
|
||||
blindable.Comp.EyeDamage += amount;
|
||||
blindable.Comp.EyeDamage = Math.Clamp(blindable.Comp.EyeDamage, 0, BlindableComponent.MaxDamage);
|
||||
Dirty(blindable);
|
||||
UpdateIsBlind(uid, blindable);
|
||||
UpdateIsBlind(blindable);
|
||||
|
||||
var ev = new EyeDamageChangedEvent(blindable.EyeDamage);
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
var ev = new EyeDamageChangedEvent(blindable.Comp.EyeDamage);
|
||||
RaiseLocalEvent(blindable.Owner, ref ev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +81,7 @@ public record struct BlindnessChangedEvent(bool Blind);
|
||||
/// This event is raised when an entity's eye damage changes
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct EyeDamageChangedEvent(int Damage);
|
||||
public record struct EyeDamageChangedEvent(int Damage);
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed at an entity to see whether the entity is currently blind or not.
|
||||
|
||||
@@ -17,17 +17,17 @@ public sealed class BlindfoldSystem : EntitySystem
|
||||
SubscribeLocalEvent<BlindfoldComponent, InventoryRelayedEvent<CanSeeAttemptEvent>>(OnBlindfoldTrySee);
|
||||
}
|
||||
|
||||
private void OnBlindfoldTrySee(EntityUid uid, BlindfoldComponent component, InventoryRelayedEvent<CanSeeAttemptEvent> args)
|
||||
private void OnBlindfoldTrySee(Entity<BlindfoldComponent> blindfold, ref InventoryRelayedEvent<CanSeeAttemptEvent> args)
|
||||
{
|
||||
args.Args.Cancel();
|
||||
}
|
||||
|
||||
private void OnEquipped(EntityUid uid, BlindfoldComponent component, GotEquippedEvent args)
|
||||
private void OnEquipped(Entity<BlindfoldComponent> blindfold, ref GotEquippedEvent args)
|
||||
{
|
||||
_blindableSystem.UpdateIsBlind(args.Equipee);
|
||||
}
|
||||
|
||||
private void OnUnequipped(EntityUid uid, BlindfoldComponent component, GotUnequippedEvent args)
|
||||
private void OnUnequipped(Entity<BlindfoldComponent> blindfold, ref GotUnequippedEvent args)
|
||||
{
|
||||
_blindableSystem.UpdateIsBlind(args.Equipee);
|
||||
}
|
||||
|
||||
@@ -6,54 +6,52 @@ namespace Content.Shared.Eye.Blinding.Systems;
|
||||
|
||||
public sealed class BlurryVisionSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<BlindableComponent, EyeDamageChangedEvent>(OnDamageChanged);
|
||||
SubscribeLocalEvent<VisionCorrectionComponent, GotEquippedEvent>(OnGlassesEquipped);
|
||||
SubscribeLocalEvent<VisionCorrectionComponent, GotUnequippedEvent>(OnGlassesUnequipped);
|
||||
SubscribeLocalEvent<VisionCorrectionComponent, InventoryRelayedEvent<GetBlurEvent>>(OnGetBlur);
|
||||
}
|
||||
|
||||
private void OnGetBlur(EntityUid uid, VisionCorrectionComponent component, InventoryRelayedEvent<GetBlurEvent> args)
|
||||
private void OnGetBlur(Entity<VisionCorrectionComponent> glasses, ref InventoryRelayedEvent<GetBlurEvent> args)
|
||||
{
|
||||
args.Args.Blur += component.VisionBonus;
|
||||
args.Args.Blur += glasses.Comp.VisionBonus;
|
||||
args.Args.CorrectionPower *= glasses.Comp.CorrectionPower;
|
||||
}
|
||||
|
||||
private void OnDamageChanged(EntityUid uid, BlindableComponent component, ref EyeDamageChangedEvent args)
|
||||
public void UpdateBlurMagnitude(Entity<BlindableComponent?> ent)
|
||||
{
|
||||
UpdateBlurMagnitude(uid, component);
|
||||
}
|
||||
|
||||
private void UpdateBlurMagnitude(EntityUid uid, BlindableComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component, false))
|
||||
if (!Resolve(ent.Owner, ref ent.Comp, false))
|
||||
return;
|
||||
|
||||
var ev = new GetBlurEvent(component.EyeDamage);
|
||||
RaiseLocalEvent(uid, ev);
|
||||
var ev = new GetBlurEvent(ent.Comp.EyeDamage);
|
||||
RaiseLocalEvent(ent, ev);
|
||||
|
||||
var blur = Math.Clamp(0, ev.Blur, BlurryVisionComponent.MaxMagnitude);
|
||||
var blur = Math.Clamp(ev.Blur, 0, BlurryVisionComponent.MaxMagnitude);
|
||||
if (blur <= 0)
|
||||
{
|
||||
RemCompDeferred<BlurryVisionComponent>(uid);
|
||||
RemCompDeferred<BlurryVisionComponent>(ent);
|
||||
return;
|
||||
}
|
||||
|
||||
var blurry = EnsureComp<BlurryVisionComponent>(uid);
|
||||
var blurry = EnsureComp<BlurryVisionComponent>(ent);
|
||||
blurry.Magnitude = blur;
|
||||
Dirty(blurry);
|
||||
blurry.CorrectionPower = ev.CorrectionPower;
|
||||
Dirty(ent, blurry);
|
||||
}
|
||||
|
||||
private void OnGlassesEquipped(EntityUid uid, VisionCorrectionComponent component, GotEquippedEvent args)
|
||||
private void OnGlassesEquipped(Entity<VisionCorrectionComponent> glasses, ref GotEquippedEvent args)
|
||||
{
|
||||
UpdateBlurMagnitude(uid);
|
||||
UpdateBlurMagnitude(args.Equipee);
|
||||
}
|
||||
|
||||
private void OnGlassesUnequipped(EntityUid uid, VisionCorrectionComponent component, GotUnequippedEvent args)
|
||||
private void OnGlassesUnequipped(Entity<VisionCorrectionComponent> glasses, ref GotUnequippedEvent args)
|
||||
{
|
||||
UpdateBlurMagnitude(uid);
|
||||
UpdateBlurMagnitude(args.Equipee);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +59,7 @@ public sealed class GetBlurEvent : EntityEventArgs, IInventoryRelayEvent
|
||||
{
|
||||
public readonly float BaseBlur;
|
||||
public float Blur;
|
||||
public float CorrectionPower = BlurryVisionComponent.DefaultCorrectionPower;
|
||||
|
||||
public GetBlurEvent(float blur)
|
||||
{
|
||||
|
||||
141
Content.Shared/Eye/Blinding/Systems/EyeClosingSystem.cs
Normal file
141
Content.Shared/Eye/Blinding/Systems/EyeClosingSystem.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Eye.Blinding.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Eye.Blinding.Systems;
|
||||
|
||||
public sealed class EyeClosingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly BlindableSystem _blindableSystem = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly ISharedPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<EyeClosingComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<EyeClosingComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<EyeClosingComponent, ToggleEyesActionEvent>(OnToggleAction);
|
||||
SubscribeLocalEvent<EyeClosingComponent, CanSeeAttemptEvent>(OnTrySee);
|
||||
SubscribeLocalEvent<EyeClosingComponent, AfterAutoHandleStateEvent>(OnHandleState);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<EyeClosingComponent> eyelids, ref MapInitEvent args)
|
||||
{
|
||||
_actionsSystem.AddAction(eyelids, ref eyelids.Comp.EyeToggleActionEntity, eyelids.Comp.EyeToggleAction);
|
||||
Dirty(eyelids);
|
||||
}
|
||||
|
||||
private void OnShutdown(Entity<EyeClosingComponent> eyelids, ref ComponentShutdown args)
|
||||
{
|
||||
_actionsSystem.RemoveAction(eyelids, eyelids.Comp.EyeToggleActionEntity);
|
||||
|
||||
SetEyelids((eyelids.Owner, eyelids.Comp), false);
|
||||
}
|
||||
|
||||
private void OnToggleAction(Entity<EyeClosingComponent> eyelids, ref ToggleEyesActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
SetEyelids((eyelids.Owner, eyelids.Comp), !eyelids.Comp.EyesClosed);
|
||||
}
|
||||
|
||||
private void OnHandleState(Entity<EyeClosingComponent> eyelids, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
DoAudioFeedback((eyelids.Owner, eyelids.Comp), eyelids.Comp.EyesClosed);
|
||||
}
|
||||
|
||||
private void OnTrySee(Entity<EyeClosingComponent> eyelids, ref CanSeeAttemptEvent args)
|
||||
{
|
||||
if (eyelids.Comp.EyesClosed)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether or not the entity's eyelids are closed.
|
||||
/// </summary>
|
||||
/// <param name="eyelids">The entity that contains an EyeClosingComponent</param>
|
||||
/// <returns>Exactly what this function says on the tin. True if eyes are closed, false if they're open.</returns>
|
||||
public bool AreEyesClosed(Entity<EyeClosingComponent?> eyelids)
|
||||
{
|
||||
return Resolve(eyelids, ref eyelids.Comp, false) && eyelids.Comp.EyesClosed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether or not the entity's eyelids are closed.
|
||||
/// </summary>
|
||||
/// <param name="eyelids">The entity that contains an EyeClosingComponent</param>
|
||||
/// <param name="value">Set to true to close the entity's eyes. Set to false to open them</param>
|
||||
public void SetEyelids(Entity<EyeClosingComponent?> eyelids, bool value)
|
||||
{
|
||||
if (!Resolve(eyelids, ref eyelids.Comp))
|
||||
return;
|
||||
|
||||
if (eyelids.Comp.EyesClosed == value)
|
||||
return;
|
||||
|
||||
eyelids.Comp.EyesClosed = value;
|
||||
Dirty(eyelids);
|
||||
|
||||
if (eyelids.Comp.EyeToggleActionEntity != null)
|
||||
_actionsSystem.SetToggled(eyelids.Comp.EyeToggleActionEntity, eyelids.Comp.EyesClosed);
|
||||
|
||||
_blindableSystem.UpdateIsBlind(eyelids.Owner);
|
||||
|
||||
DoAudioFeedback(eyelids, eyelids.Comp.EyesClosed);
|
||||
}
|
||||
|
||||
public void DoAudioFeedback(Entity<EyeClosingComponent?> eyelids, bool eyelidTarget)
|
||||
{
|
||||
if (!Resolve(eyelids, ref eyelids.Comp))
|
||||
return;
|
||||
|
||||
if (!_net.IsClient || !_timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
if (eyelids.Comp.PreviousEyelidPosition == eyelidTarget)
|
||||
return;
|
||||
|
||||
eyelids.Comp.PreviousEyelidPosition = eyelidTarget;
|
||||
|
||||
if (_playerManager.TryGetSessionByEntity(eyelids, out var session))
|
||||
_audio.PlayGlobal(eyelidTarget ? eyelids.Comp.EyeCloseSound : eyelids.Comp.EyeOpenSound, session);
|
||||
}
|
||||
|
||||
public void UpdateEyesClosable(Entity<BlindableComponent?> blindable)
|
||||
{
|
||||
if (!Resolve(blindable, ref blindable.Comp, false))
|
||||
return;
|
||||
|
||||
var ev = new GetBlurEvent(blindable.Comp.EyeDamage);
|
||||
RaiseLocalEvent(blindable.Owner, ev);
|
||||
|
||||
if (_entityManager.TryGetComponent<EyeClosingComponent>(blindable, out var eyelids) && !eyelids.NaturallyCreated)
|
||||
return;
|
||||
|
||||
if (ev.Blur < BlurryVisionComponent.MaxMagnitude || ev.Blur >= BlindableComponent.MaxDamage)
|
||||
{
|
||||
RemCompDeferred<EyeClosingComponent>(blindable);
|
||||
return;
|
||||
}
|
||||
|
||||
var naturalEyelids = EnsureComp<EyeClosingComponent>(blindable);
|
||||
naturalEyelids.NaturallyCreated = true;
|
||||
Dirty(blindable);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class ToggleEyesActionEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Eye.Blinding;
|
||||
using Content.Shared.Eye.Blinding.Components;
|
||||
using Content.Shared.Eye.Blinding.Systems;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Robust.Shared.Network;
|
||||
@@ -12,6 +12,7 @@ namespace Content.Shared.Traits.Assorted;
|
||||
public sealed class PermanentBlindnessSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly BlindableSystem _blinding = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -19,31 +20,45 @@ public sealed class PermanentBlindnessSystem : EntitySystem
|
||||
{
|
||||
SubscribeLocalEvent<PermanentBlindnessComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<PermanentBlindnessComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<PermanentBlindnessComponent, CanSeeAttemptEvent>(OnTrySee);
|
||||
SubscribeLocalEvent<PermanentBlindnessComponent, EyeDamageChangedEvent>(OnDamageChanged);
|
||||
SubscribeLocalEvent<PermanentBlindnessComponent, ExaminedEvent>(OnExamined);
|
||||
}
|
||||
|
||||
private void OnExamined(EntityUid uid, PermanentBlindnessComponent component, ExaminedEvent args)
|
||||
private void OnExamined(Entity<PermanentBlindnessComponent> blindness, ref ExaminedEvent args)
|
||||
{
|
||||
if (args.IsInDetailsRange && !_net.IsClient)
|
||||
{
|
||||
args.PushMarkup(Loc.GetString("permanent-blindness-trait-examined", ("target", Identity.Entity(uid, EntityManager))));
|
||||
args.PushMarkup(Loc.GetString("permanent-blindness-trait-examined", ("target", Identity.Entity(blindness, EntityManager))));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnShutdown(EntityUid uid, PermanentBlindnessComponent component, ComponentShutdown args)
|
||||
private void OnShutdown(Entity<PermanentBlindnessComponent> blindness, ref ComponentShutdown args)
|
||||
{
|
||||
_blinding.UpdateIsBlind(uid);
|
||||
_blinding.UpdateIsBlind(blindness.Owner);
|
||||
}
|
||||
|
||||
private void OnStartup(EntityUid uid, PermanentBlindnessComponent component, ComponentStartup args)
|
||||
private void OnStartup(Entity<PermanentBlindnessComponent> blindness, ref ComponentStartup args)
|
||||
{
|
||||
_blinding.UpdateIsBlind(uid);
|
||||
if (!_entityManager.TryGetComponent<BlindableComponent>(blindness, out var blindable))
|
||||
return;
|
||||
|
||||
var damageToDeal = (int) BlurryVisionComponent.MaxMagnitude - blindable.EyeDamage;
|
||||
|
||||
if (damageToDeal <= 0)
|
||||
return;
|
||||
|
||||
_blinding.AdjustEyeDamage(blindness.Owner, damageToDeal);
|
||||
}
|
||||
|
||||
private void OnTrySee(EntityUid uid, PermanentBlindnessComponent component, CanSeeAttemptEvent args)
|
||||
private void OnDamageChanged(Entity<PermanentBlindnessComponent> blindness, ref EyeDamageChangedEvent args)
|
||||
{
|
||||
if (component.LifeStage <= ComponentLifeStage.Running)
|
||||
args.Cancel();
|
||||
if (args.Damage >= BlurryVisionComponent.MaxMagnitude)
|
||||
return;
|
||||
|
||||
if (!_entityManager.TryGetComponent<BlindableComponent>(blindness, out var blindable))
|
||||
return;
|
||||
|
||||
var damageRestoration = (int) BlurryVisionComponent.MaxMagnitude - args.Damage;
|
||||
_blinding.AdjustEyeDamage(blindness.Owner, damageRestoration);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user