Q: How do I download DFHack?
A: Either add to your Steam library from our Steam page or scroll to the latest release on our GitHub releases page, expand the "Assets" list, and download the file for your platform (e.g. dfhack-XX.XX-rX-Windows-64bit.zip
. If you are on Windows and are manually installing from the zip file, please remember to right click on the file after downloading, open the file properties, and select the "Unblock" checkbox. This will prevent issues with Windows antivirus programs.
This is a beta release, so if you're installing from Steam, be sure to select the beta
branch for DFHack in your Steam client.
If you are on the Steam DF experimental
branch, please also switch DFHack to its experimental
branch in your Steam client.
This release is compatible with all distributions of Dwarf Fortress: Steam, Itch, and Classic.
Please report any issues (or feature requests) on the DFHack GitHub issue tracker. When reporting issues, please upload a zip file of your savegame and a zip file of your mods
directory to the cloud and add links to the GitHub issue. Make sure your files are downloadable by "everyone with the link". We need your savegame to reproduce the problem and test the fix, and we need your active mods so we can load your savegame. Issues with savegames and mods attached get fixed first!
Highlights
Follow your dwarves like a pro, or watch them like a fish tank, Skip adventure messages, Attach notes to the map, Schedule cheese making according to milk supplies
Follow your dwarves like a pro, or watch them like a fish tank
The spectate
tool has had a complete overhaul, and is now integrated into the vanilla follow mode. There are lots of ways you can interact with it.
If you start following a dwarf by clicking on the vanilla "camera" button, you'll see that the little panel that shows up in the lower left corner has a few more widgets on it. You can hit the right arrow key (or click on the icon) to follow another target, or you can hit the left arrow key (or click on the icon) to follow the previous target. This means you can quickly switch to a new dwarf and then back to a previous dwarf just by tapping the arrow keys.
There is also an indicator for whether "spectate mode" is on. If you turn it on, you can let the game run and spectate
will periodically shift the camera to follow a different dwarf. If you've managed to get your fort into a stable state, this is a good way to sit back, relax, and watch your dwarves like a fish tank.
How does it choose the next dwarf to follow? It's random, but you can tweak how it chooses targets with the new gui/spectate
interface. You can launch it by clicking on the gear icon on the follow panel, where the new left and right arrow widgets are. You can choose which kinds of units other than your own dwarves to include as possible targets, like livestock, enemies, or visitors. By default, the camera will prefer to follow units that are in combat and units that have newly arrived on the map.
If spectate mode is enabled and the new "cinematic action" option is on, the camera will even switch targets more quickly when there is combat afoot! If the "Auto unpause" option is on, events that would normally pause the game, like sieges or artifact announcements, will not pause the game at all. This allows a "true" fish tank mode where you can see your beautiful fort rise and fall of its own accord.
Spectate mode will automatically disengage when you jump in to take control. It switches off when you move the camera: the exact same way that vanilla follow mode switches off. Spectate mode will also disengage when you open the squads panel.
We've also made it easier to jump to following a specific target. There is a new global hotkey: Ctrl-g (for "go to"). It is available when you are on the main dwarf map (or the main adventure map, but "follow" mode isn't relevant there).
Ctrl-g will pop up the gui/sitemap
interface. You can start typing to search for a name, and Shift-click or Shift-Enter will start following that unit directly!
But wait, there's more!
You can also use gui/spectate
to configure live tooltips for your dwarves. If you turn on the spectate.tooltips
overlay, you can display information like their name, their current happiness level, and their current job. The "Follow" set of toggles controls what information will follow your dwarves around on the map in floating tooltips. The "Hover" set of toggles controls what information will be shown in a pop up when you hover your mouse over a unit.
Give it a try! My favorite configuration so far is:
- "Follow" shows an indicator for miserable and unhappy dwarves
- "Hover" shows the current stress level, name, and job
In graphics mode, you might prefer to set the blink period to 0 (to disable it), but in ascii mode, you'll want the "follow" tooltips to blink periodically so you can see what they are covering on the map.
Skip adventure messages
The new advtools.fastcombat
overlay allows you to skip combat animations and the announcement "More" button. If you're trying to walk through a populated area, this can be a huge time (and click) saver! Have you heard the one about the elf and the elf? Yes, we have! Let us walk across the room!
Now, to skip all the "More" messages, just hit any movement key. The first movement key will skip the messages to the end of the list. Hit the key again to move. It works the same with the mouse. The first click on the map will skip all messages to the end, and the second click will start your adventurer walking to that destination.
Attach notes to the map
We now have a tool for attaching notes to fort map tiles! gui/notes
is the UI for adding and managing map notes. You can memorialize events where they occurred
or leave design plans for yourself on the levels where you plan to expand your fort.
Schedule cheese making according to milk supplies
Cheese making is difficult to automate using work orders. A single job can consume anything from a bucket with a single unit of milk to a barrel with 100 units of milk. This makes it hard to predict how much cheese will actually be produced by a regular manager work order.
If you enable autocheese
in the DFHack control panel, it will scan your fort for barrels with a certain minimum amount of milk (default: 50), create a cheese making job specifically for that barrel, and assign this job to one of your idle dwarves (giving preference to skilled cheese makers).
Easy cheesy!
Announcements
Why beta?, PSAs
So why is this a beta?
In addition to the new features (which we always need feedback on!), DFHack has undergone an extensive internal reorganization to help align the code closer to how the internal DF structures are organized. For scripts, many of the df
namespace paths have changed. If you are maintaining an out-of-tree script, find out what identifiers have changed in the Structures release notes below.
As a player, please keep an eye out for commands that return errors when you run them or functionality that appears not to work like it used to. It is possible that typos have crept in with all the updates.
PSAs
As always, remember that, just like the vanilla DF game, DFHack tools can also have bugs. It is a good idea to save often and keep backups of the forts that you care about.
Some DFHack tools that worked in previous (pre-Steam) versions of DF have not been updated yet and are marked with the "unavailable" tag in their docs. If you try to run them, they will show a warning and exit immediately. You can run the command again to override the warning (though of course the tools may not work). We make no guarantees of reliability for the tools that are marked as "unavailable".
The in-game interface for running DFHack commands (gui/launcher
) will not show "unavailable" tools by default. You can still run them if you know their names, or you can turn on dev mode by hitting Ctrl-D while in gui/launcher
and they will be added to the autocomplete list. Some tools listed as "unavailable" in the docs do not compile yet and are not accessible at all, even when in dev mode.
If you see a tool complaining about the lack of a cursor, know that it's referring to the keyboard cursor (which used to be the only real option in Dwarf Fortress). You can enable the keyboard cursor by entering mining mode or selecting the dump/forbid tool and hitting Alt-K (the DFHack keybinding for toggle-kbd-cursor
). We're working on making DFHack tools more mouse-aware and accessible so this step isn't necessary in the future.
Changelog
New tools, fixes, and improvements
New Tools
autocheese
: automatically make cheese using barrels that have accumulated sufficient milkdevel/export-map
: export map tile data to a JSON filegui/notes
: UI for adding and managing notes attached to tiles on the mapgui/spectate
: interactive UI for configuring newspectate
features
New Features
advtools
: newadvtools.fastcombat
overlay (enabled by default) allows you to skip combat animations and the announcement "More" button by mashing the movement keysgui/sitemap
: is now the official "go to" tool. new global hotkey for fort and adventure mode: Ctrl-Gspectate
:- can now specify number of seconds (in real time) before switching to follow a new unit
- new "cinematic-action" mode that dynamically speeds up perspective switches based on intensity of conflict
- new global keybinding for toggling spectate mode: Ctrl-Shift-S
- new overlay panel that allows you to cycle through following next/previous units (regardless of whether spectate mode is enabled)
Fixes
- Windows console: fix possible hang if the console returns a too-small window width (for any reason)
changevein
: fix a crash that could occur when attempting to change a vein into itselfcreateitem
: produced items will now end up at the look cursor position (if it is active)gui/liquids
: using the remove tool with magma selected will no longer create unexpected unpathable tilesoverlay
: reset draw context between rendering widgets so context changes can't propagate from widget to widgetposition
: support for adv mode look cursorspectate
: don't allow temporarily modified announcement settings to be written to disk when "auto-unpause" mode is enabledstonesense
:- megashots no longer leave stonesense unresponsive
- items now properly render on top of stockpile indicators
- minecarts and wheelbarrows are now shown on the correct layer
Misc Improvements
autobutcher
: treat animals on restraints as unavailable for slaughtergui/confirm
: in the delete manager order confirmation dialog, show a description of which order you have selected to deletegui/design
: only display vanilla dimensions tooltip if the DFHack dimensions tooltip is disabledgui/notify
:- moody dwarf notification turns red when they can't reach workshop or items
- save reminder now appears in adventure mode
- save reminder changes color to yellow at 30 minutes and to orange at 60 minutes
gui/sitemap
: shift click to start following the selected unit or artifacthide-tutorials
:- handle tutorial popups for adventure mode
- new
reset
command that will re-enable popups in the current game (in case you hid them all and now want them back)
position
:- add adventurer tile position
- add global site position
- when a tile is selected, display relevant map block and intra-block offset
prioritize
:- when prioritizing jobs of a specified type, also output how many of those jobs were already prioritized before you ran the command
- don't include already-prioritized jobs in the output of
prioritize -j
spectate
: player-set configuration is now stored globally instead of per-fortstockpiles
: add property filters for brewable, millable, and processable (e.g. at a Farmer's workshop) organic materialsstonesense
: different types of dig-mode designations (normal, autodig, and the blueprint variants of both) now have distinct colors that more closely match the vanilla DF interface
Documentation
stonesense-art-guide
: guide for making sprite art for Stonesense
Removed
orders
: MakeCheese job removed from library/basic orders set. Please useautocheese
instead!stonesense
: removed the "follow DF cursor" tracking mode since the keyboard cursor is no longer commonly used for moving the map around
API
Buildings::checkFreeTiles
: now takes a building instead of a pointer to the building extentsItems::getItemBaseValue
: adjust to the reduced value of prepared meals (changed in DF 51.06)Items::getValue
: magical powers now correctly contribute to item valueMilitary::removeFromSquad
: removes unit from any squad assignmentsUnits::isUnitInBox
,Units::getUnitsInBox
: don't include inactive units
Lua
dfhack.buildings.checkFreeTiles
: now takes a building pointer instead of an extents parameterdfhack.military.removeFromSquad
: Lua API forMilitary::removeFromSquad
dfhack.units.setAutomaticProfessions
: sets unit labors according to current work detail settingsgui.dwarfmode
: adventure mode cursor now supported ingetCursorPos
,setCursorPos
, andclearCursorPos
funcitonsoverlay.isOverlayEnabled
: new API for querying whether a given overlay is enabledoverlay
: widgets can now declareoverlay_onenable
andoverlay_ondisable
functions to hook enable/disable
Structures
- create numerous new structures whose contents had previously been missing or inlined into other structures
- fix a variety of structure errors
- merged several duplicate structure/enum types
- promote all bay12 structures, enums, and bitfields to top-level types: this means that most
T_*
types now have top-level names - reorganize all structure definitions to match bay12 header layouts
- specific changes:
- Building vmethod
countHospitalSupplies
now returnsabstract_building_contents
instead ofhospital_supplies
, which has different field names - When indexing into a vector named
scribejobs
, replaceitem_id
andwritten_content_id
withtarget_id
andrelevant_id
conversation_state_type.DenyPermissionSleep
is nowSleepPermissionRequested
block_square_event_spoorst.[whatever]
is nowblock_square_event_spoorst.info.[whatever]
building_stockpilest.max_*/container_*
is nowbuilding_stockpilest.storage.max_*/container_*
building_civzonest.zone_settings.pen
is nowbuilding_civzonest.zone_settings.pen.flags
building_civzonest.zone_settings.tomb
is nowbuilding_civzonest.zone_settings.tomb.flags
building_bridgest.gate_flags.closed/closing/opening
are nowraised/raising/lowering
building_weaponst.gate_flags.closed/closing/opening
are nowretracted/retracting/unretracting
building.design.builder1/builder1_civ/builder2
are now.worker/worker_create_event/curworker
(and the 2nd is a History Event, not an Entity)stockpile_settings.allow_organic/allow_inorganic
are nowstockpile_settings.misc.allow_organic/allow_inorganic
world.busy_buildings[]
is nowworld.building_uses.buildings[]
world.coin_batches
is nowworld.coin_batches.all
spatter.flags.water_soluble
is nowexternal
creation_zone_pwg_alteration_campst.tent_matlgoss
is now.tent_matgloss
(spelling fix)world.raws.body_templates
andworld.raws.bodyglosses
are nowworld.raws.creaturebody.*
world.raws.tissue_templates/body_detail_plans/creature_variations
are nowworld.raws.*.all
material_force_adjustst.mat_indx
is nowmat_index
(spelling fix)game.minimap.minimap[x][y]
is nowgame.minimap.minimap[x][y].tile
historical_entity.relations.diplomacy[]
is nowhistorical_entity.relations.diplomacy.state[]
historical_entity.conquered_site_group_flags
is nowhistorical_entity.law.conquered_site_group_flags
world.effects
is nowworld.effects.all
world.raws.entities
is nowworld.raws.entities.all
site_type
enum deleted, merged withworld_site_type
world.event.dirty_waters[].*
is nowworld.event.dirty_waters[].pos.*
death_condition_type
enum replaced withhistfig_body_state
(notably instate_profilest.body_state
)history_hit_item
,history_event_reason_info
, andhistory_event_circumstance_info
removed and substitutedknowledge_profilest.known_locations.ab_review[]
is now.reports[]
(because.known_locations
got merged withsite_reputation_info
)world.raws.interactions[]
is nowworld.raws.interactions.all[]
itemdef_instrumentst.registers/timbre
are nowitemdef_instrumentst.timbre.registers/timbre
dye_info
removed and substitutedjob_art_specification
removed and substitutedentity_activity_statistics.discovered_(creature_foods/creatures/plant_foods/plants)
is nowentity_activity_statistics.knowledge.*
world.mandates[]
is nowworld.mandates.all[]
creature_interaction_effect.counter_trigger.required
is nowcreature_interaction_effect.counter_trigger.flag.bits.REQUIRED
creature_interaction_effect_target
removed and substitutedmaterial_common
removed, its contents prepended tomaterial
andmaterial_template
world.raws.material_templates
is nowworld.raws.material_templates.all
world.raws.syndromes
is nowworld.raws.mat_table.syndromes
world.raws.effects
is nowworld.raws.mat_table.effects
world.raws.inorganics
is nowworld.raws.inorganics.all
world.raws.inorganics_subset
is nowworld.raws.inorganics.cheap
plotinfo.main.selected_hotkey/in_rename_hotkey
are nowplotinfo.main.hotkey_interface.*
world.proj_list
is nowworld.projectiles.all
general_ref_building_well_tag.direction
is now a bitfieldworld_region_details.edges.(split_x/split_y)[][].x/y
are now.break_one/break_two
world_population_ref.depth
is nowworld_population_ref.layer_depth
and is now an integer instead of an enum- Bitfield
region_weather_flag
is nowregion_weather_bits
(to avoid conflicts) - Rhythm
beat_flag
realigned (PrimaryAccent
removed, because it wasn't really a unique flag) dipscript_info.script_steps/script_vars
are nowdipscript_info.script.steps/vars
script_step_discussst.event
is nowscript_step_discussst.duration
script_step_dipeventst
andscript_step_invasionst
fields renamedsite_architecture_changest.spec_flag
is now a tagged unionsquad.schedule[x][y]
is nowsquad.schedule.routine[x].month[y]
world.unit_chunks
is nowworld.unit_chunks.all
historical_entity.events[]
is nowhistorical_entity.rumor_info.events
world.enemy_status_cache.rel_map[x][y]
is nowworld.enemy_status_cache.rel_map[x][y].ur
unit.curse.interaction_id/interaction_time/interaction_delay/time_on_site/own_interaction/own_interaction_delay
are nowunit.curse.interaction.*
unit.cached_glowtile_type
is nowunit.cache.cached_glowtile_type
unit_preference.active
is nowunit_preference.flags.visible
witness_report_flags
replaced with correct flagscaste_body_info.clothing_items.[]
is nowcaste_body_info.clothing_items.bp[]
plant_tree_tile.branches_dir
enum collapsed into 4 simple flagsworld.populations
is nowworld.populations.all
world_data.constructions.map[x][y][N]
is nowworld_data.constructions.map[x][y].square[N]
world.family_info[]
is nowworld.family_info.family[]
world.fake_world_info[]
is nowworld.fake_world_info.language[]
world.selected_direction
is nowworld.selected_direction[0]
(and there are 3 additional entries)
- Building vmethod