Added a report to autoclothing, as well as some changes to DFHack::Units to enable it.

develop
Rose 2023-01-13 21:20:01 -08:00
parent 21d160c478
commit 0e021e392d
4 changed files with 121 additions and 1 deletions

@ -179,6 +179,8 @@ DFHACK_EXPORT std::string getRaceName(df::unit* unit);
DFHACK_EXPORT std::string getPhysicalDescription(df::unit* unit); DFHACK_EXPORT std::string getPhysicalDescription(df::unit* unit);
DFHACK_EXPORT std::string getRaceNamePluralById(int32_t race_id); DFHACK_EXPORT std::string getRaceNamePluralById(int32_t race_id);
DFHACK_EXPORT std::string getRaceNamePlural(df::unit* unit); DFHACK_EXPORT std::string getRaceNamePlural(df::unit* unit);
DFHACK_EXPORT std::string getRaceReadableNameById(int32_t race_id);
DFHACK_EXPORT std::string getRaceReadableName(df::unit* unit);
DFHACK_EXPORT std::string getRaceBabyNameById(int32_t race_id); DFHACK_EXPORT std::string getRaceBabyNameById(int32_t race_id);
DFHACK_EXPORT std::string getRaceBabyName(df::unit* unit); DFHACK_EXPORT std::string getRaceBabyName(df::unit* unit);
DFHACK_EXPORT std::string getRaceChildNameById(int32_t race_id); DFHACK_EXPORT std::string getRaceChildNameById(int32_t race_id);

@ -1036,6 +1036,20 @@ string Units::getRaceName(df::unit* unit)
return getRaceNameById(unit->race); return getRaceNameById(unit->race);
} }
// get human-readable race name by id or unit pointer
string Units::getRaceReadableNameById(int32_t id)
{
df::creature_raw* raw = world->raws.creatures.all[id];
if (raw)
return raw->name[0];
return "";
}
string Units::getRaceReadableName(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return getRaceReadableNameById(unit->race);
}
void df_unit_get_physical_description(df::unit* unit, string* out_str) void df_unit_get_physical_description(df::unit* unit, string* out_str)
{ {
static auto* const fn = static auto* const fn =

@ -77,7 +77,7 @@ set_source_files_properties( Brushes.h PROPERTIES HEADER_FILE_ONLY TRUE )
#dfhack_plugin(add-spatter add-spatter.cpp) #dfhack_plugin(add-spatter add-spatter.cpp)
dfhack_plugin(autobutcher autobutcher.cpp LINK_LIBRARIES lua) dfhack_plugin(autobutcher autobutcher.cpp LINK_LIBRARIES lua)
dfhack_plugin(autochop autochop.cpp LINK_LIBRARIES lua) dfhack_plugin(autochop autochop.cpp LINK_LIBRARIES lua)
#dfhack_plugin(autoclothing autoclothing.cpp) dfhack_plugin(autoclothing autoclothing.cpp)
#dfhack_plugin(autodump autodump.cpp) #dfhack_plugin(autodump autodump.cpp)
dfhack_plugin(autofarm autofarm.cpp) dfhack_plugin(autofarm autofarm.cpp)
#dfhack_plugin(autogems autogems.cpp LINK_LIBRARIES jsoncpp_static) #dfhack_plugin(autogems autogems.cpp LINK_LIBRARIES jsoncpp_static)

@ -13,6 +13,7 @@
#include "modules/Materials.h" #include "modules/Materials.h"
#include "modules/Units.h" #include "modules/Units.h"
#include "modules/World.h" #include "modules/World.h"
#include "modules/Translation.h"
#include "df/itemdef_armorst.h" #include "df/itemdef_armorst.h"
#include "df/itemdef_glovesst.h" #include "df/itemdef_glovesst.h"
@ -55,6 +56,7 @@ static void cleanup_state(color_ostream &out);
static void do_autoclothing(); static void do_autoclothing();
static bool validateMaterialCategory(ClothingRequirement * requirement); static bool validateMaterialCategory(ClothingRequirement * requirement);
static bool setItem(std::string name, ClothingRequirement* requirement); static bool setItem(std::string name, ClothingRequirement* requirement);
static void generate_report(color_ostream& out);
std::vector<ClothingRequirement>clothingOrders; std::vector<ClothingRequirement>clothingOrders;
@ -366,6 +368,12 @@ command_result autoclothing(color_ostream &out, std::vector <std::string> & para
} }
return CR_OK; return CR_OK;
} }
else if (parameters.size() == 1 && parameters[0] == "report")
{
CoreSuspender suspend;
generate_report(out);
return CR_OK;
}
else if (parameters.size() < 2 || parameters.size() > 3) else if (parameters.size() < 2 || parameters.size() > 3)
{ {
out << "Wrong number of arguments." << endl; out << "Wrong number of arguments." << endl;
@ -663,3 +671,99 @@ static void save_state(color_ostream &out)
item.val() = clothingOrders[i].Serialize(); item.val() = clothingOrders[i].Serialize();
} }
} }
static void list_unit_counts(color_ostream& out, std::map<int, int>& unitList)
{
for (const auto& race : unitList)
{
if (race.second == 1)
out << " 1 " << Units::getRaceReadableNameById(race.first) << endl;
else
out << " " << race.second << " " << Units::getRaceNamePluralById(race.first) << endl;
}
}
static void generate_report(color_ostream& out)
{
std::map<int, int> fullUnitList;
std::map<int, int> missingArmor;
std::map<int, int> missingShoes;
std::map<int, int> missingHelms;
std::map<int, int> missingGloves;
std::map<int, int> missingPants;
for (df::unit* unit : world->units.active)
{
if (!Units::isCitizen(unit))
continue;
fullUnitList[unit->race]++;
int numArmor = 0, numShoes = 0, numHelms = 0, numGloves = 0, numPants = 0;
for (auto itemId : unit->owned_items)
{
auto item = Items::findItemByID(itemId);
if (item->getWear() >= 1)
continue;
switch (item->getType())
{
case df::item_type::ARMOR:
numArmor++;
break;
case df::item_type::SHOES:
numShoes++;
break;
case df::item_type::HELM:
numHelms++;
break;
case df::item_type::GLOVES:
numGloves++;
break;
case df::item_type::PANTS:
numPants++;
break;
default:
break;
}
}
if (numArmor == 0)
missingArmor[unit->race]++;
if (numShoes < 2)
missingShoes[unit->race]++;
if (numHelms == 0)
missingHelms[unit->race]++;
if (numGloves < 2)
missingGloves[unit->race]++;
if (numPants == 0)
missingPants[unit->race]++;
//out << Translation::TranslateName(Units::getVisibleName(unit)) << " has " << numArmor << " armor, " << numShoes << " shoes, " << numHelms << " helms, " << numGloves << " gloves, " << numPants << " pants" << endl;
}
if (missingArmor.size() + missingShoes.size() + missingHelms.size() + missingGloves.size() + missingPants.size() == 0)
{
out << "Everybody has a full set of clothes to wear, congrats!" << endl;
return;
}
if (missingArmor.size())
{
out << "Following units need new bodywear:" << endl;
list_unit_counts(out, missingArmor);
}
if (missingShoes.size())
{
out << "Following units need new shoes:" << endl;
list_unit_counts(out, missingShoes);
}
if (missingHelms.size())
{
out << "Following units need new headwear:" << endl;
list_unit_counts(out, missingHelms);
}
if (missingGloves.size())
{
out << "Following units need new handwear:" << endl;
list_unit_counts(out, missingGloves);
}
if (missingPants.size())
{
out << "Following units need new legwear:" << endl;
list_unit_counts(out, missingPants);
}
}