493 lines
14 KiB
Lua
493 lines
14 KiB
Lua
-- Lazarr! mod: stairs
|
|
-- See README.txt for licensing and other information.
|
|
|
|
-- Global namespace for functions
|
|
|
|
stairs = {}
|
|
|
|
-- Load support for MT game translation.
|
|
local S = minetest.get_translator("stairs")
|
|
-- Same as S, but will be ignored by translation file update scripts
|
|
local T = S
|
|
|
|
-- If set to true, will print a list of translatable strings
|
|
-- for the registered nodes to the console so it can
|
|
-- be copied into this source file.
|
|
local GENERATE_TRANSLATABLE_STRING_LIST = false
|
|
|
|
local function rotate_and_place(itemstack, placer, pointed_thing)
|
|
local p0 = pointed_thing.under
|
|
local p1 = pointed_thing.above
|
|
local param2 = 0
|
|
|
|
if placer then
|
|
local placer_pos = placer:get_pos()
|
|
if placer_pos then
|
|
param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos))
|
|
end
|
|
|
|
local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
|
|
local fpos = finepos.y % 1
|
|
|
|
if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5)
|
|
or (fpos < -0.5 and fpos > -0.999999999) then
|
|
param2 = param2 + 20
|
|
if param2 == 21 then
|
|
param2 = 23
|
|
elseif param2 == 23 then
|
|
param2 = 21
|
|
end
|
|
end
|
|
end
|
|
return minetest.item_place(itemstack, placer, pointed_thing, param2)
|
|
end
|
|
|
|
|
|
-- Register stair.
|
|
-- CAN be rotated.
|
|
-- Node will be called stairs:stair_<subname>
|
|
|
|
function stairs.register_stair(subname, recipeitem, groups, images, description,
|
|
sounds, worldaligntex)
|
|
local src_def = minetest.registered_nodes[recipeitem]
|
|
|
|
-- Set backface culling and world-aligned textures
|
|
local stair_images = {}
|
|
for i, image in ipairs(images) do
|
|
if type(image) == "string" then
|
|
stair_images[i] = {
|
|
name = image,
|
|
backface_culling = true,
|
|
}
|
|
if worldaligntex then
|
|
stair_images[i].align_style = "world"
|
|
end
|
|
else
|
|
stair_images[i] = table.copy(image)
|
|
if stair_images[i].backface_culling == nil then
|
|
stair_images[i].backface_culling = true
|
|
end
|
|
if worldaligntex and stair_images[i].align_style == nil then
|
|
stair_images[i].align_style = "world"
|
|
end
|
|
end
|
|
end
|
|
local new_groups = table.copy(groups)
|
|
new_groups.stair = 1
|
|
new_groups.rotatable = 3
|
|
minetest.register_node(":stairs:stair_" .. subname, {
|
|
description = description,
|
|
drawtype = "nodebox",
|
|
tiles = stair_images,
|
|
use_texture_alpha = src_def and src_def.use_texture_alpha,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
is_ground_content = false,
|
|
groups = new_groups,
|
|
sounds = sounds,
|
|
node_box = {
|
|
-- This stairs nodebox is unusual and differs from most other Minetest games.
|
|
-- The segments have been made slightly different so that a laser will alway
|
|
-- be completely blocked off from any direction.
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 1/16, 0.5},
|
|
{-0.5, 1/16, -1/16, 0.5, 0.5, 0.5},
|
|
},
|
|
},
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return itemstack
|
|
end
|
|
|
|
return rotate_and_place(itemstack, placer, pointed_thing)
|
|
end,
|
|
})
|
|
end
|
|
|
|
|
|
-- Register slab.
|
|
-- CAN'T be rotated to simplify the code.
|
|
-- Rotation code MAY be added, as long the node remains compatible with lasers.
|
|
-- Registers two nodes:
|
|
-- * stairs:slab_<subname> for the normal slab and
|
|
-- * stairs:slab_laser_<subname> for the slab with laser from above
|
|
|
|
function stairs.register_slab(subname, recipeitem, groups, images, description,
|
|
sounds, worldaligntex)
|
|
local src_def = minetest.registered_nodes[recipeitem]
|
|
|
|
-- Use first tile only, for slab mesh
|
|
local slab_images = table.copy(images)
|
|
if type(slab_images[1]) == "string" then
|
|
-- Add backface culling because otherwise z-fighting occurs when
|
|
-- inside the node
|
|
slab_images[1] = { name = slab_images[1], backface_culling = true }
|
|
end
|
|
if not slab_images[2] then
|
|
slab_images[2] = slab_images[1]
|
|
end
|
|
if not slab_images[3] then
|
|
slab_images[3] = slab_images[2]
|
|
end
|
|
slab_images[4] = "blank.png"
|
|
slab_images[5] = nil
|
|
slab_images[6] = nil
|
|
|
|
local laser_slab_images = table.copy(slab_images)
|
|
laser_slab_images[4] = lzr_laser.LASER_TILE
|
|
|
|
local new_groups = table.copy(groups)
|
|
new_groups.slab = 1
|
|
new_groups.laser_block = 1
|
|
|
|
lzr_laser.register_element(":stairs:slab_" .. subname, {
|
|
description = description,
|
|
drawtype = "mesh",
|
|
mesh_off = "lzr_stairs_slab_laser.obj",
|
|
mesh_on = "lzr_stairs_slab_laser.obj",
|
|
tiles_off = slab_images,
|
|
tiles_on = laser_slab_images,
|
|
|
|
use_texture_alpha = "blend",
|
|
paramtype = "light",
|
|
is_ground_content = false,
|
|
groups = new_groups,
|
|
sounds = sounds,
|
|
collision_box = {
|
|
type = "fixed",
|
|
-- The slab nodebox is slightly higher than half of a node
|
|
-- so that an incoming laser from any direction (except the top)
|
|
-- will be visually blocked.
|
|
fixed = {-0.5, -0.5, -0.5, 0.5, 1/16, 0.5},
|
|
},
|
|
selection_box = {
|
|
type = "fixed",
|
|
fixed = {-0.5, -0.5, -0.5, 0.5, 1/16, 0.5},
|
|
},
|
|
light_source_on = lzr_globals.LASER_GLOW,
|
|
}, { group = "laser_element_slab_"..subname } )
|
|
|
|
end
|
|
|
|
-- Register inner stair
|
|
-- Node will be called stairs:stair_inner_<subname>
|
|
|
|
function stairs.register_stair_inner(subname, recipeitem, groups, images,
|
|
description, sounds, worldaligntex, full_description)
|
|
local src_def = minetest.registered_nodes[recipeitem]
|
|
|
|
-- Set backface culling and world-aligned textures
|
|
local stair_images = {}
|
|
for i, image in ipairs(images) do
|
|
if type(image) == "string" then
|
|
stair_images[i] = {
|
|
name = image,
|
|
backface_culling = true,
|
|
}
|
|
if worldaligntex then
|
|
stair_images[i].align_style = "world"
|
|
end
|
|
else
|
|
stair_images[i] = table.copy(image)
|
|
if stair_images[i].backface_culling == nil then
|
|
stair_images[i].backface_culling = true
|
|
end
|
|
if worldaligntex and stair_images[i].align_style == nil then
|
|
stair_images[i].align_style = "world"
|
|
end
|
|
end
|
|
end
|
|
local new_groups = table.copy(groups)
|
|
new_groups.stair = 1
|
|
if full_description then
|
|
description = full_description
|
|
else
|
|
description = "Inner " .. description
|
|
end
|
|
minetest.register_node(":stairs:stair_inner_" .. subname, {
|
|
description = description,
|
|
drawtype = "nodebox",
|
|
tiles = stair_images,
|
|
use_texture_alpha = src_def and src_def.use_texture_alpha,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
is_ground_content = false,
|
|
groups = new_groups,
|
|
sounds = sounds,
|
|
node_box = {
|
|
-- Unusual stairs nodebox (see stairs comment)
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 1/16, 0.5},
|
|
{-0.5, 1/16, -1/16, 0.5, 0.5, 0.5},
|
|
{-0.5, 1/16, -0.5, 1/16, 0.5, -1/16},
|
|
},
|
|
},
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return itemstack
|
|
end
|
|
|
|
return rotate_and_place(itemstack, placer, pointed_thing)
|
|
end,
|
|
})
|
|
|
|
end
|
|
|
|
|
|
-- Register outer stair
|
|
-- Node will be called stairs:stair_outer_<subname>
|
|
|
|
function stairs.register_stair_outer(subname, recipeitem, groups, images,
|
|
description, sounds, worldaligntex, full_description)
|
|
local src_def = minetest.registered_nodes[recipeitem]
|
|
|
|
-- Set backface culling and world-aligned textures
|
|
local stair_images = {}
|
|
for i, image in ipairs(images) do
|
|
if type(image) == "string" then
|
|
stair_images[i] = {
|
|
name = image,
|
|
backface_culling = true,
|
|
}
|
|
if worldaligntex then
|
|
stair_images[i].align_style = "world"
|
|
end
|
|
else
|
|
stair_images[i] = table.copy(image)
|
|
if stair_images[i].backface_culling == nil then
|
|
stair_images[i].backface_culling = true
|
|
end
|
|
if worldaligntex and stair_images[i].align_style == nil then
|
|
stair_images[i].align_style = "world"
|
|
end
|
|
end
|
|
end
|
|
local new_groups = table.copy(groups)
|
|
new_groups.stair = 1
|
|
if full_description then
|
|
description = full_description
|
|
else
|
|
description = "Outer " .. description
|
|
end
|
|
minetest.register_node(":stairs:stair_outer_" .. subname, {
|
|
description = description,
|
|
drawtype = "nodebox",
|
|
tiles = stair_images,
|
|
use_texture_alpha = src_def and src_def.use_texture_alpha,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
is_ground_content = false,
|
|
groups = new_groups,
|
|
sounds = sounds,
|
|
node_box = {
|
|
-- Unusual stairs nodebox (see stairs comment)
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 1/16, 0.5},
|
|
{-0.5, 1/16, -1/16, 1/16, 0.5, 0.5},
|
|
},
|
|
},
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return itemstack
|
|
end
|
|
|
|
return rotate_and_place(itemstack, placer, pointed_thing)
|
|
end,
|
|
})
|
|
|
|
end
|
|
|
|
|
|
-- Stair/slab registration function.
|
|
-- Nodes will be called stairs:{stair,slab}_<subname>
|
|
|
|
function stairs.register_stair_and_slab(subname, recipeitem, groups, images,
|
|
desc_stair, desc_slab, sounds, worldaligntex,
|
|
desc_stair_inner, desc_stair_outer)
|
|
stairs.register_stair(subname, recipeitem, groups, images, desc_stair,
|
|
sounds, worldaligntex)
|
|
stairs.register_stair_inner(subname, recipeitem, groups, images,
|
|
desc_stair, sounds, worldaligntex, desc_stair_inner)
|
|
stairs.register_stair_outer(subname, recipeitem, groups, images,
|
|
desc_stair, sounds, worldaligntex, desc_stair_outer)
|
|
stairs.register_slab(subname, recipeitem, groups, images, desc_slab,
|
|
sounds, worldaligntex)
|
|
end
|
|
|
|
-- Local function so we can apply translations
|
|
local function my_register_stair(subname, recipeitem, groups, images,
|
|
desc_stair, sounds, worldaligntex)
|
|
stairs.register_stair(subname, recipeitem, groups, images, S(desc_stair),
|
|
sounds, worldaligntex)
|
|
stairs.register_stair_inner(subname, recipeitem, groups, images, "",
|
|
sounds, worldaligntex, T("Inner " .. desc_stair))
|
|
stairs.register_stair_outer(subname, recipeitem, groups, images, "",
|
|
sounds, worldaligntex, T("Outer " .. desc_stair))
|
|
end
|
|
local function my_register_stair_and_slab(subname, recipeitem, groups, images,
|
|
desc_stair, desc_slab, sounds, worldaligntex)
|
|
my_register_stair(subname, recipeitem, groups, images,
|
|
desc_stair, sounds, worldaligntex)
|
|
stairs.register_slab(subname, recipeitem, groups, images, S(desc_slab),
|
|
sounds, worldaligntex)
|
|
|
|
if GENERATE_TRANSLATABLE_STRING_LIST then
|
|
for _,x in ipairs({"","Inner ","Outer "}) do
|
|
print(("S(%q)"):format(x..desc_stair))
|
|
end
|
|
print(("S(%q)"):format(desc_slab))
|
|
end
|
|
end
|
|
|
|
-- Register default stairs and slabs
|
|
|
|
my_register_stair_and_slab(
|
|
"wood",
|
|
"lzr_core:wood",
|
|
{breakable=1},
|
|
{"default_wood.png"},
|
|
"Wooden Stair",
|
|
"Wooden Slab",
|
|
lzr_sounds.node_sound_wood_defaults(),
|
|
true
|
|
)
|
|
my_register_stair_and_slab(
|
|
"wood_mossy",
|
|
"lzr_core:wood_mossy",
|
|
{breakable=1},
|
|
{"lzr_core_wood_mossy.png"},
|
|
"Mossy Wooden Stair",
|
|
"Mossy Wooden Slab",
|
|
lzr_sounds.node_sound_wood_defaults(),
|
|
true
|
|
)
|
|
my_register_stair_and_slab(
|
|
"palm_wood",
|
|
"lzr_core:palm_wood",
|
|
{breakable=1},
|
|
{"lzr_core_palm_wood.png"},
|
|
"Palm Wood Stair",
|
|
"Palm Wood Slab",
|
|
lzr_sounds.node_sound_wood_defaults(),
|
|
true
|
|
)
|
|
my_register_stair_and_slab(
|
|
"coconut_wood",
|
|
"lzr_core:coconut_wood",
|
|
{breakable=1},
|
|
{"lzr_core_coconut_wood.png"},
|
|
"Coconut Wood Stair",
|
|
"Coconut Wood Slab",
|
|
lzr_sounds.node_sound_wood_defaults(),
|
|
true
|
|
)
|
|
my_register_stair_and_slab(
|
|
"stone",
|
|
"lzr_core:stone",
|
|
{breakable=1},
|
|
{"default_stone.png"},
|
|
"Stone Stair",
|
|
"Stone Slab",
|
|
lzr_sounds.node_sound_stone_defaults(),
|
|
true
|
|
)
|
|
my_register_stair_and_slab(
|
|
"ocean_stone",
|
|
"lzr_decor:ocean_stone",
|
|
{breakable=1},
|
|
{"xocean_stone.png"},
|
|
"Ocean Stone Stair",
|
|
"Ocean Stone Slab",
|
|
lzr_sounds.node_sound_stone_defaults(),
|
|
true
|
|
)
|
|
my_register_stair_and_slab(
|
|
"ocean_cobble",
|
|
"lzr_decor:ocean_cobble",
|
|
{breakable=1},
|
|
{"xocean_cobble.png"},
|
|
"Ocean Cobblestone Stair",
|
|
"Ocean Cobblestone Slab",
|
|
lzr_sounds.node_sound_stone_defaults(),
|
|
true
|
|
)
|
|
my_register_stair_and_slab(
|
|
"thatch",
|
|
"lzr_decor:thatch",
|
|
{breakable=1},
|
|
{"dryplants_thatch.png"},
|
|
"Thatch Stair",
|
|
"Thatch Slab",
|
|
lzr_sounds.node_sound_leaves_defaults(),
|
|
true
|
|
)
|
|
my_register_stair_and_slab(
|
|
"thatch_wet",
|
|
"lzr_decor:thatch_wet",
|
|
{breakable=1},
|
|
{"dryplants_thatch_wet.png"},
|
|
"Wet Thatch Stair",
|
|
"Wet Thatch Slab",
|
|
lzr_sounds.node_sound_leaves_defaults(),
|
|
true
|
|
)
|
|
|
|
-- Dummy calls to S() to allow translation scripts to detect the strings.
|
|
-- MUST be updated before release when new nodes have arrived.
|
|
-- To update this, set GENERATE_TRANSLATABLE_STRING_LIST to true
|
|
-- and paste the console output here:
|
|
--[[
|
|
S("Wooden Stair")
|
|
S("Inner Wooden Stair")
|
|
S("Outer Wooden Stair")
|
|
S("Wooden Slab")
|
|
S("Mossy Wooden Stair")
|
|
S("Inner Mossy Wooden Stair")
|
|
S("Outer Mossy Wooden Stair")
|
|
S("Mossy Wooden Slab")
|
|
S("Palm Wood Stair")
|
|
S("Inner Palm Wood Stair")
|
|
S("Outer Palm Wood Stair")
|
|
S("Palm Wood Slab")
|
|
S("Coconut Wood Stair")
|
|
S("Inner Coconut Wood Stair")
|
|
S("Outer Coconut Wood Stair")
|
|
S("Coconut Wood Slab")
|
|
S("Stone Stair")
|
|
S("Inner Stone Stair")
|
|
S("Outer Stone Stair")
|
|
S("Stone Slab")
|
|
S("Ocean Stone Stair")
|
|
S("Inner Ocean Stone Stair")
|
|
S("Outer Ocean Stone Stair")
|
|
S("Ocean Stone Slab")
|
|
S("Ocean Cobblestone Stair")
|
|
S("Inner Ocean Cobblestone Stair")
|
|
S("Outer Ocean Cobblestone Stair")
|
|
S("Ocean Cobblestone Slab")
|
|
S("Thatch Stair")
|
|
S("Inner Thatch Stair")
|
|
S("Outer Thatch Stair")
|
|
S("Thatch Slab")
|
|
S("Wet Thatch Stair")
|
|
S("Inner Wet Thatch Stair")
|
|
S("Outer Wet Thatch Stair")
|
|
S("Wet Thatch Slab")
|
|
]]
|
|
|
|
|
|
|
|
-- Aliases for the pre-laser color era
|
|
minetest.register_alias("stairs:slab_wood_laser", "stairs:slab_wood_on_1")
|
|
minetest.register_alias("stairs:slab_wood_mossy_laser", "stairs:slab_wood_mossy_on_1")
|
|
minetest.register_alias("stairs:slab_palm_wood_laser", "stairs:slab_palm_wood_on_1")
|
|
minetest.register_alias("stairs:slab_coconut_wood_laser", "stairs:slab_coconut_wood_on_1")
|
|
minetest.register_alias("stairs:slab_stone_laser", "stairs:slab_stone_on_1")
|
|
minetest.register_alias("stairs:slab_ocean_stone_laser", "stairs:slab_ocean_stone_on_1")
|
|
minetest.register_alias("stairs:slab_ocean_cobble_laser", "stairs:slab_ocean_cobble_on_1")
|
|
minetest.register_alias("stairs:slab_thatch_laser", "stairs:slab_thatch_on_1")
|
|
minetest.register_alias("stairs:slab_thatch_wet_laser", "stairs:slab_thatch_wet_on_1")
|