Implement new transmissive mirror physics (WIP)

master
Wuzzy 2022-03-14 02:14:55 +01:00
parent cf5cf6aac3
commit e222d6d732
2 changed files with 65 additions and 14 deletions

View File

@ -80,7 +80,14 @@ 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.
-- Returns <output direction>, <mirror output side>
-- 1) If the laser can be mirrored, then <output direction> is the direction of
-- the mirrored laser and <mirror output> denotes on of the 2 possible
-- sides the laser came from: true if it came in the front side, false if
-- it came from the angled side. <mirror output> is useful for the
-- transmissive mirror.
-- 2) If the laser cannot be mirrored <mirror output> is false and
-- <mirror output side> is nil
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")
@ -94,9 +101,9 @@ lzr_laser.get_mirrored_laser_dir = function(mirror_pos, laser_dir)
return false
end
if vector.equals(reverse_laser_dir, mirror_dir_in) then
return mirror_dir_out
return mirror_dir_out, true
elseif vector.equals(reverse_laser_dir, mirror_dir_out) then
return mirror_dir_in
return mirror_dir_in, false
end
return false
end
@ -201,6 +208,9 @@ local register_element = function(subname, def, options)
if options.not_walkable_if_off then
def_core.walkable = false
end
if options.allow_take then
def_core._lzr_takable = "lzr_laser:"..subname.."_takable"
end
def_core.description = S("@1 (fixed)", def.description)
def_core.after_dig_node = full_update
@ -214,7 +224,13 @@ local register_element = function(subname, def, options)
def_core.groups = {}
end
def_core.groups.breakable = 1
def_core.groups[subname] = 1
local groupname
if options.group then
groupname = options.group
else
groupname = subname
end
def_core.groups[groupname] = 1
def_core.can_dig = element_can_dig
def_core.on_place = element_on_place
@ -237,7 +253,10 @@ local register_element = function(subname, def, options)
if not options.keep_state_on_take then
def_core_on.drop = "lzr_laser:"..subname
end
def_core_on.groups[subname] = 2
if options.allow_take then
def_core_on._lzr_takable = "lzr_laser:"..subname.."_takable_on"
end
def_core_on.groups[groupname] = 2
def_core_on.light_source = def.light_source_on
minetest.register_node("lzr_laser:"..subname.."_on", def_core_on)
end
@ -246,12 +265,14 @@ local register_element = function(subname, def, options)
local def_takable = table.copy(def_core)
def_takable.tiles = def.tiles_takable_off
def_takable.groups.takable = 1
def_takable._lzr_untakable = "lzr_laser:"..subname
def_takable.description = def.description
minetest.register_node("lzr_laser:"..subname.."_takable", def_takable)
if options.activate ~= false then
def_takable._lzr_active = "lzr_laser:"..subname.."_takable_on"
local def_takable_on = table.copy(def_core_on)
def_takable_on._lzr_untakable = "lzr_laser:"..subname.."_on"
def_takable_on.tiles = def.tiles_takable_on
def_takable_on.light_source = def.light_source_on
def_takable_on.groups.takable = 1
@ -326,10 +347,15 @@ local tm_def = {
groups = { rotatable = 1, laser_block = 1 },
sounds = lzr_sounds.node_sound_glass_defaults({
_rotate = {name = "lzr_laser_mirror_rotate", gain = 1.0},
})
}),
_lzr_transmissive_mirror_00 = "lzr_laser:transmissive_mirror_00",
_lzr_transmissive_mirror_01 = "lzr_laser:transmissive_mirror_01",
_lzr_transmissive_mirror_10 = "lzr_laser:transmissive_mirror_10",
_lzr_transmissive_mirror_11 = "lzr_laser:transmissive_mirror_11",
}
local tm_def_off = table.copy(tm_def)
tm_def_off._lzr_transmissive_mirror_state = "00"
tm_def_off.tiles_off = {
{name="lzr_laser_transmissive_mirror_block.png^lzr_laser_fixed.png", backface_culling=true},
{name="lzr_laser_transmissive_mirror_mirror.png", backface_culling=true},
@ -341,8 +367,14 @@ tm_def_off.tiles_takable_off = {
{name="lzr_laser_transmissive_mirror_mirror_out.png", backface_culling=true},
}
tm_def_off.mesh_off = "lzr_laser_mirror.obj"
-- Use custom fields to identify transmissive mirror states
-- Transmissive Mirror
-- FIXME: Takable Transmissive Mirror becomes fixed after full laser update
local tm_def_on_01 = table.copy(tm_def)
tm_def_on_01._lzr_transmissive_mirror_state = "01"
tm_def_on_01._lzr_inactive = "lzr_laser:transmissive_mirror_00"
tm_def_on_01.description = S("Transmissive Mirror (active, 01)")
tm_def_on_01.tiles_off = {
{name="lzr_laser_laser_full.png", backface_culling=true},
@ -359,17 +391,20 @@ tm_def_on_01.tiles_takable_off = {
tm_def_on_01.mesh_off = "lzr_laser_mirror_on_thru1.obj"
local tm_def_on_10 = table.copy(tm_def_on_01)
tm_def_on_10._lzr_transmissive_mirror_state = "10"
tm_def_on_10.description = S("Transmissive Mirror (active, 10)")
tm_def_on_10.mesh_off = "lzr_laser_mirror_on_thru2.obj"
local tm_def_on_11 = table.copy(tm_def_on_01)
tm_def_on_11._lzr_transmissive_mirror_state = "11"
tm_def_on_11.description = S("Transmissive Mirror (active, 11)")
tm_def_on_11.mesh_off = "lzr_laser_mirror_on_thru3.obj"
register_element("transmissive_mirror", tm_def_off, { allow_take = true, activate = false })
register_element("transmissive_mirror_on_01", tm_def_on_01, { allow_take = true, activate = false })
register_element("transmissive_mirror_on_10", tm_def_on_10, { allow_take = true, activate = false })
register_element("transmissive_mirror_on_11", tm_def_on_11, { allow_take = true, activate = false })
local tm_options = { allow_take = true, activate = false, group = "transmissive_mirror" }
register_element("transmissive_mirror_00", tm_def_off, tm_options)
register_element("transmissive_mirror_01", tm_def_on_01, tm_options)
register_element("transmissive_mirror_10", tm_def_on_10, tm_options)
register_element("transmissive_mirror_11", tm_def_on_11, tm_options)
register_element("crystal", {
description = S("Crystal"),

View File

@ -83,14 +83,30 @@ function lzr_laser.add_laser(pos, dir, varea, vdata)
end
-- Mirror and split laser
elseif minetest.get_item_group(nodename, "transmissive_mirror") > 0 then
local mirror_dir = lzr_laser.get_mirrored_laser_dir(pos, dir)
local mirror_dir, mirror_side = lzr_laser.get_mirrored_laser_dir(pos, dir)
if mirror_dir then
local def = minetest.registered_nodes[nodename]
local active = def._lzr_active
if not active then
local state = def._lzr_transmissive_mirror_state
if not state then
minetest.log("error", "[lzr_laser] Transmissive mirror node '"..nodename.."' does not have _lzr_transmissive_mirror_state!")
return false
end
-- Activate mirror node
if mirror_side == true then
state = lzr_laser.bitwise_or(state, "01")
else
state = lzr_laser.bitwise_or(state, "10")
end
local active = def["_lzr_transmissive_mirror_"..state]
if not active then
minetest.log("error", "[lzr_laser] Missing transmissive mirror node state for '"..nodename.."!")
return false
end
local is_takable = minetest.get_item_group(nodename, "takable") ~= 0
if is_takable then
local def_active = minetest.registered_nodes[active]
active = def_active._lzr_takable
end
-- Set new transmissive node state
vdata[vi] = minetest.get_content_id(active)
-- Set new pos and dir
local pos_straight = vector.add(pos, dir)