diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 11bf09a83..e9b3fff41 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -4,7 +4,6 @@ SET(PROJECT_HDRS DFCommon.h DFDataModel.h DFHackAPI.h -DFHackAPIc.h DFMemAccess.h DFMemInfo.h DFProcessManager.h @@ -30,7 +29,6 @@ DFMemInfo.cpp DFProcess.cpp DFProcessManager.cpp DFHackAPI.cpp -DFHackAPIc.cpp DFTileTypes.cpp md5/md5.cpp md5/md5wrapper.cpp diff --git a/library/DFHackAPI.cpp b/library/DFHackAPI.cpp index 909d40e3c..de5d3ca34 100644 --- a/library/DFHackAPI.cpp +++ b/library/DFHackAPI.cpp @@ -26,6 +26,7 @@ distribution. # define BUILD_DFHACK_LIB #endif + #include "DFCommon.h" #include "DFVector.h" #include "DFHackAPI.h" @@ -658,7 +659,7 @@ uint32_t DFHackAPIImpl::InitReadCreatures() creature_squad_leader_id_offset = offset_descriptor->getOffset("creature_squad_leader_id"); creature_money_offset = offset_descriptor->getOffset("creature_money"); creature_current_job_offset = offset_descriptor->getOffset("creature_current_job"); - creature_current_job_id_offset = offset_descriptor->getOffset("creature_current_job_id"); + creature_current_job_id_offset = offset_descriptor->getOffset("current_job_id"); creature_strength_offset = offset_descriptor->getOffset("creature_strength"); creature_agility_offset = offset_descriptor->getOffset("creature_agility"); creature_toughness_offset = offset_descriptor->getOffset("creature_toughness"); @@ -686,18 +687,17 @@ uint32_t DFHackAPIImpl::InitReadCreatures() ); p_cre = new DfVector(dm->readVector(creatures, 4)); InitReadNameTables(); - return p_cre->getSize(); } //This code was mostly adapted fromh dwarftherapist by chmod -string DFHackAPIImpl::getLastName(const uint32_t &index, bool use_generic) +string DFHackAPIImpl::getLastNameByAddress(const uint32_t &address, bool use_generic) { string out; uint32_t wordIndex; for (int i = 0; i<7;i++) { - MreadDWord(index+i*4, wordIndex); + MreadDWord(address+i*4, wordIndex); if(wordIndex == 0xFFFFFFFF) { break; @@ -718,18 +718,53 @@ string DFHackAPIImpl::getLastName(const uint32_t &index, bool use_generic) return out; } -string DFHackAPIImpl::getProfession(const uint32_t &index) +string DFHackAPIImpl::getSquadNameByAddress(const uint32_t &address, bool use_generic) +{ + string out; + uint32_t wordIndex; + for (int i = 0; i<6;i++) + { + MreadDWord(address+i*4, wordIndex); + if(wordIndex == 0xFFFFFFFF) + { + continue; + } + if(wordIndex == 0) + { + break; + } + if(use_generic) + { + uint32_t genericPtr; + p_generic->read(wordIndex,(uint8_t *)&genericPtr); + out.append(dm->readSTLString(genericPtr)); + } + else + { + if(i == 4) // There will be a space in game if there is a name in the last + { + out.append(" "); + } + uint32_t transPtr; + p_dwarf_names->read(wordIndex,(uint8_t *)&transPtr); + out.append(dm->readSTLString(transPtr)); + } + } + return out; +} + +string DFHackAPIImpl::getProfessionByAddress(const uint32_t &address) { string profession; - uint8_t profId = MreadByte(index); + uint8_t profId = MreadByte(address); profession = offset_descriptor->getProfession(profId); return profession; } -string DFHackAPIImpl::getJob(const uint32_t &index) +string DFHackAPIImpl::getCurrentJobByAddress(const uint32_t &address) { string job; - uint32_t jobIdAddr = MreadDWord(index); + uint32_t jobIdAddr = MreadDWord(address); if(jobIdAddr != 0) { uint8_t jobId = MreadByte(jobIdAddr+creature_current_job_id_offset); @@ -742,6 +777,103 @@ string DFHackAPIImpl::getJob(const uint32_t &index) return job; } +string DFHackAPIImpl::getLastName(const uint32_t &index, bool use_generic=false) +{ + assert(creaturesInited); + uint32_t temp; + // read pointer from vector at position + p_cre->read(index,(uint8_t *)&temp); + return(getLastNameByAddress(temp+creature_last_name_offset,use_generic)); +} +string DFHackAPIImpl::getSquadName(const uint32_t &index, bool use_generic=false) +{ + assert(creaturesInited); + uint32_t temp; + // read pointer from vector at position + p_cre->read(index,(uint8_t *)&temp); + return(getSquadNameByAddress(temp+creature_squad_name_offset,use_generic)); +} +string DFHackAPIImpl::getProfession(const uint32_t &index) +{ + assert(creaturesInited); + uint32_t temp; + // read pointer from vector at position + p_cre->read(index,(uint8_t *)&temp); + return(getProfessionByAddress(temp+creature_profession_offset)); +} +string DFHackAPIImpl::getCurrentJob(const uint32_t &index) +{ + assert(creaturesInited); + uint32_t temp; + // read pointer from vector at position + p_cre->read(index,(uint8_t *)&temp); + return(getCurrentJobByAddress(temp+creature_current_job_offset)); +} +vector DFHackAPIImpl::getSkills(const uint32_t &index) +{ + assert(creaturesInited); + uint32_t temp; + // read pointer from vector at position + p_cre->read(index,(uint8_t *)&temp); + vector tempSkillVec; + getSkillsByAddress(temp+creature_last_name_offset,tempSkillVec); + return(tempSkillVec); +} + +vector DFHackAPIImpl::getTraits(const uint32_t &index) +{ + assert(creaturesInited); + uint32_t temp; + // read pointer from vector at position + p_cre->read(index,(uint8_t *)&temp); + vector tempTraitVec; + getTraitsByAddress(temp+creature_traits_offset,tempTraitVec); + return(tempTraitVec); +} + +void DFHackAPIImpl::getSkillsByAddress(const uint32_t &address, vector & skills) +{ + DfVector* skillVector = new DfVector(dm->readVector(address,4)); + for(uint32_t i = 0; igetSize();i++) + { + uint32_t temp; + skillVector->read(i, (uint8_t *) &temp); + t_skill tempSkill; + tempSkill.id= MreadByte(temp); + tempSkill.name = offset_descriptor->getSkill(tempSkill.id); + tempSkill.experience = MreadWord(temp+8); + tempSkill.rating = MreadByte(temp+4); +// for (int j = 0; j < tempSkill.rating; ++j) { //add up all the experience per level +// tempSkill.experience += 500 + (j * 100); +// } + skills.push_back(tempSkill); + } +} + +void DFHackAPIImpl::getTraitsByAddress(const uint32_t &address, vector & traits) +{ + for(int i = 0; i < 30; i++) + { + t_trait tempTrait; + tempTrait.value =MreadWord(address+i*2); + tempTrait.displayTxt = offset_descriptor->getTrait(i,tempTrait.value); + tempTrait.name = offset_descriptor->getTraitName(i); + traits.push_back(tempTrait); + } +} + +void DFHackAPIImpl::getLaborsByAddress(const uint32_t &address, vector & labors) +{ + uint8_t laborArray[102] = {0}; + Mread(address, 102, laborArray); + for(int i = 0;i<102; i++) + { + t_labor tempLabor; + tempLabor.name = offset_descriptor->getLabor(i); + tempLabor.value = laborArray[i]; + labors.push_back(tempLabor); + } +} bool DFHackAPIImpl::ReadCreature(const uint32_t &index, t_creature & furball) { assert(creaturesInited); @@ -756,19 +888,24 @@ bool DFHackAPIImpl::ReadCreature(const uint32_t &index, t_creature & furball) // names furball.first_name = dm->readSTLString(temp+creature_first_name_offset); furball.nick_name = dm->readSTLString(temp+creature_nick_name_offset); - furball.trans_name = getLastName(temp+creature_last_name_offset); - furball.generic_name = getLastName(temp+creature_last_name_offset,true); + furball.trans_name = getLastNameByAddress(temp+creature_last_name_offset); + furball.generic_name = getLastNameByAddress(temp+creature_last_name_offset,true); + furball.generic_squad_name = getSquadNameByAddress(temp+creature_squad_name_offset, true); + furball.trans_squad_name = getSquadNameByAddress(temp+creature_squad_name_offset, false); furball.custom_profession = dm->readSTLString(temp+creature_custom_profession_offset); - furball.profession = getProfession(temp+creature_profession_offset); - furball.current_job = getJob(temp+creature_current_job_offset); - + furball.profession = getProfessionByAddress(temp+creature_profession_offset); + furball.current_job = getCurrentJobByAddress(temp+creature_current_job_offset); + getSkillsByAddress(temp+creature_skills_offset,furball.skills); + getTraitsByAddress(temp+creature_traits_offset,furball.traits); + getLaborsByAddress(temp+creature_labors_offset,furball.labors); + MreadDWord(temp + creature_happiness_offset, furball.happiness); MreadDWord(temp + creature_id_offset, furball.id); MreadDWord(temp + creature_agility_offset, furball.agility); MreadDWord(temp + creature_strength_offset, furball.strength); MreadDWord(temp + creature_toughness_offset, furball.toughness); MreadDWord(temp + creature_money_offset, furball.money); - MreadDWord(temp + creature_squad_leader_id_offset, furball.squad_leader_id); + furball.squad_leader_id = int32_t(MreadDWord(temp + creature_squad_leader_id_offset)); MreadByte(temp + creature_sex_offset, furball.sex); return true; } @@ -820,13 +957,20 @@ bool DFHackAPIImpl::Attach() { // detach all processes, destroy manager if(pm == NULL) + { pm = new ProcessManager(xml); // FIXME: handle bad XML better + } + // find a process (ProcessManager can find multiple when used properly) if(!pm->findProcessess()) + { return false; + } p = (*pm)[0]; if(!p->attach()) + { return false; // couldn't attach to process, no go + } offset_descriptor = p->getDescriptor(); dm = p->getDataModel(); // process is attached, everything went just fine... hopefully @@ -837,9 +981,13 @@ bool DFHackAPIImpl::Attach() bool DFHackAPIImpl::Detach() { if (!p->detach()) + { return false; + } if(pm != NULL) + { delete pm; + } pm = NULL; p = NULL; offset_descriptor = NULL; diff --git a/library/DFHackAPI.h b/library/DFHackAPI.h index a8fcc4c75..4e5bee35f 100644 --- a/library/DFHackAPI.h +++ b/library/DFHackAPI.h @@ -41,8 +41,6 @@ distribution. # endif #endif -#define BUILD_DFHACK_LIB - #include #include #include "integers.h" @@ -239,6 +237,13 @@ private: DfVector *p_generic; DfVector *p_dwarf_names; + string getLastNameByAddress(const uint32_t &address, bool use_generic=false); + string getSquadNameByAddress(const uint32_t &address, bool use_generic=false); + string getProfessionByAddress(const uint32_t &address); + string getCurrentJobByAddress(const uint32_t &address); + void getSkillsByAddress(const uint32_t &address, vector &); + void getTraitsByAddress(const uint32_t &address, vector &); + void getLaborsByAddress(const uint32_t &address, vector &); public: DFHackAPIImpl(const string path_to_xml); @@ -341,11 +346,16 @@ public: void InitReadNameTables(); void FinishReadNameTables(); - string getLastName(const uint32_t &index, bool use_generic=false); - string getProfession(const uint32_t &index); - string getJob(const uint32_t &index); - + void ReadRaw (const uint32_t &offset, const uint32_t &size, uint8_t *target); + + string getLastName(const uint32_t &index, bool); + string getSquadName(const uint32_t &index, bool); + string getProfession(const uint32_t &index); + string getCurrentJob(const uint32_t &index); + vector getSkills(const uint32_t &index); + vector getTraits(const uint32_t &index); + vector getLabors(const uint32_t &index); }; #endif diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 1f084b4f6..58b3579d9 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -29,7 +29,6 @@ distribution. #include "DFCommon.h" #include "DFMemInfo.h" #include -#include memory_info::memory_info() { @@ -109,8 +108,11 @@ memory_info::memory_info(const memory_info &old) classes = old.classes; classsubtypes = old.classsubtypes; classindex = old.classindex; - professions = old.professions; - jobs = old.jobs; + professions = old.professions; + jobs = old.jobs; + skills = old.skills; + traits = old.traits; + labors = old.labors; } @@ -158,24 +160,52 @@ void memory_info::setString (string key, string value) strings[key] = value; } +void memory_info::setLabor(string key, string value) +{ + uint32_t keyInt = strtol(key.c_str(), NULL, 10); + labors[keyInt] = value; +} void memory_info::setProfession (string key, string value) { - uint32_t keyInt = strtol(key.c_str(), NULL, 10); - if(professions.size() <= keyInt){ - professions.resize(keyInt+1); - } - professions[keyInt] = value; + uint32_t keyInt = strtol(key.c_str(), NULL, 10); + if(professions.size() <= keyInt){ + professions.resize(keyInt+1); + } + professions[keyInt] = value; } void memory_info::setJob (string key, string value) { - uint32_t keyInt = strtol(key.c_str(), NULL, 10); - if(jobs.size() <= keyInt){ - jobs.resize(keyInt+1); - } + uint32_t keyInt = strtol(key.c_str(), NULL, 10); + if(jobs.size() <= keyInt){ + jobs.resize(keyInt+1); + } jobs[keyInt] = value; } +void memory_info::setSkill (string key, string value) +{ + uint32_t keyInt = strtol(key.c_str(), NULL, 10); + if(skills.size() <= keyInt){ + skills.resize(keyInt+1); + } + skills[keyInt] = value; +} + +void memory_info::setTrait(string key,string value,string zero,string one,string two,string three,string four,string five) +{ + uint32_t keyInt = strtol(key.c_str(), NULL, 10); + if(traits.size() <= keyInt){ + traits.resize(keyInt+1); + } + traits[keyInt].push_back(zero); + traits[keyInt].push_back(one); + traits[keyInt].push_back(two); + traits[keyInt].push_back(three); + traits[keyInt].push_back(four); + traits[keyInt].push_back(five); + traits[keyInt].push_back(value); +} // FIXME: next three methods should use some kind of custom container so it doesn't have to search so much. void memory_info::setClass (const char * name, const char * vtable) @@ -392,24 +422,70 @@ uint32_t memory_info::getHexValue (string key) // Get Profession string memory_info::getProfession (uint32_t key) { - if(professions.size() > key) - { - return professions[key]; - } - else{ - return string(""); - } + if(professions.size() > key) + { + return professions[key]; + } + else{ + return string(""); + } } // Get Job string memory_info::getJob (uint32_t key) { - if(jobs.size() > key){ - return jobs[key]; + if(jobs.size() > key){ + return jobs[key]; + } + return string("Job Does Not Exist"); +} + +string memory_info::getSkill (uint32_t key) +{ + if(skills.size() > key){ + return skills[key]; + } + return string("Skill is not Defined"); +} + +string memory_info::getTrait (uint32_t key, uint32_t absVal) +{ + if(traits.size() > key){ + int diff = abs(absVal-50); + if(diff < 10){ + return string(""); + } + if (absVal >= 91) + return traits[key][5]; + else if (absVal >= 76) + return traits[key][4]; + else if (absVal >= 61) + return traits[key][3]; + else if (absVal >= 25) + return traits[key][2]; + else if (absVal >= 10) + return traits[key][1]; + else + return traits[key][0]; + } + return string("Trait is not Defined"); +} + +string memory_info::getTraitName(uint32_t key) +{ + if(traits.size() > key){ + return traits[key][traits[key].size()-1]; } - return string("Job Does Not Exist"); + return string("Trait is not Defined"); } +string memory_info::getLabor (uint32_t key) +{ + if(labors.count(key)){ + return labors[key]; + } + return string(""); +} // Reset everything void memory_info::flush() diff --git a/library/DFMemInfo.h b/library/DFMemInfo.h index 3968225fb..853be5a7f 100644 --- a/library/DFMemInfo.h +++ b/library/DFMemInfo.h @@ -65,6 +65,10 @@ public: string getString (string); string getProfession(uint32_t); string getJob(uint32_t); + string getSkill (uint32_t); + string getTrait (uint32_t, uint32_t); + string getTraitName(uint32_t); + string getLabor (uint32_t); void setVersion(const char *); void setVersion(string); @@ -91,6 +95,9 @@ public: void setProfession(string, string); void setJob(string, string); + void setSkill(string, string); + void setTrait(string,string,string,string,string,string,string,string); + void setLabor(string, string); void RebaseVTable(int32_t offset); void setClass (const char * name, const char * vtable); @@ -111,6 +118,9 @@ private: vector professions; vector jobs; + vector skills; + vector< vector > traits; + map labors; vector classes; vector > classsubtypes; diff --git a/library/DFProcessManager.cpp b/library/DFProcessManager.cpp index 499b21730..1f0aef5b1 100644 --- a/library/DFProcessManager.cpp +++ b/library/DFProcessManager.cpp @@ -449,6 +449,18 @@ void ProcessManager::ParseEntry (TiXmlElement* entry, memory_info& mem, map Attribute("level_0"),pMemEntry->Attribute("level_1"),pMemEntry->Attribute("level_2"),pMemEntry->Attribute("level_3"),pMemEntry->Attribute("level_4"),pMemEntry->Attribute("level_5")); + } + else if (type == "Labor") + { + mem.setLabor(value,name); + } else { cerr << "Unknown MemInfo type: " << type << endl; diff --git a/library/DFTypes.h b/library/DFTypes.h index 8a7cd6d81..47abf546f 100644 --- a/library/DFTypes.h +++ b/library/DFTypes.h @@ -380,6 +380,26 @@ union t_creaturflags2 } bits; }; +struct t_labor +{ + string name; + uint8_t value; +}; +struct t_skill +{ + string name; + uint16_t id; + uint32_t experience; + uint16_t rating; +}; + +struct t_trait +{ + uint16_t value; + string displayTxt; + string name; +}; + struct t_creature { uint16_t x; @@ -393,6 +413,8 @@ struct t_creature string last_name; string trans_name; string generic_name; + string generic_squad_name; + string trans_squad_name; string profession; string custom_profession; string current_job; @@ -402,9 +424,13 @@ struct t_creature uint32_t strength; uint32_t toughness; uint32_t money; - uint32_t squad_leader_id; + int32_t squad_leader_id; uint8_t sex; + vector skills; + vector traits; + vector labors; }; + // TODO: research this further? consult DF hacker wizards? union t_designation { diff --git a/library/DFHackAPIc.cpp b/library/unmaintained/DFHackAPIc.cpp similarity index 100% rename from library/DFHackAPIc.cpp rename to library/unmaintained/DFHackAPIc.cpp diff --git a/library/DFHackAPIc.h b/library/unmaintained/DFHackAPIc.h similarity index 100% rename from library/DFHackAPIc.h rename to library/unmaintained/DFHackAPIc.h diff --git a/output/Memory.xml b/output/Memory.xml index 9a9c11310..53f836283 100644 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -354,6 +354,187 @@ 200 201 202 + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + + 0 + 66 + 11 + 10 + 13 + 12 + 14 + 15 + 16 + 20 + 38 + 19 + 41 + 39 + 43 + 42 + 40 + 44 + 45 + 48 + 27 + 49 + 21 + 47 + 26 + 46 + 50 + 23 + 18 + 30 + 32 + 71 + 33 + 34 + 70 + 31 + 28 + 69 + 25 + 22 + 29 + 72 + 35 + 36 + 37 + 67 + 73 + 64 + 65 + 17 + 8 + 2 + 6 + 4 + 1 + 5 + 7 + 9 + 3 + 24 + 51 + 52 + 53 + 54 + 55 + 57 + -1 + diff --git a/tools/creaturedump.cpp b/tools/creaturedump.cpp index 55b46d4ca..e9b628235 100644 --- a/tools/creaturedump.cpp +++ b/tools/creaturedump.cpp @@ -43,7 +43,7 @@ int main (void) uint32_t numCreatures = DF.InitReadCreatures(); for(uint32_t i = 0; i < numCreatures; i++) { - t_creature temp; + t_creature temp = {0}; DF.ReadCreature(i, temp); cout << "creature type " << creaturestypes[temp.type].id << ", position:" << temp.x << " " << temp.y << " "<< temp.z << endl; bool addendl = false; @@ -88,7 +88,10 @@ int main (void) addendl = false; } cout << ", happiness: " << temp.happiness << ", strength: " << temp.strength << ", agility: " - << temp.agility << ", toughness: " << temp.toughness << ", money: " << temp.money; + << temp.agility << ", toughness: " << temp.toughness << ", money: " << temp.money << ", id: " << temp.id; + if(temp.squad_leader_id != -1){ + cout << ", squad_leader_id: " << temp.squad_leader_id; + } cout << ", sex"; if(temp.sex == 0){ cout << ", Female"; @@ -98,6 +101,14 @@ int main (void) } cout << endl; + //skills + for(unsigned int i = 0; i < temp.skills.size();i++){ + if(i > 0){ + cout << ", "; + } + cout << temp.skills[i].name << ": " << temp.skills[i].rating; + } + /* * FLAGS 1 */