Files
wwdpublic/Content.Server/Psionics/PsionicsSystem.cs
VMSolidus dfe5c2c540 Psionic Refactor Part 1: Respacing To Keep Files Changed Down (#698)
# Description

Due to some inherent limitations of maintenance, code review, and me
having both severely crippling ADHD and a lifelong adderal dependency,
I've made the executive decision to break apart the Psionic Refactor
into a multitude of smaller, bite sized PRs. I'm keeping the original
Psionic Refactor PR open, because I'm going to need it for code
reference to keep track of the changes I had originally worked on, but I
need to essentially restart the entire refactor from scratch, and
approach it from a new angle that's going to make everything actually
way easier. I also need to be able to work on each available system
individually wherever possible, and this fact is most readily shown by
how the Lightning Refactor and Oracle Refactor were both done
separately.

To start off, this PR is ONLY moving all of the relevant psionics code
to core folders, and nothing more. I'm doing this first so that I can
immediately cut down massively on the "Files Changed" with the simplest,
most basic change necessary to start my work.

No changelog because this isn't player facing, and no media because
there's literally nothing to show.
2024-08-07 16:18:35 -07:00

168 lines
6.2 KiB
C#

using Content.Shared.Abilities.Psionics;
using Content.Shared.StatusEffect;
using Content.Shared.Mobs;
using Content.Shared.Psionics.Glimmer;
using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Damage.Events;
using Content.Shared.IdentityManagement;
using Content.Shared.CCVar;
using Content.Server.Abilities.Psionics;
using Content.Server.Chat.Systems;
using Content.Server.Electrocution;
using Content.Server.NPC.Components;
using Content.Server.NPC.Systems;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Random;
namespace Content.Server.Psionics
{
public sealed class PsionicsSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly PsionicAbilitiesSystem _psionicAbilitiesSystem = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
[Dependency] private readonly ElectrocutionSystem _electrocutionSystem = default!;
[Dependency] private readonly MindSwapPowerSystem _mindSwapPowerSystem = default!;
[Dependency] private readonly GlimmerSystem _glimmerSystem = default!;
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly NpcFactionSystem _npcFactonSystem = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
/// <summary>
/// Unfortunately, since spawning as a normal role and anything else is so different,
/// this is the only way to unify them, for now at least.
/// </summary>
Queue<(PotentialPsionicComponent component, EntityUid uid)> _rollers = new();
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var roller in _rollers)
{
RollPsionics(roller.uid, roller.component, false);
}
_rollers.Clear();
}
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PotentialPsionicComponent, MapInitEvent>(OnStartup);
SubscribeLocalEvent<AntiPsionicWeaponComponent, MeleeHitEvent>(OnMeleeHit);
SubscribeLocalEvent<AntiPsionicWeaponComponent, TakeStaminaDamageEvent>(OnStamHit);
SubscribeLocalEvent<PsionicComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<PsionicComponent, ComponentRemove>(OnRemove);
}
private void OnStartup(EntityUid uid, PotentialPsionicComponent component, MapInitEvent args)
{
if (HasComp<PsionicComponent>(uid))
return;
_rollers.Enqueue((component, uid));
}
private void OnMeleeHit(EntityUid uid, AntiPsionicWeaponComponent component, MeleeHitEvent args)
{
foreach (var entity in args.HitEntities)
{
if (HasComp<PsionicComponent>(entity))
{
_audio.PlayPvs("/Audio/Effects/lightburn.ogg", entity);
args.ModifiersList.Add(component.Modifiers);
if (_random.Prob(component.DisableChance))
_statusEffects.TryAddStatusEffect(entity, "PsionicsDisabled", TimeSpan.FromSeconds(10), true, "PsionicsDisabled");
}
if (TryComp<MindSwappedComponent>(entity, out var swapped))
{
_mindSwapPowerSystem.Swap(entity, swapped.OriginalEntity, true);
return;
}
if (component.Punish && HasComp<PotentialPsionicComponent>(entity) && !HasComp<PsionicComponent>(entity) && _random.Prob(0.5f))
_electrocutionSystem.TryDoElectrocution(args.User, null, 20, TimeSpan.FromSeconds(5), false);
}
}
private void OnInit(EntityUid uid, PsionicComponent component, ComponentInit args)
{
if (!component.Removable)
return;
if (!TryComp<NpcFactionMemberComponent>(uid, out var factions))
return;
if (_npcFactonSystem.ContainsFaction(uid, "GlimmerMonster", factions))
return;
_npcFactonSystem.AddFaction(uid, "PsionicInterloper");
}
private void OnRemove(EntityUid uid, PsionicComponent component, ComponentRemove args)
{
if (!TryComp<NpcFactionMemberComponent>(uid, out var factions))
return;
_npcFactonSystem.RemoveFaction(uid, "PsionicInterloper");
}
private void OnStamHit(EntityUid uid, AntiPsionicWeaponComponent component, TakeStaminaDamageEvent args)
{
var bonus = false;
if (HasComp<PsionicComponent>(args.Target))
bonus = true;
if (!bonus)
return;
args.FlatModifier += component.PsychicStaminaDamage;
}
public void RollPsionics(EntityUid uid, PotentialPsionicComponent component, bool applyGlimmer = true, float multiplier = 1f)
{
if (HasComp<PsionicComponent>(uid))
return;
if (!_cfg.GetCVar(CCVars.PsionicRollsEnabled))
return;
var chance = component.Chance;
var warn = true;
if (TryComp<PsionicBonusChanceComponent>(uid, out var bonus))
{
chance *= bonus.Multiplier;
chance += bonus.FlatBonus;
warn = bonus.Warn;
}
if (applyGlimmer)
chance += ((float) _glimmerSystem.Glimmer / 1000);
chance *= multiplier;
chance = Math.Clamp(chance, 0, 1);
if (_random.Prob(chance))
_psionicAbilitiesSystem.AddPsionics(uid, warn);
}
public void RerollPsionics(EntityUid uid, PotentialPsionicComponent? psionic = null, float bonusMuliplier = 1f)
{
if (!Resolve(uid, ref psionic, false))
return;
if (psionic.Rerolled)
return;
RollPsionics(uid, psionic, multiplier: bonusMuliplier);
psionic.Rerolled = true;
}
}
}