diff --git a/Content.Server/HeightAdjust/BloodstreamAdjustSystem.cs b/Content.Server/HeightAdjust/BloodstreamAdjustSystem.cs new file mode 100644 index 00000000000..92e03e0c111 --- /dev/null +++ b/Content.Server/HeightAdjust/BloodstreamAdjustSystem.cs @@ -0,0 +1,45 @@ +using Content.Server.Body.Components; +using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Shared.CCVar; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Contests; +using Content.Shared.HeightAdjust; +using Robust.Shared.Configuration; + +namespace Content.Server.HeightAdjust; + +public sealed class BloodstreamAdjustSystem : EntitySystem +{ + [Dependency] private readonly IConfigurationManager _config = default!; + [Dependency] private readonly ContestsSystem _contests = default!; + [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + + public override void Initialize() + { + SubscribeLocalEvent((uid, comp, _) => TryAdjustBloodstream((uid, comp))); + SubscribeLocalEvent((uid, comp, _) => TryAdjustBloodstream((uid, comp))); + } + + /// + /// Adjusts the bloodstream of the specified entity based on the settings provided by the component. + /// + public bool TryAdjustBloodstream(Entity ent) + { + if (!TryComp(ent, out var bloodstream) + || !_solutionContainer.TryGetSolution(ent.Owner, bloodstream.BloodSolutionName, out var bloodSolutionEnt) + || !_config.GetCVar(CCVars.HeightAdjustModifiesBloodstream)) + return false; + + var bloodSolution = bloodSolutionEnt.Value.Comp.Solution; + + var factor = Math.Pow(_contests.MassContest(ent, bypassClamp: true, rangeFactor: 4f), ent.Comp.Power); + factor = Math.Clamp(factor, ent.Comp.Min, ent.Comp.Max); + + var newVolume = bloodstream.BloodMaxVolume * factor; + var newBloodLevel = bloodSolution.FillFraction * newVolume; + bloodSolution.MaxVolume = newVolume; + bloodSolution.SetContents([new ReagentQuantity(bloodstream.BloodReagent, newBloodLevel, null)], false); + + return true; + } +} diff --git a/Content.Server/HeightAdjust/BloodstreamAffectedByMassComponent.cs b/Content.Server/HeightAdjust/BloodstreamAffectedByMassComponent.cs new file mode 100644 index 00000000000..f6c3a0e250c --- /dev/null +++ b/Content.Server/HeightAdjust/BloodstreamAffectedByMassComponent.cs @@ -0,0 +1,26 @@ +using Content.Server.Body.Components; + +namespace Content.Server.HeightAdjust; + +/// +/// When applied to a humanoid or any mob, adjusts their blood level based on the mass contest between them +/// and an average humanoid. +///
+/// The formula for the resulting bloodstream volume is V = BloodMaxVolume * MassContest^Power +/// clamped between the specified Min and Max values. +///
+[RegisterComponent] +public sealed partial class BloodstreamAffectedByMassComponent : Component +{ + /// + /// Minimum and maximum resulting volume factors. A minimum value of 0.5 means that the resulting volume will be at least 50% of the original. + /// + [DataField] + public float Min = 1 / 3f, Max = 3f; + + /// + /// The power to which the outcome of the mass contest will be risen. + /// + [DataField] + public float Power = 1f; +} diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 84a8e460c59..1501c92f88e 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -2341,6 +2341,15 @@ public static readonly CVarDef public static readonly CVarDef HeightAdjustModifiesZoom = CVarDef.Create("heightadjust.modifies_zoom", false, CVar.SERVERONLY); + /// + /// Whether height & width sliders adjust a player's bloodstream volume. + /// + /// + /// This can be configured more precisely by modifying BloodstreamAffectedByMassComponent. + /// + public static readonly CVarDef HeightAdjustModifiesBloodstream = + CVarDef.Create("heightadjust.modifies_bloodstream", true, CVar.SERVERONLY); + /// /// Enables station goals /// diff --git a/Content.Shared/HeightAdjust/HeightAdjustSystem.cs b/Content.Shared/HeightAdjust/HeightAdjustSystem.cs index 46b2d9b656f..8bfdaccfd13 100644 --- a/Content.Shared/HeightAdjust/HeightAdjustSystem.cs +++ b/Content.Shared/HeightAdjust/HeightAdjustSystem.cs @@ -25,27 +25,7 @@ public sealed class HeightAdjustSystem : EntitySystem /// True if all operations succeeded public bool SetScale(EntityUid uid, float scale) { - var succeeded = true; - if (_config.GetCVar(CCVars.HeightAdjustModifiesZoom) && EntityManager.TryGetComponent(uid, out var eye)) - _eye.SetMaxZoom(uid, eye.MaxZoom * scale); - else - succeeded = false; - - if (_config.GetCVar(CCVars.HeightAdjustModifiesHitbox) && EntityManager.TryGetComponent(uid, out var fixtures)) - foreach (var fixture in fixtures.Fixtures) - _physics.SetRadius(uid, fixture.Key, fixture.Value, fixture.Value.Shape, MathF.MinMagnitude(fixture.Value.Shape.Radius * scale, 0.49f)); - else - succeeded = false; - - if (EntityManager.HasComponent(uid)) - { - _appearance.SetHeight(uid, scale); - _appearance.SetWidth(uid, scale); - } - else - succeeded = false; - - return succeeded; + return SetScale(uid, new Vector2(scale, scale)); } /// @@ -75,6 +55,8 @@ public bool SetScale(EntityUid uid, Vector2 scale) else succeeded = false; + RaiseLocalEvent(uid, new HeightAdjustedEvent { NewScale = scale }); + return succeeded; } } diff --git a/Content.Shared/HeightAdjust/HeightAdjustedEvent.cs b/Content.Shared/HeightAdjust/HeightAdjustedEvent.cs new file mode 100644 index 00000000000..3db856e0d83 --- /dev/null +++ b/Content.Shared/HeightAdjust/HeightAdjustedEvent.cs @@ -0,0 +1,11 @@ +using System.Numerics; + +namespace Content.Shared.HeightAdjust; + +/// +/// Raised on a humanoid after their scale has been adjusted in accordance with their profile and their physics have been updated. +/// +public sealed class HeightAdjustedEvent : EntityEventArgs +{ + public Vector2 NewScale; +} diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 8200f0cdbff..33635eeec20 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -309,6 +309,8 @@ - type: OfferItem - type: LayingDown - type: Shoving + - type: BloodstreamAffectedByMass + power: 0.6 # A minimum size felinid will have 30% blood, a minimum size vulp will have 60%, a maximum size oni will have ~200% - type: entity save: false