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

develop
Japa 2015-02-17 22:52:39 +05:30
commit f2461254d4
167 changed files with 6234 additions and 6118 deletions

@ -0,0 +1,6 @@
language: cpp
script:
- python travis/lint.py
- python travis/pr-check-base.py
notifications:
email: false

@ -160,6 +160,13 @@ Snow Leopard Changes
In <dfhack directory>/library/LuaTypes.cpp, change line 467 to
``int len = strlen((char*)ptr);``
Yoesmite Changes
================
If you have issues building after upgrading to Yosemite, try definining the folliwing environment variable:
export MACOSX_DEPLOYMENT_TARGET=10.9
=======
Windows
=======

@ -4,80 +4,93 @@ If you belong here and are missing, please add yourself and send me (peterix) a
The following is a list of people who have contributed to **DFHack**.
- Petr Mrázek <peterix@gmail.com>
- Alexander Gavrilov <angavrilov@gmail.com>
- doomchild <lee.crabtree@gmail.com>
- Quietust <quietust@gmail.com>
- jj <john-git@ofjj.net>
- Warmist <warmist@gmail.com>
- Robert Heinrich <robertheinrich73@googlemail.com>
- simon <simon@banquise.net>
- Kelly Martin <kelly.lynn.martin@gmail.com>
- mizipzor <mizipzor@gmail.com>
- Simon Jackson <sizeak@hotmail.com>
- belal <jimbelal@gmail.com>
- RusAnon <rusanon@dollchan.ru>
- Raoul XQ <raoulxq@gmail.com>
- Matthew Cline <zelgadis@sourceforge.net>
- Mike Stewart <thewonderidiot@gmail.com>
- Timothy Collett <tcollett+github@topazgryphon.org>
- RossM <Ross@Gnome>
- Tom Prince <tom.prince@ualberta.net>
- Jared Adams <jaxad0127@gmail.com>
- expwnent
- Erik Youngren <artanis.00@gmail.com>
- Espen Wiborg <espen.wiborg@telio.no>
- Tim Walberg <twalberg@comcast.net>
- Mikko Juola <mikko.juola@kolumbus.fi>
- rampaging-poet <yrudoingthis@hotmail.com>
- U-glouglou\\simon
- Clayton Hughes <clayton.hughes@gmail.com>
- zilpin <ziLpin@gmail.com>
- Will Rogers <wjrogers@gmail.com>
- NMLittle <nmlittle@gmail.com>
- root
- reverb
- Zhentar <Zhentar@gmail.com>
- Valentin Ochs <a@0au.de>
- Priit Laes <plaes@plaes.org>
- kmartin
- Neil Little
- rout <rout.mail+github@gmail.com>
- rofl0r <retnyg@gmx.net>
- harlanplayford <harlanplayford@gmail.com>
- gsvslto <gsvslto@gmail.com>
- sami
- potato
- playfordh <harlanplayford@gmail.com>
- feng1st <nf_xp@hotmail.com>
- comestible <nickolas.g.russell@gmail.com>
- Rumrusher <Anuleakage@yahoo.com>
- Rinin <RininS@Gmail.com>
- Raoul van Putten
- John Shade <gsvslto@gmail.com>
- John Beisley <greatred@gmail.com>
- Feng <nf_xp@hotmail.com>
- Donald Ruegsegger <druegsegger@gmail.com>
- Caldfir <caldfir@hotmail.com>
- Antalia <tamarakorr@gmail.com>
- Angus Mezick <amezick@gmail.com>
- PeridexisErrant <PeridexisErrant@gmail.com>
- Putnam
- Danaris
- Lethosor
- Eswald
- Ramblurr
- MithrilTuxedo
- AndreasPK
- cdombroski
======================= ==================== ===========================
Name Github Email
======================= ==================== ===========================
Petr Mrázek peterix peterix@gmail.com
Alexander Gavrilov angavrilov angavrilov@gmail.com
doomchild doomchild lee.crabtree@gmail.com
Quietust quietust quietust@gmail.com
jj jjyg john-git@ofjj.net
Warmist warmist warmist@gmail.com
Robert Heinrich rh73 robertheinrich73@googlemail.com
simon simon@banquise.net
Kelly Martin ab9rf kelly.lynn.martin@gmail.com
mizipzor mizipzor mizipzor@gmail.com
Simon Jackson sizeak sizeak@hotmail.com
belal jimhester jimbelal@gmail.com
RusAnon RusAnon rusanon@dollchan.ru
Raoul XQ raoulxq raoulxq@gmail.com
Matthew Cline zelgadis@sourceforge.net
Mike Stewart thewonderidiot thewonderidiot@gmail.com
Timothy Collett danaris tcollett+github@topazgryphon.org
RossM Ross@Gnome
Tom Prince tom.prince@ualberta.net
Jared Adams jaxad0127@gmail.com
expwnent expwnent
Erik Youngren Artanis artanis.00@gmail.com
Espen Wiborg espen.wiborg@telio.no
Tim Walberg twalberg twalberg@comcast.net
Mikko Juola Noeda mikko.juola@kolumbus.fi
rampaging-poet yrudoingthis@hotmail.com
U-glouglou\\simon simon@glouglou
Clayton Hughes clayton.hughes@gmail.com
zilpin zilpin ziLpin@gmail.com
Will Rogers wjrogers wjrogers@gmail.com
NMLittle nmlittle nmlittle@gmail.com
root
reverb
Zhentar Zhentar Zhentar@gmail.com
Valentin Ochs Cat-Ion a@0au.de
Priit Laes plaes plaes@plaes.org
kmartin
Neil Little
rout rout.mail+github@gmail.com
rofl0r rofl0r retnyg@gmx.net
harlanplayford playfordh harlanplayford@gmail.com
John Shade gsvslto gsvslto@gmail.com
sami
potato
feng1st nf_xp@hotmail.com
comestible nickrart nickolas.g.russell@gmail.com
Rumrusher rumrusher Anuleakage@yahoo.com
Rinin Rinin RininS@Gmail.com
Raoul van Putten
John Beisley huin greatred@gmail.com
Feng nf_xp@hotmail.com
Donald Ruegsegger hashaash druegsegger@gmail.com
Caldfir caldfir caldfir@hotmail.com
Antalia tamarakorr tamarakorr@gmail.com
Angus Mezick amezick amezick@gmail.com
Japa JapaMala japa.mala.illo@gmail.com
Putnam Putnam3145
Lethosor lethosor
PeridexisErrant PeridexisErrant PeridexisErrant@gmail.com
Eswald eswald
Ramblurr Ramblurr
MithrilTuxedo MithrilTuxedo
AndreasPK AndreasPK
Chris Dombroski cdombroski
Ben Lubar BenLubar
miffedmap miffedmap
scamtank scamtank
Mason11987 Mason11987
======================= ==================== ===========================
And those are the cool people who made **stonesense**.
And these are the cool people who made **Stonesense**.
- Kris Parker <kaypy>
- Japa <japa.mala.illo@gmail.com>
- Jonas Ask <jonask84@gmail.com>
- Petr Mrázek <peterix@gmail.com>
- Caldfir <aitken.tim@gmail.com>
- 8Z <git8z@ya.ru>
- Alexander Gavrilov <angavrilov@gmail.com>
- Timothy Collett <tcollett+github@topazgryphon.org>
======================= ==================== ===========================
Name Github Email
======================= ==================== ===========================
Kris Parker kaypy
Japa JapaMala japa.mala.illo@gmail.com
Jonas Ask jonask84@gmail.com
Petr Mrázek peterix peterix@gmail.com>
Caldfir caldfir aitken.tim@gmail.com
8Z 8Z git8z@ya.ru
Alexander Gavrilov angavrilov angavrilov@gmail.com
Timothy Collett danaris tcollett+github@topazgryphon.org
Lethosor lethosor
Eswald eswald
PeridexisErrant PeridexisErrant PeridexisErrant@gmail.com
======================= ==================== ===========================

@ -2,6 +2,7 @@ DFHack Future
Internals
Lua scripts will only be reloaded if necessary
Added support for onLoadMap/onUnloadMap.init scripts
Added df2console() wrapper, useful for printing DF (CP437-encoded) text to the console in a portable way
New internal commands:
hide/show: hide and show the console on Windows
sc-script: Allows additional scripts to be run when certain events occur (similar to onLoad*.init scripts)
@ -22,6 +23,8 @@ DFHack Future
tradereq-pet-gender: Displays pet genders on the trade request screen
Removed
Misc Improvements
exportlegends: 'info' and 'all' exports legends_plus xml with more data for legends utilities
remotefortressreader: Exposes more information
DFHack 0.40.24-r2
Internals
@ -71,7 +74,6 @@ DFHack 0.40.24-r2
Removed
Misc Improvements
Multiline commands are now possible inside dfhack.init scripts. See dfhack.init-example for example usage.
exportlegends: 'info' and 'all' exports legends_plus xml with more data for legends utilities
DFHack 0.40.24-r1
Internals

File diff suppressed because it is too large Load Diff

@ -1601,8 +1601,8 @@ void Core::onUpdate(color_ostream &out)
void Core::handleLoadAndUnloadScripts(color_ostream& out, state_change_event event) {
if (!df::global::world)
return;
//TODO: use different separators for windows
return;
//TODO: use different separators for windows
#ifdef _WIN32
static const std::string separator = "\\";
#else

@ -143,7 +143,7 @@ DFhackCExport uint32_t SDL_GetTicks(void)
/***** Surfaces
SDL_CreateRGBSurface
SDL_Surface * SDLCALL SDL_CreateRGBSurface
(Uint32 flags, int width, int height, int depth,
(Uint32 flags, int width, int height, int depth,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
SDL_CreateRGBSurfaceFrom
@ -216,7 +216,7 @@ SDL_SaveBMP_RW
SDL_SetAlpha
int SDLCALL SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
SDL_SetColorKey
int SDLCALL SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
@ -311,16 +311,16 @@ DFhackCExport int SDL_UpperBlit(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect*
/***** Even more surface
SDL_GL_GetAttribute
int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int* value);
SDL_GL_SetAttribute
int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value);
SDL_WM_SetCaption
void SDLCALL SDL_WM_SetCaption(const char *title, const char *icon);
SDL_WM_SetIcon
void SDLCALL SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask);
SDL_FillRect
int SDLCALL SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
*/
@ -787,7 +787,7 @@ bool FirstCall()
_SDL_mutexP = (int (*)(vPtr))GetProcAddress(realSDLlib,"SDL_mutexP");
_SDL_mutexV = (int (*)(vPtr))GetProcAddress(realSDLlib,"SDL_mutexV");
_SDL_strlcpy = (size_t (*)(char*, const char*, size_t))GetProcAddress(realSDLlib,"SDL_strlcpy");
// stuff for SDL_Image
_SDL_ClearError = (void (*)())GetProcAddress(realSDLlib,"SDL_ClearError");
_SDL_Error = (void (*)(int))GetProcAddress(realSDLlib,"SDL_Error");
@ -799,7 +799,7 @@ bool FirstCall()
_SDL_SetError = (void (*)(const char*, ...))GetProcAddress(realSDLlib,"SDL_SetError");
_SDL_UnloadObject = (void (*)(vPtr))GetProcAddress(realSDLlib,"SDL_UnloadObject");
_SDL_FillRect = (int (*)(void*,void*,uint32_t))GetProcAddress(realSDLlib,"SDL_FillRect");
// new in DF 0.31.04
_SDL_CreateSemaphore = (void* (*)(uint32_t))GetProcAddress(realSDLlib,"SDL_CreateSemaphore");
_SDL_CreateThread = (vPtr (*)(int (*fn)(void *), void *data))GetProcAddress(realSDLlib,"SDL_CreateThread");
@ -812,7 +812,7 @@ bool FirstCall()
_SDL_SemTryWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemTryWait");
_SDL_SemWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemWait");
_SDL_ThreadID = (uint32_t (*)(void))GetProcAddress(realSDLlib,"SDL_ThreadID");
_SDL_EnableUNICODE(1);
fprintf(stderr,"Initized HOOKS!\n");

@ -1282,6 +1282,7 @@ static bool isMapLoaded() { return Core::getInstance().isMapLoaded(); }
static std::string df2utf(std::string s) { return DF2UTF(s); }
static std::string utf2df(std::string s) { return UTF2DF(s); }
static std::string df2console(std::string s) { return DF2CONSOLE(s); }
static const LuaWrapper::FunctionReg dfhack_module[] = {
WRAP(getOSType),
@ -1294,6 +1295,7 @@ static const LuaWrapper::FunctionReg dfhack_module[] = {
WRAPM(Translation, TranslateName),
WRAP(df2utf),
WRAP(utf2df),
WRAP(df2console),
{ NULL, NULL }
};

@ -347,3 +347,19 @@ std::string UTF2DF(const std::string &in)
out.resize(pos);
return out;
}
DFHACK_EXPORT std::string DF2CONSOLE(const std::string &in)
{
bool is_utf = false;
#ifdef LINUX_BUILD
std::string locale = "";
if (getenv("LANG"))
locale += getenv("LANG");
if (getenv("LC_CTYPE"))
locale += getenv("LC_CTYPE");
locale = toUpper(locale);
is_utf = (locale.find("UTF-8") != std::string::npos) ||
(locale.find("UTF8") != std::string::npos);
#endif
return is_utf ? DF2UTF(in) : in;
}

@ -345,7 +345,7 @@ namespace DFHack
bool is_direct_instance(virtual_ptr instance_ptr) {
if (!instance_ptr) return false;
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
: (this == get(instance_ptr));
}

@ -348,3 +348,4 @@ DFHACK_EXPORT std::string stl_vsprintf(const char *fmt, va_list args);
// Conversion between CP437 and UTF-8
DFHACK_EXPORT std::string UTF2DF(const std::string &in);
DFHACK_EXPORT std::string DF2UTF(const std::string &in);
DFHACK_EXPORT std::string DF2CONSOLE(const std::string &in);

@ -98,6 +98,7 @@ namespace DFHack
function(function_), interactive(interactive_),
guard(NULL), usage(usage_)
{
fix_usage();
}
PluginCommand(const char * _name,
@ -109,6 +110,13 @@ namespace DFHack
function(function_), interactive(false),
guard(guard_), usage(usage_)
{
fix_usage();
}
void fix_usage()
{
if (usage.size() && usage[usage.size() - 1] != '\n')
usage.push_back('\n');
}
bool isHotkeyCommand() const { return guard != NULL; }

@ -42,7 +42,7 @@ distribution.
/**
* [peterix@peterix dfhack]$ man wcscpy_s
* No manual entry for wcscpy_s
*
*
* Proprietary extensions.
*/
// disable stupid

@ -78,7 +78,7 @@ namespace SDL
K_GREATER = 62,
K_QUESTION = 63,
K_AT = 64,
/*
/*
Skip uppercase letters
*/
K_LEFTBRACKET = 91,

@ -335,7 +335,7 @@ namespace DFHack
* zilpin: Find a tile type similar to the one given, but with a different class.
* Useful for tile-editing operations.
* If no match found, returns the sourceType
*
*
* @todo Definitely needs improvement for wall directions, etc.
*/
DFHACK_EXPORT df::tiletype findSimilarTileType( const df::tiletype sourceTileType, const df::tiletype_shape tshape );

@ -193,14 +193,14 @@ void clearBuildings(color_ostream& out);
/**
* Iterates over the items stored on a stockpile.
* (For stockpiles with containers, yields the containers, not their contents.)
*
*
* Usage:
*
*
* Buildings::StockpileIterator stored;
* for (stored.begin(stockpile); !stored.done(); ++stored) {
* df::item *item = *stored;
* }
*
*
* Implementation detail: Uses tile blocks for speed.
* For each tile block that contains at least part of the stockpile,
* starting at the top left and moving right, row by row,
@ -212,14 +212,14 @@ class DFHACK_EXPORT StockpileIterator : public std::iterator<std::input_iterator
df::map_block* block;
size_t current;
df::item *item;
public:
StockpileIterator() {
stockpile = NULL;
block = NULL;
item = NULL;
}
StockpileIterator& operator++() {
while (stockpile) {
if (block) {
@ -230,7 +230,7 @@ public:
block = Maps::getTileBlock(stockpile->x1, stockpile->y1, stockpile->z);
current = 0;
}
while (current >= block->items.size()) {
// Out of items in this block; find the next block to search.
if (block->map_pos.x + 16 < stockpile->x2) {
@ -246,39 +246,39 @@ public:
return *this;
}
}
// If the current item isn't properly stored, move on to the next.
item = df::item::find(block->items[current]);
if (!item->flags.bits.on_ground) {
continue;
}
if (!Buildings::containsTile(stockpile, item->pos, false)) {
continue;
}
// Ignore empty bins, barrels, and wheelbarrows assigned here.
if (item->isAssignedToThisStockpile(stockpile->id)) {
auto ref = Items::getGeneralRef(item, df::general_ref_type::CONTAINS_ITEM);
if (!ref) continue;
}
// Found a valid item; yield it.
break;
}
return *this;
}
void begin(df::building_stockpilest* sp) {
stockpile = sp;
operator++();
}
df::item* operator*() {
return item;
}
bool done() {
return block == NULL;
}

@ -59,7 +59,7 @@ namespace DFHack {
}
};
struct InventoryItem {
//it has to keep the id of an item because the item itself may have been deallocated
int32_t itemId;
@ -74,7 +74,7 @@ namespace DFHack {
InventoryChangeData() {}
InventoryChangeData(int32_t id_in, InventoryItem* old_in, InventoryItem* new_in): unitId(id_in), item_old(old_in), item_new(new_in) {}
};
struct UnitAttackData {
int32_t attacker;
int32_t defender;
@ -89,7 +89,7 @@ namespace DFHack {
int32_t attackReport;
int32_t defendReport;
};
DFHACK_EXPORT void registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin);
DFHACK_EXPORT int32_t registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute=false);
DFHACK_EXPORT void unregister(EventType::EventType e, EventHandler handler, Plugin* plugin);

@ -72,7 +72,7 @@ class BlockInfo
Block *mblock;
MapCache *parent;
df::map_block *block;
df::map_block_column *column; //for plants
df::map_block_column *column; //for plants
public:
enum GroundType {

@ -181,7 +181,7 @@ extern DFHACK_EXPORT bool IsValid();
* Method for reading the geological surrounding of the currently loaded region.
* assign is a reference to an array of nine vectors of unsigned words that are to be filled with the data
* array is indexed by the BiomeOffset enum
*
*
* I omitted resolving the layer matgloss in this API, because it would
* introduce overhead by calling some method for each tile. You have to do it
* yourself.

@ -63,7 +63,7 @@ namespace Windows
uint8_t bright;
};
// our silly painter things and window things follow.
class df_window;
struct df_tilebuf

@ -138,13 +138,13 @@
* only defined for compatibility. These macros should always return false
* on Windows.
*/
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#ifdef __cplusplus
extern "C" {

@ -41,7 +41,7 @@ jobs_furnace={
},
--[[ [df.furnace_type.MetalsmithsForge]={
unpack(concat(furnaces,mechanism,anvil,crafts,coins,flask))
},
]]
--MetalsmithsForge,
@ -86,7 +86,7 @@ jobs_furnace={
},
}
jobs_workshop={
[df.workshop_type.Jewelers]={
{
name="cut gems",
@ -146,7 +146,7 @@ jobs_workshop={
items={{}},
job_fields={job_type=df.job_type.ConstructArmorStand}
},
{
name="construct blocks",
items={{}},
@ -226,13 +226,13 @@ jobs_workshop={
[df.workshop_type.Carpenters]={
--training weapons, wooden shields
defaults={item_type=df.item_type.WOOD,vector_id=df.job_item_vector_id.WOOD},
{
name="make barrel",
items={{}},
job_fields={job_type=df.job_type.MakeBarrel}
},
{
name="make bucket",
items={{}},
@ -550,7 +550,7 @@ function getJobs(buildingId,workshopId,customId)
c_jobs=jobs_workshop[workshopId]
elseif buildingId==df.building_type.Furnace then
c_jobs=jobs_furnace[workshopId]
if workshopId == df.furnace_type.Smelter or workshopId == df.furnace_type.MagmaSmelter then
c_jobs=utils.clone(c_jobs,true)
addSmeltJobs(c_jobs,workshopId == df.furnace_type.Smelter)
@ -563,7 +563,7 @@ function getJobs(buildingId,workshopId,customId)
else
c_jobs=utils.clone(c_jobs,true)
end
addReactionJobs(c_jobs,buildingId,workshopId,customId)
for jobId,contents in pairs(c_jobs) do
if jobId~="defaults" then

@ -27,22 +27,22 @@ local _ENV = mkmodule('dumper')
local dumplua_closure = [[
local closures = {}
local function closure(t)
local function closure(t)
closures[#closures+1] = t
t[1] = assert(loadstring(t[1]))
return t[1]
end
for _,t in pairs(closures) do
for i = 2,#t do
debug.setupvalue(t[1], i-1, t[i])
end
for i = 2,#t do
debug.setupvalue(t[1], i-1, t[i])
end
end
]]
local lua_reserved_keywords = {
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for',
'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for',
'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
'return', 'then', 'true', 'until', 'while' }
local function keys(t)
@ -63,7 +63,7 @@ local function keys(t)
end
local c_functions = {}
for _,lib in pairs{'_G', 'string', 'table', 'math',
for _,lib in pairs{'_G', 'string', 'table', 'math',
'io', 'os', 'coroutine', 'package', 'debug'} do
local t = _G[lib] or {}
lib = lib .. "."
@ -79,9 +79,9 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
indent_step = indent_step or 2
local defined, dumplua = {}
-- Local variables for speed optimization
local string_format, type, string_dump, string_rep =
local string_format, type, string_dump, string_rep =
string.format, type, string.dump, string.rep
local tostring, pairs, table_concat =
local tostring, pairs, table_concat =
tostring, pairs, table.concat
local keycache, strvalcache, out, closure_cnt = {}, {}, {}, 0
setmetatable(strvalcache, {__index = function(t,value)
@ -94,8 +94,8 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
number = function(value) return value end,
boolean = function(value) return tostring(value) end,
['nil'] = function(value) return 'nil' end,
['function'] = function(value)
return string_format("loadstring(%q)", string_dump(value))
['function'] = function(value)
return string_format("loadstring(%q)", string_dump(value))
end,
userdata = function() error("Cannot dump userdata") end,
thread = function() error("Cannot dump threads") end,
@ -124,7 +124,7 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
for _,k in ipairs(lua_reserved_keywords) do
keycache[k] = '["'..k..'"] = '
end
if fastmode then
if fastmode then
fcts.table = function (value)
-- Table value
local numidx = 1
@ -142,9 +142,9 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
out[#out] = string.sub(out[#out], 1, -2);
end
out[#out+1] = "}"
return ""
return ""
end
else
else
fcts.table = function (value, ident, path)
if test_defined(value, path) then return "nil" end
-- Table value
@ -174,7 +174,7 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
if totallen > 80 then
sep = "\n" .. string_rep(' ', indent_step*(ident+1))
end
str = "{"..sep..table_concat(str, ","..sep).." "..sep:sub(1,-1-indent_step).."}"
str = "{"..sep..table_concat(str, ","..sep).." "..sep:sub(1,-1-indent_step).."}"
if meta then
sep = sep:sub(1,-3)
return "setmetatable("..sep..str..","..sep..metastr..sep:sub(1,-3)..")"

@ -129,9 +129,9 @@ function BuildingDialog:initBuiltinMode()
cb = self:callback('initCustomMode')
})
end
for i=0,df.building_type._last_item do
if (not WORKSHOP_ABSTRACT[i] or self.use_abstract)and not WORKSHOP_SPECIAL[i] then
self:addBuilding(choices, df.building_type[i], i, -1,-1,nil)

@ -1,300 +1,300 @@
local _ENV = mkmodule('makeown')
--[[
'tweak makeown' as a lua include
make_own(unit) -- removes foreign flags, sets civ_id to fort civ_id, and sets clothes ownership
make_citizen(unit) -- called by make_own if unit.race == fort race
eventually ought to migrate to hack/lua/plugins/tweak.lua
and local _ENV = mkmodule('plugin.tweak')
in order to link to functions in the compiled plugin (when/if they become available to lua)
make_own(unit) -- removes foreign flags, sets civ_id to fort civ_id, and sets clothes ownership
make_citizen(unit) -- called by make_own if unit.race == fort race
eventually ought to migrate to hack/lua/plugins/tweak.lua
and local _ENV = mkmodule('plugin.tweak')
in order to link to functions in the compiled plugin (when/if they become available to lua)
--]]
local utils = require 'utils'
local function fix_clothing_ownership(unit)
-- extracted/translated from tweak makeown plugin
-- to be called by tweak-fixmigrant/makeown
-- units forced into the fort by removing the flags do not own their clothes
-- which has the result that they drop all their clothes and become unhappy because they are naked
-- so we need to make them own their clothes and add them to their uniform
local fixcount = 0 --int fixcount = 0;
for j=0,#unit.inventory-1 do --for(size_t j=0; j<unit->inventory.size(); j++)
local inv_item = unit.inventory[j] --unidf::unit_inventory_item* inv_item = unit->inventory[j];
local item = inv_item.item --df::item* item = inv_item->item;
-- unforbid items (for the case of kidnapping caravan escorts who have their stuff forbidden by default)
-- moved forbid false to inside if so that armor/weapons stay equiped
-- extracted/translated from tweak makeown plugin
-- to be called by tweak-fixmigrant/makeown
-- units forced into the fort by removing the flags do not own their clothes
-- which has the result that they drop all their clothes and become unhappy because they are naked
-- so we need to make them own their clothes and add them to their uniform
local fixcount = 0 --int fixcount = 0;
for j=0,#unit.inventory-1 do --for(size_t j=0; j<unit->inventory.size(); j++)
local inv_item = unit.inventory[j] --unidf::unit_inventory_item* inv_item = unit->inventory[j];
local item = inv_item.item --df::item* item = inv_item->item;
-- unforbid items (for the case of kidnapping caravan escorts who have their stuff forbidden by default)
-- moved forbid false to inside if so that armor/weapons stay equiped
if inv_item.mode == df.unit_inventory_item.T_mode.Worn then --if(inv_item->mode == df::unit_inventory_item::T_mode::Worn)
-- ignore armor?
-- it could be leather boots, for example, in which case it would not be nice to forbid ownership
--if(item->getEffectiveArmorLevel() != 0)
-- continue;
-- ignore armor?
-- it could be leather boots, for example, in which case it would not be nice to forbid ownership
--if(item->getEffectiveArmorLevel() != 0)
-- continue;
if not dfhack.items.getOwner(item) then --if(!Items::getOwner(item))
if dfhack.items.setOwner(item,unit) then --if(Items::setOwner(item, unit))
item.flags.forbid = false --inv_item->item->flags.bits.forbid = 0;
-- add to uniform, so they know they should wear their clothes
unit.military.uniforms[0]:insert('#',item.id) --insert_into_vector(unit->military.uniforms[0], item->id);
fixcount = fixcount + 1 --fixcount++;
if not dfhack.items.getOwner(item) then --if(!Items::getOwner(item))
if dfhack.items.setOwner(item,unit) then --if(Items::setOwner(item, unit))
item.flags.forbid = false --inv_item->item->flags.bits.forbid = 0;
-- add to uniform, so they know they should wear their clothes
unit.military.uniforms[0]:insert('#',item.id) --insert_into_vector(unit->military.uniforms[0], item->id);
fixcount = fixcount + 1 --fixcount++;
else
----out << "could not change ownership for item!" << endl;
print("Makeown: could not change ownership for an item!")
end
end
end
end
-- clear uniform_drop (without this they would drop their clothes and pick them up some time later)
-- dirty?
unit.military.uniform_drop:resize(0) --unit->military.uniform_drop.clear();
----out << "ownership for " << fixcount << " clothes fixed" << endl;
print("Makeown: claimed ownership for "..tostring(fixcount).." worn items")
--return true --return CR_OK;
----out << "could not change ownership for item!" << endl;
print("Makeown: could not change ownership for an item!")
end
end
end
end
-- clear uniform_drop (without this they would drop their clothes and pick them up some time later)
-- dirty?
unit.military.uniform_drop:resize(0) --unit->military.uniform_drop.clear();
----out << "ownership for " << fixcount << " clothes fixed" << endl;
print("Makeown: claimed ownership for "..tostring(fixcount).." worn items")
--return true --return CR_OK;
end
local function entity_link(hf, eid, do_event, add, replace_idx)
do_event = (do_event == nil) and true or do_event
add = (add == nil) and true or add
replace_idx = replace_idx or -1
local link = add and df.histfig_entity_link_memberst:new() or df.histfig_entity_link_former_memberst:new()
link.entity_id = eid
if replace_idx > -1 then
local e = hf.entity_links[replace_idx]
link.link_strength = (e.link_strength > 3) and (e.link_strength - 2) or e.link_strength
hf.entity_links[replace_idx] = link -- replace member link with former member link
e:delete()
else
link.link_strength = 100
hf.entity_links:insert('#', link)
end
if do_event then
event = add and df.history_event_add_hf_entity_linkst:new() or df.history_event_remove_hf_entity_linkst:new()
event.year = df.global.cur_year
event.seconds = df.global.cur_year_tick
event.civ = eid
event.histfig = hf.id
event.link_type = 0
event.position_id = -1
event.id = df.global.hist_event_next_id
df.global.world.history.events:insert('#',event)
df.global.hist_event_next_id = df.global.hist_event_next_id + 1
end
do_event = (do_event == nil) and true or do_event
add = (add == nil) and true or add
replace_idx = replace_idx or -1
local link = add and df.histfig_entity_link_memberst:new() or df.histfig_entity_link_former_memberst:new()
link.entity_id = eid
if replace_idx > -1 then
local e = hf.entity_links[replace_idx]
link.link_strength = (e.link_strength > 3) and (e.link_strength - 2) or e.link_strength
hf.entity_links[replace_idx] = link -- replace member link with former member link
e:delete()
else
link.link_strength = 100
hf.entity_links:insert('#', link)
end
if do_event then
event = add and df.history_event_add_hf_entity_linkst:new() or df.history_event_remove_hf_entity_linkst:new()
event.year = df.global.cur_year
event.seconds = df.global.cur_year_tick
event.civ = eid
event.histfig = hf.id
event.link_type = 0
event.position_id = -1
event.id = df.global.hist_event_next_id
df.global.world.history.events:insert('#',event)
df.global.hist_event_next_id = df.global.hist_event_next_id + 1
end
end
local function change_state(hf, site_id, pos)
hf.info.unk_14.unk_0 = 3 -- state? arrived?
hf.info.unk_14.region:assign(pos)
hf.info.unk_14.site = site_id
event = df.history_event_change_hf_statest:new()
event.year = df.global.cur_year
event.seconds = df.global.cur_year_tick
event.hfid = hf.id
event.state = 3
event.site = site_id
event.region_pos:assign(pos)
event.substate = -1; event.region = -1; event.layer = -1;
event.id = df.global.hist_event_next_id
df.global.world.history.events:insert('#',event)
df.global.hist_event_next_id = df.global.hist_event_next_id + 1
hf.info.unk_14.unk_0 = 3 -- state? arrived?
hf.info.unk_14.region:assign(pos)
hf.info.unk_14.site = site_id
event = df.history_event_change_hf_statest:new()
event.year = df.global.cur_year
event.seconds = df.global.cur_year_tick
event.hfid = hf.id
event.state = 3
event.site = site_id
event.region_pos:assign(pos)
event.substate = -1; event.region = -1; event.layer = -1;
event.id = df.global.hist_event_next_id
df.global.world.history.events:insert('#',event)
df.global.hist_event_next_id = df.global.hist_event_next_id + 1
end
function make_citizen(unit)
local dfg = df.global
local civ_id = dfg.ui.civ_id
local group_id = dfg.ui.group_id
local events = dfg.world.history.events
local fortent = dfg.ui.main.fortress_entity
local civent = fortent and df.historical_entity.find(fortent.entity_links[0].target)
-- utils.binsearch(dfg.world.entities.all, fortent.entity_links[0].target, 'id')
local event
local region_pos = df.world_site.find(dfg.ui.site_id).pos -- used with state events and hf state
local hf
-- assume that hf id 1 and hf id 2 are equal. I am unaware of instances of when they are not.
-- occationally a unit does not have both flags set (missing flags1.important_historical_figure)
-- and I don't know what that means yet.
if unit.flags1.important_historical_figure and unit.flags2.important_historical_figure then
-- aready hf, find it (unlikely to happen)
hf = utils.binsearch(dfg.world.history.figures, unit.hist_figure_id, 'id')
--elseif unit.flags1.important_historical_figure or unit.flags2.important_historical_figure then
-- something wrong, try to fix it?
--[[
if unit.hist_figure_id == -1 then
unit.hist_figure_id = unit.hist_figure_id2
end
if unit.hist_figure_id > -1 then
unit.hist_figure_id2 = unit.hist_figure_id
unit.flags1.important_historical_figure = true
unit.flags2.important_historical_figure = true
hf = utils.binsearch(dfg.world.history.figures, unit.hist_figure_id, 'id')
else
unit.flags1.important_historical_figure = false
unit.flags2.important_historical_figure = false
end
--]]
--else
-- make one
end
--local new_hf = false
if not hf then
--new_hf = true
hf = df.historical_figure:new()
hf.profession = unit.profession
hf.race = unit.race
hf.caste = unit.caste
hf.sex = unit.sex
hf.appeared_year = dfg.cur_year
hf.born_year = unit.relations.birth_year
hf.born_seconds = unit.relations.birth_time
hf.curse_year = unit.relations.curse_year
hf.curse_seconds = unit.relations.curse_time
hf.anon_1 = unit.relations.anon_2
hf.anon_2 = unit.relations.anon_3
hf.old_year = unit.relations.old_year
hf.old_seconds = unit.relations.old_time
hf.died_year = -1
hf.died_seconds = -1
hf.name:assign(unit.name)
hf.civ_id = unit.civ_id
hf.population_id = unit.population_id
hf.breed_id = -1
hf.unit_id = unit.id
hf.id = dfg.hist_figure_next_id -- id must be set before adding links (for the events)
--history_event_add_hf_entity_linkst not reported for civ on starting 7
entity_link(hf, civ_id, false) -- so lets skip event here
entity_link(hf, group_id)
hf.info = df.historical_figure_info:new()
hf.info.unk_14 = df.historical_figure_info.T_unk_14:new() -- hf state?
--unk_14.region_id = -1; unk_14.beast_id = -1; unk_14.unk_14 = 0
hf.info.unk_14.unk_18 = -1; hf.info.unk_14.unk_1c = -1
-- set values that seem related to state and do event
change_state(hf, dfg.ui.site_id, region_pos)
--lets skip skills for now
--local skills = df.historical_figure_info.T_skills:new() -- skills snap shot
-- ...
--info.skills = skills
dfg.world.history.figures:insert('#', hf)
dfg.hist_figure_next_id = dfg.hist_figure_next_id + 1
--new_hf_loc = df.global.world.history.figures[#df.global.world.history.figures - 1]
fortent.histfig_ids:insert('#', hf.id)
fortent.hist_figures:insert('#', hf)
civent.histfig_ids:insert('#', hf.id)
civent.hist_figures:insert('#', hf)
unit.flags1.important_historical_figure = true
unit.flags2.important_historical_figure = true
unit.hist_figure_id = hf.id
unit.hist_figure_id2 = hf.id
print("Makeown-citizen: created historical figure")
else
-- only insert into civ/fort if not already there
-- Migrants change previous histfig_entity_link_memberst to histfig_entity_link_former_memberst
-- for group entities, add link_member for new group, and reports events for remove from group,
-- remove from civ, change state, add civ, and add group
hf.civ_id = civ_id -- ensure current civ_id
local dfg = df.global
local civ_id = dfg.ui.civ_id
local group_id = dfg.ui.group_id
local events = dfg.world.history.events
local fortent = dfg.ui.main.fortress_entity
local civent = fortent and df.historical_entity.find(fortent.entity_links[0].target)
-- utils.binsearch(dfg.world.entities.all, fortent.entity_links[0].target, 'id')
local event
local region_pos = df.world_site.find(dfg.ui.site_id).pos -- used with state events and hf state
local hf
-- assume that hf id 1 and hf id 2 are equal. I am unaware of instances of when they are not.
-- occationally a unit does not have both flags set (missing flags1.important_historical_figure)
-- and I don't know what that means yet.
if unit.flags1.important_historical_figure and unit.flags2.important_historical_figure then
-- aready hf, find it (unlikely to happen)
hf = utils.binsearch(dfg.world.history.figures, unit.hist_figure_id, 'id')
--elseif unit.flags1.important_historical_figure or unit.flags2.important_historical_figure then
-- something wrong, try to fix it?
--[[
if unit.hist_figure_id == -1 then
unit.hist_figure_id = unit.hist_figure_id2
end
if unit.hist_figure_id > -1 then
unit.hist_figure_id2 = unit.hist_figure_id
unit.flags1.important_historical_figure = true
unit.flags2.important_historical_figure = true
hf = utils.binsearch(dfg.world.history.figures, unit.hist_figure_id, 'id')
else
unit.flags1.important_historical_figure = false
unit.flags2.important_historical_figure = false
end
--]]
--else
-- make one
end
--local new_hf = false
if not hf then
--new_hf = true
hf = df.historical_figure:new()
hf.profession = unit.profession
hf.race = unit.race
hf.caste = unit.caste
hf.sex = unit.sex
hf.appeared_year = dfg.cur_year
hf.born_year = unit.relations.birth_year
hf.born_seconds = unit.relations.birth_time
hf.curse_year = unit.relations.curse_year
hf.curse_seconds = unit.relations.curse_time
hf.anon_1 = unit.relations.anon_2
hf.anon_2 = unit.relations.anon_3
hf.old_year = unit.relations.old_year
hf.old_seconds = unit.relations.old_time
hf.died_year = -1
hf.died_seconds = -1
hf.name:assign(unit.name)
hf.civ_id = unit.civ_id
hf.population_id = unit.population_id
hf.breed_id = -1
hf.unit_id = unit.id
hf.id = dfg.hist_figure_next_id -- id must be set before adding links (for the events)
--history_event_add_hf_entity_linkst not reported for civ on starting 7
entity_link(hf, civ_id, false) -- so lets skip event here
entity_link(hf, group_id)
hf.info = df.historical_figure_info:new()
hf.info.unk_14 = df.historical_figure_info.T_unk_14:new() -- hf state?
--unk_14.region_id = -1; unk_14.beast_id = -1; unk_14.unk_14 = 0
hf.info.unk_14.unk_18 = -1; hf.info.unk_14.unk_1c = -1
-- set values that seem related to state and do event
change_state(hf, dfg.ui.site_id, region_pos)
--lets skip skills for now
--local skills = df.historical_figure_info.T_skills:new() -- skills snap shot
-- ...
--info.skills = skills
dfg.world.history.figures:insert('#', hf)
dfg.hist_figure_next_id = dfg.hist_figure_next_id + 1
--new_hf_loc = df.global.world.history.figures[#df.global.world.history.figures - 1]
fortent.histfig_ids:insert('#', hf.id)
fortent.hist_figures:insert('#', hf)
civent.histfig_ids:insert('#', hf.id)
civent.hist_figures:insert('#', hf)
unit.flags1.important_historical_figure = true
unit.flags2.important_historical_figure = true
unit.hist_figure_id = hf.id
unit.hist_figure_id2 = hf.id
print("Makeown-citizen: created historical figure")
else
-- only insert into civ/fort if not already there
-- Migrants change previous histfig_entity_link_memberst to histfig_entity_link_former_memberst
-- for group entities, add link_member for new group, and reports events for remove from group,
-- remove from civ, change state, add civ, and add group
hf.civ_id = civ_id -- ensure current civ_id
local found_civlink = false
local found_fortlink = false
local v = hf.entity_links
for k=#v-1,0,-1 do
if df.histfig_entity_link_memberst:is_instance(v[k]) then
entity_link(hf, v[k].entity_id, true, false, k)
end
end
if hf.info and hf.info.unk_14 then
change_state(hf, dfg.ui.site_id, region_pos)
-- leave info nil if not found for now
end
if not found_civlink then entity_link(hf,civ_id) end
if not found_fortlink then entity_link(hf,group_id) end
--change entity_links
local found = false
for _,v in ipairs(civent.histfig_ids) do
if v == hf.id then found = true; break end
end
if not found then
civent.histfig_ids:insert('#', hf.id)
civent.hist_figures:insert('#', hf)
end
found = false
for _,v in ipairs(fortent.histfig_ids) do
if v == hf.id then found = true; break end
end
if not found then
fortent.histfig_ids:insert('#', hf.id)
fortent.hist_figures:insert('#', hf)
end
print("Makeown-citizen: migrated historical figure")
end -- hf
local found_civlink = false
local found_fortlink = false
local v = hf.entity_links
for k=#v-1,0,-1 do
if df.histfig_entity_link_memberst:is_instance(v[k]) then
entity_link(hf, v[k].entity_id, true, false, k)
end
end
if hf.info and hf.info.unk_14 then
change_state(hf, dfg.ui.site_id, region_pos)
-- leave info nil if not found for now
end
if not found_civlink then entity_link(hf,civ_id) end
if not found_fortlink then entity_link(hf,group_id) end
--change entity_links
local found = false
for _,v in ipairs(civent.histfig_ids) do
if v == hf.id then found = true; break end
end
if not found then
civent.histfig_ids:insert('#', hf.id)
civent.hist_figures:insert('#', hf)
end
found = false
for _,v in ipairs(fortent.histfig_ids) do
if v == hf.id then found = true; break end
end
if not found then
fortent.histfig_ids:insert('#', hf.id)
fortent.hist_figures:insert('#', hf)
end
print("Makeown-citizen: migrated historical figure")
end -- hf
local nemesis = dfhack.units.getNemesis(unit)
if not nemesis then
nemesis = df.nemesis_record:new()
nemesis.figure = hf
nemesis.unit = unit
nemesis.unit_id = unit.id
nemesis.save_file_id = civent.save_file_id
nemesis.unk10, nemesis.unk11, nemesis.unk12 = -1, -1, -1
--group_leader_id = -1
nemesis.id = dfg.nemesis_next_id
nemesis.member_idx = civent.next_member_idx
civent.next_member_idx = civent.next_member_idx + 1
local nemesis = dfhack.units.getNemesis(unit)
if not nemesis then
nemesis = df.nemesis_record:new()
nemesis.figure = hf
nemesis.unit = unit
nemesis.unit_id = unit.id
nemesis.save_file_id = civent.save_file_id
nemesis.unk10, nemesis.unk11, nemesis.unk12 = -1, -1, -1
--group_leader_id = -1
nemesis.id = dfg.nemesis_next_id
nemesis.member_idx = civent.next_member_idx
civent.next_member_idx = civent.next_member_idx + 1
dfg.world.nemesis.all:insert('#', nemesis)
dfg.nemesis_next_id = dfg.nemesis_next_id + 1
dfg.world.nemesis.all:insert('#', nemesis)
dfg.nemesis_next_id = dfg.nemesis_next_id + 1
nemesis_link = df.general_ref_is_nemesisst:new()
nemesis_link.nemesis_id = nemesis.id
unit.general_refs:insert('#', nemesis_link)
nemesis_link = df.general_ref_is_nemesisst:new()
nemesis_link.nemesis_id = nemesis.id
unit.general_refs:insert('#', nemesis_link)
--new_nemesis_loc = df.global.world.nemesis.all[#df.global.world.nemesis.all - 1]
fortent.nemesis_ids:insert('#', nemesis.id)
fortent.nemesis:insert('#', nemesis)
civent.nemesis_ids:insert('#', nemesis.id)
civent.nemesis:insert('#', nemesis)
print("Makeown-citizen: created nemesis entry")
else-- only insert into civ/fort if not already there
local found = false
for _,v in ipairs(civent.nemesis_ids) do
if v == nemesis.id then found = true; break end
end
if not found then
civent.nemesis_ids:insert('#', nemesis.id)
civent.nemesis:insert('#', nemesis)
end
found = false
for _,v in ipairs(fortent.nemesis_ids) do
if v == nemesis.id then found = true; break end
end
if not found then
fortent.nemesis_ids:insert('#', nemesis.id)
fortent.nemesis:insert('#', nemesis)
end
print("Makeown-citizen: migrated nemesis entry")
end -- nemesis
--new_nemesis_loc = df.global.world.nemesis.all[#df.global.world.nemesis.all - 1]
fortent.nemesis_ids:insert('#', nemesis.id)
fortent.nemesis:insert('#', nemesis)
civent.nemesis_ids:insert('#', nemesis.id)
civent.nemesis:insert('#', nemesis)
print("Makeown-citizen: created nemesis entry")
else-- only insert into civ/fort if not already there
local found = false
for _,v in ipairs(civent.nemesis_ids) do
if v == nemesis.id then found = true; break end
end
if not found then
civent.nemesis_ids:insert('#', nemesis.id)
civent.nemesis:insert('#', nemesis)
end
found = false
for _,v in ipairs(fortent.nemesis_ids) do
if v == nemesis.id then found = true; break end
end
if not found then
fortent.nemesis_ids:insert('#', nemesis.id)
fortent.nemesis:insert('#', nemesis)
end
print("Makeown-citizen: migrated nemesis entry")
end -- nemesis
end
function make_own(unit)
--tweak makeown
unit.flags2.resident = false; unit.flags1.merchant = false; unit.flags1.forest = false;
unit.civ_id = df.global.ui.civ_id
if unit.profession == df.profession.MERCHANT then unit.profession = df.profession.TRADER end
if unit.profession2 == df.profession.MERCHANT then unit.profession2 = df.profession.TRADER end
fix_clothing_ownership(unit)
if unit.race == df.global.ui.race_id then
make_citizen(unit)
end
--tweak makeown
unit.flags2.resident = false; unit.flags1.merchant = false; unit.flags1.forest = false;
unit.civ_id = df.global.ui.civ_id
if unit.profession == df.profession.MERCHANT then unit.profession = df.profession.TRADER end
if unit.profession2 == df.profession.MERCHANT then unit.profession2 = df.profession.TRADER end
fix_clothing_ownership(unit)
if unit.race == df.global.ui.race_id then
make_citizen(unit)
end
end

@ -111,7 +111,7 @@ void DFHack::EventManager::unregisterAll(Plugin* plugin) {
for ( auto i = handlers[EventType::TICK].find(plugin); i != handlers[EventType::TICK].end(); i++ ) {
if ( (*i).first != plugin )
break;
removeFromTickQueue((*i).second);
}
for ( size_t a = 0; a < (size_t)EventType::EVENT_MAX; a++ ) {
@ -248,12 +248,12 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
return;
if (!df::global::world)
return;
nextItem = *df::global::item_next_id;
nextBuilding = *df::global::building_next_id;
nextInvasion = df::global::ui->invasions.next_id;
lastJobId = -1 + *df::global::job_next_id;
constructions.clear();
for ( auto i = df::global::world->constructions.begin(); i != df::global::world->constructions.end(); i++ ) {
df::construction* constr = *i;
@ -296,7 +296,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
for ( size_t a = 0; a < EventType::EVENT_MAX; a++ ) {
eventLastTick[a] = -1;//-1000000;
}
gameLoaded = true;
}
}
@ -309,7 +309,7 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
return;
CoreSuspender suspender;
int32_t tick = df::global::world->frame_counter;
for ( size_t a = 0; a < EventType::EVENT_MAX; a++ ) {
@ -323,10 +323,10 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
eventFrequency = bob.freq;
}
else eventFrequency = 1;
if ( tick >= eventLastTick[a] && tick - eventLastTick[a] < eventFrequency )
continue;
eventManager[a](out);
eventLastTick[a] = tick;
}
@ -369,12 +369,12 @@ static void manageJobInitiatedEvent(color_ostream& out) {
lastJobId = *df::global::job_next_id - 1;
return;
}
if ( lastJobId+1 == *df::global::job_next_id ) {
return; //no new jobs
}
multimap<Plugin*,EventHandler> copy(handlers[EventType::JOB_INITIATED].begin(), handlers[EventType::JOB_INITIATED].end());
for ( df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next ) {
if ( link->item == NULL )
continue;
@ -384,7 +384,7 @@ static void manageJobInitiatedEvent(color_ostream& out) {
(*i).second.eventHandler(out, (void*)link->item);
}
}
lastJobId = *df::global::job_next_id - 1;
}
@ -402,7 +402,7 @@ static void manageJobCompletedEvent(color_ostream& out) {
return;
int32_t tick0 = eventLastTick[EventType::JOB_COMPLETED];
int32_t tick1 = df::global::world->frame_counter;
multimap<Plugin*,EventHandler> copy(handlers[EventType::JOB_COMPLETED].begin(), handlers[EventType::JOB_COMPLETED].end());
map<int32_t, df::job*> nowJobs;
for ( df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next ) {
@ -410,14 +410,14 @@ static void manageJobCompletedEvent(color_ostream& out) {
continue;
nowJobs[link->item->id] = link->item;
}
#if 0
//testing info on job initiation/completion
//newly allocated jobs
for ( auto j = nowJobs.begin(); j != nowJobs.end(); j++ ) {
if ( prevJobs.find((*j).first) != prevJobs.end() )
continue;
df::job& job1 = *(*j).second;
out.print("new job\n"
" location : 0x%X\n"
@ -445,12 +445,12 @@ static void manageJobCompletedEvent(color_ostream& out) {
continue;
}
df::job& job1 = *(*j).second;
if ( job0.flags.bits.working == job1.flags.bits.working &&
(job0.completion_timer == job1.completion_timer || (job1.completion_timer > 0 && job0.completion_timer-1 == job1.completion_timer)) &&
getWorkerID(&job0) == getWorkerID(&job1) )
continue;
out.print("job change\n"
" location : 0x%X -> 0x%X\n"
" id : %d -> %d\n"
@ -472,12 +472,12 @@ static void manageJobCompletedEvent(color_ostream& out) {
);
}
#endif
for ( auto i = prevJobs.begin(); i != prevJobs.end(); i++ ) {
//if it happened within a tick, must have been cancelled by the user or a plugin: not completed
if ( tick1 <= tick0 )
continue;
if ( nowJobs.find((*i).first) != nowJobs.end() ) {
//could have just finished if it's a repeat job
df::job& job0 = *(*i).second;
@ -488,19 +488,19 @@ static void manageJobCompletedEvent(color_ostream& out) {
continue;
if ( job1.completion_timer != -1 )
continue;
//still false positive if cancelled at EXACTLY the right time, but experiments show this doesn't happen
for ( auto j = copy.begin(); j != copy.end(); j++ ) {
(*j).second.eventHandler(out, (void*)&job0);
}
continue;
}
//recently finished or cancelled job
df::job& job0 = *(*i).second;
if ( job0.flags.bits.repeat || job0.completion_timer != 0 )
continue;
for ( auto j = copy.begin(); j != copy.end(); j++ ) {
(*j).second.eventHandler(out, (void*)&job0);
}
@ -511,7 +511,7 @@ static void manageJobCompletedEvent(color_ostream& out) {
Job::deleteJobStruct((*i).second, true);
}
prevJobs.clear();
//create new jobs
for ( auto j = nowJobs.begin(); j != nowJobs.end(); j++ ) {
/*map<int32_t, df::job*>::iterator i = prevJobs.find((*j).first);
@ -538,7 +538,7 @@ static void manageUnitDeathEvent(color_ostream& out) {
//dead: if dead since last check, trigger events
if ( livingUnits.find(unit->id) == livingUnits.end() )
continue;
for ( auto i = copy.begin(); i != copy.end(); i++ ) {
(*i).second.eventHandler(out, (void*)unit->id);
}
@ -554,7 +554,7 @@ static void manageItemCreationEvent(color_ostream& out) {
if ( nextItem >= *df::global::item_next_id ) {
return;
}
multimap<Plugin*,EventHandler> copy(handlers[EventType::ITEM_CREATED].begin(), handlers[EventType::ITEM_CREATED].end());
size_t index = df::item::binsearch_index(df::global::world->items.all, nextItem, false);
if ( index != 0 ) index--;
@ -607,7 +607,7 @@ static void manageBuildingEvent(color_ostream& out) {
}
}
nextBuilding = *df::global::building_next_id;
//now alert people about destroyed buildings
for ( auto a = buildings.begin(); a != buildings.end(); ) {
int32_t id = *a;
@ -616,7 +616,7 @@ static void manageBuildingEvent(color_ostream& out) {
a++;
continue;
}
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler bob = (*b).second;
bob.eventHandler(out, (void*)id);
@ -629,7 +629,7 @@ static void manageConstructionEvent(color_ostream& out) {
if (!df::global::world)
return;
//unordered_set<df::construction*> constructionsNow(df::global::world->constructions.begin(), df::global::world->constructions.end());
multimap<Plugin*,EventHandler> copy(handlers[EventType::CONSTRUCTION].begin(), handlers[EventType::CONSTRUCTION].end());
for ( auto a = constructions.begin(); a != constructions.end(); ) {
df::construction& construction = (*a).second;
@ -645,7 +645,7 @@ static void manageConstructionEvent(color_ostream& out) {
}
a = constructions.erase(a);
}
//for ( auto a = constructionsNow.begin(); a != constructionsNow.end(); a++ ) {
for ( auto a = df::global::world->constructions.begin(); a != df::global::world->constructions.end(); a++ ) {
df::construction* construction = *a;
@ -680,7 +680,7 @@ static void manageSyndromeEvent(color_ostream& out) {
highestTime = startTime;
if ( startTime <= lastSyndromeTime )
continue;
SyndromeData data(unit->id, b);
for ( auto c = copy.begin(); c != copy.end(); c++ ) {
EventHandler handle = (*c).second;
@ -710,7 +710,7 @@ static void manageEquipmentEvent(color_ostream& out) {
if (!df::global::world)
return;
multimap<Plugin*,EventHandler> copy(handlers[EventType::INVENTORY_CHANGE].begin(), handlers[EventType::INVENTORY_CHANGE].end());
unordered_map<int32_t, InventoryItem> itemIdToInventoryItem;
unordered_set<int32_t> currentlyEquipped;
for ( auto a = df::global::world->units.all.begin(); a != df::global::world->units.all.end(); a++ ) {
@ -720,7 +720,7 @@ static void manageEquipmentEvent(color_ostream& out) {
/*if ( unit->flags1.bits.dead )
continue;
*/
auto oldEquipment = equipmentLog.find(unit->id);
bool hadEquipment = oldEquipment != equipmentLog.end();
vector<InventoryItem>* temp;
@ -750,13 +750,13 @@ static void manageEquipmentEvent(color_ostream& out) {
continue;
}
InventoryItem item_old = (*c).second;
df::unit_inventory_item& item0 = item_old.item;
df::unit_inventory_item& item1 = item_new.item;
if ( item0.mode == item1.mode && item0.body_part_id == item1.body_part_id && item0.wound_id == item1.wound_id )
continue;
//some sort of change in how it's equipped
InventoryChangeData data(unit->id, &item_old, &item_new);
for ( auto h = copy.begin(); h != copy.end(); h++ ) {
EventHandler handle = (*h).second;
@ -777,7 +777,7 @@ static void manageEquipmentEvent(color_ostream& out) {
}
if ( !hadEquipment )
delete temp;
//update equipment
vector<InventoryItem>& equipment = equipmentLog[unit->id];
equipment.clear();
@ -795,7 +795,7 @@ static void updateReportToRelevantUnits() {
if ( df::global::world->frame_counter <= reportToRelevantUnitsTime )
return;
reportToRelevantUnitsTime = df::global::world->frame_counter;
for ( size_t a = 0; a < df::global::world->units.all.size(); a++ ) {
df::unit* unit = df::global::world->units.all[a];
for ( int16_t b = df::enum_traits<df::unit_report_type>::first_item_value; b <= df::enum_traits<df::unit_report_type>::last_item_value; b++ ) {
@ -862,7 +862,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
strikeReports.insert(report->id);
}
}
if ( strikeReports.empty() )
return;
updateReportToRelevantUnits();
@ -883,37 +883,37 @@ static void manageUnitAttackEvent(color_ostream& out) {
break;
reportStr = reportStr + report2->text;
}
std::vector<int32_t>& relevantUnits = reportToRelevantUnits[report->id];
if ( relevantUnits.size() != 2 ) {
continue;
}
df::unit* unit1 = df::unit::find(relevantUnits[0]);
df::unit* unit2 = df::unit::find(relevantUnits[1]);
df::unit_wound* wound1 = getWound(unit1,unit2);
df::unit_wound* wound2 = getWound(unit2,unit1);
if ( wound1 && !alreadyDone[unit1->id][unit2->id] ) {
UnitAttackData data;
data.attacker = unit1->id;
data.defender = unit2->id;
data.wound = wound1->id;
alreadyDone[data.attacker][data.defender] = 1;
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler handle = (*b).second;
handle.eventHandler(out, (void*)&data);
}
}
if ( wound2 && !alreadyDone[unit1->id][unit2->id] ) {
UnitAttackData data;
data.attacker = unit2->id;
data.defender = unit1->id;
data.wound = wound2->id;
alreadyDone[data.attacker][data.defender] = 1;
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler handle = (*b).second;
@ -932,7 +932,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
handle.eventHandler(out, (void*)&data);
}
}
if ( unit2->flags1.bits.dead ) {
UnitAttackData data;
data.attacker = unit1->id;
@ -944,7 +944,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
handle.eventHandler(out, (void*)&data);
}
}
if ( !wound1 && !wound2 ) {
//if ( unit1->flags1.bits.dead || unit2->flags1.bits.dead )
// continue;
@ -992,7 +992,7 @@ static std::string getVerb(df::unit* unit, std::string reportStr) {
static InteractionData getAttacker(color_ostream& out, df::report* attackEvent, df::unit* lastAttacker, df::report* defendEvent, vector<df::unit*>& relevantUnits) {
vector<df::unit*> attackers = relevantUnits;
vector<df::unit*> defenders = relevantUnits;
//find valid interactions: TODO
/*map<int32_t,vector<df::interaction*> > validInteractions;
for ( size_t a = 0; a < relevantUnits.size(); a++ ) {
@ -1000,7 +1000,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
vector<df::interaction*>& interactions = validInteractions[unit->id];
for ( size_t b = 0; b < unit->body.
}*/
//if attackEvent
// attacker must be same location
// attacker name must start attack str
@ -1019,7 +1019,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
a--;
continue;
}
std::string verbC = getVerb(attackers[a], attackEvent->text);
if ( verbC.length() == 0 ) {
attackers.erase(attackers.begin()+a);
@ -1029,7 +1029,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
attackVerb = verbC;
}
}
//if defendEvent
// defender must be same location
// defender name must start defend str
@ -1052,7 +1052,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
defendVerb = verbC;
}
}
//keep in mind one attacker zero defenders is perfectly valid for self-cast
if ( attackers.size() == 1 && defenders.size() == 1 && attackers[0] == defenders[0] ) {
//out.print("%s,%d\n",__FILE__,__LINE__);
@ -1070,7 +1070,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
defenders.erase(a);
}
}
//if trying attack-defend pair and it fails to find attacker, try defend only
InteractionData result = /*(InteractionData)*/ { std::string(), std::string(), -1, -1, -1, -1 };
if ( attackers.size() > 1 ) {
@ -1141,7 +1141,7 @@ static void manageInteractionEvent(color_ostream& out) {
}
if ( a < reports.size() )
updateReportToRelevantUnits();
df::report* lastAttackEvent = NULL;
df::unit* lastAttacker = NULL;
df::unit* lastDefender = NULL;

@ -1362,23 +1362,23 @@ int32_t Items::createItem(df::item_type item_type, int16_t item_subtype, int16_t
prod->product_dimension = 1;
break;
}
//makeItem
vector<df::item*> out_items;
vector<df::reaction_reagent*> in_reag;
vector<df::item*> in_items;
df::enums::game_type::game_type type = *df::global::gametype;
prod->produce(unit, &out_items, &in_reag, &in_items, 1, job_skill::NONE,
df::historical_entity::find(unit->civ_id),
((type == df::enums::game_type::DWARF_MAIN) || (type == df::enums::game_type::DWARF_RECLAIM)) ? df::world_site::find(df::global::ui->site_id) : NULL);
if ( out_items.size() != 1 )
return -1;
for (size_t a = 0; a < out_items.size(); a++ ) {
out_items[a]->moveToGround(unit->pos.x, unit->pos.y, unit->pos.z);
}
return out_items[0]->id;
}

@ -204,7 +204,7 @@ df::map_block *Maps::ensureTileBlock (int32_t x, int32_t y, int32_t z)
slot->temperature_1[tx][ty] = column[z2]->temperature_1[tx][ty];
slot->temperature_2[tx][ty] = column[z2]->temperature_2[tx][ty];
}
df::global::world->map.map_blocks.push_back(slot);
return slot;
}
@ -593,7 +593,7 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2)
if ( !index_tile<uint16_t>(block1->walkable,pos1) || !index_tile<uint16_t>(block2->walkable,pos2) ) {
return false;
}
if ( block1->designation[pos1.x&0xF][pos1.y&0xF].bits.flow_size >= 4 ||
block2->designation[pos2.x&0xF][pos2.y&0xF].bits.flow_size >= 4 )
return false;
@ -640,7 +640,7 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2)
}
if ( !foundWall )
return false; //unusable ramp
//there has to be an unforbidden hatch above the ramp
if ( index_tile<df::tile_occupancy>(block2->occupancy,pos2).bits.building != tile_building_occ::Dynamic )
return false;
@ -657,7 +657,7 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2)
}
return false;
}
//diagonal up: has to be a ramp
if ( shape1 == tiletype_shape::RAMP /*&& shape2 == tiletype_shape::RAMP*/ ) {
df::coord up = df::coord(pos1.x,pos1.y,pos1.z+1);
@ -681,11 +681,11 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2)
df::tiletype_shape shapeUp = ENUM_ATTR(tiletype,shape,*typeUp);
if ( shapeUp != tiletype_shape::RAMP_TOP )
return false;
df::map_block* blockUp = getTileBlock(up);
if ( !blockUp )
return false;
df::tile_building_occ occupancy = index_tile<df::tile_occupancy>(blockUp->occupancy,up).bits.building;
if ( occupancy == tile_building_occ::Obstacle || occupancy == tile_building_occ::Floored || occupancy == tile_building_occ::Impassable )
return false;

@ -1616,12 +1616,12 @@ std::string Units::getCasteProfessionName(int race, int casteid, df::profession
{
std::string prof, race_prefix;
if (pid < (df::profession)0 || !is_valid_enum_item(pid))
return "";
int16_t current_race = df::global::ui->race_id;
if (df::global::gamemode && *df::global::gamemode == df::game_mode::ADVENTURE)
current_race = world->units.active[0]->race;
bool use_race_prefix = (race >= 0 && race != current_race);
if (pid < (df::profession)0 || !is_valid_enum_item(pid))
return "";
int16_t current_race = df::global::ui->race_id;
if (df::global::gamemode && *df::global::gamemode == df::game_mode::ADVENTURE)
current_race = world->units.active[0]->race;
bool use_race_prefix = (race >= 0 && race != current_race);
if (auto creature = df::creature_raw::find(race))
{

@ -1 +1 @@
Subproject commit e1151e8d6401c286f1d7df45abbd14562bedc7e9
Subproject commit 7ff793882032374e8f9819978aa7a29d5236798c

@ -25,7 +25,7 @@ DFHACK_PLUGIN("dfusion")
static int loadObjectFile(lua_State* L)
{
std::string path;
path=luaL_checkstring(L,1);
OutFile::File f(path);
@ -36,7 +36,7 @@ static int loadObjectFile(lua_State* L)
lua_setfield(L,table_pos,"data_size");
char* buf=new char[size];
f.GetText(buf);
//Lua::PushDFObject(L,DFHack::,buf);
//Lua::Push(L,buf);
lua_pushlightuserdata(L,buf);
@ -52,7 +52,7 @@ static int loadObjectFile(lua_State* L)
Lua::Push(L,symbols[i].pos);
lua_setfield(L,-2,"pos");
lua_settable(L,-3);
}
lua_setfield(L,table_pos,"symbols");

@ -9,29 +9,29 @@
class Hexsearch
{
public:
typedef std::vector<int> SearchArgType;
enum SearchConst //TODO add more
{
ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS
};
typedef std::vector<int> SearchArgType;
enum SearchConst //TODO add more
{
ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS
};
Hexsearch(const SearchArgType &args,char * startpos,char * endpos);
~Hexsearch();
Hexsearch(const SearchArgType &args,char * startpos,char * endpos);
~Hexsearch();
void Reset(){pos_=startpos_;};
void SetStart(char * pos){pos_=pos;};
void Reset(){pos_=startpos_;};
void SetStart(char * pos){pos_=pos;};
void * FindNext();
std::vector<void *> FindAll();
void * FindNext();
std::vector<void *> FindAll();
private:
bool Compare(int a,int b);
void ReparseArgs();
SearchArgType args_;
char * pos_,* startpos_,* endpos_;
std::vector<int> BadCharShifts,GoodSuffixShift;
void PrepareGoodSuffixTable();
void PrepareBadCharShift();
bool Compare(int a,int b);
void ReparseArgs();
SearchArgType args_;
char * pos_,* startpos_,* endpos_;
std::vector<int> BadCharShifts,GoodSuffixShift;
void PrepareGoodSuffixTable();
void PrepareBadCharShift();
};
#endif

@ -11,19 +11,19 @@ namespace lua
class Hexsearch
{
int tblid;
::Hexsearch *p;
int tblid;
::Hexsearch *p;
public:
Hexsearch(lua_State *L,int id);
~Hexsearch();
Hexsearch(lua_State *L,int id);
~Hexsearch();
int GetTableId(){return tblid;};
int GetTableId(){return tblid;};
int find(lua_State *L);
int findall(lua_State *L);
int reset(lua_State *L);
int find(lua_State *L);
int findall(lua_State *L);
int reset(lua_State *L);
DEF_LUNE(Hexsearch);
DEF_LUNE(Hexsearch);
};
void RegisterHexsearch(lua::state &st);

@ -18,25 +18,25 @@ class PlugManager
{
public:
mapPlugs GetList(){return plugs;};
mapPlugs GetList(){return plugs;};
uint32_t AddNewPlug(std::string name,uint32_t size,uint32_t loc=0);
uint32_t FindPlugin(std::string name);
static PlugManager &GetInst()
{
void *p;
p=DFHack::Core::getInstance().GetData("dfusion_manager");
if(p==0)
{
p=new PlugManager;
DFHack::Core::getInstance().RegisterData(p,"dfusion_manager");
}
return *static_cast<PlugManager*>(p);
};
{
void *p;
p=DFHack::Core::getInstance().GetData("dfusion_manager");
if(p==0)
{
p=new PlugManager;
DFHack::Core::getInstance().RegisterData(p,"dfusion_manager");
}
return *static_cast<PlugManager*>(p);
};
protected:
private:
PlugManager(){};
mapPlugs plugs;
private:
PlugManager(){};
mapPlugs plugs;
};
void RegisterMisc(lua::state &st);

@ -16,7 +16,7 @@ using std::string;
namespace lua
{
//global lua state singleton
//global lua state singleton
class glua
{
public:
@ -26,13 +26,13 @@ namespace lua
static glua *ptr;
state mystate;
};
//registers basic lua commands
//registers basic lua commands
void RegBasics(lua::state &L);
//dumps lua function trace, useless unless called from lua.
//dumps lua function trace, useless unless called from lua.
string DebugDump(lua::state &L);
//register functions, first registers into global scope, second into current table
void RegFunctions(lua::state &L,luaL_Reg const *arr);
void RegFunctionsLocal(lua::state &L,luaL_Reg const *arr);
//register functions, first registers into global scope, second into current table
void RegFunctions(lua::state &L,luaL_Reg const *arr);
void RegFunctionsLocal(lua::state &L,luaL_Reg const *arr);
}

@ -5,7 +5,7 @@ File::File(std::string path)
{
//mystream.exceptions ( std::fstream::eofbit | std::fstream::failbit | std::fstream::badbit );
mystream.open(path.c_str(),std::fstream::binary|std::ios::in|std::ios::out);
if(mystream)
{

@ -3,7 +3,7 @@
Hexsearch::Hexsearch(const SearchArgType &args,char * startpos,char * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos)
{
ReparseArgs();
ReparseArgs();
}
Hexsearch::~Hexsearch()
{
@ -11,106 +11,106 @@ Hexsearch::~Hexsearch()
}
inline bool Hexsearch::Compare(int a,int b)
{
if(b==Hexsearch::ANYBYTE)
return true;
if(a==b)
return true;
return false;
if(b==Hexsearch::ANYBYTE)
return true;
if(a==b)
return true;
return false;
}
void Hexsearch::ReparseArgs()
{
union
{
uint32_t val;
uint8_t bytes[4];
}B;
SearchArgType targ;
targ=args_;
args_.clear();
for(size_t i=0;i<targ.size();)
{
if(targ[i]==DWORD_)
{
i++;
B.val=targ[i];
for(int j=0;j<4;j++)
{
args_.push_back(B.bytes[j]);
}
i++;
}
else if (targ[i]==ANYDWORD)
{
i++;
for(int j=0;j<4;j++)
args_.push_back(ANYBYTE);
}
else
{
args_.push_back(targ[i]);
i++;
}
}
union
{
uint32_t val;
uint8_t bytes[4];
}B;
SearchArgType targ;
targ=args_;
args_.clear();
for(size_t i=0;i<targ.size();)
{
if(targ[i]==DWORD_)
{
i++;
B.val=targ[i];
for(int j=0;j<4;j++)
{
args_.push_back(B.bytes[j]);
}
i++;
}
else if (targ[i]==ANYDWORD)
{
i++;
for(int j=0;j<4;j++)
args_.push_back(ANYBYTE);
}
else
{
args_.push_back(targ[i]);
i++;
}
}
}
void * Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm
{
DFHack::Core &inst=DFHack::Core::getInstance();
DFHack::Process *p=inst.p;
uint8_t *buf;
buf=new uint8_t[args_.size()];
while(pos_<endpos_)
{
bool found=true;
p->readByte(pos_,buf[0]);
if(Compare(buf[0],args_[0]))
{
p->read(pos_,args_.size(),buf);
for(size_t i=0;i<args_.size();i++)
{
if(!Compare(buf[i],args_[i]))
{
pos_+=i;
found=false;
break;
}
}
if(found)
{
pos_+=args_.size();
delete [] buf;
return pos_-args_.size();
}
}
pos_ = pos_ + 1;
}
delete [] buf;
return 0;
DFHack::Core &inst=DFHack::Core::getInstance();
DFHack::Process *p=inst.p;
uint8_t *buf;
buf=new uint8_t[args_.size()];
while(pos_<endpos_)
{
bool found=true;
p->readByte(pos_,buf[0]);
if(Compare(buf[0],args_[0]))
{
p->read(pos_,args_.size(),buf);
for(size_t i=0;i<args_.size();i++)
{
if(!Compare(buf[i],args_[i]))
{
pos_+=i;
found=false;
break;
}
}
if(found)
{
pos_+=args_.size();
delete [] buf;
return pos_-args_.size();
}
}
pos_ = pos_ + 1;
}
delete [] buf;
return 0;
}
std::vector<void *> Hexsearch::FindAll()
{
std::vector<void *> ret;
void * cpos=pos_;
while(cpos!=0)
{
cpos=FindNext();
if(cpos!=0)
ret.push_back(cpos);
}
return ret;
std::vector<void *> ret;
void * cpos=pos_;
while(cpos!=0)
{
cpos=FindNext();
if(cpos!=0)
ret.push_back(cpos);
}
return ret;
}
void Hexsearch::PrepareBadCharShift()
{
BadCharShifts.resize(256,-1);
int i=0;
for(SearchArgType::reverse_iterator it=args_.rbegin();it!=args_.rend();it++)
{
BadCharShifts[*it]=i;
i++;
}
BadCharShifts.resize(256,-1);
int i=0;
for(SearchArgType::reverse_iterator it=args_.rbegin();it!=args_.rend();it++)
{
BadCharShifts[*it]=i;
i++;
}
}
void Hexsearch::PrepareGoodSuffixTable()
{
GoodSuffixShift.resize(args_.size()+1,0);
GoodSuffixShift.resize(args_.size()+1,0);
}

@ -2,60 +2,60 @@
int lua::Hexsearch::find(lua_State *L)
{
lua::state st(L);
void * pos=p->FindNext();
st.push(reinterpret_cast<size_t>(pos));
return 1;
void * pos=p->FindNext();
st.push(reinterpret_cast<size_t>(pos));
return 1;
}
int lua::Hexsearch::findall(lua_State *L)
{
lua::state st(L);
std::vector<void *> pos=p->FindAll();
st.newtable();
for(unsigned i=0;i<pos.size();i++)
{
st.push(i+1);
st.push(reinterpret_cast<size_t>(pos[i]));
st.settable();
}
return 1;
std::vector<void *> pos=p->FindAll();
st.newtable();
for(unsigned i=0;i<pos.size();i++)
{
st.push(i+1);
st.push(reinterpret_cast<size_t>(pos[i]));
st.settable();
}
return 1;
}
lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id)
{
lua::state st(L);
char * start,* end;
::Hexsearch::SearchArgType args;
start= (char *)st.as<uint32_t>(1);
end=(char *)st.as<uint32_t>(2);
for(int i=3;i<=st.gettop();i++)
{
args.push_back(st.as<int>(i));
}
p=new ::Hexsearch(args,start,end);
char * start,* end;
::Hexsearch::SearchArgType args;
start= (char *)st.as<uint32_t>(1);
end=(char *)st.as<uint32_t>(2);
for(int i=3;i<=st.gettop();i++)
{
args.push_back(st.as<int>(i));
}
p=new ::Hexsearch(args,start,end);
}
lua::Hexsearch::~Hexsearch()
{
delete p;
delete p;
}
int lua::Hexsearch::reset(lua_State *L)
{
lua::state st(L);
p->Reset();
return 0;
p->Reset();
return 0;
}
IMP_LUNE(lua::Hexsearch,hexsearch);
LUNE_METHODS_START(lua::Hexsearch)
method(lua::Hexsearch,find),
method(lua::Hexsearch,findall),
method(lua::Hexsearch,reset),
method(lua::Hexsearch,find),
method(lua::Hexsearch,findall),
method(lua::Hexsearch,reset),
LUNE_METHODS_END();
#define __ADDCONST(name) st.push(::Hexsearch:: name); st.setglobal(#name)
void lua::RegisterHexsearch(lua::state &st)
{
Lune<lua::Hexsearch>::Register(st);
__ADDCONST(ANYBYTE);
__ADDCONST(ANYDWORD);
__ADDCONST(DWORD_);
Lune<lua::Hexsearch>::Register(st);
__ADDCONST(ANYBYTE);
__ADDCONST(ANYDWORD);
__ADDCONST(DWORD_);
}
#undef __ADDCONST

@ -1,21 +1,21 @@
#include "lua_Misc.h"
uint32_t lua::PlugManager::AddNewPlug(std::string name,uint32_t size,uint32_t loc)
{
void *p;
if(size!=0)
p=new unsigned char[size];
else
p=(void*)loc;
plugs[name]=p;
return (uint32_t)p;
void *p;
if(size!=0)
p=new unsigned char[size];
else
p=(void*)loc;
plugs[name]=p;
return (uint32_t)p;
}
uint32_t lua::PlugManager::FindPlugin(std::string name)
{
mapPlugs::iterator it=plugs.find(name);
if(it!=plugs.end())
return (uint32_t)it->second;
else
return 0;
mapPlugs::iterator it=plugs.find(name);
if(it!=plugs.end())
return (uint32_t)it->second;
else
return 0;
}
@ -24,10 +24,10 @@ static int LoadMod(lua_State *L)
lua::state st(L);
std::string modfile=st.as<std::string>(1);
std::string modname=st.as<std::string>(2);
uint32_t size_add=st.as<uint32_t>(0,3);
uint32_t size_add=st.as<uint32_t>(0,3);
OutFile::File f(modfile);
uint32_t size=f.GetTextSize();
uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size+size_add);
uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size+size_add);
char *buf;
buf=new char[size];
f.GetText(buf);
@ -133,22 +133,22 @@ static int GetMod(lua_State *L)
const luaL_Reg lua_misc_func[]=
{
{"loadmod",LoadMod},
{"getmod",GetMod},
{"loadobj",LoadObj},
{"loadobjsymbols",LoadObjSymbols},
{"findmarker",FindMarker},
{"newmod",NewMod},
{NULL,NULL}
{"loadmod",LoadMod},
{"getmod",GetMod},
{"loadobj",LoadObj},
{"loadobjsymbols",LoadObjSymbols},
{"findmarker",FindMarker},
{"newmod",NewMod},
{NULL,NULL}
};
void lua::RegisterMisc(lua::state &st)
{
st.getglobal("engine");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
lua::RegFunctionsLocal(st, lua_misc_func);
st.setglobal("engine");
st.getglobal("engine");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
lua::RegFunctionsLocal(st, lua_misc_func);
st.setglobal("engine");
}

@ -2,268 +2,268 @@
static DFHack::Process* GetProcessPtr(lua::state &st)
{
return DFHack::Core::getInstance().p;
return DFHack::Core::getInstance().p;
}
static int lua_Process_readDWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t ret=c->readDWord( (void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t ret=c->readDWord( (void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
}
static int lua_Process_writeDWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeDWord((void *) st.as<uint32_t>(1),st.as<uint32_t>(2));
return 0;
return 0;
}
static int lua_Process_readFloat(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
float ret=c->readFloat((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
st.push(ret);
return 1;
}
static int lua_Process_readWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint16_t ret=c->readWord((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
st.push(ret);
return 1;
}
static int lua_Process_writeWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeWord((void *) st.as<uint32_t>(1),st.as<uint16_t>(2));
return 0;
return 0;
}
static int lua_Process_readByte(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint8_t ret=c->readByte((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
st.push(ret);
return 1;
}
static int lua_Process_writeByte(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeByte((void *) st.as<uint32_t>(1),st.as<uint8_t>(2));
return 0;
return 0;
}
static int lua_Process_read(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
size_t len=st.as<uint32_t>(2);
uint8_t* buf;
if(!st.is<lua::nil>(3))
buf=(uint8_t*)lua_touserdata(st,3);
else
buf=new uint8_t[len];
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
size_t len=st.as<uint32_t>(2);
uint8_t* buf;
if(!st.is<lua::nil>(3))
buf=(uint8_t*)lua_touserdata(st,3);
else
buf=new uint8_t[len];
c->read((void *) st.as<uint32_t>(1),len,buf);
st.pushlightuserdata(buf);
return 1;
st.pushlightuserdata(buf);
return 1;
}
static int lua_Process_write(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c-> write((void *) st.as<uint32_t>(1),st.as<uint32_t>(2),static_cast<uint8_t*>(lua_touserdata(st,3)));
return 0;
return 0;
}
static int lua_Process_readSTLString (lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readSTLString((void *) st.as<uint32_t>(1));
st.push(r);
return 1;
st.push(r);
return 1;
}
static int lua_Process_writeSTLString(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeSTLString((void *) st.as<uint32_t>(1),st.as<std::string>(2));
return 0;
return 0;
}
static int lua_Process_copySTLString(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->copySTLString((void *) st.as<uint32_t>(1),st.as<uint32_t>(2));
return 0;
return 0;
}
static int lua_Process_doReadClassName(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->doReadClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->doReadClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
}
static int lua_Process_readClassName(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
}
static int lua_Process_readCString (lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readCString((void *) st.as<uint32_t>(1));
st.push(r);
return 1;
st.push(r);
return 1;
}
static int lua_Process_isSuspended(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isSuspended());
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isSuspended());
return 1;
}
static int lua_Process_isIdentified(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isIdentified());
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isIdentified());
return 1;
}
static int lua_Process_getMemRanges(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::vector<DFHack::t_memrange> ranges;
c->getMemRanges(ranges);
st.newtable();
for(size_t i=0;i<ranges.size();i++)
{
st.push(i);
st.newtable();
st.push((uint32_t)ranges[i].start); // WARNING!! lua has only 32bit numbers, possible loss of data!!
st.setfield("start");
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::vector<DFHack::t_memrange> ranges;
c->getMemRanges(ranges);
st.newtable();
for(size_t i=0;i<ranges.size();i++)
{
st.push(i);
st.newtable();
st.push((uint32_t)ranges[i].start); // WARNING!! lua has only 32bit numbers, possible loss of data!!
st.setfield("start");
st.push((uint32_t)ranges[i].end);
st.setfield("end");
st.push(std::string(ranges[i].name));
st.setfield("name");
st.push(ranges[i].read);
st.setfield("read");
st.push(ranges[i].write);
st.setfield("write");
st.push(ranges[i].execute);
st.setfield("execute");
st.push(ranges[i].shared);
st.setfield("shared");
st.push(ranges[i].valid);
st.setfield("valid");
st.settable();
}
return 1;
st.setfield("end");
st.push(std::string(ranges[i].name));
st.setfield("name");
st.push(ranges[i].read);
st.setfield("read");
st.push(ranges[i].write);
st.setfield("write");
st.push(ranges[i].execute);
st.setfield("execute");
st.push(ranges[i].shared);
st.setfield("shared");
st.push(ranges[i].valid);
st.setfield("valid");
st.settable();
}
return 1;
}
static int lua_Process_getBase(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t base=c->getBase();
st.push(base);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t base=c->getBase();
st.push(base);
return 1;
}
/*static int lua_Process_getPID(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
int ret=c->getPID();
st.push(ret);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
int ret=c->getPID();
st.push(ret);
return 1;
}*/
static int lua_Process_getPath(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string ret=c->getPath();
st.push(ret);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string ret=c->getPath();
st.push(ret);
return 1;
}
static int lua_Process_setPermisions(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
DFHack::t_memrange range,trange;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
DFHack::t_memrange range,trange;
st.getfield("start",1);
range.start= (void *)st.as<uint64_t>();
st.pop();
st.getfield("end",1);
range.end= (void *)st.as<uint64_t>();
st.pop();
st.getfield("start",1);
range.start= (void *)st.as<uint64_t>();
st.pop();
st.getfield("end",1);
range.end= (void *)st.as<uint64_t>();
st.pop();
st.getfield("read",2);
trange.read=st.as<bool>();
st.pop();
st.getfield("write",2);
trange.write=st.as<bool>();
st.pop();
st.getfield("execute",2);
trange.execute=st.as<bool>();
st.pop();
st.getfield("read",2);
trange.read=st.as<bool>();
st.pop();
st.getfield("write",2);
trange.write=st.as<bool>();
st.pop();
st.getfield("execute",2);
trange.execute=st.as<bool>();
st.pop();
c->setPermisions(range,trange);
c->setPermisions(range,trange);
return 0;
return 0;
}
#define PROC_FUNC(name) {#name,lua_Process_ ## name}
const luaL_Reg lua_process_func[]=
{
PROC_FUNC(readDWord),
PROC_FUNC(writeDWord),
PROC_FUNC(readFloat),
PROC_FUNC(readWord),
PROC_FUNC(writeWord),
PROC_FUNC(readByte),
PROC_FUNC(writeByte),
PROC_FUNC(read),
PROC_FUNC(write),
PROC_FUNC(readSTLString),
PROC_FUNC(writeSTLString),
PROC_FUNC(copySTLString),
PROC_FUNC(doReadClassName),
PROC_FUNC(readClassName),
PROC_FUNC(readCString ),
PROC_FUNC(isSuspended),
PROC_FUNC(isIdentified),
PROC_FUNC(getMemRanges),
PROC_FUNC(getBase),
//PROC_FUNC(getPID), //not implemented
PROC_FUNC(getPath),
PROC_FUNC(setPermisions),
{NULL,NULL}
PROC_FUNC(readDWord),
PROC_FUNC(writeDWord),
PROC_FUNC(readFloat),
PROC_FUNC(readWord),
PROC_FUNC(writeWord),
PROC_FUNC(readByte),
PROC_FUNC(writeByte),
PROC_FUNC(read),
PROC_FUNC(write),
PROC_FUNC(readSTLString),
PROC_FUNC(writeSTLString),
PROC_FUNC(copySTLString),
PROC_FUNC(doReadClassName),
PROC_FUNC(readClassName),
PROC_FUNC(readCString ),
PROC_FUNC(isSuspended),
PROC_FUNC(isIdentified),
PROC_FUNC(getMemRanges),
PROC_FUNC(getBase),
//PROC_FUNC(getPID), //not implemented
PROC_FUNC(getPath),
PROC_FUNC(setPermisions),
{NULL,NULL}
};
#undef PROC_FUNC
void lua::RegisterProcess(lua::state &st)
{
st.getglobal("Process");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
st.getglobal("Process");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
lua::RegFunctionsLocal(st, lua_process_func);
lua::RegFunctionsLocal(st, lua_process_func);
st.setglobal("Process");
st.setglobal("Process");
}

@ -1,4 +1,4 @@
// automatically chop trees
// automatically chop trees
#include "uicommon.h"
@ -549,7 +549,7 @@ public:
}
std::string getFocusString() { return "autochop"; }
void updateAutochopBurrows()
{
watchedBurrows.clear();
@ -586,7 +586,7 @@ struct autochop_hook : public df::viewscreen_dwarfmodest
using namespace df::enums::ui_sidebar_mode;
return (ui->main.mode == DesignateChopTrees);
}
void sendKey(const df::interface_key &key)
{
set<df::interface_key> tmp;

@ -220,7 +220,7 @@ struct dump_hook : public df::viewscreen_dwarfmodest
links += sp->links.give_to_workshop.size();
links += sp->links.take_from_workshop.size();
bool state = monitor.isMonitored(sp);
if (links + 12 >= y) {
y = dims.y2;
OutputString(COLOR_WHITE, x, y, "Auto: ");

@ -59,8 +59,8 @@ struct MaterialDescriptor
bool matches(const MaterialDescriptor &a) const
{
return a.valid && valid &&
a.type == type &&
return a.valid && valid &&
a.type == type &&
a.index == index &&
a.item_type == item_type &&
a.item_subtype == item_subtype;
@ -141,15 +141,15 @@ static bool allow_future_placement = false;
static inline bool in_material_choice_stage()
{
return Gui::build_selector_hotkey(Core::getTopViewscreen()) &&
return Gui::build_selector_hotkey(Core::getTopViewscreen()) &&
ui_build_selector->building_type == df::building_type::Construction &&
ui->main.mode == ui_sidebar_mode::Build &&
ui->main.mode == ui_sidebar_mode::Build &&
ui_build_selector->stage == 2;
}
static inline bool in_placement_stage()
{
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
ui->main.mode == ui_sidebar_mode::Build &&
ui_build_selector &&
ui_build_selector->building_type == df::building_type::Construction &&
@ -158,7 +158,7 @@ static inline bool in_placement_stage()
static inline bool in_type_choice_stage()
{
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
ui->main.mode == ui_sidebar_mode::Build &&
ui_build_selector &&
ui_build_selector->building_type < 0;
@ -269,7 +269,7 @@ static bool check_autoselect(MaterialDescriptor &material, bool toggle)
size_t idx;
if (is_material_in_autoselect(idx, material))
{
if (toggle)
if (toggle)
vector_erase_at(get_curr_constr_prefs(), idx);
return true;
@ -440,7 +440,7 @@ static bool is_valid_building_site(building_site &site, bool orthogonal_check, b
}
else if (orthogonal_check)
{
if (shape != tiletype_shape::RAMP &&
if (shape != tiletype_shape::RAMP &&
shape_basic != tiletype_shape_basic::Floor &&
shape_basic != tiletype_shape_basic::Stair)
return false;
@ -945,7 +945,7 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
{
// First valid site is guaranteed to be anchored, either on a tile or against a valid orthogonal tile
// Use it as an anchor point to generate materials list
anchor = valid_building_sites.front();
anchor = valid_building_sites.front();
valid_building_sites.pop_front();
valid_building_sites.push_back(anchor);
}
@ -1057,8 +1057,8 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
int16_t last_used_constr_subtype = (in_material_choice_stage()) ? ui_build_selector->building_subtype : -1;
INTERPOSE_NEXT(feed)(input);
if (revert_to_last_used_type &&
last_used_constr_subtype >= 0 &&
if (revert_to_last_used_type &&
last_used_constr_subtype >= 0 &&
in_type_choice_stage() &&
hotkeys.find(last_used_constr_subtype) != hotkeys.end())
{

@ -226,7 +226,7 @@ struct melt_hook : public df::viewscreen_dwarfmodest
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
int y = dims.y2 - 6;
int links = 0;
links += sp->links.give_to_pile.size();
links += sp->links.take_from_pile.size();

@ -142,7 +142,7 @@ static bool check_mandates(df::item *item)
if (mandate->mode != 0)
continue;
if (item->getType() != mandate->item_type ||
if (item->getType() != mandate->item_type ||
(mandate->item_subtype != -1 && item->getSubtype() != mandate->item_subtype))
continue;
@ -421,14 +421,14 @@ struct trade_hook : public df::viewscreen_dwarfmodest
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
int y = dims.y2 - 5;
int links = 0;
links += sp->links.give_to_pile.size();
links += sp->links.take_from_pile.size();
links += sp->links.give_to_workshop.size();
links += sp->links.take_from_workshop.size();
bool state = monitor.isMonitored(sp);
if (links + 12 >= y) {
y = dims.y2;
OutputString(COLOR_WHITE, x, y, "Auto: ");

@ -72,12 +72,12 @@ pair<uint32_t, uint32_t> get_building_size(df::building* b)
char get_tile_dig(MapExtras::MapCache mc, int32_t x, int32_t y, int32_t z)
{
df::tiletype tt = mc.tiletypeAt(DFCoord(x, y, z));
df::tiletype tt = mc.tiletypeAt(DFCoord(x, y, z));
df::tiletype_shape ts = tileShape(tt);
switch (ts)
{
case tiletype_shape::EMPTY:
case tiletype_shape::RAMP_TOP:
case tiletype_shape::RAMP_TOP:
return 'h';
case tiletype_shape::FLOOR:
case tiletype_shape::BOULDER:
@ -102,7 +102,7 @@ char get_tile_dig(MapExtras::MapCache mc, int32_t x, int32_t y, int32_t z)
string get_tile_build(uint32_t x, uint32_t y, df::building* b)
{
if (! b)
if (! b)
return " ";
bool at_nw_corner = x == b->x1 && y == b->y1;
bool at_se_corner = x == b->x2 && y == b->y2;
@ -366,7 +366,7 @@ string get_tile_build(uint32_t x, uint32_t y, df::building* b)
out << "CS";
if (ts->use_dump)
{
if (ts->dump_x_shift == 0)
if (ts->dump_x_shift == 0)
{
if (ts->dump_y_shift > 0)
out << "dd";
@ -429,7 +429,7 @@ string get_tile_build(uint32_t x, uint32_t y, df::building* b)
case building_type::AxleVertical:
return "Mv";
case building_type::Rollers:
if (! at_nw_corner)
if (! at_nw_corner)
return "`";
out << "Mr";
switch (((df::building_rollersst*) b)->direction)
@ -440,7 +440,7 @@ string get_tile_build(uint32_t x, uint32_t y, df::building* b)
out << "s";
case screw_pump_direction::FromSouth:
out << "s";
case screw_pump_direction::FromWest:
case screw_pump_direction::FromWest:
out << "s";
}
out << "(" << size.first << "x" << size.second << ")";
@ -533,7 +533,7 @@ string get_tile_place(uint32_t x, uint32_t y, df::building* b)
out << "p";
break;
case df::stockpile_group_set::mask_armor:
out << "d";
out << "d";
break;
default: //multiple stockpile type
return "`";

@ -332,7 +332,7 @@ static int addBuilding(lua_State* L)
newDefinition.connections.can_connect.push_back(-1);//TODO add this too...
newDefinition.connections.tiles.push_back(df::coord(x,y,0));
lua_pop(L,1);
}
lua_pop(L,1);

File diff suppressed because it is too large Load Diff

@ -52,8 +52,8 @@ struct MaterialDescriptor
bool matches(const MaterialDescriptor &a) const
{
return a.valid && valid &&
a.type == type &&
return a.valid && valid &&
a.type == type &&
a.index == index &&
a.item_type == item_type &&
a.item_subtype == item_subtype;
@ -190,7 +190,7 @@ private:
masks_column.filterDisplay();
}
void populateMaterials()
{
materials_column.clear();
@ -248,7 +248,7 @@ private:
materials_column.sort();
}
void addMaterialEntry(df::dfhack_material_category &selected_category,
void addMaterialEntry(df::dfhack_material_category &selected_category,
MaterialInfo &material, std::string name)
{
if (!selected_category.whole || material.matches(selected_category))
@ -350,7 +350,7 @@ private:
}
};
// START Planning
// START Planning
class PlannedBuilding
{
public:

@ -51,7 +51,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest
bool isInPlannedBuildingQueryMode()
{
return (ui->main.mode == df::ui_sidebar_mode::QueryBuilding ||
return (ui->main.mode == df::ui_sidebar_mode::QueryBuilding ||
ui->main.mode == df::ui_sidebar_mode::BuildingItems) &&
planner.getSelectedPlannedBuilding();
}
@ -91,7 +91,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest
{
if (getNoblePositionOfSelectedBuildingOwner().size() > 0)
return canReserveRoom(world->selected_building);
else
else
return false;
}
@ -119,7 +119,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest
{
show_help = true;
}
if (is_planmode_enabled(type))
{
if (planner.inQuickFortMode() && planner.in_dummmy_screen)
@ -184,7 +184,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest
{
planner.removeSelectedPlannedBuilding(); // Remove persistent data
}
}
else if (isInNobleRoomQueryMode())
{
@ -347,7 +347,7 @@ static command_result buildingplan_cmd(color_ostream &out, vector <string> & par
{
show_debugging = (toLower(parameters[1]) == "on");
out << "Debugging " << ((show_debugging) ? "enabled" : "disabled") << endl;
}
}
}
return CR_OK;

@ -92,7 +92,7 @@ command_result catsplosion (color_ostream &out, std::vector <std::string> & para
female_counts[raw->creature_id].size(); //auto initialize the females as well
}
}
// print (optional)
//if (showcreatures == 1)
{

@ -127,7 +127,7 @@ command_result df_changeitem(color_ostream &out, vector <string> & parameters)
for (size_t i = 0; i < parameters.size(); i++)
{
string & p = parameters[i];
if (p == "help" || p == "?")
{
out << changeitem_help << endl;
@ -328,7 +328,7 @@ command_result changeitem_execute(
out << " quality: " << describeQuality(item->getQuality()) << endl;
//if(item->isImproved())
// out << " imp.quality: " << describeQuality(item->getImprovementQuality()) << endl;
out << " material: " << mat_old.getToken() << endl;
out << " material: " << mat_old.getToken() << endl;
return CR_OK;
}
@ -350,7 +350,7 @@ command_result changeitem_execute(
// fixme: changing material of cloth items needs more work...
// <_Q> cloth items have a "CLOTH" improvement which tells you about the cloth that was used to make it
if(force||(mat_old.subtype == mat_new.subtype && mat_old.mode==mat_new.mode))
{
item->setMaterial(mat_new.type);

@ -32,8 +32,8 @@ DFHACK_PLUGIN("changelayer");
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(cursor);
const string changelayer_help =
" Allows to change the material of whole geology layers.\n"
const string changelayer_help =
" Allows to change the material of whole geology layers.\n"
" Can have impact on all surrounding regions, not only your embark!\n"
" By default changing stone to soil and vice versa is not allowed.\n"
" By default changes only the layer at the cursor position.\n"
@ -47,7 +47,7 @@ const string changelayer_help =
" all_biomes - Change layer for all biomes on your map.\n"
" Result may be undesirable since the same layer\n"
" can AND WILL be on different z-levels for different biomes.\n"
" Use the tool 'probe' to get an idea how layers and biomes\n"
" Use the tool 'probe' to get an idea how layers and biomes\n"
" are distributed on your map.\n"
" all_layers - Change all layers on your map.\n"
" Candy mountain, anyone?\n"
@ -70,7 +70,7 @@ const string changelayer_help =
" changelayer MARBLE allbiomes alllayers\n"
" Convert all layers of all biomes into marble.\n";
const string changelayer_trouble =
const string changelayer_trouble =
"Known problems with changelayer:\n\n"
" Nothing happens, the material stays the old.\n"
" Pause/unpause the game and/or move the cursor a bit. Then retry.\n"
@ -108,7 +108,7 @@ static bool warned = false;
command_result changelayer (color_ostream &out, std::vector <std::string> & parameters)
{
CoreSuspender suspend;
CoreSuspender suspend;
string material;
bool force = false;
@ -209,13 +209,13 @@ command_result changelayer (color_ostream &out, std::vector <std::string> & para
// there is no Maps::WriteGeology or whatever, and I didn't want to mess with the library and add it
// so I copied the stuff which reads the geology information and modified it to be able to change it
//
//
// a more elegant solution would probably look like this:
// 1) modify Maps::ReadGeology to accept and fill one more optional vector
// 1) modify Maps::ReadGeology to accept and fill one more optional vector
// where the geolayer ids of the 9 biomes are stored
// 2) call ReadGeology here, modify the data in the vectors without having to do all that map stuff
// 3) write Maps::WriteGeology, pass the vectors, let it do it's work
// Step 1) is optional, but it would make implementing 3) easier.
// Step 1) is optional, but it would make implementing 3) easier.
// Otherwise that "check which geo_index is used by biome X" loop would need to be done again.
// no need to touch the same geology more than once
@ -226,17 +226,17 @@ command_result changelayer (color_ostream &out, std::vector <std::string> & para
// iterate over 8 surrounding regions + local region
for (int i = eNorthWest; i < eBiomeCount; i++)
{
if(verbose)
if(verbose)
out << "---Biome: " << i;
if(!all_biomes && i!=biome)
{
if(verbose)
if(verbose)
out << "-skipping" << endl;
continue;
}
else
{
if(verbose)
if(verbose)
out << "-checking" << endl;
}
@ -304,9 +304,9 @@ command_result changelayer (color_ostream &out, std::vector <std::string> & para
if(conversionAllowed(out, mat_new, mat_old, force))
{
if(verbose)
out << "changing geolayer " << j
<< " from " << mat_old.getToken()
<< " to " << mat_new.getToken()
out << "changing geolayer " << j
<< " from " << mat_old.getToken()
<< " to " << mat_new.getToken()
<< endl;
geolayers[j]->mat_index = mat_new.index;
}
@ -329,7 +329,7 @@ command_result changelayer (color_ostream &out, std::vector <std::string> & para
}
out.print("Done.\n");
// Give control back to DF.
return CR_OK;
}

@ -326,7 +326,7 @@ command_result df_createitem (color_ostream &out, vector <string> & parameters)
out.printerr("The creature you specified has no such caste!\n");
return CR_FAILURE;
}
}
}
}
if (mat_type == -1)
{

@ -127,7 +127,7 @@ void setUnitNickname(df::unit *unit, const std::string &nick)
std::string determineCurse(df::unit * unit)
{
string cursetype = "unknown";
// ghosts: ghostly, duh
// as of DF 34.05 and higher vampire ghosts and the like should not be possible
// if they get reintroduced later it will become necessary to watch 'ghostly' seperately
@ -140,17 +140,17 @@ std::string determineCurse(df::unit * unit)
cursetype = "zombie";
// necromancers: alive, don't eat, don't drink, don't age
if(!unit->curse.add_tags1.bits.NOT_LIVING
&& unit->curse.add_tags1.bits.NO_EAT
&& unit->curse.add_tags1.bits.NO_DRINK
if(!unit->curse.add_tags1.bits.NOT_LIVING
&& unit->curse.add_tags1.bits.NO_EAT
&& unit->curse.add_tags1.bits.NO_DRINK
&& unit->curse.add_tags2.bits.NO_AGING
)
cursetype = "necromancer";
// werecreatures: alive, DO eat, DO drink, don't age
if(!unit->curse.add_tags1.bits.NOT_LIVING
&& !unit->curse.add_tags1.bits.NO_EAT
&& !unit->curse.add_tags1.bits.NO_DRINK
if(!unit->curse.add_tags1.bits.NOT_LIVING
&& !unit->curse.add_tags1.bits.NO_EAT
&& !unit->curse.add_tags1.bits.NO_DRINK
&& unit->curse.add_tags2.bits.NO_AGING )
cursetype = "werebeast";
@ -199,7 +199,7 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters)
if(parameters[i] == "verbose")
{
// verbose makes no sense without enabling details
giveDetails = true;
giveDetails = true;
verbose = true;
}
}
@ -234,7 +234,7 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters)
cursecount++;
string cursetype = determineCurse(unit);
if(giveNick)
{
setUnitNickname(unit, cursetype); //"CURSED");
@ -266,12 +266,12 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters)
{
missing = true;
}
out.print("born in %d, cursed in %d to be a %s. (%s%s%s)\n",
unit->relations.birth_year,
unit->relations.curse_year,
cursetype.c_str(),
// technically most cursed creatures are undead,
// technically most cursed creatures are undead,
// therefore output 'active' if they are not completely dead
unit->flags1.bits.dead ? "deceased" : "active",
unit->flags3.bits.ghostly ? "-ghostly" : "",
@ -298,6 +298,6 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters)
out.print("Number of cursed creatures on map: %d \n", cursecount);
else
out.print("Number of cursed creatures on tile: %d \n", cursecount);
return CR_OK;
}

File diff suppressed because it is too large Load Diff

@ -91,7 +91,7 @@ command_result writeFlag (color_ostream &out, vector <string> & parameters)
case '7':
value = parameters[0][0] - '0';
break;
default:
out.print("Invalid value specified\n");
return CR_FAILURE;

@ -70,7 +70,7 @@ command_result eventExample(color_ostream& out, vector<string>& parameters) {
}
}
*/
EventManager::EventHandler initiateHandler(jobInitiated, 1);
EventManager::EventHandler completeHandler(jobCompleted, 0);
EventManager::EventHandler timeHandler(timePassed, 1);
@ -82,7 +82,7 @@ command_result eventExample(color_ostream& out, vector<string>& parameters) {
EventManager::EventHandler invasionHandler(invasion, 1000);
EventManager::EventHandler unitAttackHandler(unitAttack, 1);
EventManager::unregisterAll(plugin_self);
EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, plugin_self);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, plugin_self);
EventManager::registerListener(EventManager::EventType::UNIT_DEATH, deathHandler, plugin_self);
@ -105,7 +105,7 @@ command_result eventExample(color_ostream& out, vector<string>& parameters) {
timeHandler.freq = t;
EventManager::unregister(EventManager::EventType::TICK, timeHandler, plugin_self);
EventManager::unregister(EventManager::EventType::TICK, timeHandler, plugin_self);
out.print("Events registered.\n");
return CR_OK;
}
@ -159,7 +159,7 @@ void construction(color_ostream& out, void* ptr) {
out.print(" construction destroyed\n");
else
out.print(" construction created\n");
}
void syndrome(color_ostream& out, void* ptr) {

@ -65,12 +65,12 @@ public:
t_itemflags &f = itm->origin->flags;
return (f.unk1 || f.unk2 || f.unk3 || f.unk4 ||
return (f.unk1 || f.unk2 || f.unk3 || f.unk4 ||
f.unk6 || f.unk7 ||
f.unk10 || f.unk11);
}
virtual void postPrint(DFHack::dfh_item *itm)
virtual void postPrint(DFHack::dfh_item *itm)
{
std::vector<std::string> flags;

@ -1,189 +1,189 @@
#include "Core.h"
#include "Console.h"
#include "PluginManager.h"
#include "MemAccess.h"
#include "MiscUtils.h"
#include <tinythread.h> //not sure if correct
#include <string>
#include <vector>
#include <sstream>
using std::vector;
using std::string;
using namespace DFHack;
uint64_t timeLast=0;
static tthread::mutex* mymutex=0;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
struct memory_data
{
void * addr;
size_t len;
size_t refresh;
int state;
uint8_t *buf,*lbuf;
vector<t_memrange> ranges;
}memdata;
enum HEXVIEW_STATES
{
STATE_OFF,STATE_ON
};
command_result memview (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("memview");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview));
memdata.state=STATE_OFF;
mymutex=new tthread::mutex;
return CR_OK;
}
size_t convert(const std::string& p,bool ishex=false)
{
size_t ret;
std::stringstream conv;
if(ishex)
conv<<std::hex;
conv<<p;
conv>>ret;
return ret;
}
bool isAddr(uint32_t *trg,vector<t_memrange> & ranges)
{
if(trg[0]%4==0)
for(size_t i=0;i<ranges.size();i++)
if(ranges[i].isInRange((void *)trg[0]))
return true;
return false;
}
void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,color_ostream &con,vector<t_memrange> & ranges)
{
const size_t page_size=16;
for(size_t i=0;i<len;i+=page_size)
{
//con.gotoxy(1,i/page_size+1);
con.print("0x%08X ",i+start);
for(size_t j=0;(j<page_size) && (i+j<len);j++)
{
if(j%4==0)
{
con.reset_color();
if(isAddr((uint32_t *)(buf+j+i),ranges))
con.color(COLOR_LIGHTRED); //coloring in the middle does not work
//TODO make something better?
}
if(lbuf[j+i]!=buf[j+i])
con.print("*%02X",buf[j+i]); //if modfied show a star
else
con.print(" %02X",buf[j+i]);
}
con.reset_color();
con.print(" | ");
for(size_t j=0;(j<page_size) && (i+j<len);j++)
if((buf[j+i]>31)&&(buf[j+i]<128)) //only printable ascii
con.print("%c",buf[j+i]);
else
con.print(".");
//con.print("\n");
}
con.print("\n");
}
void Deinit()
{
if(memdata.state==STATE_ON)
{
is_enabled = false;
memdata.state=STATE_OFF;
delete [] memdata.buf;
delete [] memdata.lbuf;
}
}
DFhackCExport command_result plugin_onupdate (color_ostream &out)
{
mymutex->lock();
if(memdata.state==STATE_OFF)
{
mymutex->unlock();
return CR_OK;
}
//Console &con=out;
uint64_t time2 = GetTimeMs64();
uint64_t delta = time2-timeLast;
if(memdata.refresh!=0)
if(delta<memdata.refresh)
{
mymutex->unlock();
return CR_OK;
}
timeLast = time2;
Core::getInstance().p->read(memdata.addr,memdata.len,memdata.buf);
outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,out,memdata.ranges);
memcpy(memdata.lbuf, memdata.buf, memdata.len);
if(memdata.refresh==0)
Deinit();
mymutex->unlock();
return CR_OK;
}
command_result memview (color_ostream &out, vector <string> & parameters)
{
mymutex->lock();
Core::getInstance().p->getMemRanges(memdata.ranges);
memdata.addr=(void *)convert(parameters[0],true);
if(memdata.addr==0)
{
Deinit();
memdata.state=STATE_OFF;
is_enabled = false;
mymutex->unlock();
return CR_OK;
}
else
{
Deinit();
bool isValid=false;
for(size_t i=0;i<memdata.ranges.size();i++)
if(memdata.ranges[i].isInRange(memdata.addr))
isValid=true;
if(!isValid)
{
out.printerr("Invalid address:%x\n",memdata.addr);
mymutex->unlock();
return CR_OK;
}
is_enabled = true;
memdata.state=STATE_ON;
}
if(parameters.size()>1)
memdata.len=convert(parameters[1]);
else
memdata.len=20*16;
if(parameters.size()>2)
memdata.refresh=convert(parameters[2]);
else
memdata.refresh=0;
memdata.buf=new uint8_t[memdata.len];
memdata.lbuf=new uint8_t[memdata.len];
Core::getInstance().p->getMemRanges(memdata.ranges);
mymutex->unlock();
return CR_OK;
}
DFhackCExport command_result plugin_shutdown (color_ostream &out)
{
mymutex->lock();
Deinit();
delete mymutex;
mymutex->unlock();
return CR_OK;
}
#include "Core.h"
#include "Console.h"
#include "PluginManager.h"
#include "MemAccess.h"
#include "MiscUtils.h"
#include <tinythread.h> //not sure if correct
#include <string>
#include <vector>
#include <sstream>
using std::vector;
using std::string;
using namespace DFHack;
uint64_t timeLast=0;
static tthread::mutex* mymutex=0;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
struct memory_data
{
void * addr;
size_t len;
size_t refresh;
int state;
uint8_t *buf,*lbuf;
vector<t_memrange> ranges;
}memdata;
enum HEXVIEW_STATES
{
STATE_OFF,STATE_ON
};
command_result memview (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("memview");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview));
memdata.state=STATE_OFF;
mymutex=new tthread::mutex;
return CR_OK;
}
size_t convert(const std::string& p,bool ishex=false)
{
size_t ret;
std::stringstream conv;
if(ishex)
conv<<std::hex;
conv<<p;
conv>>ret;
return ret;
}
bool isAddr(uint32_t *trg,vector<t_memrange> & ranges)
{
if(trg[0]%4==0)
for(size_t i=0;i<ranges.size();i++)
if(ranges[i].isInRange((void *)trg[0]))
return true;
return false;
}
void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,color_ostream &con,vector<t_memrange> & ranges)
{
const size_t page_size=16;
for(size_t i=0;i<len;i+=page_size)
{
//con.gotoxy(1,i/page_size+1);
con.print("0x%08X ",i+start);
for(size_t j=0;(j<page_size) && (i+j<len);j++)
{
if(j%4==0)
{
con.reset_color();
if(isAddr((uint32_t *)(buf+j+i),ranges))
con.color(COLOR_LIGHTRED); //coloring in the middle does not work
//TODO make something better?
}
if(lbuf[j+i]!=buf[j+i])
con.print("*%02X",buf[j+i]); //if modfied show a star
else
con.print(" %02X",buf[j+i]);
}
con.reset_color();
con.print(" | ");
for(size_t j=0;(j<page_size) && (i+j<len);j++)
if((buf[j+i]>31)&&(buf[j+i]<128)) //only printable ascii
con.print("%c",buf[j+i]);
else
con.print(".");
//con.print("\n");
}
con.print("\n");
}
void Deinit()
{
if(memdata.state==STATE_ON)
{
is_enabled = false;
memdata.state=STATE_OFF;
delete [] memdata.buf;
delete [] memdata.lbuf;
}
}
DFhackCExport command_result plugin_onupdate (color_ostream &out)
{
mymutex->lock();
if(memdata.state==STATE_OFF)
{
mymutex->unlock();
return CR_OK;
}
//Console &con=out;
uint64_t time2 = GetTimeMs64();
uint64_t delta = time2-timeLast;
if(memdata.refresh!=0)
if(delta<memdata.refresh)
{
mymutex->unlock();
return CR_OK;
}
timeLast = time2;
Core::getInstance().p->read(memdata.addr,memdata.len,memdata.buf);
outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,out,memdata.ranges);
memcpy(memdata.lbuf, memdata.buf, memdata.len);
if(memdata.refresh==0)
Deinit();
mymutex->unlock();
return CR_OK;
}
command_result memview (color_ostream &out, vector <string> & parameters)
{
mymutex->lock();
Core::getInstance().p->getMemRanges(memdata.ranges);
memdata.addr=(void *)convert(parameters[0],true);
if(memdata.addr==0)
{
Deinit();
memdata.state=STATE_OFF;
is_enabled = false;
mymutex->unlock();
return CR_OK;
}
else
{
Deinit();
bool isValid=false;
for(size_t i=0;i<memdata.ranges.size();i++)
if(memdata.ranges[i].isInRange(memdata.addr))
isValid=true;
if(!isValid)
{
out.printerr("Invalid address:%x\n",memdata.addr);
mymutex->unlock();
return CR_OK;
}
is_enabled = true;
memdata.state=STATE_ON;
}
if(parameters.size()>1)
memdata.len=convert(parameters[1]);
else
memdata.len=20*16;
if(parameters.size()>2)
memdata.refresh=convert(parameters[2]);
else
memdata.refresh=0;
memdata.buf=new uint8_t[memdata.len];
memdata.lbuf=new uint8_t[memdata.len];
Core::getInstance().p->getMemRanges(memdata.ranges);
mymutex->unlock();
return CR_OK;
}
DFhackCExport command_result plugin_shutdown (color_ostream &out)
{
mymutex->lock();
Deinit();
delete mymutex;
mymutex->unlock();
return CR_OK;
}

@ -527,7 +527,7 @@ command_result df_tiles (Core * c, vector <string> & parameters)
}
else
{
cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl;
}
biter ++;

@ -156,7 +156,7 @@ command_result df_vectors (color_ostream &con, vector <string> & parameters)
vectorsUsage(con);
return CR_FAILURE;
}
if (!hexOrDec(parameters[1], bytes))
{
vectorsUsage(con);
@ -273,7 +273,7 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
vectorsUsage(con);
return CR_FAILURE;
}
if (!hexOrDec(parameters[1], bytes))
{
vectorsUsage(con);

@ -1 +1 @@
Subproject commit a80abe848e4886a210e7a5123192e9221dc85810
Subproject commit 5b167d2ba89b877d80e0609feae8771aeaef356d

@ -1156,7 +1156,7 @@ command_result diglx (color_ostream &out, vector <string> & parameters)
return digl(out,lol);
}
// TODO:
// TODO:
// digl and digv share the longish floodfill code and only use different conditions
// to check if a tile should be marked for digging or not.
// to make the plugin a bit smaller and cleaner a main execute method would be nice
@ -1377,7 +1377,7 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
out.printerr("Too many parameters.\n");
return CR_FAILURE;
}
uint32_t targetDigType;
if ( parameters.size() == 1 )
{
@ -1406,13 +1406,13 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
{
targetDigType = -1;
}
if (!Maps::IsValid())
{
out.printerr("Map is not available!\n");
return CR_FAILURE;
}
int32_t cx, cy, cz;
uint32_t xMax,yMax,zMax;
Maps::getSize(xMax,yMax,zMax);
@ -1436,7 +1436,7 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
return CR_FAILURE;
}
out.print("(%d,%d,%d) tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, baseDes.whole);
if ( targetDigType != -1 )
{
baseDes.bits.dig = (tile_dig_designation::tile_dig_designation)targetDigType;
@ -1448,7 +1448,7 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
baseDes.bits.dig = tile_dig_designation::Default;
}
}
for( uint32_t z = 0; z < zMax; z++ )
{
for( uint32_t x = 1; x < tileXMax-1; x++ )
@ -1462,7 +1462,7 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
tt = mCache->tiletypeAt(current);
if (!DFHack::isWallTerrain(tt))
continue;
//designate it for digging
df::tile_designation des = mCache->designationAt(current);
if ( !mCache->testCoord(current) )
@ -1471,14 +1471,14 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
delete mCache;
return CR_FAILURE;
}
df::tile_designation designation = mCache->designationAt(current);
designation.bits.dig = baseDes.bits.dig;
mCache->setDesignationAt(current, designation);
}
}
}
mCache->WriteAll();
delete mCache;
return CR_OK;

@ -38,7 +38,7 @@ set<string> autodigMaterials;
DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
if (enabled == enable)
return CR_OK;
enabled = enable;
if ( enabled ) {
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, digHandler, plugin_self);
@ -79,31 +79,31 @@ void onDig(color_ostream& out, void* ptr) {
df::job* job = (df::job*)ptr;
if ( job->completion_timer > 0 )
return;
if ( job->job_type != df::enums::job_type::Dig &&
job->job_type != df::enums::job_type::CarveUpwardStaircase &&
job->job_type != df::enums::job_type::CarveDownwardStaircase &&
job->job_type != df::enums::job_type::CarveUpDownStaircase &&
job->job_type != df::enums::job_type::CarveRamp &&
job->job_type != df::enums::job_type::CarveUpwardStaircase &&
job->job_type != df::enums::job_type::CarveDownwardStaircase &&
job->job_type != df::enums::job_type::CarveUpDownStaircase &&
job->job_type != df::enums::job_type::CarveRamp &&
job->job_type != df::enums::job_type::DigChannel )
return;
set<df::coord> jobLocations;
for ( df::job_list_link* link = &world->job_list; link != NULL; link = link->next ) {
if ( link->item == NULL )
continue;
if ( link->item->job_type != df::enums::job_type::Dig &&
link->item->job_type != df::enums::job_type::CarveUpwardStaircase &&
link->item->job_type != df::enums::job_type::CarveDownwardStaircase &&
link->item->job_type != df::enums::job_type::CarveUpDownStaircase &&
link->item->job_type != df::enums::job_type::CarveRamp &&
link->item->job_type != df::enums::job_type::CarveUpwardStaircase &&
link->item->job_type != df::enums::job_type::CarveDownwardStaircase &&
link->item->job_type != df::enums::job_type::CarveUpDownStaircase &&
link->item->job_type != df::enums::job_type::CarveRamp &&
link->item->job_type != df::enums::job_type::DigChannel )
continue;
jobLocations.insert(link->item->pos);
}
MapExtras::MapCache cache;
df::coord pos = job->pos;
for ( int16_t a = -1; a <= 1; a++ ) {
@ -118,23 +118,23 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
if ( !Maps::isValidTilePos(pt) ) {
return;
}
df::map_block* block = Maps::getTileBlock(pt);
if (!block)
return;
if ( block->designation[pt.x&0xF][pt.y&0xF].bits.hidden )
return;
df::tiletype type = block->tiletype[pt.x&0xF][pt.y&0xF];
if ( ENUM_ATTR(tiletype, material, type) != df::enums::tiletype_material::MINERAL )
return;
if ( ENUM_ATTR(tiletype, shape, type) != df::enums::tiletype_shape::WALL )
return;
if ( block->designation[pt.x&0xF][pt.y&0xF].bits.dig != df::enums::tile_dig_designation::No )
return;
uint32_t xMax,yMax,zMax;
Maps::getSize(xMax,yMax,zMax);
if ( pt.x == 0 || pt.y == 0 || pt.x+1 == xMax*16 || pt.y+1 == yMax*16 )
@ -142,7 +142,7 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
if ( jobLocations.find(pt) != jobLocations.end() ) {
return;
}
int16_t mat = cache.veinMaterialAt(pt);
if ( mat == -1 )
return;
@ -152,7 +152,7 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
return;
}
}
block->designation[pt.x&0xF][pt.y&0xF].bits.dig = df::enums::tile_dig_designation::Default;
block->flags.bits.designated = true;
// *process_dig = true;
@ -174,12 +174,12 @@ command_result digFlood (color_ostream &out, std::vector <std::string> & paramet
adding = true;
continue;
}
if ( parameters[a] == "CLEAR" ) {
autodigMaterials.clear();
continue;
}
if ( parameters[a] == "digAll0" ) {
digAll = false;
continue;
@ -188,7 +188,7 @@ command_result digFlood (color_ostream &out, std::vector <std::string> & paramet
digAll = true;
continue;
}
for ( size_t b = 0; b < world->raws.inorganics.size(); b++ ) {
df::inorganic_raw* inorganic = world->raws.inorganics[b];
if ( parameters[a] == inorganic->id ) {
@ -199,16 +199,16 @@ command_result digFlood (color_ostream &out, std::vector <std::string> & paramet
goto loop;
}
}
out.print("Could not find material \"%s\".\n", parameters[a].c_str());
return CR_WRONG_USAGE;
loop: continue;
}
autodigMaterials.insert(toAdd.begin(), toAdd.end());
for ( auto a = toRemove.begin(); a != toRemove.end(); a++ )
autodigMaterials.erase(*a);
return CR_OK;
}

@ -53,7 +53,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
if ( !firstInvader ) {
return -1;
}
//do whatever you need to do at the first important edge
df::coord pt1 = firstImportantEdge.p1;
df::coord pt2 = firstImportantEdge.p2;
@ -63,14 +63,14 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
pt2 = temp;
}
//out.print("first important edge: (%d,%d,%d) -> (%d,%d,%d)\n", pt1.x,pt1.y,pt1.z, pt2.x,pt2.y,pt2.z);
int32_t jobId = -1;
df::map_block* block1 = Maps::getTileBlock(pt1);
df::map_block* block2 = Maps::getTileBlock(pt2);
bool passable1 = block1->walkable[pt1.x&0xF][pt1.y&0xF];
bool passable2 = block2->walkable[pt2.x&0xF][pt2.y&0xF];
df::coord location;
df::building* building = Buildings::findAtTile(pt2);
df::coord buildingPos = pt2;
@ -202,7 +202,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
Job::linkIntoWorld(job);
jobId = job->id;
job->completion_timer = abilities.jobDelay[CostDimension::Dig];
//TODO: test if he already has a pick
bool hasPick = false;
for ( size_t a = 0; a < firstInvader->inventory.size(); a++ ) {
@ -219,10 +219,10 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
hasPick = true;
break;
}
if ( hasPick )
return firstInvader->id;
//create and give a pick
//based on createitem.cpp
df::reaction_product_itemst *prod = NULL;
@ -240,7 +240,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
out.print("%s, %d: no valid item.\n", __FILE__, __LINE__);
return -1;
}
DFHack::MaterialInfo material;
if ( !material.find("OBSIDIAN") ) {
out.print("%s, %d: no water.\n", __FILE__, __LINE__);
@ -251,20 +251,20 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
prod->probability = 100;
prod->count = 1;
prod->product_dimension = 1;
vector<df::item*> out_items;
vector<df::reaction_reagent*> in_reag;
vector<df::item*> in_items;
prod->produce(firstInvader, &out_items, &in_reag, &in_items, 1, df::job_skill::NONE,
df::historical_entity::find(firstInvader->civ_id),
df::world_site::find(df::global::ui->site_id));
if ( out_items.size() != 1 ) {
out.print("%s, %d: wrong size: %d.\n", __FILE__, __LINE__, out_items.size());
return -1;
}
out_items[0]->moveToGround(firstInvader->pos.x, firstInvader->pos.y, firstInvader->pos.z);
#if 0
//check for existing item there
for ( size_t a = 0; a < firstInvader->inventory.size(); a++ ) {
@ -276,7 +276,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
}
#endif
Items::moveToInventory(cache, out_items[0], firstInvader, df::unit_inventory_item::T_mode::Weapon, firstInvader->body.weapon_bp);
delete prod;
}
}

@ -141,7 +141,7 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" diggingInvaders edgesPerTick n\n makes the pathfinding algorithm work on at most n edges per tick. Set to 0 or lower to make it unlimited."
// " diggingInvaders\n Makes invaders try to dig now.\n"
));
//*df::global::debug_showambush = true;
return CR_OK;
}
@ -154,7 +154,7 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
if ( enabled == enable )
return CR_OK;
enabled = enable;
EventManager::unregisterAll(plugin_self);
clearDijkstra();
@ -166,7 +166,7 @@ DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
EventManager::registerListener(EventManager::EventType::INVASION, handler, plugin_self);
findAndAssignInvasionJob(out, (void*)0);
}
return CR_OK;
}
@ -196,9 +196,9 @@ class PointComp {
public:
unordered_map<df::coord, cost_t, PointHash> *pointCost;
PointComp(unordered_map<df::coord, cost_t, PointHash> *p): pointCost(p) {
}
int32_t operator()(df::coord p1, df::coord p2) {
if ( p1 == p2 ) return 0;
auto i1 = pointCost->find(p1);
@ -246,11 +246,11 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
digAbilities.erase(race);
}
a++;
} else if ( parameters[a] == "setCost" || parameters[a] == "setDelay" ) {
if ( a+3 >= parameters.size() )
return CR_WRONG_USAGE;
string raceString = parameters[a+1];
if ( digAbilities.find(raceString) == digAbilities.end() ) {
DigAbilities bob;
@ -258,7 +258,7 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
digAbilities[raceString] = bob;
}
DigAbilities& abilities = digAbilities[raceString];
string costStr = parameters[a+2];
int32_t costDim = -1;
if ( costStr == "walk" ) {
@ -276,7 +276,7 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
} else {
return CR_WRONG_USAGE;
}
cost_t value;
stringstream asdf(parameters[a+3]);
asdf >> value;
@ -291,15 +291,15 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
} else if ( parameters[a] == "edgeCost" ) {
if ( a+1 >= parameters.size() )
return CR_WRONG_USAGE;
string raceString = parameters[a+1];
if ( digAbilities.find(raceString) == digAbilities.end() ) {
out.print("Race %s does not have dig abilities assigned.\n", raceString.c_str());
return CR_WRONG_USAGE;
}
DigAbilities& abilities = digAbilities[raceString];
df::coord bob = Gui::getCursorPos();
out.print("(%d,%d,%d), (%d,%d,%d): cost = %lld\n", lastDebugEdgeCostPoint.x, lastDebugEdgeCostPoint.y, lastDebugEdgeCostPoint.z, bob.x, bob.y, bob.z, getEdgeCost(out, lastDebugEdgeCostPoint, bob, abilities));
lastDebugEdgeCostPoint = bob;
@ -325,7 +325,7 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
}
activeDigging = enabled;
out.print("diggingInvaders: enabled = %d, activeDigging = %d, edgesPerTick = %d\n", enabled, activeDigging, edgesPerTick);
return CR_OK;
}
@ -366,14 +366,14 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
CoreSuspender suspend;
//returns the worker id of the job created //used to
//out.print("%s, %d: %d\n", __FILE__, __LINE__, (int32_t)tickTime);
if ( !enabled || !activeDigging ) {
clearDijkstra();
return;
}
EventManager::unregister(EventManager::EventType::TICK, findJobTickHandler, plugin_self);
EventManager::registerTick(findJobTickHandler, 1, plugin_self);
if ( fringe.empty() ) {
df::unit* lastDigger = df::unit::find(lastInvasionDigger);
if ( lastDigger && lastDigger->job.current_job && lastDigger->job.current_job->id == lastInvasionJob ) {
@ -381,7 +381,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
}
//out.print("%s,%d: lastDigger = %d, last job = %d, last digger's job = %d\n", __FILE__, __LINE__, lastInvasionDigger, lastInvasionJob, !lastDigger ? -1 : (!lastDigger->job.current_job ? -1 : lastDigger->job.current_job->id));
lastInvasionDigger = lastInvasionJob = -1;
clearDijkstra();
unordered_set<uint16_t> invaderConnectivity;
unordered_set<uint16_t> localConnectivity;
@ -446,13 +446,13 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
return;
}
}
df::unit* firstInvader = df::unit::find(invaders[0]);
if ( firstInvader == NULL ) {
fringe.clear();
return;
}
df::creature_raw* creature_raw = df::creature_raw::find(firstInvader->race);
if ( creature_raw == NULL || digAbilities.find(creature_raw->creature_id) == digAbilities.end() ) {
//inappropriate digger: no dig abilities
@ -464,13 +464,13 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
//out << firstInvader->id << endl;
//out << firstInvader->pos.x << ", " << firstInvader->pos.y << ", " << firstInvader->pos.z << endl;
//out << __LINE__ << endl;
uint32_t xMax, yMax, zMax;
Maps::getSize(xMax,yMax,zMax);
xMax *= 16;
yMax *= 16;
MapExtras::MapCache cache;
clock_t t0 = clock();
clock_t totalEdgeTime = 0;
int32_t edgesExpanded = 0;
@ -486,7 +486,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
break;
}
closedSet.insert(pt);
if ( localPts.find(pt) != localPts.end() ) {
localPtsFound++;
if ( true || localPtsFound >= localPts.size() ) {
@ -537,7 +537,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
unordered_set<df::coord, PointHash> requiresZNeg;
unordered_set<df::coord, PointHash> requiresZPos;
//find important edges
Edge firstImportantEdge(df::coord(), df::coord(), -1);
//df::coord closest;
@ -551,7 +551,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
continue;
//closest = pt;
//closestCostEstimate = costMap[closest];
//if ( workNeeded[pt] == 0 )
//if ( workNeeded[pt] == 0 )
// continue;
while ( parentMap.find(pt) != parentMap.end() ) {
//out.print("(%d,%d,%d)\n", pt.x, pt.y, pt.z);
@ -563,7 +563,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
}
//closestCostActual += cost;
if ( Maps::canStepBetween(parent, pt) ) {
} else {
if ( pt.x == parent.x && pt.y == parent.y ) {
if ( pt.z < parent.z ) {
@ -586,14 +586,14 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
}
if ( firstImportantEdge.p1 == df::coord() )
return;
/*
if ( closestCostActual != closestCostEstimate ) {
out.print("%s,%d: closest = (%d,%d,%d), estimate = %lld != actual = %lld\n", __FILE__, __LINE__, closest.x,closest.y,closest.z, closestCostEstimate, closestCostActual);
return;
}
*/
assignJob(out, firstImportantEdge, parentMap, costMap, invaders, requiresZNeg, requiresZPos, cache, abilities);
lastInvasionDigger = firstInvader->id;
lastInvasionJob = firstInvader->job.current_job ? firstInvader->job.current_job->id : -1;
@ -605,7 +605,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
if ( invaderJobs.find(job->id) == invaderJobs.end() ) {
continue;
}
//cancel it
job->flags.bits.item_lost = 1;
out.print("%s,%d: cancelling job %d.\n", __FILE__,__LINE__, job->id);

@ -57,34 +57,34 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
cost_t cost = abilities.costWeight[CostDimension::Walk];
if ( cost < 0 )
return -1;
if ( Maps::getTileBlock(pt1) == NULL || Maps::getTileBlock(pt2) == NULL )
return -1;
df::tiletype* type2 = Maps::getTileType(pt2);
df::tiletype_shape shape2 = ENUM_ATTR(tiletype, shape, *type2);
if ( Maps::getTileBlock(pt1)->designation[pt1.x&0xF][pt1.y&0xF].bits.flow_size >= 4 )
return -1;
if ( Maps::getTileBlock(pt2)->designation[pt2.x&0xF][pt2.y&0xF].bits.flow_size >= 4 )
return -1;
if ( shape2 == df::enums::tiletype_shape::EMPTY ) {
return -1;
}
if ( shape2 == df::enums::tiletype_shape::BRANCH ||
shape2 == df::enums::tiletype_shape::TRUNK_BRANCH ||
shape2 == df::enums::tiletype_shape::TWIG )
return -1;
/*
if () {
df::map_block* temp = Maps::getTileBlock(df::coord(pt1.x,pt1.y,pt1.z-1));
if ( temp && temp->designation[pt1.x&0xF][pt1.y&0xF]
}
*/
if ( Maps::canStepBetween(pt1, pt2) ) {
return cost;
}
@ -93,11 +93,11 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( building2 ) {
if ( abilities.costWeight[CostDimension::DestroyBuilding] < 0 )
return -1;
cost += abilities.costWeight[CostDimension::DestroyBuilding];
cost += abilities.costWeight[CostDimension::DestroyBuilding];
if ( dx*dx + dy*dy > 1 )
return -1;
}
bool construction2 = ENUM_ATTR(tiletype, material, *type2) == df::enums::tiletype_material::CONSTRUCTION;
if ( construction2 ) {
//smooth or not?
@ -113,7 +113,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
cost += abilities.costWeight[CostDimension::DestroyRoughConstruction];
}
}
if ( dz == 0 ) {
if ( !building2 && !construction2 ) {
//it has to be a wall
@ -143,7 +143,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
}
cost += abilities.costWeight[CostDimension::Dig];
}
bool walkable_high1 = shape1 == df::tiletype_shape::STAIR_UP || shape1 == df::tiletype_shape::STAIR_UPDOWN;
if ( !walkable_high1 ) {
if ( shape1 != df::enums::tiletype_shape::WALL ) {
@ -154,7 +154,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
}
cost += abilities.costWeight[CostDimension::Dig];
}
if ( building2 ) {
//moving up through an open bridge or a usable hatch is fine. other buildings are not
bool unforbiddenHatch = false;
@ -188,7 +188,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( !unforbiddenHatch && !inactiveBridge )
return -1;
}
/*bool forbidden = false;
if ( building2 && building2->getType() == df::building_type::Hatch ) {
df::building_hatchst* hatch = (df::building_hatchst*)building2;
@ -202,7 +202,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( !walkable_high2 ) {
if ( building2 || construction2 )
return -1;
if ( shape2 != df::enums::tiletype_shape::WALL )
return -1;
if ( abilities.costWeight[CostDimension::Dig] < 0 ) {
@ -240,14 +240,14 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( bridge->direction == df::building_bridgest::T_direction::Down && pt1.y == bridge->y2 )
return -1;
}
bool forbidden = false;
if ( building1 && building1->getType() == df::building_type::Hatch ) {
df::building_hatchst* hatch = (df::building_hatchst*)building1;
if ( hatch->door_flags.bits.forbidden || hatch->door_flags.bits.closed && hatch->door_flags.bits.operated_by_mechanisms )
forbidden = true;
}
//you can deconstruct a hatch from the side
if ( building1 && forbidden /*&& building1->getType() == df::building_type::Hatch*/ ) {
/*
@ -300,7 +300,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( minCost == -1 )
return -1;
cost += minCost;
*/
//note: assignJob is not ready for this level of sophistication, so don't allow it
return -1;
@ -312,7 +312,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
return -1;
}
}
return cost;
}
@ -329,7 +329,7 @@ cost_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
return cost;
return 100 + cost;
}
Maps::ensureTileBlock(pt1);
Maps::ensureTileBlock(pt2);
df::tiletype* type1 = Maps::getTileType(pt1);
@ -404,7 +404,7 @@ cost_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
if ( shape2 == df::enums::tiletype_shape::RAMP_TOP ) {
return -1;
}
//it has to be a wall
if ( shape2 != df::enums::tiletype_shape::WALL ) {
out << "shape = " << (int32_t)shape2 << endl;
@ -427,15 +427,15 @@ cost_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
cost += costWeight[CostDimension::Dig];
return cost;
}
//descending
if ( passable_high2 )
return cost;
if ( building2 || construction2 ) {
return -1;
}
//must be a wall?
if ( shape2 != df::enums::tiletype_shape::WALL ) {
out.print("%s, line %n: WTF?\n", __FILE__, __LINE__);
@ -445,7 +445,7 @@ cost_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
cost += costWeight[CostDimension::Dig];
return cost;
}
//moving diagonally
return -1;
}
@ -455,7 +455,7 @@ vector<Edge>* getEdgeSet(color_ostream &out, df::coord point, MapExtras::MapCach
//vector<Edge>* result = new vector<Edge>(26);
vector<Edge>* result = new vector<Edge>();
result->reserve(26);
//size_t count = 0;
for ( int32_t dx = -1; dx <= 1; dx++ ) {
for ( int32_t dy = -1; dy <= 1; dy++ ) {

@ -56,7 +56,7 @@ public:
cost = -1;
}
Edge(const Edge& e): p1(e.p1), p2(e.p2), cost(e.cost) {
}
Edge(df::coord p1In, df::coord p2In, cost_t costIn): cost(costIn) {
if ( p2In < p1In ) {

@ -103,7 +103,7 @@ static void printAttributes(color_ostream &con, df::unit* cre, ostream& out) {
static void printTraits(color_ostream &con, df::unit* cre, ostream& out)
{
out << " <Traits>" << endl;
df::unit_soul * s = cre->status.current_soul;
if (s)
@ -120,7 +120,7 @@ static void printTraits(color_ostream &con, df::unit* cre, ostream& out)
}
*/
out << "</Trait>" << endl;
}
}
out << " </Traits>" << endl;
@ -189,7 +189,7 @@ static void export_dwarf(color_ostream &con, df::unit* cre, ostream& out) {
info += Translation::TranslateName(&cre->name, false);
info[0] = toupper(info[0]);
con.print("Exporting %s\n", info.c_str());
out << " <Creature>" << endl;
element("Name", info.c_str(), out);
element("Nickname", cre->name.nickname.c_str(), out);
@ -225,7 +225,7 @@ command_result export_dwarves (color_ostream &con, std::vector <std::string> & p
uint32_t civ = ui->civ_id;
outf << "<?xml version='1.0' encoding='ibm850'?>" << endl << "<Creatures>" << endl;
for (int i = 0; i < world->units.all.size(); ++i)
{
df::unit* cre = world->units.all[i];

@ -1720,8 +1720,8 @@ struct dwarf_monitor_hook : public df::viewscreen_dwarfmodest
ostringstream date_str;
auto month = World::ReadCurrentMonth() + 1;
auto day = World::ReadCurrentDay();
date_str << "Date:" << World::ReadCurrentYear() << "-" <<
((month < 10) ? "0" : "") << month << "-" <<
date_str << "Date:" << World::ReadCurrentYear() << "-" <<
((month < 10) ? "0" : "") << month << "-" <<
((day < 10) ? "0" : "") << day;
OutputString(COLOR_GREY, x, y, date_str.str());

@ -463,7 +463,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
break;
case SC_WORLD_UNLOADED:
world_specific_hooks(out,false);
break;
default:
break;

@ -247,6 +247,6 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" * 0 - Disable dwarf teleportation (default)\n"
" * 1 - Make dwarves teleport to their destinations instantly.\n"
));
return CR_OK;
}

@ -71,14 +71,14 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" L: Low Traffic\n"
" R: Restricted Traffic\n"
));
commands.push_back(PluginCommand(
"restrictliquids","Restrict on every visible square with liquid",
restrictLiquid, false, ""
));
commands.push_back(PluginCommand(
"restrictice","Restrict traffic on squares above visible ice",
restrictIce, false, ""
));
commands.push_back(PluginCommand(
"restrictliquids","Restrict on every visible square with liquid",
restrictLiquid, false, ""
));
commands.push_back(PluginCommand(
"restrictice","Restrict traffic on squares above visible ice",
restrictIce, false, ""
));
return CR_OK;
}
@ -285,7 +285,7 @@ command_result restrictLiquid(color_ostream &out, std::vector<std::string> & par
command_result restrictIce(color_ostream &out, std::vector<std::string> & params)
{
return setAllMatching(out, restrictIceProc);
return setAllMatching(out, restrictIceProc);
}
//Helper function for writing new functions that check every tile on the map.
@ -383,29 +383,29 @@ void allRestricted(DFCoord coord, MapExtras::MapCache &map)
//Restrict traffic if tile is visible and liquid is present.
void restrictLiquidProc(DFCoord coord, MapExtras::MapCache &map)
{
df::tile_designation des = map.designationAt(coord);
if ((des.bits.hidden == 0) && (des.bits.flow_size != 0))
{
des.bits.traffic = tile_traffic::Restricted;
map.setDesignationAt(coord, des);
}
df::tile_designation des = map.designationAt(coord);
if ((des.bits.hidden == 0) && (des.bits.flow_size != 0))
{
des.bits.traffic = tile_traffic::Restricted;
map.setDesignationAt(coord, des);
}
}
//Restrict traffice if tile is above visible ice wall.
void restrictIceProc(DFCoord coord, MapExtras::MapCache &map)
{
//There is no ice below the bottom of the map.
if (coord.z == 0)
return;
DFCoord tile_below = DFCoord(coord.x, coord.y, coord.z - 1);
df::tiletype tt = map.tiletypeAt(tile_below);
df::tile_designation des = map.designationAt(tile_below);
if ((des.bits.hidden == 0) && (tileMaterial(tt) == tiletype_material::FROZEN_LIQUID))
{
des = map.designationAt(coord);
des.bits.traffic = tile_traffic::Restricted;
map.setDesignationAt(coord, des);
}
//There is no ice below the bottom of the map.
if (coord.z == 0)
return;
DFCoord tile_below = DFCoord(coord.x, coord.y, coord.z - 1);
df::tiletype tt = map.tiletypeAt(tile_below);
df::tile_designation des = map.designationAt(tile_below);
if ((des.bits.hidden == 0) && (tileMaterial(tt) == tiletype_material::FROZEN_LIQUID))
{
des = map.designationAt(coord);
des.bits.traffic = tile_traffic::Restricted;
map.setDesignationAt(coord, des);
}
}

@ -46,7 +46,7 @@ command_result df_fixdiplomats (color_ostream &out, vector<string> &parameters)
for (int j = 0; j < ent->positions.own.size(); j++)
{
pos = ent->positions.own[j];
if (pos->responsibilities[entity_position_responsibility::MAKE_INTRODUCTIONS] &&
if (pos->responsibilities[entity_position_responsibility::MAKE_INTRODUCTIONS] &&
pos->responsibilities[entity_position_responsibility::MAKE_PEACE_AGREEMENTS] &&
pos->responsibilities[entity_position_responsibility::MAKE_TOPIC_AGREEMENTS])
{

@ -126,7 +126,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
Gui::setCursorCoords(c_x - (prevX-x), c_y - (prevY-y), z);
//Save this round's stuff for next time so we can monitor for changes made by the user
prevX = x;
prevX = x;
prevY = y;
prevZ = z;
prevMenuWidth = menu_width;

@ -9,30 +9,30 @@ DFHACK_PLUGIN("fortplan");
command_result fortplan(color_ostream &out, vector<string> & params);
struct BuildingInfo {
std::string code;
df::building_type type;
df::furnace_type furnaceType;
df::workshop_type workshopType;
df::trap_type trapType;
std::string name;
bool variableSize;
int defaultHeight;
int defaultWidth;
bool hasCustomOptions;
BuildingInfo(std::string theCode, df::building_type theType, std::string theName, int height, int width) {
code = theCode;
type = theType;
name = theName;
variableSize = false;
defaultHeight = height;
defaultWidth = width;
hasCustomOptions = false;
}
bool allocate() {
return planner.allocatePlannedBuilding(type);
}
std::string code;
df::building_type type;
df::furnace_type furnaceType;
df::workshop_type workshopType;
df::trap_type trapType;
std::string name;
bool variableSize;
int defaultHeight;
int defaultWidth;
bool hasCustomOptions;
BuildingInfo(std::string theCode, df::building_type theType, std::string theName, int height, int width) {
code = theCode;
type = theType;
name = theName;
variableSize = false;
defaultHeight = height;
defaultWidth = width;
hasCustomOptions = false;
}
bool allocate() {
return planner.allocatePlannedBuilding(type);
}
};
class MatchesCode
@ -54,34 +54,34 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCom
commands.push_back(PluginCommand("fortplan","Lay out buildings in your fortress based on a Quickfort-style CSV input file.",fortplan,false,
"Lay out buildings in your fortress based on a Quickfort-style CSV input file.\n"
"Usage: fortplan [filename]\n"));
buildings.push_back(BuildingInfo("c",df::building_type::Chair,"Chair",1,1));
buildings.push_back(BuildingInfo("b",df::building_type::Bed,"Bed",1,1));
buildings.push_back(BuildingInfo("t",df::building_type::Table,"Table",1,1));
buildings.push_back(BuildingInfo("n",df::building_type::Coffin,"Coffin",1,1));
buildings.push_back(BuildingInfo("d",df::building_type::Door,"Door",1,1));
buildings.push_back(BuildingInfo("x",df::building_type::Floodgate,"Floodgate",1,1));
buildings.push_back(BuildingInfo("h",df::building_type::Box,"Box",1,1));
buildings.push_back(BuildingInfo("r",df::building_type::Weaponrack,"Weapon Rack",1,1));
buildings.push_back(BuildingInfo("c",df::building_type::Chair,"Chair",1,1));
buildings.push_back(BuildingInfo("b",df::building_type::Bed,"Bed",1,1));
buildings.push_back(BuildingInfo("t",df::building_type::Table,"Table",1,1));
buildings.push_back(BuildingInfo("n",df::building_type::Coffin,"Coffin",1,1));
buildings.push_back(BuildingInfo("d",df::building_type::Door,"Door",1,1));
buildings.push_back(BuildingInfo("x",df::building_type::Floodgate,"Floodgate",1,1));
buildings.push_back(BuildingInfo("h",df::building_type::Box,"Box",1,1));
buildings.push_back(BuildingInfo("r",df::building_type::Weaponrack,"Weapon Rack",1,1));
buildings.push_back(BuildingInfo("a",df::building_type::Armorstand,"Armor Stand",1,1));
buildings.push_back(BuildingInfo("f",df::building_type::Cabinet,"Cabinet",1,1));
buildings.push_back(BuildingInfo("s",df::building_type::Statue,"Statue",1,1));
buildings.push_back(BuildingInfo("y",df::building_type::WindowGlass,"Glass Window",1,1));
buildings.push_back(BuildingInfo("m",df::building_type::AnimalTrap,"Animal Trap",1,1));
buildings.push_back(BuildingInfo("v",df::building_type::Chain,"Chain",1,1));
buildings.push_back(BuildingInfo("j",df::building_type::Cage,"Cage",1,1));
buildings.push_back(BuildingInfo("H",df::building_type::Hatch,"Floor Hatch",1,1));
buildings.push_back(BuildingInfo("W",df::building_type::GrateWall,"Wall Grate",1,1));
buildings.push_back(BuildingInfo("G",df::building_type::GrateFloor,"Floor Grate",1,1));
buildings.push_back(BuildingInfo("B",df::building_type::BarsVertical,"Vertical Bars",1,1));
buildings.push_back(BuildingInfo("~b",df::building_type::BarsFloor,"Floor Bars",1,1));
buildings.push_back(BuildingInfo("R",df::building_type::TractionBench,"Traction Bench",1,1));
buildings.push_back(BuildingInfo("~s",df::building_type::Slab,"Slab",1,1));
buildings.push_back(BuildingInfo("N",df::building_type::NestBox,"Nest Box",1,1));
buildings.push_back(BuildingInfo("~h",df::building_type::Hive,"Hive",1,1));
planner.initialize();
buildings.push_back(BuildingInfo("f",df::building_type::Cabinet,"Cabinet",1,1));
buildings.push_back(BuildingInfo("s",df::building_type::Statue,"Statue",1,1));
buildings.push_back(BuildingInfo("y",df::building_type::WindowGlass,"Glass Window",1,1));
buildings.push_back(BuildingInfo("m",df::building_type::AnimalTrap,"Animal Trap",1,1));
buildings.push_back(BuildingInfo("v",df::building_type::Chain,"Chain",1,1));
buildings.push_back(BuildingInfo("j",df::building_type::Cage,"Cage",1,1));
buildings.push_back(BuildingInfo("H",df::building_type::Hatch,"Floor Hatch",1,1));
buildings.push_back(BuildingInfo("W",df::building_type::GrateWall,"Wall Grate",1,1));
buildings.push_back(BuildingInfo("G",df::building_type::GrateFloor,"Floor Grate",1,1));
buildings.push_back(BuildingInfo("B",df::building_type::BarsVertical,"Vertical Bars",1,1));
buildings.push_back(BuildingInfo("~b",df::building_type::BarsFloor,"Floor Bars",1,1));
buildings.push_back(BuildingInfo("R",df::building_type::TractionBench,"Traction Bench",1,1));
buildings.push_back(BuildingInfo("~s",df::building_type::Slab,"Slab",1,1));
buildings.push_back(BuildingInfo("N",df::building_type::NestBox,"Nest Box",1,1));
buildings.push_back(BuildingInfo("~h",df::building_type::Hive,"Hive",1,1));
planner.initialize();
return CR_OK;
}
@ -116,260 +116,260 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
}
std::vector<std::vector<std::string>> tokenizeFile(std::string filename) {
std::ifstream infile(filename.c_str());
std::vector<std::vector<std::string>> fileTokens(128, std::vector<std::string>(128));
std::vector<std::vector<std::string>>::size_type x, y;
if (!infile.good()) {
throw -1;
}
std::string line;
y = 0;
while (std::getline(infile, line)) {
x = 0;
if (strcmp(line.substr(0,1).c_str(),"#")==0) {
fileTokens[y++][0] = line;
continue;
}
int start = 0;
auto nextInd = line.find(',');
std::string curCell = line.substr(start,nextInd-start);
do {
fileTokens[y][x] = curCell;
start = nextInd+1;
nextInd = line.find(',',start);
curCell = line.substr(start,nextInd-start);
x++;
} while (nextInd != line.npos);
y++;
}
return fileTokens;
}
std::ifstream infile(filename.c_str());
std::vector<std::vector<std::string>> fileTokens(128, std::vector<std::string>(128));
std::vector<std::vector<std::string>>::size_type x, y;
if (!infile.good()) {
throw -1;
}
std::string line;
y = 0;
while (std::getline(infile, line)) {
x = 0;
if (strcmp(line.substr(0,1).c_str(),"#")==0) {
fileTokens[y++][0] = line;
continue;
}
int start = 0;
auto nextInd = line.find(',');
std::string curCell = line.substr(start,nextInd-start);
do {
fileTokens[y][x] = curCell;
start = nextInd+1;
nextInd = line.find(',',start);
curCell = line.substr(start,nextInd-start);
x++;
} while (nextInd != line.npos);
y++;
}
return fileTokens;
}
command_result fortplan(color_ostream &out, vector<string> & params) {
auto & con = out;
std::vector<std::vector<std::string>> layout(128, std::vector<std::string>(128));
if (params.size()) {
coord32_t cursor;
coord32_t userCursor;
coord32_t startCursor;
if (!DFHack::Gui::getCursorCoords(cursor.x, cursor.y, cursor.z)) {
con.print("You must have an active in-game cursor.\n");
return CR_FAILURE;
}
DFHack::Gui::getCursorCoords(startCursor.x, startCursor.y, startCursor.z);
userCursor = startCursor;
std::string cwd = Filesystem::getcwd();
std::string filename = cwd+"/"+params[0];
con.print("Loading file '%s'...\n",filename.c_str());
try {
layout = tokenizeFile(filename);
} catch (int e) {
con.print("Could not open the file.\n");
return CR_FAILURE;
}
if (!is_enabled) {
plugin_enable(out, true);
}
con.print("Loaded.\n");
std::vector<std::vector<std::string>>::size_type x, y;
bool started = false;
for (y = 0; y < layout.size(); y++) {
x = 0;
auto hashBuild = layout[y][x].find("#build");
if (hashBuild != layout[y][x].npos) {
auto startLoc = layout[y][x].find("start(");
if (startLoc != layout[y][x].npos) {
startLoc += 6;
auto nextDelimiter = layout[y][x].find(";",startLoc);
std::string startXStr = layout[y][x].substr(startLoc,nextDelimiter-startLoc);
int startXOffset = std::stoi(startXStr);
startLoc = nextDelimiter+1;
nextDelimiter = layout[y][x].find(";",startLoc);
std::string startYStr = layout[y][x].substr(startLoc,nextDelimiter-startLoc);
int startYOffset = std::stoi(startYStr);
startCursor.x -= startXOffset;
startCursor.y -= startYOffset;
DFHack::Gui::setCursorCoords(startCursor.x,startCursor.y,startCursor.z);
started = true;
auto startEnd = layout[y][x].find(")",nextDelimiter);
con.print("Starting at (%d,%d,%d) which is described as: %s\n",startCursor.x,startCursor.y,startCursor.z,layout[y][x].substr(nextDelimiter+1,startEnd-nextDelimiter).c_str());
std::string desc = layout[y][x].substr(startEnd+1);
if (desc.size()>0) {
con.print("Description of this plan: %s\n",desc.c_str());
}
continue;
} else {
con.print("No start location found for this block\n");
}
} else if (!started) {
con.print("Not a build file: %s\n",layout[y][x].c_str());
break;
}
for (x = 0; x < layout[y].size(); x++) {
if (strcmp(layout[y][x].substr(0,1).c_str(),"#")==0) {
continue;
}
if (strcmp(layout[y][x].c_str(),"`")!=0) {
auto dataIndex = layout[y][x].find("(");
std::string curCode;
std::vector<std::string> curData;
if (dataIndex != layout[y][x].npos) {
curCode = layout[y][x].substr(0,dataIndex);
int dataStart = dataIndex+1;
auto nextDataStart = layout[y][x].find(",",dataStart);
while (nextDataStart!=layout[y][x].npos) {
std::string nextData = layout[y][x].substr(dataStart,nextDataStart);
if (strcmp(nextData.substr(nextData.size()-1,1).c_str(),")")==0) {
nextData = nextData.substr(0,nextData.size()-1);
}
curData.push_back(nextData);
dataStart = nextDataStart+1;
nextDataStart = layout[y][x].find(",",dataStart);
}
} else {
curCode = layout[y][x];
}
//con.print("Found a cell with '%s' in it (layout[y][x] %d:%d-%d)\n",layout[y][x].c_str(),lineNum,start,nextInd);
auto buildingIndex = std::find_if(buildings.begin(), buildings.end(), MatchesCode(curCode.c_str()));
// = std::find(validInstructions.begin(), validInstructions.end(), layout[y][x]);
if(buildingIndex == buildings.end()) {
//con.print("That is not a valid code.\n");
} else {
//con.print("I can build that!\n");
BuildingInfo buildingInfo = *buildingIndex;
if (buildingInfo.variableSize || buildingInfo.defaultHeight > 1 || buildingInfo.defaultWidth > 1) {
//con.print("Found a building at (%d,%d) called %s, which has a size %dx%d or variable size\n",x,y,buildingInfo.name.c_str(),buildingInfo.defaultWidth, buildingInfo.defaultHeight);
// TODO: Make this function smarter, able to determine the exact shape
// and location of the building
// For now, we just assume that we are always looking at the top left
// corner of where it is located in the input file
coord32_t buildingSize;
if (!buildingInfo.variableSize) {
bool single = true;
bool block = true;
std::vector<std::vector<std::string>>::size_type checkX, checkY;
int yOffset = ((buildingInfo.defaultHeight-1)/2);
int xOffset = ((buildingInfo.defaultWidth-1)/2);
//con.print(" - Checking to see if it's a single, with %d<=x<%d and %d<=y<%d...\n",x-xOffset,x+xOffset,y-yOffset,y+yOffset);
// First, check to see if this is in the center of an empty square of its default size
for (checkY = y-yOffset; checkY <= (y+yOffset); checkY++) {
for (checkX = x-xOffset; checkX <= (x+xOffset); checkX++) {
if (checkX==x && checkY==y) {
continue;
}
auto checkDataIndex = layout[checkY][checkX].find("(");
std::string checkCode;
if (checkDataIndex != layout[checkY][checkX].npos) {
checkCode = layout[checkY][checkX].substr(0,checkDataIndex);
} else {
checkCode = layout[checkY][checkX];
}
con.print(" - Code at (%d,%d) is '%s': ",checkX,checkY,checkCode.c_str());
auto checkIndex = std::find_if(buildings.begin(), buildings.end(), MatchesCode(checkCode.c_str()));
//if (checkIndex == buildings.end()) {
// con.print("this is not a valid code, so we keep going.\n");
// continue;
//}
//if (curCode.compare(layout[checkY][checkX]) != 0) {
if (checkIndex != buildings.end()) {
//con.print("this is a building, so we break.\n");
single = false;
break;
} else {
//con.print("this is not a building, so we keep going.\n");
}
}
if (!single) {
//con.print("Not a single. Moving forward.\n");
break;
}
}
if (!single) {
// If that's not the case, check to see if this is the top-left corner of
// a square of its default size
//con.print(" - It's not single; checking to see if it's a block...\n");
for (checkY = y; checkY < (y+buildingInfo.defaultHeight); checkY++) {
for (checkX = x; checkX < (x+buildingInfo.defaultWidth); checkX++) {
if (checkX==x && checkY==y) {
continue;
}
auto checkDataIndex = layout[checkY][checkX].find("(");
std::string checkCode;
if (checkDataIndex != layout[checkY][checkX].npos) {
checkCode = layout[checkY][checkX].substr(0,checkDataIndex);
} else {
checkCode = layout[checkY][checkX];
}
//con.print(" - Code at (%d,%d) is '%s': ",checkX,checkY,checkCode.c_str());
if (curCode.compare(checkCode) != 0) {
//con.print("this is not the same as '%s', so we break.\n",curCode.c_str());
block = false;
break;
} else {
//con.print("this is the same as '%s', so we erase it and move on.\n",curCode.c_str());
layout[checkY][checkX] = "``";
}
}
if (!block) {
//con.print("Not a block. Moving forward.\n");
break;
}
}
}
if (single) {
//con.print("Placing a building with code '%s' centered at (%d,%d) and default size %dx%d.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
coord32_t offsetCursor = cursor;
offsetCursor.x -= xOffset;
offsetCursor.y -= yOffset;
DFHack::Gui::setCursorCoords(offsetCursor.x, offsetCursor.y, offsetCursor.z);
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing building with code '%s' centered at (%d,%d).\n",curCode.c_str(),x,y);
}
DFHack::Gui::setCursorCoords(cursor.x, cursor.y, cursor.z);
} else if (block) {
//con.print("Placing a building with code '%s' with corner at (%d,%d) and default size %dx%d.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing building with code '%s' with corner at (%d,%d).\n",curCode.c_str(),x,y);
}
} else {
con.print("*** Found a code '%s' at (%d,%d) for a building with default size %dx%d with an invalid size designation.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
}
} else {
//buildingSize = findBuildingExtent(layout, x, y, -1, -1, out);
//con.print(" - The building has variable size %dx%d\n",buildingSize.x, buildingSize.y);
//con.print(" - The building has a variable size, which is not yet handled.\n");
}
} else {
//con.print("Building a(n) %s.\n",buildingInfo.name.c_str());
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing the %s at (%d,%d).\n",buildingInfo.name.c_str(),x,y);
}
}
}
}
cursor.x++;
DFHack::Gui::setCursorCoords(cursor.x, cursor.y, cursor.z);
}
cursor.y++;
cursor.x = startCursor.x;
}
DFHack::Gui::setCursorCoords(userCursor.x, userCursor.y, userCursor.z);
con.print("Done with file.\n");
} else {
con.print("You must supply a filename to read.\n");
}
return CR_OK;
if (params.size()) {
coord32_t cursor;
coord32_t userCursor;
coord32_t startCursor;
if (!DFHack::Gui::getCursorCoords(cursor.x, cursor.y, cursor.z)) {
con.print("You must have an active in-game cursor.\n");
return CR_FAILURE;
}
DFHack::Gui::getCursorCoords(startCursor.x, startCursor.y, startCursor.z);
userCursor = startCursor;
std::string cwd = Filesystem::getcwd();
std::string filename = cwd+"/"+params[0];
con.print("Loading file '%s'...\n",filename.c_str());
try {
layout = tokenizeFile(filename);
} catch (int e) {
con.print("Could not open the file.\n");
return CR_FAILURE;
}
if (!is_enabled) {
plugin_enable(out, true);
}
con.print("Loaded.\n");
std::vector<std::vector<std::string>>::size_type x, y;
bool started = false;
for (y = 0; y < layout.size(); y++) {
x = 0;
auto hashBuild = layout[y][x].find("#build");
if (hashBuild != layout[y][x].npos) {
auto startLoc = layout[y][x].find("start(");
if (startLoc != layout[y][x].npos) {
startLoc += 6;
auto nextDelimiter = layout[y][x].find(";",startLoc);
std::string startXStr = layout[y][x].substr(startLoc,nextDelimiter-startLoc);
int startXOffset = std::stoi(startXStr);
startLoc = nextDelimiter+1;
nextDelimiter = layout[y][x].find(";",startLoc);
std::string startYStr = layout[y][x].substr(startLoc,nextDelimiter-startLoc);
int startYOffset = std::stoi(startYStr);
startCursor.x -= startXOffset;
startCursor.y -= startYOffset;
DFHack::Gui::setCursorCoords(startCursor.x,startCursor.y,startCursor.z);
started = true;
auto startEnd = layout[y][x].find(")",nextDelimiter);
con.print("Starting at (%d,%d,%d) which is described as: %s\n",startCursor.x,startCursor.y,startCursor.z,layout[y][x].substr(nextDelimiter+1,startEnd-nextDelimiter).c_str());
std::string desc = layout[y][x].substr(startEnd+1);
if (desc.size()>0) {
con.print("Description of this plan: %s\n",desc.c_str());
}
continue;
} else {
con.print("No start location found for this block\n");
}
} else if (!started) {
con.print("Not a build file: %s\n",layout[y][x].c_str());
break;
}
for (x = 0; x < layout[y].size(); x++) {
if (strcmp(layout[y][x].substr(0,1).c_str(),"#")==0) {
continue;
}
if (strcmp(layout[y][x].c_str(),"`")!=0) {
auto dataIndex = layout[y][x].find("(");
std::string curCode;
std::vector<std::string> curData;
if (dataIndex != layout[y][x].npos) {
curCode = layout[y][x].substr(0,dataIndex);
int dataStart = dataIndex+1;
auto nextDataStart = layout[y][x].find(",",dataStart);
while (nextDataStart!=layout[y][x].npos) {
std::string nextData = layout[y][x].substr(dataStart,nextDataStart);
if (strcmp(nextData.substr(nextData.size()-1,1).c_str(),")")==0) {
nextData = nextData.substr(0,nextData.size()-1);
}
curData.push_back(nextData);
dataStart = nextDataStart+1;
nextDataStart = layout[y][x].find(",",dataStart);
}
} else {
curCode = layout[y][x];
}
//con.print("Found a cell with '%s' in it (layout[y][x] %d:%d-%d)\n",layout[y][x].c_str(),lineNum,start,nextInd);
auto buildingIndex = std::find_if(buildings.begin(), buildings.end(), MatchesCode(curCode.c_str()));
// = std::find(validInstructions.begin(), validInstructions.end(), layout[y][x]);
if(buildingIndex == buildings.end()) {
//con.print("That is not a valid code.\n");
} else {
//con.print("I can build that!\n");
BuildingInfo buildingInfo = *buildingIndex;
if (buildingInfo.variableSize || buildingInfo.defaultHeight > 1 || buildingInfo.defaultWidth > 1) {
//con.print("Found a building at (%d,%d) called %s, which has a size %dx%d or variable size\n",x,y,buildingInfo.name.c_str(),buildingInfo.defaultWidth, buildingInfo.defaultHeight);
// TODO: Make this function smarter, able to determine the exact shape
// and location of the building
// For now, we just assume that we are always looking at the top left
// corner of where it is located in the input file
coord32_t buildingSize;
if (!buildingInfo.variableSize) {
bool single = true;
bool block = true;
std::vector<std::vector<std::string>>::size_type checkX, checkY;
int yOffset = ((buildingInfo.defaultHeight-1)/2);
int xOffset = ((buildingInfo.defaultWidth-1)/2);
//con.print(" - Checking to see if it's a single, with %d<=x<%d and %d<=y<%d...\n",x-xOffset,x+xOffset,y-yOffset,y+yOffset);
// First, check to see if this is in the center of an empty square of its default size
for (checkY = y-yOffset; checkY <= (y+yOffset); checkY++) {
for (checkX = x-xOffset; checkX <= (x+xOffset); checkX++) {
if (checkX==x && checkY==y) {
continue;
}
auto checkDataIndex = layout[checkY][checkX].find("(");
std::string checkCode;
if (checkDataIndex != layout[checkY][checkX].npos) {
checkCode = layout[checkY][checkX].substr(0,checkDataIndex);
} else {
checkCode = layout[checkY][checkX];
}
con.print(" - Code at (%d,%d) is '%s': ",checkX,checkY,checkCode.c_str());
auto checkIndex = std::find_if(buildings.begin(), buildings.end(), MatchesCode(checkCode.c_str()));
//if (checkIndex == buildings.end()) {
// con.print("this is not a valid code, so we keep going.\n");
// continue;
//}
//if (curCode.compare(layout[checkY][checkX]) != 0) {
if (checkIndex != buildings.end()) {
//con.print("this is a building, so we break.\n");
single = false;
break;
} else {
//con.print("this is not a building, so we keep going.\n");
}
}
if (!single) {
//con.print("Not a single. Moving forward.\n");
break;
}
}
if (!single) {
// If that's not the case, check to see if this is the top-left corner of
// a square of its default size
//con.print(" - It's not single; checking to see if it's a block...\n");
for (checkY = y; checkY < (y+buildingInfo.defaultHeight); checkY++) {
for (checkX = x; checkX < (x+buildingInfo.defaultWidth); checkX++) {
if (checkX==x && checkY==y) {
continue;
}
auto checkDataIndex = layout[checkY][checkX].find("(");
std::string checkCode;
if (checkDataIndex != layout[checkY][checkX].npos) {
checkCode = layout[checkY][checkX].substr(0,checkDataIndex);
} else {
checkCode = layout[checkY][checkX];
}
//con.print(" - Code at (%d,%d) is '%s': ",checkX,checkY,checkCode.c_str());
if (curCode.compare(checkCode) != 0) {
//con.print("this is not the same as '%s', so we break.\n",curCode.c_str());
block = false;
break;
} else {
//con.print("this is the same as '%s', so we erase it and move on.\n",curCode.c_str());
layout[checkY][checkX] = "``";
}
}
if (!block) {
//con.print("Not a block. Moving forward.\n");
break;
}
}
}
if (single) {
//con.print("Placing a building with code '%s' centered at (%d,%d) and default size %dx%d.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
coord32_t offsetCursor = cursor;
offsetCursor.x -= xOffset;
offsetCursor.y -= yOffset;
DFHack::Gui::setCursorCoords(offsetCursor.x, offsetCursor.y, offsetCursor.z);
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing building with code '%s' centered at (%d,%d).\n",curCode.c_str(),x,y);
}
DFHack::Gui::setCursorCoords(cursor.x, cursor.y, cursor.z);
} else if (block) {
//con.print("Placing a building with code '%s' with corner at (%d,%d) and default size %dx%d.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing building with code '%s' with corner at (%d,%d).\n",curCode.c_str(),x,y);
}
} else {
con.print("*** Found a code '%s' at (%d,%d) for a building with default size %dx%d with an invalid size designation.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
}
} else {
//buildingSize = findBuildingExtent(layout, x, y, -1, -1, out);
//con.print(" - The building has variable size %dx%d\n",buildingSize.x, buildingSize.y);
//con.print(" - The building has a variable size, which is not yet handled.\n");
}
} else {
//con.print("Building a(n) %s.\n",buildingInfo.name.c_str());
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing the %s at (%d,%d).\n",buildingInfo.name.c_str(),x,y);
}
}
}
}
cursor.x++;
DFHack::Gui::setCursorCoords(cursor.x, cursor.y, cursor.z);
}
cursor.y++;
cursor.x = startCursor.x;
}
DFHack::Gui::setCursorCoords(userCursor.x, userCursor.y, userCursor.z);
con.print("Done with file.\n");
} else {
con.print("You must supply a filename to read.\n");
}
return CR_OK;
}

@ -108,7 +108,7 @@ static bool close_hotkeys_screen()
return false;
Screen::dismiss(Core::getTopViewscreen());
for_each_(sorted_keys, [] (const string &sym)
for_each_(sorted_keys, [] (const string &sym)
{ Core::getInstance().ClearKeyBindings(sym + "@dfhack/viewscreen_hotkeys"); });
sorted_keys.clear();
return true;
@ -147,7 +147,7 @@ public:
hotkeys_column.clear();
int max_key_length = 0;
for_each_(sorted_keys, [&] (const string &sym)
for_each_(sorted_keys, [&] (const string &sym)
{ if (sym.length() > max_key_length) { max_key_length = sym.length(); } });
int padding = max_key_length + 2;
@ -200,7 +200,7 @@ public:
x += 3;
OutputHotkeyString(x, y, "Invoke", "Enter or Hotkey");
x += 3;
OutputToggleString(x, y, "Show Usage", "u", show_usage);
@ -255,7 +255,7 @@ public:
}
}
virtual std::string getFocusString()
virtual std::string getFocusString()
{
return "viewscreen_hotkeys";
}

@ -31,9 +31,9 @@ command_result infiniteSky (color_ostream &out, std::vector <std::string> & para
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand(
"infiniteSky",
"infiniteSky",
"Creates new sky levels on request, or as you construct up.",
infiniteSky, false,
infiniteSky, false,
"Usage:\n"
" infiniteSky\n"
" creates one more z-level\n"
@ -88,7 +88,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if ( mode.g_mode != df::enums::game_mode::DWARF )
return CR_OK;
}
if ( world->constructions.size() == constructionSize )
return CR_OK;
int32_t zNow = world->map.z_count_block;
@ -101,7 +101,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
///break;
}
constructionSize = world->constructions.size();
return CR_OK;
}
@ -152,7 +152,7 @@ void doInfiniteSky(color_ostream& out, int32_t howMany) {
delete[] world->map_extras.z_level_flags;
world->map_extras.z_level_flags = flags;
}
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)

@ -1 +1 @@
Subproject commit 07750ad7f7ce7c2506e5198ffb80ca50a73e9c4e
Subproject commit 85dcde97197bdde1c1e97ccb536f2cc4cab6818f

@ -130,39 +130,39 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
// CoreSuspender suspend;
// // Actually do something here. Yay.
// out.print("Doing a test...\n");
// MapExtras::MapCache MC;
// EmbarkTile test_tile;
// if(!gather_embark_tile(0,0, &test_tile, &MC))
// return CR_FAILURE;
// //test-write the file to check it.
// std::ofstream output_file("tile.p", std::ios_base::binary);
// output_file << test_tile.SerializeAsString();
// output_file.close();
// MapExtras::MapCache MC;
// EmbarkTile test_tile;
// if(!gather_embark_tile(0,0, &test_tile, &MC))
// return CR_FAILURE;
// //test-write the file to check it.
// std::ofstream output_file("tile.p", std::ios_base::binary);
// output_file << test_tile.SerializeAsString();
// output_file.close();
//
// //load it again to verify.
// std::ifstream input_file("tile.p", std::ios_base::binary);
// std::string input_string( (std::istreambuf_iterator<char>(input_file) ),
// //load it again to verify.
// std::ifstream input_file("tile.p", std::ios_base::binary);
// std::string input_string( (std::istreambuf_iterator<char>(input_file) ),
// (std::istreambuf_iterator<char>() ) );
// EmbarkTile verify_tile;
// verify_tile.ParseFromString(input_string);
// //write contents to text file.
// std::ofstream debug_text("tile.txt", std::ios_base::trunc);
// debug_text << "world coords:" << verify_tile.world_x()<< "," << verify_tile.world_y()<< "," << verify_tile.world_z() << std::endl;
// for(int i = 0; i < verify_tile.tile_layer_size(); i++) {
// debug_text << "layer: " << i << std::endl;
// for(int j = 0; j < 48; j++) {
// debug_text << " ";
// for(int k = 0; k < 48; k++) {
// debug_text << verify_tile.tile_layer(i).mat_type_table(j*48+k) << ",";
// }
// debug_text << " ";
// for(int k = 0; k < 48; k++) {
// debug_text << std::setw(3) << verify_tile.tile_layer(i).mat_subtype_table(j*48+k) << ",";
// }
// debug_text << std::endl;
// }
// debug_text << std::endl;
// }
// EmbarkTile verify_tile;
// verify_tile.ParseFromString(input_string);
// //write contents to text file.
// std::ofstream debug_text("tile.txt", std::ios_base::trunc);
// debug_text << "world coords:" << verify_tile.world_x()<< "," << verify_tile.world_y()<< "," << verify_tile.world_z() << std::endl;
// for(int i = 0; i < verify_tile.tile_layer_size(); i++) {
// debug_text << "layer: " << i << std::endl;
// for(int j = 0; j < 48; j++) {
// debug_text << " ";
// for(int k = 0; k < 48; k++) {
// debug_text << verify_tile.tile_layer(i).mat_type_table(j*48+k) << ",";
// }
// debug_text << " ";
// for(int k = 0; k < 48; k++) {
// debug_text << std::setw(3) << verify_tile.tile_layer(i).mat_subtype_table(j*48+k) << ",";
// }
// debug_text << std::endl;
// }
// debug_text << std::endl;
// }
// // Give control back to DF.
// return CR_OK;
//}
@ -197,12 +197,12 @@ static command_result GetEmbarkInfo(color_ostream &stream, const MapRequest *in,
out->set_available(false);
return CR_OK;
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
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;
}
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
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(*cur_year);
out->set_current_season(*cur_season);
@ -219,8 +219,8 @@ 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(world->map.region_x + (EmbX/3));
tile->set_world_y(world->map.region_y + (EmbY/3));
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);
@ -245,7 +245,7 @@ bool gather_embark_tile_layer(int EmbX, int EmbY, int EmbZ, EmbarkTileLayer * ti
int num_valid_blocks = 0;
for(int yy = 0; yy < 3; yy++) {
for(int xx = 0; xx < 3; xx++) {
DFCoord current_coord, upper_coord;
DFCoord current_coord, upper_coord;
current_coord.x = EmbX+xx;
current_coord.y = EmbY+yy;
current_coord.z = EmbZ;
@ -283,7 +283,7 @@ bool gather_embark_tile_layer(int EmbX, int EmbY, int EmbZ, EmbarkTileLayer * ti
num_valid_blocks++;
}
else if(designation.bits.flow_size && (tileShapeBasic(tileShape(upper_tile)) != tiletype_shape_basic::Floor)) { //Contains either water or lava.
tile->set_mat_type_table(array_index, BasicMaterial::LIQUID);
tile->set_mat_type_table(array_index, BasicMaterial::LIQUID);
if(designation.bits.liquid_type) //Magma
tile->set_mat_subtype_table(array_index, LiquidType::MAGMA);
else //water
@ -291,29 +291,29 @@ bool gather_embark_tile_layer(int EmbX, int EmbY, int EmbZ, EmbarkTileLayer * ti
num_valid_blocks++;
}
else if(((tileShapeBasic(tileShape(tile_type)) != tiletype_shape_basic::Open) ||
(tileShapeBasic(tileShape(upper_tile)) == tiletype_shape_basic::Floor)) &&
((tileShapeBasic(tileShape(tile_type)) != tiletype_shape_basic::Floor) ||
(tileShapeBasic(tileShape(upper_tile)) == tiletype_shape_basic::Floor)) &&
((tileShapeBasic(tileShape(tile_type)) != tiletype_shape_basic::Floor) ||
(tileShapeBasic(tileShape(upper_tile)) == tiletype_shape_basic::Floor))) { //if the upper tile is a floor, we don't skip, otherwise we do.
if(actual_mat.mat_type == builtin_mats::INORGANIC) { //inorganic
tile->set_mat_type_table(array_index, BasicMaterial::INORGANIC);
tile->set_mat_type_table(array_index, BasicMaterial::INORGANIC);
tile->set_mat_subtype_table(array_index, actual_mat.mat_index);
}
else if(actual_mat.mat_type == 419) { //Growing plants
tile->set_mat_type_table(array_index, BasicMaterial::PLANT);
tile->set_mat_type_table(array_index, BasicMaterial::PLANT);
tile->set_mat_subtype_table(array_index, actual_mat.mat_index);
}
else if(actual_mat.mat_type >= 420) { //Wooden constructions. Different from growing plants.
tile->set_mat_type_table(array_index, BasicMaterial::WOOD);
tile->set_mat_type_table(array_index, BasicMaterial::WOOD);
tile->set_mat_subtype_table(array_index, actual_mat.mat_index);
}
else { //Unknown and unsupported stuff. Will just be drawn as grey.
tile->set_mat_type_table(array_index, BasicMaterial::OTHER);
tile->set_mat_type_table(array_index, BasicMaterial::OTHER);
tile->set_mat_subtype_table(array_index, actual_mat.mat_type);
}
num_valid_blocks++;
}
else {
tile->set_mat_type_table(array_index, BasicMaterial::AIR);
tile->set_mat_type_table(array_index, BasicMaterial::AIR);
}
}
}
@ -344,12 +344,12 @@ static command_result GetRawNames(color_ostream &stream, const MapRequest *in, R
out->set_available(false);
return CR_OK;
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
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;
}
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
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 < world->raws.inorganics.size(); i++){
out->add_inorganic(world->raws.inorganics[i]->id);

@ -611,7 +611,7 @@ command_result df_liquids_execute(color_ostream &out, OperationMode &cur_mode, d
case M_KEEP:
{
auto bflags = (*biter)->BlockFlags();
out << "flow bit 1 = " << bflags.bits.update_liquid << endl;
out << "flow bit 1 = " << bflags.bits.update_liquid << endl;
out << "flow bit 2 = " << bflags.bits.update_liquid_twice << endl;
}
}

@ -1,24 +1,24 @@
local _ENV = mkmodule('plugins.building-hacks')
--[[
from native:
addBuilding(custom type,impassible fix (bool), consumed power, produced power, list of connection points,
update skip(0/nil to disable),table of frames,frame to tick ratio (-1 for machine control))
from here:
registerBuilding{
name -- custom workshop id e.g. SOAPMAKER << required!
fix_impassible -- make impassible tiles impassible to liquids too
consume -- how much machine power is needed to work
produce -- how much machine power is produced
gears -- a table or {x=?,y=?} of connection points for machines
action -- a table of number (how much ticks to skip) and a function which gets called on shop update
animate -- a table of
frames -- a table of
tables of 4 numbers (tile,fore,back,bright) OR
empty table (tile not modified) OR
from native:
addBuilding(custom type,impassible fix (bool), consumed power, produced power, list of connection points,
update skip(0/nil to disable),table of frames,frame to tick ratio (-1 for machine control))
from here:
registerBuilding{
name -- custom workshop id e.g. SOAPMAKER << required!
fix_impassible -- make impassible tiles impassible to liquids too
consume -- how much machine power is needed to work
produce -- how much machine power is produced
gears -- a table or {x=?,y=?} of connection points for machines
action -- a table of number (how much ticks to skip) and a function which gets called on shop update
animate -- a table of
frames -- a table of
tables of 4 numbers (tile,fore,back,bright) OR
empty table (tile not modified) OR
{x=<number> y=<number> + 4 numbers like in first case} -- this generates full frame even, usefull for animations that change little (1-2 tiles)
frameLenght -- how many ticks does one frame take OR
isMechanical -- a bool that says to try to match to mechanical system (i.e. how gears are turning)
}
frameLenght -- how many ticks does one frame take OR
isMechanical -- a bool that says to try to match to mechanical system (i.e. how gears are turning)
}
]]
_registeredStuff={}
local function unregall(state)
@ -29,23 +29,23 @@ local function unregall(state)
end
end
local function onUpdateLocal(workshop)
local f=_registeredStuff[workshop:getCustomType()]
if f then
f(workshop)
end
local f=_registeredStuff[workshop:getCustomType()]
if f then
f(workshop)
end
end
local function findCustomWorkshop(name)
local raws=df.global.world.raws.buildings.all
for k,v in ipairs(raws) do
if v.code==name then
return v
end
end
local raws=df.global.world.raws.buildings.all
for k,v in ipairs(raws) do
if v.code==name then
return v
end
end
end
local function registerUpdateAction(shopId,callback)
_registeredStuff[shopId]=callback
onUpdateAction._library=onUpdateLocal
dfhack.onStateChange.building_hacks=unregall
_registeredStuff[shopId]=callback
onUpdateAction._library=onUpdateLocal
dfhack.onStateChange.building_hacks=unregall
end
local function generateFrame(tiles,w,h)
local mTiles={}
@ -66,7 +66,7 @@ local function generateFrame(tiles,w,h)
return ret
end
local function processFrames(shop_def,frames)
local w,h=shop_def.dim_x,shop_def.dim_y
local w,h=shop_def.dim_x,shop_def.dim_y
for frame_id,frame in ipairs(frames) do
if frame[1].x~=nil then
frames[frame_id]=generateFrame(frame,w,h)
@ -75,35 +75,35 @@ local function processFrames(shop_def,frames)
return frames
end
function registerBuilding(args)
local shop_def=findCustomWorkshop(args.name)
local shop_id=shop_def.id
local fix_impassible
if args.fix_impassible then
fix_impassible=1
else
fix_impassible=0
end
local consume=args.consume or 0
local produce=args.produce or 0
local gears=args.gears or {}
local action=args.action --could be nil
local updateSkip=0
if action~=nil then
updateSkip=action[1]
registerUpdateAction(shop_id,action[2])
end
local animate=args.animate
local frameLength=1
local frames
if animate~=nil then
frameLength=animate.frameLength
if animate.isMechanical then
frameLength=-1
end
frames=processFrames(shop_def,animate.frames)
end
local roomSubset=args.canBeRoomSubset or -1
addBuilding(shop_id,fix_impassible,consume,produce,gears,updateSkip,frames,frameLength,roomSubset)
local shop_def=findCustomWorkshop(args.name)
local shop_id=shop_def.id
local fix_impassible
if args.fix_impassible then
fix_impassible=1
else
fix_impassible=0
end
local consume=args.consume or 0
local produce=args.produce or 0
local gears=args.gears or {}
local action=args.action --could be nil
local updateSkip=0
if action~=nil then
updateSkip=action[1]
registerUpdateAction(shop_id,action[2])
end
local animate=args.animate
local frameLength=1
local frames
if animate~=nil then
frameLength=animate.frameLength
if animate.isMechanical then
frameLength=-1
end
frames=processFrames(shop_def,animate.frames)
end
local roomSubset=args.canBeRoomSubset or -1
addBuilding(shop_id,fix_impassible,consume,produce,gears,updateSkip,frames,frameLength,roomSubset)
end
return _ENV

@ -54,7 +54,7 @@ function BinaryPatch:apply()
if not self:test() then
error(string.format("pre-data for binary patch does not match expected"))
end
local post_buf=df.new('uint8_t',#self.pre_data)
for k,v in ipairs(self.pre_data) do
if self.data[k]==nil then
@ -83,7 +83,7 @@ function BinaryPatch:remove(delete)
error("can't remove BinaryPatch, not applied.")
end
local arr=ms.CheckedArray.new('uint8_t',self.address,self.address+#self.pre_data)
local post_buf=df.new('uint8_t',#self.pre_data)
for k,v in pairs(self.pre_data) do
post_buf[k-1]=v
@ -112,7 +112,7 @@ plugins=plugins or {}
BinaryPlugin=defclass(BinaryPlugin)
BinaryPlugin.ATTRS {filename=DEFAULT_NIL,reloc_table={},name=DEFAULT_NIL}
function BinaryPlugin:init(args)
end
function BinaryPlugin:postinit(args)
if self.name==nil then error("Not a valid plugin name!") end
@ -211,26 +211,26 @@ function SimpleMenu:init(args)
self.items={}
end
function SimpleMenu:add(name,entry,hints)
table.insert(self.items,{entry,name,hints})
table.insert(self.items,{entry,name,hints})
end
function SimpleMenu:display()
print("Select choice (q exits):")
for p,c in pairs(self.items) do
print(string.format("%3d).%s",p,c[2]))
end
local ans
repeat
local r
r=dfhack.lineedit()
if r==nil then return end
if r=='q' then return end
ans=tonumber(r)
if ans==nil or not(ans<=#self.items and ans>0) then
print("Invalid choice.")
end
until ans~=nil and (ans<=#self.items and ans>0)
print("Select choice (q exits):")
for p,c in pairs(self.items) do
print(string.format("%3d).%s",p,c[2]))
end
local ans
repeat
local r
r=dfhack.lineedit()
if r==nil then return end
if r=='q' then return end
ans=tonumber(r)
if ans==nil or not(ans<=#self.items and ans>0) then
print("Invalid choice.")
end
until ans~=nil and (ans<=#self.items and ans>0)
if type(self.items[ans][1])=="function" then
self.items[ans][1]()
else

@ -3,99 +3,99 @@ local dfu=require("plugins.dfusion")
local tools=require("plugins.dfusion.tools")
menu=dfu.SimpleMenu()
function Reincarnate(trg_unit,swap_soul) --only for adventurer i guess
if swap_soul==nil then
swap_soul=true
end
local adv=trg_unit or df.global.world.units.active[0]
if adv.flags1.dead==false then
qerror("You are not dead (yet)!")
end
local hist_fig=dfhack.units.getNemesis(adv).figure
if hist_fig==nil then
qerror("No historical figure for adventurer...")
end
local events=df.global.world.history.events
local trg_hist_fig
for i=#events-1,0,-1 do -- reverse search because almost always it will be last entry
if df.history_event_hist_figure_diedst:is_instance(events[i]) then
--print("is instance:"..i)
if events[i].victim_hf==hist_fig.id then
--print("Is same id:"..i)
trg_hist_fig=events[i].slayer_hf
if trg_hist_fig then
trg_hist_fig=df.historical_figure.find(trg_hist_fig)
end
break
end
end
end
if trg_hist_fig ==nil then
qerror("Slayer not found")
end
local trg_unit=trg_hist_fig.unit_id
if trg_unit==nil then
qerror("Unit id not found!")
end
local trg_unit_final=df.unit.find(trg_unit)
change_adv(trg_unit_final)
if swap_soul then --actually add a soul...
t_soul=adv.status.current_soul
adv.status.current_soul=df.NULL
adv.status.souls:resize(0)
trg_unit_final.status.current_soul=t_soul
trg_unit_final.status.souls:insert(#trg_unit_final.status.souls,t_soul)
end
if swap_soul==nil then
swap_soul=true
end
local adv=trg_unit or df.global.world.units.active[0]
if adv.flags1.dead==false then
qerror("You are not dead (yet)!")
end
local hist_fig=dfhack.units.getNemesis(adv).figure
if hist_fig==nil then
qerror("No historical figure for adventurer...")
end
local events=df.global.world.history.events
local trg_hist_fig
for i=#events-1,0,-1 do -- reverse search because almost always it will be last entry
if df.history_event_hist_figure_diedst:is_instance(events[i]) then
--print("is instance:"..i)
if events[i].victim_hf==hist_fig.id then
--print("Is same id:"..i)
trg_hist_fig=events[i].slayer_hf
if trg_hist_fig then
trg_hist_fig=df.historical_figure.find(trg_hist_fig)
end
break
end
end
end
if trg_hist_fig ==nil then
qerror("Slayer not found")
end
local trg_unit=trg_hist_fig.unit_id
if trg_unit==nil then
qerror("Unit id not found!")
end
local trg_unit_final=df.unit.find(trg_unit)
change_adv(trg_unit_final)
if swap_soul then --actually add a soul...
t_soul=adv.status.current_soul
adv.status.current_soul=df.NULL
adv.status.souls:resize(0)
trg_unit_final.status.current_soul=t_soul
trg_unit_final.status.souls:insert(#trg_unit_final.status.souls,t_soul)
end
end
menu:add("Reincarnate",Reincarnate,{{df.unit,"optional"}})-- bool, optional
function change_adv(unit,nemesis)
if nemesis==nil then
nemesis=true --default value is nemesis switch too.
end
if unit==nil then
unit=dfhack.gui.getSelectedUnit()--getCreatureAtPointer()
end
if unit==nil then
error("Invalid unit!")
end
local other=df.global.world.units.active
local unit_indx
for k,v in pairs(other) do
if v==unit then
unit_indx=k
break
end
end
if unit_indx==nil then
error("Unit not found in array?!") --should not happen
end
other[unit_indx]=other[0]
other[0]=unit
if nemesis then --basicly copied from advtools plugin...
local nem=dfhack.units.getNemesis(unit)
local other_nem=dfhack.units.getNemesis(other[unit_indx])
if other_nem then
other_nem.flags[0]=false
other_nem.flags[1]=true
end
if nem then
nem.flags[0]=true
nem.flags[2]=true
for k,v in pairs(df.global.world.nemesis.all) do
if v.id==nem.id then
df.global.ui_advmode.player_id=k
end
end
else
qerror("Current unit does not have nemesis record, further working not guaranteed")
end
end
if nemesis==nil then
nemesis=true --default value is nemesis switch too.
end
if unit==nil then
unit=dfhack.gui.getSelectedUnit()--getCreatureAtPointer()
end
if unit==nil then
error("Invalid unit!")
end
local other=df.global.world.units.active
local unit_indx
for k,v in pairs(other) do
if v==unit then
unit_indx=k
break
end
end
if unit_indx==nil then
error("Unit not found in array?!") --should not happen
end
other[unit_indx]=other[0]
other[0]=unit
if nemesis then --basicly copied from advtools plugin...
local nem=dfhack.units.getNemesis(unit)
local other_nem=dfhack.units.getNemesis(other[unit_indx])
if other_nem then
other_nem.flags[0]=false
other_nem.flags[1]=true
end
if nem then
nem.flags[0]=true
nem.flags[2]=true
for k,v in pairs(df.global.world.nemesis.all) do
if v.id==nem.id then
df.global.ui_advmode.player_id=k
end
end
else
qerror("Current unit does not have nemesis record, further working not guaranteed")
end
end
end
menu:add("Change adventurer",change_adv)
function log_pos()
local adv=df.global.world.units.active[0]
local wmap=df.global.world.map
local sub_pos={x=adv.pos.x,y=adv.pos.y,z=adv.pos.z}
local region_pos={x=wmap.region_x,y=wmap.region_y,z=wmap.region_z}

@ -14,7 +14,7 @@ if myos=="windows" then
error("caste and race count must be less then "..MAX_RACES)
end
local n_to_id=require("plugins.dfusion.tools").build_race_names()
local ids={}
for k,v in pairs(races) do
local race=v[1] or v
@ -30,7 +30,7 @@ if myos=="windows" then
if race_caste_data~=nil then
self:parseRaces(race_caste_data)
end
if stoff==nil then
error("address for start_dwarf_count not found!")
end
@ -41,8 +41,8 @@ if myos=="windows" then
for k,v in ipairs(tmp_table) do
table.insert(needle,v)
end
local mem=ms.get_code_segment()
local mem=ms.get_code_segment()
print(mem.uint8_t:addr2idx(stoff))
print(mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff)))
local _,trg_offset=mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff),nil)--maybe endoff=stoff+bignumber
@ -58,31 +58,31 @@ if myos=="windows" then
if caste_offset==nil or caste_offset-stoff>1000 then
error("Caste change code not found or found too far!")
end
self.disable_castes=self.disable_castes or dfu.BinaryPatch{pre_data={0x83,0xc8,0xff},data={0x90,0x90,0x90},address=caste_offset,name="custom_embark_caste_disable"}
self.disable_castes:apply()
self:setEmbarkParty(self.race_caste_data)
local caste_array=self:get_or_alloc("caste_array","uint16_t",MAX_RACES)
local race_array=self:get_or_alloc("race_array","uint16_t",MAX_RACES)
local race_array_off,caste_array_off
local _
_,race_array_off=df.sizeof(race_array)
_,caste_array_off=df.sizeof(caste_array)
self:set_marker_dword("race",caste_array_off) --hehe... mixed them up i guess...
self:set_marker_dword("caste",race_array_off)
self:move_to_df()
self.call_patch:apply()
self.installed=true
end
function CustomEmbark:setEmbarkParty(racesAndCastes)
local stoff=dfhack.internal.getAddress('start_dwarf_count')
if self.dwarfcount== nil then
self.dwarfcount=dfu.BinaryPatch{pre_data=dfu.dwordToTable(7),data=dfu.dwordToTable(#self.race_caste_data),address=stoff,name="custom_embark_embarkcount"}
self.dwarfcount:apply()
@ -91,7 +91,7 @@ if myos=="windows" then
end
local caste_array=self:get_or_alloc("caste_array","uint16_t",MAX_RACES)
local race_array=self:get_or_alloc("race_array","uint16_t",MAX_RACES)
for k,v in ipairs(self.race_caste_data) do
caste_array[k-1]=v[2] or -1
race_array[k-1]=v[1]

@ -13,7 +13,7 @@ function FriendshipRainbow:findall_needles(codesg,needle) -- todo move to memsca
local cidx,caddr=codesg.uint8_t:find(needle)
local ret={}
while cidx~=nil do
table.insert(ret,{cidx,caddr})
table.insert(ret,{cidx,caddr})
cidx,caddr=codesg.uint8_t:find(needle,cidx+1)
end
return ret
@ -23,10 +23,10 @@ function FriendshipRainbow:find_one(codesg,needle,crace)
return self:findall_needles(codesg,needle)
end
function FriendshipRainbow:find_all()
local code=ms.get_code_segment()
local code=ms.get_code_segment()
local locations={}
local _,crace=df.sizeof(df.global.ui:_field("race_id"))
dfu.concatTables(locations,self:find_one(code,{0x66,0xa1},crace)) --mov ax,[ptr]
dfu.concatTables(locations,self:find_one(code,{0xa1},crace)) --mov ax,[ptr]
local registers=
@ -40,11 +40,11 @@ function FriendshipRainbow:find_all()
--0x2d, --ebp not used?
}
for k,reg in ipairs(registers) do
dfu.concatTables(locations,self:find_one(code,{0x0f,0xbf,reg},crace)) --movsx reg,[ptr]
dfu.concatTables(locations,self:find_one(code,{0x66,0x8b,reg},crace)) --mov reg,[ptr]
end
return self:filter_locations(code,locations)
end
function FriendshipRainbow:filter_locations(codesg,locations)
@ -57,7 +57,7 @@ function FriendshipRainbow:filter_locations(codesg,locations)
0xb8,0xbb,0xb9,0xba,0xbe,0xbf}
for _,entry in ipairs(locations) do
for _,r in ipairs(registers) do
local idx,addr=codesg.uint8_t:find({0x39,r,0x8c,0x00,0x00,0x00},
codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST)
if addr then
@ -90,7 +90,7 @@ function FriendshipRainbow:set_races(arr)
local n_to_id=require("plugins.dfusion.tools").build_race_names()
local ids={}
for k,v in ipairs(self.race_data) do -- to check if all races are valid.
ids[k]=n_to_id[v]
ids[k]=n_to_id[v]
end
for k,v in ipairs(ids) do
arr[k-1]=ids[k]

@ -19,205 +19,205 @@ function build_race_names()
return RaceNames
end
end
function setrace(name)
local RaceTable=build_race_names()
print("Your current race is:"..df.global.world.raws.creatures.all[df.global.ui.race_id].creature_id)
local id
if name == nil then
print("Type new race's token name in full caps (q to quit):")
repeat
local entry=dfhack.lineedit()
if entry=="q" then
return
end
id=RaceTable[entry]
until id~=nil
else
id=RaceTable[name]
if id==nil then
error("Name not found!")
end
end
df.global.ui.race_id=id
function setrace(name)
local RaceTable=build_race_names()
print("Your current race is:"..df.global.world.raws.creatures.all[df.global.ui.race_id].creature_id)
local id
if name == nil then
print("Type new race's token name in full caps (q to quit):")
repeat
local entry=dfhack.lineedit()
if entry=="q" then
return
end
id=RaceTable[entry]
until id~=nil
else
id=RaceTable[name]
if id==nil then
error("Name not found!")
end
end
df.global.ui.race_id=id
end
menu:add("Set current race",setrace)
function GiveSentience(names)
local RaceTable=build_race_names() --slow.If loaded don't load again
function GiveSentience(names)
local RaceTable=build_race_names() --slow.If loaded don't load again
local id,ids
if names ==nil then
ids={}
print("Type race's token name in full caps to give sentience to:")
repeat
id=dfhack.lineedit()
id=RaceTable[entry]
if names ==nil then
ids={}
print("Type race's token name in full caps to give sentience to:")
repeat
id=dfhack.lineedit()
id=RaceTable[entry]
if id~=nil then
table.insert(ids,id)
end
until id==nil
else
ids={}
for _,name in pairs(names) do
id=RaceTable[name]
table.insert(ids,id)
end
end
for _,id in pairs(ids) do
local races=df.global.world.raws.creatures.all
until id==nil
local castes=races[id].caste
print(string.format("Caste count:%i",#castes))
for i =0,#castes-1 do
print("Caste name:"..castes[i].caste_id.."...")
local flags=castes[i].flags
--print(string.format("%x",flagoffset))
if flags.CAN_SPEAK then
print("\tis sentient.")
else
print("\tnon sentient. Allocating IQ...")
flags.CAN_SPEAK=true
end
end
end
else
ids={}
for _,name in pairs(names) do
id=RaceTable[name]
table.insert(ids,id)
end
end
for _,id in pairs(ids) do
local races=df.global.world.raws.creatures.all
local castes=races[id].caste
print(string.format("Caste count:%i",#castes))
for i =0,#castes-1 do
print("Caste name:"..castes[i].caste_id.."...")
local flags=castes[i].flags
--print(string.format("%x",flagoffset))
if flags.CAN_SPEAK then
print("\tis sentient.")
else
print("\tnon sentient. Allocating IQ...")
flags.CAN_SPEAK=true
end
end
end
end
menu:add("Give Sentience",GiveSentience)
function MakeFollow(unit,trgunit)
if unit == nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit== nil then
error("Invalid creature")
end
if trgunit==nil then
trgunit=df.global.world.units.active[0]
end
unit.relations.group_leader_id=trgunit.id
local u_nem=dfhack.units.getNemesis(unit)
local t_nem=dfhack.units.getNemesis(trgunit)
if u_nem then
u_nem.group_leader_id=t_nem.id
end
if t_nem and u_nem then
t_nem.companions:insert(#t_nem.companions,u_nem.id)
end
if unit == nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit== nil then
error("Invalid creature")
end
if trgunit==nil then
trgunit=df.global.world.units.active[0]
end
unit.relations.group_leader_id=trgunit.id
local u_nem=dfhack.units.getNemesis(unit)
local t_nem=dfhack.units.getNemesis(trgunit)
if u_nem then
u_nem.group_leader_id=t_nem.id
end
if t_nem and u_nem then
t_nem.companions:insert(#t_nem.companions,u_nem.id)
end
end
menu:add("Make creature follow",MakeFollow)
function project(unit,trg) --TODO add to menu?
if unit==nil then
unit=getCreatureAtPointer()
end
if unit==nil then
error("Failed to project unit. Unit not selected/valid")
end
-- todo: add projectile to world, point to unit, add flag to unit, add gen-ref to projectile.
local p=df.proj_unitst:new()
local startpos={x=unit.pos.x,y=unit.pos.y,z=unit.pos.z}
p.origin_pos=startpos
p.target_pos=trg
p.cur_pos=startpos
p.prev_pos=startpos
p.unit=unit
--- wtf stuff
p.unk14=100
p.unk16=-1
p.unk23=-1
p.fall_delay=5
p.fall_counter=5
p.collided=true
-- end wtf
local citem=df.global.world.proj_list
local maxid=1
local newlink=df.proj_list_link:new()
newlink.item=p
while citem.item~= nil do
if citem.item.id>maxid then maxid=citem.item.id end
if citem.next ~= nil then
citem=citem.next
else
break
end
end
p.id=maxid+1
newlink.prev=citem
citem.next=newlink
local proj_ref=df.general_ref_projectile:new()
proj_ref.projectile_id=p.id
unit.general_refs:insert(#unit.general_refs,proj_ref)
unit.flags1.projectile=true
if unit==nil then
unit=getCreatureAtPointer()
end
if unit==nil then
error("Failed to project unit. Unit not selected/valid")
end
-- todo: add projectile to world, point to unit, add flag to unit, add gen-ref to projectile.
local p=df.proj_unitst:new()
local startpos={x=unit.pos.x,y=unit.pos.y,z=unit.pos.z}
p.origin_pos=startpos
p.target_pos=trg
p.cur_pos=startpos
p.prev_pos=startpos
p.unit=unit
--- wtf stuff
p.unk14=100
p.unk16=-1
p.unk23=-1
p.fall_delay=5
p.fall_counter=5
p.collided=true
-- end wtf
local citem=df.global.world.proj_list
local maxid=1
local newlink=df.proj_list_link:new()
newlink.item=p
while citem.item~= nil do
if citem.item.id>maxid then maxid=citem.item.id end
if citem.next ~= nil then
citem=citem.next
else
break
end
end
p.id=maxid+1
newlink.prev=citem
citem.next=newlink
local proj_ref=df.general_ref_projectile:new()
proj_ref.projectile_id=p.id
unit.general_refs:insert(#unit.general_refs,proj_ref)
unit.flags1.projectile=true
end
function empregnate(unit)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to empregnate. Unit not selected/valid")
end
if unit.curse then
unit.curse.add_tags2.STERILE=false
end
local genes = unit.appearance.genes
if unit.relations.pregnancy_genes == nil then
print("creating preg ptr.")
if false then
print(string.format("%x %x",df.sizeof(unit.relations:_field("pregnancy_genes"))))
return
end
unit.relations.pregnancy_genes = { new = true, assign = genes }
end
local ngenes = unit.relations.pregnancy_genes
if #ngenes.appearance ~= #genes.appearance or #ngenes.colors ~= #genes.colors then
print("Array sizes incorrect, fixing.")
ngenes:assign(genes);
end
print("Setting preg timer.")
unit.relations.pregnancy_timer=10
unit.relations.pregnancy_caste=1
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to empregnate. Unit not selected/valid")
end
if unit.curse then
unit.curse.add_tags2.STERILE=false
end
local genes = unit.appearance.genes
if unit.relations.pregnancy_genes == nil then
print("creating preg ptr.")
if false then
print(string.format("%x %x",df.sizeof(unit.relations:_field("pregnancy_genes"))))
return
end
unit.relations.pregnancy_genes = { new = true, assign = genes }
end
local ngenes = unit.relations.pregnancy_genes
if #ngenes.appearance ~= #genes.appearance or #ngenes.colors ~= #genes.colors then
print("Array sizes incorrect, fixing.")
ngenes:assign(genes);
end
print("Setting preg timer.")
unit.relations.pregnancy_timer=10
unit.relations.pregnancy_caste=1
end
menu:add("Empregnate",empregnate)
function healunit(unit)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to Heal unit. Unit not selected/valid")
end
if unit==nil then
error("Failed to Heal unit. Unit not selected/valid")
end
unit.body.wounds:resize(0) -- memory leak here :/
unit.body.blood_count=unit.body.blood_max
--set flags for standing and grasping...
unit.status2.limbs_stand_max=4
unit.status2.limbs_stand_count=4
unit.status2.limbs_grasp_max=4
unit.status2.limbs_grasp_count=4
--should also set temperatures, and flags for breath etc...
unit.flags1.dead=false
unit.flags2.calculated_bodyparts=false
unit.flags2.calculated_nerves=false
unit.flags2.circulatory_spray=false
unit.flags2.vision_good=true
unit.flags2.vision_damaged=false
unit.flags2.vision_missing=false
unit.counters.winded=0
unit.counters.unconscious=0
for k,v in pairs(unit.body.components) do
for kk,vv in pairs(v) do
if k == 'body_part_status' then v[kk].whole = 0 else v[kk] = 0 end
end
end
unit.body.blood_count=unit.body.blood_max
--set flags for standing and grasping...
unit.status2.limbs_stand_max=4
unit.status2.limbs_stand_count=4
unit.status2.limbs_grasp_max=4
unit.status2.limbs_grasp_count=4
--should also set temperatures, and flags for breath etc...
unit.flags1.dead=false
unit.flags2.calculated_bodyparts=false
unit.flags2.calculated_nerves=false
unit.flags2.circulatory_spray=false
unit.flags2.vision_good=true
unit.flags2.vision_damaged=false
unit.flags2.vision_missing=false
unit.counters.winded=0
unit.counters.unconscious=0
for k,v in pairs(unit.body.components) do
for kk,vv in pairs(v) do
if k == 'body_part_status' then v[kk].whole = 0 else v[kk] = 0 end
end
end
end
menu:add("Heal unit",healunit)
function powerup(unit,labor_rating,military_rating,skills)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to power up unit. Unit not selected/valid")
end
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to power up unit. Unit not selected/valid")
end
if unit.status.current_soul== nil then
error("Failed to power up unit. Unit has no soul")
end
@ -237,7 +237,7 @@ function powerup(unit,labor_rating,military_rating,skills)
end
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = sv, rating = new_rating, experience = (new_rating * 500) + (new_rating * (new_rating - 1)) * 50}, 'id')
end
end
menu:add("Power up",powerup)
return _ENV

@ -1,7 +1,7 @@
local _ENV = mkmodule('plugins.eventful')
--[[
--]]
local function getShopName(btype,bsubtype,bcustom)
local typenames_shop={[df.workshop_type.Carpenters]="CARPENTERS",[df.workshop_type.Farmers]="FARMERS",
@ -22,13 +22,13 @@ local function getShopName(btype,bsubtype,bcustom)
[df.furnace_type.MagmaGlassFurnace]="MAGMA_GLASS_FURNACE",[df.furnace_type.MagmaKiln]="MAGMA_KILN",
[df.furnace_type.Kiln]="KILN"}
if btype==df.building_type.Workshop then
if typenames_shop[bsubtype]~=nil then
if typenames_shop[bsubtype]~=nil then
return typenames_shop[bsubtype]
else
return df.building_def_workshopst.find(bcustom).code
end
elseif btype==df.building_type.Furnace then
if typenames_furnace[bsubtype]~=nil then
if typenames_furnace[bsubtype]~=nil then
return typenames_furnace[bsubtype]
else
return df.building_def_furnacest.find(bcustom).code

@ -62,7 +62,7 @@ function list_orders()
print("Stockpile #"..num, name, trigger)
listed = true
end
if not listed then
print("No manager jobs have been set for your stockpiles.")
print("Use j in a stockpile menu to create one...")
@ -79,7 +79,7 @@ function start_bookkeeping()
result[reaction_id] = amount
end
end
jobs_to_create = result
end
@ -89,7 +89,7 @@ function finish_bookkeeping()
for reaction, amount in pairs(jobs_to_create) do
create_orders(reaction_list[reaction].order, amount)
end
jobs_to_create = {}
end
@ -98,7 +98,7 @@ function stockpile_settings(sp)
if not order then
return "No job selected", ""
end
return order.entry.value, trigger_name(order)
end
@ -138,7 +138,7 @@ function collect_orders()
end
end
end
return result
end
@ -158,12 +158,12 @@ function reaction_entry(job_type, values, name)
mat_type = -1,
mat_index = -1,
}
if values then
-- Override default attributes.
order:assign(values)
end
return {
name = name or df.job_type.attrs[job_type].caption,
order = order,
@ -175,20 +175,20 @@ function resource_reactions(reactions, job_type, mat_info, keys, items, options)
for key, value in pairs(mat_info.management) do
values[key] = value
end
for _, itemid in ipairs(keys) do
local itemdef = items[itemid]
local start = options.verb or mat_info.verb or "Make"
if options.adjective then
start = start.." "..itemdef.adjective
end
if (not options.permissible) or options.permissible(itemdef) then
local item_name = " "..itemdef[options.name_field or "name"]
if options.capitalize then
item_name = string.gsub(item_name, " .", string.upper)
end
values.item_subtype = itemid
table.insert(reactions, reaction_entry(job_type, values, start.." "..mat_info.adjective..item_name))
end
@ -202,7 +202,7 @@ function material_reactions(reactions, itemtypes, mat_info)
if row[3] then
line = line.." "..row[3]
end
table.insert(reactions, reaction_entry(row[1], mat_info.management, line))
end
end
@ -225,38 +225,38 @@ function collect_reactions()
-- but I currently can only find it while the job selection screen is active.
-- 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",
management = {mat_type = 0},
},
}
for _, name in ipairs{"wood", "cloth", "leather", "silk", "yarn", "bone", "shell", "tooth", "horn", "pearl"} do
materials[name] = {
adjective = name,
management = {material_category = {[name] = true}},
}
end
materials.wood.adjective = "wooden"
materials.tooth.adjective = "ivory/tooth"
materials.leather.clothing_flag = "LEATHER"
-- Collection and Entrapment
table.insert(result, reaction_entry(job_types.CollectWebs))
table.insert(result, reaction_entry(job_types.CollectSand))
table.insert(result, reaction_entry(job_types.CollectClay))
table.insert(result, reaction_entry(job_types.CatchLiveLandAnimal))
table.insert(result, reaction_entry(job_types.CatchLiveFish))
-- Cutting, encrusting, and metal extraction.
local rock_types = df.global.world.raws.inorganics
for rock_id = #rock_types-1, 0, -1 do
@ -267,35 +267,35 @@ function collect_reactions()
mat_type = 0,
mat_index = rock_id,
}, "Cut "..rock_name))
table.insert(result, reaction_entry(job_types.EncrustWithGems, {
mat_type = 0,
mat_index = rock_id,
item_category = {finished_goods = true},
}, "Encrust Finished Goods With "..rock_name))
table.insert(result, reaction_entry(job_types.EncrustWithGems, {
mat_type = 0,
mat_index = rock_id,
item_category = {furniture = true},
}, "Encrust Furniture With "..rock_name))
table.insert(result, reaction_entry(job_types.EncrustWithGems, {
mat_type = 0,
mat_index = rock_id,
item_category = {ammo = true},
}, "Encrust Ammo With "..rock_name))
end
if #rock_types[rock_id].metal_ore.mat_index > 0 then
table.insert(result, reaction_entry(job_types.SmeltOre, {mat_type = 0, mat_index = rock_id}, "Smelt "..rock_name.." Ore"))
end
if #rock_types[rock_id].thread_metal.mat_index > 0 then
table.insert(result, reaction_entry(job_types.ExtractMetalStrands, {mat_type = 0, mat_index = rock_id}))
end
end
-- Glass cutting and encrusting, with different job numbers.
-- We could search the entire table, but glass is less subject to raws.
local glass_types = df.global.world.raws.mat_table.builtin
@ -309,61 +309,61 @@ function collect_reactions()
adjective = glass_name,
management = {mat_type = glass_id},
})
table.insert(result, reaction_entry(job_types.CutGlass, {mat_type = glass_id}, "Cut "..glass_name))
table.insert(result, reaction_entry(job_types.EncrustWithGlass, {
mat_type = glass_id,
item_category = {finished_goods = true},
}, "Encrust Finished Goods With "..glass_name))
table.insert(result, reaction_entry(job_types.EncrustWithGlass, {
mat_type = glass_id,
item_category = {furniture = true},
}, "Encrust Furniture With "..glass_name))
table.insert(result, reaction_entry(job_types.EncrustWithGlass, {
mat_type = glass_id,
item_category = {ammo = true},
}, "Encrust Ammo With "..glass_name))
end
end
-- Dyeing
table.insert(result, reaction_entry(job_types.DyeThread))
table.insert(result, reaction_entry(job_types.DyeCloth))
-- Sew Image
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
for _, spec in ipairs{materials.bone, materials.shell, materials.tooth, materials.horn, materials.pearl} do
material_reactions(result, {{job_types.DecorateWith, "Decorate With"}}, spec)
end
table.insert(result, reaction_entry(job_types.MakeTotem))
table.insert(result, reaction_entry(job_types.ButcherAnimal))
table.insert(result, reaction_entry(job_types.MillPlants))
table.insert(result, reaction_entry(job_types.MakePotashFromLye))
table.insert(result, reaction_entry(job_types.MakePotashFromAsh))
-- Kitchen
table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 2}, "Prepare Easy Meal"))
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"))
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"))
table.insert(result, reaction_entry(job_types.WeaveCloth, {material_category = {silk = true}}, "Weave Thread into Silk"))
table.insert(result, reaction_entry(job_types.WeaveCloth, {material_category = {yarn = true}}, "Weave Yarn into Cloth"))
-- Extracts, farmer's workshop, and wood burning
table.insert(result, reaction_entry(job_types.ExtractFromPlants))
table.insert(result, reaction_entry(job_types.ExtractFromRawFish))
@ -382,7 +382,7 @@ function collect_reactions()
table.insert(result, reaction_entry(job_types.ProcessPlantsBarrel))
table.insert(result, reaction_entry(job_types.MakeCharcoal))
table.insert(result, reaction_entry(job_types.MakeAsh))
-- Reactions defined in the raws.
-- Not all reactions are allowed to the civilization.
-- That includes "Make sharp rock" by default.
@ -392,7 +392,7 @@ function collect_reactions()
local name = string.gsub(reaction.name, "^.", string.upper)
table.insert(result, reaction_entry(job_types.CustomReaction, {reaction_name = reaction.code}, name))
end
-- Metal forging
local itemdefs = df.global.world.raws.itemdefs
for rock_id = 0, #rock_types - 1 do
@ -403,76 +403,76 @@ function collect_reactions()
management = {mat_type = 0, mat_index = rock_id},
verb = "Forge",
}
if material.flags.IS_METAL then
table.insert(result, reaction_entry(job_types.StudWith, mat_flags.management, "Stud With "..rock_name))
if material.flags.ITEMS_WEAPON then
-- Todo: Are these really the right flags to check?
resource_reactions(result, job_types.MakeWeapon, mat_flags, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.skill_ranged == -1 end),
})
-- Is this entirely disconnected from the entity?
material_reactions(result, {{MakeBallistaArrowHead, "Forge", "Ballista Arrow Head"}}, mat_flags)
resource_reactions(result, job_types.MakeTrapComponent, mat_flags, entity.resources.trapcomp_type, itemdefs.trapcomps, {
adjective = true,
})
resource_reactions(result, job_types.AssembleSiegeAmmo, mat_flags, entity.resources.siegeammo_type, itemdefs.siege_ammo, {
verb = "Assemble",
})
end
if material.flags.ITEMS_WEAPON_RANGED then
resource_reactions(result, job_types.MakeWeapon, mat_flags, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.skill_ranged >= 0 end),
})
end
if material.flags.ITEMS_DIGGER then
-- Todo: Ranged or training digging weapons?
resource_reactions(result, job_types.MakeWeapon, mat_flags, entity.resources.digger_type, itemdefs.weapons, {
})
end
if material.flags.ITEMS_AMMO then
resource_reactions(result, job_types.MakeAmmo, mat_flags, entity.resources.ammo_type, itemdefs.ammo, {
name_field = "name_plural",
})
end
if material.flags.ITEMS_ANVIL then
material_reactions(result, {{job_types.ForgeAnvil, "Forge", "Anvil"}}, mat_flags)
end
if material.flags.ITEMS_ARMOR then
local metalclothing = (function(itemdef) return itemdef.props.flags.METAL end)
clothing_reactions(result, mat_flags, metalclothing)
resource_reactions(result, job_types.MakeShield, mat_flags, entity.resources.shield_type, itemdefs.shields, {
})
end
if material.flags.ITEMS_SOFT then
local metalclothing = (function(itemdef) return itemdef.props.flags.SOFT and not itemdef.props.flags.METAL end)
clothing_reactions(result, mat_flags, metalclothing)
end
if material.flags.ITEMS_HARD then
resource_reactions(result, job_types.MakeTool, mat_flags, entity.resources.tool_type, itemdefs.tools, {
permissible = (function(itemdef) return itemdef.flags.HARD_MAT end),
capitalize = true,
})
end
if material.flags.ITEMS_METAL then
resource_reactions(result, job_types.MakeTool, mat_flags, entity.resources.tool_type, itemdefs.tools, {
permissible = (function(itemdef) return itemdef.flags.METAL_MAT end),
capitalize = true,
})
end
if material.flags.ITEMS_HARD then
material_reactions(result, {
{job_types.ConstructDoor, "Construct", "Door"},
@ -505,7 +505,7 @@ function collect_reactions()
{job_types.MakeCrafts, "Make", "Crafts"},
}, mat_flags)
end
if material.flags.ITEMS_SOFT then
material_reactions(result, {
{job_types.MakeBackpack, "Make", "Backpack"},
@ -516,26 +516,26 @@ function collect_reactions()
end
end
end
-- Traction Bench
table.insert(result, reaction_entry(job_types.ConstructTractionBench))
-- Non-metal weapons
resource_reactions(result, job_types.MakeWeapon, materials.wood, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.skill_ranged >= 0 end),
})
resource_reactions(result, job_types.MakeWeapon, materials.wood, entity.resources.training_weapon_type, itemdefs.weapons, {
})
resource_reactions(result, job_types.MakeWeapon, materials.bone, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.skill_ranged >= 0 end),
})
resource_reactions(result, job_types.MakeWeapon, materials.rock, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.flags.CAN_STONE end),
})
-- Wooden items
-- Closely related to the ITEMS_HARD list.
material_reactions(result, {
@ -552,12 +552,12 @@ function collect_reactions()
{job_types.MakeGoblet, "Make", "Cup"},
{job_types.MakeInstrument, "Make", "Instrument"},
}, materials.wood)
resource_reactions(result, job_types.MakeTool, materials.wood, entity.resources.tool_type, itemdefs.tools, {
-- permissible = (function(itemdef) return itemdef.flags.WOOD_MAT end),
capitalize = true,
})
material_reactions(result, {
{job_types.MakeToy, "Make", "Toy"},
{job_types.ConstructBlocks, "Construct", "Blocks"},
@ -570,12 +570,12 @@ function collect_reactions()
{job_types.MakeCage, "Make", "Cage"},
{job_types.MakePipeSection, "Make", "Pipe Section"},
}, materials.wood)
resource_reactions(result, job_types.MakeTrapComponent, materials.wood, entity.resources.trapcomp_type, itemdefs.trapcomps, {
permissible = (function(itemdef) return itemdef.flags.WOOD end),
adjective = true,
})
-- Rock items
material_reactions(result, {
{job_types.ConstructDoor, "Construct", "Door"},
@ -591,12 +591,12 @@ function collect_reactions()
{job_types.MakeGoblet, "Make", "Mug"},
{job_types.MakeInstrument, "Make", "Instrument"},
}, materials.rock)
resource_reactions(result, job_types.MakeTool, materials.rock, entity.resources.tool_type, itemdefs.tools, {
permissible = (function(itemdef) return itemdef.flags.HARD_MAT end),
capitalize = true,
})
material_reactions(result, {
{job_types.MakeToy, "Make", "Toy"},
{job_types.ConstructQuern, "Construct", "Quern"},
@ -605,7 +605,7 @@ function collect_reactions()
{job_types.ConstructStatue, "Construct", "Statue"},
{job_types.ConstructBlocks, "Construct", "Blocks"},
}, materials.rock)
-- Glass items
for _, mat_info in ipairs(glasses) do
material_reactions(result, {
@ -622,12 +622,12 @@ function collect_reactions()
{job_types.MakeGoblet, "Make", "Goblet"},
{job_types.MakeInstrument, "Make", "Instrument"},
}, mat_info)
resource_reactions(result, job_types.MakeTool, mat_info, entity.resources.tool_type, itemdefs.tools, {
permissible = (function(itemdef) return itemdef.flags.HARD_MAT end),
capitalize = true,
})
material_reactions(result, {
{job_types.MakeToy, "Make", "Toy"},
{job_types.ConstructStatue, "Construct", "Statue"},
@ -635,44 +635,44 @@ function collect_reactions()
{job_types.MakeCage, "Make", "Terrarium"},
{job_types.MakePipeSection, "Make", "Tube"},
}, mat_info)
resource_reactions(result, job_types.MakeTrapComponent, mat_info, entity.resources.trapcomp_type, itemdefs.trapcomps, {
adjective = true,
})
end
-- Bed, specified as wooden.
table.insert(result, reaction_entry(job_types.ConstructBed, materials.wood.management))
-- Windows
for _, mat_info in ipairs(glasses) do
material_reactions(result, {
{job_types.MakeWindow, "Make", "Window"},
}, mat_info)
end
-- Rock Mechanisms
table.insert(result, reaction_entry(job_types.ConstructMechanisms, materials.rock.management))
resource_reactions(result, job_types.AssembleSiegeAmmo, materials.wood, entity.resources.siegeammo_type, itemdefs.siege_ammo, {
verb = "Assemble",
})
for _, mat_info in ipairs(glasses) do
material_reactions(result, {
{job_types.MakeRawGlass, "Make Raw", nil},
}, mat_info)
end
material_reactions(result, {
{job_types.MakeBackpack, "Make", "Backpack"},
{job_types.MakeQuiver, "Make", "Quiver"},
}, materials.leather)
for _, material in ipairs(cloth_mats) do
clothing_reactions(result, material, (function(itemdef) return itemdef.props.flags[material.clothing_flag or "SOFT"] end))
end
-- Boxes, Bags, and Ropes
local boxmats = {
{mats = {materials.wood}, box = "Chest"},
@ -693,7 +693,7 @@ function collect_reactions()
end
end
end
for _, mat in ipairs{
materials.wood,
materials.rock,
@ -709,28 +709,28 @@ function collect_reactions()
} do
material_reactions(result, {{job_types.MakeCrafts, "Make", "Crafts"}}, mat)
end
-- Siege engine parts
table.insert(result, reaction_entry(job_types.ConstructCatapultParts, materials.wood.management))
table.insert(result, reaction_entry(job_types.ConstructBallistaParts, materials.wood.management))
for _, mat in ipairs{materials.wood, materials.bone} do
resource_reactions(result, job_types.MakeAmmo, mat, entity.resources.ammo_type, itemdefs.ammo, {
name_field = "name_plural",
})
end
-- BARRED and SCALED as flag names don't quite seem to fit, here.
clothing_reactions(result, materials.bone, (function(itemdef) return itemdef.props.flags.BARRED end))
clothing_reactions(result, materials.shell, (function(itemdef) return itemdef.props.flags.SCALED end))
for _, mat in ipairs{materials.wood, materials.leather} do
resource_reactions(result, job_types.MakeShield, mat, entity.resources.shield_type, itemdefs.shields, {})
end
-- Melt a Metal Object
table.insert(result, reaction_entry(job_types.MeltMetalObject))
return result
end
@ -782,7 +782,7 @@ function screen:onInput(keys)
self.search_string = self.search_string .. string.upper(char)
end
end
self:refilter()
end
@ -799,7 +799,7 @@ function matchall(haystack, needles)
return false
end
end
return true
end
@ -815,16 +815,16 @@ function splitstring(full, pattern)
elseif start > n then
result[#result+1] = string.sub(full, n, start - 1)
end
if stop < n then
-- The pattern matches an empty string.
-- Avoid an infinite loop.
break
end
n = stop + 1
end
return result
end
@ -839,18 +839,18 @@ function screen:refilter()
}
end
end
if self.position < 1 then
self.position = #filtered
elseif self.position > #filtered then
self.position = 1
end
local start = 1
while self.position >= start + PageSize*2 do
start = start + PageSize*2
end
local displayed = {}
for n = 0, PageSize*2 - 1 do
local item = filtered[start + n]
@ -858,7 +858,7 @@ function screen:refilter()
break
end
local name = item.name
local x = 1
local y = FirstRow + n
if n >= PageSize then
@ -866,12 +866,12 @@ function screen:refilter()
y = y - PageSize
name = " "..name
end
local color = COLOR_CYAN
if start + n == self.position then
color = COLOR_LIGHTCYAN
end
displayed[n + 1] = {
x = x,
y = y,
@ -879,7 +879,7 @@ function screen:refilter()
color = color,
}
end
self.reactions = filtered
self.displayed = displayed
end
@ -917,18 +917,18 @@ function orders_match(a, b)
"mat_type",
"mat_index",
}
for _, fieldname in ipairs(fields) do
if a[fieldname] ~= b[fieldname] then
return false
end
end
local subtables = {
"item_category",
"material_category",
}
for _, fieldname in ipairs(subtables) do
local aa = a[fieldname]
local bb = b[fieldname]
@ -938,7 +938,7 @@ function orders_match(a, b)
end
end
end
return true
end
@ -953,13 +953,13 @@ function order_quantity(order, quantity)
end
end
end
if amount > 30 then
-- Respect the quantity limit.
-- With this many in the queue, we can wait for the next cycle.
return 30
end
return amount
end
@ -993,7 +993,7 @@ function countContents(container, settings)
total = total + 1
end
end
return total
end
@ -1009,7 +1009,7 @@ function check_stockpiles(verbose)
result[reaction] = (result[reaction] or 0) + amount
end
end
return result
end
@ -1030,7 +1030,7 @@ function check_pile(sp, verbose)
end
end
end
for _, item in ipairs(dfhack.buildings.getStockpileContents(sp)) do
if item:isAssignedToThisStockpile(sp.id) then
-- This is a bin or barrel associated with the stockpile.
@ -1039,14 +1039,14 @@ function check_pile(sp, verbose)
filled = filled + 1
end
end
if verbose then
print("Stockpile #"..sp.stockpile_number,
string.format("%3d spaces", numspaces),
string.format("%4d items", filled),
string.format("%4d empty spaces", empty))
end
return filled, empty
end
@ -1094,7 +1094,7 @@ function matches_stockpile(item, settings)
elseif df.item_threadst:is_instance(item) then
return settings.flags.cloth
end
return true
end

@ -149,7 +149,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
protomap.set_z_size(z_max);
out << "Writing material dictionary..." << std::endl;
for (size_t i = 0; i < world->raws.inorganics.size(); i++)
{
dfproto::Material *protomaterial = protomap.add_inorganic_material();
@ -173,10 +173,10 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
constructionMaterials[construction->pos] = std::make_pair(construction->mat_index, construction->mat_type);
}
}
coded_output->WriteVarint32(protomap.ByteSize());
protomap.SerializeToCodedStream(coded_output);
DFHack::t_feature blockFeatureGlobal;
DFHack::t_feature blockFeatureLocal;
@ -239,7 +239,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
prototile->set_tile_material(toProto(tileMaterial(type)));
df::coord map_pos = df::coord(b_x*16+x,b_y*16+y,z);
switch (tileMaterial(type))
{
case tiletype_material::SOIL:
@ -300,7 +300,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
}
}
}
coded_output->WriteVarint32(protoblock.ByteSize());
protoblock.SerializeToCodedStream(coded_output);
} // block x

@ -5,23 +5,23 @@ message Tile
{
enum TileType
{
EMPTY = 0;
FLOOR = 1;
BOULDER = 2;
PEBBLES = 3;
WALL = 4;
FORTIFICATION = 5;
STAIR_UP = 6;
STAIR_DOWN = 7;
STAIR_UPDOWN = 8;
RAMP = 9;
RAMP_TOP = 10;
BROOK_BED = 11;
BROOK_TOP = 12;
TREE = 13;
SAPLING = 14;
SHRUB = 15;
ENDLESS_PIT = 16;
EMPTY = 0;
FLOOR = 1;
BOULDER = 2;
PEBBLES = 3;
WALL = 4;
FORTIFICATION = 5;
STAIR_UP = 6;
STAIR_DOWN = 7;
STAIR_UPDOWN = 8;
RAMP = 9;
RAMP_TOP = 10;
BROOK_BED = 11;
BROOK_TOP = 12;
TREE = 13;
SAPLING = 14;
SHRUB = 15;
ENDLESS_PIT = 16;
}
enum LiquidType
{
@ -49,8 +49,8 @@ message Tile
MAGMA_TYPE = 16;
DRIFTWOOD = 17;
POOL = 18;
BROOK = 19;
RIVER = 20;
BROOK = 19;
RIVER = 20;
}
required uint32 x = 1;
required uint32 y = 2;

@ -49,7 +49,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
}
return CR_OK;
}
if ( !wasLoaded ) {
wasLoaded = true;
}
@ -59,7 +59,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
return CR_OK;
}
count = 0;
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++ ) {
@ -69,7 +69,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
continue;
if ( unit->flags1.bits.dead )
continue;
int processedThoughtCount;
map<int,int>::iterator i = processedThoughtCountTable.find(unit->id);
if ( i == processedThoughtCountTable.end() ) {
@ -78,13 +78,13 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
} else {
processedThoughtCount = (*i).second;
}
if ( processedThoughtCount == unit->status.recent_events.size() ) {
continue;
} else if ( processedThoughtCount > unit->status.recent_events.size() ) {
processedThoughtCount = unit->status.recent_events.size();
}
//don't reprocess any old thoughts
vector<df::unit_thought*> newThoughts;
for ( size_t b = processedThoughtCount; b < unit->status.recent_events.size(); b++ ) {
@ -120,7 +120,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
}
processedThoughtCountTable[unit->id] = unit->status.recent_events.size();
}
return CR_OK;
}
@ -159,11 +159,11 @@ command_result misery(color_ostream &out, vector<string>& parameters) {
out.printerr("misery can only be enabled in fortress mode with a fully-loaded game.\n");
return CR_FAILURE;
}
if ( parameters.size() < 1 || parameters.size() > 2 ) {
return CR_WRONG_USAGE;
}
if ( parameters[0] == "disable" ) {
if ( parameters.size() > 1 ) {
return CR_WRONG_USAGE;
@ -197,7 +197,7 @@ command_result misery(color_ostream &out, vector<string>& parameters) {
factor = a;
is_enabled = factor > 1;
}
return CR_OK;
}

@ -90,7 +90,7 @@ void impregnateMany() {
else
females[unit->race].push_back(a);
}
for ( auto i = females.begin(); i != females.end(); i++ ) {
int32_t race = i->first;
vector<int32_t>& femalesList = i->second;
@ -99,10 +99,10 @@ void impregnateMany() {
break;
vector<int32_t> compatibles;
df::coord pos1 = units[femalesList[a]]->pos;
if ( males.find(i->first) == males.end() )
continue;
vector<int32_t>& malesList = males[i->first];
for ( size_t b = 0; b < malesList.size(); b++ ) {
df::coord pos2 = units[malesList[b]]->pos;
@ -111,7 +111,7 @@ void impregnateMany() {
}
if ( compatibles.empty() )
continue;
size_t maleIndex = (size_t)(compatibles.size()*((float)rand() / (1+(float)RAND_MAX)));
if ( impregnate(units[femalesList[a]], units[compatibles[maleIndex]]) )
popcount[race]++;
@ -124,7 +124,7 @@ bool impregnate(df::unit* female, df::unit* male) {
return false;
if ( female->relations.pregnancy_genes )
return false;
df::unit_genes* preg = new df::unit_genes;
*preg = male->appearance.genes;
female->relations.pregnancy_genes = preg;
@ -138,7 +138,7 @@ void tickHandler(color_ostream& out, void* data) {
return;
CoreSuspender suspend;
impregnateMany();
EventManager::unregisterAll(plugin_self);
EventManager::EventHandler handle(tickHandler, howOften);
EventManager::registerTick(handle, howOften, plugin_self);
@ -147,7 +147,7 @@ void tickHandler(color_ostream& out, void* data) {
command_result petcapRemover (color_ostream &out, std::vector <std::string> & parameters)
{
CoreSuspender suspend;
for ( size_t a = 0; a < parameters.size(); a++ ) {
if ( parameters[a] == "every" ) {
if ( a+1 >= parameters.size() )
@ -186,18 +186,18 @@ command_result petcapRemover (color_ostream &out, std::vector <std::string> & pa
out.print("%s, line %d: invalid argument: %s\n", __FILE__, __LINE__, parameters[a].c_str());
return CR_WRONG_USAGE;
}
if ( howOften < 0 ) {
is_enabled = false;
return CR_OK;
}
is_enabled = true;
EventManager::unregisterAll(plugin_self);
EventManager::EventHandler handle(tickHandler, howOften);
EventManager::registerTick(handle, howOften, plugin_self);
out.print("petcapRemover: howOften = every %d ticks, popcap per species = %d, preg time = %d ticks.\n", howOften, popcap, pregtime);
return CR_OK;
}

@ -84,7 +84,7 @@ command_result df_cprobe (color_ostream &out, vector <string> & parameters)
if(unit->pos.x == cursorX && unit->pos.y == cursorY && unit->pos.z == cursorZ)
{
out.print("Creature %d, race %d (%x), civ %d (%x)\n", unit->id, unit->race, unit->race, unit->civ_id, unit->civ_id);
for(size_t j=0; j<unit->inventory.size(); j++)
{
df::unit_inventory_item* inv_item = unit->inventory[j];
@ -101,7 +101,7 @@ command_result df_cprobe (color_ostream &out, vector <string> & parameters)
out << endl;
}
}
// don't leave loop, there may be more than 1 creature at the cursor position
//break;
}
@ -242,7 +242,7 @@ command_result df_probe (color_ostream &out, vector <string> & parameters)
const char* surroundings[] = { "Serene", "Mirthful", "Joyous Wilds", "Calm", "Wilderness", "Untamed Wilds", "Sinister", "Haunted", "Terrifying" };
// biome, geolayer
out << "biome: " << des.bits.biome << " (" <<
out << "biome: " << des.bits.biome << " (" <<
"region id=" << biome->region_id << ", " <<
surroundings[surr] << ", " <<
"savagery " << biome->savagery << ", " <<
@ -345,7 +345,7 @@ command_result df_probe (color_ostream &out, vector <string> & parameters)
out << "no grow" << endl;
for(size_t e=0; e<block.block_events.size(); e++)
{
{
df::block_square_event * blev = block.block_events[e];
df::block_square_event_type blevtype = blev->getType();
switch(blevtype)

@ -153,7 +153,7 @@ void printMats(color_ostream &con, MatMap &mat, std::vector<T*> &materials, bool
{
if(it->first >= materials.size())
{
con << "Bad index: " << it->first << " out of "
con << "Bad index: " << it->first << " out of "
<< materials.size() << endl;
continue;
}

@ -4,205 +4,205 @@ package RemoteFortressReader;
option optimize_for = LITE_RUNTIME;
//We use shapes, etc, because the actual tiletypes may differ between DF versions.
enum TiletypeShape
enum TiletypeShape
{
NO_SHAPE = -1;
EMPTY = 0;
FLOOR = 1;
BOULDER = 2;
PEBBLES = 3;
WALL = 4;
FORTIFICATION = 5;
STAIR_UP = 6;
STAIR_DOWN = 7;
STAIR_UPDOWN = 8;
RAMP = 9;
RAMP_TOP = 10;
BROOK_BED = 11;
BROOK_TOP = 12;
TREE_SHAPE = 13;
SAPLING = 14;
SHRUB = 15;
ENDLESS_PIT = 16;
BRANCH = 17;
TRUNK_BRANCH = 18;
TWIG = 19;
NO_SHAPE = -1;
EMPTY = 0;
FLOOR = 1;
BOULDER = 2;
PEBBLES = 3;
WALL = 4;
FORTIFICATION = 5;
STAIR_UP = 6;
STAIR_DOWN = 7;
STAIR_UPDOWN = 8;
RAMP = 9;
RAMP_TOP = 10;
BROOK_BED = 11;
BROOK_TOP = 12;
TREE_SHAPE = 13;
SAPLING = 14;
SHRUB = 15;
ENDLESS_PIT = 16;
BRANCH = 17;
TRUNK_BRANCH = 18;
TWIG = 19;
}
enum TiletypeSpecial
enum TiletypeSpecial
{
NO_SPECIAL = -1;
NORMAL = 0;
RIVER_SOURCE = 1;
WATERFALL = 2;
SMOOTH = 3;
FURROWED = 4;
WET = 5;
DEAD = 6;
WORN_1 = 7;
WORN_2 = 8;
WORN_3 = 9;
TRACK = 10;
SMOOTH_DEAD = 11;
NO_SPECIAL = -1;
NORMAL = 0;
RIVER_SOURCE = 1;
WATERFALL = 2;
SMOOTH = 3;
FURROWED = 4;
WET = 5;
DEAD = 6;
WORN_1 = 7;
WORN_2 = 8;
WORN_3 = 9;
TRACK = 10;
SMOOTH_DEAD = 11;
};
enum TiletypeMaterial
enum TiletypeMaterial
{
NO_MATERIAL = -1;
AIR = 0;
SOIL = 1;
STONE = 2;
FEATURE = 3;
LAVA_STONE = 4;
MINERAL = 5;
FROZEN_LIQUID = 6;
CONSTRUCTION = 7;
GRASS_LIGHT = 8;
GRASS_DARK = 9;
GRASS_DRY = 10;
GRASS_DEAD = 11;
PLANT = 12;
HFS = 13;
CAMPFIRE = 14;
FIRE = 15;
ASHES = 16;
MAGMA = 17;
DRIFTWOOD = 18;
POOL = 19;
BROOK = 20;
RIVER = 21;
ROOT = 22;
TREE_MATERIAL = 23;
MUSHROOM = 24;
UNDERWORLD_GATE = 25;
NO_MATERIAL = -1;
AIR = 0;
SOIL = 1;
STONE = 2;
FEATURE = 3;
LAVA_STONE = 4;
MINERAL = 5;
FROZEN_LIQUID = 6;
CONSTRUCTION = 7;
GRASS_LIGHT = 8;
GRASS_DARK = 9;
GRASS_DRY = 10;
GRASS_DEAD = 11;
PLANT = 12;
HFS = 13;
CAMPFIRE = 14;
FIRE = 15;
ASHES = 16;
MAGMA = 17;
DRIFTWOOD = 18;
POOL = 19;
BROOK = 20;
RIVER = 21;
ROOT = 22;
TREE_MATERIAL = 23;
MUSHROOM = 24;
UNDERWORLD_GATE = 25;
}
enum TiletypeVariant
{
NO_VARIANT = -1;
VAR_1 = 0;
VAR_2 = 1;
VAR_3 = 2;
VAR_4 = 3;
NO_VARIANT = -1;
VAR_1 = 0;
VAR_2 = 1;
VAR_3 = 2;
VAR_4 = 3;
};
message Tiletype
{
required int32 id = 1;
optional string name = 2;
optional string caption = 3;
optional TiletypeShape shape = 4;
optional TiletypeSpecial special = 5;
optional TiletypeMaterial material = 6;
optional TiletypeVariant variant = 7;
optional string direction = 8;
required int32 id = 1;
optional string name = 2;
optional string caption = 3;
optional TiletypeShape shape = 4;
optional TiletypeSpecial special = 5;
optional TiletypeMaterial material = 6;
optional TiletypeVariant variant = 7;
optional string direction = 8;
};
message TiletypeList
{
repeated Tiletype tiletype_list = 1;
repeated Tiletype tiletype_list = 1;
}
message MapBlock
{
required int32 map_x = 1;
required int32 map_y = 2;
required int32 map_z = 3;
repeated int32 tiles = 4;
repeated MatPair materials = 5;
repeated MatPair layer_materials = 6;
repeated MatPair vein_materials = 7;
repeated MatPair base_materials = 8;
repeated int32 magma = 9;
repeated int32 water = 10;
required int32 map_x = 1;
required int32 map_y = 2;
required int32 map_z = 3;
repeated int32 tiles = 4;
repeated MatPair materials = 5;
repeated MatPair layer_materials = 6;
repeated MatPair vein_materials = 7;
repeated MatPair base_materials = 8;
repeated int32 magma = 9;
repeated int32 water = 10;
}
message MatPair {
required int32 mat_type = 1;
required int32 mat_index = 2;
required int32 mat_type = 1;
required int32 mat_index = 2;
}
message ColorDefinition {
required int32 red = 1;
required int32 green = 2;
required int32 blue = 3;
required int32 red = 1;
required int32 green = 2;
required int32 blue = 3;
}
message MaterialDefinition{
required MatPair mat_pair = 1;
optional string id = 2;
optional string name = 3;
optional ColorDefinition state_color = 4; //Simplifying colors to assume room temperature.
required MatPair mat_pair = 1;
optional string id = 2;
optional string name = 3;
optional ColorDefinition state_color = 4; //Simplifying colors to assume room temperature.
}
message MaterialList{
repeated MaterialDefinition material_list = 1;
repeated MaterialDefinition material_list = 1;
}
message UnitDefinition
{
required int32 id = 1;
optional bool isValid = 2;
optional int32 pos_x = 3;
optional int32 pos_y = 4;
optional int32 pos_z = 5;
required int32 id = 1;
optional bool isValid = 2;
optional int32 pos_x = 3;
optional int32 pos_y = 4;
optional int32 pos_z = 5;
}
message UnitList
{
repeated UnitDefinition creature_list = 1;
repeated UnitDefinition creature_list = 1;
}
message BlockRequest
{
optional int32 blocks_needed = 1;
optional int32 min_x = 2;
optional int32 max_x = 3;
optional int32 min_y = 4;
optional int32 max_y = 5;
optional int32 min_z = 6;
optional int32 max_z = 7;
optional int32 blocks_needed = 1;
optional int32 min_x = 2;
optional int32 max_x = 3;
optional int32 min_y = 4;
optional int32 max_y = 5;
optional int32 min_z = 6;
optional int32 max_z = 7;
}
message BlockList
{
repeated MapBlock map_blocks = 1;
optional int32 map_x = 2;
optional int32 map_y = 3;
repeated MapBlock map_blocks = 1;
optional int32 map_x = 2;
optional int32 map_y = 3;
}
message PlantDef
{
required int32 pos_x = 1;
required int32 pos_y = 2;
required int32 pos_z = 3;
required int32 index = 4;
required int32 pos_x = 1;
required int32 pos_y = 2;
required int32 pos_z = 3;
required int32 index = 4;
}
message PlantList
{
repeated PlantDef plant_list = 1;
repeated PlantDef plant_list = 1;
}
message ViewInfo
{
optional int32 view_pos_x = 1;
optional int32 view_pos_y = 2;
optional int32 view_pos_z = 3;
optional int32 view_size_x = 4;
optional int32 view_size_y = 5;
optional int32 cursor_pos_x = 6;
optional int32 cursor_pos_y = 7;
optional int32 cursor_pos_z = 8;
optional int32 view_pos_x = 1;
optional int32 view_pos_y = 2;
optional int32 view_pos_z = 3;
optional int32 view_size_x = 4;
optional int32 view_size_y = 5;
optional int32 cursor_pos_x = 6;
optional int32 cursor_pos_y = 7;
optional int32 cursor_pos_z = 8;
}
message MapInfo
{
optional int32 block_size_x = 1;
optional int32 block_size_y = 2;
optional int32 block_size_z = 3;
optional int32 block_pos_x = 4;
optional int32 block_pos_y = 5;
optional int32 block_pos_z = 6;
optional string world_name = 7;
optional string world_name_english = 8;
optional string save_name = 9;
optional int32 block_size_x = 1;
optional int32 block_size_y = 2;
optional int32 block_size_z = 3;
optional int32 block_pos_x = 4;
optional int32 block_pos_y = 5;
optional int32 block_pos_z = 6;
optional string world_name = 7;
optional string world_name_english = 8;
optional string save_name = 9;
}

@ -1,76 +1,76 @@
package isoworldremote;
//Describes a very basic material structure for the map embark
option optimize_for = LITE_RUNTIME;
enum BasicMaterial {
AIR = 0;
OTHER = 1;
INORGANIC = 2;
LIQUID = 3;
PLANT = 4;
WOOD = 5;
};
enum LiquidType {
ICE = 0;
WATER = 1;
MAGMA = 2;
}
enum BasicShape {
NONE = 0;
OPEN = 1;
WALL = 3;
FLOOR = 4;
RAMP_UP = 5;
RAMP_DOWN = 6;
}
message ColorDefinition {
required int32 red = 1;
required int32 green = 2;
required int32 blue = 3;
}
message EmbarkTileLayer {
repeated BasicMaterial mat_type_table = 4 [packed=true];
repeated int32 mat_subtype_table = 5 [packed=true];
repeated BasicShape tile_shape_table = 6 [packed=true];
repeated ColorDefinition tile_color_table = 7;
}
message EmbarkTile {
required int32 world_x = 1;
required int32 world_y = 2;
required sint32 world_z = 3;
repeated EmbarkTileLayer tile_layer = 4;
optional int32 current_year = 5;
optional int32 current_season = 6;
optional bool is_valid = 7;
}
message TileRequest {
optional int32 want_x = 1;
optional int32 want_y = 2;
}
message MapRequest {
optional string save_folder = 1;
}
message MapReply {
required bool available = 1;
optional int32 region_x = 2;
optional int32 region_y = 3;
optional int32 region_size_x = 4;
optional int32 region_size_y = 5;
optional int32 current_year = 6;
optional int32 current_season = 7;
}
message RawNames {
required bool available = 1;
repeated string inorganic = 2;
repeated string organic = 3;
}
package isoworldremote;
//Describes a very basic material structure for the map embark
option optimize_for = LITE_RUNTIME;
enum BasicMaterial {
AIR = 0;
OTHER = 1;
INORGANIC = 2;
LIQUID = 3;
PLANT = 4;
WOOD = 5;
};
enum LiquidType {
ICE = 0;
WATER = 1;
MAGMA = 2;
}
enum BasicShape {
NONE = 0;
OPEN = 1;
WALL = 3;
FLOOR = 4;
RAMP_UP = 5;
RAMP_DOWN = 6;
}
message ColorDefinition {
required int32 red = 1;
required int32 green = 2;
required int32 blue = 3;
}
message EmbarkTileLayer {
repeated BasicMaterial mat_type_table = 4 [packed=true];
repeated int32 mat_subtype_table = 5 [packed=true];
repeated BasicShape tile_shape_table = 6 [packed=true];
repeated ColorDefinition tile_color_table = 7;
}
message EmbarkTile {
required int32 world_x = 1;
required int32 world_y = 2;
required sint32 world_z = 3;
repeated EmbarkTileLayer tile_layer = 4;
optional int32 current_year = 5;
optional int32 current_season = 6;
optional bool is_valid = 7;
}
message TileRequest {
optional int32 want_x = 1;
optional int32 want_y = 2;
}
message MapRequest {
optional string save_folder = 1;
}
message MapReply {
required bool available = 1;
optional int32 region_x = 2;
optional int32 region_y = 3;
optional int32 region_size_x = 4;
optional int32 region_size_y = 5;
optional int32 current_year = 6;
optional int32 current_season = 7;
}
message RawNames {
required bool available = 1;
repeated string inorganic = 2;
repeated string organic = 3;
}

@ -60,7 +60,7 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters)
// check block for grass events before looking at 16x16 tiles
df::block_square_event_grassst * grev = NULL;
for(size_t e=0; e<cur->block_events.size(); e++)
{
{
df::block_square_event * blev = cur->block_events[e];
df::block_square_event_type blevtype = blev->getType();
if(blevtype == df::block_square_event_type::grass)
@ -103,7 +103,7 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters)
if(max)
{
for(size_t e=0; e<cur->block_events.size(); e++)
{
{
df::block_square_event * blev = cur->block_events[e];
df::block_square_event_type blevtype = blev->getType();
if(blevtype == df::block_square_event_type::grass)
@ -118,7 +118,7 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters)
// try to find the 'original' event
bool regrew = false;
for(size_t e=0; e<cur->block_events.size(); e++)
{
{
df::block_square_event * blev = cur->block_events[e];
df::block_square_event_type blevtype = blev->getType();
if(blevtype == df::block_square_event_type::grass)
@ -138,7 +138,7 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters)
{
vector <df::block_square_event_grassst *> gr_evs;
for(size_t e=0; e<cur->block_events.size(); e++)
{
{
df::block_square_event * blev = cur->block_events[e];
df::block_square_event_type blevtype = blev->getType();
if(blevtype == df::block_square_event_type::grass)

@ -79,7 +79,7 @@ rect2d getMapViewport()
}
else
return mkrect_wh(0,0,0,0);
}
int w=gps->dimx;
int h=gps->dimy;
@ -88,7 +88,7 @@ rect2d getMapViewport()
int menu_x2=w-MENU_WIDTH-2;
int menu_x1=area_x2-MENU_WIDTH-1;
int view_rb=w-1;
int area_pos=*df::global::ui_area_map_width;
int menu_pos=*df::global::ui_menu_width;
if(area_pos<3)
@ -97,7 +97,7 @@ rect2d getMapViewport()
}
if (menu_pos<area_pos || df::global::ui->main.mode!=0)
{
if (menu_pos >= area_pos)
if (menu_pos >= area_pos)
menu_pos = area_pos-1;
int menu_x = menu_x2;
if(menu_pos < 2) menu_x = menu_x1;
@ -128,7 +128,7 @@ void lightingEngineViewscreen::reinit()
void plotCircle(int xm, int ym, int r,const std::function<void(int,int)>& setPixel)
{
int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */
int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */
do {
setPixel(xm-x, ym+y); /* I. Quadrant */
setPixel(xm-y, ym-x); /* II. Quadrant */
@ -156,7 +156,7 @@ void plotSquare(int xm, int ym, int r,const std::function<void(int,int)>& setPix
void plotLine(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf(rgbf,int,int,int,int)>& setPixel)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = dx+dy, e2; /* error value e_xy */
int rdx=0;
int rdy=0;
@ -177,9 +177,9 @@ void plotLine(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf
}
void plotLineDiffuse(int x0, int y0, int x1, int y1,rgbf power,int num_diffuse,const std::function<rgbf(rgbf,int,int,int,int)>& setPixel,bool skip_hack=false)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dsq=dx*dx+dy*dy;
int err = dx+dy, e2; /* error value e_xy */
int rdx=0;
@ -214,7 +214,7 @@ void plotLineDiffuse(int x0, int y0, int x1, int y1,rgbf power,int num_diffuse,c
void plotLineAA(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf(rgbf,int,int,int,int)>& setPixelAA)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = dx-dy, e2, x2; /* error value e_xy */
int ed = dx+dy == 0 ? 1 : sqrt((float)dx*dx+(float)dy*dy);
int rdx=0;
@ -232,7 +232,7 @@ void plotLineAA(int x0, int y0, int x1, int y1,rgbf power,const std::function<rg
rdx=rdy=0;
if (2*e2 >= -dx) { /* x step */
if (x0 == x1) break;
if (e2+dy < ed)
{
str=1-(e2+dy)/(float)ed;
@ -240,11 +240,11 @@ void plotLineAA(int x0, int y0, int x1, int y1,rgbf power,const std::function<rg
strsum+=str;
}
err -= dy; x0 += sx; rdx=sx;
}
}
if (2*e2 <= dy) { /* y step */
if (y0 == y1) break;
if (dx-e2 < ed)
if (dx-e2 < ed)
{
str=1-(dx-e2)/(float)ed;
sumPower+=setPixelAA(power*str,lrdx,lrdy,x2+sx,y0);
@ -320,16 +320,16 @@ void lightingEngineViewscreen::updateWindow()
else
std::swap(lightMap,myRenderer->lightGrid);
rect2d vp=getMapViewport();
myRenderer->invalidateRect(vp.first.x,vp.first.y,vp.second.x-vp.first.x,vp.second.y-vp.first.y);
}
void lightingEngineViewscreen::preRender()
{
}
void lightingEngineViewscreen::fixAdvMode(int mode)
{
MapExtras::MapCache mc;
const rgbf dim(levelDim,levelDim,levelDim);
rect2d vp=getMapViewport();
@ -413,7 +413,7 @@ matLightDef* lightingEngineViewscreen::getMaterialDef( int matType,int matIndex
auto it=matDefs.find(std::make_pair(matType,matIndex));
if(it!=matDefs.end())
return &it->second;
else
else
return NULL;
}
buildingLightDef* lightingEngineViewscreen::getBuildingDef( df::building* bld )
@ -421,7 +421,7 @@ buildingLightDef* lightingEngineViewscreen::getBuildingDef( df::building* bld )
auto it=buildingDefs.find(std::make_tuple((int)bld->getType(),(int)bld->getSubtype(),(int)bld->getCustomType()));
if(it!=buildingDefs.end())
return &it->second;
else
else
return NULL;
}
creatureLightDef* lightingEngineViewscreen::getCreatureDef(df::unit* u)
@ -502,10 +502,10 @@ rgbf lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int y,con
else if(basicShapeIce==df::tiletype_shape_basic::Floor || basicShapeIce==df::tiletype_shape_basic::Ramp || shapeIce==df::tiletype_shape::STAIR_UP)
if(!lastLevel)
ret*=matIce.transparency.pow(1.0f/7.0f);
}
}
lightDef=getMaterialDef(mat.mat_type,mat.mat_index);
if(!lightDef || !lightDef->isTransparent)
lightDef=&matWall;
if(basic_shape==df::tiletype_shape_basic::Wall)
@ -514,9 +514,9 @@ rgbf lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int y,con
}
else if(basic_shape==df::tiletype_shape_basic::Floor || basic_shape==df::tiletype_shape_basic::Ramp || shape==df::tiletype_shape::STAIR_UP)
{
if(!lastLevel)
ret*=lightDef->transparency.pow(1.0f/7.0f);
ret*=lightDef->transparency.pow(1.0f/7.0f);
}
else if(shape==df::tiletype_shape::STAIR_DOWN || shape==df::tiletype_shape::STAIR_UPDOWN)
{
@ -574,7 +574,7 @@ void lightingEngineViewscreen::doSun(const lightSource& sky,MapExtras::MapCache&
rgbf& curCell=cellArray[block_x][block_y];
curCell=propogateSun(b,block_x,block_y,curCell,z==window_z);
if(curCell.dot(curCell)<0.003f)
emptyCell++;
emptyCell++;
}
}
if(emptyCell==256)
@ -622,10 +622,10 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
else
daycol= fmod(dayHour,24.0f)/24.0f; //1->12h 0->24h
rgbf sky_col=getSkyColor(daycol);
lightSource sky(sky_col, -1);//auto calculate best size
MapExtras::MapCache cache;
doSun(sky,cache);
@ -640,7 +640,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
blockVp.second=(window2d+vpSize)/16;
blockVp.second.x=std::min(blockVp.second.x,(int16_t)df::global::world->map.x_count_block);
blockVp.second.y=std::min(blockVp.second.y,(int16_t)df::global::world->map.y_count_block);
for(int blockX=blockVp.first.x;blockX<=blockVp.second.x;blockX++)
for(int blockY=blockVp.first.y;blockY<=blockVp.second.y;blockY++)
{
@ -648,7 +648,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
MapExtras::Block* bDown=cache.BlockAt(DFCoord(blockX,blockY,window_z-1));
if(!b)
continue; //empty blocks fixed by sun propagation
for(int block_x = 0; block_x < 16; block_x++)
for(int block_y = 0; block_y < 16; block_y++)
{
@ -662,7 +662,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
int tile=getIndex(pos.x,pos.y);
rgbf& curCell=ocupancy[tile];
curCell=matAmbience.transparency;
df::tiletype type = b->tiletypeAt(gpos);
df::tile_designation d = b->DesignationAt(gpos);
@ -677,9 +677,9 @@ void lightingEngineViewscreen::doOcupancyAndLights()
bool is_floor=!ENUM_ATTR(tiletype_shape,passable_low,shape);
df::tiletype_shape_basic basic_shape = ENUM_ATTR(tiletype_shape, basic_shape, shape);
df::tiletype_material tileMat= ENUM_ATTR(tiletype,material,type);
DFHack::t_matpair mat=b->staticMaterialAt(gpos);
matLightDef* lightDef=getMaterialDef(mat.mat_type,mat.mat_index);
if(!lightDef || !lightDef->isTransparent)
lightDef=&matWall;
@ -698,7 +698,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
{
applyMaterial(tile,matWater, (float)d.bits.flow_size/7.0f, (float)d.bits.flow_size/7.0f);
}
if(d.bits.liquid_type && d.bits.flow_size>0)
if(d.bits.liquid_type && d.bits.flow_size>0)
{
applyMaterial(tile,matLava,(float)d.bits.flow_size/7.0f,(float)d.bits.flow_size/7.0f);
}
@ -713,10 +713,10 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
}
df::map_block* block=b->getRaw();
if(!block)
continue;
@ -749,7 +749,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
//blood and other goo
for(int i=0;i<block->block_events.size();i++)
{
@ -829,12 +829,12 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
//buildings
for(size_t i = 0; i < df::global::world->buildings.all.size(); i++)
{
df::building *bld = df::global::world->buildings.all[i];
if(window_z!=bld->z)
continue;
if(bld->getBuildStage()<bld->getMaxBuildStage()) //only work if fully built
@ -846,7 +846,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
p2=worldToViewportCoord(p2,vp,window2d);
if(isInRect(p1,vp)||isInRect(p2,vp))
{
int tile;
if(isInRect(p1,vp))
tile=getIndex(p1.x,p1.y); //TODO multitile buildings. How they would work?
@ -868,8 +868,8 @@ void lightingEngineViewscreen::doOcupancyAndLights()
if(!gate->gate_flags.bits.closed)
continue;
}
if(def->useMaterial)
{
matLightDef* mat=getMaterialDef(bld->mat_type,bld->mat_index);
@ -903,7 +903,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
}
rgbf lua_parseLightCell(lua_State* L)
{
@ -937,7 +937,7 @@ rgbf lua_parseLightCell(lua_State* L)
lua_pop(L,1)
matLightDef lua_parseMatDef(lua_State* L)
{
matLightDef ret;
lua_getfield(L,-1,"tr");
if(ret.isTransparent=!lua_isnil(L,-1))
@ -987,7 +987,7 @@ int lightingEngineViewscreen::parseMaterials(lua_State* L)
int index=lua_tonumber(L,-2);
//os->print("\tProcessing index:%d\n",index);
engine->matDefs[std::make_pair(type,index)]=lua_parseMatDef(L);
lua_pop(L, 1);
}
lua_pop(L, 1);
@ -1174,17 +1174,17 @@ void lightingEngineViewscreen::loadSettings()
std::string rawFolder;
if(df::global::world->cur_savegame.save_dir!="")
{
rawFolder= "data/save/" + (df::global::world->cur_savegame.save_dir) + "/raw/";
rawFolder= "data/save/" + (df::global::world->cur_savegame.save_dir) + "/raw/";
}
else
{
rawFolder= "raw/";
rawFolder= "raw/";
}
const std::string settingsfile=rawFolder+"rendermax.lua";
CoreSuspender lock;
color_ostream_proxy out(Core::getInstance().getConsole());
lua_State* s=DFHack::Lua::Core::State;
lua_newtable(s);
int env=lua_gettop(s);
@ -1202,7 +1202,7 @@ void lightingEngineViewscreen::loadSettings()
else
{
lua_pushvalue(s,env);
if(Lua::SafeCall(out,s,1,0))
{
lua_pushcfunction(s, parseMaterials);
@ -1235,7 +1235,7 @@ void lightingEngineViewscreen::loadSettings()
Lua::SafeCall(out,s,2,0);
out.print("%d items loaded\n",itemDefs.size());
}
}
}
catch(std::exception& e)
@ -1272,8 +1272,8 @@ void lightThread::run()
if(dispatch.occlusion.size()!=canvas.size()) //oh no somebody resized stuff
canvas.resize(dispatch.occlusion.size());
}
{ //get my rectangle (any will do)
tthread::lock_guard<tthread::mutex> guard(dispatch.unprocessedMutex);
if (dispatch.unprocessed.size()==0)
@ -1287,13 +1287,13 @@ void lightThread::run()
{
dispatch.occlusionReady=false;
}
}
work();
{
tthread::lock_guard<tthread::mutex> guard(dispatch.writeLock);
combine();//write it back
dispatch.writeCount++;
dispatch.writeCount++;
}
dispatch.writesDone.notify_one();//tell about it to the dispatch.
}
@ -1311,7 +1311,7 @@ void lightThread::work()
void lightThread::combine()
{
for(int i=0;i<canvas.size();i++)
for(int i=0;i<canvas.size();i++)
{
rgbf& c=dispatch.lightMap[i];
c=blend(c,canvas[i]);
@ -1393,7 +1393,7 @@ void lightThread::doLight( int x,int y )
surrounds += lightUpCell( power, i, j,x+i, y+j); //and this is wall hack (so that walls look nice)
if(surrounds.dot(surrounds)>0.00001f) //if we needed to light up the suroundings, then raycast
{
plotSquare(x,y,radius,
std::bind(&lightThread::doRay,this,power,x,y,_1,_2,num_diffuse));
}
@ -1438,7 +1438,7 @@ void lightThreadDispatch::shutdown()
for(int i=0;i<threadPool.size();i++)
{
threadPool[i]->isDone=true;
}
occlusionDone.notify_all();//if stuck signal that you are done with stuff.
for(int i=0;i<threadPool.size();i++)
@ -1465,7 +1465,7 @@ void threadStub(void * arg)
void lightThreadDispatch::start(int count)
{
for(int i=0;i<count;i++)
{
{
std::unique_ptr<lightThread> nthread(new lightThread(*this));
nthread->myThread=new tthread::thread(&threadStub,nthread.get());
threadPool.push_back(std::move(nthread));

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