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:
@@ -1,4 +1,5 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.Anomaly.Prototypes;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
@@ -166,6 +167,12 @@ public sealed partial class AnomalyComponent : Component
|
||||
[DataField]
|
||||
public AnomalousParticleType WeakeningParticleType;
|
||||
|
||||
/// <summary>
|
||||
/// The particle type that change anomaly behaviour.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public AnomalousParticleType TransformationParticleType;
|
||||
|
||||
#region Points and Vessels
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[DataField("maxPointsPerSecond")]
|
||||
public int MaxPointsPerSecond = 80;
|
||||
public int MaxPointsPerSecond = 70;
|
||||
|
||||
/// <summary>
|
||||
/// The multiplier applied to the point value for the
|
||||
@@ -221,6 +228,31 @@ public sealed partial class AnomalyComponent : Component
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
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
|
||||
/// <summary>
|
||||
/// 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="Severity"></param>
|
||||
[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>
|
||||
/// Event raised on an anomaly when it reaches a supercritical point.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly record struct AnomalySupercriticalEvent(EntityUid Anomaly);
|
||||
public readonly record struct AnomalySupercriticalEvent(EntityUid Anomaly, float PowerModifier);
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
[ByRefEvent]
|
||||
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);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Anomaly.Effects.Components;
|
||||
using Content.Shared.Ghost;
|
||||
@@ -27,8 +27,8 @@ public abstract class SharedGravityAnomalySystem : EntitySystem
|
||||
private void OnAnomalyPulse(EntityUid uid, GravityAnomalyComponent component, ref AnomalyPulseEvent args)
|
||||
{
|
||||
var xform = Transform(uid);
|
||||
var range = component.MaxThrowRange * args.Severity;
|
||||
var strength = component.MaxThrowStrength * args.Severity;
|
||||
var range = component.MaxThrowRange * args.Severity * args.PowerModifier;
|
||||
var strength = component.MaxThrowStrength * args.Severity * args.PowerModifier;
|
||||
var lookup = _lookup.GetEntitiesInRange(uid, range, LookupFlags.Dynamic | LookupFlags.Sundries);
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
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();
|
||||
_mapSystem.SetTiles(xform.GridUid.Value, grid, tiles);
|
||||
|
||||
var range = component.MaxThrowRange * 2;
|
||||
var strength = component.MaxThrowStrength * 2;
|
||||
var range = component.MaxThrowRange * 2 * args.PowerModifier;
|
||||
var strength = component.MaxThrowStrength * 2 * args.PowerModifier;
|
||||
var lookup = _lookup.GetEntitiesInRange(uid, range, LookupFlags.Dynamic | LookupFlags.Sundries);
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
var physQuery = GetEntityQuery<PhysicsComponent>();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -33,6 +33,7 @@ public enum AnomalousParticleType : byte
|
||||
Delta,
|
||||
Epsilon,
|
||||
Zeta,
|
||||
Sigma,
|
||||
Default
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Anomaly.Prototypes;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Interaction;
|
||||
@@ -14,6 +15,7 @@ using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -33,6 +35,7 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -90,8 +93,7 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
return;
|
||||
|
||||
DebugTools.Assert(component.MinPulseLength > TimeSpan.FromSeconds(3)); // this is just to prevent lagspikes mispredicting pulses
|
||||
var variation = Random.NextFloat(-component.PulseVariation, component.PulseVariation) + 1;
|
||||
component.NextPulseTime = Timing.CurTime + GetPulseLength(component) * variation;
|
||||
RefreshPulseTimer(uid, component);
|
||||
|
||||
if (_net.IsServer)
|
||||
Log.Info($"Performing anomaly pulse. Entity: {ToPrettyString(uid)}");
|
||||
@@ -115,10 +117,25 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
pulse.EndTime = Timing.CurTime + pulse.PulseDuration;
|
||||
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);
|
||||
}
|
||||
|
||||
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>
|
||||
/// Begins the animation for going supercritical
|
||||
/// </summary>
|
||||
@@ -159,7 +176,14 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
if (_net.IsServer)
|
||||
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);
|
||||
|
||||
EndAnomaly(uid, component, true);
|
||||
@@ -276,8 +300,17 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
public TimeSpan GetPulseLength(AnomalyComponent component)
|
||||
{
|
||||
DebugTools.Assert(component.MaxPulseLength > component.MinPulseLength);
|
||||
var modifier = Math.Clamp((component.Stability - component.GrowthThreshold) / component.GrowthThreshold, 0, 1);
|
||||
return (component.MaxPulseLength - component.MinPulseLength) * modifier + component.MinPulseLength;
|
||||
var modifier = Math.Clamp((component.Stability - component.GrowthThreshold) / component.GrowthThreshold, 0, 1);
|
||||
|
||||
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>
|
||||
@@ -335,14 +368,14 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
/// <summary>
|
||||
/// Gets random points around the anomaly based on the given parameters.
|
||||
/// </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);
|
||||
|
||||
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
|
||||
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 tilerefs = grid.GetLocalTilesIntersecting(
|
||||
|
||||
Reference in New Issue
Block a user