Get rid of tabs

develop
Quietust 2012-11-16 15:33:36 -06:00
parent d506dd7137
commit e2b9b703a0
23 changed files with 1013 additions and 1013 deletions

@ -121,7 +121,7 @@ ADD_DEFINITIONS(-DPROTOBUF_USE_DLLS)
ADD_DEFINITIONS(-DLUA_BUILD_AS_DLL) ADD_DEFINITIONS(-DLUA_BUILD_AS_DLL)
if(APPLE) if(APPLE)
add_definitions(-D_DARWIN) add_definitions(-D_DARWIN)
elseif(UNIX) elseif(UNIX)
add_definitions(-D_LINUX) add_definitions(-D_LINUX)
elseif(WIN32) elseif(WIN32)
@ -181,11 +181,11 @@ endif()
# Packaging with CPack! # Packaging with CPack!
IF(UNIX) IF(UNIX)
if(APPLE) if(APPLE)
SET(CPACK_GENERATOR "ZIP") SET(CPACK_GENERATOR "ZIP")
else() else()
SET(CPACK_GENERATOR "TGZ") SET(CPACK_GENERATOR "TGZ")
endif() endif()
ELSEIF(WIN32) ELSEIF(WIN32)
SET(CPACK_GENERATOR "ZIP") SET(CPACK_GENERATOR "ZIP")
ENDIF() ENDIF()

@ -167,7 +167,7 @@ IF(UNIX)
IF(BUILD_EGGY) IF(BUILD_EGGY)
LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_LINUX_EGGY}) LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_LINUX_EGGY})
ELSEIF(APPLE) ELSEIF(APPLE)
LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_DARWIN}) LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_DARWIN})
ELSE() ELSE()
LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_LINUX}) LIST(APPEND PROJECT_SOURCES ${MAIN_SOURCES_LINUX})
ENDIF() ENDIF()
@ -235,7 +235,7 @@ ENDIF()
IF(UNIX) IF(UNIX)
SET(PROJECT_LIBS rt dl dfhack-md5 dfhack-tinyxml dfhack-tinythread) SET(PROJECT_LIBS rt dl dfhack-md5 dfhack-tinyxml dfhack-tinythread)
IF(APPLE) IF(APPLE)
SET(PROJECT_LIBS dl dfhack-md5 dfhack-tinyxml dfhack-tinythread) SET(PROJECT_LIBS dl dfhack-md5 dfhack-tinyxml dfhack-tinythread)
ENDIF() ENDIF()
ELSE(WIN32) ELSE(WIN32)
#FIXME: do we really need psapi? #FIXME: do we really need psapi?
@ -273,14 +273,14 @@ ENDIF()
SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" ) SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" )
IF(APPLE) IF(APPLE)
SET(SDL_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/SDL.framework) SET(SDL_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/SDL.framework)
SET(CXX_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/libstdc++.6.dylib) SET(CXX_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/libstdc++.6.dylib)
SET(ZIP_LIBRARY /usr/lib/libz.dylib) SET(ZIP_LIBRARY /usr/lib/libz.dylib)
TARGET_LINK_LIBRARIES(dfhack ${SDL_LIBRARY}) TARGET_LINK_LIBRARIES(dfhack ${SDL_LIBRARY})
TARGET_LINK_LIBRARIES(dfhack ${CXX_LIBRARY}) TARGET_LINK_LIBRARIES(dfhack ${CXX_LIBRARY})
TARGET_LINK_LIBRARIES(dfhack ${ZIP_LIBRARY}) TARGET_LINK_LIBRARIES(dfhack ${ZIP_LIBRARY})
SET_TARGET_PROPERTIES(dfhack PROPERTIES VERSION 1.0.0) SET_TARGET_PROPERTIES(dfhack PROPERTIES VERSION 1.0.0)
SET_TARGET_PROPERTIES(dfhack PROPERTIES SOVERSION 1.0.0) SET_TARGET_PROPERTIES(dfhack PROPERTIES SOVERSION 1.0.0)
ENDIF() ENDIF()
TARGET_LINK_LIBRARIES(dfhack protobuf-lite clsocket lua ${PROJECT_LIBS}) TARGET_LINK_LIBRARIES(dfhack protobuf-lite clsocket lua ${PROJECT_LIBS})
@ -290,20 +290,20 @@ TARGET_LINK_LIBRARIES(dfhack-client protobuf-lite clsocket)
TARGET_LINK_LIBRARIES(dfhack-run dfhack-client) TARGET_LINK_LIBRARIES(dfhack-run dfhack-client)
if(APPLE) if(APPLE)
add_custom_command(TARGET dfhack-run COMMAND ${dfhack_SOURCE_DIR}/package/darwin/fix-libs.sh WORKING_DIRECTORY ../ COMMENT "Fixing library dependencies...") add_custom_command(TARGET dfhack-run COMMAND ${dfhack_SOURCE_DIR}/package/darwin/fix-libs.sh WORKING_DIRECTORY ../ COMMENT "Fixing library dependencies...")
endif() endif()
IF(UNIX) IF(UNIX)
if (APPLE) if (APPLE)
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/darwin/dfhack install(PROGRAMS ${dfhack_SOURCE_DIR}/package/darwin/dfhack
DESTINATION .) DESTINATION .)
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/darwin/dfhack-run install(PROGRAMS ${dfhack_SOURCE_DIR}/package/darwin/dfhack-run
DESTINATION .) DESTINATION .)
else() else()
# On linux, copy our version of the df launch script which sets LD_PRELOAD # On linux, copy our version of the df launch script which sets LD_PRELOAD
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack
DESTINATION .) DESTINATION .)
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack-run install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack-run
DESTINATION .) DESTINATION .)
endif() endif()
ELSE() ELSE()

@ -375,7 +375,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
" reload PLUGIN|all - Reload a plugin or all loaded plugins.\n" " reload PLUGIN|all - Reload a plugin or all loaded plugins.\n"
); );
con.print("\nDFHack version " DFHACK_VERSION ".\n"); con.print("\nDFHack version " DFHACK_VERSION ".\n");
} }
else if (parts.size() == 1) else if (parts.size() == 1)
{ {
@ -747,13 +747,13 @@ void fIOthread(void * iodata)
else if(ret) else if(ret)
{ {
// a proper, non-empty command was entered // a proper, non-empty command was entered
fprintf(stderr,"Adding command to history\n"); fprintf(stderr,"Adding command to history\n");
main_history.add(command); main_history.add(command);
fprintf(stderr,"Saving history\n"); fprintf(stderr,"Saving history\n");
main_history.save("dfhack.history"); main_history.save("dfhack.history");
} }
fprintf(stderr,"Running command\n"); fprintf(stderr,"Running command\n");
auto rv = core->runCommand(con, command); auto rv = core->runCommand(con, command);

@ -271,39 +271,39 @@ DFhackCExport vPtr SDL_SetVideoMode(int width, int height, int bpp, uint32_t fla
static int (*_SDL_UpperBlit)(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect) = 0; static int (*_SDL_UpperBlit)(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect) = 0;
DFhackCExport int SDL_UpperBlit(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect) DFhackCExport int SDL_UpperBlit(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect)
{ {
if ( dstrect != NULL && dstrect->h != 0 && dstrect->w != 0 ) if ( dstrect != NULL && dstrect->h != 0 && dstrect->w != 0 )
{ {
DFHack::Core & c = DFHack::Core::getInstance(); DFHack::Core & c = DFHack::Core::getInstance();
DFHack::Graphic* g = c.getGraphic(); DFHack::Graphic* g = c.getGraphic();
DFHack::DFTileSurface* ov = g->Call(dstrect->x/dstrect->w, dstrect->y/dstrect->h); DFHack::DFTileSurface* ov = g->Call(dstrect->x/dstrect->w, dstrect->y/dstrect->h);
if ( ov != NULL ) if ( ov != NULL )
{ {
if ( ov->paintOver ) if ( ov->paintOver )
{ {
_SDL_UpperBlit(src, srcrect, dst, dstrect); _SDL_UpperBlit(src, srcrect, dst, dstrect);
} }
DFHack::DFSDL_Rect* dstrect2 = new DFHack::DFSDL_Rect; DFHack::DFSDL_Rect* dstrect2 = new DFHack::DFSDL_Rect;
dstrect2->x = dstrect->x; dstrect2->x = dstrect->x;
dstrect2->y = dstrect->y; dstrect2->y = dstrect->y;
dstrect2->w = dstrect->w; dstrect2->w = dstrect->w;
dstrect2->h = dstrect->h; dstrect2->h = dstrect->h;
if ( ov->dstResize != NULL ) if ( ov->dstResize != NULL )
{ {
DFHack::DFSDL_Rect* r = (DFHack::DFSDL_Rect*)ov->dstResize; DFHack::DFSDL_Rect* r = (DFHack::DFSDL_Rect*)ov->dstResize;
dstrect2->x += r->x; dstrect2->x += r->x;
dstrect2->y += r->y; dstrect2->y += r->y;
dstrect2->w += r->w; dstrect2->w += r->w;
dstrect2->h += r->h; dstrect2->h += r->h;
} }
int result = _SDL_UpperBlit(ov->surface, ov->rect, dst, dstrect2); int result = _SDL_UpperBlit(ov->surface, ov->rect, dst, dstrect2);
delete dstrect2; delete dstrect2;
return result; return result;
} }
} }
return _SDL_UpperBlit(src, srcrect, dst, dstrect); return _SDL_UpperBlit(src, srcrect, dst, dstrect);
} }

@ -9,14 +9,14 @@
NSAutoreleasePool *thePool; NSAutoreleasePool *thePool;
int create_pool() { int create_pool() {
fprintf(stderr,"Creating autorelease pool\n"); fprintf(stderr,"Creating autorelease pool\n");
thePool = [[NSAutoreleasePool alloc] init]; thePool = [[NSAutoreleasePool alloc] init];
return 1; return 1;
} }
int destroy_pool() { int destroy_pool() {
fprintf(stderr,"Draining and releasing autorelease pool\n"); fprintf(stderr,"Draining and releasing autorelease pool\n");
[thePool drain]; [thePool drain];
[thePool release]; [thePool release];
return 0; return 0;
} }

@ -50,13 +50,13 @@ using namespace DFHack;
Process::Process(VersionInfoFactory * known_versions) Process::Process(VersionInfoFactory * known_versions)
{ {
int target_result; int target_result;
char path[1024]; char path[1024];
char *real_path; char *real_path;
uint32_t size = sizeof(path); uint32_t size = sizeof(path);
if (_NSGetExecutablePath(path, &size) == 0) { if (_NSGetExecutablePath(path, &size) == 0) {
real_path = realpath(path, NULL); real_path = realpath(path, NULL);
} }
identified = false; identified = false;
my_descriptor = 0; my_descriptor = 0;
@ -166,29 +166,29 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
(vm_region_info_t)&info, &info_count, &object); (vm_region_info_t)&info, &info_count, &object);
if (kr == KERN_SUCCESS) { if (kr == KERN_SUCCESS) {
if (info.reserved==1) { if (info.reserved==1) {
address += vmsize; address += vmsize;
continue; continue;
} }
Dl_info dlinfo; Dl_info dlinfo;
int dlcheck; int dlcheck;
dlcheck = dladdr((const void*)address, &dlinfo); dlcheck = dladdr((const void*)address, &dlinfo);
if (dlcheck==0) { if (dlcheck==0) {
dlinfo.dli_fname = ""; dlinfo.dli_fname = "";
} }
t_memrange temp; t_memrange temp;
strncpy( temp.name, dlinfo.dli_fname, 1023 ); strncpy( temp.name, dlinfo.dli_fname, 1023 );
temp.name[1023] = 0; temp.name[1023] = 0;
temp.start = (void *) address; temp.start = (void *) address;
temp.end = (void *) (address+vmsize); temp.end = (void *) (address+vmsize);
temp.read = (info.protection & VM_PROT_READ); temp.read = (info.protection & VM_PROT_READ);
temp.write = (info.protection & VM_PROT_WRITE); temp.write = (info.protection & VM_PROT_WRITE);
temp.execute = (info.protection & VM_PROT_EXECUTE); temp.execute = (info.protection & VM_PROT_EXECUTE);
temp.shared = info.shared; temp.shared = info.shared;
temp.valid = true; temp.valid = true;
ranges.push_back(temp); ranges.push_back(temp);
fprintf(stderr, fprintf(stderr,
"%08x-%08x %8uK %c%c%c/%c%c%c %11s %6s %10s uwir=%hu sub=%u dlname: %s\n", "%08x-%08x %8uK %c%c%c/%c%c%c %11s %6s %10s uwir=%hu sub=%u dlname: %s\n",
address, (address + vmsize), (vmsize >> 10), address, (address + vmsize), (vmsize >> 10),
(info.protection & VM_PROT_READ) ? 'r' : '-', (info.protection & VM_PROT_READ) ? 'r' : '-',
@ -203,7 +203,7 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
info.user_wired_count, info.user_wired_count,
info.reserved, info.reserved,
dlinfo.dli_fname); dlinfo.dli_fname);
address += vmsize; address += vmsize;
} else if (kr != KERN_INVALID_ADDRESS) { } else if (kr != KERN_INVALID_ADDRESS) {
@ -277,15 +277,15 @@ uint32_t Process::getTickCount()
string Process::getPath() string Process::getPath()
{ {
char path[1024]; char path[1024];
char *real_path; char *real_path;
uint32_t size = sizeof(path); uint32_t size = sizeof(path);
if (_NSGetExecutablePath(path, &size) == 0) { if (_NSGetExecutablePath(path, &size) == 0) {
real_path = realpath(path, NULL); real_path = realpath(path, NULL);
} }
std::string path_string(real_path); std::string path_string(real_path);
int last_slash = path_string.find_last_of("/"); int last_slash = path_string.find_last_of("/");
std::string directory = path_string.substr(0,last_slash); std::string directory = path_string.substr(0,last_slash);
return directory; return directory;
} }

@ -65,20 +65,20 @@ namespace DFHack
bool save (const char * filename) bool save (const char * filename)
{ {
std::ofstream outfile (filename); std::ofstream outfile (filename);
//fprintf(stderr,"Save: Initialized stream\n"); //fprintf(stderr,"Save: Initialized stream\n");
if(outfile.bad()) if(outfile.bad())
return false; return false;
//fprintf(stderr,"Save: Iterating...\n"); //fprintf(stderr,"Save: Iterating...\n");
for(auto iter = history.begin();iter < history.end(); iter++) for(auto iter = history.begin();iter < history.end(); iter++)
{ {
//fprintf(stderr,"Save: Dumping %s\n",(*iter).c_str()); //fprintf(stderr,"Save: Dumping %s\n",(*iter).c_str());
outfile << *iter << std::endl; outfile << *iter << std::endl;
//fprintf(stderr,"Save: Flushing\n"); //fprintf(stderr,"Save: Flushing\n");
outfile.flush(); outfile.flush();
} }
//fprintf(stderr,"Save: Closing\n"); //fprintf(stderr,"Save: Closing\n");
outfile.close(); outfile.close();
//fprintf(stderr,"Save: Done\n"); //fprintf(stderr,"Save: Done\n");
return true; return true;
} }
/// add a command to the history /// add a command to the history

@ -35,7 +35,7 @@ distribution.
// Stop some MS stupidity // Stop some MS stupidity
#ifdef interface #ifdef interface
#undef interface #undef interface
#endif #endif
typedef struct lua_State lua_State; typedef struct lua_State lua_State;

@ -41,7 +41,7 @@ namespace DFHack
struct struct
{ {
//Maybe should add 'up' and 'down' for Z-levels? //Maybe should add 'up' and 'down' for Z-levels?
unsigned char north,south,west,east; unsigned char north,south,west,east;
}; };
inline TileDirection() inline TileDirection()

@ -36,55 +36,55 @@ distribution.
namespace DFHack namespace DFHack
{ {
// SDL stuff // SDL stuff
typedef signed short SINT16; typedef signed short SINT16;
typedef struct typedef struct
{ {
int16_t x, y; int16_t x, y;
uint16_t w, h; uint16_t w, h;
} DFSDL_Rect; } DFSDL_Rect;
typedef struct typedef struct
{ {
uint32_t flags; uint32_t flags;
void* format; // PixelFormat* void* format; // PixelFormat*
int w, h; int w, h;
int pitch; int pitch;
void* pixels; void* pixels;
void* userdata; // as far as i could see DF doesnt use this void* userdata; // as far as i could see DF doesnt use this
int locked; int locked;
void* lock_data; void* lock_data;
DFSDL_Rect clip_rect; DFSDL_Rect clip_rect;
void* map; void* map;
int refcount; int refcount;
} DFSDL_Surface; } DFSDL_Surface;
// ========= // =========
struct DFTileSurface struct DFTileSurface
{ {
bool paintOver; // draw over original tile? bool paintOver; // draw over original tile?
DFSDL_Surface* surface; // from where it should be drawn DFSDL_Surface* surface; // from where it should be drawn
DFSDL_Rect* rect; // from which coords (NULL to draw whole surface) DFSDL_Rect* rect; // from which coords (NULL to draw whole surface)
DFSDL_Rect* dstResize; // if not NULL dst rect will be resized (x/y/w/h will be added to original dst) DFSDL_Rect* dstResize; // if not NULL dst rect will be resized (x/y/w/h will be added to original dst)
}; };
class DFHACK_EXPORT Graphic : public Module class DFHACK_EXPORT Graphic : public Module
{ {
public: public:
Graphic(); Graphic();
~Graphic(); ~Graphic();
bool Finish() bool Finish()
{ {
return true; return true;
} }
bool Register(DFTileSurface* (*func)(int,int)); bool Register(DFTileSurface* (*func)(int,int));
bool Unregister(DFTileSurface* (*func)(int,int)); bool Unregister(DFTileSurface* (*func)(int,int));
DFTileSurface* Call(int x, int y); DFTileSurface* Call(int x, int y);
private: private:
struct Private; struct Private;
Private *d; Private *d;
}; };
} }

@ -48,63 +48,63 @@ Module* DFHack::createGraphic()
struct Graphic::Private struct Graphic::Private
{ {
bool Started; bool Started;
vector<DFTileSurface* (*)(int,int)> funcs; vector<DFTileSurface* (*)(int,int)> funcs;
}; };
Graphic::Graphic() Graphic::Graphic()
{ {
d = new Private; d = new Private;
d->Started = true; d->Started = true;
} }
Graphic::~Graphic() Graphic::~Graphic()
{ {
delete d; delete d;
} }
bool Graphic::Register(DFTileSurface* (*func)(int,int)) bool Graphic::Register(DFTileSurface* (*func)(int,int))
{ {
d->funcs.push_back(func); d->funcs.push_back(func);
return true; return true;
} }
bool Graphic::Unregister(DFTileSurface* (*func)(int,int)) bool Graphic::Unregister(DFTileSurface* (*func)(int,int))
{ {
if ( d->funcs.empty() ) return false; if ( d->funcs.empty() ) return false;
vector<DFTileSurface* (*)(int,int)>::iterator it = d->funcs.begin(); vector<DFTileSurface* (*)(int,int)>::iterator it = d->funcs.begin();
while ( it != d->funcs.end() ) while ( it != d->funcs.end() )
{ {
if ( *it == func ) if ( *it == func )
{ {
d->funcs.erase(it); d->funcs.erase(it);
return true; return true;
} }
it++; it++;
} }
return false; return false;
} }
// This will return first DFTileSurface it can get (or NULL if theres none) // This will return first DFTileSurface it can get (or NULL if theres none)
DFTileSurface* Graphic::Call(int x, int y) DFTileSurface* Graphic::Call(int x, int y)
{ {
if ( d->funcs.empty() ) return NULL; if ( d->funcs.empty() ) return NULL;
DFTileSurface* temp = NULL; DFTileSurface* temp = NULL;
vector<DFTileSurface* (*)(int,int)>::iterator it = d->funcs.begin(); vector<DFTileSurface* (*)(int,int)>::iterator it = d->funcs.begin();
while ( it != d->funcs.end() ) while ( it != d->funcs.end() )
{ {
temp = (*it)(x,y); temp = (*it)(x,y);
if ( temp != NULL ) if ( temp != NULL )
{ {
return temp; return temp;
} }
it++; it++;
} }
return NULL; return NULL;
} }

@ -117,7 +117,7 @@ command_result df_cleanowned (color_ostream &out, vector <string> & parameters)
else if (item->flags.bits.on_ground) else if (item->flags.bits.on_ground)
{ {
df::item_type type = item->getType(); df::item_type type = item->getType();
if(type == item_type::MEAT || if(type == item_type::MEAT ||
type == item_type::FISH || type == item_type::FISH ||
type == item_type::VERMIN || type == item_type::VERMIN ||
type == item_type::PET || type == item_type::PET ||

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

@ -35,32 +35,32 @@ static bool enabled = false;
static void eggscan(color_ostream &out) static void eggscan(color_ostream &out)
{ {
CoreSuspender suspend; CoreSuspender suspend;
for (int i = 0; i < world->buildings.all.size(); ++i) for (int i = 0; i < world->buildings.all.size(); ++i)
{ {
df::building *build = world->buildings.all[i]; df::building *build = world->buildings.all[i];
auto type = build->getType(); auto type = build->getType();
if (df::enums::building_type::NestBox == type) if (df::enums::building_type::NestBox == type)
{ {
bool fertile = false; bool fertile = false;
df::building_nest_boxst *nb = virtual_cast<df::building_nest_boxst>(build); df::building_nest_boxst *nb = virtual_cast<df::building_nest_boxst>(build);
if (nb->claimed_by != -1) if (nb->claimed_by != -1)
{ {
df::unit* u = df::unit::find(nb->claimed_by); df::unit* u = df::unit::find(nb->claimed_by);
if (u && u->relations.pregnancy_timer > 0) if (u && u->relations.pregnancy_timer > 0)
fertile = true; fertile = true;
} }
for (int j = 1; j < nb->contained_items.size(); j++) for (int j = 1; j < nb->contained_items.size(); j++)
{ {
df::item* item = nb->contained_items[j]->item; df::item* item = nb->contained_items[j]->item;
if (item->flags.bits.forbid != fertile) if (item->flags.bits.forbid != fertile)
{ {
item->flags.bits.forbid = fertile; item->flags.bits.forbid = fertile;
out << item->getStackSize() << " eggs " << (fertile ? "forbidden" : "unforbidden.") << endl; out << item->getStackSize() << " eggs " << (fertile ? "forbidden" : "unforbidden.") << endl;
} }
} }
} }
} }
} }
@ -68,12 +68,12 @@ static void eggscan(color_ostream &out)
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
if (world && ui) { if (world && ui) {
commands.push_back( commands.push_back(
PluginCommand("nestboxes", "Derp.", PluginCommand("nestboxes", "Derp.",
nestboxes, false, nestboxes, false,
"Derp.\n" "Derp.\n"
) )
); );
} }
return CR_OK; return CR_OK;
} }
@ -92,28 +92,28 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out)
if ((++cnt % 5) != 0) if ((++cnt % 5) != 0)
return CR_OK; return CR_OK;
eggscan(out); eggscan(out);
return CR_OK; return CR_OK;
} }
static command_result nestboxes(color_ostream &out, vector <string> & parameters) static command_result nestboxes(color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend; CoreSuspender suspend;
bool clean = false; bool clean = false;
int dump_count = 0; int dump_count = 0;
int good_egg = 0; int good_egg = 0;
if (parameters.size() == 1) { if (parameters.size() == 1) {
if (parameters[0] == "enable") if (parameters[0] == "enable")
enabled = true; enabled = true;
else if (parameters[0] == "disable") else if (parameters[0] == "disable")
enabled = false; enabled = false;
else else
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} else { } else {
out << "Plugin " << (enabled ? "enabled" : "disabled") << "." << endl; out << "Plugin " << (enabled ? "enabled" : "disabled") << "." << endl;
} }
return CR_OK; return CR_OK;
} }

@ -67,10 +67,10 @@ command_result rprobe (color_ostream &out, vector <string> & parameters)
// Embark screen active: estimate using world geology data // Embark screen active: estimate using world geology data
VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, Core::getTopViewscreen()); VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, Core::getTopViewscreen());
if (!screen) if (!screen)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
if (!world || !world->world_data) if (!world || !world->world_data)
{ {
out.printerr("World data is not available.\n"); out.printerr("World data is not available.\n");
@ -78,9 +78,9 @@ command_result rprobe (color_ostream &out, vector <string> & parameters)
} }
if (parameters.size() == 2) if (parameters.size() == 2)
{ {
if (parameters[0] == "rai") if (parameters[0] == "rai")
set_field = 0; set_field = 0;
else if (parameters[0] == "veg") else if (parameters[0] == "veg")
set_field = 1; set_field = 1;
@ -97,7 +97,7 @@ command_result rprobe (color_ostream &out, vector <string> & parameters)
else else
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
if (screen->biome_highlighted) if (screen->biome_highlighted)
to_set = screen->biome_idx; to_set = screen->biome_idx;
else else
to_set = 0; to_set = 0;
@ -110,7 +110,7 @@ command_result rprobe (color_ostream &out, vector <string> & parameters)
coord2d cur_region = screen->region_pos; coord2d cur_region = screen->region_pos;
// Compute biomes // Compute biomes
for (int i = 0; i < screen->biome_rgn.size(); i++) for (int i = 0; i < screen->biome_rgn.size(); i++)
{ {
coord2d rg = screen->biome_rgn[i]; coord2d rg = screen->biome_rgn[i];
@ -140,7 +140,7 @@ command_result rprobe (color_ostream &out, vector <string> & parameters)
" geo_index: " << rd->geo_index << " geo_index: " << rd->geo_index <<
" landmass_id: " << rd->landmass_id << " landmass_id: " << rd->landmass_id <<
" flags: " << hex << rd->flags.as_int() << dec << endl; " flags: " << hex << rd->flags.as_int() << dec << endl;
out << out <<
"rai: " << rd->rainfall << " " << "rai: " << rd->rainfall << " " <<
"veg: " << rd->vegetation << " " << "veg: " << rd->vegetation << " " <<
"tem: " << rd->temperature << " " << "tem: " << rd->temperature << " " <<
@ -148,17 +148,17 @@ command_result rprobe (color_ostream &out, vector <string> & parameters)
"dra: " << rd->drainage << " " << "dra: " << rd->drainage << " " <<
"sav: " << rd->savagery << " " << "sav: " << rd->savagery << " " <<
"sal: " << rd->salinity; "sal: " << rd->salinity;
int32_t *p = (int32_t *)rd; int32_t *p = (int32_t *)rd;
int c = sizeof(*rd) / sizeof(int32_t); int c = sizeof(*rd) / sizeof(int32_t);
for (int j = 0; j < c; j++) { for (int j = 0; j < c; j++) {
if (j % 8 == 0) if (j % 8 == 0)
out << endl << setfill('0') << setw(8) << hex << (int)(rd+j) << ": "; out << endl << setfill('0') << setw(8) << hex << (int)(rd+j) << ": ";
out << " " << setfill('0') << setw(8) << hex << p[j]; out << " " << setfill('0') << setw(8) << hex << p[j];
} }
out << setfill(' ') << setw(0) << dec << endl; out << setfill(' ') << setw(0) << dec << endl;
} }
return CR_OK; return CR_OK;
} }

@ -38,12 +38,12 @@ DFHACK_PLUGIN("stockcheck");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
if (world && ui) { if (world && ui) {
commands.push_back( commands.push_back(
PluginCommand("stockcheck", "Check for unprotected rottable items.", PluginCommand("stockcheck", "Check for unprotected rottable items.",
stockcheck, false, stockcheck, false,
"Scan world for items that are susceptible to rot. Currently just lists the items.\n" "Scan world for items that are susceptible to rot. Currently just lists the items.\n"
) )
); );
} }
return CR_OK; return CR_OK;
} }
@ -54,90 +54,90 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
} }
struct StockpileInfo { struct StockpileInfo {
building_stockpilest* sp; building_stockpilest* sp;
int size; int size;
int free; int free;
int x1, x2, y1, y2, z; int x1, x2, y1, y2, z;
public: public:
StockpileInfo(building_stockpilest *sp_) : sp(sp_) StockpileInfo(building_stockpilest *sp_) : sp(sp_)
{ {
MapExtras::MapCache mc; MapExtras::MapCache mc;
z = sp_->z; z = sp_->z;
x1 = sp_->room.x; x1 = sp_->room.x;
x2 = sp_->room.x + sp_->room.width; x2 = sp_->room.x + sp_->room.width;
y1 = sp_->room.y; y1 = sp_->room.y;
y2 = sp_->room.y + sp_->room.height; y2 = sp_->room.y + sp_->room.height;
int e = 0; int e = 0;
size = 0; size = 0;
free = 0; free = 0;
for (int y = y1; y < y2; y++) for (int y = y1; y < y2; y++)
for (int x = x1; x < x2; x++) for (int x = x1; x < x2; x++)
if (sp_->room.extents[e++] == 1) if (sp_->room.extents[e++] == 1)
{ {
size++; size++;
DFCoord cursor (x,y,z); DFCoord cursor (x,y,z);
uint32_t blockX = x / 16; uint32_t blockX = x / 16;
uint32_t tileX = x % 16; uint32_t tileX = x % 16;
uint32_t blockY = y / 16; uint32_t blockY = y / 16;
uint32_t tileY = y % 16; uint32_t tileY = y % 16;
MapExtras::Block * b = mc.BlockAt(cursor/16); MapExtras::Block * b = mc.BlockAt(cursor/16);
if(b && b->is_valid()) if(b && b->is_valid())
{ {
auto &block = *b->getRaw(); auto &block = *b->getRaw();
df::tile_occupancy &occ = block.occupancy[tileX][tileY]; df::tile_occupancy &occ = block.occupancy[tileX][tileY];
if (!occ.bits.item) if (!occ.bits.item)
free++; free++;
} }
} }
} }
bool isFull() { return free == 0; } bool isFull() { return free == 0; }
bool canHold(df::item *i) bool canHold(df::item *i)
{ {
return false; return false;
} }
bool inStockpile(df::item *i) bool inStockpile(df::item *i)
{ {
df::item *container = Items::getContainer(i); df::item *container = Items::getContainer(i);
if (container) if (container)
return inStockpile(container); return inStockpile(container);
if (i->pos.z != z) return false; if (i->pos.z != z) return false;
if (i->pos.x < x1 || i->pos.x >= x2 || if (i->pos.x < x1 || i->pos.x >= x2 ||
i->pos.y < y1 || i->pos.y >= y2) return false; i->pos.y < y1 || i->pos.y >= y2) return false;
int e = (i->pos.x - x1) + (i->pos.y - y1) * sp->room.width; int e = (i->pos.x - x1) + (i->pos.y - y1) * sp->room.width;
return sp->room.extents[e] == 1; return sp->room.extents[e] == 1;
} }
int getId() { return sp->id; } int getId() { return sp->id; }
}; };
static command_result stockcheck(color_ostream &out, vector <string> & parameters) static command_result stockcheck(color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend; CoreSuspender suspend;
std::vector<StockpileInfo*> stockpiles; std::vector<StockpileInfo*> stockpiles;
for (int i = 0; i < world->buildings.all.size(); ++i) for (int i = 0; i < world->buildings.all.size(); ++i)
{ {
df::building *build = world->buildings.all[i]; df::building *build = world->buildings.all[i];
auto type = build->getType(); auto type = build->getType();
if (df::enums::building_type::Stockpile == type) if (df::enums::building_type::Stockpile == type)
{ {
building_stockpilest *sp = virtual_cast<building_stockpilest>(build); building_stockpilest *sp = virtual_cast<building_stockpilest>(build);
StockpileInfo *spi = new StockpileInfo(sp); StockpileInfo *spi = new StockpileInfo(sp);
stockpiles.push_back(spi); stockpiles.push_back(spi);
} }
} }
std::vector<df::item*> &items = world->items.other[items_other_id::IN_PLAY]; std::vector<df::item*> &items = world->items.other[items_other_id::IN_PLAY];
// Precompute a bitmask with the bad flags // Precompute a bitmask with the bad flags
df::item_flags bad_flags; df::item_flags bad_flags;
bad_flags.whole = 0; bad_flags.whole = 0;
@ -145,30 +145,30 @@ static command_result stockcheck(color_ostream &out, vector <string> & parameter
F(dump); F(forbid); F(garbage_collect); F(dump); F(forbid); F(garbage_collect);
F(hostile); F(on_fire); F(rotten); F(trader); F(hostile); F(on_fire); F(rotten); F(trader);
F(in_building); F(construction); F(artifact1); F(in_building); F(construction); F(artifact1);
F(spider_web); F(owned); F(in_job); F(spider_web); F(owned); F(in_job);
#undef F #undef F
for (size_t i = 0; i < items.size(); i++) for (size_t i = 0; i < items.size(); i++)
{ {
df::item *item = items[i]; df::item *item = items[i];
if (item->flags.whole & bad_flags.whole) if (item->flags.whole & bad_flags.whole)
continue; continue;
// we really only care about MEAT, FISH, FISH_RAW, PLANT, CHEESE, FOOD, and EGG // we really only care about MEAT, FISH, FISH_RAW, PLANT, CHEESE, FOOD, and EGG
df::item_type typ = item->getType(); df::item_type typ = item->getType();
if (typ != df::enums::item_type::MEAT && if (typ != df::enums::item_type::MEAT &&
typ != df::enums::item_type::FISH && typ != df::enums::item_type::FISH &&
typ != df::enums::item_type::FISH_RAW && typ != df::enums::item_type::FISH_RAW &&
typ != df::enums::item_type::PLANT && typ != df::enums::item_type::PLANT &&
typ != df::enums::item_type::CHEESE && typ != df::enums::item_type::CHEESE &&
typ != df::enums::item_type::FOOD && typ != df::enums::item_type::FOOD &&
typ != df::enums::item_type::EGG) typ != df::enums::item_type::EGG)
continue; continue;
df::item *container = 0; df::item *container = 0;
df::unit *holder = 0; df::unit *holder = 0;
df::building *building = 0; df::building *building = 0;
for (size_t i = 0; i < item->general_refs.size(); i++) for (size_t i = 0; i < item->general_refs.size(); i++)
{ {
@ -177,106 +177,106 @@ static command_result stockcheck(color_ostream &out, vector <string> & parameter
switch (ref->getType()) switch (ref->getType())
{ {
case general_ref_type::CONTAINED_IN_ITEM: case general_ref_type::CONTAINED_IN_ITEM:
container = ref->getItem(); container = ref->getItem();
break; break;
case general_ref_type::UNIT_HOLDER: case general_ref_type::UNIT_HOLDER:
holder = ref->getUnit(); holder = ref->getUnit();
break; break;
case general_ref_type::BUILDING_HOLDER: case general_ref_type::BUILDING_HOLDER:
building = ref->getBuilding(); building = ref->getBuilding();
break; break;
default: default:
break; break;
} }
} }
df::item *nextcontainer = container; df::item *nextcontainer = container;
df::item *lastcontainer = 0; df::item *lastcontainer = 0;
while(nextcontainer) { while(nextcontainer) {
df::item *thiscontainer = nextcontainer; df::item *thiscontainer = nextcontainer;
nextcontainer = 0; nextcontainer = 0;
for (size_t i = 0; i < thiscontainer->general_refs.size(); i++) for (size_t i = 0; i < thiscontainer->general_refs.size(); i++)
{ {
df::general_ref *ref = thiscontainer->general_refs[i]; df::general_ref *ref = thiscontainer->general_refs[i];
switch (ref->getType()) switch (ref->getType())
{ {
case general_ref_type::CONTAINED_IN_ITEM: case general_ref_type::CONTAINED_IN_ITEM:
lastcontainer = nextcontainer = ref->getItem(); lastcontainer = nextcontainer = ref->getItem();
break; break;
case general_ref_type::UNIT_HOLDER: case general_ref_type::UNIT_HOLDER:
holder = ref->getUnit(); holder = ref->getUnit();
break; break;
case general_ref_type::BUILDING_HOLDER: case general_ref_type::BUILDING_HOLDER:
building = ref->getBuilding(); building = ref->getBuilding();
break; break;
default: default:
break; break;
} }
} }
} }
if (holder) if (holder)
continue; // carried items do not rot as far as i know continue; // carried items do not rot as far as i know
if (building) { if (building) {
df::building_type btype = building->getType(); df::building_type btype = building->getType();
if (btype == df::enums::building_type::TradeDepot || if (btype == df::enums::building_type::TradeDepot ||
btype == df::enums::building_type::Wagon) btype == df::enums::building_type::Wagon)
continue; // items in trade depot or the embark wagon do not rot continue; // items in trade depot or the embark wagon do not rot
if (typ == df::enums::item_type::EGG && btype ==df::enums::building_type::NestBox) if (typ == df::enums::item_type::EGG && btype ==df::enums::building_type::NestBox)
continue; // eggs in nest box do not rot continue; // eggs in nest box do not rot
} }
int canHoldCount = 0; int canHoldCount = 0;
StockpileInfo *current = 0; StockpileInfo *current = 0;
for (int idx = 0; idx < stockpiles.size(); idx++) for (int idx = 0; idx < stockpiles.size(); idx++)
{ {
StockpileInfo *spi = stockpiles[idx]; StockpileInfo *spi = stockpiles[idx];
if (spi->canHold(item)) canHoldCount++; if (spi->canHold(item)) canHoldCount++;
if (spi->inStockpile(item)) current=spi; if (spi->inStockpile(item)) current=spi;
} }
if (current) if (current)
continue; continue;
std::string description; std::string description;
item->getItemDescription(&description, 0); item->getItemDescription(&description, 0);
out << " * " << description; out << " * " << description;
if (container) { if (container) {
std::string containerDescription; std::string containerDescription;
container->getItemDescription(&containerDescription, 0); container->getItemDescription(&containerDescription, 0);
out << ", in container " << containerDescription; out << ", in container " << containerDescription;
if (lastcontainer) { if (lastcontainer) {
std::string lastcontainerDescription; std::string lastcontainerDescription;
lastcontainer->getItemDescription(&lastcontainerDescription, 0); lastcontainer->getItemDescription(&lastcontainerDescription, 0);
out << ", in container " << lastcontainerDescription; out << ", in container " << lastcontainerDescription;
} }
} }
if (holder) { if (holder) {
out << ", carried"; out << ", carried";
} }
if (building) { if (building) {
out << ", in building " << building->id << " (type=" << building->getType() << ")"; out << ", in building " << building->id << " (type=" << building->getType() << ")";
} }
out << ", flags=" << std::hex << item->flags.whole << std::dec; out << ", flags=" << std::hex << item->flags.whole << std::dec;
out << endl; out << endl;
} }
return CR_OK; return CR_OK;
} }

@ -61,11 +61,11 @@ bool isContainedInItem(df::unit* unit)
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"stripcaged", "strip caged units of all items", "stripcaged", "strip caged units of all items",
df_stripcaged, false, df_stripcaged, false,
"Clears forbid and sets dump for the inventories of all caged units." "Clears forbid and sets dump for the inventories of all caged units."
)); ));
return CR_OK; return CR_OK;
} }
@ -77,39 +77,39 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
command_result df_stripcaged(color_ostream &out, vector <string> & parameters) command_result df_stripcaged(color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend; CoreSuspender suspend;
bool keeparmor = true; bool keeparmor = true;
if (parameters.size() == 1 && parameters[0] == "dumparmor") if (parameters.size() == 1 && parameters[0] == "dumparmor")
{ {
out << "Dumping armor too" << endl; out << "Dumping armor too" << endl;
keeparmor = false; keeparmor = false;
} }
size_t count = 0; size_t count = 0;
for (size_t i=0; i < world->units.all.size(); i++) for (size_t i=0; i < world->units.all.size(); i++)
{ {
df::unit* unit = world->units.all[i]; df::unit* unit = world->units.all[i];
if (isContainedInItem(unit)) if (isContainedInItem(unit))
{ {
for (size_t j=0; j < unit->inventory.size(); j++) for (size_t j=0; j < unit->inventory.size(); j++)
{ {
df::unit_inventory_item* uii = unit->inventory[j]; df::unit_inventory_item* uii = unit->inventory[j];
if (uii->item) if (uii->item)
{ {
if (keeparmor && (uii->item->isArmorNotClothing() || uii->item->isClothing())) if (keeparmor && (uii->item->isArmorNotClothing() || uii->item->isClothing()))
continue; continue;
std::string desc; std::string desc;
uii->item->getItemDescription(&desc,0); uii->item->getItemDescription(&desc,0);
out << "Item " << desc << " dumped." << endl; out << "Item " << desc << " dumped." << endl;
uii->item->flags.bits.forbid = 0; uii->item->flags.bits.forbid = 0;
uii->item->flags.bits.dump = 1; uii->item->flags.bits.dump = 1;
count++; count++;
} }
} }
} }
} }
out << count << " items marked for dumping" << endl; out << count << " items marked for dumping" << endl;
return CR_OK; return CR_OK;
} }

@ -323,7 +323,7 @@ public:
auto_renderer_decorator & operator=(renderer_decorator *p) { auto_renderer_decorator & operator=(renderer_decorator *p) {
reset(); reset();
this->p = p; this->p = p;
return *this; return *this;
} }
renderer_decorator * get() { renderer_decorator * get() {

@ -1,7 +1,7 @@
// Wide-area traffic designation utility. // Wide-area traffic designation utility.
// Flood-fill from cursor or fill entire map. // Flood-fill from cursor or fill entire map.
#include <ctype.h> //For toupper(). #include <ctype.h> //For toupper().
#include <algorithm> //for min(). #include <algorithm> //for min().
#include <map> #include <map>
#include <vector> #include <vector>

@ -57,161 +57,161 @@ command_result df_forceequip(color_ostream &out, vector <string> & parameters);
const string forceequip_help = const string forceequip_help =
"ForceEquip moves local items into a unit's inventory. It is typically\n" "ForceEquip moves local items into a unit's inventory. It is typically\n"
"used to equip specific clothing/armor items onto a dwarf, but can also\n" "used to equip specific clothing/armor items onto a dwarf, but can also\n"
"be used to put armor onto a war animal or to add unusual items (such\n" "be used to put armor onto a war animal or to add unusual items (such\n"
"as crowns) to any unit.\n" "as crowns) to any unit.\n"
"This plugin can process multiple items in a single call, but will only\n" "This plugin can process multiple items in a single call, but will only\n"
"work with a single unit (the first one it finds under the cursor).\n" "work with a single unit (the first one it finds under the cursor).\n"
"In order to minimize confusion, it is recommended that you use\n" "In order to minimize confusion, it is recommended that you use\n"
"forceequip only when you have a unit standing alone atop a pile of\n" "forceequip only when you have a unit standing alone atop a pile of\n"
"gear that you would like it to wear. Items which are stored in bins\n" "gear that you would like it to wear. Items which are stored in bins\n"
"or other containers (e.g. chests, armor racks) may also work, but\n" "or other containers (e.g. chests, armor racks) may also work, but\n"
"piling items on the floor (via a garbage dump activity zone, of the\n" "piling items on the floor (via a garbage dump activity zone, of the\n"
"DFHack autodump command) is the most reliable way to do it.\n" "DFHack autodump command) is the most reliable way to do it.\n"
"The plugin will ignore any items that are forbidden. Hence, you\n" "The plugin will ignore any items that are forbidden. Hence, you\n"
"can setup a large pile of surplus gear, walk a unit onto it (or\n" "can setup a large pile of surplus gear, walk a unit onto it (or\n"
"pasture an animal on it), unforbid a few items and run forceequip.\n" "pasture an animal on it), unforbid a few items and run forceequip.\n"
"The (forbidden) majority of your gear will remain in-place, ready\n" "The (forbidden) majority of your gear will remain in-place, ready\n"
"for the next passerby." "for the next passerby."
"\n"
"As mentioned above, this plugin can be used to equip items onto\n"
"units (such as animals) which cannot normally equip gear. There's\n"
"an important caveat here - such creatures will automatically drop\n"
"inappropriate gear almost immediately (within 10 game ticks).\n"
"If you want them to retain their equipment, you must forbid it\n"
"AFTER using forceequip to get it into their inventory.\n"
"This technique can also be used to clothe dwarven infants, but\n"
"only if you're able to separate them from their mothers.\n"
"\n" "\n"
"By default, the forceequip plugin will attempt to avoid\n" "As mentioned above, this plugin can be used to equip items onto\n"
"conflicts and outright cheating. For instance, it will skip\n" "units (such as animals) which cannot normally equip gear. There's\n"
"any item which is flagged for use in a job, and will not\n" "an important caveat here - such creatures will automatically drop\n"
"equip more than one piece of clothing/armor onto any given\n" "inappropriate gear almost immediately (within 10 game ticks).\n"
"body part. These restrictions can be overridden via command\n" "If you want them to retain their equipment, you must forbid it\n"
"switches (see examples below) but doing so puts you at greater\n" "AFTER using forceequip to get it into their inventory.\n"
"risk of unexpected consequences. For instance, a dwarf who\n" "This technique can also be used to clothe dwarven infants, but\n"
"is wearing three breastplates will not be able to move very\n" "only if you're able to separate them from their mothers.\n"
"quickly.\n" "\n"
"\n" "By default, the forceequip plugin will attempt to avoid\n"
"Items equipped by this plugin DO NOT become owned by the\n" "conflicts and outright cheating. For instance, it will skip\n"
"recipient. Adult dwarves are free to adjust their own\n" "any item which is flagged for use in a job, and will not\n"
"wardrobe, and may promptly decide to doff your gear in\n" "equip more than one piece of clothing/armor onto any given\n"
"favour of their owned items. Animals, as described above,\n" "body part. These restrictions can be overridden via command\n"
"will tend to discard ALL clothing immediately unless it is\n" "switches (see examples below) but doing so puts you at greater\n"
"manually forbidden. Armor items seem to be an exception;\n" "risk of unexpected consequences. For instance, a dwarf who\n"
"an animal will tend to retain an equipped suit of mail\n" "is wearing three breastplates will not be able to move very\n"
"even if you neglect to Forbid it.\n" "quickly.\n"
"\n" "\n"
"Please note that armored animals are quite vulnerable to ranged\n" "Items equipped by this plugin DO NOT become owned by the\n"
"attacks. Unlike dwarves, animals cannot block, dodge, or deflect\n" "recipient. Adult dwarves are free to adjust their own\n"
"arrows, and they are slowed by the weight of their armor.\n" "wardrobe, and may promptly decide to doff your gear in\n"
"\n" "favour of their owned items. Animals, as described above,\n"
"This plugin currently does not support weapons.\n" "will tend to discard ALL clothing immediately unless it is\n"
"\n" "manually forbidden. Armor items seem to be an exception;\n"
"Options:\n" "an animal will tend to retain an equipped suit of mail\n"
" here, h - process the unit and item(s) under the cursor.\n" "even if you neglect to Forbid it.\n"
" - This option is enabled by default since the plugin\n" "\n"
" - does not currently support remote equpping.\n" "Please note that armored animals are quite vulnerable to ranged\n"
"attacks. Unlike dwarves, animals cannot block, dodge, or deflect\n"
"arrows, and they are slowed by the weight of their armor.\n"
"\n"
"This plugin currently does not support weapons.\n"
"\n"
"Options:\n"
" here, h - process the unit and item(s) under the cursor.\n"
" - This option is enabled by default since the plugin\n"
" - does not currently support remote equpping.\n"
" ignore, i - bypasses the usual item eligibility checks (such as\n" " ignore, i - bypasses the usual item eligibility checks (such as\n"
" - \"Never equip gear belonging to another dwarf\" and\n" " - \"Never equip gear belonging to another dwarf\" and\n"
" - \"Nobody is allowed to equip a Hive\".)\n" " - \"Nobody is allowed to equip a Hive\".)\n"
" multi, m - bypasses the 1-item-per-bodypart limit, allowing\n" " multi, m - bypasses the 1-item-per-bodypart limit, allowing\n"
" - the unit to receive an unlimited amount of gear.\n" " - the unit to receive an unlimited amount of gear.\n"
" - Can be used legitimately (e.g. mitten + gauntlet)\n" " - Can be used legitimately (e.g. mitten + gauntlet)\n"
" - or for cheating (e.g. twelve breastplates).\n" " - or for cheating (e.g. twelve breastplates).\n"
" m2, m3, m4 - alters the 1-item-per-bodypart limit, allowing\n" " m2, m3, m4 - alters the 1-item-per-bodypart limit, allowing\n"
" - each part to receive 2, 3, or 4 pieces of gear.\n" " - each part to receive 2, 3, or 4 pieces of gear.\n"
" selected, s - rather than processing all items piled at a unit's\n" " selected, s - rather than processing all items piled at a unit's\n"
" - feet, process only the one item currently selected.\n" " - feet, process only the one item currently selected.\n"
" bodypart, bp - must be followed by a bodypart code (e.g. LH).\n" " bodypart, bp - must be followed by a bodypart code (e.g. LH).\n"
" - Instructs the plugin to equip all available items\n" " - Instructs the plugin to equip all available items\n"
" - onto this body part only. Typically used in\n" " - onto this body part only. Typically used in\n"
" - conjunction with the f switch (to over-armor\n" " - conjunction with the f switch (to over-armor\n"
" - a particular bodypart) or the i switch (to equip\n" " - a particular bodypart) or the i switch (to equip\n"
" - an unusual item onto a specific slot).\n" " - an unusual item onto a specific slot).\n"
" verbose, v - provides detailed narration and error messages.\n" " verbose, v - provides detailed narration and error messages.\n"
" - Can be helpful in resolving failures; not needed\n" " - Can be helpful in resolving failures; not needed\n"
" - for casual use.\n" " - for casual use.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
" forceequip\n" " forceequip\n"
" attempts to equip all of the items under the cursor onto the unit\n" " attempts to equip all of the items under the cursor onto the unit\n"
" under the cursor. Uses only clothing/armor items; ignores all\n" " under the cursor. Uses only clothing/armor items; ignores all\n"
" other types. Equips a maximum of 1 item onto each bodypart,\n" " other types. Equips a maximum of 1 item onto each bodypart,\n"
" and equips only \"appropriate\" items in each slot (e.g. glove\n" " and equips only \"appropriate\" items in each slot (e.g. glove\n"
" --> hand). Bypasses any item which might cause a conflict,\n" " --> hand). Bypasses any item which might cause a conflict,\n"
" such as a Boot belonging to a different dwarf.\n" " such as a Boot belonging to a different dwarf.\n"
" forceequip bp LH\n" " forceequip bp LH\n"
" attempts to equip all local items onto the left hand of the local\n" " attempts to equip all local items onto the left hand of the local\n"
" unit. If the hand is already equipped then nothing will happen,\n" " unit. If the hand is already equipped then nothing will happen,\n"
" and if it is not equipped then only one appropriate item (e.g. \n" " and if it is not equipped then only one appropriate item (e.g. \n"
" a single mitten or gauntlet) will be equipped. This command can\n" " a single mitten or gauntlet) will be equipped. This command can\n"
" be useful if you don't want to selectively forbid individual items\n" " be useful if you don't want to selectively forbid individual items\n"
" and simply want the unit to equip, say, a Helmet while leaving\n" " and simply want the unit to equip, say, a Helmet while leaving\n"
" the rest of the pile alone.\n" " the rest of the pile alone.\n"
" forceequip m bp LH\n" " forceequip m bp LH\n"
" as above, but will equip ALL appropriate items onto the unit's\n" " as above, but will equip ALL appropriate items onto the unit's\n"
" left hand. After running this command, it might end up wearing\n" " left hand. After running this command, it might end up wearing\n"
" a dozen left-handed mittens. Use with caution, and remember\n" " a dozen left-handed mittens. Use with caution, and remember\n"
" that dwarves will tend to drop supernumary items ASAP.\n" " that dwarves will tend to drop supernumary items ASAP.\n"
" forceequip m\n" " forceequip m\n"
" as above, but will equip ALL appropriate items onto any\n" " as above, but will equip ALL appropriate items onto any\n"
" appropriate bodypart. Tends to put several boots onto the right\n" " appropriate bodypart. Tends to put several boots onto the right\n"
" foot while leaving the left foot bare.\n" " foot while leaving the left foot bare.\n"
" forceequip m2\n" " forceequip m2\n"
" as above, but will equip up to two appropriate items onto each\n" " as above, but will equip up to two appropriate items onto each\n"
" bodypart. Helps to balance footwear, but doesn't ensure proper\n" " bodypart. Helps to balance footwear, but doesn't ensure proper\n"
" placement (e.g. left foot gets two socks, right foot gets two\n" " placement (e.g. left foot gets two socks, right foot gets two\n"
" shoes). For best results, use \"selected bp LH\" and\n" " shoes). For best results, use \"selected bp LH\" and\n"
" \"selected bp RH\" instead.\n" " \"selected bp RH\" instead.\n"
" forceequip i\n" " forceequip i\n"
" performs the standard \"equip appropriate items onto appropriate\n" " performs the standard \"equip appropriate items onto appropriate\n"
" bodyparts\" logic, but also includes items that would normally\n" " bodyparts\" logic, but also includes items that would normally\n"
" be considered ineligible (such as a sock which is owned by\n" " be considered ineligible (such as a sock which is owned by\n"
" a different dwarf).\n" " a different dwarf).\n"
" forceequip bp NECK\n" " forceequip bp NECK\n"
" attempts to equip any appropriate gear onto the Neck of the\n" " attempts to equip any appropriate gear onto the Neck of the\n"
" local unit. Since the plugin believes that no items are actually\n" " local unit. Since the plugin believes that no items are actually\n"
" appropriate for the Neck slot, this command does nothing.\n" " appropriate for the Neck slot, this command does nothing.\n"
" forceequip i bp NECK\n" " forceequip i bp NECK\n"
" attempts to equip items from the local pile onto the Neck\n" " attempts to equip items from the local pile onto the Neck\n"
" of the local unit. Ignores appropriateness restrictions.\n" " of the local unit. Ignores appropriateness restrictions.\n"
" If there's a millstone or an albatross carcass sitting on\n" " If there's a millstone or an albatross carcass sitting on\n"
" the same square as the targeted unit, then there's a good\n" " the same square as the targeted unit, then there's a good\n"
" chance that it will end up around his neck. For precise\n" " chance that it will end up around his neck. For precise\n"
" control, remember that you can selectively forbid some of\n" " control, remember that you can selectively forbid some of\n"
" the items that are piled on the ground.\n" " the items that are piled on the ground.\n"
" forceequip i m bp NECK\n" " forceequip i m bp NECK\n"
" as above, but equips an unlimited number of items onto the\n" " as above, but equips an unlimited number of items onto the\n"
" targeted bodypart. Effectively, all unforbidden items\n" " targeted bodypart. Effectively, all unforbidden items\n"
" (including helms, millstones, boulders, etc) will be\n" " (including helms, millstones, boulders, etc) will be\n"
" moved from the local pile and placed in the dwarf's\n" " moved from the local pile and placed in the dwarf's\n"
" inventory (specifically, on his neck). When used with\n" " inventory (specifically, on his neck). When used with\n"
" a large pile of goods, this will leave the dwarf heavily\n" " a large pile of goods, this will leave the dwarf heavily\n"
" encumbered and very slow to move.\n" " encumbered and very slow to move.\n"
" forceequip s\n" " forceequip s\n"
" requires that a single item be selected using the k menu.\n" " requires that a single item be selected using the k menu.\n"
" This item must occupy the same square as the target unit,\n" " This item must occupy the same square as the target unit,\n"
" and must be unforbidden. Attempts to equip this single\n" " and must be unforbidden. Attempts to equip this single\n"
" item onto an appropriate slot in the unit's inventory.\n" " item onto an appropriate slot in the unit's inventory.\n"
" Can serve as a quicker alternative to the selective-\n" " Can serve as a quicker alternative to the selective-\n"
" unforbidding approach described above.\n" " unforbidding approach described above.\n"
" forceequip s m i bp HD\n" " forceequip s m i bp HD\n"
" equips the selected item onto the unit's head. Ignores\n" " equips the selected item onto the unit's head. Ignores\n"
" all possible restrictions and conflicts. If you know\n" " all possible restrictions and conflicts. If you know\n"
" exactly what you want to equip, and exactly where you\n" " exactly what you want to equip, and exactly where you\n"
" want it to go, then this is the most straightforward\n" " want it to go, then this is the most straightforward\n"
" and reliable option.\n" " and reliable option.\n"
" forceequip v bp QQQ\n" " forceequip v bp QQQ\n"
" guaranteed to fail (and accomplish nothing) because\n" " guaranteed to fail (and accomplish nothing) because\n"
" there are no bodyparts called QQQ. However, since the\n" " there are no bodyparts called QQQ. However, since the\n"
" verbose switch is used, the resulting error messages\n" " verbose switch is used, the resulting error messages\n"
" will list every bodypart that the unit DOES possess.\n" " will list every bodypart that the unit DOES possess.\n"
" May be useful if you're unfamiliar with the BP codes\n" " May be useful if you're unfamiliar with the BP codes\n"
" used by Dwarf Fortress, or if you're experimenting\n" " used by Dwarf Fortress, or if you're experimenting\n"
" with an exotic creature.\n" " with an exotic creature.\n"
"\n" "\n"
; ;
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{ {
@ -233,7 +233,7 @@ static bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *u
{ {
// Step 1: Check for anti-requisite conditions // Step 1: Check for anti-requisite conditions
df::unit * itemOwner = Items::getOwner(item); df::unit * itemOwner = Items::getOwner(item);
if (ignoreRestrictions) if (ignoreRestrictions)
{ {
// If the ignoreRestrictions cmdline switch was specified, then skip all of the normal preventative rules // If the ignoreRestrictions cmdline switch was specified, then skip all of the normal preventative rules
if (verbose) { Core::print("Skipping integrity checks...\n"); } if (verbose) { Core::print("Skipping integrity checks...\n"); }
@ -244,8 +244,8 @@ static bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *u
return false; return false;
} }
else if (item->getType() != df::enums::item_type::GLOVES && else if (item->getType() != df::enums::item_type::GLOVES &&
item->getType() != df::enums::item_type::HELM && item->getType() != df::enums::item_type::HELM &&
item->getType() != df::enums::item_type::ARMOR && item->getType() != df::enums::item_type::ARMOR &&
item->getType() != df::enums::item_type::PANTS && item->getType() != df::enums::item_type::PANTS &&
item->getType() != df::enums::item_type::SHOES && item->getType() != df::enums::item_type::SHOES &&
!targetBodyPart) !targetBodyPart)
@ -295,7 +295,7 @@ static bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *u
if (verbose) { Core::printerr("Found bodypart %s; not a match; continuing search.\n", currPart->token.c_str()); } if (verbose) { Core::printerr("Found bodypart %s; not a match; continuing search.\n", currPart->token.c_str()); }
continue; continue;
} }
else else
{ {
// The specified body part has not been found, and we've reached the end of the list. Report failure. // The specified body part has not been found, and we've reached the end of the list. Report failure.
if (verbose) { Core::printerr("The specified body part (%s) does not belong to the chosen unit. Please double-check to ensure that your spelling is correct, and that you have not chosen a dismembered bodypart.\n"); } if (verbose) { Core::printerr("The specified body part (%s) does not belong to the chosen unit. Please double-check to ensure that your spelling is correct, and that you have not chosen a dismembered bodypart.\n"); }
@ -366,14 +366,14 @@ static bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *u
// Collision detected; have we reached the limit? // Collision detected; have we reached the limit?
if (++collisions >= multiEquipLimit) if (++collisions >= multiEquipLimit)
{ {
if (verbose) { Core::printerr(" but it already carries %d piece(s) of equipment. Either remove the existing equipment or use the Multi option.\n", multiEquipLimit); } if (verbose) { Core::printerr(" but it already carries %d piece(s) of equipment. Either remove the existing equipment or use the Multi option.\n", multiEquipLimit); }
confirmedBodyPart = NULL; confirmedBodyPart = NULL;
break; break;
} }
} }
} }
if (confirmedBodyPart) if (confirmedBodyPart)
{ {
// Match found; no need to examine any other BPs // Match found; no need to examine any other BPs
if (verbose) { Core::print(" eligibility confirmed..."); } if (verbose) { Core::print(" eligibility confirmed..."); }
@ -412,31 +412,31 @@ static bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *u
command_result df_forceequip(color_ostream &out, vector <string> & parameters) command_result df_forceequip(color_ostream &out, vector <string> & parameters)
{ {
// The "here" option is hardcoded to true, because the plugin currently doesn't support // The "here" option is hardcoded to true, because the plugin currently doesn't support
// equip-at-a-distance (e.g. grab items within 10 squares of the targeted unit) // equip-at-a-distance (e.g. grab items within 10 squares of the targeted unit)
bool here = true; bool here = true;
// For balance (anti-cheating) reasons, the plugin applies a limit on the number of // For balance (anti-cheating) reasons, the plugin applies a limit on the number of
// item that can be equipped on any bodypart. This limit defaults to 1 but can be // item that can be equipped on any bodypart. This limit defaults to 1 but can be
// overridden with cmdline switches. // overridden with cmdline switches.
int multiEquipLimit = 1; int multiEquipLimit = 1;
// The plugin applies several pre-checks in order to reduce the risk of conflict // The plugin applies several pre-checks in order to reduce the risk of conflict
// and unintended side-effects. Most of these checks can be disabled via cmdline // and unintended side-effects. Most of these checks can be disabled via cmdline
bool ignore = false; bool ignore = false;
// By default, the plugin uses all gear piled on the selected square. Optionally, // By default, the plugin uses all gear piled on the selected square. Optionally,
// it can target only a single item (selected on the k menu) instead // it can target only a single item (selected on the k menu) instead
bool selected = false; bool selected = false;
// Most of the plugin's text output is suppressed by default. It can be enabled // Most of the plugin's text output is suppressed by default. It can be enabled
// to provide insight into errors, and/or for debugging purposes. // to provide insight into errors, and/or for debugging purposes.
bool verbose = false; bool verbose = false;
// By default, the plugin will mate each item to an appropriate bodypart. This // By default, the plugin will mate each item to an appropriate bodypart. This
// behaviour can be skipped if the user specifies a particular BP in the cmdline input. // behaviour can be skipped if the user specifies a particular BP in the cmdline input.
std::string targetBodyPartCode; std::string targetBodyPartCode;
// Parse the input // Parse the input
for (size_t i = 0; i < parameters.size(); i++) for (size_t i = 0; i < parameters.size(); i++)
{ {
string & p = parameters[i]; string & p = parameters[i];
if (p == "help" || p == "?" || p == "h" || p == "/?" || p == "info" || p == "man") if (p == "help" || p == "?" || p == "h" || p == "/?" || p == "info" || p == "man")
{ {
out << forceequip_help << endl; out << forceequip_help << endl;
@ -446,34 +446,34 @@ command_result df_forceequip(color_ostream &out, vector <string> & parameters)
{ {
here = true; here = true;
} }
else if (p == "ignore" || p == "i") else if (p == "ignore" || p == "i")
{ {
ignore = true; ignore = true;
} }
else if (p == "multi" || p == "m") else if (p == "multi" || p == "m")
{ {
multiEquipLimit = INT_MAX; multiEquipLimit = INT_MAX;
} }
else if (p == "m2") else if (p == "m2")
{ {
multiEquipLimit = 2; multiEquipLimit = 2;
} }
else if (p == "m3") else if (p == "m3")
{ {
multiEquipLimit = 3; multiEquipLimit = 3;
} }
else if (p == "m4") else if (p == "m4")
{ {
multiEquipLimit = 4; multiEquipLimit = 4;
} }
else if (p == "selected" || p == "s") else if (p == "selected" || p == "s")
{ {
selected = true; selected = true;
} }
else if (p == "verbose" || p == "v") else if (p == "verbose" || p == "v")
{ {
verbose = true; verbose = true;
} }
else if (p == "bodypart" || p == "bp" ) else if (p == "bodypart" || p == "bp" )
{ {
// must be followed by bodypart code (e.g. NECK) // must be followed by bodypart code (e.g. NECK)
@ -492,150 +492,150 @@ command_result df_forceequip(color_ostream &out, vector <string> & parameters)
} }
} }
// Ensure that the map information is available (e.g. a game is actually in-progress) // Ensure that the map information is available (e.g. a game is actually in-progress)
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
out.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
// Lookup the cursor position // Lookup the cursor position
int cx, cy, cz; int cx, cy, cz;
DFCoord pos_cursor; DFCoord pos_cursor;
// needs a cursor // needs a cursor
if (!Gui::getCursorCoords(cx,cy,cz)) if (!Gui::getCursorCoords(cx,cy,cz))
{ {
out.printerr("Cursor position not found. Please enable the cursor.\n"); out.printerr("Cursor position not found. Please enable the cursor.\n");
return CR_FAILURE; return CR_FAILURE;
} }
pos_cursor = DFCoord(cx,cy,cz); pos_cursor = DFCoord(cx,cy,cz);
// Iterate over all units, process the first one whose pos == pos_cursor // Iterate over all units, process the first one whose pos == pos_cursor
df::unit * targetUnit; df::unit * targetUnit;
size_t numUnits = world->units.all.size(); size_t numUnits = world->units.all.size();
for(size_t i=0; i< numUnits; i++) for(size_t i=0; i< numUnits; i++)
{ {
targetUnit = world->units.all[i]; // tentatively assume that we have a match; then verify targetUnit = world->units.all[i]; // tentatively assume that we have a match; then verify
DFCoord pos_unit(targetUnit->pos.x, targetUnit->pos.y, targetUnit->pos.z); DFCoord pos_unit(targetUnit->pos.x, targetUnit->pos.y, targetUnit->pos.z);
if (pos_unit == pos_cursor) if (pos_unit == pos_cursor)
break; break;
if (i + 1 == numUnits) if (i + 1 == numUnits)
{ {
out.printerr("No unit found at cursor!\n"); out.printerr("No unit found at cursor!\n");
return CR_FAILURE; return CR_FAILURE;
} }
} }
// Assert: unit found. // Assert: unit found.
// If a specific bodypart was included in the command arguments, then search for it now // If a specific bodypart was included in the command arguments, then search for it now
df::body_part_raw * targetBodyPart = NULL; df::body_part_raw * targetBodyPart = NULL;
if (targetBodyPartCode.size() > 0) { if (targetBodyPartCode.size() > 0) {
for (int bpIndex = 0; bpIndex < targetUnit->body.body_plan->body_parts.size(); bpIndex ++) for (int bpIndex = 0; bpIndex < targetUnit->body.body_plan->body_parts.size(); bpIndex ++)
{ {
// Tentatively assume that the part is a match // Tentatively assume that the part is a match
targetBodyPart = targetUnit->body.body_plan->body_parts.at(bpIndex); targetBodyPart = targetUnit->body.body_plan->body_parts.at(bpIndex);
if (targetBodyPart->token.compare(targetBodyPartCode) == 0) if (targetBodyPart->token.compare(targetBodyPartCode) == 0)
{ {
// It is indeed a match; exit the loop (while leaving the variable populated) // It is indeed a match; exit the loop (while leaving the variable populated)
if (verbose) { out.print("Matching bodypart (%s) found.\n", targetBodyPart->token.c_str()); } if (verbose) { out.print("Matching bodypart (%s) found.\n", targetBodyPart->token.c_str()); }
break; break;
} }
else else
{ {
// Not a match; nullify the variable (it will get re-populated on the next pass through the loop) // Not a match; nullify the variable (it will get re-populated on the next pass through the loop)
if (verbose) { out.printerr("Bodypart \"%s\" does not match \"%s\".\n", targetBodyPart->token.c_str(), targetBodyPartCode.c_str()); } if (verbose) { out.printerr("Bodypart \"%s\" does not match \"%s\".\n", targetBodyPart->token.c_str(), targetBodyPartCode.c_str()); }
targetBodyPart = NULL; targetBodyPart = NULL;
} }
} }
if (!targetBodyPart) if (!targetBodyPart)
{ {
// Loop iteration is complete but no match was found. // Loop iteration is complete but no match was found.
out.printerr("The unit does not possess a bodypart of type \"%s\". Please check the spelling or choose a different unit.\n", targetBodyPartCode.c_str()); out.printerr("The unit does not possess a bodypart of type \"%s\". Please check the spelling or choose a different unit.\n", targetBodyPartCode.c_str());
return CR_FAILURE; return CR_FAILURE;
} }
} }
// Search for item(s) // Search for item(s)
MapCache mc; MapCache mc;
// iterate over all items, process those where pos == pos_cursor // iterate over all items, process those where pos == pos_cursor
int itemsEquipped = 0; int itemsEquipped = 0;
int itemsFound = 0; int itemsFound = 0;
int numItems = world->items.all.size(); // Normally, we iterate through EVERY ITEM in the world. This is expensive, but currently necessary. int numItems = world->items.all.size(); // Normally, we iterate through EVERY ITEM in the world. This is expensive, but currently necessary.
if (selected) { numItems = 1; } // If the user wants to process only the selected item, then the loop is trivialized (only one pass is needed). if (selected) { numItems = 1; } // If the user wants to process only the selected item, then the loop is trivialized (only one pass is needed).
for(int i=0; i< numItems; i++) for(int i=0; i< numItems; i++)
{ {
df::item * currentItem; df::item * currentItem;
// Search behaviour depends on whether the operation is driven by cursor location or UI selection // Search behaviour depends on whether the operation is driven by cursor location or UI selection
if (selected) if (selected)
{ {
// The "search" is trivial - the selection must always cover either one or zero items // The "search" is trivial - the selection must always cover either one or zero items
currentItem = Gui::getSelectedItem(out); currentItem = Gui::getSelectedItem(out);
if (!currentItem) { return CR_FAILURE; } if (!currentItem) { return CR_FAILURE; }
} }
else else
{ {
// Lookup the current item in the world-space // Lookup the current item in the world-space
currentItem = world->items.all[i]; currentItem = world->items.all[i];
// Test the item's position // Test the item's position
DFCoord pos_item(currentItem->pos.x, currentItem->pos.y, currentItem->pos.z); DFCoord pos_item(currentItem->pos.x, currentItem->pos.y, currentItem->pos.z);
if (pos_item != pos_cursor) if (pos_item != pos_cursor)
{ {
// The item is in the wrong place; skip it // The item is in the wrong place; skip it
// Note: we do not emit any notification, even with the "verbose" switch, because the search space is enormous and we'd invariably flood the UI with useless text // Note: we do not emit any notification, even with the "verbose" switch, because the search space is enormous and we'd invariably flood the UI with useless text
continue; continue;
} }
// Bypass any forbidden items // Bypass any forbidden items
else if (currentItem->flags.bits.forbid == 1) else if (currentItem->flags.bits.forbid == 1)
{ {
// The item is forbidden; skip it // The item is forbidden; skip it
if (verbose) { out.printerr("Forbidden item encountered; skipping to next item.\n"); } if (verbose) { out.printerr("Forbidden item encountered; skipping to next item.\n"); }
} }
} }
// Test the item; check whether we have any grounds to disqualify/reject it // Test the item; check whether we have any grounds to disqualify/reject it
if (currentItem->flags.bits.in_inventory == 1) if (currentItem->flags.bits.in_inventory == 1)
{ {
// The item is in a unit's inventory; skip it // The item is in a unit's inventory; skip it
if (verbose) { out.printerr("Inventory item encountered; skipping to next item.\n"); } if (verbose) { out.printerr("Inventory item encountered; skipping to next item.\n"); }
} }
else else
{ {
itemsFound ++; // Track the number of items found under the cursor (for feedback purposes) itemsFound ++; // Track the number of items found under the cursor (for feedback purposes)
if (moveToInventory(mc, currentItem, targetUnit, targetBodyPart, ignore, multiEquipLimit, verbose)) if (moveToInventory(mc, currentItem, targetUnit, targetBodyPart, ignore, multiEquipLimit, verbose))
{ {
// // TODO TEMP EXPERIMENTAL - try to alter the item size in order to conform to its wearer // // TODO TEMP EXPERIMENTAL - try to alter the item size in order to conform to its wearer
// currentItem->getRace(); // currentItem->getRace();
// out.print("Critter size: %d| %d | Armor size: %d", world->raws.creatures.all[targetUnit->race]->caste[targetUnit->caste]->body_size_1, world->raws.creatures.all[targetUnit->race]->caste[targetUnit->caste]->body_size_2, currentItem->getTotalDimension()); // out.print("Critter size: %d| %d | Armor size: %d", world->raws.creatures.all[targetUnit->race]->caste[targetUnit->caste]->body_size_1, world->raws.creatures.all[targetUnit->race]->caste[targetUnit->caste]->body_size_2, currentItem->getTotalDimension());
itemsEquipped++; // Track the number of items successfully processed (for feedback purposes) itemsEquipped++; // Track the number of items successfully processed (for feedback purposes)
} }
} }
} }
if (itemsFound == 0) { if (itemsFound == 0) {
out.printerr("No usable items found at the cursor position. Please choose a different location and try again.\n"); out.printerr("No usable items found at the cursor position. Please choose a different location and try again.\n");
return CR_OK; return CR_OK;
} }
if (itemsEquipped == 0 && !verbose) { out.printerr("Some items were found but no equipment changes could be made. Use the /verbose switch to display the reasons for failure.\n"); } if (itemsEquipped == 0 && !verbose) { out.printerr("Some items were found but no equipment changes could be made. Use the /verbose switch to display the reasons for failure.\n"); }
if (itemsEquipped > 0) { out.print("%d items equipped.\n", itemsEquipped); } if (itemsEquipped > 0) { out.print("%d items equipped.\n", itemsEquipped); }
// At this point, some changes may have been made (such as detaching items from their original position), regardless of whether any equipment changes succeeded. // At this point, some changes may have been made (such as detaching items from their original position), regardless of whether any equipment changes succeeded.
// Therefore, we must update the map. // Therefore, we must update the map.
mc.WriteAll(); mc.WriteAll();
// Note: we might expect to recalculate the unit's weight at this point, in order to account for the // Note: we might expect to recalculate the unit's weight at this point, in order to account for the
// added items. In fact, this recalculation occurs automatically during each dwarf's "turn". // added items. In fact, this recalculation occurs automatically during each dwarf's "turn".
// The slight delay in recalculation is probably not worth worrying about. // The slight delay in recalculation is probably not worth worrying about.
// Work complete; report success // Work complete; report success
return CR_OK; return CR_OK;
} }

@ -185,7 +185,7 @@ df::item* find_item(
} }
static void handle_reaction_done(color_ostream &out,df::reaction*, df::unit *unit, std::vector<df::item*> *in_items,std::vector<df::reaction_reagent*> *in_reag static void handle_reaction_done(color_ostream &out,df::reaction*, df::unit *unit, std::vector<df::item*> *in_items,std::vector<df::reaction_reagent*> *in_reag
, std::vector<df::item*> *out_items,bool *call_native){}; , std::vector<df::item*> *out_items,bool *call_native){};
DEFINE_LUA_EVENT_6(onReactionComplete, handle_reaction_done,df::reaction*, df::unit *, std::vector<df::item*> *,std::vector<df::reaction_reagent*> *,std::vector<df::item*> *,bool *); DEFINE_LUA_EVENT_6(onReactionComplete, handle_reaction_done,df::reaction*, df::unit *, std::vector<df::item*> *,std::vector<df::reaction_reagent*> *,std::vector<df::item*> *,bool *);
@ -208,13 +208,13 @@ struct product_hook : item_product {
) { ) {
if (auto product = products[this]) if (auto product = products[this])
{ {
df::reaction* this_reaction=product->react; df::reaction* this_reaction=product->react;
CoreSuspendClaimer suspend; CoreSuspendClaimer suspend;
color_ostream_proxy out(Core::getInstance().getConsole()); color_ostream_proxy out(Core::getInstance().getConsole());
bool call_native=true; bool call_native=true;
onReactionComplete(out,this_reaction,unit,in_items,in_reag,out_items,&call_native); onReactionComplete(out,this_reaction,unit,in_items,in_reag,out_items,&call_native);
if(!call_native) if(!call_native)
return; return;
} }
INTERPOSE_NEXT(produce)(unit, out_items, in_reag, in_items, quantity, skill, entity, site); INTERPOSE_NEXT(produce)(unit, out_items, in_reag, in_items, quantity, skill, entity, site);
@ -233,12 +233,12 @@ IMPLEMENT_VMETHOD_INTERPOSE(product_hook, produce);
static void parse_product( static void parse_product(
color_ostream &out, ProductInfo &info, df::reaction *react, item_product *prod color_ostream &out, ProductInfo &info, df::reaction *react, item_product *prod
) { ) {
info.react = react; info.react = react;
info.product = prod; info.product = prod;
info.material.mat_type = prod->mat_type; info.material.mat_type = prod->mat_type;
info.material.mat_index = prod->mat_index; info.material.mat_index = prod->mat_index;
} }
static bool find_reactions(color_ostream &out) static bool find_reactions(color_ostream &out)

@ -1095,9 +1095,9 @@ static void map_job_items(color_ostream &out)
bool is_invalid = false; bool is_invalid = false;
// don't count worn items // don't count worn items
if (item->getWear() >= 1) if (item->getWear() >= 1)
is_invalid = true; is_invalid = true;
// Special handling // Special handling
switch (itype) { switch (itype) {

@ -1,12 +1,12 @@
// Intention: help with activity zone management (auto-pasture animals, auto-pit goblins, ...) // Intention: help with activity zone management (auto-pasture animals, auto-pit goblins, ...)
// //
// the following things would be nice: // the following things would be nice:
// - dump info about pastures, pastured animals, count non-pastured tame animals, print gender info // - dump info about pastures, pastured animals, count non-pastured tame animals, print gender info
// - help finding caged dwarves? (maybe even allow to build their cages for fast release) // - help finding caged dwarves? (maybe even allow to build their cages for fast release)
// - dump info about caged goblins, animals, ... // - dump info about caged goblins, animals, ...
// - count grass tiles on pastures, move grazers to new pasture if old pasture is empty // - count grass tiles on pastures, move grazers to new pasture if old pasture is empty
// move hungry unpastured grazers to pasture with grass // move hungry unpastured grazers to pasture with grass
// //
// What is working so far: // What is working so far:
// - print detailed info about activity zone and units under cursor (mostly for checking refs and stuff) // - print detailed info about activity zone and units under cursor (mostly for checking refs and stuff)
// - mark a zone which is used for future assignment commands // - mark a zone which is used for future assignment commands
@ -287,7 +287,7 @@ static PersistentDataItem config_autonestbox;
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{ {
switch (event) switch (event)
{ {
case DFHack::SC_MAP_LOADED: case DFHack::SC_MAP_LOADED:
// initialize from the world just loaded // initialize from the world just loaded
@ -320,7 +320,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
autoNestbox(out, false); autoNestbox(out, false);
} }
} }
if(enable_autobutcher) if(enable_autobutcher)
{ {
if(++ticks_autobutcher >= sleep_autobutcher) if(++ticks_autobutcher >= sleep_autobutcher)
@ -630,7 +630,7 @@ bool isTamable(df::unit* unit)
{ {
df::caste_raw *caste = raw->caste[j]; df::caste_raw *caste = raw->caste[j];
if(caste->flags.is_set(caste_raw_flags::PET) || if(caste->flags.is_set(caste_raw_flags::PET) ||
caste->flags.is_set(caste_raw_flags::PET_EXOTIC)) caste->flags.is_set(caste_raw_flags::PET_EXOTIC))
return true; return true;
} }
return false; return false;
@ -652,8 +652,8 @@ bool isFemale(df::unit* unit)
bool hasValidMapPos(df::unit* unit) bool hasValidMapPos(df::unit* unit)
{ {
if( unit->pos.x >=0 && unit->pos.y >= 0 && unit->pos.z >= 0 if( unit->pos.x >=0 && unit->pos.y >= 0 && unit->pos.z >= 0
&& unit->pos.x < world->map.x_count && unit->pos.x < world->map.x_count
&& unit->pos.y < world->map.y_count && unit->pos.y < world->map.y_count
&& unit->pos.z < world->map.z_count) && unit->pos.z < world->map.z_count)
return true; return true;
else else
@ -662,7 +662,7 @@ bool hasValidMapPos(df::unit* unit)
bool isNaked(df::unit* unit) bool isNaked(df::unit* unit)
{ {
return (unit->inventory.empty()); return (unit->inventory.empty());
} }
@ -694,7 +694,7 @@ void unitInfo(color_ostream & out, df::unit* unit, bool verbose = false)
out << " '" << unit->name.nickname << "'"; out << " '" << unit->name.nickname << "'";
out << ", "; out << ", ";
} }
if(isAdult(unit)) if(isAdult(unit))
out << "adult"; out << "adult";
else if(isBaby(unit)) else if(isBaby(unit))
@ -702,7 +702,7 @@ void unitInfo(color_ostream & out, df::unit* unit, bool verbose = false)
else if(isChild(unit)) else if(isChild(unit))
out << "child"; out << "child";
out << " "; out << " ";
// sometimes empty even in vanilla RAWS, sometimes contains full race name (e.g. baby alpaca) // sometimes empty even in vanilla RAWS, sometimes contains full race name (e.g. baby alpaca)
// all animals I looked at don't have babies anyways, their offspring starts as CHILD // all animals I looked at don't have babies anyways, their offspring starts as CHILD
//out << getRaceBabyName(unit); //out << getRaceBabyName(unit);
//out << getRaceChildName(unit); //out << getRaceChildName(unit);
@ -725,7 +725,7 @@ void unitInfo(color_ostream & out, df::unit* unit, bool verbose = false)
out << ", age: " << getUnitAge(unit); out << ", age: " << getUnitAge(unit);
if(isTame(unit)) if(isTame(unit))
out << ", tame"; out << ", tame";
if(isOwnCiv(unit)) if(isOwnCiv(unit))
out << ", owned"; out << ", owned";
if(isWar(unit)) if(isWar(unit))
@ -742,7 +742,7 @@ void unitInfo(color_ostream & out, df::unit* unit, bool verbose = false)
out << ", grazer"; out << ", grazer";
if(isMilkable(unit)) if(isMilkable(unit))
out << ", milkable"; out << ", milkable";
if(verbose) if(verbose)
{ {
out << ". Pos: ("<<unit->pos.x << "/"<< unit->pos.y << "/" << unit->pos.z << ") " << endl; out << ". Pos: ("<<unit->pos.x << "/"<< unit->pos.y << "/" << unit->pos.z << ") " << endl;
@ -820,7 +820,7 @@ bool isPitPond(df::building * building)
if(civ->zone_flags.bits.pit_pond) // && civ->pit_flags==0) if(civ->zone_flags.bits.pit_pond) // && civ->pit_flags==0)
return true; return true;
else else
return false; return false;
} }
@ -879,7 +879,7 @@ df::unit* findUnitById(int32_t id)
int32_t findPenPitAtCursor() int32_t findPenPitAtCursor()
{ {
int32_t foundID = -1; int32_t foundID = -1;
if(cursor->x == -30000) if(cursor->x == -30000)
return -1; return -1;
@ -906,7 +906,7 @@ int32_t findPenPitAtCursor()
int32_t findCageAtCursor() int32_t findCageAtCursor()
{ {
int32_t foundID = -1; int32_t foundID = -1;
if(cursor->x == -30000) if(cursor->x == -30000)
return -1; return -1;
@ -935,7 +935,7 @@ int32_t findCageAtCursor()
int32_t findChainAtCursor() int32_t findChainAtCursor()
{ {
int32_t foundID = -1; int32_t foundID = -1;
if(cursor->x == -30000) if(cursor->x == -30000)
return -1; return -1;
@ -974,7 +974,7 @@ df::general_ref_building_civzone_assignedst * createCivzoneRef()
// being called for the first time, need to initialize the vtable // being called for the first time, need to initialize the vtable
for(size_t i = 0; i < world->units.all.size(); i++) for(size_t i = 0; i < world->units.all.size(); i++)
{ {
df::unit * creature = world->units.all[i]; df::unit * creature = world->units.all[i];
for(size_t r = 0; r<creature->general_refs.size(); r++) for(size_t r = 0; r<creature->general_refs.size(); r++)
{ {
df::general_ref* ref; df::general_ref* ref;
@ -984,7 +984,7 @@ df::general_ref_building_civzone_assignedst * createCivzoneRef()
if (strict_virtual_cast<df::general_ref_building_civzone_assignedst>(ref)) if (strict_virtual_cast<df::general_ref_building_civzone_assignedst>(ref))
{ {
// !! calling new() doesn't work, need _identity.instantiate() instead !! // !! calling new() doesn't work, need _identity.instantiate() instead !!
newref = (df::general_ref_building_civzone_assignedst*) newref = (df::general_ref_building_civzone_assignedst*)
df::general_ref_building_civzone_assignedst::_identity.instantiate(); df::general_ref_building_civzone_assignedst::_identity.instantiate();
vt_initialized = true; vt_initialized = true;
break; break;
@ -1090,13 +1090,13 @@ bool isInBuiltCageRoom(df::unit* unit)
for (size_t b=0; b < world->buildings.all.size(); b++) for (size_t b=0; b < world->buildings.all.size(); b++)
{ {
df::building* building = world->buildings.all[b]; df::building* building = world->buildings.all[b];
// !!! building->isRoom() returns true if the building can be made a room but currently isn't // !!! building->isRoom() returns true if the building can be made a room but currently isn't
// !!! except for coffins/tombs which always return false // !!! except for coffins/tombs which always return false
// !!! using the bool is_room however gives the correct state/value // !!! using the bool is_room however gives the correct state/value
if(!building->is_room) if(!building->is_room)
continue; continue;
if(building->getType() == building_type::Cage) if(building->getType() == building_type::Cage)
{ {
df::building_cagest* cage = (df::building_cagest*) building; df::building_cagest* cage = (df::building_cagest*) building;
@ -1118,7 +1118,7 @@ bool isInBuiltCageRoom(df::unit* unit)
// check a map position for a built cage // check a map position for a built cage
// animals in cages are CONTAINED_IN_ITEM, no matter if they are on a stockpile or inside a built cage // animals in cages are CONTAINED_IN_ITEM, no matter if they are on a stockpile or inside a built cage
// if they are on animal stockpiles they should count as unassigned to allow pasturing them // if they are on animal stockpiles they should count as unassigned to allow pasturing them
// if they are inside built cages they should be ignored in case the cage is a zoo or linked to a lever or whatever // if they are inside built cages they should be ignored in case the cage is a zoo or linked to a lever or whatever
bool isBuiltCageAtPos(df::coord pos) bool isBuiltCageAtPos(df::coord pos)
{ {
bool cage = false; bool cage = false;
@ -1232,7 +1232,7 @@ bool isFreeEgglayer(df::unit * unit)
{ {
if( !isDead(unit) && !isUndead(unit) if( !isDead(unit) && !isUndead(unit)
&& isFemale(unit) && isFemale(unit)
&& isTame(unit) && isTame(unit)
&& isOwnCiv(unit) && isOwnCiv(unit)
&& isEggLayer(unit) && isEggLayer(unit)
&& !isAssigned(unit) && !isAssigned(unit)
@ -1306,7 +1306,7 @@ bool unassignUnitFromBuilding(df::unit* unit)
{ {
// game does not erase the ref until creature gets removed from cage // game does not erase the ref until creature gets removed from cage
//unit->general_refs.erase(unit->general_refs.begin() + idx); //unit->general_refs.erase(unit->general_refs.begin() + idx);
// walk through buildings, check cages for inhabitants, compare ids // walk through buildings, check cages for inhabitants, compare ids
for (size_t b=0; b < world->buildings.all.size(); b++) for (size_t b=0; b < world->buildings.all.size(); b++)
{ {
@ -1379,7 +1379,7 @@ command_result assignUnitToZone(color_ostream& out, df::unit* unit, df::building
<< "before using 'assign' for the first time." << endl; << "before using 'assign' for the first time." << endl;
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
// check if unit is already pastured, remove that ref from unit and old pasture // check if unit is already pastured, remove that ref from unit and old pasture
// testing showed that removing the ref from the unit only seems to be necessary for pastured creatures // testing showed that removing the ref from the unit only seems to be necessary for pastured creatures
// if they are in cages on stockpiles the game unassigns them automatically // if they are in cages on stockpiles the game unassigns them automatically
@ -1401,8 +1401,8 @@ command_result assignUnitToZone(color_ostream& out, df::unit* unit, df::building
df::building_civzonest * civz = (df::building_civzonest *) building; df::building_civzonest * civz = (df::building_civzonest *) building;
civz->assigned_creature.push_back(unit->id); civz->assigned_creature.push_back(unit->id);
out << "Unit " << unit->id out << "Unit " << unit->id
<< "(" << getRaceName(unit) << ")" << "(" << getRaceName(unit) << ")"
<< " assigned to zone " << building->id; << " assigned to zone " << building->id;
if(isPitPond(building)) if(isPitPond(building))
out << " (pit/pond)."; out << " (pit/pond).";
@ -1425,7 +1425,7 @@ command_result assignUnitToCage(color_ostream& out, df::unit* unit, df::building
// don't assign owned pets to a cage. the owner will release them, resulting into infinite hauling (df bug) // don't assign owned pets to a cage. the owner will release them, resulting into infinite hauling (df bug)
if(unit->relations.pet_owner_id != -1) if(unit->relations.pet_owner_id != -1)
return CR_OK; return CR_OK;
// check if unit is already pastured or caged, remove refs where necessary // check if unit is already pastured or caged, remove refs where necessary
bool cleared_old = unassignUnitFromBuilding(unit); bool cleared_old = unassignUnitFromBuilding(unit);
if(verbose) if(verbose)
@ -1442,8 +1442,8 @@ command_result assignUnitToCage(color_ostream& out, df::unit* unit, df::building
df::building_cagest* civz = (df::building_cagest*) building; df::building_cagest* civz = (df::building_cagest*) building;
civz->assigned_creature.push_back(unit->id); civz->assigned_creature.push_back(unit->id);
out << "Unit " << unit->id out << "Unit " << unit->id
<< "(" << getRaceName(unit) << ")" << "(" << getRaceName(unit) << ")"
<< " assigned to cage " << building->id; << " assigned to cage " << building->id;
out << endl; out << endl;
@ -1631,7 +1631,7 @@ void zoneInfo(color_ostream & out, df::building* building, bool verbose)
out << " (pit flags:" << civ->pit_flags.whole << ")"; out << " (pit flags:" << civ->pit_flags.whole << ")";
if(civ->pit_flags.bits.is_pond) if(civ->pit_flags.bits.is_pond)
out << ", pond"; out << ", pond";
else else
out << ", pit"; out << ", pit";
} }
out << endl; out << endl;
@ -1654,7 +1654,7 @@ void zoneInfo(color_ostream & out, df::building* building, bool verbose)
df::unit * creature = world->units.all[i]; df::unit * creature = world->units.all[i];
if(creature->id != cindex) if(creature->id != cindex)
continue; continue;
unitInfo(out, creature, verbose); unitInfo(out, creature, verbose);
} }
} }
@ -1694,7 +1694,7 @@ void cageInfo(color_ostream & out, df::building* building, bool verbose)
df::unit * creature = world->units.all[i]; df::unit * creature = world->units.all[i];
if(creature->id != cindex) if(creature->id != cindex)
continue; continue;
unitInfo(out, creature, verbose); unitInfo(out, creature, verbose);
} }
} }
@ -1737,7 +1737,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
bool zone_info = false; bool zone_info = false;
//bool cage_info = false; //bool cage_info = false;
//bool chain_info = false; //bool chain_info = false;
bool invert_filter = false; bool invert_filter = false;
bool find_unassigned = false; bool find_unassigned = false;
bool find_caged = false; bool find_caged = false;
@ -1763,17 +1763,17 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
bool find_female = false; bool find_female = false;
bool find_not_female = false; bool find_not_female = false;
bool find_egglayer = false; bool find_egglayer = false;
bool find_not_egglayer = false; bool find_not_egglayer = false;
bool find_grazer = false; bool find_grazer = false;
bool find_not_grazer = false; bool find_not_grazer = false;
bool find_milkable = false; bool find_milkable = false;
bool find_not_milkable = false; bool find_not_milkable = false;
bool find_named = false; bool find_named = false;
bool find_not_named = false; bool find_not_named = false;
bool find_naked = false; bool find_naked = false;
bool find_not_naked = false; bool find_not_naked = false;
bool find_tamable = false; bool find_tamable = false;
bool find_not_tamable = false; bool find_not_tamable = false;
bool find_agemin = false; bool find_agemin = false;
bool find_agemax = false; bool find_agemax = false;
@ -1801,7 +1801,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
for (size_t i = 0; i < parameters.size(); i++) for (size_t i = 0; i < parameters.size(); i++)
{ {
string & p = parameters[i]; string & p = parameters[i];
if (p == "help" || p == "?") if (p == "help" || p == "?")
{ {
out << zone_help << endl; out << zone_help << endl;
@ -2388,7 +2388,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
df::unit *unit = world->units.all[c]; df::unit *unit = world->units.all[c];
// ignore dead and undead units // ignore dead and undead units
if (isDead(unit) || isUndead(unit)) if (isDead(unit) || isUndead(unit))
continue; continue;
// ignore merchant units by default // ignore merchant units by default
@ -2432,7 +2432,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
|| (find_grazer && !isGrazer(unit)) || (find_grazer && !isGrazer(unit))
|| (find_not_grazer && isGrazer(unit)) || (find_not_grazer && isGrazer(unit))
|| (find_egglayer && !isEggLayer(unit)) || (find_egglayer && !isEggLayer(unit))
|| (find_not_egglayer && isEggLayer(unit)) || (find_not_egglayer && isEggLayer(unit))
|| (find_milkable && !isMilkable(unit)) || (find_milkable && !isMilkable(unit))
|| (find_not_milkable && isMilkable(unit)) || (find_not_milkable && isMilkable(unit))
|| (find_male && !isMale(unit)) || (find_male && !isMale(unit))
@ -2441,10 +2441,10 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
|| (find_not_female && isFemale(unit)) || (find_not_female && isFemale(unit))
|| (find_named && !unit->name.has_name) || (find_named && !unit->name.has_name)
|| (find_not_named && unit->name.has_name) || (find_not_named && unit->name.has_name)
|| (find_naked && !isNaked(unit)) || (find_naked && !isNaked(unit))
|| (find_not_naked && isNaked(unit)) || (find_not_naked && isNaked(unit))
|| (find_tamable && !isTamable(unit)) || (find_tamable && !isTamable(unit))
|| (find_not_tamable && isTamable(unit)) || (find_not_tamable && isTamable(unit))
|| (find_trainable_war && (isWar(unit) || isHunter(unit) || !isTrainableWar(unit))) || (find_trainable_war && (isWar(unit) || isHunter(unit) || !isTrainableWar(unit)))
|| (find_not_trainable_war && isTrainableWar(unit)) // hm, is this check enough? || (find_not_trainable_war && isTrainableWar(unit)) // hm, is this check enough?
|| (find_trainable_hunting && (isWar(unit) || isHunter(unit) || !isTrainableHunting(unit))) || (find_trainable_hunting && (isWar(unit) || isHunter(unit) || !isTrainableHunting(unit)))
@ -2471,7 +2471,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
unitInfo(out, unit, verbose); unitInfo(out, unit, verbose);
continue; continue;
} }
if(nick_set) if(nick_set)
{ {
Units::setNickname(unit, target_nick); Units::setNickname(unit, target_nick);
@ -2540,8 +2540,8 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
} }
// de-assign from pen or pit // de-assign from pen or pit
// using the zone tool to free creatures from cages or chains // using the zone tool to free creatures from cages or chains
// is pointless imo since that is already quite easy using the ingame UI. // is pointless imo since that is already quite easy using the ingame UI.
// but it's easy to implement so I might as well add it later // but it's easy to implement so I might as well add it later
if(building_unassign) if(building_unassign)
{ {
@ -2555,7 +2555,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
out << "Unit unassigned." << endl; out << "Unit unassigned." << endl;
else else
out << "Unit is not assigned to an activity zone!" << endl; out << "Unit is not assigned to an activity zone!" << endl;
return CR_OK; return CR_OK;
} }
@ -2574,7 +2574,7 @@ command_result df_autonestbox(color_ostream &out, vector <string> & parameters)
for (size_t i = 0; i < parameters.size(); i++) for (size_t i = 0; i < parameters.size(); i++)
{ {
string & p = parameters[i]; string & p = parameters[i];
if (p == "help" || p == "?") if (p == "help" || p == "?")
{ {
out << autonestbox_help << endl; out << autonestbox_help << endl;
@ -2687,7 +2687,7 @@ command_result autoNestbox( color_ostream &out, bool verbose = false )
Gui::showAnnouncement(announce, 2, false); Gui::showAnnouncement(announce, 2, false);
out << announce << endl; out << announce << endl;
// can complain again // can complain again
// (might lead to spamming the same message twice, but catches the case // (might lead to spamming the same message twice, but catches the case
// where for example 2 new egglayers hatched right after 2 zones were created and assigned) // where for example 2 new egglayers hatched right after 2 zones were created and assigned)
autonestbox_did_complain = false; autonestbox_did_complain = false;
} }
@ -2699,7 +2699,7 @@ command_result autoNestbox( color_ostream &out, bool verbose = false )
// getUnitAge() returns 0 if born in current year, therefore the look at birth_time in that case // getUnitAge() returns 0 if born in current year, therefore the look at birth_time in that case
// (assuming that the value from there indicates in which tick of the current year the unit was born) // (assuming that the value from there indicates in which tick of the current year the unit was born)
bool compareUnitAgesYounger(df::unit* i, df::unit* j) bool compareUnitAgesYounger(df::unit* i, df::unit* j)
{ {
int32_t age_i = getUnitAge(i); int32_t age_i = getUnitAge(i);
int32_t age_j = getUnitAge(j); int32_t age_j = getUnitAge(j);
@ -2708,10 +2708,10 @@ bool compareUnitAgesYounger(df::unit* i, df::unit* j)
age_i = i->relations.birth_time; age_i = i->relations.birth_time;
age_j = j->relations.birth_time; age_j = j->relations.birth_time;
} }
return (age_i < age_j); return (age_i < age_j);
} }
bool compareUnitAgesOlder(df::unit* i, df::unit* j) bool compareUnitAgesOlder(df::unit* i, df::unit* j)
{ {
int32_t age_i = getUnitAge(i); int32_t age_i = getUnitAge(i);
int32_t age_j = getUnitAge(j); int32_t age_j = getUnitAge(j);
if(age_i == 0 && age_j == 0) if(age_i == 0 && age_j == 0)
@ -2719,7 +2719,7 @@ bool compareUnitAgesOlder(df::unit* i, df::unit* j)
age_i = i->relations.birth_time; age_i = i->relations.birth_time;
age_j = j->relations.birth_time; age_j = j->relations.birth_time;
} }
return (age_i > age_j); return (age_i > age_j);
} }
//enum WatchedRaceSubtypes //enum WatchedRaceSubtypes
@ -2748,7 +2748,7 @@ public:
vector <df::unit*> mk_ptr; vector <df::unit*> mk_ptr;
vector <df::unit*> fa_ptr; vector <df::unit*> fa_ptr;
vector <df::unit*> ma_ptr; vector <df::unit*> ma_ptr;
WatchedRace(bool watch, int id, int _fk, int _mk, int _fa, int _ma) WatchedRace(bool watch, int id, int _fk, int _mk, int _fa, int _ma)
{ {
isWatched = watch; isWatched = watch;
@ -2786,8 +2786,8 @@ public:
string keyname = "autobutcher/watchlist/" + getRaceName(raceId); string keyname = "autobutcher/watchlist/" + getRaceName(raceId);
out << "Something failed, could not find/create config key " << keyname << "!" << endl; out << "Something failed, could not find/create config key " << keyname << "!" << endl;
} }
} }
void RemoveConfig(color_ostream & out) void RemoveConfig(color_ostream & out)
{ {
if(!rconfig.isValid()) if(!rconfig.isValid())
@ -2802,7 +2802,7 @@ public:
sort(fa_ptr.begin(), fa_ptr.end(), compareUnitAgesYounger); sort(fa_ptr.begin(), fa_ptr.end(), compareUnitAgesYounger);
sort(ma_ptr.begin(), ma_ptr.end(), compareUnitAgesYounger); sort(ma_ptr.begin(), ma_ptr.end(), compareUnitAgesYounger);
} }
void PushUnit(df::unit * unit) void PushUnit(df::unit * unit)
{ {
if(isFemale(unit)) if(isFemale(unit))
@ -2894,7 +2894,7 @@ public:
} }
}; };
// vector of races handled by autobutcher // vector of races handled by autobutcher
// the name is a bit misleading since entries can be set to 'unwatched' // the name is a bit misleading since entries can be set to 'unwatched'
// to ignore them for a while but still keep the target count settings // to ignore them for a while but still keep the target count settings
std::vector<WatchedRace*> watched_races; std::vector<WatchedRace*> watched_races;
@ -2933,7 +2933,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
} }
// parse main command // parse main command
string & p = parameters[0]; string & p = parameters[0];
if (p == "help" || p == "?") if (p == "help" || p == "?")
{ {
out << autobutcher_help << endl; out << autobutcher_help << endl;
@ -3058,19 +3058,19 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
if(list_watched) if(list_watched)
{ {
out << "Autobutcher status: "; out << "Autobutcher status: ";
if(enable_autobutcher) if(enable_autobutcher)
out << "enabled,"; out << "enabled,";
else else
out << "not enabled,"; out << "not enabled,";
if (enable_autobutcher_autowatch) if (enable_autobutcher_autowatch)
out << " autowatch,"; out << " autowatch,";
else else
out << " noautowatch,"; out << " noautowatch,";
out << " sleep: " << sleep_autobutcher << endl; out << " sleep: " << sleep_autobutcher << endl;
out << "Default setting for new races:" out << "Default setting for new races:"
<< " fk=" << default_fk << " fk=" << default_fk
<< " mk=" << default_mk << " mk=" << default_mk
@ -3094,7 +3094,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
out << "watched: "; out << "watched: ";
else else
out << "not watched: "; out << "not watched: ";
out << name out << name
<< " fk=" << w->fk << " fk=" << w->fk
<< " mk=" << w->mk << " mk=" << w->mk
<< " fa=" << w->fa << " fa=" << w->fa
@ -3114,7 +3114,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
out << run << "start" << endl; out << run << "start" << endl;
if(!enable_autobutcher) if(!enable_autobutcher)
out << run << "stop" << endl; out << run << "stop" << endl;
if (enable_autobutcher_autowatch) if (enable_autobutcher_autowatch)
out << run << "autowatch" << endl; out << run << "autowatch" << endl;
@ -3147,8 +3147,8 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
} }
// parse rest of parameters for commands followed by a list of races // parse rest of parameters for commands followed by a list of races
if( watch_race if( watch_race
|| unwatch_race || unwatch_race
|| forget_race || forget_race
|| change_target ) || change_target )
{ {
@ -3226,7 +3226,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
else else
{ {
// map race names from parameter list to ids // map race names from parameter list to ids
size_t num_races = df::global::world->raws.creatures.all.size(); size_t num_races = df::global::world->raws.creatures.all.size();
while(target_racenames.size()) while(target_racenames.size())
{ {
bool found_race = false; bool found_race = false;
@ -3345,7 +3345,7 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
|| isHunter(unit) // ignore hunting dogs etc || isHunter(unit) // ignore hunting dogs etc
// ignore creatures in built cages which are defined as rooms to leave zoos alone // ignore creatures in built cages which are defined as rooms to leave zoos alone
// (TODO: better solution would be to allow some kind of slaughter cages which you can place near the butcher) // (TODO: better solution would be to allow some kind of slaughter cages which you can place near the butcher)
|| (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom() || (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom()
|| unit->name.has_name || unit->name.has_name
) )
continue; continue;
@ -3372,7 +3372,7 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
string announce; string announce;
announce = "New race added to autobutcher watchlist: " + getRaceName(w->raceId); announce = "New race added to autobutcher watchlist: " + getRaceName(w->raceId);
Gui::showAnnouncement(announce, 2, false); Gui::showAnnouncement(announce, 2, false);
//out << announce << endl; //out << announce << endl;
} }
} }
@ -3389,7 +3389,7 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
string announce; string announce;
announce = getRaceName(w->raceId) + " marked for slaughter: " + ss.str(); announce = getRaceName(w->raceId) + " marked for slaughter: " + ss.str();
Gui::showAnnouncement(announce, 2, false); Gui::showAnnouncement(announce, 2, false);
//out << announce << endl; //out << announce << endl;
} }
} }
//out << slaughter_count << " units total marked for slaughter." << endl; //out << slaughter_count << " units total marked for slaughter." << endl;
@ -3425,13 +3425,13 @@ command_result start_autobutcher(color_ostream &out)
config_autobutcher.ival(0) = enable_autobutcher; config_autobutcher.ival(0) = enable_autobutcher;
out << "Starting autobutcher." << endl; out << "Starting autobutcher." << endl;
init_autobutcher(out); init_autobutcher(out);
return CR_OK; return CR_OK;
} }
command_result init_autobutcher(color_ostream &out) command_result init_autobutcher(color_ostream &out)
{ {
cleanup_autobutcher(out); cleanup_autobutcher(out);
config_autobutcher = World::GetPersistentData("autobutcher/config"); config_autobutcher = World::GetPersistentData("autobutcher/config");
if(config_autobutcher.isValid()) if(config_autobutcher.isValid())
@ -3466,9 +3466,9 @@ command_result init_autobutcher(color_ostream &out)
std::vector<PersistentDataItem> items; std::vector<PersistentDataItem> items;
World::GetPersistentData(&items, "autobutcher/watchlist/", true); World::GetPersistentData(&items, "autobutcher/watchlist/", true);
for (auto p = items.begin(); p != items.end(); p++) for (auto p = items.begin(); p != items.end(); p++)
{ {
string key = p->key(); string key = p->key();
out << "Reading from save: " << key << endl; out << "Reading from save: " << key << endl;
//out << " raceid: " << p->ival(0) << endl; //out << " raceid: " << p->ival(0) << endl;
//out << " watched: " << p->ival(1) << endl; //out << " watched: " << p->ival(1) << endl;
@ -3476,7 +3476,7 @@ command_result init_autobutcher(color_ostream &out)
//out << " mk: " << p->ival(3) << endl; //out << " mk: " << p->ival(3) << endl;
//out << " fa: " << p->ival(4) << endl; //out << " fa: " << p->ival(4) << endl;
//out << " ma: " << p->ival(5) << endl; //out << " ma: " << p->ival(5) << endl;
WatchedRace * w = new WatchedRace(p->ival(1), p->ival(0), p->ival(2), p->ival(3),p->ival(4),p->ival(5)); WatchedRace * w = new WatchedRace(p->ival(1), p->ival(0), p->ival(2), p->ival(3),p->ival(4),p->ival(5));
w->rconfig = *p; w->rconfig = *p;
watched_races.push_back(w); watched_races.push_back(w);
@ -3514,13 +3514,13 @@ command_result start_autonestbox(color_ostream &out)
config_autonestbox.ival(0) = enable_autonestbox; config_autonestbox.ival(0) = enable_autonestbox;
out << "Starting autonestbox." << endl; out << "Starting autonestbox." << endl;
init_autonestbox(out); init_autonestbox(out);
return CR_OK; return CR_OK;
} }
command_result init_autonestbox(color_ostream &out) command_result init_autonestbox(color_ostream &out)
{ {
cleanup_autonestbox(out); cleanup_autonestbox(out);
config_autonestbox = World::GetPersistentData("autonestbox/config"); config_autonestbox = World::GetPersistentData("autonestbox/config");
if(config_autonestbox.isValid()) if(config_autonestbox.isValid())