feat: rework modules, items and fuel
This commit is contained in:
@@ -97,15 +97,15 @@ public sealed partial class ScenarioLoader
|
||||
var scenario = NormalizeScenarioToAvailableSystems(
|
||||
Read<ScenarioDefinition>("scenario.json"),
|
||||
systems.Select((system) => system.Id).ToList());
|
||||
var modules = Read<List<ModuleDefinition>>("modules.json");
|
||||
var ships = Read<List<ShipDefinition>>("ships.json");
|
||||
var constructibles = Read<List<ConstructibleDefinition>>("constructibles.json");
|
||||
var items = Read<List<ItemDefinition>>("items.json");
|
||||
var recipes = Read<List<RecipeDefinition>>("recipes.json");
|
||||
var moduleRecipes = Read<List<ModuleRecipeDefinition>>("module-recipes.json");
|
||||
var balance = Read<BalanceDefinition>("balance.json");
|
||||
var recipes = BuildRecipes(items, ships);
|
||||
var moduleRecipes = BuildModuleRecipes(modules);
|
||||
|
||||
var moduleDefinitions = modules.ToDictionary((definition) => definition.Id, StringComparer.Ordinal);
|
||||
var shipDefinitions = ships.ToDictionary((definition) => definition.Id, StringComparer.Ordinal);
|
||||
var constructibleDefinitions = constructibles.ToDictionary((definition) => definition.Id, StringComparer.Ordinal);
|
||||
var itemDefinitions = items.ToDictionary((definition) => definition.Id, StringComparer.Ordinal);
|
||||
var recipeDefinitions = recipes.ToDictionary((definition) => definition.Id, StringComparer.Ordinal);
|
||||
var moduleRecipeDefinitions = moduleRecipes.ToDictionary((definition) => definition.ModuleId, StringComparer.Ordinal);
|
||||
@@ -178,7 +178,7 @@ public sealed partial class ScenarioLoader
|
||||
var stationIdCounter = 0;
|
||||
foreach (var plan in scenario.InitialStations)
|
||||
{
|
||||
if (!constructibleDefinitions.TryGetValue(plan.ConstructibleId, out var definition) || !systemsById.TryGetValue(plan.SystemId, out var system))
|
||||
if (!systemsById.TryGetValue(plan.SystemId, out var system))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -188,7 +188,8 @@ public sealed partial class ScenarioLoader
|
||||
{
|
||||
Id = $"station-{++stationIdCounter}",
|
||||
SystemId = system.Definition.Id,
|
||||
Definition = definition,
|
||||
Label = plan.Label,
|
||||
Color = plan.Color,
|
||||
Position = placement.Position,
|
||||
FactionId = plan.FactionId ?? DefaultFactionId,
|
||||
};
|
||||
@@ -214,21 +215,23 @@ public sealed partial class ScenarioLoader
|
||||
Id = stationBubbleId,
|
||||
NodeId = stationNodeId,
|
||||
SystemId = station.SystemId,
|
||||
Radius = MathF.Max(160f, definition.Radius + 60f),
|
||||
Radius = MathF.Max(160f, GetStationRadius(moduleDefinitions, station) + 60f),
|
||||
});
|
||||
localBubbles[^1].OccupantStationIds.Add(station.Id);
|
||||
placement.AnchorNode.OccupyingStructureId = station.Id;
|
||||
|
||||
foreach (var moduleId in definition.Modules)
|
||||
var startingModules = plan.StartingModules.Count > 0
|
||||
? plan.StartingModules
|
||||
: ["dock-bay-small", "power-core", "bulk-bay", "liquid-tank"];
|
||||
foreach (var moduleId in startingModules)
|
||||
{
|
||||
stations[^1].InstalledModules.Add(moduleId);
|
||||
AddStationModule(stations[^1], moduleDefinitions, moduleId);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var station in stations)
|
||||
{
|
||||
InitializeStationPopulation(station);
|
||||
station.Inventory["fuel"] = 240f;
|
||||
station.Inventory["refined-metals"] = 120f;
|
||||
if (station.Population > 0f)
|
||||
{
|
||||
@@ -277,19 +280,6 @@ public sealed partial class ScenarioLoader
|
||||
ControllerTask = new ControllerTaskRuntime { Kind = ControllerTaskKind.Idle, Threshold = balance.ArrivalThreshold, Status = WorkStatus.Pending },
|
||||
Health = definition.MaxHealth,
|
||||
});
|
||||
|
||||
shipsRuntime[^1].Inventory["gas"] = definition.Id switch
|
||||
{
|
||||
_ => 0f,
|
||||
};
|
||||
shipsRuntime[^1].Inventory.Remove("gas");
|
||||
shipsRuntime[^1].Inventory["fuel"] = definition.Id switch
|
||||
{
|
||||
"constructor" => 90f,
|
||||
"miner" => 90f,
|
||||
"gas-miner" => 90f,
|
||||
_ => 120f,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,6 +310,7 @@ public sealed partial class ScenarioLoader
|
||||
Policies = policies,
|
||||
ShipDefinitions = shipDefinitions,
|
||||
ItemDefinitions = itemDefinitions,
|
||||
ModuleDefinitions = moduleDefinitions,
|
||||
ModuleRecipes = moduleRecipeDefinitions,
|
||||
Recipes = recipeDefinitions,
|
||||
OrbitalTimeSeconds = WorldSeed * 97d,
|
||||
@@ -356,8 +347,10 @@ public sealed partial class ScenarioLoader
|
||||
InitialStations = scenario.InitialStations
|
||||
.Select((station) => new InitialStationDefinition
|
||||
{
|
||||
ConstructibleId = station.ConstructibleId,
|
||||
SystemId = ResolveSystemId(station.SystemId),
|
||||
Label = station.Label,
|
||||
Color = station.Color,
|
||||
StartingModules = station.StartingModules.ToList(),
|
||||
FactionId = station.FactionId,
|
||||
PlanetIndex = station.PlanetIndex,
|
||||
LagrangeSide = station.LagrangeSide,
|
||||
@@ -404,15 +397,37 @@ public sealed partial class ScenarioLoader
|
||||
: raw;
|
||||
}
|
||||
|
||||
private static bool HasModules(ConstructibleDefinition definition, params string[] modules) =>
|
||||
modules.All((moduleId) => definition.Modules.Contains(moduleId, StringComparer.Ordinal));
|
||||
|
||||
private static bool HasInstalledModules(StationRuntime station, params string[] modules) =>
|
||||
modules.All((moduleId) => station.InstalledModules.Contains(moduleId, StringComparer.Ordinal));
|
||||
modules.All((moduleId) => station.Modules.Any((candidate) => string.Equals(candidate.ModuleId, moduleId, StringComparison.Ordinal)));
|
||||
|
||||
private static bool HasModules(ShipDefinition definition, params string[] modules) =>
|
||||
modules.All((moduleId) => definition.Modules.Contains(moduleId, StringComparer.Ordinal));
|
||||
|
||||
private static void AddStationModule(StationRuntime station, IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions, string moduleId)
|
||||
{
|
||||
if (!moduleDefinitions.TryGetValue(moduleId, out var definition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
station.Modules.Add(new StationModuleRuntime
|
||||
{
|
||||
Id = $"{station.Id}-module-{station.Modules.Count + 1}",
|
||||
ModuleId = moduleId,
|
||||
Health = definition.Hull,
|
||||
MaxHealth = definition.Hull,
|
||||
});
|
||||
station.Radius = GetStationRadius(moduleDefinitions, station);
|
||||
}
|
||||
|
||||
private static float GetStationRadius(IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions, StationRuntime station)
|
||||
{
|
||||
var totalArea = station.Modules
|
||||
.Select((module) => moduleDefinitions.TryGetValue(module.ModuleId, out var definition) ? definition.Radius * definition.Radius : 0f)
|
||||
.Sum();
|
||||
return MathF.Max(24f, MathF.Sqrt(MathF.Max(totalArea, 1f)));
|
||||
}
|
||||
|
||||
private static Vector3 Add(Vector3 left, Vector3 right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
||||
|
||||
private static int CountModules(IEnumerable<string> modules, string moduleId) =>
|
||||
@@ -429,6 +444,89 @@ public sealed partial class ScenarioLoader
|
||||
return 0.1f + (0.9f * staffedRatio);
|
||||
}
|
||||
|
||||
private static List<ModuleRecipeDefinition> BuildModuleRecipes(IEnumerable<ModuleDefinition> modules) =>
|
||||
modules
|
||||
.Where((module) => module.Construction is not null)
|
||||
.Select((module) => new ModuleRecipeDefinition
|
||||
{
|
||||
ModuleId = module.Id,
|
||||
Duration = module.Construction!.ProductionTime,
|
||||
Inputs = module.Construction.Requirements
|
||||
.Select((input) => new RecipeInputDefinition
|
||||
{
|
||||
ItemId = input.ItemId,
|
||||
Amount = input.Amount,
|
||||
})
|
||||
.ToList(),
|
||||
})
|
||||
.ToList();
|
||||
|
||||
private static List<RecipeDefinition> BuildRecipes(IEnumerable<ItemDefinition> items, IEnumerable<ShipDefinition> ships)
|
||||
{
|
||||
var recipes = new List<RecipeDefinition>();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item.Construction is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
recipes.Add(new RecipeDefinition
|
||||
{
|
||||
Id = item.Construction.RecipeId ?? $"{item.Id}-production",
|
||||
Label = item.Name,
|
||||
FacilityCategory = item.Construction.FacilityCategory,
|
||||
Duration = item.Construction.CycleTime,
|
||||
Priority = item.Construction.Priority,
|
||||
RequiredModules = item.Construction.RequiredModules.ToList(),
|
||||
Inputs = item.Construction.Requirements
|
||||
.Select((input) => new RecipeInputDefinition
|
||||
{
|
||||
ItemId = input.ItemId,
|
||||
Amount = input.Amount,
|
||||
})
|
||||
.ToList(),
|
||||
Outputs =
|
||||
[
|
||||
new RecipeOutputDefinition
|
||||
{
|
||||
ItemId = item.Id,
|
||||
Amount = item.Construction.BatchSize,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var ship in ships)
|
||||
{
|
||||
if (ship.Construction is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
recipes.Add(new RecipeDefinition
|
||||
{
|
||||
Id = ship.Construction.RecipeId ?? $"{ship.Id}-construction",
|
||||
Label = $"{ship.Label} Construction",
|
||||
FacilityCategory = ship.Construction.FacilityCategory,
|
||||
Duration = ship.Construction.CycleTime,
|
||||
Priority = ship.Construction.Priority,
|
||||
RequiredModules = ship.Construction.RequiredModules.ToList(),
|
||||
Inputs = ship.Construction.Requirements
|
||||
.Select((input) => new RecipeInputDefinition
|
||||
{
|
||||
ItemId = input.ItemId,
|
||||
Amount = input.Amount,
|
||||
})
|
||||
.ToList(),
|
||||
ShipOutputId = ship.Id,
|
||||
});
|
||||
}
|
||||
|
||||
return recipes;
|
||||
}
|
||||
|
||||
private static Vector3 Scale(Vector3 vector, float scale) => new(vector.X * scale, vector.Y * scale, vector.Z * scale);
|
||||
|
||||
private static float DegreesToRadians(float degrees) => degrees * (MathF.PI / 180f);
|
||||
|
||||
Reference in New Issue
Block a user