]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add EvenHealthChange effect (#37129)
authorNemanja <98561806+EmoGarbage404@users.noreply.github.com>
Sat, 10 May 2025 12:51:28 +0000 (08:51 -0400)
committerGitHub <noreply@github.com>
Sat, 10 May 2025 12:51:28 +0000 (14:51 +0200)
* Add EvenHealthChange effect

* cleanup

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Content.Server/EntityEffects/Effects/EvenHealthChange.cs [new file with mode: 0644]
Resources/Locale/en-US/guidebook/chemistry/effects.ftl
Resources/Prototypes/Reagents/medicine.yml

diff --git a/Content.Server/EntityEffects/Effects/EvenHealthChange.cs b/Content.Server/EntityEffects/Effects/EvenHealthChange.cs
new file mode 100644 (file)
index 0000000..acf2bfa
--- /dev/null
@@ -0,0 +1,141 @@
+using Content.Shared.Damage;
+using Content.Shared.Damage.Prototypes;
+using Content.Shared.EntityEffects;
+using Content.Shared.FixedPoint;
+using Content.Shared.Localizations;
+using JetBrains.Annotations;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
+
+namespace Content.Server.EntityEffects.Effects;
+
+/// <summary>
+/// Version of <see cref="HealthChange"/> that distributes the healing to groups
+/// </summary>
+[UsedImplicitly]
+public sealed partial class EvenHealthChange : EntityEffect
+{
+    /// <summary>
+    /// Damage to heal, collected into entire damage groups.
+    /// </summary>
+    [DataField(required: true)]
+    public Dictionary<ProtoId<DamageGroupPrototype>, FixedPoint2> Damage = new();
+
+    /// <summary>
+    /// Should this effect scale the damage by the amount of chemical in the solution?
+    /// Useful for touch reactions, like styptic powder or acid.
+    /// Only usable if the EntityEffectBaseArgs is an EntityEffectReagentArgs.
+    /// </summary>
+    [DataField]
+    public bool ScaleByQuantity;
+
+    /// <summary>
+    /// Should this effect ignore damage modifiers?
+    /// </summary>
+    [DataField]
+    public bool IgnoreResistances = true;
+
+    protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
+    {
+        var damages = new List<string>();
+        var heals = false;
+        var deals = false;
+
+        var damagableSystem = entSys.GetEntitySystem<DamageableSystem>();
+        var universalReagentDamageModifier = damagableSystem.UniversalReagentDamageModifier;
+        var universalReagentHealModifier = damagableSystem.UniversalReagentHealModifier;
+
+        foreach (var (group, amount) in Damage)
+        {
+            var groupProto = prototype.Index(group);
+
+            var sign = FixedPoint2.Sign(amount);
+            var mod = 1f;
+
+            if (sign < 0)
+            {
+                heals = true;
+                mod = universalReagentHealModifier;
+            }
+            else if (sign > 0)
+            {
+                deals = true;
+                mod = universalReagentDamageModifier;
+            }
+
+            damages.Add(
+                Loc.GetString("health-change-display",
+                    ("kind", groupProto.LocalizedName),
+                    ("amount", MathF.Abs(amount.Float() * mod)),
+                    ("deltasign", sign)
+                ));
+        }
+
+        var healsordeals = heals ? (deals ? "both" : "heals") : (deals ? "deals" : "none");
+        return Loc.GetString("reagent-effect-guidebook-even-health-change",
+            ("chance", Probability),
+            ("changes", ContentLocalizationManager.FormatList(damages)),
+            ("healsordeals", healsordeals));
+    }
+
+    public override void Effect(EntityEffectBaseArgs args)
+    {
+        if (!args.EntityManager.TryGetComponent<DamageableComponent>(args.TargetEntity, out var damageable))
+            return;
+
+        var protoMan = IoCManager.Resolve<IPrototypeManager>();
+
+        var scale = FixedPoint2.New(1);
+
+        if (args is EntityEffectReagentArgs reagentArgs)
+        {
+            scale = ScaleByQuantity ? reagentArgs.Quantity * reagentArgs.Scale : reagentArgs.Scale;
+        }
+
+        var damagableSystem = args.EntityManager.System<DamageableSystem>();
+        var universalReagentDamageModifier = damagableSystem.UniversalReagentDamageModifier;
+        var universalReagentHealModifier = damagableSystem.UniversalReagentHealModifier;
+
+        var dspec = new DamageSpecifier();
+
+        foreach (var (group, amount) in Damage)
+        {
+            var groupProto = protoMan.Index(group);
+            var groupDamage = new Dictionary<string, FixedPoint2>();
+            foreach (var damageId in groupProto.DamageTypes)
+            {
+                var damageAmount = damageable.Damage.DamageDict.GetValueOrDefault(damageId);
+                if (damageAmount != FixedPoint2.Zero)
+                    groupDamage.Add(damageId, damageAmount);
+            }
+
+            var sum = groupDamage.Values.Sum();
+            foreach (var (damageId, damageAmount) in groupDamage)
+            {
+                var existing = dspec.DamageDict.GetOrNew(damageId);
+                dspec.DamageDict[damageId] = existing + damageAmount / sum * amount;
+            }
+        }
+
+        if (universalReagentDamageModifier != 1 || universalReagentHealModifier != 1)
+        {
+            foreach (var (type, val) in dspec.DamageDict)
+            {
+                if (val < 0f)
+                {
+                    dspec.DamageDict[type] = val * universalReagentHealModifier;
+                }
+                if (val > 0f)
+                {
+                    dspec.DamageDict[type] = val * universalReagentDamageModifier;
+                }
+            }
+        }
+
+        damagableSystem.TryChangeDamage(
+            args.TargetEntity,
+            dspec * scale,
+            IgnoreResistances,
+            interruptsDoAfters: false);
+    }
+}
index 2a40d00f72288dd0e08f8ae18dd4fca034acca85..ba6ae96c82cea009d9259e0e071328536d807204 100644 (file)
@@ -87,6 +87,21 @@ reagent-effect-guidebook-health-change =
                  }
     } { $changes }
 
+reagent-effect-guidebook-even-health-change =
+    { $chance ->
+        [1] { $healsordeals ->
+            [heals] Evenly heals
+            [deals] Evenly deals
+            *[both] Evenly modifies health by
+        }
+        *[other] { $healsordeals ->
+            [heals] evenly heal
+            [deals] evenly deal
+            *[both] evenly modify health by
+        }
+    } { $changes }
+
+
 reagent-effect-guidebook-status-effect =
     { $type ->
         [add]   { $chance ->
index 4cb134059ed563c02874214e61ba5a7007092e42..f1dcbc1a226e4cf5029b990f033a36e236227887 100644 (file)
   metabolisms:
     Medicine:
       effects:
-      - !type:HealthChange
+      - !type:EvenHealthChange
         damage:
-          groups:
-            Burn: -2
-            Toxin: -2
-            Airloss: -2
-            Brute: -2
+          Burn: -2
+          Toxin: -2
+          Airloss: -2
+          Brute: -2
 
 - type: reagent
   id: Ultravasculine
         conditions:
         - !type:ReagentThreshold
           min: 12
-          
+
 - type: reagent
   id: Opporozidone #Name based of an altered version of the startreck chem "Opporozine"
   name: reagent-name-opporozidone