Zefram
2014-07-07 5e4a87b92599aa0fc9a56081209c930d08a2c3bd
commit | author | age
f90915 1
H 2 local r_corr = 0.25 -- Remove a bit more nodes (if shooting diagonal) to let it look like a hole (sth like antialiasing)
3
4 local mining_lasers_list = {
a6dae8 5 --    {<num>, <range of the laser shots>, <max_charge>, <charge_per_shot>},
BM 6     {"1", 7, 50000, 1000},
7     {"2", 14, 200000, 2000},
8     {"3", 21, 650000, 3000},
f90915 9 }
H 10
11 local f_1 = 0.5 - r_corr
12 local f_2 = 0.5 + r_corr
13
14 local S = technic.getter
15
2d7c1d 16 minetest.register_craft({
S 17     output = 'technic:laser_mk1',
18     recipe = {
5e4a87 19         {'default:diamond', 'technic:brass_ingot',        'default:obsidian_glass'},
Z 20         {'',                'technic:brass_ingot',        'technic:red_energy_crystal'},
68b7bc 21         {'',                '',                           'default:copper_ingot'},
49052d 22     }
BM 23 })
24 minetest.register_craft({
25     output = 'technic:laser_mk2',
26     recipe = {
68b7bc 27         {'default:diamond', 'technic:carbon_steel_ingot', 'technic:laser_mk1'},
Z 28         {'',                'technic:carbon_steel_ingot', 'technic:green_energy_crystal'},
29         {'',                '',                           'default:copper_ingot'},
49052d 30     }
BM 31 })
32 minetest.register_craft({
33     output = 'technic:laser_mk3',
34     recipe = {
68b7bc 35         {'default:diamond', 'technic:carbon_steel_ingot', 'technic:laser_mk2'},
Z 36         {'',                'technic:carbon_steel_ingot', 'technic:blue_energy_crystal'},
37         {'',                '',                           'default:copper_ingot'},
2d7c1d 38     }
S 39 })
40
41
f90915 42 local function get_used_dir(dir)
H 43     local abs_dir = {x = math.abs(dir.x),
44             y = math.abs(dir.y),
45             z = math.abs(dir.z)}
46     local dir_max = math.max(abs_dir.x, abs_dir.y, abs_dir.z)
47     if dir_max == abs_dir.x then
48         local tab = {"x", {x = 1, y = dir.y / dir.x, z = dir.z / dir.x}}
49         if dir.x >= 0 then
50             tab[3] = "+"
51         end
52         return tab
53     end
54     if dir_max == abs_dir.y then
55         local tab = {"y", {x = dir.x / dir.y, y = 1, z = dir.z / dir.y}}
56         if dir.y >= 0 then
57             tab[3] = "+"
58         end
59         return tab
60     end
61     local tab = {"z", {x = dir.x / dir.z, y = dir.y / dir.z, z = 1}}
62     if dir.z >= 0 then
63         tab[3] = "+"
64     end
65     return tab
66 end
67
68 local function node_tab(z, d)
69     local n1 = math.floor(z * d + f_1)
70     local n2 = math.floor(z * d + f_2)
71     if n1 == n2 then
72         return {n1}
73     end
74     return {n1, n2}
75 end
76
77 local function laser_node(pos, player)
78     local node = minetest.get_node(pos)
79     if node.name == "air"
80     or node.name == "ignore"
81     or node.name == "default:lava_source"
82     or node.name == "default:lava_flowing" then
83         return
84     end
45e1f0 85     if minetest.is_protected(pos, player:get_player_name()) then
A 86         minetest.record_protection_violation(pos, player:get_player_name())
87         return
88     end
f90915 89     if node.name == "default:water_source"
H 90     or node.name == "default:water_flowing" then
91         minetest.remove_node(pos)
92         minetest.add_particle(pos,
93                 {x=0, y=2, z=0},
94                 {x=0, y=-1, z=0},
95                 1.5,
96                 8,
97                 false,
98                 "smoke_puff.png")
99         return
100     end
101     if player then
102         minetest.node_dig(pos, node, player)
103     end
104 end
105
106 local function laser_nodes(pos, dir, player, range)
107     local t_dir = get_used_dir(dir)
108     local dir_typ = t_dir[1]
109     if t_dir[3] == "+" then
ecb53e 110         f_tab = {1, range}
f90915 111     else
ecb53e 112         f_tab = {-range, -1}
f90915 113     end
H 114     local d_ch = t_dir[2]
115     if dir_typ == "x" then
116         for d = f_tab[1],f_tab[2],1 do
117             local x = d
118             local ytab = node_tab(d_ch.y, d)
119             local ztab = node_tab(d_ch.z, d)
120             for _, y in pairs(ytab) do
121                 for _, z in pairs(ztab) do
122                     laser_node({x = pos.x + x, y = pos.y + y, z = pos.z + z}, player)
123                 end
124             end
125         end
126         return
127     end
128     if dir_typ == "y" then
129         for d = f_tab[1], f_tab[2] do
130             local xtab = node_tab(d_ch.x, d)
131             local y = d
132             local ztab = node_tab(d_ch.z, d)
133             for _, x in pairs(xtab) do
134                 for _, z in pairs(ztab) do
135                     laser_node({x = pos.x + x, y = pos.y + y, z = pos.z + z}, player)
136                 end
137             end
138         end
139         return
140     end
141     for d = f_tab[1], f_tab[2] do
142         local xtab = node_tab(d_ch.x, d)
143         local ytab = node_tab(d_ch.y, d)
144         local z = d
145         for _, x in pairs(xtab) do
146             for _, y in pairs(ytab) do
147                 laser_node({x = pos.x + x, y = pos.y + y, z = pos.z + z}, player)
148             end
149         end
150     end
151 end
152
153 local function laser_shoot(player, range, particle_texture, sound)
154     local playerpos = player:getpos()
155     local dir = player:get_look_dir()
156
157     local startpos = {x = playerpos.x, y = playerpos.y + 1.6, z = playerpos.z}
158     local mult_dir = vector.multiply(dir, 50)
159     minetest.add_particle(startpos, dir, mult_dir, range / 11, 1, false, particle_texture)
160     laser_nodes(vector.round(startpos), dir, player, range)
161     minetest.sound_play(sound, {pos = playerpos, gain = 1.0, max_hear_distance = range})
162 end
163
164
165 for _, m in pairs(mining_lasers_list) do
166     technic.register_power_tool("technic:laser_mk"..m[1], m[3])
167     minetest.register_tool("technic:laser_mk"..m[1], {
168         description = S("Mining Laser Mk%d"):format(m[1]),
169         inventory_image = "technic_mining_laser_mk"..m[1]..".png",
170         stack_max = 1,
99fd5d 171         wear_represents = "technic_RE_charge",
00d7c9 172         on_refill = technic.refill_RE_charge,
f90915 173         on_use = function(itemstack, user)
5cf765 174             local meta = minetest.deserialize(itemstack:get_metadata())
f90915 175             if not meta or not meta.charge then
H 176                 return
177             end
a6dae8 178
BM 179             -- If there's enough charge left, fire the laser
180             if meta.charge >= m[4] then
181                 meta.charge = meta.charge - m[4]
f90915 182                 laser_shoot(user, m[2], "technic_laser_beam_mk"..m[1]..".png", "technic_laser_mk"..m[1])
H 183                 technic.set_RE_wear(itemstack, meta.charge, m[3])
5cf765 184                 itemstack:set_metadata(minetest.serialize(meta))
f90915 185             end
H 186             return itemstack
187         end,
188     })
189 end
190