216 lines
7.4 KiB
Lua
216 lines
7.4 KiB
Lua
local S = minetest.get_translator("lzr_laser")
|
|
|
|
-- List of laser hex codes. Affects the actual laser color in the game!
|
|
lzr_laser.DEFAULT_LASER_COLORS = {
|
|
[lzr_globals.COLOR_RED] = "#FF0000",
|
|
[lzr_globals.COLOR_GREEN] = "#00FF00",
|
|
[lzr_globals.COLOR_BLUE] = "#0000FF",
|
|
[lzr_globals.COLOR_YELLOW] = "#FFFF00",
|
|
[lzr_globals.COLOR_CYAN] = "#00FFFF",
|
|
[lzr_globals.COLOR_MAGENTA] = "#FF00FF",
|
|
[lzr_globals.COLOR_WHITE] = "#FFFFFF",
|
|
}
|
|
|
|
-- List of patterns to apply on lasers to distinguish them by some other
|
|
-- way than just color. Implemented to deal with colorblindness.
|
|
local LASER_PATTERNS = {
|
|
[lzr_globals.COLOR_RED] = nil, -- no pattern, use a solid line
|
|
[lzr_globals.COLOR_GREEN] = { name = "lzr_laser_pattern_lines.png", size = 16 },
|
|
[lzr_globals.COLOR_BLUE] = { name = "lzr_laser_pattern_dots.png", size = 16 },
|
|
[lzr_globals.COLOR_YELLOW] = { name = "lzr_laser_pattern_checkers.png", size = 16 },
|
|
[lzr_globals.COLOR_CYAN] = { name = "lzr_laser_pattern_long_checkers.png", size = 16 },
|
|
[lzr_globals.COLOR_MAGENTA] = { name = "lzr_laser_pattern_alternating.png", size = 16 },
|
|
[lzr_globals.COLOR_WHITE] = { name = "lzr_laser_pattern_holes.png", size = 32 },
|
|
}
|
|
|
|
|
|
-- Hex alpha value for translucent lasers, as a string
|
|
local LALPHA = "8E"
|
|
|
|
|
|
-- Shorthand to generate a laser tile. We don't use texture files,
|
|
-- we generate them on the fly!
|
|
local maketile = function(colorcode, alpha)
|
|
local use_patterns = minetest.settings:get_bool("lzr_patterned_lasers", false)
|
|
local alpha_append = ""
|
|
local pattern_append = ""
|
|
if alpha then
|
|
alpha_append = LALPHA
|
|
end
|
|
local texsize = 16
|
|
if use_patterns then
|
|
local pattern = LASER_PATTERNS[colorcode]
|
|
if pattern ~= nil then
|
|
pattern_append = "^[mask:"..pattern.name
|
|
texsize = pattern.size
|
|
end
|
|
end
|
|
local texture =
|
|
-- Generate the texture base color
|
|
"([fill:"..texsize.."x"..texsize..":"..
|
|
lzr_laser.DEFAULT_LASER_COLORS[colorcode]..alpha_append..")"
|
|
-- Apply a pattern on the laser, if enabled (allows to distinguish
|
|
-- lasers other than by color to circumvent colorblindness)
|
|
.. pattern_append
|
|
|
|
return { name = texture, backface_culling = true }
|
|
end
|
|
|
|
-- List of all possible laser tiles
|
|
if lzr_globals.OPAQUE_LASERS then
|
|
lzr_laser.TILE_LASER_R = maketile(lzr_globals.COLOR_RED)
|
|
lzr_laser.TILE_LASER_G = maketile(lzr_globals.COLOR_GREEN)
|
|
lzr_laser.TILE_LASER_B = maketile(lzr_globals.COLOR_BLUE)
|
|
lzr_laser.TILE_LASER_Y = maketile(lzr_globals.COLOR_YELLOW)
|
|
lzr_laser.TILE_LASER_C = maketile(lzr_globals.COLOR_CYAN)
|
|
lzr_laser.TILE_LASER_M = maketile(lzr_globals.COLOR_MAGENTA)
|
|
lzr_laser.TILE_LASER_W = maketile(lzr_globals.COLOR_WHITE)
|
|
lzr_laser.ALPHA_LASER = "clip"
|
|
else
|
|
lzr_laser.TILE_LASER_R = maketile(lzr_globals.COLOR_RED, true)
|
|
lzr_laser.TILE_LASER_G = maketile(lzr_globals.COLOR_GREEN, true)
|
|
lzr_laser.TILE_LASER_B = maketile(lzr_globals.COLOR_BLUE, true)
|
|
lzr_laser.TILE_LASER_Y = maketile(lzr_globals.COLOR_YELLOW, true)
|
|
lzr_laser.TILE_LASER_C = maketile(lzr_globals.COLOR_CYAN, true)
|
|
lzr_laser.TILE_LASER_M = maketile(lzr_globals.COLOR_MAGENTA, true)
|
|
lzr_laser.TILE_LASER_W = maketile(lzr_globals.COLOR_WHITE, true)
|
|
lzr_laser.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
|
|
|
|
-- Register laser nodes, i.e. the actual
|
|
-- laser beams in the map.
|
|
|
|
--[[ This registers a node for every possible laser combination.
|
|
A laser node contains 1 to 3 laser beams, each along the
|
|
X, Y and Z axis. Also, each laser beam can have one of
|
|
each possible laser color (defined by colorcodes from 0
|
|
to lzr_globals.MAX_COLORCODE).
|
|
When there is no laser on any axis, there is no need
|
|
for a laser node.
|
|
|
|
The number of registered nodes is
|
|
(<number of laser colors + 1> ^ 3) - 1
|
|
]]
|
|
|
|
for color_x=0, lzr_globals.MAX_COLORCODE do
|
|
for color_y=0, lzr_globals.MAX_COLORCODE do
|
|
for color_z=0, lzr_globals.MAX_COLORCODE do
|
|
|
|
local dirstring = color_x .. color_y .. color_z
|
|
local dirs = lzr_laser.dirstring_to_dirs(dirstring)
|
|
|
|
-- Count the active axes
|
|
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 color2tile = function(colorcode)
|
|
if colorcode == 0 then
|
|
return "blank.png"
|
|
end
|
|
if colorcode == lzr_globals.COLOR_RED then
|
|
return lzr_laser.TILE_LASER_R
|
|
elseif colorcode == lzr_globals.COLOR_GREEN then
|
|
return lzr_laser.TILE_LASER_G
|
|
elseif colorcode == lzr_globals.COLOR_YELLOW then
|
|
return lzr_laser.TILE_LASER_Y
|
|
elseif colorcode == lzr_globals.COLOR_BLUE then
|
|
return lzr_laser.TILE_LASER_B
|
|
elseif colorcode == lzr_globals.COLOR_CYAN then
|
|
return lzr_laser.TILE_LASER_C
|
|
elseif colorcode == lzr_globals.COLOR_MAGENTA then
|
|
return lzr_laser.TILE_LASER_M
|
|
elseif colorcode == lzr_globals.COLOR_WHITE then
|
|
return lzr_laser.TILE_LASER_W
|
|
else
|
|
-- error
|
|
return "no_texture.png"
|
|
end
|
|
end
|
|
|
|
-- Pick a mesh depending on the axes on where to put
|
|
-- a laser beam.
|
|
-- The meshes are made so that the "ends" of the lasers
|
|
-- are "open", i.e. don't have an additional face.
|
|
-- This ensures the laser beam looks like a real
|
|
-- continuous beam reather than a sequence of nodes.
|
|
|
|
local tex, mesh
|
|
-- Single laser
|
|
if axes == 1 then
|
|
-- Simple: Just pick a mesh for the laser direction, and then the color
|
|
if axes_active.x then
|
|
mesh = "lzr_laser_laser_100.obj"
|
|
tex = { color2tile(color_x) }
|
|
elseif axes_active.y then
|
|
mesh = "lzr_laser_laser_010.obj"
|
|
tex = { color2tile(color_y)}
|
|
else
|
|
mesh = "lzr_laser_laser_001.obj"
|
|
tex = { color2tile(color_z) }
|
|
end
|
|
-- 2 lasers crossing
|
|
elseif axes == 2 then
|
|
-- A bit trickier: We have two primary colors from 2 lasers,
|
|
-- but at the crossing, we mix both colors with the 'combined' var.
|
|
if axes_active.x == false then
|
|
mesh = "lzr_laser_laser_011.obj"
|
|
-- Color mixing is just a bitwise OR of 2 colorcodes. Because the colorcodes
|
|
-- are aligned in the correct way for this to work.
|
|
local combined = bit.bor(color_y, color_z)
|
|
tex = { color2tile(combined), color2tile(color_y), color2tile(color_z) }
|
|
elseif axes_active.y == false then
|
|
mesh = "lzr_laser_laser_101.obj"
|
|
local combined = bit.bor(color_x, color_z)
|
|
tex = { color2tile(color_x), color2tile(combined), color2tile(color_z) }
|
|
else
|
|
mesh = "lzr_laser_laser_110.obj"
|
|
local combined = bit.bor(color_x, color_y)
|
|
tex = { color2tile(color_x), color2tile(color_y), color2tile(combined) }
|
|
end
|
|
-- Note
|
|
-- 3 lasers crossing
|
|
elseif axes == 3 then
|
|
-- Easy again: Pick a mesh and 3 colors for the 3 axes
|
|
mesh = "lzr_laser_laser_111.obj"
|
|
tex = { color2tile(color_x), color2tile(color_y), color2tile(color_z) }
|
|
end
|
|
|
|
-- This generates an unique number for each possible laser combination
|
|
local lasergroup = lzr_laser.colors_to_laser_group(color_x, color_y, color_z)
|
|
if tex then
|
|
-- Finally register the laser
|
|
minetest.register_node("lzr_laser:laser_"..dirstring, {
|
|
description = S("Laser (@1)", lzr_laser.dirstring_to_colstring(dirstring)),
|
|
paramtype = "light",
|
|
light_source = lzr_globals.LASER_GLOW,
|
|
drawtype = "mesh",
|
|
mesh = mesh,
|
|
sunlight_propagates = true,
|
|
walkable = false,
|
|
use_texture_alpha = lzr_laser.ALPHA_LASER,
|
|
tiles = tex,
|
|
pointable = false,
|
|
buildable_to = true,
|
|
|
|
groups = { laser = lasergroup, not_in_creative_inventory = 1, dig_immediate = 3 },
|
|
drop = "",
|
|
})
|
|
end
|
|
end
|
|
end
|
|
end
|