diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 429bcc173..f40969655 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -252,6 +252,7 @@ struct UnitInfo enum altsort_mode { ALTSORT_NAME, ALTSORT_PROFESSION, + ALTSORT_HAPPINESS, ALTSORT_MAX }; @@ -275,6 +276,14 @@ bool sortByProfession (const UnitInfo *d1, const UnitInfo *d2) return (d1->profession < d2->profession); } +bool sortByHappiness (const UnitInfo *d1, const UnitInfo *d2) +{ + if (descending) + return (d1->unit->status.happiness > d2->unit->status.happiness); + else + return (d1->unit->status.happiness < d2->unit->status.happiness); +} + bool sortBySkill (const UnitInfo *d1, const UnitInfo *d2) { if (sort_skill != job_skill::NONE) @@ -310,6 +319,14 @@ bool sortBySkill (const UnitInfo *d1, const UnitInfo *d2) return sortByName(d1, d2); } +enum display_columns { + DISP_COLUMN_HAPPINESS, + DISP_COLUMN_NAME, + DISP_COLUMN_PROFESSION, + DISP_COLUMN_LABORS, + DISP_COLUMN_MAX, +}; + class viewscreen_unitlaborsst : public dfhack_viewscreen { public: void feed(set *events); @@ -328,10 +345,11 @@ protected: vector units; altsort_mode altsort; - int first_row, sel_row; + int first_row, sel_row, num_rows; int first_column, sel_column; - int height, name_width, prof_width, labors_width; + int col_widths[DISP_COLUMN_MAX]; + int col_offsets[DISP_COLUMN_MAX]; void calcSize (); }; @@ -374,34 +392,52 @@ viewscreen_unitlaborsst::viewscreen_unitlaborsst(vector &src) void viewscreen_unitlaborsst::calcSize() { - height = gps->dimy - 10; - if (height > units.size()) - height = units.size(); - - name_width = prof_width = labors_width = 0; - for (int i = 4; i < gps->dimx; i++) + num_rows = gps->dimy - 10; + if (num_rows > units.size()) + num_rows = units.size(); + + int num_columns = gps->dimx - DISP_COLUMN_MAX - 1; + for (int i = 0; i < DISP_COLUMN_MAX; i++) + col_widths[i] = 0; + while (num_columns > 0) { - // 20% for Name, 20% for Profession, 60% for Labors - switch ((i - 4) % 5) + num_columns--; + // need at least 4 digits for happiness + if (col_widths[DISP_COLUMN_HAPPINESS] < 4) + { + col_widths[DISP_COLUMN_HAPPINESS]++; + continue; + } + // of remaining, 20% for Name, 20% for Profession, 60% for Labors + switch (num_columns % 5) { case 0: case 2: case 4: - labors_width++; + col_widths[DISP_COLUMN_LABORS]++; break; case 1: - name_width++; + col_widths[DISP_COLUMN_NAME]++; break; case 3: - prof_width++; + col_widths[DISP_COLUMN_PROFESSION]++; break; } } - while (labors_width > NUM_COLUMNS) + + while (col_widths[DISP_COLUMN_LABORS] > NUM_COLUMNS) + { + col_widths[DISP_COLUMN_LABORS]--; + if (col_widths[DISP_COLUMN_LABORS] & 1) + col_widths[DISP_COLUMN_NAME]++; + else + col_widths[DISP_COLUMN_PROFESSION]++; + } + + for (int i = 0; i < DISP_COLUMN_MAX; i++) { - if (labors_width & 1) - name_width++; + if (i == 0) + col_offsets[i] = 1; else - prof_width++; - labors_width--; + col_offsets[i] = col_offsets[i - 1] + col_widths[i - 1] + 1; } // don't adjust scroll position immediately after the window opened @@ -409,20 +445,20 @@ void viewscreen_unitlaborsst::calcSize() return; // if the window grows vertically, scroll upward to eliminate blank rows from the bottom - if (first_row > units.size() - height) - first_row = units.size() - height; + if (first_row > units.size() - num_rows) + first_row = units.size() - num_rows; // if it shrinks vertically, scroll downward to keep the cursor visible - if (first_row < sel_row - height + 1) - first_row = sel_row - height + 1; + if (first_row < sel_row - num_rows + 1) + first_row = sel_row - num_rows + 1; // if the window grows horizontally, scroll to the left to eliminate blank columns from the right - if (first_column > NUM_COLUMNS - labors_width) - first_column = NUM_COLUMNS - labors_width; + if (first_column > NUM_COLUMNS - col_widths[DISP_COLUMN_LABORS]) + first_column = NUM_COLUMNS - col_widths[DISP_COLUMN_LABORS]; // if it shrinks horizontally, scroll to the right to keep the cursor visible - if (first_column < sel_column - labors_width + 1) - first_column = sel_column - labors_width + 1; + if (first_column < sel_column - col_widths[DISP_COLUMN_LABORS] + 1) + first_column = sel_column - col_widths[DISP_COLUMN_LABORS] + 1; } void viewscreen_unitlaborsst::feed(set *events) @@ -453,8 +489,8 @@ void viewscreen_unitlaborsst::feed(set *events) if (sel_row < first_row) first_row = sel_row; - if (first_row < sel_row - height + 1) - first_row = sel_row - height + 1; + if (first_row < sel_row - num_rows + 1) + first_row = sel_row - num_rows + 1; if (events->count(interface_key::CURSOR_LEFT) || events->count(interface_key::CURSOR_UPLEFT) || events->count(interface_key::CURSOR_DOWNLEFT)) sel_column--; @@ -489,8 +525,8 @@ void viewscreen_unitlaborsst::feed(set *events) if (sel_column < first_column) first_column = sel_column; - if (first_column < sel_column - labors_width + 1) - first_column = sel_column - labors_width + 1; + if (first_column < sel_column - col_widths[DISP_COLUMN_LABORS] + 1) + first_column = sel_column - col_widths[DISP_COLUMN_LABORS] + 1; UnitInfo *cur = units[sel_row]; if (events->count(interface_key::SELECT) && (cur->allowEdit) && (columns[sel_column].labor != unit_labor::NONE)) @@ -556,6 +592,9 @@ void viewscreen_unitlaborsst::feed(set *events) case ALTSORT_PROFESSION: std::sort(units.begin(), units.end(), sortByProfession); break; + case ALTSORT_HAPPINESS: + std::sort(units.begin(), units.end(), sortByHappiness); + break; } } if (events->count(interface_key::CHANGETAB)) @@ -566,6 +605,9 @@ void viewscreen_unitlaborsst::feed(set *events) altsort = ALTSORT_PROFESSION; break; case ALTSORT_PROFESSION: + altsort = ALTSORT_HAPPINESS; + break; + case ALTSORT_HAPPINESS: altsort = ALTSORT_NAME; break; } @@ -605,7 +647,7 @@ void viewscreen_unitlaborsst::render() Screen::clear(); Screen::drawBorder(" Dwarf Manipulator - Manage Labors "); - for (int col = 0; col < labors_width; col++) + for (int col = 0; col < col_widths[DISP_COLUMN_LABORS]; col++) { int col_offset = col + first_column; if (col_offset >= NUM_COLUMNS) @@ -620,8 +662,8 @@ void viewscreen_unitlaborsst::render() bg = 7; } - Screen::paintTile(Screen::Pen(columns[col_offset].label[0], fg, bg), 1 + name_width + 1 + prof_width + 1 + col, 1); - Screen::paintTile(Screen::Pen(columns[col_offset].label[1], fg, bg), 1 + name_width + 1 + prof_width + 1 + col, 2); + Screen::paintTile(Screen::Pen(columns[col_offset].label[0], fg, bg), col_offsets[DISP_COLUMN_LABORS] + col, 1); + Screen::paintTile(Screen::Pen(columns[col_offset].label[1], fg, bg), col_offsets[DISP_COLUMN_LABORS] + col, 2); df::profession profession = columns[col_offset].profession; if ((profession != profession::NONE) && (ui->race_id != -1)) { @@ -630,11 +672,11 @@ void viewscreen_unitlaborsst::render() Screen::Pen(' ', fg, 0, graphics.profession_add_color[creature_graphics_role::DEFAULT][profession], graphics.profession_texpos[creature_graphics_role::DEFAULT][profession]), - 1 + name_width + 1 + prof_width + 1 + col, 3); + col_offsets[DISP_COLUMN_LABORS] + col, 3); } } - for (int row = 0; row < height; row++) + for (int row = 0; row < num_rows; row++) { int row_offset = row + first_row; if (row_offset >= units.size()) @@ -643,6 +685,26 @@ void viewscreen_unitlaborsst::render() UnitInfo *cur = units[row_offset]; df::unit *unit = cur->unit; int8_t fg = 15, bg = 0; + + int happy = cur->unit->status.happiness; + string happiness = stl_sprintf("%4i", happy); + if (happy == 0) // miserable + fg = 13; // 5:1 + else if (happy <= 25) // very unhappy + fg = 12; // 4:1 + else if (happy <= 50) // unhappy + fg = 4; // 4:0 + else if (happy < 75) // fine + fg = 14; // 6:1 + else if (happy < 125) // quite content + fg = 6; // 6:0 + else if (happy < 150) // happy + fg = 2; // 2:0 + else // ecstatic + fg = 10; // 2:1 + Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_HAPPINESS], 4 + row, happiness); + + fg = 15; if (row_offset == sel_row) { fg = 0; @@ -650,18 +712,18 @@ void viewscreen_unitlaborsst::render() } string name = cur->name; - name.resize(name_width); - Screen::paintString(Screen::Pen(' ', fg, bg), 1, 4 + row, name); + name.resize(col_widths[DISP_COLUMN_NAME]); + Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_NAME], 4 + row, name); string profession = cur->profession; - profession.resize(prof_width); + profession.resize(col_widths[DISP_COLUMN_PROFESSION]); fg = cur->color; bg = 0; - Screen::paintString(Screen::Pen(' ', fg, bg), 1 + name_width + 1, 4 + row, profession); + Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_PROFESSION], 4 + row, profession); // Print unit's skills and labor assignments - for (int col = 0; col < labors_width; col++) + for (int col = 0; col < col_widths[DISP_COLUMN_LABORS]; col++) { int col_offset = col + first_column; fg = 15; @@ -693,7 +755,7 @@ void viewscreen_unitlaborsst::render() } else bg = 4; - Screen::paintTile(Screen::Pen(c, fg, bg), 1 + name_width + 1 + prof_width + 1 + col, 4 + row); + Screen::paintTile(Screen::Pen(c, fg, bg), col_offsets[DISP_COLUMN_LABORS] + col, 4 + row); } } @@ -703,17 +765,17 @@ void viewscreen_unitlaborsst::render() { df::unit *unit = cur->unit; int x = 1; - Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + height + 2, cur->transname); + Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + num_rows + 2, cur->transname); x += cur->transname.length(); if (cur->transname.length()) { - Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + height + 2, ", "); + Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + num_rows + 2, ", "); x += 2; } - Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + height + 2, cur->profession); + Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + num_rows + 2, cur->profession); x += cur->profession.length(); - Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + height + 2, ": "); + Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + num_rows + 2, ": "); x += 2; string str; @@ -740,7 +802,7 @@ void viewscreen_unitlaborsst::render() else str = stl_sprintf("Not %s (0/500)", ENUM_ATTR_STR(job_skill, caption_noun, columns[sel_column].skill)); } - Screen::paintString(Screen::Pen(' ', 9, 0), x, 3 + height + 2, str); + Screen::paintString(Screen::Pen(' ', 9, 0), x, 3 + num_rows + 2, str); canToggle = (cur->allowEdit) && (columns[sel_column].labor != unit_labor::NONE); } @@ -779,6 +841,9 @@ void viewscreen_unitlaborsst::render() case ALTSORT_PROFESSION: OutputString(15, x, gps->dimy - 2, "Profession"); break; + case ALTSORT_HAPPINESS: + OutputString(15, x, gps->dimy - 2, "Happiness"); + break; default: OutputString(15, x, gps->dimy - 2, "Unknown"); break;