Salvage expeditions (#12745)
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
namespace Content.Shared.Salvage.Expeditions.Extraction;
|
||||
|
||||
public sealed class SalvageExtraction : ISalvageMission
|
||||
{
|
||||
/// <summary>
|
||||
/// Minimum weight to be used for a wave.
|
||||
/// </summary>
|
||||
[DataField("minWaveWeight")] public float MinWaveWeight = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum time between 2 waves. Roughly the end of one to the start of another.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("waveCooldown")]
|
||||
public TimeSpan WaveCooldown = TimeSpan.FromSeconds(60);
|
||||
|
||||
/// <summary>
|
||||
/// How much weight accumulates per second while the expedition is active.
|
||||
/// </summary>
|
||||
[DataField("weightAccumulator")]
|
||||
public float WeightAccumulator = 0.1f;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Content.Shared.Salvage.Expeditions;
|
||||
|
||||
|
||||
public interface IFactionExpeditionConfig
|
||||
{
|
||||
|
||||
}
|
||||
11
Content.Shared/Salvage/Expeditions/Modifiers/ISalvageMod.cs
Normal file
11
Content.Shared/Salvage/Expeditions/Modifiers/ISalvageMod.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
|
||||
public interface ISalvageMod
|
||||
{
|
||||
/// <summary>
|
||||
/// Player-friendly version describing this modifier.
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
|
||||
float Cost { get; }
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Content.Shared.Parallax.Biomes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Affects the biome to be used for salvage.
|
||||
/// </summary>
|
||||
[Prototype("salvageBiomeMod")]
|
||||
public sealed class SalvageBiomeMod : IPrototype, ISalvageMod
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
[DataField("desc")] public string Description { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Cost for difficulty modifiers.
|
||||
/// </summary>
|
||||
[DataField("cost")]
|
||||
public float Cost { get; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Is weather allowed to apply to this biome.
|
||||
/// </summary>
|
||||
[DataField("weather")]
|
||||
public bool Weather = true;
|
||||
|
||||
[DataField("biome", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<BiomeTemplatePrototype>))]
|
||||
public string? BiomePrototype;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Content.Shared.Procedural;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
|
||||
[Prototype("salvageDungeonMod")]
|
||||
public sealed class SalvageDungeonMod : IPrototype, ISalvageMod
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
[DataField("desc")] public string Description { get; } = string.Empty;
|
||||
|
||||
[DataField("proto", customTypeSerializer:typeof(PrototypeIdSerializer<DungeonConfigPrototype>))]
|
||||
public string Proto = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Cost for difficulty modifiers.
|
||||
/// </summary>
|
||||
[DataField("cost")]
|
||||
public float Cost { get; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Biomes this dungeon can occur in.
|
||||
/// </summary>
|
||||
[DataField("biomeMods", customTypeSerializer:typeof(PrototypeIdListSerializer<SalvageBiomeMod>))]
|
||||
public List<string>? BiomeMods;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
|
||||
[Prototype("salvageLightMod")]
|
||||
public sealed class SalvageLightMod : IPrototype, ISalvageMod
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
[DataField("desc")] public string Description { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Cost for difficulty modifiers.
|
||||
/// </summary>
|
||||
[DataField("cost")]
|
||||
public float Cost { get; } = 0f;
|
||||
|
||||
[DataField("color", required: true)] public Color? Color;
|
||||
|
||||
/// <summary>
|
||||
/// Biomes that this color applies to.
|
||||
/// </summary>
|
||||
[DataField("biomes", customTypeSerializer: typeof(PrototypeIdListSerializer<SalvageBiomeMod>))]
|
||||
public List<string>? Biomes;
|
||||
}
|
||||
20
Content.Shared/Salvage/Expeditions/Modifiers/SalvageMod.cs
Normal file
20
Content.Shared/Salvage/Expeditions/Modifiers/SalvageMod.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Generic modifiers with no additional data
|
||||
/// </summary>
|
||||
[Prototype("salvageMod")]
|
||||
public sealed class SalvageMod : IPrototype, ISalvageMod
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
[DataField("desc")] public string Description { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Cost for difficulty modifiers.
|
||||
/// </summary>
|
||||
[DataField("cost")]
|
||||
public float Cost { get; } = 0f;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
|
||||
[Prototype("salvageTimeMod")]
|
||||
public sealed class SalvageTimeMod : IPrototype, ISalvageMod
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
[DataField("desc")] public string Description { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Cost for difficulty modifiers.
|
||||
/// </summary>
|
||||
[DataField("cost")]
|
||||
public float Cost { get; } = 0f;
|
||||
|
||||
[DataField("minDuration")]
|
||||
public int MinDuration = 600;
|
||||
|
||||
[DataField("maxDuration")]
|
||||
public int MaxDuration = 660;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Content.Shared.Parallax.Biomes;
|
||||
using Content.Shared.Weather;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
|
||||
[Prototype("salvageWeatherMod")]
|
||||
public sealed class SalvageWeatherMod : IPrototype, ISalvageMod
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
[DataField("desc")] public string Description { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Cost for difficulty modifiers.
|
||||
/// </summary>
|
||||
[DataField("cost")]
|
||||
public float Cost { get; } = 0f;
|
||||
|
||||
[DataField("weather", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<WeatherPrototype>))]
|
||||
public string WeatherPrototype = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Whitelist for biomes. If empty assumed any allowed.
|
||||
/// </summary>
|
||||
[DataField("biomes", customTypeSerializer:typeof(PrototypeIdListSerializer<BiomeTemplatePrototype>))]
|
||||
public List<string> Biomes = new();
|
||||
}
|
||||
@@ -1,19 +1,28 @@
|
||||
using Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
|
||||
namespace Content.Shared.Salvage.Expeditions;
|
||||
|
||||
[Prototype("salvageFaction")]
|
||||
public sealed class SalvageFactionPrototype : IPrototype
|
||||
public sealed class SalvageFactionPrototype : IPrototype, ISalvageMod
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
[DataField("desc")] public string Description { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Cost for difficulty modifiers.
|
||||
/// </summary>
|
||||
[DataField("cost")]
|
||||
public float Cost { get; } = 0f;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("groups", required: true)]
|
||||
public List<SalvageMobGroup> MobGroups = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Per expedition type data for this faction.
|
||||
/// Miscellaneous data for factions.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("configs", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<IFactionExpeditionConfig, SalvageExpeditionPrototype>))]
|
||||
public Dictionary<string, IFactionExpeditionConfig> Configs = new();
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("configs")]
|
||||
public Dictionary<string, string> Configs = new();
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace Content.Shared.Salvage.Expeditions.Structure;
|
||||
|
||||
/// <summary>
|
||||
/// Destroy the specified number of structures to finish the expedition.
|
||||
/// </summary>
|
||||
[DataDefinition]
|
||||
public sealed class SalvageStructure : ISalvageMission
|
||||
{
|
||||
[DataField("desc")]
|
||||
public string Description = string.Empty;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("minStructures")]
|
||||
public int MinStructures = 3;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("maxStructures")]
|
||||
public int MaxStructures = 5;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Salvage.Expeditions.Structure;
|
||||
|
||||
/// <summary>
|
||||
/// Per-faction config for Salvage Structure expeditions.
|
||||
/// </summary>
|
||||
[DataDefinition]
|
||||
public sealed class SalvageStructureFaction : IFactionExpeditionConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity prototype of the structures to destroy.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("spawn", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Spawn = default!;
|
||||
|
||||
/// <summary>
|
||||
/// How many groups of mobs to spawn.
|
||||
/// </summary>
|
||||
[DataField("groupCount")]
|
||||
public int Groups = 5;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
namespace Content.Shared.Salvage;
|
||||
|
||||
public interface ISalvageMission {}
|
||||
@@ -1,89 +0,0 @@
|
||||
using Content.Shared.Dataset;
|
||||
using Content.Shared.Parallax.Biomes;
|
||||
using Content.Shared.Procedural;
|
||||
using Content.Shared.Procedural.Loot;
|
||||
using Content.Shared.Procedural.Rewards;
|
||||
using Content.Shared.Random;
|
||||
using Content.Shared.Salvage.Expeditions;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared.Salvage;
|
||||
|
||||
[Prototype("salvageExpedition")]
|
||||
public sealed class SalvageExpeditionPrototype : IPrototype
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Naming scheme for the FTL marker.
|
||||
/// </summary>
|
||||
[DataField("nameProto", customTypeSerializer:typeof(PrototypeIdSerializer<DatasetPrototype>))]
|
||||
public string NameProto = "names_borer";
|
||||
|
||||
/// <summary>
|
||||
/// Biome to generate the dungeon.
|
||||
/// </summary>
|
||||
[DataField("biome", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<BiomePrototype>))]
|
||||
public string Biome = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Player-friendly description for the console.
|
||||
/// </summary>
|
||||
[DataField("desc")]
|
||||
public string Description = string.Empty;
|
||||
|
||||
[DataField("difficultyRating")]
|
||||
public DifficultyRating DifficultyRating = DifficultyRating.Minor;
|
||||
|
||||
// TODO: Make these modifiers but also add difficulty modifiers.
|
||||
[DataField("light")]
|
||||
public Color Light = Color.Black;
|
||||
|
||||
[DataField("temperature")]
|
||||
public float Temperature = 293.15f;
|
||||
|
||||
[DataField("expedition", required: true)]
|
||||
public ISalvageMission Mission = default!;
|
||||
|
||||
[DataField("minDuration")]
|
||||
public TimeSpan MinDuration = TimeSpan.FromSeconds(9 * 60);
|
||||
|
||||
[DataField("maxDuration")]
|
||||
public TimeSpan MaxDuration = TimeSpan.FromSeconds(12 * 60);
|
||||
|
||||
/// <summary>
|
||||
/// Available factions for selection for this mission prototype.
|
||||
/// </summary>
|
||||
[DataField("factions", customTypeSerializer:typeof(PrototypeIdListSerializer<SalvageFactionPrototype>))]
|
||||
public List<string> Factions = new();
|
||||
|
||||
[DataField("dungeonConfig", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<DungeonConfigPrototype>))]
|
||||
public string DungeonConfigPrototype = string.Empty;
|
||||
|
||||
[DataField("reward", customTypeSerializer: typeof(PrototypeIdSerializer<WeightedRandomPrototype>))]
|
||||
public string Reward = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Possible loot prototypes available for this expedition.
|
||||
/// This spawns during the mission and is not tied to completion.
|
||||
/// </summary>
|
||||
[DataField("loot", customTypeSerializer: typeof(PrototypeIdListSerializer<WeightedRandomPrototype>))]
|
||||
public List<string> Loots = new();
|
||||
|
||||
[DataField("dungeonPosition")]
|
||||
public Vector2i DungeonPosition = new(80, -25);
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DifficultyRating : byte
|
||||
{
|
||||
None,
|
||||
Minor,
|
||||
Moderate,
|
||||
Hazardous,
|
||||
Extreme,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using Content.Shared.Salvage.Expeditions;
|
||||
using Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Salvage;
|
||||
|
||||
@@ -10,13 +11,15 @@ public sealed class SalvageExpeditionConsoleState : BoundUserInterfaceState
|
||||
{
|
||||
public TimeSpan NextOffer;
|
||||
public bool Claimed;
|
||||
public bool Cooldown;
|
||||
public ushort ActiveMission;
|
||||
public List<SalvageMission> Missions;
|
||||
public List<SalvageMissionParams> Missions;
|
||||
|
||||
public SalvageExpeditionConsoleState(TimeSpan nextOffer, bool claimed, ushort activeMission, List<SalvageMission> missions)
|
||||
public SalvageExpeditionConsoleState(TimeSpan nextOffer, bool claimed, bool cooldown, ushort activeMission, List<SalvageMissionParams> missions)
|
||||
{
|
||||
NextOffer = nextOffer;
|
||||
Claimed = claimed;
|
||||
Cooldown = cooldown;
|
||||
ActiveMission = activeMission;
|
||||
Missions = missions;
|
||||
}
|
||||
@@ -49,6 +52,12 @@ public sealed class SalvageExpeditionDataComponent : Component
|
||||
[ViewVariables]
|
||||
public bool Claimed => ActiveMission != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Are we actively cooling down from the last salvage mission.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("cooldown")]
|
||||
public bool Cooldown = false;
|
||||
|
||||
/// <summary>
|
||||
/// Nexy time salvage missions are offered.
|
||||
/// </summary>
|
||||
@@ -56,7 +65,7 @@ public sealed class SalvageExpeditionDataComponent : Component
|
||||
public TimeSpan NextOffer;
|
||||
|
||||
[ViewVariables]
|
||||
public readonly Dictionary<ushort, SalvageMission> Missions = new();
|
||||
public readonly Dictionary<ushort, SalvageMissionParams> Missions = new();
|
||||
|
||||
[ViewVariables] public ushort ActiveMission;
|
||||
|
||||
@@ -64,24 +73,84 @@ public sealed class SalvageExpeditionDataComponent : Component
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed record SalvageMission
|
||||
public sealed record SalvageMissionParams
|
||||
{
|
||||
[ViewVariables]
|
||||
public ushort Index;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("config", required: true, customTypeSerializer:typeof(SalvageExpeditionPrototype))]
|
||||
public string Config = default!;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public SalvageMissionType MissionType;
|
||||
|
||||
[ViewVariables] public TimeSpan Duration;
|
||||
[ViewVariables(VVAccess.ReadWrite)] public int Seed;
|
||||
|
||||
[ViewVariables] public int Seed;
|
||||
/// <summary>
|
||||
/// Base difficulty for this mission.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)] public DifficultyRating Difficulty;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum SalvageEnvironment : byte
|
||||
/// <summary>
|
||||
/// Created from <see cref="SalvageMissionParams"/>. Only needed for data the client also needs for mission
|
||||
/// display.
|
||||
/// </summary>
|
||||
public sealed record SalvageMission(
|
||||
int Seed,
|
||||
DifficultyRating Difficulty,
|
||||
string Dungeon,
|
||||
string Faction,
|
||||
SalvageMissionType Mission,
|
||||
string Biome,
|
||||
Color? Color,
|
||||
TimeSpan Duration,
|
||||
Dictionary<string, int> Loot,
|
||||
List<string> Modifiers)
|
||||
{
|
||||
Invalid = 0,
|
||||
Caves,
|
||||
/// <summary>
|
||||
/// Seed used for the mission.
|
||||
/// </summary>
|
||||
public readonly int Seed = Seed;
|
||||
|
||||
/// <summary>
|
||||
/// Difficulty rating.
|
||||
/// </summary>
|
||||
public DifficultyRating Difficulty = Difficulty;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="SalvageDungeonMod"/> to be used.
|
||||
/// </summary>
|
||||
public readonly string Dungeon = Dungeon;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="SalvageFactionPrototype"/> to be used.
|
||||
/// </summary>
|
||||
public readonly string Faction = Faction;
|
||||
|
||||
/// <summary>
|
||||
/// Underlying mission params that generated this.
|
||||
/// </summary>
|
||||
public readonly SalvageMissionType Mission = Mission;
|
||||
|
||||
/// <summary>
|
||||
/// Biome to be used for the mission.
|
||||
/// </summary>
|
||||
public readonly string Biome = Biome;
|
||||
|
||||
/// <summary>
|
||||
/// Lighting color to be used (AKA outdoor lighting).
|
||||
/// </summary>
|
||||
public readonly Color? Color = Color;
|
||||
|
||||
/// <summary>
|
||||
/// Mission duration.
|
||||
/// </summary>
|
||||
public TimeSpan Duration = Duration;
|
||||
|
||||
public Dictionary<string, int> Loot = Loot;
|
||||
|
||||
/// <summary>
|
||||
/// Modifiers (outside of the above) applied to the mission.
|
||||
/// </summary>
|
||||
public List<string> Modifiers = Modifiers;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
|
||||
@@ -1,77 +1,235 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Dataset;
|
||||
using Content.Shared.Procedural.Loot;
|
||||
using Content.Shared.Procedural.Rewards;
|
||||
using Content.Shared.Random;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Content.Shared.Salvage.Expeditions.Structure;
|
||||
using Content.Shared.Salvage.Expeditions;
|
||||
using Content.Shared.Salvage.Expeditions.Modifiers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Salvage;
|
||||
|
||||
public abstract class SharedSalvageSystem : EntitySystem
|
||||
{
|
||||
public static readonly TimeSpan MissionCooldown = TimeSpan.FromMinutes(5);
|
||||
public static readonly TimeSpan MissionFailedCooldown = TimeSpan.FromMinutes(10);
|
||||
[Dependency] private readonly ILocalizationManager _loc = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
public static float GetDifficultyModifier(DifficultyRating difficulty)
|
||||
public static readonly TimeSpan MissionCooldown = TimeSpan.FromMinutes(5);
|
||||
public static readonly TimeSpan MissionFailedCooldown = TimeSpan.FromMinutes(15);
|
||||
|
||||
#region Descriptions
|
||||
|
||||
public string GetMissionDescription(SalvageMission mission)
|
||||
{
|
||||
// These should reflect how many salvage staff are expected to be required for the mission.
|
||||
switch (difficulty)
|
||||
// Hardcoded in coooooz it's dynamic based on difficulty and I'm lazy.
|
||||
switch (mission.Mission)
|
||||
{
|
||||
case SalvageMissionType.Mining:
|
||||
// Taxation: , ("tax", $"{GetMiningTax(mission.Difficulty) * 100f:0}")
|
||||
return Loc.GetString("salvage-expedition-desc-mining");
|
||||
case SalvageMissionType.Destruction:
|
||||
var proto = _proto.Index<SalvageFactionPrototype>(mission.Faction).Configs["DefenseStructure"];
|
||||
|
||||
return Loc.GetString("salvage-expedition-desc-structure",
|
||||
("count", GetStructureCount(mission.Difficulty)),
|
||||
("structure", _loc.GetEntityData(proto).Name));
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public float GetMiningTax(DifficultyRating baseRating)
|
||||
{
|
||||
return 0.6f + (int) baseRating * 0.05f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of structures to destroy.
|
||||
/// </summary>
|
||||
public int GetStructureCount(DifficultyRating baseRating)
|
||||
{
|
||||
return 1 + (int) baseRating * 2;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public int GetDifficulty(DifficultyRating rating)
|
||||
{
|
||||
switch (rating)
|
||||
{
|
||||
case DifficultyRating.None:
|
||||
return 1f;
|
||||
return 1;
|
||||
case DifficultyRating.Minor:
|
||||
return 1.5f;
|
||||
return 2;
|
||||
case DifficultyRating.Moderate:
|
||||
return 3f;
|
||||
return 4;
|
||||
case DifficultyRating.Hazardous:
|
||||
return 6f;
|
||||
return 6;
|
||||
case DifficultyRating.Extreme:
|
||||
return 10f;
|
||||
return 8;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(difficulty), difficulty, null);
|
||||
throw new ArgumentOutOfRangeException(nameof(rating), rating, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How many groups of mobs to spawn for a mission.
|
||||
/// </summary>
|
||||
public float GetSpawnCount(DifficultyRating difficulty)
|
||||
{
|
||||
return (int) difficulty * 2;
|
||||
}
|
||||
|
||||
public static string GetFTLName(DatasetPrototype dataset, int seed)
|
||||
{
|
||||
var random = new System.Random(seed);
|
||||
return $"{dataset.Values[random.Next(dataset.Values.Count)]}-{random.Next(10, 100)}-{(char) (65 + random.Next(26))}";
|
||||
}
|
||||
|
||||
public static string GetFaction(List<string> factions, int seed)
|
||||
public SalvageMission GetMission(SalvageMissionType config, DifficultyRating difficulty, int seed)
|
||||
{
|
||||
var adjustedSeed = new System.Random(seed + 1);
|
||||
return factions[adjustedSeed.Next(factions.Count)];
|
||||
// This is on shared to ensure the client display for missions and what the server generates are consistent
|
||||
var rating = (float) GetDifficulty(difficulty);
|
||||
// Don't want easy missions to have any negative modifiers but also want
|
||||
// easy to be a 1 for difficulty.
|
||||
rating -= 1f;
|
||||
var rand = new System.Random(seed);
|
||||
var faction = GetMod<SalvageFactionPrototype>(rand, ref rating);
|
||||
var biome = GetMod<SalvageBiomeMod>(rand, ref rating);
|
||||
var dungeon = GetDungeon(biome.ID, rand, ref rating);
|
||||
var mods = new List<string>();
|
||||
|
||||
SalvageLightMod? light = null;
|
||||
|
||||
if (biome.BiomePrototype != null)
|
||||
{
|
||||
light = GetLight(biome.ID, rand, ref rating);
|
||||
mods.Add(light.Description);
|
||||
}
|
||||
|
||||
var time = GetMod<SalvageTimeMod>(rand, ref rating);
|
||||
// Round the duration to nearest 15 seconds.
|
||||
var exactDuration = time.MinDuration + (time.MaxDuration - time.MinDuration) * rand.NextFloat();
|
||||
exactDuration = MathF.Round(exactDuration / 15f) * 15f;
|
||||
var duration = TimeSpan.FromSeconds(exactDuration);
|
||||
|
||||
if (time.ID != "StandardTime")
|
||||
{
|
||||
mods.Add(time.Description);
|
||||
}
|
||||
|
||||
var loots = GetLoot(config, _proto.EnumeratePrototypes<SalvageLootPrototype>().ToList(), GetDifficulty(difficulty), seed);
|
||||
return new SalvageMission(seed, difficulty, dungeon.ID, faction.ID, config, biome.ID, light?.Color, duration, loots, mods);
|
||||
}
|
||||
|
||||
public static IEnumerable<SalvageLootPrototype> GetLoot(List<string> loots, int seed, IPrototypeManager protoManager)
|
||||
public SalvageDungeonMod GetDungeon(string biome, System.Random rand, ref float rating)
|
||||
{
|
||||
var mods = _proto.EnumeratePrototypes<SalvageDungeonMod>().ToList();
|
||||
mods.Sort((x, y) => string.Compare(x.ID, y.ID, StringComparison.Ordinal));
|
||||
rand.Shuffle(mods);
|
||||
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
if (mod.BiomeMods?.Contains(biome) == false ||
|
||||
mod.Cost > rating)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rating -= (int) mod.Cost;
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public SalvageLightMod GetLight(string biome, System.Random rand, ref float rating)
|
||||
{
|
||||
var mods = _proto.EnumeratePrototypes<SalvageLightMod>().ToList();
|
||||
mods.Sort((x, y) => string.Compare(x.ID, y.ID, StringComparison.Ordinal));
|
||||
rand.Shuffle(mods);
|
||||
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
if (mod.Biomes?.Contains(biome) == false || mod.Cost > rating)
|
||||
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();
|
||||
}
|
||||
|
||||
private Dictionary<string, int> GetLoot(SalvageMissionType mission, List<SalvageLootPrototype> loots, int count, int seed)
|
||||
{
|
||||
var results = new Dictionary<string, int>();
|
||||
var adjustedSeed = new System.Random(seed + 2);
|
||||
|
||||
for (var i = 0; i < loots.Count; i++)
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var loot = loots[i];
|
||||
var a = protoManager.Index<WeightedRandomPrototype>(loot);
|
||||
var lootConfig = a.Pick(adjustedSeed);
|
||||
yield return protoManager.Index<SalvageLootPrototype>(lootConfig);
|
||||
adjustedSeed.Shuffle(loots);
|
||||
|
||||
foreach (var loot in loots)
|
||||
{
|
||||
if (loot.Blacklist.Contains(mission))
|
||||
continue;
|
||||
|
||||
var weh = results.GetOrNew(loot.ID);
|
||||
weh++;
|
||||
results[loot.ID] = weh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public static ISalvageReward GetReward(WeightedRandomPrototype proto, int seed, IPrototypeManager protoManager)
|
||||
{
|
||||
var adjustedSeed = new System.Random(seed + 3);
|
||||
var rewardProto = proto.Pick(adjustedSeed);
|
||||
return protoManager.Index<SalvageRewardPrototype>(rewardProto).Reward;
|
||||
}
|
||||
|
||||
#region Structure
|
||||
|
||||
public static int GetStructureCount(SalvageStructure structure, int seed)
|
||||
{
|
||||
var adjustedSeed = new System.Random(seed + 4);
|
||||
return adjustedSeed.Next(structure.MinStructures, structure.MaxStructures + 1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum SalvageMissionType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// No dungeon, just ore loot and random mob spawns.
|
||||
/// </summary>
|
||||
Mining,
|
||||
|
||||
/// <summary>
|
||||
/// Destroy the specified structures in a dungeon.
|
||||
/// </summary>
|
||||
Destruction,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DifficultyRating : byte
|
||||
{
|
||||
None,
|
||||
Minor,
|
||||
Moderate,
|
||||
Hazardous,
|
||||
Extreme,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user