-
Notifications
You must be signed in to change notification settings - Fork 136
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Description This PR extends the system originally created for Shadeskip, into a system that allows any (currently existing) anomaly effect to be replicated as an Instant Action psionic power. This will be needed for Wizard/Rogue Psion antagonists. I'll be making a metric shitton of new powers using this in separate PRs. This is extremely blatantly re-using code as-is from the various Anomaly Systems, because it unfortunately turns out that it's simply not possible to build a constructor to interface between Psionics and Anomalies. # Changelog No changelog because this isn't player facing. --------- Signed-off-by: VMSolidus <evilexecutive@gmail.com>
- Loading branch information
Showing
13 changed files
with
973 additions
and
102 deletions.
There are no files selected for viewing
79 changes: 79 additions & 0 deletions
79
Content.Server/Abilities/Psionics/Abilities/AnomalyPowerSystem.Bluespace.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]); | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
Content.Server/Abilities/Psionics/Abilities/AnomalyPowerSystem.Electricity.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
Content.Server/Abilities/Psionics/Abilities/AnomalyPowerSystem.EntitySpawn.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
Content.Server/Abilities/Psionics/Abilities/AnomalyPowerSystem.Explosion.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
); | ||
} | ||
} |
110 changes: 110 additions & 0 deletions
110
Content.Server/Abilities/Psionics/Abilities/AnomalyPowerSystem.GasProducer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
Oops, something went wrong.