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 422060803..87c71ac67 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -1437,6 +1437,73 @@ 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); + + switch (goal) + { + default: + case df::goal_type::STAY_ALIVE: + return achieved_goal ? "Stayed Alive" : "Stay Alive"; + case df::goal_type::MAINTAIN_ENTITY_STATUS: + return achieved_goal ? "Maintained Status" : "Maintain Status"; + case df::goal_type::START_A_FAMILY: + return isFemale(unit) ? + (achieved_goal ? "Is a Mother" : "Be a Mother") : + (achieved_goal ? "Is a Father" : "Be a Father"); + case df::goal_type::RULE_THE_WORLD: + return achieved_goal ? "Ruled the World" : "Rule the World"; + case df::goal_type::CREATE_A_GREAT_WORK_OF_ART: + return achieved_goal ? "Made Great Artwork" : "Create Great Artwork"; + case df::goal_type::CRAFT_A_MASTERWORK: + return achieved_goal ? "Crafted a Masterwork" : "Craft a Masterwork"; + case df::goal_type::BRING_PEACE_TO_THE_WORLD: + return achieved_goal ? "Brought World Peace" : "Bring Peace to World"; + case df::goal_type::BECOME_A_LEGENDARY_WARRIOR: + return achieved_goal ? "Is Legendary Warrior" : "Be Legendary Warrior"; + case df::goal_type::MASTER_A_SKILL: + return achieved_goal ? "Mastered a Skill" : "Master a Skill"; + case df::goal_type::FALL_IN_LOVE: + return achieved_goal ? "Fell in Love" : "Fall in Love"; + case df::goal_type::SEE_THE_GREAT_NATURAL_SITES: + return achieved_goal ? "Saw Natural Wonders" : "See Natural Wonders"; + case df::goal_type::IMMORTALITY: + return achieved_goal ? "Immortal" : "Immortality"; + case df::goal_type::MAKE_A_GREAT_DISCOVERY: + return achieved_goal ? "Made Great Discovery" : "Make Great Discovery"; + case df::goal_type::ATTAINING_RANK_IN_SOCIETY: + return achieved_goal ? "Attained Social Rank" : "Attain Social Rank"; + case df::goal_type::BATHING_THE_WORLD_IN_CHAOS: + return achieved_goal ? "World is in Chaos" : "Bathe World in Chaos"; + } +} + +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/plugins/manipulator.cpp b/plugins/manipulator.cpp index a013df335..4bb285f0b 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -32,9 +32,12 @@ #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" +#include "manipulator.h" using std::stringstream; using std::set; @@ -287,6 +290,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 +316,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 +355,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 +605,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 +1261,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 +1330,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 +1770,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 +1813,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 +1926,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 +2018,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 +2203,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: