From a94eb538bf3273609163491e5f7bb79c1357fc4c Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 21 Jun 2025 10:09:00 -0600 Subject: [PATCH] Add "count" parameter to Items::createItem and update the "createitem" plugin to specify it instead of creating a bunch of individual items in a loop. --- docs/changelog.txt | 1 + library/LuaApi.cpp | 5 ++++- library/include/modules/Items.h | 2 +- library/modules/Items.cpp | 4 ++-- plugins/createitem.cpp | 16 +++++++--------- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index b90b39a332..539b2c2240 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -90,6 +90,7 @@ Template for new versions: - `preserve-rooms`: don't warn when a room is assigned to a non-existent unit. this is now common behavior for DF when it keeps a room for an unloaded unit - fixed an overly restrictive type constraint that resulted in some object types being glossed as a boolean when passed as an argument from C++ to Lua - `plants`: will no longer generate a traceback when a filter is used +- `createitem`: multiple items should be properly created in stacks again ## Misc Improvements - All places where units are listed in DFHack tools now show the translated English name in addition to the native name. In particular, this makes units searchable by English name in `gui/sitemap`. diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 1d77ebf15a..1d3f4075a2 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2461,8 +2461,11 @@ static int items_createItem(lua_State *state) auto mat_type = lua_tointeger(state, 4); auto mat_index = lua_tointeger(state, 5); bool no_floor = lua_toboolean(state, 6); + int count = lua_tointeger(state, 7); + if (count < 1) + count = 1; vector out_items; - Items::createItem(out_items, unit, item_type, item_subtype, mat_type, mat_index, no_floor); + Items::createItem(out_items, unit, item_type, item_subtype, mat_type, mat_index, no_floor, count); Lua::PushVector(state, out_items); return 1; } diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 6d068e8786..1189fd8bc2 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -173,7 +173,7 @@ DFHACK_EXPORT int getItemBaseValue(int16_t item_type, int16_t item_subtype, int1 DFHACK_EXPORT int getValue(df::item *item, df::caravan_state *caravan = NULL); DFHACK_EXPORT bool createItem(std::vector &out_items, df::unit *creator, df::item_type type, - int16_t item_subtype, int16_t mat_type, int32_t mat_index, bool no_floor = false); + int16_t item_subtype, int16_t mat_type, int32_t mat_index, bool no_floor = false, int32_t count = 1); // Returns true if the item is free from mandates, or false if mandates prevent trading the item. DFHACK_EXPORT bool checkMandates(df::item *item); diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index a161bea8a2..5b9e781721 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -1752,7 +1752,7 @@ int Items::getValue(df::item *item, df::caravan_state *caravan) { } bool Items::createItem(vector &out_items, df::unit *unit, df::item_type item_type, - int16_t item_subtype, int16_t mat_type, int32_t mat_index, bool no_floor) + int16_t item_subtype, int16_t mat_type, int32_t mat_index, bool no_floor, int32_t count) { // Based on Quietust's plugins/createitem.cpp CHECK_NULL_POINTER(unit); auto pos = Units::getPosition(unit); @@ -1765,7 +1765,7 @@ bool Items::createItem(vector &out_items, df::unit *unit, df::item_t prod->mat_type = mat_type; prod->mat_index = mat_index; prod->probability = 100; - prod->count = 1; + prod->count = count; switch(item_type) { using namespace df::enums::item_type; diff --git a/plugins/createitem.cpp b/plugins/createitem.cpp index 1f4b582047..fba821b270 100644 --- a/plugins/createitem.cpp +++ b/plugins/createitem.cpp @@ -50,7 +50,7 @@ DFhackCExport command_result plugin_shutdown(color_ostream &out) { return CR_OK; } -bool makeItem(df::unit *unit, df::item_type type, int16_t subtype, int16_t mat_type, int32_t mat_index, +bool makeItem(df::unit *unit, df::item_type type, int16_t subtype, int16_t mat_type, int32_t mat_index, int32_t count, bool move_to_cursor = false, bool second_item = false) { // Special logic for making Gloves and Shoes in pairs bool is_gloves = (type == item_type::GLOVES); @@ -66,7 +66,7 @@ bool makeItem(df::unit *unit, df::item_type type, int16_t subtype, int16_t mat_t bool on_floor = (container == NULL) && (building == NULL) && !move_to_cursor; vector out_items; - if (!Items::createItem(out_items, unit, type, subtype, mat_type, mat_index, !on_floor)) + if (!Items::createItem(out_items, unit, type, subtype, mat_type, mat_index, !on_floor, count)) return false; for (size_t i = 0; i < out_items.size(); i++) { @@ -105,7 +105,7 @@ bool makeItem(df::unit *unit, df::item_type type, int16_t subtype, int16_t mat_t is_shoes = false; // If we asked for gloves/shoes and only got one (and we're making the first one), make another if ((is_gloves || is_shoes) && !second_item) - return makeItem(unit, type, subtype, mat_type, mat_index, move_to_cursor, true); + return makeItem(unit, type, subtype, mat_type, mat_index, count, move_to_cursor, true); return true; } @@ -435,12 +435,10 @@ command_result df_createitem (color_ostream &out, vector ¶meters) { out.printerr("Previously selected building no longer exists - item will be placed on the floor.\n"); } - for (int i = 0; i < count; i++) { - if (!makeItem(unit, item_type, item_subtype, mat_type, mat_index, move_to_cursor, false)) - { - out.printerr("Failed to create item!\n"); - return CR_FAILURE; - } + if (!makeItem(unit, item_type, item_subtype, mat_type, mat_index, count, move_to_cursor, false)) + { + out.printerr("Failed to create item!\n"); + return CR_FAILURE; } return CR_OK; }