zone: mass-assign nicknames, assign units to multiple cages inside a pasture. autobutcher: some fixes regarding autowatch and butchering caged units.

develop
Robert Heinrich 2012-04-16 16:31:12 +02:00
parent e6ed81508d
commit 9560fc641c
1 changed files with 173 additions and 19 deletions

@ -89,11 +89,16 @@ const string zone_help =
" if no filters are used, a single unit must be selected.\n"
" with filters named units are ignored unless specified.\n"
" unassign - unassign selected creature(s) from it's zone or cage\n"
" nick - give unit(s) nicknames (e.g. all units in a cage)\n"
" remnick - remove nicknames\n"
" tocages - assign to (multiple) built cages inside a pen/pasture\n"
" spreads creatures evenly among cages for faster hauling.\n"
" uinfo - print info about selected unit\n"
" zinfo - print info about zone(s) under cursor\n"
" verbose - print some more info, mostly useless debug stuff\n"
" filters - print list of supported filters\n"
" examples - print some usage examples\n";
" examples - print some usage examples\n"
;
const string zone_help_filters =
"Filters (to be used in combination with 'all' or 'count'):\n"
@ -360,6 +365,7 @@ void zoneInfo(color_ostream & out, df::building* building, bool verbose);
void cageInfo(color_ostream & out, df::building* building, bool verbose);
void chainInfo(color_ostream & out, df::building* building, bool verbose);
bool isBuiltCageAtPos(df::coord pos);
bool isInBuiltCageRoom(df::unit*);
int32_t getUnitAge(df::unit* unit)
{
@ -734,6 +740,10 @@ void unitInfo(color_ostream & out, df::unit* unit, bool verbose = false)
}
out << endl;
}
if(isInBuiltCageRoom(unit))
{
out << "in a room." << endl;
}
}
bool isActivityZone(df::building * building)
@ -1033,7 +1043,14 @@ bool isInBuiltCageRoom(df::unit* unit)
for (size_t b=0; b < world->buildings.all.size(); b++)
{
df::building* building = world->buildings.all[b];
if(building->isRoom() && building->getType() == building_type::Cage)
// !!! for whatever reason isRoom() returns true if a cage is not a room
// !!! and false if it was defined as a room/zoo ingame
// !!! (seems not general behaviour, activity zones return false, for example)
if(building->isRoom())
continue;
if(building->getType() == building_type::Cage)
{
df::building_cagest* cage = (df::building_cagest*) building;
for(size_t c=0; c<cage->assigned_creature.size(); c++)
@ -1404,6 +1421,71 @@ command_result assignUnitToBuilding(color_ostream& out, df::unit* unit, df::buil
return result;
}
command_result assignUnitsToCagezone(color_ostream& out, vector<df::unit*> units, df::building* building, bool verbose)
{
command_result result = CR_WRONG_USAGE;
if(!isPenPasture(building))
{
out << "A cage zone needs to be a pen/pasture containing at least one cage!" << endl;
return CR_WRONG_USAGE;
}
int32_t x1 = building->x1;
int32_t x2 = building->x2;
int32_t y1 = building->y1;
int32_t y2 = building->y2;
int32_t z = building->z;
//out << " x1:"<<x1<<" x2:"<<x2
// << " y1:"<<y1<<" y2:"<<x2
// << " z:"<<z<<endl;
//out << "filling vector with cages on this zone" << endl;
vector <df::building_cagest*> cages;
for (int32_t x = x1; x<=x2; x++)
{
for (int32_t y = y1; y<=y2; y++)
{
df::building* cage = getBuiltCageAtPos(df::coord(x,y,z));
if(cage)
{
df::building_cagest* cagest = (df::building_cagest*) cage;
cages.push_back(cagest);
}
}
}
if(!cages.size())
{
out << "No cages found in this zone!" << endl;
return CR_WRONG_USAGE;
}
else
{
out << "Number of cages: " << cages.size() << endl;
}
while(units.size())
{
// hrm, better use sort() instead?
df::building_cagest * bestcage = cages[0];
size_t lowest = cages[0]->assigned_creature.size();
for(size_t i=1; i<cages.size(); i++)
{
if(cages[i]->assigned_creature.size()<lowest)
{
lowest = cages[i]->assigned_creature.size();
bestcage = cages[i];
}
}
df::unit* unit = units.back();
command_result result = assignUnitToCage(out, unit, (df::building*) bestcage, verbose);
if(result!=CR_OK)
return result;
units.pop_back();
}
return CR_OK;
}
command_result nickUnitsInZone(color_ostream& out, df::building* building, string nick)
{
// building must be a pen/pasture or pit
@ -1450,6 +1532,8 @@ command_result nickUnitsInChain(color_ostream& out, df::building* building, stri
return CR_WRONG_USAGE;
}
// give all units inside a pasture or cage the same nickname
// (usage example: protect them from being autobutchered)
command_result nickUnitsInBuilding(color_ostream& out, df::building* building, string nick)
{
command_result result = CR_WRONG_USAGE;
@ -1493,6 +1577,11 @@ void zoneInfo(color_ostream & out, df::building* building, bool verbose)
else
out << "not active";
//if(building->isRoom())
// out <<", room";
//else
// out << ", not a room";
if(civ->zone_flags.bits.pen_pasture)
out << ", pen/pasture";
else if (civ->zone_flags.bits.pit_pond)
@ -1549,7 +1638,17 @@ void cageInfo(color_ostream & out, df::building* building, bool verbose)
<< " z:" << building->z
<< endl;
//if(building->isRoom())
// out <<", bldg room";
//else
// out << ", bldg not a room";
df::building_cagest * cage = (df::building_cagest*) building;
//if(cage->isRoom())
// out <<", cage is room";
//else
// out << ", cage is not a room";
int32_t creaturecount = cage->assigned_creature.size();
out << "Creatures in this cage: " << creaturecount << endl;
for(size_t c = 0; c < creaturecount; c++)
@ -1654,6 +1753,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
bool building_assign = false;
bool building_unassign = false;
bool building_set = false;
bool cagezone_assign = false;
bool verbose = false;
bool all = false;
bool unit_slaughter = false;
@ -1740,6 +1840,38 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
building_assign = true;
}
}
else if(p == "tocages")
{
if(invert_filter)
{
out << "'not tocages' makes no sense." << endl;
return CR_WRONG_USAGE;
}
// if followed by another parameter, check if it's numeric
if(i < parameters.size()-1)
{
stringstream ss(parameters[i+1]);
int new_building = -1;
ss >> new_building;
if(new_building != -1)
{
i++;
target_building = new_building;
out << "Assign selected unit(s) to cagezone #" << target_building <<std::endl;
}
}
if(target_building == -1)
{
out.printerr("No building id specified and current one is invalid!\n");
return CR_WRONG_USAGE;
}
else
{
out << "No buiding id specified. Will try to use #" << target_building << endl;
cagezone_assign = true;
}
}
else if(p == "race" && !invert_filter)
{
if(i == parameters.size()-1)
@ -2142,7 +2274,9 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
// set building at cursor position to be new target building
if(building_set)
{
target_building = findCageAtCursor();
// cagezone wants a pen/pit as starting point
if(!cagezone_assign)
target_building = findCageAtCursor();
if(target_building != -1)
{
out << "Target building type: cage." << endl;
@ -2164,10 +2298,10 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
return CR_OK;
}
if(building_assign || unit_info || unit_slaughter || nick_set)
if(building_assign || cagezone_assign || unit_info || unit_slaughter || nick_set)
{
df::building * building;
if(building_assign || (nick_set && !all && !find_count))
if(building_assign || cagezone_assign || (nick_set && !all && !find_count))
{
// try to get building index from the id
int32_t index = findBuildingIndexById(target_building);
@ -2188,6 +2322,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
if(all || find_count)
{
vector <df::unit*> units_for_cagezone;
size_t count = 0;
for(size_t c = 0; c < world->units.all.size(); c++)
{
@ -2278,8 +2413,18 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
{
Units::setNickname(unit, target_nick);
}
if(building_assign)
if(cagezone_assign)
{
// !!! optimize me: collect a vector of unit pointers which match the search and pass it to
// a method assignUnitsToCagezone(out, units, building) which only builds the vector of cages once
//command_result result = assignUnitToCagezone(out, unit, building, verbose);
//if(result != CR_OK)
// return result;
//continue;
units_for_cagezone.push_back(unit);
}
else if(building_assign)
{
command_result result = assignUnitToBuilding(out, unit, building, verbose);
if(result != CR_OK)
@ -2289,15 +2434,21 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
if(unit_slaughter)
{
// don't slaughter named creatures unless told to do so
if(!find_named && unit->name.has_name)
continue;
doMarkForSlaughter(unit);
if(!unit->name.has_name || find_named)
doMarkForSlaughter(unit);
}
count++;
if(find_count && count >= target_count)
break;
}
if(cagezone_assign)
{
command_result result = assignUnitsToCagezone(out, units_for_cagezone, building, verbose);
if(result != CR_OK)
return result;
}
out << "Processed creatures: " << count << endl;
}
else
@ -3115,18 +3266,21 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
return CR_OK;
// check if there is anything to watch before walking through units vector
bool watching = false;
for(size_t i=0; i<watched_races.size(); i++)
if(!enable_autobutcher_autowatch)
{
WatchedRace * w = watched_races[i];
if(w->isWatched)
bool watching = false;
for(size_t i=0; i<watched_races.size(); i++)
{
watching = true;
break;
WatchedRace * w = watched_races[i];
if(w->isWatched)
{
watching = true;
break;
}
}
if(!watching)
return CR_OK;
}
if(!watching)
return CR_OK;
for(size_t i=0; i<world->units.all.size(); i++)
{
@ -3142,7 +3296,7 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
|| 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))
|| (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom()
|| unit->name.has_name
)
continue;