From 46bac9d063ca41c740453a39bfddc0b378f40563 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 21 Dec 2021 22:00:51 +0100 Subject: [PATCH] Add support for laser mirroring --- mods/lzr_laser/blocks.lua | 22 ++++++++++++++++++++++ mods/lzr_laser/physics.lua | 33 +++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/mods/lzr_laser/blocks.lua b/mods/lzr_laser/blocks.lua index 2df2d9e..0fdb4ad 100644 --- a/mods/lzr_laser/blocks.lua +++ b/mods/lzr_laser/blocks.lua @@ -43,6 +43,28 @@ lzr_laser.get_mirror_dirs = function(param2) return dir_input, dir_output end +-- Mirror a laser that touches a mirror at mirror_pos with a laser coming towards +-- the mirror with the laser_dir direction (direction vector). +-- Returns the "output direction" of the laser or false if can't get mirrored. +lzr_laser.get_mirrored_laser_dir = function(mirror_pos, laser_dir) + local mirror = minetest.get_node(mirror_pos) + local mirror_group = minetest.get_item_group(mirror.name, "mirror") + if mirror_group == 0 then + return false + end + local reverse_laser_dir = vector.multiply(laser_dir, -1) + local mirror_dir_in, mirror_dir_out = lzr_laser.get_mirror_dirs(mirror.param2) + if not mirror_dir_in then + return false + end + if vector.equals(reverse_laser_dir, mirror_dir_in) then + return mirror_dir_out + elseif vector.equals(reverse_laser_dir, mirror_dir_out) then + return mirror_dir_in + end + return false +end + minetest.register_node("lzr_laser:mirror", { description = S("Mirror"), paramtype2 = "facedir", diff --git a/mods/lzr_laser/physics.lua b/mods/lzr_laser/physics.lua index d0156a9..77ce563 100644 --- a/mods/lzr_laser/physics.lua +++ b/mods/lzr_laser/physics.lua @@ -10,7 +10,8 @@ function lzr_laser.add_laser(pos, dir) local dirs = lzr_laser.vector_to_dirs(dir) local dirstring = lzr_laser.dirs_to_dirstring(dirs) minetest.set_node(pos, {name="lzr_laser:laser_"..dirstring}) - return true + pos = vector.add(pos, dir) + return pos, dir -- Laser through laser (laser intersection) elseif minetest.get_item_group(node.name, "laser") > 0 then local dirnum = minetest.get_item_group(node.name, "laser") @@ -21,7 +22,21 @@ function lzr_laser.add_laser(pos, dir) local place_dirstring = lzr_laser.bitwise_or(dirstring_old, dirstring_new) minetest.set_node(pos, {name="lzr_laser:laser_"..place_dirstring}) - return true + pos = vector.add(pos, dir) + return pos, dir + -- Mirror laser + elseif minetest.get_item_group(node.name, "mirror") > 0 then + local mirror_dir = lzr_laser.get_mirrored_laser_dir(pos, dir) + if mirror_dir then + -- Activate mirror node + minetest.set_node(pos, {name="lzr_laser:mirror_on", param2 = node.param2}) + -- Set new pos and dir + pos = vector.add(pos, mirror_dir) + dir = mirror_dir + return pos, dir + else + return false + end -- Anything else: fail else return false @@ -52,23 +67,29 @@ function lzr_laser.travel_laser(pos, dir) break end local i_node = minetest.get_node(i_pos) - cond = lzr_laser.add_laser(i_pos, dir) - i_pos = vector.add(i_pos, dir) + i_pos, dir = lzr_laser.add_laser(i_pos, dir) + if i_pos == false then + cond = false + end end end -- Remove all lasers in area and disable all laser blocks function lzr_laser.clear_lasers_in_area(pos1, pos2) + -- Remove lasers local lasers = minetest.find_nodes_in_area(pos1, pos2, {"group:laser"}) minetest.bulk_set_node(lasers, {name="air"}) + + -- Disable laser blocks (mirror, etc.) local laser_blocks = minetest.find_nodes_in_area(pos1, pos2, {"group:laser_block"}) for b=1, #laser_blocks do - local block = minetest.get_node(laser_blocks[b]) + local block_pos = laser_blocks[b] + local block = minetest.get_node(block_pos) local def = minetest.registered_nodes[block.name] if def then local inactive = def._lzr_inactive if inactive then - minetest.set_node(block, {name="inactive", param2=block.param2}) + minetest.set_node(block_pos, {name=inactive, param2=block.param2}) end end end