diff --git a/dfhack/include/modules/Creatures.h b/dfhack/include/modules/Creatures.h index 38ed7df56..85d4f552b 100644 --- a/dfhack/include/modules/Creatures.h +++ b/dfhack/include/modules/Creatures.h @@ -344,7 +344,7 @@ namespace DFHack t_attrib recuperation; t_attrib disease_resistance; int32_t squad_leader_id; - uint8_t sex; + uint8_t sex; // really a caste uint32_t pregnancy_timer; //Countdown timer to giving birth bool has_default_soul; t_soul defaultSoul; diff --git a/dfhack/include/modules/Materials.h b/dfhack/include/modules/Materials.h index 0161d02a1..d046aff26 100644 --- a/dfhack/include/modules/Materials.h +++ b/dfhack/include/modules/Materials.h @@ -36,7 +36,7 @@ namespace DFHack char plural[128]; char adjective[128]; }; - + // this doesn't transfer well across the shm gap... struct t_creaturetype { char rawname[128]; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a00ac1662..f388f6ab1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -69,10 +69,10 @@ TARGET_LINK_LIBRARIES(dftreedump dfhack) ADD_EXECUTABLE(dfspatterdump spatterdump.cpp) TARGET_LINK_LIBRARIES(dfspatterdump dfhack) -# catsplosion - Makes every cat pregnant, and almost due... +# catsplosion - Accelerates pregnancy # Author: Zhentar -# ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp) -# TARGET_LINK_LIBRARIES(dfcatsplosion dfhack) +ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp) +TARGET_LINK_LIBRARIES(dfcatsplosion dfhack) IF(UNIX) SET(CURSES_NEED_WIDE "YES") diff --git a/examples/catsplosion.cpp b/examples/catsplosion.cpp index ba764d513..90fabf180 100644 --- a/examples/catsplosion.cpp +++ b/examples/catsplosion.cpp @@ -21,28 +21,34 @@ using namespace std; #include #include #include +#include +#include - -vector creaturestypes; -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 s_creatures; +using namespace DFHack; int main ( int argc, char** argv ) { + vector creaturestypes; + 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 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") + 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(back_inserter(s_creatures), "any number of creatures") >>help(); - + + // make the creature list unique + s_creatures.unique(); + if (!as.isOk()) { cout << as.errorLog(); @@ -58,8 +64,9 @@ int main ( int argc, char** argv ) } else if (s_creatures.size() == 0 && showcreatures != 1) { - cout << as.usage(); - return(1); + cout << as.usage() << endl << "---------------------------------------" << endl; + cout << "Creature list empty, assuming CATs" << endl; + s_creatures.push_back("CAT"); } DFHack::API DF("Memory.xml"); @@ -78,9 +85,11 @@ int main ( int argc, char** argv ) proc = DF.getProcess(); mem = DF.getMemoryInfo(); + DFHack::Materials *Mats = DF.getMaterials(); + DFHack::Creatures *Cre = DF.getCreatures(); creature_pregnancy_offset = mem->getOffset("creature_pregnancy"); - if(!DF.ReadCreatureMatgloss(creaturestypes)) + if(!Mats->ReadCreatureTypesEx(creaturestypes)) { cerr << "Can't get the creature types." << endl; #ifndef LINUX_BUILD @@ -90,7 +99,7 @@ int main ( int argc, char** argv ) } uint32_t numCreatures; - if(!DF.InitReadCreatures(numCreatures)) + if(!Cre->Start(numCreatures)) { cerr << "Can't get creatures" << endl; #ifndef LINUX_BUILD @@ -104,68 +113,62 @@ int main ( int argc, char** argv ) string sextype; // shows all the creatures and returns. - if (showcreatures == 1) + + int maxlength = 0; + map > male_counts; + map > female_counts; + + // classify + for(uint32_t i =0;i < numCreatures;i++) { - int maxlength = 0; - map male_counts; - map female_counts; - for(uint32_t i =0;i < numCreatures;i++) + DFHack::t_creature creature; + Cre->ReadCreature(i,creature); + DFHack::t_creaturetype & crt = creaturestypes[creature.race]; + string castename = crt.castes[creature.sex].rawname; + if(castename == "FEMALE") { - DFHack::t_creature creature; - DF.ReadCreature(i,creature); - if(creature.sex == 1){ - male_counts[creaturestypes[creature.type].id]++; - female_counts[creaturestypes[creature.type].id]+=0; //auto initialize the females as well - } - else{ - female_counts[creaturestypes[creature.type].id]++; - male_counts[creaturestypes[creature.type].id]+=0; - } + female_counts[creaturestypes[creature.race].rawname].push_back(creature); + male_counts[creaturestypes[creature.race].rawname].size(); } - cout << "Type\t\t\tMale #\tFemale #" << endl; - for(map::iterator it1 = male_counts.begin();it1!=male_counts.end();it1++) + else // male, other, etc. { - cout << it1->first << "\t\t" << it1->second << "\t" << female_counts[it1->first] << endl; + male_counts[creaturestypes[creature.race].rawname].push_back(creature); + female_counts[creaturestypes[creature.race].rawname].size(); //auto initialize the females as well } - return(1); } - - for(uint32_t i = 0; i < numCreatures && totalchanged != maxpreg; i++) + + // print (optional) + if (showcreatures == 1) { - DFHack::t_creature creature; - DF.ReadCreature(i,creature); - if (showcreatures == 1) + cout << "Type\t\tMale #\tFemale #" << endl; + for(map >::iterator it1 = male_counts.begin();it1!=male_counts.end();it1++) { - if (creature.sex == 0) { sextype = "Female"; } else { sextype = "Male";} - cout << string(creaturestypes[creature.type].id) << ":" << sextype << "" << endl; + cout << it1->first << "\t\t" << it1->second.size() << "\t" << female_counts[it1->first].size() << endl; } - else + } + + // process + for (list::iterator it = s_creatures.begin(); it != s_creatures.end(); ++it) + { + std::string clinput = *it; + std::transform(clinput.begin(), clinput.end(), clinput.begin(), ::toupper); + vector &females = female_counts[clinput]; + uint32_t sz_fem = females.size(); + totalcount += sz_fem; + for(uint32_t i = 0; i < sz_fem && totalchanged != maxpreg; i++) { - s_creatures.unique(); - for (list::iterator it = s_creatures.begin(); it != s_creatures.end(); ++it) + t_creature & female = females[i]; + uint32_t preg_timer = proc->readDWord(female.origin + creature_pregnancy_offset); + if(preg_timer != 0) { - std::string clinput = *it; - std::transform(clinput.begin(), clinput.end(), clinput.begin(), ::toupper); - if(string(creaturestypes[creature.type].id) == clinput) - { - if((femaleonly == 1 && creature.sex == 0) || (femaleonly != 1)) - { - proc->writeDWord(creature.origin + creature_pregnancy_offset, rand() % 100 + 1); - totalchanged+=1; - totalcount+=1; - } - else - { - totalcount+=1; - } - } + proc->writeDWord(female.origin + creature_pregnancy_offset, rand() % 100 + 1); + totalchanged++; } } } - cout << totalchanged << " animals impregnated out of a possible " << totalcount << "." << endl; - - DF.FinishReadCreatures(); + cout << totalchanged << " pregnancies accelerated. Total creatures checked: " << totalcount << "." << endl; + Cre->Finish(); DF.Detach(); #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; diff --git a/examples/creaturedump.cpp b/examples/creaturedump.cpp index 5bd8de0a8..8d3f88507 100644 --- a/examples/creaturedump.cpp +++ b/examples/creaturedump.cpp @@ -350,7 +350,7 @@ void printCreature(DFHack::API & DF, const DFHack::t_creature & creature) } -int main (void) +int main (int numargs, char ** args) { DFHack::API DF("Memory.xml"); try @@ -365,6 +365,9 @@ int main (void) #endif return 1; } + string check = ""; + if(numargs == 2) + check = args[1]; DFHack::Creatures * Creatures = DF.getCreatures(); DFHack::Materials * Materials = DF.getMaterials(); @@ -407,7 +410,7 @@ int main (void) { DFHack::t_creature temp; Creatures->ReadCreature(i,temp); - if(string(creaturestypes[temp.race].id) == "HORSE") + if(check.empty() || string(creaturestypes[temp.race].id) == check) { cout << "index " << i << " "; diff --git a/output/Memory.xml b/output/Memory.xml index ed726a1d9..4d50373c8 100644 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1135,7 +1135,9 @@ map_data_1b60_offset 0x1B9c 0X1F4 0X21C 0x238 - + + 0x28C + 0x290 0x464 - 0x28C - 0x290 0x464