init.lua 14.1 KB
Newer Older
Chris N's avatar
Chris N committed
1
-- caverealms v.0.8 by HeroOfTheWinds
Chris N's avatar
Chris N committed
2 3
-- original cave code modified from paramat's subterrain
-- For Minetest 0.4.8 stable
HeroOfTheWinds's avatar
HeroOfTheWinds committed
4 5 6
-- Depends default
-- License: code WTFPL

Chris N's avatar
Chris N committed
7

8
caverealms = {} --create a container for functions and constants
9

10
--grab a shorthand for the filepath of the mod
11 12
local modpath = minetest.get_modpath(minetest.get_current_modname())

13 14 15 16 17
--load companion lua files
dofile(modpath.."/config.lua") --configuration file; holds various constants
dofile(modpath.."/crafting.lua") --crafting recipes
dofile(modpath.."/nodes.lua") --node definitions
dofile(modpath.."/functions.lua") --function definitions
Chris N's avatar
Chris N committed
18
dofile(modpath.."/abms.lua") --abm definitions
HeroOfTheWinds's avatar
HeroOfTheWinds committed
19

20 21 22 23 24
if caverealms.config.falling_icicles == true then
	dofile(modpath.."/falling_ice.lua") --complicated function for falling icicles
	print("[caverealms] falling icicles enabled.")
end

Chris N's avatar
Chris N committed
25 26 27
local FORTRESSES = caverealms.config.fortresses --true | Should fortresses spawn?
local FOUNTAINS = caverealms.config.fountains --true | Should fountains spawn?

Chris N's avatar
Chris N committed
28
-- Parameters
29 30 31

local YMIN = caverealms.config.ymin -- Approximate realm limits.
local YMAX = caverealms.config.ymax
Chris N's avatar
Chris N committed
32 33
local TCAVE = caverealms.config.tcave --0.5 -- Cave threshold. 1 = small rare caves, 0.5 = 1/3rd ground volume, 0 = 1/2 ground volume
local BLEND = 128 -- Cave blend distance near YMIN, YMAX
HeroOfTheWinds's avatar
HeroOfTheWinds committed
34

35 36 37 38 39 40 41 42 43
local STAGCHA = caverealms.config.stagcha --0.002 --chance of stalagmites
local STALCHA = caverealms.config.stalcha --0.003 --chance of stalactites
local CRYSTAL = caverealms.config.crystal --0.007 --chance of glow crystal formations
local GEMCHA = caverealms.config.gemcha --0.03 --chance of small glow gems
local MUSHCHA = caverealms.config.mushcha --0.04 --chance of mushrooms
local MYCCHA = caverealms.config.myccha --0.03 --chance of mycena mushrooms
local WORMCHA = caverealms.config.wormcha --0.03 --chance of glow worms
local GIANTCHA = caverealms.config.giantcha --0.001 -- chance of giant mushrooms
local ICICHA = caverealms.config.icicha --0.035 -- chance of icicles
44 45 46
local FLACHA = caverealms.config.flacha --0.04 --chance of constant flames
local FOUNCHA = caverealms.config.founcha --0.001 --chance of statue + fountain
local FORTCHA = caverealms.config.fortcha --0.0003 --chance of DM Fortresses
Chris N's avatar
Chris N committed
47

48 49
local DM_TOP = caverealms.config.dm_top -- -4000 --level at which Dungeon Master Realms start to appear
local DM_BOT = caverealms.config.dm_bot -- -5000 --level at which "" ends
Chris N's avatar
Chris N committed
50
local DEEP_CAVE = caverealms.config.deep_cave -- -7000 --level at which deep cave biomes take over
51

Chris N's avatar
Chris N committed
52
-- 3D noise for caves
HeroOfTheWinds's avatar
HeroOfTheWinds committed
53 54 55 56

local np_cave = {
	offset = 0,
	scale = 1,
Chris N's avatar
Chris N committed
57 58
	spread = {x=512, y=256, z=512}, -- squashed 2:1
	seed = 59033,
HeroOfTheWinds's avatar
HeroOfTheWinds committed
59
	octaves = 6,
Chris N's avatar
Chris N committed
60
	persist = 0.63
HeroOfTheWinds's avatar
HeroOfTheWinds committed
61 62
}

Chris N's avatar
Chris N committed
63
-- 3D noise for wave
HeroOfTheWinds's avatar
HeroOfTheWinds committed
64 65 66 67 68 69 70

local np_wave = {
	offset = 0,
	scale = 1,
	spread = {x=256, y=256, z=256},
	seed = -400000000089,
	octaves = 3,
Chris N's avatar
Chris N committed
71
	persist = 0.67
HeroOfTheWinds's avatar
HeroOfTheWinds committed
72 73
}

Chris N's avatar
Chris N committed
74 75 76 77 78 79 80 81 82 83 84
-- 2D noise for biome

local np_biome = {
	offset = 0,
	scale = 1,
	spread = {x=250, y=250, z=250},
	seed = 9130,
	octaves = 3,
	persist = 0.5
}

Chris N's avatar
Chris N committed
85 86 87 88 89 90 91
-- Stuff

subterrain = {}

local yblmin = YMIN + BLEND * 1.5
local yblmax = YMAX - BLEND * 1.5

HeroOfTheWinds's avatar
HeroOfTheWinds committed
92 93 94
-- On generated function

minetest.register_on_generated(function(minp, maxp, seed)
Chris N's avatar
Chris N committed
95 96 97
	--if out of range of caverealms limits
	if minp.y > YMAX or maxp.y < YMIN then
		return --quit; otherwise, you'd have stalagmites all over the place
HeroOfTheWinds's avatar
HeroOfTheWinds committed
98
	end
99

Chris N's avatar
Chris N committed
100
	--easy reference to commonly used values
HeroOfTheWinds's avatar
HeroOfTheWinds committed
101 102 103 104 105 106 107
	local t1 = os.clock()
	local x1 = maxp.x
	local y1 = maxp.y
	local z1 = maxp.z
	local x0 = minp.x
	local y0 = minp.y
	local z0 = minp.z
Chris N's avatar
Chris N committed
108
	
Chris N's avatar
Chris N committed
109
	print ("[caverealms] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk
Chris N's avatar
Chris N committed
110
	
HeroOfTheWinds's avatar
HeroOfTheWinds committed
111 112 113
	local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
	local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
	local data = vm:get_data()
Chris N's avatar
Chris N committed
114
	
HeroOfTheWinds's avatar
HeroOfTheWinds committed
115 116
	--grab content IDs
	local c_air = minetest.get_content_id("air")
Chris N's avatar
Chris N committed
117
	local c_stone = minetest.get_content_id("default:stone")
118 119 120 121 122 123
	
	if (minetest.get_modpath("moontest")) then
		c_air = minetest.get_content_id("moontest:vacuum")
		c_stone = minetest.get_content_id("moontest:stone")
	end
	
Craig Robbins's avatar
Craig Robbins committed
124
	local c_water = minetest.get_content_id("default:water_source")
125
	local c_lava = minetest.get_content_id("default:lava_source")
Chris N's avatar
Chris N committed
126 127
	local c_ice = minetest.get_content_id("default:ice")
	local c_thinice = minetest.get_content_id("caverealms:thin_ice")
HeroOfTheWinds's avatar
HeroOfTheWinds committed
128
	local c_crystal = minetest.get_content_id("caverealms:glow_crystal")
129 130 131 132 133
	local c_gem1 = minetest.get_content_id("caverealms:glow_gem")
	local c_gem2 = minetest.get_content_id("caverealms:glow_gem_2")
	local c_gem3 = minetest.get_content_id("caverealms:glow_gem_3")
	local c_gem4 = minetest.get_content_id("caverealms:glow_gem_4")
	local c_gem5 = minetest.get_content_id("caverealms:glow_gem_5")
Chris N's avatar
Chris N committed
134 135 136 137 138 139 140 141 142 143
	local c_saltgem1 = minetest.get_content_id("caverealms:salt_gem")
	local c_saltgem2 = minetest.get_content_id("caverealms:salt_gem_2")
	local c_saltgem3 = minetest.get_content_id("caverealms:salt_gem_3")
	local c_saltgem4 = minetest.get_content_id("caverealms:salt_gem_4")
	local c_saltgem5 = minetest.get_content_id("caverealms:salt_gem_5")
	local c_spike1 = minetest.get_content_id("caverealms:spike")
	local c_spike2 = minetest.get_content_id("caverealms:spike_2")
	local c_spike3 = minetest.get_content_id("caverealms:spike_3")
	local c_spike4 = minetest.get_content_id("caverealms:spike_4")
	local c_spike5 = minetest.get_content_id("caverealms:spike_5")
HeroOfTheWinds's avatar
HeroOfTheWinds committed
144
	local c_moss = minetest.get_content_id("caverealms:stone_with_moss")
Chris N's avatar
Chris N committed
145
	local c_lichen = minetest.get_content_id("caverealms:stone_with_lichen")
146
	local c_algae = minetest.get_content_id("caverealms:stone_with_algae")
Chris N's avatar
Chris N committed
147
	local c_salt = minetest.get_content_id("caverealms:stone_with_salt")
Chris N's avatar
Chris N committed
148
	local c_hcobble = minetest.get_content_id("caverealms:hot_cobble")
Chris N's avatar
Chris N committed
149 150 151 152 153
	local c_gobsidian = minetest.get_content_id("caverealms:glow_obsidian")
	local c_gobsidian2 = minetest.get_content_id("caverealms:glow_obsidian_2")
	local c_coalblock = minetest.get_content_id("default:coalblock")
	local c_desand = minetest.get_content_id("default:desert_sand")
	local c_coaldust = minetest.get_content_id("caverealms:coal_dust")
Chris N's avatar
Chris N committed
154
	local c_fungus = minetest.get_content_id("caverealms:fungus")
Chris N's avatar
Chris N committed
155
	local c_mycena = minetest.get_content_id("caverealms:mycena")
156
	local c_worm = minetest.get_content_id("caverealms:glow_worm")
Chris N's avatar
Chris N committed
157
	local c_iciu = minetest.get_content_id("caverealms:icicle_up")
158
	local c_icid = minetest.get_content_id("caverealms:icicle_down")
Chris N's avatar
Chris N committed
159 160 161 162
	local c_flame = minetest.get_content_id("caverealms:constant_flame")
	local c_fountain = minetest.get_content_id("caverealms:s_fountain")
	local c_fortress = minetest.get_content_id("caverealms:s_fortress")
	
Chris N's avatar
Chris N committed
163 164 165
	--mandatory values
	local sidelen = x1 - x0 + 1 --length of a mapblock
	local chulens = {x=sidelen, y=sidelen, z=sidelen} --table of chunk edges
166
	local chulens2D = {x=sidelen, y=sidelen, z=1}
Chris N's avatar
Chris N committed
167 168
	local minposxyz = {x=x0, y=y0, z=z0} --bottom corner
	local minposxz = {x=x0, y=z0} --2D bottom corner
Chris N's avatar
Chris N committed
169
	
Chris N's avatar
Chris N committed
170 171
	local nvals_cave = minetest.get_perlin_map(np_cave, chulens):get3dMap_flat(minposxyz) --cave noise for structure
	local nvals_wave = minetest.get_perlin_map(np_wave, chulens):get3dMap_flat(minposxyz) --wavy structure of cavern ceilings and floors
172
	local nvals_biome = minetest.get_perlin_map(np_biome, chulens2D):get2dMap_flat({x=x0+150, y=z0+50}) --2D noise for biomes (will be 3D humidity/temp later)
Chris N's avatar
Chris N committed
173
	
Chris N's avatar
Chris N committed
174 175 176
	local nixyz = 1 --3D node index
	local nixz = 1 --2D node index
	local nixyz2 = 1 --second 3D index for second loop
Chris N's avatar
Chris N committed
177
	
Chris N's avatar
Chris N committed
178 179 180 181 182 183 184 185 186 187 188
	for z = z0, z1 do -- for each xy plane progressing northwards
		--structure loop
		for y = y0, y1 do -- for each x row progressing upwards
			local tcave --declare variable
			--determine the overal cave threshold
			if y < yblmin then
				tcave = TCAVE + ((yblmin - y) / BLEND) ^ 2
			elseif y > yblmax then
				tcave = TCAVE + ((y - yblmax) / BLEND) ^ 2
			else
				tcave = TCAVE
HeroOfTheWinds's avatar
HeroOfTheWinds committed
189
			end
Chris N's avatar
Chris N committed
190
			local vi = area:index(x0, y, z) --current node index
HeroOfTheWinds's avatar
HeroOfTheWinds committed
191
			for x = x0, x1 do -- for each node do
Chris N's avatar
Chris N committed
192 193
				if (nvals_cave[nixyz] + nvals_wave[nixyz])/2 > tcave then --if node falls within cave threshold
					data[vi] = c_air --hollow it out to make the cave
HeroOfTheWinds's avatar
HeroOfTheWinds committed
194
				end
Chris N's avatar
Chris N committed
195 196 197
				--increment indices
				nixyz = nixyz + 1
				vi = vi + 1
HeroOfTheWinds's avatar
HeroOfTheWinds committed
198 199
			end
		end
Chris N's avatar
Chris N committed
200
		
Chris N's avatar
Chris N committed
201 202
		--decoration loop
		for y = y0, y1 do -- for each x row progressing upwards
Chris N's avatar
Chris N committed
203 204 205 206 207 208
		
			local is_deep = false
			if y < DEEP_CAVE then
				is_deep = true
			end
		
Chris N's avatar
Chris N committed
209 210 211 212 213 214 215 216 217
			local tcave --same as above
			if y < yblmin then
				tcave = TCAVE + ((yblmin - y) / BLEND) ^ 2
			elseif y > yblmax then
				tcave = TCAVE + ((y - yblmax) / BLEND) ^ 2
			else
				tcave = TCAVE
			end
			local vi = area:index(x0, y, z)
HeroOfTheWinds's avatar
HeroOfTheWinds committed
218
			for x = x0, x1 do -- for each node do
Chris N's avatar
Chris N committed
219
				
Chris N's avatar
Chris N committed
220 221
				--determine biome
				local biome = false --preliminary declaration
222
				local n_biome = nvals_biome[nixz] --make an easier reference to the noise
Chris N's avatar
Chris N committed
223 224 225
				--compare noise values to determine a biome
				if n_biome >= 0 and n_biome < 0.5 then
					biome = 1 --moss
Chris N's avatar
Chris N committed
226 227 228
					if is_deep then
						biome = 7 --salt crystal
					end
Chris N's avatar
Chris N committed
229 230
				elseif n_biome <= -0.5 then
					biome = 2 --fungal
Chris N's avatar
Chris N committed
231 232 233
					if is_deep then
						biome = 8 --glow obsidian
					end
Chris N's avatar
Chris N committed
234 235 236
				elseif n_biome >= 0.5 then
					if n_biome >= 0.7 then
						biome = 5 --deep glaciated
HeroOfTheWinds's avatar
HeroOfTheWinds committed
237
					else
Chris N's avatar
Chris N committed
238
						biome = 4 --glaciated
HeroOfTheWinds's avatar
HeroOfTheWinds committed
239
					end
Chris N's avatar
Chris N committed
240 241
				else
					biome = 3 --algae
Chris N's avatar
Chris N committed
242 243 244
					if is_deep then
						biome = 9 --coal dust
					end
Chris N's avatar
Chris N committed
245
				end
Chris N's avatar
Chris N committed
246 247 248 249 250 251 252 253
				
				if y <= DM_TOP and y >= DM_BOT then
					biome = 6 --DUNGEON MASTER'S LAIR
				end
				--if y <= -1000 then
					--biome = 6 --DUNGEON MASTER'S LAIR
				--end
				
Chris N's avatar
Chris N committed
254 255 256 257 258
				if math.floor(((nvals_cave[nixyz2] + nvals_wave[nixyz2])/2)*100) == math.floor(tcave*100) then
					--ceiling
					local ai = area:index(x,y+1,z) --above index
					if data[ai] == c_stone and data[vi] == c_air then --ceiling
						if math.random() < ICICHA and (biome == 4 or biome == 5) then
259
							data[vi] = c_icid
Chris N's avatar
Chris N committed
260
						end
Chris N's avatar
Chris N committed
261
						if math.random() < WORMCHA then
Chris N's avatar
Chris N committed
262
							data[vi] = c_worm
Chris N's avatar
Chris N committed
263
							local bi = area:index(x,y-1,z)
Chris N's avatar
Chris N committed
264 265
							data[bi] = c_worm
							if math.random(2) == 1 then
Chris N's avatar
Chris N committed
266 267 268 269 270
								local bbi = area:index(x,y-2,z)
								data[bbi] = c_worm
								if math.random(2) ==1 then
									local bbbi = area:index(x,y-3,z)
									data[bbbi] = c_worm
Chris N's avatar
Chris N committed
271 272 273
								end
							end
						end
Chris N's avatar
Chris N committed
274 275
						if math.random() < STALCHA then
							caverealms:stalactite(x,y,z, area, data)
Chris N's avatar
Chris N committed
276
						end
Chris N's avatar
Chris N committed
277 278
						if math.random() < CRYSTAL then
							caverealms:crystal_stalactite(x,y,z, area, data, biome)
HeroOfTheWinds's avatar
HeroOfTheWinds committed
279 280
						end
					end
Chris N's avatar
Chris N committed
281 282 283
					--ground
					local bi = area:index(x,y-1,z) --below index
					if data[bi] == c_stone and data[vi] == c_air then --ground
284
						local ai = area:index(x,y+1,z)
Chris N's avatar
Chris N committed
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
						--place floor material, add plants/decorations
						if biome == 1 then
							data[vi] = c_moss
							if math.random() < GEMCHA then
								-- gems of random size
								local gems = { c_gem1, c_gem2, c_gem3, c_gem4, c_gem5 }
								local gidx = math.random(1, 12)
								if gidx > 5 then
									gidx = 1
								end
								data[ai] = gems[gidx]
							end
						elseif biome == 2 then
							data[vi] = c_lichen
							if math.random() < MUSHCHA then --mushrooms
								data[ai] = c_fungus
							end
							if math.random() < MYCCHA then --mycena mushrooms
								data[ai] = c_mycena
							end
							if math.random() < GIANTCHA then --giant mushrooms
								caverealms:giant_shroom(x, y, z, area, data)
							end
						elseif biome == 3 then
							data[vi] = c_algae
						elseif biome == 4 then
							data[vi] = c_thinice
							local bi = area:index(x,y-1,z)
							data[bi] = c_thinice
							if math.random() < ICICHA then --if glaciated, place icicles
								data[ai] = c_iciu
							end
						elseif biome == 5 then
							data[vi] = c_ice
							local bi = area:index(x,y-1,z)
							data[bi] = c_ice
							if math.random() < ICICHA then --if glaciated, place icicles
								data[ai] = c_iciu
							end
Chris N's avatar
Chris N committed
324 325 326 327 328
						elseif biome == 6 then
							data[vi] = c_hcobble
							if math.random() < FLACHA then --neverending flames
								data[ai] = c_flame
							end
Chris N's avatar
Chris N committed
329
							if math.random() < FOUNCHA and FOUNTAINS then --DM FOUNTAIN
Chris N's avatar
Chris N committed
330 331
								data[ai] = c_fountain
							end
Chris N's avatar
Chris N committed
332
							if math.random() < FORTCHA and FORTRESSES then --DM FORTRESS
Chris N's avatar
Chris N committed
333 334
								data[ai] = c_fortress
							end
Chris N's avatar
Chris N committed
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
						elseif biome == 7 then
							local bi = area:index(x,y-1,z)
							data[vi] = c_salt
							data[bi] = c_salt
							if math.random() < GEMCHA then
								-- gems of random size
								local gems = { c_saltgem1, c_saltgem2, c_saltgem3, c_saltgem4, c_saltgem5 }
								local gidx = math.random(1, 12)
								if gidx > 5 then
									gidx = 1
								end
								data[ai] = gems[gidx]
							end
							if math.random() < STAGCHA then
								caverealms:salt_stalagmite(x,y,z, area, data)
							end
						elseif biome == 8 then
							local bi = area:index(x,y-1,z)
							if math.random() < 0.5 then
								data[vi] = c_gobsidian
								data[bi] = c_gobsidian
							else
								data[vi] = c_gobsidian2
								data[bi] = c_gobsidian2
							end
							if math.random() < FLACHA then --neverending flames
								data[ai] = c_flame
							end
						elseif biome == 9 then
							local bi = area:index(x,y-1,z)
							if math.random() < 0.05 then
								data[vi] = c_coalblock
								data[bi] = c_coalblock
							elseif math.random() < 0.15 then
								data[vi] = c_coaldust
								data[bi] = c_coaldust
							else
								data[vi] = c_desand
								data[bi] = c_desand
							end
							if math.random() < FLACHA * 0.75 then --neverending flames
								data[ai] = c_flame
							end
							if math.random() < GEMCHA then
								-- spikes of random size
								local spikes = { c_spike1, c_spike2, c_spike3, c_spike4, c_spike5 }
								local sidx = math.random(1, 12)
								if sidx > 5 then
									sidx = 1
								end
								data[ai] = spikes[sidx]
							end
Chris N's avatar
Chris N committed
387
						end
Chris N's avatar
Chris N committed
388
						
Chris N's avatar
Chris N committed
389 390 391 392 393
						if math.random() < STAGCHA then
							caverealms:stalagmite(x,y,z, area, data)
						end
						if math.random() < CRYSTAL then
							caverealms:crystal_stalagmite(x,y,z, area, data, biome)
394 395
						end
					end
Chris N's avatar
Chris N committed
396
					
HeroOfTheWinds's avatar
HeroOfTheWinds committed
397
				end
Chris N's avatar
Chris N committed
398 399 400
				nixyz2 = nixyz2 + 1
				nixz = nixz + 1
				vi = vi + 1
HeroOfTheWinds's avatar
HeroOfTheWinds committed
401
			end
Chris N's avatar
Chris N committed
402
			nixz = nixz - sidelen --shift the 2D index back
HeroOfTheWinds's avatar
HeroOfTheWinds committed
403
		end
Chris N's avatar
Chris N committed
404
		nixz = nixz + sidelen --shift the 2D index up a layer
HeroOfTheWinds's avatar
HeroOfTheWinds committed
405
	end
Chris N's avatar
Chris N committed
406
	
Chris N's avatar
Chris N committed
407
	--send data back to voxelmanip
HeroOfTheWinds's avatar
HeroOfTheWinds committed
408
	vm:set_data(data)
Chris N's avatar
Chris N committed
409
	--calc lighting
HeroOfTheWinds's avatar
HeroOfTheWinds committed
410 411
	vm:set_lighting({day=0, night=0})
	vm:calc_lighting()
Chris N's avatar
Chris N committed
412
	--write it to world
HeroOfTheWinds's avatar
HeroOfTheWinds committed
413
	vm:write_to_map(data)
Chris N's avatar
Chris N committed
414 415

	local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took
Chris N's avatar
Chris N committed
416
	print ("[caverealms] "..chugent.." ms") --tell people how long
417
end)
Craig Robbins's avatar
Craig Robbins committed
418
print("[caverealms] loaded!")