Ninja Stealth Fix?/Nerf? (#5217)

* Changed up how ninja's stealth is removed after they get hit.

* Logic fix

* Update Content.Shared/Ninja/Systems/SharedSpaceNinjaSystem.cs

Co-authored-by: Tobias Berger <toby@tobot.dev>
Signed-off-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>

---------

Signed-off-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
Co-authored-by: Tobias Berger <toby@tobot.dev>
This commit is contained in:
Vanessa 2026-01-21 08:18:56 -06:00 committed by GitHub
parent ab5541668a
commit ea2f0a21aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 72 additions and 5 deletions

View File

@ -1,4 +1,5 @@
using Content.Shared.Alert;
using Content.Shared.FixedPoint; // DeltaV
using Content.Shared.Ninja.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
@ -54,4 +55,11 @@ public sealed partial class SpaceNinjaComponent : Component
/// </summary>
[DataField]
public ProtoId<AlertPrototype> SuitPowerAlert = "SuitPower";
/// <summary>
/// DeltaV - The minimum damage to reveal the ninja on damage. Should be positive, since negative values are considered healing.
/// Note that the ninja suit has 20% brute resist and punches deal 5 damage, so 4 should be enough to reveal.
/// </summary>
[DataField]
public FixedPoint2 MinimumRevealDamage = 4;
}

View File

@ -114,9 +114,15 @@ public abstract class SharedNinjaSuitSystem : EntitySystem
var uid = ent.Owner;
var comp = ent.Comp;
if (_toggle.TryDeactivate(uid, user) || !disable)
// DeltaV
if (!_toggle.TryDeactivate(uid, user))
return;
if (!disable)
return;
// End DeltaV
// previously cloaked, disable abilities for a short time
_audio.PlayPredicted(comp.RevealSound, uid, user);
Popup.PopupClient(Loc.GetString("ninja-revealed"), user, user, PopupType.MediumCaution);

View File

@ -3,6 +3,9 @@ using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Popups;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Damage.Systems; // DeltaV
using Content.Shared.Stealth.Components; // DeltaV
using Robust.Shared.Prototypes; // DeltaV
namespace Content.Shared.Ninja.Systems;
@ -13,6 +16,7 @@ public abstract class SharedSpaceNinjaSystem : EntitySystem
{
[Dependency] protected readonly SharedNinjaSuitSystem Suit = default!;
[Dependency] protected readonly SharedPopupSystem Popup = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; // DeltaV
public EntityQuery<SpaceNinjaComponent> NinjaQuery;
@ -22,9 +26,11 @@ public abstract class SharedSpaceNinjaSystem : EntitySystem
NinjaQuery = GetEntityQuery<SpaceNinjaComponent>();
SubscribeLocalEvent<SpaceNinjaComponent, AttackedEvent>(OnNinjaAttacked);
// SubscribeLocalEvent<SpaceNinjaComponent, AttackedEvent>(OnNinjaAttacked); // DeltaV - Handled by the DamageChangedEvent
SubscribeLocalEvent<SpaceNinjaComponent, MeleeAttackEvent>(OnNinjaAttack);
SubscribeLocalEvent<SpaceNinjaComponent, ShotAttemptedEvent>(OnShotAttempted);
SubscribeLocalEvent<SpaceNinjaComponent, DamageChangedEvent>(OnNinjaAttacked); // DeltaV - Reveal the ninja on damage
}
public bool IsNinja([NotNullWhen(true)] EntityUid? uid)
@ -78,11 +84,49 @@ public abstract class SharedSpaceNinjaSystem : EntitySystem
return false;
}
// DeltaV - Handled by the DamageChangedEvent
/// <summary>
/// Handle revealing ninja if cloaked when attacked.
/// </summary>
private void OnNinjaAttacked(Entity<SpaceNinjaComponent> ent, ref AttackedEvent args)
//private void OnNinjaAttacked(Entity<SpaceNinjaComponent> ent, ref AttackedEvent args)
//{
// TryRevealNinja(ent, disable: true);
//}
// END DeltaV
/// <summary>
/// DeltaV - Handle revealing ninja if cloaked when attacked by a hitscan attack.
/// </summary>
private void OnNinjaAttacked(Entity<SpaceNinjaComponent> ent, ref DamageChangedEvent args)
{
// If there's no damage delta, just return
if (args.DamageDelta is not { } damage)
return;
// Don't reveal on (most) healing
if (!args.DamageIncreased)
return;
// If the damage doesn't have a source, we need to check the type, in case it
// was a grenade or explosion. We want to ignore airloss and toxin damage types.
if (!args.Origin.HasValue)
{
// If there are any negative values, its probably natual or chem healing, so don't reveal. It might be an OD from medicine.
if (!damage.AnyPositive())
return;
// Check the damage types for damage types that should reveal (brute, burns)
// Basically, we want to ignore most indirect forms of damage (airloss, toxins)
var damageGroups = damage.GetDamagePerGroup(_prototypeManager);
if (!damageGroups.ContainsKey("Brute") && !damageGroups.ContainsKey("Burn")) // This feels a bit dirty, oh well.
return;
}
// Only reveal on damage at least the minumum. This prevents tiny ticks of damage (e.g. from malign rifts pulses)
if (damage.GetTotal() < ent.Comp.MinimumRevealDamage)
return;
// Yea, now reveal that son of a bitch >:3
TryRevealNinja(ent, disable: true);
}
@ -97,8 +141,17 @@ public abstract class SharedSpaceNinjaSystem : EntitySystem
private void TryRevealNinja(Entity<SpaceNinjaComponent> ent, bool disable)
{
if (ent.Comp.Suit is {} uid && TryComp<NinjaSuitComponent>(ent.Comp.Suit, out var suit))
Suit.RevealNinja((uid, suit), ent, disable: disable);
// DeltaV - Reveal ninja on damage
if (ent.Comp.Suit is not {} uid)
return;
if (!TryComp<NinjaSuitComponent>(ent.Comp.Suit, out var suit))
return;
if (!HasComp<StealthComponent>(ent)) // Only attempt to reveal if stealthed
return;
// END DeltaV
Suit.RevealNinja((uid, suit), ent, disable: disable);
}
/// <summary>