From ec7e245b9d165c0ffdd8963909c494f835ccf19a Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 7 Dec 2021 17:57:18 +0100 Subject: [PATCH] Various fixes to the enchanting and loot system - enchanted loot generated by mapgen now uses PseudoRandom for randomness - prevent fishing loot from generating loot 32767 times (!!!) when only 1 is needed - bows and fishing rods obtained from the treasure section of fishing loot are now enchanted - there is now a function to uniform enchant items other than books --- mods/CORE/mcl_loot/init.lua | 23 ++++---- mods/ENTITIES/mobs_mc/villager.lua | 2 +- mods/ITEMS/mcl_enchanting/engine.lua | 57 ++++++++++++-------- mods/ITEMS/mcl_fishing/init.lua | 26 ++++++--- mods/MAPGEN/mcl_dungeons/init.lua | 3 ++ mods/MAPGEN/mcl_structures/init.lua | 4 +- mods/MAPGEN/tsm_railcorridors/gameconfig.lua | 4 +- 7 files changed, 76 insertions(+), 43 deletions(-) diff --git a/mods/CORE/mcl_loot/init.lua b/mods/CORE/mcl_loot/init.lua index 1b2c5080..b90cd442 100644 --- a/mods/CORE/mcl_loot/init.lua +++ b/mods/CORE/mcl_loot/init.lua @@ -58,26 +58,27 @@ function mcl_loot.get_loot(loot_definitions, pr) end if item then local itemstring = item.itemstring - local itemstack = item.itemstack + if itemstring then + local stack = ItemStack(itemstring) + if item.amount_min and item.amount_max then - itemstring = itemstring .. " " .. pr:next(item.amount_min, item.amount_max) + stack:set_count(pr:next(item.amount_min, item.amount_max)) end + if item.wear_min and item.wear_max then -- Sadly, PseudoRandom only allows very narrow ranges, so we set wear in steps of 10 local wear_min = math.floor(item.wear_min / 10) local wear_max = math.floor(item.wear_max / 10) - local wear = pr:next(wear_min, wear_max) * 10 - if not item.amount_min and not item.amount_max then - itemstring = itemstring .. " 1" - end - - itemstring = itemstring .. " " .. tostring(wear) + stack:set_wear(pr:next(wear_min, wear_max) * 10) end - table.insert(items, itemstring) - elseif itemstack then - table.insert(items, itemstack) + + if item.func then + item.func(stack, pr) + end + + table.insert(items, stack) else minetest.log("error", "[mcl_loot] INTERNAL ERROR! Failed to select random loot item!") end diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 06cec9ed..ce2e7657 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -409,7 +409,7 @@ local init_trades = function(self, inv) local offered_stack = ItemStack({name = offered_item, count = offered_count}) if mcl_enchanting.is_enchanted(offered_item) then if mcl_enchanting.is_book(offered_item) then - offered_stack = mcl_enchanting.get_uniform_randomly_enchanted_book({"soul_speed"}) + mcl_enchanting.enchant_uniform_randomly(offered_stack, {"soul_speed"}) else mcl_enchanting.enchant_randomly(offered_stack, math.random(5, 19), false, false, true) mcl_enchanting.unload_enchantments(offered_stack) diff --git a/mods/ITEMS/mcl_enchanting/engine.lua b/mods/ITEMS/mcl_enchanting/engine.lua index b1cb74fb..97a176b9 100644 --- a/mods/ITEMS/mcl_enchanting/engine.lua +++ b/mods/ITEMS/mcl_enchanting/engine.lua @@ -295,6 +295,16 @@ function mcl_enchanting.initialize() end end +function mcl_enchanting.random(pr, ...) + local r = pr and pr:next(...) or math.random(...) + + if pr and not ({...})[1] then + r = r / 32767 + end + + return r +end + function mcl_enchanting.get_random_enchantment(itemstack, treasure, weighted, exclude, pr) local possible = {} @@ -310,23 +320,30 @@ function mcl_enchanting.get_random_enchantment(itemstack, treasure, weighted, ex end end - return #possible > 0 and possible[pr and pr:next(1, #possible) or math.random(#possible)] + return #possible > 0 and possible[mcl_enchanting.random(pr, 1, #possible)] end -function mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted) +function mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr) local itemname = itemstack:get_name() + if not mcl_enchanting.can_enchant_freshly(itemname) and not ignore_already_enchanted then return end + itemstack = ItemStack(itemstack) + local enchantability = minetest.get_item_group(itemname, "enchantability") - enchantability = 1 + math.random(0, math.floor(enchantability / 4)) + math.random(0, math.floor(enchantability / 4)) + enchantability = 1 + mcl_enchanting.random(pr, 0, math.floor(enchantability / 4)) + mcl_enchanting.random(pr, 0, math.floor(enchantability / 4)) + enchantment_level = enchantment_level + enchantability - enchantment_level = enchantment_level + enchantment_level * (math.random() + math.random() - 1) * 0.15 + enchantment_level = enchantment_level + enchantment_level * (mcl_enchanting.random(pr) + mcl_enchanting.random(pr) - 1) * 0.15 enchantment_level = math.max(math.floor(enchantment_level + 0.5), 1) + local enchantments = {} local description + enchantment_level = enchantment_level * 2 + repeat enchantment_level = math.floor(enchantment_level / 2) @@ -334,7 +351,7 @@ function mcl_enchanting.generate_random_enchantments(itemstack, enchantment_leve break end - local selected_enchantment = mcl_enchanting.get_random_enchantment(itemstack, treasure, true) + local selected_enchantment = mcl_enchanting.get_random_enchantment(itemstack, treasure, true, nil, pr) if not selected_enchantment then break @@ -365,43 +382,41 @@ function mcl_enchanting.generate_random_enchantments(itemstack, enchantment_leve enchantments[selected_enchantment] = enchantment_power mcl_enchanting.enchant(itemstack, selected_enchantment, enchantment_power) end - until not no_reduced_bonus_chance and math.random() >= (enchantment_level + 1) / 50 + + until not no_reduced_bonus_chance and mcl_enchanting.random(pr) >= (enchantment_level + 1) / 50 + return enchantments, description end -function mcl_enchanting.generate_random_enchantments_reliable(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted) +function mcl_enchanting.generate_random_enchantments_reliable(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr) local enchantments + repeat - enchantments = mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted) + enchantments = mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr) until enchantments + return enchantments end -function mcl_enchanting.enchant_randomly(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted) +function mcl_enchanting.enchant_randomly(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr) + local enchantments = mcl_enchanting.generate_random_enchantments_reliable(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr) + mcl_enchanting.set_enchanted_itemstring(itemstack) - mcl_enchanting.set_enchantments(itemstack, mcl_enchanting.generate_random_enchantments_reliable(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted)) + mcl_enchanting.set_enchantments(itemstack, enchantments) + return itemstack end -function mcl_enchanting.get_randomly_enchanted_book(enchantment_level, treasure, no_reduced_bonus_chance) - return mcl_enchanting.enchant_randomly(ItemStack("mcl_books:book"), enchantment_level, treasure, no_reduced_bonus_chance, true) -end - function mcl_enchanting.enchant_uniform_randomly(stack, exclude, pr) - local enchantment = mcl_enchanting.get_random_enchantment(stack, true, weighted, exclude, pr) + local enchantment = mcl_enchanting.get_random_enchantment(stack, true, false, exclude, pr) if enchantment then - local max_level = mcl_enchanting.enchantments[enchantment].max_level - mcl_enchanting.enchant(stack, enchantment, pr and pr:next(1, max_level) or math.random(max_level)) + mcl_enchanting.enchant(stack, enchantment, mcl_enchanting.random(pr, 1, mcl_enchanting.enchantments[enchantment].max_level)) end return stack end -function mcl_enchanting.get_uniform_randomly_enchanted_book(exclude, pr) - return mcl_enchanting.enchant_uniform_randomly(ItemStack("mcl_books:book"), exclude, pr) -end - function mcl_enchanting.get_random_glyph_row() local glyphs = "" local x = 1.3 diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index ade0be81..788e591d 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -71,7 +71,9 @@ local fish = function(itemstack, player, pointed_thing) { itemstring = "mcl_fishing:salmon_raw", weight = 25 }, { itemstring = "mcl_fishing:clownfish_raw", weight = 2 }, { itemstring = "mcl_fishing:pufferfish_raw", weight = 13 }, - } + }, + stacks_min = 1, + stacks_max = 1, }, pr) elseif r <= junk_value then -- Junk @@ -88,21 +90,29 @@ local fish = function(itemstack, player, pointed_thing) { itemstring = "mcl_mobitems:bone", weight = 10 }, { itemstring = "mcl_dye:black", weight = 1, amount_min = 10, amount_max = 10 }, { itemstring = "mcl_mobitems:string", weight = 10 }, -- TODO: Tripwire Hook - } + }, + stacks_min = 1, + stacks_max = 1, }, pr) else -- Treasure items = mcl_loot.get_loot({ items = { - -- TODO: Enchanted Bow - { itemstring = "mcl_bows:bow", wear_min = 49144, wear_max = 65535 }, -- 75%-100% damage - { itemstack = mcl_enchanting.get_randomly_enchanted_book(30, true, true)}, - -- TODO: Enchanted Fishing Rod - { itemstring = "mcl_fishing:fishing_rod", wear_min = 49144, wear_max = 65535 }, -- 75%-100% damage + { itemstring = "mcl_bows:bow", wear_min = 49144, wear_max = 65535, func = function(stack, pr) + mcl_enchanting.enchant_randomly(stack, 30, true, false, false, pr) + end }, -- 75%-100% damage + { itemstring = "mcl_books:book", func = function(stack, pr) + mcl_enchanting.enchant_randomly(stack, 30, true, true, false, pr) + end }, + { itemstring = "mcl_fishing:fishing_rod", wear_min = 49144, wear_max = 65535, func = function(stack, pr) + mcl_enchanting.enchant_randomly(stack, 30, true, false, false, pr) + end }, -- 75%-100% damage { itemstring = "mcl_mobs:nametag", }, { itemstring = "mcl_mobitems:saddle", }, { itemstring = "mcl_flowers:waterlily", }, - } + }, + stacks_min = 1, + stacks_max = 1, }, pr) end local item diff --git a/mods/MAPGEN/mcl_dungeons/init.lua b/mods/MAPGEN/mcl_dungeons/init.lua index 58e23b12..e6529431 100644 --- a/mods/MAPGEN/mcl_dungeons/init.lua +++ b/mods/MAPGEN/mcl_dungeons/init.lua @@ -323,6 +323,9 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) { itemstring = "mcl_jukebox:record_4", weight = 15 }, { itemstring = "mobs_mc:iron_horse_armor", weight = 15 }, { itemstring = "mcl_core:apple_gold", weight = 15 }, + { itemstring = "mcl_books:book", weight = 10, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly({"soul_speed"}, pr) + end }, { itemstack = mcl_enchanting.get_uniform_randomly_enchanted_book({"soul_speed"}, pr), weight = 10 }, { itemstring = "mobs_mc:gold_horse_armor", weight = 10 }, { itemstring = "mobs_mc:diamond_horse_armor", weight = 5 }, diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index 533c9cab..7ca7789b 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -454,7 +454,9 @@ local function temple_placement_callback(p1, p2, size, rotation, pr) { itemstring = "mcl_mobitems:bone", weight = 25, amount_min = 4, amount_max=6 }, { itemstring = "mcl_mobitems:rotten_flesh", weight = 25, amount_min = 3, amount_max=7 }, { itemstring = "mcl_mobitems:spider_eye", weight = 25, amount_min = 1, amount_max=3 }, - { itemstack = mcl_enchanting.get_uniform_randomly_enchanted_book({"soul_speed"}, pr), weight = 20, }, + { itemstring = "mcl_books:book", weight = 20, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly({"soul_speed"}, pr) + end }, { itemstring = "mcl_mobitems:saddle", weight = 20, }, { itemstring = "mcl_core:apple_gold", weight = 20, }, { itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 }, diff --git a/mods/MAPGEN/tsm_railcorridors/gameconfig.lua b/mods/MAPGEN/tsm_railcorridors/gameconfig.lua index 168ecf53..cbe2c9be 100644 --- a/mods/MAPGEN/tsm_railcorridors/gameconfig.lua +++ b/mods/MAPGEN/tsm_railcorridors/gameconfig.lua @@ -66,7 +66,9 @@ function tsm_railcorridors.get_treasures(pr) items = { { itemstring = "mcl_mobs:nametag", weight = 30 }, { itemstring = "mcl_core:apple_gold", weight = 20 }, - { itemstack = mcl_enchanting.get_uniform_randomly_enchanted_book({"soul_speed"}, pr), weight = 10 }, + { itemstring = "mcl_books:book", weight = 10, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly({"soul_speed"}, pr) + end }, { itemstring = "", weight = 5}, { itemstring = "mcl_core:pick_iron", weight = 5 }, { itemstring = "mcl_core:apple_gold_enchanted", weight = 1 },