init.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. -- caverealms v.0.8 by HeroOfTheWinds
  2. -- original cave code modified from paramat's subterrain
  3. -- For Minetest 0.4.8 stable
  4. -- Depends default
  5. -- License: code WTFPL
  6. caverealms = {} --create a container for functions and constants
  7. --grab a shorthand for the filepath of the mod
  8. local modpath = minetest.get_modpath(minetest.get_current_modname())
  9. --load companion lua files
  10. dofile(modpath.."/config.lua") --configuration file; holds various constants
  11. dofile(modpath.."/crafting.lua") --crafting recipes
  12. dofile(modpath.."/nodes.lua") --node definitions
  13. dofile(modpath.."/functions.lua") --function definitions
  14. dofile(modpath.."/abms.lua") --abm definitions
  15. if caverealms.config.falling_icicles == true then
  16. dofile(modpath.."/falling_ice.lua") --complicated function for falling icicles
  17. print("[caverealms] falling icicles enabled.")
  18. end
  19. local FORTRESSES = caverealms.config.fortresses --true | Should fortresses spawn?
  20. local FOUNTAINS = caverealms.config.fountains --true | Should fountains spawn?
  21. -- Parameters
  22. local YMIN = caverealms.config.ymin -- Approximate realm limits.
  23. local YMAX = caverealms.config.ymax
  24. local TCAVE = caverealms.config.tcave --0.5 -- Cave threshold. 1 = small rare caves, 0.5 = 1/3rd ground volume, 0 = 1/2 ground volume
  25. local BLEND = 128 -- Cave blend distance near YMIN, YMAX
  26. local STAGCHA = caverealms.config.stagcha --0.002 --chance of stalagmites
  27. local STALCHA = caverealms.config.stalcha --0.003 --chance of stalactites
  28. local CRYSTAL = caverealms.config.crystal --0.007 --chance of glow crystal formations
  29. local GEMCHA = caverealms.config.gemcha --0.03 --chance of small glow gems
  30. local MUSHCHA = caverealms.config.mushcha --0.04 --chance of mushrooms
  31. local MYCCHA = caverealms.config.myccha --0.03 --chance of mycena mushrooms
  32. local WORMCHA = caverealms.config.wormcha --0.03 --chance of glow worms
  33. local GIANTCHA = caverealms.config.giantcha --0.001 -- chance of giant mushrooms
  34. local ICICHA = caverealms.config.icicha --0.035 -- chance of icicles
  35. local FLACHA = caverealms.config.flacha --0.04 --chance of constant flames
  36. local FOUNCHA = caverealms.config.founcha --0.001 --chance of statue + fountain
  37. local FORTCHA = caverealms.config.fortcha --0.0003 --chance of DM Fortresses
  38. local DM_TOP = caverealms.config.dm_top -- -4000 --level at which Dungeon Master Realms start to appear
  39. local DM_BOT = caverealms.config.dm_bot -- -5000 --level at which "" ends
  40. local DEEP_CAVE = caverealms.config.deep_cave -- -7000 --level at which deep cave biomes take over
  41. -- 3D noise for caves
  42. local np_cave = {
  43. offset = 0,
  44. scale = 1,
  45. spread = {x=512, y=256, z=512}, -- squashed 2:1
  46. seed = 59033,
  47. octaves = 6,
  48. persist = 0.63
  49. }
  50. -- 3D noise for wave
  51. local np_wave = {
  52. offset = 0,
  53. scale = 1,
  54. spread = {x=256, y=256, z=256},
  55. seed = -400000000089,
  56. octaves = 3,
  57. persist = 0.67
  58. }
  59. -- 2D noise for biome
  60. local np_biome = {
  61. offset = 0,
  62. scale = 1,
  63. spread = {x=250, y=250, z=250},
  64. seed = 9130,
  65. octaves = 3,
  66. persist = 0.5
  67. }
  68. -- Stuff
  69. subterrain = {}
  70. local yblmin = YMIN + BLEND * 1.5
  71. local yblmax = YMAX - BLEND * 1.5
  72. local nvals_cave = {}
  73. local nvals_wave = {}
  74. local nvals_biome = {}
  75. -- On generated function
  76. minetest.register_on_generated(function(minp, maxp, seed)
  77. --if out of range of caverealms limits
  78. if minp.y > YMAX or maxp.y < YMIN then
  79. return --quit; otherwise, you'd have stalagmites all over the place
  80. end
  81. --easy reference to commonly used values
  82. local t1 = os.clock()
  83. local x1 = maxp.x
  84. local y1 = maxp.y
  85. local z1 = maxp.z
  86. local x0 = minp.x
  87. local y0 = minp.y
  88. local z0 = minp.z
  89. print ("[caverealms] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk
  90. local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
  91. local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
  92. local data = vm:get_data()
  93. --grab content IDs
  94. local c_air = minetest.get_content_id("air")
  95. local c_stone = minetest.get_content_id("default:stone")
  96. if (minetest.get_modpath("moontest")) then
  97. c_air = minetest.get_content_id("moontest:vacuum")
  98. c_stone = minetest.get_content_id("moontest:stone")
  99. end
  100. local c_water = minetest.get_content_id("default:water_source")
  101. local c_lava = minetest.get_content_id("default:lava_source")
  102. local c_ice = minetest.get_content_id("default:ice")
  103. local c_thinice = minetest.get_content_id("caverealms:thin_ice")
  104. local c_crystal = minetest.get_content_id("caverealms:glow_crystal")
  105. local c_gem1 = minetest.get_content_id("caverealms:glow_gem")
  106. local c_gem2 = minetest.get_content_id("caverealms:glow_gem_2")
  107. local c_gem3 = minetest.get_content_id("caverealms:glow_gem_3")
  108. local c_gem4 = minetest.get_content_id("caverealms:glow_gem_4")
  109. local c_gem5 = minetest.get_content_id("caverealms:glow_gem_5")
  110. local c_saltgem1 = minetest.get_content_id("caverealms:salt_gem")
  111. local c_saltgem2 = minetest.get_content_id("caverealms:salt_gem_2")
  112. local c_saltgem3 = minetest.get_content_id("caverealms:salt_gem_3")
  113. local c_saltgem4 = minetest.get_content_id("caverealms:salt_gem_4")
  114. local c_saltgem5 = minetest.get_content_id("caverealms:salt_gem_5")
  115. local c_spike1 = minetest.get_content_id("caverealms:spike")
  116. local c_spike2 = minetest.get_content_id("caverealms:spike_2")
  117. local c_spike3 = minetest.get_content_id("caverealms:spike_3")
  118. local c_spike4 = minetest.get_content_id("caverealms:spike_4")
  119. local c_spike5 = minetest.get_content_id("caverealms:spike_5")
  120. local c_moss = minetest.get_content_id("caverealms:stone_with_moss")
  121. local c_lichen = minetest.get_content_id("caverealms:stone_with_lichen")
  122. local c_algae = minetest.get_content_id("caverealms:stone_with_algae")
  123. local c_salt = minetest.get_content_id("caverealms:stone_with_salt")
  124. local c_hcobble = minetest.get_content_id("caverealms:hot_cobble")
  125. local c_gobsidian = minetest.get_content_id("caverealms:glow_obsidian")
  126. local c_gobsidian2 = minetest.get_content_id("caverealms:glow_obsidian_2")
  127. local c_coalblock = minetest.get_content_id("default:coalblock")
  128. local c_desand = minetest.get_content_id("default:desert_sand")
  129. local c_coaldust = minetest.get_content_id("caverealms:coal_dust")
  130. local c_fungus = minetest.get_content_id("caverealms:fungus")
  131. local c_mycena = minetest.get_content_id("caverealms:mycena")
  132. local c_worm = minetest.get_content_id("caverealms:glow_worm")
  133. local c_iciu = minetest.get_content_id("caverealms:icicle_up")
  134. local c_icid = minetest.get_content_id("caverealms:icicle_down")
  135. local c_flame = minetest.get_content_id("caverealms:constant_flame")
  136. local c_fountain = minetest.get_content_id("caverealms:s_fountain")
  137. local c_fortress = minetest.get_content_id("caverealms:s_fortress")
  138. --mandatory values
  139. local sidelen = x1 - x0 + 1 --length of a mapblock
  140. local chulens = {x=sidelen, y=sidelen, z=sidelen} --table of chunk edges
  141. local chulens2D = {x=sidelen, y=sidelen, z=1}
  142. local minposxyz = {x=x0, y=y0, z=z0} --bottom corner
  143. local minposxz = {x=x0, y=z0} --2D bottom corner
  144. minetest.get_perlin_map(np_cave, chulens):get3dMap_flat(minposxyz, nvals_cave) --cave noise for structure
  145. minetest.get_perlin_map(np_wave, chulens):get3dMap_flat(minposxyz, nvals_wave) --wavy structure of cavern ceilings and floors
  146. minetest.get_perlin_map(np_biome, chulens2D):get2dMap_flat({x=x0+150, y=z0+50}, nvals_biome) --2D noise for biomes (will be 3D humidity/temp later)
  147. local nixyz = 1 --3D node index
  148. local nixz = 1 --2D node index
  149. local nixyz2 = 1 --second 3D index for second loop
  150. for z = z0, z1 do -- for each xy plane progressing northwards
  151. --structure loop
  152. for y = y0, y1 do -- for each x row progressing upwards
  153. local tcave --declare variable
  154. --determine the overal cave threshold
  155. if y < yblmin then
  156. tcave = TCAVE + ((yblmin - y) / BLEND) ^ 2
  157. elseif y > yblmax then
  158. tcave = TCAVE + ((y - yblmax) / BLEND) ^ 2
  159. else
  160. tcave = TCAVE
  161. end
  162. local vi = area:index(x0, y, z) --current node index
  163. for x = x0, x1 do -- for each node do
  164. if (nvals_cave[nixyz] + nvals_wave[nixyz])/2 > tcave then --if node falls within cave threshold
  165. data[vi] = c_air --hollow it out to make the cave
  166. end
  167. --increment indices
  168. nixyz = nixyz + 1
  169. vi = vi + 1
  170. end
  171. end
  172. --decoration loop
  173. for y = y0, y1 do -- for each x row progressing upwards
  174. local is_deep = false
  175. if y < DEEP_CAVE then
  176. is_deep = true
  177. end
  178. local tcave --same as above
  179. if y < yblmin then
  180. tcave = TCAVE + ((yblmin - y) / BLEND) ^ 2
  181. elseif y > yblmax then
  182. tcave = TCAVE + ((y - yblmax) / BLEND) ^ 2
  183. else
  184. tcave = TCAVE
  185. end
  186. local vi = area:index(x0, y, z)
  187. for x = x0, x1 do -- for each node do
  188. --determine biome
  189. local biome = false --preliminary declaration
  190. local n_biome = nvals_biome[nixz] --make an easier reference to the noise
  191. --compare noise values to determine a biome
  192. if n_biome >= 0 and n_biome < 0.5 then
  193. biome = 1 --moss
  194. if is_deep then
  195. biome = 7 --salt crystal
  196. end
  197. elseif n_biome <= -0.5 then
  198. biome = 2 --fungal
  199. if is_deep then
  200. biome = 8 --glow obsidian
  201. end
  202. elseif n_biome >= 0.5 then
  203. if n_biome >= 0.7 then
  204. biome = 5 --deep glaciated
  205. else
  206. biome = 4 --glaciated
  207. end
  208. else
  209. biome = 3 --algae
  210. if is_deep then
  211. biome = 9 --coal dust
  212. end
  213. end
  214. if y <= DM_TOP and y >= DM_BOT then
  215. biome = 6 --DUNGEON MASTER'S LAIR
  216. end
  217. --if y <= -1000 then
  218. --biome = 6 --DUNGEON MASTER'S LAIR
  219. --end
  220. if math.floor(((nvals_cave[nixyz2] + nvals_wave[nixyz2])/2)*100) == math.floor(tcave*100) then
  221. --ceiling
  222. local ai = area:index(x,y+1,z) --above index
  223. if data[ai] == c_stone and data[vi] == c_air then --ceiling
  224. if math.random() < ICICHA and (biome == 4 or biome == 5) then
  225. data[vi] = c_icid
  226. end
  227. if math.random() < WORMCHA then
  228. data[vi] = c_worm
  229. local bi = area:index(x,y-1,z)
  230. data[bi] = c_worm
  231. if math.random(2) == 1 then
  232. local bbi = area:index(x,y-2,z)
  233. data[bbi] = c_worm
  234. if math.random(2) ==1 then
  235. local bbbi = area:index(x,y-3,z)
  236. data[bbbi] = c_worm
  237. end
  238. end
  239. end
  240. if math.random() < STALCHA then
  241. caverealms:stalactite(x,y,z, area, data)
  242. end
  243. if math.random() < CRYSTAL then
  244. caverealms:crystal_stalactite(x,y,z, area, data, biome)
  245. end
  246. end
  247. --ground
  248. local bi = area:index(x,y-1,z) --below index
  249. if data[bi] == c_stone and data[vi] == c_air then --ground
  250. local ai = area:index(x,y+1,z)
  251. --place floor material, add plants/decorations
  252. if biome == 1 then
  253. data[vi] = c_moss
  254. if math.random() < GEMCHA then
  255. -- gems of random size
  256. local gems = { c_gem1, c_gem2, c_gem3, c_gem4, c_gem5 }
  257. local gidx = math.random(1, 12)
  258. if gidx > 5 then
  259. gidx = 1
  260. end
  261. data[ai] = gems[gidx]
  262. end
  263. elseif biome == 2 then
  264. data[vi] = c_lichen
  265. if math.random() < MUSHCHA then --mushrooms
  266. data[ai] = c_fungus
  267. end
  268. if math.random() < MYCCHA then --mycena mushrooms
  269. data[ai] = c_mycena
  270. end
  271. if math.random() < GIANTCHA then --giant mushrooms
  272. caverealms:giant_shroom(x, y, z, area, data)
  273. end
  274. elseif biome == 3 then
  275. data[vi] = c_algae
  276. elseif biome == 4 then
  277. data[vi] = c_thinice
  278. local bi = area:index(x,y-1,z)
  279. data[bi] = c_thinice
  280. if math.random() < ICICHA then --if glaciated, place icicles
  281. data[ai] = c_iciu
  282. end
  283. elseif biome == 5 then
  284. data[vi] = c_ice
  285. local bi = area:index(x,y-1,z)
  286. data[bi] = c_ice
  287. if math.random() < ICICHA then --if glaciated, place icicles
  288. data[ai] = c_iciu
  289. end
  290. elseif biome == 6 then
  291. data[vi] = c_hcobble
  292. if math.random() < FLACHA then --neverending flames
  293. data[ai] = c_flame
  294. end
  295. if math.random() < FOUNCHA and FOUNTAINS then --DM FOUNTAIN
  296. data[ai] = c_fountain
  297. end
  298. if math.random() < FORTCHA and FORTRESSES then --DM FORTRESS
  299. data[ai] = c_fortress
  300. end
  301. elseif biome == 7 then
  302. local bi = area:index(x,y-1,z)
  303. data[vi] = c_salt
  304. data[bi] = c_salt
  305. if math.random() < GEMCHA then
  306. -- gems of random size
  307. local gems = { c_saltgem1, c_saltgem2, c_saltgem3, c_saltgem4, c_saltgem5 }
  308. local gidx = math.random(1, 12)
  309. if gidx > 5 then
  310. gidx = 1
  311. end
  312. data[ai] = gems[gidx]
  313. end
  314. if math.random() < STAGCHA then
  315. caverealms:salt_stalagmite(x,y,z, area, data)
  316. end
  317. elseif biome == 8 then
  318. local bi = area:index(x,y-1,z)
  319. if math.random() < 0.5 then
  320. data[vi] = c_gobsidian
  321. data[bi] = c_gobsidian
  322. else
  323. data[vi] = c_gobsidian2
  324. data[bi] = c_gobsidian2
  325. end
  326. if math.random() < FLACHA then --neverending flames
  327. data[ai] = c_flame
  328. end
  329. elseif biome == 9 then
  330. local bi = area:index(x,y-1,z)
  331. if math.random() < 0.05 then
  332. data[vi] = c_coalblock
  333. data[bi] = c_coalblock
  334. elseif math.random() < 0.15 then
  335. data[vi] = c_coaldust
  336. data[bi] = c_coaldust
  337. else
  338. data[vi] = c_desand
  339. data[bi] = c_desand
  340. end
  341. if math.random() < FLACHA * 0.75 then --neverending flames
  342. data[ai] = c_flame
  343. end
  344. if math.random() < GEMCHA then
  345. -- spikes of random size
  346. local spikes = { c_spike1, c_spike2, c_spike3, c_spike4, c_spike5 }
  347. local sidx = math.random(1, 12)
  348. if sidx > 5 then
  349. sidx = 1
  350. end
  351. data[ai] = spikes[sidx]
  352. end
  353. end
  354. if math.random() < STAGCHA then
  355. caverealms:stalagmite(x,y,z, area, data)
  356. end
  357. if math.random() < CRYSTAL then
  358. caverealms:crystal_stalagmite(x,y,z, area, data, biome)
  359. end
  360. end
  361. end
  362. nixyz2 = nixyz2 + 1
  363. nixz = nixz + 1
  364. vi = vi + 1
  365. end
  366. nixz = nixz - sidelen --shift the 2D index back
  367. end
  368. nixz = nixz + sidelen --shift the 2D index up a layer
  369. end
  370. --send data back to voxelmanip
  371. vm:set_data(data)
  372. --calc lighting
  373. vm:set_lighting({day=0, night=0})
  374. vm:calc_lighting()
  375. --write it to world
  376. vm:write_to_map(data)
  377. local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took
  378. print ("[caverealms] "..chugent.." ms") --tell people how long
  379. end)
  380. print("[caverealms] loaded!")