Add a new tweak, "reaction-gloves"

When enabled, custom reactions will begin to produce gloves in sets, based
on the number of hands the job performer's race has, and set the
Handedness flags accordingly.

The "createitem" plugin already contains a simpler workaround (which
doesn't check body plan but instead just produces pairs), but it shouldn't
trigger when this tweak is enabled (unless you use it on a creature which
has been modded to only have "neutral" hands).
develop
Quietust 2020-06-02 09:10:25 -06:00
parent e2301ecae7
commit 2597aeab0e
2 changed files with 81 additions and 0 deletions

@ -59,6 +59,7 @@
#include "df/reaction.h" #include "df/reaction.h"
#include "df/reaction_reagent_itemst.h" #include "df/reaction_reagent_itemst.h"
#include "df/reaction_reagent_flags.h" #include "df/reaction_reagent_flags.h"
#include "df/reaction_product_itemst.h"
#include "df/viewscreen_setupdwarfgamest.h" #include "df/viewscreen_setupdwarfgamest.h"
#include "df/viewscreen_layer_assigntradest.h" #include "df/viewscreen_layer_assigntradest.h"
#include "df/viewscreen_tradegoodsst.h" #include "df/viewscreen_tradegoodsst.h"
@ -106,6 +107,7 @@
#include "tweaks/stone-status-all.h" #include "tweaks/stone-status-all.h"
#include "tweaks/title-start-rename.h" #include "tweaks/title-start-rename.h"
#include "tweaks/tradereq-pet-gender.h" #include "tweaks/tradereq-pet-gender.h"
#include "tweaks/reaction-gloves.h"
using std::set; using std::set;
using std::vector; using std::vector;
@ -250,6 +252,8 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" Adds a safe rename option to the title screen \"Start Playing\" menu\n" " Adds a safe rename option to the title screen \"Start Playing\" menu\n"
" tweak tradereq-pet-gender [disable]\n" " tweak tradereq-pet-gender [disable]\n"
" Displays the gender of pets in the trade request list\n" " Displays the gender of pets in the trade request list\n"
" tweak reaction-gloves [disable]\n"
" Changes custom reactions to produce gloves in sets with correct handedness\n"
// " tweak military-training [disable]\n" // " tweak military-training [disable]\n"
// " Speed up melee squad training, removing inverse dependency on unit count.\n" // " Speed up melee squad training, removing inverse dependency on unit count.\n"
)); ));
@ -332,6 +336,8 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
TWEAK_HOOK("tradereq-pet-gender", pet_gender_hook, render); TWEAK_HOOK("tradereq-pet-gender", pet_gender_hook, render);
TWEAK_HOOK("reaction-gloves", reaction_gloves_hook, produce);
return CR_OK; return CR_OK;
} }

@ -0,0 +1,75 @@
// Workaround for DF bug #6273 - adjust all custom reactions to produce GLOVES items in sets with correct handedness
// It also analyzes the body plan of the unit performing the reaction, so Antmen will get 4 gloves instead of 2
// If a reaction tries to produce either 1 glove or 2 gloves, it will produce a single set
// Otherwise, it will multiply the number of products by the number of hands
struct reaction_gloves_hook : df::reaction_product_itemst {
typedef df::reaction_product_itemst interpose_base;
DEFINE_VMETHOD_INTERPOSE(void, produce, (df::unit *unit, std::vector<df::reaction_product*> *out_products, std::vector<df::item*> *out_items, std::vector<df::reaction_reagent*> *in_reag, std::vector<df::item*> *in_items, int32_t quantity, df::job_skill skill, df::historical_entity *entity, int32_t unk_1, df::world_site *site, void *unk_2))
{
if (item_type != df::item_type::GLOVES)
{
INTERPOSE_NEXT(produce)(unit, out_products, out_items, in_reag, in_items, quantity, skill, entity, unk_1, 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<df::item*> 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, entity, unk_1, 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);