diff --git a/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs b/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs index 90a28eb6ae1..07ada4c0c5d 100644 --- a/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs @@ -11,6 +11,7 @@ using Robust.Shared.Timing; using Content.Shared.Popups; using Content.Shared.Psionics.Events; +using Content.Shared.Psionics; namespace Content.Server.Psionics.Abilities { @@ -38,7 +39,7 @@ public override void Initialize() private void OnInit(EntityUid uid, PyrokinesisPowerComponent component, ComponentInit args) { _actions.AddAction(uid, ref component.PyrokinesisPrechargeActionEntity, component.PyrokinesisPrechargeActionId); - _actions.TryGetActionData( component.PyrokinesisPrechargeActionEntity, out var actionData); + _actions.TryGetActionData(component.PyrokinesisPrechargeActionEntity, out var actionData); if (actionData is { UseDelay: not null }) _actions.StartUseDelay(component.PyrokinesisPrechargeActionEntity); if (TryComp(uid, out var psionic)) @@ -107,13 +108,17 @@ private void OnPowerUsed(PyrokinesisPowerActionEvent args) var ent = Spawn("ProjectileAnomalyFireball", spawnCoords); + if (_glimmerSystem.GlimmerOutput >= 25 * psionic.Dampening) + EnsureComp(ent); + if (TryComp(ent, out var fireball)) { - fireball.MaxIntensity = (int) MathF.Round(2 * psionic.Amplification); - fireball.IntensitySlope = (int) MathF.Round(1 * psionic.Amplification); - fireball.TotalIntensity = (int) MathF.Round(25 * psionic.Amplification); + var psionicFactor = psionic.Amplification * _glimmerSystem.GetGlimmerEquilibriumRatio(); + fireball.MaxIntensity = 2 * psionicFactor; + fireball.IntensitySlope = 1 * psionicFactor; + fireball.TotalIntensity = 25 * psionicFactor; - if (_glimmerSystem.GlimmerOutput >= 500) + if (_glimmerSystem.GlimmerOutput >= _glimmerSystem.GlimmerEquilibrium) fireball.CanCreateVacuum = true; else fireball.CanCreateVacuum = false; diff --git a/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs index 09e33dd4144..b8649f71a5f 100644 --- a/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs +++ b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs @@ -76,16 +76,20 @@ public override void Update(float frameTime) if (source.Accumulator > source.SecondsPerGlimmer) { + var glimmerEquilibrium = _glimmerSystem.GlimmerEquilibrium; source.Accumulator -= source.SecondsPerGlimmer; + + // Shorthand explanation: + // This makes glimmer far more "Swingy", by making both positive and negative glimmer sources scale quite dramatically with glimmer if (source.AddToGlimmer) { - //If we're above the equilibrium point of 500, increase the output of passive glimmer sources to help fight against linear decay - //Even with this, don't expect probers to ever get to mind swap levels of power without any help - _glimmerSystem.DeltaGlimmerInput(_glimmerSystem.GlimmerOutput > 500 ? MathF.Round(_glimmerSystem.GlimmerOutput / 100) : 1f); + _glimmerSystem.DeltaGlimmerInput((_glimmerSystem.GlimmerOutput > glimmerEquilibrium ? _glimmerSystem.GetGlimmerOutputInteger() : 1f) + * (_glimmerSystem.GlimmerOutput < glimmerEquilibrium ? _glimmerSystem.GetGlimmerEquilibriumRatio() : 1f)); } else { - _glimmerSystem.DeltaGlimmerInput(-1); + _glimmerSystem.DeltaGlimmerInput(-(_glimmerSystem.GlimmerOutput > glimmerEquilibrium ? _glimmerSystem.GetGlimmerOutputInteger() : 1f) + * (_glimmerSystem.GlimmerOutput > glimmerEquilibrium ? _glimmerSystem.GetGlimmerEquilibriumRatio() : 1f)); } } } diff --git a/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs b/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs index d50b6fb2f6d..f40a916f487 100644 --- a/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs +++ b/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs @@ -2,7 +2,6 @@ using Robust.Shared.Configuration; using Content.Shared.CCVar; using Content.Shared.GameTicking; -using Content.Shared.Mobs; namespace Content.Shared.Psionics.Glimmer { @@ -12,6 +11,7 @@ namespace Content.Shared.Psionics.Glimmer public sealed class GlimmerSystem : EntitySystem { [Dependency] private readonly IConfigurationManager _cfg = default!; + private float _glimmerInput = 0; /// /// GlimmerInput represents the system-facing value of the station's glimmer, and is given by f(y) for this graph: https://www.desmos.com/calculator/posutiq38e @@ -27,6 +27,19 @@ public float GlimmerInput } private float _glimmerOutput = 0; + /// + /// This constant is equal to the intersection of the Glimmer Equation(https://www.desmos.com/calculator/posutiq38e) and the line Y = X. + /// + private const float _glimmerEquilibrium = 502.941f; + + /// + /// This constant is equal to the intersection of the Glimmer Equation(https://www.desmos.com/calculator/posutiq38e) and the line Y = X. + /// + public float GlimmerEquilibrium + { + get { return _glimmerEquilibrium; } + } + /// /// Glimmer Output represents the player-facing value of the station's glimmer, and is given by f(x) for this graph: https://www.desmos.com/calculator/posutiq38e /// Where x = GlimmerInput and y = GlimmerOutput @@ -55,7 +68,8 @@ private void Reset(RoundRestartCleanupEvent args) } /// - /// Return an abstracted range of a glimmer count. + /// Return an abstracted range of a glimmer count. This is a legacy system used to support the Prober, + /// and is the lowest form of abstracted glimmer. It's meant more for sprite states than math. /// /// What glimmer count to check. Uses the current glimmer by default. public GlimmerTier GetGlimmerTier(float? glimmer = null) @@ -66,14 +80,30 @@ public GlimmerTier GetGlimmerTier(float? glimmer = null) return glimmer switch { <= 49 => GlimmerTier.Minimal, - >= 50 and <= 99 => GlimmerTier.Low, - >= 100 and <= 299 => GlimmerTier.Moderate, - >= 300 and <= 499 => GlimmerTier.High, - >= 500 and <= 899 => GlimmerTier.Dangerous, + >= 50 and <= 399 => GlimmerTier.Low, + >= 400 and <= 599 => GlimmerTier.Moderate, + >= 600 and <= 699 => GlimmerTier.High, + >= 700 and <= 899 => GlimmerTier.Dangerous, _ => GlimmerTier.Critical, }; } + /// + /// Returns a 0 through 10 range of glimmer. Do not divide by this for any reason. + /// + /// + public int GetGlimmerOutputInteger() + { + if (!_enabled) + return 1; + else return (int) MathF.Round(GlimmerOutput / 1000); + } + + /// + /// This is the public facing function for modifying Glimmer based on the log scale. Simply add or subtract to this with any nonzero number + /// Go through this if you want glimmer to be modified faster if its below 502.941f, and slower if above said equilibrium + /// + /// public void DeltaGlimmerInput(float delta) { if (_enabled && delta != 0) @@ -83,6 +113,11 @@ public void DeltaGlimmerInput(float delta) } } + /// + /// This is the public facing function for modifying Glimmer based on a linear scale. Simply add or subtract to this with any nonzero number. + /// This is primarily intended for load bearing systems such as Probers and Drainers, and should not be called by most things by design. + /// + /// public void DeltaGlimmerOutput(float delta) { if (_enabled && delta != 0) @@ -92,23 +127,46 @@ public void DeltaGlimmerOutput(float delta) } } + /// + /// This directly sets the Player-Facing side of Glimmer to a given value, and is not intended to be called by anything other than admin commands. + /// This is clamped between 0 and 999.999f + /// + /// public void SetGlimmerOutput(float set) { if (_enabled && set != 0) { - GlimmerOutput = set; + GlimmerOutput = Math.Clamp(set, 0, 999.999f); GlimmerInput = 2000 / (1 + MathF.Pow(MathF.E, -.0022f * GlimmerOutput)) - 1000; } } + /// + /// This directly sets the code-facing side of Glimmer to a given value, and is not intended to be called by anything other than admin commands. + /// This accepts any positive float input. + /// + /// public void SetGlimmerInput(float set) { - if (_enabled && set != 0) + if (_enabled && set >= 0) { GlimmerInput = set; GlimmerOutput = 2000 / (1 + MathF.Pow(MathF.E, -.0022f * GlimmerOutput)) - 1000; } } + + /// + /// Outputs the ratio between actual glimmer and glimmer equilibrium(The intersection of the Glimmer Equation and the line y = x). + /// This will return 0.01f if glimmer is 0, and 1 if glimmer is disabled. + /// + public float GetGlimmerEquilibriumRatio() + { + if (!_enabled) + return 1; + else if (GlimmerOutput == 0) + return 0.01f; + else return GlimmerOutput / GlimmerEquilibrium; + } } [Serializable, NetSerializable] diff --git a/Content.Shared/Psionics/PsionicComponent.cs b/Content.Shared/Psionics/PsionicComponent.cs index c955626c53d..748b8ddd92a 100644 --- a/Content.Shared/Psionics/PsionicComponent.cs +++ b/Content.Shared/Psionics/PsionicComponent.cs @@ -19,10 +19,20 @@ public sealed partial class PsionicComponent : Component [DataField("psychicFeedback")] public List PsychicFeedback = new(); - [DataField("amplification")] + /// + /// An abstraction of how "Powerful" a psychic is. This is most commonly used as a multiplier on numerical outputs for psychic powers. + /// + /// + /// For an ordinary human, this will be between 0.5 and 1.2, but may be higher for some entities. + /// + [DataField] public float Amplification = 0.1f; - [DataField("dampening")] + /// + /// An abstraction of how much "Control" a psychic has over their powers. This is most commonly used to decrease glimmer output of powers, + /// or to make obvious powers less likely to be obvious. + /// + [DataField] public float Dampening = 0.1f; public bool Telepath = true; public bool TelepathicMute = false;