summaryrefslogtreecommitdiff
path: root/plugins/zone.cpp
diff options
context:
space:
mode:
authorRobert Heinrich2012-04-16 16:31:12 +0200
committerRobert Heinrich2012-04-16 16:31:12 +0200
commit9560fc641c05f28ea0e374b8cce610794c926808 (patch)
treeaa056709b695b0941492154b279c32f7b56ac041 /plugins/zone.cpp
parente6ed81508d2826b2fd4eae8c9c4ba873daeff100 (diff)
downloaddfhack-9560fc641c05f28ea0e374b8cce610794c926808.tar.gz
dfhack-9560fc641c05f28ea0e374b8cce610794c926808.tar.bz2
dfhack-9560fc641c05f28ea0e374b8cce610794c926808.tar.xz
zone: mass-assign nicknames, assign units to multiple cages inside a pasture. autobutcher: some fixes regarding autowatch and butchering caged units.
Diffstat (limited to 'plugins/zone.cpp')
-rw-r--r--plugins/zone.cpp192
1 files changed, 173 insertions, 19 deletions
diff --git a/plugins/zone.cpp b/plugins/zone.cpp
index 4ee99154..43c25972 100644
--- a/plugins/zone.cpp
+++ b/plugins/zone.cpp
@@ -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;