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:
Ed
2024-01-27 05:52:07 +03:00
committed by GitHub
parent 149654be88
commit de9d7aed17
17 changed files with 768 additions and 285 deletions

View File

@@ -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.

View File

@@ -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();
}

View File

@@ -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";
}

View File

@@ -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();
}

View File

@@ -0,0 +1,6 @@
namespace Content.Shared.Anomaly.Effects;
public abstract class SharedEntityAnomalySystem : EntitySystem
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Shared.Anomaly.Effects;
public abstract class SharedTileAnomalySystem : EntitySystem
{
}

View File

@@ -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;
}