mapgen.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. local c_air=minetest.get_content_id("air")
  2. local c_pre_barrel=minetest.get_content_id("dungeon:pre_barrel")
  3. local c_rope=minetest.get_content_id("rope:rope")
  4. local c_maze=minetest.get_content_id("dungeon:maze")
  5. local c_stone=minetest.get_content_id("default:stone")
  6. local data
  7. local va
  8. local function createCuboid(min,max,node)
  9. node=node or c_stone
  10. for fi in va:iterp(min,max) do
  11. data[fi]=node
  12. end
  13. end
  14. local function barriers(min,max)
  15. if Random:next(1,2)==1 then
  16. createCuboid(
  17. {x=max.x+2,y=min.y,z=min.z},
  18. {x=max.x+2,y=min.y,z=max.z+4},
  19. c_stone
  20. )
  21. createCuboid(
  22. {x=min.x,y=min.y,z=max.z+2},
  23. {x=max.x+2,y=max.y-32,z=max.z+2},
  24. c_maze
  25. )
  26. else
  27. createCuboid(
  28. {x=min.x,y=min.y,z=max.z+2},
  29. {x=max.x+4,y=min.y,z=max.z+2},
  30. c_stone
  31. )
  32. createCuboid(
  33. {x=max.x+2,y=min.y,z=min.z},
  34. {x=max.x+2,y=max.y-32,z=max.z+2},
  35. c_maze
  36. )
  37. end
  38. if Random:next(1,20)<20 then
  39. createCuboid(
  40. {x=min.x,y=max.y-32,z=min.z},
  41. {x=max.x+2,y=max.y-32,z=max.z+2},
  42. c_maze
  43. )
  44. end
  45. end
  46. local function createRope(ix,iy,iz,length)
  47. for fi=0,length-1,1 do
  48. data[va:index(ix,iy-fi,iz)]=c_rope
  49. end
  50. for fi=1,3,1 do
  51. data[va:index(ix,iy+fi,iz)]=c_air
  52. end
  53. end
  54. local function createPassage(ix,iy,iz,xDir,height)
  55. height=height or 2
  56. local min={x=ix,y=iy,z=iz}
  57. local max
  58. if xDir then
  59. max={x=ix+1,y=iy+height-1,z=iz}
  60. else
  61. max={x=ix,y=iy+height-1,z=iz+1}
  62. end
  63. for fi in va:iterp(min,max) do
  64. data[fi]=c_air
  65. end
  66. end
  67. local function create8Entrances(min,max,height)
  68. local ly=min.y+1
  69. local tmp=math.floor((max.z-min.z)/3)+min.z
  70. createPassage(max.x+1,ly,tmp,false,height)
  71. createPassage(min.x,ly,tmp,false,height)
  72. tmp=math.floor(2*(max.z-min.z)/3)+min.z
  73. createPassage(max.x+1,ly,tmp,false,height)
  74. createPassage(min.x,ly,tmp,false,height)
  75. tmp=math.floor((max.x-min.x)/3)+min.x
  76. createPassage(tmp,ly,max.z+1,true,height)
  77. createPassage(tmp,ly,min.z,true,height)
  78. tmp=math.floor(2*(max.x-min.x)/3)+min.x
  79. createPassage(tmp,ly,max.z+1,true,height)
  80. createPassage(tmp,ly,min.z,true,height)
  81. end
  82. local function create4Entrances(min,max,height)
  83. local ly=min.y+1
  84. local tmp=math.floor((max.z-min.z)/2)+min.z
  85. createPassage(max.x+1,ly,tmp,false,height)
  86. createPassage(min.x,ly,tmp,false,height)
  87. tmp=math.floor((max.x-min.x)/2)+min.x
  88. createPassage(tmp,ly,max.z+1,true,height)
  89. createPassage(tmp,ly,min.z,true,height)
  90. end
  91. local function createRect(min,max,node)
  92. local ly=min.y+1
  93. createCuboid({x=min.x,y=ly,z=min.z},{x=min.x,y=max.y,z=max.z},node)
  94. createCuboid({x=max.x,y=ly,z=min.z},{x=max.x,y=max.y,z=max.z},node)
  95. createCuboid({x=min.x,y=ly,z=min.z},{x=max.x,y=max.y,z=min.z},node)
  96. createCuboid({x=min.x,y=ly,z=max.z},{x=max.x,y=max.y,z=max.z},node)
  97. end
  98. local function rooms(min,max)
  99. if max.x-min.x>10 and max.z-min.z>10 then
  100. local xWall=math.ceil((max.x-min.x)/Random:next(2,4))+min.x
  101. local ly=min.y+1
  102. createCuboid({x=xWall,y=ly,z=min.z+1},{x=xWall,y=ly+2,z=max.z})
  103. createPassage(xWall,ly,math.floor((max.z-min.z)/3)+min.z,false)
  104. createPassage(xWall,ly,math.floor(2*(max.z-min.z)/3)+min.z,false)
  105. local zWall=math.ceil((max.z-min.z)/Random:next(2,4))+min.z
  106. createCuboid({x=min.x+1,y=ly,z=zWall},{x=max.x,y=ly+2,z=zWall})
  107. createPassage(math.floor((max.x-min.x)/3)+min.x,ly,zWall,true)
  108. createPassage(math.floor(2*(max.x-min.x)/3)+min.x,ly,zWall,true)
  109. rooms(min,{x=xWall,y=max.y,z=zWall})
  110. rooms({x=xWall,y=min.y,z=zWall},max)
  111. rooms({x=xWall,y=min.y,z=min.z},{x=max.x,y=max.y,z=zWall})
  112. rooms({x=min.x,y=min.y,z=zWall},{x=xWall,y=max.y,z=max.z})
  113. end
  114. end
  115. local function barrels(min,max,count)
  116. local lx
  117. local lz
  118. for fi=1,count,1 do
  119. lx=Random:next(min.x,max.x)
  120. lz=Random:next(min.z,max.z)
  121. while data[va:index(lx,min.y,lz)]==c_stone do
  122. lx=Random:next(min.x,max.x)
  123. lz=Random:next(min.z,max.z)
  124. end
  125. data[va:index(lx,min.y,lz)]=c_pre_barrel
  126. end
  127. end
  128. function tower(min,max)
  129. local ps1
  130. local ps2
  131. for fy=min.y,max.y-36,4 do
  132. ps1={x=min.x,y=fy,z=min.z}
  133. rooms(ps1,max)
  134. barrels({x=ps1.x,y=fy+1,z=ps1.z},max,3)
  135. ps2={x=max.x+1,y=fy,z=max.z+1}
  136. createCuboid(ps1,ps2)
  137. createRope(Random:next(ps1.x+5,ps2.x-6),fy,Random:next(ps1.z+5,ps2.z-6),4)
  138. end
  139. createRect(min,{x=max.x+1,y=max.y-36,z=max.z+1})
  140. create8Entrances(min,max)
  141. createCuboid({x=min.x,y=max.y-35,z=min.z},{x=max.x+1,y=max.y-35,z=max.z+1})
  142. end
  143. function platforms(min,max)
  144. local lx1_3=(max.x-min.x)/3+min.x
  145. local lx2_3=2*(max.x-min.x)/3+min.x
  146. local lz1_3=(max.z-min.z)/2+min.z
  147. local lz2_3=2*(max.z-min.z)/2+min.z
  148. local ps1={x=min.x,y=min.y,z=min.z}
  149. local ps2={x=max.x+1,y=min.y,z=max.z+1}
  150. createCuboid(ps1,ps2)
  151. barrels({x=ps1.x,y=min.y+1,z=ps1.z},ps2,1)
  152. for fy=min.y+5,max.y-36,4 do
  153. ps1={x=Random:next(min.x,lx1_3),y=fy,z=Random:next(min.z,lz1_3)}
  154. ps2={x=Random:next(lx2_3,max.x),y=fy,z=Random:next(lz2_3,max.z)}
  155. createCuboid(ps1,ps2)
  156. createRope(Random:next(lx1_3,lx2_3),fy,Random:next(lz1_3,lz2_3),4)
  157. barrels({x=ps1.x,y=fy+1,z=ps1.z},ps2,1)
  158. end
  159. end
  160. function weirdBuilding(min,max)
  161. local lx1_3=(max.x-min.x)/3+min.x
  162. local lx2_3=2*(max.x-min.x)/3+min.x
  163. local lz1_3=(max.z-min.z)/3+min.z
  164. local lz2_3=2*(max.z-min.z)/3+min.z
  165. local ps1={x=min.x,y=min.y,z=min.z}
  166. local ps2={x=max.x+1,y=min.y+3,z=max.z+1}
  167. rooms(ps1,ps2)
  168. createCuboid(ps1,{x=ps2.x,y=min.y,z=ps2.z})
  169. createRect(ps1,ps2)
  170. createCuboid({x=ps1.x,y=ps1.y+4,z=ps1.z},{x=ps2.x,y=ps1.y+4,z=ps2.z})
  171. barrels({x=ps1.x,y=ps1.y+1,z=ps1.z},ps2,2)
  172. local rx
  173. local rz
  174. for fy=min.y+5,max.y-37,5 do
  175. ps1={x=Random:next(min.x,lx1_3-1),y=fy,z=Random:next(min.z,lz1_3-1)}
  176. ps2={x=Random:next(lx2_3+5,max.x),y=fy+3,z=Random:next(lz2_3+5,max.z)}
  177. rooms(ps1,ps2)
  178. createCuboid(ps1,{x=ps2.x,y=ps1.y,z=ps2.z})
  179. createRect(ps1,ps2)
  180. createCuboid({x=ps1.x,y=ps1.y+4,z=ps1.z},{x=ps2.x,y=ps1.y+4,z=ps2.z})
  181. rx=Random:next(lx1_3,lx2_3)
  182. rz=Random:next(lz1_3,lz2_3)
  183. createRope(rx,fy,rz,5)
  184. barrels({x=ps1.x,y=fy+1,z=ps1.z},ps2,2)
  185. end
  186. create8Entrances(min,max)
  187. end
  188. function pyramid(min,max)
  189. local ps1
  190. local ps2
  191. local ld=0
  192. for fy=min.y,max.y-36,4 do
  193. ps1={x=min.x+ld,y=fy,z=min.z+ld}
  194. ps2={x=max.x+1-ld,y=fy+3,z=max.z+1-ld}
  195. rooms(ps1,ps2)
  196. createCuboid(ps1,{x=ps2.x,y=ps1.y,z=ps2.z})
  197. createRope(Random:next(ps1.x+5,ps2.x-6),fy,Random:next(ps1.z+5,ps2.z-6),4)
  198. createRect(ps1,ps2)
  199. barrels({x=ps1.x,y=fy+1,z=ps1.z},ps2,3)
  200. ld=ld+1
  201. end
  202. createCuboid({x=ps1.x,y=max.y-35,z=ps1.z},{x=ps2.x,y=max.y-35,z=ps2.z})
  203. create8Entrances(min,max)
  204. end
  205. function upsideDownPyramid(min,max)
  206. local ps1
  207. local ps2
  208. local ld=19
  209. createCuboid(min,{x=max.x+1,y=min.y,z=max.z+1})
  210. for fy=min.y,max.y-36,4 do
  211. ld=ld-1
  212. ps1={x=min.x+ld,y=fy,z=min.z+ld}
  213. ps2={x=max.x+1-ld,y=fy+3,z=max.z+1-ld}
  214. rooms(ps1,ps2)
  215. createCuboid(ps1,{x=ps2.x,y=ps1.y,z=ps2.z})
  216. createRope(Random:next(ps1.x+5,ps2.x-6),fy,Random:next(ps1.z+5,ps2.z-6),4)
  217. createRect(ps1,ps2)
  218. barrels({x=ps1.x,y=fy+1,z=ps1.z},ps2,3)
  219. end
  220. create4Entrances({x=min.x+18,y=min.y,z=min.z+18},{x=max.x-18,y=max.y,z=max.z-18})
  221. createCuboid({x=ps1.x,y=max.y-35,z=ps1.z},{x=ps2.x,y=max.y-35,z=ps2.z})
  222. end
  223. local function towerWithPool(min,max)
  224. tower(min,max)
  225. local height=min.y+4*Random:next(1,5)
  226. createRect(
  227. {x=min.x+30,y=min.y,z=min.z+30},
  228. {x=min.x+50,y=height,z=min.z+50},
  229. minetest.get_content_id("default:glass")
  230. )
  231. createCuboid(
  232. {x=min.x+31,y=min.y+1,z=min.z+31},
  233. {x=min.x+49,y=height,z=min.z+49},
  234. minetest.get_content_id("default:water_source")
  235. )
  236. createCuboid(
  237. {x=min.x+31,y=height+1,z=min.z+31},
  238. {x=min.x+49,y=height+3,z=min.z+49},
  239. c_air
  240. )
  241. for fy=min.y+3,height-2,4 do
  242. create4Entrances(
  243. {x=min.x+30,y=fy,z=min.z+30},
  244. {x=min.x+49,y=height,z=min.z+49},
  245. 3
  246. )
  247. end
  248. end
  249. local function towerWithLava(min,max)
  250. tower(min,max)
  251. local ps1
  252. local ps2
  253. local ld=0
  254. local height=min.y+4*Random:next(1,5)
  255. local lc=minetest.get_content_id("default:obsidian_glass")
  256. local lc2=minetest.get_content_id("default:lava_source")
  257. for fy=min.y,height,4 do
  258. ps1={x=min.x+30+ld,y=fy,z=min.z+30+ld}
  259. ps2={x=min.x+50-ld,y=fy+4,z=min.z+50-ld}
  260. createRect(ps1,ps2,lc)
  261. createCuboid(
  262. {x=min.x+31+ld,y=fy,z=min.z+31+ld},
  263. {x=min.x+49-ld,y=fy+4,z=min.z+49-ld},
  264. lc2
  265. )
  266. ld=ld+1
  267. end
  268. createCuboid(
  269. {x=min.x+31,y=min.y,z=min.z+31},
  270. {x=min.x+49,y=min.y,z=min.z+49}
  271. )
  272. createCuboid(
  273. {x=min.x+30+ld,y=height+5,z=min.z+30+ld},
  274. {x=min.x+50-ld,y=height+7,z=min.z+50-ld},
  275. c_air
  276. )
  277. end
  278. local generate={
  279. tower,
  280. tower,
  281. tower,
  282. tower,
  283. tower,
  284. tower,
  285. tower,
  286. tower,
  287. platforms,
  288. weirdBuilding,
  289. pyramid,
  290. upsideDownPyramid,
  291. towerWithPool,
  292. towerWithLava,
  293. }
  294. --The size of the areas is 80x80x80
  295. minetest.register_on_generated(
  296. function(minp,maxp)
  297. if minp.y>-200 then
  298. return
  299. end
  300. local vm,emin,emax=minetest.get_mapgen_object("voxelmanip")
  301. local area=vm:read_from_map(emin,emax)
  302. data=vm:get_data()
  303. va=VoxelArea:new({MinEdge=emin,MaxEdge=emax})
  304. emin.x=emin.x+17
  305. emax.x=emax.x-17
  306. emin.z=emin.z+17
  307. emax.z=emax.z-17
  308. createCuboid(emin,{x=emax.x+2,y=emax.y-33,z=emax.z+2},c_air)
  309. barriers(emin,emax)
  310. generate[Random:next(1,#generate)](emin,emax)
  311. vm:set_data(data)
  312. vm:set_lighting(vm:get_light_data())
  313. vm:write_to_map(true)
  314. end
  315. )
  316. local food={
  317. "default:apple","default:blueberries",
  318. "default:apple","default:blueberries",
  319. "default:apple","default:blueberries",
  320. "farming:bread","flowers:mushroom_brown",
  321. "farming:bread","flowers:mushroom_brown",
  322. "mobs:meat_raw","mobs:meat",
  323. "mobs:meat_raw","mobs:meat",
  324. "zombie:rotten_flesh"
  325. }
  326. local ores={
  327. "default:coal_lump",
  328. "default:coal_lump",
  329. "default:bronze_ingot",
  330. "default:bronze_ingot",
  331. "default:copper_ingot",
  332. "default:copper_ingot",
  333. "default:copper_ingot",
  334. "default:gold_ingot",
  335. "default:gold_ingot",
  336. "default:steel_ingot",
  337. "default:steel_ingot",
  338. "default:tin_ingot",
  339. "default:diamond",
  340. "default:mese_crystal"
  341. }
  342. local wood={
  343. "default:wood",
  344. "default:junglewood",
  345. "default:pine_wood",
  346. "default:acacia_wood",
  347. "default:aspen_wood",
  348. "default:stick"
  349. }
  350. local misc={
  351. {
  352. "default:cactus",
  353. "default:papyrus",
  354. "default:clay",
  355. "default:flint",
  356. "default:obsidian_shard",
  357. "default:glass",
  358. "default:ice",
  359. "default:snow",
  360. },
  361. {
  362. "flowers:rose",
  363. "flowers:tulip",
  364. "flowers:dandelion_yellow",
  365. "flowers:chrysanthemum_green",
  366. "flowers:geranium",
  367. "flowers:viola",
  368. "flowers:dandelion_white",
  369. "flowers:tulip_black",
  370. },
  371. {
  372. "farming:cotton",
  373. "farming:cotton",
  374. }
  375. }
  376. local function fill(inv)
  377. inv:add_item("main",ItemStack(food[Random:next(1,#food)]))
  378. inv:add_item("main",ItemStack(ores[Random:next(1,#ores)]))
  379. inv:add_item("main",ItemStack(wood[Random:next(1,#wood)]))
  380. local tmp=Random:next(1,#misc)
  381. inv:add_item("main",ItemStack(misc[tmp][Random:next(1,#misc[tmp])]))
  382. end
  383. local function spawn(ps)
  384. local objs=minetest.get_objects_inside_radius(ps,10)
  385. local count=0
  386. local ent=nil
  387. for _, obj in ipairs(objs) do
  388. ent=obj:get_luaentity()
  389. if ent and ent.name and ent.name=="mobs_dungeon:guard" then
  390. count=count+1
  391. end
  392. end
  393. if count<3 then
  394. for fi=count,4,1 do
  395. minetest.add_entity({x=ps.x,y=ps.y+1,z=ps.z},"mobs_dungeon:guard")
  396. end
  397. end
  398. end
  399. minetest.register_abm(
  400. {
  401. nodenames={"dungeon:barrel"},
  402. interval=10.0,
  403. chance=6,
  404. catch_up=true,
  405. action=function(ps,node)
  406. local inv=minetest.get_inventory({type="node",pos=ps})
  407. if inv:is_empty("main") then
  408. fill(minetest.get_inventory({type="node",pos=ps}))
  409. end
  410. spawn(ps)
  411. end
  412. }
  413. )
  414. minetest.register_abm(
  415. {
  416. nodenames={"dungeon:pre_barrel"},
  417. interval=1.0,
  418. chance=1,
  419. catch_up=true,
  420. action=function(ps,node)
  421. minetest.set_node(ps,{name="dungeon:barrel"})
  422. fill(minetest.get_inventory({type="node",pos=ps}))
  423. spawn(ps)
  424. end
  425. }
  426. )