From e85bdc2d87a42df603cc9d5abd1456413257792b Mon Sep 17 00:00:00 2001 From: mirrorcult Date: Sun, 20 Feb 2022 17:18:24 -0700 Subject: [PATCH] More blood tweaks (#6811) --- .../Commands/RejuvenateCommand.cs | 10 +++++++++ .../Body/Components/BloodstreamComponent.cs | 12 +++++++++++ .../Body/Systems/BloodstreamSystem.cs | 21 +++++++++++++++---- .../Fluids/Components/PuddleComponent.cs | 7 +++++++ .../Fluids/EntitySystems/PuddleSystem.cs | 2 +- .../Locale/en-US/bloodstream/bloodstream.ftl | 2 ++ Resources/Prototypes/Damage/modifier_sets.yml | 2 +- .../Prototypes/Entities/Effects/puddle.yml | 1 + Resources/Prototypes/Reagents/biological.yml | 2 +- 9 files changed, 52 insertions(+), 7 deletions(-) diff --git a/Content.Server/Administration/Commands/RejuvenateCommand.cs b/Content.Server/Administration/Commands/RejuvenateCommand.cs index db5145a999..a95fc945a1 100644 --- a/Content.Server/Administration/Commands/RejuvenateCommand.cs +++ b/Content.Server/Administration/Commands/RejuvenateCommand.cs @@ -1,5 +1,7 @@ using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; using Content.Server.Nutrition.Components; using Content.Server.Nutrition.EntitySystems; using Content.Shared.Administration; @@ -58,6 +60,7 @@ namespace Content.Server.Administration.Commands entMan.GetComponentOrNull(targetUid)?.ResetFood(); entMan.GetComponentOrNull(targetUid)?.ResetThirst(); + // TODO holy shit make this an event my man! EntitySystem.Get().TryRemoveAllStatusEffects(target); if (entMan.TryGetComponent(target, out FlammableComponent? flammable)) @@ -75,6 +78,13 @@ namespace Content.Server.Administration.Commands EntitySystem.Get().SetCreamPied(target, creamPied, false); } + if (entMan.TryGetComponent(target, out BloodstreamComponent? bloodStream)) + { + var sys = EntitySystem.Get(); + sys.TryModifyBleedAmount(target, -bloodStream.BleedAmount, bloodStream); + sys.TryModifyBloodLevel(target, bloodStream.BloodSolution.AvailableVolume, bloodStream); + } + if (entMan.HasComponent(target)) { entMan.RemoveComponent(target); diff --git a/Content.Server/Body/Components/BloodstreamComponent.cs b/Content.Server/Body/Components/BloodstreamComponent.cs index 5b3974a7a0..45a65fe4e4 100644 --- a/Content.Server/Body/Components/BloodstreamComponent.cs +++ b/Content.Server/Body/Components/BloodstreamComponent.cs @@ -36,6 +36,12 @@ namespace Content.Server.Body.Components [DataField("bleedReductionAmount")] public float BleedReductionAmount = 1.0f; + /// + /// How high can go? + /// + [DataField("maxBleedAmount")] + public float MaxBleedAmount = 20.0f; + /// /// What percentage of current blood is necessary to avoid dealing blood loss damage? /// @@ -89,6 +95,12 @@ namespace Content.Server.Body.Components [DataField("instantBloodSound")] public SoundSpecifier InstantBloodSound = new SoundCollectionSpecifier("blood"); + /// + /// The sound to be played when some damage actually heals bleeding rather than starting it. + /// + [DataField("bloodHealedSound")] + public SoundSpecifier BloodHealedSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg"); + // TODO probably damage bleed thresholds. /// diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index 7bcc7fd5da..78e1b784a6 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -3,6 +3,7 @@ using Content.Server.Body.Components; using Content.Server.Chemistry.EntitySystems; using Content.Server.Fluids.EntitySystems; using Content.Server.HealthExaminable; +using Content.Server.Popups; using Content.Shared.Chemistry.Components; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; @@ -21,6 +22,7 @@ public sealed class BloodstreamSystem : EntitySystem [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly SpillableSystem _spillableSystem = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; @@ -63,7 +65,7 @@ public sealed class BloodstreamSystem : EntitySystem // as well as stop their bleeding to a certain extent. if (bloodstream.BleedAmount > 0) { - TryModifyBloodLevel(uid, (-bloodstream.BleedAmount) / 10, bloodstream); + TryModifyBloodLevel(uid, (-bloodstream.BleedAmount) / 20, bloodstream); TryModifyBleedAmount(uid, -bloodstream.BleedReductionAmount, bloodstream); } @@ -113,17 +115,28 @@ public sealed class BloodstreamSystem : EntitySystem if (bloodloss.Empty) return; + var oldBleedAmount = component.BleedAmount; var total = bloodloss.Total; var totalFloat = total.Float(); TryModifyBleedAmount(uid, totalFloat, component); var prob = Math.Clamp(totalFloat / 50, 0, 1); - if (_robustRandom.Prob(prob)) + var healPopupProb = Math.Clamp(Math.Abs(totalFloat) / 25, 0, 1); + if (totalFloat > 0 && _robustRandom.Prob(prob)) { - // This is gonna hurt. TryModifyBloodLevel(uid, (-total) / 5, component); SoundSystem.Play(Filter.Pvs(uid), component.InstantBloodSound.GetSound(), uid, AudioParams.Default); } + else if (totalFloat < 0 && oldBleedAmount > 0 && _robustRandom.Prob(healPopupProb)) + { + // Magically, this damage has healed some bleeding, likely + // because it's burn damage that cauterized their wounds. + + // We'll play a special sound and popup for feedback. + SoundSystem.Play(Filter.Pvs(uid), component.BloodHealedSound.GetSound(), uid, AudioParams.Default); + _popupSystem.PopupEntity(Loc.GetString("bloodstream-component-wounds-cauterized"), uid, + Filter.Entities(uid)); +; } } private void OnHealthBeingExamined(EntityUid uid, BloodstreamComponent component, HealthBeingExaminedEvent args) @@ -208,7 +221,7 @@ public sealed class BloodstreamSystem : EntitySystem return false; component.BleedAmount += amount; - component.BleedAmount = Math.Clamp(component.BleedAmount, 0, 40); + component.BleedAmount = Math.Clamp(component.BleedAmount, 0, component.MaxBleedAmount); return true; } diff --git a/Content.Server/Fluids/Components/PuddleComponent.cs b/Content.Server/Fluids/Components/PuddleComponent.cs index b7bdab7568..6255c62af5 100644 --- a/Content.Server/Fluids/Components/PuddleComponent.cs +++ b/Content.Server/Fluids/Components/PuddleComponent.cs @@ -54,6 +54,13 @@ namespace Content.Server.Fluids.Components [ViewVariables] [DataField("overflowVolume")] public FixedPoint2 OverflowVolume = DefaultOverflowVolume; + /// + /// How much should this puddle's opacity be multiplied by? + /// Useful for puddles that have a high overflow volume but still want to be mostly opaque. + /// + [DataField("opacityModifier")] + public float OpacityModifier = 1.0f; + public FixedPoint2 OverflowLeft => CurrentVolume - OverflowVolume; [DataField("solution")] public string SolutionName { get; set; } = DefaultSolutionName; diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index c39a30fdf2..f18fcf1904 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -49,7 +49,7 @@ namespace Content.Server.Fluids.EntitySystems // Opacity based on level of fullness to overflow // Hard-cap lower bound for visibility reasons - var volumeScale = puddleComponent.CurrentVolume.Float() / puddleComponent.OverflowVolume.Float(); + var volumeScale = puddleComponent.CurrentVolume.Float() / puddleComponent.OverflowVolume.Float() * puddleComponent.OpacityModifier; var puddleSolution = _solutionContainerSystem.EnsureSolution(uid, puddleComponent.SolutionName); diff --git a/Resources/Locale/en-US/bloodstream/bloodstream.ftl b/Resources/Locale/en-US/bloodstream/bloodstream.ftl index d2f0501a99..4305465913 100644 --- a/Resources/Locale/en-US/bloodstream/bloodstream.ftl +++ b/Resources/Locale/en-US/bloodstream/bloodstream.ftl @@ -1,3 +1,5 @@ bloodstream-component-looks-pale = [color=bisque]{CAPITALIZE(SUBJECT($target))} looks pale.[/color] bloodstream-component-bleeding = [color=red]{CAPITALIZE(SUBJECT($target))} {CONJUGATE-BE($target)} bleeding.[/color] bloodstream-component-profusely-bleeding = [color=crimson]{CAPITALIZE(SUBJECT($target))} {CONJUGATE-BE($target)} profusely bleeding![/color] + +bloodstream-component-wounds-cauterized = You feel your wounds painfully close! diff --git a/Resources/Prototypes/Damage/modifier_sets.yml b/Resources/Prototypes/Damage/modifier_sets.yml index 2a8bc3f7fc..6dd29df3ef 100644 --- a/Resources/Prototypes/Damage/modifier_sets.yml +++ b/Resources/Prototypes/Damage/modifier_sets.yml @@ -82,7 +82,7 @@ Piercing: 2.0 Shock: 0.0 Cold: 0.0 - Heat: 0.0 + Heat: -0.25 # heat damage cauterizes wounds! Poison: 0.0 Radiation: 0.0 Asphyxiation: 0.0 diff --git a/Resources/Prototypes/Entities/Effects/puddle.yml b/Resources/Prototypes/Entities/Effects/puddle.yml index d003ec391a..e602486b39 100644 --- a/Resources/Prototypes/Entities/Effects/puddle.yml +++ b/Resources/Prototypes/Entities/Effects/puddle.yml @@ -101,6 +101,7 @@ - type: Puddle slipThreshold: 20 overflowVolume: 50 + opacityModifier: 8 - type: Evaporation evaporateTime: 400 # very slow - type: Appearance diff --git a/Resources/Prototypes/Reagents/biological.yml b/Resources/Prototypes/Reagents/biological.yml index a89831a77b..368ca643cd 100644 --- a/Resources/Prototypes/Reagents/biological.yml +++ b/Resources/Prototypes/Reagents/biological.yml @@ -3,7 +3,7 @@ name: blood group: Biological desc: I hope this is ketchup. - color: "#9e1010" + color: "#800000" physicalDesc: ferrous metabolisms: Drink: