Merge pull request #2917 from ab9rf/5007-tailor

tailor: try to squash toad clothing bug
develop
Myk 2023-02-17 12:25:43 -08:00 committed by GitHub
commit 180d10dd32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 21 deletions

@ -42,6 +42,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- `autodump`: changed behaviour to only change ``dump`` and ``forbid`` flags if an item is successfully dumped. - `autodump`: changed behaviour to only change ``dump`` and ``forbid`` flags if an item is successfully dumped.
-@ `autochop`: generate default names for burrows with no assigned names -@ `autochop`: generate default names for burrows with no assigned names
- ``Buildings::StockpileIterator``: check for stockpile items on block boundary. - ``Buildings::StockpileIterator``: check for stockpile items on block boundary.
- `tailor`: block making clothing sized for toads; make replacement clothing orders use the size of the wearer, not the size of the garment; add support for adamantine cloth (off by default); improve logging
## Misc Improvements ## Misc Improvements
- DFHack tool windows that capture mouse clicks (and therefore prevent you from clicking on the "pause" button) now unconditionally pause the game when they open (but you can still unpause with the keyboard if you want to). Examples of this behavior: `gui/quickfort`, `gui/blueprint`, `gui/liquids` - DFHack tool windows that capture mouse clicks (and therefore prevent you from clicking on the "pause" button) now unconditionally pause the game when they open (but you can still unpause with the keyboard if you want to). Examples of this behavior: `gui/quickfort`, `gui/blueprint`, `gui/liquids`

@ -30,7 +30,11 @@ By default, ``tailor`` will prefer using materials in this order::
silk cloth yarn leather silk cloth yarn leather
but you can use the ``tailor materials`` command to restrict which materials but you can use the ``tailor materials`` command to restrict which materials
are used, and in what order. are used, and in what order. ``tailor`` supports adamantine cloth (using the
keyword ``adamantine``) but does not use it by default, as most players find
adamantine too precious to routinely make into cloth. ``tailor`` does not
support modded "cloth" types which utilize custom reactions to making clothing
out of those cloth types.
Examples Examples
-------- --------
@ -46,3 +50,12 @@ Examples
Restrict the materials used for automatically manufacturing clothing to Restrict the materials used for automatically manufacturing clothing to
silk, cloth, and yarn, preferred in that order. This saves leather for silk, cloth, and yarn, preferred in that order. This saves leather for
other uses, like making armor. other uses, like making armor.
Note
----
The reason for the limitation on modded cloth-like materials is
because custom reactions do not support the in-game mechanic
which allows a manager order to specify a different size for clothing items.
This mechanic only works for reactions that use the default make-clothing or
make-armor reactions, and is a limitation of the game itself.

@ -28,7 +28,8 @@ function setMaterials(names)
idxs.silk or -1, idxs.silk or -1,
idxs.cloth or -1, idxs.cloth or -1,
idxs.yarn or -1, idxs.yarn or -1,
idxs.leather or -1) idxs.leather or -1,
idxs.adamantine or -1)
end end
function parse_commandline(...) function parse_commandline(...)

@ -56,6 +56,7 @@ enum ConfigValues {
CONFIG_CLOTH_IDX = 2, CONFIG_CLOTH_IDX = 2,
CONFIG_YARN_IDX = 3, CONFIG_YARN_IDX = 3,
CONFIG_LEATHER_IDX = 4, CONFIG_LEATHER_IDX = 4,
CONFIG_ADAMANTINE_IDX = 5,
}; };
static int get_config_val(PersistentDataItem &c, int index) { static int get_config_val(PersistentDataItem &c, int index) {
@ -119,10 +120,11 @@ static const MatType
M_SILK = MatType("silk", df::job_material_category::mask_silk, df::armor_general_flags::SOFT), M_SILK = MatType("silk", df::job_material_category::mask_silk, df::armor_general_flags::SOFT),
M_CLOTH = MatType("cloth", df::job_material_category::mask_cloth, df::armor_general_flags::SOFT), M_CLOTH = MatType("cloth", df::job_material_category::mask_cloth, df::armor_general_flags::SOFT),
M_YARN = MatType("yarn", df::job_material_category::mask_yarn, df::armor_general_flags::SOFT), M_YARN = MatType("yarn", df::job_material_category::mask_yarn, df::armor_general_flags::SOFT),
M_LEATHER = MatType("leather", df::job_material_category::mask_leather, df::armor_general_flags::LEATHER); M_LEATHER = MatType("leather", df::job_material_category::mask_leather, df::armor_general_flags::LEATHER),
M_ADAMANTINE = MatType("adamantine", df::job_material_category::mask_strand, df::armor_general_flags::SOFT);
static const std::list<MatType> all_materials = { M_SILK, M_CLOTH, M_YARN, M_LEATHER }; static const std::list<MatType> all_materials = { M_SILK, M_CLOTH, M_YARN, M_LEATHER, M_ADAMANTINE };
static std::list<MatType> material_order = all_materials; static std::list<MatType> material_order = { M_SILK, M_CLOTH, M_YARN, M_LEATHER }; // M_ADAMANTINE is not included by default
static struct BadFlags { static struct BadFlags {
uint32_t whole; uint32_t whole;
@ -208,11 +210,13 @@ public:
supply[M_CLOTH] += ss; supply[M_CLOTH] += ss;
else if (mat.material->flags.is_set(df::material_flags::YARN)) else if (mat.material->flags.is_set(df::material_flags::YARN))
supply[M_YARN] += ss; supply[M_YARN] += ss;
else if (mat.material->flags.is_set(df::material_flags::STOCKPILE_THREAD_METAL))
supply[M_ADAMANTINE] += ss;
else else
{ {
std::string d; std::string d;
i->getItemDescription(&d, 0); i->getItemDescription(&d, 0);
WARN(cycle).print("tailor: weird cloth item found: %s (%d)\n", d.c_str(), i->id); DEBUG(cycle).print("tailor: weird cloth item found: %s (%d)\n", d.c_str(), i->id);
} }
} }
} }
@ -224,7 +228,8 @@ public:
supply[M_LEATHER] += i->getStackSize(); supply[M_LEATHER] += i->getStackSize();
} }
DEBUG(cycle).print("tailor: available silk %d yarn %d cloth %d leather %d\n", supply[M_SILK], supply[M_YARN], supply[M_CLOTH], supply[M_LEATHER]); DEBUG(cycle).print("tailor: available silk %d yarn %d cloth %d leather %d adamantine %d\n",
supply[M_SILK], supply[M_YARN], supply[M_CLOTH], supply[M_LEATHER], supply[M_ADAMANTINE]);
} }
void scan_replacements() void scan_replacements()
@ -253,8 +258,8 @@ public:
wearing.insert(inv->item->getType()); wearing.insert(inv->item->getType());
} }
int size = world->raws.creatures.all[u->race]->adultsize; int usize = world->raws.creatures.all[u->race]->adultsize;
sizes[size] = u->race; sizes[usize] = u->race;
for (auto ty : std::set<df::item_type>{ df::item_type::ARMOR, df::item_type::PANTS, df::item_type::SHOES }) for (auto ty : std::set<df::item_type>{ df::item_type::ARMOR, df::item_type::PANTS, df::item_type::SHOES })
{ {
@ -262,9 +267,9 @@ public:
{ {
TRACE(cycle).print("tailor: one %s of size %d needed to cover %s\n", TRACE(cycle).print("tailor: one %s of size %d needed to cover %s\n",
ENUM_KEY_STR(item_type, ty).c_str(), ENUM_KEY_STR(item_type, ty).c_str(),
size, usize,
Translation::TranslateName(&u->name, false).c_str()); Translation::TranslateName(&u->name, false).c_str());
needed[std::make_pair(ty, size)] += 1; needed[std::make_pair(ty, usize)] += 1;
} }
} }
@ -278,11 +283,11 @@ public:
} }
const df::job_type o = oo->second; const df::job_type o = oo->second;
int size = world->raws.creatures.all[w->getMakerRace()]->adultsize; int isize = world->raws.creatures.all[w->getMakerRace()]->adultsize;
std::string description; std::string description;
w->getItemDescription(&description, 0); w->getItemDescription(&description, 0);
if (available[std::make_pair(ty, size)] > 0) if (available[std::make_pair(ty, usize)] > 0)
{ {
if (w->flags.bits.owned) if (w->flags.bits.owned)
{ {
@ -298,10 +303,10 @@ public:
if (wearing.count(ty) == 0) if (wearing.count(ty) == 0)
{ {
DEBUG(cycle).print("tailor: allocating a %s to %s\n", DEBUG(cycle).print("tailor: allocating a %s (size %d) to %s\n",
ENUM_KEY_STR(item_type, ty).c_str(), ENUM_KEY_STR(item_type, ty).c_str(), usize,
Translation::TranslateName(&u->name, false).c_str()); Translation::TranslateName(&u->name, false).c_str());
available[std::make_pair(ty, size)] -= 1; available[std::make_pair(ty, usize)] -= 1;
} }
if (w->getWear() > 1) if (w->getWear() > 1)
@ -309,10 +314,10 @@ public:
} }
else else
{ {
DEBUG(cycle).print ("tailor: %s worn by %s needs replacement, but none available\n", DEBUG(cycle).print ("tailor: %s (size %d) worn by %s (size %d) needs replacement, but none available\n",
description.c_str(), description.c_str(), isize,
Translation::TranslateName(&u->name, false).c_str()); Translation::TranslateName(&u->name, false).c_str(), usize);
orders[std::make_tuple(o, w->getSubtype(), size)] += 1; orders[std::make_tuple(o, w->getSubtype(), usize)] += 1;
} }
} }
} }
@ -405,6 +410,13 @@ public:
std::tie(ty, sub, size) = o.first; std::tie(ty, sub, size) = o.first;
int count = o.second; int count = o.second;
if (sizes.count(size) == 0)
{
WARN(cycle).print("tailor: cannot determine race for clothing of size %d, skipped\n",
size);
continue;
}
if (count > 0) if (count > 0)
{ {
std::vector<int16_t> v; std::vector<int16_t> v;
@ -573,6 +585,8 @@ static void set_material_order() {
material_order.push_back(M_YARN); material_order.push_back(M_YARN);
else if (i == (size_t)get_config_val(config, CONFIG_LEATHER_IDX)) else if (i == (size_t)get_config_val(config, CONFIG_LEATHER_IDX))
material_order.push_back(M_LEATHER); material_order.push_back(M_LEATHER);
else if (i == (size_t)get_config_val(config, CONFIG_ADAMANTINE_IDX))
material_order.push_back(M_ADAMANTINE);
} }
if (!material_order.size()) if (!material_order.size())
std::copy(all_materials.begin(), all_materials.end(), std::back_inserter(material_order)); std::copy(all_materials.begin(), all_materials.end(), std::back_inserter(material_order));
@ -689,7 +703,8 @@ static void tailor_doCycle(color_ostream &out) {
// remember, these are ONE-based indices from Lua // remember, these are ONE-based indices from Lua
static void tailor_setMaterialPreferences(color_ostream &out, int32_t silkIdx, static void tailor_setMaterialPreferences(color_ostream &out, int32_t silkIdx,
int32_t clothIdx, int32_t yarnIdx, int32_t leatherIdx) { int32_t clothIdx, int32_t yarnIdx, int32_t leatherIdx,
int32_t adamantineIdx) {
DEBUG(config,out).print("entering tailor_setMaterialPreferences\n"); DEBUG(config,out).print("entering tailor_setMaterialPreferences\n");
// it doesn't really matter if these are invalid. set_material_order will do // it doesn't really matter if these are invalid. set_material_order will do
@ -698,6 +713,7 @@ static void tailor_setMaterialPreferences(color_ostream &out, int32_t silkIdx,
set_config_val(config, CONFIG_CLOTH_IDX, clothIdx - 1); set_config_val(config, CONFIG_CLOTH_IDX, clothIdx - 1);
set_config_val(config, CONFIG_YARN_IDX, yarnIdx - 1); set_config_val(config, CONFIG_YARN_IDX, yarnIdx - 1);
set_config_val(config, CONFIG_LEATHER_IDX, leatherIdx - 1); set_config_val(config, CONFIG_LEATHER_IDX, leatherIdx - 1);
set_config_val(config, CONFIG_ADAMANTINE_IDX, adamantineIdx - 1);
set_material_order(); set_material_order();
} }