2024-08-13 10:04:37 +02:00

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