dungeon/mods/dungeon/init.lua

561 lines
15 KiB
Lua

-- minetest/dungeon: dungeon
local DUNGEON_Y = -1000
-- Define this so ores don't get placed on walls
minetest.register_node("dungeon:stone", {
description = "Dungeon Stone",
tiles = {"default_stone.png"},
groups = {},
legacy_mineral = true,
sounds = default.node_sound_stone_defaults(),
})
minetest.register_alias("mapgen_singlenode", "dungeon:stone")
-- Make chests not pickable up
local def = minetest.registered_nodes["default:chest"]
def.groups = {}
minetest.register_node(":default:chest", def)
local v3 = {}
function v3.new(x, y, z)
if x == nil then
return {
x = 0,
y = 0,
z = 0
}
end
if type(x) == "table" then
return {
x = x.x,
y = x.y,
z = x.z,
}
end
return {
x = x,
y = y,
z = z,
}
end
function v3.floor(v)
return {
x = math.floor(v.x),
y = math.floor(v.y),
z = math.floor(v.z),
}
end
function v3.cmp(v, w)
return (
v.x == w.x and
v.y == w.y and
v.z == w.z
)
end
function v3.add(v, w)
return {
x = v.x + w.x,
y = v.y + w.y,
z = v.z + w.z,
}
end
function v3.sub(v, w)
return {
x = v.x - w.x,
y = v.y - w.y,
z = v.z - w.z,
}
end
function v3.mul(v, a)
return {
x = v.x * a,
y = v.y * a,
z = v.z * a,
}
end
function v3.len(v)
return math.sqrt(
math.pow(v.x, 2) +
math.pow(v.y, 2) +
math.pow(v.z, 2)
)
end
function v3.norm(v)
return v3.mul(v, 1.0 / v3.len(v))
end
function v3.distance(v, w)
return math.sqrt(
math.pow(v.x - w.x, 2) +
math.pow(v.y - w.y, 2) +
math.pow(v.z - w.z, 2)
)
end
mobs = {}
mobs.make_vault_part = function(p, part, pr)
local ns = nil
local top_y = 2
local mob_y = 0
local mob = nil
local item = nil
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 == '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
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
local a = pr:next(1,2)
if a == 1 then
mob = "animal_dm:dm__default"
else
mob = "animal_vombie:vombie__default"
end
elseif part == 'r' then
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
mob = "animal_rat:rat__default"
elseif part == 'C' then
top_y = 3
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='air'},
{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 == 'i' then
ns = {
{name='default:cobble'},
{name='air'},
{name='air'},
{name='default:cobble'},
}
if pr:next(1,4) == 1 then
item = 'default:torch '..tostring(pr:next(1,15))
elseif pr:next(1,4) == 1 then
item = 'default:apple '..tostring(pr:next(1,3))
elseif pr:next(1,6) == 1 then
item = 'default:sword_stone '..tostring(pr:next(2,5)*100)
end
elseif part == 't' then
local invcontent = {}
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, 'default:cobble '..tostring(pr:next(1,5)))
end
if pr:next(1,3) == 1 then
table.insert(invcontent, 'default:torch '..tostring(pr:next(1,20)))
end
if pr:next(1,3) == 1 then
table.insert(invcontent, 'default:sword_stone '..tostring(pr:next(400,655)*100))
end
if pr:next(1,10) == 1 then
table.insert(invcontent, 'default:sword_steel '..tostring(pr:next(0,655)*100))
end
if pr:next(1,6) == 1 then
table.insert(invcontent, 'bucket:bucket_empty 1')
end
if pr:next(1,8) == 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,30) == 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,40) == 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,30) == 1 then
table.insert(invcontent, 'default:sign_wall 1')
end
if pr:next(1,60) == 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 i=1,#ns do
local dy = top_y + 1 - i
local p2 = v3.new(p)
p2.y = p2.y + dy
local oldn = minetest.env:get_node(p2)
local n = ns[i]
if n and oldn.name ~= "air" then
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
minetest.env:set_node(p2, ns[i])
if n.inv then
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
end
end
if mob then
minetest.env:add_entity(v3.add(p, v3.new(0, mob_y, 0)), mob)
end
if item then
minetest.env:add_item(v3.add(p, v3.new(0, mob_y, 0)), item)
end
end
mobs.generate_vault = function(vault_def, p, dir, seed)
local dim_z = #vault_def
assert(dim_z > 0)
local dim_x = #vault_def[1]
if not v3.cmp(dir, v3.new(0,0,1)) then return end
--print("Making vault at "..minetest.pos_to_string(p))
--if dim_x >= 14 then
-- mobs.debug("Making large vault at "..minetest.pos_to_string(p))
--else
-- mobs.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 = v3.new(dx,0,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 pr = PseudoRandom(seed)
local randseed = seed
for dx=1,dim_x do
for dz=1,dim_z do
local p2 = v3.add(v3.sub(p, def_door_p), v3.new(dx, 0, dz))
local part = vault_def[dim_z+1-dz][dx]
--print("Making vault part "..dump(part).." at "..minetest.pos_to_string(p2))
mobs.make_vault_part(p2, part, pr)
randseed = randseed + 1
end
end
end
-- Definition is for Z=up, X=right, dir={x=0,y=0,z=1}
mobs.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','r','C','c','w','w','C','w','w','w'},
{'w','c','c','c','w','w','C','w',nil,nil},
{'w','w','w','w','w','w','C','w',nil,nil},
{nil,nil,nil,nil,nil,'w','d','w',nil,nil},
{nil,nil,nil,nil,nil,nil,'A',nil,nil,nil},
},
{
{'w','w','w','w','w','w','w','w'},
{'w','c','c','c','c','C','c','w'},
{'w','C','c','c','C','C','c','w'},
{'w','C','c','c','C','C','c','w'},
{'w','C','t','w','C','C','r','w'},
{'w','C','c','w','C','w','d','w'},
{'w','w','w','w','C','w','A',nil},
{'w','w','w','w','C','w',nil,nil},
{nil,nil,nil,'w','w','w',nil,nil},
},
{
{'W','W','W','W','W','W','W','W','W','W','W','W','W','W','W','W'},
{'W','l','l','l','l','l','l','c','i','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','c','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','t','f','f','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','c','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'},
{nil,nil,nil,nil,nil,nil,nil,nil,'A',nil,nil,nil,nil,nil,nil,nil},
},
{
{'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','C','C','C','C','C','w'},
{'w','C','C','C','C','C','C','w'},
{'w','C','C','C','C','C','C','w'},
{'w','C','C','C','C','C','C','w'},
{'w','C','c','c','C','C','r','w'},
{'w','C','c','w','C','w','d','w'},
{'w','c','w','w','C','w','A',nil},
{'w','c','C','C','C','w',nil,nil},
{nil,nil,nil,'w','w','w',nil,nil},
},
{
{'w','w','w','w','w','w','w','w'},
{'w','c','c','c','c','C','i','w'},
{'w','C','c','c','C','C','c','w'},
{'w','C','w','w','C','C','c','w'},
{'w','C','c','c','C','C','c','w'},
{'w','C','C','w','C','w','d','w'},
{'w','c','C','C','C','w','A',nil},
{'w','c','C','C','C','w',nil,nil},
{'w','C','C','C','C','C','C','w'},
{'w','C','C','C','C','C','C','w'},
{nil,nil,nil,'w','w','w',nil,nil},
},
{
{'w','w','w','w','w','w','w','w'},
{'w','c','c','c','c','C','c','w'},
{'w','C','c','c','w','C','c','w'},
{'w','C','w','w','w','w','c','w'},
{'w','C','C','C','C','C','c','w'},
{'w','C','c','w','C','w','d','w'},
{'w','i','w','w','C','w','A',nil},
{'w','c','C','C','C','w',nil,nil},
{nil,nil,nil,'w','w','w',nil,nil},
},
{
{'w','w','w','w','w','w','w','w'},
{'w','i','c','c','c','C','t','w'},
{'w','C','w','c','C','C','c','w'},
{'w','c','w','w','w','C','w','w'},
{'w','C','w','c','C','C','C','w'},
{'w','C','w','c','C','C','d','w'},
{'w','c','w','w','w','C','A',nil},
{'w','c','C','C','C','C',nil,nil},
{nil,nil,nil,'w','w','w',nil,nil},
},
{
{'W','W','W','W','W','W','W','W','W','W','W','W','W','W','W','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','m','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','C','C','C','C','C','C','C','C','C','C','C','C','C','C','W'},
{'W','W','W','W','W','W','W','W','d','W','W','W','W','W','W','W'},
{nil,nil,nil,nil,nil,nil,nil,nil,'d',nil,nil,nil,nil,nil,nil,nil},
},
}
mobs.generate_random_vault = function(p, dir, pr)
seed = pr:next()
local vault_def = mobs.vault_defs[pr:next(1, #mobs.vault_defs)]
mobs.generate_vault(vault_def, p, dir, seed)
end
local generate_corridor = function(from, to, seed)
local pr = PseudoRandom(seed+92384)
local p = {x=from.x, y=from.y, z=from.z}
local step = 0
while p.x ~= to.x do
if step >= 5 and minetest.env:get_node(p).name == "air" then
return
end
step = step + 1
mobs.make_vault_part(p, 'C', pr)
if p.x > to.x then
p.x = p.x - 1
else
p.x = p.x + 1
end
end
local step = 0
while p.z ~= to.z do
if step >= 5 and minetest.env:get_node(p).name == "air" then
return
end
step = step + 1
mobs.make_vault_part(p, 'C', pr)
if p.z > to.z then
p.z = p.z - 1
else
p.z = p.z + 1
end
end
end
minetest.register_on_generated(function(minp, maxp, seed)
--[[if minp.x > maxp.x or minp.y > maxp.y or minp.z > maxp.z then
mobs.debug"foo")
return
end--]]
if minp.y > DUNGEON_Y or maxp.y < DUNGEON_Y then
return
end
local area = (maxp.x-minp.x+1)*(maxp.z-minp.z+1)
local possible_entrances = {}
local entrance = {
p = {x=0, y=-DUNGEON_Y, z=-5},
dir = {x=0, y=0, z=1},
}
table.insert(possible_entrances, entrance)
local pr = PseudoRandom(seed+931)
for i=0,area/300 do
local p1 = {
x = pr:next(minp.x, maxp.x),
y = DUNGEON_Y,
z = pr:next(minp.z, maxp.z),
}
local entrance = {
p = p1,
dir = {x=0, y=0, z=1},
}
table.insert(possible_entrances, entrance)
end
local pr = PseudoRandom(seed+9322)
local lastp = nil
if minp.x < 0 and maxp.x > 0 and minp.z < 0 and maxp.z > 0 then
lastp = {x=0, y=DUNGEON_Y, z=0}
end
for i,entrance in ipairs(possible_entrances) do
--mobs.debug("Entrance: "..dump(entrance))
mobs.generate_random_vault(entrance.p, entrance.dir, pr)
if lastp then
generate_corridor(lastp, entrance.p, pr:next())
end
lastp = entrance.p
end
if minp.x < 0 and maxp.x > 0 and minp.z < 0 and maxp.z > 0 then
p = {x=0, y=DUNGEON_Y+2, z=0}
minetest.env:set_node(p, {name="default:torch"})
end
end)
local function give_initial_stuff(player)
player:get_inventory():add_item('main', 'default:torch 99')
--player:get_inventory():add_item('main', 'default:shovel_steel')
--player:get_inventory():add_item('main', 'default:sword_steel')
--player:get_inventory():add_item('main', 'default:cobble 99')
end
minetest.register_on_newplayer(function(player)
player:setpos({x=0, y=DUNGEON_Y, z=0})
give_initial_stuff(player)
end)
minetest.register_on_respawnplayer(function(player)
player:setpos({x=0, y=DUNGEON_Y, z=0})
player:get_inventory():set_list("main", {})
player:get_inventory():set_list("craft", {})
give_initial_stuff(player)
return true
end)