Merge pull request #2872 from dawnmist/bugfix/issue-2871

Autobutcher check for nickname field being set - fix for #2871
develop
Myk 2023-02-12 01:25:34 -08:00 committed by GitHub
commit 53f394ce73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 64 deletions

@ -37,6 +37,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## Fixes ## Fixes
-@ `nestboxes`: fixed bug causing nestboxes themselves to be forbidden, which prevented citizens from using them to lay eggs. Now only eggs are forbidden. -@ `nestboxes`: fixed bug causing nestboxes themselves to be forbidden, which prevented citizens from using them to lay eggs. Now only eggs are forbidden.
- `autobutcher`: implemented work-around for Dwarf Fortress not setting nicknames properly, so that nicknames created in the in-game interface are detected & protect animals from being butchered properly. Note that nicknames for unnamed units are not currently saved by dwarf fortress - use ``enable fix/protect-nicks`` to fix any nicknames created/removed within dwarf fortress so they can be saved/reloaded when you reload the game.
## Misc Improvements ## Misc Improvements

@ -732,6 +732,30 @@ static bool isInBuiltCageRoom(df::unit *unit) {
return false; return false;
} }
// This can be used to identify completely inappropriate units (dead, undead, not belonging to the fort, ...)
// that autobutcher should be ignoring.
static bool isInappropriateUnit(df::unit *unit) {
return !Units::isActive(unit)
|| Units::isUndead(unit)
|| Units::isMerchant(unit) // ignore merchants' draft animals
|| Units::isForest(unit) // ignore merchants' caged animals
|| !Units::isOwnCiv(unit);
}
// This can be used to identify protected units that should be counted towards fort totals, but not scheduled
// for butchering. This way they count towards target quota, so if you order that you want 1 female adult cat
// and have 2 cats, one of them being a pet, the other gets butchered
static bool isProtectedUnit(df::unit *unit) {
return Units::isWar(unit) // ignore war dogs etc
|| Units::isHunter(unit) // ignore hunting dogs etc
// ignore creatures in built cages which are defined as rooms to leave zoos alone
// (TODO: better solution would be to allow some kind of slaughter cages which you can place near the butcher)
|| (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom()
|| Units::isAvailableForAdoption(unit)
|| unit->name.has_name
|| !unit->name.nickname.empty();
}
static void autobutcher_cycle(color_ostream &out) { static void autobutcher_cycle(color_ostream &out) {
// mark that we have recently run // mark that we have recently run
cycle_timestamp = world->frame_counter; cycle_timestamp = world->frame_counter;
@ -757,14 +781,9 @@ static void autobutcher_cycle(color_ostream &out) {
// then let autowatch add units to the watchlist which will probably start breeding (owned pets, war animals, ...) // then let autowatch add units to the watchlist which will probably start breeding (owned pets, war animals, ...)
// then process units counting those which can't be butchered (war animals, named pets, ...) // then process units counting those which can't be butchered (war animals, named pets, ...)
// so that they are treated as "own stock" as well and count towards the target quota // so that they are treated as "own stock" as well and count towards the target quota
if ( !Units::isActive(unit) if (isInappropriateUnit(unit)
|| Units::isUndead(unit)
|| Units::isMarkedForSlaughter(unit) || Units::isMarkedForSlaughter(unit)
|| Units::isMerchant(unit) // ignore merchants' draft animals || !Units::isTame(unit))
|| Units::isForest(unit) // ignore merchants' caged animals
|| !Units::isOwnCiv(unit)
|| !Units::isTame(unit)
)
continue; continue;
// found a bugged unit which had invalid coordinates but was not in a cage. // found a bugged unit which had invalid coordinates but was not in a cage.
@ -794,13 +813,7 @@ static void autobutcher_cycle(color_ostream &out) {
// don't butcher protected units, but count them as stock as well // don't butcher protected units, but count them as stock as well
// this way they count towards target quota, so if you order that you want 1 female adult cat // this way they count towards target quota, so if you order that you want 1 female adult cat
// and have 2 cats, one of them being a pet, the other gets butchered // and have 2 cats, one of them being a pet, the other gets butchered
if( Units::isWar(unit) // ignore war dogs etc if(isProtectedUnit(unit))
|| Units::isHunter(unit) // ignore hunting dogs etc
// ignore creatures in built cages which are defined as rooms to leave zoos alone
// (TODO: better solution would be to allow some kind of slaughter cages which you can place near the butcher)
|| (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom()
|| Units::isAvailableForAdoption(unit)
|| unit->name.has_name)
w->PushProtectedUnit(unit); w->PushProtectedUnit(unit);
else if ( Units::isGay(unit) else if ( Units::isGay(unit)
|| Units::isGelded(unit)) || Units::isGelded(unit))
@ -833,12 +846,7 @@ static WatchedRace * checkRaceStocksTotal(color_ostream &out, int race) {
if (unit->race != race) if (unit->race != race)
continue; continue;
if ( !Units::isActive(unit) if (isInappropriateUnit(unit))
|| Units::isUndead(unit)
|| Units::isMerchant(unit) // ignore merchants' draft animals
|| Units::isForest(unit) // ignore merchants' caged animals
|| !Units::isOwnCiv(unit)
)
continue; continue;
if(!isContainedInItem(unit) && !hasValidMapPos(unit)) if(!isContainedInItem(unit) && !hasValidMapPos(unit))
@ -855,12 +863,7 @@ WatchedRace * checkRaceStocksProtected(color_ostream &out, int race) {
if (unit->race != race) if (unit->race != race)
continue; continue;
if ( !Units::isActive(unit) if (isInappropriateUnit(unit))
|| Units::isUndead(unit)
|| Units::isMerchant(unit) // ignore merchants' draft animals
|| Units::isForest(unit) // ignore merchants' caged animals
|| !Units::isOwnCiv(unit)
)
continue; continue;
// found a bugged unit which had invalid coordinates but was not in a cage. // found a bugged unit which had invalid coordinates but was not in a cage.
@ -869,13 +872,7 @@ WatchedRace * checkRaceStocksProtected(color_ostream &out, int race) {
continue; continue;
if ( !Units::isTame(unit) if ( !Units::isTame(unit)
|| Units::isWar(unit) // ignore war dogs etc || isProtectedUnit(unit))
|| Units::isHunter(unit) // ignore hunting dogs etc
// ignore creatures in built cages which are defined as rooms to leave zoos alone
// (TODO: better solution would be to allow some kind of slaughter cages which you can place near the butcher)
|| (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom()
|| Units::isAvailableForAdoption(unit)
|| unit->name.has_name )
w->PushUnit(unit); w->PushUnit(unit);
} }
return w; return w;
@ -887,19 +884,9 @@ WatchedRace * checkRaceStocksButcherable(color_ostream &out, int race) {
if (unit->race != race) if (unit->race != race)
continue; continue;
if ( !Units::isActive(unit) if ( isInappropriateUnit(unit)
|| Units::isUndead(unit)
|| Units::isMerchant(unit) // ignore merchants' draft animals
|| Units::isForest(unit) // ignore merchants' caged animals
|| !Units::isOwnCiv(unit)
|| !Units::isTame(unit) || !Units::isTame(unit)
|| Units::isWar(unit) // ignore war dogs etc || isProtectedUnit(unit)
|| Units::isHunter(unit) // ignore hunting dogs etc
// ignore creatures in built cages which are defined as rooms to leave zoos alone
// (TODO: better solution would be to allow some kind of slaughter cages which you can place near the butcher)
|| (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom()
|| Units::isAvailableForAdoption(unit)
|| unit->name.has_name
) )
continue; continue;
@ -917,12 +904,7 @@ WatchedRace * checkRaceStocksButcherFlag(color_ostream &out, int race) {
if(unit->race != race) if(unit->race != race)
continue; continue;
if ( !Units::isActive(unit) if (isInappropriateUnit(unit))
|| Units::isUndead(unit)
|| Units::isMerchant(unit) // ignore merchants' draft animals
|| Units::isForest(unit) // ignore merchants' caged animals
|| !Units::isOwnCiv(unit)
)
continue; continue;
if (!isContainedInItem(unit) && !hasValidMapPos(unit)) if (!isContainedInItem(unit) && !hasValidMapPos(unit))
@ -1013,19 +995,9 @@ static void autobutcher_butcherRace(color_ostream &out, int id) {
if(unit->race != id) if(unit->race != id)
continue; continue;
if( !Units::isActive(unit) if( isInappropriateUnit(unit)
|| Units::isUndead(unit)
|| Units::isMerchant(unit) // ignore merchants' draught animals
|| Units::isForest(unit) // ignore merchants' caged animals
|| !Units::isOwnCiv(unit)
|| !Units::isTame(unit) || !Units::isTame(unit)
|| Units::isWar(unit) // ignore war dogs etc || isProtectedUnit(unit)
|| Units::isHunter(unit) // ignore hunting dogs etc
// ignore creatures in built cages which are defined as rooms to leave zoos alone
// (TODO: better solution would be to allow some kind of slaughter cages which you can place near the butcher)
|| (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom()
|| Units::isAvailableForAdoption(unit)
|| unit->name.has_name
) )
continue; continue;