Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions Content.Server/_DEN/Glimmer/Commands/GlimmerCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using Content.Server._DEN.Glimmer.EntitySystems;
using Content.Server.Administration;
using Content.Shared._DEN.Glimmer.Components;
using Content.Shared.Administration;
using Content.Shared.FixedPoint;
using Robust.Shared.Toolshed;

namespace Content.Server._DEN.Glimmer.Commands;

[ToolshedCommand, AdminCommand(AdminFlags.VarEdit)]
public sealed partial class GlimmerCommand : ToolshedCommand
{
private GlimmerTrackerSystem? _glimmerTracker;

[CommandImplementation("getTracker")]
public Entity<GlimmerTrackerComponent>? GetTracker([PipedArgument] EntityUid @target)
{
_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();

if (_glimmerTracker.TryGetClosestGlimmerTracker(@target, out var tracker))
return tracker;

return null;
}

[CommandImplementation("getTracker")]
public Entity<GlimmerTrackerComponent>? GetTracker(IInvocationContext ctx)
{
_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();

if (ctx.Session?.AttachedEntity is not { } entity)
return null;

if (_glimmerTracker.TryGetClosestGlimmerTracker(entity, out var tracker))
return tracker;

return null;
}

[CommandImplementation("getValue")]
public FixedPoint2? GetValue([PipedArgument] Entity<GlimmerTrackerComponent> @tracker)
{
_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();
return _glimmerTracker.GetCurrentGlimmer(@tracker);
}

[CommandImplementation("getValue")]
public FixedPoint2? GetValue([PipedArgument] Entity<GlimmerTrackerComponent>? @tracker)
{
if (@tracker == null)
return FixedPoint2.Zero;

_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();
return _glimmerTracker.GetCurrentGlimmer(@tracker.Value);
}

[CommandImplementation("getLevel")]
public int? GetLevel([PipedArgument] Entity<GlimmerTrackerComponent> @tracker)
{
_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();
return _glimmerTracker.GetCurrentGlimmerLevel(@tracker);
}

[CommandImplementation("getLevel")]
public int? GetLevel([PipedArgument] Entity<GlimmerTrackerComponent>? @tracker)
{
if (@tracker == null)
return 0;

_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();
return _glimmerTracker.GetCurrentGlimmerLevel(@tracker.Value);
}

[CommandImplementation("setValue")]
public Entity<GlimmerTrackerComponent> SetValue([PipedArgument] Entity<GlimmerTrackerComponent> @tracker, FixedPoint2 value)
{
_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();
_glimmerTracker.SetGlimmer(@tracker, value);

return @tracker;
}

[CommandImplementation("setValue")]
public Entity<GlimmerTrackerComponent>? SetValue([PipedArgument] Entity<GlimmerTrackerComponent>? @tracker, FixedPoint2 value)
{
if (@tracker == null)
return @tracker;

_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();
_glimmerTracker.SetGlimmer(@tracker.Value, value);

return @tracker;
}

[CommandImplementation("setLevel")]
public Entity<GlimmerTrackerComponent> SetLevel([PipedArgument] Entity<GlimmerTrackerComponent> @tracker, int level)
{
_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();
_glimmerTracker.SetGlimmerLevel(@tracker, level);

return @tracker;
}

[CommandImplementation("setLevel")]
public Entity<GlimmerTrackerComponent>? SetLevel([PipedArgument] Entity<GlimmerTrackerComponent>? @tracker, int level)
{
if (@tracker == null)
return @tracker;

_glimmerTracker ??= GetSys<GlimmerTrackerSystem>();
_glimmerTracker.SetGlimmerLevel(@tracker.Value, level);

return @tracker;
}
}
194 changes: 194 additions & 0 deletions Content.Server/_DEN/Glimmer/EntitySystems/GlimmerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Station.Systems;
using Content.Shared._DEN.Glimmer.Components;
using Content.Shared._DEN.Glimmer.EntitySystems;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
using Robust.Shared.Random;

namespace Content.Server._DEN.Glimmer.EntitySystems;

/// <summary>
/// Glimmer is a measure of "noospheric instability", a value that affects both the frequency
/// and severity of paranormal-themed events. It also affects the level of connection that
/// psionic users have with the noosphere - this is to say, powers scaling with glimmer.
/// </summary>
public sealed partial class GlimmerTrackerSystem : SharedGlimmerTrackerSystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly StationSystem _station = default!;

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

SubscribeLocalEvent<GlimmerTrackerComponent, ComponentStartup>(OnGlimmerTrackerStartup);
}

/// <summary>
///
/// </summary>
/// <param name="ent"></param>
/// <param name="args"></param>
private void OnGlimmerTrackerStartup(Entity<GlimmerTrackerComponent> ent, ref ComponentStartup args)
{
var comp = ent.Comp;
var min = comp.StartingGlimmerLevelRange.X;
var max = comp.StartingGlimmerLevelRange.Y;
var level = _random.Next(min, max);

SetGlimmerLevel(ent, level);
}

/// <summary>
/// Attempt to get the closest applicable glimmer tracker for a given entity.
/// </summary>
/// <remarks>
/// The entity itself will be checked if it is a glimmer tracker, then the entity's station,
/// then all trackers will be iterated over to find the closest applicable tracker.
/// </remarks>
/// <param name="uid">The entity to retrieve the nearest valid glimmer tracker for.</param>
/// <param name="trackerEnt">A glimmer tracker that applies to this entity.</param>
/// <returns>Whether or not we successfully retrieved a glimmer tracker.</returns>
[PublicAPI]
public bool TryGetClosestGlimmerTracker(EntityUid uid,
[NotNullWhen(true)] out Entity<GlimmerTrackerComponent>? trackerEnt)
{
// This entity is a glimmer tracker
if (TryComp<GlimmerTrackerComponent>(uid, out var tracker))
{
trackerEnt = (uid, tracker);
return true;
}

// This is a station map and the station has a glimmer tracker
var xform = Transform(uid);
if (_station.GetStationInMap(xform.MapID) is EntityUid station
&& TryComp(station, out tracker))
{
trackerEnt = (station, tracker);
return true;
}

// We get the closest glimmer tracker in the same map
var query = EntityQueryEnumerator<GlimmerTrackerComponent>();
(Entity<GlimmerTrackerComponent> Tracker, float Distance)? closestTracker = null;
while (query.MoveNext(out var trackerUid, out tracker))
{
var ent = (trackerUid, tracker);
var trackerXform = Transform(trackerUid);

if (xform.Coordinates.TryDistance(EntityManager, trackerXform.Coordinates, out var distance)
&& distance > closestTracker?.Distance)
closestTracker = (ent, distance);

// Global trackers do not need to be in the same map to be detected
else if (tracker.Global)
closestTracker ??= (ent, float.MaxValue);
}

// May still be null, if there are no trackers at all
trackerEnt = closestTracker?.Tracker;
return trackerEnt != null;
}

/// <summary>
///
/// </summary>
/// <param name="tracker"></param>
/// <param name="glimmer"></param>
[PublicAPI]
public void SetGlimmer(Entity<GlimmerTrackerComponent> tracker, FixedPoint2 glimmer)
{
var comp = tracker.Comp;
var maxGlimmer = comp.GlimmerLevels * comp.GlimmerPerLevel;

if (glimmer < FixedPoint2.Zero || glimmer > maxGlimmer)
throw new ArgumentOutOfRangeException(nameof(glimmer));

comp.CurrentGlimmer = glimmer;

// We're adding 1 to this, so that 0 glimmer becomes level 1.
var glimmerDivisor = (glimmer + 1) / comp.GlimmerPerLevel;
var glimmerLevel = Math.Floor(glimmerDivisor.Float());
comp.CurrentGlimmerLevel = (int)glimmerLevel;
}

/// <summary>
///
/// </summary>
/// <param name="tracker"></param>
/// <param name="level"></param>
[PublicAPI]
public void SetGlimmerLevel(Entity<GlimmerTrackerComponent> tracker, int level)
{
var comp = tracker.Comp;

if (level < 0 || level > comp.GlimmerLevels)
throw new ArgumentOutOfRangeException(nameof(level));

comp.CurrentGlimmerLevel = level;

// The highest glimmer level always represents the highest possible glimmer value.
if (level == comp.GlimmerLevels)
{
comp.CurrentGlimmer = level * comp.GlimmerPerLevel;
return;
}

var min = (level - 1) * comp.GlimmerPerLevel; // INCLUSIVE
var max = level * comp.GlimmerPerLevel; // EXCLUSIVE
var newGlimmer = _random.NextFloat(min.Float(), max.Float());
comp.CurrentGlimmer = FixedPoint2.New(newGlimmer);
}

/// <summary>
///
/// </summary>
/// <param name="tracker"></param>
/// <returns></returns>
[PublicAPI]
public FixedPoint2 GetCurrentGlimmer(Entity<GlimmerTrackerComponent> tracker)
{
return tracker.Comp.CurrentGlimmer;
}

/// <summary>
///
/// </summary>
/// <param name="uid"></param>
/// <returns></returns>
[PublicAPI]
public FixedPoint2 GetCurrentGlimmer(EntityUid uid)
{
if (!TryGetClosestGlimmerTracker(uid, out var tracker))
return FixedPoint2.Zero;

return GetCurrentGlimmer(tracker.Value);
}

/// <summary>
///
/// </summary>
/// <param name="tracker"></param>
/// <returns></returns>
[PublicAPI]
public int GetCurrentGlimmerLevel(Entity<GlimmerTrackerComponent> tracker)
{
return tracker.Comp.CurrentGlimmerLevel;
}

/// <summary>
///
/// </summary>
/// <param name="uid"></param>
/// <returns></returns>
[PublicAPI]
public int GetCurrentGlimmerLevel(EntityUid uid)
{
if (!TryGetClosestGlimmerTracker(uid, out var tracker))
return 0;

return GetCurrentGlimmerLevel(tracker.Value);
}
}
Loading
Loading