The item designator tool lives again.

develop
Petr Mrázek 2011-04-16 23:57:04 +02:00
parent 2d372aca3c
commit b0cb59a3f2
5 changed files with 55 additions and 251 deletions

@ -819,6 +819,8 @@
<Group name="block" description="The map block structure.">
<Offset name="vein_vector" description="Mineral veins, objects holding tile types under ice, etc..."/>
<Offset name="vegetation_vector" description="All the plants in this block, including farm plats."/>
<Offset name="effect_vector" description="Effect objects present in the block."/>
<Offset name="item_idx_vector" description="Indexes of item objects present in the block."/>
<Offset name="type" description="16x16 x 2B tile type values"/>
<Offset name="designation" description="16x16 * 4B designation fields"/>
<Offset name="occupancy" description="16x16 * 4B occupancy fields" />
@ -2143,6 +2145,8 @@
<Group name="Maps">
<Group name="block">
<Offset name="mystery_offset" value="0x2C" />
<Offset name="item_idx_vector" value="0x3C" />
<Offset name="effect_vector" value="0x4C" />
<Offset name="vegetation_vector" value="0x64" />
<Offset name="type" value="0x7e" />
<Offset name="designation" value="0x280" />

@ -119,6 +119,7 @@ public:
std::string getItemDescription(const dfh_item & item, Materials * Materials);
/// get a short name for an item
std::string getItemClass(int32_t index);
std::string getItemClass(const dfh_item & item);
/// read an item, including the extra attributes
bool readItem(uint32_t itemptr, dfh_item & item);
/// write item base (position and flags only = t_item part of dfh_item)

@ -525,6 +525,11 @@ int32_t Items::getItemOwnerID(const DFHack::dfh_item &item)
return -1;
}
std::string Items::getItemClass(const dfh_item & item)
{
return getItemClass(item.matdesc.itemType);
}
std::string Items::getItemClass(int32_t index)
{
std::map<int32_t, ItemDesc *>::iterator it;

@ -35,8 +35,7 @@ DFHACK_TOOL(dfdigger2 digger2.cpp)
# itemdesignator - change some item designations (dump, forbid, on-fire) for all
# items of a given type and material
# Author: belal
# FIXME: turned off. there is no reliable Items module.
#DFHACK_TOOL(dfitemdesignator itemdesignator.cpp)
DFHACK_TOOL(dfitemdesignator itemdesignator.cpp)
# catsplosion - Accelerates pregnancy
# Author: Zhentar

@ -1,202 +1,38 @@
// Item dump
// Item designator
#include <iostream>
#include <iomanip>
#include <sstream>
#include <climits>
#include <integers.h>
#include <vector>
using namespace std;
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFMemInfo.h>
#include <DFHack.h>
#include <dfhack/DFVector.h>
using namespace DFHack;
struct matGlosses
{
vector<DFHack::t_matgloss> plantMat;
vector<DFHack::t_matgloss> woodMat;
vector<DFHack::t_matgloss> stoneMat;
vector<DFHack::t_matgloss> metalMat;
vector<DFHack::t_matgloss> creatureMat;
};
string getMaterialType(DFHack::t_item item, const string & itemtype,const matGlosses & mat)
{
// plant thread seeds
if(itemtype == "item_plant" || itemtype == "item_thread" || itemtype == "item_seeds" || itemtype == "item_leaves" )
{
if(item.material.type >= 0 && item.material.type < mat.plantMat.size())
{
return mat.plantMat[item.material.type].id;
}
else
{
return "some invalid plant material";
}
}
else if (itemtype == "item_drink") // drinks must have different offset for materials
{
return "Booze or something";
}
// item_skin_raw item_bones item_skull item_fish_raw item_pet item_skin_tanned item_shell
else if(itemtype == "item_skin_raw" ||
itemtype == "item_skin_tanned" ||
itemtype == "item_fish_raw" ||
itemtype == "item_pet" ||
itemtype == "item_shell" ||
itemtype == "item_horn"||
itemtype == "item_skull" ||
itemtype == "item_bones" ||
itemtype == "item_corpse" ||
itemtype == "item_meat"
)
{
if(item.material.type >= 0 && item.material.type < mat.creatureMat.size())
return mat.creatureMat[item.material.type].id;
return "bad material";
}
else if(itemtype == "item_wood")
{
if(item.material.type >= 0 && item.material.type < mat.woodMat.size())
return mat.woodMat[item.material.type].id;
return "bad material";
}
else if(itemtype == "item_bar")
{
if(item.material.type >= 0 && item.material.type < mat.metalMat.size())
return mat.metalMat[item.material.type].id;
return "bad material";
}
else
{
/*
Mat_Wood,
Mat_Stone,
Mat_Metal,
Mat_Plant,
Mat_Leather = 10,
Mat_SilkCloth = 11,
Mat_PlantCloth = 12,
Mat_GreenGlass = 13,
Mat_ClearGlass = 14,
Mat_CrystalGlass = 15,
Mat_Ice = 17,
Mat_Charcoal =18,
Mat_Potash = 19,
Mat_Ashes = 20,
Mat_PearlAsh = 21,
Mat_Soap = 24,
*/
switch (item.material.type)
{
case DFHack::Mat_Wood:
if(item.material.index >= 0 && item.material.index < mat.woodMat.size())
return mat.woodMat[item.material.index].id;
return "bad material";
case DFHack::Mat_Stone:
if(item.material.index >= 0 && item.material.index < mat.stoneMat.size())
return mat.stoneMat[item.material.index].id;
return "bad material";
case DFHack::Mat_Metal:
if(item.material.index >= 0 && item.material.index < mat.metalMat.size())
return mat.metalMat[item.material.index].id;
return "bad material";
//case DFHack::Mat_Plant:
case DFHack::Mat_PlantCloth:
//return mat.plantMat[item.material.index].id;
if(item.material.index >= 0 && item.material.index < mat.plantMat.size())
return string(mat.plantMat[item.material.index].id) + " plant";
return "bad material";
case 3: // bone
if(item.material.index >= 0 && item.material.index < mat.creatureMat.size())
return string(mat.creatureMat[item.material.index].id) + " bone";
return "bad material";
case 25: // fat
if(item.material.index >= 0 && item.material.index < mat.creatureMat.size())
return string(mat.creatureMat[item.material.index].id) + " fat";
return "bad material";
case 23: // tallow
if(item.material.index >= 0 && item.material.index < mat.creatureMat.size())
return string(mat.creatureMat[item.material.index].id) + " tallow";
return "bad material";
case 9: // shell
if(item.material.index >= 0 && item.material.index < mat.creatureMat.size())
return string(mat.creatureMat[item.material.index].id) + " shell";
return "bad material";
case DFHack::Mat_Leather: // really a generic creature material. meat for item_food, leather for item_box...
if(item.material.index >= 0 && item.material.index < mat.creatureMat.size())
return string(mat.creatureMat[item.material.index].id);
return "bad material";
case DFHack::Mat_SilkCloth:
if(item.material.index >= 0 && item.material.index < mat.creatureMat.size())
return string(mat.creatureMat[item.material.index].id) + " silk";
return "bad material";
case DFHack::Mat_Soap:
if(item.material.index >= 0 && item.material.index < mat.creatureMat.size())
return string(mat.creatureMat[item.material.index].id) + " soap";
return "bad material";
case DFHack::Mat_GreenGlass:
return "Green Glass";
case DFHack::Mat_ClearGlass:
return "Clear Glass";
case DFHack::Mat_CrystalGlass:
return "Crystal Glass";
case DFHack::Mat_Ice:
return "Ice";
case DFHack::Mat_Charcoal:
return "Charcoal";
/*case DFHack::Mat_Potash:
return "Potash";*/
case DFHack::Mat_Ashes:
return "Ashes";
case DFHack::Mat_PearlAsh:
return "Pearlash";
default:
cout << "unknown material hit: " << item.material.type << " " << item.material.index << " " << itemtype << endl;
return "Invalid";
}
}
return "Invalid";
}
void printItem(DFHack::t_item item, const string & typeString,const matGlosses & mat)
{
cout << dec << "Item at x:" << item.x << " y:" << item.y << " z:" << item.z << endl;
cout << "Type: " << (int) item.type << " " << typeString << " Address: " << hex << item.origin << endl;
cout << "Material: ";
string itemType = getMaterialType(item,typeString,mat);
cout << itemType << endl;
}
int main ()
{
DFHack::ContextManager DF ("Memory.xml");
DFHack::ContextManager CM ("Memory.xml");
DFHack::Context * DF;
DFHack::VersionInfo *mem;
DFHack::Gui * Gui;
DFHack::Materials * Mats;
DFHack::Items * Items;
cout << "This utility lets you mass-designate items by type and material." << endl
<< "Like set on fire all MICROCLINE item_stone..." << endl
<< "Some unusual combinations might be untested and cause the program to crash..."<< endl
<< "so, watch your step and backup your fort" << endl;
try
{
DF.Attach();
DF = CM.getSingleContext();
DF->Attach();
mem = DF->getMemoryInfo();
Gui = DF->getGui();
Mats = DF->getMaterials();
Mats->ReadAllMaterials();
Items = DF->getItems();
}
catch (exception& e)
{
@ -206,64 +42,27 @@ int main ()
#endif
return 1;
}
DFHack::memory_info *mem = DF.getMemoryInfo();
DF.Suspend();
DF.InitViewAndCursor();
matGlosses mat;
DF.ReadPlantMatgloss(mat.plantMat);
DF.ReadWoodMatgloss(mat.woodMat);
DF.ReadStoneMatgloss(mat.stoneMat);
DF.ReadMetalMatgloss(mat.metalMat);
DF.ReadCreatureMatgloss(mat.creatureMat);
DFHack::Process * 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 numItems = p_items.size();
// vector <string> objecttypes;
// DF.getClassIDMapping(objecttypes);
uint32_t numItems;
DF.InitReadItems(numItems);
map< string, map<string,vector<uint32_t> > > count;
map< string, map<string,vector< dfh_item > > > itemmap;
map< string, map< string, vector< dfh_item > > >::iterator it1;
int failedItems = 0;
map <string, int > bad_mat_items;
for(uint32_t i=0; i< numItems; i++)
{
DFHack::t_item temp;
DF.ReadItem(i,temp);
if(temp.type != -1) // this should be the case pretty much always
{
string typestr;
mem->resolveClassIDToClassname(temp.type,typestr);
string material = getMaterialType(temp,typestr,mat);
if (material != "Invalid")
{
count[typestr][material].push_back(i);
}
else
{
if(bad_mat_items.count(typestr))
{
int tmp = bad_mat_items[typestr];
tmp ++;
bad_mat_items[typestr] = tmp;
}
else
{
bad_mat_items[typestr] = 1;
}
}
}
}
map< string, int >::iterator it_bad;
if(! bad_mat_items.empty())
{
cout << "Items with badly assigned materials:" << endl;
for(it_bad = bad_mat_items.begin(); it_bad!=bad_mat_items.end();it_bad++)
{
cout << it_bad->first << " : " << it_bad->second << endl;
}
DFHack::dfh_item temp;
Items->readItem(p_items[i],temp);
string typestr = Items->getItemClass(temp);
string material = Mats->getDescription(temp.matdesc);
itemmap[typestr][material].push_back(temp);
}
map< string, map<string,vector<uint32_t> > >::iterator it1;
int i =0;
for(it1 = count.begin(); it1!=count.end();it1++)
for( it1 = itemmap.begin(); it1!=itemmap.end();it1++)
{
cout << i << ": " << it1->first << "\n";
i++;
@ -271,8 +70,7 @@ int main ()
if(i == 0)
{
cout << "No items found" << endl;
DF.FinishReadBuildings();
DF.Detach();
DF->Detach();
return 0;
}
cout << endl << "Select an item type from the list:";
@ -283,14 +81,14 @@ int main ()
ss.str(in);
ss >> number;
int j = 0;
it1 = count.begin();
while(j < number && it1!=count.end())
it1 = itemmap.begin();
while(j < number && it1!=itemmap.end())
{
it1++;
j++;
}
cout << it1->first << "\n";
map<string,vector<uint32_t> >::iterator it2;
map<string,vector<dfh_item> >::iterator it2;
i=0;
for(it2 = it1->second.begin();it2!=it1->second.end();it2++){
cout << i << ":\t" << it2->first << " [" << it2->second.size() << "]" << endl;
@ -302,7 +100,7 @@ int main ()
getline(cin, in);
ss.str(in);
ss >> number2;
decideAgain:
cout << "Select a designation - (d)ump, (f)orbid, (m)melt, set on fi(r)e :" << flush;
string designationType;
@ -310,19 +108,19 @@ int main ()
DFHack::t_itemflags changeFlag = {0};
if(designationType == "d" || designationType == "dump")
{
changeFlag.bits.dump = 1;
changeFlag.dump = 1;
}
else if(designationType == "f" || designationType == "forbid")
{
changeFlag.bits.forbid = 1;
changeFlag.forbid = 1;
}
else if(designationType == "m" || designationType == "melt")
{
changeFlag.bits.melt = 1;
changeFlag.melt = 1;
}
else if(designationType == "r" || designationType == "fire")
{
changeFlag.bits.on_fire = 1;
changeFlag.on_fire = 1;
}
else
{
@ -337,14 +135,11 @@ int main ()
}
for(uint32_t k = 0;k< it2->second.size();k++)
{
DFHack::t_item temp;
DF.ReadItem(it2->second[k],temp);
temp.flags.whole |= changeFlag.whole;
DF.WriteRaw(temp.origin+12,sizeof(uint32_t),(uint8_t *)&temp.flags.whole);
DFHack::dfh_item & t = it2->second[k];
t.base.flags.whole |= changeFlag.whole;
Items->writeItem(t);
}
DF.FinishReadItems();
DF.Detach();
DF->Detach();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();