Salvage magnet revamp (#23119)

* Generic offering window

* More work

* weh

* Parity

* Progression meter

* magnet

* rona

* PG asteroid work

* code red

* Asteroid spawnings

* clams

* a

* Marker fixes

* More fixes

* Workings of biome asteroids

* A

* Fix this loading code

* a

* Fix masking

* weh

* Fixes

* Magnet claiming

* toe

* petogue

* magnet

* Bunch of fixes

* Fix default

* Fixes

* asteroids

* Fix offerings

* Localisation and a bunch of fixes

* a

* Fixes

* Preliminary draft

* Announcement fixes

* Fixes and bump spawn rate

* Fix asteroid spawns and UI

* More fixes

* Expeditions fix

* fix

* Gravity

* Fix announcement rounding

* a

* Offset tweak

* sus

* jankass

* Fix merge
This commit is contained in:
metalgearsloth
2024-01-04 14:25:32 +11:00
committed by GitHub
parent 98f5f47355
commit bf79acd127
66 changed files with 2257 additions and 1252 deletions

View File

@@ -1638,12 +1638,6 @@ namespace Content.Shared.CCVar
* Salvage
*/
/// <summary>
/// Forced salvage map prototype name (if empty, randomly selected)
/// </summary>
public static readonly CVarDef<string>
SalvageForced = CVarDef.Create("salvage.forced", "", CVar.SERVERONLY);
/// <summary>
/// Duration for missions
/// </summary>

View File

@@ -12,6 +12,12 @@ namespace Content.Shared.Parallax.Biomes;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), Access(typeof(SharedBiomeSystem))]
public sealed partial class BiomeComponent : Component
{
/// <summary>
/// Do we load / deload.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite), Access(Other = AccessPermissions.ReadWriteExecute)]
public bool Enabled = true;
[ViewVariables(VVAccess.ReadWrite), DataField("seed")]
[AutoNetworkedField]
public int Seed = -1;

View File

@@ -94,6 +94,14 @@ public abstract class SharedBiomeSystem : EntitySystem
return true;
}
return TryGetTile(indices, layers, seed, grid, out tile);
}
/// <summary>
/// Gets the underlying biome tile, ignoring any existing tile that may be there.
/// </summary>
public bool TryGetTile(Vector2i indices, List<IBiomeLayer> layers, int seed, MapGridComponent? grid, [NotNullWhen(true)] out Tile? tile)
{
for (var i = layers.Count - 1; i >= 0; i--)
{
var layer = layers[i];

View File

@@ -2,7 +2,7 @@ namespace Content.Shared.Procedural;
public sealed class Dungeon
{
public readonly List<DungeonRoom> Rooms = new();
public readonly List<DungeonRoom> Rooms;
/// <summary>
/// Hashset of the tiles across all rooms.
@@ -14,4 +14,14 @@ public sealed class Dungeon
public readonly HashSet<Vector2i> CorridorTiles = new();
public readonly HashSet<Vector2i> CorridorExteriorTiles = new();
public Dungeon()
{
Rooms = new List<DungeonRoom>();
}
public Dungeon(List<DungeonRoom> rooms)
{
Rooms = rooms;
}
}

View File

@@ -0,0 +1,58 @@
using Content.Shared.Maps;
using Robust.Shared.Noise;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.DungeonGenerators;
/// <summary>
/// Generates dungeon flooring based on the specified noise.
/// </summary>
public sealed partial class NoiseDunGen : IDunGen
{
/*
* Floodfills out from 0 until it finds a valid tile.
* From here it then floodfills until it can no longer fill in an area and generates a dungeon from that.
*/
// At some point we may want layers masking each other like a simpler version of biome code but for now
// we'll just make it circular.
/// <summary>
/// How many areas of noise to fill out. Useful if we just want 1 blob area to fill out.
/// </summary>
[DataField]
public int Iterations = int.MaxValue;
/// <summary>
/// Cap on how many tiles to include.
/// </summary>
[DataField]
public int TileCap = 128;
/// <summary>
/// Standard deviation of tilecap.
/// </summary>
[DataField]
public float CapStd = 8f;
[DataField(required: true)]
public List<NoiseDunGenLayer> Layers = new();
}
[DataRecord]
public record struct NoiseDunGenLayer
{
/// <summary>
/// If the noise value is above this then it gets output.
/// </summary>
[DataField]
public float Threshold;
[DataField(required: true)]
public string Tile;
[DataField(required: true)]
public FastNoiseLite Noise;
}

View File

@@ -0,0 +1,21 @@
using Content.Shared.Parallax.Biomes.Markers;
using Content.Shared.Procedural.PostGeneration;
using Content.Shared.Random;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Spawns the specified marker layer on top of the dungeon rooms.
/// </summary>
public sealed partial class BiomeMarkerLayerPostGen : IPostDunGen
{
/// <summary>
/// How many times to spawn marker layers; can duplicate.
/// </summary>
[DataField]
public int Count = 6;
[DataField(required: true)]
public ProtoId<WeightedRandomPrototype> MarkerTemplate;
}

View File

@@ -0,0 +1,15 @@
using Content.Shared.Parallax.Biomes;
using Content.Shared.Procedural.PostGeneration;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Generates a biome on top of valid tiles, then removes the biome when done.
/// Only works if no existing biome is present.
/// </summary>
public sealed partial class BiomePostGen : IPostDunGen
{
[DataField(required: true)]
public ProtoId<BiomeTemplatePrototype> BiomeTemplate;
}

View File

@@ -0,0 +1,16 @@
using Content.Shared.Procedural;
namespace Content.Shared.Salvage.Magnet;
/// <summary>
/// Asteroid offered for the magnet.
/// </summary>
public record struct AsteroidOffering : ISalvageMagnetOffering
{
public DungeonConfigPrototype DungeonConfig;
/// <summary>
/// Calculated marker layers for the asteroid.
/// </summary>
public Dictionary<string, int> MarkerLayers;
}

View File

@@ -0,0 +1,6 @@
namespace Content.Shared.Salvage.Magnet;
public interface ISalvageMagnetOffering
{
}

View File

@@ -0,0 +1,12 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Salvage.Magnet;
/// <summary>
/// Claim an offer from the magnet UI.
/// </summary>
[Serializable, NetSerializable]
public sealed class MagnetClaimOfferEvent : BoundUserInterfaceMessage
{
public int Index;
}

View File

@@ -0,0 +1,22 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Salvage.Magnet;
[Serializable, NetSerializable]
public sealed class SalvageMagnetBoundUserInterfaceState : BoundUserInterfaceState
{
public TimeSpan? EndTime;
public TimeSpan NextOffer;
public TimeSpan Cooldown;
public TimeSpan Duration;
public int ActiveSeed;
public List<int> Offers;
public SalvageMagnetBoundUserInterfaceState(List<int> offers)
{
Offers = offers;
}
}

View File

@@ -0,0 +1,6 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Salvage.Magnet;
[Serializable, NetSerializable]
public enum SalvageMagnetUiKey : byte { Key }

View File

@@ -0,0 +1,9 @@
namespace Content.Shared.Salvage.Magnet;
/// <summary>
/// Asteroid offered for the magnet.
/// </summary>
public record struct SalvageOffering : ISalvageMagnetOffering
{
public SalvageMapPrototype SalvageMap;
}

View File

@@ -0,0 +1,15 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.Salvage;
[Prototype]
public sealed class SalvageMapPrototype : IPrototype
{
[ViewVariables] [IdDataField] public string ID { get; } = default!;
/// <summary>
/// Relative directory path to the given map, i.e. `Maps/Salvage/template.yml`
/// </summary>
[DataField(required: true)] public ResPath MapPath;
}

View File

@@ -1,31 +0,0 @@
using Content.Shared.Construction.Prototypes;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Salvage;
public abstract partial class SharedSalvageMagnetComponent : Component
{
/// <summary>
/// The machine part that affects the attaching and cooldown times
/// </summary>
[DataField("machinePartDelay", customTypeSerializer: typeof(PrototypeIdSerializer<MachinePartPrototype>)), ViewVariables(VVAccess.ReadWrite)]
public string MachinePartDelay = "Capacitor";
/// <summary>
/// A multiplier applied to the attaching and cooldown times for each level of <see cref="MachinePartDelay"/>
/// </summary>
[DataField("partRatingDelay"), ViewVariables(VVAccess.ReadWrite)]
public float PartRatingDelay = 0.75f;
}
[Serializable, NetSerializable]
public enum SalvageMagnetVisuals : byte
{
ChargeState,
Ready,
ReadyBlinking,
Unready,
UnreadyBlinking
}

View File

@@ -0,0 +1,69 @@
using Content.Shared.Procedural;
using Content.Shared.Procedural.PostGeneration;
using Content.Shared.Random.Helpers;
using Content.Shared.Salvage.Magnet;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.Salvage;
public abstract partial class SharedSalvageSystem
{
private readonly List<SalvageMapPrototype> _salvageMaps = new();
private readonly List<ProtoId<DungeonConfigPrototype>> _asteroidConfigs = new()
{
"BlobAsteroid",
"ClusterAsteroid",
"SpindlyAsteroid",
"SwissCheeseAsteroid"
};
public ISalvageMagnetOffering GetSalvageOffering(int seed)
{
var rand = new System.Random(seed);
// Asteroid seed
if (seed % 2 == 0)
{
var config = _asteroidConfigs[rand.Next(_asteroidConfigs.Count)];
var layerRand = new System.Random(seed);
var configProto = _proto.Index(config);
var layers = new Dictionary<string, int>();
// If we ever add more random layers will need to Next on these.
foreach (var layer in configProto.PostGeneration)
{
switch (layer)
{
case BiomeMarkerLayerPostGen marker:
for (var i = 0; i < marker.Count; i++)
{
var proto = _proto.Index(marker.MarkerTemplate).Pick(layerRand);
var layerCount = layers.GetOrNew(proto);
layerCount++;
layers[proto] = layerCount;
}
break;
}
}
return new AsteroidOffering
{
DungeonConfig = configProto,
MarkerLayers = layers,
};
}
// Salvage map seed
_salvageMaps.Clear();
_salvageMaps.AddRange(_proto.EnumeratePrototypes<SalvageMapPrototype>());
var mapIndex = rand.Next(_salvageMaps.Count);
var map = _salvageMaps[mapIndex];
return new SalvageOffering()
{
SalvageMap = map,
};
}
}

View File

@@ -15,7 +15,7 @@ using Robust.Shared.Utility;
namespace Content.Shared.Salvage;
public abstract class SharedSalvageSystem : EntitySystem
public abstract partial class SharedSalvageSystem : EntitySystem
{
[Dependency] protected readonly IConfigurationManager CfgManager = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;