Add an experimental program for cleaning up garbage owned by dwarfs.

As noted by Quietust on the forum, cleaning the owned flag from the
items does not actually remove the owner, but the item ceases to be
protected from manipulation by other dwarfs. This should be enough
to work around various bugs, like untouchable rotten food producing
miasma, or dwarfs littering the place with worn objects.
develop
Alexander Gavrilov 2011-04-10 23:25:41 +04:00
parent fbf76440b5
commit 109d20d251
2 changed files with 134 additions and 0 deletions

@ -80,6 +80,8 @@ DFHACK_TOOL(dfprinttiletypes printtiletypes.cpp)
# Will have many options in the future. # Will have many options in the future.
DFHACK_TOOL(dfhellhole hellhole.cpp) DFHACK_TOOL(dfhellhole hellhole.cpp)
DFHACK_TOOL(dfcleanowned cleanowned.cpp)
# this needs the C bindings # this needs the C bindings
IF(BUILD_DFHACK_C_BINDINGS) IF(BUILD_DFHACK_C_BINDINGS)
# for trying out some 'stuff' # for trying out some 'stuff'

@ -0,0 +1,132 @@
/*
* Confiscates and dumps garbage owned by dwarfs.
*/
#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <climits>
#include <vector>
using namespace std;
#include <DFHack.h>
#include <dfhack/DFVector.h>
#include <dfhack/DFTypes.h>
DFHack::Materials * Materials;
DFHack::Items * Items;
int main (int argc, char *argv[])
{
bool dump_scattered = false;
int wear_dump_level = 65536;
for(int i = 1; i < argc; i++)
{
char *arg = argv[i];
if (arg[0] != '-')
continue;
for (; *arg; arg++) {
switch (arg[0]) {
case 'j':
dump_scattered = true;
break;
case 'x':
wear_dump_level = 1;
break;
case 'X':
wear_dump_level = 2;
break;
}
}
}
DFHack::Process * p;
unsigned int i,j;
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context * DF;
try
{
DF = DFMgr.getSingleContext();
DF->Attach();
}
catch (exception& e)
{
cerr << e.what() << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
DFHack::VersionInfo * mem = DF->getMemoryInfo();
Materials = DF->getMaterials();
Items = DF->getItems();
Materials->ReadAllMaterials();
p = DF->getProcess();
DFHack::OffsetGroup* itemGroup = mem->getGroup("Items");
unsigned vector_addr = itemGroup->getAddress("items_vector");
DFHack::DfVector <uint32_t> p_items (p, vector_addr);
uint32_t size = p_items.size();
printf("Found total %d items.\n", size);
for (i=0;i<size;i++)
{
uint32_t curItem = p_items[i];
DFHack::t_item itm;
Items->getItemData(curItem, itm);
if (!itm.header.flags.bits.owned)
continue;
bool confiscate = false;
bool dump = false;
if (itm.header.flags.bits.rotten)
{
printf("Confiscating a rotten item.\n");
confiscate = true;
}
else if (itm.wear_level >= wear_dump_level)
{
printf("Confiscating and dumping a worn item.\n");
confiscate = true;
dump = true;
}
else if (dump_scattered && itm.header.flags.bits.on_ground)
{
printf("Confiscating and dumping an untidily placed item.\n");
confiscate = true;
dump = true;
}
if (confiscate)
{
itm.header.flags.bits.owned = 0;
if (dump)
itm.header.flags.bits.dump = 1;
Items->setItemFlags(curItem, itm.header.flags);
printf(
"%5d: %08x %08x (%d,%d,%d) #%08x [%d] %s - %s\n",
i, curItem, itm.header.flags.whole,
itm.header.x, itm.header.y, itm.header.z,
p->readDWord(curItem),
itm.wear_level,
Items->getItemClass(itm.matdesc.itemType).c_str(),
Items->getItemDescription(curItem, Materials).c_str()
);
}
}
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}