updated a few mods, added Goblins

master
NathanSalapat 2015-08-20 11:47:59 -05:00
parent 825c692428
commit ceb83c9144
78 changed files with 7241 additions and 485 deletions

View File

@ -56,7 +56,7 @@ minetest.register_node('food:smoker', { --This will allow for smoking meats
--]]
if inv:contains_item('fuel', 'default:tree') or inv:contains_item('fuel', 'default:jungletree') then
minetest.swap_node(pos, {name = 'food:smoker_on', param2=node.param2})
timer:start(8*60) --eight minutes to smoke meat
timer:start(10) --eight minutes to smoke meat
meta:set_string('infotext', 'Burning Smoker')
meta:set_string('formspec',
'size[8,7]'..
@ -66,6 +66,16 @@ minetest.register_node('food:smoker', { --This will allow for smoking meats
'list[current_player;main;0,3;8,4;]')
end
end,
--[[ allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname == 'meat' then
if stack:get_name() == ('food:steak_raw') then
return 1
else
return 0
end
end
end,
--]]
})
minetest.register_node('food:smoker_on', { --Just a change in textures.
@ -84,6 +94,17 @@ minetest.register_node('food:smoker_on', { --Just a change in textures.
type = 'fixed',
fixed = {-.5, -.5, -.4, .5, .5, .4},
},
on_timer = function(pos, elapsed)
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
local timer = minetest.get_node_timer(pos)
if inv:contains_item('meat', 'food:steak_raw') then --make sure the bucket is still there
inv:set_stack('meat', 6 ,'food:steak_smoked')
meta:set_string('infotext', 'bucket filled with sap, please replace.')
timer:stop()
return
end
end,
})
--Craft Recipes

View File

@ -0,0 +1,8 @@
minetest.register_craft({
output = 'furniture:bedside_cabinet',
recipe = {
{'group:wood', 'group:wood', 'group:wood'},
{'group:wood', 'default:chest', 'group:wood'},
{'group:wood', 'default:chest', 'group:wood'},
}
})

View File

@ -0,0 +1 @@
default

2
mods/furniture/init.lua Normal file
View File

@ -0,0 +1,2 @@
dofile(minetest.get_modpath('furniture')..'/crafts.lua')
dofile(minetest.get_modpath('furniture')..'/nodes.lua')

View File

@ -0,0 +1,298 @@
# Blender v2.75 (sub 4) OBJ File: 'nightstand.blend'
# www.blender.org
o Cube_Cube.001
v 0.355439 0.041130 -0.382276
v 0.355439 0.362854 -0.382276
v 0.355439 0.041130 -0.337600
v 0.355439 0.362854 -0.337600
v -0.355439 0.041130 -0.382276
v -0.355439 0.362854 -0.382276
v -0.355439 0.041130 -0.337600
v -0.355439 0.362854 -0.337600
v 0.116264 0.149374 -0.392572
v 0.116264 0.254610 -0.392572
v 0.116264 0.149374 -0.377958
v 0.116264 0.254610 -0.377958
v -0.116264 0.149374 -0.392572
v -0.116264 0.254610 -0.392572
v -0.116264 0.149374 -0.377958
v -0.116264 0.254610 -0.377958
v 0.355439 -0.358870 -0.382276
v 0.355439 -0.037146 -0.382276
v 0.355439 -0.358870 -0.337600
v 0.355439 -0.037146 -0.337600
v -0.355439 -0.358870 -0.382276
v -0.355439 -0.037146 -0.382276
v -0.355439 -0.358870 -0.337600
v -0.355439 -0.037146 -0.337600
v 0.116264 -0.250626 -0.392572
v 0.116264 -0.145390 -0.392572
v 0.116264 -0.250626 -0.377958
v 0.116264 -0.145390 -0.377958
v -0.116264 -0.250626 -0.392572
v -0.116264 -0.145390 -0.392572
v -0.116264 -0.250626 -0.377958
v -0.116264 -0.145390 -0.377958
v 0.409091 -0.500000 -0.342386
v 0.409091 0.500000 -0.342386
v 0.409091 -0.500000 0.478737
v 0.409091 0.500000 0.478737
v -0.409091 -0.500000 -0.342386
v -0.409091 0.500000 -0.342386
v -0.409091 -0.500000 0.478737
v -0.409091 0.500000 0.478737
v 0.450000 -0.400000 -0.342386
v 0.450000 0.400000 -0.342386
v 0.450000 0.400000 0.478737
v 0.450000 -0.400000 0.478737
v -0.450000 0.400000 0.478737
v -0.450000 -0.400000 0.478737
v -0.450000 0.400000 -0.342386
v -0.450000 -0.400000 -0.342386
v -0.500000 -0.400000 0.478737
v -0.500000 -0.500000 0.478737
v -0.500000 0.500000 0.478737
v -0.500000 0.500000 -0.342386
v -0.500000 -0.400000 -0.342386
v -0.500000 -0.500000 -0.342386
v -0.500000 0.400000 0.478737
v -0.500000 0.400000 -0.342386
v 0.500000 0.400000 -0.342386
v 0.500000 0.500000 -0.342386
v 0.500000 0.500000 0.478737
v 0.500000 -0.400000 0.478737
v 0.500000 -0.500000 0.478737
v 0.500000 -0.500000 -0.342386
v 0.500000 -0.400000 -0.342386
v 0.500000 0.400000 0.478737
v 0.409091 0.400000 -0.433622
v 0.409091 0.500000 -0.433622
v -0.409091 -0.400000 -0.433622
v -0.409091 -0.500000 -0.433622
v -0.409091 0.500000 -0.433622
v 0.409091 -0.500000 -0.433622
v 0.409091 -0.400000 -0.433622
v -0.409091 0.400000 -0.433622
v -0.500000 -0.400000 -0.433622
v -0.500000 -0.500000 -0.433622
v -0.500000 0.500000 -0.433622
v -0.500000 0.400000 -0.433622
v 0.500000 0.400000 -0.433622
v 0.500000 0.500000 -0.433622
v 0.500000 -0.500000 -0.433622
v 0.500000 -0.400000 -0.433622
vt 1.995605 -1.091383
vt 2.044429 -1.091383
vt 2.044430 -0.740654
vt 1.995605 -0.740654
vt 2.044429 -0.389925
vt 1.995605 -0.389925
vt 0.523367 1.485645
vt -0.254387 1.485646
vt -0.254387 1.134051
vt 0.523367 1.134050
vt 0.998535 1.874522
vt 0.949710 1.874522
vt 0.949710 1.096769
vt 0.998535 1.096769
vt 1.921638 1.096769
vt 1.970463 1.096769
vt 1.970463 1.874522
vt 1.921638 1.874522
vt -0.094313 0.511501
vt -0.078343 0.511501
vt -0.078343 0.626225
vt -0.094313 0.626225
vt -0.078343 0.740948
vt -0.094313 0.740948
vt 2.027966 1.408676
vt 1.773562 1.408676
vt 1.773562 1.293669
vt 2.027966 1.293669
vt -0.063330 0.002693
vt -0.047360 0.002693
vt -0.047360 0.257097
vt -0.063330 0.257097
vt -0.062372 0.511501
vt -0.078343 0.257097
vt -0.062372 0.257097
vt 1.970463 1.605577
vt 2.019287 1.605577
vt 2.019287 1.956306
vt 1.970463 1.956306
vt 2.044429 -0.039196
vt 1.995605 -0.039196
vt 0.523367 1.837240
vt -0.254387 1.837241
vt 0.001465 0.780447
vt -0.047360 0.780447
vt 0.001465 0.002693
vt 1.872813 1.096769
vt 1.872813 1.874522
vt -0.062372 0.626225
vt -0.062372 0.740948
vt 2.282370 1.408676
vt 2.282370 1.293669
vt -0.094313 0.002693
vt -0.078343 0.002693
vt -0.094313 0.257097
vt -0.982098 -1.036679
vt -1.091383 -0.991922
vt -1.091383 -1.091383
vt -0.982098 -1.091383
vt -0.982098 -0.052011
vt -1.091383 -0.096769
vt 1.098242 -0.052011
vt 1.995605 -0.052011
vt 1.995605 0.002693
vt 1.098242 0.002693
vt 1.098242 -1.091383
vt 1.098242 -1.036679
vt 0.998535 -0.991922
vt 0.998535 -1.091383
vt 0.898828 -0.096769
vt 0.001465 -0.096769
vt 0.001465 -0.991921
vt 0.898828 -0.991922
vt 0.101172 0.102154
vt 0.998535 0.102154
vt 0.998535 0.997307
vt 0.101172 0.997307
vt -0.991676 0.002693
vt -0.991676 0.057397
vt -1.091383 0.102154
vt -1.091383 0.002693
vt 1.882759 0.002693
vt 1.882759 0.987361
vt 1.008481 0.987361
vt 1.008481 0.002693
vt 0.898828 0.002693
vt 0.998535 -0.096769
vt 0.998535 0.002693
vt -1.091383 1.991922
vt -1.091383 1.096769
vt -0.217105 1.096769
vt -0.217105 1.991922
vt -0.107820 -0.052011
vt -0.107820 -1.036679
vt 1.995605 -1.036679
vt 0.998535 1.882514
vt 0.998535 0.987361
vt 1.872813 0.987361
vt 1.872813 1.882514
vt 0.813940 2.091383
vt 0.813940 1.196230
vt 0.923225 1.196230
vt 0.923225 2.091383
vt 0.704655 2.091383
vt 0.704655 1.196230
vt 0.001465 -1.091383
vt 0.898828 -1.091383
vt 0.595370 1.991922
vt 0.704655 1.991922
vt 0.595370 2.091383
vt 0.101172 0.002693
vt -0.107820 0.002693
vt -0.982098 0.002693
vt -0.094313 0.057397
vt 0.486085 1.991922
vt 0.486085 1.096769
vt 0.595370 1.096769
vt 0.704655 1.096769
vt -0.991676 1.042065
vt -0.094313 1.042065
vt -0.094313 1.096768
vt -0.991676 1.096769
vt -0.107820 -1.091383
vt -1.091383 0.997307
vt 0.101172 1.096769
vt 1.982098 0.102154
vt 1.982098 0.997307
vt 1.872813 0.997307
vt 1.872813 0.102154
vt 2.091383 0.102154
vt 2.091383 0.997307
vt 1.872813 0.002693
vt 1.982098 0.002693
vt 2.091383 0.002693
vt 2.091383 1.096769
vt 1.982099 1.096769
vt 0.813940 1.096769
vt 0.923225 1.096769
vt 0.001465 0.997307
vt 0.001465 0.102154
vt 0.486085 2.091383
vt 0.001465 1.096769
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 1.000000
s off
f 2/1/1 4/2/1 3/3/1 1/4/1
f 8/5/2 6/6/2 5/4/2 7/3/2
f 6/7/3 2/8/3 1/9/3 5/10/3
f 1/11/4 3/12/4 7/13/4 5/14/4
f 6/15/5 8/16/5 4/17/5 2/18/5
f 10/19/1 12/20/1 11/21/1 9/22/1
f 16/22/2 14/21/2 13/23/2 15/24/2
f 14/25/3 10/26/3 9/27/3 13/28/3
f 9/29/4 11/30/4 15/31/4 13/32/4
f 14/33/5 16/20/5 12/34/5 10/35/5
f 18/36/1 20/37/1 19/38/1 17/39/1
f 24/40/2 22/41/2 21/6/2 23/5/2
f 22/42/3 18/43/3 17/8/3 21/7/3
f 17/44/4 19/45/4 23/30/4 21/46/4
f 22/47/5 24/15/5 20/18/5 18/48/5
f 26/20/1 28/33/1 27/49/1 25/21/1
f 32/21/2 30/49/2 29/50/2 31/23/2
f 30/51/3 26/25/3 25/28/3 29/52/3
f 25/53/4 27/54/4 31/34/4 29/55/4
f 30/20/5 32/19/5 28/55/5 26/34/5
f 44/56/6 35/57/6 61/58/6 60/59/6
f 44/56/6 46/60/6 39/61/6 35/57/6
f 47/62/4 45/63/4 55/64/4 56/65/4
f 57/66/4 42/67/4 65/68/4 77/69/4
f 33/70/4 35/71/4 39/72/4 37/73/4
f 38/74/5 40/75/5 36/76/5 34/77/5
f 53/78/5 48/79/5 67/80/5 73/81/5
f 47/82/3 42/83/3 41/84/3 48/85/3
f 62/86/4 33/70/4 70/87/4 79/88/4
f 45/89/2 47/90/2 48/91/2 46/92/2
f 36/72/6 40/71/6 45/93/6 43/94/6
f 43/94/6 45/93/6 46/60/6 44/56/6
f 43/95/4 42/67/4 57/66/4 64/1/4
f 42/96/1 43/97/1 44/98/1 41/99/1
f 49/100/2 53/101/2 54/102/2 50/103/2
f 51/104/2 52/105/2 56/101/2 55/100/2
f 37/73/4 39/72/4 50/106/4 54/107/4
f 58/108/1 57/109/1 77/104/1 78/110/1
f 40/75/5 38/74/5 52/111/5 51/88/5
f 45/93/6 40/71/6 51/46/6 55/112/6
f 39/61/6 46/60/6 49/113/6 50/81/6
f 46/114/5 48/79/5 53/78/5 49/53/5
f 63/115/1 60/116/1 61/117/1 62/108/1
f 58/108/1 59/117/1 64/118/1 57/109/1
f 37/73/4 54/107/4 74/69/4 68/68/4
f 41/119/5 44/120/5 60/121/5 63/122/5
f 36/72/6 43/94/6 64/123/6 59/106/6
f 35/71/4 33/70/4 62/86/4 61/46/4
f 48/79/5 41/119/5 71/124/5 67/80/5
f 34/77/5 36/76/5 59/14/5 58/125/5
f 67/126/3 71/127/3 70/128/3 68/129/3
f 69/130/3 66/131/3 65/127/3 72/126/3
f 67/126/3 68/129/3 74/132/3 73/133/3
f 69/130/3 72/126/3 76/133/3 75/134/3
f 65/127/3 66/131/3 78/135/3 77/136/3
f 70/128/3 71/127/3 80/136/3 79/47/3
f 54/102/2 53/101/2 73/137/2 74/138/2
f 47/62/4 56/65/4 76/88/4 72/87/4
f 38/74/5 34/77/5 66/139/5 69/140/5
f 56/101/2 52/105/2 75/118/2 76/137/2
f 33/70/4 37/73/4 68/68/4 70/87/4
f 63/115/1 62/108/1 79/110/1 80/141/1
f 52/111/5 38/74/5 69/140/5 75/46/5
f 34/77/5 58/125/5 78/142/5 66/139/5
f 41/119/5 63/122/5 80/90/5 71/124/5
f 42/67/4 47/62/4 72/87/4 65/68/4

31
mods/furniture/nodes.lua Normal file
View File

@ -0,0 +1,31 @@
minetest.register_node('furniture:bedside_cabinet', {
description = 'Nightstand',
drawtype = 'mesh',
mesh = 'furniture_nightstand.obj',
tiles = {'default_wood.png'},
groups = {choppy=2,oddly_breakable_by_hand=2, furn=1},
inventory_image = "furniture_nightstand.png",
paramtype = 'light',
paramtype2 = 'facedir',
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
inv:set_size('main', 8*4)
inv:set_size('storage', 3*3)
inv:set_size('storage1', 9*3)
meta:set_string('formspec',
'size [9,10.5]'..
'bgcolor[#00000000;false]'..
'background[9,10.5;0,0;nightstand.png;true]'..
'list[current_name;storage;3,0;3,3;]'..
'list[current_name;storage1;0,3;9,3]'..
'list[current_player;main;0.5,6.5;8,4;]')
meta:set_string('infotext', 'Bedside Cabinet')
end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty('storage') and inv:is_empty('storage1')
end,
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

View File

@ -10,7 +10,7 @@ local function merge(a, b)
end
function firstToUpper(str)
return (str:gsub("^%l", string.upper))
return (str:gsub("^%l", string.upper))
end
local basic_properties = {
@ -26,7 +26,7 @@ local basic_properties = {
wall_bottom = {-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125},
wall_side = {-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375},
},
groups = {snappy=1}, --2,dig_immediate=2,attached_node=1},
groups = {snappy=1, oddly_breakable_by_hand=2, attached_node=1},
legacy_wallmounted = true,
--sounds = default.node_sound_defaults(),
on_construct = function(pos)
@ -132,35 +132,27 @@ minetest.register_craft({
}
})
minetest.register_craft({
output = "hiking:"..colour.."_arrow_left",
recipe = {
{"dye:"..colour,"hiking:"..colour.."_sign"}
}
})
minetest.register_craft({
output = "hiking:illuminated_"..colour.."_sign",
type = "shapeless",
type = "shapeless",
recipe = { "default:torch", "hiking:"..colour.."_sign" }
})
minetest.register_craft({
output = "hiking:illuminated_"..colour.."_arrow_left",
type = "shapeless",
type = "shapeless",
recipe = { "default:torch", "hiking:"..colour.."_arrow_left" }
})
minetest.register_craft({
output = "hiking:illuminated_"..colour.."_arrow_right",
type = "shapeless",
type = "shapeless",
recipe = { "default:torch", "hiking:"..colour.."_arrow_right" }
})
end
local hiking_pole_common = {
groups = {snappy=1, oddly_breakable_by_hand=2, },
--sounds = default.node_sound_stone_defaults(),
paramtype = "light",
sunlight_propagates = true,
@ -171,17 +163,22 @@ local hiking_pole_common = {
},
}
local hiking_pole_bottom = merge(hiking_pole_common, {
buildable_to = true,
buildable_to = true,
groups = {snappy=1, oddly_breakable_by_hand=2, not_in_creative_inventory=0},
})
local hiking_pole_middle = merge(hiking_pole_common, {
buildable_to = false,
buildable_to = false,
groups = {snappy=1, oddly_breakable_by_hand=2, not_in_creative_inventory=1},
})
local hiking_pole_top = merge(hiking_pole_common, {
buildable_to = false,
buildable_to = false,
groups = {snappy=1, oddly_breakable_by_hand=2, not_in_creative_inventory=1},
})
local function mk_hiking_pole(id, name, top_face, moreprops, image)
minetest.register_node("hiking:"..id.."_bottom", merge(merge(hiking_pole_bottom, {
local ntop = "hiking:"..id.."_top"
local nbottom = "hiking:"..id.."_bottom"
minetest.register_node(nbottom, merge(merge(hiking_pole_bottom, {
-- TODO: this should be always on ground
description = name.." (bottom)",
tiles = {"hiking_pole_sign_cap.png", "hiking_pole_sign_cap.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", },
@ -191,7 +188,7 @@ minetest.register_node("hiking:"..id.."_bottom", merge(merge(hiking_pole_bottom,
after_place_node = function(pos, placer, itemstack)
local node = minetest.env:get_node(pos)
local p = {x=pos.x, y=pos.y+1, z=pos.z}
node.name = "hiking:"..id.."_top"
node.name = ntop
if minetest.registered_nodes[minetest.env:get_node(p).name].buildable_to then
minetest.env:set_node(p, node)
else
@ -202,31 +199,54 @@ minetest.register_node("hiking:"..id.."_bottom", merge(merge(hiking_pole_bottom,
after_destruct = function(pos, _)
local p = {x=pos.x, y=pos.y+1, z=pos.z}
if ( minetest.env:get_node(p).name == "hiking:"..id.."_top" ) then
if ( minetest.env:get_node(p).name == ntop ) then
minetest.env:remove_node(p)
end
end,
}), moreprops))
minetest.register_node("hiking:"..id.."_top", merge(merge(hiking_pole_bottom, {
minetest.register_node(ntop, merge(merge(hiking_pole_top, {
-- TODO: one should not build on top of this
-- TODO: should be always on top of pole_bottom
description = name.." (top)",
tiles = {"hiking_pole_sign_cap.png", "hiking_pole_sign_cap.png", top_face, top_face, top_face, top_face, },
on_dig = function(pos, _, _)
on_dig = function(pos, _, digger)
local p = {x=pos.x, y=pos.y-1, z=pos.z}
if ( minetest.env:get_node(p).name == "hiking:"..id.."_bottom" ) then
minetest.env:remove_node(p)
local n = minetest.env:get_node(p)
local nn = n.name
if ( nn == nbottom ) then
minetest.node_dig(p, n, digger)
else
minetest.log('error', "WARNING: top of hiking pole at "..minetest.pos_to_string(pos).." found on top of '"..nn.."'? This should not happen!")
minetest.env:remove_node(pos)
end
end,
end,
}), moreprops))
end
local function mk_tall_hiking_pole(id, name, top_face, moreprops, image, height)
local h = math.max(height, 2)
minetest.register_node("hiking:"..id.."_bottom", merge(merge(hiking_pole_bottom, {
local ntop = "hiking:"..id.."_top"
local nmiddle = "hiking:"..id.."_middle"
local nbottom = "hiking:"..id.."_bottom"
local function rm_tall_hiking_pole(pos)
local i
local p = {x=pos.x, y=pos.y, z=pos.z}
local nn
for i = 1, h-1 do
nn = minetest.env:get_node(p).name
if ( nn == ntop or nn == nmiddle ) then
minetest.env:remove_node(p)
if ( nn == ntop ) then return end
p.y = p.y + 1
else
return
end
end
end
minetest.register_node(nbottom, merge(merge(hiking_pole_bottom, {
-- TODO: this should be always on ground
description = name.." (bottom)",
tiles = {"hiking_pole_sign_cap.png", "hiking_pole_sign_cap.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", },
@ -246,7 +266,7 @@ minetest.register_node("hiking:"..id.."_bottom", merge(merge(hiking_pole_bottom,
end
for i = 1, h-2 do
p = {x=pos.x, y=pos.y+i, z=pos.z}
node.name = "hiking:"..id.."_middle"
node.name = nmiddle
if minetest.registered_nodes[minetest.env:get_node(p).name].buildable_to then
minetest.env:set_node(p, node)
else
@ -255,7 +275,7 @@ minetest.register_node("hiking:"..id.."_bottom", merge(merge(hiking_pole_bottom,
end
end
p = {x=pos.x, y=pos.y+h-1, z=pos.z}
node.name = "hiking:"..id.."_top"
node.name = ntop
if minetest.registered_nodes[minetest.env:get_node(p).name].buildable_to then
minetest.env:set_node(p, node)
else
@ -267,9 +287,11 @@ minetest.register_node("hiking:"..id.."_bottom", merge(merge(hiking_pole_bottom,
after_destruct = function(pos, _)
local i
local p
local nn
for i = 1, h-1 do
p = {x=pos.x, y=pos.y+i, z=pos.z}
if ( minetest.env:get_node(p).name == "hiking:"..id.."_top" or minetest.env:get_node(p).name == "hiking:"..id.."_middle" ) then
nn = minetest.env:get_node(p).name
if ( nn == ntop or nn == nmiddle ) then
minetest.env:remove_node(p)
else
return
@ -279,50 +301,57 @@ minetest.register_node("hiking:"..id.."_bottom", merge(merge(hiking_pole_bottom,
}), moreprops))
minetest.register_node("hiking:"..id.."_middle", merge(merge(hiking_pole_middle, {
minetest.register_node(nmiddle, merge(merge(hiking_pole_middle, {
-- TODO: one should not build on top of this
-- TODO: should be always on top of pole_bottom
description = name.." (middle)",
tiles = {"hiking_pole_sign_cap.png", "hiking_pole_sign_cap.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", "hiking_pole_sign_bottom_.png", },
on_dig = function(pos, _, _)
on_dig = function(pos, _, digger)
local i
local p
local n
local nn
for i = 1, h-2 do
p = {x=pos.x, y=pos.y-i, z=pos.z}
local n = minetest.env:get_node(p).name
if ( n == "hiking:"..id.."_bottom" ) then
minetest.env:remove_node(p)
n = minetest.env:get_node(p)
nn = n.name
if ( nn == nbottom ) then
minetest.node_dig(p, n, digger)
return
elseif not ( n == "hiking:"..id.."_middle" ) then
-- TODO: ERROR!
elseif not ( nn == nmiddle ) then
minetest.log('error', "WARNING: middle of hiking pole at "..minetest.pos_to_string(pos).." found on top of '"..nn.."'? This should not happen!")
rm_tall_hiking_pole({x=p.x, y=p.y+i, z=p.z})
return
end
end
end,
end,
}), moreprops))
minetest.register_node("hiking:"..id.."_top", merge(merge(hiking_pole_bottom, {
minetest.register_node(ntop, merge(merge(hiking_pole_top, {
-- TODO: one should not build on top of this
-- TODO: should be always on top of pole_bottom
description = name.." (top)",
tiles = {"hiking_pole_sign_cap.png", "hiking_pole_sign_cap.png", top_face, top_face, top_face, top_face, },
on_dig = function(pos, _, _)
on_dig = function(pos, _, digger)
local i
local p
local n
local nn
for i = 1, h-1 do
p = {x=pos.x, y=pos.y-i, z=pos.z}
local n = minetest.env:get_node(p).name
if ( n == "hiking:"..id.."_bottom" ) then
minetest.env:remove_node(p)
n = minetest.env:get_node(p)
nn = n.name
if ( nn == nbottom ) then
minetest.node_dig(p, n, digger)
return
elseif not ( n == "hiking:"..id.."_middle" ) then
-- TODO: ERROR!
elseif not ( nn == nmiddle ) then
minetest.log('error', "WARNING: top of hiking pole at "..minetest.pos_to_string(pos).." found on top of '"..nn.."'? This should not happen!")
rm_tall_hiking_pole({x=p.x, y=p.y+i, z=p.z})
return
end
end
end,
end,
}), moreprops))
end
@ -338,7 +367,7 @@ local function mk_hiking_pole_coloured(colour)
})
minetest.register_craft({
output = "hiking:"..colour.."_pole_bottom",
type = "shapeless",
type = "shapeless",
recipe = { "hiking:pole_bottom", "hiking:"..colour.."_sign" }
})
end
@ -347,17 +376,17 @@ local function mk_hiking_pole_illuminated_coloured(colour)
mk_hiking_pole("illuminated_"..colour.."_pole", "Illuminated pole sign "..colour, "hiking_pole_sign_top_"..colour..".png", illuminated_props, "hiking_illuminated_pole_sign_"..colour..".png")
minetest.register_craft({
output = "hiking:illuminated_"..colour.."_pole_bottom",
type = "shapeless",
type = "shapeless",
recipe = { "default:torch", "hiking:"..colour.."_pole_bottom" }
})
minetest.register_craft({
output = "hiking:illuminated_"..colour.."_pole_bottom",
type = "shapeless",
type = "shapeless",
recipe = { "hiking:pole_bottom", "hiking:illuminated_"..colour.."_sign" }
})
minetest.register_craft({
output = "hiking:illuminated_"..colour.."_pole_bottom",
type = "shapeless",
type = "shapeless",
recipe = { "hiking:illuminated_pole_bottom", "hiking:"..colour.."_sign" }
})
end

View File

@ -1,22 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

215
mods/hud/.gitignore vendored
View File

@ -1,215 +0,0 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg

View File

@ -1,13 +1,18 @@
function hud.register(name, def)
hud.register(name, def)
-- name: statbar name (health, air, hunger, armor already used by default)
-- def: <HUD item definition> (see below)
hud.change_item(player, name, def)
-- player: player object
-- name: statbar name (health, air, hunger, armor already used by default)
-- name: statbar name
-- def: table containing new values
-- currently supported: number, text and offset
hud.swap_statbar(player, name1, name2) -- swaps position and offset of statbar with name1 with statbar with name2
-- player: player object
-- name1: statbar name
-- name2: statbar name
hud.remove_item(player, name)
HUD item definition

View File

@ -1,6 +1,6 @@
Minetest mod "Better HUD"
=========================
Version: 2.1.2
Version: 2.1.3
(c) Copyright BlockMen (2013-2015)

View File

@ -66,6 +66,55 @@ function hud.register(name, def)
return true
end
-- swaps stabar positions
function hud.swap_statbar(player, item1, item2)
if not player or not item1 or not item2 then
throw_error("Not enough parameters given to swap statbars")
return false
end
local def1 = items[item1] or nil
local def2 = items[item2] or nil
if not def1 or not def2 then
throw_error("Can't swap statbars. Given statbars are not correct")
return false
end
local pos_swap = false
local p_name = player:get_player_name()
local elem1 = hud_id[p_name.."_"..item1]
local elem2 = hud_id[p_name.."_"..item2]
player:hud_change(elem2.id, "offset", def1.offset)
player:hud_change(elem1.id, "offset", def2.offset)
if def1.position.x ~= def2.position.x or def1.position.y ~= def2.position.y then
player:hud_change(elem2.id, "position", def1.position)
player:hud_change(elem1.id, "position", def2.position)
pos_swap = true
end
-- do the items have backgrounds? if so, swap them aswell
local bg1 = hud_id[p_name.."_"..item1.."_bg"] or nil
local bg2 = hud_id[p_name.."_"..item2.."_bg"] or nil
if bg1 ~= nil and bg1.id then
player:hud_change(bg1.id, "offset", def2.offset)
if pos_swap == true then
player:hud_change(bg1.id, "position", def2.position)
end
end
if bg2 ~= nil and bg2.id then
player:hud_change(bg2.id, "offset", def1.offset)
if pos_swap == true then
player:hud_change(bg2.id, "position", def1.position)
end
end
return true
end
function hud.change_item(player, name, def)
if not player or not player:is_player() or not name or not def then
throw_error("Not enough parameters given to change HUD item")
@ -106,6 +155,7 @@ function hud.change_item(player, name, def)
if bg and bg.max and bg.max < 1 and def.max and def.max > bg.max then
player:hud_change(bg.id, "number", def.max)
bg.max = def.max
bg.number = def.max
end
end
end
@ -119,27 +169,9 @@ function hud.change_item(player, name, def)
if def.offset and elem.offset then
if def.item_name and def.offset == "item" then
local i_name2 = player:get_player_name().."_"..def.item_name
local elem2 = hud_id[i_name2]
if elem2 then
local p2 = elem2.offset
local p1 = elem.offset
player:hud_change(elem2.id, "offset", p1)
player:hud_change(elem.id, "offset", p2)
elem2.offset = p1
elem.offset = p2
if elem.background then
local elem3 = hud_id[i_name.."_bg"]
if elem3 and elem3.offset then
player:hud_change(elem3.id, "offset", p2)
elem3.offset = p2
local elem4 = hud_id[i_name2.."_bg"]
if elem4 and elem4.offset then
player:hud_change(elem4.id, "offset", p1)
elem4.offset = p1
end
end
end
-- for legacy reasons
if def.item_name then
hud.swap_statbar(player, name, def.item_name)
end
else
player:hud_change(elem.id, "offset", def.offset)
@ -190,7 +222,7 @@ minetest.register_on_joinplayer(function(player)
hud_flags.breathbar = false
player:hud_set_flags(hud_flags)
-- now add the backgrounds (e.g. for statbars)
-- now add the backgrounds for statbars
for _,item in pairs(sb_bg) do
add_hud_item(player, _.."_bg", item)
end

View File

@ -44,70 +44,70 @@ end
if damage_enabled then
hud.register("health", {
hud_elem_type = "statbar",
position = HUD_HEALTH_POS,
size = HUD_SB_SIZE,
text = "hud_heart_fg.png",
number = 20,
alignment = {x = -1, y = -1},
offset = HUD_HEALTH_OFFSET,
background = "hud_heart_bg.png",
events = {
{
type = "damage",
func = function(player)
hud.change_item(player, "health", {number = player:get_hp()})
end
}
},
hud_elem_type = "statbar",
position = HUD_HEALTH_POS,
size = HUD_SB_SIZE,
text = "hud_heart_fg.png",
number = 20,
alignment = {x = -1, y = -1},
offset = HUD_HEALTH_OFFSET,
background = "hud_heart_bg.png",
events = {
{
type = "damage",
func = function(player)
hud.change_item(player, "health", {number = player:get_hp()})
end
}
},
})
hud.register("air", {
hud_elem_type = "statbar",
position = HUD_AIR_POS,
size = HUD_SB_SIZE,
text = "hud_air_fg.png",
number = 0,
alignment = {x = -1, y = -1},
offset = HUD_AIR_OFFSET,
background = nil,
events = {
{
type = "breath",
func = function(player)
local air = player:get_breath()
if air > 10 then
air = 0
hud_elem_type = "statbar",
position = HUD_AIR_POS,
size = HUD_SB_SIZE,
text = "hud_air_fg.png",
number = 0,
alignment = {x = -1, y = -1},
offset = HUD_AIR_OFFSET,
background = nil,
events = {
{
type = "breath",
func = function(player)
local air = player:get_breath()
if air > 10 then
air = 0
end
hud.change_item(player, "air", {number = air * 2})
end
hud.change_item(player, "air", {number = air * 2})
end
}
},
}
},
})
hud.register("armor", {
hud_elem_type = "statbar",
position = HUD_ARMOR_POS,
size = HUD_SB_SIZE,
text = "hud_armor_fg.png",
number = 0,
alignment = {x = -1, y = -1},
offset = HUD_ARMOR_OFFSET,
background = "hud_armor_bg.png",
autohide_bg = true,
max = 20,
hud_elem_type = "statbar",
position = HUD_ARMOR_POS,
size = HUD_SB_SIZE,
text = "hud_armor_fg.png",
number = 0,
alignment = {x = -1, y = -1},
offset = HUD_ARMOR_OFFSET,
background = "hud_armor_bg.png",
autohide_bg = true,
max = 20,
})
hud.register("hunger", {
hud_elem_type = "statbar",
position = HUD_HUNGER_POS,
size = HUD_SB_SIZE,
text = "hud_hunger_fg.png",
number = 0,
alignment = {x = -1, y = -1},
offset = HUD_HUNGER_OFFSET,
background = "hud_hunger_bg.png",
max = 0,
hud_elem_type = "statbar",
position = HUD_HUNGER_POS,
size = HUD_SB_SIZE,
text = "hud_hunger_fg.png",
number = 0,
alignment = {x = -1, y = -1},
offset = HUD_HUNGER_OFFSET,
background = "hud_hunger_bg.png",
max = 0,
})
else
hud.show_armor = false

View File

@ -1,3 +1,8 @@
2.1.3
-----
- Added hud.swap_statbar() and fix wrong behavior of previous workaround
- Fixed missing background of some statbars in multiplayer
2.1.2
-----
- Fixed crash caused by animated nodes (reported by Krock)

View File

@ -1,6 +1,6 @@
Minetest mod "Hunger"
=====================
Version: 1.0
Version: 1.1
(c) Copyright BlockMen (2015)
@ -19,6 +19,12 @@ Information:
This mod depends on the "Better HUD" mod (https://github.com/BlockMen/hud) to provide information about your current saturation.
For Modders:
~~~~~~~~~~~~
This mod alters the behavior of minetest.item_eat().
All callbacks that are registered via minetest.register_on_item_eat() are called AFTER this mod actions, so the itemstack
will have changed already when callbacks are called. You can get the original itemstack as 6th parameter of your function then.
License:
~~~~~~~~
(c) Copyright BlockMen (2015)

View File

@ -4,3 +4,12 @@
- Added API to register food
- Added eating sounds
- Hungerbar image changes when poisend
1.1
---
- Fixed healing after death
- Fixed healing while drowning
- Fixed crashed caused by Pipeworks mod
- Added wrapper for minetest.item_eat(). see Readme.txt for more informations
- Updated HUD-API usage
- Added beans of Farming Redo

View File

@ -253,6 +253,7 @@ if minetest.get_modpath("farming") and farming.mod == "redo" then
end
register_food("farming:rhubarb", 1)
register_food("farming:rhubarb_pie", 6)
register_food("farming:beans", 1)
end
if minetest.get_modpath("kpgmobs") ~= nil then

View File

@ -65,6 +65,10 @@ function hunger.handle_node_actions(pos, oldnode, player, ext)
return
end
local name = player:get_player_name()
if not name or not hunger[name] then
return
end
local exhaus = hunger[name].exhaus
if not exhaus then
hunger[name].exhaus = 0
@ -96,12 +100,13 @@ function hunger.handle_node_actions(pos, oldnode, player, ext)
hunger[name].exhaus = exhaus
end
-- Time based hunger functions
if minetest.setting_getbool("enable_damage") then
local hunger_timer = 0
local health_timer = 0
local action_timer = 0
minetest.register_globalstep(function(dtime)
local hunger_timer = 0
local health_timer = 0
local action_timer = 0
local function hunger_globaltimer(dtime)
hunger_timer = hunger_timer + dtime
health_timer = health_timer + dtime
action_timer = action_timer + dtime
@ -141,8 +146,8 @@ if minetest.setting_getbool("enable_damage") then
local air = player:get_breath() or 0
local hp = player:get_hp()
-- heal player by 1 hp if not dead and saturation is > 15 (of 30)
if tonumber(tab.lvl) > HUNGER_HEAL_LVL and air > 0 then
-- heal player by 1 hp if not dead and saturation is > 15 (of 30) player is not drowning
if tonumber(tab.lvl) > HUNGER_HEAL_LVL and hp > 0 and air > 0 then
player:set_hp(hp + HUNGER_HEAL)
end
@ -155,7 +160,10 @@ if minetest.setting_getbool("enable_damage") then
health_timer = 0
end
end)
end
if minetest.setting_getbool("enable_damage") then
minetest.register_globalstep(hunger_globaltimer)
end
@ -166,9 +174,9 @@ function hunger.register_food(name, hunger_change, replace_with_item, poisen, he
food[name] = {}
food[name].saturation = hunger_change -- hunger points added
food[name].replace = replace_with_item -- what item is given back after eating
food[name].poisen = poisen -- time its poisening
food[name].healing = heal -- amount of HP
food[name].sound = sound -- special sound that is played when eating
food[name].poisen = poisen -- time its poisening
food[name].healing = heal -- amount of HP
food[name].sound = sound -- special sound that is played when eating
end
-- Poison player
@ -185,6 +193,20 @@ local function poisenp(tick, time, time_left, player)
end
end
-- wrapper for minetest.item_eat (this way we make sure other mods can't break this one)
local org_eat = core.do_item_eat
core.do_item_eat = function(hp_change, replace_with_item, itemstack, user, pointed_thing)
local old_itemstack = itemstack
itemstack = hunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
for _, callback in pairs(core.registered_on_item_eats) do
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing, old_itemstack)
if result then
return result
end
end
return itemstack
end
function hunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
local item = itemstack:get_name()
local def = food[item]
@ -228,7 +250,20 @@ function hunger.item_eat(hunger_change, replace_with_item, poisen, heal, sound)
end
minetest.sound_play(sound, {to_player = name, gain = 0.7})
itemstack:add_item(replace_with_item)
if replace_with_item then
if itemstack:is_empty() then
itemstack:add_item(replace_with_item)
else
local inv = user:get_inventory()
if inv:room_for_item("main", {name=replace_with_item}) then
inv:add_item("main", replace_with_item)
else
local pos = user:getpos()
pos.y = math.floor(pos.y + 0.5)
core.add_item(pos, replace_with_item)
end
end
end
end
return itemstack

View File

@ -1,7 +1,7 @@
hunger = {}
hunger.food = {}
HUNGER_TICK = 800 -- time in seconds after that 1 hunger point is taken
HUNGER_TICK = 800 -- time in seconds after that 1 hunger point is taken
HUNGER_HEALTH_TICK = 4 -- time in seconds after player gets healed/damaged
HUNGER_MOVE_TICK = 0.5 -- time in seconds after the movement is checked
@ -10,12 +10,12 @@ HUNGER_EXHAUST_PLACE = 1 -- exhaustion increased this value after placed
HUNGER_EXHAUST_MOVE = 1.5 -- exhaustion increased this value if player movement detected
HUNGER_EXHAUST_LVL = 160 -- at what exhaustion player saturation gets lowered
HUNGER_HEAL = 1 -- number of HP player gets healed after HUNGER_HEALTH_TICK
HUNGER_HEAL = 1 -- number of HP player gets healed after HUNGER_HEALTH_TICK
HUNGER_HEAL_LVL = 15 -- lower level of saturation needed to get healed
HUNGER_STARVE = 1 -- number of HP player gets damaged by hunger after HUNGER_HEALTH_TICK
HUNGER_STARVE = 1 -- number of HP player gets damaged by hunger after HUNGER_HEALTH_TICK
HUNGER_STARVE_LVL = 3 -- level of staturation that causes starving
HUNGER_MAX = 30 -- maximum level of saturation
HUNGER_MAX = 30 -- maximum level of saturation
local modpath = minetest.get_modpath("hunger")
@ -39,7 +39,7 @@ if minetest.setting_getbool("enable_damage") then
lvl = 20
end
minetest.after(0.8, function()
hud.change_item(player, "hunger", {offset = "item", item_name = "air"})
hud.swap_statbar(player, "hunger", "air")
hud.change_item(player, "hunger", {number = lvl, max = 20})
end)
end)
@ -47,7 +47,6 @@ if minetest.setting_getbool("enable_damage") then
-- for exhaustion
minetest.register_on_placenode(hunger.handle_node_actions)
minetest.register_on_dignode(hunger.handle_node_actions)
minetest.register_on_item_eat(hunger.eat)
minetest.register_on_respawnplayer(function(player)
hunger.update_hunger(player, 20)
end)

View File

@ -0,0 +1,42 @@
# mobs_goblins
-= MOBS_GOBLINS-MOD for MINETEST =-
by FreeLikeGNU
https://forum.minetest.net/viewtopic.php?f=9&t=13004
https://github.com/FreeLikeGNU/mobs_goblins
based on MOBS-MOD by PilzAdam, KrupnovPavel, Zeg9, TenPlus1
https://forum.minetest.net/viewtopic.php?f=9&t=9917
This mod adds several Goblins to Minetest that should spawn near ore deposits or lairs underground.
v0.05 Fix errors in .04, remove texture names from goblin model, and add cobble goblins to build goblin lairs.
v0.04 Thieving goblins!
v0.03 This is a test version that adds a goblin king! Thanks to Napiophelios! Some more texture refinement and fixed naming of textures.
v0.02 This is a test version and some the goblins will not attack unless attacked. Variety varies with ore...
v0.01 This is a test version and all the goblins act like an NPC and will not attack unless attacked.
License of Media Files:
---------------------------------------
goblins_goblin.b3d and goblins_goblin.blend
by FreeLikeGNU Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) by FreeLikeGNU
http://creativecommons.org/licenses/by-sa/3.0/
above meshes based on character from minetest_game
by MirceaKitsune (WTFPL)
https://github.com/minetest/minetest_game/blob/master/mods/default/README.txt#L71
goblins_goblins*.png files and goblins_goblin.xcf files
by FreeLikeGNU Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
http://creativecommons.org/licenses/by-sa/3.0/
Thanks to Napiophelios for the goblin king skin
https://forum.minetest.net/viewtopic.php?f=9&t=13004#p186921
goblins_goblin_king.png
License: Creative Commons CC-BY-SA-3.0 SummerFeilds TP

1696
mods/mobs_goblins/api.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
{
"name": "mobs_goblins",
"description": "goblins for minetest",
"keywords": [
"mobs_goblins"
],
"homepage": "https://github.com/FreeLikeGNU/mobs_goblins",
"screenshots": [
"https://cloud.githubusercontent.com/assets/51875/9214313/50cbf752-40db-11e5-8661-ce8be773bc92.png"
],
"authors": [
"FreeLikeGNU"
],
"license": "CC-BY-SA-3.0"
}

View File

@ -0,0 +1,658 @@
-- Npc by TenPlus1 converted for FLG Goblins :D
mobs_goblins.goblin_drops = {
"default:pick_steel", "default:sword_steel",
"default:shovel_steel", "farming:bread", "bucket:bucket_water"
}
mobs_goblins:register_mob("mobs_goblins:goblin_cobble", {
description = "Cobble Goblin",
type = "animal",
passive = false,
damage = 1,
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 5,
hp_max = 10,
armor = 100,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.0,0.35},
visual = "mesh",
mesh = "goblins_goblin.b3d",
drawtype = "front",
textures = {
{"goblins_goblin_cobble1.png"},
{"goblins_goblin_cobble2.png"},
},
makes_footstep_sound = true,
sounds = {
random = "mobs_pig",
attack = "mobs_pig_angry",
},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "default:mossycobble",
chance = 1, min = 1, max = 3},
{name = "default:apple",
chance = 2, min = 1, max = 2},
{name = "default:torch",
chance = 3, min = 1, max = 10},
},
water_damage = 0,
lava_damage = 2,
light_damage = 0,
follow = {"default:diamond"},
replace_rate = 30,
replace_what = {"default:stone","default:desert_stone",},
replace_with = "default:mossycobble",
replace_offset = 1,
view_range = 15,
owner = "",
order = "follow",
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = function(self, clicker)
local item = clicker:get_wielded_item()
local name = clicker:get_player_name()
-- feed to heal goblin
if item:get_name() == "default:apple"
or item:get_name() == "farming:bread" then
local hp = self.object:get_hp()
-- return if full health
if hp >= self.hp_max then
minetest.chat_send_player(name, "goblin at full health.")
return
end
hp = hp + 4
if hp > self.hp_max then hp = self.hp_max end
self.object:set_hp(hp)
-- take item
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
-- right clicking with gold lump drops random item from mobs_goblins.goblin_drops
elseif item:get_name() == "default:gold_lump" then
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
local pos = self.object:getpos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = mobs_goblins.goblin_drops[math.random(1, #mobs_goblins.goblin_drops)]})
else
-- if owner switch between follow and stand
if self.owner and self.owner == clicker:get_player_name() then
if self.order == "follow" then
self.order = "stand"
else
self.order = "follow"
end
-- else
-- self.owner = clicker:get_player_name()
end
end
mobs_goblins:capture_mob(self, clicker, 0, 5, 80, false, nil)
end,
})
mobs_goblins:register_mob("mobs_goblins:goblin_coal", {
description = "Coal Goblin",
type = "animal",
passive = false,
damage = 1,
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 5,
hp_max = 10,
armor = 100,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.0,0.35},
visual = "mesh",
mesh = "goblins_goblin.b3d",
drawtype = "front",
textures = {
{"goblins_goblin_coal1.png"},
{"goblins_goblin_coal2.png"},
},
makes_footstep_sound = true,
sounds = {
random = "mobs_pig",
attack = "mobs_pig_angry",
},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "default:coal_lump",
chance = 1, min = 1, max = 3},
{name = "default:apple",
chance = 2, min = 1, max = 2},
{name = "default:torch",
chance = 3, min = 1, max = 10},
},
water_damage = 0,
lava_damage = 2,
light_damage = 0,
follow = {"default:diamond"},
replace_rate = 50,
replace_what = {"default:torch",},
replace_with = "air",
replace_offset = 2,
view_range = 15,
owner = "",
order = "follow",
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = function(self, clicker)
local item = clicker:get_wielded_item()
local name = clicker:get_player_name()
-- feed to heal goblin
if item:get_name() == "default:apple"
or item:get_name() == "farming:bread" then
local hp = self.object:get_hp()
-- return if full health
if hp >= self.hp_max then
minetest.chat_send_player(name, "goblin at full health.")
return
end
hp = hp + 4
if hp > self.hp_max then hp = self.hp_max end
self.object:set_hp(hp)
-- take item
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
-- right clicking with gold lump drops random item from mobs_goblins.goblin_drops
elseif item:get_name() == "default:gold_lump" then
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
local pos = self.object:getpos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = mobs_goblins.goblin_drops[math.random(1, #mobs_goblins.goblin_drops)]})
else
-- if owner switch between follow and stand
if self.owner and self.owner == clicker:get_player_name() then
if self.order == "follow" then
self.order = "stand"
else
self.order = "follow"
end
-- else
-- self.owner = clicker:get_player_name()
end
end
mobs_goblins:capture_mob(self, clicker, 0, 5, 80, false, nil)
end,
})
mobs_goblins:register_mob("mobs_goblins:goblin_iron", {
description = "Iron Goblin",
type = "animal",
passive = false,
damage = 2,
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 10,
hp_max = 20,
armor = 100,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.0,0.35},
visual = "mesh",
mesh = "goblins_goblin.b3d",
drawtype = "front",
textures = {
{"goblins_goblin_iron1.png"},
{"goblins_goblin_iron2.png"},
},
makes_footstep_sound = true,
sounds = {
random = "mobs_pig",
attack = "mobs_pig_angry",
},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "default:iron_lump",
chance = 1, min = 1, max = 3},
{name = "default:apple",
chance = 2, min = 1, max = 2},
{name = "default:pick_steel",
chance = 5, min = 1, max = 1},
},
water_damage = 0,
lava_damage = 2,
light_damage = 0,
follow = "default:diamond",
replace_rate = 50,
replace_what = {"default:torch",},
replace_with = "air",
replace_offset = 2,
view_range = 15,
owner = "",
order = "follow",
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = function(self, clicker)
local item = clicker:get_wielded_item()
local name = clicker:get_player_name()
-- feed to heal goblin
if item:get_name() == "default:apple"
or item:get_name() == "farming:bread" then
local hp = self.object:get_hp()
-- return if full health
if hp >= self.hp_max then
minetest.chat_send_player(name, "goblin at full health.")
return
end
hp = hp + 4
if hp > self.hp_max then hp = self.hp_max end
self.object:set_hp(hp)
-- take item
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
-- right clicking with gold lump drops random item from mobs_goblins.goblin_drops
elseif item:get_name() == "default:gold_lump" then
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
local pos = self.object:getpos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = mobs_goblins.goblin_drops[math.random(1, #mobs_goblins.goblin_drops)]})
else
-- if owner switch between follow and stand
if self.owner and self.owner == clicker:get_player_name() then
if self.order == "follow" then
self.order = "stand"
else
self.order = "follow"
end
-- else
-- self.owner = clicker:get_player_name()
end
end
mobs_goblins:capture_mob(self, clicker, 0, 5, 80, false, nil)
end,
})
mobs_goblins:register_mob("mobs_goblins:goblin_gold", {
description = "Gold Goblin",
type = "monster",
passive = false,
damage = 3,
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 10,
hp_max = 30,
armor = 100,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.0,0.35},
visual = "mesh",
mesh = "goblins_goblin.b3d",
drawtype = "front",
textures = {
{"goblins_goblin_gold1.png"},
{"goblins_goblin_gold2.png"},
},
makes_footstep_sound = true,
sounds = {
random = "mobs_pig",
attack = "mobs_pig_angry",
},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "default:gold_lump",
chance = 1, min = 1, max = 3},
{name = "default:apple",
chance = 2, min = 1, max = 2},
{name = "default:gold_ingot",
chance = 5, min = 1, max = 1},
},
water_damage = 0,
lava_damage = 2,
light_damage = 0,
follow = "default:diamond",
replace_rate = 50,
replace_what = {"default:torch",},
replace_with = "air",
replace_offset = 2,
view_range = 15,
owner = "",
order = "follow",
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = function(self, clicker)
local item = clicker:get_wielded_item()
local name = clicker:get_player_name()
-- feed to heal goblin
if item:get_name() == "default:apple"
or item:get_name() == "farming:bread" then
local hp = self.object:get_hp()
-- return if full health
if hp >= self.hp_max then
minetest.chat_send_player(name, "goblin at full health.")
return
end
hp = hp + 4
if hp > self.hp_max then hp = self.hp_max end
self.object:set_hp(hp)
-- take item
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
-- right clicking with gold lump drops random item from mobs_goblins.goblin_drops
elseif item:get_name() == "default:gold_lump" then
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
local pos = self.object:getpos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = mobs_goblins.goblin_drops[math.random(1, #mobs_goblins.goblin_drops)]})
else
-- if owner switch between follow and stand
if self.owner and self.owner == clicker:get_player_name() then
if self.order == "follow" then
self.order = "stand"
else
self.order = "follow"
end
-- else
-- self.owner = clicker:get_player_name()
end
end
mobs_goblins:capture_mob(self, clicker, 0, 5, 80, false, nil)
end,
})
mobs_goblins:register_mob("mobs_goblins:goblin_diamond", {
description = "Diamond Goblin",
type = "animal",
passive = false,
damage = 3,
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 20,
hp_max = 30,
armor = 100,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.0,0.35},
visual = "mesh",
mesh = "goblins_goblin.b3d",
drawtype = "front",
textures = {
{"goblins_goblin_diamond1.png"},
{"goblins_goblin_diamond2.png"},
},
makes_footstep_sound = true,
sounds = {
random = "mobs_pig",
attack = "mobs_pig_angry",
},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "default:pick_diamond",
chance = 1, min = 1, max = 1},
{name = "default:apple",
chance = 2, min = 1, max = 10},
{name = "default:diamond",
chance = 5, min = 1, max = 1},
},
water_damage = 0,
lava_damage = 2,
light_damage = 0,
follow = "default:diamond",
replace_rate = 50,
replace_what = {"default:torch",},
replace_with = "air",
replace_offset = 2,
view_range = 15,
owner = "",
order = "follow",
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = function(self, clicker)
local item = clicker:get_wielded_item()
local name = clicker:get_player_name()
-- feed to heal goblin
if item:get_name() == "default:apple"
or item:get_name() == "farming:bread" then
local hp = self.object:get_hp()
-- return if full health
if hp >= self.hp_max then
minetest.chat_send_player(name, "goblin at full health.")
return
end
hp = hp + 4
if hp > self.hp_max then hp = self.hp_max end
self.object:set_hp(hp)
-- take item
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
-- right clicking with gold lump drops random item from mobs_goblins.goblin_drops
elseif item:get_name() == "default:gold_lump" then
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
local pos = self.object:getpos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = mobs_goblins.goblin_drops[math.random(1, #mobs_goblins.goblin_drops)]})
else
-- if owner switch between follow and stand
if self.owner and self.owner == clicker:get_player_name() then
if self.order == "follow" then
self.order = "stand"
else
self.order = "follow"
end
-- else
-- self.owner = clicker:get_player_name()
end
end
mobs_goblins:capture_mob(self, clicker, 0, 5, 80, false, nil)
end,
})
mobs_goblins:register_mob("mobs_goblins:goblin_king", {
description = "Goblin King",
type = "monster",
passive = false,
damage = 4,
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 20,
hp_max = 40,
armor = 100,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.0,0.35},
visual = "mesh",
mesh = "goblins_goblin.b3d",
drawtype = "front",
textures = {
{"goblins_goblin_king.png"},
},
makes_footstep_sound = true,
sounds = {
random = "mobs_pig",
attack = "mobs_pig_angry",
},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "default:pick_mese",
chance = 1, min = 1, max = 1},
{name = "default:apple",
chance = 2, min = 1, max = 10},
{name = "default:mese_crystal",
chance = 5, min = 1, max = 1},
},
water_damage = 0,
lava_damage = 2,
light_damage = 0,
follow = "default:diamond",
replace_rate = 50,
replace_what = {"default:torch",},
replace_with = "air",
replace_offset = -1,
view_range = 15,
owner = "",
order = "follow",
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = function(self, clicker)
local item = clicker:get_wielded_item()
local name = clicker:get_player_name()
-- feed to heal goblin
if item:get_name() == "default:apple"
or item:get_name() == "farming:bread" then
local hp = self.object:get_hp()
-- return if full health
if hp >= self.hp_max then
minetest.chat_send_player(name, "goblin at full health.")
return
end
hp = hp + 4
if hp > self.hp_max then hp = self.hp_max end
self.object:set_hp(hp)
-- take item
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
-- right clicking with gold lump drops random item from mobs_goblins.goblin_drops
elseif item:get_name() == "default:gold_lump" then
if not minetest.setting_getbool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
local pos = self.object:getpos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = mobs_goblins.goblin_drops[math.random(1, #mobs_goblins.goblin_drops)]})
else
-- if owner switch between follow and stand
if self.owner and self.owner == clicker:get_player_name() then
if self.order == "follow" then
self.order = "stand"
else
self.order = "follow"
end
-- else
-- self.owner = clicker:get_player_name()
end
end
mobs_goblins:capture_mob(self, clicker, 0, 5, 80, false, nil)
end,
})
-- spawn underground near ore and dungeons, except cobble goblins who create goblin lairs.
--function mobs_goblins:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height)
mobs_goblins:register_spawn("mobs_goblins:goblin_cobble", {"group:stone"}, 1000, 0, 200, 1, 1)
mobs_goblins:register_spawn("mobs_goblins:goblin_coal", {"default:torch", "default:coal", "default:mossycobble"}, 1000, 0, 30, 1, 1)
mobs_goblins:register_spawn("mobs_goblins:goblin_iron", {"default:stone_with_iron","default:mossycobble",}, 10, 0, 30, 1, 1)
mobs_goblins:register_spawn("mobs_goblins:goblin_gold", {"default:stone_with_gold","default:mossycobble", }, 10, 0, 30, 1, 1)
mobs_goblins:register_spawn("mobs_goblins:goblin_diamond", {"default:stone_with_diamond","default:mossycobble", }, 30, 0, 100, 1, 1)
mobs_goblins:register_spawn("mobs_goblins:goblin_king", {"default:stone_with_mese","default:mossycobble", }, 10, 0, 300, 1, 1)
mobs_goblins:register_egg("mobs_goblins:goblin_coal", "goblin egg", "default:stone_with_coal", 1)

View File

@ -0,0 +1,13 @@
local path = minetest.get_modpath("mobs_goblins")
-- Mob Api
dofile(path.."/api.lua")
dofile(path.."/goblins.lua") -- TenPlus1 and FreeLikeGNU
--if minetest.setting_get("log_mods") then
minetest.log("action", "GOBLINS is lowdids!")
--end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -3,7 +3,7 @@ Thirsty [thirsty]
A Minetest mod that adds a "thirst" mechanic.
Version: 0.9.0
Version: 0.10.0
License:
Code: LGPL 2.1 (see included LICENSE file)

View File

@ -1,4 +1,4 @@
default
default?
bucket?
hud?
hudbars?

View File

@ -6,13 +6,21 @@ See init.lua for license.
]]
local PPA = persistent_player_attributes
PPA.register({
name = 'thirsty_hydro',
min = 0,
max = 50,
default = 20,
})
function thirsty.on_joinplayer(player)
local name = player:get_player_name()
-- default entry for new players
if not thirsty.players[name] then
local pos = player:getpos()
thirsty.players[name] = {
hydro = 20,
last_pos = math.floor(pos.x) .. ':' .. math.floor(pos.z),
time_in_pos = 0.0,
pending_dmg = 0.0,
@ -26,7 +34,7 @@ function thirsty.on_dieplayer(player)
local name = player:get_player_name()
local pl = thirsty.players[name]
-- reset after death
pl.hydro = 20
PPA.set_value(player, 'thirsty_hydro', 20)
pl.pending_dmg = 0.0
pl.thirst_factor = 1.0
end
@ -37,32 +45,25 @@ Getters, setters and such
]]
-- internal version, for speed
function thirsty._drink(pl, value, max)
-- test whether we're not *above* max;
-- this function should not remove any overhydration
if pl.hydro < max then
pl.hydro = math.min(pl.hydro + value, max)
--print("Drinking by "..value.." to "..pl.hydro)
return true
end
return false
end
function thirsty.drink(player, value, max)
-- if max is not specified, assume 20
if not max then
max = 20
end
local name = player:get_player_name()
local pl = thirsty.players[name]
return thirsty._drink(pl, value, max)
local hydro = PPA.get_value(player, 'thirsty_hydro')
-- test whether we're not *above* max;
-- this function should not remove any overhydration
if hydro < max then
hydro = math.min(hydro + value, max)
--print("Drinking by "..value.." to "..hydro)
PPA.set_value(player, 'thirsty_hydro', hydro)
return true
end
return false
end
function thirsty.get_hydro(player)
local name = player:get_player_name()
local pl = thirsty.players[name]
return pl.hydro
return PPA.get_value(player, 'thirsty_hydro')
end
function thirsty.set_thirst_factor(player, factor)
@ -99,6 +100,7 @@ function thirsty.main_loop(dtime)
local name = player:get_player_name()
local pos = player:getpos()
local pl = thirsty.players[name]
local hydro = PPA.get_value(player, 'thirsty_hydro')
-- how long have we been standing "here"?
-- (the node coordinates in X and Z should be enough)
@ -184,40 +186,41 @@ function thirsty.main_loop(dtime)
local wear = itemstack:get_wear()
if wear == 0 then wear = 65535.0 end
local drink = injector_max * thirsty.config.tick_time
local drink_missing = 20 - pl.hydro
local drink_missing = 20 - hydro
drink = math.max(math.min(drink, drink_missing), 0)
local drinkwear = drink / capacity * 65535.0
wear = wear + drinkwear
if wear > 65534 then wear = 65534 end
itemstack:set_wear(wear)
thirsty._drink(pl, drink, 20)
thirsty.drink(player, drink, 20)
hydro = PPA.get_value(player, 'thirsty_hydro')
player:get_inventory():set_stack("main", i, itemstack)
end
if drink_per_second > 0 and pl_standing then
-- Drinking from the ground won't give you more than max
thirsty._drink(pl, drink_per_second * thirsty.config.tick_time, 20)
--print("Raising hydration by "..(drink_per_second*thirsty.config.tick_time).." to "..pl.hydro)
thirsty.drink(player, drink_per_second * thirsty.config.tick_time, 20)
--print("Raising hydration by "..(drink_per_second*thirsty.config.tick_time).." to "..PPA.get_value(player, 'thirsty_hydro'))
else
if not pl_afk then
-- only get thirsty if not AFK
local amount = thirsty.config.thirst_per_second * thirsty.config.tick_time * pl.thirst_factor
pl.hydro = pl.hydro - amount
if pl.hydro < 0 then pl.hydro = 0 end
--print("Lowering hydration by "..amount.." to "..pl.hydro)
PPA.set_value(player, 'thirsty_hydro', hydro - amount)
hydro = PPA.get_value(player, 'thirsty_hydro')
--print("Lowering hydration by "..amount.." to "..hydro)
end
end
-- should we only update the hud on an actual change?
thirsty.hud_update(player, pl.hydro)
thirsty.hud_update(player, hydro)
-- damage, if enabled
if minetest.setting_getbool("enable_damage") then
-- maybe not the best way to do this, but it does mean
-- we can do anything with one tick loop
if pl.hydro <= 0.0 and not pl_afk then
if hydro <= 0.0 and not pl_afk then
pl.pending_dmg = pl.pending_dmg + thirsty.config.damage_per_second * thirsty.config.tick_time
--print("Pending damage at " .. pl.pending_dmg)
if pl.pending_dmg > 1.0 then
@ -247,59 +250,6 @@ end
--[[
Stash: persist the hydration values in a file in the world directory.
If this is missing or corrupted, then no worries: nobody's thirsty ;-)
]]
function thirsty.read_stash()
local filename = minetest.get_worldpath() .. "/" .. thirsty.config.stash_filename
local file, err = io.open(filename, "r")
if not file then
-- no problem, it's just not there
-- TODO: or parse err?
return
end
thirsty.players = {}
for line in file:lines() do
if string.match(line, '^%-%-') then
-- comment, ignore
elseif string.match(line, '^P [%d.]+ [%d.]+ .+') then
-- player line
-- is matching again really the best solution?
local hydro, dmg, name = string.match(line, '^P ([%d.]+) ([%d.]+) (.+)')
thirsty.players[name] = {
hydro = tonumber(hydro),
last_pos = '0:0', -- not true, but no matter
time_in_pos = 0.0,
pending_dmg = tonumber(dmg),
thirst_factor = 1.0,
}
end
end
file:close()
end
function thirsty.write_stash()
local filename = minetest.get_worldpath() .. "/" .. thirsty.config.stash_filename
local file, err = io.open(filename, "w")
if not file then
minetest.log("error", "Thirsty: could not write " .. thirsty.config.stash_filename .. ": " ..err)
return
end
file:write('-- Stash file for Minetest mod [thirsty] --\n')
-- write players:
-- P <hydro> <pending_dmg> <name>
file:write('-- Player format: "P <hydro> <pending damage> <name>"\n')
for name, data in pairs(thirsty.players) do
file:write("P " .. data.hydro .. " " .. data.pending_dmg .. " " .. name .. "\n")
end
file:close()
end
--[[
General handler
Most tools, nodes and craftitems use the same code, so here it is:
@ -308,7 +258,8 @@ Most tools, nodes and craftitems use the same code, so here it is:
function thirsty.drink_handler(player, itemstack, node)
local pl = thirsty.players[player:get_player_name()]
local old_hydro = pl.hydro
local hydro = PPA.get_value(player, 'thirsty_hydro')
local old_hydro = hydro
-- selectors, always true, to make the following code easier
local item_name = itemstack and itemstack:get_name() or ':'
@ -321,9 +272,7 @@ function thirsty.drink_handler(player, itemstack, node)
-- drink until level
local level = math.max(cont_level, node_level)
--print("Drinking to level " .. level)
if pl.hydro < level then
pl.hydro = level
end
thirsty.drink(player, level, level)
-- fill container, if applicable
if thirsty.config.container_capacity[item_name] then
@ -335,7 +284,7 @@ function thirsty.drink_handler(player, itemstack, node)
-- drinking from a container
if itemstack:get_wear() ~= 0 then
local capacity = thirsty.config.container_capacity[item_name]
local hydro_missing = 20 - pl.hydro;
local hydro_missing = 20 - hydro;
if hydro_missing > 0 then
local wear_missing = hydro_missing / capacity * 65535.0;
local wear = itemstack:get_wear()
@ -346,15 +295,16 @@ function thirsty.drink_handler(player, itemstack, node)
end
itemstack:set_wear(new_wear)
if wear_missing > 0 then -- rounding glitches?
thirsty._drink(pl, wear_missing * capacity / 65535.0, 20)
thirsty.drink(player, wear_missing * capacity / 65535.0, 20)
hydro = PPA.get_value(player, 'thirsty_hydro')
end
end
end
end
-- update HUD if value changed
if pl.hydro ~= old_hydro then
thirsty.hud_update(player, pl.hydro)
if hydro ~= old_hydro then
thirsty.hud_update(player, hydro)
end
end

View File

@ -17,6 +17,8 @@ Any hud needs to define the following functions:
]]
local PPA = persistent_player_attributes
function thirsty.hud_clamp(value)
if value < 0 then
return 0
@ -33,13 +35,11 @@ if minetest.get_modpath("hudbars") then
icon = 'thirsty_cup_100_16.png'
}, 20, 20, false)
function thirsty.hud_init(player)
local name = player:get_player_name()
hb.init_hudbar(player, 'thirst',
thirsty.hud_clamp(thirsty.players[name].hydro),
thirsty.hud_clamp(PPA.get_value(player, 'thirsty_hydro')),
20, false)
end
function thirsty.hud_update(player, value)
local name = player:get_player_name()
hb.change_hudbar(player, 'thirst', thirsty.hud_clamp(value), 20)
end
elseif minetest.get_modpath("hud") then
@ -73,7 +73,7 @@ else
hud_elem_type = "statbar",
position = { x=0.5, y=1 },
text = "thirsty_cup_100_24.png",
number = thirsty.hud_clamp(thirsty.players[name].hydro),
number = thirsty.hud_clamp(PPA.get_value(player, 'thirsty_hydro')),
direction = 0,
size = { x=24, y=24 },
offset = { x=25, y=-(48+24+16+32)},

View File

@ -47,7 +47,6 @@ thirsty = {
players = {
--[[
name = {
hydro = 20,
last_pos = '-10:3',
time_in_pos = 0.0,
pending_dmg = 0.0,
@ -72,6 +71,8 @@ thirsty = {
time_next_tick = 0.0,
}
dofile(minetest.get_modpath('thirsty')..'/persistent_player_attributes.lua')
dofile(minetest.get_modpath('thirsty')..'/configuration.lua')
thirsty.time_next_tick = thirsty.config.tick_time
@ -86,8 +87,8 @@ minetest.register_globalstep(thirsty.main_loop)
dofile(minetest.get_modpath('thirsty')..'/components.lua')
-- read on startup
thirsty.read_stash()
--thirsty.read_stash()
-- write on shutdown
minetest.register_on_shutdown(thirsty.write_stash)
--minetest.register_on_shutdown(thirsty.write_stash)

View File

@ -0,0 +1,151 @@
--[[
Persistent player attributes (mixin)
====================================
A mixin to provide persistent player attributes. Simply include and do
this file in your mod, it will take care to update itself.
Copyright (C) 2015 Ben Deutsch <ben@bendeutsch.de>
License
-------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
]]
local global_exists = minetest.global_exists or function(name) rawget(_G, name) end
if not global_exists('persistent_player_attributes') then
persistent_player_attributes = {
-- trigger "newer version available" below
version = 0.000,
}
end
--[[
DO NOT RESET THE GLOBAL VARIABLE!
The following code *and library users* localize the (overly long)
library global variable. If another mod later includes a newer version
of this library, and this newer version changes the global variable
"persistent_player_attributes", then the mods which previously
included this mixin may *or may not* be using the old version.
Chaos will certainly ensue.
]]
local PPA = persistent_player_attributes
if PPA.version < 1.000 then
-- the version, minor and patch are in thousandths,
-- e.g. 1.2.3 becomes 1.002003
PPA.version = 1.000
-- the stash of registered attributes
PPA.defs = {--[[
name = {
name = "mymod_attr1",
min = 0,
max = 10,
default = 5,
},
]]}
--[[
How to register a new attribute, with named parameters:
PPA.register({ name = "mymod_attr1", min = 0, ... })
]]
PPA.register = function(def)
PPA.defs[def.name] = {
name = name,
min = def.min or 0.0,
max = def.max or 1.0,
default = def.default or def.min or 0.0,
}
end
--[[
Helper functions that take care of the conversions *and* the
clamping for us
]]
local function _count_for_val(value, def)
local count = math.floor((value - def.min) / (def.max - def.min) * 65535)
if count < 0 then count = 0 end
if count > 65535 then count = 65535 end
return count
end
local function _val_for_count(count, def)
local value = count / 65535 * (def.max - def.min) + def.min
if value < def.min then value = def.min end
if value > def.max then value = def.max end
return value
end
--[[
We cannot override / take back a register_on_joinplayer,
so we'll only create and register this one, which calls the
(overridable) actual handler
]]
if not PPA.shim_on_joinplayer then
PPA.shim_on_joinplayer = function(player)
PPA.on_joinplayer(player)
end
minetest.register_on_joinplayer(PPA.shim_on_joinplayer)
end
-- The actual on_joinplayer handler
PPA.on_joinplayer = function(player)
local inv = player:get_inventory()
for name, def in pairs(PPA.defs) do
inv:set_size(name, 1)
if inv:is_empty(name) then
-- set default value
inv:set_stack(name, 1, ItemStack({ name = ":", count = _count_for_val(def.default, def) }))
end
end
end
--[[ get an attribute, procedural style:
local attr1 = PPA.get_value(player, "mymod_attr1")
]]
PPA.get_value = function(player, name)
local def = PPA.defs[name]
local inv = player:get_inventory()
local count = inv:get_stack(name, 1):get_count()
return _val_for_count(count, def)
end
--[[ set an attribute, procedural style:
PPA.set_value(player, "mymod_attr1", attr1)
]]
PPA.set_value = function(player, name, value)
local def = PPA.defs[name]
local inv = player:get_inventory()
inv:set_stack(name, 1, ItemStack({ name = ":", count = _count_for_val(value, def) }))
end
end

View File

@ -0,0 +1,4 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
See http://www.gnu.org/licenses/gpl-3.0.en.html

View File

@ -0,0 +1,53 @@
# Valleys Mapgen
Mapgen mod for Minetest 0.4.12+. Work in progress, not finished.
![Screenshot](http://i.imgur.com/A6CBuaV.png)
[Discussion on Minetest Forums](https://forum.minetest.net/viewtopic.php?f=9&t=11430)
## Changelog
### 2.1 ~> Latest
* Added flowers (6 species)
### 2.0 ~> 2.1 (Saturday July 4, 2015)
* Modified conditions for desert plants
* Added pine tree
* Generate special water in rivers
* Changed valley shape a bit (no more cliffs on the sides of the rivers)
* Changed river shape (smooth floor)
### 1.3 ~> 2.0 (Sunday May 31, 2015)
* Added plants, optionnal, enabled by default
* Corrected math.random too large interval (2³² → 2²⁴)
* Added snow
* When a player dies, it's respawned
* Adapted to any `chunksize` (previously the mod was only working for 5)
* Added trees (3 species for now), optionnal, enabled by default
* Added logs : see vmg.conf.example
* Added temperature and humidity noises, used by trees
* Changed parameters for lava
### 1.2 ~> 1.3 (Wednesday April 8, 2015)
* Added differents types of dirts (the aim is to make real biomes in the future)
* Added beaches
* Added setting `water_level` to set water level (default is 1)
* Fixed fatal error with number settings
### 1.1 ~> 1.2 (Tuesday March 17, 2015)
* Added lava underground
* Settings in minetest.conf : see file vmg.conf.example
* Now the player can't spawn in rivers
* Player spawn location is randomized : you can set the maximal distance from (0;0) at which the player will appear. (If it's in a big ocean, it may be farther)
* Some minor changes about terrain :
* Bare stone is rarer
* Valleys are slightly larger
* Ores are generated properly, according to [Paramat's changes](https://github.com/minetest/minetest/commit/b2b6bbf3e80f0ab06d62c43567122871ae560534) in `minetest.generate_ores`. **I advise you to update your MT version to a recent build (03/11 or later) or the ores overlapping problem will reappear.**
### 1.0 ~> 1.1 (Sunday March 8, 2015)
* Added caves: they are modelised by 4 3D noises.
* Corrected ores generation: There was too many ores because it was sometimes generated twice or even more.
* Activated versions manager: if you update the mod from 1.0 to this version, the new mapgen will only take effect on new worlds, worlds created with 1.0 will stay in 1.0. If you want to activate mapgen 1.1 in an old world (there could be cleavages), change the file vmg.conf which is in the world directory.
* Added… this changelog :-D
### 1.0 (Saturday March 7, 2015)
* Created mapgen (using 7 noises at the moment).

View File

@ -0,0 +1,2 @@
default
flowers

View File

@ -0,0 +1,91 @@
vmg = {}
vmg.version = "2.2"
vmg.path = minetest.get_modpath("valleys_mapgen")
vmg.loglevel = tonumber(minetest.setting_get("vmg_log_level") or 0)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Loading basic functions ...")
end
minetest.register_on_mapgen_init(function(mgparams)
minetest.set_mapgen_params({mgname="singlenode", flags="nolight"})
end)
if default then
if default.register_ores then
default.register_ores()
end
if default.register_blobs then
default.register_blobs()
end
end
function pos2d(pos)
if type(pos) == "number" then
return {x = pos, y = pos}
elseif pos.z then
return {x = pos.x, y = pos.z}
else
return {x = pos.x, y = pos.y}
end
end
function pos3d(pos, alt)
alt = alt or 0
if type(pos) == "number" then
return {x = pos, y = pos, z = pos}
elseif pos.z then
return {x = pos.x, y = pos.z, z = pos.z}
else
return {x = pos.x, y = alt, z = pos.y}
end
end
function minetest.add_group(node, groups)
local def = minetest.registered_items[node]
if not def then
return false
end
local def_groups = def.groups or {}
for group, value in pairs(groups) do
if value ~= 0 then
def_groups[group] = value
else
def_groups[group] = nil
end
end
minetest.override_item(node, {groups = def_groups})
return true
end
function displaytime(time)
return math.floor(time * 1000000 + 0.5) / 1000 .. " ms"
end
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Loading settings API ...")
end
dofile(vmg.path .. "/settings.lua")
if vmg.define("spawn", true) then
minetest.register_on_newplayer(vmg.spawnplayer)
end
if vmg.define("respawn", true) then
minetest.register_on_respawnplayer(vmg.spawnplayer)
end
minetest.register_on_generated(vmg.generate)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Loading nodes ...")
end
dofile(vmg.path .. "/nodes.lua")
if vmg.loglevel >= 1 then
print("[Valleys Mapgen] Loaded !")
end

View File

@ -0,0 +1,552 @@
-- Mapgen 2.2
-- Monday July 6, 2015
vmg.noises = {
-- Noise 1 : Base Ground Height 2D
{offset = -10, scale = 50, seed = 5202, spread = {x = 1024, y = 1024, z = 1024}, octaves = 6, persist = 0.4, lacunarity = 2},
-- Noise 2 : Valleys (River where around zero) 2D
{offset = 0, scale = 1, seed = -6050, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.6, lacunarity = 2},
-- Noise 3 : Valleys Depth 2D
{offset = 5, scale = 4, seed = -1914, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 4 : Valleys Profile (Higher values = Larger valleys) 2D
{offset = 0.6, scale = 0.5, seed = 777, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 5 : Inter-valleys slopes 2D
{offset = 0.5, scale = 0.5, seed = 746, spread = {x = 128, y = 128, z = 128}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 6 : Inter-valleys filling 3D
{offset = 0, scale = 1, seed = 1993, spread = {x = 256, y = 512, z = 256}, octaves = 6, persist = 0.8, lacunarity = 2},
-- Noise 7 : Dirt thickness 2D
{offset = 3, scale = 1.75, seed = 1605, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
-- Noise 8 : Caves I 3D
{offset = 0, scale = 1, seed = -4640, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 9 : Caves II 3D
{offset = 0, scale = 1, seed = 8804, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 10 : Caves III 3D
{offset = 0, scale = 1, seed = -4780, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 11 : Caves IV and Lava I 3D
{offset = 0, scale = 1, seed = -9969, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 12 : Lava II (Geologic heat) 3D
{offset = 0, scale = 1, seed = 3314, spread = {x = 64, y = 64, z = 64}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 13 : Clayey dirt noise 2D
{offset = 0, scale = 1, seed = 2835, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 14 : Silty dirt noise 2D
{offset = 0, scale = 1, seed = 6674, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 15 : Sandy dirt noise 2D
{offset = 0, scale = 1, seed = 6940, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 16 : Beaches 2D
{offset = 2, scale = 8, seed = 2349, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
-- Noise 17 : Temperature (not in maps) 3D
{offset = 2, scale = 1, seed = -1805, spread = {x = 768, y = 256, z = 768}, octaves = 4, persist = 0.5, lacunarity = 4},
-- Noise 18 : Humidity 2D
{offset = 0, scale = 1, seed = -5787, spread = {x = 243, y = 243, z = 243}, octaves = 4, persist = 0.5, lacunarity = 3},
}
function vmg.noisemap(i, minp, chulens)
local obj = minetest.get_perlin_map(vmg.noises[i], chulens)
if minp.z then
return obj:get3dMap_flat(minp)
else
return obj:get2dMap_flat(minp)
end
end
for i, n in ipairs(vmg.noises) do
vmg.noises[i] = vmg.define("noise_" .. i, n)
end
vmg.after_mapgen = {}
function vmg.register_after_mapgen(f, ...)
table.insert(vmg.after_mapgen, {f = f, ...})
end
function vmg.execute_after_mapgen()
for i, params in ipairs(vmg.after_mapgen) do
params.f(unpack(params))
end
vmg.after_mapgen = {}
end
local river_depth = vmg.define("river_depth", 3) + 1
local river_size = vmg.define("river_size", 5) / 100
local caves_size = vmg.define("caves_size", 7) / 100
local lava_depth = vmg.define("lava_depth", 2000)
local lava_max_height = vmg.define("lava_max_height", -1)
local altitude_chill = vmg.define("altitude_chill", 90)
local average_stone_level = vmg.define("average_stone_level", 180)
local dirt_thickness = math.sqrt(average_stone_level) / (vmg.noises[7].offset + 0.5)
local average_snow_level = vmg.define("average_snow_level", 100)
local snow_threshold = vmg.noises[17].offset * 0.5 ^ (average_snow_level / altitude_chill)
local player_max_distance = vmg.define("player_max_distance", 450)
local clay_threshold = vmg.define("clay_threshold", 1)
local silt_threshold = vmg.define("silt_threshold", 1)
local sand_threshold = vmg.define("sand_threshold", 0.75)
local dirt_threshold = vmg.define("dirt_threshold", 0.5)
local tree_density = vmg.define("tree_density", 5) / 100
local trees = vmg.define("trees", true)
local plant_density = vmg.define("plant_density", 32) / 100
local plants = vmg.define("plants", true)
local water_level = vmg.define("water_level", 1)
local river_water = vmg.define("river_water", true)
function vmg.generate(minp, maxp, seed)
local minps, maxps = minetest.pos_to_string(minp), minetest.pos_to_string(maxp)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Preparing to generate map from " .. minps .. " to " .. maxps .. " ...")
elseif vmg.loglevel == 1 then
print("[Valleys Mapgen] Generating map from " .. minps .. " to " .. maxps .. " ...")
end
local t0 = os.clock()
local c_stone = minetest.get_content_id("default:stone")
local c_dirt = minetest.get_content_id("default:dirt")
local c_lawn = minetest.get_content_id("default:dirt_with_grass")
local c_snow = minetest.get_content_id("default:dirt_with_snow")
local c_dirt_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey")
local c_lawn_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_grass")
local c_snow_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_snow")
local c_dirt_silt = minetest.get_content_id("valleys_mapgen:dirt_silty")
local c_lawn_silt = minetest.get_content_id("valleys_mapgen:dirt_silty_with_grass")
local c_snow_silt = minetest.get_content_id("valleys_mapgen:dirt_silty_with_snow")
local c_dirt_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy")
local c_lawn_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_grass")
local c_snow_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_snow")
local c_desert_sand = minetest.get_content_id("default:desert_sand")
local c_sand = minetest.get_content_id("default:sand")
local c_gravel = minetest.get_content_id("default:gravel")
local c_silt = minetest.get_content_id("valleys_mapgen:silt")
local c_clay = minetest.get_content_id("valleys_mapgen:red_clay")
local c_water = minetest.get_content_id("default:water_source")
local c_riverwater = minetest.get_content_id("default:river_water_source")
local c_lava = minetest.get_content_id("default:lava_source")
local c_snow_layer = minetest.get_content_id("default:snow")
local c_tree = minetest.get_content_id("default:tree")
local c_leaves = minetest.get_content_id("default:leaves")
local c_apple = minetest.get_content_id("default:apple")
local c_jungletree = minetest.get_content_id("default:jungletree")
local c_jungleleaves = minetest.get_content_id("default:jungleleaves")
local c_pinetree = minetest.get_content_id("default:pinetree")
local c_pineleaves = minetest.get_content_id("default:pine_needles")
local c_firtree = minetest.get_content_id("valleys_mapgen:fir_tree")
local c_firleaves = minetest.get_content_id("valleys_mapgen:fir_needles")
local c_grass = {
minetest.get_content_id("default:grass_1"),
minetest.get_content_id("default:grass_2"),
minetest.get_content_id("default:grass_3"),
minetest.get_content_id("default:grass_4"),
minetest.get_content_id("default:grass_5"),
}
local c_junglegrass = minetest.get_content_id("default:junglegrass")
local c_dryshrub = minetest.get_content_id("default:dry_shrub")
local c_cactus = minetest.get_content_id("default:cactus")
local c_papyrus = minetest.get_content_id("default:papyrus")
local c_geranium = minetest.get_content_id("flowers:geranium")
local c_rose = minetest.get_content_id("flowers:rose")
local c_tulip = minetest.get_content_id("flowers:tulip")
local c_viola = minetest.get_content_id("flowers:viola")
local c_dandelion_white = minetest.get_content_id("flowers:dandelion_white")
local c_dandelion_yellow = minetest.get_content_id("flowers:dandelion_yellow")
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local ystride = a.ystride
local chulens = vector.add(vector.subtract(maxp, minp), 1)
local chulens_sup = {x = chulens.x, y = chulens.y + 6, z = chulens.z}
local minp2d = pos2d(minp)
local t1 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Mapgen preparation finished in " .. displaytime(t1-t0))
print("[Valleys Mapgen] Calculating noises ...")
end
local n1 = vmg.noisemap(1, minp2d, chulens)
local n2 = vmg.noisemap(2, minp2d, chulens)
local n3 = vmg.noisemap(3, minp2d, chulens)
local n4 = vmg.noisemap(4, minp2d, chulens)
local n5 = vmg.noisemap(5, minp2d, chulens)
local n6 = vmg.noisemap(6, minp, chulens_sup)
local n7 = vmg.noisemap(7, minp2d, chulens)
local n8 = vmg.noisemap(8, minp, chulens)
local n9 = vmg.noisemap(9, minp, chulens)
local n10 = vmg.noisemap(10, minp, chulens)
local n11 = vmg.noisemap(11, minp, chulens)
local n12 = vmg.noisemap(12, minp, chulens)
local n13 = vmg.noisemap(13, minp2d, chulens)
local n14 = vmg.noisemap(14, minp2d, chulens)
local n15 = vmg.noisemap(15, minp2d, chulens)
local n16 = vmg.noisemap(16, minp2d, chulens)
local n18 = vmg.noisemap(18, minp2d, chulens)
local t2 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Noises calculation finished in " .. displaytime(t2-t1))
print("[Valleys Mapgen] Collecting data ...")
end
local i2d = 1 -- index for 2D noises
local i3d_sup = 1 -- index for noise 6 which has a special size
local i3d = 1 -- index for 3D noises
-- Calculate increments
local i2d_incrZ = chulens.z
local i2d_decrX = chulens.x * chulens.z - 1
local i3d_incrY = chulens.y
local i3d_sup_incrZ = 6 * chulens.y
local i3d_decrX = chulens.x * chulens.y * chulens.z - 1
local i3d_sup_decrX = chulens.x * (chulens.y + 6) * chulens.z - 1
for x = minp.x, maxp.x do -- for each YZ plane
for z = minp.z, maxp.z do -- for each vertical line in this plane
local v1, v2, v3, v4, v5, v7, v13, v14, v15, v16, v18 = n1[i2d], n2[i2d], n3[i2d], n4[i2d], n5[i2d], n7[i2d], n13[i2d], n14[i2d], n15[i2d], n16[i2d], n18[i2d] -- n for noise, v for value
v3 = v3 ^ 2 -- v3 must be > 0 and by the square there are high mountains but the median valleys depth is small.
local base_ground = v1 + v3 -- v3 is here because terrain is generally higher when valleys are deep (mountains)
v2 = math.abs(v2) - river_size
local river = v2 < 0
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2)) -- use the curve of the function 1exp((x/a)²) to modelise valleys. Making "a" varying 0 < a ≤ 1 will change the shape of the valleys. Try it with a geometry software ! (here x = v2 and a = v4)
local mountain_ground = base_ground + valleys
local slopes = v5 * valleys
if river then
local depth = river_depth * math.sqrt(1 - (v2 / river_size + 1) ^ 2) -- use the curve of the function sqrt(1-x²) which modelizes a circle.
mountain_ground = math.min(math.max(base_ground - depth, water_level - 6), mountain_ground)
slopes = 0
end
-- Choose biome
local dirt = c_dirt
local lawn = c_lawn
local snow = c_snow
local max = math.max(v13, v14, v15) -- the biome is the maximal of these 3 values, if bigger than 0.5. Else, make normal dirt.
if max > dirt_threshold then
if v13 == max then
if v13 > clay_threshold then
dirt = c_clay
lawn = c_clay
snow = c_clay
else
dirt = c_dirt_clay
lawn = c_lawn_clay
snow = c_snow_clay
end
elseif v14 == max then
if v14 > silt_threshold then
dirt = c_silt
lawn = c_silt
snow = c_silt
else
dirt = c_dirt_silt
lawn = c_lawn_silt
snow = c_snow_silt
end
else
if v15 > sand_threshold then
dirt = c_desert_sand
lawn = c_desert_sand
snow = c_desert_sand
else
dirt = c_dirt_sand
lawn = c_lawn_sand
snow = c_snow_sand
end
end
end
local is_beach = v15 > 0 and v16 > 0
local beach = v15 * v16 + water_level -- the y coordinate below which dirt is replaced by beach sand
-- raw humidity
local hraw = 2 ^ (v13 - v15 + v18 * 2)
for y = minp.y, maxp.y do -- for each node in vertical line
local ivm = a:index(x, y, z)
local v6, v8, v9, v10, v11, v12 = n6[i3d_sup], n8[i3d], n9[i3d], n10[i3d], n11[i3d], n12[i3d]
local is_cave = v8 ^ 2 + v9 ^ 2 + v10 ^ 2 + v11 ^ 2 < caves_size
if v6 * slopes > y - mountain_ground then -- if pos is in the ground
if not is_cave then
local thickness = v7 - math.sqrt(math.abs(y)) / dirt_thickness
local above = math.ceil(thickness + math.random()) -- The following code will look for air at this many nodes up. If any, make dirt, else, make stone. So, it's the dirt layer thickness.
if y >= water_level and n6[i3d_sup+i3d_incrY] * slopes <= y + 1 - mountain_ground and not river then
if is_beach and y < beach then
data[ivm] = c_sand
else -- if node above is not in the ground, place lawn
-- calculate humidity
local sea_water = 0.5 ^ math.max((y - water_level) / 6, 0)
local river_water = 0.5 ^ math.max((y - base_ground) / 3, 0)
local water = sea_water + (1 - sea_water) * river_water
local humidity = hraw + water
local ivm2 = ivm + ystride
y = y + 1
local pos = {x = x, y = y, z = z}
local v17 = vmg.get_noise(pos, 17)
local temp -- calculate_temperature for node above
if y > 0 then
temp = v17 * 0.5 ^ (y / altitude_chill)
else
temp = v17 * 0.5 ^ (-y / altitude_chill) + 20 * (v12 + 1) * (1 - 2 ^ (y / lava_depth))
end
if temp > snow_threshold then
if above > 0 then
data[ivm] = lawn
else
data[ivm] = c_stone
end
else
if above > 0 then
data[ivm] = snow
else
data[ivm] = c_stone
end
data[ivm2] = c_snow_layer -- set node above to snow
end
if trees and math.random() < tree_density and above > 0 then -- make a tree
-- choose a tree from climatic and geological conditions
if v14 < 0 and temp < 1.5 and temp >= 0.90 and humidity < 1 and v15 < 0.8 and math.abs(v13) < 0.2 and math.random() < 0.3 then -- Pine Tree
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
vmg.make_pine_tree(pos, data, a, height, radius, c_pinetree, c_pineleaves, c_air, c_ignore)
elseif v15 < 0.6 and temp >= 0.85 and temp < 2.3 and humidity < 3 and v16 < 2 and v14 > -0.5 and v13 < 0.8 then -- Apple Tree
local rand = math.random()
local height = math.floor(4 + 2.5 * rand)
local radius = 3 + rand
if math.random(1, 4) == 1 then
vmg.make_apple_tree(pos, data, a, height, radius, c_tree, c_leaves, c_apple, c_air, c_ignore)
else
vmg.make_tree(pos, data, a, height, radius, c_tree, c_leaves, c_air, c_ignore)
end
elseif v15 < 0.7 and temp >= 1.9 and humidity > 2 and v16 > 2 then -- Jungle Tree
local rand = math.random()
local height = math.floor(8 + 4 * rand)
local radius = 5 + 3 * rand
vmg.make_jungle_tree(pos, data, a, height, radius, c_jungletree, c_jungleleaves, c_air, c_ignore)
elseif temp > 0.38 and temp < 1 and humidity > 0.9 and v15 > 0 and v15 < 0.55 then -- Fir Tree
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
vmg.make_fir_tree(pos, data, a, height, radius, c_firtree, c_firleaves, c_air, c_ignore)
end
elseif plants and math.random() < plant_density and above > 0 then -- make a plant
if temp > 1 and temp < 1.8 and water > 0.7 and humidity > 3 and v13 > -0.4 and math.random() < 0.04 then -- Papyrus
for i = 1, 4 do
data[ivm+i*ystride] = c_papyrus
end
elseif v15 < 0.65 and temp >= 0.65 and temp < 1.5 and humidity < 2.6 and v16 < 1.5 and v13 < 0.8 and math.random() < 0.7 then -- Grass
data[ivm2] = c_grass[math.random(1, 5)]
elseif v15 > -0.6 and temp >= 1.8 and humidity > 2.2 and v16 > 1.8 then -- Jungle Grass
data[ivm2] = c_junglegrass
elseif v15 > 0.65 and humidity < 0.5 and math.random() < 0.2 then
if v16 > 0 and temp > 1.6 and math.random() < 0.12 then -- Cactus
for i = 1, 4 do
data[ivm+i*ystride] = c_cactus
end
elseif temp > 1.2 then -- Dry Shrub
data[ivm2] = c_dryshrub
end
elseif math.random() < 0.04 and temp > 0.98 and temp < 1.8 and humidity < 1.7 and v14 >= -0.1 and v15 < 0.4 and v15 >= -0.6 and v13 < 0.82 then -- Flowers
if temp > 1.2 and math.random() < 0.3 then
data[ivm2] = c_rose
elseif thickness <= 1.3 and math.random() < 0.4 then
data[ivm2] = c_geranium
elseif v16 < 1.6 and math.random() < 0.7 then
data[ivm2] = c_viola
elseif temp > 1.3 and humidity < 1.5 and math.random() < 0.2 then
data[ivm2] = c_tulip
elseif math.random() < 0.5 then
data[ivm2] = c_dandelion_white
else
data[ivm2] = c_dandelion_yellow
end
end
end
y = y - 1
end
elseif above <= 0 then
data[ivm] = c_stone
elseif n6[i3d_sup+above*i3d_incrY] * slopes <= y + above - mountain_ground then -- if node at "above" nodes up is not in the ground, make dirt
if is_beach and y < beach then
data[ivm] = c_sand
else
data[ivm] = dirt
end
else
data[ivm] = c_stone
end
elseif v11 + v12 > 2 ^ (y / lava_depth) and y <= lava_max_height then
data[ivm] = c_lava
end
elseif y <= water_level then -- if pos is not in the ground, and below water_level, it's an ocean
data[ivm] = c_water
elseif river and y + 1 < base_ground then
if river_water then
data[ivm] = c_riverwater
else
data[ivm] = c_water
end
end
i3d = i3d + i3d_incrY -- increment i3d by one line
i3d_sup = i3d_sup + i3d_incrY -- idem
end
i2d = i2d + i2d_incrZ -- increment i2d by one Z
-- useless to increment i3d, because increment would be 0 !
i3d_sup = i3d_sup + i3d_sup_incrZ -- for i3d_sup, just avoid the 6 supplemental lines
end
i2d = i2d - i2d_decrX -- decrement the Z line previously incremented and increment by one X (1)
i3d = i3d - i3d_decrX -- decrement the YZ plane previously incremented and increment by one X (1)
i3d_sup = i3d_sup - i3d_sup_decrX -- idem, including the supplemental lines
end
vmg.execute_after_mapgen() -- needed for jungletree roots
local t3 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data collecting finished in " .. displaytime(t3-t2))
print("[Valleys Mapgen] Writing data ...")
end
-- execute voxelmanip boring stuff to write to the map
vm:set_data(data)
minetest.generate_ores(vm, minp, maxp)
vm:set_lighting({day = 0, night = 0})
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
local t4 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data writing finished in " .. displaytime(t4-t3))
end
if vmg.loglevel >= 1 then
print("[Valleys Mapgen] Mapgen finished in " .. displaytime(t4-t0))
end
end
dofile(vmg.path .. "/trees.lua")
function vmg.get_humidity_raw(pos)
local v13 = vmg.get_noise(pos, 13)
local v15 = vmg.get_noise(pos, 15)
local v18 = vmg.get_noise(pos, 18)
return 2 ^ (v13 - v15 + v18 * 2)
end
function vmg.get_humidity(pos)
local y = pos.y
local flatpos = pos2d(pos)
local hraw = vmg.get_humidity_raw(flatpos)
local v1 = vmg.get_noise(flatpos, 1)
local v3 = vmg.get_noise(flatpos, 3) ^ 2
local base_ground = v1 + v3
local sea_water = 0.5 ^ math.max((y - water_level) / 6, 0)
local river_water = 0.5 ^ math.max((y - base_ground) / 3, 0)
local water = sea_water + (1 - sea_water) * river_water
return hraw + water
end
function vmg.get_temperature(pos)
local v12 = vmg.get_noise(pos, 12) + 1
local v17 = vmg.get_noise(pos, 17)
local y = pos.y
if y > 0 then
return v17 * 0.5 ^ (y / altitude_chill)
else
return v17 * 0.5 ^ (-y / altitude_chill) + 20 * v12 * (1 - 2 ^ (y / lava_depth))
end
end
function vmg.get_noise(pos, i)
local n = vmg.noises[i]
local noise = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
if not pos.z then
return noise:get2d({x = pos.x / n.spread.x, y = pos.y / n.spread.y}) * n.scale + n.offset
else
return noise:get3d({x = pos.x / n.spread.x, y = pos.y / n.spread.y, z = pos.z / n.spread.z}) * n.scale + n.offset
end
end
local function round(n)
return math.floor(n + 0.5)
end
function vmg.get_elevation(pos)
local v1 = vmg.get_noise(pos, 1)
local v2 = math.abs(vmg.get_noise(pos, 2)) - river_size
local v3 = vmg.get_noise(pos, 3) ^ 2
local base_ground = v1 + v3
if v2 < 0 then
return math.ceil(base_ground), true
end
local v4 = vmg.get_noise(pos, 4)
local v5 = vmg.get_noise(pos, 5)
local base_ground = v1 + v3
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2))
local mountain_ground = base_ground + valleys
local pos = pos3d(pos, round(mountain_ground))
local slopes = v5 * valleys
if vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground then
pos.y = pos.y + 1
while vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground do
pos.y = pos.y + 1
end
return pos.y, false
else
pos.y = pos.y - 1
while vmg.get_noise(pos, 6) * slopes <= pos.y - mountain_ground do
pos.y = pos.y - 1
end
return pos.y, false
end
end
function vmg.spawnplayer(player)
local angle = math.random() * math.pi * 2
local distance = math.random() * player_max_distance
local p_angle = {x = math.cos(angle), y = math.sin(angle)}
local pos = {x = -p_angle.x * distance, y = -p_angle.y * distance}
local elevation, river = vmg.get_elevation(pos)
while elevation < water_level + 2 or river do
pos.x = pos.x + p_angle.x
pos.y = pos.y + p_angle.y
elevation, river = vmg.get_elevation({x = round(pos.x), y = round(pos.y)})
end
pos = {x = round(pos.x), y = round(elevation + 1), z = round(pos.y)}
player:setpos(pos)
return true
end

View File

@ -0,0 +1,192 @@
local waterflow = vmg.define("waterflow", 3)
minetest.override_item("default:river_water_source", {liquid_range = waterflow})
minetest.override_item("default:river_water_flowing", {liquid_range = waterflow})
minetest.register_node("valleys_mapgen:silt", {
description = "Silt",
tiles = {"vmg_silt.png"},
is_ground_content = true,
groups = {crumbly=3},
sounds = default.node_sound_dirt_defaults(),
})
minetest.register_node("valleys_mapgen:red_clay", {
description = "Red Clay",
tiles = {"vmg_red_clay.png"},
is_ground_content = true,
groups = {crumbly=3},
sounds = default.node_sound_dirt_defaults(),
})
minetest.override_item("default:clay", {description = "White Clay"})
local function register_dirts(readname)
local name = readname:lower()
local itemstr_dirt = "valleys_mapgen:dirt_" .. name
local itemstr_lawn = itemstr_dirt .. "_with_grass"
local itemstr_snow = itemstr_dirt .. "_with_snow"
local tilestr = "vmg_dirt_" .. name .. ".png"
minetest.register_node(itemstr_dirt, {
description = readname .. " Dirt",
tiles = {tilestr},
is_ground_content = true,
groups = {crumbly=3,soil=1},
sounds = default.node_sound_dirt_defaults(),
})
minetest.register_node(itemstr_lawn, {
description = readname .. " Dirt with Grass",
tiles = {"default_grass.png", tilestr, tilestr .. "^default_grass_side.png"},
is_ground_content = true,
groups = {crumbly=3,soil=1},
drop = itemstr_dirt,
sounds = default.node_sound_dirt_defaults({
footstep = {name="default_grass_footstep", gain=0.25},
}),
})
minetest.register_node(itemstr_snow, {
description = readname .. " Dirt with Snow",
tiles = {"default_snow.png", tilestr, tilestr .. "^default_snow_side.png"},
is_ground_content = true,
groups = {crumbly=3,soil=1},
drop = itemstr_dirt,
sounds = default.node_sound_dirt_defaults({
footstep = {name="default_snow_footstep", gain=0.25},
}),
})
minetest.register_abm({
nodenames = {itemstr_dirt},
interval = 2,
chance = 200,
action = function(pos, node)
local above = {x=pos.x, y=pos.y+1, z=pos.z}
local name = minetest.get_node(above).name
local nodedef = minetest.registered_nodes[name]
if nodedef and (nodedef.sunlight_propagates or nodedef.paramtype == "light")
and nodedef.liquidtype == "none"
and (minetest.get_node_light(above) or 0) >= 13 then
if name == "default:snow" or name == "default:snowblock" then
minetest.set_node(pos, {name = itemstr_snow})
else
minetest.set_node(pos, {name = itemstr_lawn})
end
end
end
})
minetest.register_abm({
nodenames = {itemstr_lawn},
interval = 2,
chance = 20,
action = function(pos, node)
local above = {x=pos.x, y=pos.y+1, z=pos.z}
local name = minetest.get_node(above).name
local nodedef = minetest.registered_nodes[name]
if name ~= "ignore" and nodedef
and not ((nodedef.sunlight_propagates or nodedef.paramtype == "light")
and nodedef.liquidtype == "none") then
minetest.set_node(pos, {name = itemstr_dirt})
end
end
})
end
register_dirts("Clayey")
register_dirts("Silty")
register_dirts("Sandy")
-----------
-- Trees --
-----------
minetest.register_node("valleys_mapgen:fir_tree", {
description = "Fir Tree",
tiles = {"vmg_fir_tree_top.png", "vmg_fir_tree_top.png", "vmg_fir_tree.png"},
paramtype2 = "facedir",
is_ground_content = false,
groups = {tree=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
sounds = default.node_sound_wood_defaults(),
on_place = minetest.rotate_node
})
minetest.register_node("valleys_mapgen:fir_tree", {
description = "Fir Tree",
tiles = {"vmg_fir_tree_top.png", "vmg_fir_tree_top.png", "vmg_fir_tree.png"},
paramtype2 = "facedir",
is_ground_content = false,
groups = {tree=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
sounds = default.node_sound_wood_defaults(),
on_place = minetest.rotate_node
})
minetest.register_node("valleys_mapgen:fir_sapling", {
description = "Fir Sapling",
drawtype = "plantlike",
visual_scale = 1.0,
tiles = {"vmg_fir_sapling.png"},
inventory_image = "vmg_fir_sapling.png",
wield_image = "vmg_fir_sapling.png",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
},
groups = {snappy=2,dig_immediate=3,flammable=2,attached_node=1,sapling=1},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("valleys_mapgen:fir_needles", {
description = "Fir Needles",
drawtype = "allfaces_optional",
waving = 1,
visual_scale = 1.3,
tiles = {"vmg_fir_leaves.png"},
paramtype = "light",
is_ground_content = false,
groups = {snappy=3, leafdecay=7, flammable=2, leaves=1},
drop = {
max_items = 1,
items = {
{
-- player will get sapling with 1/20 chance
items = {'valleys_mapgen:fir_sapling'},
rarity = 20,
},
{
-- player will get leaves only if he get no saplings,
-- this is because max_items is 1
items = {'valleys_mapgen:fir_needles'},
}
}
},
sounds = default.node_sound_leaves_defaults(),
after_place_node = default.after_place_leaves,
})
minetest.register_node("valleys_mapgen:fir_wood", {
description = "Fir Wood Planks",
tiles = {"vmg_fir_wood.png"},
is_ground_content = false,
groups = {choppy=2,oddly_breakable_by_hand=2,flammable=3,wood=1},
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "valleys_mapgen:fir_wood 5",
recipe = {
{"valleys_mapgen:fir_tree"}
}
})
minetest.add_group("default:leaves", {leafdecay = 5})
minetest.add_group("default:jungleleaves", {leafdecay = 8})
minetest.add_group("default:pine_needles", {leafdecay = 7})

View File

@ -0,0 +1,195 @@
-- Mapgen 1.0
-- Saturday March 7, 2015
vmg.noises = {
-- Noise 1 : Base Ground Height 2D
{offset = -10, scale = 50, seed = 5202, spread = {x = 1024, y = 1024, z = 1024}, octaves = 6, persist = 0.4},
-- Noise 2 : Valleys (River where around zero) 2D
{offset = 0, scale = 1, seed = -6050, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.6},
-- Noise 3 : Valleys Depth 2D
{offset = 5, scale = 4, seed = -1914, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1},
-- Noise 4 : Valleys Profile (Higher values = Larger valleys) 2D
{offset = 0.5, scale = 0.5, seed = 777, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1},
-- Noise 5 : Inter-valleys slopes 2D
{offset = 0.5, scale = 0.5, seed = 746, spread = {x = 128, y = 128, z = 128}, octaves = 1, persist = 1},
-- Noise 6 : Inter-valleys filling 3D
{offset = 0, scale = 1, seed = 1993, spread = {x = 256, y = 512, z = 256}, octaves = 6, persist = 0.8},
-- Noise 7 : Dirt thickness 2D
{offset = 1.75, scale = 3.25, seed = 1605, spread = {x = 256, y = 256, z = 256}, octaves = 1, persist = 1},
}
function vmg.generate(minp, maxp, seed)
local minps, maxps = minetest.pos_to_string(minp), minetest.pos_to_string(maxp)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Preparing to generate map from " .. minps .. " to " .. maxps .. " ...")
elseif vmg.loglevel == 1 then
print("[Valleys Mapgen] Generating map from " .. minps .. " to " .. maxps .. " ...")
end
local t0 = os.clock()
local c_dirt = minetest.get_content_id("default:dirt")
local c_stone = minetest.get_content_id("default:stone")
local c_lawn = minetest.get_content_id("default:dirt_with_grass")
local c_water = minetest.get_content_id("default:water_source")
local c_air = minetest.get_content_id("air")
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local chulens = vector.add(vector.subtract(maxp, minp), 1)
local chulens_sup = {x = chulens.x, y = chulens.y + 6, z = chulens.z}
local minp2d = pos2d(minp)
local t1 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Mapgen preparation finished in " .. displaytime(t1-t0))
print("[Valleys Mapgen] Calculating noises ...")
end
local n1 = minetest.get_perlin_map(vmg.noises[1], chulens):get2dMap_flat(minp2d)
local n2 = minetest.get_perlin_map(vmg.noises[2], chulens):get2dMap_flat(minp2d)
local n3 = minetest.get_perlin_map(vmg.noises[3], chulens):get2dMap_flat(minp2d)
local n4 = minetest.get_perlin_map(vmg.noises[4], chulens):get2dMap_flat(minp2d)
local n5 = minetest.get_perlin_map(vmg.noises[5], chulens):get2dMap_flat(minp2d)
local n6 = minetest.get_perlin_map(vmg.noises[6], chulens_sup):get3dMap_flat(minp)
local n7 = minetest.get_perlin_map(vmg.noises[7], chulens):get2dMap_flat(minp2d)
local t2 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Noises calculation finished in " .. displaytime(t2-t1))
print("[Valleys Mapgen] Collecting data ...")
end
local i2d = 1 -- index for 2D noises
local i3d = 1 -- index for 3D noises
for x = minp.x, maxp.x do -- for each east-west and bottom-top plane
for z = minp.z, maxp.z do -- for each vertical row in this plane
local v1, v2, v3, v4, v5, v7 = n1[i2d], n2[i2d], n3[i2d], n4[i2d], n5[i2d], n7[i2d] -- n for noise, v for value
v3 = v3 ^ 2 -- v3 must be > 0 and by the square there are high mountains but the median valleys depth is small.
local base_ground = v1 + v3 -- v3 is here because terrain is generally higher when valleys are deep (mountains)
local river = math.abs(v2) < 0.05
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2)) -- use the curve of the function 1exp((x/a)²) to modelise valleys. Making "a" varying 0 < a ≤ 1 will change the shape of the valleys. v2 = x and v4 = a.
local mountain_ground = base_ground + valleys
local slopes = v5 * valleys
if river then
mountain_ground = math.min(math.max(base_ground - 3, -5), mountain_ground)
slopes = 0
end
for y = minp.y, maxp.y do -- for each node in vertical row
local ivm = a:index(x, y, z)
local v6 = n6[i3d]
if v6 * slopes > y - mountain_ground then -- if pos is in the ground
local above = math.ceil(v7 + math.random())
if above <= 0 then
data[ivm] = c_stone
elseif y > 0 and n6[i3d+80] * slopes <= y + 1 - mountain_ground and not river then
data[ivm] = c_lawn -- if node above is not in the ground, place lawn
elseif n6[i3d+above*80] * slopes <= y + above - mountain_ground then
data[ivm] = c_dirt
else
data[ivm] = c_stone
end
elseif y <= 1 or river and y - 2 <= mountain_ground then
data[ivm] = c_water
end
i3d = i3d + 80 -- increase i3d by one row
end
i2d = i2d + 80 -- increase i2d by one row
i3d = i3d + 480 -- avoid the 6 supplemental lines
end
i2d = i2d - 6399 -- i2d = 6401 after the first execution of this loop, it must be 2 before the second.
i3d = i3d - 550399 -- i3d = 550401 after the first execution of this loop, it must be 2 before the second.
end
local t3 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data collecting finished in " .. displaytime(t3-t2))
print("[Valleys Mapgen] Writing data ...")
end
-- execute voxelmanip boring stuff to write to the map
vm:set_data(data)
vm:calc_lighting()
vm:update_liquids()
minetest.generate_ores(vm) -- Thank you kwolekr ! I can generate the ores in 1 line ! And so it's compatible with moreores and other mods which add ores.
vm:write_to_map()
local t4 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data writing finished in " .. displaytime(t4-t3))
end
if vmg.loglevel >= 1 then
print("[Valleys Mapgen] Mapgen finished in " .. displaytime(t4-t0))
end
end
vmg.noises_obj = {}
for i, n in ipairs(vmg.noises) do
vmg.noises_obj[i] = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
end
function vmg.get_noise(pos, i)
local n = vmg.noises[i]
local noise = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
if not pos.z then
return noise:get2d({x = pos.x / n.spread.x, y = pos.y / n.spread.y}) * n.scale + n.offset
else
return noise:get3d({x = pos.x / n.spread.x, y = pos.y / n.spread.y, z = pos.z / n.spread.z}) * n.scale + n.offset
end
end
local function round(n)
return math.floor(n + 0.5)
end
function vmg.get_elevation(pos)
local v1 = vmg.get_noise(pos, 1)
local v2 = vmg.get_noise(pos, 2)
local v3 = vmg.get_noise(pos, 3) ^ 2
local v4 = vmg.get_noise(pos, 4)
local v5 = vmg.get_noise(pos, 5)
local base_ground = v1 + v3
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2))
local mountain_ground = base_ground + valleys
local pos = pos3d(pos, round(mountain_ground))
local slopes = v5 * valleys
if vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground then
pos.y = pos.y + 1
while vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground do
pos.y = pos.y + 1
end
return pos.y
else
pos.y = pos.y - 1
while vmg.get_noise(pos, 6) * slopes <= pos.y - mountain_ground do
pos.y = pos.y - 1
end
return pos.y
end
end
function vmg.spawnplayer(player)
local pos = {x = 0, y = 0}
local angle = math.random() * math.pi * 2
local p_angle = {x = math.cos(angle), y = math.sin(angle)}
local elevation = vmg.get_elevation(pos)
while elevation < 2 do
pos.x = pos.x + p_angle.x
pos.y = pos.y + p_angle.y
elevation = vmg.get_elevation({x = round(pos.x), y = round(pos.y)})
end
pos = {x = round(pos.x), y = round(elevation + 1), z = round(pos.y)}
player:setpos(pos)
return true
end

View File

@ -0,0 +1,222 @@
-- Mapgen 1.1
-- Sunday March 8, 2015
vmg.noises = {
-- Noise 1 : Base Ground Height 2D
{offset = -10, scale = 50, seed = 5202, spread = {x = 1024, y = 1024, z = 1024}, octaves = 6, persist = 0.4},
-- Noise 2 : Valleys (River where around zero) 2D
{offset = 0, scale = 1, seed = -6050, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.6},
-- Noise 3 : Valleys Depth 2D
{offset = 5, scale = 4, seed = -1914, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1},
-- Noise 4 : Valleys Profile (Higher values = Larger valleys) 2D
{offset = 0.5, scale = 0.5, seed = 777, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1},
-- Noise 5 : Inter-valleys slopes 2D
{offset = 0.5, scale = 0.5, seed = 746, spread = {x = 128, y = 128, z = 128}, octaves = 1, persist = 1},
-- Noise 6 : Inter-valleys filling 3D
{offset = 0, scale = 1, seed = 1993, spread = {x = 256, y = 512, z = 256}, octaves = 6, persist = 0.8},
-- Noise 7 : Dirt thickness 2D
{offset = 3, scale = 2, seed = 1605, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5},
-- Noise 8 : Caves I
{offset = 0, scale = 1, seed = -4640, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5},
-- Noise 9 : Caves II
{offset = 0, scale = 1, seed = 8804, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5},
-- Noise 10 : Caves III
{offset = 0, scale = 1, seed = -4780, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5},
-- Noise 11 : Caves IV
{offset = 0, scale = 1, seed = -9969, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5},
}
function vmg.generate(minp, maxp, seed)
local minps, maxps = minetest.pos_to_string(minp), minetest.pos_to_string(maxp)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Preparing to generate map from " .. minps .. " to " .. maxps .. " ...")
elseif vmg.loglevel == 1 then
print("[Valleys Mapgen] Generating map from " .. minps .. " to " .. maxps .. " ...")
end
local t0 = os.clock()
local c_dirt = minetest.get_content_id("default:dirt")
local c_stone = minetest.get_content_id("default:stone")
local c_lawn = minetest.get_content_id("default:dirt_with_grass")
local c_water = minetest.get_content_id("default:water_source")
local c_air = minetest.get_content_id("air")
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local chulens = vector.add(vector.subtract(maxp, minp), 1)
local chulens_sup = {x = chulens.x, y = chulens.y + 6, z = chulens.z}
local minp2d = pos2d(minp)
local t1 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Mapgen preparation finished in " .. displaytime(t1-t0))
print("[Valleys Mapgen] Calculating noises ...")
end
local n1 = minetest.get_perlin_map(vmg.noises[1], chulens):get2dMap_flat(minp2d)
local n2 = minetest.get_perlin_map(vmg.noises[2], chulens):get2dMap_flat(minp2d)
local n3 = minetest.get_perlin_map(vmg.noises[3], chulens):get2dMap_flat(minp2d)
local n4 = minetest.get_perlin_map(vmg.noises[4], chulens):get2dMap_flat(minp2d)
local n5 = minetest.get_perlin_map(vmg.noises[5], chulens):get2dMap_flat(minp2d)
local n6 = minetest.get_perlin_map(vmg.noises[6], chulens_sup):get3dMap_flat(minp)
local n7 = minetest.get_perlin_map(vmg.noises[7], chulens):get2dMap_flat(minp2d)
local n8 = minetest.get_perlin_map(vmg.noises[8], chulens):get3dMap_flat(minp)
local n9 = minetest.get_perlin_map(vmg.noises[9], chulens):get3dMap_flat(minp)
local n10 = minetest.get_perlin_map(vmg.noises[10], chulens):get3dMap_flat(minp)
local n11 = minetest.get_perlin_map(vmg.noises[11], chulens):get3dMap_flat(minp)
local t2 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Noises calculation finished in " .. displaytime(t2-t1))
print("[Valleys Mapgen] Collecting data ...")
end
local i2d = 1 -- index for 2D noises
local i3d_a = 1 -- index for noise 6 which has a special size
local i3d_b = 1 -- index for 3D noises
for x = minp.x, maxp.x do -- for each east-west and bottom-top plane
for z = minp.z, maxp.z do -- for each vertical row in this plane
local v1, v2, v3, v4, v5, v7 = n1[i2d], n2[i2d], n3[i2d], n4[i2d], n5[i2d], n7[i2d] -- n for noise, v for value
v3 = v3 ^ 2 -- v3 must be > 0 and by the square there are high mountains but the median valleys depth is small.
local base_ground = v1 + v3 -- v3 is here because terrain is generally higher when valleys are deep (mountains)
local river = math.abs(v2) < 0.05
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2)) -- use the curve of the function 1exp((x/a)²) to modelise valleys. Making "a" varying 0 < a ≤ 1 will change the shape of the valleys. v2 = x and v4 = a.
local mountain_ground = base_ground + valleys
local slopes = v5 * valleys
if river then
mountain_ground = math.min(math.max(base_ground - 3, -5), mountain_ground)
slopes = 0
end
for y = minp.y, maxp.y do -- for each node in vertical row
local ivm = a:index(x, y, z)
local v6, v8, v9, v10, v11 = n6[i3d_a], n8[i3d_b], n9[i3d_b], n10[i3d_b], n11[i3d_b]
local is_cave = v8 ^ 2 + v9 ^ 2 + v10 ^ 2 + v11 ^ 2 < 0.07
if v6 * slopes > y - mountain_ground then -- if pos is in the ground
if not is_cave then
local above = math.ceil(v7 + math.random() - math.sqrt(math.abs(y)) / 3.5)
if above <= 0 then
data[ivm] = c_stone
elseif y > 0 and n6[i3d_a+80] * slopes <= y + 1 - mountain_ground and not river then
data[ivm] = c_lawn -- if node above is not in the ground, place lawn
elseif n6[i3d_a+above*80] * slopes <= y + above - mountain_ground then
data[ivm] = c_dirt
else
data[ivm] = c_stone
end
end
elseif y <= 1 or river and y - 2 <= mountain_ground then
data[ivm] = c_water
end
i3d_a = i3d_a + 80 -- increase i3d_a by one row
i3d_b = i3d_b + 80 -- increase i3d_b by one row
end
i2d = i2d + 80 -- increase i2d by one row
i3d_a = i3d_a + 480 -- avoid the 6 supplemental lines
end
i2d = i2d - 6399 -- i2d = 6401 after the first execution of this loop, it must be 2 before the second.
i3d_a = i3d_a - 550399 -- i3d_a = 550401 after the first execution of this loop, it must be 2 before the second.
i3d_b = i3d_b - 511999 -- i3d_b = 512001 after the first execution of this loop, it must be 2 before the second.
end
local t3 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data collecting finished in " .. displaytime(t3-t2))
print("[Valleys Mapgen] Writing data ...")
end
-- execute voxelmanip boring stuff to write to the map
vm:set_data(data)
vm:set_lighting({day = 0, night = 0})
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
vm = minetest.get_voxel_manip()
vm:read_from_map(minp, maxp)
minetest.generate_ores(vm) -- Thank you kwolekr ! I can generate the ores in 1 line ! And so it's compatible with moreores and other mods which add ores.
vm:write_to_map()
local t4 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data writing finished in " .. displaytime(t4-t3))
end
if vmg.loglevel >= 1 then
print("[Valleys Mapgen] Mapgen finished in " .. displaytime(t4-t0))
end
end
vmg.noises_obj = {}
for i, n in ipairs(vmg.noises) do
vmg.noises_obj[i] = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
end
function vmg.get_noise(pos, i)
local n = vmg.noises[i]
local noise = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
if not pos.z then
return noise:get2d({x = pos.x / n.spread.x, y = pos.y / n.spread.y}) * n.scale + n.offset
else
return noise:get3d({x = pos.x / n.spread.x, y = pos.y / n.spread.y, z = pos.z / n.spread.z}) * n.scale + n.offset
end
end
local function round(n)
return math.floor(n + 0.5)
end
function vmg.get_elevation(pos)
local v1 = vmg.get_noise(pos, 1)
local v2 = vmg.get_noise(pos, 2)
local v3 = vmg.get_noise(pos, 3) ^ 2
local v4 = vmg.get_noise(pos, 4)
local v5 = vmg.get_noise(pos, 5)
local base_ground = v1 + v3
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2))
local mountain_ground = base_ground + valleys
local pos = pos3d(pos, round(mountain_ground))
local slopes = v5 * valleys
if vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground then
pos.y = pos.y + 1
while vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground do
pos.y = pos.y + 1
end
return pos.y
else
pos.y = pos.y - 1
while vmg.get_noise(pos, 6) * slopes <= pos.y - mountain_ground do
pos.y = pos.y - 1
end
return pos.y
end
end
function vmg.spawnplayer(player)
local pos = {x = 0, y = 0}
local angle = math.random() * math.pi * 2
local p_angle = {x = math.cos(angle), y = math.sin(angle)}
local elevation = vmg.get_elevation(pos)
while elevation < 2 do
pos.x = pos.x + p_angle.x
pos.y = pos.y + p_angle.y
elevation = vmg.get_elevation({x = round(pos.x), y = round(pos.y)})
end
pos = {x = round(pos.x), y = round(elevation + 1), z = round(pos.y)}
player:setpos(pos)
return true
end

View File

@ -0,0 +1,251 @@
-- Mapgen 1.2
-- Tuesday March 17, 2015
vmg.noises = {
-- Noise 1 : Base Ground Height 2D
{offset = -10, scale = 50, seed = 5202, spread = {x = 1024, y = 1024, z = 1024}, octaves = 6, persist = 0.4, lacunarity = 2},
-- Noise 2 : Valleys (River where around zero) 2D
{offset = 0, scale = 1, seed = -6050, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.6, lacunarity = 2},
-- Noise 3 : Valleys Depth 2D
{offset = 5, scale = 4, seed = -1914, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 4 : Valleys Profile (Higher values = Larger valleys) 2D
{offset = 0.6, scale = 0.5, seed = 777, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 5 : Inter-valleys slopes 2D
{offset = 0.5, scale = 0.5, seed = 746, spread = {x = 128, y = 128, z = 128}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 6 : Inter-valleys filling 3D
{offset = 0, scale = 1, seed = 1993, spread = {x = 256, y = 512, z = 256}, octaves = 6, persist = 0.8, lacunarity = 2},
-- Noise 7 : Dirt thickness 2D
{offset = 3, scale = 1.75, seed = 1605, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
-- Noise 8 : Caves I 3D
{offset = 0, scale = 1, seed = -4640, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 9 : Caves II 3D
{offset = 0, scale = 1, seed = 8804, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 10 : Caves III 3D
{offset = 0, scale = 1, seed = -4780, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 11 : Caves IV and Lava I 3D
{offset = 0, scale = 1, seed = -9969, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 12 : Lava II 3D
{offset = 0, scale = 1, seed = 3314, spread = {x = 64, y = 64, z = 64}, octaves = 4, persist = 0.5, lacunarity = 2},
}
function vmg.noisemap(i, minp, chulens)
local obj = minetest.get_perlin_map(vmg.noises[i], chulens)
if minp.z then
return obj:get3dMap_flat(minp)
else
return obj:get2dMap_flat(minp)
end
end
for i, n in ipairs(vmg.noises) do
vmg.noises[i] = vmg.define("noise_" .. i, n)
end
local average_stone_level = vmg.define("average_stone_level", 180)
local dirt_thickness = math.sqrt(average_stone_level) / (vmg.noises[7].offset + 0.5)
local river_size = vmg.define("river_size", 5) / 100
local caves_size = vmg.define("caves_size", 7) / 100
local lava_depth = vmg.define("lava_depth", 2000)
local surface_lava = vmg.define("surface_lava", false)
local player_max_distance = vmg.define("player_max_distance", 450)
function vmg.generate(minp, maxp, seed)
local minps, maxps = minetest.pos_to_string(minp), minetest.pos_to_string(maxp)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Preparing to generate map from " .. minps .. " to " .. maxps .. " ...")
elseif vmg.loglevel == 1 then
print("[Valleys Mapgen] Generating map from " .. minps .. " to " .. maxps .. " ...")
end
local t0 = os.clock()
local c_dirt = minetest.get_content_id("default:dirt")
local c_stone = minetest.get_content_id("default:stone")
local c_lawn = minetest.get_content_id("default:dirt_with_grass")
local c_water = minetest.get_content_id("default:water_source")
local c_lava = minetest.get_content_id("default:lava_source")
local c_air = minetest.get_content_id("air")
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local chulens = vector.add(vector.subtract(maxp, minp), 1)
local chulens_sup = {x = chulens.x, y = chulens.y + 6, z = chulens.z}
local minp2d = pos2d(minp)
local t1 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Mapgen preparation finished in " .. displaytime(t1-t0))
print("[Valleys Mapgen] Calculating noises ...")
end
local n1 = vmg.noisemap(1, minp2d, chulens)
local n2 = vmg.noisemap(2, minp2d, chulens)
local n3 = vmg.noisemap(3, minp2d, chulens)
local n4 = vmg.noisemap(4, minp2d, chulens)
local n5 = vmg.noisemap(5, minp2d, chulens)
local n6 = vmg.noisemap(6, minp, chulens_sup)
local n7 = vmg.noisemap(7, minp2d, chulens)
local n8 = vmg.noisemap(8, minp, chulens)
local n9 = vmg.noisemap(9, minp, chulens)
local n10 = vmg.noisemap(10, minp, chulens)
local n11 = vmg.noisemap(11, minp, chulens)
local n12 = vmg.noisemap(12, minp, chulens)
local t2 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Noises calculation finished in " .. displaytime(t2-t1))
print("[Valleys Mapgen] Collecting data ...")
end
local i2d = 1 -- index for 2D noises
local i3d_a = 1 -- index for noise 6 which has a special size
local i3d_b = 1 -- index for 3D noises
for x = minp.x, maxp.x do -- for each east-west and bottom-top plane
for z = minp.z, maxp.z do -- for each vertical row in this plane
local v1, v2, v3, v4, v5, v7 = n1[i2d], n2[i2d], n3[i2d], n4[i2d], n5[i2d], n7[i2d] -- n for noise, v for value
v3 = v3 ^ 2 -- v3 must be > 0 and by the square there are high mountains but the median valleys depth is small.
local base_ground = v1 + v3 -- v3 is here because terrain is generally higher when valleys are deep (mountains)
local river = math.abs(v2) < river_size
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2)) -- use the curve of the function 1exp((x/a)²) to modelise valleys. Making "a" varying 0 < a ≤ 1 will change the shape of the valleys. v2 = x and v4 = a.
local mountain_ground = base_ground + valleys
local slopes = v5 * valleys
if river then
mountain_ground = math.min(math.max(base_ground - 3, -5), mountain_ground)
slopes = 0
end
for y = minp.y, maxp.y do -- for each node in vertical row
local ivm = a:index(x, y, z)
local v6, v8, v9, v10, v11, v12 = n6[i3d_a], n8[i3d_b], n9[i3d_b], n10[i3d_b], n11[i3d_b], n12[i3d_b]
local is_cave = v8 ^ 2 + v9 ^ 2 + v10 ^ 2 + v11 ^ 2 < caves_size
if v6 * slopes > y - mountain_ground then -- if pos is in the ground
if not is_cave then
local above = math.ceil(
v7 + math.random() - math.sqrt(math.abs(y)) / dirt_thickness
)
if above <= 0 then
data[ivm] = c_stone
elseif y > 0 and n6[i3d_a+80] * slopes <= y + 1 - mountain_ground and not river then
data[ivm] = c_lawn -- if node above is not in the ground, place lawn
elseif n6[i3d_a+above*80] * slopes <= y + above - mountain_ground then
data[ivm] = c_dirt
else
data[ivm] = c_stone
end
elseif v11 + v12 > 2 ^ (y / lava_depth) and (surface_lava or y < 0) then
data[ivm] = c_lava
end
elseif y <= 1 or river and y - 2 <= mountain_ground then
data[ivm] = c_water
end
i3d_a = i3d_a + 80 -- increase i3d_a by one row
i3d_b = i3d_b + 80 -- increase i3d_b by one row
end
i2d = i2d + 80 -- increase i2d by one row
i3d_a = i3d_a + 480 -- avoid the 6 supplemental lines
end
i2d = i2d - 6399 -- i2d = 6401 after the first execution of this loop, it must be 2 before the second.
i3d_a = i3d_a - 550399 -- i3d_a = 550401 after the first execution of this loop, it must be 2 before the second.
i3d_b = i3d_b - 511999 -- i3d_b = 512001 after the first execution of this loop, it must be 2 before the second.
end
local t3 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data collecting finished in " .. displaytime(t3-t2))
print("[Valleys Mapgen] Writing data ...")
end
-- execute voxelmanip boring stuff to write to the map
vm:set_data(data)
minetest.generate_ores(vm, minp, maxp)
vm:set_lighting({day = 0, night = 0})
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
local t4 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data writing finished in " .. displaytime(t4-t3))
end
if vmg.loglevel >= 1 then
print("[Valleys Mapgen] Mapgen finished in " .. displaytime(t4-t0))
end
end
vmg.noises_obj = {}
for i, n in ipairs(vmg.noises) do
vmg.noises_obj[i] = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
end
function vmg.get_noise(pos, i)
local n = vmg.noises[i]
local noise = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
if not pos.z then
return noise:get2d({x = pos.x / n.spread.x, y = pos.y / n.spread.y}) * n.scale + n.offset
else
return noise:get3d({x = pos.x / n.spread.x, y = pos.y / n.spread.y, z = pos.z / n.spread.z}) * n.scale + n.offset
end
end
local function round(n)
return math.floor(n + 0.5)
end
function vmg.get_elevation(pos)
local v1 = vmg.get_noise(pos, 1)
local v2 = vmg.get_noise(pos, 2)
local v3 = vmg.get_noise(pos, 3) ^ 2
local v4 = vmg.get_noise(pos, 4)
local v5 = vmg.get_noise(pos, 5)
local base_ground = v1 + v3
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2))
local mountain_ground = base_ground + valleys
local pos = pos3d(pos, round(mountain_ground))
local slopes = v5 * valleys
if vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground then
pos.y = pos.y + 1
while vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground do
pos.y = pos.y + 1
end
return pos.y
else
pos.y = pos.y - 1
while vmg.get_noise(pos, 6) * slopes <= pos.y - mountain_ground do
pos.y = pos.y - 1
end
return pos.y
end
end
function vmg.spawnplayer(player)
local angle = math.random() * math.pi * 2
local distance = math.random() * player_max_distance
local p_angle = {x = math.cos(angle), y = math.sin(angle)}
local pos = {x = -p_angle.x * distance, y = -p_angle.y * distance}
local elevation = vmg.get_elevation(pos)
while elevation < 3 or math.abs(vmg.get_noise(pos, 2)) < river_size do
pos.x = pos.x + p_angle.x
pos.y = pos.y + p_angle.y
elevation = vmg.get_elevation({x = round(pos.x), y = round(pos.y)})
end
pos = {x = round(pos.x), y = round(elevation + 1), z = round(pos.y)}
player:setpos(pos)
return true
end

View File

@ -0,0 +1,328 @@
-- Mapgen 1.3
-- Wednesday April 8, 2015
vmg.noises = {
-- Noise 1 : Base Ground Height 2D
{offset = -10, scale = 50, seed = 5202, spread = {x = 1024, y = 1024, z = 1024}, octaves = 6, persist = 0.4, lacunarity = 2},
-- Noise 2 : Valleys (River where around zero) 2D
{offset = 0, scale = 1, seed = -6050, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.6, lacunarity = 2},
-- Noise 3 : Valleys Depth 2D
{offset = 5, scale = 4, seed = -1914, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 4 : Valleys Profile (Higher values = Larger valleys) 2D
{offset = 0.6, scale = 0.5, seed = 777, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 5 : Inter-valleys slopes 2D
{offset = 0.5, scale = 0.5, seed = 746, spread = {x = 128, y = 128, z = 128}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 6 : Inter-valleys filling 3D
{offset = 0, scale = 1, seed = 1993, spread = {x = 256, y = 512, z = 256}, octaves = 6, persist = 0.8, lacunarity = 2},
-- Noise 7 : Dirt thickness 2D
{offset = 3, scale = 1.75, seed = 1605, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
-- Noise 8 : Caves I 3D
{offset = 0, scale = 1, seed = -4640, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 9 : Caves II 3D
{offset = 0, scale = 1, seed = 8804, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 10 : Caves III 3D
{offset = 0, scale = 1, seed = -4780, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 11 : Caves IV and Lava I 3D
{offset = 0, scale = 1, seed = -9969, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 12 : Lava II 3D
{offset = 0, scale = 1, seed = 3314, spread = {x = 64, y = 64, z = 64}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 13 : Clayey dirt noise 2D
{offset = 0, scale = 1, seed = 2835, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 14 : Silty dirt noise 2D
{offset = 0, scale = 1, seed = 6674, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 15 : Sandy dirt noise 2D
{offset = 0, scale = 1, seed = 6940, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 16 : Beaches 2D
{offset = 2, scale = 8, seed = 2349, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
}
function vmg.noisemap(i, minp, chulens)
local obj = minetest.get_perlin_map(vmg.noises[i], chulens)
if minp.z then
return obj:get3dMap_flat(minp)
else
return obj:get2dMap_flat(minp)
end
end
for i, n in ipairs(vmg.noises) do
vmg.noises[i] = vmg.define("noise_" .. i, n)
end
local average_stone_level = vmg.define("average_stone_level", 180)
local dirt_thickness = math.sqrt(average_stone_level) / (vmg.noises[7].offset + 0.5)
local river_size = vmg.define("river_size", 5) / 100
local caves_size = vmg.define("caves_size", 7) / 100
local lava_depth = vmg.define("lava_depth", 2000)
local surface_lava = vmg.define("surface_lava", false)
local player_max_distance = vmg.define("player_max_distance", 450)
local clay_threshold = vmg.define("clay_threshold", 1)
local silt_threshold = vmg.define("silt_threshold", 1)
local sand_threshold = vmg.define("sand_threshold", 0.75)
local dirt_threshold = vmg.define("dirt_threshold", 0.5)
local water_level = vmg.define("water_level", 1)
function vmg.generate(minp, maxp, seed)
local minps, maxps = minetest.pos_to_string(minp), minetest.pos_to_string(maxp)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Preparing to generate map from " .. minps .. " to " .. maxps .. " ...")
elseif vmg.loglevel == 1 then
print("[Valleys Mapgen] Generating map from " .. minps .. " to " .. maxps .. " ...")
end
local t0 = os.clock()
local c_stone = minetest.get_content_id("default:stone")
local c_dirt = minetest.get_content_id("default:dirt")
local c_lawn = minetest.get_content_id("default:dirt_with_grass")
local c_dirt_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey")
local c_lawn_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_grass")
local c_dirt_silt = minetest.get_content_id("valleys_mapgen:dirt_silty")
local c_lawn_silt = minetest.get_content_id("valleys_mapgen:dirt_silty_with_grass")
local c_dirt_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy")
local c_lawn_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_grass")
local c_desert_sand = minetest.get_content_id("default:desert_sand")
local c_sand = minetest.get_content_id("default:sand")
local c_gravel = minetest.get_content_id("default:gravel")
local c_silt = minetest.get_content_id("valleys_mapgen:silt")
local c_clay = minetest.get_content_id("valleys_mapgen:red_clay")
local c_water = minetest.get_content_id("default:water_source")
local c_lava = minetest.get_content_id("default:lava_source")
local c_air = minetest.get_content_id("air")
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local chulens = vector.add(vector.subtract(maxp, minp), 1)
local chulens_sup = {x = chulens.x, y = chulens.y + 6, z = chulens.z}
local minp2d = pos2d(minp)
local t1 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Mapgen preparation finished in " .. displaytime(t1-t0))
print("[Valleys Mapgen] Calculating noises ...")
end
local n1 = vmg.noisemap(1, minp2d, chulens)
local n2 = vmg.noisemap(2, minp2d, chulens)
local n3 = vmg.noisemap(3, minp2d, chulens)
local n4 = vmg.noisemap(4, minp2d, chulens)
local n5 = vmg.noisemap(5, minp2d, chulens)
local n6 = vmg.noisemap(6, minp, chulens_sup)
local n7 = vmg.noisemap(7, minp2d, chulens)
local n8 = vmg.noisemap(8, minp, chulens)
local n9 = vmg.noisemap(9, minp, chulens)
local n10 = vmg.noisemap(10, minp, chulens)
local n11 = vmg.noisemap(11, minp, chulens)
local n12 = vmg.noisemap(12, minp, chulens)
local n13 = vmg.noisemap(13, minp2d, chulens)
local n14 = vmg.noisemap(14, minp2d, chulens)
local n15 = vmg.noisemap(15, minp2d, chulens)
local n16 = vmg.noisemap(16, minp2d, chulens)
local t2 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Noises calculation finished in " .. displaytime(t2-t1))
print("[Valleys Mapgen] Collecting data ...")
end
local i2d = 1 -- index for 2D noises
local i3d_a = 1 -- index for noise 6 which has a special size
local i3d_b = 1 -- index for 3D noises
for x = minp.x, maxp.x do -- for each east-west and bottom-top plane
for z = minp.z, maxp.z do -- for each vertical row in this plane
local v1, v2, v3, v4, v5, v7, v13, v14, v15, v16 = n1[i2d], n2[i2d], n3[i2d], n4[i2d], n5[i2d], n7[i2d], n13[i2d], n14[i2d], n15[i2d], n16[i2d] -- n for noise, v for value
v3 = v3 ^ 2 -- v3 must be > 0 and by the square there are high mountains but the median valleys depth is small.
local base_ground = v1 + v3 -- v3 is here because terrain is generally higher when valleys are deep (mountains)
local river = math.abs(v2) < river_size
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2)) -- use the curve of the function 1exp((x/a)²) to modelise valleys. Making "a" varying 0 < a ≤ 1 will change the shape of the valleys. v2 = x and v4 = a.
local mountain_ground = base_ground + valleys
local slopes = v5 * valleys
if river then
mountain_ground = math.min(math.max(base_ground - 3, water_level - 6), mountain_ground)
slopes = 0
end
local dirt = c_dirt
local lawn = c_lawn
local max = math.max(v13, v14, v15)
if max > dirt_threshold then
if v13 == max then
if v13 > clay_threshold then
dirt = c_clay
lawn = c_clay
else
dirt = c_dirt_clay
lawn = c_lawn_clay
end
elseif v14 == max then
if v14 > silt_threshold then
dirt = c_silt
lawn = c_silt
else
dirt = c_dirt_silt
lawn = c_lawn_silt
end
else
if v15 > sand_threshold then
dirt = c_desert_sand
lawn = c_desert_sand
else
dirt = c_dirt_sand
lawn = c_lawn_sand
end
end
end
local is_beach = v15 > 0 and v16 > 0
local beach = v15 * v16 + water_level
for y = minp.y, maxp.y do -- for each node in vertical row
local ivm = a:index(x, y, z)
local v6, v8, v9, v10, v11, v12 = n6[i3d_a], n8[i3d_b], n9[i3d_b], n10[i3d_b], n11[i3d_b], n12[i3d_b]
local is_cave = v8 ^ 2 + v9 ^ 2 + v10 ^ 2 + v11 ^ 2 < caves_size
if v6 * slopes > y - mountain_ground then -- if pos is in the ground
if not is_cave then
local above = math.ceil(
v7 + math.random() - math.sqrt(math.abs(y)) / dirt_thickness
)
if above <= 0 then
data[ivm] = c_stone
elseif y >= water_level and n6[i3d_a+80] * slopes <= y + 1 - mountain_ground and not river then
if is_beach and y < beach then
data[ivm] = c_sand
else
data[ivm] = lawn -- if node above is not in the ground, place lawn
end
elseif n6[i3d_a+above*80] * slopes <= y + above - mountain_ground then
if is_beach and y < beach then
data[ivm] = c_sand
else
data[ivm] = dirt
end
else
data[ivm] = c_stone
end
elseif v11 + v12 > 2 ^ (y / lava_depth) and (surface_lava or y < water_level - 1) then
data[ivm] = c_lava
end
elseif y <= water_level or river and y - 2 <= mountain_ground then
data[ivm] = c_water
end
i3d_a = i3d_a + 80 -- increase i3d_a by one row
i3d_b = i3d_b + 80 -- increase i3d_b by one row
end
i2d = i2d + 80 -- increase i2d by one row
i3d_a = i3d_a + 480 -- avoid the 6 supplemental lines
end
i2d = i2d - 6399 -- i2d = 6401 after the first execution of this loop, it must be 2 before the second.
i3d_a = i3d_a - 550399 -- i3d_a = 550401 after the first execution of this loop, it must be 2 before the second.
i3d_b = i3d_b - 511999 -- i3d_b = 512001 after the first execution of this loop, it must be 2 before the second.
end
local t3 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data collecting finished in " .. displaytime(t3-t2))
print("[Valleys Mapgen] Writing data ...")
end
-- execute voxelmanip boring stuff to write to the map
vm:set_data(data)
minetest.generate_ores(vm, minp, maxp)
vm:set_lighting({day = 0, night = 0})
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
local t4 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data writing finished in " .. displaytime(t4-t3))
end
if vmg.loglevel >= 1 then
print("[Valleys Mapgen] Mapgen finished in " .. displaytime(t4-t0))
end
end
vmg.noises_obj = {}
for i, n in ipairs(vmg.noises) do
vmg.noises_obj[i] = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
end
function vmg.get_noise(pos, i)
local n = vmg.noises[i]
local noise = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
if not pos.z then
return noise:get2d({x = pos.x / n.spread.x, y = pos.y / n.spread.y}) * n.scale + n.offset
else
return noise:get3d({x = pos.x / n.spread.x, y = pos.y / n.spread.y, z = pos.z / n.spread.z}) * n.scale + n.offset
end
end
local function round(n)
return math.floor(n + 0.5)
end
function vmg.get_elevation(pos)
local v1 = vmg.get_noise(pos, 1)
local v2 = vmg.get_noise(pos, 2)
local v3 = vmg.get_noise(pos, 3) ^ 2
local v4 = vmg.get_noise(pos, 4)
local v5 = vmg.get_noise(pos, 5)
local base_ground = v1 + v3
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2))
local mountain_ground = base_ground + valleys
local pos = pos3d(pos, round(mountain_ground))
local slopes = v5 * valleys
if vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground then
pos.y = pos.y + 1
while vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground do
pos.y = pos.y + 1
end
return pos.y
else
pos.y = pos.y - 1
while vmg.get_noise(pos, 6) * slopes <= pos.y - mountain_ground do
pos.y = pos.y - 1
end
return pos.y
end
end
function vmg.spawnplayer(player)
local angle = math.random() * math.pi * 2
local distance = math.random() * player_max_distance
local p_angle = {x = math.cos(angle), y = math.sin(angle)}
local pos = {x = -p_angle.x * distance, y = -p_angle.y * distance}
local elevation = vmg.get_elevation(pos)
while elevation < water_level + 2 or math.abs(vmg.get_noise(pos, 2)) < river_size do
pos.x = pos.x + p_angle.x
pos.y = pos.y + p_angle.y
elevation = vmg.get_elevation({x = round(pos.x), y = round(pos.y)})
end
pos = {x = round(pos.x), y = round(elevation + 1), z = round(pos.y)}
player:setpos(pos)
return true
end

View File

@ -0,0 +1,203 @@
function default.grow_tree(pos, is_apple_tree)
local rand = math.random()
local height = math.floor(4 + 2.5 * rand)
local radius = 3 + rand
local leaves = minetest.get_content_id("default:leaves")
local trunk = minetest.get_content_id("default:tree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 4, y = pos.y, z = pos.z - 4}, {x = pos.x + 4, y = pos.y + height + 4, z = pos.z + 4})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
if is_apple_tree then
vmg.grow_apple_tree(pos, data, area, height, radius, trunk, leaves, minetest.get_content_id("default:apple"), air, ignore)
else
vmg.grow_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
end
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function default.grow_jungle_tree(pos)
local rand = math.random()
local height = math.floor(8 + 4 * rand)
local radius = 5 + 3 * rand
local leaves = minetest.get_content_id("default:jungleleaves")
local trunk = minetest.get_content_id("default:jungletree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 8, y = pos.y - 1, z = pos.z - 8}, {x = pos.x + 8, y = pos.y + height + 5, z = pos.z + 8})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
vmg.grow_jungle_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
vmg.execute_after_mapgen()
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function default.grow_pine_tree(pos)
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
local leaves = minetest.get_content_id("default:pine_needles")
local trunk = minetest.get_content_id("default:pinetree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 6, y = pos.y - 1, z = pos.z - 6}, {x = pos.x + 6, y = pos.y + height + 2, z = pos.z + 6})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
vmg.grow_pine_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function vmg.grow_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.5}
pos.y = pos.y + height - 1
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius, z = radius}, np)
end
function vmg.grow_apple_tree(pos, data, area, height, radius, trunk, leaves, fruit, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating apple tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.5}
pos.y = pos.y + height - 1
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius, z = radius}, np, 0.06, fruit)
end
local function make_jungle_root(x0, y0, z0, data, area, tree, air)
local ystride = area.ystride
local ybot = y0 - 1
for x = x0 - 1, x0 + 1 do
for z = z0 - 1, z0 + 1 do
local iv = area:index(x, ybot, z)
for i = 0, 5 do
if data[iv] == air then
if math.random() < 0.6 then
data[iv-ystride] = tree -- make jungle tree below
if math.random() < 0.6 then
data[iv] = tree -- make jungle tree at this air node
end
end
break
end
iv = iv + ystride
end
end
end
end
function vmg.grow_jungle_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating jungle tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
vmg.register_after_mapgen(make_jungle_root, pos.x, pos.y, pos.z, data, area, trunk, air)
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.8}
pos.y = pos.y + height
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius * 0.5, z = radius}, np)
end
function vmg.grow_pine_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating pine tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
-- add leaves on the top (4% 0 ; 36% 1 ; 60% 2)
local rand = math.random()
if rand < 0.96 then
data[iv] = leaves
if rand < 0.60 then
iv = iv + ystride
data[iv] = leaves
end
end
-- make several leaves rings
local max_height = pos.y + height
local min_height = pos.y + math.floor((0.2 + 0.3 * math.random()) * height)
local radius_increment = (radius - 1.2) / (max_height - min_height)
local np = {offset = 0.8, scale = 0.4, spread = {x = 12, y = 4, z = 12}, octaves = 3, persist = 0.8}
pos.y = max_height - 1
while pos.y >= min_height do
local ring_radius = (max_height - pos.y) * radius_increment + 1.2
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = ring_radius, y = 2, z = ring_radius}, np)
pos.y = pos.y - math.random(2, 3)
end
end
function vmg.make_leavesblob(pos, data, area, leaves, air, ignore, radius, np, fruit_chance, fruit)
local count = 0
fruit_chance = fruit_chance or 0
np.seed = math.random(0, 16777215)
local round_radius = {x = math.ceil(radius.x), y = math.ceil(radius.y), z = math.ceil(radius.z)}
local length = vector.multiply(round_radius, 2)
local chulens = vector.add(length, 1)
local minp = vector.subtract(pos, round_radius)
local maxp = vector.add(minp, length)
local obj = minetest.get_perlin_map(np, chulens)
local pmap = obj:get3dMap_flat(minp)
local i = 1
for x = minp.x, maxp.x do
local xval = ((x - pos.x) / radius.x) ^ 2
for y = minp.y, maxp.y do
local yval = ((y - pos.y) / radius.y) ^ 2
for z = minp.z, maxp.z do
local zval = ((z - pos.z) / radius.z) ^ 2
local dist = math.sqrt(xval + yval + zval)
local nval = pmap[i]
if nval > dist then
local iv = area:index(x, y, z)
if data[iv] == air or data[iv] == ignore then
count = count + 1
if math.random() < fruit_chance then
data[iv] = fruit
else
data[iv] = leaves
end
end
end
i = i + 1
end
end
end
end

View File

@ -0,0 +1,510 @@
-- Mapgen 2.0
-- Sunday May 31, 2015
vmg.noises = {
-- Noise 1 : Base Ground Height 2D
{offset = -10, scale = 50, seed = 5202, spread = {x = 1024, y = 1024, z = 1024}, octaves = 6, persist = 0.4, lacunarity = 2},
-- Noise 2 : Valleys (River where around zero) 2D
{offset = 0, scale = 1, seed = -6050, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.6, lacunarity = 2},
-- Noise 3 : Valleys Depth 2D
{offset = 5, scale = 4, seed = -1914, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 4 : Valleys Profile (Higher values = Larger valleys) 2D
{offset = 0.6, scale = 0.5, seed = 777, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 5 : Inter-valleys slopes 2D
{offset = 0.5, scale = 0.5, seed = 746, spread = {x = 128, y = 128, z = 128}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 6 : Inter-valleys filling 3D
{offset = 0, scale = 1, seed = 1993, spread = {x = 256, y = 512, z = 256}, octaves = 6, persist = 0.8, lacunarity = 2},
-- Noise 7 : Dirt thickness 2D
{offset = 3, scale = 1.75, seed = 1605, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
-- Noise 8 : Caves I 3D
{offset = 0, scale = 1, seed = -4640, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 9 : Caves II 3D
{offset = 0, scale = 1, seed = 8804, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 10 : Caves III 3D
{offset = 0, scale = 1, seed = -4780, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 11 : Caves IV and Lava I 3D
{offset = 0, scale = 1, seed = -9969, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 12 : Lava II (Geologic heat) 3D
{offset = 0, scale = 1, seed = 3314, spread = {x = 64, y = 64, z = 64}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 13 : Clayey dirt noise 2D
{offset = 0, scale = 1, seed = 2835, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 14 : Silty dirt noise 2D
{offset = 0, scale = 1, seed = 6674, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 15 : Sandy dirt noise 2D
{offset = 0, scale = 1, seed = 6940, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 16 : Beaches 2D
{offset = 2, scale = 8, seed = 2349, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
-- Noise 17 : Temperature (not in maps) 3D
{offset = 2, scale = 1, seed = -1805, spread = {x = 768, y = 256, z = 768}, octaves = 4, persist = 0.5, lacunarity = 4},
-- Noise 18 : Humidity 2D
{offset = 0, scale = 1, seed = -5787, spread = {x = 243, y = 243, z = 243}, octaves = 4, persist = 0.5, lacunarity = 3},
}
function vmg.noisemap(i, minp, chulens)
local obj = minetest.get_perlin_map(vmg.noises[i], chulens)
if minp.z then
return obj:get3dMap_flat(minp)
else
return obj:get2dMap_flat(minp)
end
end
for i, n in ipairs(vmg.noises) do
vmg.noises[i] = vmg.define("noise_" .. i, n)
end
vmg.after_mapgen = {}
function vmg.register_after_mapgen(f, ...)
table.insert(vmg.after_mapgen, {f = f, ...})
end
function vmg.execute_after_mapgen()
for i, params in ipairs(vmg.after_mapgen) do
params.f(unpack(params))
end
vmg.after_mapgen = {}
end
local river_size = vmg.define("river_size", 5) / 100
local caves_size = vmg.define("caves_size", 7) / 100
local lava_depth = vmg.define("lava_depth", 2000)
local lava_max_height = vmg.define("lava_max_height", -1)
local altitude_chill = vmg.define("altitude_chill", 90)
local average_stone_level = vmg.define("average_stone_level", 180)
local dirt_thickness = math.sqrt(average_stone_level) / (vmg.noises[7].offset + 0.5)
local average_snow_level = vmg.define("average_snow_level", 100)
local snow_threshold = vmg.noises[17].offset * 0.5 ^ (average_snow_level / altitude_chill)
local player_max_distance = vmg.define("player_max_distance", 450)
local clay_threshold = vmg.define("clay_threshold", 1)
local silt_threshold = vmg.define("silt_threshold", 1)
local sand_threshold = vmg.define("sand_threshold", 0.75)
local dirt_threshold = vmg.define("dirt_threshold", 0.5)
local tree_density = vmg.define("tree_density", 5) / 100
local trees = vmg.define("trees", true)
local plant_density = vmg.define("plant_density", 32) / 100
local plants = vmg.define("plants", true)
local water_level = vmg.define("water_level", 1)
function vmg.generate(minp, maxp, seed)
local minps, maxps = minetest.pos_to_string(minp), minetest.pos_to_string(maxp)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Preparing to generate map from " .. minps .. " to " .. maxps .. " ...")
elseif vmg.loglevel == 1 then
print("[Valleys Mapgen] Generating map from " .. minps .. " to " .. maxps .. " ...")
end
local t0 = os.clock()
local c_stone = minetest.get_content_id("default:stone")
local c_dirt = minetest.get_content_id("default:dirt")
local c_lawn = minetest.get_content_id("default:dirt_with_grass")
local c_snow = minetest.get_content_id("default:dirt_with_snow")
local c_dirt_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey")
local c_lawn_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_grass")
local c_snow_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_snow")
local c_dirt_silt = minetest.get_content_id("valleys_mapgen:dirt_silty")
local c_lawn_silt = minetest.get_content_id("valleys_mapgen:dirt_silty_with_grass")
local c_snow_silt = minetest.get_content_id("valleys_mapgen:dirt_silty_with_snow")
local c_dirt_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy")
local c_lawn_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_grass")
local c_snow_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_snow")
local c_desert_sand = minetest.get_content_id("default:desert_sand")
local c_sand = minetest.get_content_id("default:sand")
local c_gravel = minetest.get_content_id("default:gravel")
local c_silt = minetest.get_content_id("valleys_mapgen:silt")
local c_clay = minetest.get_content_id("valleys_mapgen:red_clay")
local c_water = minetest.get_content_id("default:water_source")
local c_lava = minetest.get_content_id("default:lava_source")
local c_snow_layer = minetest.get_content_id("default:snow")
local c_tree = minetest.get_content_id("default:tree")
local c_leaves = minetest.get_content_id("default:leaves")
local c_apple = minetest.get_content_id("default:apple")
local c_jungletree = minetest.get_content_id("default:jungletree")
local c_jungleleaves = minetest.get_content_id("default:jungleleaves")
local c_pinetree = minetest.get_content_id("default:pinetree")
local c_pineleaves = minetest.get_content_id("default:pine_needles")
local c_grass = {
minetest.get_content_id("default:grass_1"),
minetest.get_content_id("default:grass_2"),
minetest.get_content_id("default:grass_3"),
minetest.get_content_id("default:grass_4"),
minetest.get_content_id("default:grass_5"),
}
local c_junglegrass = minetest.get_content_id("default:junglegrass")
local c_dryshrub = minetest.get_content_id("default:dry_shrub")
local c_cactus = minetest.get_content_id("default:cactus")
local c_papyrus = minetest.get_content_id("default:papyrus")
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local ystride = a.ystride
local chulens = vector.add(vector.subtract(maxp, minp), 1)
local chulens_sup = {x = chulens.x, y = chulens.y + 6, z = chulens.z}
local minp2d = pos2d(minp)
local t1 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Mapgen preparation finished in " .. displaytime(t1-t0))
print("[Valleys Mapgen] Calculating noises ...")
end
local n1 = vmg.noisemap(1, minp2d, chulens)
local n2 = vmg.noisemap(2, minp2d, chulens)
local n3 = vmg.noisemap(3, minp2d, chulens)
local n4 = vmg.noisemap(4, minp2d, chulens)
local n5 = vmg.noisemap(5, minp2d, chulens)
local n6 = vmg.noisemap(6, minp, chulens_sup)
local n7 = vmg.noisemap(7, minp2d, chulens)
local n8 = vmg.noisemap(8, minp, chulens)
local n9 = vmg.noisemap(9, minp, chulens)
local n10 = vmg.noisemap(10, minp, chulens)
local n11 = vmg.noisemap(11, minp, chulens)
local n12 = vmg.noisemap(12, minp, chulens)
local n13 = vmg.noisemap(13, minp2d, chulens)
local n14 = vmg.noisemap(14, minp2d, chulens)
local n15 = vmg.noisemap(15, minp2d, chulens)
local n16 = vmg.noisemap(16, minp2d, chulens)
local n18 = vmg.noisemap(18, minp2d, chulens)
local t2 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Noises calculation finished in " .. displaytime(t2-t1))
print("[Valleys Mapgen] Collecting data ...")
end
local i2d = 1 -- index for 2D noises
local i3d_sup = 1 -- index for noise 6 which has a special size
local i3d = 1 -- index for 3D noises
-- Calculate increments
local i2d_incrZ = chulens.z
local i2d_decrX = chulens.x * chulens.z - 1
local i3d_incrY = chulens.y
local i3d_sup_incrZ = 6 * chulens.y
local i3d_decrX = chulens.x * chulens.y * chulens.z - 1
local i3d_sup_decrX = chulens.x * (chulens.y + 6) * chulens.z - 1
for x = minp.x, maxp.x do -- for each YZ plane
for z = minp.z, maxp.z do -- for each vertical line in this plane
local v1, v2, v3, v4, v5, v7, v13, v14, v15, v16, v18 = n1[i2d], n2[i2d], n3[i2d], n4[i2d], n5[i2d], n7[i2d], n13[i2d], n14[i2d], n15[i2d], n16[i2d], n18[i2d] -- n for noise, v for value
v3 = v3 ^ 2 -- v3 must be > 0 and by the square there are high mountains but the median valleys depth is small.
local base_ground = v1 + v3 -- v3 is here because terrain is generally higher when valleys are deep (mountains)
local river = math.abs(v2) < river_size
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2)) -- use the curve of the function 1exp((x/a)²) to modelise valleys. Making "a" varying 0 < a ≤ 1 will change the shape of the valleys. Try it with a geometry software ! (here x = v2 and a = v4)
local mountain_ground = base_ground + valleys
local slopes = v5 * valleys
if river then
mountain_ground = math.min(math.max(base_ground - 3, water_level - 6), mountain_ground)
slopes = 0
end
-- Choose biome
local dirt = c_dirt
local lawn = c_lawn
local snow = c_snow
local max = math.max(v13, v14, v15) -- the biome is the maximal of these 3 values, if bigger than 0.5. Else, make normal dirt.
if max > dirt_threshold then
if v13 == max then
if v13 > clay_threshold then
dirt = c_clay
lawn = c_clay
snow = c_clay
else
dirt = c_dirt_clay
lawn = c_lawn_clay
snow = c_snow_clay
end
elseif v14 == max then
if v14 > silt_threshold then
dirt = c_silt
lawn = c_silt
snow = c_silt
else
dirt = c_dirt_silt
lawn = c_lawn_silt
snow = c_snow_silt
end
else
if v15 > sand_threshold then
dirt = c_desert_sand
lawn = c_desert_sand
snow = c_desert_sand
else
dirt = c_dirt_sand
lawn = c_lawn_sand
snow = c_snow_sand
end
end
end
local is_beach = v15 > 0 and v16 > 0
local beach = v15 * v16 + water_level -- the y coordinate below which dirt is replaced by beach sand
-- raw humidity
local hraw = 2 ^ (v13 - v15 + v18 * 2)
for y = minp.y, maxp.y do -- for each node in vertical line
local ivm = a:index(x, y, z)
local v6, v8, v9, v10, v11, v12 = n6[i3d_sup], n8[i3d], n9[i3d], n10[i3d], n11[i3d], n12[i3d]
local is_cave = v8 ^ 2 + v9 ^ 2 + v10 ^ 2 + v11 ^ 2 < caves_size
if v6 * slopes > y - mountain_ground then -- if pos is in the ground
if not is_cave then
local above = math.ceil(
v7 + math.random() - math.sqrt(math.abs(y)) / dirt_thickness -- The following code will look for air at this many nodes up. If any, make dirt, else, make stone. So, it's the dirt layer thickness.
)
if y >= water_level and n6[i3d_sup+i3d_incrY] * slopes <= y + 1 - mountain_ground and not river then
if is_beach and y < beach then
data[ivm] = c_sand
else -- if node above is not in the ground, place lawn
-- calculate humidity
local sea_water = 0.5 ^ math.max((y - water_level) / 6, 0)
local river_water = 0.5 ^ math.max((y - base_ground) / 3, 0)
local water = sea_water + (1 - sea_water) * river_water
local humidity = hraw + water
local ivm2 = ivm + ystride
y = y + 1
local pos = {x = x, y = y, z = z}
local v17 = vmg.get_noise(pos, 17)
local temp -- calculate_temperature for node above
if y > 0 then
temp = v17 * 0.5 ^ (y / altitude_chill)
else
temp = v17 * 0.5 ^ (-y / altitude_chill) + 20 * (v12 + 1) * (1 - 2 ^ (y / lava_depth))
end
if temp > snow_threshold then
if above > 0 then
data[ivm] = lawn
else
data[ivm] = c_stone
end
else
if above > 0 then
data[ivm] = snow
else
data[ivm] = c_stone
end
data[ivm2] = c_snow_layer -- set node above to snow
end
if trees and math.random() < tree_density and above > 0 then -- make a tree
-- choose a tree from climatic and geological conditions
if v15 < 0.6 and temp >= 0.85 and temp < 2.3 and humidity < 3 and v16 < 2 and v14 > -0.5 and v13 < 0.8 then -- Apple Tree
local rand = math.random()
local height = math.floor(4 + 2.5 * rand)
local radius = 3 + rand
if math.random(1, 4) == 1 then
vmg.grow_apple_tree(pos, data, a, height, radius, c_tree, c_leaves, c_apple, c_air, c_ignore)
else
vmg.grow_tree(pos, data, a, height, radius, c_tree, c_leaves, c_air, c_ignore)
end
elseif v15 < 0.7 and temp >= 1.9 and humidity > 2 and v16 > 2 then -- Jungle Tree
local rand = math.random()
local height = math.floor(8 + 4 * rand)
local radius = 5 + 3 * rand
vmg.grow_jungle_tree(pos, data, a, height, radius, c_jungletree, c_jungleleaves, c_air, c_ignore)
elseif temp > 0.38 and temp < 1 and humidity > 0.9 and v15 > 0 and v15 < 0.55 then -- Pine Tree (or Fir Tree)
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
vmg.grow_pine_tree(pos, data, a, height, radius, c_pinetree, c_pineleaves, c_air, c_ignore)
end
elseif plants and math.random() < plant_density and above > 0 then -- make a plant
if temp > 1 and temp < 1.8 and water > 0.7 and humidity > 3 and v13 > -0.4 and math.random() < 0.04 then -- Papyrus
for i = 1, 4 do
data[ivm+i*ystride] = c_papyrus
end
elseif v15 < 0.65 and temp >= 0.65 and temp < 1.5 and humidity < 2.6 and v16 < 1.5 and v13 < 0.8 and math.random() < 0.7 then -- Grass
data[ivm2] = c_grass[math.random(1, 5)]
elseif v15 > -0.6 and temp >= 1.8 and humidity > 2.2 and v16 > 1.8 then -- Jungle Grass
data[ivm2] = c_junglegrass
elseif v15 > 0.6 and v15 < 0.9 and humidity < 0.5 and temp > 1.8 and math.random() < 0.2 then
if v16 < 0 and math.random() < 0.12 then -- Cactus
for i = 1, 4 do
data[ivm+i*ystride] = c_cactus
end
else -- Dry Shrub
data[ivm2] = c_dryshrub
end
end
end
y = y - 1
end
elseif above <= 0 then
data[ivm] = c_stone
elseif n6[i3d_sup+above*i3d_incrY] * slopes <= y + above - mountain_ground then -- if node at "above" nodes up is not in the ground, make dirt
if is_beach and y < beach then
data[ivm] = c_sand
else
data[ivm] = dirt
end
else
data[ivm] = c_stone
end
elseif v11 + v12 > 2 ^ (y / lava_depth) and y <= lava_max_height then
data[ivm] = c_lava
end
elseif y <= water_level or river and y - 2 <= mountain_ground then -- if pos is not in the ground, and below water_level, it's an ocean
data[ivm] = c_water
end
i3d = i3d + i3d_incrY -- increment i3d by one line
i3d_sup = i3d_sup + i3d_incrY -- idem
end
i2d = i2d + i2d_incrZ -- increment i2d by one Z
-- useless to increment i3d, because increment would be 0 !
i3d_sup = i3d_sup + i3d_sup_incrZ -- for i3d_sup, just avoid the 6 supplemental lines
end
i2d = i2d - i2d_decrX -- decrement the Z line previously incremented and increment by one X (1)
i3d = i3d - i3d_decrX -- decrement the YZ plane previously incremented and increment by one X (1)
i3d_sup = i3d_sup - i3d_sup_decrX -- idem, including the supplemental lines
end
vmg.execute_after_mapgen() -- needed for jungletree roots
local t3 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data collecting finished in " .. displaytime(t3-t2))
print("[Valleys Mapgen] Writing data ...")
end
-- execute voxelmanip boring stuff to write to the map
vm:set_data(data)
minetest.generate_ores(vm, minp, maxp)
vm:set_lighting({day = 0, night = 0})
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
local t4 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data writing finished in " .. displaytime(t4-t3))
end
if vmg.loglevel >= 1 then
print("[Valleys Mapgen] Mapgen finished in " .. displaytime(t4-t0))
end
end
dofile(vmg.path .. "/old_mapgens/2.0-trees.lua")
function vmg.get_humidity_raw(pos)
local v13 = vmg.get_noise(pos, 13)
local v15 = vmg.get_noise(pos, 15)
local v18 = vmg.get_noise(pos, 18)
return 2 ^ (v13 - v15 + v18 * 2)
end
function vmg.get_humidity(pos)
local y = pos.y
local flatpos = pos2d(pos)
local hraw = vmg.get_humidity_raw(flatpos)
local v1 = vmg.get_noise(flatpos, 1)
local v3 = vmg.get_noise(flatpos, 3) ^ 2
local base_ground = v1 + v3
local sea_water = 0.5 ^ math.max((y - water_level) / 6, 0)
local river_water = 0.5 ^ math.max((y - base_ground) / 3, 0)
local water = sea_water + (1 - sea_water) * river_water
return hraw + water
end
function vmg.get_temperature(pos)
local v12 = vmg.get_noise(pos, 12) + 1
local v17 = vmg.get_noise(pos, 17)
local y = pos.y
if y > 0 then
return v17 * 0.5 ^ (y / altitude_chill)
else
return v17 * 0.5 ^ (-y / altitude_chill) + 20 * v12 * (1 - 2 ^ (y / lava_depth))
end
end
function vmg.get_noise(pos, i)
local n = vmg.noises[i]
local noise = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
if not pos.z then
return noise:get2d({x = pos.x / n.spread.x, y = pos.y / n.spread.y}) * n.scale + n.offset
else
return noise:get3d({x = pos.x / n.spread.x, y = pos.y / n.spread.y, z = pos.z / n.spread.z}) * n.scale + n.offset
end
end
local function round(n)
return math.floor(n + 0.5)
end
function vmg.get_elevation(pos)
local v1 = vmg.get_noise(pos, 1)
local v2 = vmg.get_noise(pos, 2)
local v3 = vmg.get_noise(pos, 3) ^ 2
local v4 = vmg.get_noise(pos, 4)
local v5 = vmg.get_noise(pos, 5)
local base_ground = v1 + v3
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2))
local mountain_ground = base_ground + valleys
local pos = pos3d(pos, round(mountain_ground))
local slopes = v5 * valleys
if vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground then
pos.y = pos.y + 1
while vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground do
pos.y = pos.y + 1
end
return pos.y
else
pos.y = pos.y - 1
while vmg.get_noise(pos, 6) * slopes <= pos.y - mountain_ground do
pos.y = pos.y - 1
end
return pos.y
end
end
function vmg.spawnplayer(player)
local angle = math.random() * math.pi * 2
local distance = math.random() * player_max_distance
local p_angle = {x = math.cos(angle), y = math.sin(angle)}
local pos = {x = -p_angle.x * distance, y = -p_angle.y * distance}
local elevation = vmg.get_elevation(pos)
while elevation < water_level + 2 or math.abs(vmg.get_noise(pos, 2)) < river_size do
pos.x = pos.x + p_angle.x
pos.y = pos.y + p_angle.y
elevation = vmg.get_elevation({x = round(pos.x), y = round(pos.y)})
end
pos = {x = round(pos.x), y = round(elevation + 1), z = round(pos.y)}
player:setpos(pos)
return true
end

View File

@ -0,0 +1,287 @@
local function can_grow(pos) -- from default mod
local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
if not node_under then
return false
end
local name_under = node_under.name
local is_soil = minetest.get_item_group(name_under, "soil")
if is_soil == 0 then
return false
end
return true
end
minetest.register_abm({
nodenames = {"valleys_mapgen:fir_sapling"},
interval = 14,
chance = 50,
action = function(pos, node)
if not can_grow(pos) then
return
end
minetest.log("action", "A fir sapling grows into a tree at "..
minetest.pos_to_string(pos))
vmg.grow_fir_tree(pos)
end
})
function default.grow_tree(pos, is_apple_tree)
local rand = math.random()
local height = math.floor(4 + 2.5 * rand)
local radius = 3 + rand
local leaves = minetest.get_content_id("default:leaves")
local trunk = minetest.get_content_id("default:tree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 4, y = pos.y, z = pos.z - 4}, {x = pos.x + 4, y = pos.y + height + 4, z = pos.z + 4})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
if is_apple_tree then
vmg.make_apple_tree(pos, data, area, height, radius, trunk, leaves, minetest.get_content_id("default:apple"), air, ignore)
else
vmg.make_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
end
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function default.grow_jungle_tree(pos)
local rand = math.random()
local height = math.floor(8 + 4 * rand)
local radius = 5 + 3 * rand
local leaves = minetest.get_content_id("default:jungleleaves")
local trunk = minetest.get_content_id("default:jungletree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 8, y = pos.y - 1, z = pos.z - 8}, {x = pos.x + 8, y = pos.y + height + 5, z = pos.z + 8})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
vmg.make_jungle_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
vmg.execute_after_mapgen()
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function default.grow_pine_tree(pos)
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
local leaves = minetest.get_content_id("default:pine_needles")
local trunk = minetest.get_content_id("default:pinetree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 6, y = pos.y - 1, z = pos.z - 6}, {x = pos.x + 6, y = pos.y + height + 2, z = pos.z + 6})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
vmg.make_pine_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function vmg.grow_fir_tree(pos)
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
local leaves = minetest.get_content_id("valleys_mapgen:fir_needles")
local trunk = minetest.get_content_id("valleys_mapgen:fir_tree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 6, y = pos.y - 1, z = pos.z - 6}, {x = pos.x + 6, y = pos.y + height + 2, z = pos.z + 6})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
vmg.make_fir_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function vmg.make_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.5}
pos.y = pos.y + height - 1
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius, z = radius}, np)
end
function vmg.make_apple_tree(pos, data, area, height, radius, trunk, leaves, fruit, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating apple tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.5}
pos.y = pos.y + height - 1
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius, z = radius}, np, 0.06, fruit)
end
local function make_jungle_root(x0, y0, z0, data, area, tree, air)
local ystride = area.ystride
local ybot = y0 - 1
for x = x0 - 1, x0 + 1 do
for z = z0 - 1, z0 + 1 do
local iv = area:index(x, ybot, z)
for i = 0, 5 do
if data[iv] == air then
if math.random() < 0.6 then
data[iv-ystride] = tree -- make jungle tree below
if math.random() < 0.6 then
data[iv] = tree -- make jungle tree at this air node
end
end
break
end
iv = iv + ystride
end
end
end
end
function vmg.make_jungle_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating jungle tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
vmg.register_after_mapgen(make_jungle_root, pos.x, pos.y, pos.z, data, area, trunk, air)
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.8}
pos.y = pos.y + height
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius * 0.5, z = radius}, np)
end
function vmg.make_fir_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating fir tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
-- add leaves on the top (4% 0 ; 36% 1 ; 60% 2)
local rand = math.random()
if rand < 0.96 then
data[iv] = leaves
if rand < 0.60 then
iv = iv + ystride
data[iv] = leaves
end
end
-- make several leaves rings
local max_height = pos.y + height
local min_height = pos.y + math.floor((0.2 + 0.3 * math.random()) * height)
local radius_increment = (radius - 1.2) / (max_height - min_height)
local np = {offset = 0.8, scale = 0.4, spread = {x = 12, y = 4, z = 12}, octaves = 3, persist = 0.8}
pos.y = max_height - 1
while pos.y >= min_height do
local ring_radius = (max_height - pos.y) * radius_increment + 1.2
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = ring_radius, y = 2, z = ring_radius}, np)
pos.y = pos.y - math.random(2, 3)
end
end
function vmg.make_pine_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating pine tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
-- add leaves on the top (4% 0 ; 36% 1 ; 60% 2)
local rand = math.random()
if rand < 0.96 then
data[iv] = leaves
if rand < 0.60 then
iv = iv + ystride
data[iv] = leaves
end
end
local np = {offset = 0.8, scale = 0.3, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 1}
local min_height = pos.y + math.floor((0.4 + 0.2 * math.random()) * height)
local midradius = radius / 2
pos.y = pos.y + height - 1
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = 1.5, z = radius}, np)
while pos.y >= min_height do
local angle, distance = math.random() * 2 * math.pi, math.random() * midradius
local cos, sin = math.cos(angle) * distance, math.sin(angle) * distance
local bpos = {x = pos.x + cos, y = pos.y, z = pos.z + sin}
vmg.make_leavesblob(bpos, data, area, leaves, air, ignore, {x = midradius, y = 1.5, z = midradius}, np)
pos.y = pos.y - math.random(1, 2)
end
end
function vmg.make_leavesblob(pos, data, area, leaves, air, ignore, radius, np, fruit_chance, fruit)
local count = 0
fruit_chance = fruit_chance or 0
np.seed = math.random(0, 16777215)
local minp = vector.subtract(pos, radius)
local maxp = vector.add(pos, radius)
local int_minp = {x = math.floor(minp.x), y = math.floor(minp.y), z = math.floor(minp.z)}
local int_maxp = {x = math.ceil(maxp.x), y = math.ceil(maxp.y), z = math.ceil(maxp.z)}
local length = vector.subtract(int_maxp, int_minp)
local chulens = vector.add(length, 1)
local obj = minetest.get_perlin_map(np, chulens)
local pmap = obj:get3dMap_flat(minp)
local i = 1
for x = int_minp.x, int_maxp.x do
local xval = ((x - pos.x) / radius.x) ^ 2
for y = int_minp.y, int_maxp.y do
local yval = ((y - pos.y) / radius.y) ^ 2
for z = int_minp.z, int_maxp.z do
local zval = ((z - pos.z) / radius.z) ^ 2
local dist = math.sqrt(xval + yval + zval)
local nval = pmap[i]
if nval > dist then
local iv = area:index(x, y, z)
if data[iv] == air or data[iv] == ignore then
count = count + 1
if math.random() < fruit_chance then
data[iv] = fruit
else
data[iv] = leaves
end
end
end
i = i + 1
end
end
end
end

View File

@ -0,0 +1,532 @@
-- Mapgen 2.1
-- Saturday July 4, 2015
vmg.noises = {
-- Noise 1 : Base Ground Height 2D
{offset = -10, scale = 50, seed = 5202, spread = {x = 1024, y = 1024, z = 1024}, octaves = 6, persist = 0.4, lacunarity = 2},
-- Noise 2 : Valleys (River where around zero) 2D
{offset = 0, scale = 1, seed = -6050, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.6, lacunarity = 2},
-- Noise 3 : Valleys Depth 2D
{offset = 5, scale = 4, seed = -1914, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 4 : Valleys Profile (Higher values = Larger valleys) 2D
{offset = 0.6, scale = 0.5, seed = 777, spread = {x = 512, y = 512, z = 512}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 5 : Inter-valleys slopes 2D
{offset = 0.5, scale = 0.5, seed = 746, spread = {x = 128, y = 128, z = 128}, octaves = 1, persist = 1, lacunarity = 2},
-- Noise 6 : Inter-valleys filling 3D
{offset = 0, scale = 1, seed = 1993, spread = {x = 256, y = 512, z = 256}, octaves = 6, persist = 0.8, lacunarity = 2},
-- Noise 7 : Dirt thickness 2D
{offset = 3, scale = 1.75, seed = 1605, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
-- Noise 8 : Caves I 3D
{offset = 0, scale = 1, seed = -4640, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 9 : Caves II 3D
{offset = 0, scale = 1, seed = 8804, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 10 : Caves III 3D
{offset = 0, scale = 1, seed = -4780, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 11 : Caves IV and Lava I 3D
{offset = 0, scale = 1, seed = -9969, spread = {x = 32, y = 32, z = 32}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 12 : Lava II (Geologic heat) 3D
{offset = 0, scale = 1, seed = 3314, spread = {x = 64, y = 64, z = 64}, octaves = 4, persist = 0.5, lacunarity = 2},
-- Noise 13 : Clayey dirt noise 2D
{offset = 0, scale = 1, seed = 2835, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 14 : Silty dirt noise 2D
{offset = 0, scale = 1, seed = 6674, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 15 : Sandy dirt noise 2D
{offset = 0, scale = 1, seed = 6940, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4},
-- Noise 16 : Beaches 2D
{offset = 2, scale = 8, seed = 2349, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2},
-- Noise 17 : Temperature (not in maps) 3D
{offset = 2, scale = 1, seed = -1805, spread = {x = 768, y = 256, z = 768}, octaves = 4, persist = 0.5, lacunarity = 4},
-- Noise 18 : Humidity 2D
{offset = 0, scale = 1, seed = -5787, spread = {x = 243, y = 243, z = 243}, octaves = 4, persist = 0.5, lacunarity = 3},
}
function vmg.noisemap(i, minp, chulens)
local obj = minetest.get_perlin_map(vmg.noises[i], chulens)
if minp.z then
return obj:get3dMap_flat(minp)
else
return obj:get2dMap_flat(minp)
end
end
for i, n in ipairs(vmg.noises) do
vmg.noises[i] = vmg.define("noise_" .. i, n)
end
vmg.after_mapgen = {}
function vmg.register_after_mapgen(f, ...)
table.insert(vmg.after_mapgen, {f = f, ...})
end
function vmg.execute_after_mapgen()
for i, params in ipairs(vmg.after_mapgen) do
params.f(unpack(params))
end
vmg.after_mapgen = {}
end
local river_depth = vmg.define("river_depth", 3) + 1
local river_size = vmg.define("river_size", 5) / 100
local caves_size = vmg.define("caves_size", 7) / 100
local lava_depth = vmg.define("lava_depth", 2000)
local lava_max_height = vmg.define("lava_max_height", -1)
local altitude_chill = vmg.define("altitude_chill", 90)
local average_stone_level = vmg.define("average_stone_level", 180)
local dirt_thickness = math.sqrt(average_stone_level) / (vmg.noises[7].offset + 0.5)
local average_snow_level = vmg.define("average_snow_level", 100)
local snow_threshold = vmg.noises[17].offset * 0.5 ^ (average_snow_level / altitude_chill)
local player_max_distance = vmg.define("player_max_distance", 450)
local clay_threshold = vmg.define("clay_threshold", 1)
local silt_threshold = vmg.define("silt_threshold", 1)
local sand_threshold = vmg.define("sand_threshold", 0.75)
local dirt_threshold = vmg.define("dirt_threshold", 0.5)
local tree_density = vmg.define("tree_density", 5) / 100
local trees = vmg.define("trees", true)
local plant_density = vmg.define("plant_density", 32) / 100
local plants = vmg.define("plants", true)
local water_level = vmg.define("water_level", 1)
local river_water = vmg.define("river_water", true)
function vmg.generate(minp, maxp, seed)
local minps, maxps = minetest.pos_to_string(minp), minetest.pos_to_string(maxp)
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Preparing to generate map from " .. minps .. " to " .. maxps .. " ...")
elseif vmg.loglevel == 1 then
print("[Valleys Mapgen] Generating map from " .. minps .. " to " .. maxps .. " ...")
end
local t0 = os.clock()
local c_stone = minetest.get_content_id("default:stone")
local c_dirt = minetest.get_content_id("default:dirt")
local c_lawn = minetest.get_content_id("default:dirt_with_grass")
local c_snow = minetest.get_content_id("default:dirt_with_snow")
local c_dirt_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey")
local c_lawn_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_grass")
local c_snow_clay = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_snow")
local c_dirt_silt = minetest.get_content_id("valleys_mapgen:dirt_silty")
local c_lawn_silt = minetest.get_content_id("valleys_mapgen:dirt_silty_with_grass")
local c_snow_silt = minetest.get_content_id("valleys_mapgen:dirt_silty_with_snow")
local c_dirt_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy")
local c_lawn_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_grass")
local c_snow_sand = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_snow")
local c_desert_sand = minetest.get_content_id("default:desert_sand")
local c_sand = minetest.get_content_id("default:sand")
local c_gravel = minetest.get_content_id("default:gravel")
local c_silt = minetest.get_content_id("valleys_mapgen:silt")
local c_clay = minetest.get_content_id("valleys_mapgen:red_clay")
local c_water = minetest.get_content_id("default:water_source")
local c_riverwater = minetest.get_content_id("default:river_water_source")
local c_lava = minetest.get_content_id("default:lava_source")
local c_snow_layer = minetest.get_content_id("default:snow")
local c_tree = minetest.get_content_id("default:tree")
local c_leaves = minetest.get_content_id("default:leaves")
local c_apple = minetest.get_content_id("default:apple")
local c_jungletree = minetest.get_content_id("default:jungletree")
local c_jungleleaves = minetest.get_content_id("default:jungleleaves")
local c_pinetree = minetest.get_content_id("default:pinetree")
local c_pineleaves = minetest.get_content_id("default:pine_needles")
local c_firtree = minetest.get_content_id("valleys_mapgen:fir_tree")
local c_firleaves = minetest.get_content_id("valleys_mapgen:fir_needles")
local c_grass = {
minetest.get_content_id("default:grass_1"),
minetest.get_content_id("default:grass_2"),
minetest.get_content_id("default:grass_3"),
minetest.get_content_id("default:grass_4"),
minetest.get_content_id("default:grass_5"),
}
local c_junglegrass = minetest.get_content_id("default:junglegrass")
local c_dryshrub = minetest.get_content_id("default:dry_shrub")
local c_cactus = minetest.get_content_id("default:cactus")
local c_papyrus = minetest.get_content_id("default:papyrus")
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local ystride = a.ystride
local chulens = vector.add(vector.subtract(maxp, minp), 1)
local chulens_sup = {x = chulens.x, y = chulens.y + 6, z = chulens.z}
local minp2d = pos2d(minp)
local t1 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Mapgen preparation finished in " .. displaytime(t1-t0))
print("[Valleys Mapgen] Calculating noises ...")
end
local n1 = vmg.noisemap(1, minp2d, chulens)
local n2 = vmg.noisemap(2, minp2d, chulens)
local n3 = vmg.noisemap(3, minp2d, chulens)
local n4 = vmg.noisemap(4, minp2d, chulens)
local n5 = vmg.noisemap(5, minp2d, chulens)
local n6 = vmg.noisemap(6, minp, chulens_sup)
local n7 = vmg.noisemap(7, minp2d, chulens)
local n8 = vmg.noisemap(8, minp, chulens)
local n9 = vmg.noisemap(9, minp, chulens)
local n10 = vmg.noisemap(10, minp, chulens)
local n11 = vmg.noisemap(11, minp, chulens)
local n12 = vmg.noisemap(12, minp, chulens)
local n13 = vmg.noisemap(13, minp2d, chulens)
local n14 = vmg.noisemap(14, minp2d, chulens)
local n15 = vmg.noisemap(15, minp2d, chulens)
local n16 = vmg.noisemap(16, minp2d, chulens)
local n18 = vmg.noisemap(18, minp2d, chulens)
local t2 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Noises calculation finished in " .. displaytime(t2-t1))
print("[Valleys Mapgen] Collecting data ...")
end
local i2d = 1 -- index for 2D noises
local i3d_sup = 1 -- index for noise 6 which has a special size
local i3d = 1 -- index for 3D noises
-- Calculate increments
local i2d_incrZ = chulens.z
local i2d_decrX = chulens.x * chulens.z - 1
local i3d_incrY = chulens.y
local i3d_sup_incrZ = 6 * chulens.y
local i3d_decrX = chulens.x * chulens.y * chulens.z - 1
local i3d_sup_decrX = chulens.x * (chulens.y + 6) * chulens.z - 1
for x = minp.x, maxp.x do -- for each YZ plane
for z = minp.z, maxp.z do -- for each vertical line in this plane
local v1, v2, v3, v4, v5, v7, v13, v14, v15, v16, v18 = n1[i2d], n2[i2d], n3[i2d], n4[i2d], n5[i2d], n7[i2d], n13[i2d], n14[i2d], n15[i2d], n16[i2d], n18[i2d] -- n for noise, v for value
v3 = v3 ^ 2 -- v3 must be > 0 and by the square there are high mountains but the median valleys depth is small.
local base_ground = v1 + v3 -- v3 is here because terrain is generally higher when valleys are deep (mountains)
v2 = math.abs(v2) - river_size
local river = v2 < 0
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2)) -- use the curve of the function 1exp((x/a)²) to modelise valleys. Making "a" varying 0 < a ≤ 1 will change the shape of the valleys. Try it with a geometry software ! (here x = v2 and a = v4)
local mountain_ground = base_ground + valleys
local slopes = v5 * valleys
if river then
local depth = river_depth * math.sqrt(1 - (v2 / river_size + 1) ^ 2) -- use the curve of the function sqrt(1-x²) which modelizes a circle.
mountain_ground = math.min(math.max(base_ground - depth, water_level - 6), mountain_ground)
slopes = 0
end
-- Choose biome
local dirt = c_dirt
local lawn = c_lawn
local snow = c_snow
local max = math.max(v13, v14, v15) -- the biome is the maximal of these 3 values, if bigger than 0.5. Else, make normal dirt.
if max > dirt_threshold then
if v13 == max then
if v13 > clay_threshold then
dirt = c_clay
lawn = c_clay
snow = c_clay
else
dirt = c_dirt_clay
lawn = c_lawn_clay
snow = c_snow_clay
end
elseif v14 == max then
if v14 > silt_threshold then
dirt = c_silt
lawn = c_silt
snow = c_silt
else
dirt = c_dirt_silt
lawn = c_lawn_silt
snow = c_snow_silt
end
else
if v15 > sand_threshold then
dirt = c_desert_sand
lawn = c_desert_sand
snow = c_desert_sand
else
dirt = c_dirt_sand
lawn = c_lawn_sand
snow = c_snow_sand
end
end
end
local is_beach = v15 > 0 and v16 > 0
local beach = v15 * v16 + water_level -- the y coordinate below which dirt is replaced by beach sand
-- raw humidity
local hraw = 2 ^ (v13 - v15 + v18 * 2)
for y = minp.y, maxp.y do -- for each node in vertical line
local ivm = a:index(x, y, z)
local v6, v8, v9, v10, v11, v12 = n6[i3d_sup], n8[i3d], n9[i3d], n10[i3d], n11[i3d], n12[i3d]
local is_cave = v8 ^ 2 + v9 ^ 2 + v10 ^ 2 + v11 ^ 2 < caves_size
if v6 * slopes > y - mountain_ground then -- if pos is in the ground
if not is_cave then
local above = math.ceil(
v7 + math.random() - math.sqrt(math.abs(y)) / dirt_thickness -- The following code will look for air at this many nodes up. If any, make dirt, else, make stone. So, it's the dirt layer thickness.
)
if y >= water_level and n6[i3d_sup+i3d_incrY] * slopes <= y + 1 - mountain_ground and not river then
if is_beach and y < beach then
data[ivm] = c_sand
else -- if node above is not in the ground, place lawn
-- calculate humidity
local sea_water = 0.5 ^ math.max((y - water_level) / 6, 0)
local river_water = 0.5 ^ math.max((y - base_ground) / 3, 0)
local water = sea_water + (1 - sea_water) * river_water
local humidity = hraw + water
local ivm2 = ivm + ystride
y = y + 1
local pos = {x = x, y = y, z = z}
local v17 = vmg.get_noise(pos, 17)
local temp -- calculate_temperature for node above
if y > 0 then
temp = v17 * 0.5 ^ (y / altitude_chill)
else
temp = v17 * 0.5 ^ (-y / altitude_chill) + 20 * (v12 + 1) * (1 - 2 ^ (y / lava_depth))
end
if temp > snow_threshold then
if above > 0 then
data[ivm] = lawn
else
data[ivm] = c_stone
end
else
if above > 0 then
data[ivm] = snow
else
data[ivm] = c_stone
end
data[ivm2] = c_snow_layer -- set node above to snow
end
if trees and math.random() < tree_density and above > 0 then -- make a tree
-- choose a tree from climatic and geological conditions
if v14 < 0 and temp < 1.5 and temp >= 0.90 and humidity < 1 and v15 < 0.8 and math.abs(v13) < 0.2 and math.random() < 0.3 then -- Pine Tree
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
vmg.make_pine_tree(pos, data, a, height, radius, c_pinetree, c_pineleaves, c_air, c_ignore)
elseif v15 < 0.6 and temp >= 0.85 and temp < 2.3 and humidity < 3 and v16 < 2 and v14 > -0.5 and v13 < 0.8 then -- Apple Tree
local rand = math.random()
local height = math.floor(4 + 2.5 * rand)
local radius = 3 + rand
if math.random(1, 4) == 1 then
vmg.make_apple_tree(pos, data, a, height, radius, c_tree, c_leaves, c_apple, c_air, c_ignore)
else
vmg.make_tree(pos, data, a, height, radius, c_tree, c_leaves, c_air, c_ignore)
end
elseif v15 < 0.7 and temp >= 1.9 and humidity > 2 and v16 > 2 then -- Jungle Tree
local rand = math.random()
local height = math.floor(8 + 4 * rand)
local radius = 5 + 3 * rand
vmg.make_jungle_tree(pos, data, a, height, radius, c_jungletree, c_jungleleaves, c_air, c_ignore)
elseif temp > 0.38 and temp < 1 and humidity > 0.9 and v15 > 0 and v15 < 0.55 then -- Fir Tree
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
vmg.make_fir_tree(pos, data, a, height, radius, c_firtree, c_firleaves, c_air, c_ignore)
end
elseif plants and math.random() < plant_density and above > 0 then -- make a plant
if temp > 1 and temp < 1.8 and water > 0.7 and humidity > 3 and v13 > -0.4 and math.random() < 0.04 then -- Papyrus
for i = 1, 4 do
data[ivm+i*ystride] = c_papyrus
end
elseif v15 < 0.65 and temp >= 0.65 and temp < 1.5 and humidity < 2.6 and v16 < 1.5 and v13 < 0.8 and math.random() < 0.7 then -- Grass
data[ivm2] = c_grass[math.random(1, 5)]
elseif v15 > -0.6 and temp >= 1.8 and humidity > 2.2 and v16 > 1.8 then -- Jungle Grass
data[ivm2] = c_junglegrass
elseif v15 > 0.65 and humidity < 0.5 and math.random() < 0.2 then
if v16 > 0 and temp > 1.6 and math.random() < 0.12 then -- Cactus
for i = 1, 4 do
data[ivm+i*ystride] = c_cactus
end
elseif temp > 1.2 then -- Dry Shrub
data[ivm2] = c_dryshrub
end
end
end
y = y - 1
end
elseif above <= 0 then
data[ivm] = c_stone
elseif n6[i3d_sup+above*i3d_incrY] * slopes <= y + above - mountain_ground then -- if node at "above" nodes up is not in the ground, make dirt
if is_beach and y < beach then
data[ivm] = c_sand
else
data[ivm] = dirt
end
else
data[ivm] = c_stone
end
elseif v11 + v12 > 2 ^ (y / lava_depth) and y <= lava_max_height then
data[ivm] = c_lava
end
elseif y <= water_level then -- if pos is not in the ground, and below water_level, it's an ocean
data[ivm] = c_water
elseif river and y + 1 < base_ground then
if river_water then
data[ivm] = c_riverwater
else
data[ivm] = c_water
end
end
i3d = i3d + i3d_incrY -- increment i3d by one line
i3d_sup = i3d_sup + i3d_incrY -- idem
end
i2d = i2d + i2d_incrZ -- increment i2d by one Z
-- useless to increment i3d, because increment would be 0 !
i3d_sup = i3d_sup + i3d_sup_incrZ -- for i3d_sup, just avoid the 6 supplemental lines
end
i2d = i2d - i2d_decrX -- decrement the Z line previously incremented and increment by one X (1)
i3d = i3d - i3d_decrX -- decrement the YZ plane previously incremented and increment by one X (1)
i3d_sup = i3d_sup - i3d_sup_decrX -- idem, including the supplemental lines
end
vmg.execute_after_mapgen() -- needed for jungletree roots
local t3 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data collecting finished in " .. displaytime(t3-t2))
print("[Valleys Mapgen] Writing data ...")
end
-- execute voxelmanip boring stuff to write to the map
vm:set_data(data)
minetest.generate_ores(vm, minp, maxp)
vm:set_lighting({day = 0, night = 0})
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
local t4 = os.clock()
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Data writing finished in " .. displaytime(t4-t3))
end
if vmg.loglevel >= 1 then
print("[Valleys Mapgen] Mapgen finished in " .. displaytime(t4-t0))
end
end
dofile(vmg.path .. "/old_mapgens/2.1-trees.lua")
function vmg.get_humidity_raw(pos)
local v13 = vmg.get_noise(pos, 13)
local v15 = vmg.get_noise(pos, 15)
local v18 = vmg.get_noise(pos, 18)
return 2 ^ (v13 - v15 + v18 * 2)
end
function vmg.get_humidity(pos)
local y = pos.y
local flatpos = pos2d(pos)
local hraw = vmg.get_humidity_raw(flatpos)
local v1 = vmg.get_noise(flatpos, 1)
local v3 = vmg.get_noise(flatpos, 3) ^ 2
local base_ground = v1 + v3
local sea_water = 0.5 ^ math.max((y - water_level) / 6, 0)
local river_water = 0.5 ^ math.max((y - base_ground) / 3, 0)
local water = sea_water + (1 - sea_water) * river_water
return hraw + water
end
function vmg.get_temperature(pos)
local v12 = vmg.get_noise(pos, 12) + 1
local v17 = vmg.get_noise(pos, 17)
local y = pos.y
if y > 0 then
return v17 * 0.5 ^ (y / altitude_chill)
else
return v17 * 0.5 ^ (-y / altitude_chill) + 20 * v12 * (1 - 2 ^ (y / lava_depth))
end
end
function vmg.get_noise(pos, i)
local n = vmg.noises[i]
local noise = minetest.get_perlin(n.seed, n.octaves, n.persist, 1)
if not pos.z then
return noise:get2d({x = pos.x / n.spread.x, y = pos.y / n.spread.y}) * n.scale + n.offset
else
return noise:get3d({x = pos.x / n.spread.x, y = pos.y / n.spread.y, z = pos.z / n.spread.z}) * n.scale + n.offset
end
end
local function round(n)
return math.floor(n + 0.5)
end
function vmg.get_elevation(pos)
local v1 = vmg.get_noise(pos, 1)
local v2 = math.abs(vmg.get_noise(pos, 2)) - river_size
local v3 = vmg.get_noise(pos, 3) ^ 2
local base_ground = v1 + v3
if v2 < 0 then
return math.ceil(base_ground), true
end
local v4 = vmg.get_noise(pos, 4)
local v5 = vmg.get_noise(pos, 5)
local base_ground = v1 + v3
local valleys = v3 * (1 - math.exp(- (v2 / v4) ^ 2))
local mountain_ground = base_ground + valleys
local pos = pos3d(pos, round(mountain_ground))
local slopes = v5 * valleys
if vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground then
pos.y = pos.y + 1
while vmg.get_noise(pos, 6) * slopes > pos.y - mountain_ground do
pos.y = pos.y + 1
end
return pos.y, false
else
pos.y = pos.y - 1
while vmg.get_noise(pos, 6) * slopes <= pos.y - mountain_ground do
pos.y = pos.y - 1
end
return pos.y, false
end
end
function vmg.spawnplayer(player)
local angle = math.random() * math.pi * 2
local distance = math.random() * player_max_distance
local p_angle = {x = math.cos(angle), y = math.sin(angle)}
local pos = {x = -p_angle.x * distance, y = -p_angle.y * distance}
local elevation, river = vmg.get_elevation(pos)
while elevation < water_level + 2 or river do
pos.x = pos.x + p_angle.x
pos.y = pos.y + p_angle.y
elevation, river = vmg.get_elevation({x = round(pos.x), y = round(pos.y)})
end
pos = {x = round(pos.x), y = round(elevation + 1), z = round(pos.y)}
player:setpos(pos)
return true
end

View File

@ -0,0 +1,132 @@
vmg.settings = Settings(minetest.get_worldpath() .. "/vmg.conf")
local function define_str(flag, default, write_to_config)
local value = vmg.settings:get(flag)
if value then
return value, true
else
local on_config = minetest.setting_get("vmg_" .. flag)
if on_config then
vmg.settings:set(flag, on_config)
return on_config, false
else
if write_to_config then
minetest.setting_set("vmg_" .. flag, default)
end
vmg.settings:set(flag, default)
return default, false
end
end
end
local function define_num(flag, default, write_to_config)
local value = vmg.settings:get(flag)
if value then
return tonumber(value), true
else
local on_config = minetest.setting_get("vmg_" .. flag)
if on_config then
vmg.settings:set(flag, on_config)
return tonumber(on_config), false
else
if write_to_config then
minetest.setting_set("vmg_" .. flag, default)
end
vmg.settings:set(flag, default)
return default, false
end
end
end
local function define_bool(flag, default, write_to_config)
local value = vmg.settings:get_bool(flag)
if value ~= nil then
return value, true
else
local on_config = minetest.setting_getbool("vmg_" .. flag)
if on_config ~= nil then
vmg.settings:set(flag, tostring(on_config))
return on_config, false
else
if write_to_config then
minetest.setting_setbool("vmg_" .. flag, default)
end
vmg.settings:set(flag, tostring(default))
return default, false
end
end
end
local function define_noise(flag, default, write_to_config)
local value = vmg.settings:get(flag)
if value then
return vmg.string_to_noise(value), true
else
local on_config = minetest.setting_get("vmg_" .. flag)
if on_config then
vmg.settings:set(flag, on_config)
return vmg.string_to_noise(on_config), false
else
local str_default = vmg.noise_to_string(default)
if write_to_config then
minetest.setting_set("vmg_" .. flag, str_default)
end
vmg.settings:set(flag, str_default)
return default, false
end
end
end
function vmg.define(flag, default, write_to_config)
local typeval = type(default)
if typeval == "string" then
return define_str(flag, default, write_to_config)
elseif typeval == "number" then
return define_num(flag, default, write_to_config)
elseif typeval == "boolean" then
return define_bool(flag, default, write_to_config)
elseif typeval == "table" then
return define_noise(flag, default, write_to_config)
end
end
function vmg.noise_to_string(n)
return n.offset ..
", " .. n.scale ..
", " .. minetest.pos_to_string(n.spread) ..
", " .. n.seed ..
", " .. n.octaves ..
", " .. n.persist ..
", " .. n.lacunarity
end
function vmg.string_to_noise(str)
local t = {}
for line in str:gmatch("[%d%.%-e]+") do
table.insert(t, tonumber(line))
end
return {
offset = t[1],
scale = t[2],
spread = {x=t[3], y=t[4], z=t[5]},
seed = t[6],
octaves = t[7],
persist = t[8],
lacunarity = t[9],
}
end
if vmg.loglevel >= 2 then
print("[Valleys Mapgen] Loading mapgen ...")
end
-- Choose the appropriate mapgen version
local version = vmg.define("version", vmg.version)
if version == vmg.version then
dofile(vmg.path .. "/mapgen.lua")
else
dofile(vmg.path .. "/old_mapgens/" .. version .. ".lua")
end
vmg.settings:write()

View File

@ -0,0 +1,40 @@
with GIMP :
Color ~> Hue-Saturation
vmg_dirt_clayey.png
from default_dirt.png
Hue 6
Brightness +5
Saturation +40
vmg_dirt_sandy.png
from default_dirt.png
Hue +5
Brightness +40
Saturation 10
vmg_dirt_silty.png
from default_dirt.png
Hue +8
Brightness 10
Saturation 30
vmg_red_clay.png
from default_dirt.png
Hue 5
Brightness +10
Saturation +100
vmg_silt.png
from default_dirt.png
Hue +6
Brightness +10
Saturation 78
vmg_fir_tree.png :
from default_wood.png
Hue +6
Brightness +50
Saturation 24
And convert to indexed color.

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

View File

@ -0,0 +1,295 @@
local function can_grow(pos) -- from default mod
local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
if not node_under then
return false
end
local name_under = node_under.name
local is_soil = minetest.get_item_group(name_under, "soil")
if is_soil == 0 then
return false
end
return true
end
minetest.register_abm({
nodenames = {"valleys_mapgen:fir_sapling"},
interval = 14,
chance = 50,
action = function(pos, node)
if not can_grow(pos) then
return
end
minetest.log("action", "A fir sapling grows into a tree at "..
minetest.pos_to_string(pos))
vmg.grow_fir_tree(pos)
end
})
function default.grow_tree(pos, is_apple_tree)
local rand = math.random()
local height = math.floor(4 + 2.5 * rand)
local radius = 3 + rand
local leaves = minetest.get_content_id("default:leaves")
local trunk = minetest.get_content_id("default:tree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 4, y = pos.y, z = pos.z - 4}, {x = pos.x + 4, y = pos.y + height + 4, z = pos.z + 4})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
if is_apple_tree then
vmg.make_apple_tree(pos, data, area, height, radius, trunk, leaves, minetest.get_content_id("default:apple"), air, ignore)
else
vmg.make_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
end
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function default.grow_jungle_tree(pos)
local rand = math.random()
local height = math.floor(8 + 4 * rand)
local radius = 5 + 3 * rand
local leaves = minetest.get_content_id("default:jungleleaves")
local trunk = minetest.get_content_id("default:jungletree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 8, y = pos.y - 1, z = pos.z - 8}, {x = pos.x + 8, y = pos.y + height + 5, z = pos.z + 8})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
vmg.make_jungle_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
vmg.execute_after_mapgen()
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function default.grow_pine_tree(pos)
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
local leaves = minetest.get_content_id("default:pine_needles")
local trunk = minetest.get_content_id("default:pinetree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 6, y = pos.y - 1, z = pos.z - 6}, {x = pos.x + 6, y = pos.y + height + 2, z = pos.z + 6})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
vmg.make_pine_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function vmg.grow_fir_tree(pos)
local rand = math.random()
local height = math.floor(9 + 6 * rand)
local radius = 4 + 2 * rand
local leaves = minetest.get_content_id("valleys_mapgen:fir_needles")
local trunk = minetest.get_content_id("valleys_mapgen:fir_tree")
local air = minetest.get_content_id("air")
local ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map({x = pos.x - 6, y = pos.y - 1, z = pos.z - 6}, {x = pos.x + 6, y = pos.y + height + 2, z = pos.z + 6})
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
vmg.make_fir_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
function vmg.make_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.5}
pos.y = pos.y + height - 1
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius, z = radius}, np)
end
function vmg.make_apple_tree(pos, data, area, height, radius, trunk, leaves, fruit, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating apple tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.5}
pos.y = pos.y + height - 1
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius, z = radius}, np, 0.06, fruit)
end
local function make_jungle_root(x0, y0, z0, data, area, tree, air)
local ystride = area.ystride
local ybot = y0 - 1
for x = x0 - 1, x0 + 1 do
for z = z0 - 1, z0 + 1 do
local iv = area:index(x, ybot, z)
for i = 0, 5 do
if data[iv] == air then
if math.random() < 0.6 then
data[iv-ystride] = tree -- make jungle tree below
if math.random() < 0.6 then
data[iv] = tree -- make jungle tree at this air node
end
end
break
end
iv = iv + ystride
end
end
end
end
function vmg.make_jungle_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating jungle tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
vmg.register_after_mapgen(make_jungle_root, pos.x, pos.y, pos.z, data, area, trunk, air)
local np = {offset = 0.8, scale = 0.4, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 0.8}
pos.y = pos.y + height
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = radius * 0.5, z = radius}, np)
end
function vmg.make_fir_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating fir tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
-- add leaves on the top (4% 0 ; 36% 1 ; 60% 2)
local rand = math.random()
if rand < 0.96 then
data[iv] = leaves
if rand < 0.60 then
iv = iv + ystride
data[iv] = leaves
end
end
-- make several leaves rings
local max_height = pos.y + height
local min_height = pos.y + math.floor((0.2 + 0.3 * math.random()) * height)
local radius_increment = (radius - 1.2) / (max_height - min_height)
local np = {offset = 0.8, scale = 0.4, spread = {x = 12, y = 4, z = 12}, octaves = 3, persist = 0.8}
pos.y = max_height - 1
while pos.y >= min_height do
local ring_radius = (max_height - pos.y) * radius_increment + 1.2
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = ring_radius, y = 2, z = ring_radius}, np)
pos.y = pos.y - math.random(2, 3)
end
end
function vmg.make_pine_tree(pos, data, area, height, radius, trunk, leaves, air, ignore)
if vmg.loglevel >= 3 then
print("[Valleys Mapgen] Generating pine tree at " .. minetest.pos_to_string(pos) .. " ...")
end
local ystride = area.ystride
local iv = area:indexp(pos)
for i = 1, height do
data[iv] = trunk
iv = iv + ystride
end
-- add leaves on the top (4% 0 ; 36% 1 ; 60% 2)
local rand = math.random()
if rand < 0.96 then
data[iv] = leaves
if rand < 0.60 then
iv = iv + ystride
data[iv] = leaves
end
end
local np = {offset = 0.8, scale = 0.3, spread = {x = 8, y = 4, z = 8}, octaves = 3, persist = 1}
local min_height = pos.y + math.floor((0.4 + 0.2 * math.random()) * height)
local midradius = radius / 2
pos.y = pos.y + height - 1
vmg.make_leavesblob(pos, data, area, leaves, air, ignore, {x = radius, y = 1.5, z = radius}, np)
while pos.y >= min_height do
local angle, distance = math.random() * 2 * math.pi, math.random() * midradius
local cos, sin = math.cos(angle) * distance, math.sin(angle) * distance
local bpos = {x = pos.x + cos, y = pos.y, z = pos.z + sin}
vmg.make_leavesblob(bpos, data, area, leaves, air, ignore, {x = midradius, y = 1.5, z = midradius}, np)
pos.y = pos.y - math.random(1, 2)
end
end
function vmg.make_leavesblob(pos, data, area, leaves, air, ignore, radius, np, fruit_chance, fruit)
local count = 0
fruit_chance = fruit_chance or 0
np.seed = math.random(0, 16777215)
local minp = vector.subtract(pos, radius)
local maxp = vector.add(pos, radius)
local int_minp = {x = math.floor(minp.x), y = math.floor(minp.y), z = math.floor(minp.z)}
local int_maxp = {x = math.ceil(maxp.x), y = math.ceil(maxp.y), z = math.ceil(maxp.z)}
local length = vector.subtract(int_maxp, int_minp)
local chulens = vector.add(length, 1)
local obj = minetest.get_perlin_map(np, chulens)
local pmap = obj:get3dMap_flat(minp)
local i = 1
for x = int_minp.x, int_maxp.x do
local xval = ((x - pos.x) / radius.x) ^ 2
for y = int_minp.y, int_maxp.y do
local yval = ((y - pos.y) / radius.y) ^ 2
for z = int_minp.z, int_maxp.z do
local zval = ((z - pos.z) / radius.z) ^ 2
local dist = math.sqrt(xval + yval + zval)
local nval = pmap[i]
if nval > dist then
local iv = area:index(x, y, z)
if data[iv] == air or data[iv] == ignore then
count = count + 1
if math.random() < fruit_chance then
data[iv] = fruit
else
data[iv] = leaves
end
end
end
i = i + 1
end
end
end
end
-- Adapt the code to the latest minetest_game that use these functions
function default.grow_new_apple_tree(pos)
local is_apple_tree = math.random(4) == 1
default.grow_tree(pos, is_apple_tree)
end
default.grow_new_jungle_tree = default.grow_jungle_tree
default.grow_new_pine_tree = default.grow_pine_tree

View File

@ -0,0 +1,88 @@
# format : FLAG = VALUE
# Settings are presents twice :
# - In every world :
# world_directory/vmg.conf
# - In the main directory :
# usually main_directory/minetest.conf
# /!\ IMPORTANT : In minetest.conf, flags have to be preceded by "vmg_" like "vmg_average_stone_level".
#version = 2.2
# mapgen version used.
#player_max_distance = 450
# maximal distance from (0;0) at which the player will appear. (If it's in a big ocean, it may be farther)
#spawn = true
# New players are randomely spawned by the mod. Disable it to spawn the player another way.
#respawn = true
# After death, players are respawned by the mod. Disable it to respawn the player another way.
#water_level = 1
#river_water = true
# use river water instead of normal water in rivers.
#waterflow = 3
# maximal length of a river water flowing.
#average_stone_level = 180
# height at which the half of the surface is made solely of stone.
#average_snow_level = 100
# height at which the half of the surface is covered by snow.
#clay_threshold = 1
# if noise 13 is above this value, make pure clay instead of clayey dirt.
#silt_threshold = 1
# if noise 14 is above this value, make pure silt instead of silty dirt.
#sand_threshold = 0.75
# if noise 15 is above this value, make desert sand instead of sandy dirt.
#dirt_threshold = 0.5
# if not any of noises 13, 14 and 15 is above this value, make normal dirt. Else make special dirt.
#river_depth = 3
#river_size = 5
#caves_size = 7
#lava_depth = 2000
# to manage lava amount increasing by going deep underground : lower values = bigger increasing.
#surface_lava = false
# DEPRECATED. No longer supported since mapgen version 2.0. Use lava_max_height instead.
#lava_max_height = -1
# Lava can't be generated above this height. Use 31000 to disable this restriction, or -31000 to fully disable lava.
#altitude_chill = 90
#trees = true
# If false, no trees, of course !
#plants = true
#tree_density = 5
# Percent of the lawn nodes that are covered by trees.
#plant_density = 32
# NOISES : offset, scale, (spread), seed, octaves, persist, lacunarity
# (see mapgen.lua to see what is the role of each noise)
#noise_1 = -10, 50, (1024,1024,1024), 5202, 6, 0.4, 2
#noise_2 = 0, 1, (256,256,256), -6050, 5, 0.6, 2
#noise_3 = 5, 4, (512,512,512), -1914, 1, 1, 2
#noise_4 = 0.6, 0.5, (512,512,512), 777, 1, 1, 2
#noise_5 = 0.5, 0.5, (128,128,128), 746, 1, 1, 2
#noise_6 = 0, 1, (256,512,256), 1993, 6, 0.8, 2
#noise_7 = 3, 1.75, (256,256,256), 1605, 3, 0.5, 2
#noise_8 = 0, 1, (32,32,32), -4640, 4, 0.5, 2
#noise_9 = 0, 1, (32,32,32), 8804, 4, 0.5, 2
#noise_10 = 0, 1, (32,32,32), -4780, 4, 0.5, 2
#noise_11 = 0, 1, (32,32,32), -9969, 4, 0.5, 2
#noise_12 = 0, 1, (64,64,64), 3314, 4, 0.5, 2
#noise_13 = 0, 1, (256,256,256), 2835, 5, 0.5, 4
#noise_14 = 0, 1, (256,256,256), 6674, 5, 0.5, 4
#noise_15 = 0, 1, (256,256,256), 6940, 5, 0.5, 4
#noise_16 = 2, 8, (256,256,256), 2349, 3, 0.5, 2
#noise_17 = 0, 1, (768,256,768), -1805, 4, 0.5, 4
#noise_18 = 0, 1, (243,243,243), -5787, 4, 0.5, 3
# Flags that are ONLY available in minetest.conf :
#vmg_log_level = 0
# 0 = Not any log from Valleys Mapgen
# 1 = Total mapgen time
# 2 = Detailed mapgen time (step by step)
# 3 = Detailed mapgen time + trees

View File

@ -285,3 +285,11 @@ function vmg.make_leavesblob(pos, data, area, leaves, air, ignore, radius, np, f
end
end
end
-- Adapt the code to the latest minetest_game that use these functions
function default.grow_new_apple_tree(pos)
local is_apple_tree = math.random(4) == 1
default.grow_tree(pos, is_apple_tree)
end
default.grow_new_jungle_tree = default.grow_jungle_tree
default.grow_new_pine_tree = default.grow_pine_tree