// some headers required for a plugin. Nothing special, just the basics. #include #include #include #include using namespace std; #define DFHACK_WANT_MISCUTILS #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace DFHack; using df::global::ui; using df::global::world; // our own, empty header. #include "dwarfexport.h" #include // Here go all the command declarations... // mostly to allow having the mandatory stuff on top of the file and commands on the bottom command_result export_dwarves (color_ostream &con, std::vector & parameters); DFHACK_PLUGIN("dwarfexport"); // Mandatory init function. If you have some global state, create it here. DFhackCExport command_result plugin_init (color_ostream &con, std::vector &commands) { // Fill the command list with your commands. commands.push_back(PluginCommand("dwarfexport", "Export dwarves to RuneSmith-compatible XML.", export_dwarves /*, true or false - true means that the command can't be used from non-interactive user interface'*/)); return CR_OK; } // This is called right before the plugin library is removed from memory. DFhackCExport command_result plugin_shutdown (color_ostream &con) { return CR_OK; } static const char* physicals[] = { "Strength", "Agility", "Toughness", "Endurance", "Recuperation", "DiseaseResistance", }; static const char* mentals[] = { "AnalyticalAbility", "Focus", "Willpower", "Creatvity", //Speeling deliberate "Intuition", "Patience", "Memory", "LinguisticAbility", "SpatialSense", "Musicality", "KinaestheticSense", "Empathy", "SocialAwareness", }; static void element(const char* name, const char* content, ostream& out, const char* extra_indent="") { out << extra_indent << " <" << name << ">" << content << "" << endl; } static void element(const char* name, const uint32_t content, ostream& out, const char* extra_indent="") { out << extra_indent << " <" << name << ">" << content << "" << endl; } static void printAttributes(color_ostream &con, df::unit* cre, ostream& out) { out << " " << endl; for (int i = 0; i < NUM_CREATURE_PHYSICAL_ATTRIBUTES; i++) { element(physicals[i], cre->body.physical_attrs[i].value, out, " "); } df::unit_soul * s = cre->status.current_soul; if (s) { for (int i = 0; i < NUM_CREATURE_MENTAL_ATTRIBUTES; i++) { element(mentals[i], s->mental_attrs[i].value, out, " "); } } out << " " << endl; } static void printTraits(color_ostream &con, df::unit* cre, ostream& out) { out << " " << endl; df::unit_soul * s = cre->status.current_soul; if (s) { FOR_ENUM_ITEMS(personality_facet_type,index) { out << " "; //FIXME: needs reimplementing trait string generation /* string trait = con->vinfo->getTrait(i, s->traits[i]); if (!trait.empty()) { out << trait.c_str(); } */ out << "" << endl; } } out << " " << endl; } static int32_t getCreatureAge(df::unit* cre) { int32_t yearDifference = *df::global::cur_year - cre->relations.birth_year; // If the birthday this year has not yet passed, subtract one year. // ASSUMPTION: birth_time is on the same scale as cur_year_tick if (cre->relations.birth_time >= *df::global::cur_year_tick) { yearDifference--; } return yearDifference; } static void printLabors(color_ostream &con, df::unit* cre, ostream& out) { // Using British spelling here, consistent with Runesmith out << " " << endl; FOR_ENUM_ITEMS(unit_labor, iCount) { if (cre->status.labors[iCount]) { // Get the caption for the labor index. element("Labour", ENUM_ATTR_STR(unit_labor, caption, iCount), out); } } out << " " << endl; } static void printSkill(color_ostream &con, df::unit_skill* skill, ostream& out) { out << " " << endl; element("Name", ENUM_ATTR_STR(job_skill, caption, skill->id), out); element("Level", skill->rating, out); out << " " << endl; } static void printSkills(color_ostream &con, df::unit* cre, ostream& out) { std::vector vSkills = cre->status.current_soul->skills; out << " " << endl; for (int iCount = 0; iCount < vSkills.size(); iCount++) { printSkill(con, vSkills.at(iCount), out); } out << " " << endl; } // GDC needs: // Name // Nickname // Sex // Attributes // Traits static void export_dwarf(color_ostream &con, df::unit* cre, ostream& out) { string info = cre->name.first_name; info += " "; info += Translation::TranslateName(&cre->name, false); info[0] = toupper(info[0]); con.print("Exporting %s\n", info.c_str()); out << " " << endl; element("Name", info.c_str(), out); element("Nickname", cre->name.nickname.c_str(), out); element("Sex", cre->sex == 0 ? "Female" : "Male", out); element("Age", getCreatureAge(cre), out); // Added age, active labors, and skills March 9, 2012 printAttributes(con, cre, out); printTraits(con, cre, out); printLabors(con, cre, out); printSkills(con, cre, out); out << " " << endl; } command_result export_dwarves (color_ostream &con, std::vector & parameters) { string filename; if (parameters.size() == 1) { filename = parameters[0]; } else { con.print("export \n"); return CR_OK; } ofstream outf(filename.c_str()); if (!outf) { con.printerr("Failed to open file %s\n", filename.c_str()); return CR_FAILURE; } CoreSuspender suspend; uint32_t race = ui->race_id; uint32_t civ = ui->civ_id; outf << "" << endl << "" << endl; for (int i = 0; i < world->units.all.size(); ++i) { df::unit* cre = world->units.all[i]; if (cre->race == race && cre->civ_id == civ) { export_dwarf(con, cre, outf); } } outf << "" << endl; return CR_OK; }