From a6067c20c1ada4b1297801a9bf6888ba810f2757 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Mon, 30 Jul 2018 22:36:59 -0500 Subject: [PATCH] (labormanager) only assign valid labors (fix #1142) Add a number of tests to ensure that only assignable labors are assigned to units, and that only units that are eligible to be assigned labors are considered at all. I borrowed logic from Dwarf Manipulator to identify units eligible to be assigned labors. This should prevent pets., ghosts, visitors, or any other noneligible entities from being assigned labors by labormanager, and should thus fix #1142. --- plugins/labormanager/labormanager.cpp | 82 +++++++++++++++++++-------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/plugins/labormanager/labormanager.cpp b/plugins/labormanager/labormanager.cpp index 9f874edc0..3ff8c0862 100644 --- a/plugins/labormanager/labormanager.cpp +++ b/plugins/labormanager/labormanager.cpp @@ -945,6 +945,15 @@ private: { if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor)) { + if (!Units::isValidLabor(dwarf->dwarf, labor)) + { + debug("WARN(labormanager): Attempted to %s dwarf %s with ineligible labor %s\n", + value ? "set" : "unset", + dwarf->dwarf->name.first_name.c_str(), + ENUM_KEY_STR(unit_labor, labor).c_str()); + return; + } + bool old = dwarf->dwarf->status.labors[labor]; dwarf->dwarf->status.labors[labor] = value; if (old != value) @@ -1182,7 +1191,17 @@ private: { df::unit* cre = *u; - if (Units::isCitizen(cre)) + // following tests shamelessly stolen from Dwarf Manipulator plugin + + bool isAssignable = + (Units::isOwnCiv(cre)) && + (Units::isOwnGroup(cre)) && + (Units::isActive(cre)) && + (!cre->flags2.bits.visitor) && + (!cre->flags3.bits.ghostly) && + (ENUM_ATTR(profession, can_assign_labor, cre->profession)); + + if (isAssignable) { dwarf_info_t* dwarf = add_dwarf(cre); @@ -1438,8 +1457,8 @@ private: { if (labor == unit_labor::NONE) continue; - - set_labor(dwarf, labor, false); + if (Units::isValidLabor(dwarf->dwarf, labor)) + set_labor(dwarf, labor, false); } } else { @@ -1690,12 +1709,15 @@ public: { dwarf_info_t* d = (*k); - int score = score_labor(d, df::unit_labor::HAUL_FOOD); - - if (score > best_score) + if (Units::isValidLabor(d->dwarf, df::unit_labor::HAUL_FOOD)) { - bestdwarf = k; - best_score = score; + int score = score_labor(d, df::unit_labor::HAUL_FOOD); + + if (score > best_score) + { + bestdwarf = k; + best_score = score; + } } } @@ -1708,8 +1730,8 @@ public: { if (l == df::unit_labor::NONE) continue; - - set_labor(*bestdwarf, l, l == df::unit_labor::HAUL_FOOD); + if (Units::isValidLabor((*bestdwarf)->dwarf, l)) + set_labor(*bestdwarf, l, l == df::unit_labor::HAUL_FOOD); } available_dwarfs.erase(bestdwarf); @@ -1822,12 +1844,15 @@ public: for (std::list::iterator k = available_dwarfs.begin(); k != available_dwarfs.end(); k++) { dwarf_info_t* d = (*k); - int score = score_labor(d, labor); - if (score > best_score) + if (Units::isValidLabor(d->dwarf, labor)) { - bestdwarf = k; - best_score = score; - best_labor = labor; + int score = score_labor(d, labor); + if (score > best_score) + { + bestdwarf = k; + best_score = score; + best_labor = labor; + } } } } @@ -1845,7 +1870,9 @@ public: tools_enum t = default_labor_infos[l].tool; - if (l == best_labor && (t == TOOL_NONE || tool_in_use[t] < tool_count[t])) + if (l == best_labor && + Units::isValidLabor((*bestdwarf)->dwarf, l) && + (t == TOOL_NONE || tool_in_use[t] < tool_count[t])) { set_labor(*bestdwarf, l, true); if (t != TOOL_NONE && !((*bestdwarf)->has_tool[t])) @@ -1865,7 +1892,8 @@ public: } else if ((*bestdwarf)->state == IDLE) { - set_labor(*bestdwarf, l, false); + if (Units::isValidLabor((*bestdwarf)->dwarf, l)) + set_labor(*bestdwarf, l, false); } } @@ -1897,6 +1925,8 @@ public: continue; if (labor_needed[l] <= 0) continue; + if (!Units::isValidLabor((*d)->dwarf, l)) + continue; int score = score_labor(*d, l); @@ -1934,7 +1964,8 @@ public: FOR_ENUM_ITEMS(unit_labor, l) { if (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS && - canary & (1 << l)) + canary & (1 << l) && + Units::isValidLabor(canary_dwarf->dwarf, l)) set_labor(canary_dwarf, l, true); } @@ -1967,13 +1998,14 @@ public: if (l == df::unit_labor::NONE) continue; - set_labor(*d, l, - (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS) || - l == df::unit_labor::CLEAN || - l == df::unit_labor::HAUL_WATER || - l == df::unit_labor::REMOVE_CONSTRUCTION || - l == df::unit_labor::PULL_LEVER || - l == df::unit_labor::HAUL_TRADE); + if (Units::isValidLabor((*d)->dwarf, l)) + set_labor(*d, l, + (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS) || + l == df::unit_labor::CLEAN || + l == df::unit_labor::HAUL_WATER || + l == df::unit_labor::REMOVE_CONSTRUCTION || + l == df::unit_labor::PULL_LEVER || + l == df::unit_labor::HAUL_TRADE); } }