diff --git a/changelog.txt b/changelog.txt index 622273520..a4e6539ec 100644 --- a/changelog.txt +++ b/changelog.txt @@ -19,6 +19,9 @@ Template for new versions: ## Fixes ## Misc Improvements +gui/export-world-map: more precise bridge coordinates +gui/export-world-map: export of bridge and road materials + ## Removed diff --git a/gui/export-world-map.lua b/gui/export-world-map.lua index abe7de5d2..73bd92e58 100644 --- a/gui/export-world-map.lua +++ b/gui/export-world-map.lua @@ -118,7 +118,6 @@ local SELECTED_ICON = dfhack.pen.parse{ch=string.char(251), fg=COLOR_LIGHTGREEN} local DISABLED_ICON = dfhack.pen.parse{ch='x', fg=COLOR_RED} function ExportMap:getChoices() - print("getChoices") local choices = {} for _, export in ipairs(exports) do table.insert(choices, { diff --git a/internal/export-world-map/export-roads.lua b/internal/export-world-map/export-roads.lua index ac738eb15..ac6f1c8f5 100644 --- a/internal/export-world-map/export-roads.lua +++ b/internal/export-world-map/export-roads.lua @@ -2,44 +2,93 @@ local json = require('json') local util = reqscript('internal/export-world-map/util') -local function getConstructionAndGeometryType(construction) - if df.world_construction_roadst:is_instance(construction) then +local constructions = df.global.world.world_data.constructions + +local function getConstructionAndGeometryType(construction, bridge_squares_by_id) + if construction:getType() == df.world_construction_type.ROAD then + local square = construction.square_obj[0] -- df populates square_obj for roads and tunnels (only) local subtype = "" - if df.item_type[construction.square_obj[0]["item_type"]] == "BLOCKS" then + local material = "" + + if df.item_type[square.item_type] == "BLOCKS" then subtype = "paved" - else + material = dfhack.matinfo.decode(square.mat_type, square.mat_index):toString() + elseif df.item_type[square.item_type] == "NONE" then subtype = "dirt" end - return "road", "LineString", subtype - elseif df.world_construction_bridgest:is_instance(construction) then - return "bridge", "Point", "" - elseif df.world_construction_tunnelst:is_instance(construction) then - return "tunnel", "LineString", "" + + return "road", "LineString", subtype, material + elseif construction:getType() == df.world_construction_type.BRIDGE then + local square = bridge_squares_by_id[construction.id] -- df does NOT populate square_obj for bridges + local subtype = "" + local material = "" + + if df.item_type[square.item_type] == "WOOD" then + subtype = "wooden" + material = dfhack.matinfo.decode(square.mat_type, square.mat_index):toString() + elseif df.item_type[square.item_type] == "BLOCKS" then + subtype = "stone" + material = dfhack.matinfo.decode(square.mat_type, square.mat_index):toString() + end + + return "bridge", "Point", subtype, material + elseif construction:getType() == df.world_construction_type.TUNNEL then + -- df assigns world construction squares to tunnels like it does to roads, + -- but tunnel squares have nothing besides positional data: no material info, no nothing. + return "tunnel", "LineString", "", "" else qerror("unknown construction type") end end +local function listBridgeSquaresById() + local squares = {} + + local tile_array_width = constructions.width + local tile_array_height = constructions.height + + for i = 0, (tile_array_width - 1) do + for j = 0, (tile_array_height - 1) do + for _, square in ipairs(constructions.map[i]:_displace(j).square) do + if df.world_construction_square_bridgest:is_instance(square) then + squares[square.construction_id] = square + end + end + end + end + + return squares +end + local function gatherFeatures() local features = {} - for _, construction in ipairs(df.global.world.world_data.constructions.list) do - local type, geometry_type, subtype = getConstructionAndGeometryType(construction) + + local bridge_squares_by_id = listBridgeSquaresById() + + for _, construction in ipairs(constructions.list) do + local type, geometry_type, subtype, material = getConstructionAndGeometryType(construction, bridge_squares_by_id) local coordinates if geometry_type == "Point" then - -- only world tile - not sure where to get region tile coordinates from - -- perhaps it gets them from neighbouring roads? + -- dwarf fortress doesn't populate square_obj for bridges, only for roads and tunnels. + -- but all world tiles are listed in df.global.world.world_data.constructions.map (not list), + -- a 2D array that has to be iterated over with _displace() + local region_x = construction.square_pos["x"][0] + local region_y = construction.square_pos["y"][0] + local midmap_x = bridge_squares_by_id[construction.id].embark_x[0] + local midmap_y = bridge_squares_by_id[construction.id].embark_y[0] + coordinates = { - construction.square_pos["x"][0]*768, - -(construction.square_pos["y"][0]*768) + region_x * 768 + midmap_x * 48 + 24, + -(region_y * 768 + midmap_y * 48 + 24) } else coordinates = {} - for _,square_obj in ipairs(construction.square_obj) do - for i=0,#square_obj.embark_x-1 do + for _, square_obj in ipairs(construction.square_obj) do + for i = 0, #square_obj.embark_x - 1 do table.insert(coordinates, { - square_obj.region_pos["x"]*768+square_obj.embark_x[i]*48+24, - -(square_obj.region_pos["y"]*768+square_obj.embark_y[i]*48+24) + square_obj.region_pos.x * 768 + square_obj.embark_x[i] * 48 + 24, + -(square_obj.region_pos.y * 768 + square_obj.embark_y[i] * 48 + 24) }) end end @@ -49,10 +98,11 @@ local function gatherFeatures() type = "Feature", properties = { id = construction.id, - name_df = dfhack.df2utf(dfhack.translation.translateName(construction["name"],false)), - name_en = dfhack.df2utf(dfhack.translation.translateName(construction["name"],true)), + name_df = dfhack.df2utf(dfhack.translation.translateName(construction["name"], false)), + name_en = dfhack.df2utf(dfhack.translation.translateName(construction["name"], true)), construction_type = type, construction_subtype = subtype, + construction_material = material, }, geometry = { type = geometry_type, @@ -68,7 +118,7 @@ function export(by_world, by_date) return function() json.encode_file( { type = "FeatureCollection", features = gatherFeatures() }, - util.getOutputFolder(by_world, by_date).."roads.geojson" + util.getOutputFolder(by_world, by_date) .. "roads.geojson" ) end end