|
| 1 | +#include <cmath> |
| 2 | + |
| 3 | +#include "modules/Materials.h" |
| 4 | +#include "modules/Random.h" |
| 5 | + |
| 6 | +#include "df/inorganic_raw.h" |
| 7 | +#include "df/item_armorst.h" |
| 8 | +#include "df/item_constructed.h" |
| 9 | +#include "df/item_glovesst.h" |
| 10 | +#include "df/item_helmst.h" |
| 11 | +#include "df/item_pantsst.h" |
| 12 | +#include "df/item_shieldst.h" |
| 13 | +#include "df/item_shoesst.h" |
| 14 | +#include "df/item_toolst.h" |
| 15 | +#include "df/item_trapcompst.h" |
| 16 | +#include "df/item_weaponst.h" |
| 17 | + |
| 18 | +struct Mrng { |
| 19 | + Random::MersenneRNG rng; |
| 20 | + Mrng() { rng.init(); } |
| 21 | +}; |
| 22 | + |
| 23 | +static float get_random() { |
| 24 | + static Mrng mrng; |
| 25 | + return static_cast <float> (mrng.rng.drandom1()); |
| 26 | +} |
| 27 | + |
| 28 | +static int32_t get_material_size_for_melting(df::item_constructed *item, int32_t base_material_size, float production_stack_size) { |
| 29 | + const float melt_return_per_material_size = 0.3f, base_melt_recovery = 0.95f, loss_per_wear_level = 0.1f; |
| 30 | + |
| 31 | + if (item->mat_type != 0) // bail if not INORGANIC |
| 32 | + return base_material_size; |
| 33 | + |
| 34 | + float forging_cost_per_item; |
| 35 | + if (auto inorganic = df::inorganic_raw::find(item->mat_index); |
| 36 | + inorganic && inorganic->flags.is_set(df::inorganic_flags::DEEP_SPECIAL)) |
| 37 | + { |
| 38 | + // adamantine items |
| 39 | + forging_cost_per_item = static_cast<float>(base_material_size) / production_stack_size; |
| 40 | + } else { |
| 41 | + // non adamantine items |
| 42 | + forging_cost_per_item = std::max(std::floor(static_cast<float>(base_material_size) / 3.0f), 1.0f); |
| 43 | + forging_cost_per_item /= production_stack_size; |
| 44 | + } |
| 45 | + |
| 46 | + float calculated_size = forging_cost_per_item / melt_return_per_material_size; |
| 47 | + float melt_recovery = base_melt_recovery - static_cast<float>(item->wear) * loss_per_wear_level; |
| 48 | + calculated_size *= melt_recovery; |
| 49 | + int32_t random_part = ((modff(calculated_size, &calculated_size) > get_random()) ? 1 : 0); |
| 50 | + return static_cast<int32_t>(calculated_size) + random_part; |
| 51 | +} |
| 52 | + |
| 53 | +#define DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(TYPE, PRODUCTION_STACK_SIZE) \ |
| 54 | +struct material_size_for_melting_##TYPE##_hook : df::item_##TYPE##st {\ |
| 55 | + typedef df::item_##TYPE##st interpose_base;\ |
| 56 | + DEFINE_VMETHOD_INTERPOSE(int32_t, getMaterialSizeForMelting, ()) {\ |
| 57 | + return get_material_size_for_melting(this, INTERPOSE_NEXT(getMaterialSizeForMelting)(), PRODUCTION_STACK_SIZE);\ |
| 58 | + }\ |
| 59 | +};\ |
| 60 | +IMPLEMENT_VMETHOD_INTERPOSE(material_size_for_melting_##TYPE##_hook, getMaterialSizeForMelting); |
| 61 | + |
| 62 | +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(armor, 1.0f) |
| 63 | +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(gloves, 2.0f) |
| 64 | +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(shoes, 2.0f) |
| 65 | +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(helm, 1.0f) |
| 66 | +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(pants, 1.0f) |
| 67 | +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(weapon, 1.0f) |
| 68 | +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(trapcomp, 1.0f) |
| 69 | +DEFINE_MATERIAL_SIZE_FOR_MELTING_TWEAK(tool, 1.0f) |
0 commit comments