Files
wwdpublic/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs
FoxxoTrystan af3aaa0325 Shadowkin Rework (#1200)
<!--
This is a semi-strict format, you can add/remove sections as needed but
the order/format should be kept the same
Remove these comments before submitting
-->

# Description

<!--
Explain this PR in as much detail as applicable

Some example prompts to consider:
How might this affect the game? The codebase?
What might be some alternatives to this?
How/Who does this benefit/hurt [the game/codebase]?
-->

This PR compleatly rework shadowkins, slightly been forced this makes
shadowkins more "psionic creature" then anything else.
This is a WIP, but in general this PR make Shadowkin "Psionic" and fall
under the same rule.

RIP Shadowkin for me but ye.

CHANGES TO SHADOWKINS:
Shadowkins now follow the laws of psionic, they will always spawn with
DarkSwapPower but can generate others power, they do not spawn with
Shadeskip by default anymore, Mana has been lower from 250 to 200; they
can now pick normal psionic jobs.

Changes to DarkSwap:
DarkSwap cost 30 Mana and will raise glimmer on use, its will drain 1
Mana/Sec, will eject the user when mana is fully drained.
DarkSwap is now a random roll.

Changes to Psionics:
Added the Mana Alert for all psionics

---

# TODO

<!--
A list of everything you have to do before this PR is "complete"
You probably won't have to complete everything before merging but it's
good to leave future references
-->

- [x] Psionic Mana Alert
- [x] DarkSwap Rework
- [x] Remove Unique Shadowkin Psionic Changes
- [x] Import bugs fixes/QOL changes.

---

<!--
This is default collapsed, readers click to expand it and see all your
media
The PR media section can get very large at times, so this is a good way
to keep it clean
The title is written using HTML tags
The title must be within the <summary> tags or you won't see it
-->

<details><summary><h1>Media</h1></summary>
<p>

N/A

</p>
</details>

---

# Changelog

<!--
You can add an author after the `🆑` to change the name that appears
in the changelog (ex: `🆑 Death`)
Leaving it blank will default to your GitHub display name
This includes all available types for the changelog
-->

🆑
- tweak: Shadowkins has returned and has been reworked.
- add: DarkSwap is now in the Psionic Power Pool.
- tweak: Psionics can now see their mana pools.

---------

Signed-off-by: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com>
Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>

(cherry picked from commit 93446f1004396c6d86a109690f0033f983d95d3e)
2025-01-13 22:35:59 +03:00

215 lines
7.7 KiB
C#

using Content.Shared.Administration.Logs;
using Content.Shared.Contests;
using Content.Shared.Popups;
using Content.Shared.Psionics;
using Content.Shared.Psionics.Glimmer;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Content.Shared.Mobs.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Rejuvenate;
namespace Content.Shared.Abilities.Psionics
{
public sealed class SharedPsionicAbilitiesSystem : EntitySystem
{
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly SharedPopupSystem _popups = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly GlimmerSystem _glimmerSystem = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly ContestsSystem _contests = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PsionicComponent, PsionicPowerUsedEvent>(OnPowerUsed);
SubscribeLocalEvent<PsionicComponent, RejuvenateEvent>(OnRejuvenate);
}
public bool OnAttemptPowerUse(EntityUid uid, string power, float? manacost = null, bool checkInsulation = true)
{
if (!TryComp<PsionicComponent>(uid, out var component)
|| HasComp<MindbrokenComponent>(uid)
|| checkInsulation
&& HasComp<PsionicInsulationComponent>(uid))
return false;
var tev = new OnAttemptPowerUseEvent(uid, power);
RaiseLocalEvent(uid, tev);
if (tev.Cancelled)
return false;
if (component.DoAfter is not null)
{
_popups.PopupEntity(Loc.GetString(component.AlreadyCasting), uid, uid, PopupType.LargeCaution);
return false;
}
if (manacost is null)
return true;
if (component.Mana >= manacost
|| component.BypassManaCheck)
{
var newmana = component.Mana - manacost;
component.Mana = newmana ?? component.Mana;
var ev = new OnManaUpdateEvent();
RaiseLocalEvent(uid, ref ev);
}
else
{
_popups.PopupEntity(Loc.GetString(component.NoMana), uid, uid, PopupType.LargeCaution);
return false;
}
return true;
}
private void OnPowerUsed(EntityUid uid, PsionicComponent component, PsionicPowerUsedEvent args)
{
foreach (var entity in _lookup.GetEntitiesInRange(uid, 10f))
{
if (HasComp<MetapsionicPowerComponent>(entity) && entity != uid && !(TryComp<PsionicInsulationComponent>(entity, out var insul) && !insul.Passthrough))
{
_popups.PopupEntity(Loc.GetString("metapsionic-pulse-power", ("power", args.Power)), entity, entity, PopupType.LargeCaution);
args.Handled = true;
return;
}
}
}
public void LogPowerUsed(EntityUid uid, string power, int minGlimmer = 8, int maxGlimmer = 12)
{
_adminLogger.Add(Database.LogType.Psionics, Database.LogImpact.Medium, $"{ToPrettyString(uid):player} used {power}");
var ev = new PsionicPowerUsedEvent(uid, power);
RaiseLocalEvent(uid, ev, false);
_glimmerSystem.Glimmer += _robustRandom.Next(minGlimmer, maxGlimmer);
}
/// <summary>
/// Returns the CurrentAmplification of a given Entity, multiplied by the result of that Entity's MoodContest.
/// Higher mood means more Amplification, Lower mood means less Amplification.
/// </summary>
public float ModifiedAmplification(EntityUid uid)
{
if (!TryComp<PsionicComponent>(uid, out var psionicComponent))
return 1;
return ModifiedAmplification(uid, psionicComponent);
}
/// <summary>
/// Returns the CurrentAmplification of a given Entity, multiplied by the result of that Entity's MoodContest.
/// Higher mood means more Amplification, Lower mood means less Amplification.
/// </summary>
public float ModifiedAmplification(EntityUid uid, PsionicComponent component)
{
return component.CurrentAmplification * _contests.MoodContest(uid, true);
}
/// <summary>
/// Returns the CurrentDampening of a given Entity, multiplied by the result of that Entity's MoodContest.
/// Lower mood means more Dampening, higher mood means less Dampening.
/// </summary>
public float ModifiedDampening(EntityUid uid)
{
if (!TryComp<PsionicComponent>(uid, out var psionicComponent))
return 1;
return ModifiedDampening(uid, psionicComponent);
}
/// <summary>
/// Returns the CurrentDampening of a given Entity, multiplied by the result of that Entity's MoodContest.
/// Lower mood means more Dampening, higher mood means less Dampening.
/// </summary>
public float ModifiedDampening(EntityUid uid, PsionicComponent component)
{
return component.CurrentDampening / _contests.MoodContest(uid, true);
}
public void OnRejuvenate(EntityUid uid, PsionicComponent component, RejuvenateEvent args)
{
component.Mana = component.MaxMana;
var ev = new OnManaUpdateEvent();
RaiseLocalEvent(uid, ref ev);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<PsionicComponent>();
while (query.MoveNext(out var uid, out var component))
{
if (_mobState.IsDead(uid)
|| HasComp<PsionicInsulationComponent>(uid))
continue;
component.ManaAccumulator += frameTime;
if (component.ManaAccumulator <= 1)
continue;
component.ManaAccumulator -= 1;
if (component.Mana > component.MaxMana)
component.Mana = component.MaxMana;
if (component.Mana < 0)
component.Mana = 0;
if (component.Mana < component.MaxMana)
{
var gainedmana = component.ManaGain * component.ManaGainMultiplier;
component.Mana += gainedmana;
FixedPoint2.Min(component.Mana, component.MaxMana);
var ev = new OnManaUpdateEvent();
RaiseLocalEvent(uid, ref ev);
}
}
}
}
public sealed class PsionicPowerUsedEvent : HandledEntityEventArgs
{
public EntityUid User { get; }
public string Power = string.Empty;
public PsionicPowerUsedEvent(EntityUid user, string power)
{
User = user;
Power = power;
}
}
public sealed class OnAttemptPowerUseEvent : CancellableEntityEventArgs
{
public EntityUid User { get; }
public string Power = string.Empty;
public OnAttemptPowerUseEvent(EntityUid user, string power)
{
User = user;
Power = power;
}
}
[Serializable]
[NetSerializable]
public sealed class PsionicsChangedEvent : EntityEventArgs
{
public readonly NetEntity Euid;
public PsionicsChangedEvent(NetEntity euid)
{
Euid = euid;
}
}
}