-
+
This plugin makes reactions with names starting with SPATTER_ADD_
produce contaminants on the items instead of improvements. The produced
contaminants are immune to being washed away by water or destroyed by
diff --git a/Readme.rst b/Readme.rst
index dbf04f9e8..7d715077a 100644
--- a/Readme.rst
+++ b/Readme.rst
@@ -144,6 +144,16 @@ system console:
The patches are expected to be encoded in text format used by IDA.
+
+Live patching
+-------------
+
+As an alternative, you can use the ``binpatch`` dfhack command to apply/remove
+patches live in memory during a DF session.
+
+In this case, updating symbols.xml is not necessary.
+
+
=============================
Something doesn't work, help!
=============================
@@ -1077,6 +1087,9 @@ Subcommands that persist until disabled or DF quit:
:patrol-duty: Makes Train orders not count as patrol duty to stop unhappy thoughts.
Does NOT fix the problem when soldiers go off-duty (i.e. civilian).
:readable-build-plate: Fixes rendering of creature weight limits in pressure plate build menu.
+
+ .. image:: images/tweak-plate.png
+
:stable-temp: Fixes performance bug 6012 by squashing jitter in temperature updates.
In very item-heavy forts with big stockpiles this can improve FPS by 50-100%
:fast-heat: Further improves temperature update performance by ensuring that 1 degree
@@ -1095,9 +1108,16 @@ Subcommands that persist until disabled or DF quit:
:military-stable-assign: Preserve list order and cursor position when assigning to squad,
i.e. stop the rightmost list of the Positions page of the military
screen from constantly resetting to the top.
-:military-color-assigned: Color squad candidates already assigned to other squads in brown/green
+:military-color-assigned: Color squad candidates already assigned to other squads in yellow/green
to make them stand out more in the list.
+ .. image:: images/tweak-mil-color.png
+
+:military-training: Speeds up melee squad training by removing an almost certainly
+ unintended inverse dependency of training speed on unit count
+ (i.e. the more units you have, the slower it becomes), and making
+ the units spar more.
+
fix-armory
----------
@@ -1946,6 +1966,41 @@ embark
======
Allows to embark anywhere. Currently windows only.
+lever
+=====
+Allow manipulation of in-game levers from the dfhack console.
+
+Can list levers, including state and links, with::
+
+ lever list
+
+To queue a job so that a dwarf will pull the lever 42, use ``lever pull 42``.
+This is the same as 'q'uerying the building and queue a 'P'ull request.
+
+To magically toggle the lever immediately, use::
+
+ lever pull 42 --now
+
+stripcaged
+==========
+For dumping items inside cages. Will mark selected items for dumping, then
+a dwarf may come and actually dump it. See also ``autodump``.
+
+With the ``items`` argument, only dumps items laying in the cage, excluding
+stuff worn by caged creatures. ``weapons`` will dump worn weapons, ``armor``
+will dump everything worn by caged creatures (including armor and clothing),
+and ``all`` will dump everything, on a creature or not.
+
+``stripcaged list`` will display on the dfhack console the list of all cages
+and their item content.
+
+Without further arguments, all commands work on all cages and animal traps on
+the map. With the ``here`` argument, considers only the in-game selected cage
+(or the cage under the game cursor). To target only specific cages, you can
+alternatively pass cage IDs as arguments::
+
+ stripcaged weapons 25321 34228
+
=======================
In-game interface tools
=======================
@@ -1958,6 +2013,9 @@ are mostly implemented by lua scripts.
In order to avoid user confusion, as a matter of policy all these tools
display the word "DFHack" on the screen somewhere while active.
+ 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.
+
As an exception, the tweak plugin described above does not follow this
guideline because it arguably just fixes small usability bugs in the game UI.
@@ -1968,12 +2026,18 @@ Dwarf Manipulator
Implemented by the manipulator plugin. To activate, open the unit screen and
press 'l'.
+.. image:: images/manipulator.png
+
This tool implements a Dwarf Therapist-like interface within the game UI. The
far left column displays the unit's Happiness (color-coded based on its
value), and the right half of the screen displays each dwarf's labor settings
and skill levels (0-9 for Dabbling thru Professional, A-E for Great thru Grand
-Master, and U-Z for Legendary thru Legendary+5). Cells with red backgrounds
-denote skills not controlled by labors.
+Master, and U-Z for Legendary thru Legendary+5).
+
+Cells with teal backgrounds denote skills not controlled by labors, e.g.
+military and social skills.
+
+.. image:: images/manipulator2.png
Use the arrow keys or number pad to move the cursor around, holding Shift to
move 10 tiles at a time.
@@ -2012,6 +2076,8 @@ Search
The search plugin adds search to the Stocks, Trading and Unit List screens.
+.. image:: images/search.png
+
Searching works the same way as the search option in "Move to Depot" does.
You will see the Search option displayed on screen with a hotkey (usually 's').
Pressing it lets you start typing a query and the relevant list will start
@@ -2032,10 +2098,48 @@ Value numbers displayed by the screen. Because of this, pressing the 't'
key while search is active clears the search instead of executing the trade.
+AutoMaterial
+============
+
+The automaterial plugin 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.
+
+Firstly, it moves the last used material for a given construction type to the top of
+the list, if there are any left. So if you build a wall with chalk blocks, the next
+time you place a wall the chalk blocks will be at the top of the list, regardless of
+distance (it only does this in "grouped" mode, as individual item lists could be huge).
+This should mean you can place most constructions without having to search for your
+preferred material type.
+
+.. image:: images/automaterial-mat.png
+
+Pressing 'a' while highlighting any material will enable that material for "auto select"
+for this construction type. You can enable multiple materials as autoselect. Now the next
+time you place this type of construction, the plugin will automatically choose materials
+for you from the kinds you enabled. If there is enough to satisfy the whole placement,
+you won't be prompted with the material screen - the construction will be placed and you
+will be back in the construction menu as if you did it manually.
+
+When choosing the construction placement, you will see a couple of options:
+
+.. image:: images/automaterial-pos.png
+
+Use 'a' here to temporarily disable the material autoselection, e.g. if you need
+to go to the material selection screen so you can toggle some materials on or off.
+
+The other option (auto type selection, off by default) can be toggled on with 't'. If you
+toggle this option on, instead of returning you to the main construction menu after selecting
+materials, it returns you back to this screen. If you use this along with several autoselect
+enabled materials, you should be able to place complex constructions more conveniently.
+
+
gui/liquids
===========
-To use, bind to a key and activate in the 'k' mode.
+To use, bind to a key (the example config uses Alt-L) and activate in the 'k' mode.
+
+.. image:: images/liquids.png
While active, use the suggested keys to switch the usual liquids parameters, and Enter
to select the target area and apply changes.
@@ -2044,7 +2148,9 @@ to select the target area and apply changes.
gui/mechanisms
==============
-To use, bind to a key and activate in the 'q' mode.
+To use, bind to a key (the example config uses Ctrl-M) and activate in the 'q' mode.
+
+.. image:: images/mechanisms.png
Lists mechanisms connected to the building, and their links. Navigating the list centers
the view on the relevant linked buildings.
@@ -2062,21 +2168,35 @@ via a simple dialog in the game ui.
* ``gui/rename [building]`` in 'q' mode changes the name of a building.
+ .. image:: images/rename-bld.png
+
The selected building must be one of stockpile, workshop, furnace, trap, or siege engine.
It is also possible to rename zones from the 'i' menu.
* ``gui/rename [unit]`` with a unit selected changes the nickname.
+ Unlike the built-in interface, this works even on enemies and animals.
+
* ``gui/rename unit-profession`` changes the selected unit's custom profession name.
+ .. image:: images/rename-prof.png
+
+ Likewise, this can be applied to any unit, and when used on animals it overrides
+ their species string.
+
The ``building`` or ``unit`` options are automatically assumed when in relevant ui state.
+The example config binds building/unit rename to Ctrl-Shift-N, and
+unit profession change to Ctrl-Shift-T.
+
gui/room-list
=============
-To use, bind to a key and activate in the 'q' mode, either immediately or after opening
-the assign owner page.
+To use, bind to a key (the example config uses Alt-R) and activate in the 'q' mode,
+either immediately or after opening the assign owner page.
+
+.. image:: images/room-list.png
The script lists other rooms owned by the same owner, or by the unit selected in the assign
list, and allows unassigning them.
@@ -2085,7 +2205,8 @@ list, and allows unassigning them.
gui/choose-weapons
==================
-Bind to a key, and activate in the Equip->View/Customize page of the military screen.
+Bind to a key (the example config uses Ctrl-W), and activate in the Equip->View/Customize
+page of the military screen.
Depending on the cursor location, it rewrites all 'individual choice weapon' entries
in the selected squad or position to use a specific weapon type matching the assigned
@@ -2099,7 +2220,10 @@ and may lead to inappropriate weapons being selected.
gui/guide-path
==============
-Bind to a key, and activate in the Hauling menu with the cursor over a Guide order.
+Bind to a key (the example config uses Alt-P), and activate in the Hauling menu with
+the cursor over a Guide order.
+
+.. image:: images/guide-path.png
The script displays the cached path that will be used by the order; the game
computes it when the order is executed for the first time.
@@ -2108,15 +2232,28 @@ computes it when the order is executed for the first time.
gui/workshop-job
================
-Bind to a key, and activate with a job selected in a workshop in the 'q' mode.
+Bind to a key (the example config uses Alt-A), and activate with a job selected in
+a workshop in the 'q' mode.
+
+.. image:: images/workshop-job.png
The script shows a list of the input reagents of the selected job, and allows changing
them like the ``job item-type`` and ``job item-material`` commands.
Specifically, pressing the 'i' key pops up a dialog that lets you select an item
-type from a list. Pressing 'm', unless the item type does not allow a material,
+type from a list.
+
+.. image:: images/workshop-job-item.png
+
+Pressing 'm', unless the item type does not allow a material,
lets you choose a material.
+.. image:: images/workshop-job-material.png
+
+Since there are a lot more materials than item types, this dialog is more complex
+and uses a hierarchy of sub-menus. List choices that open a sub-menu are marked
+with an arrow on the left.
+
.. warning::
Due to the way input reagent matching works in DF, you must select an item type
@@ -2143,7 +2280,10 @@ you have to unset the material first.
gui/workflow
============
-Bind to a key, and activate with a job selected in a workshop in the 'q' mode.
+Bind to a key (the example config uses Alt-W), and activate with a job selected
+in a workshop in the 'q' mode.
+
+.. image:: images/workflow.png
This script provides a simple interface to constraints managed by the workflow
plugin. When active, it displays a list of all constraints applicable to the
@@ -2161,17 +2301,31 @@ bounds by 1, 5, or 25 depending on the direction and the 'c' setting (counting
items and expanding the range each gives a 5x bonus).
Pressing 'n' produces a list of possible outputs of this job as guessed by
-workflow, and lets you create a new constraint by just choosing one. If you
+workflow, and lets you create a new constraint by choosing one as template. If you
don't see the choice you want in the list, it likely means you have to adjust
the job material first using ``job item-material`` or ``gui/workshop-job``,
as described in ``workflow`` documentation above. In this manner, this feature
can be used for troubleshooting jobs that don't match the right constraints.
+.. image:: images/workflow-new1.png
+
+After selecting one of the presented outputs, the interface proceeds to the
+next dialog, which allows you to edit the suggested constraint parameters to
+suit your need, and set the item count range.
+
+.. image:: images/workflow-new2.png
+
+If you don't need advanced settings, you can just press 'y' to confirm creation.
+
+
gui/assign-rack
===============
-Bind to a key, and activate when viewing a weapon rack in the 'q' mode.
+Bind to a key (the example config uses P), and activate when viewing a weapon
+rack in the 'q' mode.
+
+.. image:: images/assign-rack.png
This script is part of a group of related fixes to make the armory storage
work again. The existing issues are:
@@ -2191,7 +2345,8 @@ work again. The existing issues are:
The script interface simply lets you designate one of the squads that
are assigned to the barracks/armory containing the selected stand as
-the intended user.
+the intended user. In order to aid in the choice, it shows the number
+of currently assigned racks for every valid squad.
gui/advfort
@@ -2253,7 +2408,10 @@ Configuration UI
----------------
The configuration front-end to the plugin is implemented by the gui/siege-engine
-script. Bind it to a key and activate after selecting a siege engine in 'q' mode.
+script. Bind it to a key (the example config uses Alt-A) and activate after selecting
+a siege engine in 'q' mode.
+
+.. image:: images/siege-engine.png
The main mode displays the current target, selected ammo item type, linked stockpiles and
the allowed operator skill range. The map tile color is changed to signify if it can be
@@ -2283,7 +2441,10 @@ The power-meter plugin implements a modified pressure plate that detects power b
supplied to gear boxes built in the four adjacent N/S/W/E tiles.
The configuration front-end is implemented by the gui/power-meter script. Bind it to a
-key and activate after selecting Pressure Plate in the build menu.
+key (the example config uses Ctrl-Shift-M) and activate after selecting Pressure Plate
+in the build menu.
+
+.. image:: images/power-meter.png
The script follows the general look and feel of the regular pressure plate build
configuration page, but configures parameters relevant to the modded power meter building.
diff --git a/dfhack.init-example b/dfhack.init-example
index 885849c33..8fafa4cf4 100644
--- a/dfhack.init-example
+++ b/dfhack.init-example
@@ -133,6 +133,9 @@ tweak military-stable-assign
# in same list, color units already assigned to squads in brown & green
tweak military-color-assigned
+# remove inverse dependency of squad training speed on unit list size and use more sparring
+tweak military-training
+
#######################################################
# Apply binary patches at runtime #
# #
diff --git a/images/assign-rack.png b/images/assign-rack.png
new file mode 100644
index 000000000..4ebcbf590
Binary files /dev/null and b/images/assign-rack.png differ
diff --git a/images/automaterial-mat.png b/images/automaterial-mat.png
new file mode 100644
index 000000000..5517bbc6d
Binary files /dev/null and b/images/automaterial-mat.png differ
diff --git a/images/automaterial-pos.png b/images/automaterial-pos.png
new file mode 100644
index 000000000..959573643
Binary files /dev/null and b/images/automaterial-pos.png differ
diff --git a/images/guide-path.png b/images/guide-path.png
new file mode 100644
index 000000000..afb6511fa
Binary files /dev/null and b/images/guide-path.png differ
diff --git a/images/liquids.png b/images/liquids.png
new file mode 100644
index 000000000..da70a058b
Binary files /dev/null and b/images/liquids.png differ
diff --git a/images/manipulator.png b/images/manipulator.png
new file mode 100644
index 000000000..1f452549f
Binary files /dev/null and b/images/manipulator.png differ
diff --git a/images/manipulator2.png b/images/manipulator2.png
new file mode 100644
index 000000000..38c6c3cfb
Binary files /dev/null and b/images/manipulator2.png differ
diff --git a/images/mechanisms.png b/images/mechanisms.png
new file mode 100644
index 000000000..062d126cd
Binary files /dev/null and b/images/mechanisms.png differ
diff --git a/images/power-meter.png b/images/power-meter.png
new file mode 100644
index 000000000..b1a4b6229
Binary files /dev/null and b/images/power-meter.png differ
diff --git a/images/rename-bld.png b/images/rename-bld.png
new file mode 100644
index 000000000..0028a87a5
Binary files /dev/null and b/images/rename-bld.png differ
diff --git a/images/rename-prof.png b/images/rename-prof.png
new file mode 100644
index 000000000..5f2cfc453
Binary files /dev/null and b/images/rename-prof.png differ
diff --git a/images/room-list.png b/images/room-list.png
new file mode 100644
index 000000000..5a60398f8
Binary files /dev/null and b/images/room-list.png differ
diff --git a/images/search.png b/images/search.png
new file mode 100644
index 000000000..384c3c533
Binary files /dev/null and b/images/search.png differ
diff --git a/images/siege-engine.png b/images/siege-engine.png
new file mode 100644
index 000000000..032e265dc
Binary files /dev/null and b/images/siege-engine.png differ
diff --git a/images/tweak-mil-color.png b/images/tweak-mil-color.png
new file mode 100644
index 000000000..b4a012cab
Binary files /dev/null and b/images/tweak-mil-color.png differ
diff --git a/images/tweak-plate.png b/images/tweak-plate.png
new file mode 100644
index 000000000..b7ba2c88d
Binary files /dev/null and b/images/tweak-plate.png differ
diff --git a/images/workflow-new1.png b/images/workflow-new1.png
new file mode 100644
index 000000000..25b498bca
Binary files /dev/null and b/images/workflow-new1.png differ
diff --git a/images/workflow-new2.png b/images/workflow-new2.png
new file mode 100644
index 000000000..74a4922be
Binary files /dev/null and b/images/workflow-new2.png differ
diff --git a/images/workflow.png b/images/workflow.png
new file mode 100644
index 000000000..a0a0d4216
Binary files /dev/null and b/images/workflow.png differ
diff --git a/images/workshop-job-item.png b/images/workshop-job-item.png
new file mode 100644
index 000000000..cef691918
Binary files /dev/null and b/images/workshop-job-item.png differ
diff --git a/images/workshop-job-material.png b/images/workshop-job-material.png
new file mode 100644
index 000000000..d75797766
Binary files /dev/null and b/images/workshop-job-material.png differ
diff --git a/images/workshop-job.png b/images/workshop-job.png
new file mode 100644
index 000000000..938b84374
Binary files /dev/null and b/images/workshop-job.png differ
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index b141e9fa5..f67b6fe44 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -167,7 +167,7 @@ IF(UNIX)
IF(BUILD_EGGY)
LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_LINUX_EGGY})
ELSEIF(APPLE)
- LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_DARWIN})
+ LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_DARWIN})
ELSE()
LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_LINUX})
ENDIF()
@@ -235,7 +235,7 @@ ENDIF()
IF(UNIX)
SET(PROJECT_LIBS rt dl dfhack-md5 dfhack-tinyxml dfhack-tinythread)
IF(APPLE)
- SET(PROJECT_LIBS dl dfhack-md5 dfhack-tinyxml dfhack-tinythread)
+ SET(PROJECT_LIBS dl dfhack-md5 dfhack-tinyxml dfhack-tinythread)
ENDIF()
ELSE(WIN32)
#FIXME: do we really need psapi?
@@ -273,14 +273,14 @@ ENDIF()
SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" )
IF(APPLE)
- SET(SDL_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/SDL.framework)
- SET(CXX_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/libstdc++.6.dylib)
- SET(ZIP_LIBRARY /usr/lib/libz.dylib)
- TARGET_LINK_LIBRARIES(dfhack ${SDL_LIBRARY})
- TARGET_LINK_LIBRARIES(dfhack ${CXX_LIBRARY})
- TARGET_LINK_LIBRARIES(dfhack ${ZIP_LIBRARY})
- SET_TARGET_PROPERTIES(dfhack PROPERTIES VERSION 1.0.0)
- SET_TARGET_PROPERTIES(dfhack PROPERTIES SOVERSION 1.0.0)
+ SET(SDL_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/SDL.framework)
+ SET(CXX_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/libstdc++.6.dylib)
+ SET(ZIP_LIBRARY /usr/lib/libz.dylib)
+ TARGET_LINK_LIBRARIES(dfhack ${SDL_LIBRARY})
+ TARGET_LINK_LIBRARIES(dfhack ${CXX_LIBRARY})
+ TARGET_LINK_LIBRARIES(dfhack ${ZIP_LIBRARY})
+ SET_TARGET_PROPERTIES(dfhack PROPERTIES VERSION 1.0.0)
+ SET_TARGET_PROPERTIES(dfhack PROPERTIES SOVERSION 1.0.0)
ENDIF()
TARGET_LINK_LIBRARIES(dfhack protobuf-lite clsocket lua ${PROJECT_LIBS})
@@ -290,20 +290,20 @@ TARGET_LINK_LIBRARIES(dfhack-client protobuf-lite clsocket)
TARGET_LINK_LIBRARIES(dfhack-run dfhack-client)
if(APPLE)
- add_custom_command(TARGET dfhack-run COMMAND ${dfhack_SOURCE_DIR}/package/darwin/fix-libs.sh WORKING_DIRECTORY ../ COMMENT "Fixing library dependencies...")
+ add_custom_command(TARGET dfhack-run COMMAND ${dfhack_SOURCE_DIR}/package/darwin/fix-libs.sh WORKING_DIRECTORY ../ COMMENT "Fixing library dependencies...")
endif()
IF(UNIX)
- if (APPLE)
- install(PROGRAMS ${dfhack_SOURCE_DIR}/package/darwin/dfhack
- DESTINATION .)
- install(PROGRAMS ${dfhack_SOURCE_DIR}/package/darwin/dfhack-run
- DESTINATION .)
+ if (APPLE)
+ install(PROGRAMS ${dfhack_SOURCE_DIR}/package/darwin/dfhack
+ DESTINATION .)
+ install(PROGRAMS ${dfhack_SOURCE_DIR}/package/darwin/dfhack-run
+ DESTINATION .)
else()
- # On linux, copy our version of the df launch script which sets LD_PRELOAD
- install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack
+ # On linux, copy our version of the df launch script which sets LD_PRELOAD
+ install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack
DESTINATION .)
- install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack-run
+ install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack-run
DESTINATION .)
endif()
ELSE()
diff --git a/library/Core.cpp b/library/Core.cpp
index 26c0acbb0..fd96d5601 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -375,7 +375,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
" reload PLUGIN|all - Reload a plugin or all loaded plugins.\n"
);
- con.print("\nDFHack version " DFHACK_VERSION ".\n");
+ con.print("\nDFHack version " DFHACK_VERSION ".\n");
}
else if (parts.size() == 1)
{
@@ -747,13 +747,13 @@ void fIOthread(void * iodata)
else if(ret)
{
// a proper, non-empty command was entered
- fprintf(stderr,"Adding command to history\n");
+ fprintf(stderr,"Adding command to history\n");
main_history.add(command);
- fprintf(stderr,"Saving history\n");
+ fprintf(stderr,"Saving history\n");
main_history.save("dfhack.history");
}
- fprintf(stderr,"Running command\n");
+ fprintf(stderr,"Running command\n");
auto rv = core->runCommand(con, command);
diff --git a/library/Hooks-windows.cpp b/library/Hooks-windows.cpp
index 1e6679855..c8bd22dda 100644
--- a/library/Hooks-windows.cpp
+++ b/library/Hooks-windows.cpp
@@ -271,39 +271,39 @@ DFhackCExport vPtr SDL_SetVideoMode(int width, int height, int bpp, uint32_t fla
static int (*_SDL_UpperBlit)(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect) = 0;
DFhackCExport int SDL_UpperBlit(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect)
{
- if ( dstrect != NULL && dstrect->h != 0 && dstrect->w != 0 )
- {
- DFHack::Core & c = DFHack::Core::getInstance();
- DFHack::Graphic* g = c.getGraphic();
- DFHack::DFTileSurface* ov = g->Call(dstrect->x/dstrect->w, dstrect->y/dstrect->h);
-
- if ( ov != NULL )
- {
- if ( ov->paintOver )
- {
- _SDL_UpperBlit(src, srcrect, dst, dstrect);
- }
-
- DFHack::DFSDL_Rect* dstrect2 = new DFHack::DFSDL_Rect;
- dstrect2->x = dstrect->x;
- dstrect2->y = dstrect->y;
- dstrect2->w = dstrect->w;
- dstrect2->h = dstrect->h;
-
- if ( ov->dstResize != NULL )
- {
- DFHack::DFSDL_Rect* r = (DFHack::DFSDL_Rect*)ov->dstResize;
- dstrect2->x += r->x;
- dstrect2->y += r->y;
- dstrect2->w += r->w;
- dstrect2->h += r->h;
- }
-
- int result = _SDL_UpperBlit(ov->surface, ov->rect, dst, dstrect2);
- delete dstrect2;
- return result;
- }
- }
+ if ( dstrect != NULL && dstrect->h != 0 && dstrect->w != 0 )
+ {
+ DFHack::Core & c = DFHack::Core::getInstance();
+ DFHack::Graphic* g = c.getGraphic();
+ DFHack::DFTileSurface* ov = g->Call(dstrect->x/dstrect->w, dstrect->y/dstrect->h);
+
+ if ( ov != NULL )
+ {
+ if ( ov->paintOver )
+ {
+ _SDL_UpperBlit(src, srcrect, dst, dstrect);
+ }
+
+ DFHack::DFSDL_Rect* dstrect2 = new DFHack::DFSDL_Rect;
+ dstrect2->x = dstrect->x;
+ dstrect2->y = dstrect->y;
+ dstrect2->w = dstrect->w;
+ dstrect2->h = dstrect->h;
+
+ if ( ov->dstResize != NULL )
+ {
+ DFHack::DFSDL_Rect* r = (DFHack::DFSDL_Rect*)ov->dstResize;
+ dstrect2->x += r->x;
+ dstrect2->y += r->y;
+ dstrect2->w += r->w;
+ dstrect2->h += r->h;
+ }
+
+ int result = _SDL_UpperBlit(ov->surface, ov->rect, dst, dstrect2);
+ delete dstrect2;
+ return result;
+ }
+ }
return _SDL_UpperBlit(src, srcrect, dst, dstrect);
}
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index b186316a8..a4ebbea5b 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -1180,6 +1180,7 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, getAge),
WRAPM(Units, getNominalSkill),
WRAPM(Units, getEffectiveSkill),
+ WRAPM(Units, getExperience),
WRAPM(Units, computeMovementSpeed),
WRAPM(Units, getProfessionName),
WRAPM(Units, getCasteProfessionName),
diff --git a/library/MacPool.mm b/library/MacPool.mm
index 2453aca29..8f26543e9 100644
--- a/library/MacPool.mm
+++ b/library/MacPool.mm
@@ -9,14 +9,14 @@
NSAutoreleasePool *thePool;
int create_pool() {
- fprintf(stderr,"Creating autorelease pool\n");
- thePool = [[NSAutoreleasePool alloc] init];
- return 1;
+ fprintf(stderr,"Creating autorelease pool\n");
+ thePool = [[NSAutoreleasePool alloc] init];
+ return 1;
}
int destroy_pool() {
- fprintf(stderr,"Draining and releasing autorelease pool\n");
- [thePool drain];
- [thePool release];
- return 0;
+ fprintf(stderr,"Draining and releasing autorelease pool\n");
+ [thePool drain];
+ [thePool release];
+ return 0;
}
\ No newline at end of file
diff --git a/library/Process-darwin.cpp b/library/Process-darwin.cpp
index d081c8c5c..2e2be277b 100644
--- a/library/Process-darwin.cpp
+++ b/library/Process-darwin.cpp
@@ -50,13 +50,13 @@ using namespace DFHack;
Process::Process(VersionInfoFactory * known_versions)
{
int target_result;
-
+
char path[1024];
char *real_path;
- uint32_t size = sizeof(path);
- if (_NSGetExecutablePath(path, &size) == 0) {
- real_path = realpath(path, NULL);
- }
+ uint32_t size = sizeof(path);
+ if (_NSGetExecutablePath(path, &size) == 0) {
+ real_path = realpath(path, NULL);
+ }
identified = false;
my_descriptor = 0;
@@ -166,29 +166,29 @@ void Process::getMemRanges( vector & ranges )
(vm_region_info_t)&info, &info_count, &object);
if (kr == KERN_SUCCESS) {
if (info.reserved==1) {
- address += vmsize;
- continue;
+ address += vmsize;
+ continue;
}
Dl_info dlinfo;
int dlcheck;
dlcheck = dladdr((const void*)address, &dlinfo);
if (dlcheck==0) {
- dlinfo.dli_fname = "";
+ dlinfo.dli_fname = "";
}
-
+
t_memrange temp;
- strncpy( temp.name, dlinfo.dli_fname, 1023 );
- temp.name[1023] = 0;
- temp.start = (void *) address;
- temp.end = (void *) (address+vmsize);
- temp.read = (info.protection & VM_PROT_READ);
- temp.write = (info.protection & VM_PROT_WRITE);
- temp.execute = (info.protection & VM_PROT_EXECUTE);
- temp.shared = info.shared;
- temp.valid = true;
- ranges.push_back(temp);
-
- fprintf(stderr,
+ strncpy( temp.name, dlinfo.dli_fname, 1023 );
+ temp.name[1023] = 0;
+ temp.start = (void *) address;
+ temp.end = (void *) (address+vmsize);
+ temp.read = (info.protection & VM_PROT_READ);
+ temp.write = (info.protection & VM_PROT_WRITE);
+ temp.execute = (info.protection & VM_PROT_EXECUTE);
+ temp.shared = info.shared;
+ temp.valid = true;
+ ranges.push_back(temp);
+
+ fprintf(stderr,
"%08x-%08x %8uK %c%c%c/%c%c%c %11s %6s %10s uwir=%hu sub=%u dlname: %s\n",
address, (address + vmsize), (vmsize >> 10),
(info.protection & VM_PROT_READ) ? 'r' : '-',
@@ -203,7 +203,7 @@ void Process::getMemRanges( vector & ranges )
info.user_wired_count,
info.reserved,
dlinfo.dli_fname);
-
+
address += vmsize;
} else if (kr != KERN_INVALID_ADDRESS) {
@@ -277,15 +277,15 @@ uint32_t Process::getTickCount()
string Process::getPath()
{
- char path[1024];
+ char path[1024];
char *real_path;
- uint32_t size = sizeof(path);
- if (_NSGetExecutablePath(path, &size) == 0) {
- real_path = realpath(path, NULL);
- }
- std::string path_string(real_path);
- int last_slash = path_string.find_last_of("/");
- std::string directory = path_string.substr(0,last_slash);
+ uint32_t size = sizeof(path);
+ if (_NSGetExecutablePath(path, &size) == 0) {
+ real_path = realpath(path, NULL);
+ }
+ std::string path_string(real_path);
+ int last_slash = path_string.find_last_of("/");
+ std::string directory = path_string.substr(0,last_slash);
return directory;
}
@@ -304,4 +304,29 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange)
result=mprotect((void *)range.start, (size_t)range.end-(size_t)range.start,protect);
return result==0;
-}
\ No newline at end of file
+}
+
+// returns -1 on error
+void* Process::memAlloc(const int length)
+{
+ return mmap(0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+}
+
+int Process::memDealloc(const void *ptr, const int length)
+{
+ return munmap(ptr, length);
+}
+
+int Process::memProtect(const void *ptr, const int length, const int prot)
+{
+ int prot_native = 0;
+
+ if (prot & Process::MemProt::READ)
+ prot_native |= PROT_READ;
+ if (prot & Process::MemProt::WRITE)
+ prot_native |= PROT_WRITE;
+ if (prot & Process::MemProt::EXEC)
+ prot_native |= PROT_EXEC;
+
+ return mprotect(ptr, length, prot_native);
+}
diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp
index 046b7696d..c3995a2aa 100644
--- a/library/Process-linux.cpp
+++ b/library/Process-linux.cpp
@@ -235,4 +235,29 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange)
result=mprotect((void *)range.start, (size_t)range.end-(size_t)range.start,protect);
return result==0;
-}
\ No newline at end of file
+}
+
+// returns -1 on error
+void* Process::memAlloc(const int length)
+{
+ return mmap(0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+}
+
+int Process::memDealloc(void *ptr, const int length)
+{
+ return munmap(ptr, length);
+}
+
+int Process::memProtect(void *ptr, const int length, const int prot)
+{
+ int prot_native = 0;
+
+ if (prot & Process::MemProt::READ)
+ prot_native |= PROT_READ;
+ if (prot & Process::MemProt::WRITE)
+ prot_native |= PROT_WRITE;
+ if (prot & Process::MemProt::EXEC)
+ prot_native |= PROT_EXEC;
+
+ return mprotect(ptr, length, prot_native);
+}
diff --git a/library/Process-windows.cpp b/library/Process-windows.cpp
index 6f79236f9..fdef9e225 100644
--- a/library/Process-windows.cpp
+++ b/library/Process-windows.cpp
@@ -473,3 +473,42 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange)
return result;
}
+
+void* Process::memAlloc(const int length)
+{
+ void *ret;
+ // returns 0 on error
+ ret = VirtualAlloc(0, length, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
+ if (!ret)
+ ret = (void*)-1;
+ return ret;
+}
+
+int Process::memDealloc(void *ptr, const int length)
+{
+ // can only free the whole region at once
+ // vfree returns 0 on error
+ return !VirtualFree(ptr, 0, MEM_RELEASE);
+}
+
+int Process::memProtect(void *ptr, const int length, const int prot)
+{
+ int prot_native = 0;
+ DWORD old_prot = 0;
+
+ // only support a few constant combinations
+ if (prot == 0)
+ prot_native = PAGE_NOACCESS;
+ else if (prot == Process::MemProt::READ)
+ prot_native = PAGE_READONLY;
+ else if (prot == (Process::MemProt::READ | Process::MemProt::WRITE))
+ prot_native = PAGE_READWRITE;
+ else if (prot == (Process::MemProt::READ | Process::MemProt::WRITE | Process::MemProt::EXEC))
+ prot_native = PAGE_EXECUTE_READWRITE;
+ else if (prot == (Process::MemProt::READ | Process::MemProt::EXEC))
+ prot_native = PAGE_EXECUTE_READ;
+ else
+ return -1;
+
+ return !VirtualProtect(ptr, length, prot_native, &old_prot);
+}
diff --git a/library/include/Console.h b/library/include/Console.h
index 8d848135a..2f2f68cfa 100644
--- a/library/include/Console.h
+++ b/library/include/Console.h
@@ -65,20 +65,20 @@ namespace DFHack
bool save (const char * filename)
{
std::ofstream outfile (filename);
- //fprintf(stderr,"Save: Initialized stream\n");
+ //fprintf(stderr,"Save: Initialized stream\n");
if(outfile.bad())
return false;
- //fprintf(stderr,"Save: Iterating...\n");
+ //fprintf(stderr,"Save: Iterating...\n");
for(auto iter = history.begin();iter < history.end(); iter++)
{
- //fprintf(stderr,"Save: Dumping %s\n",(*iter).c_str());
+ //fprintf(stderr,"Save: Dumping %s\n",(*iter).c_str());
outfile << *iter << std::endl;
- //fprintf(stderr,"Save: Flushing\n");
- outfile.flush();
+ //fprintf(stderr,"Save: Flushing\n");
+ outfile.flush();
}
- //fprintf(stderr,"Save: Closing\n");
+ //fprintf(stderr,"Save: Closing\n");
outfile.close();
- //fprintf(stderr,"Save: Done\n");
+ //fprintf(stderr,"Save: Done\n");
return true;
}
/// add a command to the history
diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h
index 32ffabc32..3591be045 100644
--- a/library/include/DataDefs.h
+++ b/library/include/DataDefs.h
@@ -35,7 +35,7 @@ distribution.
// Stop some MS stupidity
#ifdef interface
- #undef interface
+ #undef interface
#endif
typedef struct lua_State lua_State;
diff --git a/library/include/MemAccess.h b/library/include/MemAccess.h
index 22f15eecf..31647a25e 100644
--- a/library/include/MemAccess.h
+++ b/library/include/MemAccess.h
@@ -291,6 +291,27 @@ namespace DFHack
/// write a possibly read-only memory area
bool patchMemory(void *target, const void* src, size_t count);
+
+ /// allocate new memory pages for code or stuff
+ /// returns -1 on error (0 is a valid address)
+ void* memAlloc(const int length);
+
+ /// free memory pages from memAlloc
+ /// should have length = alloced length for portability
+ /// returns 0 on success
+ int memDealloc(void *ptr, const int length);
+
+ /// change memory page permissions
+ /// prot is a bitwise OR of the MemProt enum
+ /// returns 0 on success
+ int memProtect(void *ptr, const int length, const int prot);
+
+ enum MemProt {
+ READ = 1,
+ WRITE = 2,
+ EXEC = 4
+ };
+
private:
VersionInfo * my_descriptor;
PlatformSpecific *d;
diff --git a/library/include/TileTypes.h b/library/include/TileTypes.h
index 48c10146a..f46cf2f2c 100644
--- a/library/include/TileTypes.h
+++ b/library/include/TileTypes.h
@@ -41,7 +41,7 @@ namespace DFHack
struct
{
//Maybe should add 'up' and 'down' for Z-levels?
- unsigned char north,south,west,east;
+ unsigned char north,south,west,east;
};
inline TileDirection()
diff --git a/library/include/Types.h b/library/include/Types.h
index 98dbb7e74..5412b443b 100644
--- a/library/include/Types.h
+++ b/library/include/Types.h
@@ -74,6 +74,28 @@ namespace DFHack
uint32_t xpNxtLvl;
};
+ typedef std::pair rect2d;
+
+ inline rect2d intersect(rect2d a, rect2d b) {
+ df::coord2d g1 = a.first, g2 = a.second;
+ df::coord2d c1 = b.first, c2 = b.second;
+ df::coord2d rc1 = df::coord2d(std::max(g1.x, c1.x), std::max(g1.y, c1.y));
+ df::coord2d rc2 = df::coord2d(std::min(g2.x, c2.x), std::min(g2.y, c2.y));
+ return rect2d(rc1, rc2);
+ }
+
+ inline rect2d mkrect_xy(int x1, int y1, int x2, int y2) {
+ return rect2d(df::coord2d(x1, y1), df::coord2d(x2, y2));
+ }
+
+ inline rect2d mkrect_wh(int x, int y, int w, int h) {
+ return rect2d(df::coord2d(x, y), df::coord2d(x+w-1, y+h-1));
+ }
+
+ inline df::coord2d rect_size(const rect2d &rect) {
+ return rect.second - rect.first + df::coord2d(1,1);
+ }
+
DFHACK_EXPORT int getdir(std::string dir, std::vector &files);
DFHACK_EXPORT bool hasEnding (std::string const &fullString, std::string const &ending);
diff --git a/library/include/VersionInfo.h b/library/include/VersionInfo.h
index 2ea4170fa..26aee19d1 100644
--- a/library/include/VersionInfo.h
+++ b/library/include/VersionInfo.h
@@ -27,7 +27,7 @@ distribution.
#include "Pragma.h"
#include "Export.h"
-#include "Types.h"
+/* #include "Types.h" */
#include