Merge branch 'master' of git://github.com/peterix/dfhack

develop
Espen Wiborg 2012-01-23 10:43:07 +01:00
commit 0cf3ee3dc6
91 changed files with 6137 additions and 2666 deletions

@ -1093,6 +1093,14 @@
<Address name='ui_look_list'/> <Address name='ui_look_list'/>
<Address name='ui_look_cursor'/> <Address name='ui_look_cursor'/>
<Address name='ui_workshop_job_cursor'/> <Address name='ui_workshop_job_cursor'/>
<Address name='ui_workshop_in_add'/>
<Address name='job_next_id'/>
<Address name='ui_building_item_cursor'/>
<Address name='ui_selected_unit'/>
<Address name='ui_unit_view_mode'/>
<Address name='cur_year'/>
<Address name='cur_year_tick'/>
<Address name='gps'/>
</Group> </Group>
</Offsets> </Offsets>
</Base> </Base>
@ -2343,6 +2351,17 @@
<Address name='ui_look_list' value='0x185c104'/> <Address name='ui_look_list' value='0x185c104'/>
<Address name='ui_look_cursor' value='0xedeb98'/> <Address name='ui_look_cursor' value='0xedeb98'/>
<Address name='ui_workshop_job_cursor' value='0x14ec79c'/> <Address name='ui_workshop_job_cursor' value='0x14ec79c'/>
<Address name='ui_workshop_in_add' value='0xeb0992'/>
<Address name='job_next_id' value='0xe18290'/>
<Address name='ui_building_item_cursor' value='0xef7264'/>
<Address name='ui_selected_unit' value='0xef2430'/>
<Address name='ui_unit_view_mode' value='0xec4a5c'/>
<Address name='cur_year' value='0xef7268'/>
<Address name='cur_year_tick' value='0xec5170'/>
<Address name='gps' value='0xb34d10'/>
</Group> </Group>
</Offsets> </Offsets>
cmake cmake
@ -3225,8 +3244,19 @@
<Address name='ui_sidebar_menus' value='0x958aa40'/> <Address name='ui_sidebar_menus' value='0x958aa40'/>
<Address name='ui_build_selector' value='0x8df9b20'/> <Address name='ui_build_selector' value='0x8df9b20'/>
<Address name='ui_look_list' value='0x961d840'/> <Address name='ui_look_list' value='0x961d840'/>
<!--<Address name='ui_look_cursor' value=''/>--> <Address name='ui_look_cursor' value='0x93f06dc'/>
<Address name='ui_workshop_job_cursor' value='0x93f0644'/> <Address name='ui_workshop_job_cursor' value='0x93f0644'/>
<Address name='ui_workshop_in_add' value='0x93f0651'/>
<Address name='job_next_id' value='0x961d940'/>
<Address name='ui_building_item_cursor' value='0x93f0648'/>
<Address name='ui_selected_unit' value='0x93f06d0'/>
<Address name='ui_unit_view_mode' value='0x93f06d8'/>
<Address name='cur_year' value='0x93f0600'/>
<Address name='cur_year_tick' value='0x93f0620'/>
<Address name='gps' value='0x8c3e000'/>
</Group> </Group>
</Offsets> </Offsets>
</Version> </Version>

@ -2,3 +2,4 @@ call "%VS100COMNTOOLS%vsvars32.bat"
cd VC2010 cd VC2010
msbuild /m /p:Platform=Win32 /p:Configuration=Release ALL_BUILD.vcxproj msbuild /m /p:Platform=Win32 /p:Configuration=Release ALL_BUILD.vcxproj
cd .. cd ..
pause

@ -39,7 +39,6 @@ include/SDL_keyboard.h
include/SDL_keysym.h include/SDL_keysym.h
include/TileTypes.h include/TileTypes.h
include/Types.h include/Types.h
include/Vector.h
include/VersionInfo.h include/VersionInfo.h
include/VersionInfoFactory.h include/VersionInfoFactory.h
include/Virtual.h include/Virtual.h
@ -49,6 +48,7 @@ include/modules/Units.h
include/modules/Engravings.h include/modules/Engravings.h
include/modules/Gui.h include/modules/Gui.h
include/modules/Items.h include/modules/Items.h
include/modules/Job.h
include/modules/kitchen.h include/modules/kitchen.h
include/modules/Maps.h include/modules/Maps.h
include/modules/MapCache.h include/modules/MapCache.h
@ -89,6 +89,7 @@ modules/Units.cpp
modules/Engravings.cpp modules/Engravings.cpp
modules/Gui.cpp modules/Gui.cpp
modules/Items.cpp modules/Items.cpp
modules/Job.cpp
modules/kitchen.cpp modules/kitchen.cpp
modules/Maps.cpp modules/Maps.cpp
modules/Materials.cpp modules/Materials.cpp

@ -1094,11 +1094,8 @@ MODULE_GETTER(Maps);
MODULE_GETTER(Gui); MODULE_GETTER(Gui);
MODULE_GETTER(World); MODULE_GETTER(World);
MODULE_GETTER(Materials); MODULE_GETTER(Materials);
MODULE_GETTER(Items);
MODULE_GETTER(Translation); MODULE_GETTER(Translation);
MODULE_GETTER(Vegetation); MODULE_GETTER(Vegetation);
MODULE_GETTER(Buildings);
MODULE_GETTER(Constructions); MODULE_GETTER(Constructions);
MODULE_GETTER(Vermin);
MODULE_GETTER(Notes); MODULE_GETTER(Notes);
MODULE_GETTER(Graphic); MODULE_GETTER(Graphic);

@ -35,6 +35,8 @@ distribution.
// must be last due to MS stupidity // must be last due to MS stupidity
#include "DataDefs.h" #include "DataDefs.h"
#include "MiscUtils.h"
using namespace DFHack; using namespace DFHack;
/* The order of global object constructor calls is /* The order of global object constructor calls is
@ -154,10 +156,55 @@ void virtual_identity::Init(Core *core)
// Read pre-filled vtable ptrs // Read pre-filled vtable ptrs
OffsetGroup *ptr_table = core->vinfo->getGroup("vtable"); OffsetGroup *ptr_table = core->vinfo->getGroup("vtable");
for (virtual_identity *p = list; p; p = p->next) { for (virtual_identity *p = list; p; p = p->next) {
uint32_t tmp; void * tmp;
if (ptr_table->getSafeAddress(p->getName(),tmp)) if (ptr_table->getSafeAddress(p->getName(),tmp))
p->vtable_ptr = (void*)tmp; p->vtable_ptr = tmp;
}
}
std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_item_info *items)
{
std::string res;
const char *data = (const char*)p;
for (int i = 0; i < size*8; i++) {
unsigned v;
if (items[i].size > 1) {
unsigned pdv = *(unsigned*)&data[i/8];
v = (pdv >> (i%8)) & ((1 << items[i].size)-1);
} else {
v = (data[i/8]>>(i%8)) & 1;
} }
if (v) {
if (!res.empty())
res += ' ';
if (items[i].name)
res += items[i].name;
else
res += stl_sprintf("UNK_%d", i);
if (items[i].size > 1)
res += stl_sprintf("=%u", v);
}
if (items[i].size > 1)
i += items[i].size-1;
}
return res;
}
int DFHack::findBitfieldField(const std::string &name, int size, const bitfield_item_info *items)
{
for (int i = 0; i < size*8; i++) {
if (items[i].name && items[i].name == name)
return i;
}
return -1;
} }
#define SIMPLE_GLOBAL(name,tname) \ #define SIMPLE_GLOBAL(name,tname) \
@ -169,7 +216,7 @@ DF_KNOWN_GLOBALS
void DFHack::InitDataDefGlobals(Core *core) { void DFHack::InitDataDefGlobals(Core *core) {
OffsetGroup *global_table = core->vinfo->getGroup("global"); OffsetGroup *global_table = core->vinfo->getGroup("global");
uint32_t tmp; void * tmp;
#define SIMPLE_GLOBAL(name,tname) \ #define SIMPLE_GLOBAL(name,tname) \
if (global_table->getSafeAddress(#name,tmp)) df::global::name = (tname*)tmp; if (global_table->getSafeAddress(#name,tmp)) df::global::name = (tname*)tmp;

@ -27,8 +27,6 @@ distribution.
#include "Core.h" #include "Core.h"
#include "MiscUtils.h" #include "MiscUtils.h"
#ifndef LINUX_BUILD #ifndef LINUX_BUILD
#include <Windows.h> #include <Windows.h>
#else #else
@ -36,6 +34,71 @@ distribution.
#include <ctime> #include <ctime>
#endif #endif
#include <ctype.h>
#include <stdarg.h>
std::string stl_sprintf(const char *fmt, ...) {
va_list lst;
va_start(lst, fmt);
std::string rv = stl_vsprintf(fmt, lst);
va_end(lst);
return rv;
}
std::string stl_vsprintf(const char *fmt, va_list args) {
std::vector<char> buf;
buf.resize(4096);
for (;;) {
int rsz = vsnprintf(&buf[0], buf.size(), fmt, args);
if (rsz < 0)
buf.resize(buf.size()*2);
else if (unsigned(rsz) > buf.size())
buf.resize(rsz+1);
else
return std::string(&buf[0], rsz);
}
}
bool split_string(std::vector<std::string> *out,
const std::string &str, const std::string &separator, bool squash_empty)
{
out->clear();
size_t start = 0, pos;
if (!separator.empty())
{
while ((pos = str.find(separator,start)) != std::string::npos)
{
if (pos > start || !squash_empty)
out->push_back(str.substr(start, pos-start));
start = pos + separator.size();
}
}
if (start < str.size() || !squash_empty)
out->push_back(str.substr(start));
return out->size() > 1;
}
std::string toUpper(const std::string &str)
{
std::string rv(str.size(),' ');
for (unsigned i = 0; i < str.size(); ++i)
rv[i] = toupper(str[i]);
return rv;
}
std::string toLower(const std::string &str)
{
std::string rv(str.size(),' ');
for (unsigned i = 0; i < str.size(); ++i)
rv[i] = tolower(str[i]);
return rv;
}
#ifdef LINUX_BUILD // Linux #ifdef LINUX_BUILD // Linux
uint64_t GetTimeMs64() uint64_t GetTimeMs64()
{ {

@ -111,8 +111,8 @@ Process::~Process()
string Process::doReadClassName (void * vptr) string Process::doReadClassName (void * vptr)
{ {
//FIXME: BAD!!!!! //FIXME: BAD!!!!!
int typeinfo = Process::readDWord((uint32_t)vptr - 0x4); char * typeinfo = Process::readPtr(((char *)vptr - 0x4));
int typestring = Process::readDWord(typeinfo + 0x4); char * typestring = Process::readPtr(typeinfo + 0x4);
string raw = readCString(typestring); string raw = readCString(typestring);
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
size_t end = raw.length(); size_t end = raw.length();
@ -138,8 +138,8 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
(char*)&permissions, (char*)&permissions,
&offset, &device1, &device2, &node, &offset, &device1, &device2, &node,
(char*)&temp.name); (char*)&temp.name);
temp.start = start; temp.start = (void *) start;
temp.end = end; temp.end = (void *) end;
temp.read = permissions[0] == 'r'; temp.read = permissions[0] == 'r';
temp.write = permissions[1] == 'w'; temp.write = permissions[1] == 'w';
temp.execute = permissions[2] == 'x'; temp.execute = permissions[2] == 'x';
@ -214,7 +214,7 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange)
if(trgrange.read)protect|=PROT_READ; if(trgrange.read)protect|=PROT_READ;
if(trgrange.write)protect|=PROT_WRITE; if(trgrange.write)protect|=PROT_WRITE;
if(trgrange.execute)protect|=PROT_EXEC; if(trgrange.execute)protect|=PROT_EXEC;
result=mprotect((void *)range.start, range.end-range.start,protect); result=mprotect((void *)range.start, (size_t)range.end-(size_t)range.start,protect);
return result==0; return result==0;
} }

@ -112,7 +112,7 @@ namespace DFHack
uint32_t my_pid; uint32_t my_pid;
IMAGE_NT_HEADERS pe_header; IMAGE_NT_HEADERS pe_header;
IMAGE_SECTION_HEADER * sections; IMAGE_SECTION_HEADER * sections;
uint32_t base; char * base;
}; };
} }
Process::Process(VersionInfoFactory * factory) Process::Process(VersionInfoFactory * factory)
@ -134,7 +134,7 @@ Process::Process(VersionInfoFactory * factory)
} }
// got base ;) // got base ;)
d->base = (uint32_t)hmod; d->base = (char *)hmod;
// read from this process // read from this process
try try
@ -161,7 +161,7 @@ Process::Process(VersionInfoFactory * factory)
identified = true; identified = true;
// give the process a data model and memory layout fixed for the base of first module // give the process a data model and memory layout fixed for the base of first module
my_descriptor = new VersionInfo(*vinfo); my_descriptor = new VersionInfo(*vinfo);
my_descriptor->RebaseAll(d->base); my_descriptor->RebaseAll((uint32_t)d->base);
// keep track of created memory_info object so we can destroy it later // keep track of created memory_info object so we can destroy it later
my_descriptor->setParentProcess(this); my_descriptor->setParentProcess(this);
for(size_t i = 0; i < threads_ids.size();i++) for(size_t i = 0; i < threads_ids.size();i++)
@ -236,7 +236,7 @@ struct HeapBlock
ULONG reserved; ULONG reserved;
}; };
*/ */
void HeapNodes(DWORD pid, map<uint64_t, unsigned int> & heaps) void HeapNodes(DWORD pid, map<char *, unsigned int> & heaps)
{ {
// Create debug buffer // Create debug buffer
PDEBUG_BUFFER db = RtlCreateQueryDebugBuffer(0, FALSE); PDEBUG_BUFFER db = RtlCreateQueryDebugBuffer(0, FALSE);
@ -247,7 +247,7 @@ void HeapNodes(DWORD pid, map<uint64_t, unsigned int> & heaps)
// Go through each of the heap nodes and dispaly the information // Go through each of the heap nodes and dispaly the information
for (unsigned int i = 0; i < heapNodeCount; i++) for (unsigned int i = 0; i < heapNodeCount; i++)
{ {
heaps[heapInfo[i].Base] = i; heaps[(char *)heapInfo[i].Base] = i;
} }
// Clean up the buffer // Clean up the buffer
RtlDestroyQueryDebugBuffer( db ); RtlDestroyQueryDebugBuffer( db );
@ -257,9 +257,9 @@ void HeapNodes(DWORD pid, map<uint64_t, unsigned int> & heaps)
void Process::getMemRanges( vector<t_memrange> & ranges ) void Process::getMemRanges( vector<t_memrange> & ranges )
{ {
MEMORY_BASIC_INFORMATION MBI; MEMORY_BASIC_INFORMATION MBI;
map<uint64_t, unsigned int> heaps; map<char *, unsigned int> heaps;
uint64_t movingStart = 0; uint64_t movingStart = 0;
map <uint64_t, string> nameMap; map <char *, string> nameMap;
// get page size // get page size
SYSTEM_INFO si; SYSTEM_INFO si;
@ -277,18 +277,18 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
if( !(MBI.State & MEM_COMMIT) /*|| !(MBI.Type & MEM_PRIVATE)*/ ) if( !(MBI.State & MEM_COMMIT) /*|| !(MBI.Type & MEM_PRIVATE)*/ )
continue; continue;
t_memrange temp; t_memrange temp;
temp.start = (uint64_t) MBI.BaseAddress; temp.start = (char *) MBI.BaseAddress;
temp.end = ((uint64_t)MBI.BaseAddress + (uint64_t)MBI.RegionSize); temp.end = ((char *)MBI.BaseAddress + (uint64_t)MBI.RegionSize);
temp.read = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READONLY || MBI.Protect & PAGE_READWRITE; temp.read = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READONLY || MBI.Protect & PAGE_READWRITE;
temp.write = MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READWRITE; temp.write = MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READWRITE;
temp.execute = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_EXECUTE; temp.execute = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_EXECUTE;
temp.valid = true; temp.valid = true;
if(!GetModuleBaseName(d->my_handle, (HMODULE) temp.start, temp.name, 1024)) if(!GetModuleBaseName(d->my_handle, (HMODULE) temp.start, temp.name, 1024))
{ {
if(nameMap.count(temp.start)) if(nameMap.count((char *)temp.start))
{ {
// potential buffer overflow... // potential buffer overflow...
strcpy(temp.name, nameMap[temp.start].c_str()); strcpy(temp.name, nameMap[(char *)temp.start].c_str());
} }
else else
{ {
@ -298,9 +298,9 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
else else
{ {
// could be a heap? // could be a heap?
if(heaps.count(temp.start)) if(heaps.count((char *)temp.start))
{ {
sprintf(temp.name,"HEAP %d",heaps[temp.start]); sprintf(temp.name,"HEAP %d",heaps[(char*)temp.start]);
} }
else temp.name[0]=0; else temp.name[0]=0;
} }
@ -320,7 +320,7 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
nm.append(temp.name); nm.append(temp.name);
nm.append(" : "); nm.append(" : ");
nm.append(sectionName); nm.append(sectionName);
nameMap[temp.start + d->sections[i].VirtualAddress] = nm; nameMap[(char *)temp.start + d->sections[i].VirtualAddress] = nm;
} }
} }
else else
@ -333,14 +333,14 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
uint32_t Process::getBase() uint32_t Process::getBase()
{ {
if(d) if(d)
return d->base; return (uint32_t) d->base;
return 0x400000; return 0x400000;
} }
string Process::doReadClassName (void * vptr) string Process::doReadClassName (void * vptr)
{ {
int rtti = readDWord((uint32_t)vptr - 0x4); char * rtti = readPtr((char *)vptr - 0x4);
int typeinfo = readDWord(rtti + 0xC); char * typeinfo = readPtr(rtti + 0xC);
string raw = readCString(typeinfo + 0xC); // skips the .?AV string raw = readCString(typeinfo + 0xC); // skips the .?AV
raw.resize(raw.length() - 2);// trim @@ from end raw.resize(raw.length() - 2);// trim @@ from end
return raw; return raw;
@ -367,7 +367,7 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange)
if(trgrange.read && trgrange.write && trgrange.execute)newprotect=PAGE_EXECUTE_READWRITE; if(trgrange.read && trgrange.write && trgrange.execute)newprotect=PAGE_EXECUTE_READWRITE;
DWORD oldprotect=0; DWORD oldprotect=0;
bool result; bool result;
result=VirtualProtect((LPVOID)range.start,range.end-range.start,newprotect,&oldprotect); result=VirtualProtect((LPVOID)range.start,(char *)range.end-(char *)range.start,newprotect,&oldprotect);
return result; return result;
} }

@ -158,6 +158,8 @@ namespace DFHack
{ {
typedef pair <INVAL_TYPE, uint32_t> nullableUint32; typedef pair <INVAL_TYPE, uint32_t> nullableUint32;
typedef map <string, nullableUint32 >::iterator uint32_Iter; typedef map <string, nullableUint32 >::iterator uint32_Iter;
typedef pair <INVAL_TYPE, char *> nullableBytePtr;
typedef map <string, nullableBytePtr >::iterator byteptr_Iter;
typedef pair <INVAL_TYPE, int32_t> nullableInt32; typedef pair <INVAL_TYPE, int32_t> nullableInt32;
typedef map <string, nullableInt32 >::iterator int32_Iter; typedef map <string, nullableInt32 >::iterator int32_Iter;
typedef pair <INVAL_TYPE, string> nullableString; typedef pair <INVAL_TYPE, string> nullableString;
@ -166,7 +168,7 @@ namespace DFHack
class OffsetGroupPrivate class OffsetGroupPrivate
{ {
public: public:
map <string, nullableUint32 > addresses; map <string, nullableBytePtr > addresses;
map <string, nullableUint32 > hexvals; map <string, nullableUint32 > hexvals;
map <string, nullableInt32 > offsets; map <string, nullableInt32 > offsets;
map <string, nullableString > strings; map <string, nullableString > strings;
@ -183,7 +185,7 @@ void OffsetGroup::createOffset(const string & key)
void OffsetGroup::createAddress(const string & key) void OffsetGroup::createAddress(const string & key)
{ {
OGd->addresses[key] = nullableUint32(NOT_SET, 0); OGd->addresses[key] = nullableBytePtr(NOT_SET, (char*) 0);
} }
void OffsetGroup::createHexValue(const string & key) void OffsetGroup::createHexValue(const string & key)
@ -227,10 +229,10 @@ void OffsetGroup::setOffsetValidity (const string & key, const INVAL_TYPE inval)
void OffsetGroup::setAddress (const string & key, const string & value, const INVAL_TYPE inval) void OffsetGroup::setAddress (const string & key, const string & value, const INVAL_TYPE inval)
{ {
uint32_Iter it = OGd->addresses.find(key); byteptr_Iter it = OGd->addresses.find(key);
if(it != OGd->addresses.end()) if(it != OGd->addresses.end())
{ {
uint32_t address = strtol(value.c_str(), NULL, 16); char * address = (char *) strtol(value.c_str(), NULL, 16);
if((*it).second.second == address) if((*it).second.second == address)
std::cout << "Pointless address setting: " << this->getFullName() + key << endl; std::cout << "Pointless address setting: " << this->getFullName() + key << endl;
(*it).second.second = address; (*it).second.second = address;
@ -244,7 +246,7 @@ void OffsetGroup::setAddressValidity (const string & key, const INVAL_TYPE inval
{ {
if(inval != NOT_SET) if(inval != NOT_SET)
{ {
uint32_Iter it = OGd->addresses.find(key); byteptr_Iter it = OGd->addresses.find(key);
if(it != OGd->addresses.end()) if(it != OGd->addresses.end())
{ {
(*it).second.first = inval; (*it).second.first = inval;
@ -305,9 +307,9 @@ void OffsetGroup::setStringValidity (const string & key, const INVAL_TYPE inval)
} }
// Get named address // Get named address
uint32_t OffsetGroup::getAddress (const string & key) char * OffsetGroup::getAddress (const string & key)
{ {
uint32_Iter iter = OGd->addresses.find(key); byteptr_Iter iter = OGd->addresses.find(key);
if(iter != OGd->addresses.end()) if(iter != OGd->addresses.end())
{ {
@ -321,9 +323,9 @@ uint32_t OffsetGroup::getAddress (const string & key)
} }
// Get named offset, return bool instead of throwing exceptions // Get named offset, return bool instead of throwing exceptions
bool OffsetGroup::getSafeAddress (const string & key, uint32_t & out) bool OffsetGroup::getSafeAddress (const string & key, void * & out)
{ {
uint32_Iter iter = OGd->addresses.find(key); byteptr_Iter iter = OGd->addresses.find(key);
if(iter != OGd->addresses.end() && (*iter).second.first == IS_VALID) if(iter != OGd->addresses.end() && (*iter).second.first == IS_VALID)
{ {
out = (*iter).second.second; out = (*iter).second.second;
@ -410,7 +412,7 @@ OffsetGroup * OffsetGroup::createGroup(const std::string &name)
void OffsetGroup::RebaseAddresses(int32_t offset) void OffsetGroup::RebaseAddresses(int32_t offset)
{ {
for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) for(byteptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{ {
if(iter->second.first) if(iter->second.first)
OGd->addresses[iter->first].second = iter->second.second + offset; OGd->addresses[iter->first].second = iter->second.second + offset;
@ -470,18 +472,19 @@ std::string OffsetGroup::getFullName()
std::string OffsetGroup::PrintOffsets(int indentation) std::string OffsetGroup::PrintOffsets(int indentation)
{ {
byteptr_Iter addriter;
uint32_Iter iter; uint32_Iter iter;
ostringstream ss; ostringstream ss;
indentr i(indentation); indentr i(indentation);
typedef pair <uint32_t, pair< string, nullableUint32 > > horrible; typedef pair <void *, pair< string, nullableBytePtr > > horrible;
vector < horrible > addrsorter; vector < horrible > addrsorter;
for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) for(addriter = OGd->addresses.begin(); addriter != OGd->addresses.end(); addriter++)
{ {
if(!(*iter).second.first) if(!(*addriter).second.first)
addrsorter.push_back( make_pair( 0, *iter ) ); addrsorter.push_back( make_pair( (void *)0, *addriter ) );
else else
{ {
addrsorter.push_back( make_pair( (*iter).second.second, *iter ) ); addrsorter.push_back( make_pair( (*addriter).second.second, *addriter ) );
} }
} }
std::sort(addrsorter.begin(), addrsorter.end(), compare_pair_first<>()); std::sort(addrsorter.begin(), addrsorter.end(), compare_pair_first<>());
@ -569,7 +572,7 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity)
if(invalidity == NOT_SET) if(invalidity == NOT_SET)
return; return;
uint32_Iter iter; byteptr_Iter iter;
for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{ {
if((*iter).second.first) if((*iter).second.first)
@ -581,17 +584,18 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity)
if((*iter2).second.first) if((*iter2).second.first)
(*iter2).second.first = invalidity; (*iter2).second.first = invalidity;
} }
for(iter = OGd->hexvals.begin(); iter != OGd->hexvals.end(); iter++) uint32_Iter iter3;
{ for(iter3 = OGd->hexvals.begin(); iter3 != OGd->hexvals.end(); iter3++)
if((*iter).second.first)
(*iter).second.first = invalidity;
}
strings_Iter iter3;
for(iter3 = OGd->strings.begin(); iter3 != OGd->strings.end(); iter3++)
{ {
if((*iter3).second.first) if((*iter3).second.first)
(*iter3).second.first = invalidity; (*iter3).second.first = invalidity;
} }
strings_Iter iter5;
for(iter5 = OGd->strings.begin(); iter5 != OGd->strings.end(); iter5++)
{
if((*iter5).second.first)
(*iter5).second.first = invalidity;
}
groups_Iter iter4; groups_Iter iter4;
for(iter4 = OGd->groups.begin(); iter4 != OGd->groups.end(); iter4++) for(iter4 = OGd->groups.begin(); iter4 != OGd->groups.end(); iter4++)
{ {
@ -603,7 +607,7 @@ std::vector<OffsetKey> OffsetGroup::getKeys() const
std::vector<OffsetKey> ret; std::vector<OffsetKey> ret;
OffsetKey K; OffsetKey K;
K.keytype=IS_ADDRESS; K.keytype=IS_ADDRESS;
for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) for(byteptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{ {
K.key=iter->first; K.key=iter->first;
K.inval=iter->second.first; K.inval=iter->second.first;
@ -1015,7 +1019,7 @@ void VersionInfo::setClassChild (t_class * parent, const char * name, const char
// FIXME: This in now DEPRECATED! // FIXME: This in now DEPRECATED!
bool VersionInfo::resolveObjectToClassID(const uint32_t address, int32_t & classid) bool VersionInfo::resolveObjectToClassID(const char * address, int32_t & classid)
{ {
uint32_t vtable = d->p->readDWord(address); uint32_t vtable = d->p->readDWord(address);
// try to find the vtable in our cache // try to find the vtable in our cache

@ -50,6 +50,18 @@ namespace DFHack
if(bits) if(bits)
memset(bits, 0, size); memset(bits, 0, size);
} }
void extend (T index)
{
uint32_t newsize = (index / 8) + 1;
if (newsize <= size)
return;
uint8_t *newbits = new uint8_t[newsize];
memset(newbits, 0, newsize);
memcpy(newbits, bits, size);
delete[] bits;
bits = newbits;
size = newsize;
}
void set (T index, bool value = true) void set (T index, bool value = true)
{ {
if(!value) if(!value)
@ -58,7 +70,8 @@ namespace DFHack
return; return;
} }
uint32_t byte = index / 8; uint32_t byte = index / 8;
if(byte < size) extend(index);
//if(byte < size)
{ {
uint8_t bit = 1 << (index % 8); uint8_t bit = 1 << (index % 8);
bits[byte] |= bit; bits[byte] |= bit;
@ -76,7 +89,8 @@ namespace DFHack
void toggle (T index) void toggle (T index)
{ {
uint32_t byte = index / 8; uint32_t byte = index / 8;
if(byte < size) extend(index);
//if(byte < size)
{ {
uint8_t bit = 1 << (index % 8); uint8_t bit = 1 << (index % 8);
bits[byte] ^= bit; bits[byte] ^= bit;

@ -58,12 +58,9 @@ namespace DFHack
class Gui; class Gui;
class World; class World;
class Materials; class Materials;
class Items;
class Translation; class Translation;
class Vegetation; class Vegetation;
class Buildings;
class Constructions; class Constructions;
class Vermin;
class Notes; class Notes;
class VersionInfo; class VersionInfo;
class VersionInfoFactory; class VersionInfoFactory;
@ -113,18 +110,12 @@ namespace DFHack
World * getWorld(); World * getWorld();
/// get the materials module /// get the materials module
Materials * getMaterials(); Materials * getMaterials();
/// get the items module
Items * getItems();
/// get the translation module /// get the translation module
Translation * getTranslation(); Translation * getTranslation();
/// get the vegetation module /// get the vegetation module
Vegetation * getVegetation(); Vegetation * getVegetation();
/// get the buildings module
Buildings * getBuildings();
/// get the constructions module /// get the constructions module
Constructions * getConstructions(); Constructions * getConstructions();
/// get the vermin module
Vermin * getVermin();
/// get the notes module /// get the notes module
Notes * getNotes(); Notes * getNotes();
/// get the graphic module /// get the graphic module
@ -179,12 +170,9 @@ namespace DFHack
Gui * pGui; Gui * pGui;
World * pWorld; World * pWorld;
Materials * pMaterials; Materials * pMaterials;
Items * pItems;
Translation * pTranslation; Translation * pTranslation;
Vegetation * pVegetation; Vegetation * pVegetation;
Buildings * pBuildings;
Constructions * pConstructions; Constructions * pConstructions;
Vermin * pVermin;
Notes * pNotes; Notes * pNotes;
Graphic * pGraphic; Graphic * pGraphic;
} s_mods; } s_mods;

@ -111,15 +111,66 @@ namespace DFHack
return T::_identity.is_instance(ptr) ? static_cast<T*>(ptr) : NULL; return T::_identity.is_instance(ptr) ? static_cast<T*>(ptr) : NULL;
} }
#define VIRTUAL_CAST_VAR(var,type,input) type *var = virtual_cast<type>(input)
template<class T> template<class T>
inline T *strict_virtual_cast(virtual_ptr ptr) { inline T *strict_virtual_cast(virtual_ptr ptr) {
return T::_identity.is_direct_instance(ptr) ? static_cast<T*>(ptr) : NULL; return T::_identity.is_direct_instance(ptr) ? static_cast<T*>(ptr) : NULL;
} }
#define STRICT_VIRTUAL_CAST_VAR(var,type,input) type *var = strict_virtual_cast<type>(input)
void InitDataDefGlobals(Core *core); void InitDataDefGlobals(Core *core);
template<class T> template<class T>
T *ifnull(T *a, T *b) { return a ? a : b; } T *ifnull(T *a, T *b) { return a ? a : b; }
// Enums
template<class T, T start, bool (*isvalid)(T)>
inline T next_enum_item_(T v) {
v = T(int(v) + 1);
return isvalid(v) ? v : start;
}
template<class T>
struct enum_list_attr {
int size;
const T *items;
};
// Bitfields
struct bitfield_item_info {
const char *name;
int size;
};
DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items);
DFHACK_EXPORT int findBitfieldField(const std::string &name, int size, const bitfield_item_info *items);
template<class T>
inline int findBitfieldField(const T &val, const std::string &name) {
return findBitfieldField(name, sizeof(val.whole), val.get_items());
}
template<class T>
inline std::string bitfieldToString(const T &val) {
return bitfieldToString(&val.whole, sizeof(val.whole), val.get_items());
}
}
template<class T>
int linear_index(const DFHack::enum_list_attr<T> &lst, T val) {
for (int i = 0; i < lst.size; i++)
if (lst.items[i] == val)
return i;
return -1;
}
inline int linear_index(const DFHack::enum_list_attr<const char*> &lst, const std::string &val) {
for (int i = 0; i < lst.size; i++)
if (lst.items[i] == val)
return i;
return -1;
} }
namespace df namespace df
@ -127,6 +178,8 @@ namespace df
using DFHack::virtual_ptr; using DFHack::virtual_ptr;
using DFHack::virtual_identity; using DFHack::virtual_identity;
using DFHack::virtual_class; using DFHack::virtual_class;
using DFHack::bitfield_item_info;
using DFHack::enum_list_attr;
using DFHack::BitArray; using DFHack::BitArray;
template<class T> template<class T>
@ -158,6 +211,18 @@ namespace df
} }
}; };
template<class EnumType, class IntType1, class IntType2>
inline bool operator== (enum_field<EnumType,IntType1> a, enum_field<EnumType,IntType2> b)
{
return EnumType(a) == EnumType(b);
}
template<class EnumType, class IntType1, class IntType2>
inline bool operator!= (enum_field<EnumType,IntType1> a, enum_field<EnumType,IntType2> b)
{
return EnumType(a) != EnumType(b);
}
namespace enums {} namespace enums {}
} }
@ -167,6 +232,11 @@ namespace df
#define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum) #define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum)
#define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum) #define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum)
#define ENUM_NEXT_ITEM(enum,val) \
(DFHack::next_enum_item_<df::enum,ENUM_FIRST_ITEM(enum),df::enums::enum::is_valid>(val))
#define FOR_ENUM_ITEMS(enum,iter) \
for(df::enum iter = ENUM_FIRST_ITEM(enum); iter < ENUM_LAST_ITEM(enum); iter = df::enum(1+int(iter)))
namespace df { namespace df {
#define DF_KNOWN_GLOBALS \ #define DF_KNOWN_GLOBALS \
GLOBAL(cursor,cursor) \ GLOBAL(cursor,cursor) \
@ -176,11 +246,20 @@ namespace df {
GLOBAL(gview,interface) \ GLOBAL(gview,interface) \
GLOBAL(init,init) \ GLOBAL(init,init) \
GLOBAL(d_init,d_init) \ GLOBAL(d_init,d_init) \
SIMPLE_GLOBAL(job_next_id,int) \
SIMPLE_GLOBAL(ui_look_cursor,int) \ SIMPLE_GLOBAL(ui_look_cursor,int) \
SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \ SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \
SIMPLE_GLOBAL(ui_building_item_cursor,int) \
SIMPLE_GLOBAL(ui_workshop_in_add,bool) \
SIMPLE_GLOBAL(ui_selected_unit,int) \
SIMPLE_GLOBAL(cur_year,int) \
SIMPLE_GLOBAL(cur_year_tick,int) \
GLOBAL(ui_sidebar_menus,ui_sidebar_menus) \ GLOBAL(ui_sidebar_menus,ui_sidebar_menus) \
GLOBAL(ui_build_selector,ui_build_selector) \ GLOBAL(ui_build_selector,ui_build_selector) \
GLOBAL(ui_look_list,ui_look_list) GLOBAL(ui_look_list,ui_look_list) \
GLOBAL(ui_unit_view_mode, ui_unit_view_mode) \
GLOBAL(gps, graphic) \
#define SIMPLE_GLOBAL(name,tname) \ #define SIMPLE_GLOBAL(name,tname) \
namespace global { extern DFHACK_EXPORT tname *name; } namespace global { extern DFHACK_EXPORT tname *name; }
@ -190,3 +269,7 @@ DF_KNOWN_GLOBALS
#undef GLOBAL #undef GLOBAL
#undef SIMPLE_GLOBAL #undef SIMPLE_GLOBAL
} }
// A couple of headers that have to be included at once
#include "df/coord2d.h"
#include "df/coord.h"

@ -72,8 +72,8 @@ namespace DFHack
*/ */
struct DFHACK_EXPORT t_memrange struct DFHACK_EXPORT t_memrange
{ {
uint64_t start; void * start;
uint64_t end; void * end;
// memory range name (if any) // memory range name (if any)
char name[1024]; char name[1024];
// permission to read // permission to read
@ -84,7 +84,7 @@ namespace DFHack
bool execute : 1; bool execute : 1;
// is a shared region // is a shared region
bool shared : 1; bool shared : 1;
inline bool isInRange( uint64_t address) inline bool isInRange( void * address)
{ {
if (address >= start && address < end) return true; if (address >= start && address < end) return true;
return false; return false;
@ -104,99 +104,110 @@ namespace DFHack
Process(VersionInfoFactory * known_versions); Process(VersionInfoFactory * known_versions);
~Process(); ~Process();
/// read a 8-byte integer /// read a 8-byte integer
uint64_t readQuad(const uint32_t address) uint64_t readQuad(const void * address)
{ {
return *(uint64_t *)address; return *(uint64_t *)address;
} }
/// read a 8-byte integer /// read a 8-byte integer
void readQuad(const uint32_t address, uint64_t & value) void readQuad(const void * address, uint64_t & value)
{ {
value = *(uint64_t *)address; value = *(uint64_t *)address;
}; };
/// write a 8-byte integer /// write a 8-byte integer
void writeQuad(const uint32_t address, const uint64_t value) void writeQuad(const void * address, const uint64_t value)
{ {
(*(uint64_t *)address) = value; (*(uint64_t *)address) = value;
}; };
/// read a 4-byte integer /// read a 4-byte integer
uint32_t readDWord(const uint32_t address) uint32_t readDWord(const void * address)
{ {
return *(uint32_t *)address; return *(uint32_t *)address;
} }
/// read a 4-byte integer /// read a 4-byte integer
void readDWord(const uint32_t address, uint32_t & value) void readDWord(const void * address, uint32_t & value)
{ {
value = *(uint32_t *)address; value = *(uint32_t *)address;
}; };
/// write a 4-byte integer /// write a 4-byte integer
void writeDWord(const uint32_t address, const uint32_t value) void writeDWord(const void * address, const uint32_t value)
{ {
(*(uint32_t *)address) = value; (*(uint32_t *)address) = value;
}; };
/// read a pointer
char * readPtr(const void * address)
{
return *(char **)address;
}
/// read a pointer
void readPtr(const void * address, char * & value)
{
value = *(char **)address;
};
/// read a float /// read a float
float readFloat(const uint32_t address) float readFloat(const void * address)
{ {
return *(float*)address; return *(float*)address;
} }
/// write a float /// write a float
void readFloat(const uint32_t address, float & value) void readFloat(const void * address, float & value)
{ {
value = *(float*)address; value = *(float*)address;
}; };
/// read a 2-byte integer /// read a 2-byte integer
uint16_t readWord(const uint32_t address) uint16_t readWord(const void * address)
{ {
return *(uint16_t *)address; return *(uint16_t *)address;
} }
/// read a 2-byte integer /// read a 2-byte integer
void readWord(const uint32_t address, uint16_t & value) void readWord(const void * address, uint16_t & value)
{ {
value = *(uint16_t *)address; value = *(uint16_t *)address;
}; };
/// write a 2-byte integer /// write a 2-byte integer
void writeWord(const uint32_t address, const uint16_t value) void writeWord(const void * address, const uint16_t value)
{ {
(*(uint16_t *)address) = value; (*(uint16_t *)address) = value;
}; };
/// read a byte /// read a byte
uint8_t readByte(const uint32_t address) uint8_t readByte(const void * address)
{ {
return *(uint8_t *)address; return *(uint8_t *)address;
} }
/// read a byte /// read a byte
void readByte(const uint32_t address, uint8_t & value) void readByte(const void * address, uint8_t & value)
{ {
value = *(uint8_t *)address; value = *(uint8_t *)address;
}; };
/// write a byte /// write a byte
void writeByte(const uint32_t address, const uint8_t value) void writeByte(const void * address, const uint8_t value)
{ {
(*(uint8_t *)address) = value; (*(uint8_t *)address) = value;
}; };
/// read an arbitrary amount of bytes /// read an arbitrary amount of bytes
void read( uint32_t address, uint32_t length, uint8_t* buffer) void read(void * address, uint32_t length, uint8_t* buffer)
{ {
memcpy(buffer, (void *) address, length); memcpy(buffer, (void *) address, length);
}; };
/// write an arbitrary amount of bytes /// write an arbitrary amount of bytes
void write(uint32_t address, uint32_t length, uint8_t* buffer) void write(void * address, uint32_t length, uint8_t* buffer)
{ {
memcpy((void *) address, buffer, length); memcpy((void *) address, buffer, length);
}; };
/// read an STL string /// read an STL string
const std::string readSTLString (uint32_t offset) const std::string readSTLString (void * offset)
{ {
std::string * str = (std::string *) offset; std::string * str = (std::string *) offset;
return *str; return *str;
}; };
/// read an STL string /// read an STL string
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) size_t readSTLString (void * offset, char * buffer, size_t bufcapacity)
{ {
if(!bufcapacity || bufcapacity == 1) if(!bufcapacity || bufcapacity == 1)
return 0; return 0;
@ -209,7 +220,7 @@ namespace DFHack
* write an STL string * write an STL string
* @return length written * @return length written
*/ */
size_t writeSTLString(const uint32_t address, const std::string writeString) size_t writeSTLString(const void * address, const std::string writeString)
{ {
std::string * str = (std::string *) address; std::string * str = (std::string *) address;
str->assign(writeString); str->assign(writeString);
@ -219,7 +230,7 @@ namespace DFHack
* attempt to copy a string from source address to target address. may truncate or leak, depending on platform * attempt to copy a string from source address to target address. may truncate or leak, depending on platform
* @return length copied * @return length copied
*/ */
size_t copySTLString(const uint32_t address, const uint32_t target) size_t copySTLString(const void * address, const uint32_t target)
{ {
std::string * strsrc = (std::string *) address; std::string * strsrc = (std::string *) address;
std::string * str = (std::string *) target; std::string * str = (std::string *) target;
@ -239,7 +250,7 @@ namespace DFHack
} }
/// read a null-terminated C string /// read a null-terminated C string
const std::string readCString (uint32_t offset) const std::string readCString (void * offset)
{ {
return std::string((char *) offset); return std::string((char *) offset);
}; };

@ -66,34 +66,200 @@ void print_bits ( T val, DFHack::Console& out )
out.print(strs.str().c_str()); out.print(strs.str().c_str());
} }
//FIXME: Error 8 error C4519: default template arguments are only allowed on a class template /*
template <typename CT, typename FT, typename AT/* = FT*/> * Binary search in vectors.
CT *binsearch_in_vector(std::vector<CT*> &vec, FT CT::*field, AT value) */
template <typename FT>
int linear_index(const std::vector<FT> &vec, FT key)
{
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i] == key)
return i;
return -1;
}
template <typename FT>
int linear_index(const std::vector<FT*> &vec, const FT &key)
{ {
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i] && *vec[i] == key)
return i;
return -1;
}
template <typename FT>
int binsearch_index(const std::vector<FT> &vec, FT key, bool exact = true)
{
// Returns the index of the value >= the key
int min = -1, max = (int)vec.size(); int min = -1, max = (int)vec.size();
CT **p = vec.data(); const FT *p = vec.data();
FT key = (FT)value;
for (;;) for (;;)
{ {
int mid = (min + max)>>1; int mid = (min + max)>>1;
if (mid == min) if (mid == min)
{ return exact ? -1 : max;
return NULL; FT midv = p[mid];
if (midv == key)
return mid;
else if (midv < key)
min = mid;
else
max = mid;
} }
}
template <typename CT, typename FT>
int linear_index(const std::vector<CT*> &vec, FT CT::*field, FT key)
{
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i]->*field == key)
return i;
return -1;
}
template <typename CT, typename FT>
int binsearch_index(const std::vector<CT*> &vec, FT CT::*field, FT key, bool exact = true)
{
// Returns the index of the value >= the key
int min = -1, max = (int)vec.size();
CT *const *p = vec.data();
for (;;)
{
int mid = (min + max)>>1;
if (mid == min)
return exact ? -1 : max;
FT midv = p[mid]->*field; FT midv = p[mid]->*field;
if (midv == key) if (midv == key)
{ return mid;
return p[mid];
}
else if (midv < key) else if (midv < key)
{
min = mid; min = mid;
}
else else
{
max = mid; max = mid;
} }
} }
template <typename CT>
inline int binsearch_index(const std::vector<CT*> &vec, typename CT::key_field_type key, bool exact = true)
{
return CT::binsearch_index(vec, key, exact);
}
template <typename CT>
inline int binsearch_index(const std::vector<CT*> &vec, typename CT::key_pointer_type key, bool exact = true)
{
return CT::binsearch_index(vec, key, exact);
}
template<typename FT, typename KT>
inline bool vector_contains(const std::vector<FT> &vec, KT key)
{
return binsearch_index(vec, key) >= 0;
}
template<typename CT, typename FT>
inline bool vector_contains(const std::vector<CT*> &vec, FT CT::*field, FT key)
{
return binsearch_index(vec, field, key) >= 0;
}
template<typename T>
inline T vector_get(const std::vector<T> &vec, unsigned idx, const T &defval = T())
{
if (idx < vec.size())
return vec[idx];
else
return defval;
}
template<typename T>
inline void vector_insert_at(std::vector<T> &vec, unsigned idx, const T &val)
{
vec.insert(vec.begin()+idx, val);
}
template<typename T>
inline void vector_erase_at(std::vector<T> &vec, unsigned idx)
{
if (idx < vec.size())
vec.erase(vec.begin()+idx);
}
template<typename FT>
unsigned insert_into_vector(std::vector<FT> &vec, FT key, bool *inserted = NULL)
{
unsigned pos = (unsigned)binsearch_index(vec, key, false);
bool to_ins = (pos >= vec.size() || vec[pos] != key);
if (inserted) *inserted = to_ins;
if (to_ins)
vector_insert_at(vec, pos, key);
return pos;
}
template<typename CT, typename FT>
unsigned insert_into_vector(std::vector<CT*> &vec, FT CT::*field, CT *obj, bool *inserted = NULL)
{
unsigned pos = (unsigned)binsearch_index(vec, field, obj->*field, false);
bool to_ins = (pos >= vec.size() || vec[pos] != obj);
if (inserted) *inserted = to_ins;
if (to_ins)
vector_insert_at(vec, pos, obj);
return pos;
}
template <typename CT, typename KT>
CT *binsearch_in_vector(const std::vector<CT*> &vec, KT value)
{
int idx = binsearch_index(vec, value);
return idx < 0 ? NULL : vec[idx];
}
template <typename CT, typename FT>
CT *binsearch_in_vector(const std::vector<CT*> &vec, FT CT::*field, FT value)
{
int idx = binsearch_index(vec, field, value);
return idx < 0 ? NULL : vec[idx];
}
/*
* List
*/
template<typename Link>
Link *linked_list_append(Link *head, Link *tail)
{
while (head->next)
head = head->next;
head->next = tail;
tail->prev = head;
return tail;
}
template<typename Link>
Link *linked_list_insert_after(Link *pos, Link *link)
{
link->next = pos->next;
if (pos->next)
pos->next->prev = link;
link->prev = pos;
pos->next = link;
return link;
}
/*
* MISC
*/
DFHACK_EXPORT bool split_string(std::vector<std::string> *out,
const std::string &str, const std::string &separator,
bool squash_empty = false);
DFHACK_EXPORT std::string toUpper(const std::string &str);
DFHACK_EXPORT std::string toLower(const std::string &str);
inline bool bits_match(unsigned required, unsigned ok, unsigned mask)
{
return (required & mask) == (required & mask & ok);
} }
/** /**
@ -102,3 +268,6 @@ CT *binsearch_in_vector(std::vector<CT*> &vec, FT CT::*field, AT value)
* source: http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c * source: http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c
*/ */
DFHACK_EXPORT uint64_t GetTimeMs64(); DFHACK_EXPORT uint64_t GetTimeMs64();
DFHACK_EXPORT std::string stl_sprintf(const char *fmt, ...);
DFHACK_EXPORT std::string stl_vsprintf(const char *fmt, va_list args);

@ -35,13 +35,11 @@ namespace DFHack
Module* createGui(); Module* createGui();
Module* createWorld(); Module* createWorld();
Module* createMaterials(); Module* createMaterials();
Module* createItems();
Module* createTranslation(); Module* createTranslation();
Module* createVegetation(); Module* createVegetation();
Module* createBuildings(); Module* createBuildings();
Module* createConstructions(); Module* createConstructions();
Module* createMaps(); Module* createMaps();
Module* createVermin();
Module* createNotes(); Module* createNotes();
Module* createGraphic(); Module* createGraphic();
} }

@ -43,7 +43,7 @@ namespace DFHack
{ {
class Core; class Core;
class PluginManager; class PluginManager;
struct virtual_identity; class virtual_identity;
enum command_result enum command_result
{ {

@ -1,96 +0,0 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef DFVECTOR_H_INCLUDED
#define DFVECTOR_H_INCLUDED
#include "Pragma.h"
#include "Export.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include <string.h>
#include <vector>
namespace DFHack
{
template <class T>
class DFHACK_EXPORT DfVector
{
private:
std::vector<T> * real_vec;
public:
DfVector(uint32_t address)
{
real_vec = (std::vector<T> *) address;
};
~DfVector()
{
};
// get offset of the specified index
inline const T& operator[] (uint32_t index)
{
// FIXME: vector out of bounds exception
//assert(index < size);
return real_vec->at(index);
};
// get offset of the specified index
inline const T& at (uint32_t index)
{
//assert(index < size);
return real_vec->at(index);
};
// update value at index
bool set(uint32_t index, T value)
{
if (index >= real_vec->size())
return false;
real_vec->at(index) = value;
return true;
}
// remove value
bool remove(uint32_t index)
{
if (index >= real_vec->size())
return false;
// Remove the item
real_vec->erase(real_vec->begin() + index);
return true;
}
// get vector size
inline uint32_t size ()
{
return real_vec->size();
};
// get vector start
inline const T * start ()
{
return real_vec->data();
};
};
}
#endif // DFVECTOR_H_INCLUDED

@ -88,13 +88,13 @@ namespace DFHack
OffsetGroup * createGroup ( const std::string & name ); OffsetGroup * createGroup ( const std::string & name );
int32_t getOffset (const std::string & key); int32_t getOffset (const std::string & key);
uint32_t getAddress (const std::string & key); char * getAddress (const std::string & key);
uint32_t getHexValue (const std::string & key); uint32_t getHexValue (const std::string & key);
std::string getString (const std::string & key); std::string getString (const std::string & key);
OffsetGroup * getGroup ( const std::string & name ); OffsetGroup * getGroup ( const std::string & name );
bool getSafeOffset (const std::string & key, int32_t & out); bool getSafeOffset (const std::string & key, int32_t & out);
bool getSafeAddress (const std::string & key, uint32_t & out); bool getSafeAddress (const std::string & key, void * & out);
void setOffset (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID); void setOffset (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setOffsetValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID); void setOffsetValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID);
@ -189,7 +189,7 @@ namespace DFHack
* uses memory reading directly, needs suspend. input = address of the object * uses memory reading directly, needs suspend. input = address of the object
* fails if it's unable to read from memory * fails if it's unable to read from memory
*/ */
bool resolveObjectToClassID (const uint32_t address, int32_t & classID); bool resolveObjectToClassID (const char * address, int32_t & classID);
/** /**
* Get a ClassID when you know the classname. can fail if the class is not in the cache * Get a ClassID when you know the classname. can fail if the class is not in the cache

@ -1,3 +1,3 @@
*.h *.h
*.inc static*.inc
*.xml *.xml

@ -0,0 +1,45 @@
coord(const coord2d &c, uint16_t _z) : x(c.x), y(c.y), z(_z) {}
coord(uint16_t _x, uint16_t _y, uint16_t _z) : x(_x), y(_y), z(_z) {}
operator coord2d() const { return coord2d(x,y); }
bool isValid() const { return x != -30000; }
void clear() { x = y = z = -30000; }
bool operator==(const coord &other) const
{
return (x == other.x) && (y == other.y) && (z == other.z);
}
bool operator!=(const coord &other) const
{
return (x != other.x) || (y != other.y) || (z != other.z);
}
bool operator<(const coord &other) const
{
if (x != other.x) return (x < other.x);
if (y != other.y) return (y < other.y);
return z < other.z;
}
coord operator/(int number) const
{
return coord(x/number, y/number, z);
}
coord operator*(int number) const
{
return coord(x*number, y*number, z);
}
coord operator%(int number) const
{
return coord(x%number, y%number, z);
}
coord operator-(int number) const
{
return coord(x,y,z-number);
}
coord operator+(int number) const
{
return coord(x,y,z+number);
}

@ -0,0 +1,32 @@
coord2d(uint16_t _x, uint16_t _y) : x(_x), y(_y) {}
bool isValid() const { return x != -30000; }
void clear() { x = y = -30000; }
bool operator==(const coord2d &other) const
{
return (x == other.x) && (y == other.y);
}
bool operator!=(const coord2d &other) const
{
return (x != other.x) || (y != other.y);
}
bool operator<(const coord2d &other) const
{
if (x != other.x) return (x < other.x);
return y < other.y;
}
coord2d operator/(int number) const
{
return coord2d(x/number, y/number);
}
coord2d operator*(int number) const
{
return coord2d(x*number, y*number);
}
coord2d operator%(int number) const
{
return coord2d(x%number, y%number);
}

@ -0,0 +1,8 @@
unsigned size() const { return x.size(); }
coord operator[] (unsigned idx) const {
if (idx >= x.size() || idx >= y.size() || idx >= z.size())
return coord();
else
return coord(x[idx], y[idx], z[idx]);
}

@ -23,27 +23,20 @@ distribution.
*/ */
#pragma once #pragma once
#ifndef CL_MOD_BUILDINGS
#define CL_MOD_BUILDINGS
/**
* \defgroup grp_buildings Building module parts - also includes zones and stockpiles
* @ingroup grp_modules
*/
#include "Export.h" #include "Export.h"
#include "Module.h"
#ifdef __cplusplus
namespace DFHack namespace DFHack
{ {
#endif namespace Simple
/** {
namespace Buildings
{
/**
* Structure for holding a read DF building object * Structure for holding a read DF building object
* \ingroup grp_buildings * \ingroup grp_buildings
*/ */
struct t_building struct t_building
{ {
uint32_t origin;
uint32_t vtable;
uint32_t x1; uint32_t x1;
uint32_t y1; uint32_t y1;
uint32_t x2; uint32_t x2;
@ -51,35 +44,28 @@ namespace DFHack
uint32_t z; uint32_t z;
t_matglossPair material; t_matglossPair material;
uint32_t type; uint32_t type;
// FIXME: not complete, we need building presence bitmaps for stuff like farm plots and stockpiles, orientation (N,E,S,W) and state (open/closed) int32_t custom_type;
}; void * origin;
};
#ifdef __cplusplus /**
/**
* The Buildings module - allows reading DF buildings * The Buildings module - allows reading DF buildings
* \ingroup grp_modules * \ingroup grp_modules
* \ingroup grp_buildings * \ingroup grp_buildings
*/ */
class DFHACK_EXPORT Buildings : public Module DFHACK_EXPORT uint32_t getNumBuildings ();
{
public:
Buildings();
~Buildings();
bool Start(uint32_t & numBuildings);
// read one building at offset
bool Read (const uint32_t index, t_building & building);
bool Finish();
// read a vector of names /**
bool ReadCustomWorkshopTypes(std::map <uint32_t, std::string> & btypes); * read building by index
// returns -1 on error, >= 0 for real value */
int32_t GetCustomWorkshopType(t_building & building); DFHACK_EXPORT bool Read (const uint32_t index, t_building & building);
private: /**
struct Private; * read mapping from custom_type value to building RAW name
Private *d; * custom_type of -1 implies ordinary building
}; */
} DFHACK_EXPORT bool ReadCustomWorkshopTypes(std::map <uint32_t, std::string> & btypes);
#endif // __cplusplus
#endif }
}
}

@ -74,7 +74,7 @@ namespace DFHack
uint32_t unk6; uint32_t unk6;
/// Address of the read object in DF memory. Added by DFHack. /// Address of the read object in DF memory. Added by DFHack.
uint32_t origin; t_construction * origin;
}; };
#pragma pack (pop) #pragma pack (pop)
class DFContextShared; class DFContextShared;

@ -97,7 +97,7 @@ namespace DFHack
struct dfh_engraving struct dfh_engraving
{ {
t_engraving s; t_engraving s;
uint32_t origin; t_engraving * origin;
}; };
/** /**
* The Engravings module - allows reading engravings :D * The Engravings module - allows reading engravings :D

@ -32,6 +32,13 @@ distribution.
#include "BitArray.h" #include "BitArray.h"
#include <string> #include <string>
namespace df {
struct viewscreen;
struct job;
struct unit;
struct item;
};
/** /**
* \defgroup grp_gui query DF's GUI state * \defgroup grp_gui query DF's GUI state
* @ingroup grp_modules * @ingroup grp_modules
@ -39,6 +46,45 @@ distribution.
namespace DFHack namespace DFHack
{ {
class Core;
// Full-screen item details view
DFHACK_EXPORT bool item_details_hotkey(Core *, df::viewscreen *top);
// 'u'nits or 'j'obs full-screen view
DFHACK_EXPORT bool unitjobs_hotkey(Core *, df::viewscreen *top);
// A job is selected in a workshop
DFHACK_EXPORT bool workshop_job_hotkey(Core *c, df::viewscreen *top);
// Building material selection mode
DFHACK_EXPORT bool build_selector_hotkey(Core *c, df::viewscreen *top);
// A unit is selected in the 'v' mode
DFHACK_EXPORT bool view_unit_hotkey(Core *c, df::viewscreen *top);
// Above + the inventory page is selected.
DFHACK_EXPORT bool unit_inventory_hotkey(Core *c, df::viewscreen *top);
// In workshop_job_hotkey, returns the job
DFHACK_EXPORT df::job *getSelectedWorkshopJob(Core *c, bool quiet = false);
// A job is selected in a workshop, or unitjobs
DFHACK_EXPORT bool any_job_hotkey(Core *c, df::viewscreen *top);
DFHACK_EXPORT df::job *getSelectedJob(Core *c, bool quiet = false);
// A unit is selected via 'v', 'k', unitjobs, or
// a full-screen item view of a cage or suchlike
DFHACK_EXPORT bool any_unit_hotkey(Core *c, df::viewscreen *top);
DFHACK_EXPORT df::unit *getSelectedUnit(Core *c, bool quiet = false);
// An item is selected via 'v'->inventory, 'k', 't', or
// a full-screen item view of a container. Note that in the
// last case, the highlighted contained item is returned, not
// the container itself.
DFHACK_EXPORT bool any_item_hotkey(Core *c, df::viewscreen *top);
DFHACK_EXPORT df::item *getSelectedItem(Core *c, bool quiet = false);
// Show a plain announcement, or a titan-style popup message
DFHACK_EXPORT void showAnnouncement(std::string message, int color = 7, bool bright = true);
DFHACK_EXPORT void showPopupAnnouncement(std::string message, int color = 7, bool bright = true);
class DFContextShared; class DFContextShared;
/** /**
* A GUI screen * A GUI screen

@ -32,6 +32,17 @@ distribution.
#include "Virtual.h" #include "Virtual.h"
#include "modules/Materials.h" #include "modules/Materials.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "DataDefs.h"
#include "df/item.h"
#include "df/item_type.h"
#include "df/general_ref.h"
namespace df
{
struct itemdef;
}
/** /**
* \defgroup grp_items Items module and its types * \defgroup grp_items Items module and its types
* @ingroup grp_modules * @ingroup grp_modules
@ -39,401 +50,47 @@ distribution.
namespace DFHack namespace DFHack
{ {
struct DFHACK_EXPORT ItemTypeInfo {
df::item_type type;
int16_t subtype;
class Context; df::itemdef *custom;
class DFContextShared;
class Units;
/**
* Item flags. A bit fuzzy.
* Mostly from http://dwarffortresswiki.net/index.php/User:Rick/Memory_research
* \ingroup grp_items
*/
union t_itemflags
{
uint32_t whole; ///< the whole struct. all 32 bits of it, as an integer
struct
{
unsigned int on_ground : 1; ///< 0000 0001 Item on ground
unsigned int in_job : 1; ///< 0000 0002 Item currently being used in a job
unsigned int hostile : 1; ///< 0000 0004 Item owned by hostile
unsigned int in_inventory : 1; ///< 0000 0008 Item in a creature or workshop inventory
unsigned int unk1 : 1; ///< 0000 0010 unknown, lost (artifact)?, unusable, unseen public:
unsigned int in_building : 1; ///< 0000 0020 Part of a building (including mechanisms, bodies in coffins) ItemTypeInfo(df::item_type type_ = df::enums::item_type::NONE, int16_t subtype_ = -1) {
unsigned int unk2 : 1; ///< 0000 0040 unknown, unseen decode(type_, subtype_);
unsigned int dead_dwarf : 1; ///< 0000 0080 Dwarf's dead body or body part }
template<class T> ItemTypeInfo(T *ptr) { decode(ptr); }
unsigned int rotten : 1; ///< 0000 0100 Rotten food bool isValid() const {
unsigned int spider_web : 1; ///< 0000 0200 Thread in spider web return (type != df::enums::item_type::NONE) && (subtype == -1 || custom);
unsigned int construction : 1; ///< 0000 0400 Material used in construction }
unsigned int unk3 : 1; ///< 0000 0800 unknown, unseen, unusable
unsigned int unk4 : 1; ///< 0000 1000 unknown, unseen bool decode(df::item_type type_, int16_t subtype_ = -1);
unsigned int murder : 1; ///< 0000 2000 Implies murder - used in fell moods bool decode(df::item *ptr);
unsigned int foreign : 1; ///< 0000 4000 Item is imported
unsigned int trader : 1; ///< 0000 8000 Item ownwed by trader
unsigned int owned : 1; ///< 0001 0000 Item is owned by a dwarf template<class T> bool decode(T *ptr) {
unsigned int garbage_colect : 1; ///< 0002 0000 Marked for deallocation by DF it seems return ptr ? decode(ptr->item_type, ptr->item_subtype) : decode(df::enums::item_type::NONE);
unsigned int artifact1 : 1; ///< 0004 0000 Artifact ? }
unsigned int forbid : 1; ///< 0008 0000 Forbidden item
unsigned int unk6 : 1; ///< 0010 0000 unknown, unseen std::string getToken();
unsigned int dump : 1; ///< 0020 0000 Designated for dumping std::string toString();
unsigned int on_fire: 1; ///< 0040 0000 Indicates if item is on fire, Will Set Item On Fire if Set!
unsigned int melt : 1; ///< 0080 0000 Designated for melting, if applicable
unsigned int hidden : 1; ///< 0100 0000 Hidden item bool find(const std::string &token);
unsigned int in_chest : 1; ///< 0200 0000 Stored in chest/part of well?
unsigned int unk7 : 1; ///< 0400 0000 unknown, unseen
unsigned int artifact2 : 1; ///< 0800 0000 Artifact ?
unsigned int unk8 : 1; ///< 1000 0000 unknown, unseen, common bool matches(const df::job_item &item, MaterialInfo *mat = NULL);
unsigned int unk9 : 1; ///< 2000 0000 unknown, set when viewing details
unsigned int unk10 : 1; ///< 4000 0000 unknown, unseen
unsigned int unk11 : 1; ///< 8000 0000 unknown, unseen
}; };
};
/** inline bool operator== (const ItemTypeInfo &a, const ItemTypeInfo &b) {
* Describes relationship of an item with other objects return a.type == b.type && a.subtype == b.subtype;
* \ingroup grp_items }
*/ inline bool operator!= (const ItemTypeInfo &a, const ItemTypeInfo &b) {
struct t_itemref : public t_virtual return a.type != b.type || a.subtype != b.subtype;
{ }
int32_t value;
};
struct df_contaminant class Context;
{ class DFContextShared;
int16_t material; class Units;
int32_t mat_index;
int16_t mat_state; // FIXME: enum or document in text
int16_t temperature;
int16_t temperature_fraction; // maybe...
int32_t size; ///< 1-24=spatter, 25-49=smear, 50-* = coating
};
/**
* A partial mirror of a DF base type for items
* \ingroup grp_items
*/
class df_item
{
public:
// 4
int16_t x;
int16_t y;
// 8
int16_t z;
// C
t_itemflags flags;
// 10
uint32_t age;
// 14
uint32_t id;
// 18
std::vector<void *> unk1;
// 24 L, 28 W
std::vector<t_itemref *> itemrefs;
// 30 L, 38 W - these were mostly unset (0xCC with malloc patch)
int16_t mystery_meat[12];
// 48 L, 50 W
int32_t mystery1;
// 4C L, 54 W
int32_t mystery2;
// 50 L, 58 W
int32_t mystery3;
// 54 L, 5C W
int32_t mystery4;
// 58 L, 60 W
int32_t mystery5;
// 5C L, 64 W - pointer to vector of contaminants
std::vector <df_contaminant *> * contaminants;
// 60 L, 6C W - temperature in Urists
int16_t temperature;
// 62 L, 6E W - temperature fraction (maybe, just a guess)
int16_t temperature_fraction;
public:
// 0x0
virtual t_itemType getType();
virtual t_itemSubtype getSubtype();
virtual t_materialType getMaterial();
virtual t_materialIndex getMaterialIndex();
// 0x10
virtual void setSubType(t_itemSubtype);
virtual void setMaterial(t_materialType mat);
virtual void setMaterialIndex (t_materialIndex submat);
virtual t_materialType getMaterial2(); // weird
// 0x20
virtual t_materialIndex getMaterialIndex2(); // weird
virtual void fn9(void);
virtual void fn10(void);
virtual void fn11(void);
// 0x30
virtual void fn12(void);
virtual void fn13(void);
virtual void fn14(void);
virtual void fn15(void);
// 0x40
virtual void fn16(void);
virtual void fn17(void);
virtual void fn18(void);
virtual void fn19(void);
// 0x50
virtual void fn20(void);
virtual void fn21(void);
virtual void fn22(void);
virtual void fn23(void);
// 0x60
virtual void fn24(void);
virtual void fn25(void);
virtual void fn26(void);
virtual void fn27(void);
// 0x70
virtual void fn28(void);
virtual void fn29(void);
virtual void fn30(void);
virtual void fn31(void);
// 0x80
virtual void fn32(void);
virtual void fn33(void);
virtual void fn34(void);
virtual void fn35(void);
// 0x90
virtual void fn36(void);
virtual void fn37(void);
virtual void fn38(void);
virtual void fn39(void);
// 0xA0
virtual void fn40(void);
virtual void fn41(void);
virtual void fn42(void);
virtual void fn43(void);
// 0xB0
virtual void fn44(void);
virtual void fn45(void);
virtual void fn46(void);
virtual void fn47(void);
// 0xC0
virtual void fn48(void);
virtual void fn49(void);
virtual void fn50(void);
virtual int16_t getWear(void); // 0 = normal, 1 = x, 2 = X, 3 = XX
// 0xD0
virtual void setWear(int16_t wear); // also zeroes wear timer?
virtual void fn53(void);
virtual void fn54(void);
virtual void fn55(void);
// 0xE0
virtual void fn56(void);
virtual void fn57(void);
virtual void fn58(void);
virtual void fn59(void);
// 0xF0
virtual void fn60(void);
virtual void fn61(void);
virtual void fn62(void);
virtual void fn63(void);
// 0x100
virtual void fn64(void);
virtual void fn65(void);
virtual void fn66(void);
virtual void fn67(void);
// 0x110
virtual void fn68(void);
virtual void fn69(void);
virtual void fn70(void);
virtual void fn71(void);
// 0x120
virtual void fn72(void);
virtual void fn73(void);
virtual void fn74(void);
virtual void fn75(void);
// 0x130
virtual void fn76(void);
virtual void fn77(void);
virtual void fn78(void);
virtual void fn79(void);
// 0x140
virtual void fn80(void);
virtual void fn81(void);
virtual void fn82(void);
virtual void fn83(void);
// 0x150
virtual void fn84(void);
virtual void fn85(void);
virtual void fn86(void);
virtual void fn87(void);
// 0x160
virtual void fn88(void);
virtual void fn89(void);
virtual void fn90(void);
virtual void fn91(void);
// 0x170
virtual void fn92(void);
virtual void fn93(void);
virtual void fn94(void);
virtual void fn95(void);
// 0x180
virtual void fn96(void);
virtual void fn97(void);
virtual void fn98(void);
virtual void fn99(void);
// 0x190
virtual void fn100(void);
virtual void fn101(void);
virtual void fn102(void);
virtual void fn103(void);
// 0x1A0
virtual void fn104(void);
virtual void fn105(void);
virtual void fn106(void);
virtual void fn107(void);
// 0x1B0
virtual void fn108(void);
virtual void fn109(void);
virtual void fn110(void);
virtual void fn111(void);
// 0x1C0
virtual void fn112(void);
virtual void fn113(void);
virtual void fn114(void);
virtual void fn115(void);
// 0x1D0
virtual void fn116(void);
virtual void fn117(void);
virtual void fn118(void);
virtual void fn119(void);
// 0x1E0
virtual void fn120(void);
virtual void fn121(void);
virtual void fn122(void);
virtual void fn123(void);
// 0x1F0
virtual void fn124(void);
virtual void fn125(void);
virtual void fn126(void);
virtual void fn127(void);
// 0x200
virtual void fn128(void);
virtual void fn129(void);
virtual void fn130(void);
virtual void fn131(void);
// 0x210
virtual void fn132(void);
virtual int32_t getStackSize( void );
virtual void fn134(void);
virtual void fn135(void);
// 0x220
virtual void fn136(void);
virtual void fn137(void);
virtual void fn138(void);
virtual void fn139(void);
// 0x230
virtual void fn140(void);
virtual void fn141(void);
virtual void fn142(void);
virtual void fn143(void);
// 0x240
virtual void fn144(void);
virtual void fn145(void);
virtual void fn146(void);
virtual void fn147(void);
// 0x250
virtual void fn148(void);
virtual void fn149(void);
virtual void fn150(void);
virtual int16_t getQuality( void );
// 0x260
virtual void fn152(void);
virtual void fn153(void);
virtual void fn154(void);
virtual void fn155(void);
// 0x270
virtual void fn156(void);
virtual void fn157(void);
virtual void fn158(void);
virtual void fn159(void);
// 0x280
virtual void fn160(void);
virtual void fn161(void);
virtual void fn162(void);
virtual void fn163(void);
// 0x290
virtual void fn164(void);
virtual void fn165(void);
virtual void fn166(void);
virtual void fn167(void);
// 0x2A0
virtual void fn168(void); // value returned (int) = first param to descriprion construction function
virtual void fn169(void);
virtual void fn170(void);
virtual void fn171(void);
// 0x2B0
virtual void fn172(void);
virtual void fn173(void);
virtual void fn174(void);
virtual void fn175(void);
// 0x2C0
virtual void fn176(void);
virtual void fn177(void);
//virtual std::string *getItemDescription ( std::string * str, int sizes = 0); // 0 = stacked, 1 = singular, 2 = plural
virtual std::string *getItemDescription ( std::string * str, int sizes = 0); // 0 = stacked, 1 = singular, 2 = plural
virtual void fn179(void);
// 0x2D0
virtual void fn180(void);
virtual void fn181(void);
virtual void fn182(void);
virtual void fn183(void);
// 0x2E0
virtual void fn184(void);
virtual void fn185(void);
virtual void fn186(void);
virtual void fn187(void);
// 0x2F0
virtual void fn188(void);
virtual void fn189(void);
virtual void fn190(void);
virtual void fn191(void);
// 0x300
virtual void fn192(void);
virtual void fn193(void);
virtual void fn194(void);
virtual void fn195(void);
// 0x310
virtual void fn196(void);
virtual void fn197(void);
virtual void fn198(void);
virtual void fn199(void);
// 0x320
virtual void fn200(void);
virtual void fn201(void);
virtual void fn202(void);
virtual void fn203(void);
// 0x330
virtual void fn204(void);
virtual void fn205(void);
virtual void fn206(void);
virtual void fn207(void);
// 0x340
virtual void fn208(void);
virtual void fn209(void);
virtual void fn210(void);
virtual void fn211(void);
// 0x350
virtual void fn212(void);
virtual void fn213(void);
virtual void fn214(void);
virtual void fn215(void);
// 0x360
virtual void fn216(void);
virtual void fn217(void);
// and this should be all 218 of them
// fn numbers start with 0
};
/** /**
* Type for holding an item read from DF * Type for holding an item read from DF
@ -441,11 +98,11 @@ public:
*/ */
struct dfh_item struct dfh_item
{ {
df_item *origin; // where this was read from df::item *origin; // where this was read from
int16_t x; int16_t x;
int16_t y; int16_t y;
int16_t z; int16_t z;
t_itemflags flags; df::item_flags flags;
uint32_t age; uint32_t age;
uint32_t id; uint32_t id;
t_material matdesc; t_material matdesc;
@ -454,154 +111,37 @@ struct dfh_item
int16_t wear_level; int16_t wear_level;
}; };
/**
* Type for holding item improvements. broken/unused.
* \ingroup grp_items
*/
struct t_improvement
{
t_material matdesc;
int32_t quality;
};
/** /**
* The Items module * The Items module
* \ingroup grp_modules * \ingroup grp_modules
* \ingroup grp_items * \ingroup grp_items
*/ */
class DFHACK_EXPORT Items : public Module namespace Simple
{
namespace Items
{ {
public:
/**
* All the known item types as an enum
* From http://df.magmawiki.com/index.php/DF2010:Item_token
*/
enum item_types
{
BAR, ///< Bars, such as metal, fuel, or soap.
SMALLGEM, ///< Cut gemstones usable in jeweler's workshop
BLOCKS, ///< Blocks of any kind.
ROUGH, ///< Rough gemstones.
BOULDER, ///< or IT_STONE - raw mined stone.
STONE = BOULDER,
WOOD, ///< Wooden logs.
DOOR, ///< Doors.
FLOODGATE, ///< Floodgates.
BED, ///< Beds.
CHAIR, ///< Chairs and thrones.
CHAIN, ///< Restraints.
FLASK, ///< Flasks.
GOBLET, ///< Goblets.
INSTRUMENT, ///< Musical instruments. Subtypes come from item_instrument.txt
TOY, ///< Toys. Subtypes come from item_toy.txt
WINDOW, ///< Glass windows.
CAGE, ///< Cages.
BARREL, ///< Barrels.
BUCKET, ///< Buckets.
ANIMALTRAP, ///< Animal traps.
TABLE, ///< Tables.
COFFIN, ///< Coffins.
STATUE, ///< Statues.
CORPSE, ///< Corpses.
WEAPON, ///< Weapons. Subtypes come from item_weapon.txt
ARMOR, ///< Armor and clothing worn on the upper body. Subtypes come from item_armor.txt
SHOES, ///< Armor and clothing worn on the feet. Subtypes come from item_shoes.txt
SHIELD, ///< Shields and bucklers. Subtypes come from item_shield.txt
HELM, ///< Armor and clothing worn on the head. Subtypes come from item_helm.txt
GLOVES, ///< Armor and clothing worn on the hands. Subtypes come from item_gloves.txt
BOX, ///< Chests (wood), coffers (stone), boxes (glass), and bags (cloth or leather).
BIN, ///< Bins.
ARMORSTAND, ///< Armor stands.
WEAPONRACK, ///< Weapon racks.
CABINET, ///< Cabinets.
FIGURINE, ///< Figurines.
AMULET, ///< Amulets.
SCEPTER, ///< Scepters.
AMMO, ///< Ammunition for hand-held weapons. Subtypes come from item_ammo.txt
CROWN, ///< Crowns.
RING, ///< Rings.
EARRING, ///< Earrings.
BRACELET, ///< Bracelets.
GEM, ///< Large gems.
ANVIL, ///< Anvils.
CORPSEPIECE,///< Body parts.
REMAINS, ///< Dead vermin bodies.
MEAT, ///< Butchered meat.
FISH, ///< Prepared fish.
FISH_RAW, ///< Unprepared fish.
VERMIN, ///< Live vermin.
PET, ///< Tame vermin.
SEEDS, ///< Seeds from plants.
PLANT, ///< Plants.
SKIN_TANNED,///< Tanned skins.
LEAVES, ///< Leaves, usually from quarry bushes.
THREAD, ///< Thread gathered from webs or made at the farmer's workshop.
CLOTH, ///< Cloth made at the loom.
TOTEM, ///< Skull totems.
PANTS, ///< Armor and clothing worn on the legs. Subtypes come from item_pants.txt
BACKPACK, ///< Backpacks.
QUIVER, ///< Quivers.
CATAPULTPARTS, ///< Catapult parts.
BALLISTAPARTS, ///< Ballista parts.
SIEGEAMMO, ///< Siege engine ammunition. Subtypes come from item_siegeammo.txt
BALLISTAARROWHEAD, ///< Ballista arrow heads.
TRAPPARTS, ///< Mechanisms.
TRAPCOMP, ///< Trap components. Subtypes come from item_trapcomp.txt
DRINK, ///< Alcoholic drinks.
POWDER_MISC,///< Powders such as flour, gypsum plaster, dye, or sand.
CHEESE, ///< Pieces of cheese.
FOOD, ///< Prepared meals. Subtypes come from item_food.txt
LIQUID_MISC,///< Liquids such as water, lye, and extracts.
COIN, ///< Coins.
GLOB, ///< Fat, tallow, pastes/pressed objects, and small bits of molten rock/metal.
ROCK, ///< Small rocks (usually sharpened and/or thrown in adventurer mode)
PIPE_SECTION, ///< Pipe sections.
HATCH_COVER, ///< Hatch covers.
GRATE, ///< Grates.
QUERN, ///< Querns.
MILLSTONE, ///< Millstones.
SPLINT, ///< Splints.
CRUTCH, ///< Crutches.
TRACTION_BENCH, ///< Traction benches.
ORTHOPEDIC_CAST, ///< Casts.
TOOL, ///< Tools. Subtypes come from item_tool.txt
SLAB, ///< Slabs.
EGG, ///< Eggs.
};
public:
Items();
~Items();
bool Start();
bool Finish();
/// Read the item vector from DF into a supplied vector
bool readItemVector(std::vector<df_item *> &items);
/// Look for a particular item by ID
df_item * findItemByID(int32_t id);
/// Make a partial copy of a DF item
bool copyItem(df_item * source, dfh_item & target);
/// write copied item back to its origin
bool writeItem(const dfh_item & item);
/// get the class name of an item /// Look for a particular item by ID
std::string getItemClass(const df_item * item); DFHACK_EXPORT df::item * findItemByID(int32_t id);
/// who owns this item we already read?
int32_t getItemOwnerID(const df_item * item); /// Make a partial copy of a DF item
/// which item is it contained in? DFHACK_EXPORT bool copyItem(df::item * source, dfh_item & target);
int32_t getItemContainerID(const df_item * item); /// write copied item back to its origin
/// which items does it contain? DFHACK_EXPORT bool writeItem(const dfh_item & item);
bool getContainedItems(const df_item * item, /*output*/ std::vector<int32_t> &items);
/// wipe out the owner records /// get the class name of an item
bool removeItemOwner(df_item * item, Units *creatures); DFHACK_EXPORT std::string getItemClass(const df::item * item);
/// read item references, filtered by class /// who owns this item we already read?
bool readItemRefs(const df_item * item, const ClassNameCheck &classname, DFHACK_EXPORT int32_t getItemOwnerID(const df::item * item);
/// which item is it contained in?
DFHACK_EXPORT int32_t getItemContainerID(const df::item * item);
/// which items does it contain?
DFHACK_EXPORT bool getContainedItems(const df::item * item, /*output*/ std::vector<int32_t> &items);
/// wipe out the owner records
DFHACK_EXPORT bool removeItemOwner(df::item * item, Units *creatures);
/// read item references, filtered by class
DFHACK_EXPORT bool readItemRefs(const df::item * item, const df::general_ref_type type,
/*output*/ std::vector<int32_t> &values); /*output*/ std::vector<int32_t> &values);
/// get list of item references that are unknown along with their values }
bool unknownRefs(const df_item * item, /*output*/ std::vector<std::pair<std::string, int32_t> >& refs); }
private:
class Private;
Private* d;
};
} }

@ -0,0 +1,59 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef CL_MOD_JOB
#define CL_MOD_JOB
#include "Export.h"
#include "Module.h"
#include <ostream>
namespace df
{
struct job;
struct job_item;
struct job_item_filter;
struct building;
}
namespace DFHack
{
// Duplicate the job structure. It is not linked into any DF lists.
DFHACK_EXPORT df::job *cloneJobStruct(df::job *job);
// Delete a cloned structure.
DFHACK_EXPORT void deleteJobStruct(df::job *job);
DFHACK_EXPORT bool operator== (const df::job_item &a, const df::job_item &b);
DFHACK_EXPORT bool operator== (const df::job &a, const df::job &b);
DFHACK_EXPORT void printJobDetails(Core *c, df::job *job);
DFHACK_EXPORT df::building *getJobHolder(df::job *job);
DFHACK_EXPORT bool linkJobIntoWorld(df::job *job, bool new_id = true);
}
#endif

@ -149,7 +149,7 @@ namespace DFHack
/// placeholder /// placeholder
bool discovered; bool discovered;
/// this is NOT part of the DF feature, but an address of the feature as seen by DFhack. /// this is NOT part of the DF feature, but an address of the feature as seen by DFhack.
uint32_t origin; void * origin;
}; };

@ -34,11 +34,113 @@ distribution.
#include "Types.h" #include "Types.h"
#include "BitArray.h" #include "BitArray.h"
#include "DataDefs.h"
#include "df/material.h"
#include <vector> #include <vector>
#include <string> #include <string>
namespace df
{
struct item;
struct inorganic_raw;
struct plant_raw;
struct creature_raw;
struct historical_figure;
struct material_vec_ref;
struct job_item;
union job_material_category;
union dfhack_material_category;
union job_item_flags1;
union job_item_flags2;
union job_item_flags3;
}
namespace DFHack namespace DFHack
{ {
struct DFHACK_EXPORT MaterialInfo {
static const int NUM_BUILTIN = 19;
static const int GROUP_SIZE = 200;
static const int CREATURE_BASE = NUM_BUILTIN;
static const int FIGURE_BASE = NUM_BUILTIN + GROUP_SIZE;
static const int PLANT_BASE = NUM_BUILTIN + GROUP_SIZE*2;
static const int END_BASE = NUM_BUILTIN + GROUP_SIZE*3;
int16_t type;
int32_t index;
df::material *material;
enum Mode {
Builtin,
Inorganic,
Creature,
Plant
};
Mode mode;
int16_t subtype;
df::inorganic_raw *inorganic;
df::creature_raw *creature;
df::plant_raw *plant;
df::historical_figure *figure;
public:
MaterialInfo(int16_t type = -1, int32_t index = -1) { decode(type, index); }
template<class T> MaterialInfo(T *ptr) { decode(ptr); }
bool isValid() const { return material != NULL; }
bool decode(int16_t type, int32_t index = -1);
bool decode(df::item *item);
bool decode(const df::material_vec_ref &vr, int idx);
template<class T> bool decode(T *ptr) {
// Assume and exploit a certain naming convention
return ptr ? decode(ptr->mat_type, ptr->mat_index) : decode(-1);
}
bool find(const std::string &token);
bool findBuiltin(const std::string &token);
bool findInorganic(const std::string &token);
bool findPlant(const std::string &token, const std::string &subtoken);
bool findCreature(const std::string &token, const std::string &subtoken);
std::string toString(uint16_t temp = 10015, bool named = true);
bool isAnyCloth();
void getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask);
void getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask);
void getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask);
df::craft_material_class getCraftClass();
bool matches(const MaterialInfo &mat)
{
if (!mat.isValid()) return true;
return (type == mat.type) &&
(mat.index == -1 || index == mat.index);
}
bool matches(const df::job_material_category &cat);
bool matches(const df::dfhack_material_category &cat);
bool matches(const df::job_item &item);
};
DFHACK_EXPORT bool parseJobMaterialCategory(df::job_material_category *cat, const std::string &token);
DFHACK_EXPORT bool parseJobMaterialCategory(df::dfhack_material_category *cat, const std::string &token);
inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) {
return a.type == b.type && a.index == b.index;
}
inline bool operator!= (const MaterialInfo &a, const MaterialInfo &b) {
return a.type != b.type || a.index != b.index;
}
typedef int32_t t_materialIndex; typedef int32_t t_materialIndex;
typedef int16_t t_materialType, t_itemType, t_itemSubtype; typedef int16_t t_materialType, t_itemType, t_itemSubtype;

@ -557,7 +557,7 @@ namespace DFHack
int16_t unk_280; int16_t unk_280;
int32_t unk_284; int32_t unk_284;
std::vector<df_item *> inventory; // 288 - vector of item pointers std::vector<df::item *> inventory; // 288 - vector of item pointers
std::vector<int32_t> owned_items; // 298 - vector of item IDs std::vector<int32_t> owned_items; // 298 - vector of item IDs
std::vector<uint32_t> unk_2a8; std::vector<uint32_t> unk_2a8;
std::vector<uint32_t> unk_2b8; std::vector<uint32_t> unk_2b8;
@ -777,8 +777,8 @@ namespace DFHack
bool ReadJob(const df_unit * unit, std::vector<t_material> & mat); bool ReadJob(const df_unit * unit, std::vector<t_material> & mat);
bool ReadInventoryByIdx(const uint32_t index, std::vector<df_item *> & item); bool ReadInventoryByIdx(const uint32_t index, std::vector<df::item *> & item);
bool ReadInventoryByPtr(const df_unit * unit, std::vector<df_item *> & item); bool ReadInventoryByPtr(const df_unit * unit, std::vector<df::item *> & item);
bool ReadOwnedItemsByIdx(const uint32_t index, std::vector<int32_t> & item); bool ReadOwnedItemsByIdx(const uint32_t index, std::vector<int32_t> & item);
bool ReadOwnedItemsByPtr(const df_unit * unit, std::vector<int32_t> & item); bool ReadOwnedItemsByPtr(const df_unit * unit, std::vector<int32_t> & item);
@ -807,8 +807,6 @@ namespace DFHack
void CopyNameTo(df_unit *creature, df_name * target); void CopyNameTo(df_unit *creature, df_name * target);
protected:
friend class Items;
bool RemoveOwnedItemByIdx(const uint32_t index, int32_t id); bool RemoveOwnedItemByIdx(const uint32_t index, int32_t id);
bool RemoveOwnedItemByPtr(df_unit * unit, int32_t id); bool RemoveOwnedItemByPtr(df_unit * unit, int32_t id);

@ -1,86 +1,38 @@
#pragma once #pragma once
#ifndef CL_MOD_VERMIN
#define CL_MOD_VERMIN
/** /**
* \defgroup grp_vermin Wild vermin (ants, bees, etc) * \defgroup grp_vermin Wild vermin (ants, bees, etc)
* @ingroup grp_vermin
*/ */
#include "Export.h" #include "Export.h"
#include "Module.h" namespace DFHack { namespace Simple { namespace Vermin
#ifdef __cplusplus
namespace DFHack
{ {
#endif
/** /**
* Structure for holding a read DF vermin spawn point object * Structure for holding a read DF vermin spawn point object
* \ingroup grp_vermin * \ingroup grp_vermin
*/ */
struct t_spawnPoint struct t_vermin
{ {
uint32_t origin; void * origin;
int16_t race; int16_t race;
uint16_t type; int16_t caste;
uint16_t x; uint16_t x;
uint16_t y; uint16_t y;
uint16_t z; uint16_t z;
bool in_use;
uint8_t unknown;
uint32_t countdown; uint32_t countdown;
bool visible:1;
bool is_colony:1; /// Is vermin object a colony?
}; };
#ifdef __cplusplus static const uint16_t TYPE_WILD_COLONY = 0xFFFF;
class DFContextShared;
class SpawnPoints;
/** /**
* The Vermin module - allows reading DF vermin * Get number of vermin objects
* \ingroup grp_modules
* \ingroup grp_vermin
*/ */
class DFHACK_EXPORT Vermin : public Module DFHACK_EXPORT uint32_t getNumVermin();
{ /**
public: * Read from vermin object
Vermin(); */
~Vermin(); DFHACK_EXPORT bool Read (const uint32_t index, t_vermin & point);
/**
bool Finish(); * Write into vermin object
*/
// NOTE: caller must call delete on result when done. DFHACK_EXPORT bool Write (const uint32_t index, t_vermin & point);
SpawnPoints* getSpawnPoints(); } } } // end DFHack::Simple::Vermin
private:
struct Private;
Private *d;
friend class SpawnPoints;
};
class DFHACK_EXPORT SpawnPoints
{
public:
static const uint16_t TYPE_WILD_COLONY = 0xFFFF;
protected:
SpawnPoints(Vermin * v);
public:
~SpawnPoints();
size_t size();
bool Read (const uint32_t index, t_spawnPoint & point);
bool Write (const uint32_t index, t_spawnPoint & point);
bool isValid();
static bool isWildColony(t_spawnPoint & point);
private:
Vermin* v;
std::vector <void*> * p_sp;
friend class Vermin;
};
}
#endif // __cplusplus
#endif

@ -80,6 +80,30 @@ namespace DFHack
GameType g_type; GameType g_type;
}; };
class DFContextShared; class DFContextShared;
class DFHACK_EXPORT PersistentDataItem {
friend class World;
int id;
std::string key_value;
std::string *str_value;
int *int_values;
public:
static const int NumInts = 7;
bool isValid() { return id != 0; }
const std::string &key() { return key_value; }
std::string &val() { return *str_value; }
int &ival(int i) { return int_values[i]; }
PersistentDataItem() : id(0), str_value(0), int_values(0) {}
PersistentDataItem(int id, const std::string &key, std::string *sv, int *iv)
: id(id), key_value(key), str_value(sv), int_values(iv) {}
};
/** /**
* The World module * The World module
* \ingroup grp_modules * \ingroup grp_modules
@ -108,6 +132,14 @@ namespace DFHack
bool ReadGameMode(t_gamemodes& rd); bool ReadGameMode(t_gamemodes& rd);
bool WriteGameMode(const t_gamemodes & wr); // this is very dangerous bool WriteGameMode(const t_gamemodes & wr); // this is very dangerous
std::string ReadWorldFolder(); std::string ReadWorldFolder();
// Store data in fake historical figure names.
// This ensures that the values are stored in save games.
PersistentDataItem AddPersistentData(const std::string &key);
PersistentDataItem GetPersistentData(const std::string &key);
void GetPersistentData(std::vector<PersistentDataItem> *vec, const std::string &key);
void DeletePersistentData(const PersistentDataItem &item);
private: private:
struct Private; struct Private;
Private *d; Private *d;

@ -30,9 +30,9 @@ distribution.
#include "Module.h" #include "Module.h"
#include "Types.h" #include "Types.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "modules/Materials.h"
#include "modules/Items.h"
#include "Core.h" #include "Core.h"
#include "modules/Items.h"
/** /**
* \defgroup grp_kitchen Kitchen settings * \defgroup grp_kitchen Kitchen settings
* @ingroup grp_modules * @ingroup grp_modules
@ -40,6 +40,8 @@ distribution.
namespace DFHack namespace DFHack
{ {
namespace Simple
{
namespace Kitchen namespace Kitchen
{ {
typedef uint8_t t_exclusionType; typedef uint8_t t_exclusionType;
@ -52,45 +54,33 @@ const t_itemSubtype limitSubtype = 0; // used to store limit as an entry in the
const t_exclusionType limitExclusion = 4; // used to store limit as an entry in the exclusion list const t_exclusionType limitExclusion = 4; // used to store limit as an entry in the exclusion list
/** /**
* Kitchen exclusions manipulator class. Currently geared towards plants and seeds. * Kitchen exclusions manipulator. Currently geared towards plants and seeds.
* @ingroup grp_kitchen * \ingroup grp_modules
* \ingroup grp_kitchen
*/ */
class DFHACK_EXPORT Exclusions
{
public:
/// ctor
Exclusions(DFHack::Core& core_);
/// dtor
~Exclusions();
/// print the exclusion list, with the material index also translated into its token (for organics) - for debug really
void debug_print() const;
/// remove this material from the exclusion list if it is in it // print the exclusion list, with the material index also translated into its token (for organics) - for debug really
void allowPlantSeedCookery(t_materialIndex materialIndex); DFHACK_EXPORT void debug_print(Core &);
/// add this material to the exclusion list, if it is not already in it // remove this material from the exclusion list if it is in it
void denyPlantSeedCookery(t_materialIndex materialIndex); DFHACK_EXPORT void allowPlantSeedCookery(t_materialIndex materialIndex);
/// fills a map with info from the limit info storage entries in the exclusion list // add this material to the exclusion list, if it is not already in it
void fillWatchMap(std::map<t_materialIndex, unsigned int>& watchMap) const; DFHACK_EXPORT void denyPlantSeedCookery(t_materialIndex materialIndex);
/// removes a limit info storage entry from the exclusion list if it's present // fills a map with info from the limit info storage entries in the exclusion list
void removeLimit(t_materialIndex materialIndex); DFHACK_EXPORT void fillWatchMap(std::map<t_materialIndex, unsigned int>& watchMap);
/// add a limit info storage item to the exclusion list, or alters an existing one // removes a limit info storage entry from the exclusion list if it's present
void setLimit(t_materialIndex materialIndex, unsigned int limit); DFHACK_EXPORT void removeLimit(t_materialIndex materialIndex);
/// clears all limit info storage items from the exclusion list // add a limit info storage item to the exclusion list, or alters an existing one
void clearLimits(); DFHACK_EXPORT void setLimit(t_materialIndex materialIndex, unsigned int limit);
/// the size of the exclusions vectors (they are all the same size - if not, there is a problem!) // clears all limit info storage items from the exclusion list
std::size_t size() const; DFHACK_EXPORT void clearLimits();
private:
class Private;
Private* d;
};
DFHACK_EXPORT std::size_t size();
}
} }
} }

@ -32,180 +32,65 @@ using namespace std;
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "Types.h" #include "Types.h"
#include "Error.h" #include "Error.h"
#include "modules/Buildings.h" #include "modules/Buildings.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
using namespace DFHack; using namespace DFHack;
using namespace DFHack::Simple;
//raw #include "DataDefs.h"
struct t_building_df40d #include "df/world.h"
{ #include "df/building_def.h"
uint32_t vtable; #include "df/building.h"
uint32_t x1; #include "df/building_workshopst.h"
uint32_t y1;
uint32_t centerx;
uint32_t x2;
uint32_t y2;
uint32_t centery;
uint32_t z;
uint32_t height;
t_matglossPair material;
// not complete
};
struct Buildings::Private
{
uint32_t buildings_vector;
uint32_t custom_workshop_vector;
uint32_t building_custom_workshop_type;
uint32_t custom_workshop_type;
uint32_t custom_workshop_name;
int32_t custom_workshop_id;
DfVector <uint32_t> * p_bld;
Process * owner;
bool Inited;
bool hasCustomWorkshops;
bool Started;
};
Module* DFHack::createBuildings()
{
return new Buildings();
}
Buildings::Buildings() using namespace df::enums;
{ using df::global::world;
Core & c = Core::getInstance(); using df::building_def;
d = new Private;
d->p_bld = NULL;
d->Inited = d->Started = d->hasCustomWorkshops = false;
VersionInfo * mem = c.vinfo;
d->owner = c.p;
OffsetGroup * OG_build = mem->getGroup("Buildings");
d->Inited = true;
try
{
d->buildings_vector = OG_build->getAddress ("buildings_vector");
}
catch(DFHack::Error::AllMemdef &e)
{
cerr << "Buildings not available... " << e.what() << endl;
d->Inited = false;
}
if(d->Inited)
{
try
{
d->custom_workshop_vector = OG_build->getAddress("custom_workshop_vector");
d->building_custom_workshop_type = OG_build->getOffset("building_custom_workshop_type");
d->custom_workshop_type = OG_build->getOffset("custom_workshop_type");
d->custom_workshop_name = OG_build->getOffset("custom_workshop_name");
mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id);
d->hasCustomWorkshops = true;
}
catch(DFHack::Error::AllMemdef &e)
{
cerr << "Custom workshops not available. Memory Definition: " << e.what() << endl;
}
}
}
Buildings::~Buildings() uint32_t Buildings::getNumBuildings()
{ {
if(d->Started) return world->buildings.all.size();
Finish();
delete d;
}
bool Buildings::Start(uint32_t & numbuildings)
{
if(!d->Inited)
return false;
d->p_bld = new DfVector <uint32_t> (d->buildings_vector);
numbuildings = d->p_bld->size();
d->Started = true;
return true;
} }
bool Buildings::Read (const uint32_t index, t_building & building) bool Buildings::Read (const uint32_t index, t_building & building)
{ {
if(!d->Started) Core & c = Core::getInstance();
return false; df::building *bld_40d = world->buildings.all[index];
t_building_df40d bld_40d;
// read pointer from vector at position
uint32_t temp = d->p_bld->at (index);
//d->p_bld->read(index,(uint8_t *)&temp);
//read building from memory
d->owner->read (temp, sizeof (t_building_df40d), (uint8_t *) &bld_40d);
// transform // transform
int32_t type = -1; int32_t type = -1;
d->owner->getDescriptor()->resolveObjectToClassID (temp, type); c.vinfo->resolveObjectToClassID ( (char *)bld_40d, type);
building.origin = temp; building.x1 = bld_40d->x1;
building.vtable = bld_40d.vtable; building.x2 = bld_40d->x2;
building.x1 = bld_40d.x1; building.y1 = bld_40d->y1;
building.x2 = bld_40d.x2; building.y2 = bld_40d->y2;
building.y1 = bld_40d.y1; building.z = bld_40d->z;
building.y2 = bld_40d.y2; building.material.index = bld_40d->mat_index;
building.z = bld_40d.z; building.material.type = bld_40d->mat_type;
building.material = bld_40d.material;
building.type = type; building.type = type;
return true; building.custom_type = bld_40d->getCustomType();
} building.origin = (void *) &bld_40d;
bool Buildings::Finish()
{
if(d->p_bld)
{
delete d->p_bld;
d->p_bld = NULL;
}
d->Started = false;
return true; return true;
} }
bool Buildings::ReadCustomWorkshopTypes(map <uint32_t, string> & btypes) bool Buildings::ReadCustomWorkshopTypes(map <uint32_t, string> & btypes)
{ {
if(!d->Inited) Core & c = Core::getInstance();
return false;
if(!d->hasCustomWorkshops) vector <building_def *> & bld_def = world->raws.buildings.all;
return false; uint32_t size = bld_def.size();
Process * p = d->owner;
DfVector <uint32_t> p_matgloss (d->custom_workshop_vector);
uint32_t size = p_matgloss.size();
btypes.clear(); btypes.clear();
for (uint32_t i = 0; i < size;i++) c.con.print("Probing vector at 0x%x for custom workshops.\n", &bld_def);
for (auto iter = bld_def.begin(); iter != bld_def.end();iter++)
{ {
string out = p->readSTLString (p_matgloss[i] + d->custom_workshop_name); building_def * temp = *iter;
uint32_t type = p->readDWord (p_matgloss[i] + d->custom_workshop_type); btypes[temp->id] = temp->code;
#ifdef DEBUG c.con.print("%d : %s\n",temp->id, temp->code.c_str());
cout << out << ": " << type << endl;
#endif
btypes[type] = out;
} }
return true; return true;
} }
int32_t Buildings::GetCustomWorkshopType(t_building & building)
{
if(!d->Inited)
return false;
if(!d->hasCustomWorkshops)
return false;
int32_t type = (int32_t)building.type;
int32_t ret = -1;
if(type != -1 && type == d->custom_workshop_id)
{
// read the custom workshop subtype
ret = (int32_t) d->owner->readDWord(building.origin + d->building_custom_workshop_type);
}
return ret;
}

@ -33,7 +33,6 @@ using namespace std;
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "Types.h" #include "Types.h"
#include "modules/Constructions.h" #include "modules/Constructions.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
@ -43,10 +42,7 @@ using namespace DFHack;
struct Constructions::Private struct Constructions::Private
{ {
uint32_t construction_vector; vector <t_construction *> * p_cons;
// translation
DfVector <uint32_t> * p_cons;
Process * owner; Process * owner;
bool Inited; bool Inited;
bool Started; bool Started;
@ -62,10 +58,9 @@ Constructions::Constructions()
Core & c = Core::getInstance(); Core & c = Core::getInstance();
d = new Private; d = new Private;
d->owner = c.p; d->owner = c.p;
d->p_cons = 0;
d->Inited = d->Started = false; d->Inited = d->Started = false;
VersionInfo * mem = c.vinfo; VersionInfo * mem = c.vinfo;
d->construction_vector = mem->getGroup("Constructions")->getAddress ("vector"); d->p_cons = (decltype(d->p_cons)) mem->getGroup("Constructions")->getAddress ("vector");
d->Inited = true; d->Inited = true;
} }
@ -78,7 +73,6 @@ Constructions::~Constructions()
bool Constructions::Start(uint32_t & numconstructions) bool Constructions::Start(uint32_t & numconstructions)
{ {
d->p_cons = new DfVector <uint32_t> (d->construction_vector);
numconstructions = d->p_cons->size(); numconstructions = d->p_cons->size();
d->Started = true; d->Started = true;
return true; return true;
@ -89,24 +83,14 @@ bool Constructions::Read (const uint32_t index, t_construction & construction)
{ {
if(!d->Started) return false; if(!d->Started) return false;
// read pointer from vector at position t_construction * orig = d->p_cons->at(index);
uint32_t temp = d->p_cons->at (index); construction = *orig;
construction.origin = orig;
//read construction from memory
d->owner->read (temp, sizeof (t_construction), (uint8_t *) &construction);
// transform
construction.origin = temp;
return true; return true;
} }
bool Constructions::Finish() bool Constructions::Finish()
{ {
if(d->p_cons)
{
delete d->p_cons;
d->p_cons = NULL;
}
d->Started = false; d->Started = false;
return true; return true;
} }

@ -31,8 +31,7 @@ distribution.
using namespace std; using namespace std;
#include "VersionInfo.h" #include "VersionInfo.h"
//#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "Types.h" #include "Types.h"
#include "modules/Engravings.h" #include "modules/Engravings.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
@ -43,8 +42,7 @@ using namespace DFHack;
struct Engravings::Private struct Engravings::Private
{ {
uint32_t engraving_vector; uint32_t engraving_vector;
// translation vector <t_engraving *> * p_engr;
DfVector <uint32_t> * p_engr;
Process * owner; Process * owner;
bool Inited; bool Inited;
@ -61,9 +59,8 @@ Engravings::Engravings()
Core & c = Core::getInstance(); Core & c = Core::getInstance();
d = new Private; d = new Private;
d->owner = c.p; d->owner = c.p;
d->p_engr = 0;
d->Inited = d->Started = false; d->Inited = d->Started = false;
d->engraving_vector = c.vinfo->getGroup("Engravings")->getAddress ("vector"); d->p_engr = (decltype(d->p_engr)) c.vinfo->getGroup("Engravings")->getAddress ("vector");
d->Inited = true; d->Inited = true;
} }
@ -76,7 +73,8 @@ Engravings::~Engravings()
bool Engravings::Start(uint32_t & numengravings) bool Engravings::Start(uint32_t & numengravings)
{ {
d->p_engr = new DfVector <uint32_t> (d->engraving_vector); if(!d->Inited)
return false;
numengravings = d->p_engr->size(); numengravings = d->p_engr->size();
d->Started = true; d->Started = true;
return true; return true;
@ -88,13 +86,10 @@ bool Engravings::Read (const uint32_t index, dfh_engraving & engraving)
if(!d->Started) return false; if(!d->Started) return false;
// read pointer from vector at position // read pointer from vector at position
uint32_t temp = d->p_engr->at (index); engraving.s = *d->p_engr->at (index);
//read construction from memory
d->owner->read (temp, sizeof (t_engraving), (uint8_t *) &(engraving.s));
// transform // transform
engraving.origin = temp; engraving.origin = d->p_engr->at (index);
return true; return true;
} }
@ -108,11 +103,6 @@ bool Engravings::Write (const dfh_engraving & engraving)
bool Engravings::Finish() bool Engravings::Finish()
{ {
if(d->p_engr)
{
delete d->p_engr;
d->p_engr = NULL;
}
d->Started = false; d->Started = false;
return true; return true;
} }

@ -37,7 +37,6 @@ using namespace std;
#include "Error.h" #include "Error.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"

@ -38,11 +38,29 @@ using namespace std;
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "MiscUtils.h"
using namespace DFHack; using namespace DFHack;
#include "DataDefs.h" #include "DataDefs.h"
#include "df/world.h"
#include "df/cursor.h" #include "df/cursor.h"
#include "df/viewscreen_dwarfmodest.h" #include "df/viewscreen_dwarfmodest.h"
#include "df/viewscreen_unitjobsst.h"
#include "df/viewscreen_itemst.h"
#include "df/ui.h"
#include "df/ui_unit_view_mode.h"
#include "df/ui_sidebar_menus.h"
#include "df/ui_look_list.h"
#include "df/job.h"
#include "df/ui_build_selector.h"
#include "df/building_workshopst.h"
#include "df/building_furnacest.h"
#include "df/general_ref.h"
#include "df/unit_inventory_item.h"
#include "df/report.h"
#include "df/popup_message.h"
using namespace df::enums;
// Predefined common guard functions // Predefined common guard functions
@ -61,6 +79,18 @@ bool DFHack::dwarfmode_hotkey(Core *, df::viewscreen *top)
return !!strict_virtual_cast<df::viewscreen_dwarfmodest>(top); return !!strict_virtual_cast<df::viewscreen_dwarfmodest>(top);
} }
bool DFHack::unitjobs_hotkey(Core *, df::viewscreen *top)
{
// Require the main dwarf mode screen
return !!strict_virtual_cast<df::viewscreen_unitjobsst>(top);
}
bool DFHack::item_details_hotkey(Core *, df::viewscreen *top)
{
// Require the main dwarf mode screen
return !!strict_virtual_cast<df::viewscreen_itemst>(top);
}
bool DFHack::cursor_hotkey(Core *c, df::viewscreen *top) bool DFHack::cursor_hotkey(Core *c, df::viewscreen *top)
{ {
if (!dwarfmode_hotkey(c, top)) if (!dwarfmode_hotkey(c, top))
@ -73,6 +103,347 @@ bool DFHack::cursor_hotkey(Core *c, df::viewscreen *top)
return true; return true;
} }
bool DFHack::workshop_job_hotkey(Core *c, df::viewscreen *top)
{
using namespace ui_sidebar_mode;
using df::global::ui;
using df::global::world;
using df::global::ui_workshop_in_add;
using df::global::ui_workshop_job_cursor;
if (!dwarfmode_hotkey(c,top))
return false;
switch (ui->main.mode) {
case QueryBuilding:
{
if (!ui_workshop_job_cursor) // allow missing
return false;
df::building *selected = world->selected_building;
if (!virtual_cast<df::building_workshopst>(selected) &&
!virtual_cast<df::building_furnacest>(selected))
return false;
// No jobs?
if (selected->jobs.empty() ||
selected->jobs[0]->job_type == job_type::DestroyBuilding)
return false;
// Add job gui activated?
if (ui_workshop_in_add && *ui_workshop_in_add)
return false;
return true;
};
default:
return false;
}
}
bool DFHack::build_selector_hotkey(Core *c, df::viewscreen *top)
{
using namespace ui_sidebar_mode;
using df::global::ui;
using df::global::ui_build_selector;
if (!dwarfmode_hotkey(c,top))
return false;
switch (ui->main.mode) {
case Build:
{
if (!ui_build_selector) // allow missing
return false;
// Not selecting, or no choices?
if (ui_build_selector->building_type < 0 ||
ui_build_selector->stage != 2 ||
ui_build_selector->choices.empty())
return false;
return true;
};
default:
return false;
}
}
bool DFHack::view_unit_hotkey(Core *c, df::viewscreen *top)
{
using df::global::ui;
using df::global::world;
using df::global::ui_selected_unit;
if (!dwarfmode_hotkey(c,top))
return false;
if (ui->main.mode != ui_sidebar_mode::ViewUnits)
return false;
if (!ui_selected_unit) // allow missing
return false;
return vector_get(world->units.other[0], *ui_selected_unit) != NULL;
}
bool DFHack::unit_inventory_hotkey(Core *c, df::viewscreen *top)
{
using df::global::ui_unit_view_mode;
if (!view_unit_hotkey(c,top))
return false;
if (!ui_unit_view_mode)
return false;
return ui_unit_view_mode->value == df::ui_unit_view_mode::Inventory;
}
df::job *DFHack::getSelectedWorkshopJob(Core *c, bool quiet)
{
using df::global::world;
using df::global::ui_workshop_job_cursor;
if (!workshop_job_hotkey(c, c->getTopViewscreen())) {
if (!quiet)
c->con.printerr("Not in a workshop, or no job is highlighted.\n");
return NULL;
}
df::building *selected = world->selected_building;
int idx = *ui_workshop_job_cursor;
if (idx < 0 || idx >= selected->jobs.size())
{
c->con.printerr("Invalid job cursor index: %d\n", idx);
return NULL;
}
return selected->jobs[idx];
}
bool DFHack::any_job_hotkey(Core *c, df::viewscreen *top)
{
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitjobsst, top))
return vector_get(screen->jobs, screen->cursor_pos) != NULL;
return workshop_job_hotkey(c,top);
}
df::job *DFHack::getSelectedJob(Core *c, bool quiet)
{
df::viewscreen *top = c->getTopViewscreen();
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitjobsst, top))
{
df::job *job = vector_get(screen->jobs, screen->cursor_pos);
if (!job && !quiet)
c->con.printerr("Selected unit has no job\n");
return job;
}
else
return getSelectedWorkshopJob(c, quiet);
}
static df::unit *getAnyUnit(Core *c, df::viewscreen *top)
{
using namespace ui_sidebar_mode;
using df::global::ui;
using df::global::world;
using df::global::ui_look_cursor;
using df::global::ui_look_list;
using df::global::ui_selected_unit;
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitjobsst, top))
return vector_get(screen->units, screen->cursor_pos);
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_itemst, top))
{
df::general_ref *ref = vector_get(screen->entry_ref, screen->cursor_pos);
return ref ? ref->getUnit() : NULL;
}
if (!dwarfmode_hotkey(c,top))
return NULL;
switch (ui->main.mode) {
case ViewUnits:
{
if (!ui_selected_unit)
return NULL;
return vector_get(world->units.other[0], *ui_selected_unit);
}
case LookAround:
{
if (!ui_look_list || !ui_look_cursor)
return NULL;
auto item = vector_get(ui_look_list->items, *ui_look_cursor);
if (item && item->type == df::ui_look_list::T_items::Unit)
return item->unit;
else
return NULL;
}
default:
return NULL;
}
}
bool DFHack::any_unit_hotkey(Core *c, df::viewscreen *top)
{
return getAnyUnit(c, top) != NULL;
}
df::unit *DFHack::getSelectedUnit(Core *c, bool quiet)
{
df::unit *unit = getAnyUnit(c, c->getTopViewscreen());
if (!unit && !quiet)
c->con.printerr("No unit is selected in the UI.\n");
return unit;
}
static df::item *getAnyItem(Core *c, df::viewscreen *top)
{
using namespace ui_sidebar_mode;
using df::global::ui;
using df::global::world;
using df::global::ui_look_cursor;
using df::global::ui_look_list;
using df::global::ui_unit_view_mode;
using df::global::ui_building_item_cursor;
using df::global::ui_sidebar_menus;
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_itemst, top))
{
df::general_ref *ref = vector_get(screen->entry_ref, screen->cursor_pos);
return ref ? ref->getItem() : NULL;
}
if (!dwarfmode_hotkey(c,top))
return NULL;
switch (ui->main.mode) {
case ViewUnits:
{
if (!ui_unit_view_mode || !ui_look_cursor || !ui_sidebar_menus)
return NULL;
if (ui_unit_view_mode->value != df::ui_unit_view_mode::Inventory)
return NULL;
auto inv_item = vector_get(ui_sidebar_menus->unit.inv_items, *ui_look_cursor);
return inv_item ? inv_item->item : NULL;
}
case LookAround:
{
if (!ui_look_list || !ui_look_cursor)
return NULL;
auto item = vector_get(ui_look_list->items, *ui_look_cursor);
if (item && item->type == df::ui_look_list::T_items::Item)
return item->item;
else
return NULL;
}
case BuildingItems:
{
if (!ui_building_item_cursor)
return NULL;
VIRTUAL_CAST_VAR(selected, df::building_actual, world->selected_building);
if (!selected)
return NULL;
auto inv_item = vector_get(selected->contained_items, *ui_building_item_cursor);
return inv_item ? inv_item->item : NULL;
}
default:
return NULL;
}
}
bool DFHack::any_item_hotkey(Core *c, df::viewscreen *top)
{
return getAnyItem(c, top) != NULL;
}
df::item *DFHack::getSelectedItem(Core *c, bool quiet)
{
df::item *item = getAnyItem(c, c->getTopViewscreen());
if (!item && !quiet)
c->con.printerr("No item is selected in the UI.\n");
return item;
}
//
void DFHack::showAnnouncement(std::string message, int color, bool bright)
{
using df::global::world;
using df::global::cur_year;
using df::global::cur_year_tick;
int year = 0, year_time = 0;
if (cur_year && cur_year_tick)
{
year = *cur_year;
year_time = *cur_year_tick;
}
else if (!world->status.reports.empty())
{
// Fallback: copy from the last report
df::report *last = world->status.reports.back();
year = last->year;
year_time = last->time;
}
bool continued = false;
while (!message.empty())
{
df::report *new_rep = new df::report();
new_rep->color = color;
new_rep->bright = bright;
new_rep->year = year;
new_rep->time = year_time;
new_rep->flags.bits.continuation = continued;
new_rep->flags.bits.announcement = true;
int size = std::min(message.size(), 73U);
new_rep->text = message.substr(0, size);
message = message.substr(size);
continued = true;
// Add the object to the lists
new_rep->id = world->status.next_report_id++;
world->status.reports.push_back(new_rep);
world->status.announcements.push_back(new_rep);
world->status.display_timer = 2000;
}
}
void DFHack::showPopupAnnouncement(std::string message, int color, bool bright)
{
using df::global::world;
df::popup_message *popup = new df::popup_message();
popup->text = message;
popup->color = color;
popup->bright = bright;
world->status.popups.push_back(popup);
}
// //
Module* DFHack::createGui() Module* DFHack::createGui()
@ -91,16 +462,23 @@ struct Gui::Private
} }
bool Started; bool Started;
uint32_t window_x_offset; int32_t * window_x_offset;
uint32_t window_y_offset; int32_t * window_y_offset;
uint32_t window_z_offset; int32_t * window_z_offset;
uint32_t cursor_xyz_offset; struct xyz
uint32_t designation_xyz_offset; {
uint32_t mouse_xy_offset; int32_t x;
uint32_t window_dims_offset; int32_t y;
int32_t z;
} * cursor_xyz_offset, * designation_xyz_offset;
struct xy
{
int32_t x;
int32_t y;
} * mouse_xy_offset, * window_dims_offset;
bool StartedScreen; bool StartedScreen;
uint32_t screen_tiles_ptr_offset; void * screen_tiles_ptr_offset;
Process * owner; Process * owner;
}; };
@ -157,19 +535,33 @@ Gui::Gui()
try try
{ {
OG_Position = mem->getGroup("Position"); OG_Position = mem->getGroup("Position");
d->window_x_offset = OG_Position->getAddress ("window_x"); d->window_x_offset = (int32_t *) OG_Position->getAddress ("window_x");
d->window_y_offset = OG_Position->getAddress ("window_y"); d->window_y_offset = (int32_t *) OG_Position->getAddress ("window_y");
d->window_z_offset = OG_Position->getAddress ("window_z"); d->window_z_offset = (int32_t *) OG_Position->getAddress ("window_z");
d->cursor_xyz_offset = OG_Position->getAddress ("cursor_xyz"); d->cursor_xyz_offset = (Private::xyz *) OG_Position->getAddress ("cursor_xyz");
d->window_dims_offset = OG_Position->getAddress ("window_dims"); d->window_dims_offset = (Private::xy *) OG_Position->getAddress ("window_dims");
d->Started = true; d->Started = true;
} }
catch(Error::All &){}; catch(Error::All &){};
OG_Position->getSafeAddress("mouse_xy", d->mouse_xy_offset);
OG_Position->getSafeAddress("designation_xyz", d->designation_xyz_offset);
try try
{ {
d->screen_tiles_ptr_offset = OG_Position->getAddress ("screen_tiles_pointer"); d->mouse_xy_offset = (Private::xy *) OG_Position->getAddress ("mouse_xy");
}
catch(Error::All &)
{
d->mouse_xy_offset = 0;
};
try
{
d->designation_xyz_offset = (Private::xyz *) OG_Position->getAddress ("designation_xyz");
}
catch(Error::All &)
{
d->designation_xyz_offset = 0;
};
try
{
d->screen_tiles_ptr_offset = (void *) OG_Position->getAddress ("screen_tiles_pointer");
d->StartedScreen = true; d->StartedScreen = true;
} }
catch(Error::All &){}; catch(Error::All &){};
@ -299,10 +691,10 @@ bool Gui::getScreenTiles (int32_t width, int32_t height, t_screen screen[])
{ {
if(!d->StartedScreen) return false; if(!d->StartedScreen) return false;
uint32_t screen_addr = d->owner->readDWord(d->screen_tiles_ptr_offset); void * screen_addr = (void *) d->owner->readDWord(d->screen_tiles_ptr_offset);
uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/]; uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/];
d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), (uint8_t *) tiles); d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), tiles);
for(int32_t iy=0; iy<height; iy++) for(int32_t iy=0; iy<height; iy++)
{ {

@ -1,4 +1,4 @@
/* /*
https://github.com/peterix/dfhack https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
@ -36,166 +36,382 @@ using namespace std;
#include "Types.h" #include "Types.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "modules/Materials.h" #include "modules/Materials.h"
#include "modules/Items.h" #include "modules/Items.h"
#include "modules/Units.h" #include "modules/Units.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
#include "Virtual.h" #include "Virtual.h"
#include "MiscUtils.h"
#include "df/world.h"
#include "df/item.h"
#include "df/tool_uses.h"
#include "df/itemdef_weaponst.h"
#include "df/itemdef_trapcompst.h"
#include "df/itemdef_toyst.h"
#include "df/itemdef_toolst.h"
#include "df/itemdef_instrumentst.h"
#include "df/itemdef_armorst.h"
#include "df/itemdef_ammost.h"
#include "df/itemdef_siegeammost.h"
#include "df/itemdef_glovesst.h"
#include "df/itemdef_shoesst.h"
#include "df/itemdef_shieldst.h"
#include "df/itemdef_helmst.h"
#include "df/itemdef_pantsst.h"
#include "df/itemdef_foodst.h"
#include "df/trapcomp_flags.h"
#include "df/job_item.h"
#include "df/general_ref.h"
using namespace DFHack; using namespace DFHack;
using namespace DFHack::Simple;
Module* DFHack::createItems() using namespace df::enums;
{ using df::global::world;
return new Items();
} #define ITEMDEF_VECTORS \
ITEM(WEAPON, weapons, itemdef_weaponst) \
class Items::Private ITEM(TRAPCOMP, trapcomps, itemdef_trapcompst) \
ITEM(TOY, toys, itemdef_toyst) \
ITEM(TOOL, tools, itemdef_toolst) \
ITEM(INSTRUMENT, instruments, itemdef_instrumentst) \
ITEM(ARMOR, armor, itemdef_armorst) \
ITEM(AMMO, ammo, itemdef_ammost) \
ITEM(SIEGEAMMO, siege_ammo, itemdef_siegeammost) \
ITEM(GLOVES, gloves, itemdef_glovesst) \
ITEM(SHOES, shoes, itemdef_shoesst) \
ITEM(SHIELD, shields, itemdef_shieldst) \
ITEM(HELM, helms, itemdef_helmst) \
ITEM(PANTS, pants, itemdef_pantsst) \
ITEM(FOOD, food, itemdef_foodst)
bool ItemTypeInfo::decode(df::item_type type_, int16_t subtype_)
{ {
public: using namespace df::enums::item_type;
Process * owner;
std::map<int32_t, df_item *> idLookupTable;
uint32_t refVectorOffset;
uint32_t idFieldOffset;
uint32_t itemVectorAddress;
ClassNameCheck isOwnerRefClass;
ClassNameCheck isContainerRefClass;
ClassNameCheck isContainsRefClass;
// Similar to isOwnerRefClass. Value is unique to each creature, but
// different than the creature's id.
ClassNameCheck isUnitHolderRefClass;
// One of these is present for each creature contained in a cage.
// The value is similar to that for isUnitHolderRefClass, different
// than the creature's ID but unique for each creature.
ClassNameCheck isCagedUnitRefClass;
// ID of bulding containing/holding the item.
ClassNameCheck isBuildingHolderRefClass;
// Building ID of lever/etc which triggers bridge/etc holding type = type_;
// this mechanism. subtype = subtype_;
ClassNameCheck isTriggeredByRefClass; custom = NULL;
// Building ID of bridge/etc which is triggered by lever/etc holding df::world_raws::T_itemdefs &defs = df::global::world->raws.itemdefs;
// this mechanism.
ClassNameCheck isTriggerTargetRefClass;
// Civilization ID of owner of item, for items not owned by the switch (type_) {
// fortress. case NONE:
ClassNameCheck isEntityOwnerRefClass; return false;
// Item has been offered to the caravan. The value is the
// civilization ID of
ClassNameCheck isOfferedRefClass;
// Item is in a depot for trade. Purpose of value is unknown, but is #define ITEM(type,vec,tclass) \
// different for each item, even in the same depot at the same time. case type: \
ClassNameCheck isTradingRefClass; custom = vector_get(defs.vec, subtype); \
break;
ITEMDEF_VECTORS
#undef ITEM
// Item is flying or falling through the air. The value seems to default:
// be the ID for a "projectile information" object. break;
ClassNameCheck isProjectileRefClass; }
std::set<std::string> knownItemRefTypes; return isValid();
}; }
Items::Items() bool ItemTypeInfo::decode(df::item *ptr)
{ {
Core & c = Core::getInstance(); if (!ptr)
d = new Private; return decode(item_type::NONE);
d->owner = c.p; else
return decode(ptr->getType(), ptr->getSubtype());
DFHack::OffsetGroup* itemGroup = c.vinfo->getGroup("Items");
d->itemVectorAddress = itemGroup->getAddress("items_vector");
d->idFieldOffset = itemGroup->getOffset("id");
d->refVectorOffset = itemGroup->getOffset("item_ref_vector");
d->isOwnerRefClass = ClassNameCheck("general_ref_unit_itemownerst");
d->isContainerRefClass = ClassNameCheck("general_ref_contained_in_itemst");
d->isContainsRefClass = ClassNameCheck("general_ref_contains_itemst");
d->isUnitHolderRefClass = ClassNameCheck("general_ref_unit_holderst");
d->isCagedUnitRefClass = ClassNameCheck("general_ref_contains_unitst");
d->isBuildingHolderRefClass
= ClassNameCheck("general_ref_building_holderst");
d->isTriggeredByRefClass = ClassNameCheck("general_ref_building_triggerst");
d->isTriggerTargetRefClass
= ClassNameCheck("general_ref_building_triggertargetst");
d->isEntityOwnerRefClass = ClassNameCheck("general_ref_entity_itemownerst");
d->isOfferedRefClass = ClassNameCheck("general_ref_entity_offeredst");
d->isTradingRefClass = ClassNameCheck("general_ref_unit_tradebringerst");
d->isProjectileRefClass = ClassNameCheck("general_ref_projectilest");
std::vector<std::string> known_names;
ClassNameCheck::getKnownClassNames(known_names);
for (size_t i = 0; i < known_names.size(); i++)
{
if (known_names[i].find("general_ref_") == 0)
d->knownItemRefTypes.insert(known_names[i]);
}
} }
bool Items::Start() std::string ItemTypeInfo::getToken()
{ {
d->idLookupTable.clear(); std::string rv = ENUM_KEY_STR(item_type, type);
return true; if (custom)
rv += ":" + custom->id;
else if (subtype != -1)
rv += stl_sprintf(":%d", subtype);
return rv;
} }
bool Items::Finish() std::string ItemTypeInfo::toString()
{ {
return true; using namespace df::enums::item_type;
switch (type) {
#define ITEM(type,vec,tclass) \
case type: \
if (VIRTUAL_CAST_VAR(cv, df::tclass, custom)) \
return cv->name;
ITEMDEF_VECTORS
#undef ITEM
default:
break;
}
return toLower(ENUM_KEY_STR(item_type, type));
} }
bool Items::readItemVector(std::vector<df_item *> &items) bool ItemTypeInfo::find(const std::string &token)
{ {
std::vector <df_item *> *p_items = (std::vector <df_item *> *) d->itemVectorAddress; using namespace df::enums::item_type;
std::vector<std::string> items;
split_string(&items, token, ":");
d->idLookupTable.clear(); type = NONE;
items.resize(p_items->size()); subtype = -1;
custom = NULL;
if (items.size() < 1 || items.size() > 2)
return false;
if (items[0] == "NONE")
return true;
for (unsigned i = 0; i < p_items->size(); i++) FOR_ENUM_ITEMS(item_type, i)
{ {
df_item * ptr = p_items->at(i); const char *key = ENUM_ATTR(item_type, key, i);
items[i] = ptr; if (key && key == items[0])
d->idLookupTable[ptr->id] = ptr; {
type = i;
break;
}
} }
if (type == NONE)
return false;
if (items.size() == 1)
return true; return true;
df::world_raws::T_itemdefs &defs = df::global::world->raws.itemdefs;
switch (type) {
#define ITEM(type,vec,tclass) \
case type: \
for (int i = 0; i < defs.vec.size(); i++) { \
if (defs.vec[i]->id == items[1]) { \
subtype = i; custom = defs.vec[i]; return true; \
} \
} \
break;
ITEMDEF_VECTORS
#undef ITEM
default:
break;
}
return (subtype >= 0);
} }
df_item * Items::findItemByID(int32_t id) bool ItemTypeInfo::matches(const df::job_item &item, MaterialInfo *mat)
{ {
if (id < 0) using namespace df::enums::item_type;
return 0;
if (d->idLookupTable.empty()) if (!isValid())
{ return mat ? mat->matches(item) : false;
std::vector<df_item *> tmp;
readItemVector(tmp); df::job_item_flags1 ok1, mask1, item_ok1, item_mask1;
df::job_item_flags2 ok2, mask2, item_ok2, item_mask2;
df::job_item_flags3 ok3, mask3, item_ok3, item_mask3;
ok1.whole = mask1.whole = item_ok1.whole = item_mask1.whole = 0;
ok2.whole = mask2.whole = item_ok2.whole = item_mask2.whole = 0;
ok3.whole = mask3.whole = item_ok3.whole = item_mask3.whole = 0;
if (mat) {
mat->getMatchBits(ok1, mask1);
mat->getMatchBits(ok2, mask2);
mat->getMatchBits(ok3, mask3);
} }
return d->idLookupTable[id]; #define OK(id,name) item_ok##id.bits.name = true
#define RQ(id,name) item_mask##id.bits.name = true
// Set up the flag mask
RQ(1,millable); RQ(1,sharpenable); RQ(1,distillable); RQ(1,processable); RQ(1,bag);
RQ(1,extract_bearing_plant); RQ(1,extract_bearing_fish); RQ(1,extract_bearing_vermin);
RQ(1,processable_to_vial); RQ(1,processable_to_bag); RQ(1,processable_to_barrel);
RQ(1,solid); RQ(1,tameable_vermin); RQ(1,sand_bearing); RQ(1,milk); RQ(1,milkable);
RQ(1,not_bin); RQ(1,lye_bearing);
RQ(2,dye); RQ(2,dyeable); RQ(2,dyed); RQ(2,glass_making); RQ(2,screw);
RQ(2,building_material); RQ(2,fire_safe); RQ(2,magma_safe); RQ(2,non_economic);
RQ(2,totemable); RQ(2,plaster_containing); RQ(2,body_part); RQ(2,lye_milk_free);
RQ(2,blunt); RQ(2,unengraved); RQ(2,hair_wool);
RQ(3,any_raw_material); RQ(3,non_pressed); RQ(3,food_storage);
// Compute the ok mask
OK(1,solid);
OK(1,not_bin);
// TODO: furniture, ammo, finished good, craft
switch (type) {
case PLANT:
OK(1,millable); OK(1,processable);
OK(1,distillable);
OK(1,extract_bearing_plant);
OK(1,processable_to_vial);
OK(1,processable_to_bag);
OK(1,processable_to_barrel);
break;
case BOULDER:
OK(1,sharpenable);
OK(2,non_economic);
case BAR:
OK(3,any_raw_material);
case BLOCKS:
case WOOD:
OK(2,building_material);
OK(2,fire_safe); OK(2,magma_safe);
break;
case VERMIN:
OK(1,extract_bearing_fish);
OK(1,extract_bearing_vermin);
OK(1,tameable_vermin);
OK(1,milkable);
break;
case DRINK:
item_ok1.bits.solid = false;
break;
case ROUGH:
OK(2,glass_making);
break;
case ANIMALTRAP:
case CAGE:
OK(1,milk);
OK(1,milkable);
break;
case BUCKET:
case FLASK:
OK(1,milk);
break;
case TOOL:
OK(1,lye_bearing);
OK(1,milk);
OK(2,lye_milk_free);
OK(2,blunt);
if (VIRTUAL_CAST_VAR(def, df::itemdef_toolst, custom)) {
df::enum_field<df::tool_uses,int16_t> key(tool_uses::FOOD_STORAGE);
if (linear_index(def->tool_use, key) >= 0)
OK(3,food_storage);
} else {
OK(3,food_storage);
}
break;
case BARREL:
OK(1,lye_bearing);
OK(1,milk);
OK(2,lye_milk_free);
OK(3,food_storage);
break;
case BOX:
OK(1,bag); OK(1,sand_bearing); OK(1,milk);
OK(2,dye); OK(2,plaster_containing);
break;
case BIN:
item_ok1.bits.not_bin = false;
break;
case LIQUID_MISC:
item_ok1.bits.solid = false;
OK(1,milk);
break;
case POWDER_MISC:
OK(2,dye);
case GLOB:
OK(3,any_raw_material);
OK(3,non_pressed);
break;
case THREAD:
case CLOTH:
OK(2,dyeable); OK(2,dyed);
break;
case WEAPON:
case AMMO:
case ROCK:
OK(2,blunt);
break;
case TRAPCOMP:
if (VIRTUAL_CAST_VAR(def, df::itemdef_trapcompst, custom)) {
if (def->flags.is_set(trapcomp_flags::IS_SCREW))
OK(2,screw);
} else {
OK(2,screw);
}
OK(2,blunt);
break;
case CORPSE:
case CORPSEPIECE:
OK(2,totemable);
OK(2,body_part);
OK(2,hair_wool);
break;
case SLAB:
OK(2,unengraved);
break;
case ANVIL:
OK(2,fire_safe); OK(2,magma_safe);
break;
default:
break;
}
if ((item_ok1.whole & ~item_mask1.whole) ||
(item_ok2.whole & ~item_mask2.whole) ||
(item_ok3.whole & ~item_mask3.whole))
Core::getInstance().con.printerr("ItemTypeInfo.matches inconsistent\n");
#undef OK
#undef RQ
return bits_match(item.flags1.whole, ok1.whole, mask1.whole) &&
bits_match(item.flags2.whole, ok2.whole, mask2.whole) &&
bits_match(item.flags3.whole, ok3.whole, mask3.whole) &&
bits_match(item.flags1.whole, item_ok1.whole, item_mask1.whole) &&
bits_match(item.flags2.whole, item_ok2.whole, item_mask2.whole) &&
bits_match(item.flags3.whole, item_ok3.whole, item_mask3.whole);
} }
Items::~Items() df::item * Items::findItemByID(int32_t id)
{ {
Finish(); if (id < 0)
delete d; return 0;
return df::item::find(id);
} }
bool Items::copyItem(df_item * itembase, DFHack::dfh_item &item) bool Items::copyItem(df::item * itembase, DFHack::dfh_item &item)
{ {
if(!itembase) if(!itembase)
return false; return false;
df_item * itreal = (df_item *) itembase; df::item * itreal = (df::item *) itembase;
item.origin = itembase; item.origin = itembase;
item.x = itreal->x; item.x = itreal->pos.x;
item.y = itreal->y; item.y = itreal->pos.y;
item.z = itreal->z; item.z = itreal->pos.z;
item.id = itreal->id; item.id = itreal->id;
item.age = itreal->age; item.age = itreal->age;
item.flags = itreal->flags; item.flags = itreal->flags;
@ -209,87 +425,72 @@ bool Items::copyItem(df_item * itembase, DFHack::dfh_item &item)
return true; return true;
} }
int32_t Items::getItemOwnerID(const DFHack::df_item * item) int32_t Items::getItemOwnerID(const df::item * item)
{ {
std::vector<int32_t> vals; for (uint32_t i = 0; i < item->itemrefs.size(); i++)
if (readItemRefs(item, d->isOwnerRefClass, vals)) {
return vals[0]; df::general_ref *ref = item->itemrefs[i];
else if (ref->getType() == df::general_ref_type::UNIT_ITEMOWNER)
return ref->getID();
}
return -1; return -1;
} }
int32_t Items::getItemContainerID(const DFHack::df_item * item) int32_t Items::getItemContainerID(const df::item * item)
{ {
std::vector<int32_t> vals; for (uint32_t i = 0; i < item->itemrefs.size(); i++)
if (readItemRefs(item, d->isContainerRefClass, vals)) {
return vals[0]; df::general_ref *ref = item->itemrefs[i];
else if (ref->getType() == df::general_ref_type::CONTAINED_IN_ITEM)
return ref->getID();
}
return -1; return -1;
} }
bool Items::getContainedItems(const DFHack::df_item * item, std::vector<int32_t> &items) bool Items::getContainedItems(const df::item * item, std::vector<int32_t> &items)
{ {
return readItemRefs(item, d->isContainsRefClass, items); return readItemRefs(item, df::general_ref_type::CONTAINS_ITEM, items);
} }
bool Items::readItemRefs(const df_item * item, const ClassNameCheck &classname, std::vector<int32_t> &values) bool Items::readItemRefs(const df::item * item, df::general_ref_type type, std::vector<int32_t> &values)
{ {
const std::vector <t_itemref *> &p_refs = item->itemrefs;
values.clear(); values.clear();
for (uint32_t i=0; i<p_refs.size(); i++) for (uint32_t i = 0; i < item->itemrefs.size(); i++)
{ {
if (classname(d->owner, p_refs[i]->vptr)) df::general_ref *ref = item->itemrefs[i];
values.push_back(int32_t(p_refs[i]->value)); if (ref->getType() == type)
values.push_back(ref->getID());
} }
return !values.empty(); return !values.empty();
} }
bool Items::unknownRefs(const df_item * item, std::vector<std::pair<std::string, int32_t> >& refs) bool Items::removeItemOwner(df::item * item, Units *creatures)
{
refs.clear();
const std::vector <t_itemref *> &p_refs = item->itemrefs;
for (uint32_t i=0; i<p_refs.size(); i++)
{
std::string name = p_refs[i]->getClassName();
if (d->knownItemRefTypes.find(name) == d->knownItemRefTypes.end())
{
refs.push_back(pair<string, int32_t>(name, p_refs[i]->value));
}
}
return (refs.size() > 0);
}
bool Items::removeItemOwner(df_item * item, Units *creatures)
{ {
std::vector <t_itemref *> &p_refs = item->itemrefs; for (uint32_t i = 0; i < item->itemrefs.size(); i++)
for (uint32_t i=0; i<p_refs.size(); i++)
{ {
if (!d->isOwnerRefClass(d->owner, p_refs[i]->vptr)) df::general_ref *ref = item->itemrefs[i];
if (ref->getType() != df::general_ref_type::UNIT_ITEMOWNER)
continue; continue;
int32_t & oid = p_refs[i]->value; df_unit *unit = (df_unit *)ref->getUnit();
int32_t ix = creatures->FindIndexById(oid);
if (ix < 0 || !creatures->RemoveOwnedItemByIdx(ix, item->id)) if (unit == NULL || !creatures->RemoveOwnedItemByPtr(unit, item->id))
{ {
cerr << "RemoveOwnedItemIdx: CREATURE " << ix << " ID " << item->id << " FAILED!" << endl; cerr << "RemoveOwnedItemIdx: CREATURE " << ref->getID() << " ID " << item->id << " FAILED!" << endl;
return false; return false;
} }
p_refs.erase(p_refs.begin() + i--); delete ref;
item->itemrefs.erase(item->itemrefs.begin() + i--);
} }
item->flags.owned = 0; item->flags.bits.owned = 0;
return true; return true;
} }
std::string Items::getItemClass(const df_item * item) std::string Items::getItemClass(const df::item * item)
{ {
const t_virtual * virt = (t_virtual *) item; const t_virtual * virt = (t_virtual *) item;
return virt->getClassName(); return virt->getClassName();

@ -0,0 +1,256 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include <string>
#include <vector>
#include <map>
#include <cassert>
using namespace std;
#include "Core.h"
#include "PluginManager.h"
#include "MiscUtils.h"
#include "modules/Job.h"
#include "modules/Materials.h"
#include "modules/Items.h"
#include "DataDefs.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/job.h"
#include "df/job_item.h"
#include "df/job_list_link.h"
#include "df/general_ref.h"
#include "df/general_ref_unit_workerst.h"
#include "df/general_ref_building_holderst.h"
using namespace DFHack;
using namespace df::enums;
df::job *DFHack::cloneJobStruct(df::job *job)
{
df::job *pnew = new df::job(*job);
// Clean out transient fields
pnew->flags.whole = 0;
pnew->flags.bits.repeat = job->flags.bits.repeat;
pnew->flags.bits.suspend = job->flags.bits.suspend;
pnew->list_link = NULL;
pnew->completion_timer = -1;
pnew->items.clear();
pnew->misc_links.clear();
// Clone refs
for (int i = pnew->references.size()-1; i >= 0; i--)
{
df::general_ref *ref = pnew->references[i];
if (virtual_cast<df::general_ref_unit_workerst>(ref))
vector_erase_at(pnew->references, i);
else
pnew->references[i] = ref->clone();
}
// Clone items
for (int i = pnew->job_items.size()-1; i >= 0; i--)
pnew->job_items[i] = new df::job_item(*pnew->job_items[i]);
return pnew;
}
void DFHack::deleteJobStruct(df::job *job)
{
if (!job)
return;
// Only allow free-floating job structs
assert(!job->list_link && job->items.empty() && job->misc_links.empty());
for (int i = job->references.size()-1; i >= 0; i--)
delete job->references[i];
for (int i = job->job_items.size()-1; i >= 0; i--)
delete job->job_items[i];
delete job;
}
#define CMP(field) (a.field == b.field)
bool DFHack::operator== (const df::job_item &a, const df::job_item &b)
{
if (!(CMP(item_type) && CMP(item_subtype) &&
CMP(mat_type) && CMP(mat_index) &&
CMP(flags1.whole) && CMP(quantity) && CMP(vector_id) &&
CMP(flags2.whole) && CMP(flags3.whole) &&
CMP(metal_ore) && CMP(reaction_class) &&
CMP(has_material_reaction_product) &&
CMP(min_dimension) && CMP(reagent_index) &&
CMP(reaction_id) && CMP(has_tool_use) &&
CMP(contains.size())))
return false;
for (int i = a.contains.size()-1; i >= 0; i--)
if (a.contains[i] != b.contains[i])
return false;
return true;
}
bool DFHack::operator== (const df::job &a, const df::job &b)
{
if (!(CMP(job_type) && CMP(unk2) &&
CMP(mat_type) && CMP(mat_index) &&
CMP(item_subtype) && CMP(item_category.whole) &&
CMP(hist_figure_id) && CMP(material_category.whole) &&
CMP(reaction_name) && CMP(job_items.size())))
return false;
for (int i = a.job_items.size()-1; i >= 0; i--)
if (!(*a.job_items[i] == *b.job_items[i]))
return false;
return true;
}
static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item)
{
ItemTypeInfo info(item);
c->con << " Input Item " << (idx+1) << ": " << info.toString();
if (item->quantity != 1)
c->con << "; quantity=" << item->quantity;
if (item->min_dimension >= 0)
c->con << "; min_dimension=" << item->min_dimension;
c->con << endl;
MaterialInfo mat(item);
if (mat.isValid() || item->metal_ore >= 0) {
c->con << " material: " << mat.toString();
if (item->metal_ore >= 0)
c->con << "; ore of " << MaterialInfo(0,item->metal_ore).toString();
c->con << endl;
}
if (item->flags1.whole)
c->con << " flags1: " << bitfieldToString(item->flags1) << endl;
if (item->flags2.whole)
c->con << " flags2: " << bitfieldToString(item->flags2) << endl;
if (item->flags3.whole)
c->con << " flags3: " << bitfieldToString(item->flags3) << endl;
if (!item->reaction_class.empty())
c->con << " reaction class: " << item->reaction_class << endl;
if (!item->has_material_reaction_product.empty())
c->con << " reaction product: " << item->has_material_reaction_product << endl;
if (item->has_tool_use >= 0)
c->con << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl;
}
void DFHack::printJobDetails(Core *c, df::job *job)
{
c->con.color(job->flags.bits.suspend ? Console::COLOR_DARKGREY : Console::COLOR_GREY);
c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type);
if (job->flags.whole)
c->con << " (" << bitfieldToString(job->flags) << ")";
c->con << endl;
c->con.reset_color();
df::item_type itype = ENUM_ATTR(job_type, item, job->job_type);
MaterialInfo mat(job);
if (itype == item_type::FOOD)
mat.decode(-1);
if (mat.isValid() || job->material_category.whole)
{
c->con << " material: " << mat.toString();
if (job->material_category.whole)
c->con << " (" << bitfieldToString(job->material_category) << ")";
c->con << endl;
}
if (job->item_subtype >= 0 || job->item_category.whole)
{
ItemTypeInfo iinfo(itype, job->item_subtype);
c->con << " item: " << iinfo.toString()
<< " (" << bitfieldToString(job->item_category) << ")" << endl;
}
if (job->hist_figure_id >= 0)
c->con << " figure: " << job->hist_figure_id << endl;
if (!job->reaction_name.empty())
c->con << " reaction: " << job->reaction_name << endl;
for (unsigned i = 0; i < job->job_items.size(); i++)
print_job_item_details(c, job, i, job->job_items[i]);
}
df::building *DFHack::getJobHolder(df::job *job)
{
for (unsigned i = 0; i < job->references.size(); i++)
{
VIRTUAL_CAST_VAR(ref, df::general_ref_building_holderst, job->references[i]);
if (ref)
return ref->getBuilding();
}
return NULL;
}
bool DFHack::linkJobIntoWorld(df::job *job, bool new_id)
{
using df::global::world;
using df::global::job_next_id;
assert(!job->list_link);
if (new_id) {
job->id = (*job_next_id)++;
job->list_link = new df::job_list_link();
job->list_link->item = job;
linked_list_append(&world->job_list, job->list_link);
return true;
} else {
df::job_list_link *ins_pos = &world->job_list;
while (ins_pos->next && ins_pos->next->item->id < job->id)
ins_pos = ins_pos->next;
if (ins_pos->next && ins_pos->next->item->id == job->id)
return false;
job->list_link = new df::job_list_link();
job->list_link->item = job;
linked_list_insert_after(ins_pos, job->list_link);
return true;
}
}

@ -37,7 +37,6 @@ using namespace std;
#include "Error.h" #include "Error.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
@ -96,7 +95,7 @@ struct Maps::Private
FEATURES FEATURES
*/ */
// FIXME: replace with a struct pointer, eventually. needs to be mapped out first // FIXME: replace with a struct pointer, eventually. needs to be mapped out first
uint32_t world_data; char * world_data;
uint32_t local_f_start; // offset from world_data uint32_t local_f_start; // offset from world_data
// FIXME: replace by virtual function call // FIXME: replace by virtual function call
uint32_t local_material; uint32_t local_material;
@ -122,7 +121,7 @@ struct Maps::Private
set <uint32_t> unknown_veins; set <uint32_t> unknown_veins;
// map between feature address and the read object // map between feature address and the read object
map <uint32_t, t_feature> local_feature_store; map <void *, t_feature> local_feature_store;
map <DFCoord, vector <t_feature *> > m_local_feature; map <DFCoord, vector <t_feature *> > m_local_feature;
vector <t_feature> v_global_feature; vector <t_feature> v_global_feature;
@ -508,13 +507,13 @@ bool Maps::StartFeatures()
Process * p = d->owner; Process * p = d->owner;
Private::t_offsets &off = d->offsets; Private::t_offsets &off = d->offsets;
uint32_t base = 0; char * base = 0;
uint32_t global_feature_vector = 0; char * global_feature_vector = 0;
uint32_t world = p->readDWord(off.world_data); char * world = p->readPtr( (void *) off.world_data);
if(!world) return false; if(!world) return false;
base = p->readDWord(world + off.local_f_start); base = p->readPtr(world + off.local_f_start);
global_feature_vector = p->readDWord(off.world_data) + off.global_vector; global_feature_vector = p->readPtr(off.world_data) + off.global_vector;
// deref pointer to the humongo-structure // deref pointer to the humongo-structure
if(!base) if(!base)
@ -549,22 +548,21 @@ bool Maps::StartFeatures()
// base = pointer to local feature structure (inside world data struct) // base = pointer to local feature structure (inside world data struct)
// bigregion is 16x16 regions. for each bigregion in X dimension: // bigregion is 16x16 regions. for each bigregion in X dimension:
uint32_t mega_column = p->readDWord(base + bigregion_x * 4); char * mega_column = p->readPtr(base + bigregion_x * 4);
// 16B structs, second DWORD of the struct is a pointer // 16B structs, second DWORD of the struct is a pointer
uint32_t loc_f_array16x16 = p->readDWord(mega_column + offset_elem + (sizeof_elem * bigregion_y)); char * loc_f_array16x16 = p->readPtr(mega_column + offset_elem + (sizeof_elem * bigregion_y));
if(loc_f_array16x16) if(loc_f_array16x16)
{ {
uint32_t feat_vector = loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y; vector <char *> * p_features = (vector <char *> *) (loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y);
DfVector<uint32_t> p_features(feat_vector); uint32_t size = p_features->size();
uint32_t size = p_features.size();
DFCoord pc(blockX,blockY); DFCoord pc(blockX,blockY);
std::vector<t_feature *> tempvec; std::vector<t_feature *> tempvec;
for(uint32_t i = 0; i < size; i++) for(uint32_t i = 0; i < size; i++)
{ {
uint32_t cur_ptr = p_features[i]; char * cur_ptr = p_features->at(i);
map <uint32_t, t_feature>::iterator it; map <void *, t_feature>::iterator it;
it = d->local_feature_store.find(cur_ptr); it = d->local_feature_store.find(cur_ptr);
// do we already have the feature? // do we already have the feature?
if(it != d->local_feature_store.end()) if(it != d->local_feature_store.end())
@ -579,7 +577,7 @@ bool Maps::StartFeatures()
// create, add to store // create, add to store
t_feature tftemp; t_feature tftemp;
tftemp.discovered = false; //= p->readDWord(cur_ptr + 4); tftemp.discovered = false; //= p->readDWord(cur_ptr + 4);
tftemp.origin = cur_ptr; tftemp.origin = (t_feature *) cur_ptr;
string name = p->readClassName((void *)p->readDWord( cur_ptr )); string name = p->readClassName((void *)p->readDWord( cur_ptr ));
if(name == "feature_init_deep_special_tubest") if(name == "feature_init_deep_special_tubest")
{ {
@ -611,17 +609,15 @@ bool Maps::StartFeatures()
const uint32_t global_feature_funcptr = off.global_funcptr; const uint32_t global_feature_funcptr = off.global_funcptr;
const uint32_t glob_main_mat_offset = off.global_material; const uint32_t glob_main_mat_offset = off.global_material;
const uint32_t glob_sub_mat_offset = off.global_submaterial; const uint32_t glob_sub_mat_offset = off.global_submaterial;
DfVector<uint32_t> p_features (global_feature_vector); vector <char *> * p_features = (vector <char *> *) global_feature_vector;
d->v_global_feature.clear(); d->v_global_feature.clear();
uint32_t size = p_features.size(); uint32_t size = p_features->size();
d->v_global_feature.reserve(size); d->v_global_feature.reserve(size);
for(uint32_t i = 0; i < size; i++) for(uint32_t i = 0; i < size; i++)
{ {
t_feature temp; t_feature temp;
uint32_t feat_ptr = p->readDWord(p_features[i] + global_feature_funcptr ); char * feat_ptr = p->readPtr(p_features->at(i) + global_feature_funcptr );
temp.origin = feat_ptr; temp.origin = feat_ptr;
//temp.discovered = p->readDWord( feat_ptr + 4 ); // maybe, placeholder
temp.discovered = false; temp.discovered = false;
// FIXME: use the memory_info cache mechanisms // FIXME: use the memory_info cache mechanisms
@ -887,8 +883,8 @@ bool Maps::RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, t_virtual * whic
} }
/* /*
* Layer geology * Layer geology
*/ */
bool Maps::ReadGeology (vector < vector <uint16_t> >& assign) bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
{ {
MAPS_GUARD MAPS_GUARD
@ -896,17 +892,18 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
Process *p = d->owner; Process *p = d->owner;
// get needed addresses and offsets. Now this is what I call crazy. // get needed addresses and offsets. Now this is what I call crazy.
uint16_t worldSizeX, worldSizeY; uint16_t worldSizeX, worldSizeY;
uint32_t regions, geoblocks_vector_addr; char *regions;
char *geoblocks_vector_addr;
Private::t_offsets &off = d->offsets; Private::t_offsets &off = d->offsets;
// get world size // get world size
uint32_t world = p->readDWord(off.world_data); char * world = p->readPtr(off.world_data);
p->readWord (world + off.world_size_x, worldSizeX); p->readWord (world + off.world_size_x, worldSizeX);
p->readWord (world + off.world_size_y, worldSizeY); p->readWord (world + off.world_size_y, worldSizeY);
regions = p->readDWord ( world + off.world_regions); // ptr2_region_array regions = p->readPtr ( world + off.world_regions); // ptr2_region_array
geoblocks_vector_addr = world + off.world_geoblocks_vector; geoblocks_vector_addr = world + off.world_geoblocks_vector;
// read the geoblock vector // read the geoblock vector
DfVector <uint32_t> geoblocks (geoblocks_vector_addr); vector <char *> & geoblocks = *(vector <char *> *)(geoblocks_vector_addr);
// iterate over 8 surrounding regions + local region // iterate over 8 surrounding regions + local region
for (int i = eNorthWest; i < eBiomeCount; i++) for (int i = eNorthWest; i < eBiomeCount; i++)
@ -925,8 +922,8 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
/// regions are a 2d array. consists of pointers to arrays of regions /// regions are a 2d array. consists of pointers to arrays of regions
/// regions are of region_size size /// regions are of region_size size
// get pointer to column of regions // get pointer to column of regions
uint32_t geoX; char * geoX;
p->readDWord (regions + bioRX*4, geoX); p->readPtr (regions + bioRX*4, geoX);
// get index into geoblock vector // get index into geoblock vector
uint16_t geoindex; uint16_t geoindex;
@ -935,11 +932,11 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
/// geology blocks are assigned to regions from a vector /// geology blocks are assigned to regions from a vector
// get the geoblock from the geoblock vector using the geoindex // get the geoblock from the geoblock vector using the geoindex
// read the matgloss pointer from the vector into temp // read the matgloss pointer from the vector into temp
uint32_t geoblock_off = geoblocks[geoindex]; char * geoblock_off = geoblocks[geoindex];
/// geology blocks have a vector of layer descriptors /// geology blocks have a vector of layer descriptors
// get the vector with pointer to layers // get the vector with pointer to layers
DfVector <uint32_t> geolayers (geoblock_off + off.geolayer_geoblock_offset); // let's hope vector <char *> & geolayers = *(vector <char *> *)(geoblock_off + off.geolayer_geoblock_offset);
// make sure we don't load crap // make sure we don't load crap
assert (geolayers.size() > 0 && geolayers.size() <= 16); assert (geolayers.size() > 0 && geolayers.size() <= 16);
@ -949,7 +946,7 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
for (uint32_t j = 0;j < geolayers.size();j++) for (uint32_t j = 0;j < geolayers.size();j++)
{ {
// read pointer to a layer // read pointer to a layer
uint32_t geol_offset = geolayers[j]; char * geol_offset = geolayers[j];
// read word at pointer + 2, store in our geology vectors // read word at pointer + 2, store in our geology vectors
d->v_geology[i].push_back (p->readWord (geol_offset + off.type_inside_geolayer)); d->v_geology[i].push_back (p->readWord (geol_offset + off.type_inside_geolayer));
} }

@ -35,12 +35,465 @@ using namespace std;
#include "modules/Materials.h" #include "modules/Materials.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "Error.h" #include "Error.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
#include "MiscUtils.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/item.h"
#include "df/inorganic_raw.h"
#include "df/plant_raw.h"
#include "df/plant_raw_flags.h"
#include "df/creature_raw.h"
#include "df/historical_figure.h"
#include "df/job_item.h"
#include "df/job_material_category.h"
#include "df/dfhack_material_category.h"
#include "df/matter_state.h"
#include "df/material_vec_ref.h"
using namespace DFHack; using namespace DFHack;
using namespace df::enums;
bool MaterialInfo::decode(df::item *item)
{
if (!item)
return decode(-1);
else
return decode(item->getActualMaterial(), item->getActualMaterialIndex());
}
bool MaterialInfo::decode(const df::material_vec_ref &vr, int idx)
{
if (idx < 0 || idx >= vr.mat_type.size() || idx >= vr.mat_index.size())
return decode(-1);
else
return decode(vr.mat_type[idx], vr.mat_index[idx]);
}
bool MaterialInfo::decode(int16_t type, int32_t index)
{
this->type = type;
this->index = index;
material = NULL;
mode = Builtin; subtype = 0;
inorganic = NULL; plant = NULL; creature = NULL;
figure = NULL;
df::world_raws &raws = df::global::world->raws;
if (type < 0 || type >= sizeof(raws.mat_table.builtin)/sizeof(void*))
return false;
if (index < 0)
{
material = raws.mat_table.builtin[type];
}
else if (type == 0)
{
mode = Inorganic;
inorganic = df::inorganic_raw::find(index);
if (!inorganic)
return false;
material = &inorganic->material;
}
else if (type < CREATURE_BASE)
{
material = raws.mat_table.builtin[type];
}
else if (type < FIGURE_BASE)
{
mode = Creature;
subtype = type-CREATURE_BASE;
creature = df::creature_raw::find(index);
if (!creature || subtype >= creature->material.size())
return false;
material = creature->material[subtype];
}
else if (type < PLANT_BASE)
{
mode = Creature;
subtype = type-FIGURE_BASE;
figure = df::historical_figure::find(index);
if (!figure)
return false;
creature = df::creature_raw::find(figure->race);
if (!creature || subtype >= creature->material.size())
return false;
material = creature->material[subtype];
}
else if (type < END_BASE)
{
mode = Plant;
subtype = type-PLANT_BASE;
plant = df::plant_raw::find(index);
if (!plant || subtype >= plant->material.size())
return false;
material = plant->material[subtype];
}
else
{
material = raws.mat_table.builtin[type];
}
return (material != NULL);
}
bool MaterialInfo::find(const std::string &token)
{
std::vector<std::string> items;
split_string(&items, token, ":");
if (items[0] == "INORGANIC")
return findInorganic(vector_get(items,1));
if (items[0] == "CREATURE_MAT" || items[0] == "CREATURE")
return findCreature(vector_get(items,1), vector_get(items,2));
if (items[0] == "PLANT_MAT" || items[0] == "PLANT")
return findPlant(vector_get(items,1), vector_get(items,2));
if (items.size() == 1)
{
if (findBuiltin(items[0]))
return true;
if (findInorganic(items[0]))
return true;
if (findPlant(items[0], ""))
return true;
}
else if (items.size() == 2)
{
if (findPlant(items[0], items[1]))
return true;
if (findCreature(items[0], items[1]))
return true;
}
return false;
}
bool MaterialInfo::findBuiltin(const std::string &token)
{
if (token.empty())
return decode(-1);
if (token == "NONE") {
decode(-1);
return true;
}
df::world_raws &raws = df::global::world->raws;
for (int i = 1; i < NUM_BUILTIN; i++)
if (raws.mat_table.builtin[i]->id == token)
return decode(i, -1);
return decode(-1);
}
bool MaterialInfo::findInorganic(const std::string &token)
{
if (token.empty())
return decode(-1);
if (token == "NONE") {
decode(0, -1);
return true;
}
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.inorganics.size(); i++)
{
df::inorganic_raw *p = raws.inorganics[i];
if (p->id == token)
return decode(0, i);
}
return decode(-1);
}
bool MaterialInfo::findPlant(const std::string &token, const std::string &subtoken)
{
if (token.empty())
return decode(-1);
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.plants.all.size(); i++)
{
df::plant_raw *p = raws.plants.all[i];
if (p->id != token)
continue;
// As a special exception, return the structural material with empty subtoken
if (subtoken.empty())
return decode(p->material_defs.type_basic_mat, p->material_defs.idx_basic_mat);
for (unsigned j = 0; j < p->material.size(); j++)
if (p->material[j]->id == subtoken)
return decode(PLANT_BASE+j, i);
break;
}
return decode(-1);
}
bool MaterialInfo::findCreature(const std::string &token, const std::string &subtoken)
{
if (token.empty() || subtoken.empty())
return decode(-1);
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.creatures.all.size(); i++)
{
df::creature_raw *p = raws.creatures.all[i];
if (p->creature_id != token)
continue;
for (unsigned j = 0; j < p->material.size(); j++)
if (p->material[j]->id == subtoken)
return decode(CREATURE_BASE+j, i);
break;
}
return decode(-1);
}
std::string MaterialInfo::toString(uint16_t temp, bool named)
{
if (type == -1)
return "NONE";
if (!material)
return stl_sprintf("INVALID %d:%d", type, index);
df::matter_state state = matter_state::Solid;
if (temp >= material->heat.melting_point)
state = matter_state::Liquid;
if (temp >= material->heat.boiling_point)
state = matter_state::Gas;
std::string name = material->state_name[state];
if (!material->prefix.empty())
name = material->prefix + " " + name;
if (named && figure)
name += stl_sprintf(" of HF %d", index);
return name;
}
df::craft_material_class MaterialInfo::getCraftClass()
{
if (!material)
return craft_material_class::None;
if (type == 0 && index == -1)
return craft_material_class::Stone;
FOR_ENUM_ITEMS(material_flags, i)
{
df::craft_material_class ccv = ENUM_ATTR(material_flags, type, i);
if (ccv == craft_material_class::None)
continue;
if (material->flags.is_set(i))
return ccv;
}
return craft_material_class::None;
}
bool MaterialInfo::isAnyCloth()
{
using namespace df::enums::material_flags;
return material && (
material->flags.is_set(THREAD_PLANT) ||
material->flags.is_set(SILK) ||
material->flags.is_set(YARN)
);
}
bool MaterialInfo::matches(const df::job_material_category &cat)
{
if (!material)
return false;
#define TEST(bit,flag) if (cat.bits.bit && material->flags.is_set(flag)) return true;
using namespace df::enums::material_flags;
TEST(plant, STRUCTURAL_PLANT_MAT);
TEST(wood, WOOD);
TEST(cloth, THREAD_PLANT);
TEST(silk, SILK);
TEST(leather, LEATHER);
TEST(bone, BONE);
TEST(shell, SHELL);
TEST(wood2, WOOD);
TEST(soap, SOAP);
TEST(tooth, TOOTH);
TEST(horn, HORN);
TEST(pearl, PEARL);
TEST(yarn, YARN);
return false;
}
bool MaterialInfo::matches(const df::dfhack_material_category &cat)
{
if (!material)
return false;
df::job_material_category mc;
mc.whole = cat.whole;
if (matches(mc))
return true;
using namespace df::enums::material_flags;
using namespace df::enums::inorganic_flags;
TEST(metal, IS_METAL);
TEST(stone, IS_STONE);
if (cat.bits.stone && type == 0 && index == -1)
return true;
if (cat.bits.sand && inorganic && inorganic->flags.is_set(SOIL_SAND))
return true;
TEST(glass, IS_GLASS);
if (cat.bits.clay && linear_index(material->reaction_product.id, std::string("FIRED_MAT")) >= 0)
return true;
return false;
}
#undef TEST
bool MaterialInfo::matches(const df::job_item &item)
{
if (!isValid()) return false;
df::job_item_flags1 ok1, mask1;
getMatchBits(ok1, mask1);
df::job_item_flags2 ok2, mask2;
getMatchBits(ok2, mask2);
df::job_item_flags3 ok3, mask3;
getMatchBits(ok3, mask3);
return bits_match(item.flags1.whole, ok1.whole, mask1.whole) &&
bits_match(item.flags2.whole, ok2.whole, mask2.whole) &&
bits_match(item.flags3.whole, ok3.whole, mask3.whole);
}
void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
#define MAT_FLAG(name) material->flags.is_set(df::enums::material_flags::name)
#define FLAG(field, name) (field && field->flags.is_set(name))
#define TEST(bit, check) \
mask.bits.bit = true; ok.bits.bit = !!(check);
bool structural = MAT_FLAG(STRUCTURAL_PLANT_MAT);
TEST(millable, structural && FLAG(plant, plant_raw_flags::MILL));
TEST(sharpenable, MAT_FLAG(IS_STONE));
TEST(distillable, structural && FLAG(plant, plant_raw_flags::DRINK));
TEST(processable, structural && FLAG(plant, plant_raw_flags::THREAD));
TEST(bag, isAnyCloth() || MAT_FLAG(LEATHER));
TEST(cookable, MAT_FLAG(EDIBLE_COOKED));
TEST(extract_bearing_plant, structural && FLAG(plant, plant_raw_flags::EXTRACT_STILL_VIAL));
TEST(extract_bearing_fish, false);
TEST(extract_bearing_vermin, false);
TEST(processable_to_vial, structural && FLAG(plant, plant_raw_flags::EXTRACT_VIAL));
TEST(processable_to_bag, structural && FLAG(plant, plant_raw_flags::LEAVES));
TEST(processable_to_barrel, structural && FLAG(plant, plant_raw_flags::EXTRACT_BARREL));
TEST(solid, !(MAT_FLAG(ALCOHOL_PLANT) ||
MAT_FLAG(ALCOHOL_CREATURE) ||
MAT_FLAG(LIQUID_MISC_PLANT) ||
MAT_FLAG(LIQUID_MISC_CREATURE) ||
MAT_FLAG(LIQUID_MISC_OTHER)));
TEST(tameable_vermin, false);
TEST(sharpenable, MAT_FLAG(IS_STONE));
TEST(milk, linear_index(material->reaction_product.id, std::string("CHEESE_MAT")) >= 0);
//04000000 - "milkable" - vtable[107],1,1
}
void MaterialInfo::getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
bool is_cloth = isAnyCloth();
TEST(dye, MAT_FLAG(IS_DYE));
TEST(dyeable, is_cloth);
TEST(dyed, is_cloth);
TEST(sewn_imageless, is_cloth);
TEST(glass_making, MAT_FLAG(CRYSTAL_GLASSABLE));
TEST(fire_safe, material->heat.melting_point > 11000);
TEST(magma_safe, material->heat.melting_point > 12000);
TEST(deep_material, FLAG(inorganic, df::enums::inorganic_flags::DEEP_ANY));
TEST(non_economic, inorganic && !(df::global::ui && df::global::ui->economic_stone[index]));
TEST(plant, plant);
TEST(silk, MAT_FLAG(SILK));
TEST(leather, MAT_FLAG(LEATHER));
TEST(bone, MAT_FLAG(BONE));
TEST(shell, MAT_FLAG(SHELL));
TEST(totemable, false);
TEST(horn, MAT_FLAG(HORN));
TEST(pearl, MAT_FLAG(PEARL));
TEST(soap, MAT_FLAG(SOAP));
TEST(ivory_tooth, MAT_FLAG(TOOTH));
//TEST(hair_wool, MAT_FLAG(YARN));
TEST(yarn, MAT_FLAG(YARN));
}
void MaterialInfo::getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
TEST(hard, MAT_FLAG(ITEMS_HARD));
}
#undef MAT_FLAG
#undef FLAG
#undef TEST
bool DFHack::parseJobMaterialCategory(df::job_material_category *cat, const std::string &token)
{
cat->whole = 0;
std::vector<std::string> items;
split_string(&items, toLower(token), ",", true);
for (unsigned i = 0; i < items.size(); i++)
{
int id = findBitfieldField(*cat, items[i]);
if (id < 0)
return false;
cat->whole |= (1 << id);
}
return true;
}
bool DFHack::parseJobMaterialCategory(df::dfhack_material_category *cat, const std::string &token)
{
cat->whole = 0;
std::vector<std::string> items;
split_string(&items, toLower(token), ",", true);
for (unsigned i = 0; i < items.size(); i++)
{
int id = findBitfieldField(*cat, items[i]);
if (id < 0)
return false;
cat->whole |= (1 << id);
}
return true;
}
Module* DFHack::createMaterials() Module* DFHack::createMaterials()
{ {
@ -52,8 +505,8 @@ class Materials::Private
public: public:
Process * owner; Process * owner;
OffsetGroup * OG_Materials; OffsetGroup * OG_Materials;
uint32_t vector_races; void * vector_races;
uint32_t vector_other; void * vector_other;
}; };
Materials::Materials() Materials::Materials()
@ -67,10 +520,10 @@ Materials::Materials()
df_inorganic = 0; df_inorganic = 0;
OffsetGroup *OG_Materials = d->OG_Materials = c.vinfo->getGroup("Materials"); OffsetGroup *OG_Materials = d->OG_Materials = c.vinfo->getGroup("Materials");
{ {
OG_Materials->getSafeAddress("inorganics",(uint32_t &)df_inorganic); OG_Materials->getSafeAddress("inorganics",(void * &)df_inorganic);
OG_Materials->getSafeAddress("organics_all",(uint32_t &)df_organic); OG_Materials->getSafeAddress("organics_all",(void * &)df_organic);
OG_Materials->getSafeAddress("organics_plants",(uint32_t &)df_plants); OG_Materials->getSafeAddress("organics_plants",(void * &)df_plants);
OG_Materials->getSafeAddress("organics_trees",(uint32_t &)df_trees); OG_Materials->getSafeAddress("organics_trees",(void * &)df_trees);
d->vector_races = OG_Materials->getAddress("creature_type_vector"); d->vector_races = OG_Materials->getAddress("creature_type_vector");
} }
} }
@ -111,16 +564,16 @@ bool t_matglossInorganic::isGem()
} }
// good for now // good for now
inline bool ReadNamesOnly(Process* p, uint32_t address, vector<t_matgloss> & names) inline bool ReadNamesOnly(Process* p, void * address, vector<t_matgloss> & names)
{ {
DfVector <uint32_t> p_matgloss (address); vector <string *> * p_names = (vector <string *> *) address;
uint32_t size = p_matgloss.size(); uint32_t size = p_names->size();
names.clear(); names.clear();
names.reserve (size); names.reserve (size);
for (uint32_t i = 0; i < size;i++) for (uint32_t i = 0; i < size;i++)
{ {
t_matgloss mat; t_matgloss mat;
mat.id = *(std::string *)p_matgloss[i]; mat.id = *p_names->at(i);
names.push_back(mat); names.push_back(mat);
} }
return true; return true;
@ -159,21 +612,21 @@ bool Materials::CopyInorganicMaterials (std::vector<t_matglossInorganic> & inorg
bool Materials::CopyOrganicMaterials (std::vector<t_matgloss> & organic) bool Materials::CopyOrganicMaterials (std::vector<t_matgloss> & organic)
{ {
if(df_organic) if(df_organic)
return ReadNamesOnly(d->owner, (uint32_t) df_organic, organic ); return ReadNamesOnly(d->owner, (void *) df_organic, organic );
else return false; else return false;
} }
bool Materials::CopyWoodMaterials (std::vector<t_matgloss> & tree) bool Materials::CopyWoodMaterials (std::vector<t_matgloss> & tree)
{ {
if(df_trees) if(df_trees)
return ReadNamesOnly(d->owner, (uint32_t) df_trees, tree ); return ReadNamesOnly(d->owner, (void *) df_trees, tree );
else return false; else return false;
} }
bool Materials::CopyPlantMaterials (std::vector<t_matgloss> & plant) bool Materials::CopyPlantMaterials (std::vector<t_matgloss> & plant)
{ {
if(df_plants) if(df_plants)
return ReadNamesOnly(d->owner, (uint32_t) df_plants, plant ); return ReadNamesOnly(d->owner, (void *) df_plants, plant );
else return false; else return false;
} }
@ -185,7 +638,7 @@ bool Materials::ReadCreatureTypes (void)
bool Materials::ReadOthers(void) bool Materials::ReadOthers(void)
{ {
Process * p = d->owner; Process * p = d->owner;
uint32_t matBase = d->OG_Materials->getAddress ("other"); char * matBase = d->OG_Materials->getAddress ("other");
uint32_t i = 0; uint32_t i = 0;
std::string * ptr; std::string * ptr;
@ -194,7 +647,7 @@ bool Materials::ReadOthers(void)
while(1) while(1)
{ {
t_matglossOther mat; t_matglossOther mat;
ptr = (std::string *) p->readDWord(matBase + i*4); ptr = (std::string *) p->readPtr(matBase + i*4);
if(ptr==0) if(ptr==0)
break; break;
mat.id = *ptr; mat.id = *ptr;
@ -208,7 +661,7 @@ bool Materials::ReadDescriptorColors (void)
{ {
Process * p = d->owner; Process * p = d->owner;
OffsetGroup * OG_Descriptors = p->getDescriptor()->getGroup("Materials")->getGroup("descriptors"); OffsetGroup * OG_Descriptors = p->getDescriptor()->getGroup("Materials")->getGroup("descriptors");
DfVector <uint32_t> p_colors (OG_Descriptors->getAddress ("colors_vector")); vector <char *> & p_colors = *(vector<char*> *) OG_Descriptors->getAddress ("colors_vector");
uint32_t size = p_colors.size(); uint32_t size = p_colors.size();
color.clear(); color.clear();
@ -237,7 +690,7 @@ bool Materials::ReadCreatureTypesEx (void)
uint32_t sizeof_string = OG_string->getHexValue ("sizeof"); uint32_t sizeof_string = OG_string->getHexValue ("sizeof");
OffsetGroup * OG_Mats = mem->getGroup("Materials"); OffsetGroup * OG_Mats = mem->getGroup("Materials");
DfVector <uint32_t> p_races (OG_Mats->getAddress ("creature_type_vector")); vector <char *> & p_races = *(vector<char*> *) OG_Mats->getAddress ("creature_type_vector");
OffsetGroup * OG_Creature = OG_Mats->getGroup("creature"); OffsetGroup * OG_Creature = OG_Mats->getGroup("creature");
uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector"); uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector");
@ -287,13 +740,13 @@ bool Materials::ReadCreatureTypesEx (void)
mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 ); mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 );
mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 ); mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 );
DfVector <uint32_t> p_castes(p_races[i] + castes_vector_offset); vector <char *> & p_castes = *(vector<char*> *) (p_races[i] + castes_vector_offset);
sizecas = p_castes.size(); sizecas = p_castes.size();
for (uint32_t j = 0; j < sizecas;j++) for (uint32_t j = 0; j < sizecas;j++)
{ {
/* caste name */ /* caste name */
t_creaturecaste caste; t_creaturecaste caste;
uint32_t caste_start = p_castes[j]; char * caste_start = p_castes[j];
caste.id = p->readSTLString (caste_start); caste.id = p->readSTLString (caste_start);
caste.singular = p->readSTLString (caste_start + sizeof_string); caste.singular = p->readSTLString (caste_start + sizeof_string);
caste.plural = p->readSTLString (caste_start + 2 * sizeof_string); caste.plural = p->readSTLString (caste_start + 2 * sizeof_string);
@ -303,13 +756,13 @@ bool Materials::ReadCreatureTypesEx (void)
{ {
/* color mod reading */ /* color mod reading */
// Caste + offset > color mod vector // Caste + offset > color mod vector
DfVector <uint32_t> p_colormod(caste_start + caste_colormod_offset); vector <char *> & p_colormod = *(vector<char*> *) (caste_start + caste_colormod_offset);
sizecolormod = p_colormod.size(); sizecolormod = p_colormod.size();
caste.ColorModifier.resize(sizecolormod); caste.ColorModifier.resize(sizecolormod);
for(uint32_t k = 0; k < sizecolormod;k++) for(uint32_t k = 0; k < sizecolormod;k++)
{ {
// color mod [0] -> color list // color mod [0] -> color list
DfVector <uint32_t> p_colorlist(p_colormod[k]); vector <uint32_t> & p_colorlist = *(vector<uint32_t> *) (p_colormod[k]);
sizecolorlist = p_colorlist.size(); sizecolorlist = p_colorlist.size();
caste.ColorModifier[k].colorlist.resize(sizecolorlist); caste.ColorModifier[k].colorlist.resize(sizecolorlist);
for(uint32_t l = 0; l < sizecolorlist; l++) for(uint32_t l = 0; l < sizecolorlist; l++)
@ -320,7 +773,7 @@ bool Materials::ReadCreatureTypesEx (void)
caste.ColorModifier[k].enddate = p->readDWord( p_colormod[k] + color_modifier_enddate_offset ); caste.ColorModifier[k].enddate = p->readDWord( p_colormod[k] + color_modifier_enddate_offset );
} }
/* body parts */ /* body parts */
DfVector <uint32_t> p_bodypart(caste_start + caste_bodypart_offset); vector <char *> & p_bodypart = *(vector<char*> *) (caste_start + caste_bodypart_offset);
caste.bodypart.empty(); caste.bodypart.empty();
sizebp = p_bodypart.size(); sizebp = p_bodypart.size();
for(uint32_t k = 0; k < sizebp; k++) for(uint32_t k = 0; k < sizebp; k++)
@ -338,7 +791,7 @@ bool Materials::ReadCreatureTypesEx (void)
} }
mat.castes.push_back(caste); mat.castes.push_back(caste);
} }
DfVector <uint32_t> p_extract(p_races[i] + extract_vector_offset); vector <void *> & p_extract = *(vector<void*> *) (p_races[i] + extract_vector_offset);
for(uint32_t j = 0; j < p_extract.size(); j++) for(uint32_t j = 0; j < p_extract.size(); j++)
{ {
t_creatureextract extract; t_creatureextract extract;

@ -33,7 +33,6 @@ using namespace std;
#include "modules/Translation.h" #include "modules/Translation.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "Types.h" #include "Types.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
@ -46,8 +45,8 @@ Module* DFHack::createTranslation()
struct Translation::Private struct Translation::Private
{ {
uint32_t genericAddress; void * genericAddress;
uint32_t transAddress; void * transAddress;
uint32_t word_table_offset; uint32_t word_table_offset;
uint32_t sizeof_string; uint32_t sizeof_string;
@ -97,15 +96,15 @@ bool Translation::Start()
return false; return false;
Process * p = c.p; Process * p = c.p;
Finish(); Finish();
DfVector <uint32_t> genericVec (d->genericAddress); vector <char *> & genericVec = *(vector <char *> *) d->genericAddress;
DfVector <uint32_t> transVec (d->transAddress); vector <char *> & transVec = *(vector <char *> *) d->transAddress;
DFDict & translations = d->dicts.translations; DFDict & translations = d->dicts.translations;
DFDict & foreign_languages = d->dicts.foreign_languages; DFDict & foreign_languages = d->dicts.foreign_languages;
translations.resize(10); translations.resize(10);
for (uint32_t i = 0;i < genericVec.size();i++) for (uint32_t i = 0;i < genericVec.size();i++)
{ {
uint32_t genericNamePtr = genericVec.at(i); char * genericNamePtr = genericVec[i];
for(int j=0; j<10;j++) for(int j=0; j<10;j++)
{ {
string word = p->readSTLString (genericNamePtr + j * d->sizeof_string); string word = p->readSTLString (genericNamePtr + j * d->sizeof_string);
@ -116,11 +115,11 @@ bool Translation::Start()
foreign_languages.resize(transVec.size()); foreign_languages.resize(transVec.size());
for (uint32_t i = 0; i < transVec.size();i++) for (uint32_t i = 0; i < transVec.size();i++)
{ {
uint32_t transPtr = transVec.at(i); char * transPtr = transVec.at(i);
DfVector <uint32_t> trans_names_vec (transPtr + d->word_table_offset); vector <void *> & trans_names_vec = *(vector <void *> *) (transPtr + d->word_table_offset);
for (uint32_t j = 0;j < trans_names_vec.size();j++) for (uint32_t j = 0;j < trans_names_vec.size();j++)
{ {
uint32_t transNamePtr = trans_names_vec.at(j); void * transNamePtr = trans_names_vec[j];
string name = p->readSTLString (transNamePtr); string name = p->readSTLString (transNamePtr);
foreign_languages[i].push_back (name); foreign_languages[i].push_back (name);
} }
@ -191,8 +190,6 @@ bool Translation::readName(t_name & name, df_name * source)
bool Translation::copyName(df_name * source, df_name * target) bool Translation::copyName(df_name * source, df_name * target)
{ {
uint8_t buf[28];
if (source == target) if (source == target)
return true; return true;
Core & c = Core::getInstance(); Core & c = Core::getInstance();

@ -36,7 +36,6 @@ using namespace std;
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "Error.h" #include "Error.h"
#include "Types.h" #include "Types.h"
@ -54,8 +53,8 @@ struct Units::Private
bool Inited; bool Inited;
bool Started; bool Started;
uint32_t dwarf_race_index_addr; void * dwarf_race_index_addr;
uint32_t dwarf_civ_id_addr; void * dwarf_civ_id_addr;
bool IdMapReady; bool IdMapReady;
std::map<int32_t, int32_t> IdMap; std::map<int32_t, int32_t> IdMap;
@ -86,8 +85,8 @@ Units::Units()
try try
{ {
creatures = (vector <df_unit *> *) OG_Creatures->getAddress ("vector"); creatures = (vector <df_unit *> *) OG_Creatures->getAddress ("vector");
d->dwarf_race_index_addr = OG_Creatures->getAddress("current_race"); d->dwarf_race_index_addr = (void *) OG_Creatures->getAddress("current_race");
d->dwarf_civ_id_addr = OG_Creatures->getAddress("current_civ"); d->dwarf_civ_id_addr = (void *) OG_Creatures->getAddress("current_civ");
} }
catch(Error::All&){}; catch(Error::All&){};
d->Inited = true; d->Inited = true;
@ -137,7 +136,6 @@ int32_t Units::GetCreatureInBox (int32_t index, df_unit ** furball,
return -1; return -1;
Process *p = d->owner; Process *p = d->owner;
uint16_t coords[3];
uint32_t size = creatures->size(); uint32_t size = creatures->size();
while (uint32_t(index) < size) while (uint32_t(index) < size)
{ {
@ -551,7 +549,7 @@ bool Creatures::ReadJob(const t_creature * furball, vector<t_material> & mat)
return true; return true;
} }
*/ */
bool Units::ReadInventoryByIdx(const uint32_t index, std::vector<df_item *> & item) bool Units::ReadInventoryByIdx(const uint32_t index, std::vector<df::item *> & item)
{ {
if(!d->Started) return false; if(!d->Started) return false;
if(index >= creatures->size()) return false; if(index >= creatures->size()) return false;
@ -559,7 +557,7 @@ bool Units::ReadInventoryByIdx(const uint32_t index, std::vector<df_item *> & it
return this->ReadInventoryByPtr(temp, item); return this->ReadInventoryByPtr(temp, item);
} }
bool Units::ReadInventoryByPtr(const df_unit * temp, std::vector<df_item *> & items) bool Units::ReadInventoryByPtr(const df_unit * temp, std::vector<df::item *> & items)
{ {
if(!d->Started) return false; if(!d->Started) return false;
items = temp->inventory; items = temp->inventory;
@ -576,7 +574,6 @@ bool Units::ReadOwnedItemsByIdx(const uint32_t index, std::vector<int32_t> & ite
bool Units::ReadOwnedItemsByPtr(const df_unit * temp, std::vector<int32_t> & items) bool Units::ReadOwnedItemsByPtr(const df_unit * temp, std::vector<int32_t> & items)
{ {
unsigned int i;
if(!d->Started) return false; if(!d->Started) return false;
items = temp->owned_items; items = temp->owned_items;
return true; return true;

@ -32,7 +32,6 @@ using namespace std;
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h"
#include "Types.h" #include "Types.h"
#include "modules/Vegetation.h" #include "modules/Vegetation.h"
#include "modules/Translation.h" #include "modules/Translation.h"

@ -37,150 +37,48 @@ using namespace std;
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
using namespace DFHack; using namespace DFHack;
using namespace DFHack::Simple;
struct Vermin::Private #include "DataDefs.h"
{ #include "df/world.h"
uint32_t spawn_points_vector; #include "df/vermin.h"
uint32_t race_offset; using namespace df::enums;
uint32_t type_offset; using df::global::world;
uint32_t position_offset;
uint32_t in_use_offset;
uint32_t unknown_offset;
uint32_t countdown_offset;
Process * owner;
bool Inited;
bool Started;
};
Module* DFHack::createVermin()
{
return new Vermin();
}
#include <stdio.h>
Vermin::Vermin()
{
Core & c = Core::getInstance();
d = new Private;
d->owner = c.p;
d->Inited = d->Started = false;
VersionInfo * mem = c.vinfo;
OffsetGroup * OG_vermin = mem->getGroup("Vermin");
OffsetGroup * OG_spawn = OG_vermin->getGroup("Spawn Points");
d->Inited = true;
try
{
d->spawn_points_vector = OG_spawn->getAddress("vector");
d->race_offset = OG_spawn->getOffset("race");
d->type_offset = OG_spawn->getOffset("type");
d->position_offset = OG_spawn->getOffset("position");
d->in_use_offset = OG_spawn->getOffset("in_use");
d->unknown_offset = OG_spawn->getOffset("unknown");
d->countdown_offset = OG_spawn->getOffset("countdown");
}
catch(DFHack::Error::AllMemdef &e)
{
cerr << "Vermin not available... " << e.what() << endl;
d->Inited = false;
}
}
bool Vermin::Finish()
{
return true;
}
Vermin::~Vermin()
{
delete d;
}
// NOTE: caller must call delete on result when done.
SpawnPoints* Vermin::getSpawnPoints()
{
if (!d->Inited)
{
cerr << "Couldn't get spawn points: Vermin module not inited" << endl;
return NULL;
}
return new SpawnPoints(this);
}
SpawnPoints::SpawnPoints(Vermin* v_)
{
v = v_;
p_sp = NULL;
if (!v->d->Inited)
{
cerr << "Couldn't get spawn points: Vermin module not inited" << endl;
return;
}
p_sp = (vector <void*>*) (v->d->spawn_points_vector);
}
SpawnPoints::~SpawnPoints() uint32_t Vermin::getNumVermin()
{ {
return df::vermin::get_vector().size();
} }
size_t SpawnPoints::size() bool Vermin::Read (const uint32_t index, t_vermin & sp)
{ {
if (!isValid()) df::vermin *verm = df::vermin::find(index);
return 0; if (!verm) return false;
return p_sp->size(); sp.origin = verm;
} sp.race = verm->race;
sp.caste = verm->caste;
bool SpawnPoints::Read (const uint32_t index, t_spawnPoint & sp) sp.visible = verm->visible;
{ sp.countdown = verm->countdown;
if(!isValid()) sp.x = verm->pos.x;
return false; sp.y = verm->pos.y;
sp.z = verm->pos.z;
// read pointer from vector at position sp.is_colony = verm->flags.bits.is_colony;
uint32_t temp = (uint32_t) p_sp->at (index);
sp.origin = temp;
sp.race = v->d->owner->readWord(temp + v->d->race_offset);
sp.type = v->d->owner->readWord(temp + v->d->type_offset);
sp.in_use = v->d->owner->readByte(temp + v->d->in_use_offset);
sp.unknown = v->d->owner->readByte(temp + v->d->unknown_offset);
sp.countdown = v->d->owner->readDWord(temp + v->d->countdown_offset);
// Three consecutive 16 bit numbers for x/y/z
v->d->owner->read(temp + v->d->position_offset, 6, (uint8_t*) &sp.x);
return true; return true;
} }
bool SpawnPoints::Write (const uint32_t index, t_spawnPoint & sp) bool Vermin::Write (const uint32_t index, t_vermin & sp)
{ {
if(!isValid()) df::vermin *verm = df::vermin::find(index);
return false; if (!verm) return false;
// read pointer from vector at position verm->race = sp.race;
uint32_t temp = (uint32_t) p_sp->at (index); verm->caste = sp.caste;
verm->visible = sp.visible;
v->d->owner->writeWord(temp + v->d->race_offset, sp.race); verm->countdown = sp.countdown;
v->d->owner->writeWord(temp + v->d->type_offset, sp.type); verm->pos.x = sp.x;
v->d->owner->writeByte(temp + v->d->in_use_offset, sp.in_use); verm->pos.y = sp.y;
v->d->owner->writeByte(temp + v->d->unknown_offset, sp.unknown); verm->pos.z = sp.z;
v->d->owner->writeDWord(temp + v->d->countdown_offset, sp.countdown); verm->flags.bits.is_colony = sp.is_colony;
// Three consecutive 16 bit numbers for x/y/z
v->d->owner->write(temp + v->d->position_offset, 6, (uint8_t*) &sp.x);
return true; return true;
} }
bool SpawnPoints::isWildColony(t_spawnPoint & point)
{
return (point.type == TYPE_WILD_COLONY);
}
bool SpawnPoints::isValid()
{
return (v != NULL && v->d->Inited && p_sp != NULL);
}

@ -38,6 +38,12 @@ using namespace std;
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
#include "MiscUtils.h"
#include "DataDefs.h"
#include "df/world.h"
#include "df/historical_figure.h"
using namespace DFHack; using namespace DFHack;
Module* DFHack::createWorld() Module* DFHack::createWorld()
@ -54,22 +60,22 @@ struct World::Private
bool Inited; bool Inited;
bool PauseInited; bool PauseInited;
uint32_t pause_state_offset; void * pause_state_offset;
bool StartedTime; bool StartedTime;
uint32_t year_offset; void * year_offset;
uint32_t tick_offset; void * tick_offset;
bool StartedWeather; bool StartedWeather;
uint32_t weather_offset; char * weather_offset;
bool StartedMode; bool StartedMode;
uint32_t gamemode_offset; void * gamemode_offset;
uint32_t controlmode_offset; void * controlmode_offset;
uint32_t controlmodecopy_offset; void * controlmodecopy_offset;
bool StartedFolder; bool StartedFolder;
uint32_t folder_name_offset; void * folder_name_offset;
Process * owner; Process * owner;
}; };
@ -241,3 +247,71 @@ string World::ReadWorldFolder()
} }
return string(""); return string("");
} }
static PersistentDataItem dataFromHFig(df::historical_figure *hfig)
{
return PersistentDataItem(hfig->id, hfig->name.first_name, &hfig->name.nickname, hfig->name.words);
}
PersistentDataItem World::AddPersistentData(const std::string &key)
{
std::vector<df::historical_figure*> &hfvec = df::historical_figure::get_vector();
int new_id = -100;
if (hfvec.size() > 0 && hfvec[0]->id <= new_id)
new_id = hfvec[0]->id-1;
df::historical_figure *hfig = new df::historical_figure();
hfig->id = new_id;
hfig->name.has_name = true;
hfig->name.first_name = key;
memset(hfig->name.words, 0xFF, sizeof(hfig->name.words));
hfvec.insert(hfvec.begin(), hfig);
return dataFromHFig(hfig);
}
PersistentDataItem World::GetPersistentData(const std::string &key)
{
std::vector<df::historical_figure*> &hfvec = df::historical_figure::get_vector();
for (unsigned i = 0; i < hfvec.size(); i++)
{
df::historical_figure *hfig = hfvec[i];
if (hfig->id >= 0)
break;
if (hfig->name.has_name && hfig->name.first_name == key)
return dataFromHFig(hfig);
}
return PersistentDataItem();
}
void World::GetPersistentData(std::vector<PersistentDataItem> *vec, const std::string &key)
{
std::vector<df::historical_figure*> &hfvec = df::historical_figure::get_vector();
for (unsigned i = 0; i < hfvec.size(); i++)
{
df::historical_figure *hfig = hfvec[i];
if (hfig->id >= 0)
break;
if (hfig->name.has_name && hfig->name.first_name == key)
vec->push_back(dataFromHFig(hfig));
}
}
void World::DeletePersistentData(const PersistentDataItem &item)
{
if (item.id > -100)
return;
std::vector<df::historical_figure*> &hfvec = df::historical_figure::get_vector();
int idx = binsearch_index(hfvec, item.id);
if (idx >= 0) {
delete hfvec[idx];
hfvec.erase(hfvec.begin()+idx);
}
}

@ -9,79 +9,46 @@
#include <set> #include <set>
using namespace std; using namespace std;
#include "Types.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Vector.h" #include "Types.h"
#include "modules/Materials.h" #include "Error.h"
#include "modules/Items.h"
#include "modules/Units.h"
#include "modules/kitchen.h" #include "modules/kitchen.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
#include "Virtual.h" using namespace DFHack;
using namespace DFHack::Simple;
namespace DFHack #include "DataDefs.h"
{ #include "df/world.h"
namespace Kitchen #include "df/ui.h"
{ #include "df/item_type.h"
class Exclusions::Private #include "df/plant_raw.h"
{
public:
Private (DFHack::Core& core_)
: core(core_)
, itemTypes (*((std::vector<t_itemType >*)(addr(core_,0))))
, itemSubtypes (*((std::vector<t_itemSubtype >*)(addr(core_,1))))
, materialTypes (*((std::vector<t_materialType >*)(addr(core_,2))))
, materialIndices (*((std::vector<t_materialIndex>*)(addr(core_,3))))
, exclusionTypes (*((std::vector<t_exclusionType>*)(addr(core_,4))))
{
};
DFHack::Core& core;
std::vector<t_itemType>& itemTypes; // the item types vector of the kitchen exclusion list
std::vector<t_itemSubtype>& itemSubtypes; // the item subtype vector of the kitchen exclusion list
std::vector<t_materialType>& materialTypes; // the material subindex vector of the kitchen exclusion list
std::vector<t_materialIndex>& materialIndices; // the material index vector of the kitchen exclusion list
std::vector<t_exclusionType>& exclusionTypes; // the exclusion type vector of the kitchen excluions list
static uint32_t addr(const DFHack::Core& core, int index) using namespace df::enums;
{ using df::global::world;
static uint32_t start = core.vinfo->getAddress("kitchen_limits"); using df::global::ui;
return start + sizeof(std::vector<int>) * index;
};
};
Exclusions::Exclusions(Core & c)
{
d = new Private(c);
};
Exclusions::~Exclusions()
{
delete d;
};
void Exclusions::debug_print() const void Kitchen::debug_print(Core &core)
{ {
d->core.con.print("Kitchen Exclusions\n"); core.con.print("Kitchen Exclusions\n");
Materials& materialsModule= *d->core.getMaterials();
for(std::size_t i = 0; i < size(); ++i) for(std::size_t i = 0; i < size(); ++i)
{ {
d->core.con.print("%2u: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n", core.con.print("%2u: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n",
i, i,
d->itemTypes[i], ui->kitchen.item_types[i],
d->itemSubtypes[i], ui->kitchen.item_subtypes[i],
d->materialTypes[i], ui->kitchen.mat_types[i],
d->materialIndices[i], ui->kitchen.mat_indices[i],
d->exclusionTypes[i], ui->kitchen.exc_types[i],
materialsModule.df_organic->at(d->materialIndices[i])->ID.c_str() (ui->kitchen.mat_types[i] >= 419 && ui->kitchen.mat_types[i] <= 618) ? world->raws.plants.all[ui->kitchen.mat_indices[i]]->id.c_str() : "n/a"
); );
} }
d->core.con.print("\n"); core.con.print("\n");
} }
void Exclusions::allowPlantSeedCookery(t_materialIndex materialIndex) void Kitchen::allowPlantSeedCookery(t_materialIndex materialIndex)
{ {
bool match = false; bool match = false;
do do
{ {
@ -89,9 +56,9 @@ namespace Kitchen
std::size_t matchIndex = 0; std::size_t matchIndex = 0;
for(std::size_t i = 0; i < size(); ++i) for(std::size_t i = 0; i < size(); ++i)
{ {
if(d->materialIndices[i] == materialIndex if(ui->kitchen.mat_indices[i] == materialIndex
&& (d->itemTypes[i] == DFHack::Items::SEEDS || d->itemTypes[i] == DFHack::Items::PLANT) && (ui->kitchen.item_types[i] == df::item_type::SEEDS || ui->kitchen.item_types[i] == df::item_type::PLANT)
&& d->exclusionTypes[i] == cookingExclusion && ui->kitchen.exc_types[i] == cookingExclusion
) )
{ {
match = true; match = true;
@ -100,64 +67,63 @@ namespace Kitchen
} }
if(match) if(match)
{ {
d->itemTypes.erase(d->itemTypes.begin() + matchIndex); ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex);
d->itemSubtypes.erase(d->itemSubtypes.begin() + matchIndex); ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex);
d->materialIndices.erase(d->materialIndices.begin() + matchIndex); ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex);
d->materialTypes.erase(d->materialTypes.begin() + matchIndex); ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex);
d->exclusionTypes.erase(d->exclusionTypes.begin() + matchIndex); ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex);
} }
} while(match); } while(match);
}; };
void Exclusions::denyPlantSeedCookery(t_materialIndex materialIndex) void Kitchen::denyPlantSeedCookery(t_materialIndex materialIndex)
{ {
Materials *mats = d->core.getMaterials(); df::plant_raw *type = world->raws.plants.all[materialIndex];
df_plant_type *type = mats->df_organic->at(materialIndex);
bool SeedAlreadyIn = false; bool SeedAlreadyIn = false;
bool PlantAlreadyIn = false; bool PlantAlreadyIn = false;
for(std::size_t i = 0; i < size(); ++i) for(std::size_t i = 0; i < size(); ++i)
{ {
if(d->materialIndices[i] == materialIndex if(ui->kitchen.mat_indices[i] == materialIndex
&& d->exclusionTypes[i] == cookingExclusion) && ui->kitchen.exc_types[i] == cookingExclusion)
{ {
if(d->itemTypes[i] == DFHack::Items::SEEDS) if(ui->kitchen.item_types[i] == df::item_type::SEEDS)
SeedAlreadyIn = true; SeedAlreadyIn = true;
else if (d->itemTypes[i] == DFHack::Items::PLANT) else if (ui->kitchen.item_types[i] == df::item_type::PLANT)
PlantAlreadyIn = true; PlantAlreadyIn = true;
} }
} }
if(!SeedAlreadyIn) if(!SeedAlreadyIn)
{ {
d->itemTypes.push_back(DFHack::Items::SEEDS); ui->kitchen.item_types.push_back(df::item_type::SEEDS);
d->itemSubtypes.push_back(organicSubtype); ui->kitchen.item_subtypes.push_back(organicSubtype);
d->materialTypes.push_back(type->material_type_seed); ui->kitchen.mat_types.push_back(type->material_defs.type_seed);
d->materialIndices.push_back(materialIndex); ui->kitchen.mat_indices.push_back(materialIndex);
d->exclusionTypes.push_back(cookingExclusion); ui->kitchen.exc_types.push_back(cookingExclusion);
} }
if(!PlantAlreadyIn) if(!PlantAlreadyIn)
{ {
d->itemTypes.push_back(DFHack::Items::PLANT); ui->kitchen.item_types.push_back(df::item_type::PLANT);
d->itemSubtypes.push_back(organicSubtype); ui->kitchen.item_subtypes.push_back(organicSubtype);
d->materialTypes.push_back(type->material_type_basic_mat); ui->kitchen.mat_types.push_back(type->material_defs.type_basic_mat);
d->materialIndices.push_back(materialIndex); ui->kitchen.mat_indices.push_back(materialIndex);
d->exclusionTypes.push_back(cookingExclusion); ui->kitchen.exc_types.push_back(cookingExclusion);
} }
}; };
void Exclusions::fillWatchMap(std::map<t_materialIndex, unsigned int>& watchMap) const void Kitchen::fillWatchMap(std::map<t_materialIndex, unsigned int>& watchMap)
{ {
watchMap.clear(); watchMap.clear();
for(std::size_t i = 0; i < size(); ++i) for(std::size_t i = 0; i < size(); ++i)
{ {
if(d->itemTypes[i] == limitType && d->itemSubtypes[i] == limitSubtype && d->exclusionTypes[i] == limitExclusion) if(ui->kitchen.item_subtypes[i] == limitType && ui->kitchen.item_subtypes[i] == limitSubtype && ui->kitchen.exc_types[i] == limitExclusion)
{ {
watchMap[d->materialIndices[i]] = (unsigned int) d->materialTypes[i]; watchMap[ui->kitchen.mat_indices[i]] = (unsigned int) ui->kitchen.mat_types[i];
} }
} }
}; };
void Exclusions::removeLimit(t_materialIndex materialIndex) void Kitchen::removeLimit(t_materialIndex materialIndex)
{ {
bool match = false; bool match = false;
do do
{ {
@ -165,10 +131,10 @@ namespace Kitchen
std::size_t matchIndex = 0; std::size_t matchIndex = 0;
for(std::size_t i = 0; i < size(); ++i) for(std::size_t i = 0; i < size(); ++i)
{ {
if(d->itemTypes[i] == limitType if(ui->kitchen.item_types[i] == limitType
&& d->itemSubtypes[i] == limitSubtype && ui->kitchen.item_subtypes[i] == limitSubtype
&& d->materialIndices[i] == materialIndex && ui->kitchen.mat_indices[i] == materialIndex
&& d->exclusionTypes[i] == limitExclusion) && ui->kitchen.exc_types[i] == limitExclusion)
{ {
match = true; match = true;
matchIndex = i; matchIndex = i;
@ -176,31 +142,31 @@ namespace Kitchen
} }
if(match) if(match)
{ {
d->itemTypes.erase(d->itemTypes.begin() + matchIndex); ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex);
d->itemSubtypes.erase(d->itemSubtypes.begin() + matchIndex); ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex);
d->materialTypes.erase(d->materialTypes.begin() + matchIndex); ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex);
d->materialIndices.erase(d->materialIndices.begin() + matchIndex); ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex);
d->exclusionTypes.erase(d->exclusionTypes.begin() + matchIndex); ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex);
} }
} while(match); } while(match);
}; };
void Exclusions::setLimit(t_materialIndex materialIndex, unsigned int limit) void Kitchen::setLimit(t_materialIndex materialIndex, unsigned int limit)
{ {
removeLimit(materialIndex); removeLimit(materialIndex);
if(limit > seedLimit) if(limit > seedLimit)
{ {
limit = seedLimit; limit = seedLimit;
} }
d->itemTypes.push_back(limitType); ui->kitchen.item_types.push_back(limitType);
d->itemSubtypes.push_back(limitSubtype); ui->kitchen.item_subtypes.push_back(limitSubtype);
d->materialIndices.push_back(materialIndex); ui->kitchen.mat_indices.push_back(materialIndex);
d->materialTypes.push_back((t_materialType) (limit < seedLimit) ? limit : seedLimit); ui->kitchen.mat_types.push_back((t_materialType) (limit < seedLimit) ? limit : seedLimit);
d->exclusionTypes.push_back(limitExclusion); ui->kitchen.exc_types.push_back(limitExclusion);
}; };
void Exclusions::clearLimits() void Kitchen::clearLimits()
{ {
bool match = false; bool match = false;
do do
{ {
@ -208,9 +174,9 @@ namespace Kitchen
std::size_t matchIndex; std::size_t matchIndex;
for(std::size_t i = 0; i < size(); ++i) for(std::size_t i = 0; i < size(); ++i)
{ {
if(d->itemTypes[i] == limitType if(ui->kitchen.item_types[i] == limitType
&& d->itemSubtypes[i] == limitSubtype && ui->kitchen.item_subtypes[i] == limitSubtype
&& d->exclusionTypes[i] == limitExclusion) && ui->kitchen.exc_types[i] == limitExclusion)
{ {
match = true; match = true;
matchIndex = i; matchIndex = i;
@ -218,17 +184,16 @@ namespace Kitchen
} }
if(match) if(match)
{ {
d->itemTypes.erase(d->itemTypes.begin() + matchIndex); ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex);
d->itemSubtypes.erase(d->itemSubtypes.begin() + matchIndex); ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex);
d->materialIndices.erase(d->materialIndices.begin() + matchIndex); ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex);
d->materialTypes.erase(d->materialTypes.begin() + matchIndex); ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex);
d->exclusionTypes.erase(d->exclusionTypes.begin() + matchIndex); ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex);
} }
} while(match); } while(match);
}; };
size_t Exclusions::size() const
{ size_t Kitchen::size()
return d->itemTypes.size(); {
}; return ui->kitchen.item_types.size();
}
}; };

@ -1 +1 @@
Subproject commit 7a730830c515fea701ff73b33cb604f48a4531fc Subproject commit d5abec61f72f113e023219fed19c4022363de953

@ -61,6 +61,9 @@ DFHACK_PLUGIN(initflags initflags.cpp)
DFHACK_PLUGIN(stockpiles stockpiles.cpp) DFHACK_PLUGIN(stockpiles stockpiles.cpp)
DFHACK_PLUGIN(rename rename.cpp) DFHACK_PLUGIN(rename rename.cpp)
DFHACK_PLUGIN(fixwagons fixwagons.cpp) DFHACK_PLUGIN(fixwagons fixwagons.cpp)
DFHACK_PLUGIN(jobutils jobutils.cpp)
DFHACK_PLUGIN(regrass regrass.cpp)
DFHACK_PLUGIN(workflow workflow.cpp)
#DFHACK_PLUGIN(versionosd versionosd.cpp) #DFHACK_PLUGIN(versionosd versionosd.cpp)
# this is the skeleton plugin. If you want to make your own, make a copy and then change it # this is the skeleton plugin. If you want to make your own, make a copy and then change it

@ -15,20 +15,20 @@ public:
ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS
}; };
Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos); Hexsearch(const SearchArgType &args,char * startpos,char * endpos);
~Hexsearch(); ~Hexsearch();
void Reset(){pos_=startpos_;}; void Reset(){pos_=startpos_;};
void SetStart(uint64_t pos){pos_=pos;}; void SetStart(char * pos){pos_=pos;};
uint64_t FindNext(); void * FindNext();
std::vector<uint64_t> FindAll(); std::vector<void *> FindAll();
private: private:
bool Compare(int a,int b); bool Compare(int a,int b);
void ReparseArgs(); void ReparseArgs();
SearchArgType args_; SearchArgType args_;
uint64_t pos_,startpos_,endpos_; char * pos_,* startpos_,* endpos_;
std::vector<int> BadCharShifts,GoodSuffixShift; std::vector<int> BadCharShifts,GoodSuffixShift;
void PrepareGoodSuffixTable(); void PrepareGoodSuffixTable();
void PrepareBadCharShift(); void PrepareBadCharShift();

@ -20,7 +20,7 @@ if mypos then
engine.poked(modpos+0x1c,count) --max size for div engine.poked(modpos+0x1c,count) --max size for div
else else
modpos,modsize=engine.loadmod("dfusion/migrants/migrants.o","Migrants") modpos,modsize=engine.loadmod("dfusion/migrants/migrants.o","Migrants",400)
print(string.format("Loaded module @:%x",modpos)) print(string.format("Loaded module @:%x",modpos))
count=0 count=0
for _,v in pairs(names) do for _,v in pairs(names) do

@ -1,7 +1,7 @@
#include "hexsearch.h" #include "hexsearch.h"
Hexsearch::Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) Hexsearch::Hexsearch(const SearchArgType &args,char * startpos,char * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos)
{ {
ReparseArgs(); ReparseArgs();
} }
@ -52,7 +52,7 @@ void Hexsearch::ReparseArgs()
} }
} }
} }
uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm void * Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm
{ {
DFHack::Core &inst=DFHack::Core::getInstance(); DFHack::Core &inst=DFHack::Core::getInstance();
DFHack::Process *p=inst.p; DFHack::Process *p=inst.p;
@ -81,16 +81,16 @@ uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm
return pos_-args_.size(); return pos_-args_.size();
} }
} }
pos_++; pos_ = pos_ + 1;
} }
delete [] buf; delete [] buf;
return 0; return 0;
} }
std::vector<uint64_t> Hexsearch::FindAll() std::vector<void *> Hexsearch::FindAll()
{ {
std::vector<uint64_t> ret; std::vector<void *> ret;
uint64_t cpos=pos_; void * cpos=pos_;
while(cpos!=0) while(cpos!=0)
{ {
cpos=FindNext(); cpos=FindNext();

@ -2,14 +2,14 @@
int lua::Hexsearch::find(lua_State *L) int lua::Hexsearch::find(lua_State *L)
{ {
lua::state st(L); lua::state st(L);
uint64_t pos=p->FindNext(); void * pos=p->FindNext();
st.push(pos); st.push(pos);
return 1; return 1;
} }
int lua::Hexsearch::findall(lua_State *L) int lua::Hexsearch::findall(lua_State *L)
{ {
lua::state st(L); lua::state st(L);
std::vector<uint64_t> pos=p->FindAll(); std::vector<void *> pos=p->FindAll();
st.newtable(); st.newtable();
for(unsigned i=0;i<pos.size();i++) for(unsigned i=0;i<pos.size();i++)
{ {
@ -22,10 +22,10 @@ int lua::Hexsearch::findall(lua_State *L)
lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id) lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id)
{ {
lua::state st(L); lua::state st(L);
uint64_t start,end; char * start,* end;
::Hexsearch::SearchArgType args; ::Hexsearch::SearchArgType args;
start=st.as<uint32_t>(1); start= (char *)st.as<uint32_t>(1);
end=st.as<uint32_t>(2); end=(char *)st.as<uint32_t>(2);
for(int i=3;i<=st.gettop();i++) for(int i=3;i<=st.gettop();i++)
{ {
args.push_back(st.as<int>(i)); args.push_back(st.as<int>(i));

@ -32,7 +32,7 @@ static int LoadMod(lua_State *L)
buf=new char[size]; buf=new char[size];
f.GetText(buf); f.GetText(buf);
//std::cout<<"poking @:"<<std::hex<<pos<<"size :"<<size<<std::endl; //std::cout<<"poking @:"<<std::hex<<pos<<"size :"<<size<<std::endl;
DFHack::Core::getInstance().p->write(pos,size,(uint8_t*)buf); DFHack::Core::getInstance().p->write((void *) pos,size,(uint8_t*)buf);
delete [] buf; delete [] buf;
st.push(pos); st.push(pos);
st.push(size); st.push(size);
@ -183,6 +183,18 @@ static int Call_Df(lua_State *L)
st.push(f.CallFunction(ptr,conv,args)); st.push(f.CallFunction(ptr,conv,args));
return 1; return 1;
} }
static int Suspend_Df(lua_State *L)
{
lua::state st(L);
DFHack::Core::getInstance().Suspend();
return 0;
}
static int Resume_Df(lua_State *L)
{
lua::state st(L);
DFHack::Core::getInstance().Resume();
return 0;
}
const luaL_Reg lua_misc_func[]= const luaL_Reg lua_misc_func[]=
{ {
{"loadmod",LoadMod}, {"loadmod",LoadMod},
@ -193,6 +205,8 @@ const luaL_Reg lua_misc_func[]=
{"newmod",NewMod}, {"newmod",NewMod},
{"getpushvalue",Get_PushValue}, {"getpushvalue",Get_PushValue},
{"calldf",Call_Df}, {"calldf",Call_Df},
{"suspend",Suspend_Df},
{"resume",Resume_Df},
{NULL,NULL} {NULL,NULL}
}; };
void lua::RegisterMisc(lua::state &st) void lua::RegisterMisc(lua::state &st)

@ -14,7 +14,7 @@ static int lua_Process_readDWord(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
uint32_t ret=c->readDWord(st.as<uint32_t>(1)); uint32_t ret=c->readDWord( (void *) st.as<uint32_t>(1));
st.push(ret); st.push(ret);
return 1; return 1;
} }
@ -22,14 +22,14 @@ static int lua_Process_writeDWord(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
c->writeDWord(st.as<uint32_t>(1),st.as<uint32_t>(2)); c->writeDWord((void *) st.as<uint32_t>(1),st.as<uint32_t>(2));
return 0; return 0;
} }
static int lua_Process_readFloat(lua_State *S) static int lua_Process_readFloat(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
float ret=c->readFloat(st.as<uint32_t>(1)); float ret=c->readFloat((void *) st.as<uint32_t>(1));
st.push(ret); st.push(ret);
return 1; return 1;
} }
@ -38,7 +38,7 @@ static int lua_Process_readWord(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
uint16_t ret=c->readWord(st.as<uint32_t>(1)); uint16_t ret=c->readWord((void *) st.as<uint32_t>(1));
st.push(ret); st.push(ret);
return 1; return 1;
} }
@ -47,14 +47,14 @@ static int lua_Process_writeWord(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
c->writeWord(st.as<uint32_t>(1),st.as<uint16_t>(2)); c->writeWord((void *) st.as<uint32_t>(1),st.as<uint16_t>(2));
return 0; return 0;
} }
static int lua_Process_readByte(lua_State *S) static int lua_Process_readByte(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
uint8_t ret=c->readByte(st.as<uint32_t>(1)); uint8_t ret=c->readByte((void *) st.as<uint32_t>(1));
st.push(ret); st.push(ret);
return 1; return 1;
} }
@ -63,7 +63,7 @@ static int lua_Process_writeByte(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
c->writeByte(st.as<uint32_t>(1),st.as<uint8_t>(2)); c->writeByte((void *) st.as<uint32_t>(1),st.as<uint8_t>(2));
return 0; return 0;
} }
static int lua_Process_read(lua_State *S) static int lua_Process_read(lua_State *S)
@ -77,7 +77,7 @@ static int lua_Process_read(lua_State *S)
buf=(uint8_t*)lua_touserdata(st,3); buf=(uint8_t*)lua_touserdata(st,3);
else else
buf=new uint8_t[len]; buf=new uint8_t[len];
c->read(st.as<uint32_t>(1),len,buf); c->read((void *) st.as<uint32_t>(1),len,buf);
st.pushlightuserdata(buf); st.pushlightuserdata(buf);
return 1; return 1;
} }
@ -85,14 +85,14 @@ static int lua_Process_write(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
c-> write(st.as<uint32_t>(1),st.as<uint32_t>(2),static_cast<uint8_t*>(lua_touserdata(st,3))); c-> write((void *) st.as<uint32_t>(1),st.as<uint32_t>(2),static_cast<uint8_t*>(lua_touserdata(st,3)));
return 0; return 0;
} }
static int lua_Process_readSTLString (lua_State *S) static int lua_Process_readSTLString (lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readSTLString(st.as<uint32_t>(1)); std::string r=c->readSTLString((void *) st.as<uint32_t>(1));
st.push(r); st.push(r);
return 1; return 1;
} }
@ -101,14 +101,14 @@ static int lua_Process_writeSTLString(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
c->writeSTLString(st.as<uint32_t>(1),st.as<std::string>(2)); c->writeSTLString((void *) st.as<uint32_t>(1),st.as<std::string>(2));
return 0; return 0;
} }
static int lua_Process_copySTLString(lua_State *S) static int lua_Process_copySTLString(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
c->copySTLString(st.as<uint32_t>(1),st.as<uint32_t>(2)); c->copySTLString((void *) st.as<uint32_t>(1),st.as<uint32_t>(2));
return 0; return 0;
} }
static int lua_Process_doReadClassName(lua_State *S) static int lua_Process_doReadClassName(lua_State *S)
@ -131,7 +131,7 @@ static int lua_Process_readCString (lua_State *S)
{ {
lua::state st(S); lua::state st(S);
DFHack::Process* c=GetProcessPtr(st); DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readCString(st.as<uint32_t>(1)); std::string r=c->readCString((void *) st.as<uint32_t>(1));
st.push(r); st.push(r);
return 1; return 1;
} }
@ -226,10 +226,10 @@ static int lua_Process_setPermisions(lua_State *S)
DFHack::t_memrange range,trange; DFHack::t_memrange range,trange;
st.getfield("start",1); st.getfield("start",1);
range.start=st.as<uint64_t>(); range.start= (void *)st.as<uint64_t>();
st.pop(); st.pop();
st.getfield("end",1); st.getfield("end",1);
range.end=st.as<uint64_t>(); range.end= (void *)st.as<uint64_t>();
st.pop(); st.pop();
st.getfield("read",2); st.getfield("read",2);

@ -16,7 +16,7 @@ int OffsetGroup::getOffset(lua_State *L)
int OffsetGroup::getAddress(lua_State *L) int OffsetGroup::getAddress(lua_State *L)
{ {
lua::state st(L); lua::state st(L);
uint32_t ret=p->getAddress(st.as<std::string>(1)); uint32_t ret= (uint32_t)p->getAddress(st.as<std::string>(1));
st.push(ret); st.push(ret);
return 1; return 1;
} }
@ -57,7 +57,7 @@ int OffsetGroup::getSafeOffset(lua_State *L)
int OffsetGroup::getSafeAddress(lua_State *L) int OffsetGroup::getSafeAddress(lua_State *L)
{ {
lua::state st(L); lua::state st(L);
uint32_t out; void * out;
bool ret=p->getSafeAddress(st.as<std::string>(1),out); bool ret=p->getSafeAddress(st.as<std::string>(1),out);
st.push(ret); st.push(ret);
st.push(out); st.push(out);
@ -286,7 +286,7 @@ static int __lua_resolveObjectToClassID(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
int32_t ret; int32_t ret;
bool output=DFHack::Core::getInstance().vinfo->resolveObjectToClassID(st.as<uint32_t>(1),ret); bool output=DFHack::Core::getInstance().vinfo->resolveObjectToClassID((char *)st.as<uint32_t>(1),ret);
st.push(output); st.push(output);
st.push(ret); st.push(ret);
return 2; return 2;
@ -329,7 +329,7 @@ static int __lua_getOffset(lua_State *S)
static int __lua_getAddress(lua_State *S) static int __lua_getAddress(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
uint32_t ret=DFHack::Core::getInstance().vinfo->getAddress(st.as<std::string>(1)); void * ret=DFHack::Core::getInstance().vinfo->getAddress(st.as<std::string>(1));
st.push(ret); st.push(ret);
return 1; return 1;
} }
@ -392,7 +392,7 @@ static int __lua_getSafeOffset(lua_State *S)
static int __lua_getSafeAddress(lua_State *S) static int __lua_getSafeAddress(lua_State *S)
{ {
lua::state st(S); lua::state st(S);
uint32_t out; void * out;
bool ret=DFHack::Core::getInstance().vinfo->getSafeAddress(st.as<std::string>(1),out); bool ret=DFHack::Core::getInstance().vinfo->getSafeAddress(st.as<std::string>(1),out);
st.push(ret); st.push(ret);
st.push(out); st.push(out);

@ -5,28 +5,34 @@
#include <sstream> #include <sstream>
#include <climits> #include <climits>
#include <vector> #include <vector>
#include <string>
#include <algorithm>
#include <set> #include <set>
using namespace std; using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <vector> #include "modules/Maps.h"
#include <string> #include "modules/Gui.h"
#include <algorithm> #include "modules/Items.h"
#include <modules/Maps.h> #include "modules/Materials.h"
#include "modules/MapCache.h"
#include <modules/Gui.h> #include "DataDefs.h"
#include <modules/Items.h> #include "df/item.h"
#include <modules/Materials.h> #include "df/world.h"
#include <modules/MapCache.h> #include "df/general_ref.h"
using namespace DFHack; using namespace DFHack;
using MapExtras::Block; using MapExtras::Block;
using MapExtras::MapCache; using MapExtras::MapCache;
using df::global::world;
DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters); DFhackCExport command_result df_autodump(Core * c, vector <string> & parameters);
DFhackCExport command_result df_autodump_destroy_here(Core * c, vector <string> & parameters);
DFhackCExport command_result df_autodump_destroy_item(Core * c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void ) DFhackCExport const char * plugin_name ( void )
{ {
@ -39,6 +45,18 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
commands.push_back(PluginCommand("autodump", commands.push_back(PluginCommand("autodump",
"Teleport items marked for dumping to the cursor.", "Teleport items marked for dumping to the cursor.",
df_autodump)); df_autodump));
commands.push_back(PluginCommand(
"autodump-destroy-here", "Destroy items marked for dumping under cursor.",
df_autodump_destroy_here, cursor_hotkey,
" Identical to autodump destroy-here, but intended for use as keybinding.\n"
));
commands.push_back(PluginCommand(
"autodump-destroy-item", "Destroy the selected item.",
df_autodump_destroy_item, any_item_hotkey,
" Destroy the selected item. The item may be selected\n"
" in the 'k' list, or inside a container. If called\n"
" again before the game is resumed, cancels destroy.\n"
));
return CR_OK; return CR_OK;
} }
@ -49,15 +67,18 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
typedef std::map <DFCoord, uint32_t> coordmap; typedef std::map <DFCoord, uint32_t> coordmap;
DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters) static command_result autodump_main(Core * c, vector <string> & parameters)
{ {
// Command line options // Command line options
bool destroy = false; bool destroy = false;
bool here = false;
if(parameters.size() > 0) if(parameters.size() > 0)
{ {
string & p = parameters[0]; string & p = parameters[0];
if(p == "destroy") if(p == "destroy")
destroy = true; destroy = true;
else if (p == "destroy-here")
destroy = here = true;
else if(p == "?" || p == "help") else if(p == "?" || p == "help")
{ {
c->con.print( c->con.print(
@ -67,31 +88,22 @@ DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters
"Be aware that any active dump item tasks still point at the item.\n\n" "Be aware that any active dump item tasks still point at the item.\n\n"
"Options:\n" "Options:\n"
"destroy - instead of dumping, destroy the items instantly.\n" "destroy - instead of dumping, destroy the items instantly.\n"
"destroy-here - only affect the tile under cursor.\n"
); );
return CR_OK; return CR_OK;
} }
} }
c->Suspend();
DFHack::occupancies40d * occupancies;
DFHack::VersionInfo *mem = c->vinfo; DFHack::VersionInfo *mem = c->vinfo;
DFHack::Gui * Gui = c->getGui(); DFHack::Gui * Gui = c->getGui();
DFHack::Items * Items = c->getItems();
DFHack::Maps *Maps = c->getMaps(); DFHack::Maps *Maps = c->getMaps();
vector <df_item*> p_items; std::size_t numItems = world->items.all.size();
if(!Items->readItemVector(p_items))
{
c->con.printerr("Can't access the item vector.\n");
c->Resume();
return CR_FAILURE;
}
std::size_t numItems = p_items.size();
// init the map // init the map
if(!Maps->Start()) if(!Maps->Start())
{ {
c->con.printerr("Can't initialize map.\n"); c->con.printerr("Can't initialize map.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
MapCache MC (Maps); MapCache MC (Maps);
@ -100,28 +112,28 @@ DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters
int cx, cy, cz; int cx, cy, cz;
DFCoord pos_cursor; DFCoord pos_cursor;
if(!destroy) if(!destroy || here)
{ {
if (!Gui->getCursorCoords(cx,cy,cz)) if (!Gui->getCursorCoords(cx,cy,cz))
{ {
c->con.printerr("Cursor position not found. Please enabled the cursor.\n"); c->con.printerr("Cursor position not found. Please enabled the cursor.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
pos_cursor = DFCoord(cx,cy,cz); pos_cursor = DFCoord(cx,cy,cz);
}
if (!destroy)
{
{ {
Block * b = MC.BlockAt(pos_cursor / 16); Block * b = MC.BlockAt(pos_cursor / 16);
if(!b) if(!b)
{ {
c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n"); c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
uint16_t ttype = MC.tiletypeAt(pos_cursor); uint16_t ttype = MC.tiletypeAt(pos_cursor);
if(!DFHack::isFloorTerrain(ttype)) if(!DFHack::isFloorTerrain(ttype))
{ {
c->con.printerr("Cursor should be placed over a floor.\n"); c->con.printerr("Cursor should be placed over a floor.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
} }
@ -130,8 +142,8 @@ DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters
// proceed with the dumpification operation // proceed with the dumpification operation
for(std::size_t i=0; i< numItems; i++) for(std::size_t i=0; i< numItems; i++)
{ {
df_item * itm = p_items[i]; df::item * itm = world->items.all[i];
DFCoord pos_item(itm->x, itm->y, itm->z); DFCoord pos_item(itm->pos.x, itm->pos.y, itm->pos.z);
// keep track how many items are at places. all items. // keep track how many items are at places. all items.
coordmap::iterator it = counts.find(pos_item); coordmap::iterator it = counts.find(pos_item);
@ -147,22 +159,22 @@ DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters
// iterator is valid here, we use it later to decrement the pile counter if the item is moved // iterator is valid here, we use it later to decrement the pile counter if the item is moved
// only dump the stuff marked for dumping and laying on the ground // only dump the stuff marked for dumping and laying on the ground
if ( !itm->flags.dump if ( !itm->flags.bits.dump
|| !itm->flags.on_ground || !itm->flags.bits.on_ground
|| itm->flags.construction || itm->flags.bits.construction
|| itm->flags.hidden || itm->flags.bits.hidden
|| itm->flags.in_building || itm->flags.bits.in_building
|| itm->flags.in_chest || itm->flags.bits.in_chest
|| itm->flags.in_inventory || itm->flags.bits.in_inventory
|| itm->flags.construction || itm->flags.bits.artifact1
) )
continue; continue;
if(!destroy) // move to cursor if(!destroy) // move to cursor
{ {
// Change flags to indicate the dump was completed, as if by super-dwarfs // Change flags to indicate the dump was completed, as if by super-dwarfs
itm->flags.dump = false; itm->flags.bits.dump = false;
itm->flags.forbid = true; itm->flags.bits.forbid = true;
// Don't move items if they're already at the cursor // Don't move items if they're already at the cursor
if (pos_cursor == pos_item) if (pos_cursor == pos_item)
@ -173,7 +185,7 @@ DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters
{ {
// yes... // yes...
cerr << "Moving from block to block!" << endl; cerr << "Moving from block to block!" << endl;
df_block * bl_src = Maps->getBlock(itm->x /16, itm->y/16, itm->z); df_block * bl_src = Maps->getBlock(itm->pos.x /16, itm->pos.y/16, itm->pos.z);
df_block * bl_tgt = Maps->getBlock(cx /16, cy/16, cz); df_block * bl_tgt = Maps->getBlock(cx /16, cy/16, cz);
if(bl_src) if(bl_src)
{ {
@ -194,13 +206,20 @@ DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters
} }
// Move the item // Move the item
itm->x = pos_cursor.x; itm->pos.x = pos_cursor.x;
itm->y = pos_cursor.y; itm->pos.y = pos_cursor.y;
itm->z = pos_cursor.z; itm->pos.z = pos_cursor.z;
} }
else // destroy else // destroy
{ {
itm->flags.garbage_colect = true; if (here && pos_item != pos_cursor)
continue;
itm->flags.bits.garbage_colect = true;
// Cosmetic changes: make them disappear from view instantly
itm->flags.bits.forbid = true;
itm->flags.bits.hidden = true;
} }
// keeping track of item pile sizes ;) // keeping track of item pile sizes ;)
it->second --; it->second --;
@ -238,7 +257,92 @@ DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters
// Is this necessary? Is "forbid" a dirtyable attribute like "dig" is? // Is this necessary? Is "forbid" a dirtyable attribute like "dig" is?
Maps->WriteDirtyBit(cx/16, cy/16, cz, true); Maps->WriteDirtyBit(cx/16, cy/16, cz, true);
} }
c->Resume(); c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for destruction" : "quickdumped");
c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for desctruction" : "quickdumped"); return CR_OK;
}
DFhackCExport command_result df_autodump(Core * c, vector <string> & parameters)
{
CoreSuspender suspend(c);
return autodump_main(c, parameters);
}
DFhackCExport command_result df_autodump_destroy_here(Core * c, vector <string> & parameters)
{
// HOTKEY COMMAND; CORE ALREADY SUSPENDED
if (!parameters.empty())
return CR_WRONG_USAGE;
vector<string> args;
args.push_back("destroy-here");
return autodump_main(c, args);
}
static std::map<int, df::item_flags> pending_destroy;
static int last_frame = 0;
DFhackCExport command_result df_autodump_destroy_item(Core * c, vector <string> & parameters)
{
// HOTKEY COMMAND; CORE ALREADY SUSPENDED
if (!parameters.empty())
return CR_WRONG_USAGE;
df::item *item = getSelectedItem(c);
if (!item)
return CR_FAILURE;
// Allow undoing the destroy
if (df::global::world->frame_counter != last_frame)
{
last_frame = df::global::world->frame_counter;
pending_destroy.clear();
}
if (pending_destroy.count(item->id))
{
df::item_flags old_flags = pending_destroy[item->id];
pending_destroy.erase(item->id);
item->flags.bits.garbage_colect = false;
item->flags.bits.hidden = old_flags.bits.hidden;
item->flags.bits.dump = old_flags.bits.dump;
item->flags.bits.forbid = old_flags.bits.forbid;
return CR_OK;
}
// Check the item is good to destroy
if (item->flags.bits.garbage_colect)
{
c->con.printerr("Item is already marked for destroy.\n");
return CR_FAILURE;
}
if (item->flags.bits.construction ||
item->flags.bits.in_building ||
item->flags.bits.artifact1)
{
c->con.printerr("Choosing not to destroy buildings, constructions and artifacts.\n");
return CR_FAILURE;
}
for (unsigned i = 0; i < item->itemrefs.size(); i++)
{
df::general_ref *ref = item->itemrefs[i];
if (ref->getType() == df::general_ref_type::UNIT_HOLDER)
{
c->con.printerr("Choosing not to destroy items in unit inventory.\n");
return CR_FAILURE;
}
}
// Set the flags
pending_destroy[item->id] = item->flags;
item->flags.bits.garbage_colect = true;
item->flags.bits.hidden = true;
item->flags.bits.dump = true;
item->flags.bits.forbid = true;
return CR_OK; return CR_OK;
} }

@ -1,100 +1,71 @@
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Maps.h>
#include <modules/Items.h> #include "DataDefs.h"
#include <modules/Units.h> #include "df/world.h"
#include <modules/Gui.h> #include "df/map_block.h"
#include "df/block_square_event.h"
#include "df/block_square_event_material_spatterst.h"
#include "df/item_actual.h"
#include "df/unit.h"
#include "df/unit_spatter.h"
#include "df/matter_state.h"
#include "df/cursor.h"
#include "df/builtin_mats.h"
#include "df/contaminant.h"
using namespace DFHack;
#include <vector>
#include <string>
#include <string.h>
using std::vector; using std::vector;
using std::string; using std::string;
using namespace DFHack;
DFhackCExport command_result clean (Core * c, vector <string> & parameters); using df::global::world;
DFhackCExport command_result spotclean (Core * c, vector <string> & parameters); using df::global::cursor;
DFhackCExport const char * plugin_name ( void )
{
return "cleaners";
}
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("clean","Removes contaminants from map tiles, items and creatures.",clean));
commands.push_back(PluginCommand("spotclean","Cleans map tile under cursor.",spotclean,cursor_hotkey));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}
command_result cleanmap (Core * c, bool snow, bool mud) command_result cleanmap (Core * c, bool snow, bool mud)
{ {
const uint32_t water_idx = 6; // Invoked from clean(), already suspended
const uint32_t mud_idx = 12; int num_blocks = 0, blocks_total = world->map.map_blocks.size();
vector<DFHack::t_spattervein *> splatter; for (int i = 0; i < blocks_total; i++)
DFHack::Maps *Mapz = c->getMaps();
// init the map
if(!Mapz->Start())
{
c->con << "Can't init map." << std::endl;
c->Resume();
return CR_FAILURE;
}
uint32_t x_max,y_max,z_max;
Mapz->getSize(x_max,y_max,z_max);
int num_blocks = 0;
int blocks_total = 0;
// walk the map
for(uint32_t x = 0; x< x_max;x++)
{
for(uint32_t y = 0; y< y_max;y++)
{
for(uint32_t z = 0; z< z_max;z++)
{ {
df_block * block = Mapz->getBlock(x,y,z); df::map_block *block = world->map.map_blocks[i];
if(block)
{
blocks_total ++;
bool cleaned = false; bool cleaned = false;
Mapz->SortBlockEvents(x,y,z,0,0,&splatter); for(int x = 0; x < 16; x++)
for(int i = 0; i < 16; i++) {
for(int j = 0; j < 16; j++) for(int y = 0; y < 16; y++)
{ {
block->occupancy[i][j].bits.arrow_color = 0; block->occupancy[x][y].bits.arrow_color = 0;
block->occupancy[i][j].bits.broken_arrows_variant = 0; block->occupancy[x][y].bits.arrow_variant = 0;
}
} }
for(uint32_t i = 0; i < splatter.size(); i++) for (int j = 0; j < block->block_events.size(); j++)
{ {
DFHack::t_spattervein * vein = splatter[i]; df::block_square_event *evt = block->block_events[j];
if (evt->getType() != df::block_square_event_type::material_spatter)
continue;
// type verified - recast to subclass
df::block_square_event_material_spatterst *spatter = (df::block_square_event_material_spatterst *)evt;
// filter snow // filter snow
if(!snow if(!snow
&& vein->mat1 == DFHack::Materials::WATER && spatter->mat_type == df::builtin_mats::WATER
&& vein->matter_state == DFHack::state_powder) && spatter->mat_state == df::matter_state::Powder)
continue; continue;
// filter mud // filter mud
if(!mud if(!mud
&& vein->mat1 == DFHack::Materials::MUD && spatter->mat_type == df::builtin_mats::MUD
&& vein->matter_state == DFHack::state_solid) && spatter->mat_state == df::matter_state::Solid)
continue; continue;
Mapz->RemoveBlockEvent(x,y,z,(t_virtual *) vein);
delete evt;
block->block_events.erase(block->block_events.begin() + j);
j--;
cleaned = true; cleaned = true;
} }
num_blocks += cleaned; num_blocks += cleaned;
} }
}
}
}
if(num_blocks) if(num_blocks)
c->con.print("Cleaned %d of %d map blocks.\n", num_blocks, blocks_total); c->con.print("Cleaned %d of %d map blocks.\n", num_blocks, blocks_total);
return CR_OK; return CR_OK;
@ -102,94 +73,81 @@ command_result cleanmap (Core * c, bool snow, bool mud)
command_result cleanitems (Core * c) command_result cleanitems (Core * c)
{ {
DFHack::Items * Items = c->getItems(); // Invoked from clean(), already suspended
vector <df_item*> p_items;
if(!Items->readItemVector(p_items))
{
c->con.printerr("Can't access the item vector.\n");
c->Resume();
return CR_FAILURE;
}
std::size_t numItems = p_items.size();
int cleaned_items = 0, cleaned_total = 0; int cleaned_items = 0, cleaned_total = 0;
for (std::size_t i = 0; i < numItems; i++) for (int i = 0; i < world->items.all.size(); i++)
{ {
df_item * itm = p_items[i]; // currently, all item classes extend item_actual, so this should be safe
if(!itm->contaminants) df::item_actual *item = (df::item_actual *)world->items.all[i];
continue; if (item->contaminants && item->contaminants->size())
if (itm->contaminants->size())
{ {
for(int j = 0; j < itm->contaminants->size(); j++) for (int j = 0; j < item->contaminants->size(); j++)
delete itm->contaminants->at(j); delete item->contaminants->at(j);
cleaned_items++; cleaned_items++;
cleaned_total += itm->contaminants->size(); cleaned_total += item->contaminants->size();
itm->contaminants->clear(); item->contaminants->clear();
} }
} }
if(cleaned_total) if (cleaned_total)
c->con.print("Removed %d contaminants from %d items.\n", cleaned_total, cleaned_items); c->con.print("Removed %d contaminants from %d items.\n", cleaned_total, cleaned_items);
return CR_OK; return CR_OK;
} }
command_result cleanunits (Core * c) command_result cleanunits (Core * c)
{ {
DFHack::Units * Creatures = c->getUnits(); // Invoked from clean(), already suspended
int num_units = world->units.all.size();
uint32_t num_creatures;
if (!Creatures->Start(num_creatures))
{
c->con.printerr("Can't read unit list!\n");
c->Resume();
return CR_FAILURE;
}
int cleaned_units = 0, cleaned_total = 0; int cleaned_units = 0, cleaned_total = 0;
for (std::size_t i = 0; i < num_creatures; i++) for (int i = 0; i < num_units; i++)
{ {
df_unit *unit = Creatures->creatures->at(i); df::unit *unit = world->units.all[i];
int num = unit->contaminants.size(); if (unit->body.spatters.size())
if (num)
{ {
for(int j = 0; j < unit->contaminants.size(); j++) for (int j = 0; j < unit->body.spatters.size(); j++)
delete unit->contaminants.at(j); delete unit->body.spatters[j];
cleaned_units++; cleaned_units++;
cleaned_total += num; cleaned_total += unit->body.spatters.size();
unit->contaminants.clear(); unit->body.spatters.clear();
} }
} }
if(cleaned_total) if (cleaned_total)
c->con.print("Removed %d contaminants from %d creatures.\n", cleaned_total, cleaned_units); c->con.print("Removed %d contaminants from %d creatures.\n", cleaned_total, cleaned_units);
return CR_OK; return CR_OK;
} }
// This is slightly different from what's in the Maps module - it takes tile coordinates rather than block coordinates
df::map_block *getBlock (int32_t x, int32_t y, int32_t z)
{
if ((x < 0) || (y < 0) || (z < 0))
return NULL;
if ((x >= world->map.x_count) || (y >= world->map.y_count) || (z >= world->map.z_count))
return NULL;
return world->map.block_index[x >> 4][y >> 4][z];
}
DFhackCExport command_result spotclean (Core * c, vector <string> & parameters) DFhackCExport command_result spotclean (Core * c, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
vector<DFHack::t_spattervein *> splatter; if (cursor->x == -30000)
DFHack::Maps *Mapz = c->getMaps();
DFHack::Gui *Gui = c->getGui();
// init the map
if(!Mapz->Start())
{ {
c->con.printerr("Can't init map.\n"); c->con.printerr("The cursor is not active.\n");
return CR_FAILURE; return CR_FAILURE;
} }
int32_t cursorX, cursorY, cursorZ; df::map_block *block = getBlock(cursor->x, cursor->y, cursor->z);
Gui->getCursorCoords(cursorX,cursorY,cursorZ); if (block == NULL)
if(cursorX == -30000)
{ {
c->con.printerr("The cursor is not active.\n"); c->con.printerr("Invalid map block selected!\n");
return CR_FAILURE; return CR_FAILURE;
} }
int32_t blockX = cursorX / 16, blockY = cursorY / 16;
int32_t tileX = cursorX % 16, tileY = cursorY % 16; for (int i = 0; i < block->block_events.size(); i++)
df_block *b = Mapz->getBlock(blockX,blockY,cursorZ);
vector <t_spattervein *> spatters;
Mapz->SortBlockEvents(blockX, blockY, cursorZ, 0,0, &spatters);
for(int i = 0; i < spatters.size(); i++)
{ {
spatters[i]->intensity[tileX][tileY] = 0; df::block_square_event *evt = block->block_events[i];
if (evt->getType() != df::block_square_event_type::material_spatter)
continue;
// type verified - recast to subclass
df::block_square_event_material_spatterst *spatter = (df::block_square_event_material_spatterst *)evt;
spatter->amount[cursor->x % 16][cursor->y % 16] = 0;
} }
return CR_OK; return CR_OK;
} }
@ -239,7 +197,7 @@ DFhackCExport command_result clean (Core * c, vector <string> & parameters)
"snow - also remove snow\n" "snow - also remove snow\n"
"mud - also remove mud\n" "mud - also remove mud\n"
"Example: clean all mud snow\n" "Example: clean all mud snow\n"
"This removes all spatter, including mud and snow from map tiles." "This removes all spatter, including mud and snow from map tiles.\n"
); );
return CR_OK; return CR_OK;
} }
@ -253,3 +211,21 @@ DFhackCExport command_result clean (Core * c, vector <string> & parameters)
c->Resume(); c->Resume();
return CR_OK; return CR_OK;
} }
DFhackCExport const char * plugin_name ( void )
{
return "cleaners";
}
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("clean","Removes contaminants from map tiles, items and creatures.",clean));
commands.push_back(PluginCommand("spotclean","Cleans map tile under cursor.",spotclean,cursor_hotkey));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}

@ -9,17 +9,22 @@
using namespace std; using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <vector> #include <vector>
#include <string> #include <string>
#include <modules/Maps.h> #include "modules/Maps.h"
#include <modules/Items.h> #include "modules/Items.h"
#include <modules/Units.h> #include "modules/Units.h"
#include <modules/Materials.h> #include "modules/Materials.h"
#include <modules/Translation.h> #include "modules/Translation.h"
using namespace DFHack; using namespace DFHack;
using namespace DFHack::Simple;
#include "DataDefs.h"
#include "df/world.h"
using df::global::world;
DFhackCExport command_result df_cleanowned (Core * c, vector <string> & parameters); DFhackCExport command_result df_cleanowned (Core * c, vector <string> & parameters);
@ -89,7 +94,6 @@ DFhackCExport command_result df_cleanowned (Core * c, vector <string> & paramete
} }
c->Suspend(); c->Suspend();
DFHack::Materials *Materials = c->getMaterials(); DFHack::Materials *Materials = c->getMaterials();
DFHack::Items *Items = c->getItems();
DFHack::Units *Creatures = c->getUnits(); DFHack::Units *Creatures = c->getUnits();
DFHack::Translation *Tran = c->getTranslation(); DFHack::Translation *Tran = c->getTranslation();
@ -99,28 +103,20 @@ DFhackCExport command_result df_cleanowned (Core * c, vector <string> & paramete
ok &= Creatures->Start(num_creatures); ok &= Creatures->Start(num_creatures);
ok &= Tran->Start(); ok &= Tran->Start();
vector<df_item *> p_items; c->con.print("Found total %d items.\n", world->items.all.size());
ok &= Items->readItemVector(p_items);
if(!ok)
{
c->con.printerr("Can't continue due to offset errors.\n");
c->Resume();
return CR_FAILURE;
}
c->con.print("Found total %d items.\n", p_items.size());
for (std::size_t i=0; i < p_items.size(); i++) for (std::size_t i=0; i < world->items.all.size(); i++)
{ {
df_item * item = p_items[i]; df::item * item = world->items.all[i];
bool confiscate = false; bool confiscate = false;
bool dump = false; bool dump = false;
if (!item->flags.owned) if (!item->flags.bits.owned)
{ {
int32_t owner = Items->getItemOwnerID(item); int32_t owner = Items::getItemOwnerID(item);
if (owner >= 0) if (owner >= 0)
{ {
c->con.print("Fixing a misflagged item: "); c->con.print("Fixing a misflagged item: \t");
confiscate = true; confiscate = true;
} }
else else
@ -129,23 +125,21 @@ DFhackCExport command_result df_cleanowned (Core * c, vector <string> & paramete
} }
} }
std::string name = Items->getItemClass(item); if (item->flags.bits.rotten)
if (item->flags.rotten)
{ {
c->con.print("Confiscating a rotten item: \t"); c->con.print("Confiscating a rotten item: \t");
confiscate = true; confiscate = true;
} }
else if (item->flags.on_ground) else if (item->flags.bits.on_ground)
{ {
int32_t type = item->getType(); int32_t type = item->getType();
if(type == Items::MEAT || if(type == df::item_type::MEAT ||
type == Items::FISH || type == df::item_type::FISH ||
type == Items::VERMIN || type == df::item_type::VERMIN ||
type == Items::PET || type == df::item_type::PET ||
type == Items::PLANT || type == df::item_type::PLANT ||
type == Items::CHEESE || type == df::item_type::CHEESE ||
type == Items::FOOD type == df::item_type::FOOD
) )
{ {
confiscate = true; confiscate = true;
@ -189,7 +183,7 @@ DFhackCExport command_result df_cleanowned (Core * c, vector <string> & paramete
item->getWear() item->getWear()
); );
int32_t owner = Items->getItemOwnerID(item); int32_t owner = Items::getItemOwnerID(item);
int32_t owner_index = Creatures->FindIndexById(owner); int32_t owner_index = Creatures->FindIndexById(owner);
std::string info; std::string info;
@ -206,10 +200,10 @@ DFhackCExport command_result df_cleanowned (Core * c, vector <string> & paramete
if (!dry_run) if (!dry_run)
{ {
if (!Items->removeItemOwner(item, Creatures)) if (!Items::removeItemOwner(item, Creatures))
c->con.print("(unsuccessfully) "); c->con.print("(unsuccessfully) ");
if (dump) if (dump)
item->flags.dump = 1; item->flags.bits.dump = 1;
} }
c->con.print("\n"); c->con.print("\n");
} }

@ -1,15 +1,16 @@
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <vector> #include <vector>
#include <string> #include <string>
#include <modules/Vermin.h> #include "modules/Vermin.h"
#include "modules/Materials.h"
using std::vector; using std::vector;
using std::string; using std::string;
using namespace DFHack; using namespace DFHack;
#include <DFHack.h> using namespace DFHack::Simple;
DFhackCExport command_result colonies (Core * c, vector <string> & parameters); DFhackCExport command_result colonies (Core * c, vector <string> & parameters);
@ -32,10 +33,9 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
return CR_OK; return CR_OK;
} }
void destroyColonies(DFHack::SpawnPoints *points); void destroyColonies();
void convertColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials); void convertColonies(Materials *Materials);
void showColonies(Core *c, DFHack::SpawnPoints *points, void showColonies(Core *c, Materials *Materials);
DFHack::Materials *Materials);
DFhackCExport command_result colonies (Core * c, vector <string> & parameters) DFhackCExport command_result colonies (Core * c, vector <string> & parameters)
{ {
@ -71,54 +71,42 @@ DFhackCExport command_result colonies (Core * c, vector <string> & parameters)
} }
c->Suspend(); c->Suspend();
Vermin * vermin = c->getVermin();
Materials * materials = c->getMaterials(); Materials * materials = c->getMaterials();
SpawnPoints *points = vermin->getSpawnPoints();
if(!points || !points->isValid())
{
c->con.printerr("vermin not supported for this DF version\n");
c->Resume();
return CR_FAILURE;
}
materials->ReadCreatureTypesEx(); materials->ReadCreatureTypesEx();
if (destroy) if (destroy)
destroyColonies(points); destroyColonies();
else if (convert) else if (convert)
convertColonies(points, materials); convertColonies(materials);
else else
showColonies(c, points, materials); showColonies(c, materials);
delete points;
vermin->Finish();
materials->Finish(); materials->Finish();
c->Resume(); c->Resume();
return CR_OK; return CR_OK;
} }
void destroyColonies(DFHack::SpawnPoints *points) //FIXME: this is probably bullshit
void destroyColonies()
{ {
uint32_t numSpawnPoints = points->size(); uint32_t numSpawnPoints = Vermin::getNumVermin();
for (uint32_t i = 0; i < numSpawnPoints; i++) for (uint32_t i = 0; i < numSpawnPoints; i++)
{ {
DFHack::t_spawnPoint sp; Vermin::t_vermin sp;
points->Read(i, sp); Vermin::Read(i, sp);
if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp)) if (sp.visible && sp.is_colony)
{ {
sp.in_use = false; sp.visible = false;
points->Write(i, sp); Vermin::Write(i, sp);
} }
} }
} }
// Convert all colonies to honey bees. // Convert all colonies to honey bees.
void convertColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials) void convertColonies(Materials *Materials)
{ {
int bee_idx = -1; int bee_idx = -1;
for (size_t i = 0; i < Materials->raceEx.size(); i++) for (size_t i = 0; i < Materials->raceEx.size(); i++)
@ -134,39 +122,38 @@ void convertColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials)
return; return;
} }
uint32_t numSpawnPoints = points->size(); uint32_t numSpawnPoints = Vermin::getNumVermin();
for (uint32_t i = 0; i < numSpawnPoints; i++) for (uint32_t i = 0; i < numSpawnPoints; i++)
{ {
DFHack::t_spawnPoint sp; Vermin::t_vermin sp;
points->Read(i, sp); Vermin::Read(i, sp);
if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp)) if (sp.visible && sp.is_colony)
{ {
sp.race = bee_idx; sp.race = bee_idx;
points->Write(i, sp); Vermin::Write(i, sp);
} }
} }
} }
void showColonies(Core *c, DFHack::SpawnPoints *points, void showColonies(Core *c, Materials *Materials)
DFHack::Materials *Materials)
{ {
uint32_t numSpawnPoints = points->size(); uint32_t numSpawnPoints = Vermin::getNumVermin();
int numColonies = 0; int numColonies = 0;
for (uint32_t i = 0; i < numSpawnPoints; i++) for (uint32_t i = 0; i < numSpawnPoints; i++)
{ {
DFHack::t_spawnPoint sp; Vermin::t_vermin sp;
points->Read(i, sp); Vermin::Read(i, sp);
if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp)) if (sp.visible && sp.is_colony)
{ {
numColonies++; numColonies++;
string race="(no race)"; string race="(no race)";
if(sp.race != -1) if(sp.race != -1)
race = Materials->raceEx[sp.race].id; race = Materials->raceEx[sp.race].id;
c->con.print("Spawn point %u: %s at %d:%d:%d\n", i, c->con.print("Colony %u: %s at %d:%d:%d\n", i,
race.c_str(), sp.x, sp.y, sp.z); race.c_str(), sp.x, sp.y, sp.z);
} }
} }

@ -1,56 +1,35 @@
// De-ramp. All ramps marked for removal are replaced with given tile (presently, normal floor). // De-ramp. All ramps marked for removal are replaced with given tile (presently, normal floor).
#include <iostream>
#include <vector>
#include <map>
#include <stddef.h>
#include <assert.h>
#include <string.h>
using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Maps.h>
#include <TileTypes.h>
using namespace DFHack;
DFhackCExport command_result df_deramp (Core * c, vector <string> & parameters); #include "DataDefs.h"
#include "df/world.h"
#include "df/map_block.h"
#include "df/tile_dig_designation.h"
#include "TileTypes.h"
DFhackCExport const char * plugin_name ( void ) using std::vector;
{ using std::string;
return "deramp"; using namespace DFHack;
}
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) using df::global::world;
{ using namespace DFHack;
commands.clear();
commands.push_back(PluginCommand("deramp",
"De-ramp. All ramps marked for removal are replaced with floors.",
df_deramp));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c ) // This is slightly different from what's in the Maps module - it takes tile coordinates rather than block coordinates
df::map_block *getBlock (int32_t x, int32_t y, int32_t z)
{ {
return CR_OK; if ((x < 0) || (y < 0) || (z < 0))
return NULL;
if ((x >= world->map.x_count) || (y >= world->map.y_count) || (z >= world->map.z_count))
return NULL;
return world->map.block_index[x >> 4][y >> 4][z];
} }
DFhackCExport command_result df_deramp (Core * c, vector <string> & parameters) DFhackCExport command_result df_deramp (Core * c, vector <string> & parameters)
{ {
uint32_t x_max,y_max,z_max;
uint32_t num_blocks = 0;
uint32_t bytes_read = 0;
DFHack::designations40d designations;
DFHack::tiletypes40d tiles;
DFHack::tiletypes40d tilesAbove;
//DFHack::TileRow *ptile;
int32_t oldT, newT;
bool dirty= false;
int count=0;
int countbad=0;
for(int i = 0; i < parameters.size();i++) for(int i = 0; i < parameters.size();i++)
{ {
if(parameters[i] == "help" || parameters[i] == "?") if(parameters[i] == "help" || parameters[i] == "?")
@ -62,97 +41,74 @@ DFhackCExport command_result df_deramp (Core * c, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
} }
c->Suspend();
DFHack::Maps *Mapz = c->getMaps();
// init the map
if (!Mapz->Start())
{
c->con.printerr("Can't init map.\n");
c->Resume();
return CR_FAILURE;
}
Mapz->getSize(x_max,y_max,z_max); CoreSuspender suspend(c);
uint8_t zeroes [16][16] = {0}; int count = 0;
int countbad = 0;
// walk the map int num_blocks = 0, blocks_total = world->map.map_blocks.size();
for (uint32_t x = 0; x< x_max;x++) for (int i = 0; i < blocks_total; i++)
{ {
for (uint32_t y = 0; y< y_max;y++) df::map_block *block = world->map.map_blocks[i];
{ df::map_block *above = getBlock(block->map_pos.x, block->map_pos.y, block->map_pos.z + 1);
for (uint32_t z = 0; z< z_max;z++)
{
if (Mapz->getBlock(x,y,z))
{
dirty= false;
Mapz->ReadDesignations(x,y,z, &designations);
Mapz->ReadTileTypes(x,y,z, &tiles);
if (Mapz->getBlock(x,y,z+1))
{
Mapz->ReadTileTypes(x,y,z+1, &tilesAbove);
}
else
{
memset(&tilesAbove,0,sizeof(tilesAbove));
}
for (uint32_t ty=0;ty<16;++ty) for (int x = 0; x < 16; x++)
{ {
for (uint32_t tx=0;tx<16;++tx) for (int y = 0; y < 16; y++)
{ {
//Only the remove ramp designation (ignore channel designation, etc) int16_t oldT = block->tiletype[x][y];
oldT = tiles[tx][ty]; if ((tileShape(oldT) == RAMP) &&
if ( DFHack::designation_default == designations[tx][ty].bits.dig (block->designation[x][y].bits.dig == df::tile_dig_designation::Default))
&& DFHack::RAMP==DFHack::tileShape(oldT))
{ {
//Current tile is a ramp. // Current tile is a ramp.
//Set current tile, as accurately as can be expected // Set current tile, as accurately as can be expected
newT = DFHack::findSimilarTileType(oldT,DFHack::FLOOR); int16_t newT = findSimilarTileType(oldT, FLOOR);
//If no change, skip it (couldn't find a good tile type) // If no change, skip it (couldn't find a good tile type)
if ( oldT == newT) continue; if (oldT == newT)
//Set new tile type, clear designation continue;
tiles[tx][ty] = newT; // Set new tile type, clear designation
designations[tx][ty].bits.dig = DFHack::designation_no; block->tiletype[x][y] = newT;
block->designation[x][y].bits.dig = df::tile_dig_designation::No;
//Check the tile above this one, in case a downward slope needs to be removed. // Check the tile above this one, in case a downward slope needs to be removed.
if ( DFHack::RAMP_TOP == DFHack::tileShape(tilesAbove[tx][ty]) ) if ((above) && (tileShape(above->tiletype[x][y]) == RAMP_TOP))
{ above->tiletype[x][y] = 32; // open space
tilesAbove[tx][ty] = 32; count++;
}
dirty= true;
++count;
} }
// ramp fixer // ramp fixer
else if(DFHack::RAMP!=DFHack::tileShape(oldT) && DFHack::RAMP_TOP == DFHack::tileShape(tilesAbove[tx][ty])) else if ((tileShape(oldT) != RAMP)
&& (above) && (tileShape(above->tiletype[x][y]) == RAMP_TOP))
{ {
tilesAbove[tx][ty] = 32; above->tiletype[x][y] = 32; // open space
countbad++; countbad++;
dirty = true;
}
}
}
//If anything was changed, write it all.
if (dirty)
{
Mapz->WriteDesignations(x,y,z, &designations);
Mapz->WriteTileTypes(x,y,z, &tiles);
if (Mapz->getBlock(x,y,z+1))
{
Mapz->WriteTileTypes(x,y,z+1, &tilesAbove);
} }
dirty = false;
} }
} }
} }
} if (count)
} c->con.print("Found and changed %d tiles.\n", count);
c->Resume(); if (countbad)
if(count) c->con.print("Fixed %d bad down ramps.\n", countbad);
c->con.print("Found and changed %d tiles.\n",count); return CR_OK;
if(countbad) }
c->con.print("Fixed %d bad down ramps.\n",countbad);
DFhackCExport const char * plugin_name ( void )
{
return "deramp";
}
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("deramp",
"De-ramp. All ramps marked for removal are replaced with floors.",
df_deramp));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK; return CR_OK;
} }

@ -17,7 +17,7 @@ static tthread::mutex* mymutex=0;
struct memory_data struct memory_data
{ {
size_t addr; void * addr;
size_t len; size_t len;
size_t refresh; size_t refresh;
int state; int state;
@ -57,7 +57,7 @@ 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(trg[0])) if(ranges[i].isInRange((void *)trg[0]))
return true; return true;
return false; return false;
@ -131,7 +131,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
timeLast = time2; timeLast = time2;
c->p->read(memdata.addr,memdata.len,memdata.buf); c->p->read(memdata.addr,memdata.len,memdata.buf);
outputHex(memdata.buf,memdata.lbuf,memdata.len,memdata.addr,c,memdata.ranges); outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,c,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();
@ -143,7 +143,7 @@ DFhackCExport command_result memview (Core * c, vector <string> & parameters)
{ {
mymutex->lock(); mymutex->lock();
c->p->getMemRanges(memdata.ranges); c->p->getMemRanges(memdata.ranges);
memdata.addr=convert(parameters[0],true); memdata.addr=(void *)convert(parameters[0],true);
if(memdata.addr==0) if(memdata.addr==0)
{ {
Deinit(); Deinit();

@ -19,9 +19,9 @@ using namespace DFHack;
struct t_vecTriplet struct t_vecTriplet
{ {
uint32_t start; void * start;
uint32_t end; void * end;
uint32_t alloc_end; void * alloc_end;
}; };
DFhackCExport command_result df_vectors (Core * c, DFhackCExport command_result df_vectors (Core * c,
@ -74,7 +74,7 @@ static bool mightBeVec(vector<t_memrange> &heap_ranges,
// Vector length might not be a multiple of 4 if, for example, // Vector length might not be a multiple of 4 if, for example,
// it's a vector of uint8_t or uint16_t. However, the actual memory // it's a vector of uint8_t or uint16_t. However, the actual memory
// allocated to the vector should be 4 byte aligned. // allocated to the vector should be 4 byte aligned.
if ((vec->start % 4 != 0) || (vec->alloc_end % 4 != 0)) if (((int)vec->start % 4 != 0) || ((int)vec->alloc_end % 4 != 0))
return false; return false;
for (size_t i = 0; i < heap_ranges.size(); i++) for (size_t i = 0; i < heap_ranges.size(); i++)
@ -88,7 +88,7 @@ static bool mightBeVec(vector<t_memrange> &heap_ranges,
return false; return false;
} }
static bool inAnyRange(vector<t_memrange> &ranges, uint32_t ptr) static bool inAnyRange(vector<t_memrange> &ranges, void * ptr)
{ {
for (size_t i = 0; i < ranges.size(); i++) for (size_t i = 0; i < ranges.size(); i++)
{ {
@ -141,7 +141,7 @@ static void vectorsUsage(Console &con)
static void printVec(Console &con, const char* msg, t_vecTriplet *vec, static void printVec(Console &con, const char* msg, t_vecTriplet *vec,
uint32_t start, uint32_t pos) uint32_t start, uint32_t pos)
{ {
uint32_t length = vec->end - vec->start; uint32_t length = (int)vec->end - (int)vec->start;
uint32_t offset = pos - start; uint32_t offset = pos - start;
con.print("%8s offset %06p, addr %010p, start %010p, length %u\n", con.print("%8s offset %06p, addr %010p, start %010p, length %u\n",
@ -193,15 +193,15 @@ DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters)
{ {
t_memrange &range = heap_ranges[i]; t_memrange &range = heap_ranges[i];
if (!range.isInRange(start)) if (!range.isInRange((void *)start))
continue; continue;
// Found the range containing the start // Found the range containing the start
if (!range.isInRange(end)) if (!range.isInRange((void *)end))
{ {
con.print("Scanning %u bytes would read past end of memory " con.print("Scanning %u bytes would read past end of memory "
"range.\n", bytes); "range.\n", bytes);
uint32_t diff = end - range.end; uint32_t diff = end - (int)range.end;
con.print("Cutting bytes down by %u.\n", diff); con.print("Cutting bytes down by %u.\n", diff);
end = (uint32_t) range.end; end = (uint32_t) range.end;
@ -242,7 +242,7 @@ DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters)
{ {
uint32_t ptr = * ( (uint32_t*) pos); uint32_t ptr = * ( (uint32_t*) pos);
if (inAnyRange(heap_ranges, ptr)) if (inAnyRange(heap_ranges, (void *) ptr))
{ {
t_vecTriplet* vec = (t_vecTriplet*) ptr; t_vecTriplet* vec = (t_vecTriplet*) ptr;
@ -320,7 +320,7 @@ DFhackCExport command_result df_clearvec (Core * c, vector <string> & parameters
continue; continue;
} }
if (!inAnyRange(heap_ranges, addr)) if (!inAnyRange(heap_ranges, (void *) addr))
{ {
con << addr_str << " not in any valid address range." << std::endl; con << addr_str << " not in any valid address range." << std::endl;
continue; continue;
@ -338,7 +338,7 @@ DFhackCExport command_result df_clearvec (Core * c, vector <string> & parameters
addr = * ( (uint32_t*) addr); addr = * ( (uint32_t*) addr);
vec = (t_vecTriplet*) addr; vec = (t_vecTriplet*) addr;
if (inAnyRange(heap_ranges, addr) && mightBeVec(heap_ranges, vec)) if (inAnyRange(heap_ranges, (void *) addr) && mightBeVec(heap_ranges, vec))
{ {
valid = true; valid = true;
ptr = true; ptr = true;

@ -1 +1 @@
Subproject commit 355674a508d72349983455f04791b4481b6c1515 Subproject commit c114ec5f995aec69631187212254309464f82775

@ -1,24 +1,42 @@
// Dry Buckets : Remove all "water" objects from buckets scattered around the fortress // Dry Buckets : Remove all "water" objects from buckets scattered around the fortress
#include <iostream>
#include <iomanip>
#include <sstream>
#include <climits>
#include <vector>
#include <set>
using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <vector>
#include <string>
#include <algorithm>
#include <modules/Items.h>
#include "DataDefs.h"
#include "df/world.h"
#include "df/item.h"
#include "df/builtin_mats.h"
using std::string;
using std::vector;
using namespace DFHack; using namespace DFHack;
DFhackCExport command_result df_drybuckets (Core * c, vector <string> & parameters); using df::global::world;
DFhackCExport command_result df_drybuckets (Core * c, vector <string> & parameters)
{
if (!parameters.empty())
return CR_WRONG_USAGE;
CoreSuspender suspend(c);
int dried_total = 0;
for (int i = 0; i < world->items.all.size(); i++)
{
df::item *item = world->items.all[i];
if ((item->getType() == df::item_type::LIQUID_MISC) && (item->getMaterial() == df::builtin_mats::WATER))
{
item->flags.bits.garbage_colect = 1;
dried_total++;
}
}
if (dried_total)
c->con.print("Done. %d buckets of water marked for emptying.\n", dried_total);
return CR_OK;
}
DFhackCExport const char * plugin_name ( void ) DFhackCExport const char * plugin_name ( void )
{ {
@ -36,41 +54,3 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
{ {
return CR_OK; return CR_OK;
} }
DFhackCExport command_result df_drybuckets (Core * c, vector <string> & parameters)
{
if(parameters.size() > 0)
{
string & p = parameters[0];
if(p == "?" || p == "help")
{
c->con.print("This utility removes all objects of type LIQUID_MISC:NONE and material WATER:NONE - that is, water stored in buckets.\n");
return CR_OK;
}
}
c->Suspend();
DFHack::Items * Items = c->getItems();
vector <df_item *> p_items;
if(!Items->readItemVector(p_items))
{
c->con.printerr("Can't access the item vector.\n");
c->Resume();
return CR_FAILURE;
}
std::size_t numItems = p_items.size();
int dried_total = 0;
for (std::size_t i = 0; i < numItems; i++)
{
df_item *item = p_items[i];
if ((item->getType() == Items::LIQUID_MISC) && (item->getMaterial() == Materials::WATER))
{
item->flags.garbage_colect = 1;
dried_total++;
}
}
c->Resume();
c->con.print("Done. %d buckets of water emptied.\n", dried_total);
return CR_OK;
}

@ -1,21 +1,20 @@
// foo
// vi:expandtab:sw=4
#include <iostream>
#include <vector>
#include <map>
#include <stddef.h>
#include <assert.h>
#include <string.h>
using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <VersionInfo.h>
#include <modules/Units.h> #include "DataDefs.h"
#include "df/ui.h"
#include "df/world.h"
#include "df/unit.h"
using std::string;
using std::vector;
using namespace DFHack; using namespace DFHack;
using df::global::world;
using df::global::ui;
// dfhack interface // dfhack interface
DFhackCExport const char * plugin_name ( void ) DFhackCExport const char * plugin_name ( void )
{ {
@ -33,22 +32,16 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
{ {
if (!enable_fastdwarf) if (!enable_fastdwarf)
return CR_OK; return CR_OK;
df_unit *cre; int32_t race = ui->race_id;
DFHack::Units * cr = c->getUnits(); int32_t civ = ui->civ_id;
static vector <df_unit*> *v = cr->creatures;
uint32_t race = cr->GetDwarfRaceIndex();
uint32_t civ = cr->GetDwarfCivId();
if (!v)
{
c->con.printerr("Unable to locate creature vector. Fastdwarf cancelled.\n");
}
for (unsigned i=0 ; i<v->size() ; ++i) for (int i = 0; i < world->units.all.size(); i++)
{ {
cre = v->at(i); df::unit *unit = world->units.all[i];
if (cre->race == race && cre->civ == civ && cre->job_counter > 0)
cre->job_counter = 0; if (unit->race == race && unit->civ_id == civ && unit->counters.job_counter > 0)
// could also patch the cre->current_job->counter unit->counters.job_counter = 0;
// could also patch the unit->job.current_job->completion_timer
} }
return CR_OK; return CR_OK;
} }
@ -65,7 +58,9 @@ static command_result fastdwarf (Core * c, vector <string> & parameters)
} }
else else
{ {
c->con.print("Makes your minions move at ludicrous speeds.\nActivate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\nCurrent state: %d.\n", enable_fastdwarf); c->con.print("Makes your minions move at ludicrous speeds.\n"
"Activate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\n"
"Current state: %d.\n", enable_fastdwarf);
} }
return CR_OK; return CR_OK;

@ -6,12 +6,12 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Maps.h> #include "modules/Maps.h"
#include <modules/MapCache.h> #include "modules/MapCache.h"
#include <modules/Gui.h> #include "modules/Gui.h"
using std::stack; using std::stack;
using MapExtras::MapCache; using MapExtras::MapCache;
using namespace DFHack; using namespace DFHack;

@ -1,26 +1,22 @@
// I'll fix his little red wagon... // I'll fix his little red wagon...
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <DataDefs.h> #include "DataDefs.h"
#include <df/world.h> #include "df/world.h"
#include <df/historical_entity.h> #include "df/historical_entity.h"
#include <df/entity_raw.h> #include "df/entity_raw.h"
#include <df/creature_raw.h> #include "df/creature_raw.h"
#include <df/caste_raw.h> #include "df/caste_raw.h"
using std::string; using std::string;
using std::vector; using std::vector;
using namespace DFHack; using namespace DFHack;
using df::global::world; using df::global::world;
using df::historical_entity;
using df::entity_raw_flags;
using df::creature_raw;
using df::creature_raw_flags;
command_result df_fixwagons (Core *c, vector<string> &parameters) command_result df_fixwagons (Core *c, vector<string> &parameters)
{ {
@ -29,11 +25,11 @@ command_result df_fixwagons (Core *c, vector<string> &parameters)
CoreSuspender suspend(c); CoreSuspender suspend(c);
int32_t wagon_creature = -1, wagon_puller_creature = -1; int32_t wagon_creature = -1, wagon_puller_creature = -1;
creature_raw *wagon, *wagon_puller; df::creature_raw *wagon, *wagon_puller;
for (int i = 0; i < world->raws.creatures.all.size(); i++) for (int i = 0; i < world->raws.creatures.all.size(); i++)
{ {
creature_raw *cr = world->raws.creatures.all[i]; df::creature_raw *cr = world->raws.creatures.all[i];
if (cr->flags.is_set(creature_raw_flags::EQUIPMENT_WAGON) && (wagon_creature == -1)) if (cr->flags.is_set(df::creature_raw_flags::EQUIPMENT_WAGON) && (wagon_creature == -1))
{ {
wagon = cr; wagon = cr;
wagon_creature = i; wagon_creature = i;
@ -58,8 +54,8 @@ command_result df_fixwagons (Core *c, vector<string> &parameters)
for (int i = 0; i < world->entities.all.size(); i++) for (int i = 0; i < world->entities.all.size(); i++)
{ {
bool updated = false; bool updated = false;
historical_entity *ent = world->entities.all[i]; df::historical_entity *ent = world->entities.all[i];
if (!ent->entity_raw->flags.is_set(entity_raw_flags::COMMON_DOMESTIC_PULL)) if (!ent->entity_raw->flags.is_set(df::entity_raw_flags::COMMON_DOMESTIC_PULL))
continue; continue;
if (ent->resources.animals.wagon_races.size() == 0) if (ent->resources.animals.wagon_races.size() == 0)
{ {

@ -1,19 +1,59 @@
// This tool counts static tiles and active flows of water and magma. // This tool counts static tiles and active flows of water and magma.
#include <iostream>
#include <vector>
#include <map>
#include <stddef.h>
#include <string.h>
using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Maps.h>
#include "DataDefs.h"
#include "df/world.h"
#include "df/map_block.h"
#include "df/tile_liquid.h"
using std::string;
using std::vector;
using namespace DFHack; using namespace DFHack;
DFhackCExport command_result df_flows (Core * c, vector <string> & parameters); using df::global::world;
DFhackCExport command_result df_flows (Core * c, vector <string> & parameters)
{
CoreSuspender suspend(c);
int flow1 = 0, flow2 = 0, flowboth = 0, water = 0, magma = 0;
c->con.print("Counting flows and liquids ...\n");
for (int i = 0; i < world->map.map_blocks.size(); i++)
{
df::map_block *cur = world->map.map_blocks[i];
if (cur->flags.is_set(df::block_flags::UpdateLiquid))
flow1++;
if (cur->flags.is_set(df::block_flags::UpdateLiquidTwice))
flow2++;
if (cur->flags.is_set(df::block_flags::UpdateLiquid) && cur->flags.is_set(df::block_flags::UpdateLiquidTwice))
flowboth++;
for (int x = 0; x < 16; x++)
{
for (int y = 0; y < 16; y++)
{
// only count tiles with actual liquid in them
if (cur->designation[x][y].bits.flow_size == 0)
continue;
if (cur->designation[x][y].bits.liquid_type == df::tile_liquid::Magma)
magma++;
if (cur->designation[x][y].bits.liquid_type == df::tile_liquid::Water)
water++;
}
}
}
c->con.print("Blocks with liquid_1=true: %d\n", flow1);
c->con.print("Blocks with liquid_2=true: %d\n", flow2);
c->con.print("Blocks with both: %d\n", flowboth);
c->con.print("Water tiles: %d\n", water);
c->con.print("Magma tiles: %d\n", magma);
return CR_OK;
}
DFhackCExport const char * plugin_name ( void ) DFhackCExport const char * plugin_name ( void )
{ {
@ -33,61 +73,3 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
{ {
return CR_OK; return CR_OK;
} }
DFhackCExport command_result df_flows (Core * c, vector <string> & parameters)
{
uint32_t x_max,y_max,z_max;
DFHack::designations40d designations;
DFHack::Maps *Maps;
c->Suspend();
Maps = c->getMaps();
// init the map
if(!Maps->Start())
{
c->con.printerr("Can't init map.\n");
c->Resume();
return CR_FAILURE;
}
DFHack::t_blockflags bflags;
Maps->getSize(x_max,y_max,z_max);
// walk the map, count flowing tiles, magma, water
uint32_t flow1=0, flow2=0, flowboth=0, water=0, magma=0;
c->con.print("Counting flows and liquids ...\n");
for(uint32_t x = 0; x< x_max;x++)
{
for(uint32_t y = 0; y< y_max;y++)
{
for(uint32_t z = 0; z< z_max;z++)
{
if(Maps->getBlock(x,y,z))
{
Maps->ReadBlockFlags(x, y, z, bflags);
Maps->ReadDesignations(x, y, z, &designations);
if (bflags.bits.liquid_1)
flow1++;
if (bflags.bits.liquid_2)
flow2++;
if (bflags.bits.liquid_1 && bflags.bits.liquid_2)
flowboth++;
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
if (designations[i][j].bits.liquid_type == DFHack::liquid_magma)
magma++;
if (designations[i][j].bits.liquid_type == DFHack::liquid_water)
water++;
}
}
}
}
}
c->con.print("Blocks with liquid_1=true: %d\n"
"Blocks with liquid_2=true: %d\n"
"Blocks with both: %d\n"
"Water tiles: %d\n"
"Magma tiles: %d\n"
,flow1, flow2, flowboth, water, magma
);
c->Resume();
return CR_OK;
}

@ -1,56 +1,34 @@
// Designate all matching plants for gathering/cutting // Designate all matching plants for gathering/cutting
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <stddef.h>
#include <assert.h>
#include <string.h>
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Maps.h>
#include <modules/Materials.h> #include "DataDefs.h"
#include <modules/Vegetation.h> #include "TileTypes.h"
#include <TileTypes.h> #include "df/world.h"
#include "df/map_block.h"
#include "df/tile_dig_designation.h"
#include "df/plant_raw.h"
#include "modules/Vegetation.h"
#include <set>
using namespace std; using std::string;
using std::vector;
using std::set;
using namespace DFHack; using namespace DFHack;
DFhackCExport command_result df_getplants (Core * c, vector <string> & parameters); using df::global::world;
DFhackCExport const char * plugin_name ( void )
{
return "getplants";
}
DFhackCExport command_result plugin_init ( Core * c, vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("getplants", "Cut down all of the specified trees or gather all of the specified shrubs", df_getplants));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}
DFhackCExport command_result df_getplants (Core * c, vector <string> & parameters) DFhackCExport command_result df_getplants (Core * c, vector <string> & parameters)
{ {
uint32_t x_max,y_max,z_max;
designations40d designations;
tiletypes40d tiles;
t_blockflags blockflags;
string plantMatStr = ""; string plantMatStr = "";
set<int> plantIDs; set<int> plantIDs;
set<string> plantNames; set<string> plantNames;
bool deselect = false, exclude = false, treesonly = false, shrubsonly = false; bool deselect = false, exclude = false, treesonly = false, shrubsonly = false;
bool dirty = false;
int count = 0; int count = 0;
for (size_t i = 0; i < parameters.size(); i++) for (size_t i = 0; i < parameters.size(); i++)
{ {
@ -77,16 +55,16 @@ DFhackCExport command_result df_getplants (Core * c, vector <string> & parameter
exclude = true; exclude = true;
else plantNames.insert(parameters[i]); else plantNames.insert(parameters[i]);
} }
c->Suspend();
Materials *mats = c->getMaterials(); CoreSuspender suspend(c);
for (vector<df_plant_type *>::const_iterator it = mats->df_organic->begin(); it != mats->df_organic->end(); it++)
for (int i = 0; i < world->raws.plants.all.size(); i++)
{ {
df_plant_type &plant = **it; df::plant_raw *plant = world->raws.plants.all[i];
if (plantNames.find(plant.ID) != plantNames.end()) if (plantNames.find(plant->id) != plantNames.end())
{ {
plantNames.erase(plant.ID); plantNames.erase(plant->id);
plantIDs.insert(it - mats->df_organic->begin()); plantIDs.insert(i);
} }
} }
if (plantNames.size() > 0) if (plantNames.size() > 0)
@ -95,58 +73,33 @@ DFhackCExport command_result df_getplants (Core * c, vector <string> & parameter
for (set<string>::const_iterator it = plantNames.begin(); it != plantNames.end(); it++) for (set<string>::const_iterator it = plantNames.begin(); it != plantNames.end(); it++)
c->con.printerr(" %s", it->c_str()); c->con.printerr(" %s", it->c_str());
c->con.printerr("\n"); c->con.printerr("\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
if (plantIDs.size() == 0) if (plantIDs.size() == 0)
{ {
c->con.print("Valid plant IDs:\n"); c->con.print("Valid plant IDs:\n");
for (vector<df_plant_type *>::const_iterator it = mats->df_organic->begin(); it != mats->df_organic->end(); it++) for (int i = 0; i < world->raws.plants.all.size(); i++)
{ {
df_plant_type &plant = **it; df::plant_raw *plant = world->raws.plants.all[i];
if (plant.flags.is_set(PLANT_GRASS)) if (plant->flags.is_set(df::plant_raw_flags::GRASS))
continue; continue;
c->con.print("* (%s) %s - %s\n", plant.flags.is_set(PLANT_TREE) ? "tree" : "shrub", plant.ID.c_str(), plant.name.c_str()); c->con.print("* (%s) %s - %s\n", plant->flags.is_set(df::plant_raw_flags::TREE) ? "tree" : "shrub", plant->id.c_str(), plant->name.c_str());
} }
c->Resume();
return CR_OK; return CR_OK;
} }
Maps *maps = c->getMaps(); count = 0;
for (int i = 0; i < world->map.map_blocks.size(); i++)
// init the map
if (!maps->Start())
{
c->con.printerr("Can't init map.\n");
c->Resume();
return CR_FAILURE;
}
maps->getSize(x_max,y_max,z_max);
// walk the map
for (uint32_t x = 0; x < x_max; x++)
{
for (uint32_t y = 0; y < y_max; y++)
{
for (uint32_t z = 0; z < z_max; z++)
{ {
if (maps->getBlock(x,y,z)) df::map_block *cur = world->map.map_blocks[i];
{ bool dirty = false;
dirty = false; for (int j = 0; j < cur->plants.size(); j++)
maps->ReadDesignations(x,y,z, &designations);
maps->ReadTileTypes(x,y,z, &tiles);
maps->ReadBlockFlags(x,y,z, blockflags);
vector<df_plant *> *plants;
if (maps->ReadVegetation(x, y, z, plants))
{
for (vector<df_plant *>::const_iterator it = plants->begin(); it != plants->end(); it++)
{ {
const df_plant &plant = **it; const df_plant *plant = (df_plant *)cur->plants[i];
uint32_t tx = plant.x % 16; int x = plant->x % 16;
uint32_t ty = plant.y % 16; int y = plant->y % 16;
if (plantIDs.find(plant.material) != plantIDs.end()) if (plantIDs.find(plant->material) != plantIDs.end())
{ {
if (exclude) if (exclude)
continue; continue;
@ -156,42 +109,47 @@ DFhackCExport command_result df_getplants (Core * c, vector <string> & parameter
if (!exclude) if (!exclude)
continue; continue;
} }
TileShape shape = tileShape(cur->tiletype[x][y]);
TileShape shape = tileShape(tiles[tx][ty]); if (plant->is_shrub && (treesonly || shape != SHRUB_OK))
if (plant.is_shrub && (treesonly || shape != SHRUB_OK))
continue; continue;
if (!plant.is_shrub && (shrubsonly || (shape != TREE_OK && shape != TREE_DEAD))) if (!plant->is_shrub && (shrubsonly || (shape != TREE_OK && shape != TREE_DEAD)))
continue; continue;
if (designations[tx][ty].bits.hidden) if (cur->designation[x][y].bits.hidden)
continue; continue;
if (deselect && designations[tx][ty].bits.dig != designation_no) if (deselect && cur->designation[x][y].bits.dig != df::tile_dig_designation::No)
{ {
designations[tx][ty].bits.dig = designation_no; cur->designation[x][y].bits.dig = df::tile_dig_designation::No;
dirty = true; dirty = true;
++count; ++count;
} }
if (!deselect && designations[tx][ty].bits.dig != designation_default) if (!deselect && cur->designation[x][y].bits.dig != df::tile_dig_designation::Default)
{ {
designations[tx][ty].bits.dig = designation_default; cur->designation[x][y].bits.dig = df::tile_dig_designation::Default;
dirty = true; dirty = true;
++count; ++count;
} }
} }
}
// If anything was changed, write it all.
if (dirty) if (dirty)
{ cur->flags.set(df::block_flags::Designated);
blockflags.bits.designated = 1;
maps->WriteDesignations(x,y,z, &designations);
maps->WriteBlockFlags(x,y,z, blockflags);
dirty = false;
} }
}
}
}
}
c->Resume();
if (count) if (count)
c->con.print("Updated %d plant designations.\n", count); c->con.print("Updated %d plant designations.\n", count);
return CR_OK; return CR_OK;
} }
DFhackCExport const char * plugin_name ( void )
{
return "getplants";
}
DFhackCExport command_result plugin_init ( Core * c, vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("getplants", "Cut down all of the specified trees or gather all of the specified shrubs", df_getplants));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}

@ -1,10 +1,10 @@
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <DataDefs.h> #include "DataDefs.h"
#include <df/d_init.h> #include "df/d_init.h"
using std::vector; using std::vector;
using std::string; using std::string;
@ -51,10 +51,7 @@ DFhackCExport command_result twaterlvl(Core * c, vector <string> & parameters)
DFhackCExport command_result tidlers(Core * c, vector <string> & parameters) DFhackCExport command_result tidlers(Core * c, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
df::d_init_idlers iv = df::d_init_idlers(int(d_init->idlers) + 1); d_init->idlers = ENUM_NEXT_ITEM(d_init_idlers, d_init->idlers);
if (!d_init_idlers::is_valid(iv)) c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, d_init->idlers) << endl;
iv = ENUM_FIRST_ITEM(d_init_idlers);
d_init->idlers = iv;
c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, iv) << endl;
return CR_OK; return CR_OK;
} }

@ -0,0 +1,416 @@
#include "Core.h"
#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "MiscUtils.h"
#include "modules/Materials.h"
#include "modules/Items.h"
#include "modules/Gui.h"
#include "modules/Job.h"
#include "DataDefs.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/ui_build_selector.h"
#include "df/ui_build_item_req.h"
#include "df/build_req_choice_genst.h"
#include "df/build_req_choice_specst.h"
#include "df/building_workshopst.h"
#include "df/building_furnacest.h"
#include "df/job.h"
#include "df/job_item.h"
#include "df/job_list_link.h"
#include "df/item.h"
#include "df/tool_uses.h"
#include "df/general_ref.h"
using std::vector;
using std::string;
using std::endl;
using namespace DFHack;
using namespace df::enums;
using df::global::world;
using df::global::ui;
using df::global::ui_build_selector;
using df::global::ui_workshop_job_cursor;
using df::global::job_next_id;
/* Plugin registration */
static bool job_material_hotkey(Core *c, df::viewscreen *top);
static command_result job_material(Core *c, vector <string> & parameters);
static command_result job_duplicate(Core *c, vector <string> & parameters);
static command_result job_cmd(Core *c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void )
{
return "jobutils";
}
DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &commands)
{
commands.clear();
if (!world || !ui)
return CR_FAILURE;
commands.push_back(
PluginCommand(
"job", "General job query and manipulation.",
job_cmd, false,
" job [query]\n"
" Print details of the current job.\n"
" job list\n"
" Print details of all jobs in the workshop.\n"
" job item-material <item-idx> <material[:subtoken]>\n"
" Replace the exact material id in the job item.\n"
" job item-type <item-idx> <type[:subtype]>\n"
" Replace the exact item type id in the job item.\n"
)
);
if (ui_workshop_job_cursor || ui_build_selector) {
commands.push_back(
PluginCommand(
"job-material", "Alter the material of the selected job.",
job_material, job_material_hotkey,
" job-material <inorganic-token>\n"
"Intended to be used as a keybinding:\n"
" - In 'q' mode, when a job is highlighted within a workshop\n"
" or furnace, changes the material of the job.\n"
" - In 'b' mode, during selection of building components\n"
" positions the cursor over the first available choice\n"
" with the matching material.\n"
)
);
}
if (ui_workshop_job_cursor && job_next_id) {
commands.push_back(
PluginCommand(
"job-duplicate", "Duplicate the selected job in a workshop.",
job_duplicate, workshop_job_hotkey,
" - In 'q' mode, when a job is highlighted within a workshop\n"
" or furnace building, instantly duplicates the job.\n"
)
);
}
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}
/* UI state guards */
static bool job_material_hotkey(Core *c, df::viewscreen *top)
{
return workshop_job_hotkey(c, top) ||
build_selector_hotkey(c, top);
}
/* job-material implementation */
static command_result job_material_in_job(Core *c, MaterialInfo &new_mat)
{
df::job *job = getSelectedWorkshopJob(c);
if (!job)
return CR_FAILURE;
if (!new_mat.isValid() || new_mat.type != 0)
{
c->con.printerr("New job material isn't inorganic: %s\n",
new_mat.toString().c_str());
return CR_FAILURE;
}
MaterialInfo cur_mat(job);
if (!cur_mat.isValid() || cur_mat.type != 0)
{
c->con.printerr("Current job material isn't inorganic: %s\n",
cur_mat.toString().c_str());
return CR_FAILURE;
}
df::craft_material_class old_class = cur_mat.getCraftClass();
if (old_class == craft_material_class::None)
{
c->con.printerr("Unexpected current material type: %s\n",
cur_mat.toString().c_str());
return CR_FAILURE;
}
if (new_mat.getCraftClass() != old_class)
{
c->con.printerr("New material %s does not satisfy requirement: %s\n",
new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class));
return CR_FAILURE;
}
for (unsigned i = 0; i < job->job_items.size(); i++)
{
df::job_item *item = job->job_items[i];
MaterialInfo item_mat(item);
if (item_mat != cur_mat)
{
c->con.printerr("Job item %d has different material: %s\n",
i, item_mat.toString().c_str());
return CR_FAILURE;
}
if (!new_mat.matches(*item))
{
c->con.printerr("Job item %d requirements not satisfied by %s.\n",
i, new_mat.toString().c_str());
return CR_FAILURE;
}
}
// Apply the substitution
job->mat_type = new_mat.type;
job->mat_index = new_mat.index;
for (unsigned i = 0; i < job->job_items.size(); i++)
{
df::job_item *item = job->job_items[i];
item->mat_type = new_mat.type;
item->mat_index = new_mat.index;
}
c->con << "Applied material '" << new_mat.toString()
<< "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl;
return CR_OK;
}
static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choicest *choice,
MaterialInfo &new_mat, bool ignore_select)
{
if (VIRTUAL_CAST_VAR(gen, df::build_req_choice_genst, choice))
{
if (gen->mat_type == new_mat.type &&
gen->mat_index == new_mat.index &&
(ignore_select || gen->used_count < gen->candidates.size()))
{
return true;
}
}
else if (VIRTUAL_CAST_VAR(spec, df::build_req_choice_specst, choice))
{
if (spec->candidate &&
spec->candidate->getActualMaterial() == new_mat.type &&
spec->candidate->getActualMaterialIndex() == new_mat.index &&
(ignore_select || !req->candidate_selected[spec->candidate_id]))
{
return true;
}
}
return false;
}
static command_result job_material_in_build(Core *c, MaterialInfo &new_mat)
{
df::ui_build_selector *sel = ui_build_selector;
df::ui_build_item_req *req = sel->requirements[ui_build_selector->req_index];
// Loop through matching choices
bool matches = build_choice_matches(req, sel->choices[sel->sel_index], new_mat, true);
int size = sel->choices.size();
int base = (matches ? sel->sel_index + 1 : 0);
for (unsigned i = 0; i < size; i++)
{
int idx = (base + i) % size;
if (build_choice_matches(req, sel->choices[idx], new_mat, false))
{
sel->sel_index = idx;
return CR_OK;
}
}
c->con.printerr("Could not find material in list: %s\n", new_mat.toString().c_str());
return CR_FAILURE;
}
static command_result job_material(Core * c, vector <string> & parameters)
{
// HOTKEY COMMAND: CORE ALREADY SUSPENDED
MaterialInfo new_mat;
if (parameters.size() == 1)
{
if (!new_mat.find(parameters[0])) {
c->con.printerr("Could not find material: %s\n", parameters[0].c_str());
return CR_WRONG_USAGE;
}
}
else
return CR_WRONG_USAGE;
if (ui->main.mode == ui_sidebar_mode::QueryBuilding)
return job_material_in_job(c, new_mat);
if (ui->main.mode == ui_sidebar_mode::Build)
return job_material_in_build(c, new_mat);
return CR_WRONG_USAGE;
}
/* job-duplicate implementation */
static command_result job_duplicate(Core * c, vector <string> & parameters)
{
if (!parameters.empty())
return CR_WRONG_USAGE;
df::job *job = getSelectedWorkshopJob(c);
if (!job)
return CR_FAILURE;
if (!job->misc_links.empty() ||
(job->job_items.empty() &&
job->job_type != job_type::CollectSand &&
job->job_type != job_type::CollectClay))
{
c->con.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type));
return CR_FAILURE;
}
df::building *building = world->selected_building;
if (building->jobs.size() >= 10)
{
c->con.printerr("Job list is already full.\n");
return CR_FAILURE;
}
// Actually clone
df::job *pnew = cloneJobStruct(job);
linkJobIntoWorld(pnew);
vector_insert_at(building->jobs, ++*ui_workshop_job_cursor, pnew);
return CR_OK;
}
/* Main job command implementation */
static df::job_item *getJobItem(Core *c, df::job *job, std::string idx)
{
if (!job)
return NULL;
int v = atoi(idx.c_str());
if (v < 1 || v > job->job_items.size()) {
c->con.printerr("Invalid item index.\n");
return NULL;
}
return job->job_items[v-1];
}
static command_result job_cmd(Core * c, vector <string> & parameters)
{
CoreSuspender suspend(c);
std::string cmd = (parameters.empty() ? "query" : parameters[0]);
if (cmd == "query" || cmd == "list")
{
df::job *job = getSelectedWorkshopJob(c);
if (!job)
return CR_WRONG_USAGE;
if (cmd == "query") {
printJobDetails(c, job);
} else {
df::building *selected = world->selected_building;
for (unsigned i = 0; i < selected->jobs.size(); i++)
printJobDetails(c, selected->jobs[i]);
}
}
else if (cmd == "item-material")
{
if (parameters.size() != 3)
return CR_WRONG_USAGE;
df::job *job = getSelectedWorkshopJob(c);
df::job_item *item = getJobItem(c, job, parameters[1]);
if (!item)
return CR_WRONG_USAGE;
ItemTypeInfo iinfo(item);
MaterialInfo minfo;
if (!minfo.find(parameters[2])) {
c->con.printerr("Could not find the specified material.\n");
return CR_FAILURE;
}
if (minfo.isValid() && !iinfo.matches(*item, &minfo)) {
c->con.printerr("Material does not match the requirements.\n");
printJobDetails(c, job);
return CR_FAILURE;
}
if (job->mat_type != -1 &&
job->mat_type == item->mat_type &&
job->mat_index == item->mat_index)
{
job->mat_type = minfo.type;
job->mat_index = minfo.index;
}
item->mat_type = minfo.type;
item->mat_index = minfo.index;
c->con << "Job item updated." << endl;
if (item->item_type < 0 && minfo.isValid())
c->con.printerr("WARNING: Due to a probable bug, creature & plant material subtype\n"
" is ignored unless the item type is also specified.\n");
printJobDetails(c, job);
return CR_OK;
}
else if (cmd == "item-type")
{
if (parameters.size() != 3)
return CR_WRONG_USAGE;
df::job *job = getSelectedWorkshopJob(c);
df::job_item *item = getJobItem(c, job, parameters[1]);
if (!item)
return CR_WRONG_USAGE;
ItemTypeInfo iinfo;
MaterialInfo minfo(item);
if (!iinfo.find(parameters[2])) {
c->con.printerr("Could not find the specified item type.\n");
return CR_FAILURE;
}
if (iinfo.isValid() && !iinfo.matches(*item, &minfo)) {
c->con.printerr("Item type does not match the requirements.\n");
printJobDetails(c, job);
return CR_FAILURE;
}
item->item_type = iinfo.type;
item->item_subtype = iinfo.subtype;
c->con << "Job item updated." << endl;
printJobDetails(c, job);
return CR_OK;
}
else
return CR_WRONG_USAGE;
return CR_OK;
}

@ -11,14 +11,14 @@ using std::endl;
using std::set; using std::set;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Vegetation.h> #include "modules/Vegetation.h"
#include <modules/Maps.h> #include "modules/Maps.h"
#include <modules/Gui.h> #include "modules/Gui.h"
#include <TileTypes.h> #include "TileTypes.h"
#include <modules/MapCache.h> #include "modules/MapCache.h"
using namespace MapExtras; using namespace MapExtras;
using namespace DFHack; using namespace DFHack;

@ -2,12 +2,12 @@
using namespace std; using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <vector> #include <vector>
#include <string> #include <string>
#include <modules/World.h> #include "modules/World.h"
#include <stdlib.h> #include <stdlib.h>
using namespace DFHack; using namespace DFHack;
@ -166,7 +166,7 @@ DFhackCExport command_result mode (Core * c, vector <string> & parameters)
c->Suspend(); c->Suspend();
world->WriteGameMode(gm); world->WriteGameMode(gm);
c->Resume(); c->Resume();
cout << endl; c->con << endl;
} }
return CR_OK; return CR_OK;
} }

@ -6,14 +6,14 @@
#include <string> #include <string>
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Vegetation.h> #include "modules/Vegetation.h"
#include <modules/Maps.h> #include "modules/Maps.h"
#include <modules/Gui.h> #include "modules/Gui.h"
#include <TileTypes.h> #include "TileTypes.h"
#include <modules/MapCache.h> #include "modules/MapCache.h"
using std::vector; using std::vector;
using std::string; using std::string;

@ -4,23 +4,22 @@
#include <iomanip> #include <iomanip>
#include <climits> #include <climits>
#include <vector> #include <vector>
#include <string>
#include <sstream> #include <sstream>
#include <ctime> #include <ctime>
#include <cstdio> #include <cstdio>
using namespace std; using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <vector> #include "modules/Units.h"
#include <string> #include "modules/Maps.h"
#include <modules/Units.h> #include "modules/Gui.h"
#include <modules/Maps.h> #include "modules/Materials.h"
#include <modules/Gui.h> #include "modules/MapCache.h"
#include <modules/Materials.h> #include "MiscUtils.h"
#include <modules/MapCache.h>
#include <MiscUtils.h>
using std::vector; using std::vector;
using std::string; using std::string;
@ -54,7 +53,6 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
DFhackCExport command_result df_cprobe (Core * c, vector <string> & parameters) DFhackCExport command_result df_cprobe (Core * c, vector <string> & parameters)
{ {
Console & con = c->con; Console & con = c->con;
BEGIN_PROBE:
c->Suspend(); c->Suspend();
DFHack::Gui *Gui = c->getGui(); DFHack::Gui *Gui = c->getGui();
DFHack::Units * cr = c->getUnits(); DFHack::Units * cr = c->getUnits();
@ -135,7 +133,7 @@ DFhackCExport command_result df_probe (Core * c, vector <string> & parameters)
MapExtras::Block * b = mc.BlockAt(cursor/16); MapExtras::Block * b = mc.BlockAt(cursor/16);
mapblock40d & block = b->raw; mapblock40d & block = b->raw;
if(b) if(b && b->valid)
{ {
con.print("block addr: 0x%x\n\n", block.origin); con.print("block addr: 0x%x\n\n", block.origin);
/* /*
@ -285,6 +283,10 @@ DFhackCExport command_result df_probe (Core * c, vector <string> & parameters)
con << "mystery: " << block.mystery << endl; con << "mystery: " << block.mystery << endl;
con << std::endl; con << std::endl;
} }
else
{
con.printerr("No data.\n");
}
} }
} }
c->Resume(); c->Resume();

@ -13,11 +13,14 @@
#include <vector> #include <vector>
using namespace std; using namespace std;
#include <DFHack.h>
#include <modules/MapCache.h>
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <PluginManager.h> #include "Export.h"
#include "PluginManager.h"
#include "modules/MapCache.h"
#include "DataDefs.h"
#include "df/world.h"
using namespace DFHack; using namespace DFHack;
@ -85,10 +88,30 @@ struct compare_pair_second
} }
}; };
static void printMatdata(DFHack::Console & con, const matdata &data)
{
con << std::setw(9) << data.count;
if(data.lower_z != data.upper_z)
con <<" Z:" << std::setw(4) << data.lower_z << ".." << data.upper_z << std::endl;
else
con <<" Z:" << std::setw(4) << data.lower_z << std::endl;
}
static int getValue(const df_inorganic_type &info)
{
return info.mat.MATERIAL_VALUE;
}
static int getValue(const df_plant_type &info)
{
return info.value;
}
// printMats() accepts a vector of pointers to t_matgloss so that it can // printMats() accepts a vector of pointers to t_matgloss so that it can
// deal t_matgloss and all subclasses. // deal t_matgloss and all subclasses.
template <typename T> template <typename T>
void printMats(DFHack::Console & con, MatMap &mat, std::vector<T*> &materials) void printMats(DFHack::Console & con, MatMap &mat, std::vector<T*> &materials, bool show_value)
{ {
unsigned int total = 0; unsigned int total = 0;
MatSorter sorting_vector; MatSorter sorting_vector;
@ -108,12 +131,10 @@ void printMats(DFHack::Console & con, MatMap &mat, std::vector<T*> &materials)
continue; continue;
} }
T* mat = materials[it->first]; T* mat = materials[it->first];
con << std::setw(25) << mat->ID << " : " con << std::setw(25) << mat->ID << " : ";
<< std::setw(9) << it->second.count; if (show_value)
if(it->second.lower_z != it->second.upper_z) con << std::setw(3) << getValue(*mat) << " : ";
con <<" Z:" << std::setw(4) << it->second.lower_z << ".." << it->second.upper_z << std::endl; printMatdata(con, it->second);
else
con <<" Z:" << std::setw(4) << it->second.lower_z << std::endl;
total += it->second.count; total += it->second.count;
} }
@ -121,7 +142,7 @@ void printMats(DFHack::Console & con, MatMap &mat, std::vector<T*> &materials)
} }
void printVeins(DFHack::Console & con, MatMap &mat_map, void printVeins(DFHack::Console & con, MatMap &mat_map,
DFHack::Materials* mats) DFHack::Materials* mats, bool show_value)
{ {
MatMap ores; MatMap ores;
MatMap gems; MatMap gems;
@ -140,13 +161,13 @@ void printVeins(DFHack::Console & con, MatMap &mat_map,
} }
con << "Ores:" << std::endl; con << "Ores:" << std::endl;
printMats(con, ores, *mats->df_inorganic); printMats(con, ores, *mats->df_inorganic, show_value);
con << "Gems:" << std::endl; con << "Gems:" << std::endl;
printMats(con, gems, *mats->df_inorganic); printMats(con, gems, *mats->df_inorganic, show_value);
con << "Other vein stone:" << std::endl; con << "Other vein stone:" << std::endl;
printMats(con, rest, *mats->df_inorganic); printMats(con, rest, *mats->df_inorganic, show_value);
} }
DFhackCExport command_result prospector (Core * c, vector <string> & parameters); DFhackCExport command_result prospector (Core * c, vector <string> & parameters);
@ -174,13 +195,18 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
bool showPlants = true; bool showPlants = true;
bool showSlade = true; bool showSlade = true;
bool showTemple = true; bool showTemple = true;
bool showValue = false;
Console & con = c->con; Console & con = c->con;
for(int i = 0; i < parameters.size();i++) for(int i = 0; i < parameters.size();i++)
{ {
if (parameters[0] == "all") if (parameters[i] == "all")
{ {
showHidden = true; showHidden = true;
} }
if (parameters[i] == "value")
{
showValue = true;
}
else if(parameters[i] == "help" || parameters[i] == "?") else if(parameters[i] == "help" || parameters[i] == "?")
{ {
c->con.print("Prints a big list of all the present minerals.\n" c->con.print("Prints a big list of all the present minerals.\n"
@ -188,6 +214,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
"\n" "\n"
"Options:\n" "Options:\n"
"all - Scan the whole map, as if it was revealed.\n" "all - Scan the whole map, as if it was revealed.\n"
"value - Show material value in the output.\n"
); );
return CR_OK; return CR_OK;
} }
@ -231,6 +258,10 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
MatMap plantMats; MatMap plantMats;
MatMap treeMats; MatMap treeMats;
matdata liquidWater;
matdata liquidMagma;
matdata aquiferTiles;
if (!(showSlade && maps->ReadGlobalFeatures(globalFeatures))) if (!(showSlade && maps->ReadGlobalFeatures(globalFeatures)))
{ {
con.printerr("Unable to read global features; slade won't be listed!\n"); con.printerr("Unable to read global features; slade won't be listed!\n");
@ -282,6 +313,8 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
} }
} }
int global_z = df::global::world->map.region_z + z;
// Iterate over all the tiles in the block // Iterate over all the tiles in the block
for(uint32_t y = 0; y < 16; y++) for(uint32_t y = 0; y < 16; y++)
{ {
@ -301,6 +334,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
if (des.bits.water_table) if (des.bits.water_table)
{ {
hasAquifer = true; hasAquifer = true;
aquiferTiles.add(global_z);
} }
// Check for lairs // Check for lairs
@ -309,6 +343,15 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
hasLair = true; hasLair = true;
} }
// Check for liquid
if (des.bits.flow_size)
{
if (des.bits.liquid_type == liquid_magma)
liquidMagma.add(global_z);
else
liquidWater.add(global_z);
}
uint16_t type = b->TileTypeAt(coord); uint16_t type = b->TileTypeAt(coord);
const DFHack::TileRow *info = DFHack::getTileRow(type); const DFHack::TileRow *info = DFHack::getTileRow(type);
@ -330,17 +373,17 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
} }
// Count the material type // Count the material type
baseMats[info->material].add(z); baseMats[info->material].add(global_z);
// Find the type of the tile // Find the type of the tile
switch (info->material) switch (info->material)
{ {
case DFHack::SOIL: case DFHack::SOIL:
case DFHack::STONE: case DFHack::STONE:
layerMats[b->baseMaterialAt(coord)].add(z); layerMats[b->baseMaterialAt(coord)].add(global_z);
break; break;
case DFHack::VEIN: case DFHack::VEIN:
veinMats[b->veinMaterialAt(coord)].add(z); veinMats[b->veinMaterialAt(coord)].add(global_z);
break; break;
case DFHack::FEATSTONE: case DFHack::FEATSTONE:
if (blockFeatureLocal && des.bits.feature_local) if (blockFeatureLocal && des.bits.feature_local)
@ -348,7 +391,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
if (blockFeatureLocal->type == DFHack::feature_Adamantine_Tube if (blockFeatureLocal->type == DFHack::feature_Adamantine_Tube
&& blockFeatureLocal->main_material == 0) // stone && blockFeatureLocal->main_material == 0) // stone
{ {
veinMats[blockFeatureLocal->sub_material].add(z); veinMats[blockFeatureLocal->sub_material].add(global_z);
} }
else if (showTemple else if (showTemple
&& blockFeatureLocal->type == DFHack::feature_Hell_Temple) && blockFeatureLocal->type == DFHack::feature_Hell_Temple)
@ -361,7 +404,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
&& blockFeatureGlobal->type == DFHack::feature_Underworld && blockFeatureGlobal->type == DFHack::feature_Underworld
&& blockFeatureGlobal->main_material == 0) // stone && blockFeatureGlobal->main_material == 0) // stone
{ {
layerMats[blockFeatureGlobal->sub_material].add(z); layerMats[blockFeatureGlobal->sub_material].add(global_z);
} }
break; break;
case DFHack::OBSIDIAN: case DFHack::OBSIDIAN:
@ -386,9 +429,9 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
if (showHidden || !b->DesignationAt(loc).bits.hidden) if (showHidden || !b->DesignationAt(loc).bits.hidden)
{ {
if(plant.is_shrub) if(plant.is_shrub)
plantMats[plant.material].add(z); plantMats[plant.material].add(global_z);
else else
treeMats[plant.material].add(z); treeMats[plant.material].add(global_z);
} }
} }
} }
@ -409,22 +452,44 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
con << std::setw(25) << DFHack::TileMaterialString[it->first] << " : " << it->second.count << std::endl; con << std::setw(25) << DFHack::TileMaterialString[it->first] << " : " << it->second.count << std::endl;
} }
if (liquidWater.count || liquidMagma.count)
{
con << std::endl << "Liquids:" << std::endl;
if (liquidWater.count)
{
con << std::setw(25) << "WATER" << " : ";
printMatdata(con, liquidWater);
}
if (liquidWater.count)
{
con << std::setw(25) << "MAGMA" << " : ";
printMatdata(con, liquidMagma);
}
}
con << std::endl << "Layer materials:" << std::endl; con << std::endl << "Layer materials:" << std::endl;
printMats(con, layerMats, *mats->df_inorganic); printMats(con, layerMats, *mats->df_inorganic, showValue);
printVeins(con, veinMats, mats); printVeins(con, veinMats, mats, showValue);
if (showPlants) if (showPlants)
{ {
con << "Shrubs:" << std::endl; con << "Shrubs:" << std::endl;
printMats(con, plantMats, *mats->df_organic); printMats(con, plantMats, *mats->df_organic, showValue);
con << "Wood in trees:" << std::endl; con << "Wood in trees:" << std::endl;
printMats(con, treeMats, *mats->df_organic); printMats(con, treeMats, *mats->df_organic, showValue);
} }
if (hasAquifer) if (hasAquifer)
{ {
con << "Has aquifer" << std::endl; con << "Has aquifer";
if (aquiferTiles.count)
{
con << " : ";
printMatdata(con, aquiferTiles);
}
else
con << std::endl;
} }
if (hasDemonTemple) if (hasDemonTemple)

@ -0,0 +1,82 @@
// All above-ground soil not covered by buildings will be covered with grass.
// Necessary for worlds generated prior to version 0.31.19 - otherwise, outdoor shrubs and trees no longer grow.
#include "Core.h"
#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "DataDefs.h"
#include "df/world.h"
#include "df/map_block.h"
#include "TileTypes.h"
using std::string;
using std::vector;
using namespace DFHack;
using df::global::world;
DFhackCExport command_result df_regrass (Core * c, vector <string> & parameters)
{
if (!parameters.empty())
return CR_WRONG_USAGE;
CoreSuspender suspend(c);
int count = 0;
for (int i = 0; i < world->map.map_blocks.size(); i++)
{
df::map_block *cur = world->map.map_blocks[i];
for (int x = 0; x < 16; x++)
{
for (int y = 0; y < 16; y++)
{
if (DFHack::tileShape(cur->tiletype[x][y]) != DFHack::FLOOR)
continue;
if (DFHack::tileMaterial(cur->tiletype[x][y]) != DFHack::SOIL)
continue;
if (cur->designation[x][y].bits.subterranean)
continue;
if (cur->occupancy[x][y].bits.building)
continue;
switch (rand() % 8)
{
// light grass
case 0: cur->tiletype[x][y] = 0x015C; break;
case 1: cur->tiletype[x][y] = 0x015D; break;
case 2: cur->tiletype[x][y] = 0x015E; break;
case 3: cur->tiletype[x][y] = 0x015F; break;
// dark grass
case 4: cur->tiletype[x][y] = 0x018E; break;
case 5: cur->tiletype[x][y] = 0x018F; break;
case 6: cur->tiletype[x][y] = 0x0190; break;
case 7: cur->tiletype[x][y] = 0x0191; break;
}
count++;
}
}
}
if (count)
c->con.print("Regrew %d tiles of grass.\n", count);
return CR_OK;
}
DFhackCExport const char *plugin_name ( void )
{
return "regrass";
}
DFhackCExport command_result plugin_init (Core *c, std::vector<PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("regrass", "Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.", df_regrass));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}

@ -1,12 +1,18 @@
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <DataDefs.h> #include "modules/Gui.h"
#include <df/ui.h>
#include <df/world.h> #include "DataDefs.h"
#include <df/squad.h> #include "df/ui.h"
#include "df/world.h"
#include "df/squad.h"
#include "df/unit.h"
#include "df/unit_soul.h"
#include "df/historical_figure.h"
#include "df/language_name.h"
#include <stdlib.h> #include <stdlib.h>
@ -30,7 +36,15 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
{ {
commands.clear(); commands.clear();
if (world && ui) { if (world && ui) {
commands.push_back(PluginCommand("rename", "Rename various things.", rename)); commands.push_back(PluginCommand(
"rename", "Rename various things.", rename, false,
" rename squad <index> \"name\"\n"
" rename hotkey <index> \"name\"\n"
" (identified by ordinal index)\n"
" rename unit \"nickname\"\n"
" rename unit-profession \"custom profession\"\n"
" (a unit must be highlighted in the ui)\n"
));
} }
return CR_OK; return CR_OK;
} }
@ -40,12 +54,17 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
return CR_OK; return CR_OK;
} }
static command_result usage(Core *c) static void set_nickname(df::language_name *name, std::string nick)
{ {
c->con << "Usage:" << endl if (!name->has_name)
<< " rename squad <index> \"name\"" << endl {
<< " rename hotkey <index> \"name\"" << endl; *name = df::language_name();
return CR_OK;
name->language = 0;
name->has_name = true;
}
name->nickname = nick;
} }
static command_result rename(Core * c, vector <string> &parameters) static command_result rename(Core * c, vector <string> &parameters)
@ -56,34 +75,72 @@ static command_result rename(Core * c, vector <string> &parameters)
if (!parameters.empty()) if (!parameters.empty())
cmd = parameters[0]; cmd = parameters[0];
if (cmd == "squad") { if (cmd == "squad")
{
if (parameters.size() != 3) if (parameters.size() != 3)
return usage(c); return CR_WRONG_USAGE;
std::vector<df::squad*> &squads = world->squads.all; std::vector<df::squad*> &squads = world->squads.all;
int id = atoi(parameters[1].c_str()); int id = atoi(parameters[1].c_str());
if (id < 1 || id > squads.size()) { if (id < 1 || id > squads.size()) {
c->con.printerr("Invalid squad index\n"); c->con.printerr("Invalid squad index\n");
return usage(c); return CR_WRONG_USAGE;
} }
squads[id-1]->alias = parameters[2]; squads[id-1]->alias = parameters[2];
} else if (cmd == "hotkey") { }
else if (cmd == "hotkey")
{
if (parameters.size() != 3) if (parameters.size() != 3)
return usage(c); return CR_WRONG_USAGE;
int id = atoi(parameters[1].c_str()); int id = atoi(parameters[1].c_str());
if (id < 1 || id > 16) { if (id < 1 || id > 16) {
c->con.printerr("Invalid hotkey index\n"); c->con.printerr("Invalid hotkey index\n");
return usage(c); return CR_WRONG_USAGE;
} }
ui->main.hotkeys[id-1].name = parameters[2]; ui->main.hotkeys[id-1].name = parameters[2];
} else { }
else if (cmd == "unit")
{
if (parameters.size() != 2)
return CR_WRONG_USAGE;
df::unit *unit = getSelectedUnit(c);
if (!unit)
return CR_WRONG_USAGE;
// There are 3 copies of the name, and the one
// in the unit is not the authoritative one.
// This is the reason why military units often
// lose nicknames set from Dwarf Therapist.
set_nickname(&unit->name, parameters[1]);
if (unit->status.current_soul)
set_nickname(&unit->status.current_soul->name, parameters[1]);
df::historical_figure *figure = df::historical_figure::find(unit->hist_figure_id);
if (figure)
set_nickname(&figure->name, parameters[1]);
}
else if (cmd == "unit-profession")
{
if (parameters.size() != 2)
return CR_WRONG_USAGE;
df::unit *unit = getSelectedUnit(c);
if (!unit)
return CR_WRONG_USAGE;
unit->custom_profession = parameters[1];
}
else
{
if (!parameters.empty() && cmd != "?") if (!parameters.empty() && cmd != "?")
c->con.printerr("Invalid command: %s\n", cmd.c_str()); c->con.printerr("Invalid command: %s\n", cmd.c_str());
return usage(c); return CR_WRONG_USAGE;
} }
return CR_OK; return CR_OK;

@ -3,13 +3,13 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Maps.h> #include "modules/Maps.h"
#include <modules/World.h> #include "modules/World.h"
#include <modules/MapCache.h> #include "modules/MapCache.h"
#include <modules/Gui.h> #include "modules/Gui.h"
using MapExtras::MapCache; using MapExtras::MapCache;
using namespace DFHack; using namespace DFHack;

@ -8,14 +8,17 @@
#include "Core.h" #include "Core.h"
#include "Export.h" #include "Export.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "modules/Materials.h"
#include "modules/Items.h"
#include "modules/World.h" #include "modules/World.h"
#include "modules/kitchen.h" #include "modules/kitchen.h"
#include <VersionInfo.h> #include "VersionInfo.h"
#include "df/world.h"
#include "df/plant_raw.h"
#include "df/item_flags.h"
using DFHack::t_materialType; using namespace DFHack;
using DFHack::t_materialIndex; using namespace DFHack::Simple;
using df::global::world;
const int buffer = 20; // seed number buffer - 20 is reasonable const int buffer = 20; // seed number buffer - 20 is reasonable
bool running = false; // whether seedwatch is counting the seeds or not bool running = false; // whether seedwatch is counting the seeds or not
@ -23,22 +26,22 @@ bool running = false; // whether seedwatch is counting the seeds or not
// abbreviations for the standard plants // abbreviations for the standard plants
std::map<std::string, std::string> abbreviations; std::map<std::string, std::string> abbreviations;
bool ignoreSeeds(DFHack::t_itemflags& f) // seeds with the following flags should not be counted bool ignoreSeeds(df::item_flags& f) // seeds with the following flags should not be counted
{ {
return return
f.dump || f.bits.dump ||
f.forbid || f.bits.forbid ||
f.garbage_colect || f.bits.garbage_colect ||
f.hidden || f.bits.hidden ||
f.hostile || f.bits.hostile ||
f.on_fire || f.bits.on_fire ||
f.rotten || f.bits.rotten ||
f.trader || f.bits.trader ||
f.in_building || f.bits.in_building ||
f.in_job; f.bits.in_job;
}; };
void printHelp(DFHack::Core& core) // prints help void printHelp(Core& core) // prints help
{ {
core.con.print( core.con.print(
"Watches the numbers of seeds available and enables/disables seed and plant cooking.\n" "Watches the numbers of seeds available and enables/disables seed and plant cooking.\n"
@ -92,36 +95,32 @@ std::string searchAbbreviations(std::string in)
} }
}; };
DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vector<std::string>& parameters) DFhackCExport command_result df_seedwatch(Core* pCore, std::vector<std::string>& parameters)
{ {
DFHack::Core& core = *pCore; Core& core = *pCore;
if(!core.isValid()) if(!core.isValid())
{ {
return DFHack::CR_FAILURE; return CR_FAILURE;
} }
core.Suspend(); core.Suspend();
DFHack::Materials& materialsModule = *core.getMaterials();
std::vector<DFHack::t_matgloss> organics;
materialsModule.CopyOrganicMaterials(organics);
std::map<std::string, t_materialIndex> materialsReverser; std::map<std::string, t_materialIndex> materialsReverser;
for(std::size_t i = 0; i < organics.size(); ++i) for(std::size_t i = 0; i < world->raws.plants.all.size(); ++i)
{ {
materialsReverser[organics[i].id] = i; materialsReverser[world->raws.plants.all[i]->id] = i;
} }
DFHack::World *w = core.getWorld(); World *w = core.getWorld();
DFHack::t_gamemodes gm; t_gamemodes gm;
w->ReadGameMode(gm);// FIXME: check return value w->ReadGameMode(gm);// FIXME: check return value
// if game mode isn't fortress mode // if game mode isn't fortress mode
if(gm.g_mode != DFHack::GAMEMODE_DWARF || gm.g_type != DFHack::GAMETYPE_DWARF_MAIN) if(gm.g_mode != GAMEMODE_DWARF || gm.g_type != GAMETYPE_DWARF_MAIN)
{ {
// just print the help // just print the help
printHelp(core); printHelp(core);
core.Resume(); core.Resume();
return DFHack::CR_OK; return CR_OK;
} }
std::string par; std::string par;
@ -147,8 +146,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
} }
else if(par == "clear") else if(par == "clear")
{ {
DFHack::Kitchen::Exclusions kitchenExclusions(core); Kitchen::clearLimits();
kitchenExclusions.clearLimits();
core.con.print("seedwatch watchlist cleared\n"); core.con.print("seedwatch watchlist cleared\n");
} }
else if(par == "info") else if(par == "info")
@ -162,9 +160,8 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
{ {
core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n");
} }
DFHack::Kitchen::Exclusions kitchenExclusions(core);
std::map<t_materialIndex, unsigned int> watchMap; std::map<t_materialIndex, unsigned int> watchMap;
kitchenExclusions.fillWatchMap(watchMap); Kitchen::fillWatchMap(watchMap);
if(watchMap.empty()) if(watchMap.empty())
{ {
core.con.print("The watch list is empty.\n"); core.con.print("The watch list is empty.\n");
@ -174,16 +171,15 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
core.con.print("The watch list is:\n"); core.con.print("The watch list is:\n");
for(std::map<t_materialIndex, unsigned int>::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) for(std::map<t_materialIndex, unsigned int>::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i)
{ {
core.con.print("%s : %u\n", organics[i->first].id.c_str(), i->second); core.con.print("%s : %u\n", world->raws.plants.all[i->first]->id.c_str(), i->second);
} }
} }
} }
else if(par == "debug") else if(par == "debug")
{ {
DFHack::Kitchen::Exclusions kitchenExclusions(core);
std::map<t_materialIndex, unsigned int> watchMap; std::map<t_materialIndex, unsigned int> watchMap;
kitchenExclusions.fillWatchMap(watchMap); Kitchen::fillWatchMap(watchMap);
kitchenExclusions.debug_print(); Kitchen::debug_print(core);
} }
/* /*
else if(par == "dumpmaps") else if(par == "dumpmaps")
@ -208,8 +204,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
std::string token = searchAbbreviations(par); std::string token = searchAbbreviations(par);
if(materialsReverser.count(token) > 0) if(materialsReverser.count(token) > 0)
{ {
DFHack::Kitchen::Exclusions kitchenExclusions(core); Kitchen::removeLimit(materialsReverser[token]);
kitchenExclusions.removeLimit(materialsReverser[token]);
core.con.print("%s is not being watched\n", token.c_str()); core.con.print("%s is not being watched\n", token.c_str());
} }
else else
@ -225,8 +220,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
{ {
for(std::map<std::string, std::string>::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) for(std::map<std::string, std::string>::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i)
{ {
DFHack::Kitchen::Exclusions kitchenExclusions(core); if(materialsReverser.count(i->second) > 0) Kitchen::setLimit(materialsReverser[i->second], limit);
if(materialsReverser.count(i->second) > 0) kitchenExclusions.setLimit(materialsReverser[i->second], limit);
} }
} }
else else
@ -234,8 +228,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
std::string token = searchAbbreviations(parameters[0]); std::string token = searchAbbreviations(parameters[0]);
if(materialsReverser.count(token) > 0) if(materialsReverser.count(token) > 0)
{ {
DFHack::Kitchen::Exclusions kitchenExclusions(core); Kitchen::setLimit(materialsReverser[token], limit);
kitchenExclusions.setLimit(materialsReverser[token], limit);
core.con.print("%s is being watched.\n", token.c_str()); core.con.print("%s is being watched.\n", token.c_str());
} }
else else
@ -250,7 +243,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
} }
core.Resume(); core.Resume();
return DFHack::CR_OK; return CR_OK;
} }
DFhackCExport const char* plugin_name(void) DFhackCExport const char* plugin_name(void)
@ -258,10 +251,10 @@ DFhackCExport const char* plugin_name(void)
return "seedwatch"; return "seedwatch";
} }
DFhackCExport DFHack::command_result plugin_init(DFHack::Core* pCore, std::vector<DFHack::PluginCommand>& commands) DFhackCExport command_result plugin_init(Core* pCore, std::vector<PluginCommand>& commands)
{ {
commands.clear(); commands.clear();
commands.push_back(DFHack::PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch)); commands.push_back(PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch));
// fill in the abbreviations map, with abbreviations for the standard plants // fill in the abbreviations map, with abbreviations for the standard plants
abbreviations["bs"] = "SLIVER_BARB"; abbreviations["bs"] = "SLIVER_BARB";
abbreviations["bt"] = "TUBER_BLOATED"; abbreviations["bt"] = "TUBER_BLOATED";
@ -284,14 +277,14 @@ DFhackCExport DFHack::command_result plugin_init(DFHack::Core* pCore, std::vecto
abbreviations["vh"] = "HERB_VALLEY"; abbreviations["vh"] = "HERB_VALLEY";
abbreviations["ws"] = "BERRIES_STRAW_WILD"; abbreviations["ws"] = "BERRIES_STRAW_WILD";
abbreviations["wv"] = "VINE_WHIP"; abbreviations["wv"] = "VINE_WHIP";
return DFHack::CR_OK; return CR_OK;
} }
DFhackCExport DFHack::command_result plugin_onstatechange(DFHack::Core* pCore, DFHack::state_change_event event) DFhackCExport command_result plugin_onstatechange(Core* pCore, state_change_event event)
{ {
switch (event) { switch (event) {
case DFHack::SC_GAME_LOADED: case SC_GAME_LOADED:
case DFHack::SC_GAME_UNLOADED: case SC_GAME_UNLOADED:
if (running) if (running)
pCore->con.printerr("seedwatch deactivated due to game load/unload\n"); pCore->con.printerr("seedwatch deactivated due to game load/unload\n");
running = false; running = false;
@ -300,73 +293,67 @@ DFhackCExport DFHack::command_result plugin_onstatechange(DFHack::Core* pCore, D
break; break;
} }
return DFHack::CR_OK; return CR_OK;
} }
DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore) DFhackCExport command_result plugin_onupdate(Core* pCore)
{ {
if (running) if (running)
{ {
// reduce processing rate // reduce processing rate
static int counter = 0; static int counter = 0;
if (++counter < 500) if (++counter < 500)
return DFHack::CR_OK; return CR_OK;
counter = 0; counter = 0;
DFHack::Core& core = *pCore; Core& core = *pCore;
DFHack::World *w = core.getWorld(); World *w = core.getWorld();
DFHack::t_gamemodes gm; t_gamemodes gm;
w->ReadGameMode(gm);// FIXME: check return value w->ReadGameMode(gm);// FIXME: check return value
// if game mode isn't fortress mode // if game mode isn't fortress mode
if(gm.g_mode != DFHack::GAMEMODE_DWARF || gm.g_type != DFHack::GAMETYPE_DWARF_MAIN) if(gm.g_mode != GAMEMODE_DWARF || gm.g_type != GAMETYPE_DWARF_MAIN)
{ {
// stop running. // stop running.
running = false; running = false;
core.con.printerr("seedwatch deactivated due to game mode switch\n"); core.con.printerr("seedwatch deactivated due to game mode switch\n");
return DFHack::CR_OK; return CR_OK;
} }
// this is dwarf mode, continue // this is dwarf mode, continue
std::map<t_materialIndex, unsigned int> seedCount; // the number of seeds std::map<t_materialIndex, unsigned int> seedCount; // the number of seeds
DFHack::Items& itemsModule = *core.getItems();
itemsModule.Start();
std::vector<DFHack::df_item*> items;
itemsModule.readItemVector(items);
DFHack::df_item * item;
// count all seeds and plants by RAW material // count all seeds and plants by RAW material
for(std::size_t i = 0; i < items.size(); ++i) for(std::size_t i = 0; i < world->items.all.size(); ++i)
{ {
item = items[i]; df::item * item = world->items.all[i];
t_materialIndex materialIndex = item->getMaterialIndex(); t_materialIndex materialIndex = item->getMaterialIndex();
switch(item->getType()) switch(item->getType())
{ {
case DFHack::Items::SEEDS: case df::item_type::SEEDS:
if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex]; if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex];
break; break;
case DFHack::Items::PLANT: case df::item_type::PLANT:
break; break;
} }
} }
itemsModule.Finish();
DFHack::Kitchen::Exclusions kitchenExclusions(core);
std::map<t_materialIndex, unsigned int> watchMap; std::map<t_materialIndex, unsigned int> watchMap;
kitchenExclusions.fillWatchMap(watchMap); Kitchen::fillWatchMap(watchMap);
for(auto i = watchMap.begin(); i != watchMap.end(); ++i) for(auto i = watchMap.begin(); i != watchMap.end(); ++i)
{ {
if(seedCount[i->first] <= i->second) if(seedCount[i->first] <= i->second)
{ {
kitchenExclusions.denyPlantSeedCookery(i->first); Kitchen::denyPlantSeedCookery(i->first);
} }
else if(i->second + buffer < seedCount[i->first]) else if(i->second + buffer < seedCount[i->first])
{ {
kitchenExclusions.allowPlantSeedCookery(i->first); Kitchen::allowPlantSeedCookery(i->first);
} }
} }
} }
return DFHack::CR_OK; return CR_OK;
} }
DFhackCExport DFHack::command_result plugin_shutdown(DFHack::Core* pCore) DFhackCExport command_result plugin_shutdown(Core* pCore)
{ {
return DFHack::CR_OK; return CR_OK;
} }

@ -1,14 +1,14 @@
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <DataDefs.h> #include "DataDefs.h"
#include <df/world.h> #include "df/world.h"
#include <df/ui.h> #include "df/ui.h"
#include <df/building_stockpilest.h> #include "df/building_stockpilest.h"
#include <df/selection_rect.h> #include "df/selection_rect.h"
#include <df/viewscreen_dwarfmodest.h> #include "df/viewscreen_dwarfmodest.h"
using std::vector; using std::vector;
using std::string; using std::string;

@ -1 +1 @@
Subproject commit 1b28039e2c93daa3c2f69f5e2a000ff8c96ee1f8 Subproject commit 92627e39cb3502812cd5a131716d3d1da8ef625a

@ -11,14 +11,14 @@ using std::endl;
using std::set; using std::set;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Vegetation.h> #include "modules/Vegetation.h"
#include <modules/Maps.h> #include "modules/Maps.h"
#include <modules/Gui.h> #include "modules/Gui.h"
#include <TileTypes.h> #include "TileTypes.h"
#include <modules/MapCache.h> #include "modules/MapCache.h"
using namespace MapExtras; using namespace MapExtras;
using namespace DFHack; using namespace DFHack;

@ -5,13 +5,13 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Maps.h> #include "modules/Maps.h"
#include <modules/World.h> #include "modules/World.h"
#include <modules/MapCache.h> #include "modules/MapCache.h"
#include <modules/Gui.h> #include "modules/Gui.h"
using MapExtras::MapCache; using MapExtras::MapCache;
using namespace DFHack; using namespace DFHack;

@ -1,10 +1,10 @@
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Maps.h> #include "modules/Maps.h"
#include <modules/Gui.h> #include "modules/Gui.h"
#include <modules/MapCache.h> #include "modules/MapCache.h"
#include <vector> #include <vector>
#include <cstdio> #include <cstdio>
#include <stack> #include <stack>
@ -459,6 +459,100 @@ static digmask diag5[5] =
}, },
}; };
static digmask diag5r[5] =
{
{
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
},
{
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
},
{
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
},
{
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
},
{
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
{0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},
{0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0},
{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1},
},
};
static digmask ladder[3] = static digmask ladder[3] =
{ {
{ {
@ -517,6 +611,64 @@ static digmask ladder[3] =
}, },
}; };
static digmask ladderr[3] =
{
{
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
},
{
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
},
{
{0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
},
};
static digmask all_tiles = static digmask all_tiles =
{ {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
@ -560,7 +712,9 @@ enum explo_how
{ {
EXPLO_NOTHING, EXPLO_NOTHING,
EXPLO_DIAG5, EXPLO_DIAG5,
EXPLO_DIAG5R,
EXPLO_LADDER, EXPLO_LADDER,
EXPLO_LADDERR,
EXPLO_CLEAR, EXPLO_CLEAR,
EXPLO_CROSS, EXPLO_CROSS,
}; };
@ -653,6 +807,10 @@ DFhackCExport command_result expdig (Core * c, vector <string> & parameters)
{ {
how = EXPLO_DIAG5; how = EXPLO_DIAG5;
} }
else if(parameters[i] == "diag5r")
{
how = EXPLO_DIAG5R;
}
else if(parameters[i] == "clear") else if(parameters[i] == "clear")
{ {
how = EXPLO_CLEAR; how = EXPLO_CLEAR;
@ -661,6 +819,10 @@ DFhackCExport command_result expdig (Core * c, vector <string> & parameters)
{ {
how = EXPLO_LADDER; how = EXPLO_LADDER;
} }
else if(parameters[i] == "ladderr")
{
how = EXPLO_LADDERR;
}
else if(parameters[i] == "cross") else if(parameters[i] == "cross")
{ {
how = EXPLO_CROSS; how = EXPLO_CROSS;
@ -674,7 +836,9 @@ DFhackCExport command_result expdig (Core * c, vector <string> & parameters)
"There are two variables that can be set: pattern and filter.\n" "There are two variables that can be set: pattern and filter.\n"
"Patterns:\n" "Patterns:\n"
" diag5 = diagonals separated by 5 tiles\n" " diag5 = diagonals separated by 5 tiles\n"
" diag5r = diag5 rotated 90 degrees\n"
" ladder = A 'ladder' pattern\n" " ladder = A 'ladder' pattern\n"
"ladderr = ladder rotated 90 degrees\n"
" clear = Just remove all dig designations\n" " clear = Just remove all dig designations\n"
" cross = A cross, exactly in the middle of the map.\n" " cross = A cross, exactly in the middle of the map.\n"
"Filters:\n" "Filters:\n"
@ -719,6 +883,19 @@ DFhackCExport command_result expdig (Core * c, vector <string> & parameters)
} }
} }
} }
else if(how == EXPLO_DIAG5R)
{
int which;
for(uint32_t x = 0; x < x_max; x++)
{
for(int32_t y = 0 ; y < y_max; y++)
{
which = (4*x + 1000-y) % 5;
stamp_pattern(maps, x,y_max - 1 - y, z_level, diag5r[which],
how, what, x_max, y_max);
}
}
}
else if(how == EXPLO_LADDER) else if(how == EXPLO_LADDER)
{ {
int which; int which;
@ -732,6 +909,19 @@ DFhackCExport command_result expdig (Core * c, vector <string> & parameters)
} }
} }
} }
else if(how == EXPLO_LADDERR)
{
int which;
for(int32_t y = 0 ; y < y_max; y++)
{
which = y % 3;
for(uint32_t x = 0; x < x_max; x++)
{
stamp_pattern(maps, x, y, z_level, ladderr[which],
how, what, x_max, y_max);
}
}
}
else if(how == EXPLO_CROSS) else if(how == EXPLO_CROSS)
{ {
// middle + recentering for the image // middle + recentering for the image

@ -8,11 +8,11 @@
#include <string.h> #include <string.h>
using namespace std; using namespace std;
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <modules/Graphic.h> #include "modules/Graphic.h"
#include <modules/Gui.h> #include "modules/Gui.h"
using namespace DFHack; using namespace DFHack;
DFhackCExport command_result df_versionosd (Core * c, vector <string> & parameters); DFhackCExport command_result df_versionosd (Core * c, vector <string> & parameters);

@ -1,10 +1,10 @@
#include "Core.h" #include "Core.h"
#include <Console.h> #include "Console.h"
#include <Export.h> #include "Export.h"
#include <PluginManager.h> #include "PluginManager.h"
#include <vector> #include <vector>
#include <string> #include <string>
#include <modules/World.h> #include "modules/World.h"
using std::vector; using std::vector;
using std::string; using std::string;

File diff suppressed because it is too large Load Diff