(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.
develop
Kelly Kinkade 2018-07-30 22:36:59 -05:00
parent 0983891089
commit a6067c20c1
1 changed files with 57 additions and 25 deletions

@ -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<dwarf_info_t*>::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);
}
}