Maps::Maps(DFContextShared* _d) { d = new Private; d->d = _d; Process *p = d->owner = _d->p; d->Inited = d->Started = false; DFHack::memory_info * mem = p->getDescriptor(); Server::Maps::maps_offsets &off = d->offsets; // get the offsets once here off.map_offset = mem->getAddress ("map_data"); off.x_count_offset = mem->getAddress ("x_count_block"); off.y_count_offset = mem->getAddress ("y_count_block"); off.z_count_offset = mem->getAddress ("z_count_block"); off.tile_type_offset = mem->getOffset ("map_data_type"); off.designation_offset = mem->getOffset ("map_data_designation"); off.occupancy_offset = mem->getOffset("map_data_occupancy"); off.biome_stuffs = mem->getOffset ("map_data_biome_stuffs"); off.veinvector = mem->getOffset ("map_data_vein_vector"); off.local_feature_offset = mem->getOffset ("map_data_feature_local"); off.global_feature_offset = mem->getOffset ("map_data_feature_global"); off.temperature1_offset = mem->getOffset ("map_data_temperature1_offset"); off.temperature2_offset = mem->getOffset ("map_data_temperature2_offset"); off.region_x_offset = mem->getAddress ("region_x"); off.region_y_offset = mem->getAddress ("region_y"); off.region_z_offset = mem->getAddress ("region_z"); off.world_regions = mem->getAddress ("ptr2_region_array"); off.region_size = mem->getHexValue ("region_size"); off.region_geo_index_offset = mem->getOffset ("region_geo_index_off"); off.geolayer_geoblock_offset = mem->getOffset ("geolayer_geoblock_offset"); off.world_geoblocks_vector = mem->getAddress ("geoblock_vector"); off.type_inside_geolayer = mem->getOffset ("type_inside_geolayer"); off.world_size_x = mem->getAddress ("world_size_x"); off.world_size_y = mem->getAddress ("world_size_y"); // these can fail and will be found when looking at the actual veins later // basically a cache off.vein_ice_vptr = 0; mem->resolveClassnameToVPtr("block_square_event_frozen_liquid", off.vein_ice_vptr); off.vein_mineral_vptr = 0; mem->resolveClassnameToVPtr("block_square_event_mineral",off.vein_mineral_vptr); // upload offsets to SHM server if possible d->maps_module = 0; if(p->getModuleIndex("Maps2010",1,d->maps_module)) { // supply the module with offsets so it can work with them Server::Maps::maps_offsets *off2 = SHMDATA(Server::Maps::maps_offsets); memcpy(off2, &(d->offsets), sizeof(Server::Maps::maps_offsets)); full_barrier const uint32_t cmd = Server::Maps::MAP_INIT + (d->maps_module << 16); p->SetAndWait(cmd); } d->Inited = true; }
int main ( int argc, char** argv ) { DFHack::memory_info *mem; DFHack::Process *proc; uint32_t creature_pregnancy_offset; //bool femaleonly = 0; bool showcreatures = 0; int maxpreg = 1000; // random start value, since its not required and im not sure how to set it to infinity list<string> s_creatures; // parse input, handle this nice and neat before we get to the connecting argstream as(argc,argv); as // >>option('f',"female",femaleonly,"Impregnate females only") >>option('s',"show",showcreatures,"Show creature list (read only)") >>parameter('m',"max",maxpreg,"The maximum limit of pregnancies ", false) >>values<string>(back_inserter(s_creatures), "any number of creatures") >>help(); // make the creature list unique s_creatures.unique(); if (!as.isOk()) { cout << as.errorLog(); return(0); } else if (as.helpRequested()) { cout<<as.usage()<<endl; return(1); } else if(showcreatures==1) { } else if (s_creatures.size() == 0 && showcreatures != 1) { cout << as.usage() << endl << "---------------------------------------" << endl; cout << "Creature list empty, assuming CATs" << endl; s_creatures.push_back("CAT"); } 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; } proc = DF->getProcess(); mem = DF->getMemoryInfo(); DFHack::Materials *Mats = DF->getMaterials(); DFHack::Creatures *Cre = DF->getCreatures(); creature_pregnancy_offset = mem->getOffset("creature_pregnancy"); if(!Mats->ReadCreatureTypesEx()) { cerr << "Can't get the creature types." << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } uint32_t numCreatures; if(!Cre->Start(numCreatures)) { cerr << "Can't get creatures" << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } int totalcount=0; int totalchanged=0; string sextype; // shows all the creatures and returns. int maxlength = 0; map<string, vector <t_creature> > male_counts; map<string, vector <t_creature> > female_counts; // classify for(uint32_t i =0;i < numCreatures;i++) { DFHack::t_creature creature; Cre->ReadCreature(i,creature); DFHack::t_creaturetype & crt = Mats->raceEx[creature.race]; string castename = crt.castes[creature.sex].rawname; if(castename == "FEMALE") { female_counts[Mats->raceEx[creature.race].rawname].push_back(creature); male_counts[Mats->raceEx[creature.race].rawname].size(); } else // male, other, etc. { male_counts[Mats->raceEx[creature.race].rawname].push_back(creature); female_counts[Mats->raceEx[creature.race].rawname].size(); //auto initialize the females as well } } // print (optional) if (showcreatures == 1) { cout << "Type\t\tMale #\tFemale #" << endl; for(map<string, vector <t_creature> >::iterator it1 = male_counts.begin();it1!=male_counts.end();it1++) { cout << it1->first << "\t\t" << it1->second.size() << "\t" << female_counts[it1->first].size() << endl; } } // process for (list<string>::iterator it = s_creatures.begin(); it != s_creatures.end(); ++it) { std::string clinput = *it; std::transform(clinput.begin(), clinput.end(), clinput.begin(), ::toupper); vector <t_creature> &females = female_counts[clinput]; uint32_t sz_fem = females.size(); totalcount += sz_fem; for(uint32_t i = 0; i < sz_fem && totalchanged != maxpreg; i++) { t_creature & female = females[i]; uint32_t preg_timer = proc->readDWord(female.origin + creature_pregnancy_offset); if(preg_timer != 0) { proc->writeDWord(female.origin + creature_pregnancy_offset, rand() % 100 + 1); totalchanged++; } } } cout << totalchanged << " pregnancies accelerated. Total creatures checked: " << totalcount << "." << endl; Cre->Finish(); 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; }