From 1a740f346b821b6786790ef1d696c36cdfed10cb Mon Sep 17 00:00:00 2001 From: Quietust Date: Tue, 27 Aug 2024 20:00:27 -0600 Subject: [PATCH] Items::createItem - auto-select growth prints instead of requiring the caller to figure it out on their own --- docs/changelog.txt | 2 ++ library/LuaApi.cpp | 5 ++--- library/include/modules/Items.h | 2 +- library/modules/Items.cpp | 32 +++++++++++++++++++++++++++++++- plugins/createitem.cpp | 29 ++++++----------------------- 5 files changed, 42 insertions(+), 28 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 16278a9a93..6b6bbe61d7 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -74,12 +74,14 @@ Template for new versions: ## API - ``Units``: new ``isWildlife`` and ``isAgitated`` property checks +- ``Items::createItem``: removed growth_print parameter, now determined automatically ## Lua - ``dfhack.units``: ``isWildlife`` and ``isAgitated`` property checks - ``dfhack.units.isDanger``: no longer returns true for intelligent undead - Overlay widgets can now assume their ``active`` and ``visible`` functions will only execute in a context that matches their ``viewscreens`` associations - ``gui.simulateInput``: do not generate spurious keycode from ``_STRING`` +- ``dfhack.items.createItem``: removed growth_print parameter to match C++ API ## Removed - ``quickfortress.csv``: remove old sample blueprints for "The Quick Fortress", which were unmaintained and non-functional in DF v50+. Online blueprints are available at https://docs.google.com/spreadsheets/d/1WuLYZBM6S2nt-XsPS30kpDnngpOQCuIdlw4zjrcITdY if anyone is interested in giving these blueprints some love diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index e4c1a87099..b3b56c974a 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2414,10 +2414,9 @@ static int items_createItem(lua_State *state) auto item_subtype = lua_tointeger(state, 3); auto mat_type = lua_tointeger(state, 4); auto mat_index = lua_tointeger(state, 5); - int growth_print = luaL_optint(state, 6, -1); - bool no_floor = lua_toboolean(state, 7); + bool no_floor = lua_toboolean(state, 6); vector out_items; - Items::createItem(out_items, unit, item_type, item_subtype, mat_type, mat_index, growth_print, no_floor); + Items::createItem(out_items, unit, item_type, item_subtype, mat_type, mat_index, no_floor); Lua::PushVector(state, out_items); return 1; } diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index fbc99b4b37..79aed92c36 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, int32_t growth_print = -1, bool no_floor = false); + int16_t item_subtype, int16_t mat_type, int32_t mat_index, bool no_floor = false); // 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 51797fdbcf..e87dcdab1b 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -87,6 +87,9 @@ distribution. #include "df/mandate.h" #include "df/map_block.h" #include "df/material.h" +#include "df/plant_raw.h" +#include "df/plant_growth.h" +#include "df/plant_growth_print.h" #include "df/proj_itemst.h" #include "df/proj_list_link.h" #include "df/reaction_product_itemst.h" @@ -1707,7 +1710,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, int32_t growth_print, bool no_floor) + int16_t item_subtype, int16_t mat_type, int32_t mat_index, bool no_floor) { // Based on Quietust's plugins/createitem.cpp CHECK_NULL_POINTER(unit); auto pos = Units::getPosition(unit); @@ -1756,7 +1759,34 @@ bool Items::createItem(vector &out_items, df::unit *unit, df::item_t for (auto out_item : out_items) { // Plant growths need a valid "growth print", otherwise they behave oddly if (auto growth = virtual_cast(out_item)) + { + int growth_print = -1; + // Make sure it's made of a valid plant material, then grab its definition + if (growth->mat_type >= 419 && growth->mat_type <= 618 && growth->mat_index >= 0 && (unsigned)growth->mat_index < world->raws.plants.all.size()) + { + auto plant_def = world->raws.plants.all[growth->mat_index]; + // Make sure it subtype is also valid + if (growth->subtype >= 0 && (unsigned)growth->subtype < plant_def->growths.size()) + { + auto growth_def = plant_def->growths[growth->subtype]; + // Try and find a growth print matching the current time + // (in practice, only tree leaves use this for autumn color changes) + for (size_t i = 0; i < growth_def->prints.size(); i++) + { + auto print_def = growth_def->prints[i]; + if (print_def->timing_start <= *df::global::cur_year_tick && *df::global::cur_year_tick <= print_def->timing_end) + { + growth_print = i; + break; + } + } + // If we didn't find one, then pick the first one (if it exists) + if (growth_print == -1 && !growth_def->prints.empty()) + growth_print = 0; + } + } growth->growth_print = growth_print; + } if (!no_floor) out_item->moveToGround(pos.x, pos.y, pos.z); } diff --git a/plugins/createitem.cpp b/plugins/createitem.cpp index c870b528b7..0b669258ce 100644 --- a/plugins/createitem.cpp +++ b/plugins/createitem.cpp @@ -20,7 +20,6 @@ #include "df/game_type.h" #include "df/item.h" #include "df/plant_growth.h" -#include "df/plant_growth_print.h" #include "df/plant_raw.h" #include "df/tool_uses.h" #include "df/unit.h" @@ -54,7 +53,7 @@ DFhackCExport command_result plugin_shutdown(color_ostream &out) { } bool makeItem(df::unit *unit, df::item_type type, int16_t subtype, int16_t mat_type, int32_t mat_index, - int32_t growth_print = -1, bool move_to_cursor = false, bool second_item = false) + 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); bool is_shoes = (type == item_type::SHOES); @@ -69,7 +68,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, growth_print, !on_floor)) + if (!Items::createItem(out_items, unit, type, subtype, mat_type, mat_index, !on_floor)) return false; for (size_t i = 0; i < out_items.size(); i++) { @@ -105,7 +104,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, growth_print, move_to_cursor, true); + return makeItem(unit, type, subtype, mat_type, mat_index, move_to_cursor, true); return true; } @@ -157,7 +156,7 @@ static inline bool select_caste_mat(color_ostream &out, vector &tokens, } static inline bool select_plant_growth(color_ostream &out, vector &tokens, df::item_type &item_type, - int16_t &item_subtype, int16_t &mat_type, int32_t &mat_index, int32_t &growth_print, const string &material_str) + int16_t &item_subtype, int16_t &mat_type, int32_t &mat_index, const string &material_str) { split_string(&tokens, material_str, ":"); if (tokens.size() == 1) @@ -191,21 +190,6 @@ static inline bool select_plant_growth(color_ostream &out, vector &token item_subtype = growth->item_subtype; mat_type = growth->mat_type; mat_index = growth->mat_index; - - // Try and find a growth print matching the current time - // (in practice, only tree leaves use this for autumn color changes) - for (size_t k = 0; k < growth->prints.size(); k++) - { - auto print = growth->prints[k]; - if (print->timing_start <= *cur_year_tick && *cur_year_tick <= print->timing_end) - { - growth_print = k; - break; - } - } - // If we didn't find one, then pick the first one (if it exists) - if (growth_print == -1 && !growth->prints.empty()) - growth_print = 0; break; } if (mat_type == -1) { @@ -230,7 +214,6 @@ command_result df_createitem (color_ostream &out, vector ¶meters) { int16_t item_subtype = -1; int16_t mat_type = -1; int32_t mat_index = -1; - int32_t growth_print = -1; int count = 1; bool move_to_cursor = false; @@ -372,7 +355,7 @@ command_result df_createitem (color_ostream &out, vector ¶meters) { break; case PLANT_GROWTH: if (!select_plant_growth(out, tokens, item_type, item_subtype, - mat_type, mat_index, growth_print, material_str) + mat_type, mat_index, material_str) ) return CR_FAILURE; break; @@ -452,7 +435,7 @@ command_result df_createitem (color_ostream &out, vector ¶meters) { } for (int i = 0; i < count; i++) { - if (!makeItem(unit, item_type, item_subtype, mat_type, mat_index, growth_print, move_to_cursor, false)) + 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;