2021-05-25 12:52:25 +02:00
local modname = minetest.get_current_modname ( )
local S = minetest.get_translator ( modname )
local modpath = minetest.get_modpath ( modname )
mcl_structures = { }
2021-02-22 00:15:32 +01:00
local rotations = {
" 0 " ,
" 90 " ,
" 180 " ,
" 270 "
}
local function ecb_place ( blockpos , action , calls_remaining , param )
if calls_remaining >= 1 then return end
2021-02-24 22:03:41 +01:00
minetest.place_schematic ( param.pos , param.schematic , param.rotation , param.replacements , param.force_placement , param.flags )
2021-02-22 00:15:32 +01:00
if param.after_placement_callback and param.p1 and param.p2 then
2021-04-07 01:34:15 +02:00
param.after_placement_callback ( param.p1 , param.p2 , param.size , param.rotation , param.pr , param.callback_param )
2021-02-22 00:15:32 +01:00
end
end
2021-05-25 12:52:25 +02:00
function mcl_structures . place_schematic ( pos , schematic , rotation , replacements , force_placement , flags , after_placement_callback , pr , callback_param )
2021-05-25 10:56:06 +02:00
local s = loadstring ( minetest.serialize_schematic ( schematic , " lua " , { lua_use_comments = false , lua_num_indent_spaces = 0 } ) .. " return schematic " ) ( )
2021-02-22 00:15:32 +01:00
if s and s.size then
local x , z = s.size . x , s.size . z
if rotation then
if rotation == " random " and pr then
rotation = rotations [ pr : next ( 1 , # rotations ) ]
end
if rotation == " random " then
x = math.max ( x , z )
z = x
elseif rotation == " 90 " or rotation == " 270 " then
x , z = z , x
end
end
local p1 = { x = pos.x , y = pos.y , z = pos.z }
local p2 = { x = pos.x + x - 1 , y = pos.y + s.size . y - 1 , z = pos.z + z - 1 }
2021-05-29 16:12:33 +02:00
minetest.log ( " verbose " , " [mcl_structures] size= " .. minetest.pos_to_string ( s.size ) .. " , rotation= " .. tostring ( rotation ) .. " , emerge from " .. minetest.pos_to_string ( p1 ) .. " to " .. minetest.pos_to_string ( p2 ) )
2021-04-07 01:34:15 +02:00
local param = { pos = vector.new ( pos ) , schematic = s , rotation = rotation , replacements = replacements , force_placement = force_placement , flags = flags , p1 = p1 , p2 = p2 , after_placement_callback = after_placement_callback , size = vector.new ( s.size ) , pr = pr , callback_param = callback_param }
2021-02-22 00:15:32 +01:00
minetest.emerge_area ( p1 , p2 , ecb_place , param )
end
end
2015-07-03 06:58:45 +02:00
2021-05-25 12:52:25 +02:00
function mcl_structures . get_struct ( file )
2021-05-29 16:12:33 +02:00
local localfile = modpath .. " /schematics/ " .. file
2015-07-03 06:58:45 +02:00
local file , errorload = io.open ( localfile , " rb " )
2021-05-29 16:12:33 +02:00
if errorload then
minetest.log ( " error " , " [mcl_structures] Could not open this struct: " .. localfile )
2021-02-22 00:15:32 +01:00
return nil
2015-07-03 06:58:45 +02:00
end
2021-02-22 00:15:32 +01:00
local allnode = file : read ( " *a " )
file : close ( )
2015-07-03 06:58:45 +02:00
2021-02-22 00:15:32 +01:00
return allnode
2015-07-03 06:58:45 +02:00
end
2019-02-28 18:19:57 +01:00
-- Call on_construct on pos.
-- Useful to init chests from formspec.
2021-05-25 12:52:25 +02:00
local function init_node_construct ( pos )
2019-02-28 18:19:57 +01:00
local node = minetest.get_node ( pos )
local def = minetest.registered_nodes [ node.name ]
if def and def.on_construct then
def.on_construct ( pos )
return true
end
return false
end
2015-07-04 04:56:02 +02:00
-- The call of Struct
2021-05-25 12:52:25 +02:00
function mcl_structures . call_struct ( pos , struct_style , rotation , pr )
2021-02-22 00:15:32 +01:00
minetest.log ( " action " , " [mcl_structures] call_struct " .. struct_style .. " at " .. minetest.pos_to_string ( pos ) )
2017-09-10 20:16:13 +02:00
if not rotation then
rotation = " random "
end
2020-06-03 19:57:04 +02:00
if struct_style == " desert_temple " then
2021-02-22 00:15:32 +01:00
return mcl_structures.generate_desert_temple ( pos , rotation , pr )
2017-05-20 06:47:42 +02:00
elseif struct_style == " desert_well " then
2017-09-10 20:18:16 +02:00
return mcl_structures.generate_desert_well ( pos , rotation )
2017-05-20 07:46:57 +02:00
elseif struct_style == " igloo " then
2021-02-22 00:15:32 +01:00
return mcl_structures.generate_igloo ( pos , rotation , pr )
2017-08-11 00:28:29 +02:00
elseif struct_style == " witch_hut " then
2017-09-10 20:18:16 +02:00
return mcl_structures.generate_witch_hut ( pos , rotation )
2017-08-11 00:28:29 +02:00
elseif struct_style == " ice_spike_small " then
2017-09-10 20:18:16 +02:00
return mcl_structures.generate_ice_spike_small ( pos , rotation )
2017-08-11 01:48:36 +02:00
elseif struct_style == " ice_spike_large " then
2017-09-10 20:18:16 +02:00
return mcl_structures.generate_ice_spike_large ( pos , rotation )
2017-08-11 00:28:29 +02:00
elseif struct_style == " boulder " then
2021-02-22 00:15:32 +01:00
return mcl_structures.generate_boulder ( pos , rotation , pr )
2017-08-11 00:28:29 +02:00
elseif struct_style == " fossil " then
2021-02-22 00:15:32 +01:00
return mcl_structures.generate_fossil ( pos , rotation , pr )
2017-11-21 07:24:56 +01:00
elseif struct_style == " end_exit_portal " then
return mcl_structures.generate_end_exit_portal ( pos , rotation )
2021-04-06 15:48:17 +02:00
elseif struct_style == " end_exit_portal_open " then
return mcl_structures.generate_end_exit_portal_open ( pos , rotation )
2021-04-06 20:08:20 +02:00
elseif struct_style == " end_gateway_portal " then
return mcl_structures.generate_end_gateway_portal ( pos , rotation )
2017-12-10 22:22:37 +01:00
elseif struct_style == " end_portal_shrine " then
2021-02-22 00:15:32 +01:00
return mcl_structures.generate_end_portal_shrine ( pos , rotation , pr )
2017-05-20 06:47:42 +02:00
end
2015-07-04 04:56:02 +02:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_desert_well ( pos , rot )
2017-05-20 05:57:38 +02:00
local newpos = { x = pos.x , y = pos.y - 2 , z = pos.z }
2021-05-25 12:52:25 +02:00
local path = modpath .. " /schematics/mcl_structures_desert_well.mts "
2021-03-07 00:49:34 +01:00
return mcl_structures.place_schematic ( newpos , path , rot or " 0 " , nil , true )
2017-05-20 05:57:38 +02:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_igloo ( pos , rotation , pr )
2019-10-02 22:29:25 +02:00
-- Place igloo
2021-02-22 00:15:32 +01:00
local success , rotation = mcl_structures.generate_igloo_top ( pos , pr )
2019-10-02 22:31:19 +02:00
-- Place igloo basement with 50% chance
2021-02-22 00:15:32 +01:00
local r = pr : next ( 1 , 2 )
if r == 1 then
2019-10-02 22:29:25 +02:00
-- Select basement depth
2019-10-02 22:06:26 +02:00
local dim = mcl_worlds.pos_to_dimension ( pos )
2021-04-17 07:46:24 +02:00
--local buffer = pos.y - (mcl_vars.mg_lava_overworld_max + 10)
local buffer
2019-10-02 22:06:26 +02:00
if dim == " nether " then
buffer = pos.y - ( mcl_vars.mg_lava_nether_max + 10 )
elseif dim == " end " then
buffer = pos.y - ( mcl_vars.mg_end_min + 1 )
elseif dim == " overworld " then
buffer = pos.y - ( mcl_vars.mg_lava_overworld_max + 10 )
else
return success
end
2019-02-06 02:02:18 +01:00
if buffer <= 19 then
2019-10-02 22:06:26 +02:00
return success
2019-02-06 02:02:18 +01:00
end
2021-02-22 00:15:32 +01:00
local depth = pr : next ( 19 , buffer )
2019-02-06 02:02:18 +01:00
local bpos = { x = pos.x , y = pos.y - depth , z = pos.z }
-- trapdoor position
local tpos
local dir , tdir
if rotation == " 0 " then
dir = { x =- 1 , y = 0 , z = 0 }
tdir = { x = 1 , y = 0 , z = 0 }
tpos = { x = pos.x + 7 , y = pos.y - 1 , z = pos.z + 3 }
elseif rotation == " 90 " then
dir = { x = 0 , y = 0 , z =- 1 }
tdir = { x = 0 , y = 0 , z =- 1 }
tpos = { x = pos.x + 3 , y = pos.y - 1 , z = pos.z + 1 }
elseif rotation == " 180 " then
dir = { x = 1 , y = 0 , z = 0 }
tdir = { x =- 1 , y = 0 , z = 0 }
tpos = { x = pos.x + 1 , y = pos.y - 1 , z = pos.z + 3 }
elseif rotation == " 270 " then
dir = { x = 0 , y = 0 , z = 1 }
tdir = { x = 0 , y = 0 , z = 1 }
tpos = { x = pos.x + 3 , y = pos.y - 1 , z = pos.z + 7 }
else
return success
end
2021-05-25 12:52:25 +02:00
local function set_brick ( pos )
2021-02-22 00:15:32 +01:00
local c = pr : next ( 1 , 3 ) -- cracked chance
local m = pr : next ( 1 , 10 ) -- chance for monster egg
2019-02-06 02:02:18 +01:00
local brick
if m == 1 then
if c == 1 then
brick = " mcl_monster_eggs:monster_egg_stonebrickcracked "
else
brick = " mcl_monster_eggs:monster_egg_stonebrick "
end
else
if c == 1 then
brick = " mcl_core:stonebrickcracked "
else
brick = " mcl_core:stonebrick "
end
end
minetest.set_node ( pos , { name = brick } )
end
local ladder_param2 = minetest.dir_to_wallmounted ( tdir )
2019-10-02 22:06:26 +02:00
local real_depth = 0
2019-10-02 22:29:25 +02:00
-- Check how deep we can actuall dig
2019-02-06 02:02:18 +01:00
for y = 1 , depth - 5 do
2019-10-02 22:06:26 +02:00
real_depth = real_depth + 1
local node = minetest.get_node ( { x = tpos.x , y = tpos.y - y , z = tpos.z } )
local def = minetest.registered_nodes [ node.name ]
2022-03-09 15:14:22 +01:00
if not ( def and def.walkable and def.liquidtype == " none " and def.is_ground_content ) then
2019-10-02 22:29:25 +02:00
bpos.y = tpos.y - y + 1
2019-10-02 22:06:26 +02:00
break
end
2019-10-02 22:29:25 +02:00
end
if real_depth <= 6 then
return success
end
-- Generate ladder to basement
2019-10-02 22:31:19 +02:00
for y = 1 , real_depth - 1 do
2019-02-06 02:02:18 +01:00
set_brick ( { x = tpos.x - 1 , y = tpos.y - y , z = tpos.z } )
set_brick ( { x = tpos.x + 1 , y = tpos.y - y , z = tpos.z } )
set_brick ( { x = tpos.x , y = tpos.y - y , z = tpos.z - 1 } )
set_brick ( { x = tpos.x , y = tpos.y - y , z = tpos.z + 1 } )
minetest.set_node ( { x = tpos.x , y = tpos.y - y , z = tpos.z } , { name = " mcl_core:ladder " , param2 = ladder_param2 } )
end
2019-10-02 22:29:25 +02:00
-- Place basement
2021-02-22 00:15:32 +01:00
mcl_structures.generate_igloo_basement ( bpos , rotation , pr )
2021-06-22 14:53:55 +02:00
-- Place hidden trapdoor
minetest.after ( 5 , function ( tpos , dir )
minetest.set_node ( tpos , { name = " mcl_doors:trapdoor " , param2 = 20 + minetest.dir_to_facedir ( dir ) } ) -- TODO: more reliable param2
end , tpos , dir )
2019-02-06 02:02:18 +01:00
end
return success
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_igloo_top ( pos , pr )
2017-05-20 07:46:57 +02:00
-- FIXME: This spawns bookshelf instead of furnace. Fix this!
-- Furnace does ot work atm because apparently meta is not set. :-(
2017-05-20 07:59:10 +02:00
local newpos = { x = pos.x , y = pos.y - 1 , z = pos.z }
2021-05-25 12:52:25 +02:00
local path = modpath .. " /schematics/mcl_structures_igloo_top.mts "
2021-02-22 00:15:32 +01:00
local rotation = tostring ( pr : next ( 0 , 3 ) * 90 )
2021-02-24 22:03:41 +01:00
return mcl_structures.place_schematic ( newpos , path , rotation , nil , true ) , rotation
2017-05-20 07:46:57 +02:00
end
2021-02-22 00:15:32 +01:00
local function igloo_placement_callback ( p1 , p2 , size , orientation , pr )
local chest_offset
if orientation == " 0 " then
chest_offset = { x = 5 , y = 1 , z = 5 }
elseif orientation == " 90 " then
chest_offset = { x = 5 , y = 1 , z = 3 }
elseif orientation == " 180 " then
chest_offset = { x = 3 , y = 1 , z = 1 }
elseif orientation == " 270 " then
chest_offset = { x = 1 , y = 1 , z = 5 }
else
return
end
2021-04-17 07:46:24 +02:00
--local size = {x=9,y=5,z=7}
2021-02-22 00:15:32 +01:00
local lootitems = mcl_loot.get_multi_loot ( {
{
stacks_min = 1 ,
stacks_max = 1 ,
items = {
{ itemstring = " mcl_core:apple_gold " , weight = 1 } ,
}
} ,
{
stacks_min = 2 ,
stacks_max = 8 ,
items = {
{ itemstring = " mcl_core:coal_lump " , weight = 15 , amount_min = 1 , amount_max = 4 } ,
{ itemstring = " mcl_core:apple " , weight = 15 , amount_min = 1 , amount_max = 3 } ,
{ itemstring = " mcl_farming:wheat_item " , weight = 10 , amount_min = 2 , amount_max = 3 } ,
{ itemstring = " mcl_core:gold_nugget " , weight = 10 , amount_min = 1 , amount_max = 3 } ,
{ itemstring = " mcl_mobitems:rotten_flesh " , weight = 10 } ,
{ itemstring = " mcl_tools:axe_stone " , weight = 2 } ,
{ itemstring = " mcl_core:emerald " , weight = 1 } ,
}
} } , pr )
local chest_pos = vector.add ( p1 , chest_offset )
init_node_construct ( chest_pos )
local meta = minetest.get_meta ( chest_pos )
local inv = meta : get_inventory ( )
2021-02-22 18:58:35 +01:00
mcl_loot.fill_inventory ( inv , " main " , lootitems , pr )
2021-02-22 00:15:32 +01:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_igloo_basement ( pos , orientation , pr )
2017-05-24 05:43:01 +02:00
-- TODO: Add brewing stand
2019-02-06 02:23:51 +01:00
-- TODO: Add monster eggs
2019-02-06 02:02:18 +01:00
-- TODO: Spawn villager and zombie villager
2021-05-25 12:52:25 +02:00
local path = modpath .. " /schematics/mcl_structures_igloo_basement.mts "
2021-02-22 00:15:32 +01:00
mcl_structures.place_schematic ( pos , path , orientation , nil , true , nil , igloo_placement_callback , pr )
2017-05-24 05:43:01 +02:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_boulder ( pos , rotation , pr )
2017-08-12 02:24:34 +02:00
-- Choose between 2 boulder sizes (2× 2× 2 or 3× 3× 3)
2021-02-22 00:15:32 +01:00
local r = pr : next ( 1 , 10 )
2017-09-03 06:38:50 +02:00
local path
2017-08-12 02:24:34 +02:00
if r <= 3 then
2021-05-25 12:52:25 +02:00
path = modpath .. " /schematics/mcl_structures_boulder_small.mts "
2017-08-12 02:24:34 +02:00
else
2021-05-25 12:52:25 +02:00
path = modpath .. " /schematics/mcl_structures_boulder.mts "
2017-08-12 02:24:34 +02:00
end
2017-09-10 05:03:20 +02:00
local newpos = { x = pos.x , y = pos.y - 1 , z = pos.z }
2021-02-28 13:35:21 +01:00
2021-03-07 00:49:34 +01:00
return minetest.place_schematic ( newpos , path , rotation ) -- don't serialize schematics for registered biome decorations, for MT 5.4.0, https://github.com/minetest/minetest/issues/10995
2017-08-11 00:28:29 +02:00
end
2022-05-26 02:24:56 +02:00
local function spawn_witch ( p1 , p2 )
local c = minetest.find_node_near ( p1 , 15 , { " mcl_cauldrons:cauldron " } )
if c then
2022-05-26 14:46:06 +02:00
local nn = minetest.find_nodes_in_area_under_air ( vector.new ( p1.x , c.y - 1 , p1.z ) , vector.new ( p2.x , c.y - 1 , p2.z ) , { " mcl_core:sprucewood " } )
local witch = minetest.add_entity ( vector.offset ( nn [ math.random ( # nn ) ] , 0 , 1 , 0 ) , " mobs_mc:witch " ) : get_luaentity ( )
local cat = minetest.add_entity ( vector.offset ( nn [ math.random ( # nn ) ] , 0 , 1 , 0 ) , " mobs_mc:cat " ) : get_luaentity ( )
witch._home = c
witch.can_despawn = false
cat.object : set_properties ( { textures = { " mobs_mc_cat_black.png " } } )
cat.owner = " !witch! " --so it's not claimable by player
2022-05-26 15:16:06 +02:00
cat._home = c
2022-05-26 14:46:06 +02:00
cat.can_despawn = false
return
2022-05-26 02:24:56 +02:00
end
end
2021-02-22 00:15:32 +01:00
local function hut_placement_callback ( p1 , p2 , size , orientation , pr )
if not p1 or not p2 then return end
local legs = minetest.find_nodes_in_area ( p1 , p2 , " mcl_core:tree " )
for i = 1 , # legs do
2021-03-28 20:56:51 +02:00
while minetest.get_item_group ( mcl_vars.get_node ( { x = legs [ i ] . x , y = legs [ i ] . y - 1 , z = legs [ i ] . z } , true , 333333 ) . name , " water " ) ~= 0 do
2021-02-22 00:15:32 +01:00
legs [ i ] . y = legs [ i ] . y - 1
minetest.swap_node ( legs [ i ] , { name = " mcl_core:tree " , param2 = 2 } )
end
end
2022-05-26 02:24:56 +02:00
spawn_witch ( p1 , p2 )
2021-02-22 00:15:32 +01:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_witch_hut ( pos , rotation , pr )
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/mcl_structures_witch_hut.mts "
2021-02-22 00:15:32 +01:00
mcl_structures.place_schematic ( pos , path , rotation , nil , true , nil , hut_placement_callback , pr )
2017-08-11 00:28:29 +02:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_ice_spike_small ( pos , rotation )
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/mcl_structures_ice_spike_small.mts "
2021-03-07 00:49:34 +01:00
return minetest.place_schematic ( pos , path , rotation or " random " , nil , false ) -- don't serialize schematics for registered biome decorations, for MT 5.4.0
2017-08-11 00:28:29 +02:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_ice_spike_large ( pos , rotation )
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/mcl_structures_ice_spike_large.mts "
2021-03-07 00:49:34 +01:00
return minetest.place_schematic ( pos , path , rotation or " random " , nil , false ) -- don't serialize schematics for registered biome decorations, for MT 5.4.0
2017-08-11 01:48:36 +02:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_fossil ( pos , rotation , pr )
2017-08-11 00:28:29 +02:00
-- Generates one out of 8 possible fossil pieces
local newpos = { x = pos.x , y = pos.y - 1 , z = pos.z }
local fossils = {
2017-09-08 01:39:14 +02:00
" mcl_structures_fossil_skull_1.mts " , -- 4× 5× 5
" mcl_structures_fossil_skull_2.mts " , -- 5× 5× 5
" mcl_structures_fossil_skull_3.mts " , -- 5× 5× 7
" mcl_structures_fossil_skull_4.mts " , -- 7× 5× 5
" mcl_structures_fossil_spine_1.mts " , -- 3× 3× 13
" mcl_structures_fossil_spine_2.mts " , -- 5× 4× 13
" mcl_structures_fossil_spine_3.mts " , -- 7× 4× 13
" mcl_structures_fossil_spine_4.mts " , -- 8× 5× 13
2017-08-11 00:28:29 +02:00
}
2021-02-22 00:15:32 +01:00
local r = pr : next ( 1 , # fossils )
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/ " .. fossils [ r ]
2021-03-07 00:49:34 +01:00
return mcl_structures.place_schematic ( newpos , path , rotation or " random " , nil , true )
2017-08-11 00:28:29 +02:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_end_exit_portal ( pos , rot )
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/mcl_structures_end_exit_portal.mts "
2021-04-07 09:17:13 +02:00
return mcl_structures.place_schematic ( pos , path , rot or " 0 " , { [ " mcl_portals:portal_end " ] = " air " } , true )
2017-11-21 07:24:56 +01:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_end_exit_portal_open ( pos , rot )
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/mcl_structures_end_exit_portal.mts "
2021-04-06 15:48:17 +02:00
return mcl_structures.place_schematic ( pos , path , rot or " 0 " , nil , true )
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_end_gateway_portal ( pos , rot )
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/mcl_structures_end_gateway_portal.mts "
2021-04-06 20:08:20 +02:00
return mcl_structures.place_schematic ( pos , path , rot or " 0 " , nil , true )
end
2021-02-22 00:15:32 +01:00
local function shrine_placement_callback ( p1 , p2 , size , rotation , pr )
2017-12-09 02:05:41 +01:00
-- Find and setup spawner with silverfish
2021-02-22 00:15:32 +01:00
local spawners = minetest.find_nodes_in_area ( p1 , p2 , " mcl_mobspawners:spawner " )
2017-12-09 02:05:41 +01:00
for s = 1 , # spawners do
2021-04-17 07:46:24 +02:00
--local meta = minetest.get_meta(spawners[s])
2017-12-09 02:05:41 +01:00
mcl_mobspawners.setup_spawner ( spawners [ s ] , " mobs_mc:silverfish " )
end
-- Shuffle stone brick types
2021-02-22 00:15:32 +01:00
local bricks = minetest.find_nodes_in_area ( p1 , p2 , " mcl_core:stonebrick " )
2017-12-09 02:05:41 +01:00
for b = 1 , # bricks do
local r_bricktype = pr : next ( 1 , 100 )
local r_infested = pr : next ( 1 , 100 )
local bricktype
2017-12-09 14:08:36 +01:00
if r_infested <= 5 then
if r_bricktype <= 30 then -- 30%
2017-12-09 02:05:41 +01:00
bricktype = " mcl_monster_eggs:monster_egg_stonebrickmossy "
2017-12-09 14:08:36 +01:00
elseif r_bricktype <= 50 then -- 20%
2017-12-09 02:05:41 +01:00
bricktype = " mcl_monster_eggs:monster_egg_stonebrickcracked "
2017-12-09 14:08:36 +01:00
else -- 50%
2017-12-09 02:05:41 +01:00
bricktype = " mcl_monster_eggs:monster_egg_stonebrick "
end
else
2017-12-09 14:08:36 +01:00
if r_bricktype <= 30 then -- 30%
2017-12-09 02:05:41 +01:00
bricktype = " mcl_core:stonebrickmossy "
2017-12-09 14:08:36 +01:00
elseif r_bricktype <= 50 then -- 20%
2017-12-09 02:05:41 +01:00
bricktype = " mcl_core:stonebrickcracked "
end
2017-12-09 14:08:36 +01:00
-- 50% stonebrick (no change necessary)
2017-12-09 02:05:41 +01:00
end
2021-05-29 16:12:33 +02:00
if bricktype then
2017-12-09 02:05:41 +01:00
minetest.set_node ( bricks [ b ] , { name = bricktype } )
end
end
2017-12-09 16:50:32 +01:00
-- Also replace stairs
2021-02-22 00:15:32 +01:00
local stairs = minetest.find_nodes_in_area ( p1 , p2 , { " mcl_stairs:stair_stonebrick " , " mcl_stairs:stair_stonebrick_outer " , " mcl_stairs:stair_stonebrick_inner " } )
2017-12-09 16:50:32 +01:00
for s = 1 , # stairs do
local stair = minetest.get_node ( stairs [ s ] )
local r_type = pr : next ( 1 , 100 )
if r_type <= 30 then -- 30% mossy
if stair.name == " mcl_stairs:stair_stonebrick " then
stair.name = " mcl_stairs:stair_stonebrickmossy "
elseif stair.name == " mcl_stairs:stair_stonebrick_outer " then
stair.name = " mcl_stairs:stair_stonebrickmossy_outer "
elseif stair.name == " mcl_stairs:stair_stonebrick_inner " then
stair.name = " mcl_stairs:stair_stonebrickmossy_inner "
end
minetest.set_node ( stairs [ s ] , stair )
elseif r_type <= 50 then -- 20% cracky
if stair.name == " mcl_stairs:stair_stonebrick " then
stair.name = " mcl_stairs:stair_stonebrickcracked "
elseif stair.name == " mcl_stairs:stair_stonebrick_outer " then
stair.name = " mcl_stairs:stair_stonebrickcracked_outer "
elseif stair.name == " mcl_stairs:stair_stonebrick_inner " then
stair.name = " mcl_stairs:stair_stonebrickcracked_inner "
end
minetest.set_node ( stairs [ s ] , stair )
end
-- 50% no change
end
2017-12-09 02:05:41 +01:00
-- Randomly add ender eyes into end portal frames, but never fill the entire frame
2021-02-22 00:15:32 +01:00
local frames = minetest.find_nodes_in_area ( p1 , p2 , " mcl_portals:end_portal_frame " )
2017-12-09 02:05:41 +01:00
local eyes = 0
for f = 1 , # frames do
local r_eye = pr : next ( 1 , 10 )
if r_eye == 1 then
eyes = eyes + 1
if eyes < # frames then
local frame_node = minetest.get_node ( frames [ f ] )
frame_node.name = " mcl_portals:end_portal_frame_eye "
minetest.set_node ( frames [ f ] , frame_node )
end
end
end
2020-10-14 15:23:39 +02:00
end
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_end_portal_shrine ( pos , rotation , pr )
2021-02-22 00:15:32 +01:00
local offset = { x = 6 , y = 4 , z = 6 }
2021-04-17 07:46:24 +02:00
--local size = {x=13, y=8, z=13}
2020-10-14 15:23:39 +02:00
local newpos = { x = pos.x - offset.x , y = pos.y , z = pos.z - offset.z }
2021-02-22 00:15:32 +01:00
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/mcl_structures_end_portal_room_simple.mts "
2021-03-07 00:49:34 +01:00
mcl_structures.place_schematic ( newpos , path , rotation or " 0 " , nil , true , nil , shrine_placement_callback , pr )
2020-10-14 15:23:39 +02:00
end
2021-02-22 00:15:32 +01:00
local function temple_placement_callback ( p1 , p2 , size , rotation , pr )
-- Delete cacti leftovers:
local cactus_nodes = minetest.find_nodes_in_area_under_air ( p1 , p2 , " mcl_core:cactus " )
if cactus_nodes and # cactus_nodes > 0 then
for _ , pos in pairs ( cactus_nodes ) do
local node_below = minetest.get_node ( { x = pos.x , y = pos.y - 1 , z = pos.z } )
if node_below and node_below.name == " mcl_core:sandstone " then
minetest.swap_node ( pos , { name = " air " } )
end
end
2017-09-10 20:18:16 +02:00
end
2017-09-08 04:30:47 +02:00
-- Find chests.
-- FIXME: Searching this large area just for the chets is not efficient. Need a better way to find the chests;
-- probably let's just infer it from newpos because the schematic always the same.
2021-02-22 00:15:32 +01:00
local chests = minetest.find_nodes_in_area ( p1 , p2 , " mcl_chests:chest " )
2017-05-19 19:26:59 +02:00
-- Add desert temple loot into chests
for c = 1 , # chests do
local lootitems = mcl_loot.get_multi_loot ( {
{
stacks_min = 2 ,
stacks_max = 4 ,
items = {
{ itemstring = " mcl_mobitems:bone " , weight = 25 , amount_min = 4 , amount_max = 6 } ,
{ itemstring = " mcl_mobitems:rotten_flesh " , weight = 25 , amount_min = 3 , amount_max = 7 } ,
{ itemstring = " mcl_mobitems:spider_eye " , weight = 25 , amount_min = 1 , amount_max = 3 } ,
2021-12-07 17:57:18 +01:00
{ itemstring = " mcl_books:book " , weight = 20 , func = function ( stack , pr )
2021-12-07 18:19:41 +01:00
mcl_enchanting.enchant_uniform_randomly ( stack , { " soul_speed " } , pr )
2021-12-07 17:57:18 +01:00
end } ,
2017-05-19 19:26:59 +02:00
{ itemstring = " mcl_mobitems:saddle " , weight = 20 , } ,
{ itemstring = " mcl_core:apple_gold " , weight = 20 , } ,
{ itemstring = " mcl_core:gold_ingot " , weight = 15 , amount_min = 2 , amount_max = 7 } ,
{ itemstring = " mcl_core:iron_ingot " , weight = 15 , amount_min = 1 , amount_max = 5 } ,
{ itemstring = " mcl_core:emerald " , weight = 15 , amount_min = 1 , amount_max = 3 } ,
{ itemstring = " " , weight = 15 , } ,
2022-05-25 23:25:15 +02:00
{ itemstring = " mcl_mobitems:iron_horse_armor " , weight = 15 , } ,
{ itemstring = " mcl_mobitems:gold_horse_armor " , weight = 10 , } ,
{ itemstring = " mcl_mobitems:diamond_horse_armor " , weight = 5 , } ,
2017-05-19 19:26:59 +02:00
{ itemstring = " mcl_core:diamond " , weight = 5 , amount_min = 1 , amount_max = 3 } ,
2021-01-22 19:45:18 +01:00
{ itemstring = " mcl_core:apple_gold_enchanted " , weight = 2 , } ,
2017-05-19 19:26:59 +02:00
}
} ,
{
stacks_min = 4 ,
stacks_max = 4 ,
items = {
{ itemstring = " mcl_mobitems:bone " , weight = 10 , amount_min = 1 , amount_max = 8 } ,
{ itemstring = " mcl_mobitems:rotten_flesh " , weight = 10 , amount_min = 1 , amount_max = 8 } ,
{ itemstring = " mcl_mobitems:gunpowder " , weight = 10 , amount_min = 1 , amount_max = 8 } ,
{ itemstring = " mcl_core:sand " , weight = 10 , amount_min = 1 , amount_max = 8 } ,
{ itemstring = " mcl_mobitems:string " , weight = 10 , amount_min = 1 , amount_max = 8 } ,
}
} } , pr )
2019-02-28 18:19:57 +01:00
i nit_node_construct ( chests [ c ] )
2017-05-19 19:26:59 +02:00
local meta = minetest.get_meta ( chests [ c ] )
local inv = meta : get_inventory ( )
2021-02-22 18:58:35 +01:00
mcl_loot.fill_inventory ( inv , " main " , lootitems , pr )
2017-05-19 19:26:59 +02:00
end
2017-09-10 20:18:16 +02:00
2018-01-17 19:30:43 +01:00
-- Initialize pressure plates and randomly remove up to 5 plates
2021-02-22 00:15:32 +01:00
local pplates = minetest.find_nodes_in_area ( p1 , p2 , " mesecons_pressureplates:pressure_plate_stone_off " )
2018-01-17 19:30:43 +01:00
local pplates_remove = 5
2017-09-14 03:41:06 +02:00
for p = 1 , # pplates do
2018-01-17 19:30:43 +01:00
if pplates_remove > 0 and pr : next ( 1 , 100 ) >= 50 then
-- Remove plate
minetest.remove_node ( pplates [ p ] )
pplates_remove = pplates_remove - 1
else
-- Initialize plate
minetest.registered_nodes [ " mesecons_pressureplates:pressure_plate_stone_off " ] . on_construct ( pplates [ p ] )
end
2017-09-14 03:41:06 +02:00
end
2021-02-22 00:15:32 +01:00
end
2017-09-14 03:41:06 +02:00
2021-05-25 12:52:25 +02:00
function mcl_structures . generate_desert_temple ( pos , rotation , pr )
2021-02-22 00:15:32 +01:00
-- No Generating for the temple ... Why using it ? No Change
2021-05-29 16:12:33 +02:00
local path = modpath .. " /schematics/mcl_structures_desert_temple.mts "
2021-02-22 00:15:32 +01:00
local newpos = { x = pos.x , y = pos.y - 12 , z = pos.z }
2021-04-17 07:46:24 +02:00
--local size = {x=22, y=24, z=22}
2021-02-22 00:15:32 +01:00
if newpos == nil then
return
end
2021-03-07 00:49:34 +01:00
mcl_structures.place_schematic ( newpos , path , rotation or " random " , nil , true , nil , temple_placement_callback , pr )
2015-07-04 04:56:02 +02:00
end
2022-06-06 01:46:32 +02:00
local structure_data = { }
2017-12-10 22:20:48 +01:00
--[[ Returns a table of structure of the specified type.
Currently the only valid parameter is " stronghold " .
Format of return value :
{
{ pos = < position > , generated =< true / false > } , -- first structure
{ pos = < position > , generated =< true / false > } , -- second structure
-- and so on
}
TODO : Implement this function for all other structure types as well .
] ]
2022-06-06 01:46:32 +02:00
function mcl_structures . get_structure_data ( structure_type )
if structure_data [ structure_type ] then
return table.copy ( structure_data [ structure_type ] )
2017-12-11 19:33:58 +01:00
else
return { }
end
2017-12-10 22:20:48 +01:00
end
-- Register a structures table for the given type. The table format is the same as for
2022-06-06 01:46:32 +02:00
-- mcl_structures.get_structure_data.
function mcl_structures . register_structure_data ( structure_type , structures )
structure_data [ structure_type ] = structures
2017-12-10 22:20:48 +01:00
end
2015-07-04 04:56:02 +02:00
2021-02-27 20:20:57 +01:00
local function dir_to_rotation ( dir )
local ax , az = math.abs ( dir.x ) , math.abs ( dir.z )
if ax > az then
if dir.x < 0 then
return " 270 "
end
2021-02-27 19:44:34 +01:00
return " 90 "
end
2021-02-27 20:20:57 +01:00
if dir.z < 0 then
return " 180 "
2021-02-27 19:44:34 +01:00
end
return " 0 "
end
2022-06-06 03:34:31 +02:00
dofile ( modpath .. " /api.lua " )
2022-06-15 04:48:26 +02:00
-- Debug command
minetest.register_chatcommand ( " spawnstruct " , {
params = " desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_exit_portal_open | end_gateway_portal | end_portal_shrine | nether_portal | dungeon " ,
description = S ( " Generate a pre-defined structure near your position. " ) ,
privs = { debug = true } ,
func = function ( name , param )
local player = minetest.get_player_by_name ( name )
if not player then return end
local pos = player : get_pos ( )
if not pos then return end
pos = vector.round ( pos )
local dir = minetest.yaw_to_dir ( player : get_look_horizontal ( ) )
local rot = dir_to_rotation ( dir )
local pr = PseudoRandom ( pos.x + pos.y + pos.z )
local errord = false
local message = S ( " Structure placed. " )
if param == " desert_temple " then
mcl_structures.generate_desert_temple ( pos , rot , pr )
elseif param == " desert_well " then
mcl_structures.generate_desert_well ( pos , rot )
elseif param == " igloo " then
mcl_structures.generate_igloo ( pos , rot , pr )
elseif param == " witch_hut " then
mcl_structures.generate_witch_hut ( pos , rot , pr )
elseif param == " boulder " then
mcl_structures.generate_boulder ( pos , rot , pr )
elseif param == " fossil " then
mcl_structures.generate_fossil ( pos , rot , pr )
elseif param == " ice_spike_small " then
mcl_structures.generate_ice_spike_small ( pos , rot , pr )
elseif param == " ice_spike_large " then
mcl_structures.generate_ice_spike_large ( pos , rot , pr )
elseif param == " end_exit_portal " then
mcl_structures.generate_end_exit_portal ( pos , rot , pr )
elseif param == " end_exit_portal_open " then
mcl_structures.generate_end_exit_portal_open ( pos , rot , pr )
elseif param == " end_gateway_portal " then
mcl_structures.generate_end_gateway_portal ( pos , rot , pr )
elseif param == " end_portal_shrine " then
mcl_structures.generate_end_portal_shrine ( pos , rot , pr )
elseif param == " dungeon " and mcl_dungeons and mcl_dungeons.spawn_dungeon then
mcl_dungeons.spawn_dungeon ( pos , rot , pr )
elseif param == " nether_portal " and mcl_portals and mcl_portals.spawn_nether_portal then
mcl_portals.spawn_nether_portal ( pos , rot , pr , name )
elseif param == " " then
message = S ( " Error: No structure type given. Please use “/spawnstruct <type>”. " )
errord = true
else
for n , d in pairs ( mcl_structures.registered_structures ) do
if n == param then
mcl_structures.place_structure ( pos , d , pr )
return true , message
2022-06-10 02:40:33 +02:00
end
end
2022-06-15 04:48:26 +02:00
message = S ( " Error: Unknown structure type. Please use “/spawnstruct <type>”. " )
errord = true
end
minetest.chat_send_player ( name , message )
if errord then
minetest.chat_send_player ( name , S ( " Use /help spawnstruct to see a list of avaiable types. " ) )
2022-06-10 02:40:33 +02:00
end
2022-06-15 04:48:26 +02:00
end
} )
minetest.register_on_mods_loaded ( function ( )
local p = " "
for n , _ in pairs ( mcl_structures.registered_structures ) do
p = p .. " | " .. n
end
minetest.registered_chatcommands [ " spawnstruct " ] . params = minetest.registered_chatcommands [ " spawnstruct " ] . params .. p
2022-06-10 02:40:33 +02:00
end )