1 local S
= minetest
.get_translator("tsm_pyramids")
3 -- Pyramid width (must be an odd number)
5 -- Pyramid width minus 1
6 local PYRA_Wm
= PYRA_W
- 1
7 -- Half of (Pyramid width minus 1)
8 local PYRA_Wh
= PYRA_Wm
/ 2
9 -- Minimum spawn height
14 dofile(minetest
.get_modpath("tsm_pyramids").."/mummy.lua")
15 dofile(minetest
.get_modpath("tsm_pyramids").."/nodes.lua")
16 dofile(minetest
.get_modpath("tsm_pyramids").."/room.lua")
18 local mg_name
= minetest
.get_mapgen_setting("mg_name")
21 {name
="default:apple", max = 3},
22 {name
="default:steel_ingot", max = 3},
23 {name
="default:copper_ingot", max = 3},
24 {name
="default:gold_ingot", max = 2},
25 {name
="default:diamond", max = 1},
26 {name
="default:pick_steel", max = 1},
27 {name
="default:pick_diamond", max = 1},
28 {name
="default:papyrus", max = 9},
31 if minetest
.get_modpath("farming") then
32 table.insert(chest_stuff
, {name
="farming:bread", max = 3})
33 table.insert(chest_stuff
, {name
="farming:cotton", max = 8})
35 table.insert(chest_stuff
, {name
="farming:apple", max = 8})
36 table.insert(chest_stuff
, {name
="farming:apple", max = 3})
38 if minetest
.get_modpath("tnt") then
39 table.insert(chest_stuff
, {name
="tnt:gunpowder", max = 6})
41 table.insert(chest_stuff
, {name
="farming:apple", max = 3})
44 function tsm_pyramids
.fill_chest(pos
, stype
, flood_sand
)
45 local sand
= "default:sand"
46 if stype
== "desert_sandstone" or stype
== "desert_stone" then
47 sand
= "default:desert_sand"
49 local n
= minetest
.get_node(pos
)
50 if n
and n
.name
and n
.name
== "default:chest" then
51 local meta
= minetest
.get_meta(pos
)
52 local inv
= meta
:get_inventory()
53 inv
:set_size("main", 8*4)
55 -- Fill with sand in sand-flooded pyramids
57 table.insert(stacks
, {name
=sand
, count
= math
.random(1,32)})
60 if math
.random(1,10) >= 7 then
61 if minetest
.get_modpath("treasurer") ~= nil then
62 stacks
= treasurer
.select_random_treasures(3,7,9,{"minetool", "food", "crafting_component"})
65 local stuff
= chest_stuff
[math
.random(1,#chest_stuff
)]
66 table.insert(stacks
, {name
=stuff
.name
, count
= math
.random(1,stuff
.max)})
71 if not inv
:contains_item("main", stacks
[s
]) then
72 inv
:set_stack("main", math
.random(1,32), stacks
[s
])
78 local function add_spawner(pos
, mummy_offset
)
79 minetest
.set_node(pos
, {name
="tsm_pyramids:spawner_mummy"})
80 if not minetest
.settings
:get_bool("only_peaceful_mobs") then tsm_pyramids
.spawn_mummy(vector
.add(pos
, mummy_offset
),2) end
83 local function can_replace(pos
)
84 local n
= minetest
.get_node_or_nil(pos
)
85 if n
and n
.name
and minetest
.registered_nodes
[n
.name
] and not minetest
.registered_nodes
[n
.name
].walkable
then
94 local function make_foundation_part(pos
, set_to_stone
)
98 while can_replace(p2
)==true do
103 table.insert(set_to_stone
, table.copy(p2
))
108 local function make_entrance(pos
, rot
, brick
, sand
, flood_sand
)
109 local roffset_arr
= {
110 { x
=0, y
=0, z
=1 }, -- front
111 { x
=-1, y
=0, z
=0 }, -- left
112 { x
=0, y
=0, z
=-1 }, -- back
113 { x
=1, y
=0, z
=0 }, -- right
115 local roffset
= roffset_arr
[rot
+ 1]
118 way
= vector
.add(pos
, {x
=PYRA_Wh
, y
=0, z
=0})
120 way
= vector
.add(pos
, {x
=PYRA_Wm
, y
=0, z
=PYRA_Wh
})
122 way
= vector
.add(pos
, {x
=PYRA_Wh
, y
=0, z
=PYRA_Wm
})
124 way
= vector
.add(pos
, {x
=0, y
=0, z
=PYRA_Wh
})
126 local max_sand_height
= math
.random(1,3)
128 local sand_height
= math
.random(1,max_sand_height
)
131 local way_dir
= vector
.add(vector
.add(way
, {x
=0,y
=iy
,z
=0}), vector
.multiply(roffset
, ie
))
132 if flood_sand
and sand
~= "ignore" and iy
<= sand_height
and ie
>= 3 then
133 minetest
.set_node(way_dir
, {name
=sand
})
135 minetest
.remove_node(way_dir
)
137 -- build decoration above entrance
138 if ie
>=3 and iy
== 3 then
139 local deco
= {x
=way_dir
.x
, y
=way_dir
.y
+1,z
=way_dir
.z
}
140 minetest
.set_node(deco
, {name
=brick
})
141 if rot
== 0 or rot
== 2 then
142 minetest
.set_node(vector
.add(deco
, {x
=-1, y
=0, z
=0}), {name
=brick
})
143 minetest
.set_node(vector
.add(deco
, {x
=1, y
=0, z
=0}), {name
=brick
})
145 minetest
.set_node(vector
.add(deco
, {x
=0, y
=0, z
=-1}), {name
=brick
})
146 minetest
.set_node(vector
.add(deco
, {x
=0, y
=0, z
=1}), {name
=brick
})
153 local function make_pyramid(pos
, brick
, sandstone
, stone
, sand
)
154 local set_to_brick
= {}
155 local set_to_sand
= {}
156 local set_to_stone
= {}
158 for iy
=0,math
.random(10,PYRA_Wh
),1 do
159 for ix
=iy
,PYRA_W
-1-iy
,1 do
160 for iz
=iy
,PYRA_W
-1-iy
,1 do
162 make_foundation_part({x
=pos
.x
+ix
,y
=pos
.y
,z
=pos
.z
+iz
}, set_to_stone
)
164 table.insert(set_to_brick
, {x
=pos
.x
+ix
,y
=pos
.y
+iy
,z
=pos
.z
+iz
})
165 if sand
~= "ignore" then
167 local n
= minetest
.get_node({x
=pos
.x
+ix
,y
=pos
.y
+iy
+yy
,z
=pos
.z
+iz
})
168 if n
and n
.name
and n
.name
== stone
then
169 table.insert(set_to_sand
, {x
=pos
.x
+ix
,y
=pos
.y
+iy
+yy
,z
=pos
.z
+iz
})
176 minetest
.bulk_set_node(set_to_stone
, {name
=stone
})
177 minetest
.bulk_set_node(set_to_brick
, {name
=brick
})
178 if sand
~= "ignore" then
179 minetest
.bulk_set_node(set_to_sand
, {name
=sand
})
183 local function make(pos
, brick
, sandstone
, stone
, sand
, ptype
, room_id
)
185 make_pyramid(pos
, brick
, sandstone
, stone
, sand
)
187 local rot
= math
.random(0, 3)
189 local ok
, msg
, flood_sand
= tsm_pyramids
.make_room(pos
, ptype
, room_id
, rot
)
190 -- Place mummy spawner
191 local r
= math
.random(1,3)
192 -- 4 possible spawner positions
193 local spawner_posses
= {
195 {{x
=pos
.x
+PYRA_Wh
,y
=pos
.y
+2, z
=pos
.z
+5}, {x
=0, y
=0, z
=2}},
197 {{x
=pos
.x
+PYRA_Wm
-5,y
=pos
.y
+2, z
=pos
.z
+PYRA_Wh
}, {x
=-2, y
=0, z
=0}},
199 {{x
=pos
.x
+PYRA_Wh
,y
=pos
.y
+2, z
=pos
.z
+PYRA_W
-5}, {x
=0, y
=0, z
=-2}},
201 {{x
=pos
.x
+5,y
=pos
.y
+2, z
=pos
.z
+PYRA_Wh
}, {x
=2, y
=0, z
=0}},
203 -- Delete the spawner position in which the entrance will be placed
204 table.remove(spawner_posses
, (rot
% 4) + 1)
205 add_spawner(spawner_posses
[r
][1], spawner_posses
[r
][2])
207 make_entrance(pos
, rot
, brick
, sand
, flood_sand
)
209 minetest
.log("action", "Created pyramid at ("..pos
.x
..","..pos
.y
..","..pos
.z
..")")
213 local perl1
= {SEED1
= 9130, OCTA1
= 3, PERS1
= 0.5, SCAL1
= 250} -- Values should match minetest mapgen V6 desert noise.
216 local function hlp_fnct(pos
, name
)
217 local n
= minetest
.get_node_or_nil(pos
)
218 if n
and n
.name
and n
.name
== name
then
224 local function ground(pos
, old
)
226 while hlp_fnct(p2
, "air") do
237 minetest
.register_on_generated(function(minp
, maxp
, seed
)
238 if maxp
.y
< PYRA_MIN_Y
then return end
239 math
.randomseed(seed
)
241 perlin1
= minetest
.get_perlin(perl1
.SEED1
, perl1
.OCTA1
, perl1
.PERS1
, perl1
.SCAL1
)
243 --[[ Make sure the pyramid doesn't bleed outside of maxp,
244 so it doesn't get placed incompletely by the mapgen.
245 This creates a bias somewhat, as this means there are some coordinates in
246 which pyramids cannot spawn. But it's still better to have broken pyramids.
248 local limit
= function(pos
, maxp
)
249 pos
.x
= math
.min(pos
.x
, maxp
.x
- PYRA_W
+1)
250 pos
.y
= math
.min(pos
.y
, maxp
.y
- PYRA_Wh
)
251 pos
.z
= math
.min(pos
.z
, maxp
.z
- PYRA_W
+1)
254 local noise1
= perlin1
:get_2d({x
=minp
.x
,y
=minp
.y
})--,z=minp.z})
256 if noise1
> 0.25 or noise1
< -0.26 then
257 local mpos
= {x
=math
.random(minp
.x
,maxp
.x
), y
=math
.random(minp
.y
,maxp
.y
), z
=math
.random(minp
.z
,maxp
.z
)}
259 local sands
= {"default:sand", "default:desert_sand", "default:desert_stone"}
264 local sand_cnt_max
= 0
265 local sand_cnt_max_id
270 psand
[s
] = minetest
.find_node_near(mpos
, 25, sand
)
273 mpos
= {x
=math
.random(minp
.x
,maxp
.x
), y
=math
.random(minp
.y
,maxp
.y
), z
=math
.random(minp
.z
,maxp
.z
)}
274 local spos
= minetest
.find_node_near(mpos
, 25, sand
)
276 sand_cnt
= sand_cnt
+ 1
277 if psand
[s
] == nil then
281 if sand_cnt
> sand_cnt_max
then
282 sand_cnt_max
= sand_cnt
288 if sand_cnt_max_id
then
289 sand
= sands
[sand_cnt_max_id
]
291 if p2
== nil then return end
292 if p2
.y
< PYRA_MIN_Y
then return end
295 local opos1
= {x
=p2
.x
+PYRA_Wm
,y
=p2
.y
-1,z
=p2
.z
+PYRA_Wm
}
296 local opos2
= {x
=p2
.x
+PYRA_Wm
,y
=p2
.y
-1,z
=p2
.z
}
297 local opos3
= {x
=p2
.x
,y
=p2
.y
-1,z
=p2
.z
+PYRA_Wm
}
298 local opos1_n
= minetest
.get_node_or_nil(opos1
)
299 local opos2_n
= minetest
.get_node_or_nil(opos2
)
300 local opos3_n
= minetest
.get_node_or_nil(opos3
)
301 if opos1_n
and opos1_n
.name
and opos1_n
.name
== "air" then
302 p2
= ground(opos1
, p2
)
304 if opos2_n
and opos2_n
.name
and opos2_n
.name
== "air" then
305 p2
= ground(opos2
, p2
)
307 if opos3_n
and opos3_n
.name
and opos3_n
.name
== "air" then
308 p2
= ground(opos3
, p2
)
312 if p2
.y
< PYRA_MIN_Y
then p2
.y
= PYRA_MIN_Y
end
313 if minetest
.find_node_near(p2
, 5, {"default:water_source"}) ~= nil or
314 minetest
.find_node_near(vector
.add(p2
, {x
=PYRA_W
, y
=0, z
=0}), 5, {"default:water_source"}) ~= nil or
315 minetest
.find_node_near(vector
.add(p2
, {x
=0, y
=0, z
=PYRA_W
}), 5, {"default:water_source"}) ~= nil or
316 minetest
.find_node_near(vector
.add(p2
, {x
=PYRA_W
, y
=0, z
=PYRA_W
}), 5, {"default:water_source"}) ~= nil or
318 minetest
.find_node_near(p2
, 22, {"default:dirt_with_grass"}) ~= nil or
319 minetest
.find_node_near(p2
, 52, {"default:sandstonebrick"}) ~= nil or
320 minetest
.find_node_near(p2
, 52, {"default:desert_sandstone_brick"}) ~= nil then
324 if math
.random(0,10) > 7 then
327 if (mg_name
== "v6" and sand
== "default:desert_sand" and math
.random(1, 2) == 1) then
328 sand
= "default:sand"
330 -- Desert stone pyramids only generate in areas with almost no sand
331 if sand
== "default:desert_stone" then
332 local nodes
= minetest
.find_nodes_in_area(vector
.add(p2
, {x
=-1, y
=-2, z
=-1}), vector
.add(p2
, {x
=PYRA_W
+1, y
=PYRA_Wh
, z
=PYRA_W
+1}), {"group:sand"})
334 sand
= "default:desert_sand"
337 if sand
== "default:desert_sand" then
338 -- Desert sandstone pyramid
339 make(p2
, "default:desert_sandstone_brick", "default:desert_sandstone", "default:desert_stone", "default:desert_sand", "desert_sandstone")
340 elseif sand
== "default:sand" then
342 make(p2
, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone")
344 -- Desert stone pyramid
345 make(p2
, "default:desert_stonebrick", "default:desert_stone_block", "default:desert_stone", "ignore", "desert_stone")
350 -- Add backwards-compability for nodes from the original pyramids mod
351 if minetest
.get_modpath("pyramids") == nil then
353 minetest
.register_alias("pyramids:trap", "tsm_pyramids:trap")
354 minetest
.register_alias("pyramids:trap_2", "tsm_pyramids:trap_2")
355 minetest
.register_alias("pyramids:deco_stone1", "tsm_pyramids:deco_stone1")
356 minetest
.register_alias("pyramids:deco_stone2", "tsm_pyramids:deco_stone2")
357 minetest
.register_alias("pyramids:deco_stone3", "tsm_pyramids:deco_stone3")
358 minetest
.register_alias("pyramids:spawner_mummy", "tsm_pyramids:spawner_mummy")
361 minetest
.register_chatcommand("spawnpyramid", {
362 description
= S("Generate a pyramid"),
363 params
= S("[<room_type>]"),
364 privs
= { server
= true },
365 func
= function(name
, param
)
366 local player
= minetest
.get_player_by_name(name
)
368 return false, S("No player.")
370 local pos
= player
:get_pos()
371 pos
= vector
.round(pos
)
372 local s
= math
.random(1,3)
373 local r
= tonumber(param
)
379 pos
= vector
.add(pos
, {x
=-PYRA_Wh
, y
=-1, z
=0})
382 ok
, msg
= make(pos
, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone", room_id
)
385 ok
, msg
= make(pos
, "default:desert_sandstone_brick", "default:desert_sandstone", "default:desert_stone", "default:desert_sand", "desert_sandstone", room_id
)
388 ok
, msg
= make(pos
, "default:desert_stonebrick", "default:desert_stone_block", "default:desert_stone", "ignore", "desert_stone", room_id
)
391 return true, S("Pyramid generated at @1.", minetest
.pos_to_string(pos
))