From e299f4d6af2782735035a470760aabcc83af4372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Mon, 23 Sep 2024 14:16:35 +0200 Subject: [PATCH 01/15] adjust material size for melting for armor parts, weapons, trap components and tools to minimize differences between cost of forging and melting return, heavily inspired by adamantine-cloth-wear.h --- plugins/tweak/tweak.cpp | 11 ++ .../tweak/tweaks/material-size-for-melting.h | 106 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 plugins/tweak/tweaks/material-size-for-melting.h diff --git a/plugins/tweak/tweak.cpp b/plugins/tweak/tweak.cpp index e10a9535a3..0ea8069746 100644 --- a/plugins/tweak/tweak.cpp +++ b/plugins/tweak/tweak.cpp @@ -20,6 +20,7 @@ using namespace DFHack; #include "tweaks/named-codices.h" #include "tweaks/partial-items.h" #include "tweaks/reaction-gloves.h" +#include "tweaks/material-size-for-melting.h" class tweak_onupdate_hookst { public: @@ -74,6 +75,16 @@ DFhackCExport command_result plugin_init(color_ostream &out, vector + +static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t base_material_size, float production_stack_size) { + + if (item->mat_type == 0) // INORGANIC only + { + const float melt_return_per_material_size = 0.3f; + auto inorganic = df::inorganic_raw::find(item->mat_index); + if (inorganic && inorganic->flags.is_set(df::inorganic_flags::DEEP_SPECIAL)){ + return static_cast(std::round(static_cast(base_material_size) / production_stack_size / melt_return_per_material_size)); + // get size for melting to minimize diff between forging cost and melting return, for adamantine forging cost == base_material_size, divided by amount of items created in batch + } + return static_cast(std::round(std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f) / production_stack_size / melt_return_per_material_size)); + // (std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f) / production_stack_size) - forging cost for non adamantine item + } + return base_material_size; +} + +static int32_t get_material_size_for_melting(df::item_constructed* item, int32_t base_size) { + return get_material_size_for_melting(item, base_size, 1.0f); +} + +struct material_size_for_melting_armor_hook : df::item_armorst { + typedef df::item_armorst interpose_base; + + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_armor_hook, getMaterialSizeForMelting); + +struct material_size_for_melting_gloves_hook : df::item_glovesst { + typedef df::item_glovesst interpose_base; + + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)(), 2.0f); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_gloves_hook, getMaterialSizeForMelting); + +struct material_size_for_melting_shoes_hook : df::item_shoesst { + typedef df::item_shoesst interpose_base; + + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)(), 2.0f); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_shoes_hook, getMaterialSizeForMelting); + +struct material_size_for_melting_helm_hook : df::item_helmst { + typedef df::item_helmst interpose_base; + + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_helm_hook, getMaterialSizeForMelting); + +struct material_size_for_melting_pants_hook : df::item_pantsst { + typedef df::item_pantsst interpose_base; + + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_pants_hook, getMaterialSizeForMelting); + +struct material_size_for_melting_weapon_hook : df::item_weaponst { + typedef df::item_weaponst interpose_base; + + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_weapon_hook, getMaterialSizeForMelting); + +struct material_size_for_melting_trapcomp_hook : df::item_trapcompst { + typedef df::item_trapcompst interpose_base; + + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_trapcomp_hook, getMaterialSizeForMelting); + +struct material_size_for_melting_tool_hook : df::item_toolst { + typedef df::item_toolst interpose_base; + + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_tool_hook, getMaterialSizeForMelting); From 41b67904fe2a34a40fa93b6ea909c0170907f8b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Tue, 24 Sep 2024 21:47:54 +0200 Subject: [PATCH 02/15] Change how material size for melting is calculated. On average weapons, trap components, armor parts, shields and tools will return 95% of their forging cost. Each wear level will decrease melt return by additional 10% --- .../tweak/tweaks/material-size-for-melting.h | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/plugins/tweak/tweaks/material-size-for-melting.h b/plugins/tweak/tweaks/material-size-for-melting.h index 56da416de5..86887a0ec1 100644 --- a/plugins/tweak/tweaks/material-size-for-melting.h +++ b/plugins/tweak/tweaks/material-size-for-melting.h @@ -12,19 +12,40 @@ #include "df/item_toolst.h" #include "df/item_trapcompst.h" #include +#include + + +static Random::MersenneRNG rng; +static bool init_rng = true; + +static float get_random() { + if (init_rng) { + rng.init(); + init_rng = false; + } + return static_cast (rng.drandom1()); +} static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t base_material_size, float production_stack_size) { + const float melt_return_per_material_size = 0.3f, base_melt_recovery = 0.95f, loss_per_wear_level = 0.1f; if (item->mat_type == 0) // INORGANIC only { - const float melt_return_per_material_size = 0.3f; + float calculated_size; + auto inorganic = df::inorganic_raw::find(item->mat_index); if (inorganic && inorganic->flags.is_set(df::inorganic_flags::DEEP_SPECIAL)){ - return static_cast(std::round(static_cast(base_material_size) / production_stack_size / melt_return_per_material_size)); - // get size for melting to minimize diff between forging cost and melting return, for adamantine forging cost == base_material_size, divided by amount of items created in batch + calculated_size =static_cast(base_material_size) / production_stack_size / melt_return_per_material_size; + // get size for melting, for adamantine forging cost == base_material_size, divided by amount of items created in batch } - return static_cast(std::round(std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f) / production_stack_size / melt_return_per_material_size)); + else { + calculated_size = std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f) / production_stack_size / melt_return_per_material_size; // (std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f) / production_stack_size) - forging cost for non adamantine item + } + float melt_recovery = base_melt_recovery - static_cast(item->wear) * loss_per_wear_level; + calculated_size = calculated_size * melt_recovery; + int32_t random_part = ((modf(calculated_size, &calculated_size) > get_random()) ? 1 : 0); + return static_cast(calculated_size) + random_part; } return base_material_size; } From baa33375f99a8681b772632d90336aab47e38f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Tue, 24 Sep 2024 22:25:34 +0200 Subject: [PATCH 03/15] add tweak description to .rst --- docs/plugins/tweak.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/plugins/tweak.rst b/docs/plugins/tweak.rst index 996b0ec103..a4c6616efd 100644 --- a/docs/plugins/tweak.rst +++ b/docs/plugins/tweak.rst @@ -53,6 +53,17 @@ Commands Names filled waterskins, flasks, and vials according to their contents, the same way other containers such as barrels, bins, and cages are named. (:bug:`4914`) +``material-size-for-melting`` + Changes how item size for melting is calculated. Affects weapons, shields, + armor parts, tools, trap components including items made from adamantine. + As result base return for melting is equal to 95% of production cost. + Each level of wear decreases melt return by further 10%. + Limitation of melting return being handled by game in 0,3 bar increments is + solved by adding random component to material size. E.g. for cap with item + size 1 melting return will be equal to 0,9 bar base return with 16,(6)% + chance for additional 0,3 bar. As result average return for melting cap + will be ~0,95 bar. + (:bug:`6027`). ``named-codices`` Displays titles for books instead of the default material description. ``partial-items`` From e140794c61d0265941b350c796f90e90ccce047e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Wed, 25 Sep 2024 12:21:16 +0200 Subject: [PATCH 04/15] move rng init to tweak plugin_init --- plugins/tweak/tweak.cpp | 2 +- plugins/tweak/tweaks/material-size-for-melting.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/plugins/tweak/tweak.cpp b/plugins/tweak/tweak.cpp index 0ea8069746..f6da66a84c 100644 --- a/plugins/tweak/tweak.cpp +++ b/plugins/tweak/tweak.cpp @@ -75,7 +75,6 @@ DFhackCExport command_result plugin_init(color_ostream &out, vector #include - static Random::MersenneRNG rng; -static bool init_rng = true; - static float get_random() { - if (init_rng) { - rng.init(); - init_rng = false; - } return static_cast (rng.drandom1()); } From 1c6cb586c9a7d9e17bd1cfda30b1b822934ce53c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Thu, 26 Sep 2024 18:53:52 +0200 Subject: [PATCH 05/15] update changelog, fix include order --- docs/changelog.txt | 1 + plugins/tweak/tweak.cpp | 2 +- plugins/tweak/tweaks/material-size-for-melting.h | 11 ++++++----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index e6baf71475..07b0aaf8d7 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -54,6 +54,7 @@ Template for new versions: ## New Tools ## New Features +- `tweak`: ``material-size-for-melting``: change melting return for inorganic armor parts, shields, weapons, trap components and tools to stop smelters from creating metal, bring melt return for adamantine in line with other metals to ~95% of forging cost. wear reduces melt return by 10% per level ## Fixes diff --git a/plugins/tweak/tweak.cpp b/plugins/tweak/tweak.cpp index f6da66a84c..412b18d078 100644 --- a/plugins/tweak/tweak.cpp +++ b/plugins/tweak/tweak.cpp @@ -17,10 +17,10 @@ using namespace DFHack; #include "tweaks/eggs-fertile.h" #include "tweaks/fast-heat.h" #include "tweaks/flask-contents.h" +#include "tweaks/material-size-for-melting.h" #include "tweaks/named-codices.h" #include "tweaks/partial-items.h" #include "tweaks/reaction-gloves.h" -#include "tweaks/material-size-for-melting.h" class tweak_onupdate_hookst { public: diff --git a/plugins/tweak/tweaks/material-size-for-melting.h b/plugins/tweak/tweaks/material-size-for-melting.h index 1829d5ba32..66e6b4310a 100644 --- a/plugins/tweak/tweaks/material-size-for-melting.h +++ b/plugins/tweak/tweaks/material-size-for-melting.h @@ -1,18 +1,19 @@ +#include + #include "modules/Materials.h" +#include "modules/Random.h" #include "df/inorganic_raw.h" -#include "df/item_constructed.h" #include "df/item_armorst.h" +#include "df/item_constructed.h" #include "df/item_glovesst.h" #include "df/item_helmst.h" -#include "df/item_shoesst.h" #include "df/item_pantsst.h" -#include "df/item_weaponst.h" #include "df/item_shieldst.h" +#include "df/item_shoesst.h" #include "df/item_toolst.h" #include "df/item_trapcompst.h" -#include -#include +#include "df/item_weaponst.h" static Random::MersenneRNG rng; static float get_random() { From 5673722d3e6ddf7f223c3d7ac953ba065b673c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Thu, 26 Sep 2024 19:24:21 +0200 Subject: [PATCH 06/15] replace modf with modff --- plugins/tweak/tweaks/material-size-for-melting.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tweak/tweaks/material-size-for-melting.h b/plugins/tweak/tweaks/material-size-for-melting.h index 66e6b4310a..85f6c47218 100644 --- a/plugins/tweak/tweaks/material-size-for-melting.h +++ b/plugins/tweak/tweaks/material-size-for-melting.h @@ -38,7 +38,7 @@ static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t } float melt_recovery = base_melt_recovery - static_cast(item->wear) * loss_per_wear_level; calculated_size = calculated_size * melt_recovery; - int32_t random_part = ((modf(calculated_size, &calculated_size) > get_random()) ? 1 : 0); + int32_t random_part = ((modff(calculated_size, &calculated_size) > get_random()) ? 1 : 0); return static_cast(calculated_size) + random_part; } return base_material_size; From 3f213ec47e6f891d44240e922053cbef46c12ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Fri, 27 Sep 2024 17:42:34 +0200 Subject: [PATCH 07/15] use #define to reduce repetitive code --- .../tweak/tweaks/material-size-for-melting.h | 92 ++++--------------- 1 file changed, 17 insertions(+), 75 deletions(-) diff --git a/plugins/tweak/tweaks/material-size-for-melting.h b/plugins/tweak/tweaks/material-size-for-melting.h index 85f6c47218..cc20ca10e6 100644 --- a/plugins/tweak/tweaks/material-size-for-melting.h +++ b/plugins/tweak/tweaks/material-size-for-melting.h @@ -44,78 +44,20 @@ static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t return base_material_size; } -static int32_t get_material_size_for_melting(df::item_constructed* item, int32_t base_size) { - return get_material_size_for_melting(item, base_size, 1.0f); -} - -struct material_size_for_melting_armor_hook : df::item_armorst { - typedef df::item_armorst interpose_base; - - DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); - } -}; -IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_armor_hook, getMaterialSizeForMelting); - -struct material_size_for_melting_gloves_hook : df::item_glovesst { - typedef df::item_glovesst interpose_base; - - DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)(), 2.0f); - } -}; -IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_gloves_hook, getMaterialSizeForMelting); - -struct material_size_for_melting_shoes_hook : df::item_shoesst { - typedef df::item_shoesst interpose_base; - - DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)(), 2.0f); - } -}; -IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_shoes_hook, getMaterialSizeForMelting); - -struct material_size_for_melting_helm_hook : df::item_helmst { - typedef df::item_helmst interpose_base; - - DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); - } -}; -IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_helm_hook, getMaterialSizeForMelting); - -struct material_size_for_melting_pants_hook : df::item_pantsst { - typedef df::item_pantsst interpose_base; - - DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); - } -}; -IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_pants_hook, getMaterialSizeForMelting); - -struct material_size_for_melting_weapon_hook : df::item_weaponst { - typedef df::item_weaponst interpose_base; - - DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); - } -}; -IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_weapon_hook, getMaterialSizeForMelting); - -struct material_size_for_melting_trapcomp_hook : df::item_trapcompst { - typedef df::item_trapcompst interpose_base; - - DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); - } -}; -IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_trapcomp_hook, getMaterialSizeForMelting); - -struct material_size_for_melting_tool_hook : df::item_toolst { - typedef df::item_toolst interpose_base; - - DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) { - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)()); - } -}; -IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_tool_hook, getMaterialSizeForMelting); +#define DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(TYPE, PRODUCTION_STACK_SIZE) \ +struct material_size_for_melting_##TYPE##_hook : df::item_##TYPE##st {\ + typedef df::item_##TYPE##st interpose_base;\ + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) {\ + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)(),PRODUCTION_STACK_SIZE);\ + }\ +};\ +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_##TYPE##_hook, getMaterialSizeForMelting); + +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(armor, 1.0f) +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(gloves, 2.0f) +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(shoes, 2.0f) +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(helm, 1.0f) +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(pants, 1.0f) +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(weapon, 1.0f) +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(trapcomp, 1.0f) +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(tool, 1.0f) From e1e4c87c2426c8e0fd4d1ff5c2a54b096264ce39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Fri, 27 Sep 2024 17:43:13 +0200 Subject: [PATCH 08/15] shortened long lines, improved readability --- plugins/tweak/tweaks/material-size-for-melting.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/tweak/tweaks/material-size-for-melting.h b/plugins/tweak/tweaks/material-size-for-melting.h index cc20ca10e6..570c3df2ea 100644 --- a/plugins/tweak/tweaks/material-size-for-melting.h +++ b/plugins/tweak/tweaks/material-size-for-melting.h @@ -25,19 +25,22 @@ static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t if (item->mat_type == 0) // INORGANIC only { - float calculated_size; + float calculated_size, forging_cost_per_item; auto inorganic = df::inorganic_raw::find(item->mat_index); if (inorganic && inorganic->flags.is_set(df::inorganic_flags::DEEP_SPECIAL)){ - calculated_size =static_cast(base_material_size) / production_stack_size / melt_return_per_material_size; - // get size for melting, for adamantine forging cost == base_material_size, divided by amount of items created in batch + //adamantine items + forging_cost_per_item = static_cast(base_material_size) / production_stack_size; + calculated_size = forging_cost_per_item / melt_return_per_material_size; } else { - calculated_size = std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f) / production_stack_size / melt_return_per_material_size; - // (std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f) / production_stack_size) - forging cost for non adamantine item + // non adamantine items + forging_cost_per_item = std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f); + forging_cost_per_item /= production_stack_size; + calculated_size = forging_cost_per_item / melt_return_per_material_size; } float melt_recovery = base_melt_recovery - static_cast(item->wear) * loss_per_wear_level; - calculated_size = calculated_size * melt_recovery; + calculated_size *= melt_recovery; int32_t random_part = ((modff(calculated_size, &calculated_size) > get_random()) ? 1 : 0); return static_cast(calculated_size) + random_part; } From f94979adb550cdeba72d8b9344caf8d67819ff1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Fri, 27 Sep 2024 23:58:26 +0200 Subject: [PATCH 09/15] removed duplicated code --- plugins/tweak/tweaks/material-size-for-melting.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/tweak/tweaks/material-size-for-melting.h b/plugins/tweak/tweaks/material-size-for-melting.h index 570c3df2ea..65fa090853 100644 --- a/plugins/tweak/tweaks/material-size-for-melting.h +++ b/plugins/tweak/tweaks/material-size-for-melting.h @@ -31,14 +31,13 @@ static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t if (inorganic && inorganic->flags.is_set(df::inorganic_flags::DEEP_SPECIAL)){ //adamantine items forging_cost_per_item = static_cast(base_material_size) / production_stack_size; - calculated_size = forging_cost_per_item / melt_return_per_material_size; } else { // non adamantine items forging_cost_per_item = std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f); forging_cost_per_item /= production_stack_size; - calculated_size = forging_cost_per_item / melt_return_per_material_size; } + calculated_size = forging_cost_per_item / melt_return_per_material_size; float melt_recovery = base_melt_recovery - static_cast(item->wear) * loss_per_wear_level; calculated_size *= melt_recovery; int32_t random_part = ((modff(calculated_size, &calculated_size) > get_random()) ? 1 : 0); From 9fb0d9efba3da0b885c2e42fb081f7d6e576e6cd Mon Sep 17 00:00:00 2001 From: Birkow <56039938+Birkow@users.noreply.github.com> Date: Sat, 28 Sep 2024 09:22:37 +0200 Subject: [PATCH 10/15] Update docs/plugins/tweak.rst Co-authored-by: Myk --- docs/plugins/tweak.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/plugins/tweak.rst b/docs/plugins/tweak.rst index a4c6616efd..7649c97315 100644 --- a/docs/plugins/tweak.rst +++ b/docs/plugins/tweak.rst @@ -54,16 +54,15 @@ Commands the same way other containers such as barrels, bins, and cages are named. (:bug:`4914`) ``material-size-for-melting`` - Changes how item size for melting is calculated. Affects weapons, shields, - armor parts, tools, trap components including items made from adamantine. - As result base return for melting is equal to 95% of production cost. - Each level of wear decreases melt return by further 10%. - Limitation of melting return being handled by game in 0,3 bar increments is - solved by adding random component to material size. E.g. for cap with item - size 1 melting return will be equal to 0,9 bar base return with 16,(6)% - chance for additional 0,3 bar. As result average return for melting cap - will be ~0,95 bar. - (:bug:`6027`). + Makes amortized metal bar returns for melting uniform across all item types. + Affects weapons, shields, armor parts, tools, and trap components. The target + amount of metal produced by melting is 95% of the metal used for production + of the item. Each level of wear decreases melt return by a further 10%. The game + has a fixed granularity of 0.3 for metal bar returns, so individual items will + randomly return an amount that may be above or below the target. For example + a metal cap with item size 1 will produce 0.9 of a bar with a 16.6% chance of + producing an additional 0.3 of a bar. Over time, the average return for melting + these types of caps will be ~0.95 of a bar. (:bug:`6027`) ``named-codices`` Displays titles for books instead of the default material description. ``partial-items`` From 7a5e0fdd7a587a85d9bd446b2acd3f6ad9d07918 Mon Sep 17 00:00:00 2001 From: Birkow <56039938+Birkow@users.noreply.github.com> Date: Sat, 28 Sep 2024 09:29:13 +0200 Subject: [PATCH 11/15] Apply suggestions from code review Co-authored-by: Myk --- .../tweak/tweaks/material-size-for-melting.h | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/plugins/tweak/tweaks/material-size-for-melting.h b/plugins/tweak/tweaks/material-size-for-melting.h index 65fa090853..ea6548b6af 100644 --- a/plugins/tweak/tweaks/material-size-for-melting.h +++ b/plugins/tweak/tweaks/material-size-for-melting.h @@ -15,42 +15,46 @@ #include "df/item_trapcompst.h" #include "df/item_weaponst.h" -static Random::MersenneRNG rng; +struct Mrng { + Random::MersenneRNG rng; + Mrng() { rng.init(); } +}; + static float get_random() { - return static_cast (rng.drandom1()); + static Mrng mrng; + return static_cast (mrng.rng.drandom1()); } static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t base_material_size, float production_stack_size) { const float melt_return_per_material_size = 0.3f, base_melt_recovery = 0.95f, loss_per_wear_level = 0.1f; - if (item->mat_type == 0) // INORGANIC only + if (item->mat_type != 0) // bail if not INORGANIC + return base_material_size; + + float forging_cost_per_item; + if (auto inorganic = df::inorganic_raw::find(item->mat_index); + inorganic && inorganic->flags.is_set(df::inorganic_flags::DEEP_SPECIAL)) { - float calculated_size, forging_cost_per_item; - - auto inorganic = df::inorganic_raw::find(item->mat_index); - if (inorganic && inorganic->flags.is_set(df::inorganic_flags::DEEP_SPECIAL)){ - //adamantine items - forging_cost_per_item = static_cast(base_material_size) / production_stack_size; - } - else { - // non adamantine items - forging_cost_per_item = std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f); - forging_cost_per_item /= production_stack_size; - } - calculated_size = forging_cost_per_item / melt_return_per_material_size; - float melt_recovery = base_melt_recovery - static_cast(item->wear) * loss_per_wear_level; - calculated_size *= melt_recovery; - int32_t random_part = ((modff(calculated_size, &calculated_size) > get_random()) ? 1 : 0); - return static_cast(calculated_size) + random_part; + // adamantine items + forging_cost_per_item = static_cast(base_material_size) / production_stack_size; + } else { + // non adamantine items + forging_cost_per_item = std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f); + forging_cost_per_item /= production_stack_size; } - return base_material_size; + + float calculated_size = forging_cost_per_item / melt_return_per_material_size; + float melt_recovery = base_melt_recovery - static_cast(item->wear) * loss_per_wear_level; + calculated_size *= melt_recovery; + int32_t random_part = ((modff(calculated_size, &calculated_size) > get_random()) ? 1 : 0); + return static_cast(calculated_size) + random_part; } #define DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(TYPE, PRODUCTION_STACK_SIZE) \ struct material_size_for_melting_##TYPE##_hook : df::item_##TYPE##st {\ typedef df::item_##TYPE##st interpose_base;\ DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) {\ - return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)(),PRODUCTION_STACK_SIZE);\ + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)(), PRODUCTION_STACK_SIZE);\ }\ };\ IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_##TYPE##_hook, getMaterialSizeForMelting); From 119e169f1cd0662e6da29d6d5ecd0d6b067d559d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Sat, 28 Sep 2024 09:35:41 +0200 Subject: [PATCH 12/15] remove redundant call to rng.init() from tweak.cpp, remove white spaces --- plugins/tweak/tweak.cpp | 1 - plugins/tweak/tweaks/material-size-for-melting.h | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/tweak/tweak.cpp b/plugins/tweak/tweak.cpp index 412b18d078..6cf13c434f 100644 --- a/plugins/tweak/tweak.cpp +++ b/plugins/tweak/tweak.cpp @@ -83,7 +83,6 @@ DFhackCExport command_result plugin_init(color_ostream &out, vectormat_type != 0) // bail if not INORGANIC return base_material_size; - + float forging_cost_per_item; if (auto inorganic = df::inorganic_raw::find(item->mat_index); inorganic && inorganic->flags.is_set(df::inorganic_flags::DEEP_SPECIAL)) @@ -42,7 +42,7 @@ static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t forging_cost_per_item = std::max(std::floor(static_cast(base_material_size) / 3.0f), 1.0f); forging_cost_per_item /= production_stack_size; } - + float calculated_size = forging_cost_per_item / melt_return_per_material_size; float melt_recovery = base_melt_recovery - static_cast(item->wear) * loss_per_wear_level; calculated_size *= melt_recovery; From b2d150128c979eef8624d6446a0c331fb8711fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Panto=C5=82?= Date: Sat, 28 Sep 2024 10:11:40 +0200 Subject: [PATCH 13/15] renamed tweak from "material-size-for-melting" to "realistic-melting" --- docs/changelog.txt | 2 +- docs/plugins/tweak.rst | 2 +- plugins/tweak/tweak.cpp | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index e2e52d4a6d..c7ab543db2 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -54,7 +54,7 @@ Template for new versions: ## New Tools ## New Features -- `tweak`: ``material-size-for-melting``: change melting return for inorganic armor parts, shields, weapons, trap components and tools to stop smelters from creating metal, bring melt return for adamantine in line with other metals to ~95% of forging cost. wear reduces melt return by 10% per level +- `tweak`: ``realistic-melting``: change melting return for inorganic armor parts, shields, weapons, trap components and tools to stop smelters from creating metal, bring melt return for adamantine in line with other metals to ~95% of forging cost. wear reduces melt return by 10% per level ## Fixes diff --git a/docs/plugins/tweak.rst b/docs/plugins/tweak.rst index 7649c97315..4997bd4c51 100644 --- a/docs/plugins/tweak.rst +++ b/docs/plugins/tweak.rst @@ -53,7 +53,7 @@ Commands Names filled waterskins, flasks, and vials according to their contents, the same way other containers such as barrels, bins, and cages are named. (:bug:`4914`) -``material-size-for-melting`` +``realistic-melting`` Makes amortized metal bar returns for melting uniform across all item types. Affects weapons, shields, armor parts, tools, and trap components. The target amount of metal produced by melting is 95% of the metal used for production diff --git a/plugins/tweak/tweak.cpp b/plugins/tweak/tweak.cpp index 6cf13c434f..e621a14d5e 100644 --- a/plugins/tweak/tweak.cpp +++ b/plugins/tweak/tweak.cpp @@ -75,14 +75,14 @@ DFhackCExport command_result plugin_init(color_ostream &out, vector Date: Sat, 28 Sep 2024 17:54:24 +0200 Subject: [PATCH 14/15] Added information about production cost calculation to description --- docs/plugins/tweak.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/plugins/tweak.rst b/docs/plugins/tweak.rst index 4997bd4c51..76f1b7a475 100644 --- a/docs/plugins/tweak.rst +++ b/docs/plugins/tweak.rst @@ -62,7 +62,10 @@ Commands randomly return an amount that may be above or below the target. For example a metal cap with item size 1 will produce 0.9 of a bar with a 16.6% chance of producing an additional 0.3 of a bar. Over time, the average return for melting - these types of caps will be ~0.95 of a bar. (:bug:`6027`) + these types of caps will be ~0.95 of a bar. Calculations for melting return are + done for items with base game production cost. Melting return might not be + calculated correctly for modded items or created in custom reactions not + respecting vanilla production costs. (:bug:`6027`) ``named-codices`` Displays titles for books instead of the default material description. ``partial-items`` From 6b553c608ffc955395839799c384d8cfc99d1d36 Mon Sep 17 00:00:00 2001 From: Myk Date: Sat, 28 Sep 2024 11:57:47 -0700 Subject: [PATCH 15/15] reword description --- docs/plugins/tweak.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/plugins/tweak.rst b/docs/plugins/tweak.rst index 76f1b7a475..7c72f946c7 100644 --- a/docs/plugins/tweak.rst +++ b/docs/plugins/tweak.rst @@ -64,8 +64,8 @@ Commands producing an additional 0.3 of a bar. Over time, the average return for melting these types of caps will be ~0.95 of a bar. Calculations for melting return are done for items with base game production cost. Melting return might not be - calculated correctly for modded items or created in custom reactions not - respecting vanilla production costs. (:bug:`6027`) + calculated correctly for modded items or items created in custom reactions + that don't respect vanilla production costs. (:bug:`6027`) ``named-codices`` Displays titles for books instead of the default material description. ``partial-items``