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

Conflicts:
	plugins/remotefortressreader.cpp
develop
JapaMala 2014-08-15 19:15:00 +05:30
commit 5add8c433d
62 changed files with 398 additions and 2530 deletions

@ -58,8 +58,8 @@ if (NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl OR NOT EXISTS ${dfhac
endif()
# set up versioning.
set(DF_VERSION "0.40.05")
SET(DFHACK_RELEASE "r0" CACHE STRING "Current release revision.")
set(DF_VERSION "0.40.08")
SET(DFHACK_RELEASE "r1" CACHE STRING "Current release revision.")
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
add_definitions(-DDFHACK_VERSION="${DFHACK_VERSION}")

@ -1591,6 +1591,17 @@ Basic painting functions:
Returns the string that should be used to represent the given
logical keybinding on the screen in texts like "press Key to ...".
* ``dfhack.screen.keyToChar(key)``
Returns the integer character code of the string input
character represented by the given logical keybinding,
or *nil* if not a string input key.
* ``dfhack.screen.charToKey(charcode)``
Returns the keybinding representing the given string input
character, or *nil* if impossible.
The "pen" argument used by functions above may be represented by
a table with the following possible fields:

15
NEWS

@ -1,5 +1,7 @@
DFHack future
DFHack v0.40.08-r1
Internals:
supported per save script folders
Items module: added createItem function
@ -12,19 +14,18 @@ DFHack future
UNIT_ATTACK
UNLOAD
INTERACTION
sorted CMakeLists for plugins and devel plugins
New scripts:
lua/ //lua module folder
lua/
repeat-util.lua
makes it easier to make things repeat indefinitely
syndrome-util.lua
makes it easier to deal with unit syndromes
scripts/
forum-dwarves.lua
helps copies df viewscreens to a file
helps copy df viewscreens to a file
full-heal.lua
fully heals a unit
fully heal a unit
remove-wear.lua
removes wear from all items in the fort
repeat.lua
@ -40,8 +41,6 @@ DFHack future
makes it so civs don't bring barrels full of blood ichor or goo
feeding-timers.lua
reset the feeding timers of all units
growth-bug.lua
fixes the growth bug
scripts/gui/
hack-wish.lua
creates items out of any material
@ -50,6 +49,8 @@ DFHack future
scripts/modtools/
add-syndrome.lua
add a syndrome to a unit or remove one
anonymous-script.lua
execute an lua script defined by a string. For example, 'scripts/modtools/anonymous-script "print(args[2] .. args[1])" one two' will print 'twoone'. Useful for the *-trigger scripts.
force.lua
forces events: caravan, migrants, diplomat, megabeast, curiousbeast, mischievousbeast, flier, siege, nightcreature
item-trigger.lua
@ -95,7 +96,7 @@ DFHack future
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/printArgs.lua
devel/printArgs plugin converted to scripts/devel/print-args.lua
DFHack v0.34.11-r5

@ -2433,7 +2433,8 @@ instantly duplicates the job.</li>
</div>
<div class="section" id="stockflow">
<h3><a class="toc-backref" href="#id109">stockflow</a></h3>
<p>Allows the fortress bookkeeper to queue jobs through the manager.</p>
<p>Allows the fortress bookkeeper to queue jobs through the manager,
based on space or items available in stockpiles.</p>
<p>Usage:</p>
<blockquote>
<dl class="docutils">

@ -1478,7 +1478,8 @@ Duplicate the selected job in a workshop:
stockflow
---------
Allows the fortress bookkeeper to queue jobs through the manager.
Allows the fortress bookkeeper to queue jobs through the manager,
based on space or items available in stockpiles.
Usage:
@ -1486,12 +1487,15 @@ Usage:
Enable the plugin.
``stockflow disable``
Disable the plugin.
``stockflow fast``
Enable the plugin in fast mode.
``stockflow list``
List any work order settings for your stockpiles.
``stockflow status``
Display whether the plugin is enabled.
While enabled, the 'q' menu of each stockpile will have two new options:
* j: Select a job to order, from an interface like the manager's screen.
* J: Cycle between several options for how many such jobs to order.
@ -1499,6 +1503,9 @@ Whenever the bookkeeper updates stockpile records, new work orders will
be placed on the manager's queue for each such selection, reduced by the
number of identical orders already in the queue.
In fast mode, new work orders will be enqueued once per day, instead of
waiting for the bookkeeper.
workflow
--------
Manage control of repeat jobs.

@ -129,20 +129,10 @@ tweak stable-cursor
# stop military from considering training as 'patrol duty'
tweak patrol-duty
# display creature weight in build plate menu as ??K, instead of (???df: Max
tweak readable-build-plate
# improve FPS by squashing endless item temperature update loops
tweak stable-temp
# speed up items reaching temp equilibrium with environment by
# capping the rate to no less than 1 degree change per 500 frames
# Note: will also cause stuff to melt faster in magma etc
tweak fast-heat 500
# stop stacked liquid/bar/thread/cloth items from lasting forever
# if used in reactions that use only a fraction of the dimension.
tweak fix-dimensions
# might be fixed by DF
# tweak fix-dimensions
# make reactions requiring containers usable in advmode - the issue is
# that the screen asks for those reagents to be selected directly
@ -158,10 +148,7 @@ tweak military-stable-assign
tweak military-color-assigned
# remove inverse dependency of squad training speed on unit list size and use more sparring
tweak military-training
# prevent crash if bees die in a hive with ungathered products by insta-gathering them
tweak hive-crash
# tweak military-training
# make crafted cloth items wear out with time like in old versions (bug 6003)
tweak craft-age-wear
@ -201,32 +188,6 @@ soundsense-season
# write identifying information about the fort to gamelog on world load
log-region
# patch the material objects in memory to fix cloth stockpiles
fix/cloth-stockpile enable
# civs don't bring blood
#:lua dfhack.onStateChange.onLoadBloodDel = function(state) if state == SC_WORLD_LOADED then dfhack.run_command('repeat -time 1 -timeUnits months -command fix/blood-del') end end
# run growth bug regularly
#:lua dfhack.onStateChange.onLoadGrowthBug = function(state) if state == SC_WORLD_LOADED then dfhack.run_command('repeat -time 1 -timeUnits months -command fix/growth-bug') end end
#######################################################
# Apply binary patches at runtime #
#######################################################
# Bug 5994 - items teleported when removing a construction
binpatch apply deconstruct-teleport
binpatch apply deconstruct-heapfall
# Bug 4406 - hospital overstocking on all items
binpatch apply hospital-overstocking
# Bug 808 - custom reactions completely using up all of their reagents
binpatch apply custom-reagent-size
# Bug 4530 - marksdwarves not training when quiver full of combat-only ammo
binpatch apply training-ammo
# Bug 1445 - weapon racks broken, armor stand capacity too low
binpatch apply weaponrack-unassign
binpatch apply armorstand-capacity

@ -85,14 +85,14 @@ IF(WIN32)
ENDIF()
SET(MAIN_SOURCES_LINUX
Console-linux.cpp
Console-posix.cpp
Hooks-linux.cpp
PlugLoad-linux.cpp
Process-linux.cpp
)
SET(MAIN_SOURCES_DARWIN
Console-darwin.cpp
Console-posix.cpp
PlugLoad-darwin.cpp
Process-darwin.cpp
Hooks-darwin.cpp

@ -1,832 +0,0 @@
/*
https://github.com/peterix/dfhack
A thread-safe logging console with a line editor.
Based on linenoise:
linenoise -- guerrilla line editing library against the idea that a
line editing lib needs to be 20,000 lines of C code.
You can find the latest source code at:
http://github.com/antirez/linenoise
Does a number of crazy assumptions that happen to be true in 99.9999% of
the 2010 UNIX computers around.
------------------------------------------------------------------------
Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
Copyright (c) 2011, Petr Mrázek <peterix@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string.h>
#include <string>
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <errno.h>
#include <deque>
// George Vulov for MacOSX
#ifndef __LINUX__
#define TEMP_FAILURE_RETRY(expr) \
({ long int _res; \
do _res = (long int) (expr); \
while (_res == -1L && errno == EINTR); \
_res; })
#endif
#include "Console.h"
#include "Hooks.h"
using namespace DFHack;
#include "tinythread.h"
using namespace tthread;
static int isUnsupportedTerm(void)
{
static const char *unsupported_term[] = {"dumb","cons25",NULL};
char *term = getenv("TERM");
int j;
if (term == NULL) return 0;
for (j = 0; unsupported_term[j]; j++)
if (!strcasecmp(term,unsupported_term[j])) return 1;
return 0;
}
const char * ANSI_CLS = "\033[2J";
const char * ANSI_BLACK = "\033[22;30m";
const char * ANSI_RED = "\033[22;31m";
const char * ANSI_GREEN = "\033[22;32m";
const char * ANSI_BROWN = "\033[22;33m";
const char * ANSI_BLUE = "\033[22;34m";
const char * ANSI_MAGENTA = "\033[22;35m";
const char * ANSI_CYAN = "\033[22;36m";
const char * ANSI_GREY = "\033[22;37m";
const char * ANSI_DARKGREY = "\033[01;30m";
const char * ANSI_LIGHTRED = "\033[01;31m";
const char * ANSI_LIGHTGREEN = "\033[01;32m";
const char * ANSI_YELLOW = "\033[01;33m";
const char * ANSI_LIGHTBLUE = "\033[01;34m";
const char * ANSI_LIGHTMAGENTA = "\033[01;35m";
const char * ANSI_LIGHTCYAN = "\033[01;36m";
const char * ANSI_WHITE = "\033[01;37m";
const char * RESETCOLOR = "\033[0m";
const char * getANSIColor(const int c)
{
switch (c)
{
case -1: return RESETCOLOR; // HACK! :P
case 0 : return ANSI_BLACK;
case 1 : return ANSI_BLUE; // non-ANSI
case 2 : return ANSI_GREEN;
case 3 : return ANSI_CYAN; // non-ANSI
case 4 : return ANSI_RED; // non-ANSI
case 5 : return ANSI_MAGENTA;
case 6 : return ANSI_BROWN;
case 7 : return ANSI_GREY;
case 8 : return ANSI_DARKGREY;
case 9 : return ANSI_LIGHTBLUE; // non-ANSI
case 10: return ANSI_LIGHTGREEN;
case 11: return ANSI_LIGHTCYAN; // non-ANSI;
case 12: return ANSI_LIGHTRED; // non-ANSI;
case 13: return ANSI_LIGHTMAGENTA;
case 14: return ANSI_YELLOW; // non-ANSI
case 15: return ANSI_WHITE;
default: return "";
}
}
namespace DFHack
{
class Private
{
public:
Private()
{
dfout_C = NULL;
rawmode = false;
in_batch = false;
supported_terminal = false;
state = con_unclaimed;
};
virtual ~Private()
{
//sync();
}
private:
bool read_char(unsigned char & out)
{
FD_ZERO(&descriptor_set);
FD_SET(STDIN_FILENO, &descriptor_set);
FD_SET(exit_pipe[0], &descriptor_set);
int ret = TEMP_FAILURE_RETRY(
select (FD_SETSIZE,&descriptor_set, NULL, NULL, NULL)
);
if(ret == -1)
return false;
if (FD_ISSET(exit_pipe[0], &descriptor_set))
return false;
if (FD_ISSET(STDIN_FILENO, &descriptor_set))
{
// read byte from stdin
ret = TEMP_FAILURE_RETRY(
read(STDIN_FILENO, &out, 1)
);
if(ret == -1)
return false;
return true;
}
return false;
}
public:
void print(const char *data)
{
fputs(data, dfout_C);
}
void print_text(color_ostream::color_value clr, const std::string &chunk)
{
if(!in_batch && state == con_lineedit)
{
disable_raw();
fprintf(dfout_C,"\x1b[1G");
fprintf(dfout_C,"\x1b[0K");
color(clr);
print(chunk.c_str());
reset_color();
enable_raw();
prompt_refresh();
}
else
{
color(clr);
print(chunk.c_str());
}
}
void begin_batch()
{
assert(!in_batch);
in_batch = true;
if (state == con_lineedit)
{
disable_raw();
fprintf(dfout_C,"\x1b[1G");
fprintf(dfout_C,"\x1b[0K");
}
}
void end_batch()
{
assert(in_batch);
flush();
in_batch = false;
if (state == con_lineedit)
{
reset_color();
enable_raw();
prompt_refresh();
}
}
void flush()
{
if (!rawmode)
fflush(dfout_C);
}
/// Clear the console, along with its scrollback
void clear()
{
if(rawmode)
{
const char * clr = "\033c\033[3J\033[H";
::write(STDIN_FILENO,clr,strlen(clr));
}
else
{
print("\033c\033[3J\033[H");
fflush(dfout_C);
}
}
/// Position cursor at x,y. 1,1 = top left corner
void gotoxy(int x, int y)
{
char tmp[64];
sprintf(tmp,"\033[%d;%dH", y,x);
print(tmp);
}
/// Set color (ANSI color number)
void color(Console::color_value index)
{
if(!rawmode)
fprintf(dfout_C,getANSIColor(index));
else
{
const char * colstr = getANSIColor(index);
int lstr = strlen(colstr);
::write(STDIN_FILENO,colstr,lstr);
}
}
/// Reset color to default
void reset_color(void)
{
color(COLOR_RESET);
if(!rawmode)
fflush(dfout_C);
}
/// Enable or disable the caret/cursor
void cursor(bool enable = true)
{
if(enable)
print("\033[?25h");
else
print("\033[?25l");
}
/// Waits given number of milliseconds before continuing.
void msleep(unsigned int msec);
/// get the current number of columns
int get_columns(void)
{
winsize ws;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) return 80;
return ws.ws_col;
}
/// get the current number of rows
int get_rows(void)
{
winsize ws;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) return 25;
return ws.ws_row;
}
/// beep. maybe?
//void beep (void);
void back_word()
{
if (raw_cursor == 0)
return;
raw_cursor--;
while (raw_cursor > 0 && !isalnum(raw_buffer[raw_cursor]))
raw_cursor--;
while (raw_cursor > 0 && isalnum(raw_buffer[raw_cursor]))
raw_cursor--;
if (!isalnum(raw_buffer[raw_cursor]) && raw_cursor != 0)
raw_cursor++;
prompt_refresh();
}
void forward_word()
{
int len = raw_buffer.size();
if (raw_cursor == len)
return;
raw_cursor++;
while (raw_cursor <= len && !isalnum(raw_buffer[raw_cursor]))
raw_cursor++;
while (raw_cursor <= len && isalnum(raw_buffer[raw_cursor]))
raw_cursor++;
if (raw_cursor > len)
raw_cursor = len;
prompt_refresh();
}
/// A simple line edit (raw mode)
int lineedit(const std::string& prompt, std::string& output, recursive_mutex * lock, CommandHistory & ch)
{
output.clear();
reset_color();
this->prompt = prompt;
if (!supported_terminal)
{
print(prompt.c_str());
fflush(dfout_C);
// FIXME: what do we do here???
//SDL_recursive_mutexV(lock);
std::getline(std::cin, output);
//SDL_recursive_mutexP(lock);
return output.size();
}
else
{
int count;
if (enable_raw() == -1) return 0;
if(state == con_lineedit)
return -1;
state = con_lineedit;
count = prompt_loop(lock,ch);
state = con_unclaimed;
disable_raw();
print("\n");
if(count != -1)
{
output = raw_buffer;
}
return count;
}
}
int enable_raw()
{
struct termios raw;
if (!supported_terminal)
return -1;
if (tcgetattr(STDIN_FILENO,&orig_termios) == -1)
return -1;
raw = orig_termios; //modify the original mode
// input modes: no break, no CR to NL, no parity check, no strip char,
// no start/stop output control.
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
// output modes - disable post processing
raw.c_oflag &= ~(OPOST);
// control modes - set 8 bit chars
raw.c_cflag |= (CS8);
// local modes - choing off, canonical off, no extended functions,
// no signal chars (^Z,^C)
#ifdef CONSOLE_NO_CATCH
raw.c_lflag &= ~( ECHO | ICANON | IEXTEN );
#else
raw.c_lflag &= ~( ECHO | ICANON | IEXTEN | ISIG );
#endif
// control chars - set return condition: min number of bytes and timer.
// We want read to return every single byte, without timeout.
raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0;// 1 byte, no timer
// put terminal in raw mode after flushing
if (tcsetattr(STDIN_FILENO,TCSAFLUSH,&raw) < 0)
return -1;
rawmode = 1;
return 0;
}
void disable_raw()
{
/* Don't even check the return value as it's too late. */
if (rawmode && tcsetattr(STDIN_FILENO,TCSAFLUSH,&orig_termios) != -1)
rawmode = 0;
}
void prompt_refresh()
{
char seq[64];
int cols = get_columns();
int plen = prompt.size();
const char * buf = raw_buffer.c_str();
int len = raw_buffer.size();
int cooked_cursor = raw_cursor;
// Use math! This is silly.
while((plen+cooked_cursor) >= cols)
{
buf++;
len--;
cooked_cursor--;
}
while (plen+len > cols)
{
len--;
}
/* Cursor to left edge */
snprintf(seq,64,"\x1b[1G");
if (::write(STDIN_FILENO,seq,strlen(seq)) == -1) return;
/* Write the prompt and the current buffer content */
if (::write(STDIN_FILENO,prompt.c_str(),plen) == -1) return;
if (::write(STDIN_FILENO,buf,len) == -1) return;
/* Erase to right */
snprintf(seq,64,"\x1b[0K");
if (::write(STDIN_FILENO,seq,strlen(seq)) == -1) return;
/* Move cursor to original position. */
snprintf(seq,64,"\x1b[1G\x1b[%dC", (int)(cooked_cursor+plen));
if (::write(STDIN_FILENO,seq,strlen(seq)) == -1) return;
}
int prompt_loop(recursive_mutex * lock, CommandHistory & history)
{
int fd = STDIN_FILENO;
size_t plen = prompt.size();
int history_index = 0;
raw_buffer.clear();
raw_cursor = 0;
/* The latest history entry is always our current buffer, that
* initially is just an empty string. */
const std::string empty;
history.add(empty);
if (::write(fd,prompt.c_str(),prompt.size()) == -1) return -1;
while(1)
{
unsigned char c;
int isok;
unsigned char seq[2], seq2;
lock->unlock();
if(!read_char(c))
{
lock->lock();
return -2;
}
lock->lock();
/* Only autocomplete when the callback is set. It returns < 0 when
* there was an error reading from fd. Otherwise it will return the
* character that should be handled next. */
if (c == 9)
{
/*
if( completionCallback != NULL) {
c = completeLine(fd,prompt,buf,buflen,&len,&pos,cols);
// Return on errors
if (c < 0) return len;
// Read next character when 0
if (c == 0) continue;
}
else
{
// ignore tab
continue;
}
*/
// just ignore tabs
continue;
}
switch(c)
{
case 13: // enter
history.remove();
return raw_buffer.size();
case 3: // ctrl-c
errno = EAGAIN;
return -1;
case 127: // backspace
case 8: // ctrl-h
if (raw_cursor > 0 && raw_buffer.size() > 0)
{
raw_buffer.erase(raw_cursor-1,1);
raw_cursor--;
prompt_refresh();
}
break;
case 27: // escape sequence
lock->unlock();
if (!read_char(seq[0]))
{
lock->lock();
return -2;
}
lock->lock();
if (seq[0] == 'b')
{
back_word();
}
else if (seq[0] == 'f')
{
forward_word();
}
else if(seq[0] == '[')
{
if (!read_char(seq[1]))
{
lock->lock();
return -2;
}
if (seq[1] == 'D')
{
left_arrow:
if (raw_cursor > 0)
{
raw_cursor--;
prompt_refresh();
}
}
else if ( seq[1] == 'C')
{
right_arrow:
/* right arrow */
if (size_t(raw_cursor) != raw_buffer.size())
{
raw_cursor++;
prompt_refresh();
}
}
else if (seq[1] == 'A' || seq[1] == 'B')
{
/* up and down arrow: history */
if (history.size() > 1)
{
/* Update the current history entry before to
* overwrite it with tne next one. */
history[history_index] = raw_buffer;
/* Show the new entry */
history_index += (seq[1] == 'A') ? 1 : -1;
if (history_index < 0)
{
history_index = 0;
break;
}
else if (size_t(history_index) >= history.size())
{
history_index = history.size()-1;
break;
}
raw_buffer = history[history_index];
raw_cursor = raw_buffer.size();
prompt_refresh();
}
}
else if(seq[1] == 'H')
{
// home
raw_cursor = 0;
prompt_refresh();
}
else if(seq[1] == 'F')
{
// end
raw_cursor = raw_buffer.size();
prompt_refresh();
}
else if (seq[1] > '0' && seq[1] < '7')
{
// extended escape
unsigned char seq3[3];
lock->unlock();
if(!read_char(seq2))
{
lock->lock();
return -2;
}
lock->lock();
if (seq[1] == '3' && seq2 == '~' )
{
// delete
if (raw_buffer.size() > 0 && size_t(raw_cursor) < raw_buffer.size())
{
raw_buffer.erase(raw_cursor,1);
prompt_refresh();
}
}
if (!read_char(seq3[0]) || !read_char(seq3[1]))
{
lock->lock();
return -2;
}
if (seq2 == ';')
{
// Format: esc [ n ; n DIRECTION
// Ignore first character (second "n")
if (seq3[1] == 'C')
{
forward_word();
}
else if (seq3[1] == 'D')
{
back_word();
}
}
}
}
break;
default:
if (raw_buffer.size() == size_t(raw_cursor))
{
raw_buffer.append(1,c);
raw_cursor++;
if (plen+raw_buffer.size() < size_t(get_columns()))
{
/* Avoid a full update of the line in the
* trivial case. */
if (::write(fd,&c,1) == -1) return -1;
}
else
{
prompt_refresh();
}
}
else
{
raw_buffer.insert(raw_cursor,1,c);
raw_cursor++;
prompt_refresh();
}
break;
case 21: // Ctrl+u, delete the whole line.
raw_buffer.clear();
raw_cursor = 0;
prompt_refresh();
break;
case 11: // Ctrl+k, delete from current to end of line.
raw_buffer.erase(raw_cursor);
prompt_refresh();
break;
case 1: // Ctrl+a, go to the start of the line
raw_cursor = 0;
prompt_refresh();
break;
case 5: // ctrl+e, go to the end of the line
raw_cursor = raw_buffer.size();
prompt_refresh();
break;
case 12: // ctrl+l, clear screen
clear();
prompt_refresh();
}
}
return raw_buffer.size();
}
FILE * dfout_C;
bool supported_terminal;
// state variables
bool rawmode; // is raw mode active?
termios orig_termios; // saved/restored by raw mode
// current state
enum console_state
{
con_unclaimed,
con_lineedit
} state;
bool in_batch;
std::string prompt; // current prompt string
std::string raw_buffer; // current raw mode buffer
int raw_cursor; // cursor position in the buffer
// thread exit mechanism
int exit_pipe[2];
fd_set descriptor_set;
};
}
Console::Console()
{
d = 0;
inited = false;
// we can't create the mutex at this time. the SDL functions aren't hooked yet.
wlock = new recursive_mutex();
}
Console::~Console()
{
if(inited)
shutdown();
if(wlock)
delete wlock;
if(d)
delete d;
}
bool Console::init(bool sharing)
{
if(sharing)
{
inited = false;
return false;
}
freopen("stdout.log", "w", stdout);
d = new Private();
// make our own weird streams so our IO isn't redirected
d->dfout_C = fopen("/dev/tty", "w");
std::cin.tie(this);
clear();
d->supported_terminal = !isUnsupportedTerm() && isatty(STDIN_FILENO);
// init the exit mechanism
pipe(d->exit_pipe);
FD_ZERO(&d->descriptor_set);
FD_SET(STDIN_FILENO, &d->descriptor_set);
FD_SET(d->exit_pipe[0], &d->descriptor_set);
inited = true;
return true;
}
bool Console::shutdown(void)
{
if(!d)
return true;
lock_guard <recursive_mutex> g(*wlock);
if(d->rawmode)
d->disable_raw();
d->print("\n");
inited = false;
// kill the thing
close(d->exit_pipe[1]);
return true;
}
void Console::begin_batch()
{
//color_ostream::begin_batch();
wlock->lock();
if (inited)
d->begin_batch();
}
void Console::end_batch()
{
if (inited)
d->end_batch();
wlock->unlock();
}
void Console::flush_proxy()
{
lock_guard <recursive_mutex> g(*wlock);
if (inited)
d->flush();
}
void Console::add_text(color_value color, const std::string &text)
{
lock_guard <recursive_mutex> g(*wlock);
if (inited)
d->print_text(color, text);
}
int Console::get_columns(void)
{
lock_guard <recursive_mutex> g(*wlock);
int ret = -1;
if(inited)
ret = d->get_columns();
return ret;
}
int Console::get_rows(void)
{
lock_guard <recursive_mutex> g(*wlock);
int ret = -1;
if(inited)
ret = d->get_rows();
return ret;
}
void Console::clear()
{
lock_guard <recursive_mutex> g(*wlock);
if(inited)
d->clear();
}
void Console::gotoxy(int x, int y)
{
lock_guard <recursive_mutex> g(*wlock);
if(inited)
d->gotoxy(x,y);
}
void Console::cursor(bool enable)
{
lock_guard <recursive_mutex> g(*wlock);
if(inited)
d->cursor(enable);
}
int Console::lineedit(const std::string & prompt, std::string & output, CommandHistory & ch)
{
lock_guard <recursive_mutex> g(*wlock);
int ret = -2;
if(inited)
ret = d->lineedit(prompt,output,wlock,ch);
return ret;
}
void Console::msleep (unsigned int msec)
{
if (msec > 1000) sleep(msec/1000000);
usleep((msec % 1000000) * 1000);
}

@ -46,6 +46,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <iostream>
@ -85,7 +86,7 @@ static int isUnsupportedTerm(void)
if (term == NULL) return 0;
for (j = 0; unsupported_term[j]; j++)
if (!strcasecmp(term,unsupported_term[j])) return 1;
return 0;
return 0;
}
const char * ANSI_CLS = "\033[2J";
@ -625,38 +626,37 @@ namespace DFHack
}
}
break;
default:
if (raw_buffer.size() == size_t(raw_cursor))
{
raw_buffer.append(1,c);
raw_cursor++;
if (plen+raw_buffer.size() < size_t(get_columns()))
{
/* Avoid a full update of the line in the
* trivial case. */
if (::write(fd,&c,1) == -1) return -1;
}
else
{
prompt_refresh();
}
}
else
{
raw_buffer.insert(raw_cursor,1,c);
raw_cursor++;
prompt_refresh();
}
break;
case 21: // Ctrl+u, delete the whole line.
raw_buffer.clear();
case 21: // Ctrl+u, delete from current to beginning of line.
if (raw_cursor > 0)
yank_buffer = raw_buffer.substr(0, raw_cursor);
raw_buffer.erase(0, raw_cursor);
raw_cursor = 0;
prompt_refresh();
break;
case 11: // Ctrl+k, delete from current to end of line.
if (raw_cursor < raw_buffer.size())
yank_buffer = raw_buffer.substr(raw_cursor);
raw_buffer.erase(raw_cursor);
prompt_refresh();
break;
case 25: // Ctrl+y, paste last text deleted with Ctrl+u/k
if (yank_buffer.size())
{
raw_buffer.insert(raw_cursor, yank_buffer);
raw_cursor += yank_buffer.size();
prompt_refresh();
}
break;
case 20: // Ctrl+t, transpose current and previous characters
if (raw_buffer.size() >= 2 && raw_cursor > 0)
{
if (raw_cursor == raw_buffer.size())
raw_cursor--;
std::swap(raw_buffer[raw_cursor - 1], raw_buffer[raw_cursor]);
raw_cursor++;
prompt_refresh();
}
break;
case 1: // Ctrl+a, go to the start of the line
raw_cursor = 0;
prompt_refresh();
@ -668,6 +668,32 @@ namespace DFHack
case 12: // ctrl+l, clear screen
clear();
prompt_refresh();
default:
if (c >= 32) // Space
{
if (raw_buffer.size() == size_t(raw_cursor))
{
raw_buffer.append(1,c);
raw_cursor++;
if (plen+raw_buffer.size() < size_t(get_columns()))
{
/* Avoid a full update of the line in the
* trivial case. */
if (::write(fd,&c,1) == -1) return -1;
}
else
{
prompt_refresh();
}
}
else
{
raw_buffer.insert(raw_cursor,1,c);
raw_cursor++;
prompt_refresh();
}
break;
}
}
}
return raw_buffer.size();
@ -684,9 +710,10 @@ namespace DFHack
con_lineedit
} state;
bool in_batch;
std::string prompt; // current prompt string
std::string raw_buffer; // current raw mode buffer
int raw_cursor; // cursor position in the buffer
std::string prompt; // current prompt string
std::string raw_buffer; // current raw mode buffer
std::string yank_buffer; // last text deleted with Ctrl-K/Ctrl-U
int raw_cursor; // cursor position in the buffer
// thread exit mechanism
int exit_pipe[2];
fd_set descriptor_set;

@ -1924,6 +1924,28 @@ static int screen_doSimulateInput(lua_State *L)
return 0;
}
static int screen_keyToChar(lua_State *L)
{
auto keycode = (df::interface_key)luaL_checkint(L, 1);
int charcode = Screen::keyToChar(keycode);
if (charcode >= 0)
lua_pushinteger(L, charcode);
else
lua_pushnil(L);
return 1;
}
static int screen_charToKey(lua_State *L)
{
auto charcode = (char)luaL_checkint(L, 1);
df::interface_key keycode = Screen::charToKey(charcode);
if (keycode)
lua_pushinteger(L, keycode);
else
lua_pushnil(L);
return 1;
}
}
static const luaL_Reg dfhack_screen_funcs[] = {
@ -1938,6 +1960,8 @@ static const luaL_Reg dfhack_screen_funcs[] = {
{ "dismiss", screen_dismiss },
{ "isDismissed", screen_isDismissed },
{ "_doSimulateInput", screen_doSimulateInput },
{ "keyToChar", screen_keyToChar },
{ "charToKey", screen_charToKey },
{ NULL, NULL }
};

@ -225,7 +225,7 @@ static int lua_dfhack_print(lua_State *S)
{
std::string str = lua_print_fmt(S);
if (color_ostream *out = Lua::GetOutput(S))
*out << str;
out->print("%s", str.c_str());//*out << str;
else
Core::print("%s", str.c_str());
return 0;

@ -195,6 +195,11 @@ namespace DFHack
/// Retrieve the string representation of the bound key.
DFHACK_EXPORT std::string getKeyDisplay(df::interface_key key);
/// Return the character represented by this key, or -1
DFHACK_EXPORT int keyToChar(df::interface_key key);
/// Return the key code matching this character, or NONE
DFHACK_EXPORT df::interface_key charToKey(char code);
/// A painter class that implements a clipping area and cursor/pen state
struct DFHACK_EXPORT Painter : ViewRect {
df::coord2d gcursor;

@ -413,6 +413,29 @@ string Screen::getKeyDisplay(df::interface_key key)
return "?";
}
int Screen::keyToChar(df::interface_key key)
{
if (key < interface_key::STRING_A000 ||
key > interface_key::STRING_A255)
return -1;
if (key < interface_key::STRING_A128)
return key - interface_key::STRING_A000;
return key - interface_key::STRING_A128 + 128;
}
df::interface_key Screen::charToKey(char code)
{
int val = (unsigned char)code;
if (val < 127)
return df::interface_key(interface_key::STRING_A000 + val);
else if (val == 127)
return interface_key::NONE;
else
return df::interface_key(interface_key::STRING_A128 + (val-128));
}
/*
* Base DFHack viewscreen.
*/
@ -654,10 +677,10 @@ int dfhack_lua_viewscreen::do_input(lua_State *L)
lua_pushboolean(L, true);
lua_rawset(L, -3);
if (key >= interface_key::STRING_A000 &&
key <= interface_key::STRING_A255)
int charval = Screen::keyToChar(key);
if (charval >= 0)
{
lua_pushinteger(L, key - interface_key::STRING_A000);
lua_pushinteger(L, charval);
lua_setfield(L, -2, "_STRING");
}
}

@ -1,142 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
0x2ac6b
CC CC CC CC CC
66 39 E8 EB 53
.text:0042B86B loc_42B86B:
.text:0042B86B cmp ax, bp
.text:0042B86E jmp short loc_42B8C3
0x2ac7b
CC CC CC CC CC
E9 96 A2 00 00
.text:0042B87B loc_42B87B:
.text:0042B87B jmp loc_435B16
0x2acc3
CC CC CC CC CC CC CC CC CC CC CC CC CC
75 0A 66 FF 4C 24 16 79 03 58 EB AC C3
.text:0042B8C3 loc_42B8C3:
.text:0042B8C3 jnz short locret_42B8CF
.text:0042B8C5 dec word ptr [esp+16h] ; 4+8+8+2
.text:0042B8CA jns short locret_42B8CF
.text:0042B8CC pop eax
.text:0042B8CD jmp short loc_42B87B
.text:0042B8CF locret_42B8CF:
.text:0042B8CF retn
0x2b2a1
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
66 C7 44 24 0E 01 00 8B 90 44 01 00 00 C3 CC
.text:0042BEA1 loc_42BEA1:
.text:0042BEA1 mov word ptr [esp+0Eh], 1 ; 4+8+2
.text:0042BEA8 mov edx, [eax+144h]
.text:0042BEAE retn
0x34d91
8B 90 44 01 00 00
E8 0B 65 FF FF 90
<<<<
.text:00435991 mov edx, [eax+144h]
====
.text:00435991 call loc_42BEA1
.text:00435996 nop
>>>>
0x34e53
0F 84 BD 00 00 00
E8 6B 5E FF FF 90
<<<<
.text:00435A53 jz loc_435B16
====
.text:00435A53 call loc_42B8C3
.text:00435A58 nop
>>>>
0x34ef3
66 3B C5 74 1E
E8 73 5D FF FF
<<<<
.text:00435AF3 cmp ax, bp
.text:00435AF6 jz short loc_435B16
====
.text:00435AF3 call loc_42B86B
>>>>
basically:
+ int allowed_count = 1; // to mean 2
...
- if (type(item) == new_type)
+ if (type(item) == new_type && --allowed_count < 0)
return false;
to allow up to two items of the same type at the same time
---8<---
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
0002AC6B: CC 66
0002AC6C: CC 39
0002AC6D: CC E8
0002AC6E: CC EB
0002AC6F: CC 53
0002AC7B: CC E9
0002AC7C: CC 96
0002AC7D: CC A2
0002AC7E: CC 00
0002AC7F: CC 00
0002ACC3: CC 75
0002ACC4: CC 0A
0002ACC5: CC 66
0002ACC6: CC FF
0002ACC7: CC 4C
0002ACC8: CC 24
0002ACC9: CC 16
0002ACCA: CC 79
0002ACCB: CC 03
0002ACCC: CC 58
0002ACCD: CC EB
0002ACCE: CC AC
0002ACCF: CC C3
0002B2A1: CC 66
0002B2A2: CC C7
0002B2A3: CC 44
0002B2A4: CC 24
0002B2A5: CC 0E
0002B2A6: CC 01
0002B2A7: CC 00
0002B2A8: CC 8B
0002B2A9: CC 90
0002B2AA: CC 44
0002B2AB: CC 01
0002B2AC: CC 00
0002B2AD: CC 00
0002B2AE: CC C3
00034D91: 8B E8
00034D92: 90 0B
00034D93: 44 65
00034D94: 01 FF
00034D95: 00 FF
00034D96: 00 90
00034E53: 0F E8
00034E54: 84 6B
00034E55: BD 5E
00034E56: 00 FF
00034E57: 00 FF
00034E58: 00 90
00034EF3: 66 E8
00034EF4: 3B 73
00034EF5: C5 5D
00034EF6: 74 FF
00034EF7: 1E FF

@ -1,91 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=808
Original code:
.text:00916BCE mov edi, ebp
.text:00916BD0 call eax
.text:00916BD2 test eax, eax
.text:00916BD4 jnz short loc_916C1C
.text:00916C0A mov edi, ebp
.text:00916C14 mov edi, ebp
Patch:
0x2ac34:
CC CC CC CC CC CC CC CC CC CC CC CC
8B 7C 24 78 8B 3C B7 FF D0 EB 25 CC
.text:0042B834 loc_42B834:
.text:0042B834 mov edi, [esp+78h]
.text:0042B838 mov edi, [edi+esi*4]
.text:0042B83B call eax
.text:0042B83D jmp short unk_42B864
0x2ac64
CC CC CC CC CC CC CC CC CC CC CC CC
85 C0 E9 69 B3 4E 00 CC CC CC CC CC
.text:0042B864 loc_42B864:
.text:0042B864 test eax, eax
.text:0042B866 jmp loc_916BD4
0x515fce
8B FD FF D0 85 C0
E9 61 4C B1 FF 90
.text:00916BCE jmp loc_42B834
.text:00916BD3 nop
.text:00916BD4 loc_916BD4:
0x51600a
8B FD
90 90
.text:00916C0A nop
.text:00916C0B nop
0x516014
8B FD
90 90
.text:00916C14 nop
.text:00916C15 nop
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
0002AC34: CC 8B
0002AC35: CC 7C
0002AC36: CC 24
0002AC37: CC 78
0002AC38: CC 8B
0002AC39: CC 3C
0002AC3A: CC B7
0002AC3B: CC FF
0002AC3C: CC D0
0002AC3D: CC EB
0002AC3E: CC 25
0002AC64: CC 85
0002AC65: CC C0
0002AC66: CC E9
0002AC67: CC 69
0002AC68: CC B3
0002AC69: CC 4E
0002AC6A: CC 00
00515FCE: 8B E9
00515FCF: FD 61
00515FD0: FF 4C
00515FD1: D0 B1
00515FD2: 85 FF
00515FD3: C0 90
0051600A: 8B 90
0051600B: FD 90
00516014: 8B 90
00516015: FD 90

@ -1,61 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
Original code:
.text:008629BD mov edi, [eax+38h]
.text:008629C0 mov eax, [eax+3Ch]
.text:008629C3 mov [esp+1Ch], eax
.text:008629C7 cmp edi, eax
.text:008629C9 jnb short loc_862A22
.text:008629CB jmp short loc_8629D0
.text:008629CD lea ecx, [ecx+0]
...
.text:00862A19 add edi, 4
.text:00862A1C cmp edi, [esp+1Ch]
.text:00862A20 jb short loc_8629D0
Patch:
0x461dbd
8B 78 38 8B 40 3C 89 44 24 1C 3B F8
8B 78 3C 8B 40 38 89 44 24 1C 39 F8
.text:008629BD mov edi, [eax+3Ch]
.text:008629C0 mov eax, [eax+38h]
.text:008629C3 mov [esp+1Ch], eax
.text:008629C7 cmp eax, edi
0x461dcb
EB 03 8D 49 00
83 EF 04 90 90
.text:008629CB sub edi, 4
.text:008629CE nop
.text:008629CF nop
0x461e19
83 C7 04 3B 7C 24 1C 72 AE
83 EF 04 3B 7C 24 1C 73 AE
.text:00862A19 sub edi, 4
.text:00862A1C cmp edi, [esp+1Ch]
.text:00862A20 jnb short loc_8629D0
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
00461DBF: 38 3C
00461DC2: 3C 38
00461DC7: 3B 39
00461DCB: EB 83
00461DCC: 03 EF
00461DCD: 8D 04
00461DCE: 49 90
00461DCF: 00 90
00461E1A: C7 EF
00461E20: 72 73

@ -1,104 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
0x461de2
F6 46 0C 01 74 31
E9 0A 8E BC FF 90
.text:008629E2 jmp near ptr loc_42B7F1 ; << CAVE
.text:008629E7 nop
.text:008629E8 loc_8629E8:
0x2abf1
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
8B 4C 24 2C F6 46 0C 01 75 08 E9 19 72 43 00
.text:0042B7F1 loc_42B7F1:
.text:0042B7F1 mov ecx, [esp+2Ch] ; job
.text:0042B7F5 test byte ptr [esi+0Ch], 1
.text:0042B7F9 jnz short near ptr loc_42B803
.text:0042B7FB coord_test_jfail:
.text:0042B7FB jmp loc_862A19
0x2ac03
CC CC CC CC CC CC CC CC CC CC CC CC CC
8B 41 10 3B 46 04 75 F0 EB 06 CC CC CC
.text:0042B803 loc_42B803:
.text:0042B803 mov eax, [ecx+10h] ; job->pos.(x,y)
.text:0042B806 cmp eax, [esi+4] ; item->pos.(x,y)
.text:0042B809 jnz short coord_test_jfail
.text:0042B80B jmp short near ptr loc_42B813
0x2ac13
CC CC CC CC CC CC CC CC CC CC CC CC CC
66 8B 41 14 66 3B 46 08 75 DE EB 06 CC
text:0042B813 loc_42B813:
.text:0042B813 mov ax, [ecx+14h] ; job->pos.z
.text:0042B817 cmp ax, [esi+8] ; item->pos.z
.text:0042B81B jnz short coord_test_jfail
.text:0042B81D jmp short near ptr loc_42B825
0x2ac25
CC CC CC CC CC CC CC CC CC CC CC
E9 BE 71 43 00 CC CC CC CC CC CC
.text:0042B825 loc_42B825:
.text:0042B825 jmp loc_8629E8
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
0002ABF1: CC 8B
0002ABF2: CC 4C
0002ABF3: CC 24
0002ABF4: CC 2C
0002ABF5: CC F6
0002ABF6: CC 46
0002ABF7: CC 0C
0002ABF8: CC 01
0002ABF9: CC 75
0002ABFA: CC 08
0002ABFB: CC E9
0002ABFC: CC 19
0002ABFD: CC 72
0002ABFE: CC 43
0002ABFF: CC 00
0002AC03: CC 8B
0002AC04: CC 41
0002AC05: CC 10
0002AC06: CC 3B
0002AC07: CC 46
0002AC08: CC 04
0002AC09: CC 75
0002AC0A: CC F0
0002AC0B: CC EB
0002AC0C: CC 06
0002AC13: CC 66
0002AC14: CC 8B
0002AC15: CC 41
0002AC16: CC 14
0002AC17: CC 66
0002AC18: CC 3B
0002AC19: CC 46
0002AC1A: CC 08
0002AC1B: CC 75
0002AC1C: CC DE
0002AC1D: CC EB
0002AC1E: CC 06
0002AC25: CC E9
0002AC26: CC BE
0002AC27: CC 71
0002AC28: CC 43
0002AC29: CC 00
00461DE2: F6 E9
00461DE3: 46 0A
00461DE4: 0C 8E
00461DE5: 01 BC
00461DE6: 74 FF
00461DE7: 31 90

@ -1,62 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4406
1. Include store in hospital jobs when recomputing counters
0x68a63
0F 85 58 01 00 00
90 90 90 90 90 90
<<<<
.text:00469663 jnz loc_4697C1
====
.text:00469663 nop
.text:00469664 nop
.text:00469665 nop
.text:00469666 nop
.text:00469667 nop
.text:00469668 nop
>>>>
- if (job->getBuildingRef(BUILDING_DESTINATION) != this) continue;
+ // NOP
This reference points to the containers, not the hospital civzone.
Since fixing this properly is too hard for a patch, just remove the
check. Most people have only one hospital anyway, and it is better
to err on the side of caution here.
2. Make the stockpiling code increment the right stock counters
0x3dcbf9
8B 0C 90 8B 81 80 00 00 00
8B 3C 90 8B 87 80 00 00 00
<<<<
.text:007DD7F9 mov ecx, [eax+edx*4]
.text:007DD7FC mov eax, [ecx+80h]
====
.text:007DD7F9 mov edi, [eax+edx*4]
.text:007DD7FC mov eax, [edi+80h]
>>>>
- id = civzones[i]->children[child_idx[i]]->id
+ cur_civzone = civzones[i] // existing var from previous loop
+ id = cur_civzone->children[child_idx[i]]->id
The reason being, later code uses that var (at this point containing
useless data) to increment counters and amounts in the hospital.
---8<---
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
00068A63: 0F 90
00068A64: 85 90
00068A65: 58 90
00068A66: 01 90
00068A67: 00 90
00068A68: 00 90
003DCBFA: 0C 3C
003DCBFD: 81 87

@ -1,83 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4530
0x2ac85
CC CC CC CC CC CC CC CC CC CC CC
29 44 24 24 8B 9D 28 01 00 00 C3
.text:0042B885 loc_42B885:
.text:0042B885 sub [esp+24h], eax
.text:0042B889 mov ebx, [ebp+128h]
.text:0042B88F retn
0x2ac94
CC CC CC CC CC CC CC CC CC CC CC CC
89 C1 8B 00 FF 90 34 02 00 00 EB E5
.text:0042B894 loc_42B894:
.text:0042B894 mov ecx, eax
.text:0042B896 mov eax, [eax]
.text:0042B898 call dword ptr [eax+234h]
.text:0042B89E jmp short loc_42B885
0x6e28ff
29 44 24 20
90 90 90 90
<<<<
.text:00AE34FF sub [esp+20h], eax
====
.text:00AE34FF nop
.text:00AE3500 nop
.text:00AE3501 nop
.text:00AE3502 nop
>>>>
0x6e2999
8B 9D 28 01 00 00
E8 F6 82 94 FF 90
<<<<
.text:00AE3599 mov ebx, [ebp+128h]
====
.text:00AE3599 call loc_42B894
.text:00AE359E nop
>>>>
---8<---
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
0002AC85: CC 29
0002AC86: CC 44
0002AC87: CC 24
0002AC88: CC 24
0002AC89: CC 8B
0002AC8A: CC 9D
0002AC8B: CC 28
0002AC8C: CC 01
0002AC8D: CC 00
0002AC8E: CC 00
0002AC8F: CC C3
0002AC94: CC 89
0002AC95: CC C1
0002AC96: CC 8B
0002AC97: CC 00
0002AC98: CC FF
0002AC99: CC 90
0002AC9A: CC 34
0002AC9B: CC 02
0002AC9C: CC 00
0002AC9D: CC 00
0002AC9E: CC EB
0002AC9F: CC E5
006E28FF: 29 90
006E2900: 44 90
006E2901: 24 90
006E2902: 20 90
006E2999: 8B E8
006E299A: 9D F6
006E299B: 28 82
006E299C: 01 94
006E299D: 00 FF
006E299E: 00 90

@ -1,61 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
0x4c05c4
8B 8C 24 80 00 00 00
89 C1 90 90 90 90 90
<<<<
.text:008C11C4 mov ecx, [esp+98h+var_18]
====
.text:008C11C4 mov ecx, eax
.text:008C11C6 nop
.text:008C11C7 nop
.text:008C11C8 nop
.text:008C11C9 nop
.text:008C11CA nop
>>>>
0x4c06a1
8B 8C 24 80 00 00 00
89 C1 90 90 90 90 90
<<<<
.text:008C12A1 mov ecx, [esp+98h+var_18]
====
.text:008C12A1 mov ecx, eax
.text:008C12A3 nop
.text:008C12A4 nop
.text:008C12A5 nop
.text:008C12A6 nop
.text:008C12A7 nop
>>>>
basically:
b_squad_id = building->getSpecificSquad();
- if (b_squad_id != squad->id || !building->canUse(some_squad_id, 4))
+ if (b_squad_id != squad->id || !building->canUse(b_squad_id, 4))
unassign(building);
the reason being, some_other_squad_id contains irrelevant garbage at this point
---8<---
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
004C05C4: 8B 89
004C05C5: 8C C1
004C05C6: 24 90
004C05C7: 80 90
004C05C8: 00 90
004C05C9: 00 90
004C05CA: 00 90
004C06A1: 8B 89
004C06A2: 8C C1
004C06A3: 24 90
004C06A4: 80 90
004C06A5: 00 90
004C06A6: 00 90
004C06A7: 00 90

@ -1,147 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
0x9461
90 90 90 90 90 90 90 90 90 90 90 90 90 90
C7 44 24 18 01 00 00 00 FF A0 44 01 00 00
.text:08051461 sub_8051461 proc near
.text:08051461 mov dword ptr [esp+18h], 1
.text:08051469 jmp dword ptr [eax+144h]
.text:08051469 sub_8051461 endp
0x9548
90 90 90 90 90 90 90 90
FF 4C 24 14 78 08 EB 0B
.text:08051548 loc_8051548:
.text:08051548 dec dword ptr [esp+14h]
.text:0805154C js short loc_8051556
.text:0805154E jmp short loc_805155B
0x9556
90 90 90 90 90 90 90 90 90 90
E9 F6 8C 05 00 E9 D0 8D 05 00
.text:08051556 loc_8051556:
.text:08051556 jmp loc_80AA251
.text:0805155B loc_805155B:
.text:0805155B jmp loc_80AA330
0x9568
90 90 90 90 90 90 90 90
FF 4C 24 14 78 E8 EB 06
.text:08051568 loc_8051568:
.text:08051568 dec [esp+14h]
.text:0805156C js short loc_8051556
.text:0805156E jmp short loc_8051576
0x9576
90 90 90 90 90
E9 4D 8E 05 00
.text:08051576 loc_8051576:
.text:08051576 jmp loc_80AA3C8
0x62243
FF 90 44 01 00 00
E8 19 72 FA FF 90
<<<<
.text:080AA243 call dword ptr [eax+144h]
====
.text:080AA243 call sub_8051461
.text:080AA248 nop
>>>>
0x62369
E9 E3 FE FF FF
E9 DA 71 FA FF
<<<<
.text:080AA369 jmp loc_80AA251
====
.text:080AA369 jmp loc_8051548
>>>>
0x623f6
E9 56 FE FF FF
E9 6D 71 FA FF
<<<<
.text:080AA3F6 jmp loc_80AA251
====
.text:080AA3F6 jmp loc_8051568
>>>>
basically:
+ int allowed_count = 1; // to mean 2
...
- if (type(item) == new_type)
+ if (type(item) == new_type && --allowed_count < 0)
return false;
to allow up to two items of the same type at the same time
---8<---
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
00009461: 90 C7
00009462: 90 44
00009463: 90 24
00009464: 90 18
00009465: 90 01
00009466: 90 00
00009467: 90 00
00009468: 90 00
00009469: 90 FF
0000946A: 90 A0
0000946B: 90 44
0000946C: 90 01
0000946D: 90 00
0000946E: 90 00
00009548: 90 FF
00009549: 90 4C
0000954A: 90 24
0000954B: 90 14
0000954C: 90 78
0000954D: 90 08
0000954E: 90 EB
0000954F: 90 0B
00009556: 90 E9
00009557: 90 F6
00009558: 90 8C
00009559: 90 05
0000955A: 90 00
0000955B: 90 E9
0000955C: 90 D0
0000955D: 90 8D
0000955E: 90 05
0000955F: 90 00
00009568: 90 FF
00009569: 90 4C
0000956A: 90 24
0000956B: 90 14
0000956C: 90 78
0000956D: 90 E8
0000956E: 90 EB
0000956F: 90 06
00009576: 90 E9
00009577: 90 4D
00009578: 90 8E
00009579: 90 05
0000957A: 90 00
00062243: FF E8
00062244: 90 19
00062245: 44 72
00062246: 01 FA
00062247: 00 FF
00062248: 00 90
0006236A: E3 DA
0006236B: FE 71
0006236C: FF FA
000623F7: 56 6D
000623F8: FE 71
000623F9: FF FA

@ -1,40 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=808
for (i = 0; i < num_items; i++)
{
ridx = reagent_idx[i];
sz = reagent_quantity[ridx]; // used quantity
if (sz <= 0) continue;
reag = reagent[ridx];
if (reag->flags.PRESERVE_REAGENT) continue;
rsz = items[i]->getTotalDimension();
<<<<<<<<
if (reag->flags3.ANY_RAW_MATERIAL)
rsz *= BASE_SIZE(items[i]->getType());
if (items[i]->subtractDimension(rsz))
========
/* Not in patch, but necessary for full correctness:
if (reag->flags3.ANY_RAW_MATERIAL)
rsz /= BASE_SIZE(items[i]->getType());
*/
if (reag->flags3.ANY_RAW_MATERIAL)
sz *= BASE_SIZE(items[i]->getType());
if (items[i]->subtractDimension(sz))
>>>>>>>>
destroy_item(items[i]);
reagent_quantity[ridx] -= rsz
if (reagent_quantity[ridx] < 0)
reagent_quantity[ridx] = 0;
}
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
0087F7EF: F8 D8
0087F86F: F8 D8
0087F9AD: C7 C3
0087F9ED: C7 C3

@ -1,83 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
Original code:
.text:087AC378 cmp edx, eax
.text:087AC37A mov [esp+4Ch], eax
.text:087AC37E jnb loc_87A7034
.text:087AC384 mov [esp+48h], edx
.text:087AC388 mov [esp+54h], ebx
...
.text:087AC440 add dword ptr [esp+48h], 4
.text:087AC445 mov ebp, [esp+48h]
.text:087AC449 cmp [esp+4Ch], ebp
.text:087AC44D ja loc_87AC38C
Patch:
0x76437a
89 44 24 4C
89 54 24 4C
.text:087AC37A mov [esp+4Ch], edx
0x764384
89 54 24 48 89 5C 24 54
E8 8A 51 8A FF 90 90 90
.text:087AC384 call sub_8051513
.text:087AC389 nop
.text:087AC38A nop
.text:087AC38B nop
0x764440
83 44 24 48 04 8B 6C 24 48 39 6C 24 4C 0F 87 39 FF FF FF
83 6C 24 48 04 8B 6C 24 48 39 6C 24 4C 0F 86 39 FF FF FF
.text:087AC440 sub dword ptr [esp+48h], 4
.text:087AC445 mov ebp, [esp+48h]
.text:087AC449 cmp [esp+4Ch], ebp
.text:087AC44D jbe loc_87AC38C
0x9513
90 90 90 90 90 90 90 90 90 90 90 90 90
83 E8 04 89 44 24 4C 89 5C 24 58 C3 90
.text:08051513 sub_8051513 proc near
.text:08051513 sub eax, 4
.text:08051516 mov [esp+4Ch], eax ; 48h
.text:0805151A mov [esp+58h], ebx ; 54h
.text:0805151E retn
.text:0805151E sub_8051513 endp
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
00009513: 90 83
00009514: 90 E8
00009515: 90 04
00009516: 90 89
00009517: 90 44
00009518: 90 24
00009519: 90 4C
0000951A: 90 89
0000951B: 90 5C
0000951C: 90 24
0000951D: 90 58
0000951E: 90 C3
0076437B: 44 54
00764384: 89 E8
00764385: 54 8A
00764386: 24 51
00764387: 48 8A
00764388: 89 FF
00764389: 5C 90
0076438A: 24 90
0076438B: 54 90
00764441: 44 6C
0076444E: 87 86

@ -1,139 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
0x7643f8
F6 46 0C 01 74 42
E9 B6 50 8A FF 90
.text:087AC3F8 jmp loc_80514B3 ; << CAVE
.text:087AC3FD nop
.text:087AC3FE loc_87AC3FE:
0x94b3
90 90 90 90 90 90 90 90 90 90 90 90 90
F6 46 0C 01 75 0A E9 82 AF 75 00 90 90
.text:080514B3 loc_80514B3:
.text:080514B3 test byte ptr [esi+0Ch], 1
.text:080514B7 jnz short loc_80514C3
.text:080514B9 coord_test_jfail:
.text:080514B9 jmp loc_87AC440
0x94c3
90 90 90 90 90 90 90 90 90 90 90 90 90
8D 9C 24 60 03 00 00 0F BF 03 EB 07 90
.text:080514C3 loc_80514C3:
.text:080514C3 lea ebx, [esp+360h]
.text:080514CA movsx eax, word ptr [ebx] ; job_z
.text:080514CD jmp short loc_80514D6
0x94d6
90 90 90 90 90 90 90 90 90 90
66 3B 46 08 75 DD EB 05 90 90
.text:080514D6 loc_80514D6:
.text:080514D6 cmp ax, [esi+8] ; item->pos.z
.text:080514DA jnz short coord_test_jfail
.text:080514DC jmp short loc_80514E3
0x94e3
90 90 90 90 90 90 90 90 90 90 90 90 90
0F BF 43 10 66 3B 46 04 75 CC EB 04 90
.text:080514E3 loc_80514E3:
.text:080514E3 movsx eax, word ptr [ebx+10h] ; job_x
.text:080514E7 cmp ax, [esi+4] ; item->pos.x
.text:080514EB jnz short coord_test_jfail
.text:080514ED jmp short loc_80514F3
0x94f3
90 90 90 90 90 90 90 90 90 90 90 90 90
0F BF 43 20 66 3B 46 06 75 BC EB 04 90
.text:080514F3 loc_80514F3:
.text:080514F3 movsx eax, word ptr [ebx+20h] ; job_y
.text:080514F7 cmp ax, [esi+6] ; item->pos.y
.text:080514FB jnz short coord_test_jfail
.text:080514FD jmp short loc_8051503
0x9503
90 90 90 90 90 90 90 90 90 90 90 90 90
E9 F6 AE 75 00 90 90 90 90 90 90 90 90
.text:08051503 loc_8051503:
.text:08051503 jmp loc_87AC3FE
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
000094B3: 90 F6
000094B4: 90 46
000094B5: 90 0C
000094B6: 90 01
000094B7: 90 75
000094B8: 90 0A
000094B9: 90 E9
000094BA: 90 82
000094BB: 90 AF
000094BC: 90 75
000094BD: 90 00
000094C3: 90 8D
000094C4: 90 9C
000094C5: 90 24
000094C6: 90 60
000094C7: 90 03
000094C8: 90 00
000094C9: 90 00
000094CA: 90 0F
000094CB: 90 BF
000094CC: 90 03
000094CD: 90 EB
000094CE: 90 07
000094D6: 90 66
000094D7: 90 3B
000094D8: 90 46
000094D9: 90 08
000094DA: 90 75
000094DB: 90 DD
000094DC: 90 EB
000094DD: 90 05
000094E3: 90 0F
000094E4: 90 BF
000094E5: 90 43
000094E6: 90 10
000094E7: 90 66
000094E8: 90 3B
000094E9: 90 46
000094EA: 90 04
000094EB: 90 75
000094EC: 90 CC
000094ED: 90 EB
000094EE: 90 04
000094F3: 90 0F
000094F4: 90 BF
000094F5: 90 43
000094F6: 90 20
000094F7: 90 66
000094F8: 90 3B
000094F9: 90 46
000094FA: 90 06
000094FB: 90 75
000094FC: 90 BC
000094FD: 90 EB
000094FE: 90 04
00009503: 90 E9
00009504: 90 F6
00009505: 90 AE
00009506: 90 75
00009507: 90 00
007643F8: F6 E9
007643F9: 46 B6
007643FA: 0C 50
007643FB: 01 8A
007643FC: 74 FF
007643FD: 42 90

@ -1,60 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4406
1. Include store in hospital jobs when recomputing counters
0x746d7
75 D7
90 90
<<<<
.text:080BC6D7 jnz short loc_80BC6B0
====
.text:080BC6D7 nop
.text:080BC6D8 nop
>>>>
- if (job->getBuildingRef(BUILDING_DESTINATION) != this) continue;
+ // NOP
This reference points to the containers, not the hospital civzone.
Since fixing this properly is too hard for a patch, just remove the
check. Most people have only one hospital anyway, and it is better
to err on the side of caution here.
2. Make the stockpiling code increment the right stock counters
0x67cb0e
0B 04 90
8B 1C 90
0x67cb18
8B 40 74
8B 43 74
<<<<
.text:086C4B0E mov eax, [eax+edx*4]
.text:086C4B11 mov edx, [esp+ecx*4+39Ch+var_2B4]
.text:086C4B18 mov eax, [eax+74h]
====
.text:086C4B0E mov ebx, [eax+edx*4]
.text:086C4B11 mov edx, [esp+ecx*4+39Ch+var_2B4]
.text:086C4B18 mov eax, [ebx+74h]
>>>>
- id = civzones[i]->children[child_idx[i]]->id
+ cur_civzone = civzones[i] // existing var from previous loop
+ id = cur_civzone->children[child_idx[i]]->id
The reason being, later code uses that var (at this point containing
useless data) to increment counters and amounts in the hospital.
---8<---
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
000746D7: 75 90
000746D8: D7 90
0067CB0F: 04 1C
0067CB19: 40 43

@ -1,85 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4530
0x9508
90 90 90 90 90 90 90 90
E9 13 76 9C 00 90 90 90
.text:08051508 loc_8051508:
.text:08051508 jmp sub_8A18B20
0x9523
90 90 90 90 90 90 90 90 90 90 90 90 90
50 8B 03 53 FF 90 34 02 00 00 EB 09 90
.text:08051523 sub_8051523:
.text:08051523 push eax
.text:08051524 mov eax, [ebx]
.text:08051526 push ebx
.text:08051527 call dword ptr [eax+234h]
.text:0805152D jmp short loc_8051538
0x9538
90 90 90 90 90 90 90 90
29 44 24 64 5B 58 EB C8
.text:08051538 loc_8051538:
.text:08051538 sub [esp+64h], eax
.text:0805153C pop ebx
.text:0805153D pop eax
.text:0805153E jmp short loc_8051508
0xa5cdd0
29 44 24 58
90 90 90 90
.text:08AA4DD0 nop
.text:08AA4DD1 nop
.text:08AA4DD2 nop
.text:08AA4DD3 nop
0xa5e2c3
E8 58 28 F7 FF
E8 5B B2 5A FF
.text:08AA62C3 call sub_8051523
---8<---
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
00009508: 90 E9
00009509: 90 13
0000950A: 90 76
0000950B: 90 9C
0000950C: 90 00
00009523: 90 50
00009524: 90 8B
00009525: 90 03
00009526: 90 53
00009527: 90 FF
00009529: 90 34
0000952A: 90 02
0000952B: 90 00
0000952C: 90 00
0000952D: 90 EB
0000952E: 90 09
00009538: 90 29
00009539: 90 44
0000953A: 90 24
0000953B: 90 64
0000953C: 90 5B
0000953D: 90 58
0000953E: 90 EB
0000953F: 90 C8
00A5CDD0: 29 90
00A5CDD1: 44 90
00A5CDD2: 24 90
00A5CDD3: 58 90
00A5E2C4: 58 5B
00A5E2C5: 28 B2
00A5E2C6: F7 5A

@ -1,45 +0,0 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
Fix use of uninitialized variables to stop auto-unassigning racks:
0x7ee948
8B 7C 24 3C
89 C7 90 90
.text:08836948 mov edi, eax
.text:0883694A nop
.text:0883694B nop
0x7eea2f
8B 7C 24 3C
89 C7 90 90
.text:08836A2F mov edi, eax
.text:08836A31 nop
.text:08836A32 nop
basically:
b_squad_id = building->getSpecificSquad();
- if (b_squad_id != squad->id || !building->canUse(some_squad_id, 4))
+ if (b_squad_id != squad->id || !building->canUse(b_squad_id, 4))
unassign(building);
the reason being, some_other_squad_id contains irrelevant garbage at this point
---8<---
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
007EE948: 8B 89
007EE949: 7C C7
007EE94A: 24 90
007EE94B: 3C 90
007EEA2F: 8B 89
007EEA30: 7C C7
007EEA31: 24 90
007EEA32: 3C 90

@ -1,20 +0,0 @@
see linux patch for info
- .text:00111776 jnz loc_111750
+ .text:00111776 nop
+ .text:00111777 nop
sub_660360
osx stores pointer in edi instead of ebx
- .text:006612C3 mov eax, [eax+edx*4]
+ .text:006612C3 mov edi, [eax+edx*4]
- .text:006612CD mov eax, [eax+74h]
+ .text:006612CD mov eax, [edi+74h]
---8<---
Dwarf_Fortress
00110776: 75 90
00110777: D8 90
006602C4: 04 3C
006602CE: 40 47

@ -87,7 +87,7 @@ if (BUILD_SUPPORTED)
# DFHACK_PLUGIN(advtools advtools.cpp)
DFHACK_PLUGIN(autochop autochop.cpp)
DFHACK_PLUGIN(autodump autodump.cpp)
DFHACK_PLUGIN(autolabor autolabor.cpp)
# DFHACK_PLUGIN(autolabor autolabor.cpp)
DFHACK_PLUGIN(automaterial automaterial.cpp)
DFHACK_PLUGIN(autotrade autotrade.cpp)
DFHACK_PLUGIN(burrows burrows.cpp LINK_LIBRARIES lua)

@ -180,7 +180,6 @@ struct work_hook : df::building_workshopst{
{
if(def->skip_updates!=0 && is_fully_built())
{
df::world* world = df::global::world;
if(world->frame_counter % def->skip_updates == 0)
{
CoreSuspendClaimer suspend;
@ -203,7 +202,6 @@ struct work_hook : df::building_workshopst{
if(!def->machine_timing)
{
int frame_mod=def->frames.size()* def->frame_skip;
df::world* world = df::global::world;
frame=(world->frame_counter % frame_mod)/def->frame_skip;
}
else

@ -39,6 +39,7 @@ using namespace dfproto;
using df::global::ui;
using df::global::world;
using df::global::gamemode;
/*
* Initialization.
@ -101,8 +102,8 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
switch (event) {
case SC_MAP_LOADED:
deinit_map(out);
if (df::global::gamemode &&
*df::global::gamemode == game_mode::DWARF)
if (gamemode &&
*gamemode == game_mode::DWARF)
init_map(out);
break;
case SC_MAP_UNLOADED:

@ -25,6 +25,7 @@ using namespace std;
#include <df/unit_genes.h>
using namespace DFHack;
using df::global::world;
command_result catsplosion (color_ostream &out, std::vector <std::string> & parameters);
@ -79,7 +80,7 @@ command_result catsplosion (color_ostream &out, std::vector <std::string> & para
for(uint32_t i =0;i < numCreatures;i++)
{
df::unit * creature = Units::GetCreature(i);
df::creature_raw *raw = df::global::world->raws.creatures.all[creature->race];
df::creature_raw *raw = world->raws.creatures.all[creature->race];
if(creature->sex == 0) // female
{
female_counts[raw->creature_id].push_back(creature);

@ -53,8 +53,8 @@ public:
std::string getFocusString() { return "commandprompt"; }
viewscreen_commandpromptst(std::string entry):is_response(false)
{
show_fps=df::global::gps->display_frames;
df::global::gps->display_frames=0;
show_fps=gps->display_frames;
gps->display_frames=0;
cursor_pos = 0;
frame = 0;
history_idx = command_history.size();
@ -70,7 +70,7 @@ public:
}
~viewscreen_commandpromptst()
{
df::global::gps->display_frames=show_fps;
gps->display_frames=show_fps;
}
void add_response(color_value v, std::string s)
@ -138,7 +138,7 @@ void prompt_ostream::flush_proxy()
void viewscreen_commandpromptst::render()
{
++frame;
if (frame >= df::global::enabler->gfps)
if (frame >= enabler->gfps)
frame = 0;
if (Screen::isDismissed(this))
return;
@ -162,7 +162,7 @@ void viewscreen_commandpromptst::render()
std::string entry = get_entry();
Screen::fillRect(Screen::Pen(' ', 7, 0),0,0,dim.x,0);
Screen::paintString(Screen::Pen(' ', 7, 0), 0, 0,"[DFHack]#");
std::string cursor = (frame < df::global::enabler->gfps / 2) ? "_" : " ";
std::string cursor = (frame < enabler->gfps / 2) ? "_" : " ";
if(cursor_pos < (dim.x - 10))
{
Screen::paintString(Screen::Pen(' ', 7, 0), 10,0 , entry);
@ -238,10 +238,10 @@ void viewscreen_commandpromptst::feed(std::set<df::interface_key> *events)
cursor_pos = entry.size();
continue;
}
if (key >= interface_key::STRING_A000 &&
key <= interface_key::STRING_A255)
int charcode = Screen::keyToChar(key);
if (charcode > 0)
{
entry.insert(cursor_pos, 1, char(key - interface_key::STRING_A000));
entry.insert(cursor_pos, 1, char(charcode));
cursor_pos++;
set_entry(entry);
return;
@ -328,4 +328,4 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
return CR_OK;
}
}

@ -21,6 +21,10 @@
using namespace DFHack;
using namespace std;
using df::global::world;
// using df::global::process_jobs;
// using df::global::process_dig;
command_result digFlood (color_ostream &out, std::vector <std::string> & parameters);
DFHACK_PLUGIN("digFlood");
@ -88,7 +92,7 @@ void onDig(color_ostream& out, void* ptr) {
return;
set<df::coord> jobLocations;
for ( df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next ) {
for ( df::job_list_link* link = &world->job_list; link != NULL; link = link->next ) {
if ( link->item == NULL )
continue;
@ -146,7 +150,7 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
if ( mat == -1 )
return;
if ( !digAll ) {
df::inorganic_raw* inorganic = df::global::world->raws.inorganics[mat];
df::inorganic_raw* inorganic = world->raws.inorganics[mat];
if ( autodigMaterials.find(inorganic->id) == autodigMaterials.end() ) {
return;
}
@ -154,8 +158,8 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
block->designation[pt.x&0xF][pt.y&0xF].bits.dig = df::enums::tile_dig_designation::Default;
block->flags.bits.designated = true;
// *df::global::process_dig = true;
// *df::global::process_jobs = true;
// *process_dig = true;
// *process_jobs = true;
}
command_result digFlood (color_ostream &out, std::vector <std::string> & parameters)
@ -186,8 +190,8 @@ command_result digFlood (color_ostream &out, std::vector <std::string> & paramet
continue;
}
for ( size_t b = 0; b < df::global::world->raws.inorganics.size(); b++ ) {
df::inorganic_raw* inorganic = df::global::world->raws.inorganics[b];
for ( size_t b = 0; b < world->raws.inorganics.size(); b++ ) {
df::inorganic_raw* inorganic = world->raws.inorganics[b];
if ( parameters[a] == inorganic->id ) {
if ( adding )
toAdd.insert(parameters[a]);

@ -1040,7 +1040,7 @@ struct preference_map
string getItemLabel()
{
df::world_raws::T_itemdefs &defs = df::global::world->raws.itemdefs;
df::world_raws::T_itemdefs &defs = world->raws.itemdefs;
label = ENUM_ATTR_STR(item_type, caption, pref.item_type);
switch (pref.item_type)
{

@ -201,7 +201,7 @@ static bool can_store_ammo_rec(df::item *item, df::building *holder, int squad_i
// Ugh, archery targets don't actually have a squad use vector
else if (holder->getType() == building_type::ArcheryTarget)
{
auto &squads = df::global::world->squads.all;
auto &squads = world->squads.all;
for (size_t si = 0; si < squads.size(); si++)
{
@ -710,7 +710,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out, state_change_ev
return CR_OK;
// Loop over squads
auto &squads = df::global::world->squads.all;
auto &squads = world->squads.all;
for (size_t si = 0; si < squads.size(); si++)
{

@ -16,6 +16,7 @@
using namespace DFHack;
using namespace df::enums;
using df::global::world;
command_result follow (color_ostream &out, std::vector <std::string> & parameters);
@ -151,7 +152,7 @@ command_result follow (color_ostream &out, std::vector <std::string> & parameter
{
is_enabled = true;
std::ostringstream ss;
ss << "Unpause to begin following " << df::global::world->raws.creatures.all[followedUnit->race]->name[0];
ss << "Unpause to begin following " << world->raws.creatures.all[followedUnit->race]->name[0];
if (followedUnit->name.has_name) ss << " " << followedUnit->name.first_name;
ss << ". Simply manually move the view to break the following.\n";
out.print(ss.str().c_str());

@ -23,6 +23,8 @@ using namespace std;
using namespace DFHack;
using namespace df::enums;
using df::global::world;
command_result infiniteSky (color_ostream &out, std::vector <std::string> & parameters);
DFHACK_PLUGIN("infiniteSky");
@ -88,24 +90,23 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
return CR_OK;
}
if ( df::global::world->constructions.size() == constructionSize )
if ( world->constructions.size() == constructionSize )
return CR_OK;
int32_t zNow = df::global::world->map.z_count_block;
for ( size_t a = constructionSize; a < df::global::world->constructions.size(); a++ ) {
df::construction* construct = df::global::world->constructions[a];
int32_t zNow = world->map.z_count_block;
for ( size_t a = constructionSize; a < world->constructions.size(); a++ ) {
df::construction* construct = world->constructions[a];
if ( construct->pos.z+2 < zNow )
continue;
doInfiniteSky(out, 1);
zNow = df::global::world->map.z_count_block;
zNow = world->map.z_count_block;
///break;
}
constructionSize = df::global::world->constructions.size();
constructionSize = world->constructions.size();
return CR_OK;
}
void doInfiniteSky(color_ostream& out, int32_t howMany) {
df::world* world = df::global::world;
CoreSuspender suspend;
int32_t x_count_block = world->map.x_count_block;
int32_t y_count_block = world->map.y_count_block;

@ -31,6 +31,10 @@ using namespace DFHack;
using namespace df::enums;
using namespace isoworldremote;
using df::global::gamemode;
using df::global::world;
using df::global::cur_year;
using df::global::cur_season;
// Here go all the command declarations...
// mostly to allow having the mandatory stuff on top of the file and commands on the bottom
@ -185,11 +189,11 @@ static command_result GetEmbarkInfo(color_ostream &stream, const MapRequest *in,
out->set_available(false);
return CR_OK;
}
if(!df::global::gamemode) {
if(!gamemode) {
out->set_available(false);
return CR_OK;
}
if((*df::global::gamemode != game_mode::ADVENTURE) && (*df::global::gamemode != game_mode::DWARF)) {
if((*gamemode != game_mode::ADVENTURE) && (*gamemode != game_mode::DWARF)) {
out->set_available(false);
return CR_OK;
}
@ -198,18 +202,18 @@ static command_result GetEmbarkInfo(color_ostream &stream, const MapRequest *in,
return CR_OK;
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
if (!(in->save_folder() == df::global::world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them.
if (!(in->save_folder() == world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them.
out->set_available(false);
return CR_OK;
}
}
out->set_available(true);
out->set_current_year(*df::global::cur_year);
out->set_current_season(*df::global::cur_season);
out->set_region_x(df::global::world->map.region_x);
out->set_region_y(df::global::world->map.region_y);
out->set_region_size_x(df::global::world->map.x_count_block / 3);
out->set_region_size_y(df::global::world->map.y_count_block / 3);
out->set_current_year(*cur_year);
out->set_current_season(*cur_season);
out->set_region_x(world->map.region_x);
out->set_region_y(world->map.region_y);
out->set_region_size_x(world->map.x_count_block / 3);
out->set_region_size_y(world->map.y_count_block / 3);
return CR_OK;
}
@ -219,11 +223,11 @@ int coord_to_index_48(int x, int y) {
bool gather_embark_tile(int EmbX, int EmbY, EmbarkTile * tile, MapExtras::MapCache * MP) {
tile->set_is_valid(false);
tile->set_world_x(df::global::world->map.region_x + (EmbX/3));
tile->set_world_y(df::global::world->map.region_y + (EmbY/3));
tile->set_world_z(df::global::world->map.region_z + 1); //adding one because floors get shifted one downwards.
tile->set_current_year(*df::global::cur_year);
tile->set_current_season(*df::global::cur_season);
tile->set_world_x(world->map.region_x + (EmbX/3));
tile->set_world_y(world->map.region_y + (EmbY/3));
tile->set_world_z(world->map.region_z + 1); //adding one because floors get shifted one downwards.
tile->set_current_year(*cur_year);
tile->set_current_season(*cur_season);
int num_valid_layers = 0;
for(int z = 0; z < MP->maxZ(); z++)
{
@ -332,11 +336,11 @@ static command_result GetRawNames(color_ostream &stream, const MapRequest *in, R
out->set_available(false);
return CR_OK;
}
if(!df::global::gamemode) {
if(!gamemode) {
out->set_available(false);
return CR_OK;
}
if((*df::global::gamemode != game_mode::ADVENTURE) && (*df::global::gamemode != game_mode::DWARF)) {
if((*gamemode != game_mode::ADVENTURE) && (*gamemode != game_mode::DWARF)) {
out->set_available(false);
return CR_OK;
}
@ -345,18 +349,18 @@ static command_result GetRawNames(color_ostream &stream, const MapRequest *in, R
return CR_OK;
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
if (!(in->save_folder() == df::global::world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them.
if (!(in->save_folder() == world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them.
out->set_available(false);
return CR_OK;
}
}
out->set_available(true);
for(int i = 0; i < df::global::world->raws.inorganics.size(); i++){
out->add_inorganic(df::global::world->raws.inorganics[i]->id);
for(int i = 0; i < world->raws.inorganics.size(); i++){
out->add_inorganic(world->raws.inorganics[i]->id);
}
for(int i = 0; i < df::global::world->raws.plants.all.size(); i++){
out->add_organic(df::global::world->raws.plants.all[i]->id);
for(int i = 0; i < world->raws.plants.all.size(); i++){
out->add_organic(world->raws.plants.all[i]->id);
}
return CR_OK;
}

@ -46,6 +46,7 @@ using std::set;
using namespace MapExtras;
using namespace DFHack;
using namespace df::enums;
using df::global::world;
CommandHistory liquids_hist;
@ -440,7 +441,7 @@ command_result df_liquids_execute(color_ostream &out, OperationMode &cur_mode, d
coord_vec all_tiles = brush->points(mcache,cursor);
// Force the game to recompute its walkability cache
df::global::world->reindex_pathfinding = true;
world->reindex_pathfinding = true;
switch (cur_mode.paint)
{

@ -19,8 +19,6 @@ triggers = {
{name = "Never"},
}
local job_types = df.job_type
entry_ints = {
stockpile_id = 1,
order_number = 2,
@ -75,7 +73,7 @@ end
-- Save the stockpile jobs for later creation.
-- Called when the bookkeeper starts updating stockpile records.
function start_bookkeeping()
result = {}
local result = {}
for reaction_id, quantity in pairs(check_stockpiles()) do
local amount = order_quantity(reaction_list[reaction_id].order, quantity)
if amount > 0 then
@ -123,11 +121,22 @@ function collect_orders()
local spid = entry.ints[entry_ints.stockpile_id]
local stockpile = utils.binsearch(stockpiles, spid, "id")
if stockpile then
-- Todo: What if entry.value ~= reaction_list[order_number].name?
result[spid] = {
stockpile = stockpile,
entry = entry,
}
local order_number = entry.ints[entry_ints.order_number]
if reaction_list[order_number] and entry.value == reaction_list[order_number].name then
result[spid] = {
stockpile = stockpile,
entry = entry,
}
else
-- It might be worth searching reaction_list for the name.
-- Then again, this should only happen in unusual situations.
print("Mismatched stockflow entry for stockpile #"..stockpile.stockpile_number..": "..entry.value.." ("..order_number..")")
end
else
-- The stockpile no longer exists.
-- Perhaps it has been deleted, or perhaps this is a different fortress.
-- print("Missing stockflow pile "..spid)
entry:delete()
end
end
end
@ -203,6 +212,7 @@ end
function clothing_reactions(reactions, mat_info, filter)
local resources = df.historical_entity.find(df.global.ui.civ_id).resources
local itemdefs = df.global.world.raws.itemdefs
local job_types = df.job_type
resource_reactions(reactions, job_types.MakeArmor, mat_info, resources.armor_type, itemdefs.armor, {permissible = filter})
resource_reactions(reactions, job_types.MakePants, mat_info, resources.pants_type, itemdefs.pants, {permissible = filter})
resource_reactions(reactions, job_types.MakeGloves, mat_info, resources.gloves_type, itemdefs.gloves, {permissible = filter})
@ -218,6 +228,12 @@ function collect_reactions()
-- Even that list doesn't seem to include their names.
local result = {}
-- A few task types are obsolete in newer DF versions.
local v34 = string.match(dfhack.getDFVersion(), "v0.34")
-- Caching the enumeration might not be important, but saves lookups.
local job_types = df.job_type
local materials = {
rock = {
adjective = "rock",
@ -320,7 +336,7 @@ function collect_reactions()
table.insert(result, reaction_entry(job_types.DyeCloth))
-- Sew Image
cloth_mats = {materials.cloth, materials.silk, materials.yarn, materials.leather}
local cloth_mats = {materials.cloth, materials.silk, materials.yarn, materials.leather}
for _, material in ipairs(cloth_mats) do
material_reactions(result, {{job_types.SewImage, "Sew", "Image"}}, material)
end
@ -340,8 +356,10 @@ function collect_reactions()
table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 3}, "Prepare Fine Meal"))
table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 4}, "Prepare Lavish Meal"))
-- Brew Drink
table.insert(result, reaction_entry(job_types.BrewDrink))
if v34 then
-- Brew Drink
table.insert(result, reaction_entry(job_types.BrewDrink))
end
-- Weaving
table.insert(result, reaction_entry(job_types.WeaveCloth, {material_category = {plant = true}}, "Weave Thread into Cloth"))
@ -359,7 +377,9 @@ function collect_reactions()
table.insert(result, reaction_entry(job_types.SpinThread))
table.insert(result, reaction_entry(job_types.MakeLye))
table.insert(result, reaction_entry(job_types.ProcessPlants))
table.insert(result, reaction_entry(job_types.ProcessPlantsBag))
if v34 then
table.insert(result, reaction_entry(job_types.ProcessPlantsBag))
end
table.insert(result, reaction_entry(job_types.ProcessPlantsVial))
table.insert(result, reaction_entry(job_types.ProcessPlantsBarrel))
table.insert(result, reaction_entry(job_types.MakeCharcoal))
@ -656,7 +676,7 @@ function collect_reactions()
end
-- Boxes, Bags, and Ropes
boxmats = {
local boxmats = {
{mats = {materials.wood}, box = "Chest"},
{mats = {materials.rock}, box = "Coffer"},
{mats = glasses, box = "Box", flask = "Vial"},

@ -179,12 +179,16 @@ const SkillColumn columns[] = {
{11, 3, profession::NONE, unit_labor::HAUL_FOOD, job_skill::NONE, "Fo"},
{11, 3, profession::NONE, unit_labor::HAUL_REFUSE, job_skill::NONE, "Re"},
{11, 3, profession::NONE, unit_labor::HAUL_FURNITURE, job_skill::NONE, "Fu"},
{11, 3, profession::NONE, unit_labor::HAUL_ANIMAL, job_skill::NONE, "An"},
{11, 3, profession::NONE, unit_labor::HAUL_ANIMALS, job_skill::NONE, "An"},
{11, 3, profession::NONE, unit_labor::HANDLE_VEHICLES, job_skill::NONE, "Ve"},
{11, 3, profession::NONE, unit_labor::HAUL_TRADE, job_skill::NONE, "Tr"},
{11, 3, profession::NONE, unit_labor::HAUL_WATER, job_skill::NONE, "Wa"},
// Other Jobs
{12, 4, profession::ARCHITECT, unit_labor::ARCHITECT, job_skill::DESIGNBUILDING, "Ar"},
{12, 4, profession::ALCHEMIST, unit_labor::ALCHEMIST, job_skill::ALCHEMY, "Al"},
{12, 4, profession::NONE, unit_labor::CLEAN, job_skill::NONE, "Cl"},
{12, 4, profession::NONE, unit_labor::PULL_LEVER, job_skill::NONE, "Lv"},
{12, 4, profession::NONE, unit_labor::REMOVE_CONSTRUCTION, job_skill::NONE, "Co"},
// Military - Weapons
{13, 7, profession::WRESTLER, unit_labor::NONE, job_skill::WRESTLING, "Wr"},
{13, 7, profession::AXEMAN, unit_labor::NONE, job_skill::AXE, "Ax"},

@ -11,10 +11,13 @@
#include <string>
#include <vector>
#include <map>
using namespace std;
using namespace std;
using namespace DFHack;
using df::global::world;
using df::global::ui;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
static int factor = 1;
@ -36,7 +39,7 @@ DFhackCExport command_result plugin_shutdown(color_ostream& out) {
DFhackCExport command_result plugin_onupdate(color_ostream& out) {
static bool wasLoaded = false;
if ( factor == 1 || !df::global::world || !df::global::world->map.block_index ) {
if ( factor == 1 || !world || !world->map.block_index ) {
if ( wasLoaded ) {
//we just unloaded the game: clear all data
factor = 1;
@ -58,10 +61,10 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
}
count = 0;
int32_t race_id = df::global::ui->race_id;
int32_t civ_id = df::global::ui->civ_id;
for ( size_t a = 0; a < df::global::world->units.all.size(); a++ ) {
df::unit* unit = df::global::world->units.all[a]; //TODO: consider units.active
int32_t race_id = ui->race_id;
int32_t civ_id = ui->civ_id;
for ( size_t a = 0; a < world->units.all.size(); a++ ) {
df::unit* unit = world->units.all[a]; //TODO: consider units.active
//living, native units only
if ( unit->race != race_id || unit->civ_id != civ_id )
continue;
@ -153,7 +156,7 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
}
command_result misery(color_ostream &out, vector<string>& parameters) {
if ( !df::global::world || !df::global::world->map.block_index ) {
if ( !world || !world->map.block_index ) {
out.printerr("misery can only be enabled in fortress mode with a fully-loaded game.\n");
return CR_FAILURE;
}
@ -184,7 +187,7 @@ command_result misery(color_ostream &out, vector<string>& parameters) {
for ( size_t a = 0; a < fakeThoughts.size(); a++ ) {
int dorfIndex = fakeThoughts[a].first;
int thoughtIndex = fakeThoughts[a].second;
df::global::world->units.all[dorfIndex]->status.recent_events[thoughtIndex]->age = 1000000;
world->units.all[dorfIndex]->status.recent_events[thoughtIndex]->age = 1000000;
}
fakeThoughts.clear();
} else {

@ -23,6 +23,7 @@
using df::global::world;
using df::global::ui;
using df::global::ui_build_selector;
using namespace df::enums::ui_sidebar_mode;
@ -330,9 +331,9 @@ struct mousequery_hook : public df::viewscreen_dwarfmodest
break;
case Build:
if (df::global::ui_build_selector)
if (ui_build_selector)
{
if (df::global::ui_build_selector->stage < 2)
if (ui_build_selector->stage < 2)
{
designationMode = true;
key = df::interface_key::SELECT;
@ -502,9 +503,9 @@ struct mousequery_hook : public df::viewscreen_dwarfmodest
bool inBuildPlacement()
{
return df::global::ui_build_selector &&
df::global::ui_build_selector->building_type != -1 &&
df::global::ui_build_selector->stage == 1;
return ui_build_selector &&
ui_build_selector->building_type != -1 &&
ui_build_selector->stage == 1;
}
bool shouldTrack()

@ -20,6 +20,8 @@
using namespace DFHack;
using namespace std;
using df::global::world;
static int32_t howOften = 10000;
static int32_t popcap = 100;
static int32_t pregtime = 200000;
@ -58,7 +60,7 @@ void impregnateMany() {
map<int32_t, vector<int32_t> > males;
map<int32_t, vector<int32_t> > females;
map<int32_t, int32_t> popcount;
auto units = df::global::world->units.all;
auto units = world->units.all;
for ( size_t a = 0; a < units.size(); a++ ) {
df::unit* unit = units[a];
if ( unit->flags1.bits.dead || unit->flags1.bits.active_invader || unit->flags2.bits.underworld || unit->flags2.bits.visitor_uninvited || unit->flags2.bits.visitor )
@ -74,7 +76,7 @@ void impregnateMany() {
continue;
int32_t race = unit->race;
int16_t caste = unit->caste;
df::creature_raw* creatureRaw = df::global::world->raws.creatures.all[race];
df::creature_raw* creatureRaw = world->raws.creatures.all[race];
df::caste_raw* casteRaw = creatureRaw->caste[caste];
//must have PET or PET_EXOTIC
if ( !(casteRaw->flags.is_set(df::enums::caste_raw_flags::PET) || casteRaw->flags.is_set(df::enums::caste_raw_flags::PET_EXOTIC) ) )

@ -297,7 +297,7 @@ module DFHack
mapblock.flags.update_liquid = true
mapblock.flags.update_liquid_twice = true
zf = df.world.map.z_level_flags[z]
zf = df.world.map_extras.z_level_flags[z]
zf.update = true
zf.update_twice = true
end

@ -39,6 +39,7 @@ using namespace df::enums;
using df::global::gps;
using df::global::gview;
using df::global::ui;
/*
Search Plugin
@ -130,7 +131,8 @@ public:
this->cursor_pos = get_viewscreen_cursor();
this->primary_list = get_primary_list();
this->select_key = get_search_select_key();
select_token = (df::interface_key) (ascii_to_enum_offset + select_key);
select_token = Screen::charToKey(select_key);
shift_select_token = Screen::charToKey(select_key + 'A' - 'a');
valid = true;
do_post_init();
}
@ -185,10 +187,11 @@ public:
return false;
}
df::interface_key last_token = *input->rbegin();
if (last_token >= interface_key::STRING_A032 && last_token <= interface_key::STRING_A126)
int charcode = Screen::keyToChar(last_token);
if (charcode >= 32 && charcode <= 126)
{
// Standard character
search_string += last_token - ascii_to_enum_offset;
search_string += char(charcode);
do_search();
}
else if (last_token == interface_key::STRING_A000)
@ -219,7 +222,7 @@ public:
// Hotkey pressed, enter typing mode
start_entry_mode();
}
else if (input->count((df::interface_key) (select_token + shift_offset)))
else if (input->count(shift_select_token))
{
// Shift + Hotkey pressed, clear query
clear_search();
@ -246,7 +249,7 @@ protected:
virtual int32_t *get_viewscreen_cursor() = 0;
virtual vector<T> *get_primary_list() = 0;
search_generic() : ascii_to_enum_offset(interface_key::STRING_A048 - '0'), shift_offset('A' - 'a')
search_generic()
{
reset_all();
}
@ -412,9 +415,7 @@ private:
bool entry_mode;
df::interface_key select_token;
const int ascii_to_enum_offset;
const int shift_offset;
df::interface_key shift_select_token;
};
template <class S, class T> search_generic<S, T> *search_generic<S, T> ::lock = NULL;
@ -1575,7 +1576,6 @@ IMPLEMENT_HOOKS(df::viewscreen_joblistst, joblist_search);
//
// START: Burrow assignment search
//
using df::global::ui;
typedef search_twocolumn_modifiable<df::viewscreen_dwarfmodest, df::unit*, bool> burrow_search_base;
class burrow_search : public burrow_search_base

@ -70,6 +70,7 @@ using df::global::gps;
using df::global::world;
using df::global::ui;
using df::global::ui_build_selector;
using df::global::process_jobs;
using Screen::Pen;
@ -1505,8 +1506,8 @@ static void releaseTiredWorker(EngineInfo *engine, df::job *job, df::unit *worke
color_ostream_proxy out(Core::getInstance().getConsole());
out.print("Released tired operator %d from siege engine.\n", worker->id);
if (df::global::process_jobs)
*df::global::process_jobs = true;
if (process_jobs)
*process_jobs = true;
}
return;

@ -121,6 +121,7 @@ using df::global::gps;
using df::global::world;
using df::global::ui;
using df::global::ui_build_selector;
using df::global::cursor;
DFHACK_PLUGIN("steam-engine");
@ -833,8 +834,6 @@ struct dwarfmode_hook : df::viewscreen_dwarfmodest
void check_hanging_tiles(steam_engine_workshop *engine)
{
using df::global::cursor;
if (!engine) return;
bool error = false;

@ -31,12 +31,15 @@ DFHACK_PLUGIN_IS_ENABLED(enabled);
bool enabled = false;
#endif
bool fast = false;
const char *tagline = "Allows the fortress bookkeeper to queue jobs through the manager.";
const char *usage = (
" stockflow enable\n"
" Enable the plugin.\n"
" stockflow disable\n"
" Disable the plugin.\n"
" stockflow fast\n"
" Enable the plugin in fast mode.\n"
" stockflow list\n"
" List any work order settings for your stockpiles.\n"
" stockflow status\n"
@ -49,6 +52,9 @@ const char *usage = (
"Whenever the bookkeeper updates stockpile records, new work orders will\n"
"be placed on the manager's queue for each such selection, reduced by the\n"
"number of identical orders already in the queue.\n"
"\n"
"In fast mode, new work orders will be enqueued once per day, instead of\n"
"waiting for the bookkeeper.\n"
);
/*
@ -59,11 +65,19 @@ class LuaHelper {
public:
void cycle(color_ostream &out) {
bool found = false;
for (df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next) {
if (link->item == NULL) continue;
if (link->item->job_type == job_type::UpdateStockpileRecords) {
found = true;
break;
if (fast) {
// Ignore the bookkeeper; either gather or enqueue orders every cycle.
found = !bookkeeping;
} else {
// Gather orders when the bookkeeper starts updating stockpile records,
// and enqueue them when the job is done.
for (df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next) {
if (link->item == NULL) continue;
if (link->item->job_type == job_type::UpdateStockpileRecords) {
found = true;
break;
}
}
}
@ -307,8 +321,13 @@ static command_result stockflow_cmd(color_ostream &out, vector <string> & parame
if (parameters.size() == 1) {
if (parameters[0] == "enable" || parameters[0] == "on" || parameters[0] == "1") {
desired = true;
fast = false;
} else if (parameters[0] == "disable" || parameters[0] == "off" || parameters[0] == "0") {
desired = false;
fast = false;
} else if (parameters[0] == "fast" || parameters[0] == "always" || parameters[0] == "2") {
desired = true;
fast = true;
} else if (parameters[0] == "usage" || parameters[0] == "help" || parameters[0] == "?") {
out.print("%s: %s\nUsage:\n%s", name, tagline, usage);
return CR_OK;
@ -338,7 +357,7 @@ static command_result stockflow_cmd(color_ostream &out, vector <string> & parame
}
}
out.print("Stockflow is %s %s.\n", (desired == enabled)? "currently": "now", desired? "enabled": "disabled");
out.print("Stockflow is %s %s%s.\n", (desired == enabled)? "currently": "now", desired? "enabled": "disabled", fast? ", in fast mode": "");
enabled = desired;
return CR_OK;
}

@ -40,6 +40,7 @@ using df::global::created_item_type;
using df::global::created_item_subtype;
using df::global::created_item_mattype;
using df::global::created_item_matindex;
using df::global::debug_nomoods;
Random::MersenneRNG rng;
@ -473,7 +474,7 @@ command_result df_strangemood (color_ostream &out, vector <string> & parameters)
out.printerr("ARTIFACTS are not enabled!\n");
return CR_FAILURE;
}
if (*df::global::debug_nomoods)
if (*debug_nomoods)
{
out.printerr("Strange moods disabled via debug flag!\n");
return CR_FAILURE;

@ -44,6 +44,8 @@ using namespace MapExtras;
using namespace DFHack;
using namespace df::enums;
using df::global::world;
CommandHistory tiletypes_hist;
command_result df_tiletypes (color_ostream &out, vector <string> & parameters);
@ -738,7 +740,7 @@ command_result executePaintJob(color_ostream &out)
out.print("working...\n");
// Force the game to recompute its walkability cache
df::global::world->reindex_pathfinding = true;
world->reindex_pathfinding = true;
int failures = 0;

@ -21,6 +21,9 @@
using namespace DFHack;
using df::global::world;
using df::global::ui;
void checkFarms(color_ostream& out, void* ptr);
command_result treefarm (color_ostream &out, std::vector <std::string> & parameters);
@ -66,8 +69,6 @@ void checkFarms(color_ostream& out, void* ptr) {
EventManager::registerTick(handler, frequency, plugin_self);
CoreSuspender suspend;
df::world* world = df::global::world;
df::ui* ui = df::global::ui;
int32_t xOffset = world->map.region_x*3;
int32_t yOffset = world->map.region_y*3;
int32_t zOffset = world->map.region_z;

@ -65,7 +65,7 @@
#include "df/activity_event_individual_skill_drillst.h"
#include "df/activity_event_skill_demonstrationst.h"
#include "df/activity_event_sparringst.h"
#include "df/building_hivest.h"
//#include "df/building_hivest.h"
#include <stdlib.h>
@ -119,8 +119,6 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" Causes 'Train' orders to no longer be considered 'patrol duty' so\n"
" soldiers will stop getting unhappy thoughts. Does NOT fix the problem\n"
" when soldiers go off-duty (i.e. civilian).\n"
" tweak readable-build-plate [disable]\n"
" Fixes rendering of creature weight limits in pressure plate build menu.\n"
" tweak confirm-embark [disable]\n"
" Asks for confirmation on the embark setup screen before embarking\n"
" tweak stable-temp [disable]\n"
@ -129,9 +127,9 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" Further improves temperature updates by ensuring that 1 degree of\n"
" item temperature is crossed in no more than specified number of frames\n"
" when updating from the environment temperature. Use 0 to disable.\n"
" tweak fix-dimensions [disable]\n"
/*" tweak fix-dimensions [disable]\n"
" Fixes subtracting small amount of thread/cloth/liquid from a stack\n"
" by splitting the stack and subtracting from the remaining single item.\n"
" by splitting the stack and subtracting from the remaining single item.\n"*/
" tweak advmode-contained [disable]\n"
" Fixes custom reactions with container inputs in advmode. The issue is\n"
" that the screen tries to force you to select the contents separately\n"
@ -146,10 +144,8 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" tweak military-color-assigned [disable]\n"
" Color squad candidates already assigned to other squads in brown/green\n"
" to make them stand out more in the list.\n"
" tweak military-training [disable]\n"
" Speed up melee squad training, removing inverse dependency on unit count.\n"
" tweak hive-crash [disable]\n"
" Prevents crash if bees die in a hive with uncollected products (bug 6368).\n"
// " tweak military-training [disable]\n"
// " Speed up melee squad training, removing inverse dependency on unit count.\n"
" tweak craft-age-wear [disable]\n"
" Makes cloth and leather items wear out at the correct rate (bug 6003).\n"
" tweak adamantine-cloth-wear [disable]\n"
@ -302,38 +298,6 @@ struct patrol_duty_hook : df::squad_order_trainst
IMPLEMENT_VMETHOD_INTERPOSE(patrol_duty_hook, isPatrol);
struct readable_build_plate_hook : df::viewscreen_dwarfmodest
{
typedef df::viewscreen_dwarfmodest interpose_base;
DEFINE_VMETHOD_INTERPOSE(void, render, ())
{
INTERPOSE_NEXT(render)();
if (ui->main.mode == ui_sidebar_mode::Build &&
ui_build_selector->stage == 1 &&
ui_build_selector->building_type == building_type::Trap &&
ui_build_selector->building_subtype == trap_type::PressurePlate &&
ui_build_selector->plate_info.flags.bits.units)
{
auto dims = Gui::getDwarfmodeViewDims();
int x = dims.menu_x1;
Screen::Pen pen(' ',COLOR_WHITE);
int minv = ui_build_selector->plate_info.unit_min;
if ((minv % 1000) == 0)
Screen::paintString(pen, x+11, 14, stl_sprintf("%3dK ", minv/1000));
int maxv = ui_build_selector->plate_info.unit_max;
if (maxv < 200000 && (maxv % 1000) == 0)
Screen::paintString(pen, x+24, 14, stl_sprintf("%3dK ", maxv/1000));
}
}
};
IMPLEMENT_VMETHOD_INTERPOSE(readable_build_plate_hook, render);
enum confirm_embark_states
{
ECS_INACTIVE = 0,
@ -1043,62 +1007,21 @@ struct military_training_id_hook : df::activity_event_individual_skill_drillst {
IMPLEMENT_VMETHOD_INTERPOSE(military_training_id_hook, process);
*/
struct hive_crash_hook : df::building_hivest {
typedef df::building_hivest interpose_base;
DEFINE_VMETHOD_INTERPOSE(void, updateAction, ())
{
bool any_bees = false;
for (size_t i = 0; i < contained_items.size(); i++)
{
if (contained_items[i]->item->getType() != item_type::VERMIN)
continue;
any_bees = true;
break;
}
if (!any_bees)
{
bool any_products = false;
for (size_t i = 0; i < contained_items.size(); i++)
{
if (contained_items[i]->use_mode != 0 ||
!contained_items[i]->item->flags.bits.in_building)
continue;
contained_items[i]->item->flags.bits.in_building = false;
any_products = true;
}
if (any_products)
{
color_ostream_proxy out(Core::getInstance().getConsole());
out.print("Bees died in hive with products at (%d,%d,%d); preventing crash.\n",
centerx, centery, z);
}
}
INTERPOSE_NEXT(updateAction)();
}
};
IMPLEMENT_VMETHOD_INTERPOSE(hive_crash_hook, updateAction);
struct craft_age_wear_hook : df::item_crafted {
typedef df::item_crafted interpose_base;
DEFINE_VMETHOD_INTERPOSE(void, ageItem, (int amount))
DEFINE_VMETHOD_INTERPOSE(bool, ageItem, (int amount))
{
int orig_age = age;
age += amount;
if (age > 200000000)
age = 200000000;
if (age == orig_age)
return;
return false;
MaterialInfo mat(mat_type, mat_index);
if (!mat.isValid())
return;
return false;
int wear = 0;
if (mat.material->flags.is_set(material_flags::WOOD))
@ -1109,10 +1032,12 @@ struct craft_age_wear_hook : df::item_crafted {
mat.material->flags.is_set(material_flags::YARN))
wear = 1;
else
return;
return false;
wear = ((orig_age % wear) + (age - orig_age)) / wear;
if (wear > 0)
addWear(wear, false, false);
return incWearTimer(wear);
else
return false;
}
};
IMPLEMENT_VMETHOD_INTERPOSE(craft_age_wear_hook, ageItem);
@ -1247,7 +1172,7 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
if (!unit)
return CR_FAILURE;
if(unit->race != df::global::ui->race_id)
if(unit->race != ui->race_id)
{
out << "Selected unit does not belong to your race!" << endl;
return CR_FAILURE;
@ -1267,8 +1192,8 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
// so it should not be triggered in most cases
// if it happens that the player has 'foreign' units of the same race
// (vanilla df: dwarves not from mountainhome) on his map, just grab them
if(unit->civ_id != df::global::ui->civ_id)
unit->civ_id = df::global::ui->civ_id;
if(unit->civ_id != ui->civ_id)
unit->civ_id = ui->civ_id;
return fix_clothing_ownership(out, unit);
}
@ -1286,8 +1211,8 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
unit->flags1.bits.merchant = 0;
if(unit->flags1.bits.forest)
unit->flags1.bits.forest = 0;
if(unit->civ_id != df::global::ui->civ_id)
unit->civ_id = df::global::ui->civ_id;
if(unit->civ_id != ui->civ_id)
unit->civ_id = ui->civ_id;
if(unit->profession == df::profession::MERCHANT)
unit->profession = df::profession::TRADER;
if(unit->profession2 == df::profession::MERCHANT)
@ -1302,16 +1227,6 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
{
enable_hook(out, INTERPOSE_HOOK(patrol_duty_hook, isPatrol), parameters);
}
else if (cmd == "readable-build-plate")
{
if (!ui_build_selector || !ui_menu_width || !ui_area_map_width)
{
out.printerr("Necessary globals not known.\n");
return CR_FAILURE;
}
enable_hook(out, INTERPOSE_HOOK(readable_build_plate_hook, render), parameters);
}
else if (cmd == "confirm-embark")
{
enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, feed), parameters);
@ -1334,14 +1249,14 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
enable_hook(out, INTERPOSE_HOOK(fast_heat_hook, updateTemperature), parameters);
enable_hook(out, INTERPOSE_HOOK(fast_heat_hook, adjustTemperature), parameters);
}
else if (cmd == "fix-dimensions")
/*else if (cmd == "fix-dimensions")
{
enable_hook(out, INTERPOSE_HOOK(dimension_liquid_hook, subtractDimension), parameters);
enable_hook(out, INTERPOSE_HOOK(dimension_powder_hook, subtractDimension), parameters);
enable_hook(out, INTERPOSE_HOOK(dimension_bar_hook, subtractDimension), parameters);
enable_hook(out, INTERPOSE_HOOK(dimension_thread_hook, subtractDimension), parameters);
enable_hook(out, INTERPOSE_HOOK(dimension_cloth_hook, subtractDimension), parameters);
}
}*/
else if (cmd == "advmode-contained")
{
enable_hook(out, INTERPOSE_HOOK(advmode_contained_hook, feed), parameters);
@ -1367,10 +1282,6 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
enable_hook(out, INTERPOSE_HOOK(military_training_sp_hook, process), parameters);
enable_hook(out, INTERPOSE_HOOK(military_training_id_hook, process), parameters);
}*/
else if (cmd == "hive-crash")
{
enable_hook(out, INTERPOSE_HOOK(hive_crash_hook, updateAction), parameters);
}
else if (cmd == "craft-age-wear")
{
enable_hook(out, INTERPOSE_HOOK(craft_age_wear_hook, ageItem), parameters);

@ -143,8 +143,6 @@ void OutputToggleString(int &x, int &y, const char *text, const char *hotkey, bo
OutputString(COLOR_GREY, x, y, "Off", newline, left_margin);
}
const int ascii_to_enum_offset = interface_key::STRING_A048 - '0';
inline string int_to_string(const int n)
{
return static_cast<ostringstream*>( &(ostringstream() << n) )->str();
@ -792,11 +790,11 @@ public:
{
// Search query typing mode always on
df::interface_key last_token = *input->rbegin();
if ((last_token >= interface_key::STRING_A096 && last_token <= interface_key::STRING_A123) ||
last_token == interface_key::STRING_A032)
int charcode = Screen::keyToChar(last_token);
if ((charcode >= 96 && charcode <= 123) || charcode == 32)
{
// Standard character
search_string += last_token - ascii_to_enum_offset;
search_string += char(charcode);
filterDisplay();
centerSelection();
}

@ -13,6 +13,8 @@ using std::string;
using namespace DFHack;
using namespace df::enums;
using df::global::current_weather;
bool locked = false;
unsigned char locked_data[25];
@ -84,7 +86,7 @@ command_result weather (color_ostream &con, vector <string> & parameters)
CoreSuspender suspend;
if(!df::global::current_weather)
if(!current_weather)
{
con << "Weather support seems broken :(" << std::endl;
return CR_FAILURE;
@ -97,7 +99,7 @@ command_result weather (color_ostream &con, vector <string> & parameters)
{
for(int x = 0; x<5;x++)
{
switch((*df::global::current_weather)[x][y])
switch((*current_weather)[x][y])
{
case weather_type::None:
con << "C ";
@ -109,7 +111,7 @@ command_result weather (color_ostream &con, vector <string> & parameters)
con << "S ";
break;
default:
con << (int) (*df::global::current_weather)[x][y] << " ";
con << (int) (*current_weather)[x][y] << " ";
break;
}
}

@ -14,6 +14,9 @@
using namespace std;
using namespace DFHack;
using df::global::process_jobs;
using df::global::process_dig;
DFHACK_PLUGIN("workNow");
static int mode = 0;
@ -24,6 +27,9 @@ void jobCompletedHandler(color_ostream& out, void* ptr);
EventManager::EventHandler handler(jobCompletedHandler,1);
DFhackCExport command_result plugin_init(color_ostream& out, std::vector<PluginCommand> &commands) {
if (!process_jobs || !process_dig)
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"
"workNow\n"
" print workNow status\n"
@ -53,8 +59,8 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
if ( e != DFHack::SC_PAUSED )
return CR_OK;
*df::global::process_jobs = true;
*df::global::process_dig = true;
*process_jobs = true;
*process_dig = true;
return CR_OK;
}
@ -88,6 +94,6 @@ void jobCompletedHandler(color_ostream& out, void* ptr) {
if ( mode < 2 )
return;
*df::global::process_jobs = true;
*df::global::process_dig = true;
*process_jobs = true;
*process_dig = true;
}

@ -79,6 +79,18 @@ using df::global::cursor;
using df::global::ui;
using df::global::ui_build_selector;
using df::global::gps;
using df::global::cur_year;
using df::global::cur_year_tick;
using df::global::ui_building_item_cursor;
using df::global::ui_building_assign_type;
using df::global::ui_building_assign_is_marked;
using df::global::ui_building_assign_units;
using df::global::ui_building_assign_items;
using df::global::ui_building_in_assign;
using df::global::ui_menu_width;
using df::global::ui_area_map_width;
using namespace DFHack::Gui;
@ -360,8 +372,8 @@ int32_t getUnitAge(df::unit* unit)
{
// If the birthday this year has not yet passed, subtract one year.
// ASSUMPTION: birth_time is on the same scale as cur_year_tick
int32_t yearDifference = *df::global::cur_year - unit->relations.birth_year;
if (unit->relations.birth_time >= *df::global::cur_year_tick)
int32_t yearDifference = *cur_year - unit->relations.birth_year;
if (unit->relations.birth_time >= *cur_year_tick)
yearDifference--;
return yearDifference;
}
@ -529,12 +541,12 @@ bool isOwnRace(df::unit* unit)
// todo: rename these two functions to "getRaceToken" since the output is more of a token
string getRaceName(int32_t id)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[id];
df::creature_raw *raw = world->raws.creatures.all[id];
return raw->creature_id;
}
string getRaceName(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
return raw->creature_id;
}
@ -542,18 +554,18 @@ string getRaceName(df::unit* unit)
string getRaceNamePlural(int32_t id)
{
//WatchedRace * w = watched_races[idx];
df::creature_raw *raw = df::global::world->raws.creatures.all[id];
df::creature_raw *raw = world->raws.creatures.all[id];
return raw->name[1]; // second field is plural of race name
}
string getRaceBabyName(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
return raw->general_baby_name[0];
}
string getRaceChildName(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
return raw->general_child_name[0];
}
@ -574,7 +586,7 @@ bool isAdult(df::unit* unit)
bool isEggLayer(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
@ -588,7 +600,7 @@ bool isEggLayer(df::unit* unit)
bool isGrazer(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
@ -601,7 +613,7 @@ bool isGrazer(df::unit* unit)
bool isMilkable(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
@ -614,7 +626,7 @@ bool isMilkable(df::unit* unit)
bool isTrainableWar(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
@ -627,7 +639,7 @@ bool isTrainableWar(df::unit* unit)
bool isTrainableHunting(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
@ -640,7 +652,7 @@ bool isTrainableHunting(df::unit* unit)
bool isTamable(df::unit* unit)
{
df::creature_raw *raw = df::global::world->raws.creatures.all[unit->race];
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
@ -3162,7 +3174,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
for(size_t i=0; i<watched_races.size(); i++)
{
WatchedRace * w = watched_races[i];
df::creature_raw * raw = df::global::world->raws.creatures.all[w->raceId];
df::creature_raw * raw = world->raws.creatures.all[w->raceId];
string name = raw->creature_id;
if(w->isWatched)
out << "watched: ";
@ -3204,7 +3216,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
for(size_t i=0; i<watched_races.size(); i++)
{
WatchedRace * w = watched_races[i];
df::creature_raw * raw = df::global::world->raws.creatures.all[w->raceId];
df::creature_raw * raw = world->raws.creatures.all[w->raceId];
string name = raw->creature_id;
out << run << "target"
@ -3300,7 +3312,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
else
{
// map race names from parameter list to ids
size_t num_races = df::global::world->raws.creatures.all.size();
size_t num_races = world->raws.creatures.all.size();
while(target_racenames.size())
{
bool found_race = false;
@ -4079,15 +4091,6 @@ DFHACK_PLUGIN_LUA_COMMANDS {
//START zone filters
using df::global::ui_building_item_cursor;
using df::global::ui_building_assign_type;
using df::global::ui_building_assign_is_marked;
using df::global::ui_building_assign_units;
using df::global::ui_building_assign_items;
using df::global::ui_building_in_assign;
static const int ascii_to_enum_offset = interface_key::STRING_A048 - '0';
void OutputString(int8_t color, int &x, int y, const std::string &text)
{
@ -4241,10 +4244,11 @@ public:
}
df::interface_key last_token = *input->rbegin();
if (last_token >= interface_key::STRING_A032 && last_token <= interface_key::STRING_A126)
int charcode = Screen::keyToChar(last_token);
if (charcode >= 32 && charcode <= 126)
{
// Standard character
search_string += last_token - ascii_to_enum_offset;
search_string += char(charcode);
apply_filters();
}
else if (last_token == interface_key::STRING_A000)
@ -4319,8 +4323,8 @@ public:
return;
int left_margin = gps->dimx - 30;
int8_t a = *df::global::ui_menu_width;
int8_t b = *df::global::ui_area_map_width;
int8_t a = *ui_menu_width;
int8_t b = *ui_area_map_width;
if ((a == 1 && b > 1) || (a == 2 && b == 2))
left_margin -= 24;

@ -137,8 +137,8 @@ local function exec_finder(finder, names)
end
local search = force_scan['all']
for _,v in ipairs(names) do
table.insert(finder_searches, v)
if force_scan[v] or not is_known(v) then
table.insert(finder_searches, v)
search = true
end
end
@ -704,9 +704,9 @@ Auto-searching for ui_build_selector. This requires mechanisms.]],
'BUILDING_TRIGGER_ENABLE_CREATURE'
)
else
dwarfmode_feed_input('BUILDING_TRIGGER_MIN_SIZE_DOWN')
dwarfmode_feed_input('BUILDING_TRIGGER_MIN_SIZE_UP')
end
return true, 50000 - 1000*idx
return true, 5000 + 1000*idx
end,
20
)
@ -716,10 +716,9 @@ Auto-searching for ui_build_selector. This requires mechanisms.]],
addr = searcher:find_menu_cursor([[
Searching for ui_build_selector. Please start constructing
a pressure plate, and enable creatures. Then change the min
weight as requested, remembering that the ui truncates the
number, so when it shows "Min (5000df", it means 50000:]],
weight as requested, knowing that the ui shows 5000 as 5K:]],
'int32_t',
{ 50000, 49000, 48000, 47000, 46000, 45000, 44000 }
{ 5000, 6000, 7000, 8000, 9000, 10000, 11000 }
)
end
@ -1546,7 +1545,9 @@ exec_finder(find_process_jobs, 'process_jobs')
exec_finder(find_process_dig, 'process_dig')
exec_finder(find_pause_state, 'pause_state')
print('\nDone. Now add newly-found globals to symbols.xml.\n')
print('\nDone. Now exit the game with the die command and add\n'..
'the newly-found globals to symbols.xml. You can find them\n'..
'in stdout.log or here:\n')
for _, global in ipairs(finder_searches) do
local addr = dfhack.internal.getAddress(global)

@ -1,88 +0,0 @@
-- Fixes cloth/thread stockpiles by correcting material object data.
local raws = df.global.world.raws
-- Cache references to vectors in lua tables for a speed-up
local organic_types = {}
for i,v in ipairs(raws.mat_table.organic_types) do
organic_types[i] = v
end
local organic_indexes = {}
for i,v in ipairs(raws.mat_table.organic_indexes) do
organic_indexes[i] = v
end
local function verify(category,idx,vtype,vidx)
if idx == -1 then
-- Purely for reporting reasons
return true
end
local tvec = organic_types[category]
if idx < 0 or idx >= #tvec or tvec[idx] ~= vtype then
return false
end
return organic_indexes[category][idx] == vidx
end
local patched_cnt = 0
local mat_cnt = 0
function patch_material(mat,mat_type,mat_index)
local idxarr = mat.food_mat_index
-- These refer to fish/eggs, i.e. castes and not materials
idxarr[1] = -1
idxarr[2] = -1
idxarr[3] = -1
for i = 0,#idxarr-1 do
if not verify(i,idxarr[i],mat_type,mat_index) then
idxarr[i] = -1
patched_cnt = patched_cnt+1
end
end
mat_cnt = mat_cnt + 1
end
function patch_materials()
patched_cnt = 0
mat_cnt = 0
print('Fixing cloth stockpile handling (bug 5739)...')
for i,v in ipairs(raws.inorganics) do
patch_material(v.material, 0, i)
end
for i,v in ipairs(raws.creatures.all) do
for j,m in ipairs(v.material) do
patch_material(m, 19+j, i)
end
end
for i,v in ipairs(raws.plants.all) do
for j,m in ipairs(v.material) do
patch_material(m, 419+j, i)
end
end
print('Patched '..patched_cnt..' bad references in '..mat_cnt..' materials.')
end
local args = {...}
if args[1] == 'enable' then
dfhack.onStateChange[_ENV] = function(sc)
if sc == SC_WORLD_LOADED then
patch_materials()
end
end
if dfhack.isWorldLoaded() then
patch_materials()
end
elseif args[1] == 'disable' then
dfhack.onStateChange[_ENV] = nil
else
patch_materials()
end

@ -1,35 +0,0 @@
--growth-bug.lua: units only grow when the current tick is 0 mod 10, so only 1/10 units will grow naturally. this script periodically sets the birth time of each unit so that it will grow
--to run periodically, use "repeat -time 2 months -command fix/growth-bug -now". see repeat.lua for details
--author expwnent
local utils = require 'utils'
validArgs = validArgs or utils.invert({
'help',
'now'
})
local args = utils.processArgs({...}, validArgs)
if args.help or not next(args) then
print("fix/growth-bug usage")
print(" fix/growth-bug")
print(" fix the growth bug for all units on the map")
print(" fix/growth-bug -help")
print(" print this help message")
print(" repeat -time [n] [years/months/ticks/days/etc] -command fix/growth-bug now")
print(" run this script every n time units")
print(" repeat -cancel fix/growth-bug")
print(" stop automatically running this script")
end
local count = 0
for _,unit in ipairs(df.global.world.units.all) do
local offset = unit.relations.birth_time % 10;
if offset ~= 0 then
unit.relations.birth_time = unit.relations.birth_time - offset
count = count+1
end
end
print("Fixed growth bug for "..count.." units.")

@ -3,7 +3,7 @@
-- replaces autoSyndrome: trigger commands when custom reactions are completed
local eventful = require 'plugins.eventful'
local syndromeUtil = require 'syndromeUtil'
local syndromeUtil = require 'syndrome-util'
local utils = require 'utils'
reactionHooks = reactionHooks or {}