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 newspectatefeatures
New Features
advtools: newadvtools.fastcombatoverlay (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
resetcommand 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 useautocheeseinstead!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::removeFromSquaddfhack.units.setAutomaticProfessions: sets unit labors according to current work detail settingsgui.dwarfmode: adventure mode cursor now supported ingetCursorPos,setCursorPos, andclearCursorPosfuncitonsoverlay.isOverlayEnabled: new API for querying whether a given overlay is enabledoverlay: widgets can now declareoverlay_onenableandoverlay_ondisablefunctions 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
countHospitalSuppliesnow returnsabstract_building_contentsinstead ofhospital_supplies, which has different field names - When indexing into a vector named
scribejobs, replaceitem_idandwritten_content_idwithtarget_idandrelevant_id conversation_state_type.DenyPermissionSleepis nowSleepPermissionRequestedblock_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.penis nowbuilding_civzonest.zone_settings.pen.flagsbuilding_civzonest.zone_settings.tombis nowbuilding_civzonest.zone_settings.tomb.flagsbuilding_bridgest.gate_flags.closed/closing/openingare nowraised/raising/loweringbuilding_weaponst.gate_flags.closed/closing/openingare nowretracted/retracting/unretractingbuilding.design.builder1/builder1_civ/builder2are now.worker/worker_create_event/curworker(and the 2nd is a History Event, not an Entity)stockpile_settings.allow_organic/allow_inorganicare nowstockpile_settings.misc.allow_organic/allow_inorganicworld.busy_buildings[]is nowworld.building_uses.buildings[]world.coin_batchesis nowworld.coin_batches.allspatter.flags.water_solubleis nowexternalcreation_zone_pwg_alteration_campst.tent_matlgossis now.tent_matgloss(spelling fix)world.raws.body_templatesandworld.raws.bodyglossesare nowworld.raws.creaturebody.*world.raws.tissue_templates/body_detail_plans/creature_variationsare nowworld.raws.*.allmaterial_force_adjustst.mat_indxis nowmat_index(spelling fix)game.minimap.minimap[x][y]is nowgame.minimap.minimap[x][y].tilehistorical_entity.relations.diplomacy[]is nowhistorical_entity.relations.diplomacy.state[]historical_entity.conquered_site_group_flagsis nowhistorical_entity.law.conquered_site_group_flagsworld.effectsis nowworld.effects.allworld.raws.entitiesis nowworld.raws.entities.allsite_typeenum deleted, merged withworld_site_typeworld.event.dirty_waters[].*is nowworld.event.dirty_waters[].pos.*death_condition_typeenum replaced withhistfig_body_state(notably instate_profilest.body_state)history_hit_item,history_event_reason_info, andhistory_event_circumstance_inforemoved and substitutedknowledge_profilest.known_locations.ab_review[]is now.reports[](because.known_locationsgot merged withsite_reputation_info)world.raws.interactions[]is nowworld.raws.interactions.all[]itemdef_instrumentst.registers/timbreare nowitemdef_instrumentst.timbre.registers/timbredye_inforemoved and substitutedjob_art_specificationremoved 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.requiredis nowcreature_interaction_effect.counter_trigger.flag.bits.REQUIREDcreature_interaction_effect_targetremoved and substitutedmaterial_commonremoved, its contents prepended tomaterialandmaterial_templateworld.raws.material_templatesis nowworld.raws.material_templates.allworld.raws.syndromesis nowworld.raws.mat_table.syndromesworld.raws.effectsis nowworld.raws.mat_table.effectsworld.raws.inorganicsis nowworld.raws.inorganics.allworld.raws.inorganics_subsetis nowworld.raws.inorganics.cheapplotinfo.main.selected_hotkey/in_rename_hotkeyare nowplotinfo.main.hotkey_interface.*world.proj_listis nowworld.projectiles.allgeneral_ref_building_well_tag.directionis now a bitfieldworld_region_details.edges.(split_x/split_y)[][].x/yare now.break_one/break_twoworld_population_ref.depthis nowworld_population_ref.layer_depthand is now an integer instead of an enum- Bitfield
region_weather_flagis nowregion_weather_bits(to avoid conflicts) - Rhythm
beat_flagrealigned (PrimaryAccentremoved, because it wasn't really a unique flag) dipscript_info.script_steps/script_varsare nowdipscript_info.script.steps/varsscript_step_discussst.eventis nowscript_step_discussst.durationscript_step_dipeventstandscript_step_invasionstfields renamedsite_architecture_changest.spec_flagis now a tagged unionsquad.schedule[x][y]is nowsquad.schedule.routine[x].month[y]world.unit_chunksis nowworld.unit_chunks.allhistorical_entity.events[]is nowhistorical_entity.rumor_info.eventsworld.enemy_status_cache.rel_map[x][y]is nowworld.enemy_status_cache.rel_map[x][y].urunit.curse.interaction_id/interaction_time/interaction_delay/time_on_site/own_interaction/own_interaction_delayare nowunit.curse.interaction.*unit.cached_glowtile_typeis nowunit.cache.cached_glowtile_typeunit_preference.activeis nowunit_preference.flags.visiblewitness_report_flagsreplaced with correct flagscaste_body_info.clothing_items.[]is nowcaste_body_info.clothing_items.bp[]plant_tree_tile.branches_direnum collapsed into 4 simple flagsworld.populationsis nowworld.populations.allworld_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_directionis nowworld.selected_direction[0](and there are 3 additional entries)
- Building vmethod










