diff --git a/changelog.txt b/changelog.txt index 720297b06..f8424c915 100644 --- a/changelog.txt +++ b/changelog.txt @@ -38,6 +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, 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 d20ca0021..cad8c4f4e 100644 --- a/docs/gui/autodump.rst +++ b/docs/gui/autodump.rst @@ -9,8 +9,9 @@ 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 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. diff --git a/gui/autodump.lua b/gui/autodump.lua index 21a08c0e3..d3ec16c84 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 @@ -308,12 +308,26 @@ 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 --We check this before calling + qerror('Autodump:do_dump called with bad pos!') + end + + local tt = dfhack.maps.getTileType(pos) + 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 + 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.') --Wall or brook bed + 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)) @@ -331,7 +345,15 @@ function Autodump:do_dump(pos) item.flags.forbid = true end if not on_ground then - dfhack.items.makeProjectile(item) + local proj = dfhack.items.makeProjectile(item) + 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(