diff options
Diffstat (limited to 'src/game/data.cpp')
| -rw-r--r-- | src/game/data.cpp | 107 |
1 files changed, 78 insertions, 29 deletions
diff --git a/src/game/data.cpp b/src/game/data.cpp index 3d9f6c0..bbcf2d0 100644 --- a/src/game/data.cpp +++ b/src/game/data.cpp @@ -163,11 +163,17 @@ std::vector<WeaponDef> load_weapons(ScriptEngine& script, const std::string& dat return out; } -void load_structures(ScriptEngine& script, const std::string& data_dir, - BuildGraph& graph) { - run_layered(script, data_dir, "structures.lua"); - sol::optional<sol::table> structs = script.lua()["Structures"]; - if (!structs) return; +void build_map(const MapDef& m, BuildGraph& graph) { + graph.nodes.clear(); + graph.edges.clear(); + // Clearing the vectors does NOT touch the private adjacency and edge-key + // caches, so rebuild them now. Skipping this leaves the PREVIOUS map's edge + // keys in the set and add_edge then refuses the new map's beams as + // duplicates, quietly producing a fort that collapses on load. + graph.rebuild(); + // Set the ground BEFORE welding: node_at asks is_on_ground() to decide which + // endpoints are pinned foundations. + graph.ground_level = m.ground_level; auto mat_index = [&](const std::string& nm) -> int { for (int i = 0; i < (int)graph.materials.size(); i++) @@ -180,25 +186,22 @@ void load_structures(ScriptEngine& script, const std::string& data_dir, }; int built = 0; - for (std::size_t si = 1; ; si++) { - sol::object so = (*structs)[si]; - if (so.get_type() != sol::type::table) break; - sol::table S = so.as<sol::table>(); - sol::optional<sol::table> beams = S["beams"]; - if (!beams) continue; - for (std::size_t bi = 1; ; bi++) { - sol::object bo = (*beams)[bi]; - if (bo.get_type() != sol::type::table) break; - sol::table b = bo.as<sol::table>(); - float x1 = b.get_or(1, 0.0f), y1 = b.get_or(2, 0.0f); - float x2 = b.get_or(3, 0.0f), y2 = b.get_or(4, 0.0f); - std::string mat = b.get_or(5, std::string("wood")); - if (graph.add_edge(node_at(x1, y1), node_at(x2, y2), mat_index(mat)) >= 0) - built++; - } + for (const auto& b : m.beams) { + int na = node_at(b.x1, b.y1), nb = node_at(b.x2, b.y2); + if (graph.add_edge(na, nb, mat_index(b.material)) >= 0) { built++; continue; } + // A dropped beam silently weakens the fort, so never fail quietly: + // endpoints closer than SNAP_RADIUS collapse onto one node, and a + // repeated node pair is refused as a duplicate. + fprintf(stderr, + "map '%s': beam (%g,%g)-(%g,%g) [%s] rejected -> nodes %d,%d%s\n", + m.name.c_str(), b.x1, b.y1, b.x2, b.y2, b.material.c_str(), + na, nb, na == nb ? " (endpoints snapped together)" : " (duplicate)"); } + for (auto& e : graph.edges) e.settle = 0.0f; // prebuilt = already cured - printf("Loaded %d prebuilt struts from Structures\n", built); + graph.rebuild(); + printf("Map '%s': %d prebuilt struts, ground %.1f\n", + m.name.c_str(), built, m.ground_level); } namespace { @@ -243,10 +246,14 @@ std::vector<DeviceDef> load_devices(ScriptEngine& script, const std::string& dat return out; } -MapData load_map(ScriptEngine& script, const std::string& data_dir) { - MapData m; - run_layered(script, data_dir, "map.lua"); - if (sol::optional<sol::table> dep = script.lua()["Deposits"]) { +namespace { +MapDef read_map(const sol::table& M) { + MapDef m; + m.name = M.get_or("name", std::string("unnamed")); + m.description = M.get_or("description", std::string("")); + m.ground_level = M.get_or("ground_level", 1.0f); + + if (sol::optional<sol::table> dep = M["deposits"]) { for (std::size_t i = 1; ; i++) { sol::object o = (*dep)[i]; if (o.get_type() != sol::type::table) break; @@ -254,9 +261,9 @@ MapData load_map(ScriptEngine& script, const std::string& data_dir) { m.deposits.emplace_back(p.get_or(1, 0.0f), p.get_or(2, 0.0f)); } } - if (sol::optional<sol::table> md = script.lua()["MapDevices"]) { + if (sol::optional<sol::table> dv = M["devices"]) { for (std::size_t i = 1; ; i++) { - sol::object o = (*md)[i]; + sol::object o = (*dv)[i]; if (o.get_type() != sol::type::table) break; sol::table d = o.as<sol::table>(); m.devices.push_back({ d.get_or("type", std::string("reactor")), @@ -264,6 +271,48 @@ MapData load_map(ScriptEngine& script, const std::string& data_dir) { d.get_or("team", 0) }); } } - printf("Loaded map: %zu deposits, %zu devices\n", m.deposits.size(), m.devices.size()); + if (sol::optional<sol::table> wp = M["weapons"]) { + for (std::size_t i = 1; ; i++) { + sol::object o = (*wp)[i]; + if (o.get_type() != sol::type::table) break; + sol::table w = o.as<sol::table>(); + m.weapons.push_back({ w.get_or("type", std::string("cannon")), + w.get_or("x", 0.0f), w.get_or("y", 0.0f) }); + } + } + // structures[] -> beams[] {x1,y1,x2,y2,material}, flattened: which fort a + // beam belonged to does not matter once it is welded into the graph. + if (sol::optional<sol::table> st = M["structures"]) { + for (std::size_t si = 1; ; si++) { + sol::object so = (*st)[si]; + if (so.get_type() != sol::type::table) break; + sol::table S = so.as<sol::table>(); + sol::optional<sol::table> beams = S["beams"]; + if (!beams) continue; + for (std::size_t bi = 1; ; bi++) { + sol::object bo = (*beams)[bi]; + if (bo.get_type() != sol::type::table) break; + sol::table b = bo.as<sol::table>(); + m.beams.push_back({ b.get_or(1, 0.0f), b.get_or(2, 0.0f), + b.get_or(3, 0.0f), b.get_or(4, 0.0f), + b.get_or(5, std::string("wood")) }); + } + } + } return m; } +} // namespace + +std::vector<MapDef> load_maps(ScriptEngine& script, const std::string& data_dir) { + std::vector<MapDef> out; + run_layered(script, data_dir, "maps.lua"); + sol::optional<sol::table> maps = script.lua()["Maps"]; + if (!maps) { fprintf(stderr, "load_maps: no global 'Maps' table\n"); return out; } + for (std::size_t i = 1; ; i++) { + sol::object o = (*maps)[i]; + if (o.get_type() != sol::type::table) break; + out.push_back(read_map(o.as<sol::table>())); + } + printf("Loaded %zu maps\n", out.size()); + return out; +} |
