diff --git a/Content.Server/Anomaly/Effects/EntityAnomalySystem.cs b/Content.Server/Anomaly/Effects/EntityAnomalySystem.cs index ee4e2ac115..9bfc48f4ba 100644 --- a/Content.Server/Anomaly/Effects/EntityAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/EntityAnomalySystem.cs @@ -1,18 +1,16 @@ -using System.Linq; -using System.Numerics; +using Content.Shared.Anomaly; using Content.Shared.Anomaly.Components; +using Content.Shared.Anomaly.Effects; using Content.Shared.Anomaly.Effects.Components; -using Content.Shared.Physics; using Robust.Shared.Map; -using Robust.Shared.Physics; -using Robust.Shared.Physics.Components; -using Robust.Shared.Prototypes; +using Robust.Shared.Map.Components; using Robust.Shared.Random; namespace Content.Server.Anomaly.Effects; -public sealed class EntityAnomalySystem : EntitySystem +public sealed class EntityAnomalySystem : SharedEntityAnomalySystem { + [Dependency] private readonly SharedAnomalySystem _anomaly = default!; [Dependency] private readonly IMapManager _map = default!; [Dependency] private readonly IRobustRandom _random = default!; @@ -22,84 +20,78 @@ public sealed class EntityAnomalySystem : EntitySystem SubscribeLocalEvent(OnPulse); SubscribeLocalEvent(OnSupercritical); SubscribeLocalEvent(OnStabilityChanged); + SubscribeLocalEvent(OnSeverityChanged); + SubscribeLocalEvent(OnShutdown); } - private void OnPulse(EntityUid uid, EntitySpawnAnomalyComponent component, ref AnomalyPulseEvent args) + private void OnPulse(Entity component, ref AnomalyPulseEvent args) { - if (!component.SpawnOnPulse) - return; - - var range = component.SpawnRange * args.Stability; - var amount = (int) (component.MaxSpawnAmount * args.Severity + 0.5f); - - var xform = Transform(uid); - SpawnEntitesOnOpenTiles(component, xform, amount, range, component.Spawns); - } - - private void OnSupercritical(EntityUid uid, EntitySpawnAnomalyComponent component, ref AnomalySupercriticalEvent args) - { - if (!component.SpawnOnSuperCritical) - return; - - var xform = Transform(uid); - // A cluster of entities - SpawnEntitesOnOpenTiles(component, xform, component.MaxSpawnAmount, component.SpawnRange, component.Spawns); - // And so much meat (for the meat anomaly at least) - SpawnEntitesOnOpenTiles(component, xform, component.MaxSpawnAmount, component.SpawnRange, component.SuperCriticalSpawns); - } - - private void OnStabilityChanged(EntityUid uid, EntitySpawnAnomalyComponent component, ref AnomalyStabilityChangedEvent args) - { - if (!component.SpawnOnStabilityChanged) - return; - - var range = component.SpawnRange * args.Stability; - var amount = (int) (component.MaxSpawnAmount * args.Stability + 0.5f); - - var xform = Transform(uid); - SpawnEntitesOnOpenTiles(component, xform, amount, range, component.Spawns); - } - - private void SpawnEntitesOnOpenTiles(EntitySpawnAnomalyComponent component, TransformComponent xform, int amount, float radius, List spawns) - { - if (!component.Spawns.Any()) - return; - - if (!_map.TryGetGrid(xform.GridUid, out var grid)) - return; - - var localpos = xform.Coordinates.Position; - var tilerefs = grid.GetLocalTilesIntersecting( - new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))).ToArray(); - - if (tilerefs.Length == 0) - return; - - _random.Shuffle(tilerefs); - var physQuery = GetEntityQuery(); - var amountCounter = 0; - foreach (var tileref in tilerefs) + foreach (var entry in component.Comp.Entries) { - 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) + if (!entry.Settings.SpawnOnPulse) continue; - amountCounter++; - Spawn(_random.Pick(spawns), tileref.GridIndices.ToEntityCoordinates(xform.GridUid.Value, _map)); - if (amountCounter >= amount) - return; + + SpawnEntities(component, entry, args.Stability, args.Severity); + } + } + + private void OnSupercritical(Entity component, ref AnomalySupercriticalEvent args) + { + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnSuperCritical) + continue; + + SpawnEntities(component, entry, 1, 1); + } + } + + private void OnShutdown(Entity component, ref AnomalyShutdownEvent args) + { + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnShutdown || args.Supercritical) + continue; + + SpawnEntities(component, entry, 1, 1); + } + } + + private void OnStabilityChanged(Entity component, ref AnomalyStabilityChangedEvent args) + { + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnStabilityChanged) + continue; + + SpawnEntities(component, entry, args.Stability, args.Severity); + } + } + + private void OnSeverityChanged(Entity component, ref AnomalySeverityChangedEvent args) + { + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnSeverityChanged) + continue; + + SpawnEntities(component, entry, args.Stability, args.Severity); + } + } + + private void SpawnEntities(Entity anomaly, EntitySpawnSettingsEntry entry, float stability, float severity) + { + var xform = Transform(anomaly); + if (!TryComp(xform.GridUid, out var grid)) + return; + + var tiles = _anomaly.GetSpawningPoints(anomaly, stability, severity, entry.Settings); + if (tiles == null) + return; + + foreach (var tileref in tiles) + { + Spawn(_random.Pick(entry.Spawns), tileref.GridIndices.ToEntityCoordinates(xform.GridUid.Value, _map)); } } } diff --git a/Content.Server/Anomaly/Effects/TileAnomalySystem.cs b/Content.Server/Anomaly/Effects/TileAnomalySystem.cs index 08ec3a1c93..c1487cfc8c 100644 --- a/Content.Server/Anomaly/Effects/TileAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/TileAnomalySystem.cs @@ -1,41 +1,101 @@ +using System.Linq; using System.Numerics; +using Content.Shared.Anomaly; using Content.Shared.Anomaly.Components; +using Content.Shared.Anomaly.Effects; using Content.Shared.Anomaly.Effects.Components; using Content.Shared.Maps; using Robust.Shared.Map; +using Robust.Shared.Map.Components; using Robust.Shared.Random; namespace Content.Server.Anomaly.Effects; -public sealed class TileAnomalySystem : EntitySystem +public sealed class TileAnomalySystem : SharedTileAnomalySystem { - [Dependency] private readonly IMapManager _map = default!; - [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedAnomalySystem _anomaly = default!; [Dependency] private readonly ITileDefinitionManager _tiledef = default!; [Dependency] private readonly TileSystem _tile = default!; /// public override void Initialize() { - SubscribeLocalEvent(OnSeverityChanged); + SubscribeLocalEvent(OnPulse); + SubscribeLocalEvent(OnSupercritical); + SubscribeLocalEvent(OnStabilityChanged); + SubscribeLocalEvent(OnSeverityChanged); + SubscribeLocalEvent(OnShutdown); } - private void OnSeverityChanged(EntityUid uid, TileSpawnAnomalyComponent component, ref AnomalyStabilityChangedEvent args) + private void OnPulse(Entity component, ref AnomalyPulseEvent args) { - var xform = Transform(uid); - if (!_map.TryGetGrid(xform.GridUid, out var grid)) + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnPulse) + continue; + + SpawnTiles(component, entry, args.Stability, args.Severity); + } + } + + private void OnSupercritical(Entity component, ref AnomalySupercriticalEvent args) + { + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnSuperCritical) + continue; + + SpawnTiles(component, entry, 1, 1); + } + } + + private void OnShutdown(Entity component, ref AnomalyShutdownEvent args) + { + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnShutdown || args.Supercritical) + continue; + + SpawnTiles(component, entry, 1, 1); + } + } + + private void OnStabilityChanged(Entity component, ref AnomalyStabilityChangedEvent args) + { + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnStabilityChanged) + continue; + + SpawnTiles(component, entry, args.Stability, args.Severity); + } + } + + private void OnSeverityChanged(Entity component, ref AnomalySeverityChangedEvent args) + { + foreach (var entry in component.Comp.Entries) + { + if (!entry.Settings.SpawnOnSeverityChanged) + continue; + + SpawnTiles(component, entry, args.Stability, args.Severity); + } + } + + private void SpawnTiles(Entity anomaly, TileSpawnSettingsEntry entry, float stability, float severity) + { + var xform = Transform(anomaly); + if (!TryComp(xform.GridUid, out var grid)) return; - var radius = component.SpawnRange * args.Stability; - var fleshTile = (ContentTileDefinition) _tiledef[component.FloorTileId]; - var localpos = xform.Coordinates.Position; - var tilerefs = grid.GetLocalTilesIntersecting( - new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))); - foreach (var tileref in tilerefs) + var tiles = _anomaly.GetSpawningPoints(anomaly, stability, severity, entry.Settings); + if (tiles == null) + return; + + foreach (var tileref in tiles) { - if (!_random.Prob(component.SpawnChance)) - continue; - _tile.ReplaceTile(tileref, fleshTile); + var tile = (ContentTileDefinition) _tiledef[entry.Floor]; + _tile.ReplaceTile(tileref, tile); } } } diff --git a/Content.Shared/Anomaly/Components/AnomalyComponent.cs b/Content.Shared/Anomaly/Components/AnomalyComponent.cs index 0e83861863..89afbb0122 100644 --- a/Content.Shared/Anomaly/Components/AnomalyComponent.cs +++ b/Content.Shared/Anomaly/Components/AnomalyComponent.cs @@ -268,13 +268,13 @@ public readonly record struct AnomalyShutdownEvent(EntityUid Anomaly, bool Super /// /// The anomaly being changed [ByRefEvent] -public readonly record struct AnomalySeverityChangedEvent(EntityUid Anomaly, float Severity); +public readonly record struct AnomalySeverityChangedEvent(EntityUid Anomaly, float Stability, float Severity); /// /// Event broadcast when an anomaly's stability is changed. /// [ByRefEvent] -public readonly record struct AnomalyStabilityChangedEvent(EntityUid Anomaly, float Stability); +public readonly record struct AnomalyStabilityChangedEvent(EntityUid Anomaly, float Stability, float Severity); /// /// Event broadcast when an anomaly's health is changed. diff --git a/Content.Shared/Anomaly/Effects/Components/EntitySpawnAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/EntitySpawnAnomalyComponent.cs index 7a816e4312..07cd5c6825 100644 --- a/Content.Shared/Anomaly/Effects/Components/EntitySpawnAnomalyComponent.cs +++ b/Content.Shared/Anomaly/Effects/Components/EntitySpawnAnomalyComponent.cs @@ -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 +{ + /// + /// All types of entity spawns with their settings + /// + [DataField] + public List Entries = new(); +} + +[DataRecord] +public partial record struct EntitySpawnSettingsEntry() { /// /// A list of entities that are random picked to be spawned on each pulse /// - [DataField] - public List Spawns = new(); + public List Spawns { get; set; } = new(); - /// - /// A list of entities that are random picked to be spawned when supercritical; - /// - [DataField] - public List SuperCriticalSpawns = new(); - - /// - /// The maximum number of entities that spawn per pulse - /// scales with severity. - /// - [DataField("maxSpawnAmount"), ViewVariables(VVAccess.ReadWrite)] - public int MaxSpawnAmount = 7; - - /// - /// The maximum radius the entities will spawn in. - /// Also governs the maximum reach of flesh tiles - /// scales with stability - /// - [DataField("spawnRange"), ViewVariables(VVAccess.ReadWrite)] - public float SpawnRange = 5f; - - /// - /// Whether or not anomaly spawns entities on Pulse - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public bool SpawnOnPulse = true; - - /// - /// Whether or not anomaly spawns entities on SuperCritical - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public bool SpawnOnSuperCritical = true; - - /// - /// Whether or not anomaly spawns entities on StabilityChanged - /// The idea was to spawn entities either on Pulse/Supercritical OR StabilityChanged - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public bool SpawnOnStabilityChanged = false; + public AnomalySpawnSettings Settings { get; set; } = new(); } diff --git a/Content.Shared/Anomaly/Effects/Components/TileSpawnAnomaly.cs b/Content.Shared/Anomaly/Effects/Components/TileSpawnAnomaly.cs deleted file mode 100644 index 7e3125ba20..0000000000 --- a/Content.Shared/Anomaly/Effects/Components/TileSpawnAnomaly.cs +++ /dev/null @@ -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 -{ - /// - /// The maximum radius of tiles scales with stability - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float SpawnRange = 5f; - - /// - /// The probability a tile will spawn. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float SpawnChance = 0.33f; - - /// - /// The tile that is spawned by the anomaly's effect - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public ProtoId FloorTileId = "FloorFlesh"; -} diff --git a/Content.Shared/Anomaly/Effects/Components/TileSpawnAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/TileSpawnAnomalyComponent.cs new file mode 100644 index 0000000000..1105589d4e --- /dev/null +++ b/Content.Shared/Anomaly/Effects/Components/TileSpawnAnomalyComponent.cs @@ -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 +{ + /// + /// All types of floors spawns with their settings + /// + [DataField] + public List Entries = new(); +} + +[DataRecord] +public partial record struct TileSpawnSettingsEntry() +{ + /// + /// The tile that is spawned by the anomaly's effect + /// + public ProtoId Floor { get; set; } = default!; + + public AnomalySpawnSettings Settings { get; set; } = new(); +} diff --git a/Content.Shared/Anomaly/Effects/SharedEntityAnomalySystem.cs b/Content.Shared/Anomaly/Effects/SharedEntityAnomalySystem.cs new file mode 100644 index 0000000000..28732f4022 --- /dev/null +++ b/Content.Shared/Anomaly/Effects/SharedEntityAnomalySystem.cs @@ -0,0 +1,6 @@ + +namespace Content.Shared.Anomaly.Effects; + +public abstract class SharedEntityAnomalySystem : EntitySystem +{ +} diff --git a/Content.Shared/Anomaly/Effects/SharedTileAnomalySystem.cs b/Content.Shared/Anomaly/Effects/SharedTileAnomalySystem.cs new file mode 100644 index 0000000000..199c6b6f13 --- /dev/null +++ b/Content.Shared/Anomaly/Effects/SharedTileAnomalySystem.cs @@ -0,0 +1,6 @@ + +namespace Content.Shared.Anomaly.Effects; + +public abstract class SharedTileAnomalySystem : EntitySystem +{ +} diff --git a/Content.Shared/Anomaly/SharedAnomalySystem.cs b/Content.Shared/Anomaly/SharedAnomalySystem.cs index c014ff90e1..dcf7cae215 100644 --- a/Content.Shared/Anomaly/SharedAnomalySystem.cs +++ b/Content.Shared/Anomaly/SharedAnomalySystem.cs @@ -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); } } + + /// + /// Gets random points around the anomaly based on the given parameters. + /// + public List? GetSpawningPoints(EntityUid uid, float stability, float severity, AnomalySpawnSettings settings) + { + var xform = Transform(uid); + + if (!TryComp(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(); + var resultList = new List(); + 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() +{ + /// + /// should entities block spawning? + /// + public bool CanSpawnOnEntities { get; set; } = true; + + /// + /// The minimum number of entities that spawn per pulse + /// + public int MinAmount { get; set; } = 0; + + /// + /// The maximum number of entities that spawn per pulse + /// scales with severity. + /// + public int MaxAmount { get; set; } = 1; + + /// + /// The distance from the anomaly in which the entities will not appear + /// + public float MinRange { get; set; } = 0f; + + /// + /// The maximum radius the entities will spawn in. + /// + public float MaxRange { get; set; } = 1f; + + /// + /// Whether or not anomaly spawns entities on Pulse + /// + public bool SpawnOnPulse { get; set; } = false; + + /// + /// Whether or not anomaly spawns entities on SuperCritical + /// + public bool SpawnOnSuperCritical { get; set; } = false; + + /// + /// Whether or not anomaly spawns entities when destroyed + /// + public bool SpawnOnShutdown { get; set; } = false; + + /// + /// Whether or not anomaly spawns entities on StabilityChanged + /// + public bool SpawnOnStabilityChanged { get; set; } = false; + + /// + /// Whether or not anomaly spawns entities on SeverityChanged + /// + public bool SpawnOnSeverityChanged { get; set; } = false; } diff --git a/Resources/Prototypes/Entities/Effects/wallspawn.yml b/Resources/Prototypes/Entities/Effects/wallspawn.yml index 2010b8e73e..f1bd236a8a 100644 --- a/Resources/Prototypes/Entities/Effects/wallspawn.yml +++ b/Resources/Prototypes/Entities/Effects/wallspawn.yml @@ -26,15 +26,57 @@ prototype: AsteroidRock - type: entity - id: WallSpawnAsteroidCrab + id: WallSpawnAsteroidUraniumCrab parent: WallSpawnAsteroid components: - type: SpawnOnDespawn - prototype: AsteroidRockCrab + prototype: AsteroidRockUraniumCrab - type: entity - id: WallSpawnAsteroidCrab1 + id: WallSpawnAsteroidUranium parent: WallSpawnAsteroid components: - type: SpawnOnDespawn - prototype: AsteroidRockCrab1 + prototype: AsteroidRockUranium + +- type: entity + id: WallSpawnAsteroidQuartzCrab + parent: WallSpawnAsteroid + components: + - type: SpawnOnDespawn + prototype: AsteroidRockQuartzCrab + +- type: entity + id: WallSpawnAsteroidQuartz + parent: WallSpawnAsteroid + components: + - type: SpawnOnDespawn + prototype: AsteroidRockQuartz + +- type: entity + id: WallSpawnAsteroidSilverCrab + parent: WallSpawnAsteroid + components: + - type: SpawnOnDespawn + prototype: AsteroidRockSilverCrab + +- type: entity + id: WallSpawnAsteroidSilver + parent: WallSpawnAsteroid + components: + - type: SpawnOnDespawn + prototype: AsteroidRockSilver + +- type: entity + id: WallSpawnAsteroidIronCrab + parent: WallSpawnAsteroid + components: + - type: SpawnOnDespawn + prototype: AsteroidRockTinCrab + +- type: entity + id: WallSpawnAsteroidIron + parent: WallSpawnAsteroid + components: + - type: SpawnOnDespawn + prototype: AsteroidRockTin \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml index 6d2149965f..c81c840fb0 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml @@ -16,8 +16,26 @@ - AnomalyFlesh - AnomalyBluespace - AnomalyIce - - AnomalyRock + - RandomRockAnomalySpawner - AnomalyLiquid - AnomalyFlora chance: 1 offset: 0.15 # not to put it higher. The anomaly sychnronizer looks for anomalies within this radius, and if the radius is higher, the anomaly can be attracted from a neighboring tile. + +- type: entity + id: RandomRockAnomalySpawner + parent: MarkerBase + components: + - type: Sprite + layers: + - state: red + - sprite: Structures/Specific/anomaly.rsi + state: anom6 + - type: RandomSpawner + prototypes: + - AnomalyRockIron + - AnomalyRockSilver + - AnomalyRockQuartz + - AnomalyRockUranium + chance: 1 + offset: 0.15 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/asteroidcrab.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/asteroidcrab.yml deleted file mode 100644 index 4c4b969335..0000000000 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/asteroidcrab.yml +++ /dev/null @@ -1,31 +0,0 @@ -- type: entity - name: Asteroid Crab Spawner - id: AsteroidCrabSpawner - parent: MarkerBase - components: - - type: Sprite - layers: - - state: red - - sprite: Structures/Walls/rock.rsi - state: rock_asteroid_ore - - type: RandomSpawner - prototypes: - - AsteroidRockCrab - - AsteroidRockCrab1 - chance: 1 - -- type: entity - name: Rock Anom Crab Spawner - id: RockAnomCrabSpawner - parent: MarkerBase - components: - - type: Sprite - layers: - - state: red - - sprite: Structures/Walls/rock.rsi - state: rock_asteroid_ore - - type: RandomSpawner - prototypes: - - WallSpawnAsteroidCrab - - WallSpawnAsteroidCrab1 - chance: 1 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Misc/ice_crust.yml b/Resources/Prototypes/Entities/Objects/Misc/ice_crust.yml index ad1f876675..bc3488aaf4 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/ice_crust.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/ice_crust.yml @@ -10,8 +10,7 @@ - type: MeleeSound soundGroups: Brute: - path: - "/Audio/Weapons/slash.ogg" + collection: GlassBreak - type: Sprite sprite: Objects/Misc/ice_crust.rsi layers: diff --git a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml index aecef8c637..56c970929c 100644 --- a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml +++ b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml @@ -147,16 +147,75 @@ color: "#cb5b7e" castShadows: false - type: TileSpawnAnomaly - floorTileId: FloorFlesh + entries: + - settings: + spawnOnPulse: true + spawnOnStabilityChanged: true + minAmount: 3 + maxAmount: 7 + maxRange: 4 + floor: FloorFlesh + - settings: + spawnOnSuperCritical: true + minAmount: 10 + maxAmount: 30 + maxRange: 10 + floor: FloorFlesh - type: EntitySpawnAnomaly - superCriticalSpawns: - - FleshKudzu - spawns: - - MobFleshJared - - MobFleshGolem - - MobFleshClamp - - MobFleshLover - - FleshBlocker + entries: + - settings: + spawnOnPulse: true + minAmount: 1 + maxAmount: 4 + minRange: 1.5 + maxRange: 2.5 + spawns: + - FleshBlocker + - settings: + spawnOnPulse: true + maxAmount: 3 + minRange: 3 + maxRange: 4.5 + spawns: + - MobFleshJared + - MobFleshGolem + - MobFleshClamp + - MobFleshLover + - settings: + spawnOnSuperCritical: true + minAmount: 10 + maxAmount: 15 + minRange: 5 + maxRange: 15 + spawns: + - FleshBlocker + - settings: + spawnOnSuperCritical: true + minAmount: 5 + maxAmount: 10 + maxRange: 8 + spawns: + - MobFleshJared + - MobFleshGolem + - MobFleshClamp + - MobFleshLover + - settings: + spawnOnSuperCritical: true + minAmount: 5 + maxAmount: 8 + maxRange: 10 + spawns: + - FleshKudzu + - settings: + spawnOnShutdown: true + maxAmount: 2 + maxRange: 1 + spawns: + - MobFleshJared + - MobFleshGolem + - MobFleshClamp + - MobFleshLover + - FleshKudzu - type: entity id: AnomalyBluespace @@ -241,12 +300,14 @@ projectilePrototype: ProjectileIcicle targetNonSentientChance: 0.1 - type: EntitySpawnAnomaly - spawns: - - IceCrust - maxSpawnAmount: 17 - spawnOnPulse: false - spawnOnSuperCritical: false - spawnOnStabilityChanged: true + entries: + - settings: + spawnOnStabilityChanged: true + minAmount: 5 + maxAmount: 15 + maxRange: 4 + spawns: + - IceCrust - type: TempAffectingAnomaly tempChangePerSecond: -25 hotspotExposeTemperature: -1000 @@ -256,8 +317,9 @@ spawnRadius: 0 - type: entity - id: AnomalyRock + id: AnomalyRockBase parent: BaseAnomaly + abstract: true suffix: Rock components: - type: Anomaly @@ -276,18 +338,219 @@ color: "#5ca8cb" castShadows: false - type: TileSpawnAnomaly - floorTileId: FloorAsteroidTile - spawnChance: 0.8 + entries: + - settings: + spawnOnPulse: true + minAmount: 15 + maxAmount: 20 + maxRange: 7.5 + floor: FloorAsteroidTile + - settings: + spawnOnSuperCritical: true + minAmount: 30 + maxAmount: 50 + maxRange: 12 + floor: FloorAsteroidTile + +- type: entity + id: AnomalyRockUranium + parent: AnomalyRockBase + suffix: Rock, Uranium + components: + - type: Sprite + color: "#52ff39" + - type: PointLight + radius: 2.0 + energy: 7.5 + color: "#52ff39" - type: EntitySpawnAnomaly - maxSpawnAmount: 50 - spawnRange: 10 - spawns: - - WallSpawnAsteroid - - RockAnomCrabSpawner - - CrystalSpawner - superCriticalSpawns: - - WallSpawnAsteroid - - SpawnMobOreCrab + entries: + - settings: + spawnOnPulse: true + minAmount: 8 + maxAmount: 15 + minRange: 4.5 + maxRange: 7.5 + spawns: + - WallSpawnAsteroid + - WallSpawnAsteroid + - WallSpawnAsteroidUranium + - WallSpawnAsteroidUraniumCrab + - settings: + spawnOnPulse: true + maxAmount: 3 + minRange: 2.5 + maxRange: 4.5 + spawns: + - CrystalGreen + - settings: + spawnOnSuperCritical: true + minAmount: 30 + maxAmount: 40 + minRange: 5 + maxRange: 15 + spawns: + - CrystalGreen + - WallSpawnAsteroid + - WallSpawnAsteroid + - WallSpawnAsteroidUraniumCrab + - settings: + spawnOnSuperCritical: true + minAmount: 6 + maxAmount: 10 + maxRange: 5 + spawns: + - MobSpawnCrabUranium + +- type: entity + id: AnomalyRockQuartz + parent: AnomalyRockBase + suffix: Rock, Quartz + components: + - type: Sprite + color: "#fb4747" + - type: PointLight + radius: 2.0 + energy: 7.5 + color: "#fb4747" + - type: EntitySpawnAnomaly + entries: + - settings: + spawnOnPulse: true + minAmount: 8 + maxAmount: 15 + minRange: 4.5 + maxRange: 7.5 + spawns: + - WallSpawnAsteroid + - WallSpawnAsteroid + - WallSpawnAsteroidQuartz + - WallSpawnAsteroidQuartzCrab + - settings: + spawnOnPulse: true + maxAmount: 3 + minRange: 2.5 + maxRange: 4.5 + spawns: + - CrystalGrey + - settings: + spawnOnSuperCritical: true + minAmount: 30 + maxAmount: 40 + minRange: 5 + maxRange: 15 + spawns: + - CrystalGrey + - WallSpawnAsteroid + - WallSpawnAsteroid + - WallSpawnAsteroidQuartzCrab + - settings: + spawnOnSuperCritical: true + minAmount: 6 + maxAmount: 10 + maxRange: 5 + spawns: + - MobSpawnCrabQuartz + +- type: entity + id: AnomalyRockSilver + parent: AnomalyRockBase + suffix: Rock, Silver + components: + - type: Sprite + color: "#47f8ff" + - type: PointLight + radius: 2.0 + energy: 7.5 + color: "#47f8ff" + - type: EntitySpawnAnomaly + entries: + - settings: + spawnOnPulse: true + minAmount: 8 + maxAmount: 15 + minRange: 4.5 + maxRange: 7.5 + spawns: + - WallSpawnAsteroid + - WallSpawnAsteroid + - WallSpawnAsteroidSilver + - WallSpawnAsteroidSilverCrab + - settings: + spawnOnPulse: true + maxAmount: 3 + minRange: 2.5 + maxRange: 4.5 + spawns: + - CrystalCyan + - settings: + spawnOnSuperCritical: true + minAmount: 30 + maxAmount: 40 + minRange: 5 + maxRange: 15 + spawns: + - CrystalCyan + - WallSpawnAsteroid + - WallSpawnAsteroid + - WallSpawnAsteroidSilverCrab + - settings: + spawnOnSuperCritical: true + minAmount: 6 + maxAmount: 10 + maxRange: 5 + spawns: + - MobSpawnCrabSilver + +- type: entity + id: AnomalyRockIron + parent: AnomalyRockBase + suffix: Rock, Iron + components: + - type: Sprite + color: "#ff8227" + - type: PointLight + radius: 2.0 + energy: 7.5 + color: "#ff8227" + - type: EntitySpawnAnomaly + entries: + - settings: + spawnOnPulse: true + minAmount: 8 + maxAmount: 15 + minRange: 4.5 + maxRange: 7.5 + spawns: + - WallSpawnAsteroid + - WallSpawnAsteroid + - WallSpawnAsteroidIron + - WallSpawnAsteroidIronCrab + - settings: + spawnOnPulse: true + maxAmount: 3 + minRange: 2.5 + maxRange: 4.5 + spawns: + - CrystalOrange + - settings: + spawnOnSuperCritical: true + minAmount: 30 + maxAmount: 40 + minRange: 5 + maxRange: 15 + spawns: + - CrystalOrange + - WallSpawnAsteroid + - WallSpawnAsteroid + - WallSpawnAsteroidIronCrab + - settings: + spawnOnSuperCritical: true + minAmount: 6 + maxAmount: 10 + maxRange: 5 + spawns: + - MobSpawnCrabIron - type: entity id: AnomalyFlora @@ -316,15 +579,35 @@ types: Slash: 0 - type: TileSpawnAnomaly - floorTileId: FloorAstroGrass - spawnRange: 6 + entries: + - settings: + spawnOnPulse: true + minAmount: 3 + maxAmount: 7 + maxRange: 5 + floor: FloorAstroGrass + - settings: + spawnOnSuperCritical: true + minAmount: 10 + maxAmount: 30 + maxRange: 15 + floor: FloorAstroGrass - type: EntitySpawnAnomaly - maxSpawnAmount: 15 - spawnRange: 6 - superCriticalSpawns: - - KudzuFlowerAngry - spawns: - - KudzuFlowerFriendly + entries: + - settings: + spawnOnPulse: true + minAmount: 2 + maxAmount: 5 + maxRange: 2 + spawns: + - KudzuFlowerFriendly + - settings: + spawnOnSuperCritical: true + minAmount: 5 + maxAmount: 10 + maxRange: 6 + spawns: + - KudzuFlowerAngry - type: entity id: AnomalyFloraBulb @@ -400,10 +683,14 @@ types: Slash: 1 - type: EntitySpawnAnomaly - superCriticalSpawns: - - ReagentSlimeSpawner - spawns: - - PuddleSparkle + entries: + - settings: + spawnOnSuperCritical: true + minAmount: 3 + maxAmount: 8 + maxRange: 2 + spawns: + - ReagentSlimeSpawner - type: SolutionContainerManager solutions: anomaly: diff --git a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml index d5c542a0a1..aa5f1421c7 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml @@ -148,6 +148,28 @@ state: rock_asteroid_west - state: rock_quartz +- type: entity + id: AsteroidRockQuartzCrab + parent: AsteroidRock + description: An ore vein rich with quartz. + suffix: Quartz Crab + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreQuartzCrab + - type: Sprite + layers: + - state: rock_asteroid + - map: [ "enum.EdgeLayer.South" ] + state: rock_asteroid_south + - map: [ "enum.EdgeLayer.East" ] + state: rock_asteroid_east + - map: [ "enum.EdgeLayer.North" ] + state: rock_asteroid_north + - map: [ "enum.EdgeLayer.West" ] + state: rock_asteroid_west + - state: rock_quartz + - type: entity id: AsteroidRockSilver parent: AsteroidRock @@ -169,6 +191,15 @@ - map: [ "enum.EdgeLayer.West" ] state: rock_asteroid_west - state: rock_silver + +- type: entity + id: AsteroidRockSilverCrab + parent: AsteroidRockSilver + suffix: Silver Crab + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreSilverCrab # Yes I know it drops steel but we may get smelting at some point - type: entity @@ -192,6 +223,15 @@ - map: [ "enum.EdgeLayer.West" ] state: rock_asteroid_west - state: rock_tin + +- type: entity + id: AsteroidRockTinCrab + parent: AsteroidRockTin + suffix: Iron + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreIronCrab - type: entity id: AsteroidRockUranium @@ -215,6 +255,14 @@ state: rock_asteroid_west - state: rock_uranium +- type: entity + id: AsteroidRockUraniumCrab + parent: AsteroidRockUranium + suffix: Uranium Crab + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreUraniumCrab - type: entity id: AsteroidRockBananium @@ -271,46 +319,6 @@ oreChance: 0.33 oreRarityPrototypeId: RandomOreDistributionStandard -- type: entity - id: AsteroidRockCrab - parent: AsteroidRock - name: asteroid rock - suffix: orecrab - description: An asteroid. - components: - - type: Sprite - sprite: Structures/Walls/rock.rsi - layers: - - state: rock_asteroid_ore - - map: [ "enum.EdgeLayer.South" ] - state: rock_asteroid_south - - map: [ "enum.EdgeLayer.East" ] - state: rock_asteroid_east - - map: [ "enum.EdgeLayer.North" ] - state: rock_asteroid_north - - map: [ "enum.EdgeLayer.West" ] - state: rock_asteroid_west - - type: OreVein - oreChance: 0.33 - oreRarityPrototypeId: OreCrab - -- type: entity - id: AsteroidRockCrab1 - parent: AsteroidRockCrab - components: - - type: Sprite - sprite: Structures/Walls/rock.rsi - layers: - - state: rock_asteroid_ore1 - - map: [ "enum.EdgeLayer.South" ] - state: rock_asteroid_south - - map: [ "enum.EdgeLayer.East" ] - state: rock_asteroid_east - - map: [ "enum.EdgeLayer.North" ] - state: rock_asteroid_north - - map: [ "enum.EdgeLayer.West" ] - state: rock_asteroid_west - - type: entity id: IronRock parent: AsteroidRock diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom6-pulse.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom6-pulse.png index f92a77a95e..cfeabdaa81 100644 Binary files a/Resources/Textures/Structures/Specific/anomaly.rsi/anom6-pulse.png and b/Resources/Textures/Structures/Specific/anomaly.rsi/anom6-pulse.png differ diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom6.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom6.png index 04c772bca1..14fc7d80c0 100644 Binary files a/Resources/Textures/Structures/Specific/anomaly.rsi/anom6.png and b/Resources/Textures/Structures/Specific/anomaly.rsi/anom6.png differ