implement ship modules
This commit is contained in:
@@ -358,6 +358,7 @@ ShipsConfig ConfigLoader::loadShips(const std::string& path)
|
||||
ShipDef def;
|
||||
def.id = requireString(mt["id"], file, elemPath + ".id");
|
||||
def.availableFromStart = requireBool(mt["available_from_start"], file, elemPath + ".available_from_start");
|
||||
def.layout = requireStringArray(mt["layout"], file, elemPath + ".layout");
|
||||
|
||||
// Schematic
|
||||
{
|
||||
@@ -498,6 +499,106 @@ StationsConfig ConfigLoader::loadStations(const std::string& path)
|
||||
return cfg;
|
||||
}
|
||||
|
||||
// Known category→stat mappings for module stat modifier discovery.
|
||||
struct StatEntry
|
||||
{
|
||||
const char* category;
|
||||
const char* stat;
|
||||
};
|
||||
|
||||
static const StatEntry kKnownStats[] = {
|
||||
{"health", "hp"},
|
||||
{"movement", "speed"},
|
||||
{"sensor", "sensor_range"},
|
||||
{"combat", "damage"},
|
||||
{"combat", "attack_range"},
|
||||
{"combat", "attack_rate"},
|
||||
{"repair", "repair_rate"},
|
||||
{"repair", "repair_range"},
|
||||
};
|
||||
|
||||
ModulesConfig ConfigLoader::loadModules(const std::string& path)
|
||||
{
|
||||
const std::string file = "modules.toml";
|
||||
toml::table tbl = parseFile(path, file);
|
||||
|
||||
ModulesConfig cfg;
|
||||
|
||||
if (!tbl.contains("module"))
|
||||
{
|
||||
return cfg;
|
||||
}
|
||||
|
||||
const toml::array& arr = requireArray(tbl["module"], file, "module");
|
||||
|
||||
for (std::size_t i = 0; i < arr.size(); ++i)
|
||||
{
|
||||
const std::string elemPath = "module[" + std::to_string(i) + "]";
|
||||
const toml::table* st = arr[i].as_table();
|
||||
if (st == nullptr)
|
||||
{
|
||||
throw makeError(file, elemPath, "not a table");
|
||||
}
|
||||
toml::table& mt = const_cast<toml::table&>(*st);
|
||||
|
||||
ModuleDef def;
|
||||
def.id = requireString(mt["id"], file, elemPath + ".id");
|
||||
def.surfaceMask = requireStringArray(mt["surface_mask"], file, elemPath + ".surface_mask");
|
||||
def.playerProductionLevel = static_cast<int>(requireInt(
|
||||
mt["player_production_level"], file, elemPath + ".player_production_level"));
|
||||
def.productionTimeSeconds = requireDouble(
|
||||
mt["production_time_seconds"], file, elemPath + ".production_time_seconds");
|
||||
def.threatCost = requireDouble(mt["threat_cost"], file, elemPath + ".threat_cost");
|
||||
def.fillColor = requireString(mt["fill_color"], file, elemPath + ".fill_color");
|
||||
def.glyph = requireString(mt["glyph"], file, elemPath + ".glyph");
|
||||
|
||||
// Materials
|
||||
{
|
||||
const toml::array& materials = requireArray(mt["materials"], file, elemPath + ".materials");
|
||||
def.materials = parseIngredients(materials, file, elemPath + ".materials");
|
||||
}
|
||||
|
||||
// Stat modifiers from [module.<category>] sub-tables
|
||||
for (const StatEntry& se : kKnownStats)
|
||||
{
|
||||
if (!mt.contains(se.category))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const toml::table& catTable = requireTable(mt[se.category], file,
|
||||
elemPath + "." + se.category);
|
||||
toml::table& catMt = const_cast<toml::table&>(catTable);
|
||||
|
||||
const std::string addedKey = std::string("added_") + se.stat + "_formula";
|
||||
const std::string multipliedKey = std::string("multiplied_") + se.stat + "_formula";
|
||||
|
||||
if (catMt.contains(addedKey))
|
||||
{
|
||||
ModuleStatModifier mod;
|
||||
mod.stat = se.stat;
|
||||
mod.modifierType = "additive";
|
||||
mod.formula = requireFormula(catMt[addedKey], file,
|
||||
elemPath + "." + se.category + "." + addedKey);
|
||||
def.statModifiers.push_back(std::move(mod));
|
||||
}
|
||||
|
||||
if (catMt.contains(multipliedKey))
|
||||
{
|
||||
ModuleStatModifier mod;
|
||||
mod.stat = se.stat;
|
||||
mod.modifierType = "multiplicative";
|
||||
mod.formula = requireFormula(catMt[multipliedKey], file,
|
||||
elemPath + "." + se.category + "." + multipliedKey);
|
||||
def.statModifiers.push_back(std::move(mod));
|
||||
}
|
||||
}
|
||||
|
||||
cfg.modules.push_back(std::move(def));
|
||||
}
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
GameConfig ConfigLoader::loadFromDirectory(const std::string& configDir)
|
||||
{
|
||||
GameConfig cfg;
|
||||
@@ -506,5 +607,6 @@ GameConfig ConfigLoader::loadFromDirectory(const std::string& configDir)
|
||||
cfg.recipes = loadRecipes(configDir + "/recipes.toml");
|
||||
cfg.ships = loadShips(configDir + "/ships.toml");
|
||||
cfg.stations = loadStations(configDir + "/stations.toml");
|
||||
cfg.modules = loadModules(configDir + "/modules.toml");
|
||||
return cfg;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user