dfhack/tools/customCreatureNameProf.cpp

387 lines
12 KiB
C++

2009-12-12 12:52:30 -07:00
// Creature dump
#include <iostream>
#include <sstream>
#include <climits>
#include <integers.h>
#include <vector>
using namespace std;
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFMemInfo.h>
template <typename T>
void print_bits ( T val, std::ostream& out )
{
T n_bits = sizeof ( val ) * CHAR_BIT;
for ( unsigned i = 0; i < n_bits; ++i ) {
out<< !!( val & 1 ) << " ";
val >>= 1;
}
}
vector <string> buildingtypes;
map<string, vector<string> > names;
uint32_t numCreatures;
2009-12-12 17:47:58 -07:00
vector<DFHack::t_matgloss> creaturestypes;
2009-12-12 12:52:30 -07:00
void printDwarves(DFHack::API & DF)
{
int dwarfCounter = 0;
for(uint32_t i = 0; i < numCreatures; i++)
{
2009-12-12 17:47:58 -07:00
DFHack::t_creature temp;
2009-12-12 12:52:30 -07:00
DF.ReadCreature(i, temp);
string type = creaturestypes[temp.type].id;
if(type == "DWARF" && !temp.flags1.bits.dead && !temp.flags2.bits.killed){
cout << i << ":";
if(temp.nick_name[0])
{
cout << temp.nick_name;
}
else{
cout << temp.first_name;
}
string transName = DF.TranslateName(temp.last_name,names,creaturestypes[temp.type].id);
cout << " " << temp.custom_profession; //transName;
if(dwarfCounter%3 != 2){
cout << '\t';
}
else{
cout << endl;
}
dwarfCounter++;
}
}
}
2009-12-12 17:47:58 -07:00
bool getDwarfSelection(DFHack::API & DF, DFHack::t_creature & toChange,string & changeString, string & commandString,int & eraseAmount,int &dwarfNum,bool &isName)
2009-12-12 12:52:30 -07:00
{
DF.ForceResume();
static string lastText;
bool dwarfSuccess = false;
while(!dwarfSuccess)
{
string input;
cout << "\nSelect Dwarf to Change or q to Quit" << endl;
getline (cin, input);
if(input == "q")
{
return false;
}
else if(input == "r")
{
DF.Suspend();
printDwarves(DF);
DF.Resume();
}
else if(!input.empty())
{
int num;
stringstream(input) >> num;//= atol(input.c_str());
DF.Suspend();
dwarfSuccess = DF.ReadCreature(num,toChange);
DF.Resume();
string type = creaturestypes[toChange.type].id;
if(type != "DWARF"){
dwarfSuccess = false;
}
else
{
dwarfNum = num;
}
}
}
bool changeType = false;
while(!changeType)
{
string input;
cout << "\n(n)ickname or (p)rofession?" << endl;
getline(cin, input);
if(input == "q"){
return false;
}
if(input == "n"){
commandString = "pzyn";
eraseAmount = string(toChange.nick_name).length();
changeType = true;
isName = true;
}
else if(input == "p"){
commandString = "pzyp";
eraseAmount = string(toChange.custom_profession).length();
changeType = true;
isName = false;
}
}
bool changeValue = false;
while(!changeValue)
{
string input;
cout << "value to change to?" << endl;
getline(cin, input);
if(input == "q"){
return false;
}
if(!lastText.empty() && input.empty()){
changeValue = true;
}
else if( !input.empty()){
lastText = input;
changeValue = true;
}
}
changeString = lastText;
return true;
}
bool waitTillChanged(DFHack::API &DF, int creatureToCheck, string changeValue, bool isName)
{
2009-12-22 14:19:39 -07:00
DFHack::DFWindow * w = DF.getWindow();
2009-12-12 12:52:30 -07:00
DF.Suspend();
2009-12-12 17:47:58 -07:00
DFHack::t_creature testCre;
2009-12-12 12:52:30 -07:00
DF.ReadCreature(creatureToCheck,testCre);
int tryCount = 0;
if(isName)
{
while(testCre.nick_name != changeValue && tryCount <50)
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeSpecial(DFHack::WAIT,1,100);
2009-12-12 12:52:30 -07:00
DF.Suspend();
DF.ReadCreature(creatureToCheck,testCre);
tryCount++;
}
}
else
{
while(testCre.custom_profession != changeValue && tryCount < 50)
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeSpecial(DFHack::WAIT,1,100);
2009-12-12 12:52:30 -07:00
DF.Suspend();
DF.ReadCreature(creatureToCheck,testCre);
tryCount++;
}
}
if(tryCount >= 50){
cerr << "Something went wrong, make sure that DF is at the correct screen";
return false;
}
DF.Resume();
2009-12-12 12:52:30 -07:00
return true;
}
bool waitTillScreenState(DFHack::API &DF, string screenState,bool EqualTo=true)
2009-12-12 12:52:30 -07:00
{
2009-12-22 14:19:39 -07:00
DFHack::DFWindow * w = DF.getWindow();
2009-12-12 17:47:58 -07:00
DFHack::t_viewscreen current;
2009-12-12 12:52:30 -07:00
DF.Suspend();
DF.ReadViewScreen(current);
int tryCount = 0;
while(((EqualTo && buildingtypes[current.type] != screenState) || (!EqualTo && buildingtypes[current.type] == screenState)) && tryCount < 50)
2009-12-22 14:19:39 -07:00
{
DF.Resume();
w->TypeSpecial(DFHack::WAIT,1,100);
2009-12-12 12:52:30 -07:00
DF.Suspend();
DF.ReadViewScreen(current);
tryCount++;
}
if(tryCount >= 50){
cerr << "Something went wrong, DF at " << buildingtypes[current.type] << endl;
return false;
}
DF.Resume();
2009-12-12 12:52:30 -07:00
return true;
}
bool waitTillCursorState(DFHack::API &DF, bool On)
{
2009-12-22 14:19:39 -07:00
DFHack::DFWindow * w = DF.getWindow();
2009-12-12 12:52:30 -07:00
int32_t x,y,z;
int tryCount = 0;
DF.Suspend();
bool cursorResult = DF.getCursorCoords(x,y,z);
while(tryCount < 50 && On && !cursorResult || !On && cursorResult)
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeSpecial(DFHack::WAIT,1,100);
2009-12-12 12:52:30 -07:00
tryCount++;
DF.Suspend();
cursorResult = DF.getCursorCoords(x,y,z);
}
if(tryCount >= 50)
{
cerr << "Something went wrong, cursor at x: " << x << " y: " << y << " z: " << z << endl;
return false;
}
DF.Resume();
return true;
}
bool waitTillMenuState(DFHack::API &DF, uint32_t menuState,bool EqualTo=true)
{
int tryCount = 0;
DFHack::DFWindow * w = DF.getWindow();
DF.Suspend();
uint32_t testState = DF.ReadMenuState();
while(tryCount < 50 && ((EqualTo && menuState != testState) || (!EqualTo && menuState == testState)))
{
DF.Resume();
w->TypeSpecial(DFHack::WAIT,1,100);
tryCount++;
DF.Suspend();
testState = DF.ReadMenuState();
}
if(tryCount >= 50)
{
cerr << "Something went wrong, menuState: "<<testState << endl;
return false;
}
DF.Resume();
return true;
}
bool moveToBaseWindow(DFHack::API &DF)
{
DFHack::DFWindow * w = DF.getWindow();
DFHack::t_viewscreen current;
DF.ReadViewScreen(current);
while(buildingtypes[current.type] != string("viewscreen_dwarfmode")){
w->TypeSpecial(DFHack::F9); // cancel out of text input in names
// DF.TypeSpecial(DFHack::ENTER); // cancel out of text input in hotkeys
w->TypeSpecial(DFHack::SPACE); // should move up a level
if(!waitTillScreenState(DF,buildingtypes[current.type],false)) return false; // wait until screen changes from current
DF.ReadViewScreen(current);
}
if(DF.ReadMenuState() != 0){// if menu state != 0 then there is a menu, so escape it
w->TypeSpecial(DFHack::F9);w->TypeSpecial(DFHack::ENTER); // exit out of any text prompts
w->TypeSpecial(DFHack::SPACE); // go back to base state
if(!waitTillMenuState(DF,0))return false;
}
DF.Resume();
return true;
}
bool setCursorToCreature(DFHack::API &DF)
{
DFHack::DFWindow * w = DF.getWindow();
int32_t x,y,z;
DF.Suspend();
DF.getCursorCoords(x,y,z);
DF.Resume();
if(x == -30000){
w->TypeStr("v");
if(!waitTillCursorState(DF,true)) return false;
}
else{ // reset the cursor to be the creature cursor
w->TypeSpecial(DFHack::SPACE);
if(!waitTillCursorState(DF,false)) return false;
w->TypeStr("v");
if(!waitTillCursorState(DF,true)) return false;
}
2009-12-12 12:52:30 -07:00
return true;
}
int main (void)
{
DFHack::API DF("Memory.xml");
if(!DF.Attach())
{
cerr << "DF not found" << endl;
return 1;
}
//Need buildingtypes for the viewscreen vtables, this really should not be just buildings, as viewscreen and items both use the same interface
uint32_t numBuildings = DF.InitReadBuildings(buildingtypes);
DFHack::memory_info mem = DF.getMemoryInfo();
// get stone matgloss mapping
if(!DF.ReadCreatureMatgloss(creaturestypes))
{
cerr << "Can't get the creature types." << endl;
return 1;
}
DF.InitReadNameTables(names);
numCreatures = DF.InitReadCreatures();
DF.InitViewAndCursor();
DF.Suspend();
printDwarves(DF);
2009-12-12 17:47:58 -07:00
DFHack::t_creature toChange;
2009-12-12 12:52:30 -07:00
string changeString,commandString;
int eraseAmount;
int toChangeNum;
bool isName;
2009-12-22 14:19:39 -07:00
DFHack::DFWindow * w = DF.getWindow();
2009-12-12 12:52:30 -07:00
while(getDwarfSelection(DF,toChange,changeString,commandString,eraseAmount,toChangeNum,isName))
{
start:
2009-12-12 12:52:30 -07:00
bool completed = false;
if(moveToBaseWindow(DF) && setCursorToCreature(DF))
2009-12-12 12:52:30 -07:00
{
DF.Suspend();
DF.setCursorCoords(toChange.x, toChange.y,toChange.z);
vector<uint32_t> underCursor;
while(!DF.getCurrentCursorCreatures(underCursor))
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeSpecial(DFHack::WAIT,1,100);
2009-12-12 12:52:30 -07:00
DF.Suspend();
DF.setCursorCoords(toChange.x, toChange.y,toChange.z);
DF.ReadCreature(toChangeNum,toChange);
2009-12-12 12:52:30 -07:00
}
//CurrentCursorCreatures gives the creatures in the order that you see them with the 'k' cursor.
//The 'v' cursor displays them in the order of last, then first,second,third and so on
//Pretty weird, but it works
//The only place that seems to display which creature is currently selected is on the stack, whose location is likely not static, so not usable
if(underCursor[underCursor.size()-1] != toChange.origin)
{
for(int i = 0;i<underCursor.size()-1;i++)
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeStr("v",100);
2009-12-12 12:52:30 -07:00
if(underCursor[i] == toChange.origin)
{
break;
}
}
}
DF.Resume();
2009-12-22 14:19:39 -07:00
w->TypeStr(commandString.c_str());
2009-12-12 12:52:30 -07:00
if(waitTillScreenState(DF,"viewscreen_customize_unit"))
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeSpecial(DFHack::BACK_SPACE,eraseAmount);
2009-12-12 12:52:30 -07:00
if(waitTillChanged(DF,toChangeNum,"",isName))
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeStr(changeString.c_str());
2009-12-12 12:52:30 -07:00
if(waitTillChanged(DF,toChangeNum,changeString,isName))
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeSpecial(DFHack::ENTER);
w->TypeSpecial(DFHack::SPACE); // should take you to unit screen if everything worked
2009-12-12 12:52:30 -07:00
if(waitTillScreenState(DF,"viewscreen_unit"))
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeSpecial(DFHack::SPACE);
2009-12-12 12:52:30 -07:00
if(waitTillScreenState(DF,"viewscreen_dwarfmode"))
{
2009-12-22 14:19:39 -07:00
DF.Resume();
w->TypeSpecial(DFHack::SPACE);
2009-12-12 12:52:30 -07:00
if(waitTillCursorState(DF,false))
{
completed = true;
}
}
}
}
}
}
}
if(!completed){
cerr << "Something went wrong, please reset DF to its original state, then press any key to continue" << endl;
goto start;
2009-12-12 12:52:30 -07:00
}
DF.Suspend();
printDwarves(DF);
}
return 0;
}