Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions.Events;
using Content.Shared.Mobs.Components;
using System.Linq;
using System.Numerics;
using Content.Shared.Database;
using Robust.Shared.Collections;

namespace Content.Server.Abilities.Psionics;

public sealed partial class AnomalyPowerSystem
{
/// <summary>
/// This function handles emulating the effects of a "Bluespace Anomaly", using the caster as the "Anomaly",
/// while substituting their Psionic casting stats for "Severity and Stability".
/// Essentially, scramble the location of entities near the caster(possibly to include the caster).
/// </summary>
private void DoBluespaceAnomalyEffects(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args, bool overcharged = false)
{
if (args.Bluespace is null)
return;

if (overcharged)
BluespaceSupercrit(uid, component, args);
else BluespacePulse(uid, component, args);
}

private void BluespaceSupercrit(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
var xform = Transform(uid);
var mapPos = _xform.GetWorldPosition(xform);
var radius = args.Bluespace!.Value.SupercriticalTeleportRadius * component.CurrentAmplification;
var gridBounds = new Box2(mapPos - new Vector2(radius, radius), mapPos + new Vector2(radius, radius));
var mobs = new HashSet<Entity<MobStateComponent>>();
_lookup.GetEntitiesInRange(xform.Coordinates, args.Bluespace!.Value.MaxShuffleRadius, mobs);
foreach (var comp in mobs)
{
if (args.Bluespace!.Value.SupercritTeleportsCaster && comp.Owner == uid)
continue;

var ent = comp.Owner;
var randomX = _random.NextFloat(gridBounds.Left, gridBounds.Right);
var randomY = _random.NextFloat(gridBounds.Bottom, gridBounds.Top);

var pos = new Vector2(randomX, randomY);

_adminLogger.Add(LogType.Teleport, $"{ToPrettyString(ent)} has been teleported to {pos} by the supercritical {ToPrettyString(uid)} at {mapPos}");

_xform.SetWorldPosition(ent, pos);
_audio.PlayPvs(args.Bluespace!.Value.TeleportSound, ent);
}
}

private void BluespacePulse(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
var xformQuery = GetEntityQuery<TransformComponent>();
var xform = xformQuery.GetComponent(uid);
var range = args.Bluespace!.Value.MaxShuffleRadius * component.CurrentAmplification;
var mobs = new HashSet<Entity<MobStateComponent>>();
_lookup.GetEntitiesInRange(xform.Coordinates, range, mobs);
var allEnts = new ValueList<EntityUid>(mobs.Select(m => m.Owner)) { uid };
var coords = new ValueList<Vector2>();
foreach (var ent in allEnts)
{
if (args.Bluespace!.Value.PulseTeleportsCaster && ent == uid
|| !xformQuery.TryGetComponent(ent, out var allXform))
continue;

coords.Add(_xform.GetWorldPosition(allXform));
}

_random.Shuffle(coords);
for (var i = 0; i < allEnts.Count; i++)
{
_adminLogger.Add(LogType.Teleport, $"{ToPrettyString(allEnts[i])} has been shuffled to {coords[i]} by the {ToPrettyString(uid)} at {xform.Coordinates}");
_xform.SetWorldPosition(allEnts[i], coords[i]);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions.Events;

namespace Content.Server.Abilities.Psionics;

public sealed partial class AnomalyPowerSystem
{
/// <summary>
/// This function handles emulating the effects of a "Electrical Anomaly", using the caster as the "Anomaly",
/// while substituting their Psionic casting stats for "Severity and Stability".
/// This fires lightning bolts at random entities near the caster.
/// </summary>
private void DoElectricityAnomalyEffects(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args, bool overcharged = false)
{
if (args.Electricity is null)
return;

if (overcharged)
ElectricitySupercrit(uid, component, args);
else ElectricityPulse(uid, component, args);
}

private void ElectricitySupercrit(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
var range = args.Electricity!.Value.MaxElectrocuteRange * component.CurrentAmplification;

_emp.EmpPulse(_xform.GetMapCoordinates(uid), range, args.Electricity!.Value.EmpEnergyConsumption, args.Electricity!.Value.EmpDisabledDuration);
_lightning.ShootRandomLightnings(uid, range, args.Electricity!.Value.MaxBoltCount * (int) component.CurrentAmplification, arcDepth: (int) component.CurrentDampening);
}

private void ElectricityPulse(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
var range = args.Electricity!.Value.MaxElectrocuteRange * component.CurrentAmplification;

int boltCount = (int) MathF.Floor(MathHelper.Lerp(args.Electricity!.Value.MinBoltCount, args.Electricity!.Value.MaxBoltCount, component.CurrentAmplification));

_lightning.ShootRandomLightnings(uid, range, boltCount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions.Events;
using Content.Shared.Random.Helpers;
using Robust.Shared.Random;
using Content.Shared.Anomaly.Effects.Components;
using Robust.Shared.Map.Components;

namespace Content.Server.Abilities.Psionics;

public sealed partial class AnomalyPowerSystem
{
private const string NoGrid = "entity-anomaly-no-grid";

/// <summary>
/// This function handles emulating the effects of an "Entity Anomaly", using the caster as the "Anomaly",
/// while substituting their Psionic casting stats for "Severity and Stability".
/// Essentially, spawn entities on random tiles in a radius around the caster.
/// </summary>
private void DoEntityAnomalyEffects(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args, bool overcharged = false)
{
if (args.EntitySpawnEntries is null)
return;

if (Transform(uid).GridUid is null)
{
_popup.PopupEntity(Loc.GetString(NoGrid), uid, uid);
return;
}

if (overcharged)
EntitySupercrit(uid, component, args);
else EntityPulse(uid, component, args);
}

private void EntitySupercrit(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
foreach (var entry in args.EntitySpawnEntries!)
{
if (!entry.Settings.SpawnOnSuperCritical)
continue;

SpawnEntities(uid, component, entry);
}
}

private void EntityPulse(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
if (args.EntitySpawnEntries is null)
return;

foreach (var entry in args.EntitySpawnEntries!)
{
if (!entry.Settings.SpawnOnPulse)
continue;

SpawnEntities(uid, component, entry);
}
}

private void SpawnEntities(EntityUid uid, PsionicComponent component, EntitySpawnSettingsEntry entry)
{
if (!TryComp<MapGridComponent>(Transform(uid).GridUid, out var grid))
return;

var tiles = _anomalySystem.GetSpawningPoints(uid,
component.CurrentDampening,
component.CurrentAmplification,
entry.Settings,
_glimmerSystem.Glimmer / 1000,
component.CurrentAmplification,
component.CurrentAmplification);

if (tiles is null)
return;

foreach (var tileref in tiles)
Spawn(_random.Pick(entry.Spawns), _mapSystem.ToCenterCoordinates(tileref, grid));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions.Events;

namespace Content.Server.Abilities.Psionics;

public sealed partial class AnomalyPowerSystem
{
/// <summary>
/// This function handles emulating the effects of a "Explosion Anomaly", using the caster as the "Anomaly",
/// while substituting their Psionic casting stats for "Severity and Stability".
/// Generates an explosion centered on the caster.
/// </summary>
private void DoExplosionAnomalyEffects(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args, bool overcharged = false)
{
if (args.Explosion is null)
return;

if (overcharged)
ExplosionSupercrit(uid, component, args);
else ExplosionPulse(uid, component, args);
}

private void ExplosionSupercrit(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
if (args.Explosion!.Value.SupercritExplosionPrototype is null)
return;

var explosion = args.Explosion!.Value;
_boom.QueueExplosion(
uid,
explosion.SupercritExplosionPrototype,
explosion.SupercritTotalIntensity * component.CurrentAmplification,
explosion.SupercritDropoff / component.CurrentDampening,
explosion.SupercritMaxTileIntensity * component.CurrentDampening
);
}

private void ExplosionPulse(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
if (args.Explosion!.Value.ExplosionPrototype is null)
return;

var explosion = args.Explosion!.Value;
_boom.QueueExplosion(
uid,
explosion.ExplosionPrototype,
explosion.TotalIntensity * component.CurrentAmplification,
explosion.Dropoff / component.CurrentDampening,
explosion.MaxTileIntensity * component.CurrentDampening
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions.Events;
using Robust.Shared.Map.Components;
using System.Linq;
using System.Numerics;

namespace Content.Server.Abilities.Psionics;

public sealed partial class AnomalyPowerSystem
{
private void DoGasProducerAnomalyEffects(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args, bool overcharged = false)
{
if (args.Gas is not null)
return;

if (overcharged)
GasProducerSupercrit(uid, component, args);
else GasProducerPulse(uid, component, args);
}

private void GasProducerSupercrit(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
var xform = Transform(uid);
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
return;

var gas = args.Gas!.Value.SupercritReleasedGas;
var mols = args.Gas!.Value.SupercritMoleAmount * component.CurrentAmplification;
var radius = args.Gas!.Value.SupercritSpawnRadius * component.CurrentAmplification;
var count = args.Gas!.Value.SupercritTileCount * component.CurrentDampening;
var temp = args.Gas!.Value.SupercritTempChange * component.CurrentDampening;
var localpos = xform.Coordinates.Position;
var tilerefs = grid.GetLocalTilesIntersecting(
new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))).ToArray();

if (tilerefs.Length == 0)
return;

var mixture = _atmosphere.GetTileMixture((uid, xform), true);
if (mixture != null)
{
mixture.AdjustMoles(gas, mols);
mixture.Temperature += temp;
}

if (count == 0)
return;

_random.Shuffle(tilerefs);
var amountCounter = 0;
foreach (var tileref in tilerefs)
{
var mix = _atmosphere.GetTileMixture(xform.GridUid, xform.MapUid, tileref.GridIndices, true);
amountCounter++;
if (mix is not { })
continue;

mix.AdjustMoles(gas, mols);
mix.Temperature += temp;

if (amountCounter >= count)
return;
}
}

private void GasProducerPulse(EntityUid uid, PsionicComponent component, AnomalyPowerActionEvent args)
{
var xform = Transform(uid);
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
return;

var gas = args.Gas!.Value.ReleasedGas;
var mols = args.Gas!.Value.MoleAmount * component.CurrentAmplification;
var radius = args.Gas!.Value.SpawnRadius * component.CurrentAmplification;
var count = args.Gas!.Value.TileCount * component.CurrentDampening;
var temp = args.Gas!.Value.TempChange * component.CurrentDampening;
var localpos = xform.Coordinates.Position;
var tilerefs = grid.GetLocalTilesIntersecting(
new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))).ToArray();

if (tilerefs.Length == 0)
return;

var mixture = _atmosphere.GetTileMixture((uid, xform), true);
if (mixture != null)
{
mixture.AdjustMoles(gas, mols);
mixture.Temperature += temp;
}

if (count == 0)
return;

_random.Shuffle(tilerefs);
var amountCounter = 0;
foreach (var tileref in tilerefs)
{
var mix = _atmosphere.GetTileMixture(xform.GridUid, xform.MapUid, tileref.GridIndices, true);
amountCounter++;
if (mix is not { })
continue;

mix.AdjustMoles(gas, mols);
mix.Temperature += temp;

if (amountCounter >= count)
return;
}
}
}
Loading