update mining lasers
authorHybridDog <adresse_test@t-online.de>
Tue, 16 Sep 2014 13:36:13 +0000 (15:36 +0200)
committerShadowNinja <shadowninja@minetest.net>
Tue, 16 Sep 2014 19:23:46 +0000 (15:23 -0400)
technic/depends.txt
technic/tools/mining_lasers.lua
technic/tools/vector_line.lua [new file with mode: 0644]

index c2671c5fdce7220bd5e6c87196894dcabfd41307..746fe3426eb1156409b2ec0c4f85fff7ed23aa36 100644 (file)
@@ -5,3 +5,4 @@ bucket?
 mesecons_mvps?
 intllib?
 unified_inventory?
+vector_extras?
index a6c8682de3d59c1496486c59f6380e92ab46decd..5c8d1e4dec818e0846fb72e94f6f2105db0f58f8 100644 (file)
@@ -1,6 +1,3 @@
-
-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},
@@ -8,9 +5,6 @@ local mining_lasers_list = {
        {"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({
@@ -38,64 +32,35 @@ 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
@@ -103,62 +68,28 @@ local function laser_node(pos, player)
        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
 
 
diff --git a/technic/tools/vector_line.lua b/technic/tools/vector_line.lua
new file mode 100644 (file)
index 0000000..950c93b
--- /dev/null
@@ -0,0 +1,83 @@
+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