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!; /// /// Main loot table for salvage expeditions. /// [ValidatePrototypeId] public const string ExpeditionsLootProto = "NFSalvageLootModerate"; // Frontier: SalvageLoot(rand, ref modifierBudget); var light = GetBiomeMod(biome.ID, rand, ref modifierBudget); var temp = GetBiomeMod(biome.ID, rand, ref modifierBudget); var air = GetBiomeMod(biome.ID, rand, ref modifierBudget); var dungeon = GetBiomeMod(biome.ID, rand, ref modifierBudget); // Frontier: restrict factions per difficulty // var factionProtos = _proto.EnumeratePrototypes().ToList(); var factionProtos = _proto.EnumeratePrototypes() .Where(x => { return !x.Configs.TryGetValue("Difficulties", out var difficulties) || string.IsNullOrWhiteSpace(difficulties) || difficulties.Split(",").Contains(difficulty.ID.ToString()); } ).ToList(); // End Frontier: difficulties per faction factionProtos.Sort((x, y) => string.Compare(x.ID, y.ID, StringComparison.Ordinal)); var faction = factionProtos[rand.Next(factionProtos.Count)]; var mods = new List(); 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, difficulty.ID, config); // Frontier: add difficulty.ID, config } public T GetBiomeMod(string biome, System.Random rand, ref float rating) where T : class, IPrototype, IBiomeSpecificMod { var mods = _proto.EnumeratePrototypes().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(System.Random rand, ref float rating) where T : class, IPrototype, ISalvageMod { var mods = _proto.EnumeratePrototypes().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(); } } // Frontier: salvage mission type [Serializable, NetSerializable] public enum SalvageMissionType : byte { /// /// Destroy the specified structures in a dungeon. /// Destruction = 0, /// /// Kill a large creature in a dungeon. /// Elimination = 1, /// /// Maximum value for random generation, should not be used directly. /// Max = Elimination, } // End Frontier