dungeon/mods/animal_dm/vault.lua

529 lines
18 KiB
Lua

--(c) Celeron55
local vault = {}
function vault.cmp(v, w)
return (
v.x == w.x and
v.y == w.y and
v.z == w.z
)
end
function vault.add(v, w)
return {
x = v.x + w.x,
y = v.y + w.y,
z = v.z + w.z,
}
end
function vault.sub(v, w)
return {
x = v.x - w.x,
y = v.y - w.y,
z = v.z - w.z,
}
end
vault.make_vault_part = function(p, part, seed)
local ns = nil
local top_y = 2
local mob = nil
--choose what to do at position
if part == 'w' then
ns = {
{name='default:cobble'},
{name='default:cobble'},
{name='default:cobble'},
{name='default:cobble'},
}
elseif part == 'W' then
top_y = 3
ns = {
{name='default:cobble'},
{name='default:cobble'},
{name='default:cobble'},
{name='default:cobble'},
{name='default:cobble'},
{name='default:cobble'},
}
elseif part == 'c' then
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
elseif part == 'T' then
ns = {
{name='default:cobble'},
{name='default:torch'},
{name='air'},
{name='default:cobble'},
}
elseif part == 'f' then
ns = {
{name='air'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
elseif part == 'l' then
top_y = 3
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='air'},
{name='air'},
{name='default:lava_source'},
}
elseif part == 'm' then
top_y = 3
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
mob = "animal_dm:dm__default"
elseif part == 'C' then
top_y = 3
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
elseif part == 'S' then
top_y = 3
ns = {
{name='default:cobble'},
{name='air'},
{name='default:bookshelf'},
{name='default:bookshelf'},
{name='default:cobble'},
}
elseif part == 'd' then
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
elseif part == 'a' then
ns = {
nil,
{name='air'},
{name='air'},
nil,
}
elseif part == 'A' then
ns = {
nil,
{name='air'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
elseif part == 't' then
local invcontent = {}
local pr = PseudoRandom(seed)
if pr:next(1,4) == 1 then
table.insert(invcontent, 'default:apple '..tostring(pr:next(1,5)))
end
if pr:next(1,3) == 1 then
table.insert(invcontent, 'bucket:bucket_empty 1')
end
if pr:next(1,4) == 1 then
table.insert(invcontent, 'bucket:bucket_lava 1')
end
if pr:next(1,20) == 1 then
table.insert(invcontent, 'bucket:bucket_water 1')
end
if pr:next(1,34) == 1 then
table.insert(invcontent, 'bucket:nyancat 1')
table.insert(invcontent, 'bucket:nyancat_rainbow '..tostring(pr:next(1,6)))
end
if pr:next(1,2) == 1 then
table.insert(invcontent, 'default:gravel '..tostring(pr:next(1,10)))
end
if pr:next(1,3) == 1 then
table.insert(invcontent, 'default:bookshelf '..tostring(pr:next(1,2)))
end
if pr:next(1,8) == 1 then
table.insert(invcontent, 'default:cactus '..tostring(pr:next(1,2)))
end
if pr:next(1,4) == 1 then
table.insert(invcontent, 'default:rail '..tostring(pr:next(1,10)))
end
if pr:next(1,5) == 1 then
table.insert(invcontent, 'default:ladder '..tostring(pr:next(1,9)))
end
if pr:next(1,3) == 1 then
table.insert(invcontent, 'default:sign_wall 1')
end
if pr:next(1,6) == 1 then
table.insert(invcontent, 'default:steelblock '..tostring(pr:next(1,6)))
end
ns = {
{name='default:cobble'},
{name='air'},
{name='default:chest', inv=invcontent},
{name='default:cobble'},
}
else
return
end
--for all nodes in definition
for i=1,#ns do
local dy = top_y + 1 - i
local p2 = {x=p.x,y=p.y+dy,z=p.z}
--get node at position
local oldn = minetest.env:get_node(p2)
local n = ns[i]
--don't do anything if no new node is specified or
--old node is air
if n and oldn.name ~= "air" then
--possibly add mossy if it's a cobble node
if n.name == 'default:cobble' then
local perlin = minetest.env:get_perlin(123, 2, 0.8, 2.0)
if perlin:get3d(p2) >= 0.0 then
n.name = 'default:mossycobble'
end
end
--set node
--dm_debug("pos: " .. minetest.pos_to_string(p2) .. " replacing " .. oldn.name .. " by " .. n.name)
minetest.env:set_node(p2, ns[i])
--special handling for chests
if n.inv then
dm_debug("adding chest at " .. minetest.pos_to_string(p2) )
local meta = minetest.env:get_meta(p2)
local inv = meta:get_inventory()
for _,itemstring in ipairs(n.inv) do
inv:add_item('main', itemstring)
end
end
else
--dm_debug("pos: " .. minetest.pos_to_string(p) .. " not replacing " .. oldn.name)
end
end
if mob then
--dm_debug("adding dm at " .. minetest.pos_to_string({x=p.x,y=p.y+1,z=p.z}) )
local newobject = minetest.env:add_entity({x=p.x,y=p.y+1,z=p.z}, mob)
local newentity = mobf_find_entity(newobject)
if newentity and
newentity.dynamic_data and
newentity.dynamic_data.spawning then
newentity.dynamic_data.spawning.player_spawned = playerspawned
newentity.dynamic_data.spawning.spawner = "vault"
end
end
end
vault.generate_vault = function(vault_def, p, dir, seed)
local dim_z = #vault_def
assert(dim_z > 0)
local dim_x = #vault_def[1]
--don't generate vault if entrance dir not z +1
if not vault.cmp(dir, {x=0,y=0,z=1}) then
--dm_debug("entrance direction wrong: " .. minetest.pos_to_string(p))
return
else
dm_debug("generating vault at: " .. minetest.pos_to_string(p))
end
--print("Making vault at "..minetest.pos_to_string(p))
if dim_x >= 14 then
--dm_debug("Making large vault at "..minetest.pos_to_string(p))
else
--dm_debug("Making vault at "..minetest.pos_to_string(p))
end
-- Find door in definition
local def_door_p = nil
for dx=1,dim_x do
for dz=1,dim_z do
if vault_def[dim_z+1-dz][dx] == 'd' then
def_door_p = {x=dx,y=0,z=dz}
end
if def_door_p then break end
end
if def_door_p then break end
end
--print("Vault door found at "..minetest.pos_to_string(def_door_p).." in definition")
assert(def_door_p)
local randseed = seed
for dx=1,dim_x do
for dz=1,dim_z do
local p2 = vault.add(vault.sub(p, def_door_p), {x=dx, y=0, z=dz})
local part = vault_def[dim_z+1-dz][dx]
--dm_debug("Making vault part "..dump(part).." at "..minetest.pos_to_string(p2))
vault.make_vault_part(p2, part, randseed)
randseed = randseed + 1
end
end
end
-- Definition is for Z=up, X=right, dir={x=0,y=0,z=1}
vault.vault_defs = {
---[[
{
{'w','w','w','w','w','w','w','w','w','w'},
{'w','c','c','c','c','c','C','C','c','w'},
{'w','c','C','c','c','c','C','C','m','w'},
{'w','C','C','C','w','w','C','C','c','w'},
{'w','C','C','C','w','w','C','C','c','w'},
{'w','T','C','c','w','w','C','w','w','w'},
{'w','c','t','c','w','w','C','w','n','n'},
{'w','w','w','w','w','w','C','w','n','n'},
{'n','n','n','n','n','w','d','w','n','n'},
{'n','n','n','n','n','n','A','n','n','n'},
},
--]]
---[[
{
{'w','w','w','w','w','w','w','w'},
{'w','c','c','c','m','C','c','w'},
{'w','C','c','c','C','C','c','w'},
{'w','C','w','w','C','C','c','w'},
{'w','C','t','w','C','C','c','w'},
{'w','C','t','w','C','w','d','w'},
{'w','T','w','w','C','w','A','n'},
{'w','c','C','C','C','w','n','n'},
{'n','n','n','w','w','w','n','n'},
},
--]]
---[[
{
{'W','W','W','W','W','W','W','W','W','W','W','W','W','W','W','W'},
{'W','l','l','l','l','l','l','t','t','l','l','l','l','l','l','W'},
{'W','l','l','l','l','l','l','f','f','l','l','l','l','l','l','W'},
{'W','l','l','l','l','l','l','f','f','l','l','l','l','l','l','W'},
{'W','m','l','l','l','l','l','f','f','l','l','l','l','l','m','W'},
{'W','c','l','l','l','l','l','f','f','l','l','l','l','l','c','W'},
{'W','c','l','l','l','l','l','f','f','l','l','l','l','l','c','W'},
{'W','c','l','l','l','l','l','f','f','l','l','l','l','l','c','W'},
{'W','m','l','l','l','l','l','f','f','l','l','l','l','l','m','W'},
{'W','l','l','l','l','l','l','f','f','l','l','l','l','l','l','W'},
{'W','l','l','l','l','l','l','f','f','l','l','l','l','l','l','W'},
{'W','l','l','l','l','l','l','f','f','l','l','l','l','l','l','W'},
{'W','W','W','W','W','W','W','W','d','W','W','W','W','W','W','W'},
{'n','n','n','n','n','n','n','n','A','n','n','n','n','n','n','n'},
},
--]]
---[[
{
{'W','W','W','W','W','W','W','W','W','W','W','W','W','W','W','W'},
{'W','f','f','f','f','l','l','t','l','l','l','l','l','l','l','W'},
{'W','f','l','l','l','l','l','f','l','l','l','l','l','l','l','W'},
{'W','f','l','l','f','l','l','l','l','l','l','l','l','l','l','W'},
{'W','f','l','l','l','l','l','l','f','l','f','f','l','l','m','W'},
{'W','f','l','l','l','l','f','l','l','l','l','l','f','l','c','W'},
{'W','f','f','l','l','l','l','l','l','l','l','l','f','l','c','W'},
{'W','c','f','l','l','l','l','l','l','l','l','l','f','l','c','W'},
{'W','m','f','l','l','l','l','l','l','l','l','l','f','l','m','W'},
{'W','l','f','l','l','l','l','f','f','l','f','f','f','l','l','W'},
{'W','l','t','l','l','l','l','f','f','l','l','l','l','l','l','W'},
{'W','l','l','l','l','l','l','f','f','l','l','l','l','l','l','W'},
{'W','W','W','W','W','W','W','W','d','W','W','W','W','W','W','W'},
{'n','n','n','n','n','n','n','n','A','n','n','n','n','n','n','n'},
},
--]]
---[[
{
{'n','n','n','n','n','n','n','n','n','n','n','n','w','w','w','w','n','n','n','n'},
{'n','n','n','n','n','n','n','n','w','w','w','w','w','c','c','w','w','w','w','n'},
{'n','n','n','n','n','n','n','w','w','c','c','c','c','c','c','c','c','w','w','n'},
{'n','n','n','n','n','n','w','w','c','c','c','c','c','c','c','c','c','c','W','W'},
{'n','n','n','n','n','n','w','t','c','C','C','m','c','c','C','C','m','c','c','W'},
{'n','n','n','n','n','n','w','t','c','C','C','c','c','c','C','C','c','c','c','W'},
{'n','n','n','n','n','n','w','w','c','c','c','c','c','c','c','c','c','c','c','W'},
{'n','n','n','n','n','n','n','w','w','c','c','c','C','C','C','C','C','C','C','W'},
{'n','n','n','n','n','n','n','n','w','w','c','c','l','l','l','l','l','l','l','W'},
{'n','n','n','n','n','n','n','n','W','W','l','l','l','l','l','l','l','l','l','W'},
{'w','w','w','w','W','W','W','W','W','l','l','l','l','l','l','l','l','l','l','W'},
{'w','w','c','c','C','S','S','C','C','l','l','l','l','l','l','l','l','l','l','W'},
{'w','c','c','c','C','C','C','C','l','l','l','l','l','l','l','l','l','l','l','W'},
{'w','c','c','C','C','C','C','C','l','l','l','l','m','C','l','l','l','l','l','W'},
{'w','c','c','C','C','C','C','C','l','l','l','l','C','t','l','l','l','l','l','W'},
{'w','c','c','C','C','l','l','l','l','l','l','l','l','l','l','l','l','l','l','W'},
{'w','c','C','C','l','l','l','l','l','l','l','l','l','l','l','l','l','l','l','W'},
{'w','W','C','C','l','l','l','l','l','l','l','l','l','l','l','l','l','l','W','W'},
{'n','W','d','W','W','W','W','W','W','W','W','W','W','W','W','W','W','W','W','n'},
{'n','n','A','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n'},
},
--]]
}
function vault.node_is_solid(n)
return (n and n.name and minetest.registered_nodes[n.name] and
minetest.registered_nodes[n.name].walkable)
end
vault.generate_random_vault = function(p, dir, seed)
--random select of vault template
local pr = PseudoRandom(seed+9322)
local vault_def = vault.vault_defs[pr:next(1, #vault.vault_defs)]
--generate vault by template
vault.generate_vault(vault_def, p, dir, seed)
end
minetest.register_on_generated(function(minp, maxp, seed)
--abort in case of dm disabled
if minetest.registered_entities["animal_dm:dm"] == nil then
return
end
--abort in case of above sea level
if maxp.y > -10 then
return
end
--calculate area of generated chunk
local area = (maxp.x-minp.x+1)*(maxp.z-minp.z+1)
--initialize dungeon level with 2
local dungeon_level_y = 2
--get random dungeon level within generated chunk
if maxp.y < 2 then
local pr = PseudoRandom(seed+932)
dungeon_level_y = pr:next(minp.y, maxp.y)
end
--initialize check values
local is_empty = false
local light = nil
local last_empty = false
local last_light = nil
local possible_entrances = {}
local d = 4
--loop through chunk using d frames in x direction
for x=minp.x/d+1,maxp.x/d-1 do
--set to unknown on start of x-loop (why?)
local last_node_known = false
--loop through cunk in z direction
for z=minp.z+1,maxp.z-1 do
--get information of current node to check
local p = {x=x*d, y=dungeon_level_y, z=z}
local n = minetest.env:get_node(p)
--save values from last loop
last_empty = is_empty
last_light = light
--get new values
is_empty = not vault.node_is_solid(n)
light = minetest.env:get_node_light(p, 0.5)
--if last node was known
if last_node_known then
--initialize values
local useful_light = nil
--save values
if is_empty then
useful_light = light
else
useful_light = last_light
end
--if current node isn't solid,
--last was solid and we're not at daylight
if is_empty and not last_empty and useful_light < 15 then
--calculate ??? positions next to current pos
local p1 = vault.add(p, {x=0, y=0, z=-1})
local p2 = vault.add(p1, {x=0, y=2, z=-1})
local p3 = vault.add(p1, {x=0, y=2, z=-8})
local p4 = vault.add(p1, {x=-3, y=1, z=-2})
local p5 = vault.add(p1, {x=3, y=1, z=-2})
--if all nodes are solid
if vault.node_is_solid(minetest.env:get_node(p2)) and
vault.node_is_solid(minetest.env:get_node(p3)) and
vault.node_is_solid(minetest.env:get_node(p4)) and
vault.node_is_solid(minetest.env:get_node(p5))
then
local entrance = {
p = p1,
dir = {x=0, y=0, z=-1},
}
--add to entrance table with direction z = -1
table.insert(possible_entrances, entrance)
end
end
--if current node isn't solid,
--last was solid and we're not at daylight
if last_empty and not is_empty and useful_light < 15 then
local p1 = vault.add(p, {x=0, y=0, z=0})
local p2 = vault.add(p1, {x=0, y=2, z=1})
local p3 = vault.add(p1, {x=0, y=2, z=8})
local p4 = vault.add(p1, {x=-3, y=1, z=2})
local p5 = vault.add(p1, {x=3, y=1, z=2})
--if all nodes are solid
if vault.node_is_solid(minetest.env:get_node(p2)) and
vault.node_is_solid(minetest.env:get_node(p3)) and
vault.node_is_solid(minetest.env:get_node(p4)) and
vault.node_is_solid(minetest.env:get_node(p5))
then
local entrance = {
p = p1,
dir = {x=0, y=0, z=1},
}
--add to entrance table with direction z = 1
table.insert(possible_entrances, entrance)
end
end
end
last_node_known = true
end
end
--for _,entrance in ipairs(possible_entrances) do
-- dm_debug("Possible entrance: "..dump(entrance))
--end
--calculate number of entrances to generate per area
local num_entrances_to_generate = area/200
--check if there are enough possible entrances
if num_entrances_to_generate > #possible_entrances then
num_entrances_to_generate = #possible_entrances
end
local pr = PseudoRandom(seed+9452)
--generate vault for max number of entraces to generate at random
--selected possible entrances
for entrances_generate_i=1,num_entrances_to_generate do
local entrance_i = pr:next(1, #possible_entrances)
local entrance = possible_entrances[entrance_i]
--dm_debug("Entrance: "..dump(entrance))
vault.generate_random_vault(entrance.p, entrance.dir, seed)
end
end)