Merge remote-tracking branch 'origin/develop' into plugin-globals

develop
lethosor 2014-12-06 17:32:44 -05:00
commit 5de3e6110a
17 changed files with 792 additions and 82 deletions

@ -59,7 +59,7 @@ endif()
# set up versioning. # set up versioning.
set(DF_VERSION "0.40.19") set(DF_VERSION "0.40.19")
SET(DFHACK_RELEASE "r0" CACHE STRING "Current release revision.") SET(DFHACK_RELEASE "r1" CACHE STRING "Current release revision.")
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}") set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
add_definitions(-DDFHACK_VERSION="${DFHACK_VERSION}") add_definitions(-DDFHACK_VERSION="${DFHACK_VERSION}")

@ -3,13 +3,13 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8.1: http://docutils.sourceforge.net/" /> <meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>Building DFHACK</title> <title>Building DFHACK</title>
<style type="text/css"> <style type="text/css">
/* /*
:Author: David Goodger (goodger@python.org) :Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7056 2011-06-17 10:50:48Z milde $ :Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain. :Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils. Default cascading style sheet for the HTML output of Docutils.
@ -77,7 +77,7 @@ div.tip p.admonition-title {
div.attention p.admonition-title, div.caution p.admonition-title, div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title, div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title { div.warning p.admonition-title, .code .error {
color: red ; color: red ;
font-weight: bold ; font-weight: bold ;
font-family: sans-serif } font-family: sans-serif }
@ -249,10 +249,19 @@ pre.address {
margin-top: 0 ; margin-top: 0 ;
font: inherit } font: inherit }
pre.literal-block, pre.doctest-block, pre.math { pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ; margin-left: 2em ;
margin-right: 2em } margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier { span.classifier {
font-family: sans-serif ; font-family: sans-serif ;
font-style: oblique } font-style: oblique }
@ -304,6 +313,21 @@ table.docutils th.field-name, table.docinfo th.docinfo-name {
white-space: nowrap ; white-space: nowrap ;
padding-left: 0 } padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% } font-size: 100% }

@ -3,7 +3,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>Contributors</title> <title>Contributors</title>
<style type="text/css"> <style type="text/css">
@ -402,6 +402,7 @@ ul.auto-toc {
<li>Antalia &lt;<a class="reference external" href="mailto:tamarakorr&#64;gmail.com">tamarakorr&#64;gmail.com</a>&gt;</li> <li>Antalia &lt;<a class="reference external" href="mailto:tamarakorr&#64;gmail.com">tamarakorr&#64;gmail.com</a>&gt;</li>
<li>Angus Mezick &lt;<a class="reference external" href="mailto:amezick&#64;gmail.com">amezick&#64;gmail.com</a>&gt;</li> <li>Angus Mezick &lt;<a class="reference external" href="mailto:amezick&#64;gmail.com">amezick&#64;gmail.com</a>&gt;</li>
<li>PeridexisErrant &lt;<a class="reference external" href="mailto:PeridexisErrant&#64;gmail.com">PeridexisErrant&#64;gmail.com</a>&gt;</li> <li>PeridexisErrant &lt;<a class="reference external" href="mailto:PeridexisErrant&#64;gmail.com">PeridexisErrant&#64;gmail.com</a>&gt;</li>
<li>Putnam</li>
</ul> </ul>
<p>And those are the cool people who made <strong>stonesense</strong>.</p> <p>And those are the cool people who made <strong>stonesense</strong>.</p>
<ul class="simple"> <ul class="simple">

@ -3,13 +3,13 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8.1: http://docutils.sourceforge.net/" /> <meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>DFHack Lua API</title> <title>DFHack Lua API</title>
<style type="text/css"> <style type="text/css">
/* /*
:Author: David Goodger (goodger@python.org) :Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7056 2011-06-17 10:50:48Z milde $ :Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain. :Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils. Default cascading style sheet for the HTML output of Docutils.
@ -77,7 +77,7 @@ div.tip p.admonition-title {
div.attention p.admonition-title, div.caution p.admonition-title, div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title, div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title { div.warning p.admonition-title, .code .error {
color: red ; color: red ;
font-weight: bold ; font-weight: bold ;
font-family: sans-serif } font-family: sans-serif }
@ -249,10 +249,19 @@ pre.address {
margin-top: 0 ; margin-top: 0 ;
font: inherit } font: inherit }
pre.literal-block, pre.doctest-block, pre.math { pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ; margin-left: 2em ;
margin-right: 2em } margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier { span.classifier {
font-family: sans-serif ; font-family: sans-serif ;
font-style: oblique } font-style: oblique }
@ -304,6 +313,21 @@ table.docutils th.field-name, table.docinfo th.docinfo-name {
white-space: nowrap ; white-space: nowrap ;
padding-left: 0 } padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% } font-size: 100% }
@ -1222,6 +1246,11 @@ Returns <em>true</em> on success.</p>
<li><p class="first"><tt class="docutils literal">dfhack.job.is_item_equal(job_item1,job_item2)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.job.is_item_equal(job_item1,job_item2)</tt></p>
<p>Compares important fields in the job item structures.</p> <p>Compares important fields in the job item structures.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.job.linkIntoWorld(job,new_id)</tt></p>
<p>Adds job into <tt class="docutils literal">df.global.job_list</tt>, and if new_id
is true, then also sets it's id and increases
<tt class="docutils literal">df.global.job_next_id</tt></p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.job.listNewlyCreated(first_id)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.job.listNewlyCreated(first_id)</tt></p>
<p>Returns the current value of <tt class="docutils literal">df.global.job_next_id</tt>, and <p>Returns the current value of <tt class="docutils literal">df.global.job_next_id</tt>, and
if there are any jobs with <tt class="docutils literal">first_id &lt;= id &lt; job_next_id</tt>, if there are any jobs with <tt class="docutils literal">first_id &lt;= id &lt; job_next_id</tt>,
@ -3249,7 +3278,8 @@ tweaking (e.g. adding custom reactions)</p>
<p>Enable event checking for EventManager events. For event types use <tt class="docutils literal">eventType</tt> table. Note that different types of events require different frequencies to be effective. The frequency is how many ticks EventManager will wait before checking if that type of event has happened. If multiple scripts or plugins use the same event type, the smallest frequency is the one that is used, so you might get events triggered more often than the frequency you use here.</p> <p>Enable event checking for EventManager events. For event types use <tt class="docutils literal">eventType</tt> table. Note that different types of events require different frequencies to be effective. The frequency is how many ticks EventManager will wait before checking if that type of event has happened. If multiple scripts or plugins use the same event type, the smallest frequency is the one that is used, so you might get events triggered more often than the frequency you use here.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">registerSidebar(shop_name,callback)</tt></p> <li><p class="first"><tt class="docutils literal">registerSidebar(shop_name,callback)</tt></p>
<p>Enable callback when sidebar for <tt class="docutils literal">shop_name</tt> is drawn. Usefull for custom workshop views e.g. using gui.dwarfmode lib.</p> <p>Enable callback when sidebar for <tt class="docutils literal">shop_name</tt> is drawn. Usefull for custom workshop views e.g. using gui.dwarfmode lib. Also accepts a <tt class="docutils literal">class</tt> instead of function
as callback. Best used with <tt class="docutils literal">gui.dwarfmode</tt> class <tt class="docutils literal">WorkshopOverlay</tt>.</p>
</li> </li>
</ol> </ol>
</div> </div>
@ -3310,6 +3340,7 @@ plugin export a function it's recommended to use lua decorated function.</p>
<li><tt class="docutils literal"><span class="pre">{x=&lt;number&gt;</span> <span class="pre">y=&lt;number&gt;</span> + 4 numbers like in first case}</tt>, this generates full frame useful for animations that change little (1-2 tiles)</li> <li><tt class="docutils literal"><span class="pre">{x=&lt;number&gt;</span> <span class="pre">y=&lt;number&gt;</span> + 4 numbers like in first case}</tt>, this generates full frame useful for animations that change little (1-2 tiles)</li>
</ol> </ol>
</li> </li>
<li>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</li>
</ol> </ol>
</dd> </dd>
<dt>Animate table also might contain:</dt> <dt>Animate table also might contain:</dt>

@ -1,4 +1,11 @@
DFHack Future DFHack Future
Internals
Fixes
New Plugins
New Scripts
Misc Improvements
DFHack 0.40.19-r1
Internals: Internals:
Fixes: Fixes:
typo fix in modtools/reaction-trigger typo fix in modtools/reaction-trigger
@ -12,6 +19,7 @@ DFHack Future
this script replaces removebadthoughts.rb this script replaces removebadthoughts.rb
Misc improvements: Misc improvements:
cmd-prompt can now access selected items, units, and buildings cmd-prompt can now access selected items, units, and buildings
autolabor plugin: add an optional talent pool parameter
DFHack 0.40.16-r1 DFHack 0.40.16-r1
Internals: Internals:

@ -2803,6 +2803,9 @@ if labors change mid-job, are handled slightly differently to minimise churn.</p
<tr class="field"><th class="field-name" colspan="2"><cite>autolabor CUT_GEM 1 1</cite>:</th></tr> <tr class="field"><th class="field-name" colspan="2"><cite>autolabor CUT_GEM 1 1</cite>:</th></tr>
<tr class="field"><td>&nbsp;</td><td class="field-body">Keep exactly 1 dwarf with gemcutting enabled.</td> <tr class="field"><td>&nbsp;</td><td class="field-body">Keep exactly 1 dwarf with gemcutting enabled.</td>
</tr> </tr>
<tr class="field"><th class="field-name" colspan="2"><cite>autolabor COOK 1 1 3</cite>:</th></tr>
<tr class="field"><td>&nbsp;</td><td class="field-body">Keep 1 dwarf with cooking enabled, selected only from the top 3.</td>
</tr>
<tr class="field"><th class="field-name" colspan="2"><cite>autolabor FEED_WATER_CIVILIANS haulers</cite>:</th></tr> <tr class="field"><th class="field-name" colspan="2"><cite>autolabor FEED_WATER_CIVILIANS haulers</cite>:</th></tr>
<tr class="field"><td>&nbsp;</td><td class="field-body">Have haulers feed and water wounded dwarves.</td> <tr class="field"><td>&nbsp;</td><td class="field-body">Have haulers feed and water wounded dwarves.</td>
</tr> </tr>

@ -2007,6 +2007,7 @@ Advanced usage:
:`autolabor MINE 5`: Keep at least 5 dwarves with mining enabled. :`autolabor MINE 5`: Keep at least 5 dwarves with mining enabled.
:`autolabor CUT_GEM 1 1`: Keep exactly 1 dwarf with gemcutting enabled. :`autolabor CUT_GEM 1 1`: Keep exactly 1 dwarf with gemcutting enabled.
:`autolabor COOK 1 1 3`: Keep 1 dwarf with cooking enabled, selected only from the top 3.
:`autolabor FEED_WATER_CIVILIANS haulers`: Have haulers feed and water wounded dwarves. :`autolabor FEED_WATER_CIVILIANS haulers`: Have haulers feed and water wounded dwarves.
:`autolabor CUTWOOD disable`: Turn off autolabor for wood cutting. :`autolabor CUTWOOD disable`: Turn off autolabor for wood cutting.

@ -4,6 +4,7 @@
# show all current key bindings # show all current key bindings
keybinding add Ctrl-F1 hotkeys keybinding add Ctrl-F1 hotkeys
keybinding add Alt-F1 hotkeys
# toggle the display of water level as 1-7 tiles # toggle the display of water level as 1-7 tiles
keybinding add Ctrl-W twaterlvl keybinding add Ctrl-W twaterlvl

@ -1,11 +1,30 @@
#!/bin/bash #!/bin/bash
# regenerate documentation after editing the .rst files. Requires python and docutils. # regenerate documentation after editing the .rst files. Requires python and docutils.
rst2html=$(which rst2html || which rst2html.py)
if [[ -z "$rst2html" ]]; then
echo "Docutils not found: See http://docutils.sourceforge.net/"
exit 1
fi
rst2html_version=$("$rst2html" --version | cut -d' ' -f3)
if [[ $(echo $rst2html_version | cut -d. -f2) -lt 12 ]]; then
echo "You are using docutils $rst2html_version. Docutils 0.12+ is recommended
to build these documents."
read -r -n1 -p "Continue? [y/N] " reply
echo
if [[ ! $reply =~ ^[Yy]$ ]]; then
exit
fi
fi
cd `dirname $0` cd `dirname $0`
function process() { function process() {
if [ "$1" -nt "$2" ]; then if [ "$1" -nt "$2" ]; then
rst2html --no-generator --no-datestamp "$1" "$2" echo -n "Updating $2... "
"$rst2html" --no-generator --no-datestamp "$1" "$2"
echo "Done"
else else
echo "$2 - up to date." echo "$2 - up to date."
fi fi

@ -1 +1 @@
Subproject commit a39ef9656e5eb257bf4c262eab3a7e7fd8b672c9 Subproject commit 55b60e3aa99aece7e9a239b041dc4f95a58dcef3

@ -359,7 +359,8 @@ static const dwarf_state dwarf_states[] = {
BUSY /* CarveTrack */, BUSY /* CarveTrack */,
BUSY /* PushTrackVehicle */, BUSY /* PushTrackVehicle */,
BUSY /* PlaceTrackVehicle */, BUSY /* PlaceTrackVehicle */,
BUSY /* StoreItemInVehicle */ BUSY /* StoreItemInVehicle */,
BUSY /* GeldAnimal */
}; };
struct labor_info struct labor_info
@ -378,6 +379,8 @@ struct labor_info
int maximum_dwarfs() { return config.ival(2); } int maximum_dwarfs() { return config.ival(2); }
void set_maximum_dwarfs(int maximum_dwarfs) { config.ival(2) = maximum_dwarfs; } void set_maximum_dwarfs(int maximum_dwarfs) { config.ival(2) = maximum_dwarfs; }
int talent_pool() { return config.ival(3); }
void set_talent_pool(int talent_pool) { config.ival(3) = talent_pool; }
}; };
struct labor_default struct labor_default
@ -471,7 +474,8 @@ static const struct labor_default default_labor_infos[] = {
/* HAUL_TRADE */ {HAULERS, false, 1, 200, 0}, /* HAUL_TRADE */ {HAULERS, false, 1, 200, 0},
/* PULL_LEVER */ {HAULERS, false, 1, 200, 0}, /* PULL_LEVER */ {HAULERS, false, 1, 200, 0},
/* REMOVE_CONSTRUCTION */ {HAULERS, false, 1, 200, 0}, /* REMOVE_CONSTRUCTION */ {HAULERS, false, 1, 200, 0},
/* HAUL_WATER */ {HAULERS, false, 1, 200, 0} /* HAUL_WATER */ {HAULERS, false, 1, 200, 0},
/* GELD */ {AUTOMATIC, false, 1, 200, 0}
}; };
static const int responsibility_penalties[] = { static const int responsibility_penalties[] = {
@ -543,6 +547,7 @@ static void reset_labor(df::unit_labor labor)
{ {
labor_infos[labor].set_minimum_dwarfs(default_labor_infos[labor].minimum_dwarfs); labor_infos[labor].set_minimum_dwarfs(default_labor_infos[labor].minimum_dwarfs);
labor_infos[labor].set_maximum_dwarfs(default_labor_infos[labor].maximum_dwarfs); labor_infos[labor].set_maximum_dwarfs(default_labor_infos[labor].maximum_dwarfs);
labor_infos[labor].set_talent_pool(200);
labor_infos[labor].set_mode(default_labor_infos[labor].mode); labor_infos[labor].set_mode(default_labor_infos[labor].mode);
} }
@ -650,7 +655,10 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
{ {
// initialize labor infos table from default table // initialize labor infos table from default table
if(ARRAY_COUNT(default_labor_infos) != ENUM_LAST_ITEM(unit_labor) + 1) if(ARRAY_COUNT(default_labor_infos) != ENUM_LAST_ITEM(unit_labor) + 1)
{
out.printerr("autolabor: labor size mismatch\n");
return CR_FAILURE; return CR_FAILURE;
}
// Fill the command list with your commands. // Fill the command list with your commands.
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
@ -660,7 +668,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" autolabor enable\n" " autolabor enable\n"
" autolabor disable\n" " autolabor disable\n"
" Enables or disables the plugin.\n" " Enables or disables the plugin.\n"
" autolabor <labor> <minimum> [<maximum>]\n" " autolabor <labor> <minimum> [<maximum>] [<talent pool>]\n"
" Set number of dwarves assigned to a labor.\n" " Set number of dwarves assigned to a labor.\n"
" autolabor <labor> haulers\n" " autolabor <labor> haulers\n"
" Set a labor to be handled by hauler dwarves.\n" " Set a labor to be handled by hauler dwarves.\n"
@ -682,11 +690,15 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" while it is enabled.\n" " while it is enabled.\n"
" To prevent particular dwarves from being managed by autolabor, put them\n" " To prevent particular dwarves from being managed by autolabor, put them\n"
" in any burrow.\n" " in any burrow.\n"
" To restrict the assignment of a labor to only the top <n> most skilled\n"
" dwarves, add a talent pool number <n>.\n"
"Examples:\n" "Examples:\n"
" autolabor MINE 2\n" " autolabor MINE 2\n"
" Keep at least 2 dwarves with mining enabled.\n" " Keep at least 2 dwarves with mining enabled.\n"
" autolabor CUT_GEM 1 1\n" " autolabor CUT_GEM 1 1\n"
" Keep exactly 1 dwarf with gemcutting enabled.\n" " Keep exactly 1 dwarf with gemcutting enabled.\n"
" autolabor COOK 1 1 3\n"
" Keep 1 dwarf with cooking enabled, selected only from the top 3.\n"
" autolabor FEED_WATER_CIVILIANS haulers\n" " autolabor FEED_WATER_CIVILIANS haulers\n"
" Have haulers feed and water wounded dwarves.\n" " Have haulers feed and water wounded dwarves.\n"
" autolabor CUTWOOD disable\n" " autolabor CUTWOOD disable\n"
@ -758,6 +770,7 @@ static void assign_labor(unit_labor::unit_labor labor,
std::vector<int> values(n_dwarfs); std::vector<int> values(n_dwarfs);
std::vector<int> candidates; std::vector<int> candidates;
std::map<int, int> dwarf_skill; std::map<int, int> dwarf_skill;
std::map<int, int> dwarf_skillxp;
std::vector<bool> previously_enabled(n_dwarfs); std::vector<bool> previously_enabled(n_dwarfs);
auto mode = labor_infos[labor].mode(); auto mode = labor_infos[labor].mode();
@ -795,6 +808,7 @@ static void assign_labor(unit_labor::unit_labor labor,
} }
dwarf_skill[dwarf] = skill_level; dwarf_skill[dwarf] = skill_level;
dwarf_skillxp[dwarf] = skill_experience;
value += skill_level * 100; value += skill_level * 100;
value += skill_experience / 20; value += skill_experience / 20;
@ -825,6 +839,32 @@ static void assign_labor(unit_labor::unit_labor labor,
} }
int pool = labor_infos[labor].talent_pool();
if (pool < 200 && candidates.size() > 1 && pool < candidates.size())
{
// Sort in descending order
std::sort(candidates.begin(), candidates.end(), [&](const int lhs, const int rhs) -> bool {
if (dwarf_skill[lhs] == dwarf_skill[rhs])
return dwarf_skillxp[lhs] > dwarf_skillxp[rhs];
else
return dwarf_skill[lhs] > dwarf_skill[rhs];
});
// Check if all dwarves have equivalent skills, usually zero
int first_dwarf = candidates[0];
int last_dwarf = candidates[candidates.size() - 1];
if (dwarf_skill[first_dwarf] == dwarf_skill[last_dwarf] &&
dwarf_skillxp[first_dwarf] == dwarf_skillxp[last_dwarf])
{
// There's no difference in skill, so change nothing
}
else
{
// Trim down to our top talents
candidates.resize(pool);
}
}
// Sort candidates by preference value // Sort candidates by preference value
values_sorter ivs(values); values_sorter ivs(values);
std::sort(candidates.begin(), candidates.end(), ivs); std::sort(candidates.begin(), candidates.end(), ivs);
@ -1294,7 +1334,8 @@ void print_labor (df::unit_labor labor, color_ostream &out)
if (labor_infos[labor].mode() == HAULERS) if (labor_infos[labor].mode() == HAULERS)
out << "haulers"; out << "haulers";
else else
out << "minimum " << labor_infos[labor].minimum_dwarfs() << ", maximum " << labor_infos[labor].maximum_dwarfs(); out << "minimum " << labor_infos[labor].minimum_dwarfs() << ", maximum " << labor_infos[labor].maximum_dwarfs()
<< ", pool " << labor_infos[labor].talent_pool();
out << ", currently " << labor_infos[labor].active_dwarfs << " dwarfs" << endl; out << ", currently " << labor_infos[labor].active_dwarfs << " dwarfs" << endl;
} }
} }
@ -1350,7 +1391,7 @@ command_result autolabor (color_ostream &out, std::vector <std::string> & parame
hauler_pct = pct; hauler_pct = pct;
return CR_OK; return CR_OK;
} }
else if (parameters.size() == 2 || parameters.size() == 3) else if (parameters.size() >= 2 && parameters.size() <= 4)
{ {
if (!enable_autolabor) if (!enable_autolabor)
{ {
@ -1393,17 +1434,22 @@ command_result autolabor (color_ostream &out, std::vector <std::string> & parame
int minimum = atoi (parameters[1].c_str()); int minimum = atoi (parameters[1].c_str());
int maximum = 200; int maximum = 200;
if (parameters.size() == 3) int pool = 200;
if (parameters.size() >= 3)
maximum = atoi (parameters[2].c_str()); maximum = atoi (parameters[2].c_str());
if (parameters.size() == 4)
pool = std::stoi(parameters[3]);
if (maximum < minimum || maximum < 0 || minimum < 0) if (maximum < minimum || maximum < 0 || minimum < 0 || pool < 0)
{ {
out.printerr("Syntax: autolabor <labor> <minimum> [<maximum>]\n", maximum, minimum); out.printerr("Syntax: autolabor <labor> <minimum> [<maximum>] [<talent pool>]\n", maximum, minimum);
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
labor_infos[labor].set_minimum_dwarfs(minimum); labor_infos[labor].set_minimum_dwarfs(minimum);
labor_infos[labor].set_maximum_dwarfs(maximum); labor_infos[labor].set_maximum_dwarfs(maximum);
labor_infos[labor].set_talent_pool(pool);
labor_infos[labor].set_mode(AUTOMATIC); labor_infos[labor].set_mode(AUTOMATIC);
print_labor(labor, out); print_labor(labor, out);

@ -141,6 +141,7 @@ const SkillColumn columns[] = {
{5, 6, profession::COOK, unit_labor::COOK, job_skill::COOK, "Co"}, {5, 6, profession::COOK, unit_labor::COOK, job_skill::COOK, "Co"},
{5, 6, profession::PRESSER, unit_labor::PRESSING, job_skill::PRESSING, "Pr"}, {5, 6, profession::PRESSER, unit_labor::PRESSING, job_skill::PRESSING, "Pr"},
{5, 6, profession::BEEKEEPER, unit_labor::BEEKEEPING, job_skill::BEEKEEPING, "Be"}, {5, 6, profession::BEEKEEPER, unit_labor::BEEKEEPING, job_skill::BEEKEEPING, "Be"},
{5, 6, profession::GELDER, unit_labor::GELD, job_skill::GELD, "Ge"},
// Fishing/Related // Fishing/Related
{6, 1, profession::FISHERMAN, unit_labor::FISH, job_skill::FISH, "Fi"}, {6, 1, profession::FISHERMAN, unit_labor::FISH, job_skill::FISH, "Fi"},
{6, 1, profession::FISH_CLEANER, unit_labor::CLEAN_FISH, job_skill::PROCESSFISH, "Cl"}, {6, 1, profession::FISH_CLEANER, unit_labor::CLEAN_FISH, job_skill::PROCESSFISH, "Cl"},

@ -655,6 +655,13 @@ public:
void feed(set<df::interface_key> *input) void feed(set<df::interface_key> *input)
{ {
if (input->count(interface_key::LEAVESCREEN))
{
input->clear();
Screen::dismiss(this);
return;
}
bool key_processed = false; bool key_processed = false;
switch (selected_column) switch (selected_column)
{ {
@ -666,13 +673,6 @@ public:
if (key_processed) if (key_processed)
return; return;
if (input->count(interface_key::LEAVESCREEN))
{
input->clear();
Screen::dismiss(this);
return;
}
if (input->count(interface_key::CUSTOM_CTRL_J)) if (input->count(interface_key::CUSTOM_CTRL_J))
{ {
hide_flags.bits.in_job = !hide_flags.bits.in_job; hide_flags.bits.in_job = !hide_flags.bits.in_job;

@ -0,0 +1,69 @@
-- Executes an autolabor command for each labor where skill level influences output quality.
local artisan_labors = {
"CARPENTER",
"DETAIL",
"MASON",
"ARCHITECT",
"ANIMALTRAIN",
"LEATHER",
"BREWER",
"WEAVER",
"CLOTHESMAKER",
"COOK",
"FORGE_WEAPON",
"FORGE_ARMOR",
"FORGE_FURNITURE",
"METAL_CRAFT",
"CUT_GEM",
"ENCRUST_GEM",
"WOOD_CRAFT",
"STONE_CRAFT",
"BONE_CARVE",
"GLASSMAKER",
"SIEGECRAFT",
"BOWYER",
"MECHANIC",
"DYER",
"POTTERY",
"WAX_WORKING",
}
local args = {...}
function make_cmd(labor)
local cmd = string.format("autolabor %s", labor)
for i, arg in ipairs(args) do
cmd = cmd .. " " .. arg
end
return cmd
end
function run()
if #args == 0 or args[1] == "help" then
print('Applies an autolabor command to all labors with quality-based output.')
print('')
print('Examples:')
print(' autolabor-artisans 0 2 3')
print(' autolabor-artisans disable')
return false
end
dfhack.run_command("autolabor enable")
-- Test with one to make sure the arguments are valid.
local cmd = make_cmd(artisan_labors[1])
local output, status = dfhack.run_command_silent(cmd)
if status ~= CR_OK then
qerror("Invalid arguments.", status)
return false
end
for i, labor in ipairs(artisan_labors) do
dfhack.run_command(make_cmd(labor))
end
return true
end
run()

@ -201,6 +201,11 @@ address('id',df.history_event,'id')
address('killed_hist_id',df.history_event_hist_figure_diedst,'victim_hf') address('killed_hist_id',df.history_event_hist_figure_diedst,'victim_hf')
header('item_offsets') header('item_offsets')
if os_type == 'darwin' then
value('item_type',0x4)
else
value('item_type',0x1)
end
address('item_def',df.item_ammost,'subtype') --currently same for all address('item_def',df.item_ammost,'subtype') --currently same for all
address('id',df.item,'id') address('id',df.item,'id')
address('general_refs',df.item,'general_refs') address('general_refs',df.item,'general_refs')
@ -306,13 +311,12 @@ address('turn_count',df.unit,'curse','time_on_site')
address('souls',df.unit,'status','souls') address('souls',df.unit,'status','souls')
address('states',df.unit,'status','misc_traits') address('states',df.unit,'status','misc_traits')
address('labors',df.unit,'status','labors') address('labors',df.unit,'status','labors')
--address('thoughts',df.unit,'status','recent_events')
--address('happiness',df.unit,'status','happiness')
address('hist_id',df.unit,'hist_figure_id') address('hist_id',df.unit,'hist_figure_id')
address('artifact_name',df.unit,'status','artifact_name') address('artifact_name',df.unit,'status','artifact_name')
address('active_syndrome_vector',df.unit,'syndromes','active') address('active_syndrome_vector',df.unit,'syndromes','active')
address('syn_sick_flag',df.unit_syndrome,'flags') address('syn_sick_flag',df.unit_syndrome,'flags')
address('unit_health_info',df.unit,'health') address('unit_health_info',df.unit,'health')
address('temp_mood',df.unit,'counters','soldier_mood')
address('counters1',df.unit,'counters','winded') address('counters1',df.unit,'counters','winded')
address('counters2',df.unit, 'counters','pain') address('counters2',df.unit, 'counters','pain')
address('counters3',df.unit, 'counters2','paralysis') address('counters3',df.unit, 'counters2','paralysis')
@ -358,9 +362,20 @@ address('skills',df.unit_soul,'skills')
address('preferences',df.unit_soul,'preferences') address('preferences',df.unit_soul,'preferences')
address('personality',df.unit_soul,'personality') address('personality',df.unit_soul,'personality')
address('beliefs',df.unit_personality,'values') address('beliefs',df.unit_personality,'values')
address('emotions',df.unit_personality,'emotions')
address('goals',df.unit_personality,'dreams') address('goals',df.unit_personality,'dreams')
address('goal_realized',df.unit_personality.T_dreams,'unk8') address('goal_realized',df.unit_personality.T_dreams,'unk8')
address('traits',df.unit_personality,'traits') address('traits',df.unit_personality,'traits')
address('stress_level',df.unit_personality,'stress_level')
header('emotion_offsets')
address('emotion_type',df.unit_personality.T_emotions,'type')
address('strength',df.unit_personality.T_emotions,'strength')
address('thought_id',df.unit_personality.T_emotions,'thought')
address('sub_id',df.unit_personality.T_emotions,'subthought')
address('level',df.unit_personality.T_emotions,'severity')
address('year',df.unit_personality.T_emotions,'year')
address('year_tick',df.unit_personality.T_emotions,'year_tick')
header('job_details') header('job_details')
address('id',df.job,'job_type') address('id',df.job,'job_type')
@ -426,8 +441,8 @@ size=10
5\value=0x00020000 5\value=0x00020000
6\name=an invader or hostile 6\name=an invader or hostile
6\value=0x00080000 6\value=0x00080000
7\name=an invader or hostile 7\name=resident, invader or ambusher
7\value=0x000C0000 7\value=0x00600000
8\name=part of a merchant caravan 8\name=part of a merchant caravan
8\value=0x00000080 8\value=0x00000080
9\name="Dead, Jim." 9\name="Dead, Jim."
@ -443,7 +458,7 @@ size=5
2\value=0x00040000 2\value=0x00040000
3\name=resident 3\name=resident
3\value=0x00080000 3\value=0x00080000
4\name=visitor_uninvited 4\name=uninvited visitor
4\value=0x00400000 4\value=0x00400000
5\name=visitor 5\name=visitor
5\value=0x00800000 5\value=0x00800000

@ -0,0 +1,492 @@
#!/usr/bin/perl
use strict;
use warnings;
my ($version, $timestamp, $hash);
open FH, 'version.lisp' or die "Cannot open version";
while (<FH>) {
if (/df-version-str.*\"(.*)\"/) {
$version = $1;
} elsif (/windows-timestamp.*#x([0-9a-f]+)/) {
$timestamp = $1;
} elsif (/linux-hash.*\"(.*)\"/) {
$hash = $1;
}
}
close FH;
sub load_csv(\%$) {
my ($rhash, $fname) = @_;
open FH, $fname or die "Cannot open $fname";
while (<FH>) {
next unless /^\"([^\"]*)\",\"(\d+)\",\"(?:0x([0-9a-fA-F]+))?\",\"[^\"]*\",\"([^\"]*)\",\"([^\"]*)\",\"([^\"]*)\"/;
my ($top, $level, $addr, $type, $name, $target) = ($1,$2,$3,$4,$5,$6);
next if defined $rhash->{$top}{$name};
$rhash->{$top}{$name} = ($type eq 'enum-item' ? $target : hex $addr);
}
close FH;
}
our $complete;
sub lookup_addr(\%$$;$) {
my ($rhash, $top, $name, $bias) = @_;
my $val = $rhash->{$top}{$name};
unless (defined $val) {
$complete = 0;
return 0;
}
return $val + ($bias||0);
}
our @lines;
sub emit_header($) {
my ($name) = @_;
push @lines, '' if @lines;
push @lines, "[$name]";
}
sub emit_addr($\%$$;$) {
my ($name, $rhash, $top, $var, $bias) = @_;
my $val = $rhash->{$top}{$var};
if (defined $val) {
$val += ($bias||0);
if ($val < 0x10000) {
push @lines, sprintf('%s=0x%04x', $name, $val);
} else {
push @lines, sprintf('%s=0x%08x', $name, $val);
}
} else {
$complete = 0;
push @lines, "$name=0x0";
}
}
sub generate_dt_ini($$$$) {
my ($subdir, $version, $checksum, $ssize) = @_;
my %globals;
load_csv %globals, "$subdir/globals.csv";
my %all;
load_csv %all, "$subdir/all.csv";
local $complete = 1;
local @lines;
emit_header 'addresses';
emit_addr 'translation_vector',%globals,'world','world.raws.language.translations';
emit_addr 'language_vector',%globals,'world','world.raws.language.words';
emit_addr 'creature_vector',%globals,'world','world.units.all';
emit_addr 'active_creature_vector',%globals,'world','world.units.active';
emit_addr 'dwarf_race_index',%globals,'ui','ui.race_id';
emit_addr 'squad_vector',%globals,'world','world.squads.all';
emit_addr 'current_year',%globals,'cur_year','cur_year';
emit_addr 'cur_year_tick',%globals,'cur_year_tick','cur_year_tick';
emit_addr 'dwarf_civ_index',%globals,'ui','ui.civ_id';
emit_addr 'races_vector',%globals,'world','world.raws.creatures.all';
emit_addr 'reactions_vector',%globals,'world','world.raws.reactions';
emit_addr 'events_vector',%globals,'world','world.history.events';
emit_addr 'historical_figures_vector',%globals,'world','world.history.figures';
emit_addr 'fake_identities_vector',%globals,'world','world.identities.all';
emit_addr 'fortress_entity',%globals,'ui','ui.main.fortress_entity';
emit_addr 'historical_entities_vector',%globals,'world','world.entities.all';
emit_addr 'itemdef_weapons_vector',%globals,'world','world.raws.itemdefs.weapons';
emit_addr 'itemdef_trap_vector',%globals,'world','world.raws.itemdefs.trapcomps';
emit_addr 'itemdef_toy_vector',%globals,'world','world.raws.itemdefs.toys';
emit_addr 'itemdef_tool_vector',%globals,'world','world.raws.itemdefs.tools';
emit_addr 'itemdef_instrument_vector',%globals,'world','world.raws.itemdefs.instruments';
emit_addr 'itemdef_armor_vector',%globals,'world','world.raws.itemdefs.armor';
emit_addr 'itemdef_ammo_vector',%globals,'world','world.raws.itemdefs.ammo';
emit_addr 'itemdef_siegeammo_vector',%globals,'world','world.raws.itemdefs.siege_ammo';
emit_addr 'itemdef_glove_vector',%globals,'world','world.raws.itemdefs.gloves';
emit_addr 'itemdef_shoe_vector',%globals,'world','world.raws.itemdefs.shoes';
emit_addr 'itemdef_shield_vector',%globals,'world','world.raws.itemdefs.shields';
emit_addr 'itemdef_helm_vector',%globals,'world','world.raws.itemdefs.helms';
emit_addr 'itemdef_pant_vector',%globals,'world','world.raws.itemdefs.pants';
emit_addr 'itemdef_food_vector',%globals,'world','world.raws.itemdefs.food';
emit_addr 'colors_vector',%globals,'world','world.raws.language.colors';
emit_addr 'shapes_vector',%globals,'world','world.raws.language.shapes';
emit_addr 'base_materials',%globals,'world','world.raws.mat_table.builtin';
emit_addr 'inorganics_vector',%globals,'world','world.raws.inorganics';
emit_addr 'plants_vector',%globals,'world','world.raws.plants.all';
emit_addr 'material_templates_vector',%globals,'world','world.raws.material_templates';
emit_addr 'all_syndromes_vector',%globals,'world','world.raws.syndromes.all';
emit_addr 'world_data',%globals,'world','world.world_data';
emit_addr 'active_sites_vector',%all,'world_data','active_site';
emit_addr 'world_site_type',%all,'world_site','type';
emit_addr 'weapons_vector',%globals,'world','world.items.other[WEAPON]';
emit_addr 'shields_vector',%globals,'world','world.items.other[SHIELD]';
emit_addr 'quivers_vector',%globals,'world','world.items.other[QUIVER]';
emit_addr 'crutches_vector',%globals,'world','world.items.other[CRUTCH]';
emit_addr 'backpacks_vector',%globals,'world','world.items.other[BACKPACK]';
emit_addr 'ammo_vector',%globals,'world','world.items.other[AMMO]';
emit_addr 'flasks_vector',%globals,'world','world.items.other[FLASK]';
emit_addr 'pants_vector',%globals,'world','world.items.other[PANTS]';
emit_addr 'armor_vector',%globals,'world','world.items.other[ARMOR]';
emit_addr 'shoes_vector',%globals,'world','world.items.other[SHOES]';
emit_addr 'helms_vector',%globals,'world','world.items.other[HELM]';
emit_addr 'gloves_vector',%globals,'world','world.items.other[GLOVES]';
emit_addr 'artifacts_vector',%globals,'world','world.artifacts.all';
emit_header 'offsets';
emit_addr 'word_table',%all,'language_translation','words';
push @lines, 'string_buffer_offset=0x0000';
emit_header 'word_offsets';
emit_addr 'base',%all,'language_word','word';
emit_addr 'noun_singular',%all,'language_word','forms[Noun]';
emit_addr 'noun_plural',%all,'language_word','forms[NounPlural]';
emit_addr 'adjective',%all,'language_word','forms[Adjective]';
emit_addr 'verb',%all,'language_word','forms[Verb]';
emit_addr 'present_simple_verb',%all,'language_word','forms[Verb3rdPerson]';
emit_addr 'past_simple_verb',%all,'language_word','forms[VerbPast]';
emit_addr 'past_participle_verb',%all,'language_word','forms[VerbPassive]';
emit_addr 'present_participle_verb',%all,'language_word','forms[VerbGerund]';
emit_addr 'words',%all,'language_name','words';
emit_addr 'word_type',%all,'language_name','parts_of_speech';
emit_addr 'language_id',%all,'language_name','language';
emit_header 'general_ref_offsets';
emit_addr 'ref_type',%all,'general_ref::vtable','getType';
emit_addr 'artifact_id',%all,'general_ref_artifact','artifact_id';
emit_addr 'item_id',%all,'general_ref_item','item_id';
emit_header 'race_offsets';
emit_addr 'name_singular',%all,'creature_raw','name';
emit_addr 'name_plural',%all,'creature_raw','name',$ssize;
emit_addr 'adjective',%all,'creature_raw','name',$ssize*2;
emit_addr 'baby_name_singular',%all,'creature_raw','general_baby_name';
emit_addr 'baby_name_plural',%all,'creature_raw','general_baby_name',$ssize;
emit_addr 'child_name_singular',%all,'creature_raw','general_child_name';
emit_addr 'child_name_plural',%all,'creature_raw','general_child_name',$ssize;
emit_addr 'pref_string_vector',%all,'creature_raw','prefstring';
emit_addr 'castes_vector',%all,'creature_raw','caste';
emit_addr 'pop_ratio_vector',%all,'creature_raw','pop_ratio';
emit_addr 'materials_vector',%all,'creature_raw','material';
emit_addr 'flags',%all,'creature_raw','flags';
emit_addr 'tissues_vector',%all,'creature_raw','tissue';
emit_header 'caste_offsets';
emit_addr 'caste_name',%all,'caste_raw','caste_name';
emit_addr 'caste_descr',%all,'caste_raw','description';
emit_addr 'caste_trait_ranges',%all,'caste_raw','personality.a';
emit_addr 'caste_phys_att_ranges',%all,'caste_raw','attributes.phys_att_range';
emit_addr 'baby_age',%all,'caste_raw','misc.baby_age';
emit_addr 'child_age',%all,'caste_raw','misc.child_age';
emit_addr 'adult_size',%all,'caste_raw','misc.adult_size';
emit_addr 'flags',%all,'caste_raw','flags';
emit_addr 'body_info',%all,'caste_raw','body_info';
emit_addr 'skill_rates',%all,'caste_raw','skill_rates';
emit_addr 'caste_att_rates',%all,'caste_raw','attributes.phys_att_rates';
emit_addr 'caste_att_caps',%all,'caste_raw','attributes.phys_att_cap_perc';
emit_addr 'shearable_tissues_vector',%all,'caste_raw','shearable_tissue_layer';
emit_addr 'extracts',%all,'caste_raw','extracts.extract_matidx';
emit_header 'hist_entity_offsets';
emit_addr 'beliefs',%all,'historical_entity','resources.values';
emit_addr 'squads',%all,'historical_entity','squads';
emit_addr 'positions',%all,'historical_entity','positions.own';
emit_addr 'assignments',%all,'historical_entity','positions.assignments';
emit_addr 'assign_hist_id',%all,'entity_position_assignment','histfig';
emit_addr 'assign_position_id',%all,'entity_position_assignment','position_id';
emit_addr 'position_id',%all,'entity_position','id';
emit_addr 'position_name',%all,'entity_position','name';
emit_addr 'position_female_name',%all,'entity_position','name_female';
emit_addr 'position_male_name',%all,'entity_position','name_male';
emit_header 'hist_figure_offsets';
emit_addr 'hist_race',%all,'historical_figure','race';
emit_addr 'hist_name',%all,'historical_figure','name';
emit_addr 'id',%all,'historical_figure','id';
emit_addr 'hist_fig_info',%all,'historical_figure','info';
emit_addr 'reputation',%all,'historical_figure_info','reputation';
emit_addr 'current_ident',%all,'historical_figure_info::anon13','cur_identity';
emit_addr 'fake_name',%all,'identity','name';
emit_addr 'fake_birth_year',%all,'identity','birth_year';
emit_addr 'fake_birth_time',%all,'identity','birth_second';
emit_addr 'kills',%all,'historical_figure_info','kills';
emit_addr 'killed_race_vector',%all,'historical_kills','killed_race';
emit_addr 'killed_undead_vector',%all,'historical_kills','killed_undead';
emit_addr 'killed_counts_vector',%all,'historical_kills','killed_count';
emit_header 'hist_event_offsets';
emit_addr 'event_year',%all,'history_event','year';
emit_addr 'id',%all,'history_event','id';
emit_addr 'killed_hist_id',%all,'history_event_hist_figure_diedst','victim_hf';
emit_header 'item_offsets';
if ($subdir eq 'osx') {
push @lines, 'item_type=0x0004';
} else {
push @lines, 'item_type=0x0001';
}
emit_addr 'item_def',%all,'item_ammost','subtype'; #currently same for all
emit_addr 'id',%all,'item','id';
emit_addr 'general_refs',%all,'item','general_refs';
emit_addr 'stack_size',%all,'item_actual','stack_size';
emit_addr 'wear',%all,'item_actual','wear';
emit_addr 'mat_type',%all,'item_crafted','mat_type';
emit_addr 'mat_index',%all,'item_crafted','mat_index';
emit_addr 'quality',%all,'item_crafted','quality';
emit_header 'item_subtype_offsets';
emit_addr 'sub_type',%all,'itemdef','subtype';
emit_addr 'name',%all,'itemdef_armorst','name';
emit_addr 'name_plural',%all,'itemdef_armorst','name_plural';
emit_addr 'adjective',%all,'itemdef_armorst','name_preplural';
emit_header 'item_filter_offsets';
emit_addr 'item_subtype',%all,'item_filter_spec','item_subtype';
emit_addr 'mat_class',%all,'item_filter_spec','material_class';
emit_addr 'mat_type',%all,'item_filter_spec','mattype';
emit_addr 'mat_index',%all,'item_filter_spec','matindex';
emit_header 'weapon_subtype_offsets';
emit_addr 'single_size',%all,'itemdef_weaponst','two_handed';
emit_addr 'multi_size',%all,'itemdef_weaponst','minimum_size';
emit_addr 'ammo',%all,'itemdef_weaponst','ranged_ammo';
emit_addr 'melee_skill',%all,'itemdef_weaponst','skill_melee';
emit_addr 'ranged_skill',%all,'itemdef_weaponst','skill_ranged';
emit_header 'armor_subtype_offsets';
emit_addr 'layer',%all,'armor_properties','layer';
emit_addr 'mat_name',%all,'itemdef_armorst','material_placeholder';
emit_addr 'other_armor_level',%all,'itemdef_helmst','armorlevel';
emit_addr 'armor_adjective',%all,'itemdef_armorst','adjective';
emit_addr 'armor_level',%all,'itemdef_armorst','armorlevel';
emit_addr 'chest_armor_properties',%all,'itemdef_armorst','props';
emit_addr 'pants_armor_properties',%all,'itemdef_pantsst','props';
emit_addr 'other_armor_properties',%all,'itemdef_helmst','props';
emit_header 'material_offsets';
emit_addr 'solid_name',%all,'material_common','state_name[Solid]';
emit_addr 'liquid_name',%all,'material_common','state_name[Liquid]';
emit_addr 'gas_name',%all,'material_common','state_name[Gas]';
emit_addr 'powder_name',%all,'material_common','state_name[Powder]';
emit_addr 'paste_name',%all,'material_common','state_name[Paste]';
emit_addr 'pressed_name',%all,'material_common','state_name[Pressed]';
emit_addr 'flags',%all,'material_common','flags';
emit_addr 'inorganic_materials_vector',%all,'inorganic_raw','material';
emit_addr 'inorganic_flags',%all,'inorganic_raw','flags';
emit_header 'plant_offsets';
emit_addr 'name',%all,'plant_raw','name';
emit_addr 'name_plural',%all,'plant_raw','name_plural';
emit_addr 'name_leaf_plural',%all,'plant_raw','leaves_plural';
emit_addr 'name_seed_plural',%all,'plant_raw','seed_plural';
emit_addr 'materials_vector',%all,'plant_raw','material';
emit_addr 'flags',%all,'plant_raw','flags';
emit_header 'descriptor_offsets';
emit_addr 'color_name',%all,'descriptor_color','name';
emit_addr 'shape_name_plural',%all,'descriptor_shape','name_plural';
emit_header 'health_offsets';
emit_addr 'parent_id',%all,'body_part_raw','con_part_id';
emit_addr 'layers_vector',%all,'body_part_raw','layers';
emit_addr 'number',%all,'body_part_raw','number';
emit_addr 'names_vector',%all,'body_part_raw','name_singular';
emit_addr 'names_plural_vector',%all,'body_part_raw','name_plural';
emit_addr 'layer_tissue',%all,'body_part_layer_raw','tissue_id';
emit_addr 'layer_global_id',%all,'body_part_layer_raw','layer_id';
emit_addr 'tissue_name',%all,'tissue_template','tissue_name_singular';
emit_addr 'tissue_flags',%all,'tissue_template','flags';
emit_header 'dwarf_offsets';
emit_addr 'first_name',%all,'unit','name',lookup_addr(%all,'language_name','first_name');
emit_addr 'nick_name',%all,'unit','name',lookup_addr(%all,'language_name','nickname');
emit_addr 'last_name',%all,'unit','name',lookup_addr(%all,'language_name','words');
emit_addr 'custom_profession',%all,'unit','custom_profession';
emit_addr 'profession',%all,'unit','profession';
emit_addr 'race',%all,'unit','race';
emit_addr 'flags1',%all,'unit','flags1';
emit_addr 'flags2',%all,'unit','flags2';
emit_addr 'flags3',%all,'unit','flags3';
emit_addr 'caste',%all,'unit','caste';
emit_addr 'sex',%all,'unit','sex';
emit_addr 'id',%all,'unit','id';
emit_addr 'animal_type',%all,'unit','training_level';
emit_addr 'civ',%all,'unit','civ_id';
emit_addr 'specific_refs',%all,'unit','specific_refs';
emit_addr 'squad_id',%all,'unit','military.squad_id';
emit_addr 'squad_position',%all,'unit','military.squad_position';
emit_addr 'recheck_equipment',%all,'unit','military.pickup_flags';
emit_addr 'mood',%all,'unit','mood';
emit_addr 'birth_year',%all,'unit','relations.birth_year';
emit_addr 'birth_time',%all,'unit','relations.birth_time';
emit_addr 'pet_owner_id',%all,'unit','relations.pet_owner_id';
emit_addr 'current_job',%all,'unit','job.current_job';
emit_addr 'physical_attrs',%all,'unit','body.physical_attrs';
emit_addr 'body_size',%all,'unit','appearance.body_modifiers';
emit_addr 'size_info',%all,'unit','body.size_info';
emit_addr 'curse',%all,'unit','curse.name';
emit_addr 'curse_add_flags1',%all,'unit','curse.add_tags1';
emit_addr 'turn_count',%all,'unit','curse.time_on_site';
emit_addr 'souls',%all,'unit','status.souls';
emit_addr 'states',%all,'unit','status.misc_traits';
emit_addr 'labors',%all,'unit','status.labors';
emit_addr 'hist_id',%all,'unit','hist_figure_id';
emit_addr 'artifact_name',%all,'unit','status.artifact_name';
emit_addr 'active_syndrome_vector',%all,'unit','syndromes.active';
emit_addr 'syn_sick_flag',%all,'unit_syndrome','flags.is_sick';
emit_addr 'unit_health_info',%all,'unit','health';
emit_addr 'temp_mood',%all,'unit','counters.soldier_mood';
emit_addr 'counters1',%all,'unit','counters.winded';
emit_addr 'counters2',%all,'unit','counters.pain';
emit_addr 'counters3',%all,'unit','counters2.paralysis';
emit_addr 'limb_counters',%all,'unit','status2.limbs_stand_max';
emit_addr 'blood',%all,'unit','body.blood_max';
emit_addr 'body_component_info',%all,'unit','body.components';
emit_addr 'layer_status_vector',%all,'body_component_info','layer_status';
emit_addr 'wounds_vector',%all,'unit','body.wounds';
emit_addr 'mood_skill',%all,'unit','job.mood_skill';
emit_addr 'used_items_vector',%all,'unit','used_items';
emit_addr 'affection_level',%all,'unit_item_use','affection_level';
emit_addr 'inventory',%all,'unit','inventory';
emit_addr 'inventory_item_mode',%all,'unit_inventory_item','mode';
emit_addr 'inventory_item_bodypart',%all,'unit_inventory_item','body_part_id';
emit_header 'syndrome_offsets';
emit_addr 'cie_effects',%all,'syndrome','ce';
emit_addr 'cie_end',%all,'creature_interaction_effect','end';
emit_addr 'cie_first_perc',%all,'creature_interaction_effect_phys_att_changest','phys_att_perc'; #same for mental
emit_addr 'cie_phys',%all,'creature_interaction_effect_phys_att_changest','phys_att_add';
emit_addr 'cie_ment',%all,'creature_interaction_effect_ment_att_changest','ment_att_add';
emit_addr 'syn_classes_vector',%all,'syndrome','syn_class';
emit_addr 'trans_race_id',%all,'creature_interaction_effect_body_transformationst','race';
emit_header 'unit_wound_offsets';
emit_addr 'parts',%all,'unit_wound','parts';
emit_addr 'id',%all,'unit_wound::anon2','body_part_id';
emit_addr 'layer',%all,'unit_wound::anon2','layer_idx';
emit_addr 'general_flags',%all,'unit_wound','flags';
emit_addr 'flags1',%all,'unit_wound::anon2','flags1';
emit_addr 'flags2',%all,'unit_wound::anon2','flags2';
emit_addr 'effects_vector',%all,'unit_wound::anon2','effect_type';
emit_addr 'bleeding',%all,'unit_wound::anon2','bleeding';
emit_addr 'pain',%all,'unit_wound::anon2','pain';
emit_addr 'cur_pen',%all,'unit_wound::anon2','cur_penetration_perc';
emit_addr 'max_pen',%all,'unit_wound::anon2','max_penetration_perc';
emit_header 'soul_details';
emit_addr 'name',%all,'unit_soul','name';
emit_addr 'orientation',%all,'unit_soul','orientation_flags';
emit_addr 'mental_attrs',%all,'unit_soul','mental_attrs';
emit_addr 'skills',%all,'unit_soul','skills';
emit_addr 'preferences',%all,'unit_soul','preferences';
emit_addr 'personality',%all,'unit_soul','personality';
emit_addr 'beliefs',%all,'unit_personality','values';
emit_addr 'emotions',%all,'unit_personality','emotions';
emit_addr 'goals',%all,'unit_personality','dreams';
emit_addr 'goal_realized',%all,'unit_personality::anon5','unk8';
emit_addr 'traits',%all,'unit_personality','traits';
emit_addr 'stress_level',%all,'unit_personality','stress_level';
emit_header 'emotion_offsets';
emit_addr 'emotion_type',%all,'unit_personality::anon4','type';
emit_addr 'strength',%all,'unit_personality::anon4','strength';
emit_addr 'thought_id',%all,'unit_personality::anon4','thought';
emit_addr 'sub_id',%all,'unit_personality::anon4','subthought';
emit_addr 'level',%all,'unit_personality::anon4','severity';
emit_addr 'year',%all,'unit_personality::anon4','year';
emit_addr 'year_tick',%all,'unit_personality::anon4','year_tick';
emit_header 'job_details';
emit_addr 'id',%all,'job','job_type';
emit_addr 'mat_type',%all,'job','mat_type';
emit_addr 'mat_index',%all,'job','mat_index';
emit_addr 'mat_category',%all,'job','material_category';
emit_addr 'on_break_flag',%all,'misc_trait_type','OnBreak';
emit_addr 'sub_job_id',%all,'job','reaction_name';
emit_addr 'reaction',%all,'reaction','name';
emit_addr 'reaction_skill',%all,'reaction','skill';
emit_header 'squad_offsets';
emit_addr 'id',%all,'squad','id';
emit_addr 'name',%all,'squad','name';
emit_addr 'alias',%all,'squad','alias';
emit_addr 'members',%all,'squad','positions';
emit_addr 'carry_food',%all,'squad','carry_food';
emit_addr 'carry_water',%all,'squad','carry_water';
emit_addr 'ammunition',%all,'squad','ammunition';
emit_addr 'quiver',%all,'squad_position','quiver';
emit_addr 'backpack',%all,'squad_position','backpack';
emit_addr 'flask',%all,'squad_position','flask';
emit_addr 'armor_vector',%all,'squad_position','uniform[body]';
emit_addr 'helm_vector',%all,'squad_position','uniform[head]';
emit_addr 'pants_vector',%all,'squad_position','uniform[pants]';
emit_addr 'gloves_vector',%all,'squad_position','uniform[gloves]';
emit_addr 'shoes_vector',%all,'squad_position','uniform[shoes]';
emit_addr 'shield_vector',%all,'squad_position','uniform[shield]';
emit_addr 'weapon_vector',%all,'squad_position','uniform[weapon]';
emit_addr 'uniform_item_filter',%all,'squad_uniform_spec','item_filter';
emit_addr 'uniform_indiv_choice',%all,'squad_uniform_spec','indiv_choice';
my $body_str = join("\n",@lines);
my $complete_str = ($complete ? 'true' : 'false');
open OUT, ">$subdir/therapist.ini" or die "Cannot open output file";
print OUT <<__END__;
[info]
checksum=0x$checksum
version_name=$version
complete=$complete_str
$body_str
[valid_flags_2]
size=0
[invalid_flags_1]
size=10
1\\name=a zombie
1\\value=0x00001000
2\\name=a skeleton
2\\value=0x00002000
3\\name=a merchant
3\\value=0x00000040
4\\name=outpost liason or diplomat
4\\value=0x00000800
5\\name=an invader or hostile
5\\value=0x00020000
6\\name=an invader or hostile
6\\value=0x00080000
7\\name=resident, invader or ambusher
7\\value=0x00600000
8\\name=part of a merchant caravan
8\\value=0x00000080
9\\name="Dead, Jim."
9\\value=0x00000002
10\\name=marauder
10\\value=0x00000010
[invalid_flags_2]
size=5
1\\name="killed, Jim."
1\\value=0x00000080
2\\name=from the Underworld. SPOOKY!
2\\value=0x00040000
3\\name=resident
3\\value=0x00080000
4\\name=uninvited visitor
4\\value=0x00400000
5\\name=visitor
5\\value=0x00800000
[invalid_flags_3]
size=1
1\\name=a ghost
1\\value=0x00001000
__END__
close OUT;
}
generate_dt_ini 'linux', $version, substr($hash,0,8), 4;
generate_dt_ini 'windows', $version.' (graphics)', $timestamp, 0x1C;
generate_dt_ini 'osx', $version, substr($hash,0,8), 4;

@ -35,7 +35,6 @@ if args.showunitid or args.showpos then
printall(df.global.cursor) printall(df.global.cursor)
end end
else else
local teleportSettings=getArgsTogether(args)
local unit = args.unit and df.unit.find(args.unit) or dfhack.gui.getSelectedUnit(true) local unit = args.unit and df.unit.find(args.unit) or dfhack.gui.getSelectedUnit(true)
local pos = not(not args.x or not args.y or not args.z) and {x=args.x,y=args.y,z=args.z} or df.global.cursor local pos = not(not args.x or not args.y or not args.z) and {x=args.x,y=args.y,z=args.z} or df.global.cursor