diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 8c3763245..45ccd46a9 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1277,6 +1277,30 @@ Units module Retrieves the profession color for the given race/caste using raws. +* ``dfhack.units.getGoalType(unit[,goalIndex])`` + + Retrieves the goal type of the dream that the given unit has. + By default the goal of the first dream is returned. + The goalIndex parameter may be used to retrieve additional dream goals. + Currently only one dream per unit is supported by Dwarf Fortress. + Support for multiple dreams may be added in future versions of Dwarf Fortress. + +* ``dfhack.units.getGoalName(unit[,goalIndex])`` + + Retrieves the short name describing the goal of the dream that the given unit has. + By default the goal of the first dream is returned. + The goalIndex parameter may be used to retrieve additional dream goals. + Currently only one dream per unit is supported by Dwarf Fortress. + Support for multiple dreams may be added in future versions of Dwarf Fortress. + +* ``dfhack.units.isGoalAchieved(unit[,goalIndex])`` + + Checks if given unit has achieved the goal of the dream. + By default the status of the goal of the first dream is returned. + The goalIndex parameter may be used to check additional dream goals. + Currently only one dream per unit is supported by Dwarf Fortress. + Support for multiple dreams may be added in future versions of Dwarf Fortress. + * ``dfhack.units.getStressCategory(unit)`` Returns a number from 0-6 indicating stress. 0 is most stressed; 6 is least. diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 25843875d..13c9386ff 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1604,6 +1604,9 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = { WRAPM(Units, getCasteProfessionName), WRAPM(Units, getProfessionColor), WRAPM(Units, getCasteProfessionColor), + WRAPM(Units, getGoalType), + WRAPM(Units, getGoalName), + WRAPM(Units, isGoalAchieved), WRAPM(Units, getSquadName), WRAPM(Units, isWar), WRAPM(Units, isHunter), diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index f5995583b..c719a60a9 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -32,6 +32,7 @@ distribution. #include "DataDefs.h" #include "df/caste_raw_flags.h" +#include "df/goal_type.h" #include "df/job_skill.h" #include "df/mental_attribute_type.h" #include "df/misc_trait_type.h" @@ -180,6 +181,10 @@ DFHACK_EXPORT std::string getCasteProfessionName(int race, int caste, df::profes DFHACK_EXPORT int8_t getProfessionColor(df::unit *unit, bool ignore_noble = false); DFHACK_EXPORT int8_t getCasteProfessionColor(int race, int caste, df::profession pid); +DFHACK_EXPORT df::goal_type getGoalType(df::unit *unit, int goalIndex = 0); +DFHACK_EXPORT std::string getGoalName(df::unit *unit, int goalIndex = 0); +DFHACK_EXPORT bool isGoalAchieved(df::unit *unit, int goalIndex = 0); + DFHACK_EXPORT std::string getSquadName(df::unit *unit); DFHACK_EXPORT df::activity_entry *getMainSocialActivity(df::unit *unit); diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index ddcfcd31e..d5c871f5b 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -61,6 +61,7 @@ using namespace std; #include "df/identity_type.h" #include "df/game_mode.h" #include "df/histfig_entity_link_positionst.h" +#include "df/histfig_relationship_type.h" #include "df/historical_entity.h" #include "df/historical_figure.h" #include "df/historical_figure_info.h" @@ -1438,6 +1439,47 @@ int8_t Units::getCasteProfessionColor(int race, int casteid, df::profession pid) return 3; } +df::goal_type Units::getGoalType(df::unit *unit, int goalIndex) +{ + CHECK_NULL_POINTER(unit); + + df::goal_type goal = df::goal_type::STAY_ALIVE; + if (unit->status.current_soul + && unit->status.current_soul->personality.dreams.size() > goalIndex) + { + goal = unit->status.current_soul->personality.dreams[goalIndex]->type; + } + return goal; +} + +std::string Units::getGoalName(df::unit *unit, int goalIndex) +{ + CHECK_NULL_POINTER(unit); + + df::goal_type goal = getGoalType(unit, goalIndex); + bool achieved_goal = isGoalAchieved(unit, goalIndex); + + std::string goal_name = achieved_goal ? ENUM_ATTR(goal_type, achieved_short_name, goal) : ENUM_ATTR(goal_type, short_name, goal); + if (goal == df::goal_type::START_A_FAMILY) { + std::string parent = ENUM_KEY_STR(histfig_relationship_type, histfig_relationship_type::Parent); + size_t start_pos = goal_name.find(parent); + if (start_pos != std::string::npos) { + df::histfig_relationship_type parent_type = isFemale(unit) ? histfig_relationship_type::Mother : histfig_relationship_type::Father; + goal_name.replace(start_pos, parent.length(), ENUM_KEY_STR(histfig_relationship_type, parent_type)); + } + } + return goal_name; +} + +bool Units::isGoalAchieved(df::unit *unit, int goalIndex) +{ + CHECK_NULL_POINTER(unit); + + return unit->status.current_soul + && unit->status.current_soul->personality.dreams.size() > goalIndex + && unit->status.current_soul->personality.dreams[goalIndex]->flags.whole != 0; +} + std::string Units::getSquadName(df::unit *unit) { CHECK_NULL_POINTER(unit); diff --git a/library/xml b/library/xml index 9fca46ccc..51e237b9b 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 9fca46ccca28e0948014b9d56a096ad7343473f1 +Subproject commit 51e237b9b2e667d48fbb793ac29d782d7326c39a diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index a013df335..ae7b3f800 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -32,6 +32,8 @@ #include "df/caste_raw.h" #include "df/historical_entity.h" #include "df/entity_raw.h" +#include "df/goal_type.h" +#include "df/unit_personality.h" #include "uicommon.h" #include "listcolumn.h" @@ -287,6 +289,9 @@ struct UnitInfo string name; string transname; string profession; + string goal; + enum { NEUTRAL, MALE, FEMALE } goal_gender; + bool achieved_goal; int8_t color; int active_index; string squad_effective_name; @@ -310,7 +315,8 @@ struct UnitInfo enum detail_cols { DETAIL_MODE_PROFESSION, DETAIL_MODE_SQUAD, - DETAIL_MODE_JOB + DETAIL_MODE_JOB, + DETAIL_MODE_GOAL }; enum altsort_mode { ALTSORT_NAME, @@ -348,6 +354,21 @@ bool sortByProfession (const UnitInfo *d1, const UnitInfo *d2) return (d1->profession < d2->profession); } +bool sortByGoal (const UnitInfo *d1, const UnitInfo *d2) +{ + if (!d1->unit->status.current_soul) + return !descending; + if (!d2->unit->status.current_soul) + return descending; + + df::goal_type goal1 = Units::getGoalType(d1->unit); + df::goal_type goal2 = Units::getGoalType(d2->unit); + if (descending) + return (goal1 > goal2); + else + return (goal1 < goal2); +} + bool sortBySquad (const UnitInfo *d1, const UnitInfo *d2) { bool gt = false; @@ -583,6 +604,8 @@ namespace unit_ops { } string get_profname(UnitInfo *u) { return Units::getProfessionName(u->unit); } + string get_goalname(UnitInfo *u) + { return Units::getGoalName(u->unit); } string get_real_profname(UnitInfo *u) { string tmp = u->unit->custom_profession; @@ -1237,6 +1260,14 @@ void viewscreen_unitlaborsst::refreshNames() cur->name = Translation::TranslateName(Units::getVisibleName(unit), false); cur->transname = Translation::TranslateName(Units::getVisibleName(unit), true); cur->profession = Units::getProfessionName(unit); + cur->goal = Units::getGoalName(unit); + df::goal_type goal = Units::getGoalType(unit); + if (goal == df::goal_type::START_A_FAMILY) { + cur->goal_gender = Units::isFemale(unit) ? UnitInfo::FEMALE : UnitInfo::MALE; + } else { + cur->goal_gender = UnitInfo::NEUTRAL; + } + cur->achieved_goal = Units::isGoalAchieved(unit); if (unit->job.current_job == NULL) { df::activity_event *event = Units::getMainSocialEvent(unit); @@ -1298,8 +1329,10 @@ void viewscreen_unitlaborsst::calcSize() detail_cmp = units[i]->squad_info.size(); } else if (detail_mode == DETAIL_MODE_JOB) { detail_cmp = units[i]->job_desc.size(); - } else { + } else if (detail_mode == DETAIL_MODE_PROFESSION) { detail_cmp = units[i]->profession.size(); + } else { + detail_cmp = units[i]->goal.size(); } if (size_t(col_maxwidth[DISP_COLUMN_DETAIL]) < detail_cmp) col_maxwidth[DISP_COLUMN_DETAIL] = detail_cmp; @@ -1736,8 +1769,10 @@ void viewscreen_unitlaborsst::feed(set *events) std::stable_sort(units.begin(), units.end(), sortBySquad); } else if (detail_mode == DETAIL_MODE_JOB) { std::stable_sort(units.begin(), units.end(), sortByJob); - } else { + } else if (detail_mode == DETAIL_MODE_PROFESSION){ std::stable_sort(units.begin(), units.end(), sortByProfession); + } else { + std::stable_sort(units.begin(), units.end(), sortByGoal); } break; case ALTSORT_STRESS: @@ -1777,9 +1812,11 @@ void viewscreen_unitlaborsst::feed(set *events) if (detail_mode == DETAIL_MODE_SQUAD) { detail_mode = DETAIL_MODE_JOB; } else if (detail_mode == DETAIL_MODE_JOB) { - detail_mode = DETAIL_MODE_PROFESSION; - } else { + detail_mode = DETAIL_MODE_GOAL; + } else if (detail_mode == DETAIL_MODE_PROFESSION) { detail_mode = DETAIL_MODE_SQUAD; + } else { + detail_mode = DETAIL_MODE_PROFESSION; } } @@ -1888,8 +1925,10 @@ void viewscreen_unitlaborsst::render() detail_str = "Squad"; } else if (detail_mode == DETAIL_MODE_JOB) { detail_str = "Job"; - } else { + } else if (detail_mode == DETAIL_MODE_PROFESSION) { detail_str = "Profession"; + } else { + detail_str = "Goal"; } Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_DETAIL], 2, detail_str); @@ -1978,9 +2017,32 @@ void viewscreen_unitlaborsst::render() } else { fg = COLOR_LIGHTCYAN; } - } else { + } else if (detail_mode == DETAIL_MODE_PROFESSION) { fg = cur->color; detail_str = cur->profession; + } else { + if (cur->goal_gender == UnitInfo::NEUTRAL) { + if (cur->achieved_goal) { + fg = COLOR_LIGHTGREEN; + } else { + fg = COLOR_BROWN; + } + } else if (cur->goal_gender == UnitInfo::FEMALE) { + if (cur->achieved_goal) { + fg = COLOR_LIGHTRED; + } + else { + fg = COLOR_MAGENTA; + } + } else { + if (cur->achieved_goal) { + fg = COLOR_LIGHTCYAN; + } + else { + fg = COLOR_BLUE; + } + } + detail_str = cur->goal; } detail_str.resize(col_widths[DISP_COLUMN_DETAIL]); Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_DETAIL], 4 + row, detail_str); @@ -2140,8 +2202,10 @@ void viewscreen_unitlaborsst::render() OutputString(15, x, y, "Squad"); } else if (detail_mode == DETAIL_MODE_JOB) { OutputString(15, x, y, "Job"); - } else { + } else if (detail_mode == DETAIL_MODE_PROFESSION){ OutputString(15, x, y, "Profession"); + } else { + OutputString(15, x, y, "Goal"); } break; case ALTSORT_STRESS: