diff --git a/Memory.xml b/Memory.xml index 29efd1857..a9421e8f6 100644 --- a/Memory.xml +++ b/Memory.xml @@ -819,6 +819,8 @@ + + @@ -2143,6 +2145,8 @@ + + diff --git a/library/include/dfhack/modules/Items.h b/library/include/dfhack/modules/Items.h index a69f657e1..bc520f87e 100644 --- a/library/include/dfhack/modules/Items.h +++ b/library/include/dfhack/modules/Items.h @@ -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) diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index fdf57105c..b17c52e38 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -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::iterator it; diff --git a/tools/playground/CMakeLists.txt b/tools/playground/CMakeLists.txt index 14db195b8..7b15e6d39 100644 --- a/tools/playground/CMakeLists.txt +++ b/tools/playground/CMakeLists.txt @@ -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 diff --git a/tools/playground/itemdesignator.cpp b/tools/playground/itemdesignator.cpp index 35e1cfdf6..a1211c013 100644 --- a/tools/playground/itemdesignator.cpp +++ b/tools/playground/itemdesignator.cpp @@ -1,202 +1,38 @@ -// Item dump +// Item designator #include #include #include #include -#include #include using namespace std; -#include -#include -#include +#include +#include +using namespace DFHack; -struct matGlosses -{ - vector plantMat; - vector woodMat; - vector stoneMat; - vector metalMat; - vector 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 p_items (p, vector_addr); + uint32_t numItems = p_items.size(); -// vector objecttypes; -// DF.getClassIDMapping(objecttypes); - uint32_t numItems; - DF.InitReadItems(numItems); - map< string, map > > count; + map< string, map > > itemmap; + map< string, map< string, vector< dfh_item > > >::iterator it1; int failedItems = 0; map 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 > >::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 >::iterator it2; + map >::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();