int main () { DFHack::ContextManager DF ("Memory.xml"); 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(); } catch (exception& e) { cerr << e.what() << endl; #ifndef LINUX_BUILD cin.ignore(); #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); // vector <string> objecttypes; // DF.getClassIDMapping(objecttypes); uint32_t numItems; DF.InitReadItems(numItems); map< string, map<string,vector<uint32_t> > > count; 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; } } map< string, map<string,vector<uint32_t> > >::iterator it1; int i =0; for(it1 = count.begin(); it1!=count.end();it1++) { cout << i << ": " << it1->first << "\n"; i++; } if(i == 0) { cout << "No items found" << endl; DF.FinishReadBuildings(); DF.Detach(); return 0; } cout << endl << "Select an item type from the list:"; int number; string in; stringstream ss; getline(cin, in); ss.str(in); ss >> number; int j = 0; it1 = count.begin(); while(j < number && it1!=count.end()) { it1++; j++; } cout << it1->first << "\n"; map<string,vector<uint32_t> >::iterator it2; i=0; for(it2 = it1->second.begin();it2!=it1->second.end();it2++){ cout << i << ":\t" << it2->first << " [" << it2->second.size() << "]" << endl; i++; } cout << endl << "Select a material type: "; int number2; ss.clear(); 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; getline(cin,designationType); DFHack::t_itemflags changeFlag = {0}; if(designationType == "d" || designationType == "dump") { changeFlag.bits.dump = 1; } else if(designationType == "f" || designationType == "forbid") { changeFlag.bits.forbid = 1; } else if(designationType == "m" || designationType == "melt") { changeFlag.bits.melt = 1; } else if(designationType == "r" || designationType == "fire") { changeFlag.bits.on_fire = 1; } else { goto decideAgain; } j=0; it2= it1->second.begin(); while(j < number2 && it2!=it1->second.end()) { it2++; j++; } 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); } DF.FinishReadItems(); DF.Detach(); #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); #endif return 0; }
int main () { DFHack::Process *proc; DFHack::memory_info *meminfo; DFHack::DfVector *items_vector; DFHack::t_item_df40d item_40d; DFHack::t_matglossPair item_40d_material; vector<DFHack::t_matgloss> stoneMat; uint32_t item_material_offset; uint32_t temp; int32_t type; int items; int found = 0, converted = 0; DFHack::API DF("Memory.xml"); try { DF.Attach(); } catch (exception& e) { cerr << e.what() << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } // Find out which material is bauxite if(!DF.ReadStoneMatgloss(stoneMat)) { cout << "Materials not supported for this version of DF, exiting." << endl; #ifndef LINUX_BUILD cin.ignore(); #endif DF.Detach(); return EXIT_FAILURE; } int bauxiteIndex = -1; for (int i = 0; i < stoneMat.size();i++) { if(strcmp(stoneMat[i].id, "BAUXITE") == 0) { bauxiteIndex = i; break; } } if(bauxiteIndex == -1) { cout << "Cannot locate bauxite in the DF raws, exiting" << endl; #ifndef LINUX_BUILD cin.ignore(); #endif DF.Detach(); return EXIT_FAILURE; } // Get some basics needed for full access proc = DF.getProcess(); meminfo = proc->getDescriptor(); // Get the object name/ID mapping //FIXME: work on the 'supported features' system required // Check availability of required addresses and offsets (doing custom stuff here) items = meminfo->getAddress("items"); item_material_offset = meminfo->getOffset("item_materials"); if( !items || ! item_material_offset) { cout << "Items not supported for this DF version, exiting" << endl; #ifndef LINUX_BUILD cin.ignore(); #endif DF.Detach(); return EXIT_FAILURE; } items_vector = new DFHack::DfVector (proc->readVector (items, 4)); for(uint32_t i = 0; i < items_vector->getSize(); i++) { // get pointer to object temp = * (uint32_t *) items_vector->at (i); // read object proc->read (temp, sizeof (DFHack::t_item_df40d), (uint8_t *) &item_40d); // resolve object type type = -1; // skip things we can't identify if(!meminfo->resolveObjectToClassID (temp, type)) continue; string classname; if(!meminfo->resolveClassIDToClassname (type, classname)) continue; if(classname == "item_trapparts") { proc->read (temp + item_material_offset, sizeof (DFHack::t_matglossPair), (uint8_t *) &item_40d_material); cout << dec << "Mechanism at x:" << item_40d.x << " y:" << item_40d.y << " z:" << item_40d.z << " ID:" << item_40d.ID << endl; if (item_40d_material.index != bauxiteIndex) { item_40d_material.index = bauxiteIndex; proc->write (temp + item_material_offset, sizeof (DFHack::t_matglossPair), (uint8_t *) &item_40d_material); converted++; } found++; } } if (found == 0) { cout << "No mechanisms to convert" << endl; } else { cout << found << " mechanisms found" << endl; cout << converted << " mechanisms converted" << endl; } DF.Resume(); DF.Detach(); delete items_vector; #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); #endif return 0; }