lazarr/mods/lzr_laser/laser.lua

127 lines
3.9 KiB
Lua

local S = minetest.get_translator("lzr_laser")
local TEX_LASER, TEX_LASER_NOCENTER
local ALPHA_LASER
if lzr_globals.OPAQUE_LASERS then
TEX_LASER = "lzr_laser_laser_opaque.png"
TEX_LASER_NOCENTER = "lzr_laser_laser_nocenter_opaque.png"
ALPHA_LASER = "clip"
else
TEX_LASER = "lzr_laser_laser.png"
TEX_LASER_NOCENTER = "lzr_laser_laser_nocenter.png"
ALPHA_LASER = "blend"
end
-- Distance from center to side of the laser beam square. Not really the radius, but it sounds cooler. :P
local LASER_RADIUS = -1/16
-- Returns a nodebox for the given dirs table
local function dirs_to_nodebox(dirs)
local boxes = {}
local x = dirs[1] == 1
local y = dirs[2] == 1
local z = dirs[3] == 1
-- True if 2 or more axes are used
local multidir = (x and y) or (x and z) or (y and z)
-- Center block
if multidir and (x or y or z) then
table.insert(boxes, { -LASER_RADIUS, -LASER_RADIUS, -LASER_RADIUS, LASER_RADIUS, LASER_RADIUS, LASER_RADIUS })
end
-- Axes (X, Y, Z)
if x then
if not multidir then
table.insert(boxes, { -0.5, -LASER_RADIUS, -LASER_RADIUS, 0.5, LASER_RADIUS, LASER_RADIUS })
else
table.insert(boxes, { -0.5, -LASER_RADIUS, -LASER_RADIUS, LASER_RADIUS, LASER_RADIUS, LASER_RADIUS })
table.insert(boxes, { -LASER_RADIUS, -LASER_RADIUS, -LASER_RADIUS, 0.5, LASER_RADIUS, LASER_RADIUS })
end
end
if y then
if not multidir then
table.insert(boxes, { -LASER_RADIUS, -0.5, -LASER_RADIUS, LASER_RADIUS, 0.5, LASER_RADIUS })
else
table.insert(boxes, { -LASER_RADIUS, -0.5, -LASER_RADIUS, LASER_RADIUS, LASER_RADIUS, LASER_RADIUS })
table.insert(boxes, { -LASER_RADIUS, -LASER_RADIUS, -LASER_RADIUS, LASER_RADIUS, 0.5, LASER_RADIUS })
end
end
if z then
if not multidir then
table.insert(boxes, { -LASER_RADIUS, -LASER_RADIUS, -0.5, LASER_RADIUS, LASER_RADIUS, 0.5 })
else
table.insert(boxes, { -LASER_RADIUS, -LASER_RADIUS, -0.5, LASER_RADIUS, LASER_RADIUS, LASER_RADIUS })
table.insert(boxes, { -LASER_RADIUS, -LASER_RADIUS, -LASER_RADIUS, LASER_RADIUS, LASER_RADIUS, 0.5 })
end
end
return boxes
end
-- Register laser nodes
-- 7 nodes because (2^3)-1 (2 states for each of 3 axes, minus the state when there's no laser (=air))
for i=1, 7 do
local dirstring = lzr_laser.dec2bin(i, 3)
local dirs = lzr_laser.dirstring_to_dirs(dirstring)
-- Check which textures to render.
-- This looks complicated but serves a simple purpose: To prevent the laser cross-section
-- to render, so there is a "clean" laser beam look.
-- This works because lzr_laser_laser_nocenter.png.
local axes = 0
local axes_active = {x=false,y=false,z=false}
for a=1,3 do
if dirs[a] ~= 0 then
axes = axes + 1
if a == 1 then
axes_active.x = true
elseif a == 2 then
axes_active.y = true
elseif a == 3 then
axes_active.z = true
end
end
end
local tex
if axes == 1 then
if axes_active.x then
tex = { TEX_LASER, TEX_LASER, "blank.png", "blank.png", TEX_LASER }
elseif axes_active.y then
tex = { "blank.png", "blank.png", TEX_LASER }
else
tex = { TEX_LASER, TEX_LASER, TEX_LASER, TEX_LASER, "blank.png" }
end
elseif axes == 2 then
if axes_active.x == false then
tex = { TEX_LASER_NOCENTER, TEX_LASER_NOCENTER, TEX_LASER, TEX_LASER, TEX_LASER_NOCENTER }
elseif axes_active.y == false then
tex = { TEX_LASER, TEX_LASER, TEX_LASER_NOCENTER }
else
tex = { TEX_LASER_NOCENTER, TEX_LASER_NOCENTER, TEX_LASER_NOCENTER, TEX_LASER_NOCENTER, TEX_LASER }
end
elseif axes == 3 then
tex = { TEX_LASER_NOCENTER }
end
-- Finally register the laser
minetest.register_node("lzr_laser:laser_"..dirstring, {
description = S("Laser (@1)", dirstring),
paramtype = "light",
light_source = lzr_globals.LASER_GLOW,
drawtype = "nodebox",
sunlight_propagates = true,
walkable = false,
use_texture_alpha = ALPHA_LASER,
tiles = tex,
pointable = false,
buildable_to = true,
node_box = {
type = "fixed",
fixed = dirs_to_nodebox(dirs),
},
groups = { laser = i, not_in_creative_inventory = 1 },
drop = "",
})
end