From 971cc31d1d286c1cbfbdd6835611eca7617a5d32 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Sat, 27 Jul 2024 19:15:41 -0700 Subject: [PATCH 01/11] Update autodump.lua --- gui/autodump.lua | 50 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/gui/autodump.lua b/gui/autodump.lua index 21a08c0e3c..61265dc5f5 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -306,14 +306,50 @@ function Autodump:onRenderFrame(dc, rect) end end +local function tile_props(pos, tt) --Returns is_ground, is_open_air + local shape_attrs = df.tiletype_shape.attrs[df.tiletype.attrs[tt].shape] + if shape_attrs.walkable then --TODO: don't dump on statues, etc.? + return true, false --Floor, stair, or ramp + elseif shape_attrs.basic_shape == df.tiletype_shape_basic.Wall then + return false, false --Wall or fortification + end + + local _, occ = dfhack.maps.getTileFlags(pos) + if occ.building == df.tile_building_occ.None or + occ.building == df.tile_building_occ.Planned or + occ.building == df.tile_building_occ.Passable or + occ.building == df.tile_building_occ.Well then + return false, true --Item can fall safely through; any other may delete item projectile + elseif occ.building == df.tile_building_occ.Floored then + return true, false --Lowered bridge, forbidden hatch, etc. + elseif occ.building == df.tile_building_occ.Dynamic then + local bld = dfhack.buildings.findAtTile(pos) --Unforbidden closed hatch, etc. + return (bld and (bld._type == df.building_hatchst or + bld._type == df.building_grate_floorst or + bld._type == df.building_bars_floorst)), false + end + return false, false +end + function Autodump:do_dump(pos) pos = pos or dfhack.gui.getMousePos() - if not pos then return end - local tileattrs = df.tiletype.attrs[dfhack.maps.getTileType(pos)] - local basic_shape = df.tiletype_shape.attrs[tileattrs.shape].basic_shape - local on_ground = basic_shape == df.tiletype_shape_basic.Floor or - basic_shape == df.tiletype_shape_basic.Stair or - basic_shape == df.tiletype_shape_basic.Ramp + if not pos then + print('No cursor') + return + end + + local tt = dfhack.maps.getTileType(pos) + if not tt then + print('No map block') + return + end + + local on_ground, in_air = tile_props(pos, tt) + if not (on_ground or in_air) then + print('Dump tile blocked') + return + end + local items = #self.selected_items.list > 0 and self.selected_items.list or self.dump_items local mark_as_forbidden = self.subviews.mark_as_forbidden:getOptionValue() print(('teleporting %d items'):format(#items)) @@ -330,7 +366,7 @@ function Autodump:do_dump(pos) if mark_as_forbidden then item.flags.forbid = true end - if not on_ground then + if in_air then dfhack.items.makeProjectile(item) end else From 90760c8f0a3a6cda99c829100223ffa16d088b74 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Sat, 27 Jul 2024 19:46:04 -0700 Subject: [PATCH 02/11] Update changelog.txt --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 288bd442d0..81e6955cc7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -38,6 +38,7 @@ Template for new versions: - `prioritize`: fix incorrect loading of persisted data on some OS types - `list-waves`: no longer gets confused by units that leave the map and then return (e.g. squads who go out on raids) - `fix/dead-units`: fix error when removing dead units from burrows and the unit with the greatest ID was dead +- `gui/autodump`: fix dumping into invalid tiles, creating item projectiles that get destroyed ## Misc Improvements - `build-now`: if `suspendmanager` is running, run an unsuspend cycle immediately before scanning for buildings to build From c45a91be4c8583717e35b5451a89045d87d1ab9d Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Sun, 28 Jul 2024 09:33:36 -0700 Subject: [PATCH 03/11] Update autodump.lua - Just comments --- gui/autodump.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/autodump.lua b/gui/autodump.lua index 61265dc5f5..3a3556aaaa 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -323,12 +323,12 @@ local function tile_props(pos, tt) --Returns is_ground, is_open_air elseif occ.building == df.tile_building_occ.Floored then return true, false --Lowered bridge, forbidden hatch, etc. elseif occ.building == df.tile_building_occ.Dynamic then - local bld = dfhack.buildings.findAtTile(pos) --Unforbidden closed hatch, etc. + local bld = dfhack.buildings.findAtTile(pos) --Unforbidden hatch, etc. return (bld and (bld._type == df.building_hatchst or bld._type == df.building_grate_floorst or bld._type == df.building_bars_floorst)), false end - return false, false + return false, false --Don't trust it end function Autodump:do_dump(pos) From 03a403fe706bd15656cee216dd3bdda287b06518 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 29 Jul 2024 15:07:51 -0700 Subject: [PATCH 04/11] Update autodump.lua --- gui/autodump.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gui/autodump.lua b/gui/autodump.lua index 3a3556aaaa..fe925e342e 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -308,7 +308,7 @@ end local function tile_props(pos, tt) --Returns is_ground, is_open_air local shape_attrs = df.tiletype_shape.attrs[df.tiletype.attrs[tt].shape] - if shape_attrs.walkable then --TODO: don't dump on statues, etc.? + if shape_attrs.walkable then return true, false --Floor, stair, or ramp elseif shape_attrs.basic_shape == df.tiletype_shape_basic.Wall then return false, false --Wall or fortification @@ -334,19 +334,19 @@ end function Autodump:do_dump(pos) pos = pos or dfhack.gui.getMousePos() if not pos then - print('No cursor') + dfhack.printerr('Please hover mouse cursor over a target tile to dump to!') return end local tt = dfhack.maps.getTileType(pos) - if not tt then - print('No map block') + if not tt or !dfhack.maps.isTileVisible(pos) then + dfhack.printerr('Dump tile not visible! Must be in a revealed area of map.') return end local on_ground, in_air = tile_props(pos, tt) if not (on_ground or in_air) then - print('Dump tile blocked') + dfhack.printerr('Dump tile blocked! Can\'t dump on walls, fortifications, or certain midair buildings.') return end From 2ba17c9c2ff5eaff531f11443a257d2c4ca3bddd Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 29 Jul 2024 15:17:47 -0700 Subject: [PATCH 05/11] Docs * Update autodump.rst * Update autodump.lua --- docs/gui/autodump.rst | 7 +++++-- gui/autodump.lua | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/gui/autodump.rst b/docs/gui/autodump.rst index d20ca0021f..ec715af5a7 100644 --- a/docs/gui/autodump.rst +++ b/docs/gui/autodump.rst @@ -9,8 +9,11 @@ This is a general point and click interface for teleporting or destroying items. By default, it will teleport items you have marked for dumping, but if you draw boxes around items on the map, it will act on the selected items instead. Double-click anywhere on the map to teleport the items there. Be wary -(or excited) that if you teleport the items into an unsupported position (e.g. -mid-air), then they will become projectiles and fall. +(or excited) that if you teleport the items into an unsupported position +(e.g., mid-air), then they will become projectiles and fall. Items may not be +teleported into walls or fortifications. They may also not be teleported into +projectile-blocking mid-air buildings (such as water wheels), as this can +result in unintended item destruction. There are options to include or exclude forbidden items, items that are currently tagged as being used by an active job, and items dropped by traders. diff --git a/gui/autodump.lua b/gui/autodump.lua index fe925e342e..caee30c3b8 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -339,14 +339,14 @@ function Autodump:do_dump(pos) end local tt = dfhack.maps.getTileType(pos) - if not tt or !dfhack.maps.isTileVisible(pos) then + if not (tt and dfhack.maps.isTileVisible(pos)) then dfhack.printerr('Dump tile not visible! Must be in a revealed area of map.') return end local on_ground, in_air = tile_props(pos, tt) if not (on_ground or in_air) then - dfhack.printerr('Dump tile blocked! Can\'t dump on walls, fortifications, or certain midair buildings.') + dfhack.printerr('Dump tile blocked! Can\'t dump on walls, fortifications, or certain mid-air buildings.') return end From ec3e49e8580830fb27508880be30609315a07dcd Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 29 Jul 2024 18:38:02 -0700 Subject: [PATCH 06/11] Just set proper projectile flags --- changelog.txt | 2 +- docs/gui/autodump.rst | 4 +--- gui/autodump.lua | 44 ++++++++++++++----------------------------- 3 files changed, 16 insertions(+), 34 deletions(-) diff --git a/changelog.txt b/changelog.txt index 68e10f0dd6..9c3b96618a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -38,7 +38,7 @@ Template for new versions: - `prioritize`: fix incorrect loading of persisted data on some OS types - `list-waves`: no longer gets confused by units that leave the map and then return (e.g. squads who go out on raids) - `fix/dead-units`: fix error when removing dead units from burrows and the unit with the greatest ID was dead -- `gui/autodump`: fix dumping into invalid tiles, creating item projectiles that get destroyed +- `gui/autodump`: prevent dumping into walls or invalid map area, set proper projectile flags to prevent items from being destroyed ## Misc Improvements - `build-now`: if `suspendmanager` is running, run an unsuspend cycle immediately before scanning for buildings to build diff --git a/docs/gui/autodump.rst b/docs/gui/autodump.rst index ec715af5a7..2d92bfa41d 100644 --- a/docs/gui/autodump.rst +++ b/docs/gui/autodump.rst @@ -11,9 +11,7 @@ you draw boxes around items on the map, it will act on the selected items instead. Double-click anywhere on the map to teleport the items there. Be wary (or excited) that if you teleport the items into an unsupported position (e.g., mid-air), then they will become projectiles and fall. Items may not be -teleported into walls or fortifications. They may also not be teleported into -projectile-blocking mid-air buildings (such as water wheels), as this can -result in unintended item destruction. +teleported into walls or fortifications. There are options to include or exclude forbidden items, items that are currently tagged as being used by an active job, and items dropped by traders. diff --git a/gui/autodump.lua b/gui/autodump.lua index caee30c3b8..b26ea8b5c2 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -306,31 +306,6 @@ function Autodump:onRenderFrame(dc, rect) end end -local function tile_props(pos, tt) --Returns is_ground, is_open_air - local shape_attrs = df.tiletype_shape.attrs[df.tiletype.attrs[tt].shape] - if shape_attrs.walkable then - return true, false --Floor, stair, or ramp - elseif shape_attrs.basic_shape == df.tiletype_shape_basic.Wall then - return false, false --Wall or fortification - end - - local _, occ = dfhack.maps.getTileFlags(pos) - if occ.building == df.tile_building_occ.None or - occ.building == df.tile_building_occ.Planned or - occ.building == df.tile_building_occ.Passable or - occ.building == df.tile_building_occ.Well then - return false, true --Item can fall safely through; any other may delete item projectile - elseif occ.building == df.tile_building_occ.Floored then - return true, false --Lowered bridge, forbidden hatch, etc. - elseif occ.building == df.tile_building_occ.Dynamic then - local bld = dfhack.buildings.findAtTile(pos) --Unforbidden hatch, etc. - return (bld and (bld._type == df.building_hatchst or - bld._type == df.building_grate_floorst or - bld._type == df.building_bars_floorst)), false - end - return false, false --Don't trust it -end - function Autodump:do_dump(pos) pos = pos or dfhack.gui.getMousePos() if not pos then @@ -344,9 +319,12 @@ function Autodump:do_dump(pos) return end - local on_ground, in_air = tile_props(pos, tt) - if not (on_ground or in_air) then - dfhack.printerr('Dump tile blocked! Can\'t dump on walls, fortifications, or certain mid-air buildings.') + local on_ground + local shape_attrs = df.tiletype_shape.attrs[df.tiletype.attrs[tt].shape] + if shape_attrs.walkable then + on_ground = true --Floor, stair, or ramp + elseif shape_attrs.basic_shape == df.tiletype_shape_basic.Wall then + dfhack.printerr('Dump tile blocked! Can\'t dump on walls or fortifications.') return end @@ -366,8 +344,14 @@ function Autodump:do_dump(pos) if mark_as_forbidden then item.flags.forbid = true end - if in_air then - dfhack.items.makeProjectile(item) + if not on_ground then + local proj = dfhack.items.makeProjectile(item) + proj.flags.no_impact_destroy = true + proj.flags.bouncing = true + proj.flags.piercing = true + proj.flags.parabolic = true + proj.flags.no_adv_pause = true + proj.flags.no_collide = true end else print(('Could not move item: %s from (%d, %d, %d)'):format( From b8cb6ab156240f1c19704bdbbcc4c103e8c7f4d2 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 29 Jul 2024 19:05:54 -0700 Subject: [PATCH 07/11] Update autodump.lua --- gui/autodump.lua | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/gui/autodump.lua b/gui/autodump.lua index b26ea8b5c2..01191349b8 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -324,7 +324,7 @@ function Autodump:do_dump(pos) if shape_attrs.walkable then on_ground = true --Floor, stair, or ramp elseif shape_attrs.basic_shape == df.tiletype_shape_basic.Wall then - dfhack.printerr('Dump tile blocked! Can\'t dump on walls or fortifications.') + dfhack.printerr('Dump tile blocked! Can\'t dump inside walls or fortifications.') return end @@ -346,12 +346,14 @@ function Autodump:do_dump(pos) end if not on_ground then local proj = dfhack.items.makeProjectile(item) - proj.flags.no_impact_destroy = true - proj.flags.bouncing = true - proj.flags.piercing = true - proj.flags.parabolic = true - proj.flags.no_adv_pause = true - proj.flags.no_collide = true + if proj then + proj.flags.no_impact_destroy = true + proj.flags.bouncing = true + proj.flags.piercing = true + proj.flags.parabolic = true + proj.flags.no_adv_pause = true + proj.flags.no_collide = true + end end else print(('Could not move item: %s from (%d, %d, %d)'):format( From 2fa3a432d9d5cbfdc1eafa304a6303b5ca2fde6e Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 29 Jul 2024 19:14:33 -0700 Subject: [PATCH 08/11] Update autodump.lua --- gui/autodump.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gui/autodump.lua b/gui/autodump.lua index 01191349b8..606c76ccdc 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -308,10 +308,7 @@ end function Autodump:do_dump(pos) pos = pos or dfhack.gui.getMousePos() - if not pos then - dfhack.printerr('Please hover mouse cursor over a target tile to dump to!') - return - end + if not pos then return end --Shouldn't happen since button would be disabled local tt = dfhack.maps.getTileType(pos) if not (tt and dfhack.maps.isTileVisible(pos)) then From 9f4b85f4dab424ef5e8e57d1c50d3a93dc98ebc5 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 29 Jul 2024 19:18:17 -0700 Subject: [PATCH 09/11] Update autodump.lua --- gui/autodump.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/autodump.lua b/gui/autodump.lua index 606c76ccdc..f1975c0ce7 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -308,7 +308,9 @@ end function Autodump:do_dump(pos) pos = pos or dfhack.gui.getMousePos() - if not pos then return end --Shouldn't happen since button would be disabled + if not pos then --We check this before calling + dfhack.printerr('Autodump:do_dump called with bad pos!') + end local tt = dfhack.maps.getTileType(pos) if not (tt and dfhack.maps.isTileVisible(pos)) then From 73aea9af724cdefad758e982f95a8e0a346e607e Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 30 Jul 2024 21:57:19 -0700 Subject: [PATCH 10/11] Changes; prevent selecting in nil map block * Update autodump.lua * Update autodump.rst * Update changelog.txt --- changelog.txt | 3 ++- docs/gui/autodump.rst | 2 +- gui/autodump.lua | 13 +++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/changelog.txt b/changelog.txt index 9c3b96618a..5332812833 100644 --- a/changelog.txt +++ b/changelog.txt @@ -38,7 +38,8 @@ Template for new versions: - `prioritize`: fix incorrect loading of persisted data on some OS types - `list-waves`: no longer gets confused by units that leave the map and then return (e.g. squads who go out on raids) - `fix/dead-units`: fix error when removing dead units from burrows and the unit with the greatest ID was dead -- `gui/autodump`: prevent dumping into walls or invalid map area, set proper projectile flags to prevent items from being destroyed +- `gui/autodump`: prevent dumping into walls or invalid map area, as well as selecting in unallocated blocks +- `gui/autodump`: set proper projectile flags to prevent items from being destroyed ## Misc Improvements - `build-now`: if `suspendmanager` is running, run an unsuspend cycle immediately before scanning for buildings to build diff --git a/docs/gui/autodump.rst b/docs/gui/autodump.rst index 2d92bfa41d..1b8b28c823 100644 --- a/docs/gui/autodump.rst +++ b/docs/gui/autodump.rst @@ -11,7 +11,7 @@ you draw boxes around items on the map, it will act on the selected items instead. Double-click anywhere on the map to teleport the items there. Be wary (or excited) that if you teleport the items into an unsupported position (e.g., mid-air), then they will become projectiles and fall. Items may not be -teleported into walls or fortifications. +teleported into walls. There are options to include or exclude forbidden items, items that are currently tagged as being used by an active job, and items dropped by traders. diff --git a/gui/autodump.lua b/gui/autodump.lua index f1975c0ce7..d3ec16c840 100644 --- a/gui/autodump.lua +++ b/gui/autodump.lua @@ -229,7 +229,7 @@ function Autodump:select_box(bounds) for x=bounds.x1,bounds.x2 do local block = dfhack.maps.getTileBlock(xyz2pos(x, y, z)) local block_str = tostring(block) - if not seen_blocks[block_str] then + if block and not seen_blocks[block_str] then seen_blocks[block_str] = true self:select_items_in_block(block, bounds) end @@ -309,7 +309,7 @@ end function Autodump:do_dump(pos) pos = pos or dfhack.gui.getMousePos() if not pos then --We check this before calling - dfhack.printerr('Autodump:do_dump called with bad pos!') + qerror('Autodump:do_dump called with bad pos!') end local tt = dfhack.maps.getTileType(pos) @@ -319,11 +319,12 @@ function Autodump:do_dump(pos) end local on_ground - local shape_attrs = df.tiletype_shape.attrs[df.tiletype.attrs[tt].shape] - if shape_attrs.walkable then - on_ground = true --Floor, stair, or ramp + local shape = df.tiletype.attrs[tt].shape + local shape_attrs = df.tiletype_shape.attrs[shape] + if shape_attrs.walkable or shape == df.tiletype_shape.FORTIFICATION then + on_ground = true --Floor, stair, ramp, or fortification elseif shape_attrs.basic_shape == df.tiletype_shape_basic.Wall then - dfhack.printerr('Dump tile blocked! Can\'t dump inside walls or fortifications.') + dfhack.printerr('Dump tile blocked! Can\'t dump inside walls.') --Wall or brook bed return end From ad0df042da253c0c31e1310851f6a865199fd1ec Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 30 Jul 2024 22:01:59 -0700 Subject: [PATCH 11/11] Update autodump.rst --- docs/gui/autodump.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gui/autodump.rst b/docs/gui/autodump.rst index 1b8b28c823..cad8c4f4eb 100644 --- a/docs/gui/autodump.rst +++ b/docs/gui/autodump.rst @@ -11,7 +11,7 @@ you draw boxes around items on the map, it will act on the selected items instead. Double-click anywhere on the map to teleport the items there. Be wary (or excited) that if you teleport the items into an unsupported position (e.g., mid-air), then they will become projectiles and fall. Items may not be -teleported into walls. +teleported into walls or hidden tiles. There are options to include or exclude forbidden items, items that are currently tagged as being used by an active job, and items dropped by traders.