From b18aa8fd4aa313fc3935f6ed62ee4829be4bbcaa Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 21 Oct 2024 09:04:39 -0500 Subject: [PATCH 1/8] Add export map tool --- docs/export-map.rst | 169 +++++++++++++++++++++++++++ export-map.lua | 279 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 448 insertions(+) create mode 100644 docs/export-map.rst create mode 100644 export-map.lua diff --git a/docs/export-map.rst b/docs/export-map.rst new file mode 100644 index 000000000..fabf543eb --- /dev/null +++ b/docs/export-map.rst @@ -0,0 +1,169 @@ +export-map +========== + +.. dfhack-tool:: + :summary: Export fortress map tile data to a JSON file + :tags: dev map + +WARNING - This command will cause the game to freeze for minutes depending on +map size and options enabled. + +Exports the fortress map tile data to a JSON file. (does not include items, +characters, buildings, etc.) Depending on options enabled, there will be a +``KEY`` table in the JSON with relevant [number ID] values that match a number +to their object type. + +Usage +----- + +:: + + export-map [include|exclude] [] + +Examples +-------- + +``export-map`` + Exports the fortress map to JSON with ALL data included + +``export-map include -m -s -v`` + Exports the fortress map to JSON with only materials, shape, and vein data + included + +``export-map exclude --variant --hidden --light`` + Exports the fortress map to JSON with variant, hidden, and light data + excluded + +Required +-------- + +When you are using options, you must include one of these settings. + +``include`` + Include only the data listed from options to the JSON (whitelist) + +``exclude`` + Exclude only the data listed from options to the JSON (blacklist) + +Options +------- + +``help``, ``--help`` + Shows the help menu + +``-t``, ``--tiletype`` + The tile material classification [number ID] (AIR/SOIL/STONE/RIVER/etc.) + +``-s``, ``--shape`` + The tile shape classification [number ID] (EMPTY/FLOOR/WALL/STAIR/etc.) + +``-p``, ``--special`` + The tile surface special properties for smoothness [number ID] + (NORMAL/SMOOTH/ROUGH/etc.) (used for engraving) + +``-r``, ``--variant`` + The specific variant of a tile that have visual variations [number] (like + grass tiles in ASCII mode) + +``-h``, ``--hidden`` + Whether tile is revealed or unrevealed [boolean] + +``-l``, ``--light`` + Whether tile is exposed to light [boolean] + +``-b``, ``--subterranean`` + Whether the tile is considered underground [boolean] (used to determine + crops that can be planted underground) + +``-o``, ``--outside`` + Whether the tile is considered “outside”. [boolean] (used by weather effects + to trigger on outside tiles) + +``-a``, ``--aquifer`` + Whether the tile is considered an aquifer [number ID] (NONE/LIGHT/HEAVY) + +``-m``, ``--material`` + The material inside the tile [number ID] (IRON/GRANITE/CLAY/ + TOPAZOLITE/BLACK_OPAL/etc.) (will return nil if the tile is empty) + +``-u``, ``--underworld`` + Whether the underworld z-levels will be included [boolean] + +JSON DATA +--------- + +``ARGUMENT_OPTION_ORDER`` + The order of the selected options for how data is arranged at a map position + Example 1: + ``{"material": 1, "shape": 2, "hidden": 3}`` + ``map[z][y][x] = {material_data, shape_data, hidden_data}`` + Example 2: + ``{"variant": 3, "light": 1, "outside": 2, "aquifer": 4}`` + ``map[z][y][x] = {light_data, outside_data, variant_data, aquifer_data}`` + +``MAP_SIZE`` + A table containing basic information about the map size for width, height, + depth. (x, y, z) The underworld_z_level is included if the underworld option + is enabled and the map depth (z) will be automatically adjusted. + +``KEYS`` + The tables containing the [number ID] values for different options. + + ``"SHAPE": { + "-1": "NONE", + "0": "EMPTY", + "1": "FLOOR", + "2": "BOULDERS", + "3": "PEBBLES", + "4": "WALL", + ... + "18": "ENDLESS_PIT" + `` + + ``"PLANT": { + "0": "SINGLE-GRAIN_WHEAT", + "1": "TWO-GRAIN_WHEAT", + "2": "SOFT_WHEAT", + "3": "HARD_WHEAT", + "4": "SPELT", + "5": "BARLEY", + ... + "224": "PALM" + `` + + ``"AQUIFER": { + "0": "NONE", + "1": "LIGHT", + "2": "HEAVY" + `` + + Note - when using the ``materials`` option, you need to pair the [number ID] + with the correct ``KEYS`` material table. Generally you use ``tiletype`` + option as a helper to sort tiles into different material types. I would + recommend consulting ``tile-material.lua`` to see how materials are sorted. + +``map`` + JSON map data is arranged as: ``map[z][y][x] = {tile_data}`` + + JSON maps start at index [1]. (starts at map[1][1][1]) + DF maps start at index [0]. (starts at map[0][0][0]) + + To translate an actual DF map position from the JSON map you need add +1 to + all x/y/z coordinates to get the correct tile position. + + The ``ARGUMENT_OPTION_ORDER`` determines order of tile data. (see above) + I would recommend referencing the tile data like so: + ``shape = json_data.map[z][x][y][json_data.ARGUMENT_OPTIONS_ORDER.shape]`` + ``light = json_data.map[z][x][y][json_data.ARGUMENT_OPTIONS_ORDER.light]`` + + Note - some of the bottom z-levels for hell do not have the same + width/height as the default map. So if your map is 190x190, the last hell + z-levels are gonna be like 90x90. + + Instead of returning normal tile data like: + ``map[0][90][90] = {tile_data}`` + + It will return nil instead: + ``map[0][91][91] = nil`` + + So you need to account for this! \ No newline at end of file diff --git a/export-map.lua b/export-map.lua new file mode 100644 index 000000000..0c600d8c8 --- /dev/null +++ b/export-map.lua @@ -0,0 +1,279 @@ +-- Export fortress map tile data to a JSON file +-- based on export-map.lua by mikerenfro: +-- https://github.com/mikerenfro/df-map-export/blob/main/export-map.lua +-- redux version by timothymtorres + +local tm = require('tile-material') +local utils = require('utils') +local json = require('json') +local argparse = require('argparse') + +local include_underworld_z = false +local underworld_z + +-- the layer of the underworld +for _, feature in ipairs(df.global.world.features.map_features) do + if feature:getType() == df.feature_type.underworld_from_layer then + underworld_z = feature.layer + end +end + +local function classify_tile(options, x, y, z) + -- The last z-levels of hell shrink their x/y size unexpectedly! (ಠ_ಠ) + -- if your map is 190x190, the last hell z-levels are gonna be like 90x90 + if dfhack.maps.getTileType(x, y, z) == nil then + return nil -- Designating the non-tiles of hell to be nil + end + + local tileattrs = df.tiletype.attrs[dfhack.maps.getTileType(x, y, z)] + local tileflags, tile_occupancy = dfhack.maps.getTileFlags(x, y, z) + + local tile_data = {} + + for map_option, position in pairs(options) do + if(map_option == "tiletype") then + tile_data[position] = tileattrs.material + elseif(map_option == "shape") then + tile_data[position] = tileattrs.shape + elseif(map_option == "special") then + tile_data[position] = tileattrs.special + elseif(map_option == "variant") then + tile_data[position] = tileattrs.variant + elseif(map_option == "hidden") then + tile_data[position] = tileflags.hidden + elseif(map_option == "light") then + tile_data[position] = tileflags.light + elseif(map_option == "subterranean") then + tile_data[position] = tileflags.subterranean + elseif(map_option == "outside") then + tile_data[position] = tileflags.outside + elseif(map_option == "aquifer") then + -- hardcoding these values bc they are not directly in a list + if(tileflags.water_table and tile_occupancy.heavy_aquifer) then + tile_data[position] = 2 + elseif(tileflags.water_table) then + tile_data[position] = 1 + else + tile_data[position] = 0 + end + elseif(map_option == "material") then + if(tileattrs.material >= 8 and tileattrs.material <= 11) then + -- grass material IDs [8-11] will throw an error so we skip them + tile_data[position] = nil + else + local material = tm.GetTileMat(x, y, z) + tile_data[position] = material and material.index or nil + end + end + end + + return tile_data +end + +local function setup_keys(options) + local KEYS = {} + + if(options.tiletype) then + KEYS.TILETYPE = {} + for id, material in ipairs(df.tiletype_material) do + KEYS.TILETYPE[id] = material + end + end + + if(options.shape) then + KEYS.SHAPE = {} + for id, shape in ipairs(df.tiletype_shape) do + KEYS.SHAPE[id] = shape + end + end + + if(options.special) then + KEYS.SPECIAL = {} + for id, special in ipairs(df.tiletype_special) do + KEYS.SPECIAL[id] = special + end + end + + if(options.variant) then + KEYS.VARIANT = {} + for id, variant in ipairs(df.tiletype_variant) do + KEYS.VARIANT[id] = variant + end + end + + if(options.aquifer) then + -- We are hardcoding since this info is not easily listed anywhere + KEYS.AQUIFER = { + [0] = "NONE", + [1] = "LIGHT", + [2] = "HEAVY", + } + end + + if(options.material) then + KEYS.MATERIAL = {} + KEYS.MATERIAL.PLANT = {} + for id, plant in ipairs(df.global.world.raws.plants.all) do + KEYS.MATERIAL.PLANT[id] = plant.id + end + + KEYS.MATERIAL.SOLID = {} -- everything but plants (stones, gems, metals) + KEYS.MATERIAL.METAL = {} + KEYS.MATERIAL.STONE = {} + KEYS.MATERIAL.GEM = {} + + for id, rock in ipairs(df.global.world.raws.inorganics) do + local material = rock.material + local name = material.state_adj.Solid + KEYS.MATERIAL.SOLID[id] = name +-- cant sort by key see +-- https://stackoverflow.com/questions/26160327/sorting-a-lua-table-by-key + KEYS.MATERIAL.STONE[id] = material.flags.IS_STONE and name or false + KEYS.MATERIAL.GEM[id] = material.flags.IS_GEM and name or false + KEYS.MATERIAL.METAL[id] = material.flags.IS_METAL and name or false + end + end + + return KEYS +end + +local function export_all_z_levels(fortress_name, folder, options) + local xmax, ymax, zmax = dfhack.maps.getTileSize() + local filename = string.format("%s/%s.json", folder, fortress_name) + + if dfhack.filesystem.exists(filename) then + qerror('Destination file ' .. filename .. ' already exists!') + return false + end + + local data = {} + + data.ARGUMENT_OPTION_ORDER = options + data.MAP_SIZE = { + x = xmax, + y = ymax, + -- subtract underworld levels if excluded from options + z = include_underworld_z and zmax or (zmax - underworld_z), + underworld_z_level = include_underworld_z and underworld_z or nil, + } + data.KEYS = setup_keys(options) + + data.map = {} + + local zmin = 0 + if not include_underworld_z then -- skips all z-levels in the underworld + zmin = underworld_z + end + + -- start from bottom z-level (underworld) to top z-level (sky) + for z = zmin, zmax-1 do + local level_data = {} + for y = 0, ymax - 1 do + local row_data = {} + for x = 0, xmax - 1 do + local classification = classify_tile(options, x, y, z) + table.insert(row_data, classification) + end + table.insert(level_data, row_data) + end + table.insert(data.map, level_data) + end + + local f = assert(io.open(filename, 'w')) + f:write(json.encode(data)) + f:close() + print("File created in Dwarf Fortress folder under " .. filename) +end + + +local function export_fortress_map(options) + local fortress_name = dfhack.TranslateName( + df.global.world.world_data.active_site[0].name + ) + local export_path = "map-exports/" .. fortress_name + dfhack.filesystem.mkdir_recursive(export_path) + export_all_z_levels(fortress_name, export_path, options) +end + +if dfhack_flags.module then + return +end + +if not dfhack.isMapLoaded() then + qerror('This script requires a fortress map to be loaded') +end + +local options, args = { + help = false, + tiletype = false, + shape = false, + special = false, + variant = false, + hidden = false, + light = false, + subterranean = false, + outside = false, + aquifer = false, + material = false, +}, {...} + +local positionals = argparse.processArgsGetopt(args, { + {'', 'help', handler=function() options.help = true end}, + {'t', 'tiletype', handler=function() options.tiletype = true end}, + {'s', 'shape', handler=function() options.shape = true end}, + {'p', 'special', handler=function() options.special = true end}, + {'r', 'variant', handler=function() options.variant = true end}, + {'h', 'hidden', handler=function() options.hidden = true end}, + {'l', 'light', handler=function() options.light = true end}, + {'b', 'subterranean', handler=function() options.subterranean = true end}, + {'o', 'outside', handler=function() options.outside = true end}, + {'a', 'aquifer', handler=function() options.aquifer = true end}, + {'m', 'material', handler=function() options.material = true end}, + -- local var since underworld not in ordered option + {'u', 'underworld', handler= function() include_underworld_z = true end}, +}) + +if positionals[1] == "help" or options.help then + print(dfhack.script_help()) + return false +elseif positionals[1] == "include" then + -- no need to change anything +elseif positionals[1] == "exclude" then + for setting in pairs(options) do + options[setting] = not options[setting] + end +else -- include everything + for setting in pairs(options) do + options[setting] = true + end + -- don't forget to include underworld + include_underworld_z = true +end + +local ordered_options = { + "tiletype", + "shape", + "special", + "variant", + "hidden", + "light", + "subterranean", + "outside", + "aquifer", + "material", +} + +-- reorganize ordered options based on selected options via argparse +-- this is so ARGUMENT_OPTION_ORDER has the correct order with no gaps +for setting in pairs(options) do + if not options[setting] then + for pos, json_setting in ipairs(ordered_options) do + if setting == json_setting then + table.remove(ordered_options, pos) + end + end + end +end + +ordered_options = utils.invert(ordered_options) +export_fortress_map(ordered_options) From d60099016ca9ef58860b14f1f5f67bb2f403851f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:41:13 +0000 Subject: [PATCH 2/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/export-map.rst | 52 ++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/export-map.rst b/docs/export-map.rst index fabf543eb..85ce6a586 100644 --- a/docs/export-map.rst +++ b/docs/export-map.rst @@ -5,12 +5,12 @@ export-map :summary: Export fortress map tile data to a JSON file :tags: dev map -WARNING - This command will cause the game to freeze for minutes depending on +WARNING - This command will cause the game to freeze for minutes depending on map size and options enabled. -Exports the fortress map tile data to a JSON file. (does not include items, -characters, buildings, etc.) Depending on options enabled, there will be a -``KEY`` table in the JSON with relevant [number ID] values that match a number +Exports the fortress map tile data to a JSON file. (does not include items, +characters, buildings, etc.) Depending on options enabled, there will be a +``KEY`` table in the JSON with relevant [number ID] values that match a number to their object type. Usage @@ -27,17 +27,17 @@ Examples Exports the fortress map to JSON with ALL data included ``export-map include -m -s -v`` - Exports the fortress map to JSON with only materials, shape, and vein data + Exports the fortress map to JSON with only materials, shape, and vein data included ``export-map exclude --variant --hidden --light`` - Exports the fortress map to JSON with variant, hidden, and light data + Exports the fortress map to JSON with variant, hidden, and light data excluded Required -------- -When you are using options, you must include one of these settings. +When you are using options, you must include one of these settings. ``include`` Include only the data listed from options to the JSON (whitelist) @@ -58,11 +58,11 @@ Options The tile shape classification [number ID] (EMPTY/FLOOR/WALL/STAIR/etc.) ``-p``, ``--special`` - The tile surface special properties for smoothness [number ID] + The tile surface special properties for smoothness [number ID] (NORMAL/SMOOTH/ROUGH/etc.) (used for engraving) ``-r``, ``--variant`` - The specific variant of a tile that have visual variations [number] (like + The specific variant of a tile that have visual variations [number] (like grass tiles in ASCII mode) ``-h``, ``--hidden`` @@ -72,7 +72,7 @@ Options Whether tile is exposed to light [boolean] ``-b``, ``--subterranean`` - Whether the tile is considered underground [boolean] (used to determine + Whether the tile is considered underground [boolean] (used to determine crops that can be planted underground) ``-o``, ``--outside`` @@ -84,7 +84,7 @@ Options ``-m``, ``--material`` The material inside the tile [number ID] (IRON/GRANITE/CLAY/ - TOPAZOLITE/BLACK_OPAL/etc.) (will return nil if the tile is empty) + TOPAZOLITE/BLACK_OPAL/etc.) (will return nil if the tile is empty) ``-u``, ``--underworld`` Whether the underworld z-levels will be included [boolean] @@ -103,15 +103,15 @@ JSON DATA ``MAP_SIZE`` A table containing basic information about the map size for width, height, - depth. (x, y, z) The underworld_z_level is included if the underworld option + depth. (x, y, z) The underworld_z_level is included if the underworld option is enabled and the map depth (z) will be automatically adjusted. ``KEYS`` The tables containing the [number ID] values for different options. ``"SHAPE": { - "-1": "NONE", - "0": "EMPTY", + "-1": "NONE", + "0": "EMPTY", "1": "FLOOR", "2": "BOULDERS", "3": "PEBBLES", @@ -121,7 +121,7 @@ JSON DATA `` ``"PLANT": { - "0": "SINGLE-GRAIN_WHEAT", + "0": "SINGLE-GRAIN_WHEAT", "1": "TWO-GRAIN_WHEAT", "2": "SOFT_WHEAT", "3": "HARD_WHEAT", @@ -132,38 +132,38 @@ JSON DATA `` ``"AQUIFER": { - "0": "NONE", + "0": "NONE", "1": "LIGHT", "2": "HEAVY" `` Note - when using the ``materials`` option, you need to pair the [number ID] - with the correct ``KEYS`` material table. Generally you use ``tiletype`` - option as a helper to sort tiles into different material types. I would + with the correct ``KEYS`` material table. Generally you use ``tiletype`` + option as a helper to sort tiles into different material types. I would recommend consulting ``tile-material.lua`` to see how materials are sorted. ``map`` - JSON map data is arranged as: ``map[z][y][x] = {tile_data}`` - + JSON map data is arranged as: ``map[z][y][x] = {tile_data}`` + JSON maps start at index [1]. (starts at map[1][1][1]) DF maps start at index [0]. (starts at map[0][0][0]) - To translate an actual DF map position from the JSON map you need add +1 to + To translate an actual DF map position from the JSON map you need add +1 to all x/y/z coordinates to get the correct tile position. - The ``ARGUMENT_OPTION_ORDER`` determines order of tile data. (see above) + The ``ARGUMENT_OPTION_ORDER`` determines order of tile data. (see above) I would recommend referencing the tile data like so: ``shape = json_data.map[z][x][y][json_data.ARGUMENT_OPTIONS_ORDER.shape]`` ``light = json_data.map[z][x][y][json_data.ARGUMENT_OPTIONS_ORDER.light]`` - Note - some of the bottom z-levels for hell do not have the same - width/height as the default map. So if your map is 190x190, the last hell + Note - some of the bottom z-levels for hell do not have the same + width/height as the default map. So if your map is 190x190, the last hell z-levels are gonna be like 90x90. Instead of returning normal tile data like: ``map[0][90][90] = {tile_data}`` It will return nil instead: - ``map[0][91][91] = nil`` + ``map[0][91][91] = nil`` - So you need to account for this! \ No newline at end of file + So you need to account for this! From 9cbfcbd95fc4b1bca590d114747cd7524c8da312 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 21 Oct 2024 10:37:19 -0500 Subject: [PATCH 3/8] Fix bad code quote markdown --- docs/export-map.rst | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/export-map.rst b/docs/export-map.rst index 85ce6a586..8da9fd742 100644 --- a/docs/export-map.rst +++ b/docs/export-map.rst @@ -109,7 +109,7 @@ JSON DATA ``KEYS`` The tables containing the [number ID] values for different options. - ``"SHAPE": { + "SHAPE": { "-1": "NONE", "0": "EMPTY", "1": "FLOOR", @@ -118,9 +118,8 @@ JSON DATA "4": "WALL", ... "18": "ENDLESS_PIT" - `` - - ``"PLANT": { + + "PLANT": { "0": "SINGLE-GRAIN_WHEAT", "1": "TWO-GRAIN_WHEAT", "2": "SOFT_WHEAT", @@ -129,13 +128,11 @@ JSON DATA "5": "BARLEY", ... "224": "PALM" - `` - ``"AQUIFER": { + "AQUIFER": { "0": "NONE", "1": "LIGHT", "2": "HEAVY" - `` Note - when using the ``materials`` option, you need to pair the [number ID] with the correct ``KEYS`` material table. Generally you use ``tiletype`` From f72204de02d5d1ab0f5924d872ee31cfc432b51b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 15:38:34 +0000 Subject: [PATCH 4/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/export-map.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/export-map.rst b/docs/export-map.rst index 8da9fd742..5d922554c 100644 --- a/docs/export-map.rst +++ b/docs/export-map.rst @@ -118,7 +118,7 @@ JSON DATA "4": "WALL", ... "18": "ENDLESS_PIT" - + "PLANT": { "0": "SINGLE-GRAIN_WHEAT", "1": "TWO-GRAIN_WHEAT", From 56c04f0da12c581bff68fda0e8cd1783000ebe39 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 21 Oct 2024 11:02:49 -0500 Subject: [PATCH 5/8] Fix markdown newlines formatting --- docs/export-map.rst | 46 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/docs/export-map.rst b/docs/export-map.rst index 8da9fd742..04e1f2c1b 100644 --- a/docs/export-map.rst +++ b/docs/export-map.rst @@ -94,12 +94,16 @@ JSON DATA ``ARGUMENT_OPTION_ORDER`` The order of the selected options for how data is arranged at a map position + Example 1: - ``{"material": 1, "shape": 2, "hidden": 3}`` - ``map[z][y][x] = {material_data, shape_data, hidden_data}`` + ``{"material": 1, "shape": 2, "hidden": 3}`` + + ``map[z][y][x] = {material_data, shape_data, hidden_data}`` + Example 2: - ``{"variant": 3, "light": 1, "outside": 2, "aquifer": 4}`` - ``map[z][y][x] = {light_data, outside_data, variant_data, aquifer_data}`` + ``{"variant": 3, "light": 1, "outside": 2, "aquifer": 4}`` + + ``map[z][y][x] = {light_data, outside_data, variant_data, aquifer_data}`` ``MAP_SIZE`` A table containing basic information about the map size for width, height, @@ -109,30 +113,14 @@ JSON DATA ``KEYS`` The tables containing the [number ID] values for different options. - "SHAPE": { - "-1": "NONE", - "0": "EMPTY", - "1": "FLOOR", - "2": "BOULDERS", - "3": "PEBBLES", - "4": "WALL", - ... - "18": "ENDLESS_PIT" + ``"SHAPE": {"-1": "NONE", "0": "EMPTY", "1": "FLOOR", "2": "BOULDERS", + "3": "PEBBLES", "4": "WALL", ..., "18": "ENDLESS_PIT"}`` - "PLANT": { - "0": "SINGLE-GRAIN_WHEAT", - "1": "TWO-GRAIN_WHEAT", - "2": "SOFT_WHEAT", - "3": "HARD_WHEAT", - "4": "SPELT", - "5": "BARLEY", - ... - "224": "PALM" - - "AQUIFER": { - "0": "NONE", - "1": "LIGHT", - "2": "HEAVY" + ``"PLANT": {"0": "SINGLE-GRAIN_WHEAT", "1": "TWO-GRAIN_WHEAT", + "2": "SOFT_WHEAT", "3": "HARD_WHEAT", "4": "SPELT", "5": "BARLEY", ..., + "224": "PALM"}`` + + ``"AQUIFER": {"0": "NONE", "1": "LIGHT", "2": "HEAVY"}`` Note - when using the ``materials`` option, you need to pair the [number ID] with the correct ``KEYS`` material table. Generally you use ``tiletype`` @@ -150,7 +138,9 @@ JSON DATA The ``ARGUMENT_OPTION_ORDER`` determines order of tile data. (see above) I would recommend referencing the tile data like so: + ``shape = json_data.map[z][x][y][json_data.ARGUMENT_OPTIONS_ORDER.shape]`` + ``light = json_data.map[z][x][y][json_data.ARGUMENT_OPTIONS_ORDER.light]`` Note - some of the bottom z-levels for hell do not have the same @@ -158,9 +148,11 @@ JSON DATA z-levels are gonna be like 90x90. Instead of returning normal tile data like: + ``map[0][90][90] = {tile_data}`` It will return nil instead: + ``map[0][91][91] = nil`` So you need to account for this! From 7caa91e8e599d4550d80ff6a2b3dabaaed0f05ba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:06:38 +0000 Subject: [PATCH 6/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/export-map.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/export-map.rst b/docs/export-map.rst index 0092500a5..449187dff 100644 --- a/docs/export-map.rst +++ b/docs/export-map.rst @@ -27,7 +27,7 @@ Examples Exports the fortress map to JSON with ALL data included ``export-map include -m -s -v`` - Exports the fortress map to JSON with only materials, shape, and variant + Exports the fortress map to JSON with only materials, shape, and variant data included ``export-map exclude --variant --hidden --light`` @@ -113,11 +113,11 @@ JSON DATA ``KEYS`` The tables containing the [number ID] values for different options. - ``"SHAPE": {"-1": "NONE", "0": "EMPTY", "1": "FLOOR", "2": "BOULDERS", + ``"SHAPE": {"-1": "NONE", "0": "EMPTY", "1": "FLOOR", "2": "BOULDERS", "3": "PEBBLES", "4": "WALL", ..., "18": "ENDLESS_PIT"}`` - - ``"PLANT": {"0": "SINGLE-GRAIN_WHEAT", "1": "TWO-GRAIN_WHEAT", - "2": "SOFT_WHEAT", "3": "HARD_WHEAT", "4": "SPELT", "5": "BARLEY", ..., + + ``"PLANT": {"0": "SINGLE-GRAIN_WHEAT", "1": "TWO-GRAIN_WHEAT", + "2": "SOFT_WHEAT", "3": "HARD_WHEAT", "4": "SPELT", "5": "BARLEY", ..., "224": "PALM"}`` ``"AQUIFER": {"0": "NONE", "1": "LIGHT", "2": "HEAVY"}`` From 09c5b267c78b747e27d247c14bb80ba0423a6df6 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 22 Oct 2024 09:38:53 -0500 Subject: [PATCH 7/8] Add evilness option --- docs/export-map.rst | 7 ++++++- export-map.lua | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/export-map.rst b/docs/export-map.rst index 449187dff..11d1b87fb 100644 --- a/docs/export-map.rst +++ b/docs/export-map.rst @@ -87,7 +87,12 @@ Options TOPAZOLITE/BLACK_OPAL/etc.) (will return nil if the tile is empty) ``-u``, ``--underworld`` - Whether the underworld z-levels will be included [boolean] + Whether the underworld z-levels will be included + +``-e``, ``--evilness`` + Whether the evilness value will be included in MAP_SIZE table. This only + checks the value of the center map tile at ground level and will ignore + biomes at the edges of the map. JSON DATA --------- diff --git a/export-map.lua b/export-map.lua index f0706542e..4eff32cbf 100644 --- a/export-map.lua +++ b/export-map.lua @@ -10,6 +10,7 @@ local argparse = require('argparse') local include_underworld_z = false local underworld_z +local evilness -- the layer of the underworld for _, feature in ipairs(df.global.world.features.map_features) do @@ -18,6 +19,21 @@ for _, feature in ipairs(df.global.world.features.map_features) do end end +-- copied from agitation-rebalance.lua +-- check only one tile at the center of the map at ground lvl +-- (this ignore different biomes on the edges of the map) +local function get_evilness() + -- check around ground level + local lvls_above_ground = world.worldgen.worldgen_parms.levels_above_ground + local ground_z = (world.map.z_count - 2) - lvls_above_ground + local xmax, ymax = dfhack.maps.getTileSize() + local center_x, center_y = math.floor(xmax/2), math.floor(ymax/2) + local rgnX, rgnY = dfhack.maps.getTileBiomeRgn(center_x, center_y, ground_z) + local biome = dfhack.maps.getRegionBiome(rgnX, rgnY) + + return biome and biome.evilness or 0 +end + local function classify_tile(options, x, y, z) -- The last z-levels of hell shrink their x/y size unexpectedly! (ಠ_ಠ) -- if your map is 190x190, the last hell z-levels are gonna be like 90x90 @@ -155,6 +171,7 @@ local function export_all_z_levels(fortress_name, folder, options) -- subtract underworld levels if excluded from options z = include_underworld_z and zmax or (zmax - underworld_z), underworld_z_level = include_underworld_z and underworld_z or nil, + evilness = evilness or nil, } data.KEYS = setup_keys(options) @@ -230,7 +247,8 @@ local positionals = argparse.processArgsGetopt(args, { {'a', 'aquifer', handler=function() options.aquifer = true end}, {'m', 'material', handler=function() options.material = true end}, -- local var since underworld not in ordered option - {'u', 'underworld', handler= function() include_underworld_z = true end}, + {'u', 'underworld', handler=function() include_underworld_z = true end}, + {'e', 'evilness', handler=function() evilness = get_evilness() end}, }) if positionals[1] == "help" or options.help then From b2ec8837bfcced3240d35774eb28e78720286254 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 22 Oct 2024 10:30:20 -0500 Subject: [PATCH 8/8] Fix global world var --- export-map.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/export-map.lua b/export-map.lua index 4eff32cbf..16691f8a4 100644 --- a/export-map.lua +++ b/export-map.lua @@ -21,11 +21,13 @@ end -- copied from agitation-rebalance.lua -- check only one tile at the center of the map at ground lvl --- (this ignore different biomes on the edges of the map) +-- (this ignores different biomes on the edges of the map) local function get_evilness() -- check around ground level - local lvls_above_ground = world.worldgen.worldgen_parms.levels_above_ground - local ground_z = (world.map.z_count - 2) - lvls_above_ground + + local lvls_above + lvls_above = df.global.world.worldgen.worldgen_parms.levels_above_ground + local ground_z = (df.global.world.map.z_count - 2) - lvls_above local xmax, ymax = dfhack.maps.getTileSize() local center_x, center_y = math.floor(xmax/2), math.floor(ymax/2) local rgnX, rgnY = dfhack.maps.getTileBiomeRgn(center_x, center_y, ground_z) @@ -183,7 +185,7 @@ local function export_all_z_levels(fortress_name, folder, options) end -- start from bottom z-level (underworld) to top z-level (sky) - for z = zmin, zmax-1 do + for z = 0, 1-1 do local level_data = {} for y = 0, ymax - 1 do local row_data = {}