Add sorting, command help; replace filtering with just using the current page of the UnitList viewscreen (and don't close it)

develop
Quietust 2012-08-25 10:57:50 -05:00
parent 41ad42d0fd
commit dcdff40c85
1 changed files with 191 additions and 104 deletions

@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <set> #include <set>
#include <algorithm>
#include <VTableInterpose.h> #include <VTableInterpose.h>
#include "df/world.h" #include "df/world.h"
@ -41,36 +42,36 @@ DFHACK_PLUGIN("manipulator");
struct SkillLevel struct SkillLevel
{ {
const char *name; const char *name;
int points; int points;
char abbrev; char abbrev;
}; };
#define NUM_SKILL_LEVELS (sizeof(skill_levels) / sizeof(SkillLevel)) #define NUM_SKILL_LEVELS (sizeof(skill_levels) / sizeof(SkillLevel))
// The various skill rankings. Zero skill is hardcoded to "Not" and '-'. // The various skill rankings. Zero skill is hardcoded to "Not" and '-'.
const SkillLevel skill_levels[] = { const SkillLevel skill_levels[] = {
{"Dabbling", 500, '0'}, {"Dabbling", 500, '0'},
{"Novice", 600, '1'}, {"Novice", 600, '1'},
{"Adequate", 700, '2'}, {"Adequate", 700, '2'},
{"Competent", 800, '3'}, {"Competent", 800, '3'},
{"Skilled", 900, '4'}, {"Skilled", 900, '4'},
{"Proficient", 1000, '5'}, {"Proficient", 1000, '5'},
{"Talented", 1100, '6'}, {"Talented", 1100, '6'},
{"Adept", 1200, '7'}, {"Adept", 1200, '7'},
{"Expert", 1300, '8'}, {"Expert", 1300, '8'},
{"Professional",1400, '9'}, {"Professional",1400, '9'},
{"Accomplished",1500, 'A'}, {"Accomplished",1500, 'A'},
{"Great", 1600, 'B'}, {"Great", 1600, 'B'},
{"Master", 1700, 'C'}, {"Master", 1700, 'C'},
{"High Master", 1800, 'D'}, {"High Master", 1800, 'D'},
{"Grand Master",1900, 'E'}, {"Grand Master",1900, 'E'},
{"Legendary", 2000, 'U'}, {"Legendary", 2000, 'U'},
{"Legendary+1", 2100, 'V'}, {"Legendary+1", 2100, 'V'},
{"Legendary+2", 2200, 'W'}, {"Legendary+2", 2200, 'W'},
{"Legendary+3", 2300, 'X'}, {"Legendary+3", 2300, 'X'},
{"Legendary+4", 2400, 'Y'}, {"Legendary+4", 2400, 'Y'},
{"Legendary+5", 0, 'Z'} {"Legendary+5", 0, 'Z'}
}; };
struct SkillColumn struct SkillColumn
@ -82,7 +83,7 @@ struct SkillColumn
bool special; // specified labor is mutually exclusive with all other special labors bool special; // specified labor is mutually exclusive with all other special labors
}; };
#define NUM_COLUMNS (sizeof(columns) / sizeof(SkillColumn)) #define NUM_COLUMNS (sizeof(columns) / sizeof(SkillColumn))
// All of the skill/labor columns we want to display. Includes profession (for color), labor, skill, and 2 character label // All of the skill/labor columns we want to display. Includes profession (for color), labor, skill, and 2 character label
const SkillColumn columns[] = { const SkillColumn columns[] = {
@ -247,17 +248,69 @@ struct UnitInfo
int8_t color; int8_t color;
}; };
#define FILTER_NONWORKERS 0x0001 enum altsort_mode {
#define FILTER_NONDWARVES 0x0002 ALTSORT_NAME,
#define FILTER_NONCIV 0x0004 ALTSORT_PROFESSION,
#define FILTER_ANIMALS 0x0008 ALTSORT_MAX
#define FILTER_LIVING 0x0010 };
#define FILTER_DEAD 0x0020
bool descending;
df::job_skill sort_skill;
df::unit_labor sort_labor;
bool sortByName (const UnitInfo *d1, const UnitInfo *d2)
{
if (descending)
return (d1->name > d2->name);
else
return (d1->name < d2->name);
}
bool sortByProfession (const UnitInfo *d1, const UnitInfo *d2)
{
if (descending)
return (d1->profession > d2->profession);
else
return (d1->profession < d2->profession);
}
bool sortBySkill (const UnitInfo *d1, const UnitInfo *d2)
{
if (sort_skill != job_skill::NONE)
{
df::unit_skill *s1 = binsearch_in_vector<df::unit_skill,df::enum_field<df::job_skill,int16_t>>(d1->unit->status.current_soul->skills, &df::unit_skill::id, sort_skill);
df::unit_skill *s2 = binsearch_in_vector<df::unit_skill,df::enum_field<df::job_skill,int16_t>>(d1->unit->status.current_soul->skills, &df::unit_skill::id, sort_skill);
int l1 = s1 ? s1->rating : 0;
int l2 = s2 ? s2->rating : 0;
int e1 = s1 ? s1->experience : 0;
int e2 = s2 ? s2->experience : 0;
if (descending)
{
if (l1 != l2)
return l1 > l2;
if (e1 != e2)
return e1 > e2;
}
else
{
if (l1 != l2)
return l1 < l2;
if (e1 != e2)
return e1 < e2;
}
}
if (sort_labor != unit_labor::NONE)
{
if (descending)
return d1->unit->status.labors[sort_labor] > d2->unit->status.labors[sort_labor];
else
return d1->unit->status.labors[sort_labor] < d2->unit->status.labors[sort_labor];
}
return sortByName(d1, d2);
}
class viewscreen_unitlaborsst : public dfhack_viewscreen { class viewscreen_unitlaborsst : public dfhack_viewscreen {
public: public:
static viewscreen_unitlaborsst *create (char pushtype, df::viewscreen *scr = NULL);
void feed(set<df::interface_key> *events); void feed(set<df::interface_key> *events);
void render(); void render();
@ -267,86 +320,41 @@ public:
std::string getFocusString() { return "unitlabors"; } std::string getFocusString() { return "unitlabors"; }
viewscreen_unitlaborsst(); viewscreen_unitlaborsst(vector<df::unit*> &src);
~viewscreen_unitlaborsst() { }; ~viewscreen_unitlaborsst() { };
protected: protected:
vector<UnitInfo *> units; vector<UnitInfo *> units;
int filter; altsort_mode altsort;
int first_row, sel_row; int first_row, sel_row;
int first_column, sel_column; int first_column, sel_column;
int height, name_width, prof_width, labors_width; int height, name_width, prof_width, labors_width;
// bool descending;
// int sort_skill;
// int sort_labor;
void readUnits ();
void calcSize (); void calcSize ();
}; };
viewscreen_unitlaborsst::viewscreen_unitlaborsst() viewscreen_unitlaborsst::viewscreen_unitlaborsst(vector<df::unit*> &src)
{
filter = FILTER_LIVING;
first_row = sel_row = 0;
first_column = sel_column = 0;
calcSize();
readUnits();
}
void viewscreen_unitlaborsst::readUnits ()
{ {
for (size_t i = 0; i < units.size(); i++) for (size_t i = 0; i < src.size(); i++)
delete units[i];
units.clear();
UnitInfo *cur = new UnitInfo;
for (size_t i = 0; i < world->units.active.size(); i++)
{ {
df::unit *unit = world->units.active[i]; UnitInfo *cur = new UnitInfo;
df::unit *unit = src[i];
cur->unit = unit; cur->unit = unit;
cur->allowEdit = true; cur->allowEdit = true;
if (unit->race != ui->race_id) if (unit->race != ui->race_id)
{
cur->allowEdit = false; cur->allowEdit = false;
if (!(filter & FILTER_NONDWARVES))
continue;
}
if (unit->civ_id != ui->civ_id) if (unit->civ_id != ui->civ_id)
{
cur->allowEdit = false; cur->allowEdit = false;
if (!(filter & FILTER_NONCIV))
continue;
}
if (unit->flags1.bits.dead) if (unit->flags1.bits.dead)
{
cur->allowEdit = false; cur->allowEdit = false;
if (!(filter & FILTER_DEAD))
continue;
}
else
{
if (!(filter & FILTER_LIVING))
continue;
}
if (!ENUM_ATTR(profession, can_assign_labor, unit->profession)) if (!ENUM_ATTR(profession, can_assign_labor, unit->profession))
{
cur->allowEdit = false; cur->allowEdit = false;
if (!(filter & FILTER_NONWORKERS))
continue;
}
if (!unit->name.first_name.length())
{
if (!(filter & FILTER_ANIMALS))
continue;
}
cur->name = Translation::TranslateName(&unit->name, false); cur->name = Translation::TranslateName(&unit->name, false);
cur->transname = Translation::TranslateName(&unit->name, true); cur->transname = Translation::TranslateName(&unit->name, true);
@ -354,9 +362,13 @@ void viewscreen_unitlaborsst::readUnits ()
cur->color = Units::getProfessionColor(unit); cur->color = Units::getProfessionColor(unit);
units.push_back(cur); units.push_back(cur);
cur = new UnitInfo;
} }
delete cur; std::sort(units.begin(), units.end(), sortByName);
altsort = ALTSORT_NAME;
first_row = sel_row = 0;
first_column = sel_column = 0;
calcSize();
} }
void viewscreen_unitlaborsst::calcSize() void viewscreen_unitlaborsst::calcSize()
@ -421,8 +433,6 @@ void viewscreen_unitlaborsst::feed(set<df::interface_key> *events)
return; return;
} }
// TODO - allow modifying filters
if (!units.size()) if (!units.size())
return; return;
@ -501,9 +511,46 @@ void viewscreen_unitlaborsst::feed(set<df::interface_key> *events)
unit->status.labors[col.labor] = !unit->status.labors[col.labor]; unit->status.labors[col.labor] = !unit->status.labors[col.labor];
} }
// TODO: add sorting if (events->count(interface_key::SECONDSCROLL_UP) || events->count(interface_key::SECONDSCROLL_DOWN))
{
descending = events->count(interface_key::SECONDSCROLL_UP);
sort_skill = columns[sel_column].skill;
sort_labor = columns[sel_column].labor;
std::sort(units.begin(), units.end(), sortBySkill);
}
if (events->count(interface_key::SECONDSCROLL_PAGEUP) || events->count(interface_key::SECONDSCROLL_PAGEDOWN))
{
descending = events->count(interface_key::SECONDSCROLL_PAGEUP);
switch (altsort)
{
case ALTSORT_NAME:
std::sort(units.begin(), units.end(), sortByName);
break;
case ALTSORT_PROFESSION:
std::sort(units.begin(), units.end(), sortByProfession);
break;
}
}
if (events->count(interface_key::CHANGETAB))
{
switch (altsort)
{
case ALTSORT_NAME:
altsort = ALTSORT_PROFESSION;
break;
case ALTSORT_PROFESSION:
altsort = ALTSORT_NAME;
break;
}
}
} }
void OutputString(int8_t color, int &x, int y, const std::string &text)
{
Screen::paintString(Screen::Pen(' ', color, 0), x, y, text);
x += text.length();
}
void viewscreen_unitlaborsst::render() void viewscreen_unitlaborsst::render()
{ {
if (Screen::isDismissed(this)) if (Screen::isDismissed(this))
@ -528,6 +575,7 @@ void viewscreen_unitlaborsst::render()
fg = 0; fg = 0;
bg = 7; 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[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[1], fg, bg), 1 + name_width + 1 + prof_width + 1 + col, 2);
} }
@ -537,6 +585,7 @@ void viewscreen_unitlaborsst::render()
int row_offset = row + first_row; int row_offset = row + first_row;
if (row_offset >= units.size()) if (row_offset >= units.size())
break; break;
UnitInfo *cur = units[row_offset]; UnitInfo *cur = units[row_offset];
df::unit *unit = cur->unit; df::unit *unit = cur->unit;
int8_t fg = 15, bg = 0; int8_t fg = 15, bg = 0;
@ -554,7 +603,8 @@ void viewscreen_unitlaborsst::render()
profession.resize(prof_width); profession.resize(prof_width);
fg = cur->color; fg = cur->color;
bg = 0; bg = 0;
Screen::paintString(Screen::Pen(' ', fg, bg), 1 + prof_width + 1, 3 + row, profession);
Screen::paintString(Screen::Pen(' ', fg, bg), 1 + name_width + 1, 3 + row, profession);
// Print unit's skills and labor assignments // Print unit's skills and labor assignments
for (int col = 0; col < labors_width; col++) for (int col = 0; col < labors_width; col++)
@ -586,15 +636,21 @@ void viewscreen_unitlaborsst::render()
if (cur != NULL) if (cur != NULL)
{ {
df::unit *unit = cur->unit; df::unit *unit = cur->unit;
string str = cur->transname; int x = 1;
if (str.length()) Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + height + 2, cur->transname);
str += ", "; x += cur->transname.length();
str += cur->profession;
str += ":";
Screen::paintString(Screen::Pen(' ', 15, 0), 1, 3 + height + 2, str); if (cur->transname.length())
int y = 1 + str.length() + 1; {
Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + height + 2, ", ");
x += 2;
}
Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + height + 2, cur->profession);
x += cur->profession.length();
Screen::paintString(Screen::Pen(' ', 15, 0), x, 3 + height + 2, ": ");
x += 2;
string str;
if (columns[sel_column].skill == job_skill::NONE) if (columns[sel_column].skill == job_skill::NONE)
{ {
str = ENUM_ATTR_STR(unit_labor, caption, columns[sel_column].labor); str = ENUM_ATTR_STR(unit_labor, caption, columns[sel_column].labor);
@ -602,7 +658,6 @@ void viewscreen_unitlaborsst::render()
str += " Enabled"; str += " Enabled";
else else
str += " Not Enabled"; str += " Not Enabled";
Screen::paintString(Screen::Pen(' ', 9, 0), y, 3 + height + 2, str);
} }
else else
{ {
@ -618,11 +673,41 @@ void viewscreen_unitlaborsst::render()
} }
else else
str = stl_sprintf("Not %s (0/500)", ENUM_ATTR_STR(job_skill, caption_noun, columns[sel_column].skill)); str = stl_sprintf("Not %s (0/500)", ENUM_ATTR_STR(job_skill, caption_noun, columns[sel_column].skill));
Screen::paintString(Screen::Pen(' ', 9, 0), y, 3 + height + 2, str);
} }
Screen::paintString(Screen::Pen(' ', 9, 0), x, 3 + height + 2, str);
} }
// TODO - print command help info int x = 1;
OutputString( 2, x, gps->dimy - 3, "Enter"); // SELECT key
OutputString(15, x, gps->dimy - 3, ": Toggle labor");
x += 2;
OutputString( 2, x, gps->dimy - 3, "Esc"); // LEAVESCREEN key
OutputString(15, x, gps->dimy - 3, ": Done");
x = 1;
OutputString( 2, x, gps->dimy - 2, "+"); // SECONDSCROLL_DOWN key
OutputString( 2, x, gps->dimy - 2, "-"); // SECONDSCROLL_UP key
OutputString(15, x, gps->dimy - 2, ": Sort by Skill");
x += 2;
OutputString( 2, x, gps->dimy - 2, "*"); // SECONDSCROLL_PAGEDOWN key
OutputString( 2, x, gps->dimy - 2, "/"); // SECONDSCROLL_PAGEUP key
OutputString(15, x, gps->dimy - 2, ": Sort by (");
OutputString( 2, x, gps->dimy - 2, "Tab"); // CHANGETAB key
OutputString(15, x, gps->dimy - 2, ") ");
switch (altsort)
{
case ALTSORT_NAME:
OutputString(15, x, gps->dimy - 2, "Name");
break;
case ALTSORT_PROFESSION:
OutputString(15, x, gps->dimy - 2, "Profession");
break;
default:
OutputString(15, x, gps->dimy - 2, "Unknown");
break;
}
} }
struct unitlist_hook : df::viewscreen_unitlistst struct unitlist_hook : df::viewscreen_unitlistst
@ -633,9 +718,11 @@ struct unitlist_hook : df::viewscreen_unitlistst
{ {
if (input->count(interface_key::UNITVIEW_PRF_PROF)) if (input->count(interface_key::UNITVIEW_PRF_PROF))
{ {
Screen::dismiss(this); if (units[page].size())
Screen::show(new viewscreen_unitlaborsst()); {
return; Screen::show(new viewscreen_unitlaborsst(units[page]));
return;
}
} }
INTERPOSE_NEXT(feed)(input); INTERPOSE_NEXT(feed)(input);
} }