Merge remote-tracking branch 'cdombroski/zone-plugin-cleanup' into temp

Conflicts:
	NEWS
	plugins/zone.cpp
develop
expwnent 2015-01-31 21:01:41 -05:00
commit e9b4fc513a
15 changed files with 512 additions and 552 deletions

30
NEWS

@ -3,6 +3,36 @@ DFHack Future
Lua scripts can set environment variables of each other with dfhack.run_script_with_env. Lua scripts can set environment variables of each other with dfhack.run_script_with_env.
eventful Lua reactions no longer require LUA_HOOK as a prefix: you can register a callback for the completion of any reaction with a name eventful Lua reactions no longer require LUA_HOOK as a prefix: you can register a callback for the completion of any reaction with a name
Filesystem module now provides file access/modification times and can list directories (normally and recursively) Filesystem module now provides file access/modification times and can list directories (normally and recursively)
Units Module: New functions:
isWar
isHunter
isAvailableForAdoption
isOwnCiv
isOwnRace
getRaceName
getRaceNamePlural
getRaceBabyName
getRaceChildName
isBaby
isChild
isAdult
isEggLayer
isGrazer
isMilkable
isTrainableWar
isTrainableHunting
isTamable
isMale
isFemale
isMerchant
isForest
isMarkedForSlaughter
Buildings Module: New Functions:
isActivityZone
isPenPasture
isPitPond
isActive
findPenPitAt
Fixes Fixes
dfhack.run_script should correctly find save-specific scripts now. dfhack.run_script should correctly find save-specific scripts now.
Updated add-thought to properly affect stress. Updated add-thought to properly affect stress.

@ -1401,6 +1401,29 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, getCasteProfessionName), WRAPM(Units, getCasteProfessionName),
WRAPM(Units, getProfessionColor), WRAPM(Units, getProfessionColor),
WRAPM(Units, getCasteProfessionColor), WRAPM(Units, getCasteProfessionColor),
WRAPM(Units, isWar),
WRAPM(Units, isHunter),
WRAPM(Units, isAvailableForAdoption),
WRAPM(Units, isOwnCiv),
WRAPM(Units, isOwnRace),
WRAPM(Units, getRaceName),
WRAPM(Units, getRaceNamePlural),
WRAPM(Units, getRaceBabyName),
WRAPM(Units, getRaceChildName),
WRAPM(Units, isBaby),
WRAPM(Units, isChild),
WRAPM(Units, isAdult),
WRAPM(Units, isEggLayer),
WRAPM(Units, isGrazer),
WRAPM(Units, isMilkable),
WRAPM(Units, isTrainableWar),
WRAPM(Units, isTrainableHunting),
WRAPM(Units, isTamable),
WRAPM(Units, isMale),
WRAPM(Units, isFemale),
WRAPM(Units, isMerchant),
WRAPM(Units, isForest),
WRAPM(Units, isMarkedForSlaughter),
{ NULL, NULL } { NULL, NULL }
}; };
@ -1678,6 +1701,10 @@ static const LuaWrapper::FunctionReg dfhack_buildings_module[] = {
WRAPM(Buildings, constructWithItems), WRAPM(Buildings, constructWithItems),
WRAPM(Buildings, constructWithFilters), WRAPM(Buildings, constructWithFilters),
WRAPM(Buildings, deconstruct), WRAPM(Buildings, deconstruct),
WRAPM(Buildings, isActivityZone),
WRAPM(Buildings, isPenPasture),
WRAPM(Buildings, isPitPond),
WRAPM(Buildings, isActive),
{ NULL, NULL } { NULL, NULL }
}; };
@ -1699,6 +1726,13 @@ static int buildings_findCivzonesAt(lua_State *L)
return 1; return 1;
} }
static int buildings_findPenPitAt(lua_State *L)
{
auto pos = CheckCoordXYZ(L, 1, true);
Lua::PushDFObject(L, Buildings::findPenPitAt(pos));
return 1;
}
static int buildings_getCorrectSize(lua_State *state) static int buildings_getCorrectSize(lua_State *state)
{ {
df::coord2d size(luaL_optint(state, 1, 1), luaL_optint(state, 2, 1)); df::coord2d size(luaL_optint(state, 1, 1), luaL_optint(state, 2, 1));
@ -1758,6 +1792,7 @@ static const luaL_Reg dfhack_buildings_funcs[] = {
{ "getCorrectSize", buildings_getCorrectSize }, { "getCorrectSize", buildings_getCorrectSize },
{ "setSize", &Lua::CallWithCatchWrapper<buildings_setSize> }, { "setSize", &Lua::CallWithCatchWrapper<buildings_setSize> },
{ "getStockpileContents", buildings_getStockpileContents}, { "getStockpileContents", buildings_getStockpileContents},
{ "findPenPitAt", buildings_findPenPitAt},
{ NULL, NULL } { NULL, NULL }
}; };

@ -288,6 +288,11 @@ public:
* Collects items stored on a stockpile into a vector. * Collects items stored on a stockpile into a vector.
*/ */
DFHACK_EXPORT void getStockpileContents(df::building_stockpilest *stockpile, std::vector<df::item*> *items); DFHACK_EXPORT void getStockpileContents(df::building_stockpilest *stockpile, std::vector<df::item*> *items);
DFHACK_EXPORT bool isActivityZone(df::building * building);
DFHACK_EXPORT bool isPenPasture(df::building * building);
DFHACK_EXPORT bool isPitPond(df::building * building);
DFHACK_EXPORT bool isActive(df::building * building);
DFHACK_EXPORT df::building* findPenPitAt(df::coord coord);
} }
} }

@ -233,6 +233,35 @@ DFHACK_EXPORT bool isAlive(df::unit *unit);
DFHACK_EXPORT bool isSane(df::unit *unit); DFHACK_EXPORT bool isSane(df::unit *unit);
DFHACK_EXPORT bool isCitizen(df::unit *unit); DFHACK_EXPORT bool isCitizen(df::unit *unit);
DFHACK_EXPORT bool isDwarf(df::unit *unit); DFHACK_EXPORT bool isDwarf(df::unit *unit);
DFHACK_EXPORT bool isWar(df::unit* unit);
DFHACK_EXPORT bool isHunter(df::unit* unit);
DFHACK_EXPORT bool isAvailableForAdoption(df::unit* unit);
DFHACK_EXPORT bool isOwnCiv(df::unit* unit);
DFHACK_EXPORT bool isOwnRace(df::unit* unit);
DFHACK_EXPORT std::string getRaceNameById(int32_t race_id);
DFHACK_EXPORT std::string getRaceName(df::unit* unit);
DFHACK_EXPORT std::string getRaceNamePluralById(int32_t race_id);
DFHACK_EXPORT std::string getRaceNamePlural(df::unit* unit);
DFHACK_EXPORT std::string getRaceBabyNameById(int32_t race_id);
DFHACK_EXPORT std::string getRaceBabyName(df::unit* unit);
DFHACK_EXPORT std::string getRaceChildNameById(int32_t race_id);
DFHACK_EXPORT std::string getRaceChildName(df::unit* unit);
DFHACK_EXPORT bool isBaby(df::unit* unit);
DFHACK_EXPORT bool isChild(df::unit* unit);
DFHACK_EXPORT bool isAdult(df::unit* unit);
DFHACK_EXPORT bool isEggLayer(df::unit* unit);
DFHACK_EXPORT bool isGrazer(df::unit* unit);
DFHACK_EXPORT bool isMilkable(df::unit* unit);
DFHACK_EXPORT bool isTrainableWar(df::unit* unit);
DFHACK_EXPORT bool isTrainableHunting(df::unit* unit);
DFHACK_EXPORT bool isTamable(df::unit* unit);
DFHACK_EXPORT bool isMale(df::unit* unit);
DFHACK_EXPORT bool isFemale(df::unit* unit);
DFHACK_EXPORT bool isMerchant(df::unit* unit);
DFHACK_EXPORT bool isForest(df::unit* unit);
DFHACK_EXPORT bool isMarkedForSlaughter(df::unit* unit);
DFHACK_EXPORT double getAge(df::unit *unit, bool true_age = false); DFHACK_EXPORT double getAge(df::unit *unit, bool true_age = false);

@ -1176,3 +1176,45 @@ void Buildings::getStockpileContents(df::building_stockpilest *stockpile, std::v
items->push_back(item); items->push_back(item);
} }
} }
bool Buildings::isActivityZone(df::building * building)
{
CHECK_NULL_POINTER(building);
return building->getType() == building_type::Civzone
&& building->getSubtype() == (short)civzone_type::ActivityZone;
}
bool Buildings::isPenPasture(df::building * building)
{
if (!isActivityZone(building))
return false;
return ((df::building_civzonest*) building)->zone_flags.bits.pen_pasture != 0;
}
bool Buildings::isPitPond(df::building * building)
{
if (!isActivityZone(building))
return false;
return ((df::building_civzonest*) building)->zone_flags.bits.pit_pond != 0;
}
bool Buildings::isActive(df::building * building)
{
if (!isActivityZone(building))
return false;
return ((df::building_civzonest*) building)->zone_flags.bits.active != 0;
}
// returns building of pen/pit at cursor position (NULL if nothing found)
df::building* Buildings::findPenPitAt(df::coord coord)
{
vector<df::building_civzonest*> zones;
Buildings::findCivzonesAt(&zones, coord);
for (auto zone = zones.begin(); zone != zones.end(); ++zone)
{
if (isPenPasture(*zone) || isPitPond(*zone))
return (*zone);
}
return NULL;
}

@ -765,7 +765,7 @@ df::unit_misc_trait *Units::getMiscTrait(df::unit *unit, df::misc_trait_type typ
return NULL; return NULL;
} }
bool DFHack::Units::isDead(df::unit *unit) bool Units::isDead(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
@ -773,7 +773,7 @@ bool DFHack::Units::isDead(df::unit *unit)
unit->flags3.bits.ghostly; unit->flags3.bits.ghostly;
} }
bool DFHack::Units::isAlive(df::unit *unit) bool Units::isAlive(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
@ -782,12 +782,11 @@ bool DFHack::Units::isAlive(df::unit *unit)
!unit->curse.add_tags1.bits.NOT_LIVING; !unit->curse.add_tags1.bits.NOT_LIVING;
} }
bool DFHack::Units::isSane(df::unit *unit) bool Units::isSane(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
if (unit->flags1.bits.dead || if (isDead(unit) ||
unit->flags3.bits.ghostly ||
isOpposedToLife(unit) || isOpposedToLife(unit) ||
unit->enemy.undead) unit->enemy.undead)
return false; return false;
@ -808,7 +807,7 @@ bool DFHack::Units::isSane(df::unit *unit)
return true; return true;
} }
bool DFHack::Units::isCitizen(df::unit *unit) bool Units::isCitizen(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
@ -838,7 +837,7 @@ bool DFHack::Units::isCitizen(df::unit *unit)
!unit->flags2.bits.visitor; !unit->flags2.bits.visitor;
} }
bool DFHack::Units::isDwarf(df::unit *unit) bool Units::isDwarf(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
@ -846,7 +845,220 @@ bool DFHack::Units::isDwarf(df::unit *unit)
unit->enemy.normal_race == ui->race_id; unit->enemy.normal_race == ui->race_id;
} }
double DFHack::Units::getAge(df::unit *unit, bool true_age) // check for profession "war creature"
bool Units::isWar(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->profession == df::profession::TRAINED_WAR
|| unit->profession2 == df::profession::TRAINED_WAR;
}
// check for profession "hunting creature"
bool Units::isHunter(df::unit* unit)
{
CHECK_NULL_POINTER(unit)
return unit->profession == df::profession::TRAINED_HUNTER
|| unit->profession2 == df::profession::TRAINED_HUNTER;
}
// check if unit is marked as available for adoption
bool Units::isAvailableForAdoption(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
auto refs = unit->specific_refs;
for(size_t i=0; i<refs.size(); i++)
{
auto ref = refs[i];
auto reftype = ref->type;
if( reftype == df::specific_ref_type::PETINFO_PET )
{
//df::pet_info* pet = ref->pet;
return true;
}
}
return false;
}
// check if creature belongs to the player's civilization
// (don't try to pasture/slaughter random untame animals)
bool Units::isOwnCiv(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->civ_id == ui->civ_id;
}
// check if creature belongs to the player's race
// (in combination with check for civ helps to filter out own dwarves)
bool Units::isOwnRace(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->race == ui->race_id;
}
// get race name by id or unit pointer
string Units::getRaceNameById(int32_t id)
{
df::creature_raw *raw = world->raws.creatures.all[id];
if (raw)
return raw->creature_id;
return "";
}
string Units::getRaceName(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return getRaceNameById(unit->race);
}
// get plural of race name (used for display in autobutcher UI and for sorting the watchlist)
string Units::getRaceNamePluralById(int32_t id)
{
df::creature_raw *raw = world->raws.creatures.all[id];
if (raw)
return raw->name[1]; // second field is plural of race name
return "";
}
string Units::getRaceNamePlural(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return getRaceNamePluralById(unit->race);
}
string Units::getRaceBabyNameById(int32_t id)
{
df::creature_raw *raw = world->raws.creatures.all[id];
if (raw)
return raw->general_baby_name[0];
return "";
}
string Units::getRaceBabyName(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return getRaceBabyNameById(unit->race);
}
string Units::getRaceChildNameById(int32_t id)
{
df::creature_raw *raw = world->raws.creatures.all[id];
if (raw)
return raw->general_child_name[0];
return "";
}
string Units::getRaceChildName(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return getRaceChildNameById(unit->race);
}
bool Units::isBaby(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->profession == df::profession::BABY;
}
bool Units::isChild(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->profession == df::profession::CHILD;
}
bool Units::isAdult(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return !isBaby(unit) && !isChild(unit);
}
bool Units::isEggLayer(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
df::creature_raw *raw = world->raws.creatures.all[unit->race];
for (auto caste = raw->caste.begin(); caste != raw->caste.end(); ++caste)
{
if ((*caste)->flags.is_set(caste_raw_flags::LAYS_EGGS)
|| (*caste)->flags.is_set(caste_raw_flags::LAYS_UNUSUAL_EGGS))
return true;
}
return false;
}
bool Units::isGrazer(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
df::creature_raw *raw = world->raws.creatures.all[unit->race];
for (auto caste = raw->caste.begin(); caste != raw->caste.end(); ++caste)
{
if((*caste)->flags.is_set(caste_raw_flags::GRAZER))
return true;
}
return false;
}
bool Units::isMilkable(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
df::creature_raw *raw = world->raws.creatures.all[unit->race];
for (auto caste = raw->caste.begin(); caste != raw->caste.end(); ++caste)
{
if((*caste)->flags.is_set(caste_raw_flags::MILKABLE))
return true;
}
return false;
}
bool Units::isTrainableWar(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
df::creature_raw *raw = world->raws.creatures.all[unit->race];
for (auto caste = raw->caste.begin(); caste != raw->caste.end(); ++caste)
{
if((*caste)->flags.is_set(caste_raw_flags::TRAINABLE_WAR))
return true;
}
return false;
}
bool Units::isTrainableHunting(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
df::creature_raw *raw = world->raws.creatures.all[unit->race];
for (auto caste = raw->caste.begin(); caste != raw->caste.end(); ++caste)
{
if((*caste)->flags.is_set(caste_raw_flags::TRAINABLE_HUNTING))
return true;
}
return false;
}
bool Units::isTamable(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
df::creature_raw *raw = world->raws.creatures.all[unit->race];
for (auto caste = raw->caste.begin(); caste != raw->caste.end(); ++caste)
{
if((*caste)->flags.is_set(caste_raw_flags::PET) ||
(*caste)->flags.is_set(caste_raw_flags::PET_EXOTIC))
return true;
}
return false;
}
bool Units::isMale(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->sex == 1;
}
bool Units::isFemale(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->sex == 0;
}
double Units::getAge(df::unit *unit, bool true_age)
{ {
using df::global::cur_year; using df::global::cur_year;
using df::global::cur_year_tick; using df::global::cur_year_tick;
@ -1126,7 +1338,7 @@ int Units::computeMovementSpeed(df::unit *unit)
// General counters and flags // General counters and flags
if (unit->profession == profession::BABY) if (isBaby(unit))
speed += 3000; speed += 3000;
if (unit->flags3.bits.unk15) if (unit->flags3.bits.unk15)
@ -1326,7 +1538,7 @@ static bool noble_pos_compare(const Units::NoblePosition &a, const Units::NobleP
return a.position->id < b.position->id; return a.position->id < b.position->id;
} }
bool DFHack::Units::getNoblePositions(std::vector<NoblePosition> *pvec, df::unit *unit) bool Units::getNoblePositions(std::vector<NoblePosition> *pvec, df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
@ -1367,7 +1579,7 @@ bool DFHack::Units::getNoblePositions(std::vector<NoblePosition> *pvec, df::unit
return true; return true;
} }
std::string DFHack::Units::getProfessionName(df::unit *unit, bool ignore_noble, bool plural) std::string Units::getProfessionName(df::unit *unit, bool ignore_noble, bool plural)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
@ -1400,7 +1612,7 @@ std::string DFHack::Units::getProfessionName(df::unit *unit, bool ignore_noble,
return getCasteProfessionName(unit->race, unit->caste, unit->profession, plural); return getCasteProfessionName(unit->race, unit->caste, unit->profession, plural);
} }
std::string DFHack::Units::getCasteProfessionName(int race, int casteid, df::profession pid, bool plural) std::string Units::getCasteProfessionName(int race, int casteid, df::profession pid, bool plural)
{ {
std::string prof, race_prefix; std::string prof, race_prefix;
@ -1517,7 +1729,7 @@ std::string DFHack::Units::getCasteProfessionName(int race, int casteid, df::pro
return Translation::capitalize(prof, true); return Translation::capitalize(prof, true);
} }
int8_t DFHack::Units::getProfessionColor(df::unit *unit, bool ignore_noble) int8_t Units::getProfessionColor(df::unit *unit, bool ignore_noble)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
@ -1532,7 +1744,7 @@ int8_t DFHack::Units::getProfessionColor(df::unit *unit, bool ignore_noble)
return getCasteProfessionColor(unit->race, unit->caste, unit->profession); return getCasteProfessionColor(unit->race, unit->caste, unit->profession);
} }
int8_t DFHack::Units::getCasteProfessionColor(int race, int casteid, df::profession pid) int8_t Units::getCasteProfessionColor(int race, int casteid, df::profession pid)
{ {
// make sure it's an actual profession // make sure it's an actual profession
if (pid < 0 || !is_valid_enum_item(pid)) if (pid < 0 || !is_valid_enum_item(pid))
@ -1556,7 +1768,7 @@ int8_t DFHack::Units::getCasteProfessionColor(int race, int casteid, df::profess
return 3; return 3;
} }
std::string DFHack::Units::getSquadName(df::unit *unit) std::string Units::getSquadName(df::unit *unit)
{ {
if (unit->military.squad_id == -1) if (unit->military.squad_id == -1)
return ""; return "";
@ -1567,3 +1779,22 @@ std::string DFHack::Units::getSquadName(df::unit *unit)
return squad->alias; return squad->alias;
return Translation::TranslateName(&squad->name, true); return Translation::TranslateName(&squad->name, true);
} }
bool Units::isMerchant(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->flags1.bits.merchant == 1;
}
bool Units::isForest(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->flags1.bits.forest == 1;
}
bool Units::isMarkedForSlaughter(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->flags2.bits.slaughter == 1;
}

@ -38,6 +38,7 @@
#include "modules/MapCache.h" #include "modules/MapCache.h"
#include "modules/Items.h" #include "modules/Items.h"
#include "modules/Units.h"
using std::string; using std::string;
using std::endl; using std::endl;
@ -1158,8 +1159,8 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
is_on_break = true; is_on_break = true;
} }
if (dwarfs[dwarf]->profession == profession::BABY || if (Units::isBaby(dwarfs[dwarf]) ||
dwarfs[dwarf]->profession == profession::CHILD || Units::isChild(dwarfs[dwarf]) ||
dwarfs[dwarf]->profession == profession::DRUNK) dwarfs[dwarf]->profession == profession::DRUNK)
{ {
dwarf_info[dwarf].state = CHILD; dwarf_info[dwarf].state = CHILD;

@ -81,7 +81,7 @@ command_result catsplosion (color_ostream &out, std::vector <std::string> & para
{ {
df::unit * creature = Units::GetCreature(i); df::unit * creature = Units::GetCreature(i);
df::creature_raw *raw = world->raws.creatures.all[creature->race]; df::creature_raw *raw = world->raws.creatures.all[creature->race];
if(creature->sex == 0) // female if(Units::isFemale(creature))
{ {
female_counts[raw->creature_id].push_back(creature); female_counts[raw->creature_id].push_back(creature);
male_counts[raw->creature_id].size(); male_counts[raw->creature_id].size();

@ -1109,18 +1109,14 @@ struct preference_map
case (T_type::LikeCreature): case (T_type::LikeCreature):
{ {
label = "Creature :"; label = "Creature :";
auto creature = df::creature_raw::find(pref.creature_id); Units::getRaceNamePluralById(pref.creature_id);
if (creature)
label += creature->name[1];
break; break;
} }
case (T_type::HateCreature): case (T_type::HateCreature):
{ {
label = "Hates :"; label = "Hates :";
auto creature = df::creature_raw::find(pref.creature_id); Units::getRaceNamePluralById(pref.creature_id);
if (creature)
label += creature->name[1];
break; break;
} }
@ -1619,8 +1615,8 @@ static void update_dwarf_stats(bool is_paused)
if (!monitor_jobs || is_paused) if (!monitor_jobs || is_paused)
continue; continue;
if (unit->profession == profession::BABY || if (Units::isBaby(unit) ||
unit->profession == profession::CHILD || Units::isChild(unit) ||
unit->profession == profession::DRUNK) unit->profession == profession::DRUNK)
{ {
continue; continue;

@ -445,10 +445,10 @@ viewscreen_unitlaborsst::viewscreen_unitlaborsst(vector<df::unit*> &src, int cur
cur->allowEdit = true; cur->allowEdit = true;
cur->active_index = active_idx[unit]; cur->active_index = active_idx[unit];
if (unit->race != ui->race_id) if (!Units::isOwnRace(unit))
cur->allowEdit = false; cur->allowEdit = false;
if (unit->civ_id != ui->civ_id) if (!Units::isOwnCiv(unit))
cur->allowEdit = false; cur->allowEdit = false;
if (unit->flags1.bits.dead) if (unit->flags1.bits.dead)

@ -5,6 +5,7 @@
#include "Export.h" #include "Export.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "modules/EventManager.h" #include "modules/EventManager.h"
#include "modules/Units.h"
#include "modules/Maps.h" #include "modules/Maps.h"
#include "df/caste_raw.h" #include "df/caste_raw.h"
@ -79,12 +80,12 @@ void impregnateMany() {
df::creature_raw* creatureRaw = world->raws.creatures.all[race]; df::creature_raw* creatureRaw = world->raws.creatures.all[race];
df::caste_raw* casteRaw = creatureRaw->caste[caste]; df::caste_raw* casteRaw = creatureRaw->caste[caste];
//must have PET or PET_EXOTIC //must have PET or PET_EXOTIC
if ( !(casteRaw->flags.is_set(df::enums::caste_raw_flags::PET) || casteRaw->flags.is_set(df::enums::caste_raw_flags::PET_EXOTIC) ) ) if ( !Units::isTamable(unit))
continue; continue;
//check for adulthood //check for adulthood
if ( unit->profession == df::enums::profession::CHILD || unit->profession == df::enums::profession::BABY ) if ( Units::isBaby(unit) || Units::isChild(unit))
continue; continue;
if ( unit->sex == 1 ) if ( Units::isMale(unit))
males[unit->race].push_back(a); males[unit->race].push_back(a);
else else
females[unit->race].push_back(a); females[unit->race].push_back(a);

@ -960,8 +960,8 @@ private:
} }
} }
if (unit->profession == profession::BABY || if (Units::isBaby(unit) ||
unit->profession == profession::CHILD || Units::isChild(unit) ||
unit->profession == profession::DRUNK) unit->profession == profession::DRUNK)
{ {
return ""; return "";

@ -7,6 +7,7 @@
#include "modules/Materials.h" #include "modules/Materials.h"
#include "modules/Translation.h" #include "modules/Translation.h"
#include "modules/Items.h" #include "modules/Items.h"
#include "modules/Units.h"
#include "DataDefs.h" #include "DataDefs.h"
#include "df/world.h" #include "df/world.h"
@ -153,7 +154,7 @@ command_result df_showmood (color_ostream &out, vector <string> & parameters)
break; break;
} }
out.print(".\n"); out.print(".\n");
if (unit->sex) if (Units::isMale(unit))
out.print("He has "); out.print("He has ");
else else
out.print("She has "); out.print("She has ");

@ -707,7 +707,7 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
if (!unit) if (!unit)
return CR_FAILURE; return CR_FAILURE;
if(unit->race != ui->race_id) if(!Units::isOwnRace(unit))
{ {
out << "Selected unit does not belong to your race!" << endl; out << "Selected unit does not belong to your race!" << endl;
return CR_FAILURE; return CR_FAILURE;
@ -720,14 +720,14 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
// case #2: migrants who have the merchant flag // case #2: migrants who have the merchant flag
// happens on almost all maps after a few migrant waves // happens on almost all maps after a few migrant waves
if(unit->flags1.bits.merchant) if(Units::isMerchant(unit))
unit->flags1.bits.merchant = 0; unit->flags1.bits.merchant = 0;
// this one is a cheat, but bugged migrants usually have the same civ_id // this one is a cheat, but bugged migrants usually have the same civ_id
// so it should not be triggered in most cases // so it should not be triggered in most cases
// if it happens that the player has 'foreign' units of the same race // if it happens that the player has 'foreign' units of the same race
// (vanilla df: dwarves not from mountainhome) on his map, just grab them // (vanilla df: dwarves not from mountainhome) on his map, just grab them
if(unit->civ_id != ui->civ_id) if(!Units::isOwnCiv(unit))
unit->civ_id = ui->civ_id; unit->civ_id = ui->civ_id;
return fix_clothing_ownership(out, unit); return fix_clothing_ownership(out, unit);
@ -742,11 +742,11 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
if (unit->flags2.bits.resident) if (unit->flags2.bits.resident)
unit->flags2.bits.resident = 0; unit->flags2.bits.resident = 0;
if(unit->flags1.bits.merchant) if(Units::isMerchant(unit))
unit->flags1.bits.merchant = 0; unit->flags1.bits.merchant = 0;
if(unit->flags1.bits.forest) if(Units::isForest(unit))
unit->flags1.bits.forest = 0; unit->flags1.bits.forest = 0;
if(unit->civ_id != ui->civ_id) if(!Units::isOwnCiv(unit))
unit->civ_id = ui->civ_id; unit->civ_id = ui->civ_id;
if(unit->profession == df::profession::MERCHANT) if(unit->profession == df::profession::MERCHANT)
unit->profession = df::profession::TRADER; unit->profession = df::profession::TRADER;

@ -75,6 +75,8 @@ using namespace std;
using std::vector; using std::vector;
using std::string; using std::string;
using namespace DFHack; using namespace DFHack;
using namespace DFHack::Units;
using namespace DFHack::Buildings;
using namespace df::enums; using namespace df::enums;
DFHACK_PLUGIN("zone"); DFHACK_PLUGIN("zone");
@ -339,26 +341,12 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
// Various small tool functions // Various small tool functions
// probably many of these should be moved to Unit.h and Building.h sometime later... // probably many of these should be moved to Unit.h and Building.h sometime later...
int32_t getUnitAge(df::unit* unit);
bool isTame(df::unit* unit); bool isTame(df::unit* unit);
bool isTrained(df::unit* unit); bool isTrained(df::unit* unit);
bool isWar(df::unit* unit);
bool isHunter(df::unit* unit);
bool isOwnCiv(df::unit* unit);
bool isMerchant(df::unit* unit);
bool isForest(df::unit* unit);
bool isGay(df::unit* unit); bool isGay(df::unit* unit);
bool isGelded(df::unit* unit);
bool isActivityZone(df::building * building); df::building* findCageAtCursor();
bool isPenPasture(df::building * building); df::building* findChainAtCursor();
bool isPitPond(df::building * building);
bool isActive(df::building * building);
int32_t findBuildingIndexById(int32_t id);
int32_t findPenPitAtCursor();
int32_t findCageAtCursor();
int32_t findChainAtCursor();
df::general_ref_building_civzone_assignedst * createCivzoneRef(); df::general_ref_building_civzone_assignedst * createCivzoneRef();
bool unassignUnitFromBuilding(df::unit* unit); bool unassignUnitFromBuilding(df::unit* unit);
@ -370,22 +358,6 @@ void chainInfo(color_ostream & out, df::building* building, bool verbose);
bool isBuiltCageAtPos(df::coord pos); bool isBuiltCageAtPos(df::coord pos);
bool isInBuiltCageRoom(df::unit*); bool isInBuiltCageRoom(df::unit*);
bool isNaked(df::unit *); bool isNaked(df::unit *);
bool isTamable(df::unit *);
int32_t getUnitAge(df::unit* unit)
{
// If the birthday this year has not yet passed, subtract one year.
// ASSUMPTION: birth_time is on the same scale as cur_year_tick
int32_t yearDifference = *cur_year - unit->relations.birth_year;
if (unit->relations.birth_time >= *cur_year_tick)
yearDifference--;
return yearDifference;
}
bool isDead(df::unit* unit)
{
return unit->flags1.bits.dead;
}
// ignore vampires, they should be treated like normal dwarves // ignore vampires, they should be treated like normal dwarves
bool isUndead(df::unit* unit) bool isUndead(df::unit* unit)
@ -395,21 +367,6 @@ bool isUndead(df::unit* unit)
&& !unit->curse.add_tags1.bits.BLOODSUCKER )); && !unit->curse.add_tags1.bits.BLOODSUCKER ));
} }
bool isMerchant(df::unit* unit)
{
return unit->flags1.bits.merchant;
}
bool isForest(df::unit* unit)
{
return unit->flags1.bits.forest;
}
bool isMarkedForSlaughter(df::unit* unit)
{
return unit->flags2.bits.slaughter;
}
void doMarkForSlaughter(df::unit* unit) void doMarkForSlaughter(df::unit* unit)
{ {
unit->flags2.bits.slaughter = 1; unit->flags2.bits.slaughter = 1;
@ -489,195 +446,6 @@ bool isTrained(df::unit* unit)
return trained; return trained;
} }
// check for profession "war creature"
bool isWar(df::unit* unit)
{
if( unit->profession == df::profession::TRAINED_WAR
|| unit->profession2 == df::profession::TRAINED_WAR)
return true;
else
return false;
}
// check for profession "hunting creature"
bool isHunter(df::unit* unit)
{
if( unit->profession == df::profession::TRAINED_HUNTER
|| unit->profession2 == df::profession::TRAINED_HUNTER)
return true;
else
return false;
}
// check if unit is marked as available for adoption
bool isAvailableForAdoption(df::unit* unit)
{
auto refs = unit->specific_refs;
for(int i=0; i<refs.size(); i++)
{
auto ref = refs[i];
auto reftype = ref->type;
if( reftype == df::specific_ref_type::PETINFO_PET )
{
//df::pet_info* pet = ref->pet;
return true;
}
}
return false;
}
// check if creature belongs to the player's civilization
// (don't try to pasture/slaughter random untame animals)
bool isOwnCiv(df::unit* unit)
{
return unit->civ_id == ui->civ_id;
}
// check if creature belongs to the player's race
// (in combination with check for civ helps to filter out own dwarves)
bool isOwnRace(df::unit* unit)
{
return unit->race == ui->race_id;
}
// get race name by id or unit pointer
// todo: rename these two functions to "getRaceToken" since the output is more of a token
string getRaceName(int32_t id)
{
df::creature_raw *raw = world->raws.creatures.all[id];
return raw->creature_id;
}
string getRaceName(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
return raw->creature_id;
}
// get plural of race name (used for display in autobutcher UI and for sorting the watchlist)
string getRaceNamePlural(int32_t id)
{
//WatchedRace * w = watched_races[idx];
df::creature_raw *raw = world->raws.creatures.all[id];
return raw->name[1]; // second field is plural of race name
}
string getRaceBabyName(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
return raw->general_baby_name[0];
}
string getRaceChildName(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
return raw->general_child_name[0];
}
bool isBaby(df::unit* unit)
{
return unit->profession == df::profession::BABY;
}
bool isChild(df::unit* unit)
{
return unit->profession == df::profession::CHILD;
}
bool isAdult(df::unit* unit)
{
return !isBaby(unit) && !isChild(unit);
}
bool isEggLayer(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
df::caste_raw *caste = raw->caste[j];
if( caste->flags.is_set(caste_raw_flags::LAYS_EGGS)
|| caste->flags.is_set(caste_raw_flags::LAYS_UNUSUAL_EGGS))
return true;
}
return false;
}
bool isGrazer(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
df::caste_raw *caste = raw->caste[j];
if(caste->flags.is_set(caste_raw_flags::GRAZER))
return true;
}
return false;
}
bool isMilkable(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
df::caste_raw *caste = raw->caste[j];
if(caste->flags.is_set(caste_raw_flags::MILKABLE))
return true;
}
return false;
}
bool isTrainableWar(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
df::caste_raw *caste = raw->caste[j];
if(caste->flags.is_set(caste_raw_flags::TRAINABLE_WAR))
return true;
}
return false;
}
bool isTrainableHunting(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
df::caste_raw *caste = raw->caste[j];
if(caste->flags.is_set(caste_raw_flags::TRAINABLE_HUNTING))
return true;
}
return false;
}
bool isTamable(df::unit* unit)
{
df::creature_raw *raw = world->raws.creatures.all[unit->race];
size_t sizecas = raw->caste.size();
for (size_t j = 0; j < sizecas;j++)
{
df::caste_raw *caste = raw->caste[j];
if(caste->flags.is_set(caste_raw_flags::PET) ||
caste->flags.is_set(caste_raw_flags::PET_EXOTIC))
return true;
}
return false;
}
bool isMale(df::unit* unit)
{
return unit->sex == 1;
}
bool isFemale(df::unit* unit)
{
return unit->sex == 0;
}
// found a unit with weird position values on one of my maps (negative and in the thousands) // found a unit with weird position values on one of my maps (negative and in the thousands)
// it didn't appear in the animal stocks screen, but looked completely fine otherwise (alive, tame, own, etc) // it didn't appear in the animal stocks screen, but looked completely fine otherwise (alive, tame, own, etc)
// maybe a rare bug, but better avoid assigning such units to zones or slaughter etc. // maybe a rare bug, but better avoid assigning such units to zones or slaughter etc.
@ -697,23 +465,11 @@ bool isNaked(df::unit* unit)
return (unit->inventory.empty()); return (unit->inventory.empty());
} }
int getUnitIndexFromId(df::unit* unit_)
{
for (size_t i=0; i < world->units.all.size(); i++)
{
df::unit* unit = world->units.all[i];
if(unit->id == unit_->id)
return i;
}
return -1;
}
bool isGay(df::unit* unit) bool isGay(df::unit* unit)
{ {
df::orientation_flags orientation = unit->status.current_soul->orientation_flags; df::orientation_flags orientation = unit->status.current_soul->orientation_flags;
return isFemale(unit) && ! (orientation.whole & (orientation.mask_marry_male | orientation.mask_romance_male)) return (isFemale(unit) && ! (orientation.whole & (orientation.mask_marry_male | orientation.mask_romance_male)))
|| ! isFemale(unit) && ! (orientation.whole & (orientation.mask_marry_female | orientation.mask_romance_female)); || (! isFemale(unit) && ! (orientation.whole & (orientation.mask_marry_female | orientation.mask_romance_female)));
} }
bool isGelded(df::unit* unit) bool isGelded(df::unit* unit)
@ -776,7 +532,7 @@ void unitInfo(color_ostream & out, df::unit* unit, bool verbose = false)
break; break;
} }
out << ")"; out << ")";
out << ", age: " << getUnitAge(unit); out << ", age: " << getAge(unit, true);
if(isTame(unit)) if(isTame(unit))
out << ", tame"; out << ", tame";
@ -800,7 +556,7 @@ void unitInfo(color_ostream & out, df::unit* unit, bool verbose = false)
if(verbose) if(verbose)
{ {
out << ". Pos: ("<<unit->pos.x << "/"<< unit->pos.y << "/" << unit->pos.z << ") " << endl; out << ". Pos: ("<<unit->pos.x << "/"<< unit->pos.y << "/" << unit->pos.z << ") " << endl;
out << "index in units vector: " << getUnitIndexFromId(unit) << endl; out << "index in units vector: " << FindIndexById(unit->id) << endl;
} }
out << endl; out << endl;
@ -843,41 +599,6 @@ void unitInfo(color_ostream & out, df::unit* unit, bool verbose = false)
} }
} }
bool isActivityZone(df::building * building)
{
if( building->getType() == building_type::Civzone
&& building->getSubtype() == (short)civzone_type::ActivityZone)
return true;
else
return false;
}
bool isPenPasture(df::building * building)
{
if(!isActivityZone(building))
return false;
df::building_civzonest * civ = (df::building_civzonest *) building;
if(civ->zone_flags.bits.pen_pasture)
return true;
else
return false;
}
bool isPitPond(df::building * building)
{
if(!isActivityZone(building))
return false;
df::building_civzonest * civ = (df::building_civzonest *) building;
if(civ->zone_flags.bits.pit_pond) // && civ->pit_flags==0)
return true;
else
return false;
}
bool isCage(df::building * building) bool isCage(df::building * building)
{ {
return building->getType() == building_type::Cage; return building->getType() == building_type::Cage;
@ -888,128 +609,21 @@ bool isChain(df::building * building)
return building->getType() == building_type::Chain; return building->getType() == building_type::Chain;
} }
bool isActive(df::building * building) // returns building of cage at cursor position (NULL if nothing found)
{ df::building* findCageAtCursor()
if(!isActivityZone(building))
return false;
df::building_civzonest * civ = (df::building_civzonest *) building;
if(civ->zone_flags.bits.active)
return true;
else
return false;
}
int32_t findBuildingIndexById(int32_t id)
{
for (size_t b = 0; b < world->buildings.all.size(); b++)
{
if(world->buildings.all.at(b)->id == id)
return b;
}
return -1;
}
int32_t findUnitIndexById(int32_t id)
{
for (size_t i = 0; i < world->units.all.size(); i++)
{
if(world->units.all.at(i)->id == id)
return i;
}
return -1;
}
df::unit* findUnitById(int32_t id)
{
int32_t index = findUnitIndexById(id);
if(index != -1)
return world->units.all[index];
else
return NULL;
}
// returns id of pen/pit at cursor position (-1 if nothing found)
int32_t findPenPitAtCursor()
{
int32_t foundID = -1;
if(cursor->x == -30000)
return -1;
for (size_t b = 0; b < world->buildings.all.size(); b++)
{
df::building* building = world->buildings.all[b];
// find zone under cursor
if (!(building->x1 <= cursor->x && cursor->x <= building->x2 &&
building->y1 <= cursor->y && cursor->y <= building->y2 &&
building->z == cursor->z))
continue;
if(isPenPasture(building) || isPitPond(building))
{
foundID = building->id;
break;
}
}
return foundID;
}
// returns id of cage at cursor position (-1 if nothing found)
int32_t findCageAtCursor()
{ {
int32_t foundID = -1; df::building* building = Buildings::findAtTile(Gui::getCursorPos());
if(cursor->x == -30000)
return -1;
for (size_t b = 0; b < world->buildings.all.size(); b++)
{
df::building* building = world->buildings.all[b];
if (!(building->x1 <= cursor->x && cursor->x <= building->x2 &&
building->y1 <= cursor->y && cursor->y <= building->y2 &&
building->z == cursor->z))
continue;
// don't set id if cage is not constructed yet
if(building->getBuildStage()!=building->getMaxBuildStage())
break;
if (isCage(building)) if (isCage(building))
{ return building;
foundID = building->id; return NULL;
break;
}
}
return foundID;
} }
int32_t findChainAtCursor() df::building* findChainAtCursor()
{
int32_t foundID = -1;
if(cursor->x == -30000)
return -1;
for (size_t b = 0; b < world->buildings.all.size(); b++)
{ {
df::building* building = world->buildings.all[b]; df::building* building = Buildings::findAtTile(Gui::getCursorPos());
// find zone under cursor
if (!(building->x1 <= cursor->x && cursor->x <= building->x2 &&
building->y1 <= cursor->y && cursor->y <= building->y2 &&
building->z == cursor->z))
continue;
if (isChain(building)) if (isChain(building))
{ return building;
foundID = building->id; return NULL;
break;
}
}
return foundID;
} }
df::general_ref_building_civzone_assignedst * createCivzoneRef() df::general_ref_building_civzone_assignedst * createCivzoneRef()
@ -1283,7 +897,6 @@ bool isEmptyPasture(df::building* building)
df::building* findFreeNestboxZone() df::building* findFreeNestboxZone()
{ {
df::building * free_building = NULL; df::building * free_building = NULL;
bool cage = false;
for (size_t b=0; b < world->buildings.all.size(); b++) for (size_t b=0; b < world->buildings.all.size(); b++)
{ {
df::building* building = world->buildings.all[b]; df::building* building = world->buildings.all[b];
@ -1544,8 +1157,6 @@ command_result assignUnitToBuilding(color_ostream& out, df::unit* unit, df::buil
command_result assignUnitsToCagezone(color_ostream& out, vector<df::unit*> units, df::building* building, bool verbose) command_result assignUnitsToCagezone(color_ostream& out, vector<df::unit*> units, df::building* building, bool verbose)
{ {
command_result result = CR_WRONG_USAGE;
if(!isPenPasture(building)) if(!isPenPasture(building))
{ {
out << "A cage zone needs to be a pen/pasture containing at least one cage!" << endl; out << "A cage zone needs to be a pen/pasture containing at least one cage!" << endl;
@ -1615,7 +1226,7 @@ command_result nickUnitsInZone(color_ostream& out, df::building* building, strin
df::building_civzonest * civz = (df::building_civzonest *) building; df::building_civzonest * civz = (df::building_civzonest *) building;
for(size_t i = 0; i < civz->assigned_units.size(); i++) for(size_t i = 0; i < civz->assigned_units.size(); i++)
{ {
df::unit* unit = findUnitById(civz->assigned_units[i]); df::unit* unit = df::unit::find(civz->assigned_units[i]);
if(unit) if(unit)
Units::setNickname(unit, nick); Units::setNickname(unit, nick);
} }
@ -1635,7 +1246,7 @@ command_result nickUnitsInCage(color_ostream& out, df::building* building, strin
df::building_cagest* cage = (df::building_cagest*) building; df::building_cagest* cage = (df::building_cagest*) building;
for(size_t i=0; i<cage->assigned_units.size(); i++) for(size_t i=0; i<cage->assigned_units.size(); i++)
{ {
df::unit* unit = findUnitById(cage->assigned_units[i]); df::unit* unit = df::unit::find(cage->assigned_units[i]);
if(unit) if(unit)
Units::setNickname(unit, nick); Units::setNickname(unit, nick);
} }
@ -1670,10 +1281,7 @@ command_result nickUnitsInBuilding(color_ostream& out, df::building* building, s
// dump some zone info // dump some zone info
void zoneInfo(color_ostream & out, df::building* building, bool verbose) void zoneInfo(color_ostream & out, df::building* building, bool verbose)
{ {
if(building->getType()!= building_type::Civzone) if(!isActivityZone(building))
return;
if(building->getSubtype() != (short)civzone_type::ActivityZone)
return; return;
string name; string name;
@ -1689,7 +1297,7 @@ void zoneInfo(color_ostream & out, df::building* building, bool verbose)
out.print("\n"); out.print("\n");
df::building_civzonest * civ = (df::building_civzonest *) building; df::building_civzonest * civ = (df::building_civzonest *) building;
if(civ->zone_flags.bits.active) if(isActive(civ))
out << "active"; out << "active";
else else
out << "not active"; out << "not active";
@ -1712,7 +1320,7 @@ void zoneInfo(color_ostream & out, df::building* building, bool verbose)
<< " z:" <<building->z << " z:" <<building->z
<< endl; << endl;
int32_t creaturecount = civ->assigned_units.size(); size_t creaturecount = civ->assigned_units.size();
out << "Creatures in this zone: " << creaturecount << endl; out << "Creatures in this zone: " << creaturecount << endl;
for(size_t c = 0; c < creaturecount; c++) for(size_t c = 0; c < creaturecount; c++)
{ {
@ -1752,7 +1360,7 @@ void cageInfo(color_ostream & out, df::building* building, bool verbose)
df::building_cagest * cage = (df::building_cagest*) building; df::building_cagest * cage = (df::building_cagest*) building;
int32_t creaturecount = cage->assigned_units.size(); size_t creaturecount = cage->assigned_units.size();
out << "Creatures in this cage: " << creaturecount << endl; out << "Creatures in this cage: " << creaturecount << endl;
for(size_t c = 0; c < creaturecount; c++) for(size_t c = 0; c < creaturecount; c++)
{ {
@ -1827,7 +1435,6 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
bool find_tame = false; bool find_tame = false;
bool find_not_tame = false; bool find_not_tame = false;
bool find_merchant = false; bool find_merchant = false;
bool find_not_merchant = false;
bool find_male = false; bool find_male = false;
bool find_not_male = false; bool find_not_male = false;
bool find_female = false; bool find_female = false;
@ -1864,7 +1471,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
bool verbose = false; bool verbose = false;
bool all = false; bool all = false;
bool unit_slaughter = false; bool unit_slaughter = false;
static int target_building = -1; static df::building* target_building = NULL;
bool nick_set = false; bool nick_set = false;
string target_nick = ""; string target_nick = "";
@ -1935,19 +1542,19 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
if(new_building != -1) if(new_building != -1)
{ {
i++; i++;
target_building = new_building; target_building = df::building::find(new_building);
out << "Assign selected unit(s) to building #" << target_building <<std::endl; out << "Assign selected unit(s) to building #" << new_building <<std::endl;
} }
} }
} }
if(target_building == -1) if(!target_building)
{ {
out.printerr("No building id specified and current one is invalid!\n"); out.printerr("No building id specified and current one is invalid!\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
else else
{ {
out << "No buiding id specified. Will try to use #" << target_building << endl; out << "No buiding id specified. Will try to use #" << target_building->id << endl;
building_assign = true; building_assign = true;
} }
} }
@ -1968,18 +1575,18 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
if(new_building != -1) if(new_building != -1)
{ {
i++; i++;
target_building = new_building; target_building = df::building::find(new_building);
out << "Assign selected unit(s) to cagezone #" << target_building <<std::endl; out << "Assign selected unit(s) to cagezone #" << new_building <<std::endl;
} }
} }
if(target_building == -1) if(!target_building)
{ {
out.printerr("No building id specified and current one is invalid!\n"); out.printerr("No building id specified and current one is invalid!\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
else else
{ {
out << "No buiding id specified. Will try to use #" << target_building << endl; out << "No buiding id specified. Will try to use #" << target_building->id << endl;
cagezone_assign = true; cagezone_assign = true;
} }
} }
@ -2260,7 +1867,6 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
else if(p == "merchant" && invert_filter) else if(p == "merchant" && invert_filter)
{ {
// actually 'not merchant' is pointless since merchant units are ignored by default // actually 'not merchant' is pointless since merchant units are ignored by default
find_not_merchant = true;
invert_filter=false; invert_filter=false;
} }
else if(p == "milkable" && !invert_filter) else if(p == "milkable" && !invert_filter)
@ -2382,21 +1988,13 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
// (doesn't use the findXyzAtCursor() methods because zones might overlap and contain a cage or chain) // (doesn't use the findXyzAtCursor() methods because zones might overlap and contain a cage or chain)
if(zone_info) // || chain_info || cage_info) if(zone_info) // || chain_info || cage_info)
{ {
for (size_t b = 0; b < world->buildings.all.size(); b++) vector<df::building_civzonest*> zones;
{ Buildings::findCivzonesAt(&zones, Gui::getCursorPos());
df::building * building = world->buildings.all[b]; for (auto zone = zones.begin(); zone != zones.end(); ++zone)
zoneInfo(out, *zone, verbose);
// find building under cursor df::building* building = Buildings::findAtTile(Gui::getCursorPos());
if (!all &&
!(building->x1 <= cursor->x && cursor->x <= building->x2 &&
building->y1 <= cursor->y && cursor->y <= building->y2 &&
building->z == cursor->z))
continue;
zoneInfo(out, building, verbose);
chainInfo(out, building, verbose); chainInfo(out, building, verbose);
cageInfo(out, building, verbose); cageInfo(out, building, verbose);
}
return CR_OK; return CR_OK;
} }
@ -2406,14 +2004,14 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
// cagezone wants a pen/pit as starting point // cagezone wants a pen/pit as starting point
if(!cagezone_assign) if(!cagezone_assign)
target_building = findCageAtCursor(); target_building = findCageAtCursor();
if(target_building != -1) if(!target_building)
{ {
out << "Target building type: cage." << endl; out << "Target building type: cage." << endl;
} }
else else
{ {
target_building = findPenPitAtCursor(); target_building = findPenPitAt(Gui::getCursorPos());
if(target_building == -1) if(!target_building)
{ {
out << "No pen/pasture or pit under cursor!" << endl; out << "No pen/pasture or pit under cursor!" << endl;
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
@ -2423,29 +2021,23 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
out << "Target building type: pen/pasture or pit." << endl; out << "Target building type: pen/pasture or pit." << endl;
} }
} }
out << "Current building set to #" << target_building << endl; out << "Current building set to #" << target_building->id << endl;
return CR_OK; return CR_OK;
} }
if(building_assign || cagezone_assign || unit_info || unit_slaughter || nick_set) if(building_assign || cagezone_assign || unit_info || unit_slaughter || nick_set)
{ {
df::building * building;
if(building_assign || cagezone_assign || (nick_set && !all && !find_count)) if(building_assign || cagezone_assign || (nick_set && !all && !find_count))
{ {
// try to get building index from the id if (!target_building)
int32_t index = findBuildingIndexById(target_building);
if(index == -1)
{ {
out << "Invalid building id." << endl; out << "Invalid building id." << endl;
target_building = -1;
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
building = world->buildings.all.at(index);
if(nick_set && !building_assign) if(nick_set && !building_assign)
{ {
out << "Renaming all units in target building." << endl; out << "Renaming all units in target building." << endl;
return nickUnitsInBuilding(out, building, target_nick); return nickUnitsInBuilding(out, target_building, target_nick);
} }
} }
@ -2497,8 +2089,8 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
|| (find_not_war && isWar(unit)) || (find_not_war && isWar(unit))
|| (find_hunter && !isHunter(unit)) || (find_hunter && !isHunter(unit))
|| (find_not_hunter && isHunter(unit)) || (find_not_hunter && isHunter(unit))
|| (find_agemin && getUnitAge(unit)<target_agemin) || (find_agemin && (int) getAge(unit, true)<target_agemin)
|| (find_agemax && getUnitAge(unit)>target_agemax) || (find_agemax && (int) getAge(unit, true)>target_agemax)
|| (find_grazer && !isGrazer(unit)) || (find_grazer && !isGrazer(unit))
|| (find_not_grazer && isGrazer(unit)) || (find_not_grazer && isGrazer(unit))
|| (find_egglayer && !isEggLayer(unit)) || (find_egglayer && !isEggLayer(unit))
@ -2553,7 +2145,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
} }
else if(building_assign) else if(building_assign)
{ {
command_result result = assignUnitToBuilding(out, unit, building, verbose); command_result result = assignUnitToBuilding(out, unit, target_building, verbose);
if(result != CR_OK) if(result != CR_OK)
return result; return result;
} }
@ -2571,7 +2163,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
} }
if(cagezone_assign) if(cagezone_assign)
{ {
command_result result = assignUnitsToCagezone(out, units_for_cagezone, building, verbose); command_result result = assignUnitsToCagezone(out, units_for_cagezone, target_building, verbose);
if(result != CR_OK) if(result != CR_OK)
return result; return result;
} }
@ -2592,7 +2184,7 @@ command_result df_zone (color_ostream &out, vector <string> & parameters)
} }
else if(building_assign) else if(building_assign)
{ {
return assignUnitToBuilding(out, unit, building, verbose); return assignUnitToBuilding(out, unit, target_building, verbose);
} }
else if(unit_slaughter) else if(unit_slaughter)
{ {
@ -2771,8 +2363,8 @@ command_result autoNestbox( color_ostream &out, bool verbose = false )
// (assuming that the value from there indicates in which tick of the current year the unit was born) // (assuming that the value from there indicates in which tick of the current year the unit was born)
bool compareUnitAgesYounger(df::unit* i, df::unit* j) bool compareUnitAgesYounger(df::unit* i, df::unit* j)
{ {
int32_t age_i = getUnitAge(i); int32_t age_i = (int32_t) getAge(i, true);
int32_t age_j = getUnitAge(j); int32_t age_j = (int32_t) getAge(j, true);
if(age_i == 0 && age_j == 0) if(age_i == 0 && age_j == 0)
{ {
age_i = i->relations.birth_time; age_i = i->relations.birth_time;
@ -2782,8 +2374,8 @@ bool compareUnitAgesYounger(df::unit* i, df::unit* j)
} }
bool compareUnitAgesOlder(df::unit* i, df::unit* j) bool compareUnitAgesOlder(df::unit* i, df::unit* j)
{ {
int32_t age_i = getUnitAge(i); int32_t age_i = (int32_t) getAge(i, true);
int32_t age_j = getUnitAge(j); int32_t age_j = (int32_t) getAge(j, true);
if(age_i == 0 && age_j == 0) if(age_i == 0 && age_j == 0)
{ {
age_i = i->relations.birth_time; age_i = i->relations.birth_time;
@ -2811,30 +2403,32 @@ public:
int raceId; int raceId;
// target amounts // target amounts
int fk; // max female kids unsigned fk; // max female kids
int mk; // max male kids unsigned mk; // max male kids
int fa; // max female adults unsigned fa; // max female adults
int ma; // max male adults unsigned ma; // max male adults
// amounts of protected (not butcherable) units // amounts of protected (not butcherable) units
int fk_prot; unsigned fk_prot;
int fa_prot; unsigned fa_prot;
int mk_prot; unsigned mk_prot;
int ma_prot; unsigned ma_prot;
// butcherable units // butcherable units
vector <df::unit*> fk_ptr; vector <df::unit*> unit_ptr[4];
vector <df::unit*> mk_ptr; vector <df::unit*> fk_ptr = unit_ptr[0];
vector <df::unit*> fa_ptr; vector <df::unit*> mk_ptr = unit_ptr[1];
vector <df::unit*> ma_ptr; vector <df::unit*> fa_ptr = unit_ptr[2];
vector <df::unit*> ma_ptr = unit_ptr[3];
// priority butcherable units // priority butcherable units
vector <df::unit*> fk_pri_ptr; vector <df::unit*> prot_ptr[4];
vector <df::unit*> mk_pri_ptr; vector <df::unit*> fk_pri_ptr = prot_ptr[0];
vector <df::unit*> fa_pri_ptr; vector <df::unit*> mk_pri_ptr = prot_ptr[1];
vector <df::unit*> ma_pri_ptr; vector <df::unit*> fa_pri_ptr = prot_ptr[2];
vector <df::unit*> ma_pri_ptr = prot_ptr[3];
WatchedRace(bool watch, int id, int _fk, int _mk, int _fa, int _ma) WatchedRace(bool watch, int id, unsigned _fk, unsigned _mk, unsigned _fa, unsigned _ma)
{ {
isWatched = watch; isWatched = watch;
raceId = id; raceId = id;
@ -2854,7 +2448,7 @@ public:
{ {
if(!rconfig.isValid()) if(!rconfig.isValid())
{ {
string keyname = "autobutcher/watchlist/" + getRaceName(raceId); string keyname = "autobutcher/watchlist/" + getRaceNameById(raceId);
rconfig = World::GetPersistentData(keyname, NULL); rconfig = World::GetPersistentData(keyname, NULL);
} }
if(rconfig.isValid()) if(rconfig.isValid())
@ -2869,7 +2463,7 @@ public:
else else
{ {
// this should never happen // this should never happen
string keyname = "autobutcher/watchlist/" + getRaceName(raceId); string keyname = "autobutcher/watchlist/" + getRaceNameById(raceId);
out << "Something failed, could not find/create config key " << keyname << "!" << endl; out << "Something failed, could not find/create config key " << keyname << "!" << endl;
} }
} }
@ -2950,17 +2544,14 @@ public:
void ClearUnits() void ClearUnits()
{ {
fk_prot = fa_prot = mk_prot = ma_prot = 0; fk_prot = fa_prot = mk_prot = ma_prot = 0;
fk_ptr.clear(); for (size_t i = 0; i < 4; i++)
mk_ptr.clear(); {
fa_ptr.clear(); unit_ptr[i].clear();
ma_ptr.clear(); prot_ptr[i].clear();
fk_pri_ptr.clear(); }
mk_pri_ptr.clear();
fa_pri_ptr.clear();
ma_pri_ptr.clear();
} }
int ProcessUnits(vector<df::unit*>& unit_ptr, vector<df::unit*>& unit_pri_ptr, int prot, int goal) int ProcessUnits(vector<df::unit*>& unit_ptr, vector<df::unit*>& unit_pri_ptr, unsigned prot, unsigned goal)
{ {
int subcount = 0; int subcount = 0;
while(unit_pri_ptr.size() && (unit_ptr.size() + unit_pri_ptr.size() + prot > goal) ) while(unit_pri_ptr.size() && (unit_ptr.size() + unit_pri_ptr.size() + prot > goal) )
@ -3000,8 +2591,8 @@ std::vector<WatchedRace*> watched_races;
// helper for sorting the watchlist alphabetically // helper for sorting the watchlist alphabetically
bool compareRaceNames(WatchedRace* i, WatchedRace* j) bool compareRaceNames(WatchedRace* i, WatchedRace* j)
{ {
string name_i = getRaceNamePlural(i->raceId); string name_i = getRaceNamePluralById(i->raceId);
string name_j = getRaceNamePlural(j->raceId); string name_j = getRaceNamePluralById(j->raceId);
return (name_i < name_j); return (name_i < name_j);
} }
@ -3009,10 +2600,10 @@ bool compareRaceNames(WatchedRace* i, WatchedRace* j)
static void autobutcher_sortWatchList(color_ostream &out); static void autobutcher_sortWatchList(color_ostream &out);
// default target values for autobutcher // default target values for autobutcher
static int default_fk = 5; static unsigned default_fk = 5;
static int default_mk = 1; static unsigned default_mk = 1;
static int default_fa = 5; static unsigned default_fa = 5;
static int default_ma = 1; static unsigned default_ma = 1;
command_result df_autobutcher(color_ostream &out, vector <string> & parameters) command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
{ {
@ -3028,12 +2619,10 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
vector <string> target_racenames; vector <string> target_racenames;
vector <int> target_raceids; vector <int> target_raceids;
int target_fk = default_fk; unsigned target_fk = default_fk;
int target_mk = default_mk; unsigned target_mk = default_mk;
int target_fa = default_fa; unsigned target_fa = default_fa;
int target_ma = default_ma; unsigned target_ma = default_ma;
int32_t target_raceid = -1;
if(!parameters.size()) if(!parameters.size())
{ {
@ -3343,7 +2932,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
bool found_race = false; bool found_race = false;
for(size_t i=0; i<num_races; i++) for(size_t i=0; i<num_races; i++)
{ {
if(getRaceName(i) == target_racenames.back()) if(getRaceNameById(i) == target_racenames.back())
{ {
target_raceids.push_back(i); target_raceids.push_back(i);
target_racenames.pop_back(); target_racenames.pop_back();
@ -3480,7 +3069,7 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
watched_races.push_back(w); watched_races.push_back(w);
string announce; string announce;
announce = "New race added to autobutcher watchlist: " + getRaceNamePlural(w->raceId); announce = "New race added to autobutcher watchlist: " + getRaceNamePluralById(w->raceId);
Gui::showAnnouncement(announce, 2, false); Gui::showAnnouncement(announce, 2, false);
autobutcher_sortWatchList(out); autobutcher_sortWatchList(out);
} }
@ -3517,7 +3106,7 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
stringstream ss; stringstream ss;
ss << slaughter_subcount; ss << slaughter_subcount;
string announce; string announce;
announce = getRaceNamePlural(w->raceId) + " marked for slaughter: " + ss.str(); announce = getRaceNamePluralById(w->raceId) + " marked for slaughter: " + ss.str();
Gui::showAnnouncement(announce, 2, false); Gui::showAnnouncement(announce, 2, false);
} }
} }
@ -3845,7 +3434,7 @@ void butcherRace(int race)
if(!isContainedInItem(unit) && !hasValidMapPos(unit)) if(!isContainedInItem(unit) && !hasValidMapPos(unit))
continue; continue;
unit->flags2.bits.slaughter = true; doMarkForSlaughter(unit);
} }
} }
@ -3868,7 +3457,7 @@ void unbutcherRace(int race)
if(!isContainedInItem(unit) && !hasValidMapPos(unit)) if(!isContainedInItem(unit) && !hasValidMapPos(unit))
continue; continue;
unit->flags2.bits.slaughter = false; unit->flags2.bits.slaughter = 0;
} }
} }
@ -3954,7 +3543,7 @@ static void autobutcher_setWatchListRace(color_ostream &out, unsigned id, unsign
watched_races.push_back(w); watched_races.push_back(w);
string announce; string announce;
announce = "New race added to autobutcher watchlist: " + getRaceNamePlural(w->raceId); announce = "New race added to autobutcher watchlist: " + getRaceNamePluralById(w->raceId);
Gui::showAnnouncement(announce, 2, false); Gui::showAnnouncement(announce, 2, false);
autobutcher_sortWatchList(out); autobutcher_sortWatchList(out);
} }
@ -4049,7 +3638,7 @@ static int autobutcher_getWatchList(lua_State *L)
WatchedRace * w = watched_races[i]; WatchedRace * w = watched_races[i];
Lua::SetField(L, w->raceId, ctable, "id"); Lua::SetField(L, w->raceId, ctable, "id");
Lua::SetField(L, w->isWatched, ctable, "watched"); Lua::SetField(L, w->isWatched, ctable, "watched");
Lua::SetField(L, getRaceNamePlural(w->raceId), ctable, "name"); Lua::SetField(L, getRaceNamePluralById(w->raceId), ctable, "name");
Lua::SetField(L, w->fk, ctable, "fk"); Lua::SetField(L, w->fk, ctable, "fk");
Lua::SetField(L, w->mk, ctable, "mk"); Lua::SetField(L, w->mk, ctable, "mk");
Lua::SetField(L, w->fa, ctable, "fa"); Lua::SetField(L, w->fa, ctable, "fa");
@ -4178,7 +3767,7 @@ public:
int adjusted_item_index = i; int adjusted_item_index = i;
if (list_has_been_sorted) if (list_has_been_sorted)
{ {
for (int j = 0; j < ui_building_assign_units->size(); j++) for (size_t j = 0; j < ui_building_assign_units->size(); j++)
{ {
if (ui_building_assign_units->at(j) == reference_list[i]) if (ui_building_assign_units->at(j) == reference_list[i])
{ {