Rock and Meat anom rework (try 2) (#24449)
* rework * bruh * all fixed * balance * bb * Update TileAnomalySystem.cs * Update EntityAnomalySystem.cs * spawn on shutdown variant * fix entites, fix DataRecord * fix some review * god forgive me * oh fuck wrong brench * Revert "oh fuck wrong brench" This reverts commit c81f57f7830c8e55fd47982500c57281af40b0dc.
This commit is contained in:
@@ -268,13 +268,13 @@ public readonly record struct AnomalyShutdownEvent(EntityUid Anomaly, bool Super
|
||||
/// </summary>
|
||||
/// <param name="Anomaly">The anomaly being changed</param>
|
||||
[ByRefEvent]
|
||||
public readonly record struct AnomalySeverityChangedEvent(EntityUid Anomaly, float Severity);
|
||||
public readonly record struct AnomalySeverityChangedEvent(EntityUid Anomaly, float Stability, float Severity);
|
||||
|
||||
/// <summary>
|
||||
/// Event broadcast when an anomaly's stability is changed.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly record struct AnomalyStabilityChangedEvent(EntityUid Anomaly, float Stability);
|
||||
public readonly record struct AnomalyStabilityChangedEvent(EntityUid Anomaly, float Stability, float Severity);
|
||||
|
||||
/// <summary>
|
||||
/// Event broadcast when an anomaly's health is changed.
|
||||
|
||||
@@ -1,53 +1,25 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Anomaly.Effects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedEntityAnomalySystem))]
|
||||
public sealed partial class EntitySpawnAnomalyComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// All types of entity spawns with their settings
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<EntitySpawnSettingsEntry> Entries = new();
|
||||
}
|
||||
|
||||
[DataRecord]
|
||||
public partial record struct EntitySpawnSettingsEntry()
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of entities that are random picked to be spawned on each pulse
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<EntProtoId> Spawns = new();
|
||||
public List<EntProtoId> Spawns { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// A list of entities that are random picked to be spawned when supercritical;
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<EntProtoId> SuperCriticalSpawns = new();
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of entities that spawn per pulse
|
||||
/// scales with severity.
|
||||
/// </summary>
|
||||
[DataField("maxSpawnAmount"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int MaxSpawnAmount = 7;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum radius the entities will spawn in.
|
||||
/// Also governs the maximum reach of flesh tiles
|
||||
/// scales with stability
|
||||
/// </summary>
|
||||
[DataField("spawnRange"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpawnRange = 5f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not anomaly spawns entities on Pulse
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool SpawnOnPulse = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not anomaly spawns entities on SuperCritical
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool SpawnOnSuperCritical = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not anomaly spawns entities on StabilityChanged
|
||||
/// The idea was to spawn entities either on Pulse/Supercritical OR StabilityChanged
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool SpawnOnStabilityChanged = false;
|
||||
public AnomalySpawnSettings Settings { get; set; } = new();
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Anomaly.Effects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class TileSpawnAnomalyComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum radius of tiles scales with stability
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpawnRange = 5f;
|
||||
|
||||
/// <summary>
|
||||
/// The probability a tile will spawn.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpawnChance = 0.33f;
|
||||
|
||||
/// <summary>
|
||||
/// The tile that is spawned by the anomaly's effect
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public ProtoId<ContentTileDefinition> FloorTileId = "FloorFlesh";
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Anomaly.Effects.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedTileAnomalySystem))]
|
||||
public sealed partial class TileSpawnAnomalyComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// All types of floors spawns with their settings
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<TileSpawnSettingsEntry> Entries = new();
|
||||
}
|
||||
|
||||
[DataRecord]
|
||||
public partial record struct TileSpawnSettingsEntry()
|
||||
{
|
||||
/// <summary>
|
||||
/// The tile that is spawned by the anomaly's effect
|
||||
/// </summary>
|
||||
public ProtoId<ContentTileDefinition> Floor { get; set; } = default!;
|
||||
|
||||
public AnomalySpawnSettings Settings { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
namespace Content.Shared.Anomaly.Effects;
|
||||
|
||||
public abstract class SharedEntityAnomalySystem : EntitySystem
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
namespace Content.Shared.Anomaly.Effects;
|
||||
|
||||
public abstract class SharedTileAnomalySystem : EntitySystem
|
||||
{
|
||||
}
|
||||
@@ -3,10 +3,13 @@ using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Weapons.Melee.Components;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
@@ -14,6 +17,8 @@ using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Shared.Anomaly;
|
||||
|
||||
@@ -28,6 +33,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 IRobustRandom _random = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
@@ -227,7 +233,7 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
component.Stability = Math.Clamp(newVal, 0, 1);
|
||||
Dirty(component);
|
||||
|
||||
var ev = new AnomalyStabilityChangedEvent(uid, component.Stability);
|
||||
var ev = new AnomalyStabilityChangedEvent(uid, component.Stability, component.Severity);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
}
|
||||
|
||||
@@ -250,7 +256,7 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
component.Severity = Math.Clamp(newVal, 0, 1);
|
||||
Dirty(component);
|
||||
|
||||
var ev = new AnomalySeverityChangedEvent(uid, component.Severity);
|
||||
var ev = new AnomalySeverityChangedEvent(uid, component.Stability, component.Severity);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
}
|
||||
|
||||
@@ -349,4 +355,122 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
RemComp(ent, super);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
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 localpos = xform.Coordinates.Position;
|
||||
var tilerefs = grid.GetLocalTilesIntersecting(
|
||||
new Box2(localpos + new Vector2(-settings.MaxRange, -settings.MaxRange), localpos + new Vector2(settings.MaxRange, settings.MaxRange))).ToList();
|
||||
|
||||
if (tilerefs.Count == 0)
|
||||
return null;
|
||||
|
||||
var physQuery = GetEntityQuery<PhysicsComponent>();
|
||||
var resultList = new List<TileRef>();
|
||||
while (resultList.Count() < amount)
|
||||
{
|
||||
if (tilerefs.Count() == 0)
|
||||
break;
|
||||
|
||||
var tileref = _random.Pick(tilerefs);
|
||||
var distance = MathF.Sqrt(MathF.Pow(tileref.X - xform.LocalPosition.X, 2) + MathF.Pow(tileref.Y - xform.LocalPosition.Y, 2));
|
||||
|
||||
//cut outer & inner circle
|
||||
if (distance > settings.MaxRange || distance < settings.MinRange)
|
||||
{
|
||||
tilerefs.Remove(tileref);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!settings.CanSpawnOnEntities)
|
||||
{
|
||||
var valid = true;
|
||||
foreach (var ent in grid.GetAnchoredEntities(tileref.GridIndices))
|
||||
{
|
||||
if (!physQuery.TryGetComponent(ent, out var body))
|
||||
continue;
|
||||
|
||||
if (body.BodyType != BodyType.Static ||
|
||||
!body.Hard ||
|
||||
(body.CollisionLayer & (int) CollisionGroup.Impassable) == 0)
|
||||
continue;
|
||||
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (!valid)
|
||||
{
|
||||
tilerefs.Remove(tileref);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
resultList.Add(tileref);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
}
|
||||
|
||||
[DataRecord]
|
||||
public partial record struct AnomalySpawnSettings()
|
||||
{
|
||||
/// <summary>
|
||||
/// should entities block spawning?
|
||||
/// </summary>
|
||||
public bool CanSpawnOnEntities { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum number of entities that spawn per pulse
|
||||
/// </summary>
|
||||
public int MinAmount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of entities that spawn per pulse
|
||||
/// scales with severity.
|
||||
/// </summary>
|
||||
public int MaxAmount { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The distance from the anomaly in which the entities will not appear
|
||||
/// </summary>
|
||||
public float MinRange { get; set; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum radius the entities will spawn in.
|
||||
/// </summary>
|
||||
public float MaxRange { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not anomaly spawns entities on Pulse
|
||||
/// </summary>
|
||||
public bool SpawnOnPulse { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not anomaly spawns entities on SuperCritical
|
||||
/// </summary>
|
||||
public bool SpawnOnSuperCritical { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not anomaly spawns entities when destroyed
|
||||
/// </summary>
|
||||
public bool SpawnOnShutdown { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not anomaly spawns entities on StabilityChanged
|
||||
/// </summary>
|
||||
public bool SpawnOnStabilityChanged { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not anomaly spawns entities on SeverityChanged
|
||||
/// </summary>
|
||||
public bool SpawnOnSeverityChanged { get; set; } = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user