From 9560fc641c05f28ea0e374b8cce610794c926808 Mon Sep 17 00:00:00 2001 From: Robert Heinrich Date: Mon, 16 Apr 2012 16:31:12 +0200 Subject: [PATCH] zone: mass-assign nicknames, assign units to multiple cages inside a pasture. autobutcher: some fixes regarding autowatch and butchering caged units. --- plugins/zone.cpp | 192 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 173 insertions(+), 19 deletions(-) diff --git a/plugins/zone.cpp b/plugins/zone.cpp index 4ee991549..43c259723 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; cassigned_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 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:"< 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; iassigned_creature.size()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 & 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 & 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 < & 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 & 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 & parameters) if(all || find_count) { + vector 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 & 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 & 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; iisWatched) + bool watching = false; + for(size_t i=0; iisWatched) + { + watching = true; + break; + } } + if(!watching) + return CR_OK; } - if(!watching) - return CR_OK; for(size_t i=0; iunits.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;