Files
wwdpublic/Content.Shared/Eye/Blinding/Systems/BlindableSystem.cs
GNUtopia 1b5c4cd923 Make Disabilities Permanent + Glasses' Fury (#2327)
# Description

Removes the ability to circumvent the effects of Blindness and
Wheelchair User through surgery. Additionally tweaks glasses to better
counteract nearsightedness and minor eye damage. Most glasses now
mitigate 3 points of eye damage, fully countering the nearsighted
penalty, while jamjars mitigate 3.5 points of eye damage. Also tweaks
the starting amounts of eye damage given by Blindness and Nearsighted.
Blindness gives 8 points of eye damage, up from 6 (this doesn't have any
visual effect but makes glasses worse since visual effects cap at 6
points), and Nearsighted gives 3 points of eye damage, down from 4.

---
<details><summary><h1>Media</h1></summary>
<p>

![Updated Wheelchair User
description](https://github.com/user-attachments/assets/5c97be58-1c07-452e-acaf-9f83290204ed)
![Updated Blindness
description](https://github.com/user-attachments/assets/085676fc-ff25-47fc-a673-fb89d1899a38)
![Blindness being retained after
surgery](https://github.com/user-attachments/assets/1aa6b35a-129e-4965-bf20-85f3c3f4bfa3)
![Inability to walk being retained after
surgery](https://github.com/user-attachments/assets/2f3b9d19-a75f-429d-8c9a-eeb9ee7dd82b)
(i'm trying to walk around after the surgery in the second video,
prommy)
![Blindness being partially remedied by
glasses](https://github.com/user-attachments/assets/14b8191d-d65f-4034-af37-ac331320dabe)
![Shortsighted being fully mitigated with
glasses](https://github.com/user-attachments/assets/81236a50-1898-441e-bbb2-4ae78165fd99)

</p>
</details>

---

# Changelog

🆑
- tweak: Made Wheelchair User and Blindness permanent
- tweak: Made Shortsighted less visually intense
- tweak: Made glasses counteract eye damage better

---------

Signed-off-by: Timfa <timfalken@hotmail.com>
Co-authored-by: Timfa <timfalken@hotmail.com>
(cherry picked from commit 0187c38b3a96220f133281adf311cf259b3f4e50)
2025-05-03 01:38:32 +03:00

141 lines
4.7 KiB
C#

using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Inventory;
using Content.Shared.Rejuvenate;
using JetBrains.Annotations;
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(Entity<BlindableComponent> ent, ref RejuvenateEvent args)
{
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(Entity<BlindableComponent?> blindable)
{
if (!Resolve(blindable, ref blindable.Comp, false))
return;
var old = blindable.Comp.IsBlind;
// Don't bother raising an event if the eye is too damaged.
if (blindable.Comp.EyeDamage >= blindable.Comp.MaxDamage)
{
blindable.Comp.IsBlind = true;
}
else
{
var ev = new CanSeeAttemptEvent();
RaiseLocalEvent(blindable.Owner, ev);
blindable.Comp.IsBlind = ev.Blind;
}
if (old == blindable.Comp.IsBlind)
return;
var changeEv = new BlindnessChangedEvent(blindable.Comp.IsBlind);
RaiseLocalEvent(blindable.Owner, ref changeEv);
Dirty(blindable);
}
public void AdjustEyeDamage(Entity<BlindableComponent?> blindable, int amount)
{
if (!Resolve(blindable, ref blindable.Comp, false) || amount == 0)
return;
blindable.Comp.EyeDamage += amount;
UpdateEyeDamage(blindable, true);
}
private void UpdateEyeDamage(Entity<BlindableComponent?> blindable, bool isDamageChanged)
{
if (!Resolve(blindable, ref blindable.Comp, false))
return;
var previousDamage = blindable.Comp.EyeDamage;
blindable.Comp.EyeDamage = Math.Clamp(blindable.Comp.EyeDamage, blindable.Comp.MinDamage, blindable.Comp.MaxDamage);
Dirty(blindable);
if (!isDamageChanged && previousDamage == blindable.Comp.EyeDamage)
return;
UpdateIsBlind(blindable);
var ev = new EyeDamageChangedEvent(blindable.Comp.EyeDamage);
RaiseLocalEvent(blindable.Owner, ref ev);
}
public void SetMinDamage(Entity<BlindableComponent?> blindable, int amount)
{
if (!Resolve(blindable, ref blindable.Comp, false))
return;
blindable.Comp.MinDamage = amount;
UpdateEyeDamage(blindable, false);
}
public void SetIncurable(Entity<BlindableComponent?> blindable, bool isIncurable)
{
if (!Resolve(blindable, ref blindable.Comp, false))
return;
blindable.Comp.Incurable = isIncurable;
}
public void TransferBlindness(BlindableComponent newSight, BlindableComponent oldSight, EntityUid newEntity)
{
newSight.IsBlind = oldSight.IsBlind;
newSight.EyeDamage = oldSight.EyeDamage;
newSight.LightSetup = oldSight.LightSetup;
newSight.GraceFrame = oldSight.GraceFrame;
if (!oldSight.Incurable || !newSight.Incurable)
newSight.MinDamage = oldSight.MinDamage;
newSight.MaxDamage = oldSight.MaxDamage;
UpdateEyeDamage((newEntity, newSight), true);
}
}
/// <summary>
/// This event is raised when an entity's blindness changes
/// </summary>
[ByRefEvent]
public record struct BlindnessChangedEvent(bool Blind);
/// <summary>
/// This event is raised when an entity's eye damage changes
/// </summary>
[ByRefEvent]
public record struct EyeDamageChangedEvent(int Damage);
/// <summary>
/// Raised directed at an entity to see whether the entity is currently blind or not.
/// </summary>
public sealed class CanSeeAttemptEvent : CancellableEntityEventArgs, IInventoryRelayEvent
{
public bool Blind => Cancelled;
public SlotFlags TargetSlots => SlotFlags.EYES | SlotFlags.MASK | SlotFlags.HEAD;
}
public sealed class GetEyeProtectionEvent : EntityEventArgs, IInventoryRelayEvent
{
/// <summary>
/// Time to subtract from any temporary blindness sources.
/// </summary>
public TimeSpan Protection;
public SlotFlags TargetSlots => SlotFlags.EYES | SlotFlags.MASK | SlotFlags.HEAD;
}