From 38f6e6e8496512e993a363012fa32736179558ae Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Sat, 10 May 2025 08:51:28 -0400 Subject: [PATCH] Add EvenHealthChange effect (#37129) * Add EvenHealthChange effect * cleanup --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- .../EntityEffects/Effects/EvenHealthChange.cs | 141 ++++++++++++++++++ .../en-US/guidebook/chemistry/effects.ftl | 15 ++ Resources/Prototypes/Reagents/medicine.yml | 13 +- 3 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 Content.Server/EntityEffects/Effects/EvenHealthChange.cs diff --git a/Content.Server/EntityEffects/Effects/EvenHealthChange.cs b/Content.Server/EntityEffects/Effects/EvenHealthChange.cs new file mode 100644 index 0000000000..acf2bfafab --- /dev/null +++ b/Content.Server/EntityEffects/Effects/EvenHealthChange.cs @@ -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; + +/// +/// Version of that distributes the healing to groups +/// +[UsedImplicitly] +public sealed partial class EvenHealthChange : EntityEffect +{ + /// + /// Damage to heal, collected into entire damage groups. + /// + [DataField(required: true)] + public Dictionary, FixedPoint2> Damage = new(); + + /// + /// 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. + /// + [DataField] + public bool ScaleByQuantity; + + /// + /// Should this effect ignore damage modifiers? + /// + [DataField] + public bool IgnoreResistances = true; + + protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + var damages = new List(); + var heals = false; + var deals = false; + + var damagableSystem = entSys.GetEntitySystem(); + 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(args.TargetEntity, out var damageable)) + return; + + var protoMan = IoCManager.Resolve(); + + var scale = FixedPoint2.New(1); + + if (args is EntityEffectReagentArgs reagentArgs) + { + scale = ScaleByQuantity ? reagentArgs.Quantity * reagentArgs.Scale : reagentArgs.Scale; + } + + var damagableSystem = args.EntityManager.System(); + 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(); + 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); + } +} diff --git a/Resources/Locale/en-US/guidebook/chemistry/effects.ftl b/Resources/Locale/en-US/guidebook/chemistry/effects.ftl index 2a40d00f72..ba6ae96c82 100644 --- a/Resources/Locale/en-US/guidebook/chemistry/effects.ftl +++ b/Resources/Locale/en-US/guidebook/chemistry/effects.ftl @@ -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 -> diff --git a/Resources/Prototypes/Reagents/medicine.yml b/Resources/Prototypes/Reagents/medicine.yml index 4cb134059e..f1dcbc1a22 100644 --- a/Resources/Prototypes/Reagents/medicine.yml +++ b/Resources/Prototypes/Reagents/medicine.yml @@ -822,13 +822,12 @@ 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 @@ -1205,7 +1204,7 @@ conditions: - !type:ReagentThreshold min: 12 - + - type: reagent id: Opporozidone #Name based of an altered version of the startreck chem "Opporozine" name: reagent-name-opporozidone -- 2.51.2