diff --git a/Content.Server/Nyanotrasen/Chemistry/ReactionEffects/ChangeGlimmerReactionEffect.cs b/Content.Server/Nyanotrasen/Chemistry/ReactionEffects/ChangeGlimmerReactionEffect.cs index 65aaf350cba..cd7010700a1 100644 --- a/Content.Server/Nyanotrasen/Chemistry/ReactionEffects/ChangeGlimmerReactionEffect.cs +++ b/Content.Server/Nyanotrasen/Chemistry/ReactionEffects/ChangeGlimmerReactionEffect.cs @@ -21,6 +21,6 @@ public override void Effect(ReagentEffectArgs args) { var glimmersys = args.EntityManager.EntitySysManager.GetEntitySystem(); - glimmersys.Glimmer += Count; + glimmersys.DeltaGlimmerInput(Count); } } diff --git a/Content.Server/Nyanotrasen/Objectives/Systems/RaiseGlimmerConditionSystem.cs b/Content.Server/Nyanotrasen/Objectives/Systems/RaiseGlimmerConditionSystem.cs index d7aae44afa7..5d2cd3fa633 100644 --- a/Content.Server/Nyanotrasen/Objectives/Systems/RaiseGlimmerConditionSystem.cs +++ b/Content.Server/Nyanotrasen/Objectives/Systems/RaiseGlimmerConditionSystem.cs @@ -6,8 +6,8 @@ namespace Content.Server.Objectives.Systems { public sealed class RaiseGlimmerConditionSystem : EntitySystem { - [Dependency] private readonly IEntitySystemManager _sysMan = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; + [Dependency] private readonly GlimmerSystem _glimmer = default!; public override void Initialize() { base.Initialize(); @@ -32,8 +32,7 @@ private void OnGetProgress(EntityUid uid, RaiseGlimmerConditionComponent comp, r private float GetProgress(int target) { - var glimmer = _sysMan.GetEntitySystem().Glimmer; - var progress = Math.Min((float) glimmer / (float) target, 1f); + var progress = Math.Min((float) _glimmer.GlimmerOutput / (float) target, 1f); return progress; } } diff --git a/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs b/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs index 3a0e912c08a..c3eced61da9 100644 --- a/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs +++ b/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs @@ -166,7 +166,7 @@ private void DispenseLiquidReward(EntityUid uid, OracleComponent component) .Where(x => !x.Abstract) .Select(x => x.ID).ToList(); - var amount = 20 + _random.Next(1, 30) + _glimmerSystem.Glimmer / 10f; + var amount = 20 + _random.Next(1, 30) + _glimmerSystem.GlimmerOutput / 10f; amount = (float) Math.Round(amount); var sol = new Solution(); diff --git a/Content.Server/Nyanotrasen/Research/SophicScribe/SophicScribeSystem.cs b/Content.Server/Nyanotrasen/Research/SophicScribe/SophicScribeSystem.cs index b8cdcb56d47..b1a6c1e9de1 100644 --- a/Content.Server/Nyanotrasen/Research/SophicScribe/SophicScribeSystem.cs +++ b/Content.Server/Nyanotrasen/Research/SophicScribe/SophicScribeSystem.cs @@ -23,7 +23,7 @@ public override void Update(float frameTime) { base.Update(frameTime); - if (_glimmerSystem.Glimmer == 0) + if (_glimmerSystem.GlimmerOutput == 0) return; // yes, return. Glimmer value is global. var curTime = _timing.CurTime; @@ -37,7 +37,7 @@ public override void Update(float frameTime) if (!TryComp(scribe, out var radio)) continue; - var message = Loc.GetString("glimmer-report", ("level", _glimmerSystem.Glimmer)); + var message = Loc.GetString("glimmer-report", ("level", (int) Math.Round(_glimmerSystem.GlimmerOutput))); var channel = _prototypeManager.Index("Science"); _radioSystem.SendRadioMessage(scribe, message, channel, scribe); @@ -61,7 +61,7 @@ private void OnInteractHand(EntityUid uid, SophicScribeComponent component, Inte component.StateTime = _timing.CurTime + component.StateCD; - _chat.TrySendInGameICMessage(uid, Loc.GetString("glimmer-report", ("level", _glimmerSystem.Glimmer)), InGameICChatType.Speak, true); + _chat.TrySendInGameICMessage(uid, Loc.GetString("glimmer-report", ("level", (int) Math.Round(_glimmerSystem.GlimmerOutput))), InGameICChatType.Speak, true); } private void OnGlimmerEventEnded(GlimmerEventEndedEvent args) @@ -78,7 +78,7 @@ private void OnGlimmerEventEnded(GlimmerEventEndedEvent args) speaker = swapped.OriginalEntity; } - var message = Loc.GetString(args.Message, ("decrease", args.GlimmerBurned), ("level", _glimmerSystem.Glimmer)); + var message = Loc.GetString(args.Message, ("decrease", args.GlimmerBurned), ("level", (int) Math.Round(_glimmerSystem.GlimmerOutput))); var channel = _prototypeManager.Index("Common"); _radioSystem.SendRadioMessage(speaker, message, channel, speaker); } diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/FreeProberRule.cs b/Content.Server/Nyanotrasen/StationEvents/Events/FreeProberRule.cs index 0aa8ecc47cc..46dff726e55 100644 --- a/Content.Server/Nyanotrasen/StationEvents/Events/FreeProberRule.cs +++ b/Content.Server/Nyanotrasen/StationEvents/Events/FreeProberRule.cs @@ -36,7 +36,7 @@ protected override void Started(EntityUid uid, FreeProberRuleComponent component } } - if (PossibleSpawns.Count == 0 || _glimmerSystem.Glimmer >= 500 || _robustRandom.Prob(0.25f)) + if (PossibleSpawns.Count == 0 || _glimmerSystem.GlimmerOutput >= 500 || _robustRandom.Prob(0.25f)) { var queryBattery = EntityQueryEnumerator(); while (query.MoveNext(out var battery, out var _)) diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/GlimmerEventSystem.cs b/Content.Server/Nyanotrasen/StationEvents/Events/GlimmerEventSystem.cs index a3d36ae7157..078826604eb 100644 --- a/Content.Server/Nyanotrasen/StationEvents/Events/GlimmerEventSystem.cs +++ b/Content.Server/Nyanotrasen/StationEvents/Events/GlimmerEventSystem.cs @@ -13,7 +13,7 @@ protected override void Ended(EntityUid uid, GlimmerEventComponent component, Ga base.Ended(uid, component, gameRule, args); var glimmerBurned = RobustRandom.Next(component.GlimmerBurnLower, component.GlimmerBurnUpper); - _glimmerSystem.Glimmer -= glimmerBurned; + _glimmerSystem.DeltaGlimmerInput(-glimmerBurned); var reportEv = new GlimmerEventEndedEvent(component.SophicReport, glimmerBurned); RaiseLocalEvent(reportEv); diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs b/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs index 6a2c1c3ba7d..cf7b8e6cc9c 100644 --- a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs +++ b/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs @@ -77,7 +77,7 @@ protected override void Started(EntityUid uid, NoosphericFryRuleComponent compon damage.DamageDict.Add("Heat", 2.5); damage.DamageDict.Add("Shock", 2.5); - if (_glimmerSystem.Glimmer > 500 && _glimmerSystem.Glimmer < 750) + if (_glimmerSystem.GlimmerOutput > 500 && _glimmerSystem.GlimmerOutput < 750) { damage *= 2; if (TryComp(pair.wearer, out var flammableComponent)) @@ -85,7 +85,7 @@ protected override void Started(EntityUid uid, NoosphericFryRuleComponent compon flammableComponent.FireStacks += 1; _flammableSystem.Ignite(pair.wearer, pair.wearer, flammableComponent); } - } else if (_glimmerSystem.Glimmer > 750) + } else if (_glimmerSystem.GlimmerOutput > 750) { damage *= 3; if (TryComp(pair.wearer, out var flammableComponent)) diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericStormRule.cs b/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericStormRule.cs index 8812ed1fe37..c26ab1481ac 100644 --- a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericStormRule.cs +++ b/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericStormRule.cs @@ -54,6 +54,6 @@ protected override void Started(EntityUid uid, NoosphericStormRuleComponent comp //var glimmerSeverityMod = 1 + (component.GlimmerSeverityCoefficient * (GetSeverityModifier() - 1f)); var glimmerAdded = (int) baseGlimmerAdd; // Math.Round(baseGlimmerAdd * glimmerSeverityMod); - _glimmerSystem.Glimmer += glimmerAdded; + _glimmerSystem.DeltaGlimmerInput(glimmerAdded); } } diff --git a/Content.Server/Psionics/Abilities/DispelPowerSystem.cs b/Content.Server/Psionics/Abilities/DispelPowerSystem.cs index 3489b15bcf3..33c6b5dcaed 100644 --- a/Content.Server/Psionics/Abilities/DispelPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/DispelPowerSystem.cs @@ -84,7 +84,7 @@ private void OnPowerUsed(DispelPowerActionEvent args) { args.Handled = true; _psionics.LogPowerUsed(args.Performer, "dispel", psionic, 1, 1, true); - _glimmerSystem.Glimmer -= _random.Next((int) Math.Round(2 * psionic.Dampening), (int) Math.Round(4 - psionic.Amplification)); + _glimmerSystem.DeltaGlimmerInput(-_random.NextFloat(2 * psionic.Dampening - psionic.Amplification, 4 * psionic.Dampening - psionic.Amplification)); } } diff --git a/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs b/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs index 480cf561001..9de4e412c81 100644 --- a/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs +++ b/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs @@ -58,7 +58,7 @@ public void AddRandomPsionicPower(EntityUid uid) EntityManager.AddComponent(uid, newComponent); - _glimmerSystem.Glimmer += _random.Next((int) MathF.Round(psionic.Amplification * psionic.Dampening * 1), (int) MathF.Round(psionic.Amplification * psionic.Dampening * 5)); + _glimmerSystem.DeltaGlimmerInput(_random.NextFloat(psionic.Amplification * psionic.Dampening, psionic.Amplification * psionic.Dampening * 5)); } public void RemovePsionics(EntityUid uid) @@ -96,7 +96,7 @@ public void RemovePsionics(EntityUid uid) _statusEffectsSystem.TryAddStatusEffect(uid, "Stutter", TimeSpan.FromMinutes(5), false, "StutteringAccent"); - _glimmerSystem.Glimmer += _random.Next((int) MathF.Round(psionic.Amplification * psionic.Dampening * -10), (int) MathF.Round(psionic.Amplification * psionic.Dampening * -5)); + _glimmerSystem.DeltaGlimmerOutput(-_random.NextFloat((int) MathF.Round(psionic.Amplification * psionic.Dampening * 5), (int) MathF.Round(psionic.Amplification * psionic.Dampening * 10))); RemComp(uid); RemComp(uid); } diff --git a/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs b/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs index c69e05af452..0e7269c6b8d 100644 --- a/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs @@ -1,4 +1,5 @@ using Content.Shared.Actions; +using Content.Shared.DoAfter; using Content.Shared.Psionics.Abilities; using Content.Shared.Psionics.Glimmer; using Content.Server.Atmos.Components; @@ -6,7 +7,13 @@ using Robust.Server.GameObjects; using Content.Shared.Actions.Events; using Content.Server.Explosion.Components; +using Robust.Server.Audio; using Robust.Shared.Map; +using Robust.Shared.Timing; +using Content.Shared.Popups; +using Content.Shared.Mobs; +using Linguini.Syntax.Ast; +using Content.Shared.Psionics.Events; namespace Content.Server.Psionics.Abilities { @@ -17,20 +24,26 @@ public sealed class PyrokinesisPowerSystem : EntitySystem [Dependency] private readonly SharedPsionicAbilitiesSystem _psionics = default!; [Dependency] private readonly GunSystem _gunSystem = default!; [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly AudioSystem _audioSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnPowerUsed); + SubscribeLocalEvent(OnPrecharge); + SubscribeLocalEvent(OnDoAfter); } private void OnInit(EntityUid uid, PyrokinesisPowerComponent component, ComponentInit args) { - _actions.AddAction(uid, ref component.PyrokinesisActionEntity, component.PyrokinesisActionId); - _actions.TryGetActionData( component.PyrokinesisActionEntity, out var actionData); + _actions.AddAction(uid, ref component.PyrokinesisPrechargeActionEntity, component.PyrokinesisPrechargeActionId); + _actions.TryGetActionData( component.PyrokinesisPrechargeActionEntity, out var actionData); if (actionData is { UseDelay: not null }) - _actions.StartUseDelay(component.PyrokinesisActionEntity); + _actions.StartUseDelay(component.PyrokinesisPrechargeActionEntity); if (TryComp(uid, out var psionic)) { psionic.ActivePowers.Add(component); @@ -39,9 +52,46 @@ private void OnInit(EntityUid uid, PyrokinesisPowerComponent component, Componen } } + private void OnPrecharge(PyrokinesisPrechargeActionEvent args) + { + if (!HasComp(args.Performer) + && TryComp(args.Performer, out var psionic) + && TryComp(args.Performer, out var pyroComp)) + { + _actions.AddAction(args.Performer, ref pyroComp.PyrokinesisActionEntity, pyroComp.PyrokinesisActionId); + _actions.TryGetActionData(pyroComp.PyrokinesisActionEntity, out var actionData); + if (actionData is { UseDelay: not null }) + _actions.StartUseDelay(pyroComp.PyrokinesisActionEntity); + _actions.TryGetActionData(pyroComp.PyrokinesisPrechargeActionEntity, out var prechargeData); + if (prechargeData is { UseDelay: not null }) + _actions.StartUseDelay(pyroComp.PyrokinesisPrechargeActionEntity); + + if (_glimmerSystem.GlimmerOutput >= 100 * psionic.Dampening) + { + _popup.PopupEntity(Loc.GetString(pyroComp.PyrokinesisObviousPopup, ("entity", args.Performer)), args.Performer, PopupType.Medium); + _audioSystem.PlayPvs(pyroComp.SoundUse, args.Performer); + } + else + _popup.PopupEntity(Loc.GetString(pyroComp.PyrokinesisSubtlePopup), args.Performer, args.Performer, PopupType.Medium); + + pyroComp.FireballThrown = false; + + var ev = new PyrokinesisPrechargeDoAfterEvent(_gameTiming.CurTime); + var duration = TimeSpan.FromSeconds(pyroComp.ResetDuration.Seconds + psionic.Dampening); + + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.Performer, duration, ev, args.Performer, args.Performer, args.Performer) + { + BlockDuplicate = true, + Hidden = true, + }, out var doAfterId); + + pyroComp.ResetDoAfter = doAfterId; + } + } + private void OnShutdown(EntityUid uid, PyrokinesisPowerComponent component, ComponentShutdown args) { - _actions.RemoveAction(uid, component.PyrokinesisActionEntity); + _actions.RemoveAction(uid, component.PyrokinesisPrechargeActionEntity); if (TryComp(uid, out var psionic)) { psionic.ActivePowers.Remove(component); @@ -53,7 +103,8 @@ private void OnShutdown(EntityUid uid, PyrokinesisPowerComponent component, Comp private void OnPowerUsed(PyrokinesisPowerActionEvent args) { if (!HasComp(args.Performer) - && TryComp(args.Performer, out var psionic)) + && TryComp(args.Performer, out var psionic) + && TryComp(args.Performer, out var pyroComp)) { var spawnCoords = Transform(args.Performer).Coordinates; @@ -61,11 +112,11 @@ private void OnPowerUsed(PyrokinesisPowerActionEvent args) if (TryComp(ent, out var fireball)) { - fireball.MaxIntensity = (int) MathF.Round(5 * psionic.Amplification); + fireball.MaxIntensity = (int) MathF.Round(2 * psionic.Amplification); fireball.IntensitySlope = (int) MathF.Round(1 * psionic.Amplification); - fireball.TotalIntensity = (int) MathF.Round(10 * psionic.Amplification); + fireball.TotalIntensity = (int) MathF.Round(25 * psionic.Amplification); - if (_glimmerSystem.Glimmer >= 500) + if (_glimmerSystem.GlimmerOutput >= 500) fireball.CanCreateVacuum = true; else fireball.CanCreateVacuum = false; @@ -77,10 +128,28 @@ private void OnPowerUsed(PyrokinesisPowerActionEvent args) var direction = args.Target.ToMapPos(EntityManager, _xform) - spawnCoords.ToMapPos(EntityManager, _xform); _gunSystem.ShootProjectile(ent, direction, new System.Numerics.Vector2(0, 0), args.Performer, args.Performer, 20f); - + _actions.RemoveAction(args.Performer, pyroComp.PyrokinesisActionEntity); + _doAfterSystem.Cancel(pyroComp.ResetDoAfter); _psionics.LogPowerUsed(args.Performer, "pyrokinesis", psionic, 6, 8); + pyroComp.FireballThrown = true; args.Handled = true; } } + + private void OnDoAfter(EntityUid uid, PyrokinesisPowerComponent component, PyrokinesisPrechargeDoAfterEvent args) + { + if (!args.Cancelled && TryComp(uid, out var psionic)) + { + if (!component.FireballThrown) + { + _actions.TryGetActionData(component.PyrokinesisPrechargeActionEntity, out var actionData); + if (actionData is { UseDelay: not null }) + _actions.SetCooldown(component.PyrokinesisPrechargeActionEntity, TimeSpan.FromSeconds(15 - psionic.Dampening)); + + _popup.PopupEntity(Loc.GetString(component.PyrokinesisRefundCooldown), uid, uid, PopupType.Medium); + } + _actions.RemoveAction(uid, component.PyrokinesisActionEntity); + } + } } } diff --git a/Content.Server/Psionics/Glimmer/GlimmerCommands.cs b/Content.Server/Psionics/Glimmer/GlimmerCommands.cs index 744f4cdb9a8..d17f1c04565 100644 --- a/Content.Server/Psionics/Glimmer/GlimmerCommands.cs +++ b/Content.Server/Psionics/Glimmer/GlimmerCommands.cs @@ -14,7 +14,7 @@ public sealed class GlimmerShowCommand : IConsoleCommand public async void Execute(IConsoleShell shell, string argStr, string[] args) { var entMan = IoCManager.Resolve(); - shell.WriteLine(entMan.EntitySysManager.GetEntitySystem().Glimmer.ToString()); + shell.WriteLine(entMan.EntitySysManager.GetEntitySystem().GlimmerOutput.ToString()); } } @@ -34,6 +34,6 @@ public async void Execute(IConsoleShell shell, string argStr, string[] args) return; var entMan = IoCManager.Resolve(); - entMan.EntitySysManager.GetEntitySystem().Glimmer = glimmerValue; + entMan.EntitySysManager.GetEntitySystem().SetGlimmerOutput(glimmerValue); } } diff --git a/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs b/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs index c0802c8b670..85034574885 100644 --- a/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs +++ b/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs @@ -176,7 +176,7 @@ private void AddShockVerb(EntityUid uid, SharedGlimmerReactiveComponent componen Act = () => { _sharedAudioSystem.PlayPvs(component.ShockNoises, args.User); - _electrocutionSystem.TryDoElectrocution(args.User, null, _glimmerSystem.Glimmer / 200, TimeSpan.FromSeconds((float) _glimmerSystem.Glimmer / 100), false); + _electrocutionSystem.TryDoElectrocution(args.User, null, (int) Math.Round(_glimmerSystem.GlimmerOutput / 200), TimeSpan.FromSeconds((float) _glimmerSystem.GlimmerOutput / 100), false); }, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png")), Text = Loc.GetString("power-switch-component-toggle-verb"), @@ -190,7 +190,7 @@ private void OnDamageChanged(EntityUid uid, SharedGlimmerReactiveComponent compo if (args.Origin == null) return; - if (!_random.Prob((float) _glimmerSystem.Glimmer / 1000)) + if (!_random.Prob(_glimmerSystem.GlimmerOutput / 1000)) return; var tier = _glimmerSystem.GetGlimmerTier(); @@ -207,13 +207,13 @@ private void OnDestroyed(EntityUid uid, SharedGlimmerReactiveComponent component if (tier < GlimmerTier.High) return; - var totalIntensity = (float) (_glimmerSystem.Glimmer * 2); - var slope = (float) (11 - _glimmerSystem.Glimmer / 100); + var totalIntensity = (float) (_glimmerSystem.GlimmerOutput * 2); + var slope = (float) (11 - _glimmerSystem.GlimmerOutput / 100); var maxIntensity = 20; - var removed = (float) _glimmerSystem.Glimmer * _random.NextFloat(0.1f, 0.15f); - _glimmerSystem.Glimmer -= (int) removed; - BeamRandomNearProber(uid, _glimmerSystem.Glimmer / 350, _glimmerSystem.Glimmer / 50); + var removed = (float) _glimmerSystem.GlimmerOutput * _random.NextFloat(0.1f, 0.15f); + _glimmerSystem.DeltaGlimmerOutput(-removed); + BeamRandomNearProber(uid, (int) Math.Round(_glimmerSystem.GlimmerOutput / 350), _glimmerSystem.GlimmerOutput / 50); _explosionSystem.QueueExplosion(uid, "Default", totalIntensity, slope, maxIntensity); } @@ -222,7 +222,7 @@ private void OnUnanchorAttempt(EntityUid uid, SharedGlimmerReactiveComponent com if (_glimmerSystem.GetGlimmerTier() >= GlimmerTier.Dangerous) { _sharedAudioSystem.PlayPvs(component.ShockNoises, args.User); - _electrocutionSystem.TryDoElectrocution(args.User, null, _glimmerSystem.Glimmer / 200, TimeSpan.FromSeconds((float) _glimmerSystem.Glimmer / 100), false); + _electrocutionSystem.TryDoElectrocution(args.User, null, (int) Math.Round(_glimmerSystem.GlimmerOutput / 200), TimeSpan.FromSeconds((float) _glimmerSystem.GlimmerOutput / 100), false); args.Cancel(); } } @@ -265,7 +265,7 @@ private void Beam(EntityUid prober, EntityUid target, GlimmerTier tier, bool obe if (!lxform.Coordinates.TryDistance(EntityManager, txform.Coordinates, out var distance)) return; - if (distance > (float) (_glimmerSystem.Glimmer / 100)) + if (distance > (float) (_glimmerSystem.GlimmerOutput / 100)) return; string beamproto; diff --git a/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs b/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs index 57c74398b08..a17a97410ac 100644 --- a/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs +++ b/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs @@ -1,9 +1,7 @@ -using Robust.Shared.Random; using Robust.Shared.Timing; using Robust.Shared.Configuration; using Content.Shared.CCVar; using Content.Shared.Psionics.Glimmer; -using Content.Shared.GameTicking; namespace Content.Server.Psionics.Glimmer { @@ -13,7 +11,6 @@ namespace Content.Server.Psionics.Glimmer public sealed class PassiveGlimmerReductionSystem : EntitySystem { [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; - [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; @@ -21,58 +18,38 @@ public sealed class PassiveGlimmerReductionSystem : EntitySystem public List GlimmerValues = new(); public TimeSpan TargetUpdatePeriod = TimeSpan.FromSeconds(6); - - private int _updateIncrementor; public TimeSpan NextUpdateTime = default!; public TimeSpan LastUpdateTime = default!; - private float _glimmerLostPerSecond; + private float _glimmerLinearDecay; + private bool _enabled; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnRoundRestartCleanup); - _cfg.OnValueChanged(CCVars.GlimmerLostPerSecond, UpdatePassiveGlimmer, true); - } - - private void OnRoundRestartCleanup(RoundRestartCleanupEvent args) - { - GlimmerValues.Clear(); + _cfg.OnValueChanged(CCVars.GlimmerLinearDecayPerMinute, UpdatePassiveGlimmer, true); + _enabled = _cfg.GetCVar(CCVars.GlimmerEnabled); + _cfg.OnValueChanged(CCVars.GlimmerEnabled, value => _enabled = value, true); } public override void Update(float frameTime) { base.Update(frameTime); + if (!_enabled) + return; var curTime = _timing.CurTime; if (NextUpdateTime > curTime) return; + var glimmerDecay = _glimmerLinearDecay / (60 / TargetUpdatePeriod.Seconds); - var delta = curTime - LastUpdateTime; - var maxGlimmerLost = (int) Math.Round(delta.TotalSeconds * _glimmerLostPerSecond); - - // It used to be 75% to lose one glimmer per ten seconds, but now it's 50% per six seconds. - // The probability is exactly the same over the same span of time. (0.25 ^ 3 == 0.5 ^ 6) - // This math is just easier to do for pausing's sake. - var actualGlimmerLost = _random.Next(0, 1 + maxGlimmerLost); - - _glimmerSystem.Glimmer -= actualGlimmerLost; - - _updateIncrementor++; - - // Since we normally update every 6 seconds, this works out to a minute. - if (_updateIncrementor == 10) - { - GlimmerValues.Add(_glimmerSystem.Glimmer); - - _updateIncrementor = 0; - } + _glimmerSystem.DeltaGlimmerOutput(-glimmerDecay); NextUpdateTime = curTime + TargetUpdatePeriod; LastUpdateTime = curTime; } - private void UpdatePassiveGlimmer(float value) => _glimmerLostPerSecond = value; + private void UpdatePassiveGlimmer(float value) => _glimmerLinearDecay = value; } } diff --git a/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs index 5d16c4e5e42..5e0e3f04cff 100644 --- a/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs +++ b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs @@ -47,12 +47,12 @@ private void OnAnomalyPulse(EntityUid uid, GlimmerSourceComponent component, ref // component. if (TryComp(uid, out var anomaly)) - _glimmerSystem.Glimmer += (int) (5f * anomaly.Severity); + _glimmerSystem.DeltaGlimmerInput(5f * anomaly.Severity); } private void OnAnomalySupercritical(EntityUid uid, GlimmerSourceComponent component, ref AnomalySupercriticalEvent args) { - _glimmerSystem.Glimmer += 100; + _glimmerSystem.DeltaGlimmerOutput(100); } private void OnMobStateChanged(EntityUid uid, GlimmerSourceComponent component, ref MobStateChangedEvent args) @@ -79,11 +79,11 @@ public override void Update(float frameTime) source.Accumulator -= source.SecondsPerGlimmer; if (source.AddToGlimmer) { - _glimmerSystem.Glimmer++; + _glimmerSystem.DeltaGlimmerInput(1); } else { - _glimmerSystem.Glimmer--; + _glimmerSystem.DeltaGlimmerInput(1); } } } diff --git a/Content.Server/Psionics/PsionicsSystem.cs b/Content.Server/Psionics/PsionicsSystem.cs index 04a7597c900..06250f77ba3 100644 --- a/Content.Server/Psionics/PsionicsSystem.cs +++ b/Content.Server/Psionics/PsionicsSystem.cs @@ -141,7 +141,7 @@ public void RollPsionics(EntityUid uid, PotentialPsionicComponent component, boo } if (applyGlimmer) - chance += (float) _glimmerSystem.Glimmer / 1000; + chance += (float) _glimmerSystem.GlimmerOutput / 1000; chance *= multiplier; diff --git a/Content.Server/Psionics/Telepathy/TelepathyChatSystem.cs b/Content.Server/Psionics/Telepathy/TelepathyChatSystem.cs index 2c6b93e2542..917511d1477 100644 --- a/Content.Server/Psionics/Telepathy/TelepathyChatSystem.cs +++ b/Content.Server/Psionics/Telepathy/TelepathyChatSystem.cs @@ -100,11 +100,11 @@ public void SendTelepathicChat(EntityUid source, string message, bool hideChat) _chatManager.ChatMessageToMany(ChatChannel.Telepathic, message, adminMessageWrap, source, hideChat, true, admins, Color.PaleVioletRed); if (_random.Prob(0.1f)) - _glimmerSystem.Glimmer++; + _glimmerSystem.DeltaGlimmerInput(1); - if (_random.Prob(Math.Min(0.33f + (float) _glimmerSystem.Glimmer / 1500, 1))) + if (_random.Prob(Math.Min(0.33f + (float) _glimmerSystem.GlimmerOutput / 1500, 1))) { - float obfuscation = 0.25f + (float) _glimmerSystem.Glimmer / 2000; + float obfuscation = 0.25f + (float) _glimmerSystem.GlimmerOutput / 2000; var obfuscated = ObfuscateMessageReadability(message, obfuscation); _chatManager.ChatMessageToMany(ChatChannel.Telepathic, obfuscated, messageWrap, source, hideChat, false, GetDreamers(clients), Color.PaleVioletRed); } diff --git a/Content.Server/StationEvents/EventManagerSystem.cs b/Content.Server/StationEvents/EventManagerSystem.cs index 261e8ca46dd..d33a373b377 100644 --- a/Content.Server/StationEvents/EventManagerSystem.cs +++ b/Content.Server/StationEvents/EventManagerSystem.cs @@ -191,8 +191,8 @@ private bool CanRun(EntityPrototype prototype, StationEventComponent stationEven // This could not be cleanly done anywhere else. if (_configurationManager.GetCVar(CCVars.GlimmerEnabled) && prototype.TryGetComponent(out var glimmerEvent) && - (_glimmerSystem.Glimmer < glimmerEvent.MinimumGlimmer || - _glimmerSystem.Glimmer > glimmerEvent.MaximumGlimmer)) + (_glimmerSystem.GlimmerOutput < glimmerEvent.MinimumGlimmer || + _glimmerSystem.GlimmerOutput > glimmerEvent.MaximumGlimmer)) { return false; } diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs index 27caebef808..de869ab7e89 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs @@ -366,13 +366,11 @@ private void OnExtractButton(EntityUid uid, AnalysisConsoleComponent component, _research.ModifyServerPoints(server.Value, pointValue, serverComponent); _artifact.AdjustConsumedPoints(artifact.Value, pointValue); - // Nyano - Summary - Begin modified code block: tie artifacts to glimmer. if (TryComp(component.AnalyzerEntity.Value, out var analyzer) && analyzer != null) { - _glimmerSystem.Glimmer += (int) pointValue / analyzer.ExtractRatio; + _glimmerSystem.DeltaGlimmerInput(pointValue / analyzer.ExtractRatio); } - // Nyano - End modified code block. _audio.PlayPvs(component.ExtractSound, component.AnalyzerEntity.Value, AudioParams.Default.WithVolume(2f)); diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 7d7f3c70449..926701400ea 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -2141,11 +2141,11 @@ public static readonly CVarDef CVarDef.Create("glimmer.enabled", true, CVar.REPLICATED); /// - /// Passive glimmer drain per second. - /// Note that this is randomized and this is an average value. + /// The rate at which glimmer linearly decays. Since glimmer increases (usually) follow a logistic curve, this means glimmer + /// becomes increasingly harder to raise after ~502 points. /// - public static readonly CVarDef GlimmerLostPerSecond = - CVarDef.Create("glimmer.passive_drain_per_second", 0.1f, CVar.SERVERONLY); + public static readonly CVarDef GlimmerLinearDecayPerMinute = + CVarDef.Create("glimmer.linear_decay_per_minute", 6f, CVar.SERVERONLY); /// /// Whether random rolls for psionics are allowed. diff --git a/Content.Shared/Nyanotrasen/Actions/Events/PyrokinesisPowerActionEvent.cs b/Content.Shared/Nyanotrasen/Actions/Events/PyrokinesisPowerActionEvent.cs index 4639aadd55b..2493be58fab 100644 --- a/Content.Shared/Nyanotrasen/Actions/Events/PyrokinesisPowerActionEvent.cs +++ b/Content.Shared/Nyanotrasen/Actions/Events/PyrokinesisPowerActionEvent.cs @@ -1,4 +1,5 @@ namespace Content.Shared.Actions.Events; public sealed partial class PyrokinesisPowerActionEvent : WorldTargetActionEvent {} +public sealed partial class PyrokinesisPrechargeActionEvent : InstantActionEvent {} diff --git a/Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs b/Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs index 1f88741b9a9..b95ead8ec1a 100644 --- a/Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs +++ b/Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs @@ -1,4 +1,5 @@ -using Content.Shared.Actions; +using Content.Shared.DoAfter; +using Robust.Shared.Audio; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -7,7 +8,13 @@ namespace Content.Shared.Psionics.Abilities [RegisterComponent] public sealed partial class PyrokinesisPowerComponent : Component { - public EntityTargetActionComponent? PyrokinesisPowerAction = null; + [DataField("pyrokinesisPrechargeActionId", + customTypeSerializer: typeof(PrototypeIdSerializer))] + public string? PyrokinesisPrechargeActionId = "ActionPrechargePyrokinesis"; + + [DataField("pyrokinesisPrechargeActionEntity")] + public EntityUid? PyrokinesisPrechargeActionEntity; + [DataField("pyrokinesisActionId", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? PyrokinesisActionId = "ActionPyrokinesis"; @@ -17,5 +24,22 @@ public sealed partial class PyrokinesisPowerComponent : Component [DataField("pyrokinesisFeedback")] public string PyrokinesisFeedback = "pyrokinesis-feedback"; + + [DataField] + public string PyrokinesisObviousPopup = "pyrokinesis-obvious"; + + [DataField] + public string PyrokinesisSubtlePopup = "pyrokinesis-subtle"; + + [DataField] + public string PyrokinesisRefundCooldown = "pyrokinesis-refund-cooldown"; + + public DoAfterId? ResetDoAfter; + public bool FireballThrown; + + [DataField] + public SoundSpecifier SoundUse = new SoundPathSpecifier("/Audio/Items/welder.ogg"); + [DataField] + public TimeSpan ResetDuration = TimeSpan.FromSeconds(7); } } diff --git a/Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPrechargeComponent.cs b/Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPrechargeComponent.cs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Content.Shared/Psionics/Events.cs b/Content.Shared/Psionics/Events.cs index 45a00b5f048..88cf17a4a2f 100644 --- a/Content.Shared/Psionics/Events.cs +++ b/Content.Shared/Psionics/Events.cs @@ -57,6 +57,24 @@ public FocusedMetapsionicDoAfterEvent(TimeSpan startedAt) public override DoAfterEvent Clone() => this; } + [Serializable, NetSerializable] + public sealed partial class PyrokinesisPrechargeDoAfterEvent : DoAfterEvent + { + [DataField("startedAt", required: true)] + public TimeSpan StartedAt; + + private PyrokinesisPrechargeDoAfterEvent() + { + } + + public PyrokinesisPrechargeDoAfterEvent(TimeSpan startedAt) + { + StartedAt = startedAt; + } + + public override DoAfterEvent Clone() => this; + } + [Serializable, NetSerializable] public sealed partial class GlimmerWispDrainDoAfterEvent : SimpleDoAfterEvent { diff --git a/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs b/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs index 8be02f936a9..8d1393b8846 100644 --- a/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs +++ b/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs @@ -11,11 +11,32 @@ namespace Content.Shared.Psionics.Glimmer public sealed class GlimmerSystem : EntitySystem { [Dependency] private readonly IConfigurationManager _cfg = default!; - private int _glimmer = 0; - public int Glimmer + 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 + /// Where x = GlimmerOutput and y = GlimmerInput + /// + /// + /// This is private set for a good reason, if you're looking to change it, do so via DeltaGlimmerInput or SetGlimmerInput + /// + public float GlimmerInput + { + get { return _glimmerInput; } + private set { _glimmerInput = _enabled ? Math.Min(value, 0) : 0; } + } + private float _glimmerOutput = 0; + + /// + /// 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 + /// + /// + /// This is private set for a good reason, if you're looking to change it, do so via DeltaGlimmerOutput or SetGlimmerOutput + /// + public float GlimmerOutput { - get { return _glimmer; } - set { _glimmer = _enabled ? Math.Clamp(value, 0, 1000) : 0; } + get { return _glimmerOutput; } + private set { _glimmerOutput = _enabled ? Math.Min(value, 0) : 0; } } private bool _enabled; public override void Initialize() @@ -28,17 +49,18 @@ public override void Initialize() private void Reset(RoundRestartCleanupEvent args) { - Glimmer = 0; + GlimmerInput = 0; + GlimmerOutput = 0; } /// /// Return an abstracted range of a glimmer count. /// /// What glimmer count to check. Uses the current glimmer by default. - public GlimmerTier GetGlimmerTier(int? glimmer = null) + public GlimmerTier GetGlimmerTier(float? glimmer = null) { if (glimmer == null) - glimmer = Glimmer; + glimmer = GlimmerOutput; return glimmer switch { @@ -50,6 +72,47 @@ public GlimmerTier GetGlimmerTier(int? glimmer = null) _ => GlimmerTier.Critical, }; } + + // Ignore the bracket warnings on these, Intellisense is wrong and doesn't understand polynomials. + /// + /// The primary intended accessors for + /// + /// + public void DeltaGlimmerInput(float delta) + { + if (_enabled && delta != 0) + { + GlimmerInput += delta; + GlimmerOutput = (2000 / (1 + MathF.Pow(MathF.E, -.0022f * GlimmerInput))) - 1000; + } + } + + public void DeltaGlimmerOutput(float delta) + { + if (_enabled && delta != 0) + { + GlimmerOutput += delta; + GlimmerInput = (2000 / (1 + MathF.Pow(MathF.E, -.0022f * GlimmerOutput))) - 1000; + } + } + + public void SetGlimmerOutput(float set) + { + if (_enabled && set != 0) + { + GlimmerOutput = set; + GlimmerInput = (2000 / (1 + MathF.Pow(MathF.E, -.0022f * GlimmerOutput))) - 1000; + } + } + + public void SetGlimmerInput(float set) + { + if (_enabled && set != 0) + { + GlimmerInput = set; + GlimmerOutput = (2000 / (1 + MathF.Pow(MathF.E, -.0022f * GlimmerOutput))) - 1000; + } + } } [Serializable, NetSerializable] diff --git a/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs b/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs index cf3bafab5ad..f905ec4dd44 100644 --- a/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs +++ b/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs @@ -91,10 +91,10 @@ public void LogPowerUsed(EntityUid uid, string power, PsionicComponent? psionic if (!overrideGlimmer) { if (psionic == null) - _glimmerSystem.Glimmer += _robustRandom.Next(minGlimmer, maxGlimmer); - else _glimmerSystem.Glimmer += _robustRandom.Next( - (int) Math.Round(minGlimmer * psionic.Amplification - psionic.Dampening), - (int) Math.Round(maxGlimmer * psionic.Amplification - psionic.Dampening)); + _glimmerSystem.DeltaGlimmerInput(_robustRandom.NextFloat(minGlimmer, maxGlimmer)); + else _glimmerSystem.DeltaGlimmerInput(_robustRandom.NextFloat( + minGlimmer * psionic.Amplification - psionic.Dampening, + maxGlimmer * psionic.Amplification - psionic.Dampening)); } } } diff --git a/Resources/Locale/en-US/customization/character-requirements.ftl b/Resources/Locale/en-US/customization/character-requirements.ftl index b073bdb773f..e7bcf0669f7 100644 --- a/Resources/Locale/en-US/customization/character-requirements.ftl +++ b/Resources/Locale/en-US/customization/character-requirements.ftl @@ -9,7 +9,7 @@ character-species-requirement = You must {$inverted -> character-trait-requirement = You must {$inverted -> [true] not have *[other] have -} the trait [color=lightblue]{$trait}[/color] +} the trait [color=lightblue]{$traits}[/color] character-backpack-type-requirement = You must {$inverted -> [true] not use *[other] use diff --git a/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl b/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl index 02800953b1e..c3a9641768f 100644 --- a/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl +++ b/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl @@ -63,7 +63,10 @@ action-name-noospheric-zap = Noospheric Zap action-description-noospheric-zap = Shocks the conciousness of the target and leaves them stunned and stuttering. action-name-pyrokinesis = Pyrokinesis -action-description-pyrokinesis = Hurl a small gateway to the plane of Gehenna at your target. +action-description-pyrokinesis = Hurl a fire bolt at your target + +action-name-precharge-pyrokinesis = Precharge Pyrokinesis +action-description-precharge-pyrokinesis = Draw forth the Secret of Fire, and prepare to launch a fire bolt action-name-psychokinesis = Psychokinesis action-description-psychokinesis = Bend the fabric of space to instantly move across it. diff --git a/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl b/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl index 2add055f7bd..311d71d6ac7 100644 --- a/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl +++ b/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl @@ -44,6 +44,10 @@ focused-metapsionic-pulse-begin = The air around {CAPITALIZE($entity)} begins to psionic-regeneration-self-revive = {CAPITALIZE($entity)} begins to visibly regenerate mindbreaking-feedback = The light of life vanishes from {CAPITALIZE($entity)}'s eyes, leaving behind a husk pretending at sapience regenerative-stasis-begin = {CAPITALIZE($entity)} swoons for a moment, then begins visibly regenerating +pyrokinesis-obvious = A mote of flame dances around {CAPITALIZE($entity)}'s fingers +pyrokinesis-subtle = You draw upon the Secret of Fire. + Use this action again to throw a fire bolt. +pyrokinesis-refund-cooldown = You reclaim some of the energy spent drawing forth the Secret of Fire # Misc Psionic Messages telepathic-mute-message = You strain, but are unable to send your thoughts to the Noosphere diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index bfda7e48be7..dc3d407e5e8 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -36,3 +36,15 @@ trait-name-LatentPsychic = Latent Psychic trait-description-LatentPsychic = Your mind and soul are open to the noosphere, allowing for a limited use of Telepathy. Thus, you are eligible for potentially receiving psychic powers. It is possible that you may be hunted by otherworldly forces, so consider keeping your powers a secret. + +trait-name-PsionicInsulation = χ Waveform Misalignment +trait-description-PsionicInsulation = Through a quirk of fate, your brainwaves are permanently out of phase with the noösphere + You are immune to both positive and negative effects of nearly all psychic powers, + But you can never be a psionic yourself in this life. This trait is incompatible with + all other psychic traits. + +trait-name-NaturalTelepath = Natural Telepath +trait-description-NaturalTelepath = As a naturally occuring Telepath, you are capable of fluent telepathic communication, regardless of + whether or not you possess any notable psychic powers. This offers all of the same benefits and + drawbacks of Latent Psychic, except that you are guaranteed to start with full Telepathy. You may + still gain powers as normal for a Latent Psychic. diff --git a/Resources/Prototypes/Nyanotrasen/Actions/types.yml b/Resources/Prototypes/Nyanotrasen/Actions/types.yml index 55dd48e5470..4ee617931dc 100644 --- a/Resources/Prototypes/Nyanotrasen/Actions/types.yml +++ b/Resources/Prototypes/Nyanotrasen/Actions/types.yml @@ -96,12 +96,24 @@ components: - type: WorldTargetAction icon: Nyanotrasen/Interface/VerbIcons/pyrokinesis.png - useDelay: 50 - range: 6 + useDelay: 1 + range: 15 checkCanAccess: false + checkCanInteract: true itemIconStyle: BigAction event: !type:PyrokinesisPowerActionEvent +- type: entity + id: ActionPrechargePyrokinesis + name: action-name-precharge-pyrokinesis + description: action-description-precharge-pyrokinesis + noSpawn: true + components: + - type: InstantAction + icon: Nyanotrasen/Interface/VerbIcons/pyrokinesis.png + useDelay: 50 + event: !type:PyrokinesisPrechargeActionEvent + - type: entity id: ActionWideMetapsionic name: action-name-widemetapsionic diff --git a/Resources/Prototypes/Traits/psionics.yml b/Resources/Prototypes/Traits/psionics.yml index 01c8a5750eb..277070617cf 100644 --- a/Resources/Prototypes/Traits/psionics.yml +++ b/Resources/Prototypes/Traits/psionics.yml @@ -4,3 +4,36 @@ points: -1 components: - type: PotentialPsionic + requirements: + - !type:CharacterTraitRequirement + inverted: true + traits: + - PsionicInsulation + - NaturalTelepath + +- type: trait + id: PsionicInsulation + category: Psionic + points: -5 + components: + - type: PsionicInsulation + requirements: + - !type:CharacterTraitRequirement + inverted: true + traits: + - LatentPsychic + - NaturalTelepath + +- type: trait + id: NaturalTelepath + category: Psionic + points: -3 + components: + - type: PotentialPsionic + - type: Psionic + requirements: + - !type:CharacterTraitRequirement + inverted: true + traits: + - LatentPsychic + - PsionicInsulation