diff --git a/docs/Plugins.rst b/docs/Plugins.rst index 0185dbee5..e3c9ec9c1 100644 --- a/docs/Plugins.rst +++ b/docs/Plugins.rst @@ -335,6 +335,7 @@ Subcommands that persist until disabled or DF quits: :stone-status-all: Adds an option to toggle the economic status of all stones :title-start-rename: Adds a safe rename option to the title screen "Start Playing" menu :tradereq-pet-gender: Displays pet genders on the trade request screen +:reaction-gloves: Fixes reactions to produce gloves in sets with correct handedness .. _fix-armory: diff --git a/docs/changelog.txt b/docs/changelog.txt index 11ec944a9..2bc506565 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -33,6 +33,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: # Future +## New Tweaks +- `tweak` reaction-gloves: adds an option to make reactions produce gloves in sets with correct handedness + ## Fixes - Fixed a segfault when attempting to start a headless session with a graphical PRINT_MODE setting - Fixed an issue with the macOS launcher failing to un-quarantine some files diff --git a/plugins/tweak/tweak.cpp b/plugins/tweak/tweak.cpp index 49d96cc74..13e08f174 100644 --- a/plugins/tweak/tweak.cpp +++ b/plugins/tweak/tweak.cpp @@ -59,6 +59,7 @@ #include "df/reaction.h" #include "df/reaction_reagent_itemst.h" #include "df/reaction_reagent_flags.h" +#include "df/reaction_product_itemst.h" #include "df/viewscreen_setupdwarfgamest.h" #include "df/viewscreen_layer_assigntradest.h" #include "df/viewscreen_tradegoodsst.h" @@ -106,6 +107,7 @@ #include "tweaks/stone-status-all.h" #include "tweaks/title-start-rename.h" #include "tweaks/tradereq-pet-gender.h" +#include "tweaks/reaction-gloves.h" using std::set; using std::vector; @@ -250,6 +252,8 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector *out_products, std::vector *out_items, + std::vector *in_reag, std::vector *in_items, + int32_t quantity, df::job_skill skill, int32_t quality, + df::historical_entity *entity, df::world_site *site, std::vector *unk_2)) + { + if (item_type != df::item_type::GLOVES) + { + INTERPOSE_NEXT(produce)(unit, out_products, out_items, in_reag, in_items, quantity, skill, quality, entity, site, unk_2); + return; + } + + // Examine creator unit's body plan, see how many hands it has + // Count left hands and right hands, as well as "neutral" hands for compatibility + int num_hands = 0, num_left = 0, num_right = 0; + for (int i = 0; i < unit->body.body_plan->body_parts.size(); i++) + { + df::body_part_raw *part = unit->body.body_plan->body_parts[i]; + if (part->flags.is_set(df::body_part_raw_flags::GRASP)) + { + num_hands++; + if (part->flags.is_set(df::body_part_raw_flags::LEFT)) + num_left++; + if (part->flags.is_set(df::body_part_raw_flags::RIGHT)) + num_right++; + } + } + + std::vector out_items_temp; + int old_count = count; + + // If the reaction product's count is set to 1 or 2, set it to the number of hands + // Otherwise, *multiply* it by the number of hands (and multiply the left/right counts accordingly) + if (count <= 2) + count = num_hands; + else + { + num_left *= count; + num_right *= count; + count *= num_hands; + } + + INTERPOSE_NEXT(produce)(unit, out_products, &out_items_temp, in_reag, in_items, quantity, skill, quality, entity, site, unk_2); + count = old_count; + + // If the reaction was somehow asked to produce multiple sets (due to excess inputs), multiply the outputs too + num_left *= quantity; + num_right *= quantity; + + // Iterate across the output gloves, set their handedness, then append them to the actual out_items list for DF + for (int i = 0; i < out_items_temp.size(); i++) + { + // Do left gloves first, then right gloves, then "neutral" ones last + // This is important for the "createitem" plugin, which contains similar workaround logic + if (num_left > 0) + { + out_items_temp[i]->setGloveHandedness(1); + --num_left; + } + else if (num_right > 0) + { + out_items_temp[i]->setGloveHandedness(2); + --num_right; + } + out_items->push_back(out_items_temp[i]); + } + } +}; + +IMPLEMENT_VMETHOD_INTERPOSE(reaction_gloves_hook, produce); \ No newline at end of file