Anomalies behaviours (#24683)

* Added new anomaly particle

* Add basic anomaly behaviour

* +2 parametres

* add functional to new particle

* add components to behaviours

* big content

* add shuffle, moved thing to server

* clean up

* fixes

* random pick redo

* bonjour behavioUr

* fix AJCM

* fix

* add some new behaviours

* power modifier behaviour

* rmeove timer

* new event for update ui fix

* refactor!

* fixes

* enum

* Fix mapinit

* Minor touches

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
Ed
2024-04-01 11:29:13 +03:00
committed by GitHub
parent de8b788856
commit a4ec01d471
29 changed files with 832 additions and 91 deletions

View File

@@ -1,9 +1,9 @@
<controls:FancyWindow <controls:FancyWindow
xmlns="https://spacestation14.io" xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'anomaly-scanner-ui-title'}" Title="{Loc 'anomaly-scanner-ui-title'}"
MinSize="350 260" MinSize="350 400"
SetSize="350 260"> SetSize="350 400">
<BoxContainer Orientation="Vertical" VerticalExpand="True" Margin="10 0 10 10"> <BoxContainer Orientation="Vertical" VerticalExpand="True" Margin="10 0 10 10">
<RichTextLabel Name="TextDisplay"></RichTextLabel> <RichTextLabel Name="TextDisplay"></RichTextLabel>
</BoxContainer> </BoxContainer>

View File

@@ -1,4 +1,4 @@
using Content.Server.Anomaly.Components; using Content.Server.Anomaly.Components;
using Content.Shared.Anomaly; using Content.Shared.Anomaly;
using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Components;
using Content.Shared.DoAfter; using Content.Shared.DoAfter;
@@ -21,6 +21,7 @@ public sealed partial class AnomalySystem
SubscribeLocalEvent<AnomalySeverityChangedEvent>(OnScannerAnomalySeverityChanged); SubscribeLocalEvent<AnomalySeverityChangedEvent>(OnScannerAnomalySeverityChanged);
SubscribeLocalEvent<AnomalyHealthChangedEvent>(OnScannerAnomalyHealthChanged); SubscribeLocalEvent<AnomalyHealthChangedEvent>(OnScannerAnomalyHealthChanged);
SubscribeLocalEvent<AnomalyBehaviorChangedEvent>(OnScannerAnomalyBehaviorChanged);
} }
private void OnScannerAnomalyShutdown(ref AnomalyShutdownEvent args) private void OnScannerAnomalyShutdown(ref AnomalyShutdownEvent args)
@@ -67,6 +68,17 @@ public sealed partial class AnomalySystem
} }
} }
private void OnScannerAnomalyBehaviorChanged(ref AnomalyBehaviorChangedEvent args)
{
var query = EntityQueryEnumerator<AnomalyScannerComponent>();
while (query.MoveNext(out var uid, out var component))
{
if (component.ScannedAnomaly != args.Anomaly)
continue;
UpdateScannerUi(uid, component);
}
}
private void OnScannerUiOpened(EntityUid uid, AnomalyScannerComponent component, BoundUIOpenedEvent args) private void OnScannerUiOpened(EntityUid uid, AnomalyScannerComponent component, BoundUIOpenedEvent args)
{ {
UpdateScannerUi(uid, component); UpdateScannerUi(uid, component);
@@ -132,29 +144,95 @@ public sealed partial class AnomalySystem
return msg; return msg;
} }
msg.AddMarkup(Loc.GetString("anomaly-scanner-severity-percentage", ("percent", anomalyComp.Severity.ToString("P")))); TryComp<SecretDataAnomalyComponent>(anomaly, out var secret);
msg.PushNewline();
string stateLoc; //Severity
if (anomalyComp.Stability < anomalyComp.DecayThreshold) if (secret != null && secret.Secret.Contains(AnomalySecretData.Severity))
stateLoc = Loc.GetString("anomaly-scanner-stability-low"); msg.AddMarkup(Loc.GetString("anomaly-scanner-severity-percentage-unknown"));
else if (anomalyComp.Stability > anomalyComp.GrowthThreshold)
stateLoc = Loc.GetString("anomaly-scanner-stability-high");
else else
stateLoc = Loc.GetString("anomaly-scanner-stability-medium"); msg.AddMarkup(Loc.GetString("anomaly-scanner-severity-percentage", ("percent", anomalyComp.Severity.ToString("P"))));
msg.AddMarkup(stateLoc);
msg.PushNewline(); msg.PushNewline();
msg.AddMarkup(Loc.GetString("anomaly-scanner-point-output", ("point", GetAnomalyPointValue(anomaly, anomalyComp)))); //Stability
if (secret != null && secret.Secret.Contains(AnomalySecretData.Stability))
msg.AddMarkup(Loc.GetString("anomaly-scanner-stability-unknown"));
else
{
string stateLoc;
if (anomalyComp.Stability < anomalyComp.DecayThreshold)
stateLoc = Loc.GetString("anomaly-scanner-stability-low");
else if (anomalyComp.Stability > anomalyComp.GrowthThreshold)
stateLoc = Loc.GetString("anomaly-scanner-stability-high");
else
stateLoc = Loc.GetString("anomaly-scanner-stability-medium");
msg.AddMarkup(stateLoc);
}
msg.PushNewline();
//Point output
if (secret != null && secret.Secret.Contains(AnomalySecretData.OutputPoint))
msg.AddMarkup(Loc.GetString("anomaly-scanner-point-output-unknown"));
else
msg.AddMarkup(Loc.GetString("anomaly-scanner-point-output", ("point", GetAnomalyPointValue(anomaly, anomalyComp))));
msg.PushNewline(); msg.PushNewline();
msg.PushNewline(); msg.PushNewline();
//Particles title
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-readout")); msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-readout"));
msg.PushNewline(); msg.PushNewline();
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-danger", ("type", GetParticleLocale(anomalyComp.SeverityParticleType))));
//Danger
if (secret != null && secret.Secret.Contains(AnomalySecretData.ParticleDanger))
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-danger-unknown"));
else
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-danger", ("type", GetParticleLocale(anomalyComp.SeverityParticleType))));
msg.PushNewline(); msg.PushNewline();
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-unstable", ("type", GetParticleLocale(anomalyComp.DestabilizingParticleType))));
//Unstable
if (secret != null && secret.Secret.Contains(AnomalySecretData.ParticleUnstable))
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-unstable-unknown"));
else
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-unstable", ("type", GetParticleLocale(anomalyComp.DestabilizingParticleType))));
msg.PushNewline(); msg.PushNewline();
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-containment", ("type", GetParticleLocale(anomalyComp.WeakeningParticleType))));
//Containment
if (secret != null && secret.Secret.Contains(AnomalySecretData.ParticleContainment))
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-containment-unknown"));
else
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-containment", ("type", GetParticleLocale(anomalyComp.WeakeningParticleType))));
msg.PushNewline();
//Transformation
if (secret != null && secret.Secret.Contains(AnomalySecretData.ParticleTransformation))
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-transformation-unknown"));
else
msg.AddMarkup(Loc.GetString("anomaly-scanner-particle-transformation", ("type", GetParticleLocale(anomalyComp.TransformationParticleType))));
//Behavior
msg.PushNewline();
msg.PushNewline();
msg.AddMarkup(Loc.GetString("anomaly-behavior-title"));
msg.PushNewline();
if (secret != null && secret.Secret.Contains(AnomalySecretData.Behavior))
msg.AddMarkup(Loc.GetString("anomaly-behavior-unknown"));
else
{
if (anomalyComp.CurrentBehavior != null)
{
var behavior = _prototype.Index(anomalyComp.CurrentBehavior.Value);
msg.AddMarkup("- " + Loc.GetString(behavior.Description));
msg.PushNewline();
var mod = Math.Floor((behavior.EarnPointModifier) * 100);
msg.AddMarkup("- " + Loc.GetString("anomaly-behavior-point", ("mod", mod)));
}
else
{
msg.AddMarkup(Loc.GetString("anomaly-behavior-balanced"));
}
}
//The timer at the end here is actually added in the ui itself. //The timer at the end here is actually added in the ui itself.
return msg; return msg;

View File

@@ -8,13 +8,18 @@ using Content.Server.Radio.EntitySystems;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Shared.Anomaly; using Content.Shared.Anomaly;
using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Components;
using Content.Shared.Anomaly.Prototypes;
using Content.Shared.DoAfter; using Content.Shared.DoAfter;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Events;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager;
using System.Linq;
namespace Content.Server.Anomaly; namespace Content.Server.Anomaly;
@@ -33,13 +38,20 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
[Dependency] private readonly SharedPointLightSystem _pointLight = default!; [Dependency] private readonly SharedPointLightSystem _pointLight = default!;
[Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly RadioSystem _radio = default!; [Dependency] private readonly RadioSystem _radio = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly RadiationSystem _radiation = default!; [Dependency] private readonly RadiationSystem _radiation = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly IComponentFactory _componentFactory = default!;
[Dependency] private readonly ISerializationManager _serialization = default!;
[Dependency] private readonly IEntityManager _entity = default!;
public const float MinParticleVariation = 0.8f; public const float MinParticleVariation = 0.8f;
public const float MaxParticleVariation = 1.2f; public const float MaxParticleVariation = 1.2f;
[ValidatePrototypeId<WeightedRandomPrototype>]
const string WeightListProto = "AnomalyBehaviorList";
/// <inheritdoc/> /// <inheritdoc/>
public override void Initialize() public override void Initialize()
{ {
@@ -54,25 +66,34 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
InitializeCommands(); InitializeCommands();
} }
private void OnMapInit(EntityUid uid, AnomalyComponent component, MapInitEvent args) private void OnMapInit(Entity<AnomalyComponent> anomaly, ref MapInitEvent args)
{ {
component.NextPulseTime = Timing.CurTime + GetPulseLength(component) * 3; // longer the first time anomaly.Comp.NextPulseTime = Timing.CurTime + GetPulseLength(anomaly.Comp) * 3; // longer the first time
ChangeAnomalyStability(uid, Random.NextFloat(component.InitialStabilityRange.Item1 , component.InitialStabilityRange.Item2), component); ChangeAnomalyStability(anomaly, Random.NextFloat(anomaly.Comp.InitialStabilityRange.Item1 , anomaly.Comp.InitialStabilityRange.Item2), anomaly.Comp);
ChangeAnomalySeverity(uid, Random.NextFloat(component.InitialSeverityRange.Item1, component.InitialSeverityRange.Item2), component); ChangeAnomalySeverity(anomaly, Random.NextFloat(anomaly.Comp.InitialSeverityRange.Item1, anomaly.Comp.InitialSeverityRange.Item2), anomaly.Comp);
ShuffleParticlesEffect(anomaly.Comp);
anomaly.Comp.Continuity = _random.NextFloat(anomaly.Comp.MinContituty, anomaly.Comp.MaxContituty);
SetBehavior(anomaly, GetRandomBehavior());
}
public void ShuffleParticlesEffect(AnomalyComponent anomaly)
{
var particles = new List<AnomalousParticleType> var particles = new List<AnomalousParticleType>
{ AnomalousParticleType.Delta, AnomalousParticleType.Epsilon, AnomalousParticleType.Zeta }; { AnomalousParticleType.Delta, AnomalousParticleType.Epsilon, AnomalousParticleType.Zeta, AnomalousParticleType.Sigma };
component.SeverityParticleType = Random.PickAndTake(particles);
component.DestabilizingParticleType = Random.PickAndTake(particles); anomaly.SeverityParticleType = Random.PickAndTake(particles);
component.WeakeningParticleType = Random.PickAndTake(particles); anomaly.DestabilizingParticleType = Random.PickAndTake(particles);
anomaly.WeakeningParticleType = Random.PickAndTake(particles);
anomaly.TransformationParticleType = Random.PickAndTake(particles);
} }
private void OnShutdown(EntityUid uid, AnomalyComponent component, ComponentShutdown args) private void OnShutdown(Entity<AnomalyComponent> anomaly, ref ComponentShutdown args)
{ {
EndAnomaly(uid, component); EndAnomaly(anomaly);
} }
private void OnStartCollide(EntityUid uid, AnomalyComponent component, ref StartCollideEvent args) private void OnStartCollide(Entity<AnomalyComponent> anomaly, ref StartCollideEvent args)
{ {
if (!TryComp<AnomalousParticleComponent>(args.OtherEntity, out var particle)) if (!TryComp<AnomalousParticleComponent>(args.OtherEntity, out var particle))
return; return;
@@ -80,21 +101,33 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
if (args.OtherFixtureId != particle.FixtureId) if (args.OtherFixtureId != particle.FixtureId)
return; return;
var behaviorMod = 1f;
if (anomaly.Comp.CurrentBehavior != null)
{
var b = _prototype.Index(anomaly.Comp.CurrentBehavior.Value);
behaviorMod = b.ParticleSensivity;
}
// small function to randomize because it's easier to read like this // small function to randomize because it's easier to read like this
float VaryValue(float v) => v * Random.NextFloat(MinParticleVariation, MaxParticleVariation); float VaryValue(float v) => v * behaviorMod * Random.NextFloat(MinParticleVariation, MaxParticleVariation);
if (particle.ParticleType == component.DestabilizingParticleType || particle.DestabilzingOverride) if (particle.ParticleType == anomaly.Comp.DestabilizingParticleType || particle.DestabilzingOverride)
{ {
ChangeAnomalyStability(uid, VaryValue(particle.StabilityPerDestabilizingHit), component); ChangeAnomalyStability(anomaly, VaryValue(particle.StabilityPerDestabilizingHit), anomaly.Comp);
} }
if (particle.ParticleType == component.SeverityParticleType || particle.SeverityOverride) if (particle.ParticleType == anomaly.Comp.SeverityParticleType || particle.SeverityOverride)
{ {
ChangeAnomalySeverity(uid, VaryValue(particle.SeverityPerSeverityHit), component); ChangeAnomalySeverity(anomaly, VaryValue(particle.SeverityPerSeverityHit), anomaly.Comp);
} }
if (particle.ParticleType == component.WeakeningParticleType || particle.WeakeningOverride) if (particle.ParticleType == anomaly.Comp.WeakeningParticleType || particle.WeakeningOverride)
{ {
ChangeAnomalyHealth(uid, VaryValue(particle.HealthPerWeakeningeHit), component); ChangeAnomalyHealth(anomaly, VaryValue(particle.HealthPerWeakeningeHit), anomaly.Comp);
ChangeAnomalyStability(uid, VaryValue(particle.StabilityPerWeakeningeHit), component); ChangeAnomalyStability(anomaly, VaryValue(particle.StabilityPerWeakeningeHit), anomaly.Comp);
}
if (particle.ParticleType == anomaly.Comp.TransformationParticleType || particle.TransmutationOverride)
{
ChangeAnomalySeverity(anomaly, VaryValue(particle.SeverityPerSeverityHit), anomaly.Comp);
if (_random.Prob(anomaly.Comp.Continuity))
SetBehavior(anomaly, GetRandomBehavior());
} }
} }
@@ -116,6 +149,13 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
//penalty of up to 50% based on health //penalty of up to 50% based on health
multiplier *= MathF.Pow(1.5f, component.Health) - 0.5f; multiplier *= MathF.Pow(1.5f, component.Health) - 0.5f;
//Apply behavior modifier
if (component.CurrentBehavior != null)
{
var behavior = _prototype.Index(component.CurrentBehavior.Value);
multiplier *= behavior.EarnPointModifier;
}
var severityValue = 1 / (1 + MathF.Pow(MathF.E, -7 * (component.Severity - 0.5f))); var severityValue = 1 / (1 + MathF.Pow(MathF.E, -7 * (component.Severity - 0.5f)));
return (int) ((component.MaxPointsPerSecond - component.MinPointsPerSecond) * severityValue * multiplier) + component.MinPointsPerSecond; return (int) ((component.MaxPointsPerSecond - component.MinPointsPerSecond) * severityValue * multiplier) + component.MinPointsPerSecond;
@@ -133,6 +173,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
AnomalousParticleType.Delta => Loc.GetString("anomaly-particles-delta"), AnomalousParticleType.Delta => Loc.GetString("anomaly-particles-delta"),
AnomalousParticleType.Epsilon => Loc.GetString("anomaly-particles-epsilon"), AnomalousParticleType.Epsilon => Loc.GetString("anomaly-particles-epsilon"),
AnomalousParticleType.Zeta => Loc.GetString("anomaly-particles-zeta"), AnomalousParticleType.Zeta => Loc.GetString("anomaly-particles-zeta"),
AnomalousParticleType.Sigma => Loc.GetString("anomaly-particles-sigma"),
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };
} }
@@ -144,4 +185,40 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
UpdateGenerator(); UpdateGenerator();
UpdateVessels(); UpdateVessels();
} }
#region Behavior
private string GetRandomBehavior()
{
var weightList = _prototype.Index<WeightedRandomPrototype>(WeightListProto);
return weightList.Pick(_random);
}
private void SetBehavior(Entity<AnomalyComponent> anomaly, ProtoId<AnomalyBehaviorPrototype> behaviorProto)
{
if (anomaly.Comp.CurrentBehavior == behaviorProto)
return;
if (anomaly.Comp.CurrentBehavior != null)
RemoveBehavior(anomaly, anomaly.Comp.CurrentBehavior.Value);
//event broadcast
var ev = new AnomalyBehaviorChangedEvent(anomaly, anomaly.Comp.CurrentBehavior, behaviorProto);
anomaly.Comp.CurrentBehavior = behaviorProto;
RaiseLocalEvent(anomaly, ref ev, true);
var behavior = _prototype.Index(behaviorProto);
EntityManager.AddComponents(anomaly, behavior.Components);
}
private void RemoveBehavior(Entity<AnomalyComponent> anomaly, ProtoId<AnomalyBehaviorPrototype> behaviorProto)
{
if (anomaly.Comp.CurrentBehavior == null)
return;
var behavior = _prototype.Index(anomaly.Comp.CurrentBehavior.Value);
EntityManager.RemoveComponents(anomaly, behavior.Components);
}
#endregion
} }

View File

@@ -13,58 +13,64 @@ public sealed partial class AnomalousParticleComponent : Component
/// The type of particle that the projectile /// The type of particle that the projectile
/// imbues onto the anomaly on contact. /// imbues onto the anomaly on contact.
/// </summary> /// </summary>
[DataField("particleType", required: true)] [DataField(required: true)]
public AnomalousParticleType ParticleType; public AnomalousParticleType ParticleType;
/// <summary> /// <summary>
/// The fixture that's checked on collision. /// The fixture that's checked on collision.
/// </summary> /// </summary>
[DataField("fixtureId")] [DataField]
public string FixtureId = "projectile"; public string FixtureId = "projectile";
/// <summary> /// <summary>
/// The amount that the <see cref="AnomalyComponent.Severity"/> increases by when hit /// The amount that the <see cref="AnomalyComponent.Severity"/> increases by when hit
/// of an anomalous particle of <seealso cref="AnomalyComponent.SeverityParticleType"/>. /// of an anomalous particle of <seealso cref="AnomalyComponent.SeverityParticleType"/>.
/// </summary> /// </summary>
[DataField("severityPerSeverityHit")] [DataField]
public float SeverityPerSeverityHit = 0.025f; public float SeverityPerSeverityHit = 0.025f;
/// <summary> /// <summary>
/// The amount that the <see cref="AnomalyComponent.Stability"/> increases by when hit /// The amount that the <see cref="AnomalyComponent.Stability"/> increases by when hit
/// of an anomalous particle of <seealso cref="AnomalyComponent.DestabilizingParticleType"/>. /// of an anomalous particle of <seealso cref="AnomalyComponent.DestabilizingParticleType"/>.
/// </summary> /// </summary>
[DataField("stabilityPerDestabilizingHit")] [DataField]
public float StabilityPerDestabilizingHit = 0.04f; public float StabilityPerDestabilizingHit = 0.04f;
/// <summary> /// <summary>
/// The amount that the <see cref="AnomalyComponent.Stability"/> increases by when hit /// The amount that the <see cref="AnomalyComponent.Stability"/> increases by when hit
/// of an anomalous particle of <seealso cref="AnomalyComponent.DestabilizingParticleType"/>. /// of an anomalous particle of <seealso cref="AnomalyComponent.DestabilizingParticleType"/>.
/// </summary> /// </summary>
[DataField("healthPerWeakeningeHit")] [DataField]
public float HealthPerWeakeningeHit = -0.05f; public float HealthPerWeakeningeHit = -0.05f;
/// <summary> /// <summary>
/// The amount that the <see cref="AnomalyComponent.Stability"/> increases by when hit /// The amount that the <see cref="AnomalyComponent.Stability"/> increases by when hit
/// of an anomalous particle of <seealso cref="AnomalyComponent.DestabilizingParticleType"/>. /// of an anomalous particle of <seealso cref="AnomalyComponent.DestabilizingParticleType"/>.
/// </summary> /// </summary>
[DataField("stabilityPerWeakeningeHit")] [DataField]
public float StabilityPerWeakeningeHit = -0.1f; public float StabilityPerWeakeningeHit = -0.1f;
/// <summary> /// <summary>
/// If this is true then the particle will always affect the stability of the anomaly. /// If this is true then the particle will always affect the stability of the anomaly.
/// </summary> /// </summary>
[DataField("destabilzingOverride")] [DataField]
public bool DestabilzingOverride = false; public bool DestabilzingOverride = false;
/// <summary> /// <summary>
/// If this is true then the particle will always affect the weakeness of the anomaly. /// If this is true then the particle will always affect the weakeness of the anomaly.
/// </summary> /// </summary>
[DataField("weakeningOverride")] [DataField]
public bool WeakeningOverride = false; public bool WeakeningOverride = false;
/// <summary> /// <summary>
/// If this is true then the particle will always affect the severity of the anomaly. /// If this is true then the particle will always affect the severity of the anomaly.
/// </summary> /// </summary>
[DataField("severityOverride")] [DataField]
public bool SeverityOverride = false; public bool SeverityOverride = false;
/// <summary>
/// If this is true then the particle will always affect the behaviour.
/// </summary>
[DataField]
public bool TransmutationOverride = false;
} }

View File

@@ -0,0 +1,45 @@
using Content.Server.Anomaly.Effects;
namespace Content.Server.Anomaly.Components;
/// <summary>
/// Hides some information about the anomaly when scanning it
/// </summary>
[RegisterComponent, Access(typeof(SecretDataAnomalySystem), typeof(AnomalySystem))]
public sealed partial class SecretDataAnomalyComponent : Component
{
/// <summary>
/// Minimum hidden data elements on MapInit
/// </summary>
[DataField]
public int RandomStartSecretMin = 0;
/// <summary>
/// Maximum hidden data elements on MapInit
/// </summary>
[DataField]
public int RandomStartSecretMax = 0;
/// <summary>
/// Current secret data
/// </summary>
[DataField]
public List<AnomalySecretData> Secret = new();
}
/// <summary>
/// Enum with secret data field variants
/// </summary>
[Serializable]
public enum AnomalySecretData : byte
{
Severity,
Stability,
OutputPoint,
ParticleDanger,
ParticleUnstable,
ParticleContainment,
ParticleTransformation,
Behavior,
Default
}

View File

@@ -0,0 +1,28 @@
using Content.Server.Anomaly.Effects;
namespace Content.Server.Anomaly.Components;
/// <summary>
/// Shuffle Particle types in some situations
/// </summary>
[RegisterComponent, Access(typeof(ShuffleParticlesAnomalySystem))]
public sealed partial class ShuffleParticlesAnomalyComponent : Component
{
/// <summary>
/// Prob() chance to randomize particle types after Anomaly pulation
/// </summary>
[DataField]
public bool ShuffleOnPulse = false;
/// <summary>
/// Prob() chance to randomize particle types after APE or CHIMP projectile
/// </summary>
[DataField]
public bool ShuffleOnParticleHit = false;
/// <summary>
/// Chance to random particles
/// </summary>
[DataField]
public float Prob = 0.5f;
}

View File

@@ -1,4 +1,4 @@
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using Content.Server.Anomaly.Components; using Content.Server.Anomaly.Components;
using Content.Shared.Administration.Logs; using Content.Shared.Administration.Logs;
@@ -33,7 +33,7 @@ public sealed class BluespaceAnomalySystem : EntitySystem
{ {
var xformQuery = GetEntityQuery<TransformComponent>(); var xformQuery = GetEntityQuery<TransformComponent>();
var xform = xformQuery.GetComponent(uid); var xform = xformQuery.GetComponent(uid);
var range = component.MaxShuffleRadius * args.Severity; var range = component.MaxShuffleRadius * args.Severity * args.PowerModifier;
var mobs = new HashSet<Entity<MobStateComponent>>(); var mobs = new HashSet<Entity<MobStateComponent>>();
_lookup.GetEntitiesInRange(xform.Coordinates, range, mobs); _lookup.GetEntitiesInRange(xform.Coordinates, range, mobs);
var allEnts = new ValueList<EntityUid>(mobs.Select(m => m.Owner)) { uid }; var allEnts = new ValueList<EntityUid>(mobs.Select(m => m.Owner)) { uid };
@@ -56,7 +56,7 @@ public sealed class BluespaceAnomalySystem : EntitySystem
{ {
var xform = Transform(uid); var xform = Transform(uid);
var mapPos = _xform.GetWorldPosition(xform); var mapPos = _xform.GetWorldPosition(xform);
var radius = component.SupercriticalTeleportRadius; var radius = component.SupercriticalTeleportRadius * args.PowerModifier;
var gridBounds = new Box2(mapPos - new Vector2(radius, radius), mapPos + new Vector2(radius, radius)); var gridBounds = new Box2(mapPos - new Vector2(radius, radius), mapPos + new Vector2(radius, radius));
var mobs = new HashSet<Entity<MobStateComponent>>(); var mobs = new HashSet<Entity<MobStateComponent>>();
_lookup.GetEntitiesInRange(xform.Coordinates, component.MaxShuffleRadius, mobs); _lookup.GetEntitiesInRange(xform.Coordinates, component.MaxShuffleRadius, mobs);

View File

@@ -28,7 +28,7 @@ public sealed class ElectricityAnomalySystem : EntitySystem
private void OnPulse(Entity<ElectricityAnomalyComponent> anomaly, ref AnomalyPulseEvent args) private void OnPulse(Entity<ElectricityAnomalyComponent> anomaly, ref AnomalyPulseEvent args)
{ {
var range = anomaly.Comp.MaxElectrocuteRange * args.Stability; var range = anomaly.Comp.MaxElectrocuteRange * args.Stability * args.PowerModifier;
int boltCount = (int)MathF.Floor(MathHelper.Lerp((float)anomaly.Comp.MinBoltCount, (float)anomaly.Comp.MaxBoltCount, args.Severity)); int boltCount = (int)MathF.Floor(MathHelper.Lerp((float)anomaly.Comp.MinBoltCount, (float)anomaly.Comp.MaxBoltCount, args.Severity));
@@ -37,7 +37,7 @@ public sealed class ElectricityAnomalySystem : EntitySystem
private void OnSupercritical(Entity<ElectricityAnomalyComponent> anomaly, ref AnomalySupercriticalEvent args) private void OnSupercritical(Entity<ElectricityAnomalyComponent> anomaly, ref AnomalySupercriticalEvent args)
{ {
var range = anomaly.Comp.MaxElectrocuteRange * 3; var range = anomaly.Comp.MaxElectrocuteRange * 3 * args.PowerModifier;
_emp.EmpPulse(_transform.GetMapCoordinates(anomaly), range, anomaly.Comp.EmpEnergyConsumption, anomaly.Comp.EmpDisabledDuration); _emp.EmpPulse(_transform.GetMapCoordinates(anomaly), range, anomaly.Comp.EmpEnergyConsumption, anomaly.Comp.EmpDisabledDuration);
_lightning.ShootRandomLightnings(anomaly, range, anomaly.Comp.MaxBoltCount * 3, arcDepth: 3); _lightning.ShootRandomLightnings(anomaly, range, anomaly.Comp.MaxBoltCount * 3, arcDepth: 3);

View File

@@ -35,7 +35,7 @@ public sealed class EntityAnomalySystem : SharedEntityAnomalySystem
if (!entry.Settings.SpawnOnPulse) if (!entry.Settings.SpawnOnPulse)
continue; continue;
SpawnEntities(component, entry, args.Stability, args.Severity); SpawnEntities(component, entry, args.Stability, args.Severity, args.PowerModifier);
} }
} }
@@ -46,7 +46,7 @@ public sealed class EntityAnomalySystem : SharedEntityAnomalySystem
if (!entry.Settings.SpawnOnSuperCritical) if (!entry.Settings.SpawnOnSuperCritical)
continue; continue;
SpawnEntities(component, entry, 1, 1); SpawnEntities(component, entry, 1, 1, args.PowerModifier);
} }
} }
@@ -57,7 +57,7 @@ public sealed class EntityAnomalySystem : SharedEntityAnomalySystem
if (!entry.Settings.SpawnOnShutdown || args.Supercritical) if (!entry.Settings.SpawnOnShutdown || args.Supercritical)
continue; continue;
SpawnEntities(component, entry, 1, 1); SpawnEntities(component, entry, 1, 1, 1);
} }
} }
@@ -68,7 +68,7 @@ public sealed class EntityAnomalySystem : SharedEntityAnomalySystem
if (!entry.Settings.SpawnOnStabilityChanged) if (!entry.Settings.SpawnOnStabilityChanged)
continue; continue;
SpawnEntities(component, entry, args.Stability, args.Severity); SpawnEntities(component, entry, args.Stability, args.Severity, 1);
} }
} }
@@ -79,17 +79,17 @@ public sealed class EntityAnomalySystem : SharedEntityAnomalySystem
if (!entry.Settings.SpawnOnSeverityChanged) if (!entry.Settings.SpawnOnSeverityChanged)
continue; continue;
SpawnEntities(component, entry, args.Stability, args.Severity); SpawnEntities(component, entry, args.Stability, args.Severity, 1);
} }
} }
private void SpawnEntities(Entity<EntitySpawnAnomalyComponent> anomaly, EntitySpawnSettingsEntry entry, float stability, float severity) private void SpawnEntities(Entity<EntitySpawnAnomalyComponent> anomaly, EntitySpawnSettingsEntry entry, float stability, float severity, float powerMod)
{ {
var xform = Transform(anomaly); var xform = Transform(anomaly);
if (!TryComp(xform.GridUid, out MapGridComponent? grid)) if (!TryComp(xform.GridUid, out MapGridComponent? grid))
return; return;
var tiles = _anomaly.GetSpawningPoints(anomaly, stability, severity, entry.Settings); var tiles = _anomaly.GetSpawningPoints(anomaly, stability, severity, entry.Settings, powerMod);
if (tiles == null) if (tiles == null)
return; return;

View File

@@ -29,12 +29,12 @@ public sealed class InjectionAnomalySystem : EntitySystem
private void OnPulse(Entity<InjectionAnomalyComponent> entity, ref AnomalyPulseEvent args) private void OnPulse(Entity<InjectionAnomalyComponent> entity, ref AnomalyPulseEvent args)
{ {
PulseScalableEffect(entity, entity.Comp.InjectRadius, entity.Comp.MaxSolutionInjection * args.Severity); PulseScalableEffect(entity, entity.Comp.InjectRadius * args.PowerModifier, entity.Comp.MaxSolutionInjection * args.Severity * args.PowerModifier);
} }
private void OnSupercritical(Entity<InjectionAnomalyComponent> entity, ref AnomalySupercriticalEvent args) private void OnSupercritical(Entity<InjectionAnomalyComponent> entity, ref AnomalySupercriticalEvent args)
{ {
PulseScalableEffect(entity, entity.Comp.SuperCriticalInjectRadius, entity.Comp.SuperCriticalSolutionInjection); PulseScalableEffect(entity, entity.Comp.SuperCriticalInjectRadius * args.PowerModifier, entity.Comp.SuperCriticalSolutionInjection * args.PowerModifier);
} }
private void PulseScalableEffect(Entity<InjectionAnomalyComponent> entity, float injectRadius, float maxInject) private void PulseScalableEffect(Entity<InjectionAnomalyComponent> entity, float injectRadius, float maxInject)

View File

@@ -31,12 +31,12 @@ public sealed class ProjectileAnomalySystem : EntitySystem
private void OnPulse(EntityUid uid, ProjectileAnomalyComponent component, ref AnomalyPulseEvent args) private void OnPulse(EntityUid uid, ProjectileAnomalyComponent component, ref AnomalyPulseEvent args)
{ {
ShootProjectilesAtEntities(uid, component, args.Severity); ShootProjectilesAtEntities(uid, component, args.Severity * args.PowerModifier);
} }
private void OnSupercritical(EntityUid uid, ProjectileAnomalyComponent component, ref AnomalySupercriticalEvent args) private void OnSupercritical(EntityUid uid, ProjectileAnomalyComponent component, ref AnomalySupercriticalEvent args)
{ {
ShootProjectilesAtEntities(uid, component, 1.0f); ShootProjectilesAtEntities(uid, component, args.PowerModifier);
} }
private void ShootProjectilesAtEntities(EntityUid uid, ProjectileAnomalyComponent component, float severity) private void ShootProjectilesAtEntities(EntityUid uid, ProjectileAnomalyComponent component, float severity)

View File

@@ -25,9 +25,10 @@ public sealed class PuddleCreateAnomalySystem : EntitySystem
return; return;
var xform = Transform(entity.Owner); var xform = Transform(entity.Owner);
var puddleSol = _solutionContainer.SplitSolution(sol.Value, entity.Comp.MaxPuddleSize * args.Severity); var puddleSol = _solutionContainer.SplitSolution(sol.Value, entity.Comp.MaxPuddleSize * args.Severity * args.PowerModifier);
_puddle.TrySplashSpillAt(entity.Owner, xform.Coordinates, puddleSol, out _); _puddle.TrySplashSpillAt(entity.Owner, xform.Coordinates, puddleSol, out _);
} }
private void OnSupercritical(Entity<PuddleCreateAnomalyComponent> entity, ref AnomalySupercriticalEvent args) private void OnSupercritical(Entity<PuddleCreateAnomalyComponent> entity, ref AnomalySupercriticalEvent args)
{ {
if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var sol)) if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var sol))

View File

@@ -1,4 +1,4 @@
using Content.Server.Atmos.Components; using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.EntitySystems;
using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Components;
using Content.Shared.Anomaly.Effects.Components; using Content.Shared.Anomaly.Effects.Components;
@@ -24,14 +24,14 @@ public sealed class PyroclasticAnomalySystem : EntitySystem
private void OnPulse(EntityUid uid, PyroclasticAnomalyComponent component, ref AnomalyPulseEvent args) private void OnPulse(EntityUid uid, PyroclasticAnomalyComponent component, ref AnomalyPulseEvent args)
{ {
var xform = Transform(uid); var xform = Transform(uid);
var ignitionRadius = component.MaximumIgnitionRadius * args.Stability; var ignitionRadius = component.MaximumIgnitionRadius * args.Stability * args.PowerModifier;
IgniteNearby(uid, xform.Coordinates, args.Severity, ignitionRadius); IgniteNearby(uid, xform.Coordinates, args.Severity, ignitionRadius);
} }
private void OnSupercritical(EntityUid uid, PyroclasticAnomalyComponent component, ref AnomalySupercriticalEvent args) private void OnSupercritical(EntityUid uid, PyroclasticAnomalyComponent component, ref AnomalySupercriticalEvent args)
{ {
var xform = Transform(uid); var xform = Transform(uid);
IgniteNearby(uid, xform.Coordinates, 1, component.MaximumIgnitionRadius * 2); IgniteNearby(uid, xform.Coordinates, 1, component.MaximumIgnitionRadius * 2 * args.PowerModifier);
} }
public void IgniteNearby(EntityUid uid, EntityCoordinates coordinates, float severity, float radius) public void IgniteNearby(EntityUid uid, EntityCoordinates coordinates, float severity, float radius)

View File

@@ -0,0 +1,40 @@
using Content.Server.Anomaly.Components;
using Robust.Shared.Random;
namespace Content.Server.Anomaly.Effects;
public sealed class SecretDataAnomalySystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
private readonly List<AnomalySecretData> _deita = new();
public override void Initialize()
{
SubscribeLocalEvent<SecretDataAnomalyComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(EntityUid uid, SecretDataAnomalyComponent anomaly, MapInitEvent args)
{
RandomizeSecret(uid,_random.Next(anomaly.RandomStartSecretMin, anomaly.RandomStartSecretMax), anomaly);
}
public void RandomizeSecret(EntityUid uid, int count, SecretDataAnomalyComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
component.Secret.Clear();
// I also considered just adding all the enum values and pruning but that seems more wasteful.
_deita.Clear();
_deita.AddRange(Enum.GetValues<AnomalySecretData>());
var actualCount = Math.Min(count, _deita.Count);
for (int i = 0; i < actualCount; i++)
{
component.Secret.Add(_random.PickAndTake(_deita));
}
}
}

View File

@@ -0,0 +1,41 @@
using Content.Server.Anomaly.Components;
using Content.Shared.Anomaly.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Random;
namespace Content.Server.Anomaly.Effects;
public sealed class ShuffleParticlesAnomalySystem : EntitySystem
{
[Dependency] private readonly AnomalySystem _anomaly = default!;
[Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize()
{
SubscribeLocalEvent<ShuffleParticlesAnomalyComponent, AnomalyPulseEvent>(OnPulse);
SubscribeLocalEvent<ShuffleParticlesAnomalyComponent, StartCollideEvent>(OnStartCollide);
}
private void OnStartCollide(EntityUid uid, ShuffleParticlesAnomalyComponent shuffle, StartCollideEvent args)
{
if (!TryComp<AnomalyComponent>(uid, out var anomaly))
return;
if (shuffle.ShuffleOnParticleHit && _random.Prob(shuffle.Prob))
_anomaly.ShuffleParticlesEffect(anomaly);
if (!TryComp<AnomalousParticleComponent>(args.OtherEntity, out var particle))
return;
}
private void OnPulse(EntityUid uid, ShuffleParticlesAnomalyComponent shuffle, AnomalyPulseEvent args)
{
if (!TryComp<AnomalyComponent>(uid, out var anomaly))
return;
if (shuffle.ShuffleOnPulse && _random.Prob(shuffle.Prob))
{
_anomaly.ShuffleParticlesEffect(anomaly);
}
}
}

View File

@@ -34,7 +34,7 @@ public sealed class TileAnomalySystem : SharedTileAnomalySystem
if (!entry.Settings.SpawnOnPulse) if (!entry.Settings.SpawnOnPulse)
continue; continue;
SpawnTiles(component, entry, args.Stability, args.Severity); SpawnTiles(component, entry, args.Stability, args.Severity, args.PowerModifier);
} }
} }
@@ -45,7 +45,7 @@ public sealed class TileAnomalySystem : SharedTileAnomalySystem
if (!entry.Settings.SpawnOnSuperCritical) if (!entry.Settings.SpawnOnSuperCritical)
continue; continue;
SpawnTiles(component, entry, 1, 1); SpawnTiles(component, entry, 1, 1, args.PowerModifier);
} }
} }
@@ -56,7 +56,7 @@ public sealed class TileAnomalySystem : SharedTileAnomalySystem
if (!entry.Settings.SpawnOnShutdown || args.Supercritical) if (!entry.Settings.SpawnOnShutdown || args.Supercritical)
continue; continue;
SpawnTiles(component, entry, 1, 1); SpawnTiles(component, entry, 1, 1, 1);
} }
} }
@@ -67,7 +67,7 @@ public sealed class TileAnomalySystem : SharedTileAnomalySystem
if (!entry.Settings.SpawnOnStabilityChanged) if (!entry.Settings.SpawnOnStabilityChanged)
continue; continue;
SpawnTiles(component, entry, args.Stability, args.Severity); SpawnTiles(component, entry, args.Stability, args.Severity, 1);
} }
} }
@@ -78,17 +78,17 @@ public sealed class TileAnomalySystem : SharedTileAnomalySystem
if (!entry.Settings.SpawnOnSeverityChanged) if (!entry.Settings.SpawnOnSeverityChanged)
continue; continue;
SpawnTiles(component, entry, args.Stability, args.Severity); SpawnTiles(component, entry, args.Stability, args.Severity, 1);
} }
} }
private void SpawnTiles(Entity<TileSpawnAnomalyComponent> anomaly, TileSpawnSettingsEntry entry, float stability, float severity) private void SpawnTiles(Entity<TileSpawnAnomalyComponent> anomaly, TileSpawnSettingsEntry entry, float stability, float severity, float powerMod)
{ {
var xform = Transform(anomaly); var xform = Transform(anomaly);
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid)) if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
return; return;
var tiles = _anomaly.GetSpawningPoints(anomaly, stability, severity, entry.Settings); var tiles = _anomaly.GetSpawningPoints(anomaly, stability, severity, entry.Settings, powerMod);
if (tiles == null) if (tiles == null)
return; return;

View File

@@ -1,4 +1,5 @@
using System.Numerics; using System.Numerics;
using Content.Shared.Anomaly.Prototypes;
using Content.Shared.Damage; using Content.Shared.Damage;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
@@ -166,6 +167,12 @@ public sealed partial class AnomalyComponent : Component
[DataField] [DataField]
public AnomalousParticleType WeakeningParticleType; public AnomalousParticleType WeakeningParticleType;
/// <summary>
/// The particle type that change anomaly behaviour.
/// </summary>
[DataField]
public AnomalousParticleType TransformationParticleType;
#region Points and Vessels #region Points and Vessels
/// <summary> /// <summary>
/// The vessel that the anomaly is connceted to. Stored so that multiple /// The vessel that the anomaly is connceted to. Stored so that multiple
@@ -185,7 +192,7 @@ public sealed partial class AnomalyComponent : Component
/// This doesn't include the point bonus for being unstable. /// This doesn't include the point bonus for being unstable.
/// </summary> /// </summary>
[DataField("maxPointsPerSecond")] [DataField("maxPointsPerSecond")]
public int MaxPointsPerSecond = 80; public int MaxPointsPerSecond = 70;
/// <summary> /// <summary>
/// The multiplier applied to the point value for the /// The multiplier applied to the point value for the
@@ -221,6 +228,31 @@ public sealed partial class AnomalyComponent : Component
[DataField, ViewVariables(VVAccess.ReadWrite)] [DataField, ViewVariables(VVAccess.ReadWrite)]
public EntProtoId? CoreInertPrototype; public EntProtoId? CoreInertPrototype;
#region Behavior Deviations
[DataField]
public ProtoId<AnomalyBehaviorPrototype>? CurrentBehavior;
/// <summary>
/// Presumption of anomaly to change behavior. The higher the number, the higher the chance that the anomaly will change its behavior.
/// </summary>
[DataField]
public float Continuity = 0f;
/// <summary>
/// Minimum contituty probability chance, that can be selected by anomaly on MapInit
/// </summary>
[DataField]
public float MinContituty = 0.1f;
/// <summary>
/// Maximum contituty probability chance, that can be selected by anomaly on MapInit
/// </summary>
[DataField]
public float MaxContituty = 1.0f;
#endregion
#region Floating Animation #region Floating Animation
/// <summary> /// <summary>
/// How long it takes to go from the bottom of the animation to the top. /// How long it takes to go from the bottom of the animation to the top.
@@ -247,13 +279,13 @@ public sealed partial class AnomalyComponent : Component
/// <param name="Stability"></param> /// <param name="Stability"></param>
/// <param name="Severity"></param> /// <param name="Severity"></param>
[ByRefEvent] [ByRefEvent]
public readonly record struct AnomalyPulseEvent(EntityUid Anomaly, float Stability, float Severity); public readonly record struct AnomalyPulseEvent(EntityUid Anomaly, float Stability, float Severity, float PowerModifier);
/// <summary> /// <summary>
/// Event raised on an anomaly when it reaches a supercritical point. /// Event raised on an anomaly when it reaches a supercritical point.
/// </summary> /// </summary>
[ByRefEvent] [ByRefEvent]
public readonly record struct AnomalySupercriticalEvent(EntityUid Anomaly); public readonly record struct AnomalySupercriticalEvent(EntityUid Anomaly, float PowerModifier);
/// <summary> /// <summary>
/// Event broadcast after an anomaly goes supercritical /// Event broadcast after an anomaly goes supercritical
@@ -282,3 +314,9 @@ public readonly record struct AnomalyStabilityChangedEvent(EntityUid Anomaly, fl
/// <param name="Anomaly">The anomaly being changed</param> /// <param name="Anomaly">The anomaly being changed</param>
[ByRefEvent] [ByRefEvent]
public readonly record struct AnomalyHealthChangedEvent(EntityUid Anomaly, float Health); public readonly record struct AnomalyHealthChangedEvent(EntityUid Anomaly, float Health);
/// <summary>
/// Event broadcast when an anomaly's behavior is changed.
/// </summary>
[ByRefEvent]
public readonly record struct AnomalyBehaviorChangedEvent(EntityUid Anomaly, ProtoId<AnomalyBehaviorPrototype>? Old, ProtoId<AnomalyBehaviorPrototype>? New);

View File

@@ -1,4 +1,4 @@
using System.Linq; using System.Linq;
using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Components;
using Content.Shared.Anomaly.Effects.Components; using Content.Shared.Anomaly.Effects.Components;
using Content.Shared.Ghost; using Content.Shared.Ghost;
@@ -27,8 +27,8 @@ public abstract class SharedGravityAnomalySystem : EntitySystem
private void OnAnomalyPulse(EntityUid uid, GravityAnomalyComponent component, ref AnomalyPulseEvent args) private void OnAnomalyPulse(EntityUid uid, GravityAnomalyComponent component, ref AnomalyPulseEvent args)
{ {
var xform = Transform(uid); var xform = Transform(uid);
var range = component.MaxThrowRange * args.Severity; var range = component.MaxThrowRange * args.Severity * args.PowerModifier;
var strength = component.MaxThrowStrength * args.Severity; var strength = component.MaxThrowStrength * args.Severity * args.PowerModifier;
var lookup = _lookup.GetEntitiesInRange(uid, range, LookupFlags.Dynamic | LookupFlags.Sundries); var lookup = _lookup.GetEntitiesInRange(uid, range, LookupFlags.Dynamic | LookupFlags.Sundries);
var xformQuery = GetEntityQuery<TransformComponent>(); var xformQuery = GetEntityQuery<TransformComponent>();
var worldPos = _xform.GetWorldPosition(xform, xformQuery); var worldPos = _xform.GetWorldPosition(xform, xformQuery);
@@ -61,8 +61,8 @@ public abstract class SharedGravityAnomalySystem : EntitySystem
var tiles = tileref.Select(t => (t.GridIndices, Tile.Empty)).ToList(); var tiles = tileref.Select(t => (t.GridIndices, Tile.Empty)).ToList();
_mapSystem.SetTiles(xform.GridUid.Value, grid, tiles); _mapSystem.SetTiles(xform.GridUid.Value, grid, tiles);
var range = component.MaxThrowRange * 2; var range = component.MaxThrowRange * 2 * args.PowerModifier;
var strength = component.MaxThrowStrength * 2; var strength = component.MaxThrowStrength * 2 * args.PowerModifier;
var lookup = _lookup.GetEntitiesInRange(uid, range, LookupFlags.Dynamic | LookupFlags.Sundries); var lookup = _lookup.GetEntitiesInRange(uid, range, LookupFlags.Dynamic | LookupFlags.Sundries);
var xformQuery = GetEntityQuery<TransformComponent>(); var xformQuery = GetEntityQuery<TransformComponent>();
var physQuery = GetEntityQuery<PhysicsComponent>(); var physQuery = GetEntityQuery<PhysicsComponent>();

View File

@@ -0,0 +1,45 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Anomaly.Prototypes;
[Prototype]
public sealed partial class AnomalyBehaviorPrototype : IPrototype
{
[IdDataField] public string ID { get; private set; } = default!;
/// <summary>
/// Description for anomaly scanner
/// </summary>
[DataField]
public string Description = string.Empty;
/// <summary>
/// modification of the number of points earned from an anomaly
/// </summary>
[DataField]
public float EarnPointModifier = 1f;
/// <summary>
/// deceleration or acceleration of the pulsation frequency of the anomaly
/// </summary>
[DataField]
public float PulseFrequencyModifier = 1f;
/// <summary>
/// pulse and supercrit power modifier
/// </summary>
[DataField]
public float PulsePowerModifier = 1f;
/// <summary>
/// how much the particles will affect the anomaly
/// </summary>
[DataField]
public float ParticleSensivity = 1f;
/// <summary>
/// Components that are added to the anomaly when this behavior is selected, and removed when another behavior is selected.
/// </summary>
[DataField(serverOnly: true)]
public ComponentRegistry Components = new();
}

View File

@@ -33,6 +33,7 @@ public enum AnomalousParticleType : byte
Delta, Delta,
Epsilon, Epsilon,
Zeta, Zeta,
Sigma,
Default Default
} }

View File

@@ -1,5 +1,6 @@
using Content.Shared.Administration.Logs; using Content.Shared.Administration.Logs;
using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Components;
using Content.Shared.Anomaly.Prototypes;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Interaction; using Content.Shared.Interaction;
@@ -14,6 +15,7 @@ using Robust.Shared.Network;
using Robust.Shared.Physics; using Robust.Shared.Physics;
using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems; using Robust.Shared.Physics.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -33,6 +35,7 @@ public abstract class SharedAnomalySystem : EntitySystem
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!; [Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] protected readonly SharedPopupSystem Popup = default!; [Dependency] protected readonly SharedPopupSystem Popup = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize() public override void Initialize()
@@ -90,8 +93,7 @@ public abstract class SharedAnomalySystem : EntitySystem
return; return;
DebugTools.Assert(component.MinPulseLength > TimeSpan.FromSeconds(3)); // this is just to prevent lagspikes mispredicting pulses DebugTools.Assert(component.MinPulseLength > TimeSpan.FromSeconds(3)); // this is just to prevent lagspikes mispredicting pulses
var variation = Random.NextFloat(-component.PulseVariation, component.PulseVariation) + 1; RefreshPulseTimer(uid, component);
component.NextPulseTime = Timing.CurTime + GetPulseLength(component) * variation;
if (_net.IsServer) if (_net.IsServer)
Log.Info($"Performing anomaly pulse. Entity: {ToPrettyString(uid)}"); Log.Info($"Performing anomaly pulse. Entity: {ToPrettyString(uid)}");
@@ -115,10 +117,25 @@ public abstract class SharedAnomalySystem : EntitySystem
pulse.EndTime = Timing.CurTime + pulse.PulseDuration; pulse.EndTime = Timing.CurTime + pulse.PulseDuration;
Appearance.SetData(uid, AnomalyVisuals.IsPulsing, true); Appearance.SetData(uid, AnomalyVisuals.IsPulsing, true);
var ev = new AnomalyPulseEvent(uid, component.Stability, component.Severity); var powerMod = 1f;
if (component.CurrentBehavior != null)
{
var beh = _prototype.Index<AnomalyBehaviorPrototype>(component.CurrentBehavior);
powerMod = beh.PulsePowerModifier;
}
var ev = new AnomalyPulseEvent(uid, component.Stability, component.Severity, powerMod);
RaiseLocalEvent(uid, ref ev, true); RaiseLocalEvent(uid, ref ev, true);
} }
public void RefreshPulseTimer(EntityUid uid, AnomalyComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
var variation = Random.NextFloat(-component.PulseVariation, component.PulseVariation) + 1;
component.NextPulseTime = Timing.CurTime + GetPulseLength(component) * variation;
}
/// <summary> /// <summary>
/// Begins the animation for going supercritical /// Begins the animation for going supercritical
/// </summary> /// </summary>
@@ -159,7 +176,14 @@ public abstract class SharedAnomalySystem : EntitySystem
if (_net.IsServer) if (_net.IsServer)
Log.Info($"Raising supercritical event. Entity: {ToPrettyString(uid)}"); Log.Info($"Raising supercritical event. Entity: {ToPrettyString(uid)}");
var ev = new AnomalySupercriticalEvent(uid); var powerMod = 1f;
if (component.CurrentBehavior != null)
{
var beh = _prototype.Index<AnomalyBehaviorPrototype>(component.CurrentBehavior);
powerMod = beh.PulsePowerModifier;
}
var ev = new AnomalySupercriticalEvent(uid, powerMod);
RaiseLocalEvent(uid, ref ev, true); RaiseLocalEvent(uid, ref ev, true);
EndAnomaly(uid, component, true); EndAnomaly(uid, component, true);
@@ -276,8 +300,17 @@ public abstract class SharedAnomalySystem : EntitySystem
public TimeSpan GetPulseLength(AnomalyComponent component) public TimeSpan GetPulseLength(AnomalyComponent component)
{ {
DebugTools.Assert(component.MaxPulseLength > component.MinPulseLength); DebugTools.Assert(component.MaxPulseLength > component.MinPulseLength);
var modifier = Math.Clamp((component.Stability - component.GrowthThreshold) / component.GrowthThreshold, 0, 1); var modifier = Math.Clamp((component.Stability - component.GrowthThreshold) / component.GrowthThreshold, 0, 1);
return (component.MaxPulseLength - component.MinPulseLength) * modifier + component.MinPulseLength;
var lenght = (component.MaxPulseLength - component.MinPulseLength) * modifier + component.MinPulseLength;
//Apply behavior modifier
if (component.CurrentBehavior != null)
{
var behavior = _prototype.Index(component.CurrentBehavior.Value);
lenght *= behavior.PulseFrequencyModifier;
}
return lenght;
} }
/// <summary> /// <summary>
@@ -335,14 +368,14 @@ public abstract class SharedAnomalySystem : EntitySystem
/// <summary> /// <summary>
/// Gets random points around the anomaly based on the given parameters. /// Gets random points around the anomaly based on the given parameters.
/// </summary> /// </summary>
public List<TileRef>? GetSpawningPoints(EntityUid uid, float stability, float severity, AnomalySpawnSettings settings) public List<TileRef>? GetSpawningPoints(EntityUid uid, float stability, float severity, AnomalySpawnSettings settings, float powerModifier = 1f)
{ {
var xform = Transform(uid); var xform = Transform(uid);
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid)) if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
return null; return null;
var amount = (int) (MathHelper.Lerp(settings.MinAmount, settings.MaxAmount, severity * stability) + 0.5f); var amount = (int) (MathHelper.Lerp(settings.MinAmount, settings.MaxAmount, severity * stability * powerModifier) + 0.5f);
var localpos = xform.Coordinates.Position; var localpos = xform.Coordinates.Position;
var tilerefs = grid.GetLocalTilesIntersecting( var tilerefs = grid.GetLocalTilesIntersecting(

View File

@@ -8,20 +8,29 @@ anomaly-particles-delta = Delta particles
anomaly-particles-epsilon = Epsilon particles anomaly-particles-epsilon = Epsilon particles
anomaly-particles-zeta = Zeta particles anomaly-particles-zeta = Zeta particles
anomaly-particles-omega = Omega particles anomaly-particles-omega = Omega particles
anomaly-particles-sigma = Sigma particles
anomaly-scanner-component-scan-complete = Scan complete! anomaly-scanner-component-scan-complete = Scan complete!
anomaly-scanner-ui-title = anomaly scanner anomaly-scanner-ui-title = anomaly scanner
anomaly-scanner-no-anomaly = No anomaly currently scanned. anomaly-scanner-no-anomaly = No anomaly currently scanned.
anomaly-scanner-severity-percentage = Current severity: [color=gray]{$percent}[/color] anomaly-scanner-severity-percentage = Current severity: [color=gray]{$percent}[/color]
anomaly-scanner-severity-percentage-unknown = Current severity: [color=red]ERROR[/color]
anomaly-scanner-stability-low = Current anomaly state: [color=gold]Decaying[/color] anomaly-scanner-stability-low = Current anomaly state: [color=gold]Decaying[/color]
anomaly-scanner-stability-medium = Current anomaly state: [color=forestgreen]Stable[/color] anomaly-scanner-stability-medium = Current anomaly state: [color=forestgreen]Stable[/color]
anomaly-scanner-stability-high = Current anomaly state: [color=crimson]Growing[/color] anomaly-scanner-stability-high = Current anomaly state: [color=crimson]Growing[/color]
anomaly-scanner-stability-unknown = Current anomaly state: [color=red]ERROR[/color]
anomaly-scanner-point-output = Point output: [color=gray]{$point}[/color] anomaly-scanner-point-output = Point output: [color=gray]{$point}[/color]
anomaly-scanner-point-output-unknown = Point output: [color=red]ERROR[/color]
anomaly-scanner-particle-readout = Particle Reaction Analysis: anomaly-scanner-particle-readout = Particle Reaction Analysis:
anomaly-scanner-particle-danger = - [color=crimson]Danger type:[/color] {$type} anomaly-scanner-particle-danger = - [color=crimson]Danger type:[/color] {$type}
anomaly-scanner-particle-unstable = - [color=plum]Unstable type:[/color] {$type} anomaly-scanner-particle-unstable = - [color=plum]Unstable type:[/color] {$type}
anomaly-scanner-particle-containment = - [color=goldenrod]Containment type:[/color] {$type} anomaly-scanner-particle-containment = - [color=goldenrod]Containment type:[/color] {$type}
anomaly-scanner-particle-transformation = - [color=#6b75fa]Transformation type:[/color] {$type}
anomaly-scanner-particle-danger-unknown = - [color=crimson]Danger type:[/color] [color=red]ERROR[/color]
anomaly-scanner-particle-unstable-unknown = - [color=plum]Unstable type:[/color] [color=red]ERROR[/color]
anomaly-scanner-particle-containment-unknown = - [color=goldenrod]Containment type:[/color] [color=red]ERROR[/color]
anomaly-scanner-particle-transformation-unknown = - [color=#6b75fa]Transformation type:[/color] [color=red]ERROR[/color]
anomaly-scanner-pulse-timer = Time until next pulse: [color=gray]{$time}[/color] anomaly-scanner-pulse-timer = Time until next pulse: [color=gray]{$time}[/color]
anomaly-gorilla-core-slot-name = Anomaly core anomaly-gorilla-core-slot-name = Anomaly core
@@ -65,3 +74,23 @@ anomaly-command-supercritical = Makes a target anomaly go supercritical
# Flavor text on the footer # Flavor text on the footer
anomaly-generator-flavor-left = Anomaly may spawn inside the operator. anomaly-generator-flavor-left = Anomaly may spawn inside the operator.
anomaly-generator-flavor-right = v1.1 anomaly-generator-flavor-right = v1.1
anomaly-behavior-unknown = [color=red]ERROR. Cannot be read.[/color]
anomaly-behavior-title = behavior deviation analysis:
anomaly-behavior-point =[color=gold]Anomaly produces {$mod}% of the points[/color]
anomaly-behavior-safe = [color=forestgreen]The anomaly is extremely stable. Extremely rare pulsations.[/color]
anomaly-behavior-slow = [color=forestgreen]The frequency of pulsations is much less frequent.[/color]
anomaly-behavior-light = [color=forestgreen]Pulsation power is significantly reduced.[/color]
anomaly-behavior-balanced = No behavior deviations detected.
anomaly-behavior-delayed-force = The frequency of pulsations is greatly reduced, but their power is increased.
anomaly-behavior-rapid = The frequency of the pulsation is much higher, but its strength is attenuated.
anomaly-behavior-reflect = A protective coating was detected.
anomaly-behavior-nonsensivity = A weak reaction to particles was detected.
anomaly-behavior-sensivity = Amplified reaction to particles was detected.
anomaly-behavior-secret = Interference detected. Some data cannot be read
anomaly-behavior-inconstancy = [color=crimson]Impermanence has been detected. Particle types can change over time.[/color]
anomaly-behavior-fast = [color=crimson]The pulsation frequency is strongly increased.[/color]
anomaly-behavior-strenght = [color=crimson]The pulsation power is significantly increased.[/color]
anomaly-behavior-moving = [color=crimson]Coordinate instability was detected.[/color]

View File

@@ -70,6 +70,9 @@ signal-port-description-set-particle-epsilon = Sets the type of particle this de
signal-port-name-set-particle-zeta = Set particle type: zeta signal-port-name-set-particle-zeta = Set particle type: zeta
signal-port-description-set-particle-zeta = Sets the type of particle this device emits to zeta. signal-port-description-set-particle-zeta = Sets the type of particle this device emits to zeta.
signal-port-name-set-particle-sigma = Set particle type: sigma
signal-port-description-set-particle-sigma = Sets the type of particle this device emits to sigma.
signal-port-name-logic-input-a = Input A signal-port-name-logic-input-a = Input A
signal-port-description-logic-input-a = First input of a logic gate. signal-port-description-logic-input-a = First input of a logic gate.

View File

@@ -0,0 +1,208 @@
- type: weightedRandom
id: AnomalyBehaviorList
weights:
#safe
Slow: 0.5
Light: 0.5
FullSafe: 0.1
#balanced
Balanced: 3
DelayedForce: 1
Rapid: 1
BalancedSecret: 1
Reflect: 1
NonSensivity: 1
Sensivity: 1
#Hard
Fast: 0.5
Strenght: 0.5
Inconstancy: 0.5
InconstancyParticle: 0.5
FullUnknown: 0.5
Jumping: 0.3
Moving: 0.1
#Complex
FastUnknown: 0.2
JumpingUnknown: 0.1
InconstancyParticleUnknown: 0.1
# Easy x0.5 point production
- type: anomalyBehavior
id: FullSafe
pulseFrequencyModifier: 3
pulsePowerModifier: 0.5
earnPointModifier: 0.05
description: anomaly-behavior-safe
- type: anomalyBehavior
id: Slow
pulseFrequencyModifier: 2
earnPointModifier: 0.5
description: anomaly-behavior-slow
- type: anomalyBehavior
id: Light
pulsePowerModifier: 0.5
earnPointModifier: 0.5
description: anomaly-behavior-light
# Balanced x1 point production
- type: anomalyBehavior
id: Balanced
earnPointModifier: 1
description: anomaly-behavior-balanced
- type: anomalyBehavior
id: DelayedForce
earnPointModifier: 1.15
description: anomaly-behavior-delayed-force
pulseFrequencyModifier: 0.5
pulsePowerModifier: 2
- type: anomalyBehavior
id: Rapid
earnPointModifier: 1.15
description: anomaly-behavior-rapid
pulseFrequencyModifier: 2
pulsePowerModifier: 0.5
- type: anomalyBehavior
id: BalancedSecret
earnPointModifier: 1.2
description: anomaly-behavior-secret
components:
- type: SecretDataAnomaly
randomStartSecretMin: 2
randomStartSecretMax: 3
- type: anomalyBehavior
id: Reflect
earnPointModifier: 1.1
particleSensivity: 0.5
description: anomaly-behavior-reflect
components:
- type: Reflect
reflectProb: 0.5
reflects:
- Energy
- type: anomalyBehavior
id: NonSensivity
earnPointModifier: 0.8
particleSensivity: 0.5
description: anomaly-behavior-nonsensivity
- type: anomalyBehavior
id: Sensivity
earnPointModifier: 1.2
particleSensivity: 1.5
description: anomaly-behavior-sensivity
# Hard x2 point production
- type: anomalyBehavior
id: Fast
earnPointModifier: 1.9
pulseFrequencyModifier: 0.5
description: anomaly-behavior-fast
- type: anomalyBehavior
id: Strenght
pulsePowerModifier: 1.5
earnPointModifier: 1.4
description: anomaly-behavior-strenght
- type: anomalyBehavior
id: Inconstancy
earnPointModifier: 1.7
description: anomaly-behavior-inconstancy
components:
- type: ShuffleParticlesAnomaly
shuffleOnPulse: true
prob: 1
- type: anomalyBehavior
id: InconstancyParticle
earnPointModifier: 1.8
description: anomaly-behavior-inconstancy
components:
- type: ShuffleParticlesAnomaly
shuffleOnParticleHit: true
prob: 0.8
- type: anomalyBehavior
id: Moving
earnPointModifier: 2.2
description: anomaly-behavior-moving
components:
- type: RandomWalk
minSpeed: 0
maxSpeed: 0.3
- type: CanMoveInAir
- type: Physics
bodyType: Dynamic
bodyStatus: InAir
- type: anomalyBehavior
id: Jumping
earnPointModifier: 1.8
description: anomaly-behavior-moving
components:
- type: ChaoticJump
jumpMinInterval: 15
jumpMaxInterval: 25
rangeMin: 1
rangeMax: 4
effect: PuddleSparkle
- type: anomalyBehavior
id: FullUnknown
earnPointModifier: 1.9
description: anomaly-behavior-secret
components:
- type: SecretDataAnomaly
randomStartSecretMin: 4
randomStartSecretMax: 6
# Complex Effects
- type: anomalyBehavior
id: JumpingUnknown
earnPointModifier: 1.9
description: anomaly-behavior-moving
components:
- type: ChaoticJump
jumpMinInterval: 15
jumpMaxInterval: 25
rangeMin: 1
rangeMax: 1
effect: PuddleSparkle
- type: SecretDataAnomaly
randomStartSecretMin: 3
randomStartSecretMax: 5
- type: anomalyBehavior
id: FastUnknown
earnPointModifier: 1.9
pulseFrequencyModifier: 0.5
description: anomaly-behavior-fast
components:
- type: SecretDataAnomaly
randomStartSecretMin: 3
randomStartSecretMax: 5
- type: anomalyBehavior
id: InconstancyParticleUnknown
earnPointModifier: 1.95
description: anomaly-behavior-inconstancy
components:
- type: ShuffleParticlesAnomaly
shuffleOnParticleHit: true
prob: 0.5
- type: SecretDataAnomaly
randomStartSecretMin: 3
randomStartSecretMax: 5

View File

@@ -107,3 +107,8 @@
id: SetParticleZeta id: SetParticleZeta
name: signal-port-name-set-particle-zeta name: signal-port-name-set-particle-zeta
description: signal-port-description-set-particle-zeta description: signal-port-description-set-particle-zeta
- type: sinkPort
id: SetParticleSigma
name: signal-port-name-set-particle-sigma
description: signal-port-description-set-particle-sigma

View File

@@ -643,6 +643,7 @@
- type: Clothing - type: Clothing
sprite: Objects/Weapons/Guns/Revolvers/chimp.rsi sprite: Objects/Weapons/Guns/Revolvers/chimp.rsi
- type: Gun - type: Gun
projectileSpeed: 4
fireRate: 1.5 fireRate: 1.5
soundGunshot: soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/taser2.ogg path: /Audio/Weapons/Guns/Gunshots/taser2.ogg
@@ -657,6 +658,8 @@
fireCost: 100 fireCost: 100
- proto: AnomalousParticleZetaStrong - proto: AnomalousParticleZetaStrong
fireCost: 100 fireCost: 100
- proto: AnomalousParticleSigmaStrong
fireCost: 100
- type: Construction - type: Construction
graph: UpgradeWeaponPistolCHIMP graph: UpgradeWeaponPistolCHIMP
node: start node: start
@@ -679,6 +682,8 @@
fireCost: 100 fireCost: 100
- proto: AnomalousParticleZetaStrong - proto: AnomalousParticleZetaStrong
fireCost: 100 fireCost: 100
- proto: AnomalousParticleSigmaStrong
fireCost: 100
- type: entity - type: entity
name: eye of a behonker name: eye of a behonker

View File

@@ -487,6 +487,11 @@
name: delta particles name: delta particles
noSpawn: true noSpawn: true
components: components:
- type: PointLight
enabled: true
color: "#c2385d"
radius: 2.0
energy: 7.0
- type: AnomalousParticle - type: AnomalousParticle
particleType: Delta particleType: Delta
- type: Sprite - type: Sprite
@@ -513,6 +518,9 @@
Heat: 5 Heat: 5
- type: TimedDespawn - type: TimedDespawn
lifetime: 3 lifetime: 3
- type: Reflective
reflective:
- Energy
- type: entity - type: entity
@@ -533,6 +541,11 @@
name: epsilon particles name: epsilon particles
noSpawn: true noSpawn: true
components: components:
- type: PointLight
enabled: true
color: "#38c296"
radius: 2.0
energy: 7.0
- type: Sprite - type: Sprite
layers: layers:
- state: magicm_cyan - state: magicm_cyan
@@ -558,6 +571,11 @@
name: zeta particles name: zeta particles
noSpawn: true noSpawn: true
components: components:
- type: PointLight
enabled: true
color: "#b9c238"
radius: 2.0
energy: 7.0
- type: Sprite - type: Sprite
layers: layers:
- state: magicm_yellow - state: magicm_yellow
@@ -583,6 +601,11 @@
name: omega particles name: omega particles
noSpawn: true noSpawn: true
components: components:
- type: PointLight
enabled: true
color: "#38c24f"
radius: 2.0
energy: 7.0
- type: Sprite - type: Sprite
sprite: Objects/Weapons/Guns/Projectiles/magic.rsi sprite: Objects/Weapons/Guns/Projectiles/magic.rsi
layers: layers:
@@ -601,6 +624,33 @@
types: types:
Heat: 20 Heat: 20
- type: entity
parent: AnomalousParticleDelta
id: AnomalousParticleSigma
name: sigma particles
noSpawn: true
components:
- type: PointLight
enabled: true
color: "#8d38c2"
radius: 2.0
energy: 7.0
- type: Sprite
layers:
- state: magicm
shader: unshaded
- type: AnomalousParticle
particleType: Sigma
- type: entity
parent: AnomalousParticleSigma
id: AnomalousParticleSigmaStrong
name: sigma particles
noSpawn: true
components:
- type: AnomalousParticle
particleType: Sigma
# Launcher projectiles (grenade / rocket) # Launcher projectiles (grenade / rocket)
- type: entity - type: entity
id: BulletRocket id: BulletRocket

View File

@@ -172,10 +172,12 @@
- AnomalousParticleDelta - AnomalousParticleDelta
- AnomalousParticleEpsilon - AnomalousParticleEpsilon
- AnomalousParticleZeta - AnomalousParticleZeta
- AnomalousParticleSigma
setTypePorts: setTypePorts:
SetParticleDelta: AnomalousParticleDelta SetParticleDelta: AnomalousParticleDelta
SetParticleEpsilon: AnomalousParticleEpsilon SetParticleEpsilon: AnomalousParticleEpsilon
SetParticleZeta: AnomalousParticleZeta SetParticleZeta: AnomalousParticleZeta
SetParticleSigma: AnomalousParticleSigma
fireBurstSize: 1 fireBurstSize: 1
fireBurstDelayMin: 2 fireBurstDelayMin: 2
fireBurstDelayMax: 6 fireBurstDelayMax: 6
@@ -185,6 +187,7 @@
guides: guides:
- APE - APE
- type: Gun - type: Gun
projectileSpeed: 4
fireRate: 10 #just has to be fast enough to keep up with upgrades fireRate: 10 #just has to be fast enough to keep up with upgrades
showExamineText: false showExamineText: false
selectedMode: SemiAuto selectedMode: SemiAuto
@@ -219,6 +222,7 @@
- SetParticleDelta - SetParticleDelta
- SetParticleEpsilon - SetParticleEpsilon
- SetParticleZeta - SetParticleZeta
- SetParticleSigma
- type: entity - type: entity
id: MachineAnomalyGenerator id: MachineAnomalyGenerator

View File

@@ -21,6 +21,7 @@
anchored: false anchored: false
- type: Physics - type: Physics
bodyType: Static bodyType: Static
bodyStatus: InAir
- type: Fixtures - type: Fixtures
fixtures: fixtures:
fix1: fix1:
@@ -47,6 +48,9 @@
- type: EmitSoundOnSpawn - type: EmitSoundOnSpawn
sound: sound:
path: /Audio/Effects/teleport_arrival.ogg path: /Audio/Effects/teleport_arrival.ogg
- type: SecretDataAnomaly
randomStartSecretMin: 0
randomStartSecretMax: 2
- type: entity - type: entity
id: AnomalyPyroclastic id: AnomalyPyroclastic
@@ -119,11 +123,11 @@
castShadows: false castShadows: false
- type: GravityAnomaly - type: GravityAnomaly
- type: GravityWell - type: GravityWell
- type: RadiationSource - type: RadiationSource
- type: Physics - type: Physics
bodyType: Dynamic bodyType: Dynamic
bodyStatus: InAir bodyStatus: InAir
- type: CanMoveInAir - type: CanMoveInAir
- type: RandomWalk - type: RandomWalk
- type: SingularityDistortion - type: SingularityDistortion
intensity: 1000 intensity: 1000
@@ -598,7 +602,7 @@
color: "#6270bb" color: "#6270bb"
- type: Anomaly - type: Anomaly
animationTime: 6 animationTime: 6
offset: 0.05, 0 offset: 0, 0
corePrototype: AnomalyCoreFlora corePrototype: AnomalyCoreFlora
coreInertPrototype: AnomalyCoreFloraInert coreInertPrototype: AnomalyCoreFloraInert
anomalyContactDamage: anomalyContactDamage: