Skip to content

Commit

Permalink
add glimmer/psionic artifact stuff (#1785)
Browse files Browse the repository at this point in the history
* add TryMakePsionic

* refactor psionic abilities file, add PsionicPowerDetectedEvent

* add glimmer/psionic artifact code

* add glimmer/psionic artifact triggers and effects

* pro

* o

* fix hint

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
  • Loading branch information
deltanedas authored Sep 12, 2024
1 parent 9eee5c8 commit 845d584
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 88 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Effects.Systems;
using Content.Shared.Destructible.Thresholds;

namespace Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Effects.Components;

/// <summary>
/// Raises or lowers glimmer when this artifact is triggered.
/// </summary>
[RegisterComponent, Access(typeof(GlimmerArtifactSystem))]
public sealed partial class GlimmerArtifactComponent : Component
{
/// <summary>
/// If glimmer is not in this range it won't do anything.
/// Prevents the trigger being too extreme or too beneficial.
/// </summary>
[DataField(required: true)]
public MinMax Range;

/// <summary>
/// Number to add to glimmer when triggering.
/// </summary>
[DataField(required: true)]
public int Change;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Effects.Systems;

namespace Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Effects.Components;

/// <summary>
/// Makes people in a radius around it psionic when triggered.
/// </summary>
[RegisterComponent, Access(typeof(PsionicProducingArtifactSystem))]
public sealed partial class PsionicProducingArtifactComponent : Component
{
/// <summary>
/// Range to look for potential psionics in.
/// </summary>
[DataField(required: true)]
public float Range;

/// <summary>
/// Number of times this node can trigger before it switches to doing nothing.
/// </summary>
[DataField]
public int Limit = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Effects.Components;
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
using Content.Shared.Psionics.Glimmer;

namespace Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Effects.Systems;

public sealed class GlimmerArtifactSystem : EntitySystem
{
[Dependency] private readonly GlimmerSystem _glimmer = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<GlimmerArtifactComponent, ArtifactActivatedEvent>(OnActivated);
}

private void OnActivated(Entity<GlimmerArtifactComponent> ent, ref ArtifactActivatedEvent args)
{
var range = ent.Comp.Range;
var current = _glimmer.Glimmer;
if (current < range.Min || current > range.Max)
return;

_glimmer.Glimmer += ent.Comp.Change;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Effects.Components;
using Content.Server.Xenoarchaeology.XenoArtifacts;
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
using Content.Server.Psionics;

public sealed class PsionicProducingArtifactSystem : EntitySystem
{
[Dependency] private readonly ArtifactSystem _artifact = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly PsionicsSystem _psionics = default!;

public const string NodeDataPsionicAmount = "nodeDataPsionicAmount";

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<PsionicProducingArtifactComponent, ArtifactActivatedEvent>(OnActivated);
}

private void OnActivated(Entity<PsionicProducingArtifactComponent> ent, ref ArtifactActivatedEvent args)
{
var (uid, comp) = ent;
if (!_artifact.TryGetNodeData(uid, NodeDataPsionicAmount, out int amount))
amount = 0;

if (amount >= comp.Limit)
return;

var coords = Transform(uid).Coordinates;
foreach (var target in _lookup.GetEntitiesInRange<PotentialPsionicComponent>(coords, comp.Range))
{
_psionics.TryMakePsionic(target);
}

_artifact.SetNodeData(uid, NodeDataPsionicAmount, amount + 1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Triggers.Components;

/// <summary>
/// Triggers if a psionic power is used nearby.
/// Requires <c>MetapsionicPowerComponent</c> to be added too.
/// </summary>
[RegisterComponent]
public sealed partial class ArtifactMetapsionicTriggerComponent : Component;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Content.Server.DeltaV.Xenoarchaeology.XenoArtifacts.Triggers.Components;
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
using Content.Shared.Abilities.Psionics;

namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;

public sealed class ArtifactMetapsionicTriggerSystem : EntitySystem
{
[Dependency] private readonly ArtifactSystem _artifact = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<ArtifactMetapsionicTriggerComponent, PsionicPowerDetectedEvent>(OnPowerDetected);
}

private void OnPowerDetected(Entity<ArtifactMetapsionicTriggerComponent> ent, ref PsionicPowerDetectedEvent args)
{
_artifact.TryActivateArtifact(ent);
}
}
24 changes: 17 additions & 7 deletions Content.Server/Nyanotrasen/Psionics/PsionicsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,21 +128,31 @@ private void OnStamHit(EntityUid uid, AntiPsionicWeaponComponent component, Stam
args.FlatModifier += component.PsychicStaminaDamage;
}

public void RollPsionics(EntityUid uid, PotentialPsionicComponent component, bool applyGlimmer = true, float multiplier = 1f)
/// <summary>
/// Makes the entity psionic if it is possible.
/// Ignores rolling and rerolling prevention.
/// </summary>
public bool TryMakePsionic(Entity<PotentialPsionicComponent> ent)
{
if (HasComp<PsionicComponent>(uid))
return;
if (HasComp<PsionicComponent>(ent))
return false;

if (!_cfg.GetCVar(CCVars.PsionicRollsEnabled))
return;
return false;

var warn = CompOrNull<PsionicBonusChanceComponent>(ent)?.Warn ?? true;
_psionicAbilitiesSystem.AddPsionics(ent, warn);
return true;
}

public void RollPsionics(EntityUid uid, PotentialPsionicComponent component, bool applyGlimmer = true, float multiplier = 1f)
{

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)
Expand All @@ -153,7 +163,7 @@ public void RollPsionics(EntityUid uid, PotentialPsionicComponent component, boo
chance = Math.Clamp(chance, 0, 1);

if (_random.Prob(chance))
_psionicAbilitiesSystem.AddPsionics(uid, warn);
TryMakePsionic((uid, component));
}

public void RerollPsionics(EntityUid uid, PotentialPsionicComponent? psionic = null, float bonusMuliplier = 1f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,111 +7,118 @@
using Robust.Shared.Random;
using Robust.Shared.Serialization;

namespace Content.Shared.Abilities.Psionics
namespace Content.Shared.Abilities.Psionics;

public sealed class SharedPsionicAbilitiesSystem : EntitySystem
{
public sealed class SharedPsionicAbilitiesSystem : EntitySystem
[Dependency] private readonly SharedActionsSystem _actions = default!;
[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!;

public override void Initialize()
{
[Dependency] private readonly SharedActionsSystem _actions = default!;
[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!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PsionicsDisabledComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<PsionicsDisabledComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<PsionicComponent, PsionicPowerUsedEvent>(OnPowerUsed);
base.Initialize();
SubscribeLocalEvent<PsionicsDisabledComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<PsionicsDisabledComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<PsionicComponent, PsionicPowerUsedEvent>(OnPowerUsed);

SubscribeLocalEvent<PsionicComponent, MobStateChangedEvent>(OnMobStateChanged);
}
SubscribeLocalEvent<PsionicComponent, MobStateChangedEvent>(OnMobStateChanged);
}

private void OnPowerUsed(EntityUid uid, PsionicComponent component, PsionicPowerUsedEvent args)
private void OnPowerUsed(EntityUid uid, PsionicComponent component, PsionicPowerUsedEvent args)
{
var ev = new PsionicPowerDetectedEvent(uid, args.Power);
var coords = Transform(uid).Coordinates;
foreach (var ent in _lookup.GetEntitiesInRange<MetapsionicPowerComponent>(coords, 10f))
{
foreach (var entity in _lookup.GetEntitiesInRange(uid, 10f))
if (ent.Owner != uid && !(TryComp<PsionicInsulationComponent>(ent, out var insul) && !insul.Passthrough))
{
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;
}
RaiseLocalEvent(ent, ref ev);
_popups.PopupEntity(Loc.GetString("metapsionic-pulse-power", ("power", args.Power)), ent, ent, PopupType.LargeCaution);
args.Handled = true;
}
}
}

private void OnInit(EntityUid uid, PsionicsDisabledComponent component, ComponentInit args)
{
SetPsionicsThroughEligibility(uid);
}
private void OnInit(EntityUid uid, PsionicsDisabledComponent component, ComponentInit args)
{
SetPsionicsThroughEligibility(uid);
}

private void OnShutdown(EntityUid uid, PsionicsDisabledComponent component, ComponentShutdown args)
{
SetPsionicsThroughEligibility(uid);
}
private void OnShutdown(EntityUid uid, PsionicsDisabledComponent component, ComponentShutdown args)
{
SetPsionicsThroughEligibility(uid);
}

private void OnMobStateChanged(EntityUid uid, PsionicComponent component, MobStateChangedEvent args)
{
SetPsionicsThroughEligibility(uid);
}
private void OnMobStateChanged(EntityUid uid, PsionicComponent component, MobStateChangedEvent args)
{
SetPsionicsThroughEligibility(uid);
}

/// <summary>
/// Checks whether the entity is eligible to use its psionic ability. This should be run after anything that could effect psionic eligibility.
/// </summary>
public void SetPsionicsThroughEligibility(EntityUid uid)
{
PsionicComponent? component = null;
if (!Resolve(uid, ref component, false))
return;
/// <summary>
/// Checks whether the entity is eligible to use its psionic ability. This should be run after anything that could effect psionic eligibility.
/// </summary>
public void SetPsionicsThroughEligibility(EntityUid uid)
{
PsionicComponent? component = null;
if (!Resolve(uid, ref component, false))
return;

if (component.PsionicAbility == null)
return;
if (component.PsionicAbility == null)
return;

_actions.TryGetActionData( component.PsionicAbility, out var actionData );
_actions.TryGetActionData( component.PsionicAbility, out var actionData );

if (actionData == null)
return;
if (actionData == null)
return;

_actions.SetEnabled(actionData.Owner, IsEligibleForPsionics(uid));
}
_actions.SetEnabled(actionData.Owner, IsEligibleForPsionics(uid));
}

private bool IsEligibleForPsionics(EntityUid uid)
{
return !HasComp<PsionicInsulationComponent>(uid)
&& (!TryComp<MobStateComponent>(uid, out var mobstate) || mobstate.CurrentState == MobState.Alive);
}
private bool IsEligibleForPsionics(EntityUid uid)
{
return !HasComp<PsionicInsulationComponent>(uid)
&& (!TryComp<MobStateComponent>(uid, out var mobstate) || mobstate.CurrentState == MobState.Alive);
}

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);
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);
}
_glimmerSystem.Glimmer += _robustRandom.Next(minGlimmer, maxGlimmer);
}
}

public sealed class PsionicPowerUsedEvent : HandledEntityEventArgs
{
public EntityUid User { get; }
public string Power = string.Empty;
/// <summary>
/// Event raised on a metapsionic entity when someone used a psionic power nearby.
/// </summary>
[ByRefEvent]
public record struct PsionicPowerDetectedEvent(EntityUid Psionic, string Power);

public PsionicPowerUsedEvent(EntityUid user, string power)
{
User = user;
Power = power;
}
public sealed class PsionicPowerUsedEvent : HandledEntityEventArgs
{
public EntityUid User { get; }
public string Power = string.Empty;

public PsionicPowerUsedEvent(EntityUid user, string power)
{
User = user;
Power = power;
}
}

[Serializable]
[NetSerializable]
public sealed class PsionicsChangedEvent : EntityEventArgs
[Serializable]
[NetSerializable]
public sealed class PsionicsChangedEvent : EntityEventArgs
{
public readonly NetEntity Euid;
public PsionicsChangedEvent(NetEntity euid)
{
public readonly NetEntity Euid;
public PsionicsChangedEvent(NetEntity euid)
{
Euid = euid;
}
Euid = euid;
}
}
Loading

0 comments on commit 845d584

Please sign in to comment.