Added two different methods to generate item stacks by depth,
as well as a whole config file for easier editing or tuning by others. - Also push to Version 1.1
This commit is contained in:
parent
c27c165169
commit
2391f04700
10
README.txt
10
README.txt
@ -1,14 +1,16 @@
|
||||
Mod "Dungeon Loot" [dungeon_loot]
|
||||
=================================
|
||||
Copyright (c) 2015 BlockMen <blockmen2015@gmail.com>
|
||||
and Amoeba <amoeba@iki.fi>
|
||||
|
||||
Version: 1.0 alpha
|
||||
Version: 1.1 alpha
|
||||
|
||||
|
||||
A simple mod that add to dungeons with more than 4 rooms chests that contain some loot.
|
||||
A simple mod that add to dungeons chests that contain some loot.
|
||||
Configurable in many aspects, see "config.lua" for more details.
|
||||
|
||||
|
||||
License:
|
||||
License:
|
||||
~~~~~~~~
|
||||
Code:
|
||||
(c) Copyright 2015 BlockMen; modified zlib-License
|
||||
@ -25,7 +27,7 @@ https://github.com/BlockMen/dungeon_loot
|
||||
|
||||
Forum:
|
||||
~~~~~~
|
||||
-
|
||||
https://forum.minetest.net/viewtopic.php?id=13487
|
||||
|
||||
|
||||
Changelog:
|
||||
|
106
config.lua
Normal file
106
config.lua
Normal file
@ -0,0 +1,106 @@
|
||||
-- "Dungeon Loot" [dungeon_loot]
|
||||
-- Original by BlockMen, this entire file by Amoeba
|
||||
--
|
||||
-- config.lua
|
||||
--
|
||||
-- Note: All positive heights (above water level) are treated as depth 0.
|
||||
-- Also, no comma after the item of a list.
|
||||
|
||||
-- Minimum number of rooms a dungeon should have for a chest to be generated
|
||||
dungeon_loot.min_num_of_rooms = 4
|
||||
-- Items on basic lists have three depth ranges for their listed amount
|
||||
-- maximums; they get max/2 before first increase point (minimum of 1 if
|
||||
-- amount is >0), the given max between the 1st and 2nd increase point,
|
||||
-- and max*2 after the 2nd.
|
||||
dungeon_loot.depth_first_basic_increase = 200
|
||||
dungeon_loot.depth_second_basic_increase = 2000
|
||||
|
||||
-- The master list of loot types
|
||||
-- Note that tools and weapons should always have max_amount = 1.
|
||||
-- Chance is a probability between 0 (practically never) and 1 (always),
|
||||
-- so change a chance to 0 if you don't want a type (eg. weapons) included
|
||||
-- in your game (or -0.001 if you want to be REALLY sure).
|
||||
dungeon_loot.loot_types = {
|
||||
{name="treasure", max_amount = 10, chance = 0.7, type = "depth_cutoff"},
|
||||
{name="tools", max_amount = 1, chance = 0.5, type = "depth_cutoff"},
|
||||
{name="weapons", max_amount = 1, chance = 0.1, type = "depth_cutoff"},
|
||||
{name="consumables", max_amount = 80, chance = 0.9, type = "basic_list"},
|
||||
{name="seedlings", max_amount = 5, chance = 0.3, type = "basic_list"}
|
||||
}
|
||||
|
||||
-- Loot type lists; these names MUST be exactly of the format:
|
||||
-- "dungeon_loot.name_list" where "name" is in the above list
|
||||
|
||||
-- Depth cutoff lists
|
||||
-- These must be in order of increasing depth (but can include the same item
|
||||
-- more than once). Method: a random number between 1 and chest depth is
|
||||
-- chosen, and the item in that range is added to the loot. Then, there's
|
||||
-- a chance additional items of the same type are added to stack; if the
|
||||
-- random number is much greater than the item's min_depth, the amount
|
||||
-- can grow pretty big.
|
||||
dungeon_loot.treasure_list = {
|
||||
{name="default:steel_ingot", min_depth = 0},
|
||||
{name="default:bronze_ingot", min_depth = 20},
|
||||
{name="default:gold_ingot", min_depth = 45},
|
||||
{name="default:mese_crystal", min_depth = 50},
|
||||
{name="default:diamond", min_depth = 150},
|
||||
{name="default:gold_block", min_depth = 777},
|
||||
{name="default:mese", min_depth = 800},
|
||||
{name="default:diamond_block", min_depth = 1800},
|
||||
{name="default:mese", min_depth = 2000}
|
||||
}
|
||||
|
||||
dungeon_loot.tools_list = {
|
||||
{name="default:pick_steel", min_depth = 0},
|
||||
{name="default:shovel_diamond", min_depth = 38},
|
||||
{name="default:pick_bronze", min_depth = 40},
|
||||
{name="default:axe_diamond", min_depth = 95},
|
||||
{name="default:pick_diamond", min_depth = 100}
|
||||
}
|
||||
|
||||
dungeon_loot.weapons_list = {
|
||||
{name="default:sword_steel", min_depth = 0},
|
||||
{name="default:sword_bronze", min_depth = 50},
|
||||
{name="default:sword_mese", min_depth = 150},
|
||||
{name="default:sword_diamond", min_depth = 250}
|
||||
}
|
||||
|
||||
|
||||
-- Basic lists
|
||||
-- These can be of two types, either with combined chance and amount,
|
||||
-- or with the two variables separated. "chance" means each item has a
|
||||
-- N/M chance of being chosen, where N is it's own chance and M is the
|
||||
-- total sum of chances on the list. "amount" is the maximum amount of
|
||||
-- items given at the middle depth range.
|
||||
dungeon_loot.consumables_list = {
|
||||
{name="default:apple", chance_and_amount = 20},
|
||||
{name="default:torch", chance_and_amount = 30},
|
||||
{name="default:stick", chance_and_amount = 10}
|
||||
}
|
||||
|
||||
dungeon_loot.seedlings_list = {
|
||||
{name="default:sapling", chance = 5, amount = 2},
|
||||
{name="default:pine_sapling", chance = 10, amount = 2},
|
||||
{name="default:junglesapling", chance = 15, amount = 2},
|
||||
{name="default:acacia_sapling", chance = 15, amount = 2}
|
||||
}
|
||||
|
||||
-- Add items from other mods here inside the appropriate
|
||||
-- "if ... then ... end" test
|
||||
-- For basic lists, just using insert without a value works fine.
|
||||
-- For depth cutoff lists, you can use insert with a table index, eg.
|
||||
-- table.insert(dungeon_loot.treasure_list, 5, {name="your_mod:platinum_ingot", min_depth = 120}
|
||||
-- The above would add a new item to the treasure list as the 5th item,
|
||||
-- moving diamond and all below it one down in the list. Just make sure
|
||||
-- that the increasing min_depth order is kept.
|
||||
-- Tips: With multiple insertions in a depth cutoff list, start from the
|
||||
-- last item and work towards the beginning, then you don't have to calculate
|
||||
-- your number of additions. Also, trying to make sure too many different
|
||||
-- mods work together in a single list will probably give you a headache;
|
||||
-- just create a new list (or two) for mods with lots of additions.
|
||||
|
||||
if minetest.get_modpath("farming") then
|
||||
table.insert(dungeon_loot.consumables_list, {name="farming:bread", chance_and_amount = 10})
|
||||
table.insert(dungeon_loot.seedlings_list, {name="farming:seed_wheat", chance = 1, amount = 10})
|
||||
table.insert(dungeon_loot.seedlings_list, {name="farming:seed_cotton", chance = 20, amount = 5})
|
||||
end
|
153
init.lua
153
init.lua
@ -19,18 +19,125 @@
|
||||
-- 3. This notice may not be removed or altered from any source distribution.
|
||||
--
|
||||
|
||||
local chest_stuff = {
|
||||
{name="default:apple", max = 3},
|
||||
{name="default:steel_ingot", max = 2},
|
||||
{name="default:gold_ingot", max = 2},
|
||||
{name="default:diamond", max = 1},
|
||||
{name="default:pick_steel", max = 1},
|
||||
{name="default:pick_diamond", max = 1},
|
||||
{name="default:acacia_sapling", max = 3}
|
||||
}
|
||||
|
||||
if minetest.get_modpath("farming") then
|
||||
chest_stuff[8] = {name="farming:bread", max = 3}
|
||||
-- Following Code (everything before fill_chest) by Amoeba <amoeba@iki.fi>
|
||||
dungeon_loot = {}
|
||||
dungeon_loot.version = 1.2
|
||||
|
||||
-- Load other file(s)
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
dofile(modpath.."/config.lua") -- All the constants for simple tuning
|
||||
|
||||
|
||||
local function get_max_loot(loot_list, depth)
|
||||
local loot_type = loot_list[1].name
|
||||
local loot_min_depth = loot_list[1].min_depth
|
||||
for i,v in ipairs(loot_list) do
|
||||
if v.min_depth < depth then
|
||||
loot_type = v.name
|
||||
loot_min_depth = v.min_depth
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
return loot_type, loot_min_depth
|
||||
end
|
||||
|
||||
local function get_basic_loot(loot_list, depth)
|
||||
local loot_type = ""
|
||||
local loot_amount = 0
|
||||
local total_chance = 0
|
||||
for i,v in ipairs(loot_list) do
|
||||
if v.chance_and_amount then
|
||||
total_chance = total_chance + v.chance_and_amount
|
||||
elseif v.chance then
|
||||
total_chance = total_chance + v.chance
|
||||
else
|
||||
error("No chance_and_amount or chance found in basic_list table.")
|
||||
return nil, 0
|
||||
end
|
||||
end
|
||||
local leftover = math.random(1,total_chance)
|
||||
local type_amount = 0
|
||||
for i,v in ipairs(loot_list) do
|
||||
if v.chance_and_amount then
|
||||
leftover = leftover - v.chance_and_amount
|
||||
elseif v.chance then
|
||||
leftover = leftover - v.chance
|
||||
end
|
||||
if leftover < 1 then
|
||||
loot_type = v.name
|
||||
if v.chance_and_amount then
|
||||
type_amount = v.chance_and_amount
|
||||
else
|
||||
type_amount = v.amount
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
if loot_type == "" then -- Paranoia
|
||||
error("Unable to choose a loot_type from basic_list table.")
|
||||
return nil, 0
|
||||
end
|
||||
loot_amount = math.random(1,math.ceil(type_amount/2))
|
||||
if depth > dungeon_loot.depth_first_basic_increase then
|
||||
loot_amount = math.random(1,type_amount)
|
||||
end
|
||||
if depth > dungeon_loot.depth_second_basic_increase then
|
||||
loot_amount = math.random(1,type_amount*2)
|
||||
end
|
||||
return loot_type, loot_amount
|
||||
end
|
||||
|
||||
local function get_item_and_amount(list_item, actual_depth)
|
||||
if list_item.chance < math.random() then
|
||||
return nil, 0
|
||||
end
|
||||
-- Suspicious trickery
|
||||
list_name = nil
|
||||
list_name_string = "dungeon_loot." .. list_item.name .. "_list"
|
||||
-- list_name = _G[list_name_string]
|
||||
lsf = loadstring("list_name = " .. list_name_string)
|
||||
lsf()
|
||||
if list_name == nil then
|
||||
error("Unable to connect " .. list_name_string .. " to actual table")
|
||||
return nil, 0
|
||||
end
|
||||
local amount = 0
|
||||
local loot_type = ""
|
||||
local loot_depth = 0
|
||||
local max_depth = 1
|
||||
if actual_depth < 0 then
|
||||
max_depth = math.ceil(math.abs(actual_depth))
|
||||
end
|
||||
if list_item.type == "depth_cutoff" then
|
||||
local rnd_depth = math.random(1,max_depth)
|
||||
loot_type, loot_depth = get_max_loot(list_name, rnd_depth)
|
||||
if list_item.max_amount == 1 then -- For tools & weapons
|
||||
amount = 1
|
||||
else
|
||||
-- Stop large amounts of the first item
|
||||
if loot_depth < 1 then
|
||||
loot_depth = 5
|
||||
end
|
||||
local leftover = rnd_depth
|
||||
while leftover > 0 do
|
||||
amount = amount + 1
|
||||
leftover = leftover - math.random(1,loot_depth)
|
||||
leftover = leftover - math.ceil(loot_depth/2)
|
||||
end
|
||||
end
|
||||
elseif list_item.type == "basic_list" then
|
||||
loot_type, amount = get_basic_loot(list_name, max_depth)
|
||||
else
|
||||
error("Got unknown loot table type " .. list_item.type)
|
||||
loot_type = nil
|
||||
end
|
||||
-- Hey, if you leave out the max_amount, you deserve what you get
|
||||
if list_item.max_amount and amount > list_item.max_amount then
|
||||
amount = list_item.max_amount
|
||||
end
|
||||
return loot_type, amount
|
||||
end
|
||||
|
||||
local function fill_chest(pos)
|
||||
@ -40,14 +147,11 @@ local function fill_chest(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 8*4)
|
||||
if math.random(1, 10) < 7 then
|
||||
return
|
||||
end
|
||||
for i=1,3,1 do
|
||||
local stuff = chest_stuff[math.random(1, #chest_stuff)]
|
||||
local stack = ItemStack({name = stuff.name, count = math.random(1, stuff.max)})
|
||||
if not inv:contains_item("main", stack) then
|
||||
inv:set_stack("main", math.random(1, 32), stack)
|
||||
for i,v in ipairs(dungeon_loot.loot_types) do
|
||||
local item, num = get_item_and_amount(v,pos.y)
|
||||
if item then
|
||||
local stack = ItemStack({name = item, count = num, wear = 0, metadata = ""})
|
||||
inv:set_stack("main",i,stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -57,10 +161,13 @@ end
|
||||
-- Place chest in dungeons
|
||||
|
||||
local function place_spawner(tab)
|
||||
local pos = tab[math.random(1, (#tab or 4))]
|
||||
if tab == nil or #tab < 1 then
|
||||
return
|
||||
end
|
||||
local pos = tab[math.random(1, #tab)]
|
||||
pos.y = pos.y - 1
|
||||
local n = core.get_node_or_nil(pos)
|
||||
if n and n.name ~= "air" then
|
||||
local below = core.get_node_or_nil(pos)
|
||||
if below and below.name ~= "air" then
|
||||
pos.y = pos.y + 1
|
||||
core.set_node(pos, {name = "default:chest"})
|
||||
fill_chest(pos)
|
||||
@ -70,7 +177,7 @@ end
|
||||
core.set_gen_notify("dungeon")
|
||||
core.register_on_generated(function(minp, maxp, blockseed)
|
||||
local ntf = core.get_mapgen_object("gennotify")
|
||||
if ntf and ntf.dungeon and #ntf.dungeon > 3 then
|
||||
if ntf and ntf.dungeon and #ntf.dungeon >= dungeon_loot.min_num_of_rooms then
|
||||
core.after(3, place_spawner, table.copy(ntf.dungeon))
|
||||
end
|
||||
end)
|
||||
|
Loading…
x
Reference in New Issue
Block a user