Compare commits
2 Commits
e8fb033a01
...
04d182e93f
| Author | SHA1 | Date | |
|---|---|---|---|
| 04d182e93f | |||
| 3237735b08 |
@@ -114,10 +114,8 @@ public sealed class ItemDefinition
|
|||||||
public required string Id { get; set; }
|
public required string Id { get; set; }
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
public string Type { get; set; } = "material";
|
|
||||||
public string CargoKind { get; set; } = string.Empty;
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public StorageKind? CargoStorageKind { get; set; }
|
public StorageKind? CargoKind { get; set; }
|
||||||
public float Volume { get; set; } = 1f;
|
public float Volume { get; set; } = 1f;
|
||||||
public int Version { get; set; }
|
public int Version { get; set; }
|
||||||
public string FactoryName { get; set; } = string.Empty;
|
public string FactoryName { get; set; } = string.Empty;
|
||||||
@@ -130,7 +128,8 @@ public sealed class ItemDefinition
|
|||||||
[JsonPropertyName("transport")]
|
[JsonPropertyName("transport")]
|
||||||
public string Transport
|
public string Transport
|
||||||
{
|
{
|
||||||
set => CargoKind = value;
|
get => CargoKind?.ToDataValue() ?? string.Empty;
|
||||||
|
set => CargoKind = value.ToNullableStorageKind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,12 +150,6 @@ public sealed class RecipeInputDefinition
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ModuleConstructionDefinition
|
|
||||||
{
|
|
||||||
public required List<RecipeInputDefinition> Requirements { get; set; }
|
|
||||||
public float ProductionTime { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class ModuleDockDefinition
|
public sealed class ModuleDockDefinition
|
||||||
{
|
{
|
||||||
public int Capacity { get; set; }
|
public int Capacity { get; set; }
|
||||||
@@ -169,10 +162,14 @@ public sealed class ModuleCargoDefinition
|
|||||||
public required string Type { get; set; }
|
public required string Type { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ModuleWorkForceDefinition
|
public sealed class ModuleWorkforceDefinition
|
||||||
{
|
{
|
||||||
public float Capacity { get; set; }
|
[JsonPropertyName("capacity")]
|
||||||
public float Max { get; set; }
|
public float SupportedPopulation { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("max")]
|
||||||
|
public float RequiredWorkforce { get; set; }
|
||||||
|
|
||||||
public string Race { get; set; } = string.Empty;
|
public string Race { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +181,7 @@ public sealed class ModuleMountDefinition
|
|||||||
public List<string> Types { get; set; } = [];
|
public List<string> Types { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ModuleProductionDefinition
|
public sealed class ModuleBuildRecipeDefinition
|
||||||
{
|
{
|
||||||
public float Time { get; set; }
|
public float Time { get; set; }
|
||||||
public float Amount { get; set; }
|
public float Amount { get; set; }
|
||||||
@@ -207,12 +204,9 @@ public class ModuleDefinition
|
|||||||
Description = source.Description;
|
Description = source.Description;
|
||||||
Type = source.Type;
|
Type = source.Type;
|
||||||
ModuleType = source.ModuleType;
|
ModuleType = source.ModuleType;
|
||||||
Product = source.Product;
|
ProductIds = [.. source.ProductIds];
|
||||||
Products = [.. source.Products];
|
|
||||||
ProductionMode = source.ProductionMode;
|
|
||||||
Radius = source.Radius;
|
Radius = source.Radius;
|
||||||
Hull = source.Hull;
|
Hull = source.Hull;
|
||||||
WorkforceNeeded = source.WorkforceNeeded;
|
|
||||||
Version = source.Version;
|
Version = source.Version;
|
||||||
Macro = source.Macro;
|
Macro = source.Macro;
|
||||||
MakerRace = source.MakerRace;
|
MakerRace = source.MakerRace;
|
||||||
@@ -220,12 +214,11 @@ public class ModuleDefinition
|
|||||||
Price = source.Price;
|
Price = source.Price;
|
||||||
Owners = [.. source.Owners];
|
Owners = [.. source.Owners];
|
||||||
Cargo = source.Cargo;
|
Cargo = source.Cargo;
|
||||||
WorkForce = source.WorkForce;
|
SerializedWorkforce = source.SerializedWorkforce;
|
||||||
Docks = [.. source.Docks];
|
Docks = [.. source.Docks];
|
||||||
Shields = [.. source.Shields];
|
Shields = [.. source.Shields];
|
||||||
Turrets = [.. source.Turrets];
|
Turrets = [.. source.Turrets];
|
||||||
Production = [.. source.Production];
|
BuildRecipes = [.. source.BuildRecipes];
|
||||||
Construction = source.Construction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public required string Id { get; set; }
|
public required string Id { get; set; }
|
||||||
@@ -234,13 +227,12 @@ public class ModuleDefinition
|
|||||||
public required string Type { get; set; }
|
public required string Type { get; set; }
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public ModuleType ModuleType { get; set; }
|
public ModuleType ModuleType { get; set; }
|
||||||
|
[JsonPropertyName("product")]
|
||||||
|
public List<string> ProductIds { get; set; } = [];
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string? Product { get; set; }
|
public virtual IReadOnlyList<string> ProductItemIds => [];
|
||||||
public List<string> Products { get; set; } = [];
|
|
||||||
public string ProductionMode { get; set; } = "passive";
|
|
||||||
public float Radius { get; set; } = 12f;
|
public float Radius { get; set; } = 12f;
|
||||||
public float Hull { get; set; } = 100f;
|
public float Hull { get; set; } = 100f;
|
||||||
public float WorkforceNeeded { get; set; }
|
|
||||||
public int Version { get; set; }
|
public int Version { get; set; }
|
||||||
public string Macro { get; set; } = string.Empty;
|
public string Macro { get; set; } = string.Empty;
|
||||||
public string MakerRace { get; set; } = string.Empty;
|
public string MakerRace { get; set; } = string.Empty;
|
||||||
@@ -248,30 +240,58 @@ public class ModuleDefinition
|
|||||||
public ItemPriceDefinition? Price { get; set; }
|
public ItemPriceDefinition? Price { get; set; }
|
||||||
public List<string> Owners { get; set; } = [];
|
public List<string> Owners { get; set; } = [];
|
||||||
public ModuleCargoDefinition? Cargo { get; set; }
|
public ModuleCargoDefinition? Cargo { get; set; }
|
||||||
public ModuleWorkForceDefinition? WorkForce { get; set; }
|
[JsonPropertyName("workForce")]
|
||||||
|
public ModuleWorkforceDefinition? SerializedWorkforce { get; set; }
|
||||||
public List<ModuleDockDefinition> Docks { get; set; } = [];
|
public List<ModuleDockDefinition> Docks { get; set; } = [];
|
||||||
public List<ModuleMountDefinition> Shields { get; set; } = [];
|
public List<ModuleMountDefinition> Shields { get; set; } = [];
|
||||||
public List<ModuleMountDefinition> Turrets { get; set; } = [];
|
public List<ModuleMountDefinition> Turrets { get; set; } = [];
|
||||||
public List<ModuleProductionDefinition> Production { get; set; } = [];
|
[JsonPropertyName("production")]
|
||||||
public ModuleConstructionDefinition? Construction { get; set; }
|
public List<ModuleBuildRecipeDefinition> BuildRecipes { get; set; } = [];
|
||||||
[JsonPropertyName("product")]
|
}
|
||||||
public List<string> ProductIds
|
|
||||||
|
public abstract class ProductionLaneModuleDefinition : ModuleDefinition
|
||||||
|
{
|
||||||
|
[SetsRequiredMembers]
|
||||||
|
protected ProductionLaneModuleDefinition(ModuleDefinition source, float requiredWorkforce)
|
||||||
|
: base(source)
|
||||||
|
{
|
||||||
|
RequiredWorkforce = requiredWorkforce;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float RequiredWorkforce { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ProductionModuleDefinition : ProductionLaneModuleDefinition
|
||||||
|
{
|
||||||
|
[SetsRequiredMembers]
|
||||||
|
internal ProductionModuleDefinition(ModuleDefinition source, float requiredWorkforce)
|
||||||
|
: base(source, requiredWorkforce)
|
||||||
|
{
|
||||||
|
ProductItemIds = [.. source.ProductIds];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IReadOnlyList<string> ProductItemIds { get; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class BuildModuleDefinition : ProductionLaneModuleDefinition
|
||||||
|
{
|
||||||
|
[SetsRequiredMembers]
|
||||||
|
internal BuildModuleDefinition(ModuleDefinition source, float requiredWorkforce)
|
||||||
|
: base(source, requiredWorkforce)
|
||||||
{
|
{
|
||||||
get => Products;
|
|
||||||
set => Products = value ?? [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ProductionModuleDefinition : ModuleDefinition
|
public sealed class HabitationModuleDefinition : ModuleDefinition
|
||||||
{
|
{
|
||||||
[SetsRequiredMembers]
|
[SetsRequiredMembers]
|
||||||
internal ProductionModuleDefinition(ModuleDefinition source)
|
internal HabitationModuleDefinition(ModuleDefinition source, float supportedPopulation)
|
||||||
: base(source)
|
: base(source)
|
||||||
{
|
{
|
||||||
ProductItemIds = [.. source.Products];
|
SupportedPopulation = supportedPopulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IReadOnlyList<string> ProductItemIds { get; init; } = [];
|
public float SupportedPopulation { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class StorageModuleDefinition : ModuleDefinition
|
public sealed class StorageModuleDefinition : ModuleDefinition
|
||||||
@@ -338,9 +358,14 @@ public sealed class ShipDefinition
|
|||||||
public float FtlSpeed { get; set; }
|
public float FtlSpeed { get; set; }
|
||||||
public float SpoolTime { get; set; }
|
public float SpoolTime { get; set; }
|
||||||
public float CargoCapacity { get; set; }
|
public float CargoCapacity { get; set; }
|
||||||
public string? CargoKind { get; set; }
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public StorageKind? CargoStorageKind { get; set; }
|
public StorageKind? CargoKind { get; set; }
|
||||||
|
[JsonPropertyName("cargoKind")]
|
||||||
|
public string? SerializedCargoKind
|
||||||
|
{
|
||||||
|
get => CargoKind?.ToDataValue();
|
||||||
|
set => CargoKind = value.ToNullableStorageKind();
|
||||||
|
}
|
||||||
public required string Color { get; set; }
|
public required string Color { get; set; }
|
||||||
public required string HullColor { get; set; }
|
public required string HullColor { get; set; }
|
||||||
public float Size { get; set; }
|
public float Size { get; set; }
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ internal static class ProductionGraphBuilder
|
|||||||
ItemId = item.Id,
|
ItemId = item.Id,
|
||||||
Name = item.Name,
|
Name = item.Name,
|
||||||
Group = item.Group,
|
Group = item.Group,
|
||||||
CargoKind = item.CargoKind,
|
CargoKind = item.CargoKind?.ToDataValue() ?? string.Empty,
|
||||||
},
|
},
|
||||||
StringComparer.Ordinal);
|
StringComparer.Ordinal);
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ internal static class ProductionGraphBuilder
|
|||||||
outputsByModuleId[module.Id] = outputs;
|
outputsByModuleId[module.Id] = outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var product in module.Products)
|
foreach (var product in module.ProductItemIds)
|
||||||
{
|
{
|
||||||
outputs.Add(product);
|
outputs.Add(product);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,6 +265,9 @@ public static class SimulationEnumMappings
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StorageKind? ToNullableStorageKind(this string? value) =>
|
||||||
|
string.IsNullOrWhiteSpace(value) ? null : value.ToStorageKind();
|
||||||
|
|
||||||
public static string ToContractValue(this SpatialNodeKind kind) => kind switch
|
public static string ToContractValue(this SpatialNodeKind kind) => kind switch
|
||||||
{
|
{
|
||||||
SpatialNodeKind.Star => "star",
|
SpatialNodeKind.Star => "star",
|
||||||
|
|||||||
@@ -9,6 +9,25 @@ internal static class SimulationRuntimeSupport
|
|||||||
internal static int CountStationModules(StationRuntime station, ModuleType moduleType) =>
|
internal static int CountStationModules(StationRuntime station, ModuleType moduleType) =>
|
||||||
station.Modules.Count(module => module.ModuleType == moduleType);
|
station.Modules.Count(module => module.ModuleType == moduleType);
|
||||||
|
|
||||||
|
internal static float GetStationSupportedPopulation(
|
||||||
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions,
|
||||||
|
StationRuntime station) =>
|
||||||
|
40f + station.Modules
|
||||||
|
.Select(module => moduleDefinitions.TryGetValue(module.ModuleId, out var definition) && definition is HabitationModuleDefinition habitation
|
||||||
|
? habitation.SupportedPopulation
|
||||||
|
: 0f)
|
||||||
|
.Sum();
|
||||||
|
|
||||||
|
internal static float GetStationRequiredWorkforce(
|
||||||
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions,
|
||||||
|
StationRuntime station) =>
|
||||||
|
MathF.Max(12f, station.Modules
|
||||||
|
.Select(module => moduleDefinitions.TryGetValue(module.ModuleId, out var definition)
|
||||||
|
&& definition is ProductionLaneModuleDefinition productionLane
|
||||||
|
? productionLane.RequiredWorkforce
|
||||||
|
: 0f)
|
||||||
|
.Sum());
|
||||||
|
|
||||||
internal static float GetStationStorageCapacity(SimulationWorld world, StationRuntime station, StorageKind storageKind)
|
internal static float GetStationStorageCapacity(SimulationWorld world, StationRuntime station, StorageKind storageKind)
|
||||||
{
|
{
|
||||||
SyncStorageModuleLevels(world, station, storageKind);
|
SyncStorageModuleLevels(world, station, storageKind);
|
||||||
@@ -46,7 +65,7 @@ internal static class SimulationRuntimeSupport
|
|||||||
}
|
}
|
||||||
|
|
||||||
var remaining = station.Inventory
|
var remaining = station.Inventory
|
||||||
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
|
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
|
||||||
.Sum(entry => entry.Value);
|
.Sum(entry => entry.Value);
|
||||||
|
|
||||||
foreach (var (module, definition) in storageModules)
|
foreach (var (module, definition) in storageModules)
|
||||||
@@ -114,8 +133,8 @@ internal static class SimulationRuntimeSupport
|
|||||||
internal static bool CanExtractNode(ShipRuntime ship, ResourceNodeRuntime node, SimulationWorld world) =>
|
internal static bool CanExtractNode(ShipRuntime ship, ResourceNodeRuntime node, SimulationWorld world) =>
|
||||||
HasShipCapabilities(ship.Definition, "mining")
|
HasShipCapabilities(ship.Definition, "mining")
|
||||||
&& world.ItemDefinitions.TryGetValue(node.ItemId, out var item)
|
&& world.ItemDefinitions.TryGetValue(node.ItemId, out var item)
|
||||||
&& item.CargoStorageKind is not null
|
&& item.CargoKind is not null
|
||||||
&& item.CargoStorageKind == ship.Definition.CargoStorageKind;
|
&& item.CargoKind == ship.Definition.CargoKind;
|
||||||
|
|
||||||
internal static bool CanBuildClaimBeacon(ShipRuntime ship) =>
|
internal static bool CanBuildClaimBeacon(ShipRuntime ship) =>
|
||||||
string.Equals(ship.Definition.Kind, "military", StringComparison.Ordinal);
|
string.Equals(ship.Definition.Kind, "military", StringComparison.Ordinal);
|
||||||
@@ -176,7 +195,7 @@ internal static class SimulationRuntimeSupport
|
|||||||
return 0f;
|
return 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
var storageKind = itemDefinition.CargoStorageKind;
|
var storageKind = itemDefinition.CargoKind;
|
||||||
if (storageKind is null)
|
if (storageKind is null)
|
||||||
{
|
{
|
||||||
return 0f;
|
return 0f;
|
||||||
@@ -194,7 +213,7 @@ internal static class SimulationRuntimeSupport
|
|||||||
}
|
}
|
||||||
|
|
||||||
var used = station.Inventory
|
var used = station.Inventory
|
||||||
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
|
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
|
||||||
.Sum(entry => entry.Value);
|
.Sum(entry => entry.Value);
|
||||||
var accepted = MathF.Min(amount, MathF.Max(0f, capacity - used));
|
var accepted = MathF.Min(amount, MathF.Max(0f, capacity - used));
|
||||||
if (accepted <= 0.01f)
|
if (accepted <= 0.01f)
|
||||||
|
|||||||
@@ -2619,7 +2619,7 @@ internal sealed class ShipAiService
|
|||||||
{
|
{
|
||||||
if (world.ItemDefinitions.TryGetValue(itemId, out var itemDefinition))
|
if (world.ItemDefinitions.TryGetValue(itemId, out var itemDefinition))
|
||||||
{
|
{
|
||||||
var storageModule = GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoStorageKind);
|
var storageModule = GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoKind);
|
||||||
if (storageModule is not null && !modules.Contains(storageModule, StringComparer.Ordinal))
|
if (storageModule is not null && !modules.Contains(storageModule, StringComparer.Ordinal))
|
||||||
{
|
{
|
||||||
modules.Add(storageModule);
|
modules.Add(storageModule);
|
||||||
|
|||||||
@@ -801,7 +801,7 @@ internal sealed class SimulationProjectionService
|
|||||||
.Select(storageKind => new StationStorageUsageSnapshot(
|
.Select(storageKind => new StationStorageUsageSnapshot(
|
||||||
storageKind.ToDataValue(),
|
storageKind.ToDataValue(),
|
||||||
station.Inventory
|
station.Inventory
|
||||||
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
|
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
|
||||||
.Sum(entry => entry.Value),
|
.Sum(entry => entry.Value),
|
||||||
GetStationStorageCapacity(world, station, storageKind)))
|
GetStationStorageCapacity(world, station, storageKind)))
|
||||||
.Where(snapshot => snapshot.Capacity > 0.01f)
|
.Where(snapshot => snapshot.Capacity > 0.01f)
|
||||||
|
|||||||
@@ -65,6 +65,14 @@ public class StationModuleRuntime
|
|||||||
Health = production.Hull,
|
Health = production.Hull,
|
||||||
MaxHealth = production.Hull,
|
MaxHealth = production.Hull,
|
||||||
},
|
},
|
||||||
|
BuildModuleDefinition build => new BuildStationModuleRuntime
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
ModuleId = build.Id,
|
||||||
|
ModuleType = build.ModuleType,
|
||||||
|
Health = build.Hull,
|
||||||
|
MaxHealth = build.Hull,
|
||||||
|
},
|
||||||
_ => new StationModuleRuntime
|
_ => new StationModuleRuntime
|
||||||
{
|
{
|
||||||
Id = id,
|
Id = id,
|
||||||
@@ -81,6 +89,10 @@ public sealed class ProductionStationModuleRuntime : StationModuleRuntime
|
|||||||
public IReadOnlyList<string> ProductItemIds { get; init; } = [];
|
public IReadOnlyList<string> ProductItemIds { get; init; } = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class BuildStationModuleRuntime : StationModuleRuntime
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class StorageStationModuleRuntime : StationModuleRuntime
|
public sealed class StorageStationModuleRuntime : StationModuleRuntime
|
||||||
{
|
{
|
||||||
public StorageKind StorageKind { get; init; }
|
public StorageKind StorageKind { get; init; }
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ internal sealed class InfrastructureSimulationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var used = station.Inventory
|
var used = station.Inventory
|
||||||
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var def) && def.CargoStorageKind == storageKind)
|
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var def) && def.CargoKind == storageKind)
|
||||||
.Sum(entry => entry.Value);
|
.Sum(entry => entry.Value);
|
||||||
if (used / capacity >= 0.65f)
|
if (used / capacity >= 0.65f)
|
||||||
{
|
{
|
||||||
@@ -195,7 +195,7 @@ internal sealed class InfrastructureSimulationService
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoStorageKind) is { } storageModuleId)
|
if (GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoKind) is { } storageModuleId)
|
||||||
{
|
{
|
||||||
yield return storageModuleId;
|
yield return storageModuleId;
|
||||||
}
|
}
|
||||||
@@ -203,14 +203,14 @@ internal sealed class InfrastructureSimulationService
|
|||||||
|
|
||||||
if (world.ModuleDefinitions.TryGetValue(recipe.ModuleId, out var moduleDefinition))
|
if (world.ModuleDefinitions.TryGetValue(recipe.ModuleId, out var moduleDefinition))
|
||||||
{
|
{
|
||||||
foreach (var productItemId in moduleDefinition.Products)
|
foreach (var productItemId in moduleDefinition.ProductItemIds)
|
||||||
{
|
{
|
||||||
if (!world.ItemDefinitions.TryGetValue(productItemId, out var itemDefinition))
|
if (!world.ItemDefinitions.TryGetValue(productItemId, out var itemDefinition))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoStorageKind) is { } storageModuleId)
|
if (GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoKind) is { } storageModuleId)
|
||||||
{
|
{
|
||||||
yield return storageModuleId;
|
yield return storageModuleId;
|
||||||
}
|
}
|
||||||
@@ -325,7 +325,7 @@ internal sealed class InfrastructureSimulationService
|
|||||||
|
|
||||||
var capacity = GetStationStorageCapacity(world, station, storageKind);
|
var capacity = GetStationStorageCapacity(world, station, storageKind);
|
||||||
var used = station.Inventory
|
var used = station.Inventory
|
||||||
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var def) && def.CargoStorageKind == storageKind)
|
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var def) && def.CargoKind == storageKind)
|
||||||
.Sum(entry => entry.Value);
|
.Sum(entry => entry.Value);
|
||||||
var utilization = capacity <= 0.01f ? 0f : used / capacity;
|
var utilization = capacity <= 0.01f ? 0f : used / capacity;
|
||||||
|
|
||||||
@@ -621,7 +621,7 @@ internal sealed class InfrastructureSimulationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var score = 0f;
|
var score = 0f;
|
||||||
foreach (var productItemId in moduleDefinition.Products)
|
foreach (var productItemId in moduleDefinition.ProductItemIds)
|
||||||
{
|
{
|
||||||
if (!constructionDemandByItem.TryGetValue(productItemId, out var outstandingDemand) || outstandingDemand <= 0.01f)
|
if (!constructionDemandByItem.TryGetValue(productItemId, out var outstandingDemand) || outstandingDemand <= 0.01f)
|
||||||
{
|
{
|
||||||
@@ -689,12 +689,12 @@ internal sealed class InfrastructureSimulationService
|
|||||||
|
|
||||||
return recipe.Inputs.Any(input =>
|
return recipe.Inputs.Any(input =>
|
||||||
world.ItemDefinitions.TryGetValue(input.ItemId, out var itemDefinition)
|
world.ItemDefinitions.TryGetValue(input.ItemId, out var itemDefinition)
|
||||||
&& itemDefinition.CargoStorageKind == storageKind);
|
&& itemDefinition.CargoKind == storageKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CommodityUsesStorageClass(SimulationWorld world, string commodityId, StorageKind storageKind) =>
|
private static bool CommodityUsesStorageClass(SimulationWorld world, string commodityId, StorageKind storageKind) =>
|
||||||
world.ItemDefinitions.TryGetValue(commodityId, out var itemDefinition)
|
world.ItemDefinitions.TryGetValue(commodityId, out var itemDefinition)
|
||||||
&& itemDefinition.CargoStorageKind == storageKind;
|
&& itemDefinition.CargoKind == storageKind;
|
||||||
|
|
||||||
private static bool CanStationAcceptStationOutputSoon(SimulationWorld world, StationRuntime station, string itemId, float amount)
|
private static bool CanStationAcceptStationOutputSoon(SimulationWorld world, StationRuntime station, string itemId, float amount)
|
||||||
{
|
{
|
||||||
@@ -703,7 +703,7 @@ internal sealed class InfrastructureSimulationService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemDefinition.CargoStorageKind is not { } storageKind)
|
if (itemDefinition.CargoKind is not { } storageKind)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -715,7 +715,7 @@ internal sealed class InfrastructureSimulationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var used = station.Inventory
|
var used = station.Inventory
|
||||||
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
|
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
|
||||||
.Sum(entry => entry.Value);
|
.Sum(entry => entry.Value);
|
||||||
return used + amount <= capacity * 0.95f;
|
return used + amount <= capacity * 0.95f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,17 +34,16 @@ internal sealed class StationLifecycleService
|
|||||||
|
|
||||||
private void UpdateStationPopulation(SimulationWorld world, StationRuntime station, float deltaSeconds, ICollection<SimulationEventRecord> events)
|
private void UpdateStationPopulation(SimulationWorld world, StationRuntime station, float deltaSeconds, ICollection<SimulationEventRecord> events)
|
||||||
{
|
{
|
||||||
station.WorkforceRequired = MathF.Max(12f, station.Modules.Count * 14f);
|
station.WorkforceRequired = GetStationRequiredWorkforce(world.ModuleDefinitions, station);
|
||||||
|
|
||||||
var requiredWater = station.Population * WaterConsumptionPerWorkerPerSecond * deltaSeconds;
|
var requiredWater = station.Population * WaterConsumptionPerWorkerPerSecond * deltaSeconds;
|
||||||
var consumedWater = RemoveInventory(station.Inventory, "water", requiredWater);
|
var consumedWater = RemoveInventory(station.Inventory, "water", requiredWater);
|
||||||
var waterSatisfied = requiredWater <= 0.01f || consumedWater + 0.001f >= requiredWater;
|
var waterSatisfied = requiredWater <= 0.01f || consumedWater + 0.001f >= requiredWater;
|
||||||
var habitatModules = CountStationModules(station, ModuleType.Habitation);
|
station.PopulationCapacity = GetStationSupportedPopulation(world.ModuleDefinitions, station);
|
||||||
station.PopulationCapacity = 40f + (habitatModules * 220f);
|
|
||||||
|
|
||||||
if (waterSatisfied)
|
if (waterSatisfied)
|
||||||
{
|
{
|
||||||
if (habitatModules > 0 && station.Population < station.PopulationCapacity)
|
if (station.PopulationCapacity > 40f && station.Population < station.PopulationCapacity)
|
||||||
{
|
{
|
||||||
station.Population = MathF.Min(station.PopulationCapacity, station.Population + (PopulationGrowthPerSecond * deltaSeconds));
|
station.Population = MathF.Min(station.PopulationCapacity, station.Population + (PopulationGrowthPerSecond * deltaSeconds));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,12 +216,8 @@ internal sealed class StationSimulationService
|
|||||||
{
|
{
|
||||||
foreach (var moduleId in station.InstalledModules.Distinct(StringComparer.Ordinal))
|
foreach (var moduleId in station.InstalledModules.Distinct(StringComparer.Ordinal))
|
||||||
{
|
{
|
||||||
if (!world.ModuleDefinitions.TryGetValue(moduleId, out var def) || string.IsNullOrEmpty(def.ProductionMode))
|
if (!world.ModuleDefinitions.TryGetValue(moduleId, out var definition)
|
||||||
{
|
|| definition is not ProductionLaneModuleDefinition)
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(def.ProductionMode, "commanded", StringComparison.Ordinal) && station.CommanderId is null)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -241,7 +237,7 @@ internal sealed class StationSimulationService
|
|||||||
|
|
||||||
internal static string? GetStationProductionLaneKey(SimulationWorld world, RecipeDefinition recipe) =>
|
internal static string? GetStationProductionLaneKey(SimulationWorld world, RecipeDefinition recipe) =>
|
||||||
recipe.RequiredModules.FirstOrDefault(moduleId =>
|
recipe.RequiredModules.FirstOrDefault(moduleId =>
|
||||||
world.ModuleDefinitions.TryGetValue(moduleId, out var def) && !string.IsNullOrEmpty(def.ProductionMode));
|
world.ModuleDefinitions.TryGetValue(moduleId, out var definition) && definition is ProductionLaneModuleDefinition);
|
||||||
|
|
||||||
internal static float GetStationProductionThroughput(SimulationWorld world, StationRuntime station, RecipeDefinition recipe)
|
internal static float GetStationProductionThroughput(SimulationWorld world, StationRuntime station, RecipeDefinition recipe)
|
||||||
{
|
{
|
||||||
@@ -408,7 +404,7 @@ internal sealed class StationSimulationService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var storageKind = itemDefinition.CargoStorageKind;
|
var storageKind = itemDefinition.CargoKind;
|
||||||
if (storageKind is null)
|
if (storageKind is null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -426,7 +422,7 @@ internal sealed class StationSimulationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var used = station.Inventory
|
var used = station.Inventory
|
||||||
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
|
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
|
||||||
.Sum(entry => entry.Value);
|
.Sum(entry => entry.Value);
|
||||||
return used + amount <= capacity + 0.001f;
|
return used + amount <= capacity + 0.001f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ internal sealed class DataCatalogLoader(string dataRoot)
|
|||||||
var authoredSystems = Read<List<SolarSystemDefinition>>("systems.json");
|
var authoredSystems = Read<List<SolarSystemDefinition>>("systems.json");
|
||||||
var scenario = Read<ScenarioDefinition>("scenario.json");
|
var scenario = Read<ScenarioDefinition>("scenario.json");
|
||||||
var modules = NormalizeModules(Read<List<ModuleDefinition>>("modules.json"));
|
var modules = NormalizeModules(Read<List<ModuleDefinition>>("modules.json"));
|
||||||
var ships = NormalizeShips(Read<List<ShipDefinition>>("ships.json"));
|
var ships = Read<List<ShipDefinition>>("ships.json");
|
||||||
var items = NormalizeItems(Read<List<ItemDefinition>>("items.json"));
|
var items = Read<List<ItemDefinition>>("items.json");
|
||||||
var balance = Read<BalanceDefinition>("balance.json");
|
var balance = Read<BalanceDefinition>("balance.json");
|
||||||
var recipes = BuildRecipes(items, ships, modules);
|
var recipes = BuildRecipes(items, ships, modules);
|
||||||
var moduleRecipes = BuildModuleRecipes(modules);
|
var moduleRecipes = BuildModuleRecipes(modules);
|
||||||
@@ -103,12 +103,12 @@ internal sealed class DataCatalogLoader(string dataRoot)
|
|||||||
|
|
||||||
private static List<ModuleRecipeDefinition> BuildModuleRecipes(IEnumerable<ModuleDefinition> modules) =>
|
private static List<ModuleRecipeDefinition> BuildModuleRecipes(IEnumerable<ModuleDefinition> modules) =>
|
||||||
modules
|
modules
|
||||||
.Where(module => module.Construction is not null || module.Production.Count > 0)
|
.Where(module => module.BuildRecipes.Count > 0)
|
||||||
.Select(module => new ModuleRecipeDefinition
|
.Select(module => new ModuleRecipeDefinition
|
||||||
{
|
{
|
||||||
ModuleId = module.Id,
|
ModuleId = module.Id,
|
||||||
Duration = module.Construction?.ProductionTime ?? module.Production[0].Time,
|
Duration = module.BuildRecipes[0].Time,
|
||||||
Inputs = (module.Construction?.Requirements ?? module.Production[0].Wares)
|
Inputs = module.BuildRecipes[0].Wares
|
||||||
.Select(input => new RecipeInputDefinition
|
.Select(input => new RecipeInputDefinition
|
||||||
{
|
{
|
||||||
ItemId = input.ItemId,
|
ItemId = input.ItemId,
|
||||||
@@ -122,8 +122,8 @@ internal sealed class DataCatalogLoader(string dataRoot)
|
|||||||
{
|
{
|
||||||
var recipes = new List<RecipeDefinition>();
|
var recipes = new List<RecipeDefinition>();
|
||||||
var preferredProducerByItemId = modules
|
var preferredProducerByItemId = modules
|
||||||
.Where(module => module.Products.Count > 0)
|
.Where(module => module.ProductItemIds.Count > 0)
|
||||||
.GroupBy(module => module.Products[0], StringComparer.Ordinal)
|
.GroupBy(module => module.ProductItemIds[0], StringComparer.Ordinal)
|
||||||
.ToDictionary(
|
.ToDictionary(
|
||||||
group => group.Key,
|
group => group.Key,
|
||||||
group => group.OrderBy(module => module.Id, StringComparer.Ordinal).First().Id,
|
group => group.OrderBy(module => module.Id, StringComparer.Ordinal).First().Id,
|
||||||
@@ -255,60 +255,6 @@ internal sealed class DataCatalogLoader(string dataRoot)
|
|||||||
_ => 60,
|
_ => 60,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static List<ItemDefinition> NormalizeItems(List<ItemDefinition> items)
|
|
||||||
{
|
|
||||||
foreach (var item in items)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(item.Type))
|
|
||||||
{
|
|
||||||
item.Type = string.IsNullOrWhiteSpace(item.Group) ? "material" : item.Group;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(item.CargoKind))
|
|
||||||
{
|
|
||||||
item.CargoStorageKind = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
item.CargoStorageKind = item.CargoKind.ToStorageKind();
|
|
||||||
item.CargoKind = item.CargoStorageKind.Value.ToDataValue();
|
|
||||||
}
|
|
||||||
catch (ArgumentOutOfRangeException exception)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Item '{item.Id}' has unsupported cargo kind '{item.CargoKind}'.", exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<ShipDefinition> NormalizeShips(List<ShipDefinition> ships)
|
|
||||||
{
|
|
||||||
foreach (var ship in ships)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(ship.CargoKind))
|
|
||||||
{
|
|
||||||
ship.CargoStorageKind = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ship.CargoStorageKind = ship.CargoKind.ToStorageKind();
|
|
||||||
ship.CargoKind = ship.CargoStorageKind.Value.ToDataValue();
|
|
||||||
}
|
|
||||||
catch (ArgumentOutOfRangeException exception)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Ship '{ship.Id}' has unsupported cargo kind '{ship.CargoKind}'.", exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ships;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<ModuleDefinition> NormalizeModules(List<ModuleDefinition> modules)
|
private static List<ModuleDefinition> NormalizeModules(List<ModuleDefinition> modules)
|
||||||
{
|
{
|
||||||
for (var index = 0; index < modules.Count; index += 1)
|
for (var index = 0; index < modules.Count; index += 1)
|
||||||
@@ -325,23 +271,6 @@ internal sealed class DataCatalogLoader(string dataRoot)
|
|||||||
|
|
||||||
module.Type = module.ModuleType.ToDataValue();
|
module.Type = module.ModuleType.ToDataValue();
|
||||||
|
|
||||||
if (module.Products.Count == 0 && !string.IsNullOrWhiteSpace(module.Product))
|
|
||||||
{
|
|
||||||
module.Products = [module.Product];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(module.ProductionMode))
|
|
||||||
{
|
|
||||||
module.ProductionMode = module.ModuleType == ModuleType.BuildModule
|
|
||||||
? "commanded"
|
|
||||||
: "passive";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module.WorkforceNeeded <= 0f)
|
|
||||||
{
|
|
||||||
module.WorkforceNeeded = module.WorkForce?.Max ?? 0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
modules[index] = CreateSpecializedModuleDefinition(module);
|
modules[index] = CreateSpecializedModuleDefinition(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,9 +296,19 @@ internal sealed class DataCatalogLoader(string dataRoot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (module.Products.Count > 0)
|
if (module.ModuleType == ModuleType.Habitation)
|
||||||
{
|
{
|
||||||
return new ProductionModuleDefinition(module);
|
return new HabitationModuleDefinition(module, module.SerializedWorkforce?.SupportedPopulation ?? 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module.ModuleType == ModuleType.BuildModule)
|
||||||
|
{
|
||||||
|
return new BuildModuleDefinition(module, module.SerializedWorkforce?.RequiredWorkforce ?? 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module.ModuleType == ModuleType.Production)
|
||||||
|
{
|
||||||
|
return new ProductionModuleDefinition(module, module.SerializedWorkforce?.RequiredWorkforce ?? 0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ internal sealed class WorldBuilder(
|
|||||||
catalog.ModuleDefinitions,
|
catalog.ModuleDefinitions,
|
||||||
catalog.ItemDefinitions);
|
catalog.ItemDefinitions);
|
||||||
|
|
||||||
seedingService.InitializeStationStockpiles(stations);
|
seedingService.InitializeStationStockpiles(stations, catalog.ModuleDefinitions);
|
||||||
var refinery = seedingService.SelectRefineryStation(stations, scenario);
|
var refinery = seedingService.SelectRefineryStation(stations, scenario);
|
||||||
var patrolRoutes = BuildPatrolRoutes(scenario, systemsById);
|
var patrolRoutes = BuildPatrolRoutes(scenario, systemsById);
|
||||||
var ships = CreateShips(scenario, systemsById, spatialLayout.Celestials, catalog.Balance, catalog.ShipDefinitions, patrolRoutes, stations, refinery);
|
var ships = CreateShips(scenario, systemsById, spatialLayout.Celestials, catalog.Balance, catalog.ShipDefinitions, patrolRoutes, stations, refinery);
|
||||||
@@ -208,9 +208,9 @@ internal sealed class WorldBuilder(
|
|||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var wareId in moduleDefinition.Production
|
foreach (var wareId in moduleDefinition.BuildRecipes
|
||||||
.SelectMany(production => production.Wares.Select(ware => ware.ItemId))
|
.SelectMany(production => production.Wares.Select(ware => ware.ItemId))
|
||||||
.Concat(moduleDefinition.Products)
|
.Concat(moduleDefinition.ProductItemIds)
|
||||||
.Distinct(StringComparer.Ordinal))
|
.Distinct(StringComparer.Ordinal))
|
||||||
{
|
{
|
||||||
if (!itemDefinitions.TryGetValue(wareId, out var itemDefinition))
|
if (!itemDefinitions.TryGetValue(wareId, out var itemDefinition))
|
||||||
@@ -218,7 +218,7 @@ internal sealed class WorldBuilder(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStorageRequirement(moduleDefinitions, itemDefinition.CargoStorageKind) is { } storageModuleId)
|
if (SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStorageRequirement(moduleDefinitions, itemDefinition.CargoKind) is { } storageModuleId)
|
||||||
{
|
{
|
||||||
yield return storageModuleId;
|
yield return storageModuleId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,11 +60,13 @@ internal sealed class WorldSeedingService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void InitializeStationStockpiles(IReadOnlyCollection<StationRuntime> stations)
|
internal void InitializeStationStockpiles(
|
||||||
|
IReadOnlyCollection<StationRuntime> stations,
|
||||||
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions)
|
||||||
{
|
{
|
||||||
foreach (var station in stations)
|
foreach (var station in stations)
|
||||||
{
|
{
|
||||||
InitializeStationPopulation(station);
|
InitializeStationPopulation(station, moduleDefinitions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,9 +233,9 @@ internal sealed class WorldSeedingService
|
|||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var wareId in moduleDefinition.Production
|
foreach (var wareId in moduleDefinition.BuildRecipes
|
||||||
.SelectMany(production => production.Wares.Select(ware => ware.ItemId))
|
.SelectMany(production => production.Wares.Select(ware => ware.ItemId))
|
||||||
.Concat(moduleDefinition.Products)
|
.Concat(moduleDefinition.ProductItemIds)
|
||||||
.Distinct(StringComparer.Ordinal))
|
.Distinct(StringComparer.Ordinal))
|
||||||
{
|
{
|
||||||
if (!world.ItemDefinitions.TryGetValue(wareId, out var itemDefinition))
|
if (!world.ItemDefinitions.TryGetValue(wareId, out var itemDefinition))
|
||||||
@@ -241,7 +243,7 @@ internal sealed class WorldSeedingService
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoStorageKind) is { } storageModuleId)
|
if (SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoKind) is { } storageModuleId)
|
||||||
{
|
{
|
||||||
yield return storageModuleId;
|
yield return storageModuleId;
|
||||||
}
|
}
|
||||||
@@ -549,12 +551,13 @@ internal sealed class WorldSeedingService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InitializeStationPopulation(StationRuntime station)
|
private static void InitializeStationPopulation(
|
||||||
|
StationRuntime station,
|
||||||
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions)
|
||||||
{
|
{
|
||||||
var habitatModules = station.Modules.Count(module => module.ModuleType == ModuleType.Habitation);
|
station.PopulationCapacity = SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStationSupportedPopulation(moduleDefinitions, station);
|
||||||
station.PopulationCapacity = 40f + (habitatModules * 220f);
|
station.WorkforceRequired = SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStationRequiredWorkforce(moduleDefinitions, station);
|
||||||
station.WorkforceRequired = MathF.Max(12f, station.Modules.Count * 14f);
|
station.Population = station.PopulationCapacity > 40f
|
||||||
station.Population = habitatModules > 0
|
|
||||||
? MathF.Min(station.PopulationCapacity * 0.65f, station.WorkforceRequired * 1.05f)
|
? MathF.Min(station.PopulationCapacity * 0.65f, station.WorkforceRequired * 1.05f)
|
||||||
: MathF.Min(28f, station.PopulationCapacity);
|
: MathF.Min(28f, station.PopulationCapacity);
|
||||||
station.WorkforceEffectiveRatio = ComputeWorkforceRatio(station.Population, station.WorkforceRequired);
|
station.WorkforceEffectiveRatio = ComputeWorkforceRatio(station.Population, station.WorkforceRequired);
|
||||||
|
|||||||
Reference in New Issue
Block a user