Files
tbd-station-14/Content.Shared/Salvage/SharedSalvageSystem.cs
Tayrtahn c565b44965 Replace ValidatePrototypeId uses with ProtoId or EntProtoId (#38814)
* The easy ones

* For certain values of easy

* Easy test

* Hair

* Fix sandbox violations

* Sort usings
2025-07-07 21:57:05 +02:00

115 lines
4.0 KiB
C#

using System.Linq;
using Content.Shared.CCVar;
using Content.Shared.Dataset;
using Content.Shared.Procedural;
using Content.Shared.Procedural.Loot;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
using Content.Shared.Salvage.Expeditions;
using Content.Shared.Salvage.Expeditions.Modifiers;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Salvage;
public abstract partial class SharedSalvageSystem : EntitySystem
{
[Dependency] protected readonly IConfigurationManager CfgManager = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
/// <summary>
/// Main loot table for salvage expeditions.
/// </summary>
public static readonly ProtoId<SalvageLootPrototype> ExpeditionsLootProto = "SalvageLoot";
public string GetFTLName(LocalizedDatasetPrototype dataset, int seed)
{
var random = new System.Random(seed);
return $"{Loc.GetString(dataset.Values[random.Next(dataset.Values.Count)])}-{random.Next(10, 100)}-{(char) (65 + random.Next(26))}";
}
public SalvageMission GetMission(SalvageDifficultyPrototype difficulty, int seed)
{
// This is on shared to ensure the client display for missions and what the server generates are consistent
var modifierBudget = difficulty.ModifierBudget;
var rand = new System.Random(seed);
// Run budget in order of priority
// - Biome
// - Lighting
// - Atmos
var biome = GetMod<SalvageBiomeModPrototype>(rand, ref modifierBudget);
var light = GetBiomeMod<SalvageLightMod>(biome.ID, rand, ref modifierBudget);
var temp = GetBiomeMod<SalvageTemperatureMod>(biome.ID, rand, ref modifierBudget);
var air = GetBiomeMod<SalvageAirMod>(biome.ID, rand, ref modifierBudget);
var dungeon = GetBiomeMod<SalvageDungeonModPrototype>(biome.ID, rand, ref modifierBudget);
var factionProtos = _proto.EnumeratePrototypes<SalvageFactionPrototype>().ToList();
factionProtos.Sort((x, y) => string.Compare(x.ID, y.ID, StringComparison.Ordinal));
var faction = factionProtos[rand.Next(factionProtos.Count)];
var mods = new List<string>();
if (air.Description != string.Empty)
{
mods.Add(Loc.GetString(air.Description));
}
// only show the description if there is an atmosphere since wont matter otherwise
if (temp.Description != string.Empty && !air.Space)
{
mods.Add(Loc.GetString(temp.Description));
}
if (light.Description != string.Empty)
{
mods.Add(Loc.GetString(light.Description));
}
var duration = TimeSpan.FromSeconds(CfgManager.GetCVar(CCVars.SalvageExpeditionDuration));
return new SalvageMission(seed, dungeon.ID, faction.ID, biome.ID, air.ID, temp.Temperature, light.Color, duration, mods);
}
public T GetBiomeMod<T>(string biome, System.Random rand, ref float rating) where T : class, IPrototype, IBiomeSpecificMod
{
var mods = _proto.EnumeratePrototypes<T>().ToList();
mods.Sort((x, y) => string.Compare(x.ID, y.ID, StringComparison.Ordinal));
rand.Shuffle(mods);
foreach (var mod in mods)
{
if (mod.Cost > rating || (mod.Biomes != null && !mod.Biomes.Contains(biome)))
continue;
rating -= mod.Cost;
return mod;
}
throw new InvalidOperationException();
}
public T GetMod<T>(System.Random rand, ref float rating) where T : class, IPrototype, ISalvageMod
{
var mods = _proto.EnumeratePrototypes<T>().ToList();
mods.Sort((x, y) => string.Compare(x.ID, y.ID, StringComparison.Ordinal));
rand.Shuffle(mods);
foreach (var mod in mods)
{
if (mod.Cost > rating)
continue;
rating -= mod.Cost;
return mod;
}
throw new InvalidOperationException();
}
}