Merge branch 'develop' of https://github.com/DFHack/dfhack into develop

develop
Japa 2016-04-19 18:17:39 +05:30
commit 1317792cde
126 changed files with 1564 additions and 1018 deletions

@ -30,6 +30,7 @@ before_install:
script: script:
- git tag tmp-travis-build - git tag tmp-travis-build
- sh travis/git-info.sh - sh travis/git-info.sh
- sphinx-build -qW -j3 . docs/html
- python travis/pr-check-base.py - python travis/pr-check-base.py
- python travis/lint.py - python travis/lint.py
- python travis/authors-rst.py - python travis/authors-rst.py

@ -106,7 +106,7 @@ endif()
# set up versioning. # set up versioning.
set(DF_VERSION "0.42.06") set(DF_VERSION "0.42.06")
SET(DFHACK_RELEASE "alpha2") SET(DFHACK_RELEASE "beta1")
SET(DFHACK_PRERELEASE TRUE) SET(DFHACK_PRERELEASE TRUE)
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}") set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")

@ -21,6 +21,7 @@
When adding a new release, change "DFHack future" to the appropriate title When adding a new release, change "DFHack future" to the appropriate title
before releasing, and then add a new "DFHack future" section after releasing. before releasing, and then add a new "DFHack future" section after releasing.
.. _changelog:
######### #########
Changelog Changelog
@ -82,6 +83,8 @@ Fixes
- Fixed a crash bug caused by the historical figures DFHack uses to store persistent data. - Fixed a crash bug caused by the historical figures DFHack uses to store persistent data.
- More plugins should recognize non-dwarf citizens - More plugins should recognize non-dwarf citizens
- Fixed a possible crash from cloning jobs - Fixed a possible crash from cloning jobs
- moveToBuilding() now sets flags for items that aren't a structural part of the building properly
- `autotrade`, `stocks`: Made trading work when multiple caravans are present but only some can trade
- `confirm` note-delete: No longer interferes with name entry - `confirm` note-delete: No longer interferes with name entry
- `exportlegends`: Handles entities without specific races, and a few other fixes for things new to v0.42 - `exportlegends`: Handles entities without specific races, and a few other fixes for things new to v0.42
- `fastdwarf`: Fixed a bug involving teleporting mothers but not the babies they're holding. - `fastdwarf`: Fixed a bug involving teleporting mothers but not the babies they're holding.
@ -103,10 +106,13 @@ Fixes
Misc Improvements Misc Improvements
----------------- -----------------
- `autochop`: Can now edit log minimum/maximum directly and remove limit entirely
- `autolabor`, `autohauler`, `manipulator`: Added support for new jobs/labors/skills - `autolabor`, `autohauler`, `manipulator`: Added support for new jobs/labors/skills
- `colonies`: now implemented by a script - `colonies`: now implemented by a script
- `createitem`: Can now create items anywhere without specifying a unit, as long as a unit exists on the map
- `devel/export-dt-ini`: Updated for 0.42.06 - `devel/export-dt-ini`: Updated for 0.42.06
- `devel/find-offsets`: Automated several more scans - `devel/find-offsets`: Automated several more scans
- `gui/gm-editor`: Now supports finding some items with a numeric ID (with ``i``)
- `lua`: Now supports some built-in variables like `gui/gm-editor`, e.g. ``unit``, ``screen`` - `lua`: Now supports some built-in variables like `gui/gm-editor`, e.g. ``unit``, ``screen``
- `remotefortressreader`: Can now trigger keyboard events - `remotefortressreader`: Can now trigger keyboard events
- `stockflow`: Now offers better control over individual craft jobs - `stockflow`: Now offers better control over individual craft jobs
@ -159,28 +165,29 @@ Internals
- More DFHack build information used in plugin version checks and available to plugins and lua scripts - More DFHack build information used in plugin version checks and available to plugins and lua scripts
- Fixed a rare overflow issue that could cause crashes on Linux and OS X - Fixed a rare overflow issue that could cause crashes on Linux and OS X
- Stopped DF window from receiving input when unfocused on OS X - Stopped DF window from receiving input when unfocused on OS X
- Fixed issues with keybindings involving Ctrl-A and Ctrl-Z, as well as Alt-E/U/N on OS X - Fixed issues with keybindings involving :kbd:`Ctrl`:kbd:`A` and :kbd:`Ctrl`:kbd:`Z`,
as well as :kbd:`Alt`:kbd:`E`/:kbd:`U`/:kbd:`N` on OS X
- Multiple contexts can now be specified when adding keybindings - Multiple contexts can now be specified when adding keybindings
- Keybindings can now use F10-F12 and 0-9 - Keybindings can now use :kbd:`F10`-:kbd:`F12` and :kbd:`0`-:kbd:`9`
- Plugin system is no longer restricted to plugins that exist on startup - Plugin system is no longer restricted to plugins that exist on startup
- :file:`dfhack.init` file locations significantly generalized - :file:`dfhack.init` file locations significantly generalized
Lua Lua
--- ---
- Scripts can be enabled with the built-in enable/disable commands - Scripts can be enabled with the built-in `enable`/`disable <disable>` commands
- A new function, ``reqscript()``, is available as a safer alternative to ``script_environment()`` - A new function, ``reqscript()``, is available as a safer alternative to ``script_environment()``
- Lua viewscreens can choose not to intercept the OPTIONS keybinding - Lua viewscreens can choose not to intercept the OPTIONS keybinding
New internal commands New internal commands
--------------------- ---------------------
- kill-lua: Interrupt running Lua scripts - `kill-lua`: Interrupt running Lua scripts
- type: Show where a command is implemented - `type`: Show where a command is implemented
New plugins New plugins
----------- -----------
- `confirm`: Adds confirmation dialogs for several potentially dangerous actions - `confirm`: Adds confirmation dialogs for several potentially dangerous actions
- `fix-unit-occupancy`: Fixes issues with unit occupancy, such as faulty "unit blocking tile" messages (:bug:`3499`) - `fix-unit-occupancy`: Fixes issues with unit occupancy, such as faulty "unit blocking tile" messages (:bug:`3499`)
- title-version (formerly vshook): Display DFHack version on title screen - `title-version` (formerly ``vshook``): Display DFHack version on title screen
New scripts New scripts
----------- -----------
@ -222,7 +229,7 @@ Fixes
- `buildingplan`: Now supports hatch covers - `buildingplan`: Now supports hatch covers
- `gui/create-item`: fixed assigning quality to items, made :kbd:`Esc` work properly - `gui/create-item`: fixed assigning quality to items, made :kbd:`Esc` work properly
- `gui/gm-editor`: handles lua tables properly - `gui/gm-editor`: handles lua tables properly
- help: now recognizes built-in commands, like "help" - `help`: now recognizes built-in commands, like ``help``
- `manipulator`: fixed crash when selecting custom professions when none are found - `manipulator`: fixed crash when selecting custom professions when none are found
- `remotefortressreader`: fixed crash when attempting to send map info when no map was loaded - `remotefortressreader`: fixed crash when attempting to send map info when no map was loaded
- `search-plugin`: fixed crash in unit list after cancelling a job; fixed crash when disabling stockpile category after searching in a subcategory - `search-plugin`: fixed crash in unit list after cancelling a job; fixed crash when disabling stockpile category after searching in a subcategory
@ -254,7 +261,7 @@ Misc Improvements
- `automaterial`: Fixed several issues with constructions being allowed/disallowed incorrectly when using box-select - `automaterial`: Fixed several issues with constructions being allowed/disallowed incorrectly when using box-select
- `dwarfmonitor`: - `dwarfmonitor`:
- widgets' positions, formats, etc. are now customizable (see Readme) - widgets' positions, formats, etc. are now customizable
- weather display now separated from the date display - weather display now separated from the date display
- New mouse cursor widget - New mouse cursor widget
@ -267,16 +274,16 @@ Misc Improvements
- Now avoids errors with unrecognized types - Now avoids errors with unrecognized types
- `gui/hack-wish`: renamed to `gui/create-item` - `gui/hack-wish`: renamed to `gui/create-item`
- "keybinding list" accepts a context - `keybinding list <keybinding>` accepts a context
- `lever`: - `lever`:
- Lists lever names - Lists lever names
- "lever pull" can be used to pull the currently-selected lever - ``lever pull`` can be used to pull the currently-selected lever
- memview: Fixed display issue - ``memview``: Fixed display issue
- `modtools/create-item`: arguments are named more clearly, and you can specify the creator to be the unit with id ``df.global.unit_next_id-1`` (useful in conjunction with `modtools/create-unit`) - `modtools/create-item`: arguments are named more clearly, and you can specify the creator to be the unit with id ``df.global.unit_next_id-1`` (useful in conjunction with `modtools/create-unit`)
- nyan: Can now be stopped with dfhack-run - ``nyan``: Can now be stopped with dfhack-run
- plug: lists all plugins; shows state and number of commands in plugins - `plug`: lists all plugins; shows state and number of commands in plugins
- `prospect`: works from within command-prompt - `prospect`: works from within command-prompt
- `quicksave`: Restricted to fortress mode - `quicksave`: Restricted to fortress mode
- `remotefortressreader`: Exposes more information - `remotefortressreader`: Exposes more information
@ -307,7 +314,7 @@ Internals
--------- ---------
- Ruby library now included on OS X - Ruby scripts should work on OS X 10.10 - Ruby library now included on OS X - Ruby scripts should work on OS X 10.10
- libstdc++ should work with older versions of OS X - libstdc++ should work with older versions of OS X
- Added support for ``onLoadMap.init``/``onUnloadMap.init`` scripts - Added support for `onMapLoad.init / onMapUnload.init <other_init_files>` scripts
- game type detection functions are now available in the World module - game type detection functions are now available in the World module
- The ``DFHACK_LOG_MEM_RANGES`` environment variable can be used to log information to ``stderr.log`` on OS X - The ``DFHACK_LOG_MEM_RANGES`` environment variable can be used to log information to ``stderr.log`` on OS X
- Fixed adventure mode menu names - Fixed adventure mode menu names
@ -322,7 +329,7 @@ Lua
New Internal Commands New Internal Commands
--------------------- ---------------------
- `hide`, `show`: hide and show the console on Windows - `hide`, `show`: hide and show the console on Windows
- `sc-script`: Allows additional scripts to be run when certain events occur (similar to onLoad*.init scripts) - `sc-script`: Allows additional scripts to be run when certain events occur (similar to `onLoad.init` scripts)
New Plugins New Plugins
----------- -----------
@ -341,7 +348,7 @@ New Tweaks
Fixes Fixes
----- -----
- Fixed game type detection in `3dveins`, `gui/create-item`, `reveal`, `seedwatch` - Fixed game type detection in `3dveins`, `gui/create-item`, `reveal`, `seedwatch`
- PRELOAD_LIB: More extensible on Linux - ``PRELOAD_LIB``: More extensible on Linux
- `add-spatter`, `eventful`: Fixed crash on world load - `add-spatter`, `eventful`: Fixed crash on world load
- `add-thought`: Now has a proper subthought arg. - `add-thought`: Now has a proper subthought arg.
- `building-hacks`: Made buildings produce/consume correct amount of power - `building-hacks`: Made buildings produce/consume correct amount of power
@ -355,7 +362,7 @@ Fixes
- Fixed error message in Arena mode - Fixed error message in Arena mode
- no longer checks the DF version - no longer checks the DF version
- fixed ballistic arrow head orders - fixed ballistic arrow head orders
- convinces the bookkeeper to update records more often' - convinces the bookkeeper to update records more often
- `zone`: Stopped crash when scrolling cage owner list - `zone`: Stopped crash when scrolling cage owner list
@ -383,8 +390,8 @@ DFHack 0.40.24-r2
Internals Internals
--------- ---------
- Lua scripts can set environment variables of each other with dfhack.run_script_with_env. - Lua scripts can set environment variables of each other with ``dfhack.run_script_with_env``
- Lua scripts can now call each others internal nonlocal functions with dfhack.script_environment(scriptName).functionName(arg1,arg2). - Lua scripts can now call each others internal nonlocal functions with ``dfhack.script_environment(scriptName).functionName(arg1,arg2)``
- `eventful`: Lua reactions no longer require LUA_HOOK as a prefix; you can register a callback for the completion of any reaction with a name - `eventful`: Lua reactions no longer require LUA_HOOK as a prefix; you can register a callback for the completion of any reaction with a name
- Filesystem module now provides file access/modification times and can list directories (normally and recursively) - Filesystem module now provides file access/modification times and can list directories (normally and recursively)
- Units Module: New functions:: - Units Module: New functions::
@ -427,7 +434,7 @@ Fixes
- `add-thought`: updated to properly affect stress. - `add-thought`: updated to properly affect stress.
- `hfs-pit`: should work now - `hfs-pit`: should work now
- `autobutcher`: takes gelding into account - `autobutcher`: takes gelding into account
- init.lua existence checks should be more reliable (notably when using non-English locales) - :file:`init.lua` existence checks should be more reliable (notably when using non-English locales)
Misc Improvements Misc Improvements
----------------- -----------------
@ -464,7 +471,6 @@ New Scripts
Removed Removed
------- -------
- embark.lua
- needs_porting/* - needs_porting/*
Misc Improvements Misc Improvements
@ -472,615 +478,8 @@ Misc Improvements
Added support for searching more lists Added support for searching more lists
DFHack 0.40.23-r1 Older Changelogs
================= ================
Are kept in a seperate file: `HISTORY`
Internals
- plugins will not be loaded if globals they specify as required are not located (should prevent some crashes)
Fixes
-----
- Fixed numerous (mostly Lua-related) crashes on OS X by including a more up-to-date libstdc++
- :kbd:`Alt` should no longer get stuck on Windows (and perhaps other platforms as well)
- `gui/advfort` works again
- `autobutcher`: takes sexualities into account
- devel/export-dt-ini: Updated for 0.40.20+
- `digfort`: now checks file type and existence
- `exportlegends`: Fixed map export
- `full-heal`: Fixed a problem with selecting units in the GUI
- `gui/hack-wish`: Fixed restrictive material filters
- `mousequery`: Changed box-select key to Alt+M
- `dwarfmonitor`: correct date display (month index, separator)
- `putontable`: added to the readme
- `siren` should work again
- stderr.log: removed excessive debug output on OS X
- `trackstop`: No longer prevents cancelling the removal of a track stop or roller.
- Fixed a display issue with ``PRINT_MODE:TEXT``
- Fixed a symbol error (MapExtras::BiomeInfo::MAX_LAYERS) when compiling DFHack in Debug mode
New Plugins
-----------
- `fortplan`: designate construction of (limited) buildings from .csv file, quickfort-style
New Scripts
-----------
- `gui/stockpiles`: an in-game interface for saving and loading stockpile settings files.
- `position`: Reports the current date, time, month, and season, plus some location info. Port/update of position.py
- `hfs-pit`: Digs a hole to hell under the cursor. Replaces needs_porting/hellhole.cpp
Removed
-------
- embark.lua: Obsolete, use `embark-tools`
New tweaks
----------
- `eggs-fertile <tweak>`: Displays an egg fertility indicator on nestboxes
- `max-wheelbarrow <tweak>`: Allows assigning more than 3 wheelbarrows to a stockpile
Misc Improvements
-----------------
- `embark-tools`: Added basic mouse support on the local map
- Made some adventure mode keybindings in :file:`dfhack.init-example` only work in adventure mode
- `gui/companion-order`: added a default keybinding
- further work on needs_porting
DFHack 0.40.19-r1
=================
Fixes
-----
- `modtools/reaction-trigger`: fixed typo
- `modtools/item-trigger`: should now work with item types
New plugins
-----------
- `savestock, loadstock <stocksettings>`: save and load stockpile settings across worlds and saves
New scripts
-----------
- `remove-stress`: set selected or all units unit to -1,000,000 stress (this script replaces removebadthoughts)
Misc improvements
-----------------
- `command-prompt`: can now access selected items, units, and buildings
- `autolabor`: add an optional talent pool parameter
DFHack 0.40.16-r1
=================
Internals
---------
- `EventManager` should handle INTERACTION triggers a little better. It still can get confused about who did what but only rarely.
- `EventManager` should no longer trigger REPORT events for old reports after loading a save.
- lua/persist-table: a convenient way of using persistent tables of arbitrary structure and dimension in Lua
Fixes
-----
- `mousequery`: Disabled when linking levers
- `stocks`: Melting should work now
- `full-heal`: Updated with proper argument handling
- `modtools/reaction-trigger-transition`: should produce the correct syntax now
- `superdwarf`: should work better now
- `forum-dwarves`: update for new df-structures changes
New Scripts
-----------
- `adaptation`: view or set the cavern adaptation level of your citizens
- `add-thought`: allows the user to add thoughts to creatures.
- `gaydar`: detect the sexual orientation of units on the map
- `markdown`: Save a copy of a text screen in markdown (for reddit among others).
- devel/all-bob: renames everyone Bob to help test interaction-trigger
Misc Improvements
-----------------
- `autodump`: Can now mark a stockpile for auto-dumping (similar to automelt and autotrade)
- `buildingplan`: Can now auto-allocate rooms to dwarves with specific positions (e.g. expedition leader, mayor)
- `dwarfmonitor`: now displays a weather indicator and date
- lua/syndrome-util, `modtools/add-syndrome`: now you can remove syndromes by SYN_CLASS
- No longer write empty :file:`.history` files
DFHack 0.40.15-r1
=================
Fixes
-----
- mousequery: Fixed behavior when selecting a tile on the lowest z-level
Misc Improvements
-----------------
- `EventManager`: deals with frame_counter getting reset properly now.
- `modtools/item-trigger`: fixed equip/unequip bug and corrected minor documentation error
- `teleport`: Updated with proper argument handling and proper unit-at-destination handling.
- `autotrade`: Removed the newly obsolete :guilabel:`Mark all` functionality.
- `search-plugin`: Adapts to the new trade screen column width
- `tweak fast-trade <tweak>`: Switching the fast-trade keybinding to Shift-Up/Shift-Down, due to Select All conflict
DFHack 0.40.14-r1
=================
Internals
---------
- The DFHack console can now be disabled by setting the DFHACK_DISABLE_CONSOLE environment variable: ``DFHACK_DISABLE_CONSOLE=1 ./dfhack``
Fixes
-----
- Stopped duplicate load/unload events when unloading a world
- Stopped ``-e`` from being echoed when DFHack quits on Linux
- `automelt`: now uses a faster method to locate items
- `autotrade`: "Mark all" no longer double-marks bin contents
- `drain-aquifer`: new script replaces the buggy plugin
- `embark-tools`: no longer conflicts with keys on the notes screen
- `fastdwarf`: Fixed problems with combat/attacks
- `forum-dwarves`: should work now
- `manipulator`: now uses a stable sort, allowing sorting by multiple categories
- `rendermax`: updated to work with 0.40
New Plugins
-----------
- `trackstop`: Shows track stop friction and dump direction in its :kbd:`q` menu
New Tweaks
----------
- farm-plot-select: Adds "Select all" and "Deselect all" options to farm plot menus
- import-priority-category: Allows changing the priority of all goods in a category when discussing an import agreement with the liaison
- manager-quantity: Removes the limit of 30 jobs per manager order
- civ-view-agreement: Fixes overlapping text on the "view agreement" screen
- nestbox-color: Fixes the color of built nestboxes
Misc Improvements
-----------------
- `exportlegends`: can now handle site maps
DFHack 0.40.13-r1
=================
Internals
---------
- unified spatter structs
- added ruby df.print_color(color, string) method for dfhack console
Fixes
-----
- no more ``-e`` after terminating
- fixed `superdwarf`
DFHack 0.40.12-r1
=================
Internals
---------
- support for global :file:`onLoadWorld.init` and :file:`onUnloadWorld.init` files, called when loading and unloading a world
- Close file after loading a binary patch.
New Plugins
-----------
- `hotkeys`: Shows ingame viewscreen with all dfhack keybindings active in current mode.
- `automelt`: allows marking stockpiles so any items placed in them will be designated for melting
Fixes
-----
- possible crash fixed for `gui/hack-wish`
- `search-plugin`: updated to not conflict with BUILDJOB_SUSPEND
- `workflow`: job_material_category -> dfhack_material_category
Misc Improvements
-----------------
- now you can use ``@`` to print things in interactive Lua with subtley different semantics
- optimizations for stockpiles for `autotrade` and `stockflow`
- updated `exportlegends` to work with new maps, dfhack 40.11 r1+
DFHack 0.40.11-r1
=================
Internals
- Plugins on OS X now use ``.plug.dylib` as an extension instead of ``.plug.so``
Fixes
-----
- `3dveins`: should no longer hang/crash on specific maps
- `autotrade`, `search-plugin`: fixed some layout issues
- `deathcause`: updated
- `gui/hack-wish`: should work now
- `reveal`: no longer allocates data for nonexistent map blocks
- Various documentation fixes and updates
DFHack v0.40.10-r1
==================
A few bugfixes.
DFHack v0.40.08-r2
==================
Internals
---------
- supported per save script folders
- Items module: added createItem function
- Sorted CMakeList for plugins and plugins/devel
- diggingInvaders no longer builds if plugin building is disabled
- `EventManager`: EQUIPMENT_CHANGE now triggers for new units. New events::
ON_REPORT
UNIT_ATTACK
UNLOAD
INTERACTION
New Scripts
-----------
- lua/repeat-util: makes it easier to make things repeat indefinitely
- lua/syndrome-util: makes it easier to deal with unit syndromes
- forum-dwarves: helps copy df viewscreens to a file
- full-heal: fully heal a unit
- remove-wear: removes wear from all items in the fort
- repeat: repeatedly calls a script or a plugin
- ShowUnitSyndromes: shows syndromes affecting units and other relevant info
- teleport: teleports units
- devel/print-args
- fix/blood-del: makes it so civs don't bring barrels full of blood ichor or goo
- fix/feeding-timers: reset the feeding timers of all units
- gui/hack-wish: creates items out of any material
- gui/unit-info-viewer: displays information about units
- modtools/add-syndrome: add a syndrome to a unit or remove one
- modtools/anonymous-script: execute an lua script defined by a string. Useful for the ``*-trigger`` scripts.
- modtools/force: forces events: caravan, migrants, diplomat, megabeast, curiousbeast, mischievousbeast, flier, siege, nightcreature
- modtools/item-trigger: triggers commands based on equipping, unequipping, and wounding units with items
- modtools/interaction-trigger: triggers commands when interactions happen
- modtools/invader-item-destroyer: destroys invaders' items when they die
- modtools/moddable-gods: standardized version of Putnam's moddable gods script
- modtools/projectile-trigger: standardized version of projectileExpansion
- modtools/reaction-trigger: trigger commands when custom reactions complete; replaces autoSyndrome
- modtools/reaction-trigger-transition: a tool for converting mods from autoSyndrome to reaction-trigger
- modtools/random-trigger: triggers random scripts that you register
- modtools/skill-change: for incrementing and setting skills
- modtools/spawn-flow: creates flows, like mist or dragonfire
- modtools/syndrome-trigger: trigger commands when syndromes happen
- modtools/transform-unit: shapeshifts a unit, possibly permanently
Misc improvements
-----------------
- new function in utils.lua for standardized argument processing
Removed
-------
- digmat.rb: digFlood does the same functionality with less FPS impact
- scripts/invasionNow: scripts/modtools/force.lua does it better
- autoSyndrome replaced with scripts/modtools/reaction-trigger.lua
- syndromeTrigger replaced with scripts/modtools/syndrome-trigger.lua
- devel/printArgs plugin converted to scripts/devel/print-args.lua
- outsideOnly plugin replaced by modtools/outside-only
DFHack v0.40.08-r1
==================
Was a mistake. Don't use it.
DFHack v0.34.11-r5
==================
Internals
---------
- support for calling a lua function via a protobuf request (demonstrated by dfhack-run --lua).
- support for basic filesystem operations (e.g. chdir, mkdir, rmdir, stat) in C++ and Lua
- Lua API for listing files in directory. Needed for mod-manager.
- Lua API for creating unit combat reports and writing to gamelog.
- Lua API for running arbitrary DFHack commands
- support for multiple ``raw/init.d/*.lua`` init scripts in one save.
- eventful now has a more friendly way of making custom sidebars
- on Linux and OS X the console now supports moving the cursor back and forward by a whole word.
New scripts
-----------
- gui/mod-manager: allows installing/uninstalling mods into df from df/mods directory.
- gui/clone-uniform: duplicates the currently selected uniform in the military screen.
- fix/build-location: partial work-around for bug 5991 (trying to build wall while standing on it)
- undump-buildings: removes dump designation from materials used in buildings.
- exportlegends: exports data from legends mode, allowing a set-and-forget export of large worlds.
- log-region: each time a fort is loaded identifying information will be written to the gamelog.
- dfstatus: show an overview of critical stock quantities, including food, drinks, wood, and bars.
- command-prompt: a dfhack command prompt in df.
New plugins
-----------
- rendermax: replace the renderer with something else, eg ``rendermax light``- a lighting engine
- automelt: allows marking stockpiles for automelt (i.e. any items placed in stocpile will be designated for melting)
- embark-tools: implementations of Embark Anywhere, Nano Embark, and a few other embark-related utilities
- building-hacks: Allows to add custom functionality and/or animations to buildings.
- petcapRemover: triggers pregnancies in creatures so that you can effectively raise the default pet population cap
- 'plant create': spawn a new shrub under the cursor
New tweaks
----------
- craft-age-wear: make crafted items wear out with time like in old versions (bug 6003)
- adamantine-cloth-wear: stop adamantine clothing from wearing out (bug 6481)
- confirm-embark: adds a prompt before embarking (on the "prepare carefully" screen)
Misc improvements
-----------------
- plant: move the 'grow', 'extirpate' and 'immolate' commands as 'plant' subcommands
- digfort: improved csv parsing, add start() comment handling
- exterminate: allow specifying a caste (exterminate gob:male)
- createitem: in adventure mode it now defaults to the controlled unit as maker.
- autotrade: adds "(Un)mark All" options to both panes of trade screen.
- mousequery: several usability improvements.
- mousequery: show live overlay (in menu area) of what's on the tile under the mouse cursor.
- search: workshop profile search added.
- dwarfmonitor: add screen to summarise preferences of fortress dwarfs.
- getplants: add autochop function to automate woodcutting.
- stocks: added more filtering and display options.
- Siege engine plugin:
- engine quality and distance to target now affect accuracy
- firing the siege engine at a target produces a combat report
- improved movement speed computation for meandering units
- operators in Prepare To Fire mode are released from duty once hungry/thirsty if there is a free replacement
DFHack v0.34.11-r4
==================
New commands
------------
- diggingInvaders - allows invaders to dig and/or deconstruct walls and buildings in order to get at your dwarves.
- digFlood - automatically dig out specified veins as they are revealed
- enable, disable - Built-in commands that can be used to enable/disable many plugins.
- restrictice - Restrict traffic on squares above visible ice.
- restrictliquid - Restrict traffic on every visible square with liquid.
- treefarm - automatically chop trees and dig obsidian
New Scripts
-----------
- autobutcher: A GUI front-end for the autobutcher plugin.
- invasionNow: trigger an invasion, or many
- locate_ore: scan the map for unmined ore veins
- masspit: designate caged creatures in a zone for pitting
- multicmd: run a sequence of dfhack commands, separated by ';'
- startdwarf: change the number of dwarves for a new embark
- digmat: dig veins/layers tile by tile, as discovered
Misc improvements
-----------------
- autoSyndrome:
- disable by default
- reorganized special tags
- minimized error spam
- reset policies: if the target already has an instance of the syndrome you can skip,
add another instance, reset the timer, or add the full duration to the time remaining
- core: fix SC_WORLD_(UN)LOADED event for arena mode
- exterminate: renamed from slayrace, add help message, add butcher mode
- fastdwarf: fixed bug involving fastdwarf and teledwarf being on at the same time
- magmasource: rename to ``source``, allow water/magma sources/drains
- ruby: add df.dfhack_run "somecommand"
- syndromeTrigger: replaces and extends trueTransformation. Can trigger things when syndromes are added for any reason.
- tiletypes: support changing tile material to arbitrary stone.
- workNow: can optionally look for jobs when jobs are completed
New tweaks
----------
- hive-crash: Prevent crash if bees die in a hive with ungathered products (bug 6368).
New plugins
-----------
- 3dveins: Reshapes all veins on the map in a way that flows between Z levels. May be unstable. Backup before using.
- autotrade: Automatically send items in marked stockpiles to trade depot, when trading is possible.
- buildingplan: Place furniture before it's built
- dwarfmonitor: Records dwarf activity to measure fort efficiency
- mousequery: Look and poke at the map elements with the mouse.
- outsideOnly: make raw-specified buildings impossible to build inside
- resume: A plugin to help display and resume suspended constructions conveniently
- stocks: An improved stocks display screen.
Internals
---------
- Core: there is now a per-save dfhack.init file for when the save is loaded, and another for when it is unloaded
- EventManager: fixed job completion detection, fixed removal of TICK events, added EQUIPMENT_CHANGE event
- Lua API for a better random number generator and perlin noise functions.
- Once: easy way to make sure something happens once per run of DF, such as an error message
DFHack v0.34.11-r3
==================
Internals
---------
- support for displaying active keybindings properly.
- support for reusable widgets in lua screen library.
- Maps::canStepBetween: returns whether you can walk between two tiles in one step.
- EventManager: monitors various in game events centrally so that individual plugins
don't have to monitor the same things redundantly.
- Now works with OS X 10.6.8
Notable bugfixes
----------------
- autobutcher can be re-enabled again after being stopped.
- stopped Dwarf Manipulator from unmasking vampires.
- Stonesense is now fixed on OS X
Misc improvements
-----------------
- fastdwarf: new mode using debug flags, and some internal consistency fixes.
- added a small stand-alone utility for applying and removing binary patches.
- removebadthoughts: add --dry-run option
- superdwarf: work in adventure mode too
- tweak stable-cursor: carries cursor location from/to Build menu.
- deathcause: allow selection from the unitlist screen
- slayrace: allow targetting undeads
- Workflow plugin:
- properly considers minecarts assigned to routes busy.
- code for deducing job outputs rewritten in lua for flexibility.
- logic fix: collecting webs produces silk, and ungathered webs are not thread.
- items assigned to squads are considered busy, even if not in inventory.
- shearing and milking jobs are supported, but only with generic MILK or YARN outputs.
- workflow announces when the stock level gets very low once a season.
- Auto syndrome plugin: A way of automatically applying boiling rock syndromes and calling dfhack commands controlled by raws.
- Infinite sky plugin: Create new z-levels automatically or on request.
- True transformation plugin: A better way of doing permanent transformations that allows later transformations.
- Work now plugin: Makes the game assign jobs every time you pause.
New tweaks
----------
- tweak military-training: speed up melee squad training up to 10x (normally 3-5x).
New scripts
-----------
- binpatch: the same as the stand-alone binpatch.exe, but works at runtime.
- region-pops: displays animal populations of the region and allows tweaking them.
- lua: lua interpreter front-end converted to a script from a native command.
- dfusion: misc scripts with a text based menu.
- embark: lets you embark anywhere.
- lever: list and pull fort levers from the dfhack console.
- stripcaged: mark items inside cages for dumping, eg caged goblin weapons.
- soundsense-season: writes the correct season to gamelog.txt on world load.
- create-items: spawn items
- fix/cloth-stockpile: fixes bug 5739; needs to be run after savegame load every time.
New GUI scripts
---------------
- gui/guide-path: displays the cached path for minecart Guide orders.
- gui/workshop-job: displays inputs of a workshop job and allows tweaking them.
- gui/workflow: a front-end for the workflow plugin (part inspired by falconne).
- gui/assign-rack: works together with a binary patch to fix weapon racks.
- gui/gm-editor: an universal editor for lots of dfhack things.
- gui/companion-order: a adventure mode command interface for your companions.
- gui/advfort: a way to do jobs with your adventurer (e.g. build fort).
New binary patches
------------------
(for use with binpatch)
- armorstand-capacity: doubles the capacity of armor stands.
- custom-reagent-size: lets custom reactions use small amounts of inputs.
- deconstruct-heapfall: stops some items still falling on head when deconstructing.
- deconstruct-teleport: stops items from 16x16 block teleporting when deconstructing.
- hospital-overstocking: stops hospital overstocking with supplies.
- training-ammo: lets dwarves with quiver full of combat-only ammo train.
- weaponrack-unassign: fixes bug that negates work done by gui/assign-rack.
New Plugins
-----------
- fix-armory: Together with a couple of binary patches and the gui/assign-rack script, this plugin makes weapon racks, armor stands, chests and cabinets in properly designated barracks be used again for storage of squad equipment.
- search: Adds an incremental search function to the Stocks, Trading, Stockpile and Unit List screens.
- automaterial: Makes building constructions (walls, floors, fortifications, etc) a little bit easier by saving you from having to trawl through long lists of materials each time you place one.
- Dfusion: Reworked to make use of lua modules, now all the scripts can be used from other scripts.
- Eventful: A collection of lua events, that will allow new ways to interact with df world.
DFHack v0.34.11-r2
==================
Internals
---------
- full support for Mac OS X.
- a plugin that adds scripting in ruby.
- support for interposing virtual methods in DF from C++ plugins.
- support for creating new interface screens from C++ and lua.
- added various other API functions.
Notable bugfixes
----------------
- better terminal reset after exit on linux.
- seedwatch now works on reclaim.
- the sort plugin won't crash on cages anymore.
Misc improvements
-----------------
- autodump: can move items to any walkable tile, not just floors.
- stripcaged: by default keep armor, new dumparmor option.
- zone: allow non-domesticated birds in nestboxes.
- workflow: quality range in constraints.
- cleanplants: new command to remove rain water from plants.
- liquids: can paint permaflow, i.e. what makes rivers power water wheels.
- prospect: pre-embark prospector accounts for caves & magma sea in its estimate.
- rename: supports renaming stockpiles, workshops, traps, siege engines.
- fastdwarf: now has an additional option to make dwarves teleport to their destination.
- Autolabor plugin:
- can set nonidle hauler percentage.
- broker excluded from all labors when needed at depot.
- likewise, anybody with a scheduled diplomat meeting.
New commands
------------
- misery: multiplies every negative thought gained (2x by default).
- digtype: designates every tile of the same type of vein on the map for 'digging' (any dig designation).
New tweaks
----------
- tweak stable-cursor: keeps exact cursor position between d/k/t/q/v etc menus.
- tweak patrol-duty: makes Train orders reduce patrol timer, like the binary patch does.
- tweak readable-build-plate: fix unreadable truncation in unit pressure plate build ui.
- tweak stable-temp: fixes bug 6012; may improve FPS by 50-100% on a slow item-heavy fort.
- tweak fast-heat: speeds up item heating & cooling, thus making stable-temp act faster.
- tweak fix-dimensions: fixes subtracting small amounts from stacked liquids etc.
- tweak advmode-contained: fixes UI bug in custom reactions with container inputs in advmode.
- tweak fast-trade: Shift-Enter for selecting items quckly in Trade and Move to Depot screens.
- tweak military-stable-assign: Stop rightmost list of military->Positions from jumping to top.
- tweak military-color-assigned: In same list, color already assigned units in brown & green.
New scripts
-----------
- fixnaked: removes thoughts about nakedness.
- setfps: set FPS cap at runtime, in case you want slow motion or speed-up.
- siren: wakes up units, stops breaks and parties - but causes bad thoughts.
- fix/population-cap: run after every migrant wave to prevent exceeding the cap.
- fix/stable-temp: counts items with temperature updates; does instant one-shot stable-temp.
- fix/loyaltycascade: fix units allegiance, eg after ordering a dwarf merchant kill.
- deathcause: shows the circumstances of death for a given body.
- digfort: designate areas to dig from a csv file.
- drainaquifer: remove aquifers from the map.
- growcrops: cheat to make farm crops instantly grow.
- magmasource: continuously spawn magma from any map tile.
- removebadthoughts: delete all negative thoughts from your dwarves.
- slayrace: instakill all units of a given race, optionally with magma.
- superdwarf: per-creature fastdwarf.
- gui/mechanisms: browse mechanism links of the current building.
- gui/room-list: browse other rooms owned by the unit when assigning one.
- gui/liquids: a GUI front-end for the liquids plugin.
- gui/rename: renaming stockpiles, workshops and units via an in-game dialog.
- gui/power-meter: front-end for the Power Meter plugin.
- gui/siege-engine: front-end for the Siege Engine plugin.
- gui/choose-weapons: auto-choose matching weapons in the military equip screen.
New Plugins
-----------
- Dwarf Manipulator: Open the unit list, and press 'l' to access a Dwarf Therapist like UI in the game.
- Steam Engine:
Dwarven Water Reactors don't make any sense whatsoever and cause lag, so this may be
a replacement for those concerned by it. The plugin detects if a workshop with a
certain name is in the raws used by the current world, and provides the necessary
behavior. See ``hack/raw/*_steam_engine.txt`` for the necessary raw definitions.
Note: Stuff like animal treadmills might be more period, but absolutely can't be
done with tools dfhack has access to.
- Power Meter:
When activated, implements a pressure plate modification that detects power in gear
boxes built on the four adjacent N/S/W/E tiles. The gui/power-meter script implements
the necessary build configuration UI.
- Siege Engine:
When enabled and configured via gui/siege-engine, allows aiming siege engines
at a designated rectangular area with 360 degree fire range and across Z levels;
this works by rewriting the projectile trajectory immediately after it appears.
Also supports loading catapults with non-boulder projectiles, taking from a stockpile,
and restricting operator skill range like with ordinary workshops.
Disclaimer: not in any way to undermine the future siege update from Toady, but
the aiming logic of existing engines hasn't been updated since 2D, and is almost
useless above ground :(. Again, things like making siegers bring their own engines
is totally out of the scope of dfhack and can only be done by Toady.
- Add Spatter:
Detects reactions with certain names in the raws, and changes them from adding
improvements to adding item contaminants. This allows directly covering items
with poisons. The added spatters are immune both to water and 'clean items'.
Intended to give some use to all those giant cave spider poison barrels brought
by the caravans.
.. that's ``docs/history.rst``, if you're reading the raw text.

@ -4,13 +4,13 @@
<html lang="en-US"> <html lang="en-US">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=./docs/html/index.html"> <meta http-equiv="refresh" content="0;url=./docs/index.html">
<script type="text/javascript"> <script type="text/javascript">
window.location.href = "./docs/html/index.html" window.location.href = "./docs/index.html"
</script> </script>
<title>Page Redirection</title> <title>Page Redirection</title>
</head> </head>
<body> <body>
Follow this <a href='./docs/html/index.html'>link to the documentation.</a> Follow this <a href='./docs/index.html'>link to the documentation.</a>
</body> </body>
</html> </html>

@ -108,6 +108,7 @@ extlinks = {
'bug': ('http://www.bay12games.com/dwarves/mantisbt/view.php?id=%s', 'bug': ('http://www.bay12games.com/dwarves/mantisbt/view.php?id=%s',
'Bug '), 'Bug '),
'issue': ('https://github.com/DFHack/dfhack/issues/%s', 'Issue '), 'issue': ('https://github.com/DFHack/dfhack/issues/%s', 'Issue '),
'commit': ('https://github.com/DFHack/dfhack/commit/%s', 'Commit '),
} }
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.

@ -7,7 +7,7 @@ If you should be here and aren't, please get in touch on IRC or the forums,
or make a pull request! or make a pull request!
======================= ======================= =========================== ======================= ======================= ===========================
Name Github Other names Name Github Other
======================= ======================= =========================== ======================= ======================= ===========================
8Z 8Z 8Z 8Z
acwatkins acwatkins acwatkins acwatkins
@ -91,11 +91,13 @@ Sebastian Wolfertz Enkrod
Seth Woodworth sethwoodworth Seth Woodworth sethwoodworth
simon simon
Simon Jackson sizeak Simon Jackson sizeak
sv-esk sv-esk
Tacomagic Tacomagic
Tim Walberg twalberg Tim Walberg twalberg
Timothy Collett danaris Timothy Collett danaris
Tom Jobbins TheBloke Tom Jobbins TheBloke
Tom Prince Tom Prince
Travis Hoppe thoppe orthographic-pedant
txtsd txtsd txtsd txtsd
U-glouglou\\simon U-glouglou\\simon
Valentin Ochs Cat-Ion Valentin Ochs Cat-Ion

@ -29,8 +29,7 @@ decent skill in `memory research <contributing-memory-research>`.
* The patches are expected to be encoded in text format used by IDA. * The patches are expected to be encoded in text format used by IDA.
* See `this commit <https://github.com/DFHack/dfhack/commit/8a9e3d1a728>`_, * See :commit:`8a9e3d1a728` for examples.
when the 0.34.11 patches were discarded, for example patches.
* :issue:`546` is about the future of the binpatches, and may be useful reading. * :issue:`546` is about the future of the binpatches, and may be useful reading.
@ -50,7 +49,7 @@ directly in memory at runtime::
binpatch [check|apply|remove] <patchname> binpatch [check|apply|remove] <patchname>
If the name of the patch has no extension or directory separators, the If the name of the patch has no extension or directory separators, the
script uses ``hack/patches/<df-version>/<name>.dif``, thus auto-selecting script uses :file:`hack/patches/<df-version>/<name>.dif`, thus auto-selecting
the version appropriate for the currently loaded executable. the version appropriate for the currently loaded executable.
This is the preferred method; it's easier to debug, does not cause persistent This is the preferred method; it's easier to debug, does not cause persistent

@ -42,9 +42,11 @@ Contributing to DFHack
If you want to get involved with the development, create an account on If you want to get involved with the development, create an account on
GitHub, make a clone there and then use that as your remote repository instead. GitHub, make a clone there and then use that as your remote repository instead.
We'd love that; join us on IRC (#dfhack channel on freenode) for discussion, We'd love that; join us on IRC_ (#dfhack channel on freenode) for discussion,
and whenever you need help. and whenever you need help.
.. _IRC: https://webchat.freenode.net/?channels=dfhack
For lots more details on contributing to DFHack, including pull requests, code format, For lots more details on contributing to DFHack, including pull requests, code format,
and more, please see `contributing-code`. and more, please see `contributing-code`.
@ -101,7 +103,7 @@ Before you can build anything, you'll also need ``cmake``. It is advisable to al
You also need perl and the XML::LibXML and XML::LibXSLT perl packages (for the code generation parts). You also need perl and the XML::LibXML and XML::LibXSLT perl packages (for the code generation parts).
You should be able to find them in your distro repositories. You should be able to find them in your distro repositories.
To build Stonesense, you'll also need OpenGL headers. To build `stonesense`, you'll also need OpenGL headers.
Here are some package install commands for various platforms: Here are some package install commands for various platforms:
@ -109,15 +111,15 @@ Here are some package install commands for various platforms:
* For the required Perl modules: ``perl-xml-libxml`` and ``perl-xml-libxslt`` (or through ``cpan``) * For the required Perl modules: ``perl-xml-libxml`` and ``perl-xml-libxslt`` (or through ``cpan``)
* On 64-bit Ubuntu: * On 64-bit Ubuntu::
* ``apt-get install gcc cmake git gcc-multilib g++-multilib zlib1g-dev:i386 libxml-libxml-perl libxml-libxslt-perl``. apt-get install gcc cmake git gcc-multilib g++-multilib zlib1g-dev:i386 libxml-libxml-perl libxml-libxslt-perl
* On 32-bit Ubuntu: * On 32-bit Ubuntu::
* ``apt-get install gcc cmake git gcc-multilib g++-multilib zlib1g-dev libxml-libxml-perl libxml-libxslt-perl``. apt-get install gcc cmake git gcc-multilib g++-multilib zlib1g-dev libxml-libxml-perl libxml-libxslt-perl
* Debian-derived distros should have similar requirements. * Debian and derived distros should have similar requirements to Ubuntu.
Build Build
@ -505,9 +507,8 @@ or ``RelWithDebInfo``.
Then build the ``INSTALL`` target listed under ``CMakePredefinedTargets``. Then build the ``INSTALL`` target listed under ``CMakePredefinedTargets``.
##########################
Building the documentation Building the documentation
########################## ==========================
DFHack documentation, like the file you are reading now, is created as .rst files, DFHack documentation, like the file you are reading now, is created as .rst files,
which are in `reStructuredText (reST) <http://sphinx-doc.org/rest.html>`_ format. which are in `reStructuredText (reST) <http://sphinx-doc.org/rest.html>`_ format.
@ -530,7 +531,7 @@ The main thing you lose in plain text format is hyperlinking.)
Enabling documentation building Enabling documentation building
=============================== -------------------------------
First, make sure you have followed all the necessary steps for your platform as First, make sure you have followed all the necessary steps for your platform as
outlined in the rest of this document. outlined in the rest of this document.
@ -550,7 +551,7 @@ through the GUI, or else if you want to use an alternate file, such as
Or you could just run ``cmake`` on the command line like in other platforms. Or you could just run ``cmake`` on the command line like in other platforms.
Required dependencies Required dependencies
===================== ---------------------
In order to build the documentation, you must have Python with Sphinx In order to build the documentation, you must have Python with Sphinx
version 1.3.1 or later. Both Python 2.x and 3.x are supported. version 1.3.1 or later. Both Python 2.x and 3.x are supported.

@ -69,6 +69,7 @@ on how to write one yet, but it should be easy enough to copy one and just follo
Other than through plugins, it is possible to use DFHack via remote access interface, Other than through plugins, it is possible to use DFHack via remote access interface,
or by writing scripts in Lua or Ruby. There are plenty of examples in the scripts folder. or by writing scripts in Lua or Ruby. There are plenty of examples in the scripts folder.
The `lua-api` is quite well documented.
The most important parts of DFHack are the Core, Console, Modules and Plugins. The most important parts of DFHack are the Core, Console, Modules and Plugins.
@ -85,7 +86,9 @@ The most important parts of DFHack are the Core, Console, Modules and Plugins.
Rudimentary API documentation can be built using doxygen (see build options Rudimentary API documentation can be built using doxygen (see build options
in ``CMakeCache.txt`` or with ``ccmake`` or ``cmake-gui``). The full DFHack in ``CMakeCache.txt`` or with ``ccmake`` or ``cmake-gui``). The full DFHack
documentation is built with Sphinx, which runs automatically at compile time. documentation is built with Sphinx_, which runs automatically at compile time.
.. _Sphinx: http://www.sphinx-doc.org
DFHack consists of variously licensed code, but invariably weak copyleft. DFHack consists of variously licensed code, but invariably weak copyleft.
The main license is zlib/libpng, some bits are MIT licensed, and some are The main license is zlib/libpng, some bits are MIT licensed, and some are
@ -101,14 +104,14 @@ in the ``library/xml/`` submodule.
See https://github.com/DFHack/df-structures, and the documentation linked in the index. See https://github.com/DFHack/df-structures, and the documentation linked in the index.
Data structure layouts are described in files following the ``df.\*.xml`` name pattern. Data structure layouts are described in files following the ``df.*.xml`` name pattern.
This information is transformed by a perl script into C++ headers describing the This information is transformed by a perl script into C++ headers describing the
structures, and associated metadata for the Lua wrapper. These headers and data structures, and associated metadata for the Lua wrapper. These headers and data
are then compiled into the DFHack libraries, thus necessitating a compatibility are then compiled into the DFHack libraries, thus necessitating a compatibility
break every time layouts change; in return it significantly boosts the efficiency break every time layouts change; in return it significantly boosts the efficiency
and capabilities of DFHack code. and capabilities of DFHack code.
Global object addresses are stored in ``symbols.xml``, which is copied to the dfhack Global object addresses are stored in :file:`symbols.xml`, which is copied to the dfhack
release package and loaded as data at runtime. release package and loaded as data at runtime.
Remote access interface Remote access interface
@ -118,13 +121,13 @@ socket. Both the core and plugins can define remotely accessible methods. The
``dfhack-run`` command uses this interface to invoke ordinary console commands. ``dfhack-run`` command uses this interface to invoke ordinary console commands.
Currently the supported set of requests is limited, because the developers don't Currently the supported set of requests is limited, because the developers don't
know what exactly is most useful. ``remotefortressreader`` provides a fairly know what exactly is most useful. `remotefortressreader` provides a fairly
comprehensive interface for visualisers such as Armok Vision. comprehensive interface for visualisers such as :forums:`Armok Vision <146473>`.
Documentation Standards Documentation Standards
======================= =======================
DFHack documentation is built with Sphinx, and configured automatically DFHack documentation is built with Sphinx_, and configured automatically
through CMake. If you want to build the docs *only*, use this command:: through CMake. If you want to build the docs *only*, use this command::
sphinx-build . docs/html sphinx-build . docs/html
@ -134,10 +137,15 @@ there are a few important standards for completeness and consistent style. Trea
this section as a guide rather than iron law, match the surrounding text, and you'll this section as a guide rather than iron law, match the surrounding text, and you'll
be fine. be fine.
Everything should be documented! For plugins, it's a work in progress - use Each command should have a short (~54 character) help string, which is shown
``docs/Plugins.rst`` for now. Core functions and general explanations should by the `ls` command. For scripts, this is a comment on the first line
go in the documents for that component; if it's not clear add a new section (the comment marker and whitespace is stripped). For plugins it's the second
as some may be missing. argument to ``PluginCommand``. Please make this brief but descriptive!
Everything should be documented! If it's not clear *where* a particular
thing should be documented, ask on IRC or in the DFHack thread on Bay12 -
as well as getting help, you'll be providing valuable feedback that
makes it easier for future readers!
Scripts can use a custom autodoc function, based on the Sphinx ``include`` Scripts can use a custom autodoc function, based on the Sphinx ``include``
directive and Ruby docstring conventions - any lines between ``=begin`` and directive and Ruby docstring conventions - any lines between ``=begin`` and

@ -312,6 +312,7 @@ All matching init files will be executed in alphebetical order.
Modders often use such scripts to disable tools which should not affect Modders often use such scripts to disable tools which should not affect
an unmodded save. an unmodded save.
.. _other_init_files:
Other init files Other init files
---------------- ----------------

@ -0,0 +1,605 @@
:orphan:
.. _HISTORY:
########################
HISTORY - old changelogs
########################
This file is where old changelogs live, so the current `changelog`
in ``NEWS.rst`` doesn't get too long.
.. contents::
:depth: 2
DFHack 0.40.23-r1
=================
Internals
- plugins will not be loaded if globals they specify as required are not located (should prevent some crashes)
Fixes
-----
- Fixed numerous (mostly Lua-related) crashes on OS X by including a more up-to-date libstdc++
- :kbd:`Alt` should no longer get stuck on Windows (and perhaps other platforms as well)
- `gui/advfort` works again
- `autobutcher`: takes sexualities into account
- devel/export-dt-ini: Updated for 0.40.20+
- `digfort`: now checks file type and existence
- `exportlegends`: Fixed map export
- `full-heal`: Fixed a problem with selecting units in the GUI
- `gui/hack-wish`: Fixed restrictive material filters
- `mousequery`: Changed box-select key to Alt+M
- `dwarfmonitor`: correct date display (month index, separator)
- `putontable`: added to the readme
- `siren` should work again
- stderr.log: removed excessive debug output on OS X
- `trackstop`: No longer prevents cancelling the removal of a track stop or roller.
- Fixed a display issue with ``PRINT_MODE:TEXT``
- Fixed a symbol error (MapExtras::BiomeInfo::MAX_LAYERS) when compiling DFHack in Debug mode
New Plugins
-----------
- `fortplan`: designate construction of (limited) buildings from .csv file, quickfort-style
New Scripts
-----------
- `gui/stockpiles`: an in-game interface for saving and loading stockpile settings files.
- `position`: Reports the current date, time, month, and season, plus some location info. Port/update of position.py
- `hfs-pit`: Digs a hole to hell under the cursor. Replaces needs_porting/hellhole.cpp
Removed
-------
- embark.lua: Obsolete, use `embark-tools`
New tweaks
----------
- `eggs-fertile <tweak>`: Displays an egg fertility indicator on nestboxes
- `max-wheelbarrow <tweak>`: Allows assigning more than 3 wheelbarrows to a stockpile
Misc Improvements
-----------------
- `embark-tools`: Added basic mouse support on the local map
- Made some adventure mode keybindings in :file:`dfhack.init-example` only work in adventure mode
- `gui/companion-order`: added a default keybinding
- further work on needs_porting
DFHack 0.40.19-r1
=================
Fixes
-----
- `modtools/reaction-trigger`: fixed typo
- `modtools/item-trigger`: should now work with item types
New plugins
-----------
- `savestock, loadstock <stocksettings>`: save and load stockpile settings across worlds and saves
New scripts
-----------
- `remove-stress`: set selected or all units unit to -1,000,000 stress (this script replaces removebadthoughts)
Misc improvements
-----------------
- `command-prompt`: can now access selected items, units, and buildings
- `autolabor`: add an optional talent pool parameter
DFHack 0.40.16-r1
=================
Internals
---------
- `EventManager` should handle INTERACTION triggers a little better. It still can get confused about who did what but only rarely.
- `EventManager` should no longer trigger REPORT events for old reports after loading a save.
- lua/persist-table: a convenient way of using persistent tables of arbitrary structure and dimension in Lua
Fixes
-----
- `mousequery`: Disabled when linking levers
- `stocks`: Melting should work now
- `full-heal`: Updated with proper argument handling
- `modtools/reaction-trigger-transition`: should produce the correct syntax now
- `superdwarf`: should work better now
- `forum-dwarves`: update for new df-structures changes
New Scripts
-----------
- `adaptation`: view or set the cavern adaptation level of your citizens
- `add-thought`: allows the user to add thoughts to creatures.
- `gaydar`: detect the sexual orientation of units on the map
- `markdown`: Save a copy of a text screen in markdown (for reddit among others).
- devel/all-bob: renames everyone Bob to help test interaction-trigger
Misc Improvements
-----------------
- `autodump`: Can now mark a stockpile for auto-dumping (similar to `automelt` and `autotrade`)
- `buildingplan`: Can now auto-allocate rooms to dwarves with specific positions (e.g. expedition leader, mayor)
- `dwarfmonitor`: now displays a weather indicator and date
- lua/syndrome-util, `modtools/add-syndrome`: now you can remove syndromes by SYN_CLASS
- No longer write empty :file:`.history` files
DFHack 0.40.15-r1
=================
Fixes
-----
- mousequery: Fixed behavior when selecting a tile on the lowest z-level
Misc Improvements
-----------------
- `EventManager`: deals with frame_counter getting reset properly now.
- `modtools/item-trigger`: fixed equip/unequip bug and corrected minor documentation error
- `teleport`: Updated with proper argument handling and proper unit-at-destination handling.
- `autotrade`: Removed the newly obsolete :guilabel:`Mark all` functionality.
- `search-plugin`: Adapts to the new trade screen column width
- `tweak fast-trade <tweak>`: Switching the fast-trade keybinding to Shift-Up/Shift-Down, due to Select All conflict
DFHack 0.40.14-r1
=================
Internals
---------
- The DFHack console can now be disabled by setting the DFHACK_DISABLE_CONSOLE environment variable: ``DFHACK_DISABLE_CONSOLE=1 ./dfhack``
Fixes
-----
- Stopped duplicate load/unload events when unloading a world
- Stopped ``-e`` from being echoed when DFHack quits on Linux
- `automelt`: now uses a faster method to locate items
- `autotrade`: "Mark all" no longer double-marks bin contents
- `drain-aquifer`: new script replaces the buggy plugin
- `embark-tools`: no longer conflicts with keys on the notes screen
- `fastdwarf`: Fixed problems with combat/attacks
- `forum-dwarves`: should work now
- `manipulator`: now uses a stable sort, allowing sorting by multiple categories
- `rendermax`: updated to work with 0.40
New Plugins
-----------
- `trackstop`: Shows track stop friction and dump direction in its :kbd:`q` menu
New Tweaks
----------
- farm-plot-select: Adds "Select all" and "Deselect all" options to farm plot menus
- import-priority-category: Allows changing the priority of all goods in a category when discussing an import agreement with the liaison
- manager-quantity: Removes the limit of 30 jobs per manager order
- civ-view-agreement: Fixes overlapping text on the "view agreement" screen
- nestbox-color: Fixes the color of built nestboxes
Misc Improvements
-----------------
- `exportlegends`: can now handle site maps
DFHack 0.40.13-r1
=================
Internals
---------
- unified spatter structs
- added ruby df.print_color(color, string) method for dfhack console
Fixes
-----
- no more ``-e`` after terminating
- fixed `superdwarf`
DFHack 0.40.12-r1
=================
Internals
---------
- support for global `onLoad.init` and `onUnload.init` files, called when loading and unloading a world
- Close file after loading a `binary patch <binpatches>`.
New Plugins
-----------
- `hotkeys`: Shows ingame viewscreen with all dfhack keybindings active in current mode.
- `automelt`: allows marking stockpiles so any items placed in them will be designated for melting
Fixes
-----
- possible crash fixed for `gui/hack-wish`
- `search-plugin`: updated to not conflict with BUILDJOB_SUSPEND
- `workflow`: job_material_category -> dfhack_material_category
Misc Improvements
-----------------
- now you can use ``@`` to print things in interactive Lua with subtley different semantics
- optimizations for stockpiles for `autotrade` and `stockflow`
- updated `exportlegends` to work with new maps, dfhack 40.11 r1+
DFHack 0.40.11-r1
=================
Internals
- Plugins on OS X now use ``.plug.dylib` as an extension instead of ``.plug.so``
Fixes
-----
- `3dveins`: should no longer hang/crash on specific maps
- `autotrade`, `search-plugin`: fixed some layout issues
- `deathcause`: updated
- `gui/hack-wish`: should work now
- `reveal`: no longer allocates data for nonexistent map blocks
- Various documentation fixes and updates
DFHack v0.40.10-r1
==================
A few bugfixes.
DFHack v0.40.08-r2
==================
Internals
---------
- supported per save script folders
- Items module: added createItem function
- Sorted CMakeList for plugins and plugins/devel
- `diggingInvaders` no longer builds if plugin building is disabled
- `EventManager`: EQUIPMENT_CHANGE now triggers for new units. New events::
ON_REPORT
UNIT_ATTACK
UNLOAD
INTERACTION
New Scripts
-----------
- lua/repeat-util: makes it easier to make things repeat indefinitely
- lua/syndrome-util: makes it easier to deal with unit syndromes
- `forum-dwarves`: helps copy df viewscreens to a file
- `full-heal`: fully heal a unit
- `remove-wear`: removes wear from all items in the fort
- `repeat`: repeatedly calls a script or a plugin
- ShowUnitSyndromes: shows syndromes affecting units and other relevant info
- `teleport`: teleports units
- `devel/print-args`
- `fix/blood-del`: makes it so civs don't bring barrels full of blood ichor or goo
- `fix/feeding-timers`: reset the feeding timers of all units
- `gui/hack-wish`: creates items out of any material
- `gui/unit-info-viewer`: displays information about units
- `modtools/add-syndrome`: add a syndrome to a unit or remove one
- `modtools/anonymous-script`: execute an lua script defined by a string. Useful for the ``*-trigger`` scripts.
- `modtools/force`: forces events: caravan, migrants, diplomat, megabeast, curiousbeast, mischievousbeast, flier, siege, nightcreature
- `modtools/item-trigger`: triggers commands based on equipping, unequipping, and wounding units with items
- `modtools/interaction-trigger`: triggers commands when interactions happen
- `modtools/invader-item-destroyer`: destroys invaders' items when they die
- `modtools/moddable-gods`: standardized version of Putnam's moddable gods script
- `modtools/projectile-trigger`: standardized version of projectileExpansion
- `modtools/reaction-trigger`: trigger commands when custom reactions complete; replaces autoSyndrome
- `modtools/reaction-trigger-transition`: a tool for converting mods from autoSyndrome to reaction-trigger
- `modtools/random-trigger`: triggers random scripts that you register
- `modtools/skill-change`: for incrementing and setting skills
- `modtools/spawn-flow`: creates flows, like mist or dragonfire
- `modtools/syndrome-trigger`: trigger commands when syndromes happen
- `modtools/transform-unit`: shapeshifts a unit, possibly permanently
Misc improvements
-----------------
- new function in utils.lua for standardized argument processing
Removed
-------
- digmat.rb: digFlood does the same functionality with less FPS impact
- invasionNow: `modtools/force` does it better
- autoSyndrome replaced with `modtools/reaction-trigger`
- syndromeTrigger replaced with `modtools/syndrome-trigger`
- devel/printArgs plugin converted to `devel/print-args`
- outsideOnly plugin replaced by `modtools/outside-only`
DFHack v0.40.08-r1
==================
Was a mistake. Don't use it.
DFHack v0.34.11-r5
==================
Internals
---------
- support for calling a lua function via a protobuf request (demonstrated by dfhack-run --lua).
- support for basic filesystem operations (e.g. chdir, mkdir, rmdir, stat) in C++ and Lua
- Lua API for listing files in directory. Needed for `gui/mod-manager`
- Lua API for creating unit combat reports and writing to gamelog.
- Lua API for running arbitrary DFHack commands
- support for multiple ``raw/init.d/*.lua`` init scripts in one save.
- eventful now has a more friendly way of making custom sidebars
- on Linux and OS X the console now supports moving the cursor back and forward by a whole word.
New scripts
-----------
- `gui/mod-manager`: allows installing/uninstalling mods into df from ``df/mods`` directory.
- `gui/clone-uniform`: duplicates the currently selected uniform in the military screen.
- `fix/build-location`: partial work-around for :bug:`5991` (trying to build wall while standing on it)
- `undump-buildings`: removes dump designation from materials used in buildings.
- `exportlegends`: exports data from legends mode, allowing a set-and-forget export of large worlds.
- log-region: each time a fort is loaded identifying information will be written to the gamelog.
- `dfstatus <gui/dfstatus>`: show an overview of critical stock quantities, including food, drinks, wood, and bars.
- `command-prompt`: a dfhack command prompt in df.
New plugins
-----------
- `rendermax`: replace the renderer with something else, eg ``rendermax light``- a lighting engine
- `automelt`: allows marking stockpiles for automelt (i.e. any items placed in stocpile will be designated for melting)
- `embark-tools`: implementations of Embark Anywhere, Nano Embark, and a few other embark-related utilities
- `building-hacks`: Allows to add custom functionality and/or animations to buildings.
- `petcapRemover`: triggers pregnancies in creatures so that you can effectively raise the default pet population cap
- `plant create <plant>`: spawn a new shrub under the cursor
New tweaks
----------
- craft-age-wear: make crafted items wear out with time like in old versions (:bug:`6003`)
- adamantine-cloth-wear: stop adamantine clothing from wearing out (:bug:`6481`)
- confirm-embark: adds a prompt before embarking (on the "prepare carefully" screen)
Misc improvements
-----------------
- `plant`: move the 'grow', 'extirpate' and 'immolate' commands as 'plant' subcommands
- `digfort`: improved csv parsing, add start() comment handling
- `exterminate`: allow specifying a caste (exterminate gob:male)
- `createitem`: in adventure mode it now defaults to the controlled unit as maker.
- `autotrade`: adds "(Un)mark All" options to both panes of trade screen.
- `mousequery`: several usability improvements; show live overlay (in menu area) of what's on the tile under the mouse cursor.
- `search`: workshop profile search added.
- `dwarfmonitor`: add screen to summarise preferences of fortress dwarfs.
- `getplants`: add autochop function to automate woodcutting.
- `stocks`: added more filtering and display options.
- `siege-engine`:
- engine quality and distance to target now affect accuracy
- firing the siege engine at a target produces a combat report
- improved movement speed computation for meandering units
- operators in Prepare To Fire mode are released from duty once hungry/thirsty if there is a free replacement
DFHack v0.34.11-r4
==================
New commands
------------
- `diggingInvaders` - allows invaders to dig and/or deconstruct walls and buildings in order to get at your dwarves.
- `digFlood` - automatically dig out specified veins as they are revealed
- `enable, disable <enable>` - Built-in commands that can be used to enable/disable many plugins.
- `restrictice` - Restrict traffic on squares above visible ice.
- `restrictliquids` - Restrict traffic on every visible square with liquid.
- treefarm - automatically chop trees and dig obsidian
New Scripts
-----------
- `autobutcher`: A GUI front-end for the autobutcher plugin.
- invasionNow: trigger an invasion, or many
- `locate-ore`: scan the map for unmined ore veins
- `masspit`: designate caged creatures in a zone for pitting
- `multicmd`: run a sequence of dfhack commands, separated by ';'
- `startdwarf`: change the number of dwarves for a new embark
- digmat: dig veins/layers tile by tile, as discovered
Misc improvements
-----------------
- autoSyndrome:
- disable by default
- reorganized special tags
- minimized error spam
- reset policies: if the target already has an instance of the syndrome you can skip,
add another instance, reset the timer, or add the full duration to the time remaining
- core: fix SC_WORLD_(UN)LOADED event for arena mode
- `exterminate`: renamed from slayrace, add help message, add butcher mode
- `fastdwarf`: fixed bug involving fastdwarf and teledwarf being on at the same time
- magmasource: rename to `source`, allow water/magma sources/drains
- Add df.dfhack_run "somecommand" to Ruby
- syndromeTrigger: replaces and extends trueTransformation. Can trigger things when syndromes are added for any reason.
- `tiletypes`: support changing tile material to arbitrary stone.
- `workNow`: can optionally look for jobs when jobs are completed
New tweaks
----------
- hive-crash: Prevent crash if bees die in a hive with ungathered products (:bug:`6368`).
New plugins
-----------
- `3dveins`: Reshapes all veins on the map in a way that flows between Z levels. May be unstable. Backup before using.
- `autotrade`: Automatically send items in marked stockpiles to trade depot, when trading is possible.
- `buildingplan`: Place furniture before it's built
- `dwarfmonitor`: Records dwarf activity to measure fort efficiency
- `mousequery`: Look and poke at the map elements with the mouse.
- outsideOnly: make raw-specified buildings impossible to build inside
- `resume`: A plugin to help display and resume suspended constructions conveniently
- `stocks`: An improved stocks display screen.
Internals
---------
- Core: there is now a per-save dfhack.init file for when the save is loaded, and another for when it is unloaded
- EventManager: fixed job completion detection, fixed removal of TICK events, added EQUIPMENT_CHANGE event
- Lua API for a better `random number generator <lua_api_random>` and perlin noise functions.
- Once: easy way to make sure something happens once per run of DF, such as an error message
DFHack v0.34.11-r3
==================
Internals
---------
- support for displaying active keybindings properly.
- support for reusable widgets in lua screen library.
- Maps::canStepBetween: returns whether you can walk between two tiles in one step.
- EventManager: monitors various in game events centrally so that individual plugins
don't have to monitor the same things redundantly.
- Now works with OS X 10.6.8
Notable bugfixes
----------------
- `autobutcher` can be re-enabled again after being stopped.
- stopped `Dwarf Manipulator <manipulator>` from unmasking vampires.
- `stonesense` is now fixed on OS X
Misc improvements
-----------------
- `fastdwarf`: new mode using debug flags, and some internal consistency fixes.
- added a small stand-alone utility for applying and removing `binary patches <binpatches>`.
- removebadthoughts: add --dry-run option
- `superdwarf`: work in adventure mode too
- `tweak` stable-cursor: carries cursor location from/to Build menu.
- `deathcause`: allow selection from the unitlist screen
- slayrace: allow targetting undeads
- `workflow` plugin:
- properly considers minecarts assigned to routes busy.
- code for deducing job outputs rewritten in lua for flexibility.
- logic fix: collecting webs produces silk, and ungathered webs are not thread.
- items assigned to squads are considered busy, even if not in inventory.
- shearing and milking jobs are supported, but only with generic MILK or YARN outputs.
- workflow announces when the stock level gets very low once a season.
- Auto syndrome plugin: A way of automatically applying boiling rock syndromes and calling dfhack commands controlled by raws.
- `infiniteSky` plugin: Create new z-levels automatically or on request.
- True transformation plugin: A better way of doing permanent transformations that allows later transformations.
- `workNow` plugin: Makes the game assign jobs every time you pause.
New tweaks
----------
- tweak military-training: speed up melee squad training up to 10x (normally 3-5x).
New scripts
-----------
- `binpatch`: the same as the stand-alone binpatch.exe, but works at runtime.
- region-pops: displays animal populations of the region and allows tweaking them.
- `lua`: lua interpreter front-end converted to a script from a native command.
- dfusion: misc scripts with a text based menu.
- embark: lets you embark anywhere.
- `lever`: list and pull fort levers from the dfhack console.
- `stripcaged`: mark items inside cages for dumping, eg caged goblin weapons.
- soundsense-season: writes the correct season to gamelog.txt on world load.
- create-items: spawn items
- fix/cloth-stockpile: fixes :bug:`5739`; needs to be run after savegame load every time.
New GUI scripts
---------------
- `gui/guide-path`: displays the cached path for minecart Guide orders.
- `gui/workshop-job`: displays inputs of a workshop job and allows tweaking them.
- `gui/workflow`: a front-end for the workflow plugin (part inspired by falconne).
- `gui/assign-rack`: works together with a binary patch to fix weapon racks.
- `gui/gm-editor`: an universal editor for lots of dfhack things.
- `gui/companion-order`: a adventure mode command interface for your companions.
- `gui/advfort`: a way to do jobs with your adventurer (e.g. build fort).
New binary patches
------------------
(for use with `binpatch`)
- armorstand-capacity: doubles the capacity of armor stands.
- custom-reagent-size: lets custom reactions use small amounts of inputs.
- deconstruct-heapfall: stops some items still falling on head when deconstructing.
- deconstruct-teleport: stops items from 16x16 block teleporting when deconstructing.
- hospital-overstocking: stops hospital overstocking with supplies.
- training-ammo: lets dwarves with quiver full of combat-only ammo train.
- weaponrack-unassign: fixes bug that negates work done by gui/assign-rack.
New Plugins
-----------
- `fix-armory`: Together with a couple of binary patches and the `gui/assign-rack` script, this plugin makes weapon racks, armor stands, chests and cabinets in properly designated barracks be used again for storage of squad equipment.
- `search`: Adds an incremental search function to the Stocks, Trading, Stockpile and Unit List screens.
- `automaterial`: Makes building constructions (walls, floors, fortifications, etc) a little bit easier by saving you from having to trawl through long lists of materials each time you place one.
- Dfusion: Reworked to make use of lua modules, now all the scripts can be used from other scripts.
- Eventful: A collection of lua events, that will allow new ways to interact with df world.
DFHack v0.34.11-r2
==================
Internals
---------
- full support for Mac OS X.
- a plugin that adds scripting in `ruby <rb>`.
- support for interposing virtual methods in DF from C++ plugins.
- support for creating new interface screens from C++ and lua.
- added various other API functions.
Notable bugfixes
----------------
- better terminal reset after exit on linux.
- `seedwatch` now works on reclaim.
- the sort plugin won't crash on cages anymore.
Misc improvements
-----------------
- `autodump`: can move items to any walkable tile, not just floors.
- `stripcaged`: by default keep armor, new dumparmor option.
- `zone`: allow non-domesticated birds in nestboxes.
- `workflow`: quality range in constraints.
- cleanplants: new command to remove rain water from plants.
- `liquids`: can paint permaflow, i.e. what makes rivers power water wheels.
- `prospect`: pre-embark prospector accounts for caves & magma sea in its estimate.
- `rename`: supports renaming stockpiles, workshops, traps, siege engines.
- `fastdwarf`: now has an additional option to make dwarves teleport to their destination.
- `autolabor`:
- can set nonidle hauler percentage.
- broker excluded from all labors when needed at depot.
- likewise, anybody with a scheduled diplomat meeting.
New commands
------------
- misery: multiplies every negative thought gained (2x by default).
- `digtype`: designates every tile of the same type of vein on the map for 'digging' (any dig designation).
New tweaks
----------
- tweak stable-cursor: keeps exact cursor position between d/k/t/q/v etc menus.
- tweak patrol-duty: makes Train orders reduce patrol timer, like the binary patch does.
- tweak readable-build-plate: fix unreadable truncation in unit pressure plate build ui.
- tweak stable-temp: fixes bug 6012; may improve FPS by 50-100% on a slow item-heavy fort.
- tweak fast-heat: speeds up item heating & cooling, thus making stable-temp act faster.
- tweak fix-dimensions: fixes subtracting small amounts from stacked liquids etc.
- tweak advmode-contained: fixes UI bug in custom reactions with container inputs in advmode.
- tweak fast-trade: Shift-Enter for selecting items quckly in Trade and Move to Depot screens.
- tweak military-stable-assign: Stop rightmost list of military->Positions from jumping to top.
- tweak military-color-assigned: In same list, color already assigned units in brown & green.
New scripts
-----------
- `fixnaked`: removes thoughts about nakedness.
- `setfps`: set FPS cap at runtime, in case you want slow motion or speed-up.
- `siren`: wakes up units, stops breaks and parties - but causes bad thoughts.
- `fix/population-cap`: run after every migrant wave to prevent exceeding the cap.
- `fix/stable-temp`: counts items with temperature updates; does instant one-shot stable-temp.
- `fix/loyaltycascade`: fix units allegiance, eg after ordering a dwarf merchant kill.
- `deathcause`: shows the circumstances of death for a given body.
- `digfort`: designate areas to dig from a csv file.
- `drain-aquifer`: remove aquifers from the map.
- `growcrops`: cheat to make farm crops instantly grow.
- magmasource: continuously spawn magma from any map tile.
- removebadthoughts: delete all negative thoughts from your dwarves.
- slayrace: instakill all units of a given race, optionally with magma.
- `superdwarf`: per-creature `fastdwarf`.
- `gui/mechanisms`: browse mechanism links of the current building.
- `gui/room-list`: browse other rooms owned by the unit when assigning one.
- `gui/liquids`: a GUI front-end for the liquids plugin.
- `gui/rename`: renaming stockpiles, workshops and units via an in-game dialog.
- `gui/power-meter`: front-end for the Power Meter plugin.
- `gui/siege-engine`: front-end for the Siege Engine plugin.
- `gui/choose-weapons`: auto-choose matching weapons in the military equip screen.
New Plugins
-----------
- `manipulator`: a Dwarf Therapist like UI in the game (:kbd:`u`:kbd:`l`)
- `steam-engine`: an alternative to Water Reactors which make more sense.
See ``hack/raw/*_steam_engine.txt`` for the necessary raw definitions.
- `power-meter`: a pressure plate modification to detect powered gear
boxes on adjacent tiles. `gui/power-meter` implements
the build configuration UI.
- `siege-engine`: massive overhaul for siege engines, configured via `gui/siege-engine`
- `add-spatter`: allows poison coatings via raw reactions, among other things.

@ -1,11 +1,13 @@
.. _lua-api:
############## ##############
DFHack Lua API DFHack Lua API
############## ##############
.. contents:: DFHack has extensive support for
the Lua_ scripting language, providing access to:
The current version of DFHack has extensive support for .. _Lua: http://www.lua.org
the Lua scripting language, providing access to:
1. Raw data structures used by the game. 1. Raw data structures used by the game.
2. Many C++ functions for high-level access to these 2. Many C++ functions for high-level access to these
@ -14,26 +16,36 @@ the Lua scripting language, providing access to:
Lua code can be used both for writing scripts, which Lua code can be used both for writing scripts, which
are treated by DFHack command line prompt almost as are treated by DFHack command line prompt almost as
native C++ commands, and invoked by plugins written in c++. native C++ commands, and invoked by plugins written in C++.
This document describes native API available to Lua in detail. This document describes native API available to Lua in detail.
It does not describe all of the utility functions It does not describe all of the utility functions
implemented by Lua files located in hack/lua/... implemented by Lua files located in :file:`hack/lua/*`
(:file:`library/lua/*` in the git repo).
.. contents::
:depth: 3
========================= =========================
DF data structure wrapper DF data structure wrapper
========================= =========================
Data structures of the game are defined in XML files located in library/xml .. contents::
(and online at http://github.com/DFHack/df-structures), and automatically exported :local:
Data structures of the game are defined in XML files located in :file:`library/xml`
(and `online <http://github.com/DFHack/df-structures>`_, and automatically exported
to lua code as a tree of objects and functions under the ``df`` global, which to lua code as a tree of objects and functions under the ``df`` global, which
also broadly maps to the ``df`` namespace in the headers generated for C++. also broadly maps to the ``df`` namespace in the headers generated for C++.
**WARNING**: The wrapper provides almost raw access to the memory .. warning::
The wrapper provides almost raw access to the memory
of the game, so mistakes in manipulating objects are as likely to of the game, so mistakes in manipulating objects are as likely to
crash the game as equivalent plain C++ code would be. E.g. NULL crash the game as equivalent plain C++ code would be.
pointer access is safely detected, but dangling pointers aren't.
eg. NULL pointer access is safely detected, but dangling pointers aren't.
Objects managed by the wrapper can be broadly classified into the following groups: Objects managed by the wrapper can be broadly classified into the following groups:
@ -86,7 +98,8 @@ All typed objects have the following built-in features:
and values. Fields are enumerated in memory order. Methods and and values. Fields are enumerated in memory order. Methods and
lua wrapper properties are not included in the iteration. lua wrapper properties are not included in the iteration.
**WARNING**: a few of the data structures (like ui_look_list) .. warning::
a few of the data structures (like ui_look_list)
contain unions with pointers to different types with vtables. contain unions with pointers to different types with vtables.
Using pairs on such structs is an almost sure way to crash with Using pairs on such structs is an almost sure way to crash with
an access violation. an access violation.
@ -115,7 +128,8 @@ All typed objects have the following built-in features:
Destroys the object with the C++ ``delete`` operator. Destroys the object with the C++ ``delete`` operator.
If destructor is not available, returns *false*. If destructor is not available, returns *false*.
**WARNING**: the lua reference object remains as a dangling .. warning::
the lua reference object remains as a dangling
pointer, like a raw C++ pointer would. pointer, like a raw C++ pointer would.
* ``ref:assign(object)`` * ``ref:assign(object)``
@ -158,13 +172,15 @@ They implement the following features:
Primitive typed fields, i.e. numbers & strings, are converted Primitive typed fields, i.e. numbers & strings, are converted
to/from matching lua values. The value of a pointer is a reference to/from matching lua values. The value of a pointer is a reference
to the target, or nil/NULL. Complex types are represented by to the target, or ``nil``/NULL. Complex types are represented by
a reference to the field within the structure; unless recursive a reference to the field within the structure; unless recursive
lua table assignment is used, such fields can only be read. lua table assignment is used, such fields can only be read.
**NOTE:** In case of inheritance, *superclass* fields have precedence .. note::
In case of inheritance, *superclass* fields have precedence
over the subclass, but fields shadowed in this way can still over the subclass, but fields shadowed in this way can still
be accessed as ``ref['subclasstype.field']``. be accessed as ``ref['subclasstype.field']``.
This shadowing order is necessary because vtable-based classes This shadowing order is necessary because vtable-based classes
are automatically exposed in their exact type, and the reverse are automatically exposed in their exact type, and the reverse
rule would make access to superclass fields unreliable. rule would make access to superclass fields unreliable.
@ -183,7 +199,7 @@ They implement the following features:
* ``pairs(ref)`` * ``pairs(ref)``
Enumerates all real fields (but not methods) in memory Enumerates all real fields (but not methods) in memory
(= declaration) order. order, which is the same as declaration order.
Container references Container references
-------------------- --------------------
@ -278,7 +294,7 @@ All types and the global object have the following features:
* ``type._identity`` * ``type._identity``
Contains a lightuserdata pointing to the underlying Contains a lightuserdata pointing to the underlying
DFHack::type_instance object. ``DFHack::type_instance`` object.
Types excluding the global object also support: Types excluding the global object also support:
@ -294,8 +310,8 @@ Types excluding the global object also support:
Returns true if object is same or subclass type, or a reference Returns true if object is same or subclass type, or a reference
to an object of same or subclass type. It is permissible to pass to an object of same or subclass type. It is permissible to pass
nil, NULL or non-wrapper value as object; in this case the ``nil``, NULL or non-wrapper value as object; in this case the
method returns nil. method returns ``nil``.
In addition to this, enum and bitfield types contain a In addition to this, enum and bitfield types contain a
bi-directional mapping between key strings and values, and bi-directional mapping between key strings and values, and
@ -362,6 +378,7 @@ The ``df`` table itself contains the following functions and values:
Returns *nil* if NULL, or a ref. Returns *nil* if NULL, or a ref.
.. _lua-api-table-assignment:
Recursive table assignment Recursive table assignment
========================== ==========================
@ -437,7 +454,7 @@ on the type of the field being assigned to:
{ resize=false, [idx]=value } { resize=false, [idx]=value }
Since nil inside a table is indistinguishable from missing key, Since ``nil`` inside a table is indistinguishable from missing key,
it is necessary to use ``df.NULL`` as a null pointer value. it is necessary to use ``df.NULL`` as a null pointer value.
This system is intended as a way to define a nested object This system is intended as a way to define a nested object
@ -452,6 +469,9 @@ cleanup.
DFHack API DFHack API
========== ==========
.. contents::
:local:
DFHack utility functions are placed in the ``dfhack`` global tree. DFHack utility functions are placed in the ``dfhack`` global tree.
Native utilities Native utilities
@ -722,6 +742,8 @@ Functions:
Checks if the material matches job_material_category or job_item. Checks if the material matches job_material_category or job_item.
Accept dfhack_material_category auto-assign table. Accept dfhack_material_category auto-assign table.
.. _lua_api_random:
Random number generation Random number generation
------------------------ ------------------------
@ -798,7 +820,8 @@ can be omitted.
Return information about the DFHack build in use. Return information about the DFHack build in use.
**Note:** ``getCompiledDFVersion()`` returns the DF version specified at compile time, .. note::
``getCompiledDFVersion()`` returns the DF version specified at compile time,
while ``getDFVersion()`` returns the version and typically the OS as well. while ``getDFVersion()`` returns the version and typically the OS as well.
These do not necessarily match - for example, DFHack 0.34.11-r5 worked with These do not necessarily match - for example, DFHack 0.34.11-r5 worked with
DF 0.34.10 and 0.34.11, so the former function would always return ``0.34.11`` DF 0.34.10 and 0.34.11, so the former function would always return ``0.34.11``
@ -875,7 +898,7 @@ Gui module
* ``dfhack.gui.getSelectedWorkshopJob([silent])`` * ``dfhack.gui.getSelectedWorkshopJob([silent])``
When a job is selected in *'q'* mode, returns the job, else When a job is selected in :kbd:`q` mode, returns the job, else
prints error unless silent and returns *nil*. prints error unless silent and returns *nil*.
* ``dfhack.gui.getSelectedJob([silent])`` * ``dfhack.gui.getSelectedJob([silent])``
@ -884,31 +907,31 @@ Gui module
* ``dfhack.gui.getSelectedUnit([silent])`` * ``dfhack.gui.getSelectedUnit([silent])``
Returns the unit selected via *'v'*, *'k'*, unit/jobs, or Returns the unit selected via :kbd:`v`, :kbd:`k`, unit/jobs, or
a full-screen item view of a cage or suchlike. a full-screen item view of a cage or suchlike.
* ``dfhack.gui.getSelectedItem([silent])`` * ``dfhack.gui.getSelectedItem([silent])``
Returns the item selected via *'v'* ->inventory, *'k'*, *'t'*, or Returns the item selected via :kbd:`v` ->inventory, :kbd:`k`, :kbd:`t`, or
a full-screen item view of a container. Note that in the a full-screen item view of a container. Note that in the
last case, the highlighted *contained item* is returned, not last case, the highlighted *contained item* is returned, not
the container itself. the container itself.
* ``dfhack.gui.getSelectedBuilding([silent])`` * ``dfhack.gui.getSelectedBuilding([silent])``
Returns the building selected via *'q'*, *'t'*, *'k'* or *'i'*. Returns the building selected via :kbd:`q`, :kbd:`t`, :kbd:`k` or :kbd:`i`.
* ``dfhack.gui.writeToGamelog(text)`` * ``dfhack.gui.writeToGamelog(text)``
Writes a string to gamelog.txt without doing an announcement. Writes a string to :file:`gamelog.txt` without doing an announcement.
* ``dfhack.gui.makeAnnouncement(type,flags,pos,text,color[,is_bright])`` * ``dfhack.gui.makeAnnouncement(type,flags,pos,text,color[,is_bright])``
Adds an announcement with given announcement_type, text, color, and brightness. Adds an announcement with given announcement_type, text, color, and brightness.
The is_bright boolean actually seems to invert the brightness. The is_bright boolean actually seems to invert the brightness.
The announcement is written to gamelog.txt. The announcement_flags The announcement is written to :file:`gamelog.txt`. The announcement_flags
argument provides a custom set of announcements.txt options, argument provides a custom set of :file:`announcements.txt` options,
which specify if the message should actually be displayed in the which specify if the message should actually be displayed in the
announcement list, and whether to recenter or show a popup. announcement list, and whether to recenter or show a popup.
@ -1003,7 +1026,7 @@ Job module
* ``dfhack.job.linkIntoWorld(job,new_id)`` * ``dfhack.job.linkIntoWorld(job,new_id)``
Adds job into ``df.global.job_list``, and if new_id Adds job into ``df.global.job_list``, and if new_id
is true, then also sets it's id and increases is true, then also sets its id and increases
``df.global.job_next_id`` ``df.global.job_next_id``
* ``dfhack.job.listNewlyCreated(first_id)`` * ``dfhack.job.listNewlyCreated(first_id)``
@ -1161,7 +1184,7 @@ Items module
* ``dfhack.items.getDescription(item, type[, decorate])`` * ``dfhack.items.getDescription(item, type[, decorate])``
Returns the string description of the item, as produced by the getItemDescription Returns the string description of the item, as produced by the ``getItemDescription``
method. If decorate is true, also adds markings for quality and improvements. method. If decorate is true, also adds markings for quality and improvements.
* ``dfhack.items.getGeneralRef(item, type)`` * ``dfhack.items.getGeneralRef(item, type)``
@ -1205,10 +1228,15 @@ Items module
Move the item to the container. Returns *false* if impossible. Move the item to the container. Returns *false* if impossible.
* ``dfhack.items.moveToBuilding(item,building,use_mode)`` * ``dfhack.items.moveToBuilding(item,building[,use_mode[,force_in_building])``
Move the item to the building. Returns *false* if impossible. Move the item to the building. Returns *false* if impossible.
``use_mode`` defaults to 0. If set to 2, the item will be treated as part of the building.
If ``force_in_building`` is true, the item will be considered to be stored by the building
(used for items temporarily used in traps in vanilla DF)
* ``dfhack.items.moveToInventory(item,unit,use_mode,body_part)`` * ``dfhack.items.moveToInventory(item,unit,use_mode,body_part)``
Move the item to the unit inventory. Returns *false* if impossible. Move the item to the unit inventory. Returns *false* if impossible.
@ -1305,10 +1333,12 @@ Maps module
* ``dfhack.maps.canWalkBetween(pos1, pos2)`` * ``dfhack.maps.canWalkBetween(pos1, pos2)``
Checks if a dwarf may be able to walk between the two tiles, Checks if a dwarf may be able to walk between the two tiles,
using a pathfinding cache maintained by the game. Note that using a pathfinding cache maintained by the game.
this cache is only updated when the game is unpaused, and thus
.. note::
This cache is only updated when the game is unpaused, and thus
can get out of date if doors are forbidden or unforbidden, or can get out of date if doors are forbidden or unforbidden, or
tools like liquids or tiletypes are used. It also cannot possibly tools like `liquids` or `tiletypes` are used. It also cannot possibly
take into account anything that depends on the actual units, like take into account anything that depends on the actual units, like
burrows, or the presence of invaders. burrows, or the presence of invaders.
@ -1376,6 +1406,9 @@ Burrows module
Buildings module Buildings module
---------------- ----------------
General
~~~~~~~
* ``dfhack.buildings.getGeneralRef(building, type)`` * ``dfhack.buildings.getGeneralRef(building, type)``
Searches for a general_ref with the given type. Searches for a general_ref with the given type.
@ -1434,7 +1467,9 @@ Buildings module
Returns a list of items stored on the given stockpile. Returns a list of items stored on the given stockpile.
Ignores empty bins, barrels, and wheelbarrows assigned as storage and transport for that stockpile. Ignores empty bins, barrels, and wheelbarrows assigned as storage and transport for that stockpile.
Low-level building creation functions; Low-level
~~~~~~~~~
Low-level building creation functions:
* ``dfhack.buildings.allocInstance(pos, type, subtype, custom)`` * ``dfhack.buildings.allocInstance(pos, type, subtype, custom)``
@ -1477,6 +1512,8 @@ Low-level building creation functions;
Destroys the building, or queues a deconstruction job. Destroys the building, or queues a deconstruction job.
Returns *true* if the building was destroyed and deallocated immediately. Returns *true* if the building was destroyed and deallocated immediately.
High-level
~~~~~~~~~~
More high-level functions are implemented in lua and can be loaded by More high-level functions are implemented in lua and can be loaded by
``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``. ``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``.
@ -1503,7 +1540,8 @@ Among them are:
Creates a building in one call, using options contained Creates a building in one call, using options contained
in the argument table. Returns the building, or *nil, error*. in the argument table. Returns the building, or *nil, error*.
**NOTE:** Despite the name, unless the building is abstract, .. note::
Despite the name, unless the building is abstract,
the function creates it in an 'unconstructed' stage, with the function creates it in an 'unconstructed' stage, with
a queued in-game job that will actually construct it. I.e. a queued in-game job that will actually construct it. I.e.
the function replicates programmatically what can be done the function replicates programmatically what can be done
@ -1707,7 +1745,8 @@ In order to actually be able to paint to the screen, it is necessary
to create and register a viewscreen (basically a modal dialog) with to create and register a viewscreen (basically a modal dialog) with
the game. the game.
**NOTE**: As a matter of policy, in order to avoid user confusion, all .. warning::
As a matter of policy, in order to avoid user confusion, all
interface screens added by dfhack should bear the "DFHack" signature. interface screens added by dfhack should bear the "DFHack" signature.
Screens are managed with the following functions: Screens are managed with the following functions:
@ -1730,7 +1769,7 @@ Apart from a native viewscreen object, these functions accept a table
as a screen. In this case, ``show`` creates a new native viewscreen as a screen. In this case, ``show`` creates a new native viewscreen
that delegates all processing to methods stored in that table. that delegates all processing to methods stored in that table.
**NOTE**: Lua-implemented screens are only supported in the core context. .. note:: Lua-implemented screens are only supported in the core context.
Supported callbacks and fields are: Supported callbacks and fields are:
@ -2017,8 +2056,9 @@ and are only documented here for completeness:
Searches script paths for the script ``name`` and returns the path of the first Searches script paths for the script ``name`` and returns the path of the first
file found, or ``nil`` on failure. file found, or ``nil`` on failure.
Note: This requires an extension to be specified (``.lua`` or ``.rb``) - .. note::
use ``dfhack.findScript()`` to include the ``.lua`` extension automatically. This requires an extension to be specified (``.lua`` or ``.rb``) - use
``dfhack.findScript()`` to include the ``.lua`` extension automatically.
Core interpreter context Core interpreter context
======================== ========================
@ -2078,7 +2118,8 @@ Features:
Sets the function as one of the listeners. Assign *nil* to remove it. Sets the function as one of the listeners. Assign *nil* to remove it.
**NOTE**: The ``df.NULL`` key is reserved for the use by .. note::
The ``df.NULL`` key is reserved for the use by
the C++ owner of the event; it is an error to try setting it. the C++ owner of the event; it is an error to try setting it.
* ``#event`` * ``#event``
@ -2099,8 +2140,11 @@ Features:
Lua Modules Lua Modules
=========== ===========
.. contents::
:local:
DFHack sets up the lua interpreter so that the built-in ``require`` DFHack sets up the lua interpreter so that the built-in ``require``
function can be used to load shared lua code from hack/lua/. function can be used to load shared lua code from :file:`hack/lua/`.
The ``dfhack`` namespace reference itself may be obtained via The ``dfhack`` namespace reference itself may be obtained via
``require('dfhack')``, although it is initially created as a ``require('dfhack')``, although it is initially created as a
global by C++ bootstrap code. global by C++ bootstrap code.
@ -2138,7 +2182,7 @@ environment by the mandatory init file dfhack.lua:
* Color constants * Color constants
These are applicable both for ``dfhack.color()`` and color fields These are applicable both for ``dfhack.color()`` and color fields
in DF functions or structures: in DF functions or structures::
COLOR_RESET, COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RESET, COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN,
COLOR_RED, COLOR_MAGENTA, COLOR_BROWN, COLOR_GREY, COLOR_DARKGREY, COLOR_RED, COLOR_MAGENTA, COLOR_BROWN, COLOR_GREY, COLOR_DARKGREY,
@ -2158,8 +2202,10 @@ environment by the mandatory init file dfhack.lua:
* Miscellaneous constants * Miscellaneous constants
:NEWLINE, COMMA, PERIOD: evaluate to the relevant character strings. ``NEWLINE``, ``COMMA``, ``PERIOD``
:DEFAULT_NIL: is an unspecified unique token used by the class module below. evaluate to the relevant character strings.
``DEFAULT_NIL``
is an unspecified unique token used by the class module below.
* ``printall(obj)`` * ``printall(obj)``
@ -2266,7 +2312,7 @@ utils
Performs a shallow, or semi-deep copy of the object as a lua table tree. Performs a shallow, or semi-deep copy of the object as a lua table tree.
The deep mode recurses into lua tables and subobjects, except pointers The deep mode recurses into lua tables and subobjects, except pointers
to other heap objects. to other heap objects.
Null pointers are represented as df.NULL. Zero-based native containers Null pointers are represented as ``df.NULL``. Zero-based native containers
are converted to 1-based lua sequences. are converted to 1-based lua sequences.
* ``utils.clone_with_default(obj, default, force)`` * ``utils.clone_with_default(obj, default, force)``
@ -2323,7 +2369,7 @@ utils
utils.insert_or_update(soul.skills, {new=true, id=..., rating=...}, 'id') utils.insert_or_update(soul.skills, {new=true, id=..., rating=...}, 'id')
(For an explanation of ``new=true``, see table assignment in the wrapper section) (For an explanation of ``new=true``, see `lua-api-table-assignment`)
* ``utils.erase_sorted_key(vector,key,field,cmpfun)`` * ``utils.erase_sorted_key(vector,key,field,cmpfun)``
@ -2485,6 +2531,9 @@ To avoid confusion, these methods cannot be redefined.
In-game UI Library In-game UI Library
================== ==================
.. contents::
:local:
A number of lua modules with names starting with ``gui`` are dedicated A number of lua modules with names starting with ``gui`` are dedicated
to wrapping the natives of the ``dfhack.screen`` module in a way that to wrapping the natives of the ``dfhack.screen`` module in a way that
is easy to use. This allows relatively easily and naturally creating is easy to use. This allows relatively easily and naturally creating
@ -3214,6 +3263,9 @@ The widget implements:
Plugins Plugins
======= =======
.. contents::
:local:
DFHack plugins may export native functions and events DFHack plugins may export native functions and events
to lua contexts. They are automatically imported by to lua contexts. They are automatically imported by
``mkmodule('plugins.<name>')``; this means that a lua ``mkmodule('plugins.<name>')``; this means that a lua
@ -3444,24 +3496,45 @@ Functions
--------- ---------
``registerBuilding(table)`` where table must contain name, as a workshop raw name, the rest are optional: ``registerBuilding(table)`` where table must contain name, as a workshop raw name, the rest are optional:
1. name -- custom workshop id e.g. ``SOAPMAKER``
2. fix_impassible -- if true make impassible tiles impassible to liquids too :name:
3. consume -- how much machine power is needed to work. Disables reactions if not supplied enough and needs_power=1 custom workshop id e.g. ``SOAPMAKER``
4. produce -- how much machine power is produced.
5. needs_power -- if produced in network < consumed stop working, default true .. note:: this is the only mandatory field.
6. gears -- a table or ``{x=?,y=?}`` of connection points for machines.
7. action -- a table of number (how much ticks to skip) and a function which gets called on shop update :fix_impassible:
8. animate -- a table of frames which can be a table of: if true make impassible tiles impassible to liquids too
:consume:
how much machine power is needed to work.
Disables reactions if not supplied enough and ``needs_power==1``
:produce:
how much machine power is produced.
:needs_power:
if produced in network < consumed stop working, default true
:gears:
a table or ``{x=?,y=?}`` of connection points for machines.
:action:
a table of number (how much ticks to skip) and a function which
gets called on shop update
:animate:
a table of frames which can be a table of:
a. tables of 4 numbers ``{tile,fore,back,bright}`` OR a. tables of 4 numbers ``{tile,fore,back,bright}`` OR
b. empty table (tile not modified) OR b. empty table (tile not modified) OR
c. ``{x=<number> y=<number> + 4 numbers like in first case}``, this generates full frame useful for animations that change little (1-2 tiles) c. ``{x=<number> y=<number> + 4 numbers like in first case}``,
9. canBeRoomSubset -- a flag if this building can be counted in room. 1 means it can, 0 means it can't and -1 default building behaviour this generates full frame useful for animations that change little (1-2 tiles)
10. auto_gears -- a flag that automatically fills up gears and animate. It looks over building definition for gear icons and maps them.
:canBeRoomSubset:
a flag if this building can be counted in room. 1 means it can, 0 means it can't and -1 default building behaviour
:auto_gears:
a flag that automatically fills up gears and animate. It looks over building definition for gear icons and maps them.
Animate table also might contain: Animate table also might contain:
1. frameLenght -- how many ticks does one frame take OR
2. isMechanical -- a bool that says to try to match to mechanical system (i.e. how gears are turning) :frameLength:
how many ticks does one frame take OR
:isMechanical:
a bool that says to try to match to mechanical system (i.e. how gears are turning)
``getPower(building)`` returns two number - produced and consumed power if building can be modified and returns nothing otherwise ``getPower(building)`` returns two number - produced and consumed power if building can be modified and returns nothing otherwise
@ -3476,7 +3549,7 @@ Simple mechanical workshop::
consume=15, consume=15,
gears={x=0,y=0}, --connection point gears={x=0,y=0}, --connection point
animate={ animate={
isMechanical=true, --animate the same connection point as vanilla gear isMechanical=true, --animate the same conn. point as vanilla gear
frames={ frames={
{{x=0,y=0,42,7,0,0}}, --first frame, 1 changed tile {{x=0,y=0,42,7,0,0}}, --first frame, 1 changed tile
{{x=0,y=0,15,7,0,0}} -- second frame, same {{x=0,y=0,15,7,0,0}} -- second frame, same
@ -3520,15 +3593,12 @@ from ``server:accept()``. It's a subclass of ``socket``.
* ``client:receive(pattern)`` * ``client:receive(pattern)``
Receives data. If ``pattern`` is a number, it receives that much data. Other supported patterns: Receives data. Pattern is one of:
* ``*a``
Read all available data. :``*l``: read one line (default, if pattern is *nil*)
:<number>: read specified number of bytes
:``*a``: read all available data
* ``*l``
Read one line. This is the default mode (if pattern is nil).
* ``client:send(data)`` * ``client:send(data)``
Sends data. Data is a string. Sends data. Data is a string.
@ -3537,11 +3607,13 @@ from ``server:accept()``. It's a subclass of ``socket``.
Server class Server class
------------ ------------
Server is a socket that is waiting for clients. You can get this object from ``tcp:bind(address,port)``. Server is a socket that is waiting for clients.
You can get this object from ``tcp:bind(address,port)``.
* ``server:accept()`` * ``server:accept()``
Accepts an incoming connection if it exists. Returns a ``client`` object representing that socket. Accepts an incoming connection if it exists.
Returns a ``client`` object representing that socket.
Tcp class Tcp class
--------- ---------
@ -3561,16 +3633,22 @@ A class with all the tcp functionality.
Scripts Scripts
======= =======
Any files with the .lua extension placed into hack/scripts/* .. contents::
:local:
Any files with the .lua extension placed into :file:`hack/scripts/*`
are automatically used by the DFHack core as commands. The are automatically used by the DFHack core as commands. The
matching command name consists of the name of the file without matching command name consists of the name of the file without
the extension. First DFHack searches for the script in the save folder/raw/scripts folder. If it is not found there, it searches in the DF/raw/scripts folder. If it is not there, it searches in DF/hack/scripts. If it is not there, it gives up. the extension. First DFHack searches for the script in the :file:`<save_folder>/raw/scripts/` folder. If it is not found there, it searches in the :file:`<DF>/raw/scripts/` folder. If it is not there, it searches in
:file:`<DF>/hack/scripts/`. If it is not there, it gives up.
If the first line of the script is a one-line comment, it is If the first line of the script is a one-line comment, it is
used by the built-in ``ls`` and ``help`` commands. used by the built-in ``ls`` and ``help`` commands.
Such a comment is required for every script in the official DFHack repository.
**NOTE:** Scripts placed in subdirectories still can be accessed, but .. note::
do not clutter the ``ls`` command list; thus it is preferred Scripts placed in subdirectories still can be accessed, but
do not clutter the `ls` command list (unless ``ls -a``; thus it is preferred
for obscure developer-oriented scripts and scripts used by tools. for obscure developer-oriented scripts and scripts used by tools.
When calling such scripts, always use '/' as the separator for When calling such scripts, always use '/' as the separator for
directories, e.g. ``devel/lua-example``. directories, e.g. ``devel/lua-example``.
@ -3600,12 +3678,15 @@ Note that this function lets errors propagate to the caller.
Run an Lua script and return its environment. Run an Lua script and return its environment.
This command allows you to use scripts like modules for increased portability. This command allows you to use scripts like modules for increased portability.
It is highly recommended that if you are a modder you put your custom modules in ``raw/scripts`` and use ``script_environment`` instead of ``require`` so that saves with your mod installed will be self-contained and can be transferred to people who do have DFHack but do not have your mod installed. It is highly recommended that if you are a modder you put your custom modules in ``raw/scripts`` and use ``script_environment`` instead of ``require`` so that saves with your mod installed will be self-contained and can be transferred to people who do have DFHack but do not have your mod installed.
You can say ``dfhack.script_environment('add-thought').addEmotionToUnit([arguments go here])`` and it will have the desired effect. You can say ``dfhack.script_environment('add-thought').addEmotionToUnit([arguments go here])`` and it will have the desired effect.
It will call the script in question with the global ``moduleMode`` set to ``true`` so that the script can return early. It will call the script in question with the global ``moduleMode`` set to ``true`` so that the script can return early.
This is useful because if the script is called from the console it should deal with its console arguments and if it is called by ``script_environment`` it should only create its global functions and return. This is useful because if the script is called from the console it should deal with its console arguments and if it is called by ``script_environment`` it should only create its global functions and return.
You can also access global variables with, for example ``print(dfhack.script_environment('add-thought').validArgs)`` You can also access global variables with, for example ``print(dfhack.script_environment('add-thought').validArgs)``
The function ``script_environment`` is fast enough that it is recommended that you not store its result in a nonlocal variable, because your script might need to load a different version of that script if the save is unloaded and a save with a different mod that overrides the same script with a slightly different functionality is loaded. The function ``script_environment`` is fast enough that it is recommended that you not store its result in a nonlocal variable, because your script might need to load a different version of that script if the save is unloaded and a save with a different mod that overrides the same script with a slightly different functionality is loaded.
This will not be an issue in most cases. This will not be an issue in most cases.
This function also permits circular dependencies of scripts. This function also permits circular dependencies of scripts.
* ``dfhack.reqscript(name)`` or ``reqscript(name)`` * ``dfhack.reqscript(name)`` or ``reqscript(name)``

@ -10,32 +10,25 @@ Most commands offered by plugins are listed here,
hopefully organised in a way you will find useful. hopefully organised in a way you will find useful.
.. contents:: .. contents::
:depth: 3 :depth: 2
=============================== ===============================
Data inspection and visualizers Data inspection and visualizers
=============================== ===============================
.. _stonesense: .. contents::
:local:
.. _plugin-stonesense:
stonesense stonesense
========== ==========
An isometric visualizer that runs in a second window. This requires working An isometric visualizer that runs in a second window. Usage:
graphics acceleration and at least a dual core CPU (otherwise it will slow
down DF). Usage:
:stonesense: Open the visualiser in a new window. Alias ``ssense``. :stonesense: Open the visualiser in a new window. Alias ``ssense``.
:ssense overlay: Overlay DF window, replacing the map area. :ssense overlay: Overlay DF window, replacing the map area.
``PRINT_MODE:2D`` strongly recommended for stability.
Stonesense can be configured by editing the :file:`stonesense/init.txt`
and :file:`stonesense/keybinds.txt` files. Additional content, such as sprites
for modded creatures, is available from the content repository on the wiki.
For detailed information, see the `stonesense readme`_, the :wiki:`wiki page For more information, see `the full Stonesense README <stonesense>`.
<Utility:Stonesense>`, or the :forums:`Bay12 forums thread <106497>`.
.. _`stonesense readme`: https://github.com/DFHack/stonesense/blob/master/README.md
.. _blueprint: .. _blueprint:
@ -164,7 +157,7 @@ Usage and related commands:
:reveal: Reveal the whole map, except for HFS to avoid demons spawning :reveal: Reveal the whole map, except for HFS to avoid demons spawning
:reveal hell: Also show hell, but requires ``unreveal`` before unpausing :reveal hell: Also show hell, but requires ``unreveal`` before unpausing
:reveal demons: Reveals everything and allows unpausing - good luck! :reveal demon: Reveals everything and allows unpausing - good luck!
:unreveal: Reverts the effects of ``reveal`` :unreveal: Reverts the effects of ``reveal``
:revtoggle: Switches between ``reveal`` and ``unreveal`` :revtoggle: Switches between ``reveal`` and ``unreveal``
:revflood: Hide everything, then reveal tiles with a path to the cursor :revflood: Hide everything, then reveal tiles with a path to the cursor
@ -173,6 +166,8 @@ Usage and related commands:
Only useful where (eg) you abandoned with the fort revealed Only useful where (eg) you abandoned with the fort revealed
and no longer want the data. and no longer want the data.
.. _showmood:
showmood showmood
======== ========
Shows all items needed for the currently active strange mood. Shows all items needed for the currently active strange mood.
@ -182,6 +177,9 @@ Shows all items needed for the currently active strange mood.
Bugfixes Bugfixes
======== ========
.. contents::
:local:
fixdiplomats fixdiplomats
============ ============
Adds a Diplomat position to all Elven civilizations, allowing them to negotiate Adds a Diplomat position to all Elven civilizations, allowing them to negotiate
@ -217,6 +215,8 @@ Removes invalid references to mineral inclusions and restores missing ones.
Use this if you broke your embark with tools like `tiletypes`, or if you Use this if you broke your embark with tools like `tiletypes`, or if you
accidentally placed a construction on top of a valuable mineral floor. accidentally placed a construction on top of a valuable mineral floor.
.. _petcapRemover:
petcapRemover petcapRemover
============= =============
Allows you to remove or raise the pet population cap. In vanilla Allows you to remove or raise the pet population cap. In vanilla
@ -275,7 +275,7 @@ One-shot subcommands:
Subcommands that persist until disabled or DF quits: Subcommands that persist until disabled or DF quits:
:adamantine-cloth-wear: Prevents adamantine clothing from wearing out while being worn (bug 6481). :adamantine-cloth-wear: Prevents adamantine clothing from wearing out while being worn (:bug:`6481`).
:advmode-contained: Works around :bug:`6202`, custom reactions with container inputs :advmode-contained: Works around :bug:`6202`, custom reactions with container inputs
in advmode. The issue is that the screen tries to force you to select in advmode. The issue is that the screen tries to force you to select
the contents separately from the container. This forcefully skips child the contents separately from the container. This forcefully skips child
@ -333,13 +333,15 @@ UI Upgrades
=========== ===========
.. note:: .. note::
In order to avoid user confusion, as a matter of policy all GUI tools In order to avoid user confusion, as a matter of policy all GUI tools
display the word :guilabel:`DFHack` on the screen somewhere while active. display the word :guilabel:`DFHack` on the screen somewhere while active.
When that is not appropriate because they merely add keybinding hints to When that is not appropriate because they merely add keybinding hints to
existing DF screens, they deliberately use red instead of green for the key. existing DF screens, they deliberately use red instead of green for the key.
.. contents::
:local:
.. _automelt: .. _automelt:
@ -612,6 +614,12 @@ resume
Allows automatic resumption of suspended constructions, along with colored Allows automatic resumption of suspended constructions, along with colored
UI hints for construction status. UI hints for construction status.
.. _title-version:
title-version
=============
Displays the DFHack version on DF's title screen when enabled.
.. _trackstop: .. _trackstop:
trackstop trackstop
@ -739,6 +747,9 @@ materials that color the light etc...
Job and Fortress management Job and Fortress management
=========================== ===========================
.. contents::
:local:
.. _autolabor: .. _autolabor:
autolabor autolabor
@ -1072,7 +1083,7 @@ This plugin adds an option to the :kbd:`q` menu for stckpiles when `enabled <ena
When autodump is enabled for a stockpile, any items placed in the stockpile will When autodump is enabled for a stockpile, any items placed in the stockpile will
automatically be designated to be dumped. automatically be designated to be dumped.
ALternatively, you can use it to quickly move all items designated to be dumped. Alternatively, you can use it to quickly move all items designated to be dumped.
Items are instantly moved to the cursor position, the dump flag is unset, Items are instantly moved to the cursor position, the dump flag is unset,
and the forbid flag is set, as if it had been dumped normally. and the forbid flag is set, as if it had been dumped normally.
Be aware that any active dump item tasks still point at the item. Be aware that any active dump item tasks still point at the item.
@ -1176,7 +1187,9 @@ Some widgets support additional options:
* ``D``: The current day, zero-padded if necessary * ``D``: The current day, zero-padded if necessary
* ``d``: The current day, *not* zero-padded * ``d``: The current day, *not* zero-padded
The default date format is ``Y-M-D``, per the ISO8601 standard. The default date format is ``Y-M-D``, per the ISO8601_ standard.
.. _ISO8601: https://en.wikipedia.org/wiki/ISO_8601
* ``cursor`` widget: * ``cursor`` widget:
@ -1187,6 +1200,8 @@ Some widgets support additional options:
displayed as ``-1`` when the cursor is outside of the DF window; otherwise, displayed as ``-1`` when the cursor is outside of the DF window; otherwise,
nothing will be displayed. nothing will be displayed.
.. _workNow:
workNow workNow
======= =======
Force all dwarves to look for a job immediately, or as soon as the game is unpaused. Force all dwarves to look for a job immediately, or as soon as the game is unpaused.
@ -1464,6 +1479,8 @@ add some new races with 'watch'. If you simply want to stop it completely use
autobutcher unwatch ALPACA CAT autobutcher unwatch ALPACA CAT
.. _autochop:
autochop autochop
======== ========
Automatically manage tree cutting designation to keep available logs withing given Automatically manage tree cutting designation to keep available logs withing given
@ -1485,6 +1502,9 @@ open the dashboard from the chop designation menu.
Map modification Map modification
================ ================
.. contents::
:local:
.. _3dveins: .. _3dveins:
3dveins 3dveins
@ -1558,6 +1578,8 @@ Features:
Digging 1-wide corridors with the miner inside the burrow is SLOW. Digging 1-wide corridors with the miner inside the burrow is SLOW.
.. _changelayer:
changelayer changelayer
=========== ===========
Changes material of the geology layer under cursor to the specified inorganic Changes material of the geology layer under cursor to the specified inorganic
@ -1632,6 +1654,8 @@ Example:
``changevein NATIVE_PLATINUM`` ``changevein NATIVE_PLATINUM``
Convert vein at cursor position into platinum ore. Convert vein at cursor position into platinum ore.
.. _changeitem:
changeitem changeitem
========== ==========
Allows changing item material and base quality. By default the item currently Allows changing item material and base quality. By default the item currently
@ -1659,6 +1683,8 @@ Examples:
``changeitem q 5`` ``changeitem q 5``
Change currently selected item to masterpiece quality. Change currently selected item to masterpiece quality.
.. _cleanconst:
cleanconst cleanconst
========== ==========
Cleans up construction materials. Cleans up construction materials.
@ -1667,6 +1693,8 @@ This utility alters all constructions on the map so that they spawn their
building component when they are disassembled, allowing their actual building component when they are disassembled, allowing their actual
build items to be safely deleted. This can improve FPS in extreme situations. build items to be safely deleted. This can improve FPS in extreme situations.
.. _deramp:
deramp deramp
====== ======
Removes all ramps designated for removal from the map. This is useful for Removes all ramps designated for removal from the map. This is useful for
@ -1688,6 +1716,8 @@ Basic commands:
to remove designations, for if you accidentally set 50 levels at once. to remove designations, for if you accidentally set 50 levels at once.
:diglx: Also cross z-levels, digging stairs as needed. Alias for ``digl x``. :diglx: Also cross z-levels, digging stairs as needed. Alias for ``digl x``.
.. _digexp:
digexp digexp
====== ======
This command is for :wiki:`exploratory mining <Exploratory_mining>`. This command is for :wiki:`exploratory mining <Exploratory_mining>`.
@ -1720,6 +1750,8 @@ Examples:
``expdig ladder designated`` ``expdig ladder designated``
Take current designations and replace them with the ladder pattern Take current designations and replace them with the ladder pattern
.. _digcircle:
digcircle digcircle
========= =========
A command for easy designation of filled and hollow circles. A command for easy designation of filled and hollow circles.
@ -1756,6 +1788,8 @@ Examples:
``digcircle`` ``digcircle``
Do it again. Do it again.
.. _digtype:
digtype digtype
======= =======
For every tile on the map of the same vein type as the selected tile, For every tile on the map of the same vein type as the selected tile,
@ -1776,6 +1810,8 @@ Options:
:down: down stairs :down: down stairs
:clear: clear designation :clear: clear designation
.. _digFlood:
digFlood digFlood
======== ========
Automatically digs out specified veins as they are discovered. It runs once Automatically digs out specified veins as they are discovered. It runs once
@ -1834,9 +1870,8 @@ is an optional description of where that is. You may also leave a description
of the contents of the file itself following the closing parenthesis on the of the contents of the file itself following the closing parenthesis on the
same line. same line.
The syntax of the file itself is similar to `digfort` or The syntax of the file itself is similar to `digfort` or :forums:`quickfort <35931>`.
`quickfort <http://www.bay12forums.com/smf/index.php?topic=35931>`_. At present, At present, only buildings constructed of an item with the same name as the building
only buildings constructed of an item with the same name as the building
are supported. All other characters are ignored. For example:: are supported. All other characters are ignored. For example::
`,`,d,`,` `,`,d,`,`
@ -1847,10 +1882,12 @@ This section of a file would designate for construction a door and some
furniture inside a bedroom: specifically, clockwise from top left, a cabinet, furniture inside a bedroom: specifically, clockwise from top left, a cabinet,
a table, a chair, a bed, and a statue. a table, a chair, a bed, and a statue.
All of the building designation uses `Planning Mode <buildingplan>`, so you do not need to All of the building designation uses `buildingplan`, so you do not need to
have the items available to construct all the buildings when you run have the items available to construct all the buildings when you run
fortplan with the .csv file. fortplan with the .csv file.
.. _getplants:
getplants getplants
========= =========
This tool allows plant gathering and tree cutting by RAW ID. Specify the types This tool allows plant gathering and tree cutting by RAW ID. Specify the types
@ -1869,6 +1906,8 @@ Options:
Specifying both ``-t`` and ``-s`` will have no effect. If no plant IDs are specified, Specifying both ``-t`` and ``-s`` will have no effect. If no plant IDs are specified,
all valid plant IDs will be listed. all valid plant IDs will be listed.
.. _infiniteSky:
infiniteSky infiniteSky
=========== ===========
Automatically allocates new z-levels of sky at the top of the map as you build up, Automatically allocates new z-levels of sky at the top of the map as you build up,
@ -1957,6 +1996,8 @@ settings in liquids were made it paints a point of 7/7 magma by default).
Intended to be used as keybinding. Requires an active in-game cursor. Intended to be used as keybinding. Requires an active in-game cursor.
.. _plant:
plant plant
===== =====
A tool for creating shrubs, growing, or getting rid of them. A tool for creating shrubs, growing, or getting rid of them.
@ -1976,6 +2017,8 @@ For mass effects, use one of the additional options:
:trees: affect all trees on the map :trees: affect all trees on the map
:all: affect every plant! :all: affect every plant!
.. _regrass:
regrass regrass
======= =======
Regrows all the grass. Not much to it ;) Regrows all the grass. Not much to it ;)
@ -2078,21 +2121,29 @@ up.
For more details, use ``tiletypes help``. For more details, use ``tiletypes help``.
.. _tiletypes-command:
tiletypes-command tiletypes-command
----------------- -----------------
Runs tiletypes commands, separated by ;. This makes it possible to change Runs tiletypes commands, separated by ;. This makes it possible to change
tiletypes modes from a hotkey or via dfhack-run. tiletypes modes from a hotkey or via dfhack-run.
.. _tiletypes-here:
tiletypes-here tiletypes-here
-------------- --------------
Apply the current tiletypes options at the in-game cursor position, including Apply the current tiletypes options at the in-game cursor position, including
the brush. Can be used from a hotkey. the brush. Can be used from a hotkey.
.. _tiletypes-here-point:
tiletypes-here-point tiletypes-here-point
-------------------- --------------------
Apply the current tiletypes options at the in-game cursor position to a single Apply the current tiletypes options at the in-game cursor position to a single
tile. Can be used from a hotkey. tile. Can be used from a hotkey.
.. _tubefill:
tubefill tubefill
======== ========
Fills all the adamantine veins again. Veins that were hollow will be left Fills all the adamantine veins again. Veins that were hollow will be left
@ -2111,6 +2162,9 @@ your miner when you dig into the region that used to be hollow.
Mods and Cheating Mods and Cheating
================= =================
.. contents::
:local:
.. _add-spatter: .. _add-spatter:
add-spatter add-spatter
@ -2231,6 +2285,8 @@ armor onto a war animal or to add unusual items (such as crowns) to any unit.
For more information run ``forceequip help``. See also `modtools/equip-item`. For more information run ``forceequip help``. See also `modtools/equip-item`.
.. _lair:
lair lair
==== ====
This command allows you to mark the map as a monster lair, preventing item This command allows you to mark the map as a monster lair, preventing item
@ -2244,6 +2300,8 @@ Options:
:lair: Mark the map as monster lair :lair: Mark the map as monster lair
:lair reset: Mark the map as ordinary (not lair) :lair reset: Mark the map as ordinary (not lair)
.. _mode:
mode mode
==== ====
This command lets you see and change the game mode directly. This command lets you see and change the game mode directly.
@ -2294,9 +2352,11 @@ Known limitations: if the selected unit is currently performing a job, the mood
siege-engine siege-engine
============ ============
Siege engines in DF haven't been updated since the game was 2D, and can Siege engines in DF haven't been updated since the game was 2D, and can
only aim in four directions. This plugin allows you to: only aim in four directions. To make them useful above-ground,
this plugin allows you to:
* link siege engines to stockpiles * link siege engines to stockpiles
* restrict operator skill levels (like workshops)
* load any object into a catapult, not just stones * load any object into a catapult, not just stones
* aim at a rectangular area in any direction, and across Z-levels * aim at a rectangular area in any direction, and across Z-levels

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<!--
DO NOT CHANGE THIS FILE - it redirects to the actual documentation.
If the page is not found, you can read the raw docs in the docs folder.
This file is an additional redirect for users in the DFHack code repo
who are visiting from ../README.html
For end-users, the real index.html will be in this relative location.
-->
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=./html/index.html">
<script type="text/javascript">
window.location.href = "./html/index.html"
</script>
<title>Page Redirection</title>
</head>
<body>
Follow this <a href='./html/index.html'>link to the documentation.</a>
</body>
</html>

@ -1597,12 +1597,6 @@ static bool items_moveToContainer(df::item *item, df::item *container)
return Items::moveToContainer(mc, item, container); return Items::moveToContainer(mc, item, container);
} }
static bool items_moveToBuilding(df::item *item, df::building_actual *building, int use_mode)
{
MapExtras::MapCache mc;
return Items::moveToBuilding(mc, item, building,use_mode);
}
static bool items_moveToInventory static bool items_moveToInventory
(df::item *item, df::unit *unit, df::unit_inventory_item::T_mode mode, int body_part) (df::item *item, df::unit *unit, df::unit_inventory_item::T_mode mode, int body_part)
{ {
@ -1653,7 +1647,6 @@ static const LuaWrapper::FunctionReg dfhack_items_module[] = {
WRAPM(Items, createItem), WRAPM(Items, createItem),
WRAPN(moveToGround, items_moveToGround), WRAPN(moveToGround, items_moveToGround),
WRAPN(moveToContainer, items_moveToContainer), WRAPN(moveToContainer, items_moveToContainer),
WRAPN(moveToBuilding, items_moveToBuilding),
WRAPN(moveToInventory, items_moveToInventory), WRAPN(moveToInventory, items_moveToInventory),
WRAPN(makeProjectile, items_makeProjectile), WRAPN(makeProjectile, items_makeProjectile),
WRAPN(remove, items_remove), WRAPN(remove, items_remove),
@ -1675,9 +1668,22 @@ static int items_getContainedItems(lua_State *state)
return 1; return 1;
} }
static int items_moveToBuilding(lua_State *state)
{
MapExtras::MapCache mc;
auto item = Lua::CheckDFObject<df::item>(state, 1);
auto building = Lua::CheckDFObject<df::building_actual>(state, 2);
int use_mode = luaL_optint(state, 3, 0);
bool force_in_building = lua_toboolean(state, 4);
lua_pushboolean(state, Items::moveToBuilding(mc, item, building, use_mode, force_in_building));
return 1;
}
static const luaL_Reg dfhack_items_funcs[] = { static const luaL_Reg dfhack_items_funcs[] = {
{ "getPosition", items_getPosition }, { "getPosition", items_getPosition },
{ "getContainedItems", items_getContainedItems }, { "getContainedItems", items_getContainedItems },
{ "moveToBuilding", items_moveToBuilding },
{ NULL, NULL } { NULL, NULL }
}; };

@ -448,19 +448,29 @@ Lua::ObjectClass Lua::IsDFObject(lua_State *state, int val_index)
static const char *const primitive_types[] = { static const char *const primitive_types[] = {
"string", "string",
"ptr-string",
"int8_t", "uint8_t", "int16_t", "uint16_t", "int8_t", "uint8_t", "int16_t", "uint16_t",
"int32_t", "uint32_t", "int64_t", "uint64_t", "int32_t", "uint32_t", "int64_t", "uint64_t",
"bool", "float", "double", "bool", "float", "double",
"pointer",
"ptr-vector",
"bit-vector",
"bit-array",
NULL NULL
}; };
static type_identity *const primitive_identities[] = { static type_identity *const primitive_identities[] = {
df::identity_traits<std::string>::get(), df::identity_traits<std::string>::get(),
df::identity_traits<const char*>::get(),
df::identity_traits<int8_t>::get(), df::identity_traits<uint8_t>::get(), df::identity_traits<int8_t>::get(), df::identity_traits<uint8_t>::get(),
df::identity_traits<int16_t>::get(), df::identity_traits<uint16_t>::get(), df::identity_traits<int16_t>::get(), df::identity_traits<uint16_t>::get(),
df::identity_traits<int32_t>::get(), df::identity_traits<uint32_t>::get(), df::identity_traits<int32_t>::get(), df::identity_traits<uint32_t>::get(),
df::identity_traits<int64_t>::get(), df::identity_traits<uint64_t>::get(), df::identity_traits<int64_t>::get(), df::identity_traits<uint64_t>::get(),
df::identity_traits<bool>::get(), df::identity_traits<bool>::get(),
df::identity_traits<float>::get(), df::identity_traits<double>::get(), df::identity_traits<float>::get(), df::identity_traits<double>::get(),
df::identity_traits<void*>::get(),
df::identity_traits<std::vector<void*> >::get(),
df::identity_traits<std::vector<bool> >::get(),
df::identity_traits<BitArray<int> >::get(),
NULL NULL
}; };

@ -148,6 +148,18 @@ namespace DFHack
return 0; return 0;
return (void*)i->second; return (void*)i->second;
} }
bool getVTableName (const void *vtable, std::string &out) const
{
for (auto i = VTables.begin(); i != VTables.end(); ++i)
{
if ((void*)i->second == vtable)
{
out = i->first;
return true;
}
}
return false;
}
void setOS(const OSType os) void setOS(const OSType os)
{ {

@ -164,7 +164,8 @@ DFHACK_EXPORT std::string getDescription(df::item *item, int type = 0, bool deco
DFHACK_EXPORT bool moveToGround(MapExtras::MapCache &mc, df::item *item, df::coord pos); DFHACK_EXPORT bool moveToGround(MapExtras::MapCache &mc, df::item *item, df::coord pos);
DFHACK_EXPORT bool moveToContainer(MapExtras::MapCache &mc, df::item *item, df::item *container); DFHACK_EXPORT bool moveToContainer(MapExtras::MapCache &mc, df::item *item, df::item *container);
DFHACK_EXPORT bool moveToBuilding(MapExtras::MapCache &mc, df::item *item, df::building_actual *building,int16_t use_mode); DFHACK_EXPORT bool moveToBuilding(MapExtras::MapCache &mc, df::item *item, df::building_actual *building,
int16_t use_mode = 0, bool force_in_building = false);
DFHACK_EXPORT bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *unit, DFHACK_EXPORT bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *unit,
df::unit_inventory_item::T_mode mode = df::unit_inventory_item::Hauled, int body_part = -1); df::unit_inventory_item::T_mode mode = df::unit_inventory_item::Hauled, int body_part = -1);

@ -247,6 +247,14 @@ function safe_index(obj,idx,...)
end end
end end
function string:startswith(prefix)
return self:sub(1, #prefix) == prefix
end
function string:endswith(suffix)
return self:sub(-#suffix) == suffix or #suffix == 0
end
-- String conversions -- String conversions
function dfhack.persistent:__tostring() function dfhack.persistent:__tostring()

@ -419,14 +419,23 @@ function MenuOverlay:render(dc)
end end
--fakes a "real" workshop sidebar menu, but on exactly selected workshop --fakes a "real" workshop sidebar menu, but on exactly selected workshop
WorkshopOverlay = defclass(WorkshopOverlay, MenuOverlay) WorkshopOverlay = defclass(WorkshopOverlay, MenuOverlay)
WorkshopOverlay.focus_path="WorkshopOverlay"
WorkshopOverlay.ATTRS={ WorkshopOverlay.ATTRS={
workshop=DEFAULT_NIL, workshop=DEFAULT_NIL,
} }
function WorkshopOverlay:onAboutToShow(below)
WorkshopOverlay.super.onAboutToShow(self,below)
if df.global.world.selected_building ~= self.workshop then
error("The workshop overlay tried to show up for incorrect workshop")
end
end
function WorkshopOverlay:onInput(keys) function WorkshopOverlay:onInput(keys)
local allowedKeys={ --TODO add options: job management, profile, etc... local allowedKeys={ --TODO add options: job management, profile, etc...
"CURSOR_RIGHT","CURSOR_LEFT","CURSOR_UP","CURSOR_DOWN", "CURSOR_RIGHT","CURSOR_LEFT","CURSOR_UP","CURSOR_DOWN",
"CURSOR_UPRIGHT","CURSOR_UPLEFT","CURSOR_DOWNRIGHT","CURSOR_DOWNLEFT", "CURSOR_UPRIGHT","CURSOR_UPLEFT","CURSOR_DOWNRIGHT","CURSOR_DOWNLEFT",
"CURSOR_UP_Z","CURSOR_DOWN_Z","DESTROYBUILDING","CHANGETAB"} "CURSOR_UP_Z","CURSOR_DOWN_Z","DESTROYBUILDING","CHANGETAB","SUSPENDBUILDING"}
if keys.LEAVESCREEN then if keys.LEAVESCREEN then
self:dismiss() self:dismiss()
self:sendInputToParent('LEAVESCREEN') self:sendInputToParent('LEAVESCREEN')
@ -448,4 +457,26 @@ function WorkshopOverlay:onInput(keys)
return return
end end
end end
function WorkshopOverlay:onGetSelectedBuilding()
return self.workshop
end
local function is_slated_for_remove( bld )
for i,v in ipairs(bld.jobs) do
if v.job_type==df.job_type.DestroyBuilding then
return true
end
end
return false
end
function WorkshopOverlay:render(dc)
self:renderParent()
if df.global.world.selected_building ~= self.workshop then
return
end
if is_slated_for_remove(self.workshop) then
return
end
WorkshopOverlay.super.render(self, dc)
end
return _ENV return _ENV

@ -1,5 +1,6 @@
local _ENV = mkmodule('json') local _ENV = mkmodule('json')
local internal = require 'json.internal' local internal = require 'json.internal'
local fs = dfhack.filesystem
encode_defaults = { encode_defaults = {
-- For compatibility with jsonxx (C++) -- For compatibility with jsonxx (C++)
@ -14,11 +15,8 @@ function encode(data, options, msg)
return internal:encode(data, msg, opts) return internal:encode(data, msg, opts)
end end
function encode_file(data, path, overwrite, ...) function encode_file(data, path, ...)
if dfhack.filesystem.exists(path) and not overwrite then if fs.isdir(path) then
error('File exists: ' .. path)
end
if dfhack.filesystem.isdir(path) then
error('Is a directory: ' .. path) error('Is a directory: ' .. path)
end end
local contents = encode(data, ...) local contents = encode(data, ...)
@ -41,4 +39,42 @@ function decode_file(path, ...)
return decode(contents, ...) return decode(contents, ...)
end end
local _file = defclass()
function _file:init(opts)
self.path = opts.path
self.data = {}
self.exists = false
self:read(opts.strict)
end
function _file:read(strict)
if not fs.exists(self.path) then
if strict then
error('cannot read file: ' .. self.path)
else
self.data = {}
end
else
self.exists = true
self.data = decode_file(self.path)
end
return self.data
end
function _file:write(data)
if data then
self.data = data
end
encode_file(self.data, self.path)
self.exists = true
end
function _file:__tostring()
return ('<json file: %s>'):format(self.path)
end
function open(path, strict)
return _file{path=path, strict=strict}
end
return _ENV return _ENV

@ -892,7 +892,8 @@ bool DFHack::Items::moveToContainer(MapExtras::MapCache &mc, df::item *item, df:
return true; return true;
} }
bool DFHack::Items::moveToBuilding(MapExtras::MapCache &mc, df::item *item, df::building_actual *building,int16_t use_mode) bool DFHack::Items::moveToBuilding(MapExtras::MapCache &mc, df::item *item, df::building_actual *building,
int16_t use_mode, bool force_in_building)
{ {
CHECK_NULL_POINTER(item); CHECK_NULL_POINTER(item);
CHECK_NULL_POINTER(building); CHECK_NULL_POINTER(building);
@ -915,6 +916,7 @@ bool DFHack::Items::moveToBuilding(MapExtras::MapCache &mc, df::item *item, df::
item->pos.x=building->centerx; item->pos.x=building->centerx;
item->pos.y=building->centery; item->pos.y=building->centery;
item->pos.z=building->z; item->pos.z=building->z;
if (use_mode == 2 || force_in_building)
item->flags.bits.in_building=true; item->flags.bits.in_building=true;
ref->building_id=building->id; ref->building_id=building->id;

@ -1 +1 @@
Subproject commit baba4f54464a303bab6bc4f1b7d90cc9e4ff107b Subproject commit 58806dc7e4bfcc1bb5f33b15395bdc9fd5a1ea28

@ -44,6 +44,7 @@ REQUIRE_GLOBAL(ui);
static bool autochop_enabled = false; static bool autochop_enabled = false;
static int min_logs, max_logs; static int min_logs, max_logs;
static const int LOG_CAP_MAX = 99999;
static bool wait_for_threshold; static bool wait_for_threshold;
static PersistentDataItem config_autochop; static PersistentDataItem config_autochop;
@ -157,6 +158,18 @@ private:
static WatchedBurrows watchedBurrows; static WatchedBurrows watchedBurrows;
static int string_to_int(string s, int default_ = 0)
{
try
{
return std::stoi(s);
}
catch (std::exception&)
{
return default_;
}
}
static void save_config() static void save_config()
{ {
config_autochop.val() = watchedBurrows.getSerialisedIds(); config_autochop.val() = watchedBurrows.getSerialisedIds();
@ -359,6 +372,7 @@ class ViewscreenAutochop : public dfhack_viewscreen
public: public:
ViewscreenAutochop() ViewscreenAutochop()
{ {
edit_mode = EDIT_NONE;
burrows_column.multiselect = true; burrows_column.multiselect = true;
burrows_column.setTitle("Burrows"); burrows_column.setTitle("Burrows");
burrows_column.bottom_margin = 3; burrows_column.bottom_margin = 3;
@ -415,6 +429,46 @@ public:
void feed(set<df::interface_key> *input) void feed(set<df::interface_key> *input)
{ {
if (edit_mode != EDIT_NONE)
{
string entry = int_to_string(edit_mode == EDIT_MIN ? min_logs : max_logs);
if (input->count(interface_key::LEAVESCREEN) || input->count(interface_key::SELECT))
{
if (edit_mode == EDIT_MIN)
max_logs = std::max(min_logs, max_logs);
else if (edit_mode == EDIT_MAX)
min_logs = std::min(min_logs, max_logs);
edit_mode = EDIT_NONE;
}
else if (input->count(interface_key::STRING_A000))
{
if (!entry.empty())
entry.erase(entry.size() - 1);
}
else if (entry.size() < 5)
{
for (auto k = input->begin(); k != input->end(); ++k)
{
char ch = char(Screen::keyToChar(*k));
if (ch >= '0' && ch <= '9')
entry += ch;
}
}
switch (edit_mode)
{
case EDIT_MIN:
min_logs = string_to_int(entry);
break;
case EDIT_MAX:
max_logs = string_to_int(entry);
break;
default: break;
}
return;
}
bool key_processed = false; bool key_processed = false;
message.clear(); message.clear();
switch (selected_column) switch (selected_column)
@ -456,6 +510,19 @@ public:
message = "Trees unmarked: " + int_to_string(count); message = "Trees unmarked: " + int_to_string(count);
marked_tree_count = do_chop_designation(false, true); marked_tree_count = do_chop_designation(false, true);
} }
else if (input->count(interface_key::CUSTOM_N))
{
edit_mode = EDIT_MIN;
}
else if (input->count(interface_key::CUSTOM_M))
{
edit_mode = EDIT_MAX;
}
else if (input->count(interface_key::CUSTOM_SHIFT_N))
{
min_logs = LOG_CAP_MAX + 1;
max_logs = LOG_CAP_MAX + 1;
}
else if (input->count(interface_key::CUSTOM_H)) else if (input->count(interface_key::CUSTOM_H))
{ {
change_min_logs(-1); change_min_logs(-1);
@ -537,8 +604,38 @@ public:
OutputHotkeyString(x, y, "Toggle Burrow", "Enter", true, left_margin); OutputHotkeyString(x, y, "Toggle Burrow", "Enter", true, left_margin);
if (autochop_enabled) if (autochop_enabled)
{ {
OutputLabelString(x, y, "Min Logs", "hjHJ", int_to_string(min_logs), true, left_margin); using namespace df::enums::interface_key;
OutputLabelString(x, y, "Max Logs", "klKL", int_to_string(max_logs), true, left_margin); const struct {
const char *caption;
int count;
bool in_edit;
df::interface_key key;
df::interface_key skeys[4];
} rows[] = {
{"Min Logs: ", min_logs, edit_mode == EDIT_MIN, CUSTOM_N, {CUSTOM_H, CUSTOM_J, CUSTOM_SHIFT_H, CUSTOM_SHIFT_J}},
{"Max Logs: ", max_logs, edit_mode == EDIT_MAX, CUSTOM_M, {CUSTOM_K, CUSTOM_L, CUSTOM_SHIFT_K, CUSTOM_SHIFT_L}}
};
for (size_t i = 0; i < sizeof(rows)/sizeof(rows[0]); ++i)
{
auto row = rows[i];
OutputHotkeyString(x, y, row.caption, row.key);
auto prev_x = x;
if (row.in_edit)
OutputString(COLOR_LIGHTCYAN, x, y, int_to_string(row.count) + "_");
else if (row.count <= LOG_CAP_MAX)
OutputString(COLOR_LIGHTGREEN, x, y, int_to_string(row.count));
else
OutputString(COLOR_LIGHTBLUE, x, y, "Unlimited");
if (edit_mode == EDIT_NONE)
{
x = std::max(x, prev_x + 10);
for (size_t j = 0; j < sizeof(row.skeys)/sizeof(row.skeys[0]); ++j)
OutputString(COLOR_LIGHTGREEN, x, y, DFHack::Screen::getKeyDisplay(row.skeys[j]));
OutputString(COLOR_WHITE, x, y, ": Step");
}
OutputString(COLOR_WHITE, x, y, "", true, left_margin);
}
OutputHotkeyString(x, y, "No limit", CUSTOM_SHIFT_N, true, left_margin);
} }
++y; ++y;
@ -565,6 +662,7 @@ private:
int marked_tree_count; int marked_tree_count;
MapExtras::MapCache mcache; MapExtras::MapCache mcache;
string message; string message;
enum { EDIT_NONE, EDIT_MIN, EDIT_MAX } edit_mode;
void validateColumn() void validateColumn()
{ {
@ -693,7 +791,7 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"autochop", "Allows automatic harvesting of trees based on the number of stockpiled logs", "autochop", "Auto-harvest trees when low on stockpiled logs",
df_autochop, false, df_autochop, false,
"Opens the automated chopping control screen. Specify 'debug' to forcibly save settings.\n" "Opens the automated chopping control screen. Specify 'debug' to forcibly save settings.\n"
)); ));

@ -299,7 +299,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
{ {
commands.push_back( commands.push_back(
PluginCommand( PluginCommand(
"automelt", "Automatically flag metal items in marked stockpiles for melting.", "automelt", "Automatically melt metal items in marked stockpiles.",
automelt_cmd, false, "")); automelt_cmd, false, ""));
return CR_OK; return CR_OK;

@ -236,7 +236,7 @@ command_result clean (color_ostream &out, vector <string> & parameters)
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"clean","Removes contaminants from map tiles, items and creatures.", "clean","Remove contaminants from tiles, items and creatures.",
clean, false, clean, false,
" Removes contaminants from map tiles, items and creatures.\n" " Removes contaminants from map tiles, items and creatures.\n"
"Options:\n" "Options:\n"

@ -33,6 +33,7 @@ using namespace DFHack;
using namespace df::enums; using namespace df::enums;
DFHACK_PLUGIN("createitem"); DFHACK_PLUGIN("createitem");
REQUIRE_GLOBAL(cursor);
REQUIRE_GLOBAL(world); REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(ui); REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(gametype); REQUIRE_GLOBAL(gametype);
@ -68,7 +69,7 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
return CR_OK; return CR_OK;
} }
bool makeItem (df::reaction_product_itemst *prod, df::unit *unit, bool second_item = false) bool makeItem (df::reaction_product_itemst *prod, df::unit *unit, bool second_item = false, bool move_to_cursor = false)
{ {
vector<df::reaction_product*> out_products; vector<df::reaction_product*> out_products;
vector<df::item *> out_items; vector<df::item *> out_items;
@ -115,6 +116,8 @@ bool makeItem (df::reaction_product_itemst *prod, df::unit *unit, bool second_it
} }
if (on_ground) if (on_ground)
out_items[i]->moveToGround(unit->pos.x, unit->pos.y, unit->pos.z); out_items[i]->moveToGround(unit->pos.x, unit->pos.y, unit->pos.z);
if (move_to_cursor)
out_items[i]->moveToGround(cursor->x, cursor->y, cursor->z);
if (is_gloves) if (is_gloves)
{ {
// if the reaction creates gloves without handedness, then create 2 sets (left and right) // if the reaction creates gloves without handedness, then create 2 sets (left and right)
@ -138,6 +141,7 @@ command_result df_createitem (color_ostream &out, vector <string> & parameters)
int16_t mat_type = -1; int16_t mat_type = -1;
int32_t mat_index = -1; int32_t mat_index = -1;
int count = 1; int count = 1;
bool move_to_cursor = false;
if (parameters.size() == 1) if (parameters.size() == 1)
{ {
@ -355,6 +359,12 @@ command_result df_createitem (color_ostream &out, vector <string> & parameters)
// Use the adventurer unit // Use the adventurer unit
unit = world->units.active[0]; unit = world->units.active[0];
} }
else if (!world->units.active.empty() && cursor->x >= 0)
{
// Use the first possible unit and the cursor position
unit = world->units.active[0];
move_to_cursor = true;
}
else else
{ {
out.printerr("No unit selected!\n"); out.printerr("No unit selected!\n");
@ -410,7 +420,7 @@ command_result df_createitem (color_ostream &out, vector <string> & parameters)
out.printerr("Previously selected building no longer exists - item will be placed on the floor.\n"); out.printerr("Previously selected building no longer exists - item will be placed on the floor.\n");
} }
bool result = makeItem(prod, unit); bool result = makeItem(prod, unit, false, move_to_cursor);
delete prod; delete prod;
if (!result) if (!result)
{ {

@ -58,7 +58,7 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters);
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("cursecheck", commands.push_back(PluginCommand("cursecheck",
"Checks for cursed creatures (vampires, necromancers, zombies, ...).", "Check for cursed creatures (undead, necromancers...)",
cursecheck, false )); cursecheck, false ));
return CR_OK; return CR_OK;
} }

@ -83,7 +83,7 @@ command_result df_deramp (color_ostream &out, vector <string> & parameters)
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"deramp", "De-ramp. All ramps marked for removal are replaced with floors.", "deramp", "Replace all ramps marked for removal with floors.",
df_deramp, false, df_deramp, false,
" If there are any ramps designated for removal, they will be instantly\n" " If there are any ramps designated for removal, they will be instantly\n"
" removed. Any ramps that don't have their counterpart will also be removed\n" " removed. Any ramps that don't have their counterpart will also be removed\n"

@ -42,7 +42,7 @@ DFHACK_PLUGIN("kittens");
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("nyan","NYAN CAT INVASION!",kittens)); commands.push_back(PluginCommand("nyan","NYAN CAT INVASION!",kittens));
commands.push_back(PluginCommand("ktimer","Measure time between game updates and console lag (toggle).",ktimer)); commands.push_back(PluginCommand("ktimer","Measure time between game updates and console lag.",ktimer));
commands.push_back(PluginCommand("trackmenu","Track menu ID changes (toggle).",trackmenu)); commands.push_back(PluginCommand("trackmenu","Track menu ID changes (toggle).",trackmenu));
commands.push_back(PluginCommand("trackpos","Track mouse and designation coords (toggle).",trackpos)); commands.push_back(PluginCommand("trackpos","Track mouse and designation coords (toggle).",trackpos));
commands.push_back(PluginCommand("trackstate","Track world and map state (toggle).",trackstate)); commands.push_back(PluginCommand("trackstate","Track world and map state (toggle).",trackstate));

@ -36,7 +36,7 @@ DFHACK_PLUGIN("memview");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview)); commands.push_back(PluginCommand("memview","Shows DF memory in real time.",memview,false,"Shows memory in real time.\nParams: adrr length refresh_rate. If addr==0 then stop viewing."));
memdata.state=STATE_OFF; memdata.state=STATE_OFF;
mymutex=new tthread::mutex; mymutex=new tthread::mutex;
return CR_OK; return CR_OK;

@ -45,7 +45,7 @@ DFHACK_PLUGIN("rprobe");
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"rprobe", "Display assorted region information from embark screen", "rprobe", "Display region information from embark screen",
rprobe, false, rprobe, false,
"Display assorted region information from embark screen\n" "Display assorted region information from embark screen\n"
)); ));

@ -1,18 +1,20 @@
// Lists embeded STL vectors and pointers to STL vectors found in the given // Lists embeded STL vectors and pointers to STL vectors found in the given
// memory range. // memory range.
// //
// Linux only, enabled with BUILD_VECTORS cmake option. // Linux and OS X only
#include "Core.h"
#include <Console.h>
#include <Export.h>
#include <PluginManager.h>
#include <MemAccess.h>
#include <vector> #include <vector>
#include <string> #include <string>
#include <stdio.h> #include <stdio.h>
#include "Core.h"
#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "MemAccess.h"
#include "VersionInfo.h"
using std::vector; using std::vector;
using std::string; using std::string;
using namespace DFHack; using namespace DFHack;
@ -58,7 +60,7 @@ static bool hexOrDec(string &str, uint32_t &value)
return false; return false;
} }
static bool mightBeVec(vector<t_memrange> &heap_ranges, static bool mightBeVec(vector<t_memrange> &ranges,
t_vecTriplet *vec) t_vecTriplet *vec)
{ {
if ((vec->start > vec->end) || (vec->end > vec->alloc_end)) if ((vec->start > vec->end) || (vec->end > vec->alloc_end))
@ -70,9 +72,9 @@ static bool mightBeVec(vector<t_memrange> &heap_ranges,
if (((int)vec->start % 4 != 0) || ((int)vec->alloc_end % 4 != 0)) if (((int)vec->start % 4 != 0) || ((int)vec->alloc_end % 4 != 0))
return false; return false;
for (size_t i = 0; i < heap_ranges.size(); i++) for (size_t i = 0; i < ranges.size(); i++)
{ {
t_memrange &range = heap_ranges[i]; t_memrange &range = ranges[i];
if (range.isInRange(vec->start) && range.isInRange(vec->alloc_end)) if (range.isInRange(vec->start) && range.isInRange(vec->alloc_end))
return true; return true;
@ -92,7 +94,7 @@ static bool inAnyRange(vector<t_memrange> &ranges, void * ptr)
return false; return false;
} }
static bool getHeapRanges(color_ostream &out, std::vector<t_memrange> &heap_ranges) static bool getRanges(color_ostream &out, std::vector<t_memrange> &out_ranges)
{ {
std::vector<t_memrange> ranges; std::vector<t_memrange> ranges;
@ -102,19 +104,13 @@ static bool getHeapRanges(color_ostream &out, std::vector<t_memrange> &heap_rang
{ {
t_memrange &range = ranges[i]; t_memrange &range = ranges[i];
// Some kernels don't report [heap], and the heap can consist of
// more segments than just the one labeled with [heap], so include
// all segments which *might* be part of the heap.
if (range.read && range.write && !range.shared) if (range.read && range.write && !range.shared)
{ out_ranges.push_back(range);
if (strlen(range.name) == 0 || strcmp(range.name, "[heap]") == 0)
heap_ranges.push_back(range);
}
} }
if (heap_ranges.empty()) if (out_ranges.empty())
{ {
out << "No possible heap segments." << std::endl; out << "No readable segments." << std::endl;
return false; return false;
} }
@ -132,13 +128,26 @@ static void vectorsUsage(color_ostream &con)
} }
static void printVec(color_ostream &con, const char* msg, t_vecTriplet *vec, static void printVec(color_ostream &con, const char* msg, t_vecTriplet *vec,
uint32_t start, uint32_t pos) uint32_t start, uint32_t pos, std::vector<t_memrange> &ranges)
{ {
uint32_t length = (int)vec->end - (int)vec->start; uint32_t length = (int)vec->end - (int)vec->start;
uint32_t offset = pos - start; uint32_t offset = pos - start;
con.print("%8s offset %06p, addr %010p, start %010p, length %u\n", con.print("%8s offset %06p, addr %010p, start %010p, length %u",
msg, offset, pos, vec->start, length); msg, offset, pos, vec->start, length);
if (length >= 4 && length % 4 == 0)
{
void *ptr = vec->start;
for (int level = 0; level < 2; level++)
{
if (inAnyRange(ranges, ptr))
ptr = *(void**)ptr;
}
std::string classname;
if (Core::getInstance().vinfo->getVTableName(ptr, classname))
con.print(", 1st item: %s", classname.c_str());
}
con.print("\n");
} }
command_result df_vectors (color_ostream &con, vector <string> & parameters) command_result df_vectors (color_ostream &con, vector <string> & parameters)
@ -171,17 +180,17 @@ command_result df_vectors (color_ostream &con, vector <string> & parameters)
CoreSuspender suspend; CoreSuspender suspend;
std::vector<t_memrange> heap_ranges; std::vector<t_memrange> ranges;
if (!getHeapRanges(con, heap_ranges)) if (!getRanges(con, ranges))
{ {
return CR_FAILURE; return CR_FAILURE;
} }
bool startInRange = false; bool startInRange = false;
for (size_t i = 0; i < heap_ranges.size(); i++) for (size_t i = 0; i < ranges.size(); i++)
{ {
t_memrange &range = heap_ranges[i]; t_memrange &range = ranges[i];
if (!range.isInRange((void *)start)) if (!range.isInRange((void *)start))
continue; continue;
@ -217,9 +226,9 @@ command_result df_vectors (color_ostream &con, vector <string> & parameters)
{ {
t_vecTriplet* vec = (t_vecTriplet*) pos; t_vecTriplet* vec = (t_vecTriplet*) pos;
if (mightBeVec(heap_ranges, vec)) if (mightBeVec(ranges, vec))
{ {
printVec(con, "VEC:", vec, start, pos); printVec(con, "VEC:", vec, start, pos, ranges);
// Skip over rest of vector. // Skip over rest of vector.
pos += sizeof(t_vecTriplet) - ptr_size; pos += sizeof(t_vecTriplet) - ptr_size;
continue; continue;
@ -231,13 +240,13 @@ command_result df_vectors (color_ostream &con, vector <string> & parameters)
{ {
uint32_t ptr = * ( (uint32_t*) pos); uint32_t ptr = * ( (uint32_t*) pos);
if (inAnyRange(heap_ranges, (void *) ptr)) if (inAnyRange(ranges, (void *) ptr))
{ {
t_vecTriplet* vec = (t_vecTriplet*) ptr; t_vecTriplet* vec = (t_vecTriplet*) ptr;
if (mightBeVec(heap_ranges, vec)) if (mightBeVec(ranges, vec))
{ {
printVec(con, "VEC PTR:", vec, start, pos); printVec(con, "VEC PTR:", vec, start, pos, ranges);
continue; continue;
} }
} }
@ -282,9 +291,9 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
CoreSuspender suspend; CoreSuspender suspend;
std::vector<t_memrange> heap_ranges; std::vector<t_memrange> ranges;
if (!getHeapRanges(con, heap_ranges)) if (!getRanges(con, ranges))
{ {
return CR_FAILURE; return CR_FAILURE;
} }
@ -305,7 +314,7 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
continue; continue;
} }
if (!inAnyRange(heap_ranges, (void *) addr)) if (!inAnyRange(ranges, (void *) addr))
{ {
con << addr_str << " not in any valid address range." << std::endl; con << addr_str << " not in any valid address range." << std::endl;
continue; continue;
@ -315,7 +324,7 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
bool ptr = false; bool ptr = false;
t_vecTriplet* vec = (t_vecTriplet*) addr; t_vecTriplet* vec = (t_vecTriplet*) addr;
if (mightBeVec(heap_ranges, vec)) if (mightBeVec(ranges, vec))
valid = true; valid = true;
else else
{ {
@ -323,7 +332,7 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
addr = * ( (uint32_t*) addr); addr = * ( (uint32_t*) addr);
vec = (t_vecTriplet*) addr; vec = (t_vecTriplet*) addr;
if (inAnyRange(heap_ranges, (void *) addr) && mightBeVec(heap_ranges, vec)) if (inAnyRange(ranges, (void *) addr) && mightBeVec(ranges, vec))
{ {
valid = true; valid = true;
ptr = true; ptr = true;

@ -55,8 +55,8 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" Designates layerstone under the cursor for digging.\n" " Designates layerstone under the cursor for digging.\n"
" Also follows the stone between z-levels with stairs, like 'digl x' would.\n" " Also follows the stone between z-levels with stairs, like 'digl x' would.\n"
)); ));
commands.push_back(PluginCommand("digexp","Select or designate an exploratory pattern. Use 'digexp ?' for help.",digexp)); commands.push_back(PluginCommand("digexp","Select or designate an exploratory pattern.",digexp));
commands.push_back(PluginCommand("digcircle","Dig designate a circle (filled or hollow) with given diameter.",digcircle)); commands.push_back(PluginCommand("digcircle","Dig designate a circle (filled or hollow)",digcircle));
//commands.push_back(PluginCommand("digauto","Mark a tile for continuous digging.",autodig)); //commands.push_back(PluginCommand("digauto","Mark a tile for continuous digging.",autodig));
commands.push_back(PluginCommand("digtype", "Dig all veins of a given type.", digtype,Gui::cursor_hotkey, commands.push_back(PluginCommand("digtype", "Dig all veins of a given type.", digtype,Gui::cursor_hotkey,
"For every tile on the map of the same vein type as the selected tile, this command designates it to have the same designation as the selected tile. If the selected tile has no designation, they will be dig designated.\n" "For every tile on the map of the same vein type as the selected tile, this command designates it to have the same designation as the selected tile. If the selected tile has no designation, they will be dig designated.\n"

@ -246,7 +246,7 @@ DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable )
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("fastdwarf", commands.push_back(PluginCommand("fastdwarf",
"enable/disable fastdwarf and teledwarf (parameters=0/1)", "let dwarves teleport and/or finish jobs instantly",
fastdwarf, false, fastdwarf, false,
"fastdwarf: make dwarves faster.\n" "fastdwarf: make dwarves faster.\n"
"Usage:\n" "Usage:\n"

@ -44,7 +44,7 @@ DFHACK_PLUGIN("filltraffic");
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"filltraffic","Flood-fill with selected traffic designation from cursor", "filltraffic","Flood-fill selected traffic designation from cursor",
filltraffic, Gui::cursor_hotkey, filltraffic, Gui::cursor_hotkey,
" Flood-fill selected traffic type from the cursor.\n" " Flood-fill selected traffic type from the cursor.\n"
"Traffic Type Codes:\n" "Traffic Type Codes:\n"

@ -29,7 +29,7 @@ uint8_t prevMenuWidth;
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"follow", "Follow the selected unit until camera control is released", "follow", "Make the screen follow the selected unit",
follow, Gui::view_unit_hotkey, follow, Gui::view_unit_hotkey,
" Select a unit and run this plugin to make the camera follow it.\n" " Select a unit and run this plugin to make the camera follow it.\n"
" Moving the camera yourself deactivates the plugin.\n" " Moving the camera yourself deactivates the plugin.\n"

@ -216,7 +216,7 @@ const string forceequip_help =
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"forceequip", "Moves local items from the ground into a unit's inventory", "forceequip", "Move items from the ground into a unit's inventory",
df_forceequip, false, df_forceequip, false,
forceequip_help.c_str() forceequip_help.c_str()
)); ));

@ -51,7 +51,7 @@ public:
std::vector<BuildingInfo> buildings; std::vector<BuildingInfo> buildings;
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands) { DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands) {
commands.push_back(PluginCommand("fortplan","Lay out buildings in your fortress based on a Quickfort-style CSV input file.",fortplan,false, commands.push_back(PluginCommand("fortplan","Lay out buildings from a Quickfort-style CSV file.",fortplan,false,
"Lay out buildings in your fortress based on a Quickfort-style CSV input file.\n" "Lay out buildings in your fortress based on a Quickfort-style CSV input file.\n"
"Usage: fortplan [filename]\n")); "Usage: fortplan [filename]\n"));

@ -152,7 +152,7 @@ command_result df_getplants (color_ostream &out, vector <string> & parameters)
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"getplants", "Cut down all of the specified trees or gather specified shrubs", "getplants", "Cut down trees or gather shrubs by ID",
df_getplants, false, df_getplants, false,
" Specify the types of trees to cut down and/or shrubs to gather by their\n" " Specify the types of trees to cut down and/or shrubs to gather by their\n"
" plant IDs, separated by spaces.\n" " plant IDs, separated by spaces.\n"

@ -354,7 +354,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
commands.push_back( commands.push_back(
PluginCommand( PluginCommand(
"hotkeys", "Shows ingame viewscreen with all dfhack keybindings active in current mode.", "hotkeys", "Show all dfhack keybindings in current context.",
hotkeys_cmd, false, "")); hotkeys_cmd, false, ""));
return CR_OK; return CR_OK;

@ -32,7 +32,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"infiniteSky", "infiniteSky",
"Creates new sky levels on request, or as you construct up.", "Creates new sky levels on request, or as needed.",
infiniteSky, false, infiniteSky, false,
"Usage:\n" "Usage:\n"
" infiniteSky\n" " infiniteSky\n"

@ -58,7 +58,7 @@ command_result lair(color_ostream &out, std::vector<std::string> & params)
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("lair","Mark the map as a monster lair, preventing item scatter.",lair, false, commands.push_back(PluginCommand("lair","Mark the map as a monster lair (avoids item scatter)",lair, false,
"Usage: 'lair' to mark entire map as monster lair, 'lair reset' to undo the operation.\n")); "Usage: 'lair' to mark entire map as monster lair, 'lair reset' to undo the operation.\n"));
return CR_OK; return CR_OK;
} }

@ -95,8 +95,8 @@ local function findGears( shop_def ) --finds positions of all gears and inverted
end end
return ret return ret
end end
local function lookup_color( shop_def,x,y,stage )--TODO: background and bright? local function lookup_color( shop_def,x,y,stage )
return shop_def.tile_color[stage][x][y] return shop_def.tile_color[0][stage][x][y],shop_def.tile_color[1][stage][x][y],shop_def.tile_color[2][stage][x][y]
end end
local function processFramesAuto( shop_def ,gears) --adds frames for all gear icons and inverted gear icons local function processFramesAuto( shop_def ,gears) --adds frames for all gear icons and inverted gear icons
local w,h=shop_def.dim_x,shop_def.dim_y local w,h=shop_def.dim_x,shop_def.dim_y
@ -114,8 +114,8 @@ local function processFramesAuto( shop_def ,gears) --adds frames for all gear ic
tile_inv=42 tile_inv=42
end end
table.insert(frames[1],{x=v.x,y=v.y,tile,lookup_color(shop_def,v.x,v.y),0,0}) table.insert(frames[1],{x=v.x,y=v.y,tile,lookup_color(shop_def,v.x,v.y,stage)})
table.insert(frames[2],{x=v.x,y=v.y,tile_inv,lookup_color(shop_def,v.x,v.y),0,0}) table.insert(frames[2],{x=v.x,y=v.y,tile_inv,lookup_color(shop_def,v.x,v.y,stage)})
end end
for frame_id,frame in ipairs(frames) do for frame_id,frame in ipairs(frames) do

@ -105,13 +105,15 @@ function registerSidebar(shop_name,callback)
dfhack.onStateChange.eventful=unregall dfhack.onStateChange.eventful=unregall
else else
local function drawSidebar( wshop ) local function drawSidebar( wshop )
local valid_focus="dwarfmode/QueryBuilding/Some" local valid_focus="dwarfmode/QueryBuilding"
local another_overlay="dfhack/lua/WorkshopOverlay"
if wshop:getMaxBuildStage()==wshop:getBuildStage() then if wshop:getMaxBuildStage()==wshop:getBuildStage() then
local sidebar=callback{workshop=wshop} local sidebar=callback{workshop=wshop}
if string.sub(dfhack.gui.getCurFocus(),1,#valid_focus)==valid_focus then if string.sub(dfhack.gui.getCurFocus(true),1,#another_overlay)==another_overlay then
sidebar:show() dfhack.screen.dismiss(dfhack.gui.getCurViewscreen(true))
else end
sidebar:show(dfhack.gui.getCurViewscreen(true).parent) if string.sub(dfhack.gui.getCurFocus(true),1,#valid_focus)==valid_focus then
sidebar:show(dfhack.gui.getCurViewscreen(true))
end end
end end
end end

@ -36,7 +36,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"petcapRemover", "petcapRemover",
"Removes the pet population cap by causing pregnancies.", "Remove the pet population cap by causing pregnancies.",
petcapRemover, petcapRemover,
false, //allow non-interactive use false, //allow non-interactive use
"petcapRemover\n" "petcapRemover\n"

@ -298,7 +298,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
{ {
commands.push_back( commands.push_back(
PluginCommand( PluginCommand(
"resume", "A plugin to help display and resume suspended constructions conveniently", "resume", "Display and easily resume suspended constructions",
resume_cmd, false, resume_cmd, false,
"resume show\n" "resume show\n"
" Show overlay when paused:\n" " Show overlay when paused:\n"

@ -77,7 +77,7 @@ command_result nopause(color_ostream &out, vector<string> & params);
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("reveal","Reveal the map. 'reveal hell' will also reveal hell. 'reveal demon' won't pause.",reveal,false, commands.push_back(PluginCommand("reveal","Reveal the map.",reveal,false,
"Reveals the map, by default ignoring hell.\n" "Reveals the map, by default ignoring hell.\n"
"Options:\n" "Options:\n"
"hell - also reveal hell, while forcing the game to pause.\n" "hell - also reveal hell, while forcing the game to pause.\n"
@ -86,12 +86,12 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCom
"Reverts the previous reveal operation, hiding the map again.\n")); "Reverts the previous reveal operation, hiding the map again.\n"));
commands.push_back(PluginCommand("revtoggle","Reveal/unreveal depending on state.",revtoggle,false, commands.push_back(PluginCommand("revtoggle","Reveal/unreveal depending on state.",revtoggle,false,
"Toggles between reveal and unreveal.\n")); "Toggles between reveal and unreveal.\n"));
commands.push_back(PluginCommand("revflood","Hide all, reveal all tiles reachable from cursor position.",revflood,false, commands.push_back(PluginCommand("revflood","Hide all, and reveal tiles reachable from the cursor.",revflood,false,
"This command hides the whole map. Then, starting from the cursor,\n" "This command hides the whole map. Then, starting from the cursor,\n"
"reveals all accessible tiles. Allows repairing parma-revealed maps.\n")); "reveals all accessible tiles. Allows repairing parma-revealed maps.\n"));
commands.push_back(PluginCommand("revforget", "Forget the current reveal data, allowing to use reveal again.",revforget,false, commands.push_back(PluginCommand("revforget", "Forget the current reveal data.",revforget,false,
"Forget the current reveal data, allowing to use reveal again.\n")); "Forget the current reveal data, allowing to use reveal again.\n"));
commands.push_back(PluginCommand("nopause","Disable pausing (doesn't affect pause forced by reveal).",nopause,false, commands.push_back(PluginCommand("nopause","Disable manual and automatic pausing.",nopause,false,
"Disable pausing (doesn't affect pause forced by reveal).\n" "Disable pausing (doesn't affect pause forced by reveal).\n"
"Activate with 'nopause 1', deactivate with 'nopause 0'.\n")); "Activate with 'nopause 1', deactivate with 'nopause 0'.\n"));
return CR_OK; return CR_OK;

@ -99,7 +99,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
df_rubyeval)); df_rubyeval));
commands.push_back(PluginCommand("rb", commands.push_back(PluginCommand("rb",
"Ruby interpreter. Eval() a ruby string (alias for rb_eval).", "Ruby interpreter. Eval() a ruby string.",
df_rubyeval)); df_rubyeval));
return CR_OK; return CR_OK;

@ -254,7 +254,7 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
DFhackCExport command_result plugin_init(color_ostream &out, vector<PluginCommand>& commands) DFhackCExport command_result plugin_init(color_ostream &out, vector<PluginCommand>& commands)
{ {
commands.push_back(PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch)); commands.push_back(PluginCommand("seedwatch", "Toggles seed cooking based on quantity available", df_seedwatch));
// fill in the abbreviations map, with abbreviations for the standard plants // fill in the abbreviations map, with abbreviations for the standard plants
abbreviations["bs"] = "SLIVER_BARB"; abbreviations["bs"] = "SLIVER_BARB";
abbreviations["bt"] = "TUBER_BLOATED"; abbreviations["bt"] = "TUBER_BLOATED";

@ -29,7 +29,7 @@ REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(ui); REQUIRE_GLOBAL(ui);
bool fast = false; bool fast = false;
const char *tagline = "Allows the fortress bookkeeper to queue jobs through the manager."; const char *tagline = "Allow the bookkeeper to queue manager jobs.";
const char *usage = ( const char *usage = (
" stockflow enable\n" " stockflow enable\n"
" Enable the plugin.\n" " Enable the plugin.\n"

@ -85,7 +85,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
); );
commands.push_back ( commands.push_back (
PluginCommand ( PluginCommand (
"loadstock", "Load settings from a file and apply them to the active stockpile.", "loadstock", "Load and apply stockpile settings from a file.",
loadstock, loadstock_guard, loadstock, loadstock_guard,
"Must be in 'q' mode and have a stockpile selected.\n" "Must be in 'q' mode and have a stockpile selected.\n"
"example: 'loadstock food.dfstock' will load the settings from 'food.dfstock'\n" "example: 'loadstock food.dfstock' will load the settings from 'food.dfstock'\n"

@ -1 +1 @@
Subproject commit 571938a34669503a9dc068dc62cce40b7c6594ba Subproject commit bd6e8f9f90af1586f5b1eb0003d7e0e133acecc8

@ -1316,7 +1316,7 @@ command_result df_strangemood (color_ostream &out, vector <string> & parameters)
DFhackCExport command_result plugin_init (color_ostream &out, std::vector<PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector<PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("strangemood", "Force a strange mood to happen.\n", df_strangemood, false, commands.push_back(PluginCommand("strangemood", "Force a strange mood to happen.", df_strangemood, false,
"Options:\n" "Options:\n"
" -force - Ignore standard mood preconditions.\n" " -force - Ignore standard mood preconditions.\n"
" -unit - Use the selected unit instead of picking one randomly.\n" " -unit - Use the selected unit instead of picking one randomly.\n"

@ -58,9 +58,9 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
{ {
tiletypes_hist.load("tiletypes.history"); tiletypes_hist.load("tiletypes.history");
commands.push_back(PluginCommand("tiletypes", "Paint map tiles freely, similar to liquids.", df_tiletypes, true)); commands.push_back(PluginCommand("tiletypes", "Paint map tiles freely, similar to liquids.", df_tiletypes, true));
commands.push_back(PluginCommand("tiletypes-command", "Run the given commands (seperated by ' ; '; an empty command is the same as run).", df_tiletypes_command)); commands.push_back(PluginCommand("tiletypes-command", "Run tiletypes commands (seperated by ' ; ')", df_tiletypes_command));
commands.push_back(PluginCommand("tiletypes-here", "Use the last settings from tiletypes, including brush, at cursor location.", df_tiletypes_here)); commands.push_back(PluginCommand("tiletypes-here", "Repeat tiletypes command at cursor (with brush)", df_tiletypes_here));
commands.push_back(PluginCommand("tiletypes-here-point", "Use the last settings from tiletypes, not including brush, at cursor location.", df_tiletypes_here_point)); commands.push_back(PluginCommand("tiletypes-here-point", "Repeat tiletypes command at cursor (without brush)", df_tiletypes_here_point));
return CR_OK; return CR_OK;
} }

@ -259,14 +259,15 @@ static bool can_trade()
for (auto it = df::global::ui->caravans.begin(); it != df::global::ui->caravans.end(); it++) for (auto it = df::global::ui->caravans.begin(); it != df::global::ui->caravans.end(); it++)
{ {
typedef df::caravan_state::T_trade_state state;
auto caravan = *it; auto caravan = *it;
auto trade_state = caravan->trade_state; auto trade_state = caravan->trade_state;
auto time_remaining = caravan->time_remaining; auto time_remaining = caravan->time_remaining;
if ((trade_state != 1 && trade_state != 2) || time_remaining == 0) if ((trade_state == state::Approaching || trade_state == state::AtDepot) && time_remaining != 0)
return false; return true;
} }
return true; return false;
} }
static bool is_metal_item(df::item *item) static bool is_metal_item(df::item *item)

@ -29,7 +29,7 @@ DFhackCExport command_result plugin_init(color_ostream& out, std::vector<PluginC
if (!process_jobs || !process_dig) if (!process_jobs || !process_dig)
return CR_FAILURE; return CR_FAILURE;
commands.push_back(PluginCommand("workNow", "makes dwarves look for jobs whever they finish one, or every time you pause", workNow, false, "When workNow is active, every time the game pauses, DF will make dwarves perform any appropriate available jobs. This includes when you one step through the game using the pause menu. When workNow is in mode 2, it will make dwarves look for jobs every time a job completes.\n" commands.push_back(PluginCommand("workNow", "Don't allow dwarves to idle if any jobs are available", workNow, false, "When workNow is active, every time the game pauses, DF will make dwarves perform any appropriate available jobs. This includes when you one step through the game using the pause menu. When workNow is in mode 2, it will make dwarves look for jobs every time a job completes.\n"
"workNow\n" "workNow\n"
" print workNow status\n" " print workNow status\n"
"workNow 0\n" "workNow 0\n"

@ -1,4 +1,4 @@
# View or set level of cavern adaptation for the selected unit or the whole fort # View or set cavern adaptation levels
# based on removebadthoughts.rb # based on removebadthoughts.rb
=begin =begin

@ -1,7 +1,4 @@
-- Adjust all attributes, personality, age and skills of all dwarves in play -- Adjust all attributes of all dwarves to an ideal
-- without arguments, all attributes, age & personalities are adjusted
-- arguments allow for skills to be adjusted as well
-- WARNING: USING THIS SCRIPT WILL ADJUST ALL DWARVES IN PLAY!
-- by vjek -- by vjek
--[[=begin --[[=begin
@ -12,6 +9,9 @@ Runs the equivalent of `rejuvenate`, `elevate-physical`, `elevate-mental`, and
which sets every stat to an ideal - legendary skills, great traits, and which sets every stat to an ideal - legendary skills, great traits, and
easy-to-satisfy preferences. easy-to-satisfy preferences.
Without arguments, all attributes, age & personalities are adjusted.
Arguments allow for skills to be adjusted as well.
=end]] =end]]
function rejuvenate(unit) function rejuvenate(unit)
if unit==nil then if unit==nil then

@ -1,4 +1,4 @@
# Select crops to plant based on current stocks
=begin =begin
autofarm autofarm

@ -1,10 +1,14 @@
-- Executes an autolabor command for each labor where skill level influences output quality. -- Run an autolabor command for skill-affected labors.
--[[=begin --[[=begin
autolabor-artisans autolabor-artisans
================== ==================
Runs `autolabor`, with settings tuned for small but highly skilled workforces. Runs an `autolabor` command, for all labors where skill level
influences output quality. Examples::
autolabor-artisans 0 2 3
autolabor-artisans disable
=end]] =end]]
local artisan_labors = { local artisan_labors = {

@ -1,4 +1,4 @@
-- This script will brainwash a dwarf, modifying their personality -- Brainwash a dwarf, modifying their personality
-- usage is: target a unit in DF, and execute this script in dfhack -- usage is: target a unit in DF, and execute this script in dfhack
-- by vjek -- by vjek
--[[=begin --[[=begin

@ -1,4 +1,4 @@
# Make food and plants decay, and vanish after a few months # Food and plants decay, and vanish after a few months
=begin =begin
deterioratefood deterioratefood

@ -1,4 +1,4 @@
--all-bob.lua -- Changes the first name of all units to "Bob"
--author expwnent --author expwnent
-- --
--[[=begin --[[=begin

@ -1,4 +1,4 @@
-- Injects new reaction, item and building defs into the world. -- Inject new raw definitions into the world
--[[=begin --[[=begin
devel/inject-raws devel/inject-raws
@ -9,6 +9,8 @@ This script attempts to inject new raw objects into your
world. If the injected references do not match the actual world. If the injected references do not match the actual
edited raws, your save will refuse to load, or load but crash. edited raws, your save will refuse to load, or load but crash.
This script can handle reaction, item and building definitions.
The savegame contains a list of the relevant definition tokens in The savegame contains a list of the relevant definition tokens in
the right order, but all details are read from raws every time. the right order, but all details are read from raws every time.
This allows just adding stub definitions, and simply saving and This allows just adding stub definitions, and simply saving and

@ -1,4 +1,4 @@
-- Read the tiles from the screen and display info about them. -- Read from the screen and display info about the tiles
--[[=begin --[[=begin
devel/inspect-screen devel/inspect-screen

@ -1,4 +1,4 @@
-- List input items for the building currently being built. -- List input items for the building being built.
--[[=begin --[[=begin
devel/list-filters devel/list-filters

@ -1,4 +1,4 @@
-- Deletes ALL items not held by units, buildings or jobs. -- Delete ALL items not held by units, buildings or jobs
--[[=begin --[[=begin
devel/nuke-items devel/nuke-items

@ -1,4 +1,4 @@
-- Prepare the current save for use with devel/find-offsets. -- Prepare the current save for devel/find-offsets
--[[=begin --[[=begin
devel/prepare-save devel/prepare-save

@ -1,4 +1,4 @@
# list indices in world.item.other[] where current selected item appears # list selected item's indices in world.item.other[]
=begin =begin
devel/scanitemother devel/scanitemother

@ -1,4 +1,4 @@
# setup stuff to allow arena creature spawn after a mode change # Allow arena creature spawn after a mode change
df.world.arena_spawn.race.clear df.world.arena_spawn.race.clear
df.world.arena_spawn.caste.clear df.world.arena_spawn.caste.clear

@ -1,4 +1,4 @@
-- Generates an image using multiple octaves of perlin noise. -- Generates an image using perlin noise
--[[=begin --[[=begin
devel/test-perlin devel/test-perlin

@ -1,4 +1,4 @@
# designate an area for digging according to a plan in csv format # designate an area based on a '.csv' plan
=begin =begin
digfort digfort

@ -1,4 +1,4 @@
-- This script will elevate all the mental attributes of a unit -- Elevate all the mental attributes of a unit
-- by vjek -- by vjek
--[[=begin --[[=begin

@ -1,4 +1,4 @@
-- This script will elevate all the physical attributes of a unit -- Elevate all the physical attributes of a unit
-- by vjek -- by vjek
--[[=begin --[[=begin

@ -1,6 +1,5 @@
--makes it so that civs won't come with barrels full of blood, ichor, or goo -- Stop traders bringing blood, ichor, or goo
--author Urist Da Vinci --author Urist Da Vinci; edited by expwnent, scamtank
--edited by expwnent, scamtank
--[[=begin --[[=begin
fix/blood-del fix/blood-del

@ -1,4 +1,4 @@
# script to fix loyalty cascade, when you order your militia to kill friendly units # Cancels a 'loyalty cascade' when citizens are killed
=begin =begin
fix/loyaltycascade fix/loyaltycascade

@ -1,4 +1,4 @@
-- Communicates current population to mountainhomes to avoid cap overshooting. -- Tells mountainhomes your pop. to avoid overshoot
--[[=begin --[[=begin

@ -1,7 +1,5 @@
-- scripts/forum-dwarves.lua -- Save a copy of a text screen for the DF forums
-- Save a copy of a text screen for the DF forums. Use 'forumdwarves help' for more details. -- original author: Caldfir; edited by expwnent, Mchl
-- original author: Caldfir
-- edited by expwnent, Mchl
--[[=begin --[[=begin
forum-dwarves forum-dwarves

@ -1,4 +1,4 @@
--full-heal.lua -- Attempts to fully heal the selected unit
--author Kurik Amudnil, Urist DaVinci --author Kurik Amudnil, Urist DaVinci
--edited by expwnent --edited by expwnent

@ -1,4 +1,4 @@
local utils = require('utils') -- Shows the sexual orientation of units
--[[=begin --[[=begin
gaydar gaydar
@ -8,6 +8,7 @@ the viability of livestock breeding programs. Use ``gaydar -help`` for informat
on available filters for orientation, citizenship, species, etc. on available filters for orientation, citizenship, species, etc.
=end]] =end]]
local utils = require('utils')
validArgs = utils.invert({ validArgs = utils.invert({
'all', 'all',

@ -1,4 +1,4 @@
# grow crops in farm plots. ex: growcrops helmet_plump 20 # Instantly grow crops in farm plots
=begin =begin
growcrops growcrops

@ -1,4 +1,4 @@
--Does something with items in adventure mode jobs
--[[=begin --[[=begin
gui/advfort_items gui/advfort_items

@ -1,5 +1,4 @@
-- Assign weapon racks to squads. Requires the weaponrack-unassign patch. -- Assign weapon racks to squads (needs binpatch)
--[[=begin --[[=begin
gui/assign-rack gui/assign-rack

@ -1,4 +1,4 @@
-- Rewrite individual choice weapons into specific types. -- Rewrite individual choice weapons to specific types
--[[=begin --[[=begin
gui/choose-weapons gui/choose-weapons

@ -1,4 +1,4 @@
-- Clone the current uniform template in the military screen. -- Clone a uniform template in the military screen
--[[=begin --[[=begin
gui/clone-uniform gui/clone-uniform

@ -1,4 +1,4 @@
-- Issue orders to companions in Adventure mode
--[[=begin --[[=begin
gui/companion-order gui/companion-order

@ -25,9 +25,20 @@ local widgets =require 'gui.widgets'
local guiScript = require 'gui.script' local guiScript = require 'gui.script'
local args={...} local args={...}
find_funcs = find_funcs or (function()
local t = {}
for k in pairs(df) do
pcall(function()
t[k] = df[k].find
end)
end
return t
end)()
local keybindings={ local keybindings={
offset={key="CUSTOM_ALT_O",desc="Show current items offset"}, offset={key="CUSTOM_ALT_O",desc="Show current items offset"},
find={key="CUSTOM_F",desc="Find a value by entering a predicate"}, find={key="CUSTOM_F",desc="Find a value by entering a predicate"},
find_id={key="CUSTOM_I",desc="Find object with this ID"},
lua_set={key="CUSTOM_ALT_S",desc="Set by using a lua function"}, lua_set={key="CUSTOM_ALT_S",desc="Set by using a lua function"},
insert={key="CUSTOM_ALT_I",desc="Insert a new value to the vector"}, insert={key="CUSTOM_ALT_I",desc="Insert a new value to the vector"},
delete={key="CUSTOM_ALT_D",desc="Delete selected entry"}, delete={key="CUSTOM_ALT_D",desc="Delete selected entry"},
@ -62,6 +73,24 @@ function getTargetFromScreens()
end end
return my_trg return my_trg
end end
function search_relevance(search, candidate)
local function clean(str)
return ' ' .. str:lower():gsub('[^a-z0-9]','') .. ' '
end
search = clean(search)
candidate = clean(candidate)
local ret = 0
while #search > 0 do
local pos = candidate:find(search:sub(1, 1), 1, true)
if pos then
ret = ret + (#search - pos)
candidate = candidate:sub(pos + 1)
end
search = search:sub(2)
end
return ret
end
GmEditorUi = defclass(GmEditorUi, gui.FramedScreen) GmEditorUi = defclass(GmEditorUi, gui.FramedScreen)
GmEditorUi.ATTRS={ GmEditorUi.ATTRS={
@ -135,7 +164,7 @@ function GmEditorUi:find(test)
local e,what=load("return function(k,v) return "..test.." end") local e,what=load("return function(k,v) return "..test.." end")
if e==nil then if e==nil then
dialog.showMessage("Error!","function failed to compile\n"..what,COLOR_RED) dialog.showMessage("Error!","function failed to compile\n"..what,COLOR_LIGHTRED)
end end
if trg.target and trg.target._kind and trg.target._kind=="container" then if trg.target and trg.target._kind and trg.target._kind=="container" then
@ -157,6 +186,29 @@ function GmEditorUi:find(test)
end end
end end
end end
function GmEditorUi:find_id()
local key = self:getSelectedKey()
local id = tonumber(self:getSelectedValue())
if not id then return end
local opts = {}
for name, func in pairs(find_funcs) do
table.insert(opts, {text=name, callback=func, weight=search_relevance(key, name)})
end
table.sort(opts, function(a, b)
return a.weight > b.weight
end)
guiScript.start(function()
local ret,idx,choice=guiScript.showListPrompt("Choose type:",nil,3,opts,nil,true)
if ret then
local obj = choice.callback(id)
if obj then
self:pushTarget(obj)
else
dialog.showMessage("Error!", ('%s with ID %d not found'):format(choice.text, id), COLOR_LIGHTRED)
end
end
end)
end
function GmEditorUi:insertNew(typename) function GmEditorUi:insertNew(typename)
local tp=typename local tp=typename
if typename== nil then if typename== nil then
@ -165,7 +217,7 @@ function GmEditorUi:insertNew(typename)
end end
local ntype=df[tp] local ntype=df[tp]
if ntype== nil then if ntype== nil then
dialog.showMessage("Error!","Type '"..tp.." not found",COLOR_RED) dialog.showMessage("Error!","Type '"..tp.." not found",COLOR_LIGHTRED)
return return
end end
@ -187,6 +239,9 @@ end
function GmEditorUi:getSelectedKey() function GmEditorUi:getSelectedKey()
return self:currentTarget().keys[self.subviews.list_main:getSelected()] return self:currentTarget().keys[self.subviews.list_main:getSelected()]
end end
function GmEditorUi:getSelectedValue()
return self:currentTarget().target[self:getSelectedKey()]
end
function GmEditorUi:currentTarget() function GmEditorUi:currentTarget()
return self.stack[#self.stack] return self.stack[#self.stack]
end end
@ -298,7 +353,7 @@ function GmEditorUi:set(key,input)
end end
local e,what=load("return function(v) return "..input.." end") local e,what=load("return function(v) return "..input.." end")
if e==nil then if e==nil then
dialog.showMessage("Error!","function failed to compile\n"..what,COLOR_RED) dialog.showMessage("Error!","function failed to compile\n"..what,COLOR_LIGHTRED)
return return
end end
trg.target[key]=e()(trg) trg.target[key]=e()(trg)
@ -331,6 +386,8 @@ function GmEditorUi:onInput(keys)
self:openOffseted(self.subviews.list_main:getSelected()) self:openOffseted(self.subviews.list_main:getSelected())
elseif keys[keybindings.find.key] then elseif keys[keybindings.find.key] then
self:find() self:find()
elseif keys[keybindings.find_id.key] then
self:find_id()
elseif keys[keybindings.lua_set.key] then elseif keys[keybindings.lua_set.key] then
self:set(self:getSelectedKey()) self:set(self:getSelectedKey())
elseif keys[keybindings.insert.key] then --insert elseif keys[keybindings.insert.key] then --insert

@ -1,4 +1,4 @@
-- Interface powered (somewhat user friendly) unit editor. -- Interface powered, user friendly, unit editor
--[[=begin --[[=begin

@ -1,4 +1,4 @@
-- Show and manipulate the path used by Guide Cart orders. -- Show/change the path used by Guide Cart orders
--[[=begin --[[=begin
gui/guide-path gui/guide-path

@ -5,27 +5,81 @@ gui/prerelease-warning
====================== ======================
Shows a warning on world load for pre-release builds. Shows a warning on world load for pre-release builds.
With no arguments passed, the warning is shown unless the "do not show again"
option has been selected. With the ``force`` argument, the warning is always
shown.
=end]] =end]]
shown = shown or false local gui = require 'gui'
if shown then return end local dlg = require 'gui.dialogs'
if not dfhack.isPrerelease() then qerror('not a prerelease build') end local json = require 'json'
local utils = require 'utils'
local force = ({...})[1] == 'force'
local config = json.open('dfhack-config/prerelease-warning.json')
if config.data.hide and not force then
return
end
if not dfhack.isPrerelease() and not force then
qerror('not a prerelease build')
end
-- Don't fire during worldgen -- Don't fire during worldgen
if dfhack.internal.getAddress('gametype') and df.global.gametype == df.game_type.NONE then if dfhack.internal.getAddress('gametype') and df.global.gametype == df.game_type.NONE and not force then
return return
end end
local gui = require 'gui' local state = dfhack.getDFHackRelease():lower():match('[a-z]+')
local dlg = require 'gui.dialogs' if not utils.invert{'alpha', 'beta', 'rc', 'r'}[state] then
local utils = require 'utils' dfhack.printerr('warning: unknown release state: ' .. state)
state = 'unknown'
end
message = { message = ({
'This is a prerelease build of DFHack. Some structures are likely', NEWLINE, alpha = {
'Warning',
COLOR_YELLOW,
'This is an alpha build of DFHack. Some structures are likely', NEWLINE,
'to be incorrect, resulting in crashes or save corruption', NEWLINE, 'to be incorrect, resulting in crashes or save corruption', NEWLINE,
{pen=COLOR_LIGHTRED, text='Make backups of your saves often!'}, {pen=COLOR_LIGHTRED, text='Make backups of your saves often!'}
},
beta = {
'Warning',
COLOR_YELLOW,
'This is a beta release of DFHack. It is more stable than an', NEWLINE,
'alpha release, but bugs are still possible, possibly including', NEWLINE,
'crashes and save corruption.', NEWLINE,
'Make backups of your saves beforehand to be safe.'
},
rc = {
'Notice',
COLOR_YELLOW,
'This is a DFHack release candidate. It is fairly stable but', NEWLINE,
'likely contains newer features that are not fully-tested.', NEWLINE,
'Crashes are unlikely, but always make backups of your saves', NEWLINE,
'to be safe.'
},
r = {
'Error',
COLOR_LIGHTRED,
'This release is flagged as a prerelease but named as a', NEWLINE,
'stable release.', NEWLINE,
{pen=COLOR_LIGHTMAGENTA, text='Please report this to the DFHack team or a pack maintainer.'}
},
unknown = {
'Error',
COLOR_LIGHTMAGENTA,
'Unknown prerelease DFHack build. This should never happen!', NEWLINE,
'Please report this to the DFHack team or a pack maintainer.'
} }
})[state]
title = table.remove(message, 1)
color = table.remove(message, 1)
pack_message = pack_message or [[ pack_message = [[
This should not be enabled by default in a pack. This should not be enabled by default in a pack.
If you are seeing this message and did not enable/install DFHack If you are seeing this message and did not enable/install DFHack
@ -37,7 +91,6 @@ if #pack_message > 0 and (path:find('lnp') or path:find('starter') or path:find(
table.insert(message, NEWLINE) table.insert(message, NEWLINE)
table.insert(message, {text=v, pen=COLOR_LIGHTMAGENTA}) table.insert(message, {text=v, pen=COLOR_LIGHTMAGENTA})
end end
pack_message = ''
end end
dfhack.print('\n') dfhack.print('\n')
@ -47,7 +100,7 @@ for k,v in ipairs(message) do
dfhack.color(v.pen) dfhack.color(v.pen)
dfhack.print(v.text) dfhack.print(v.text)
else else
dfhack.color(COLOR_YELLOW) dfhack.color(color)
dfhack.print(v) dfhack.print(v)
end end
end end
@ -55,5 +108,34 @@ end
dfhack.color(COLOR_RESET) dfhack.color(COLOR_RESET)
dfhack.print('\n\n') dfhack.print('\n\n')
dlg.showMessage('Warning', message, COLOR_YELLOW) WarningBox = defclass(nil, dlg.MessageBox)
shown = true
function WarningBox:getWantedFrameSize()
local w, h = WarningBox.super.getWantedFrameSize(self)
return w, h + 2
end
function WarningBox:onRenderFrame(dc,rect)
WarningBox.super.onRenderFrame(self,dc,rect)
dc:pen(COLOR_WHITE):key_pen(COLOR_LIGHTRED)
:seek(rect.x1 + 2, rect.y2 - 2)
:key('CUSTOM_D'):string(': Do not show again')
:advance(10)
:key('LEAVESCREEN'):string('/')
:key('SELECT'):string(': Dismiss')
end
function WarningBox:onInput(keys)
if keys.CUSTOM_D then
config.data.hide = true
config:write()
keys.LEAVESCREEN = true
end
WarningBox.super.onInput(self, keys)
end
WarningBox{
frame_title = title,
text = message,
text_pen = color
}:show()

@ -1,4 +1,4 @@
-- Creates a pit under the target leading straight to the Underworld. Type '?' for help. -- Creates a pit to the Underworld under the target
-- Based on script by IndigoFenix, @ https://gist.github.com/IndigoFenix/8776696 -- Based on script by IndigoFenix, @ https://gist.github.com/IndigoFenix/8776696
--[[=begin --[[=begin

@ -1,5 +1,4 @@
-- This script will modify a skill or the skills of a single unit -- Make a skill or skills of a unit Legendary +5
-- the skill will be increased to 20 (Legendary +5)
-- by vjek -- by vjek
--[[=begin --[[=begin

@ -1,4 +1,4 @@
-- Save a copy of a text screen in markdown (for reddit among others). Use 'markdown help' for more details. -- Save a text screen in markdown (eg for reddit)
-- This is a derivatiwe work based upon scripts/forum-dwarves.lua by Caldfir and expwnent -- This is a derivatiwe work based upon scripts/forum-dwarves.lua by Caldfir and expwnent
-- Adapted for markdown by Mchl https://github.com/Mchl -- Adapted for markdown by Mchl https://github.com/Mchl
--[[=begin --[[=begin

@ -1,4 +1,4 @@
-- Force a migrant wave (only works after hardcoded waves) -- Force a migrant wave (only after hardcoded waves)
--[[=begin --[[=begin
migrants-now migrants-now

@ -1,4 +1,4 @@
--modtools/add-syndrome.lua -- Add or remove syndromes from units
--author expwnent --author expwnent
--[[=begin --[[=begin

@ -1,6 +1,5 @@
--scripts/modtools/anonymous-script.lua -- invoke simple lua scripts from strings
--author expwnent --author expwnent
--a tool for invoking simple lua scripts without putting them in a file first
--[[=begin --[[=begin
modtools/anonymous-script modtools/anonymous-script

@ -1,6 +1,5 @@
--scripts/modtools/create-item.lua
--author expwnent
-- creates an item of a given type and material -- creates an item of a given type and material
--author expwnent
--[[=begin --[[=begin
modtools/create-item modtools/create-item

@ -1,4 +1,4 @@
-- create-unit.lua -- Creates a unit. Beta; use at own risk.
-- Originally created by warmist, edited by Putnam for the dragon ball mod to be used in reactions, modified by Dirst for use in The Earth Strikes Back mod, incorporating fixes discovered by Boltgun then Mifiki wrote the bit where it switches to arena mode briefly to do some of the messy work, then Expwnent combined that with the old script to make it function for histfigs -- Originally created by warmist, edited by Putnam for the dragon ball mod to be used in reactions, modified by Dirst for use in The Earth Strikes Back mod, incorporating fixes discovered by Boltgun then Mifiki wrote the bit where it switches to arena mode briefly to do some of the messy work, then Expwnent combined that with the old script to make it function for histfigs
-- version 0.51 -- version 0.51
-- This is a beta version. Use at your own risk. -- This is a beta version. Use at your own risk.

@ -1,4 +1,3 @@
-- modtools/equip-item.lua
-- equip an item on a unit with a particular body part -- equip an item on a unit with a particular body part
--[[=begin --[[=begin

Some files were not shown because too many files have changed in this diff Show More