-
-local r_corr = 0.25 -- Remove a bit more nodes (if shooting diagonal) to let it look like a hole (sth like antialiasing)
-
local mining_lasers_list = {
-- {<num>, <range of the laser shots>, <max_charge>, <charge_per_shot>},
{"1", 7, 50000, 1000},
{"3", 21, 650000, 3000},
}
-local f_1 = 0.5 - r_corr
-local f_2 = 0.5 + r_corr
-
local S = technic.getter
minetest.register_craft({
}
})
-
-local function get_used_dir(dir)
- local abs_dir = {x = math.abs(dir.x),
- y = math.abs(dir.y),
- z = math.abs(dir.z)}
- local dir_max = math.max(abs_dir.x, abs_dir.y, abs_dir.z)
- if dir_max == abs_dir.x then
- local tab = {"x", {x = 1, y = dir.y / dir.x, z = dir.z / dir.x}}
- if dir.x >= 0 then
- tab[3] = "+"
- end
- return tab
- end
- if dir_max == abs_dir.y then
- local tab = {"y", {x = dir.x / dir.y, y = 1, z = dir.z / dir.y}}
- if dir.y >= 0 then
- tab[3] = "+"
+local function table_icontains(t, v)
+ for i = 1,#t do
+ if v == t[i] then
+ return true
end
- return tab
end
- local tab = {"z", {x = dir.x / dir.z, y = dir.y / dir.z, z = 1}}
- if dir.z >= 0 then
- tab[3] = "+"
- end
- return tab
-end
-
-local function node_tab(z, d)
- local n1 = math.floor(z * d + f_1)
- local n2 = math.floor(z * d + f_2)
- if n1 == n2 then
- return {n1}
- end
- return {n1, n2}
+ return false
end
local function laser_node(pos, player)
local node = minetest.get_node(pos)
- if node.name == "air"
- or node.name == "ignore"
- or node.name == "default:lava_source"
- or node.name == "default:lava_flowing" then
+ if table_icontains({"air", "ignore", "default:lava_source", "default:lava_flowing"}, node.name) then
return
end
- if minetest.is_protected(pos, player:get_player_name()) then
- minetest.record_protection_violation(pos, player:get_player_name())
+ local pname = player:get_player_name()
+ if minetest.is_protected(pos, pname) then
+ minetest.record_protection_violation(pos, pname)
return
end
- if node.name == "default:water_source"
- or node.name == "default:water_flowing" then
+ if table_icontains({"default:water_flowing", "default:water_source"}, node.name) then
minetest.remove_node(pos)
- minetest.add_particle(pos,
- {x=0, y=2, z=0},
- {x=0, y=-1, z=0},
- 1.5,
- 8,
- false,
- "smoke_puff.png")
+ minetest.add_particle({
+ pos = pos,
+ vel = {x=0, y=2, z=0},
+ acc = {x=0, y=-1, z=0},
+ expirationtime = 1.5,
+ size = 6+math.random()*2,
+ texture = "smoke_puff.png^[transform"..math.random(0,7),
+ })
return
end
if player then
end
end
-local function laser_nodes(pos, dir, player, range)
- local t_dir = get_used_dir(dir)
- local dir_typ = t_dir[1]
- if t_dir[3] == "+" then
- f_tab = {1, range}
- else
- f_tab = {-range, -1}
- end
- local d_ch = t_dir[2]
- if dir_typ == "x" then
- for d = f_tab[1],f_tab[2],1 do
- local x = d
- local ytab = node_tab(d_ch.y, d)
- local ztab = node_tab(d_ch.z, d)
- for _, y in pairs(ytab) do
- for _, z in pairs(ztab) do
- laser_node({x = pos.x + x, y = pos.y + y, z = pos.z + z}, player)
- end
- end
- end
- return
- end
- if dir_typ == "y" then
- for d = f_tab[1], f_tab[2] do
- local xtab = node_tab(d_ch.x, d)
- local y = d
- local ztab = node_tab(d_ch.z, d)
- for _, x in pairs(xtab) do
- for _, z in pairs(ztab) do
- laser_node({x = pos.x + x, y = pos.y + y, z = pos.z + z}, player)
- end
- end
- end
- return
- end
- for d = f_tab[1], f_tab[2] do
- local xtab = node_tab(d_ch.x, d)
- local ytab = node_tab(d_ch.y, d)
- local z = d
- for _, x in pairs(xtab) do
- for _, y in pairs(ytab) do
- laser_node({x = pos.x + x, y = pos.y + y, z = pos.z + z}, player)
- end
- end
- end
+if not vector.line then
+ dofile(technic.modpath.."/tools/vector_line.lua")
end
local function laser_shoot(player, range, particle_texture, sound)
local playerpos = player:getpos()
local dir = player:get_look_dir()
- local startpos = {x = playerpos.x, y = playerpos.y + 1.6, z = playerpos.z}
+ local startpos = {x = playerpos.x, y = playerpos.y + 1.625, z = playerpos.z}
local mult_dir = vector.multiply(dir, 50)
- minetest.add_particle(startpos, dir, mult_dir, range / 11, 1, false, particle_texture)
- laser_nodes(vector.round(startpos), dir, player, range)
- minetest.sound_play(sound, {pos = playerpos, gain = 1.0, max_hear_distance = range})
+ minetest.add_particle({
+ pos = startpos,
+ vel = dir,
+ acc = mult_dir,
+ expirationtime = range / 11,
+ size = 1,
+ texture = particle_texture.."^[transform"..math.random(0,7),
+ })
+ for _,pos in ipairs(vector.line(vector.round(startpos), dir, range)) do
+ laser_node(pos, player)
+ end
+ minetest.sound_play(sound, {pos = playerpos, max_hear_distance = range})
end
--- /dev/null
+local twolines = {}
+function vector.twoline(x, y)
+ local pstr = x.." "..y
+ local line = twolines[pstr]
+ if line then
+ return line
+ end
+ line = {}
+ local n = 1
+ local dirx = 1
+ if x < 0 then
+ dirx = -dirx
+ end
+ local ymin, ymax = 0, y
+ if y < 0 then
+ ymin, ymax = ymax, ymin
+ end
+ local m = y/x --y/0 works too
+ local dir = 1
+ if m < 0 then
+ dir = -dir
+ end
+ for i = 0,x,dirx do
+ local p1 = math.max(math.min(math.floor((i-0.5)*m+0.5), ymax), ymin)
+ local p2 = math.max(math.min(math.floor((i+0.5)*m+0.5), ymax), ymin)
+ for j = p1,p2,dir do
+ line[n] = {i, j}
+ n = n+1
+ end
+ end
+ twolines[pstr] = line
+ return line
+end
+
+local threelines = {}
+function vector.threeline(x, y, z)
+ local pstr = x.." "..y.." "..z
+ local line = threelines[pstr]
+ if line then
+ return line
+ end
+ if x ~= math.floor(x) then
+ print("[technic] INFO: The position used for vector.threeline isn't round.")
+ end
+ local two_line = vector.twoline(x, y)
+ line = {}
+ local n = 1
+ local zmin, zmax = 0, z
+ if z < 0 then
+ zmin, zmax = zmax, zmin
+ end
+ local m = z/math.hypot(x, y)
+ local dir = 1
+ if m < 0 then
+ dir = -dir
+ end
+ for _,i in ipairs(two_line) do
+ local px, py = unpack(i)
+ local ph = math.hypot(px, py)
+ local z1 = math.max(math.min(math.floor((ph-0.5)*m+0.5), zmax), zmin)
+ local z2 = math.max(math.min(math.floor((ph+0.5)*m+0.5), zmax), zmin)
+ for pz = z1,z2,dir do
+ line[n] = {px, py, pz}
+ n = n+1
+ end
+ end
+ threelines[pstr] = line
+ return line
+end
+
+function vector.line(pos, dir, range)
+ if range then --dir = pos2
+ dir = vector.round(vector.multiply(dir, range))
+ else
+ dir = vector.subtract(dir, pos)
+ end
+ local line,n = {},1
+ for _,i in ipairs(vector.threeline(dir.x, dir.y, dir.z)) do
+ line[n] = {x=pos.x+i[1], y=pos.y+i[2], z=pos.z+i[3]}
+ n = n+1
+ end
+ return line
+end