From 5ba9529414bddec5486b3e1986ab1f2156be4403 Mon Sep 17 00:00:00 2001 From: mirrorcult Date: Wed, 10 Nov 2021 03:06:27 -0700 Subject: [PATCH] Damage movespeed (#5244) --- .../{ => Components}/DamageableComponent.cs | 0 .../Components/SlowOnDamageComponent.cs | 22 ++++++++ .../Damage/{ => Systems}/DamageableSystem.cs | 1 + .../Damage/Systems/SlowOnDamageSystem.cs | 54 +++++++++++++++++++ Content.Shared/FixedPoint/FixedPoint2.cs | 11 ++++ .../Entities/Mobs/Species/human.yml | 6 +++ 6 files changed, 94 insertions(+) rename Content.Shared/Damage/{ => Components}/DamageableComponent.cs (100%) create mode 100644 Content.Shared/Damage/Components/SlowOnDamageComponent.cs rename Content.Shared/Damage/{ => Systems}/DamageableSystem.cs (99%) create mode 100644 Content.Shared/Damage/Systems/SlowOnDamageSystem.cs diff --git a/Content.Shared/Damage/DamageableComponent.cs b/Content.Shared/Damage/Components/DamageableComponent.cs similarity index 100% rename from Content.Shared/Damage/DamageableComponent.cs rename to Content.Shared/Damage/Components/DamageableComponent.cs diff --git a/Content.Shared/Damage/Components/SlowOnDamageComponent.cs b/Content.Shared/Damage/Components/SlowOnDamageComponent.cs new file mode 100644 index 0000000000..5381549ef4 --- /dev/null +++ b/Content.Shared/Damage/Components/SlowOnDamageComponent.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Content.Shared.FixedPoint; +using Robust.Shared.GameObjects; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.Manager.Attributes; + +namespace Content.Shared.Damage.Components +{ + // TODO It'd be nice if this could be a destructible threshold, but on the other hand, + // that doesn't really work with events at all, and + [RegisterComponent, NetworkedComponent] + public class SlowOnDamageComponent : Component + { + public override string Name => "SlowOnDamage"; + + /// + /// Damage -> movespeed dictionary. This is -damage-, not -health-. + /// + [DataField("speedModifierThresholds", required: true)] + public readonly Dictionary SpeedModifierThresholds = default!; + } +} diff --git a/Content.Shared/Damage/DamageableSystem.cs b/Content.Shared/Damage/Systems/DamageableSystem.cs similarity index 99% rename from Content.Shared/Damage/DamageableSystem.cs rename to Content.Shared/Damage/Systems/DamageableSystem.cs index f20773e853..5f47981d4a 100644 --- a/Content.Shared/Damage/DamageableSystem.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; +using Content.Shared.Movement.EntitySystems; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.IoC; diff --git a/Content.Shared/Damage/Systems/SlowOnDamageSystem.cs b/Content.Shared/Damage/Systems/SlowOnDamageSystem.cs new file mode 100644 index 0000000000..b7d605f438 --- /dev/null +++ b/Content.Shared/Damage/Systems/SlowOnDamageSystem.cs @@ -0,0 +1,54 @@ +using System; +using Content.Shared.Damage.Components; +using Content.Shared.FixedPoint; +using Content.Shared.Movement.EntitySystems; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Shared.Damage.Systems +{ + public class SlowOnDamageSystem : EntitySystem + { + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnDamageChanged); + SubscribeLocalEvent(OnRefreshMovespeed); + } + + private void OnRefreshMovespeed(EntityUid uid, SlowOnDamageComponent component, RefreshMovementSpeedModifiersEvent args) + { + if (!EntityManager.TryGetComponent(uid, out var damage)) + return; + + if (damage.TotalDamage == FixedPoint2.Zero) + return; + + // Get closest threshold + FixedPoint2 closest = FixedPoint2.Zero; + var total = damage.TotalDamage; + foreach (var thres in component.SpeedModifierThresholds) + { + if (FixedPoint2.Dist(thres.Key, total) < FixedPoint2.Dist(closest, total)) + closest = thres.Key; + } + + if (closest != FixedPoint2.Zero) + { + var speed = component.SpeedModifierThresholds[closest]; + args.ModifySpeed(speed, speed); + } + } + + private void OnDamageChanged(EntityUid uid, SlowOnDamageComponent component, DamageChangedEvent args) + { + // We -could- only refresh if it crossed a threshold but that would kind of be a lot of duplicated + // code and this isn't a super hot path anyway since basically only humans have this + + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid); + } + } +} diff --git a/Content.Shared/FixedPoint/FixedPoint2.cs b/Content.Shared/FixedPoint/FixedPoint2.cs index 0b1bb1afb6..bfca9c9478 100644 --- a/Content.Shared/FixedPoint/FixedPoint2.cs +++ b/Content.Shared/FixedPoint/FixedPoint2.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; +using Content.Shared.ActionBlocker; using Robust.Shared.Serialization; namespace Content.Shared.FixedPoint @@ -210,6 +211,16 @@ namespace Content.Shared.FixedPoint return a > b ? a : b; } + public static FixedPoint2 Abs(FixedPoint2 a) + { + return FixedPoint2.New(Math.Abs(a._value)); + } + + public static FixedPoint2 Dist(FixedPoint2 a, FixedPoint2 b) + { + return FixedPoint2.Abs(a - b); + } + public static FixedPoint2 Clamp(FixedPoint2 reagent, FixedPoint2 min, FixedPoint2 max) { if (min > max) diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 0491907b2a..b8b1b136cd 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -232,6 +232,12 @@ damage: 400 behaviors: - !type:GibBehavior { } + - type: SlowOnDamage + speedModifierThresholds: + 40: 0.8 + 60: 0.6 + 80: 0.4 + 90: 0.2 - type: HeatResistance - type: Appearance visuals: