commit | author | age
|
30a37a
|
1 |
--- Forcefield generator. |
S |
2 |
-- @author ShadowNinja |
ee0765
|
3 |
-- |
S |
4 |
-- Forcefields are powerful barriers but they consume huge amounts of power. |
30a37a
|
5 |
-- The forcefield Generator is an HV machine. |
ee0765
|
6 |
|
S |
7 |
-- How expensive is the generator? |
|
8 |
-- Leaves room for upgrades lowering the power drain? |
ef8bb3
|
9 |
local digilines_path = minetest.get_modpath("digilines") |
D |
10 |
|
ee0765
|
11 |
local forcefield_power_drain = 10 |
S |
12 |
|
be2f30
|
13 |
local S = technic.getter |
S |
14 |
|
54004f
|
15 |
local cable_entry = "^technic_cable_connection_overlay.png" |
VE |
16 |
|
ee0765
|
17 |
minetest.register_craft({ |
30a37a
|
18 |
output = "technic:forcefield_emitter_off", |
ee0765
|
19 |
recipe = { |
44cb8d
|
20 |
{"default:mese", "basic_materials:motor", "default:mese" }, |
51f9df
|
21 |
{"technic:deployer_off", "technic:machine_casing", "technic:deployer_off"}, |
D |
22 |
{"default:mese", "technic:hv_cable", "default:mese" }, |
ee0765
|
23 |
} |
S |
24 |
}) |
30a37a
|
25 |
|
S |
26 |
|
|
27 |
local replaceable_cids = {} |
|
28 |
|
|
29 |
minetest.after(0, function() |
|
30 |
for name, ndef in pairs(minetest.registered_nodes) do |
|
31 |
if ndef.buildable_to == true and name ~= "ignore" then |
|
32 |
replaceable_cids[minetest.get_content_id(name)] = true |
|
33 |
end |
|
34 |
end |
|
35 |
end) |
ee0765
|
36 |
|
S |
37 |
|
|
38 |
-- Idea: Let forcefields have different colors by upgrade slot. |
|
39 |
-- Idea: Let forcefields add up by detecting if one hits another. |
|
40 |
-- ___ __ |
|
41 |
-- / \/ \ |
|
42 |
-- | | |
|
43 |
-- \___/\___/ |
|
44 |
|
aa82fa
|
45 |
local function update_forcefield(pos, meta, active) |
830de4
|
46 |
local shape = meta:get_int("shape") |
Z |
47 |
local range = meta:get_int("range") |
ee0765
|
48 |
local vm = VoxelManip() |
30a37a
|
49 |
local MinEdge, MaxEdge = vm:read_from_map(vector.subtract(pos, range), |
S |
50 |
vector.add(pos, range)) |
ee0765
|
51 |
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge}) |
S |
52 |
local data = vm:get_data() |
|
53 |
|
30a37a
|
54 |
local c_air = minetest.get_content_id("air") |
ee0765
|
55 |
local c_field = minetest.get_content_id("technic:forcefield") |
S |
56 |
|
30a37a
|
57 |
for z = -range, range do |
S |
58 |
for y = -range, range do |
|
59 |
local vi = area:index(pos.x + (-range), pos.y + y, pos.z + z) |
|
60 |
for x = -range, range do |
830de4
|
61 |
local relevant |
Z |
62 |
if shape == 0 then |
30a37a
|
63 |
local squared = x * x + y * y + z * z |
830de4
|
64 |
relevant = |
30a37a
|
65 |
squared <= range * range + range and |
S |
66 |
squared >= (range - 1) * (range - 1) + (range - 1) |
830de4
|
67 |
else |
Z |
68 |
relevant = |
|
69 |
x == -range or x == range or |
|
70 |
y == -range or y == range or |
|
71 |
z == -range or z == range |
|
72 |
end |
|
73 |
if relevant then |
30a37a
|
74 |
local cid = data[vi] |
S |
75 |
if active and replaceable_cids[cid] then |
ee0765
|
76 |
data[vi] = c_field |
30a37a
|
77 |
elseif not active and cid == c_field then |
ee0765
|
78 |
data[vi] = c_air |
S |
79 |
end |
|
80 |
end |
|
81 |
vi = vi + 1 |
|
82 |
end |
|
83 |
end |
|
84 |
end |
|
85 |
|
|
86 |
vm:set_data(data) |
|
87 |
vm:update_liquids() |
|
88 |
vm:write_to_map() |
|
89 |
end |
|
90 |
|
2d6f34
|
91 |
local function set_forcefield_formspec(meta) |
ef8bb3
|
92 |
local formspec |
D |
93 |
if digilines_path then |
|
94 |
formspec = "size[5,3.25]".. |
|
95 |
"field[0.3,3;5,1;channel;Digiline Channel;"..meta:get_string("channel").."]" |
|
96 |
else |
|
97 |
formspec = "size[5,2.25]" |
|
98 |
end |
|
99 |
formspec = formspec.. |
830de4
|
100 |
"field[0.3,0.5;2,1;range;"..S("Range")..";"..meta:get_int("range").."]" |
cca72f
|
101 |
-- The names for these toggle buttons are explicit about which |
Z |
102 |
-- state they'll switch to, so that multiple presses (arising |
|
103 |
-- from the ambiguity between lag and a missed press) only make |
|
104 |
-- the single change that the user expects. |
830de4
|
105 |
if meta:get_int("shape") == 0 then |
Z |
106 |
formspec = formspec.."button[3,0.2;2,1;shape1;"..S("Sphere").."]" |
|
107 |
else |
|
108 |
formspec = formspec.."button[3,0.2;2,1;shape0;"..S("Cube").."]" |
|
109 |
end |
6a4cb1
|
110 |
if meta:get_int("mesecon_mode") == 0 then |
cca72f
|
111 |
formspec = formspec.."button[0,1;5,1;mesecon_mode_1;"..S("Ignoring Mesecon Signal").."]" |
2d6f34
|
112 |
else |
cca72f
|
113 |
formspec = formspec.."button[0,1;5,1;mesecon_mode_0;"..S("Controlled by Mesecon Signal").."]" |
6a4cb1
|
114 |
end |
Z |
115 |
if meta:get_int("enabled") == 0 then |
cca72f
|
116 |
formspec = formspec.."button[0,1.75;5,1;enable;"..S("%s Disabled"):format(S("%s Forcefield Emitter"):format("HV")).."]" |
6a4cb1
|
117 |
else |
cca72f
|
118 |
formspec = formspec.."button[0,1.75;5,1;disable;"..S("%s Enabled"):format(S("%s Forcefield Emitter"):format("HV")).."]" |
2d6f34
|
119 |
end |
Z |
120 |
meta:set_string("formspec", formspec) |
ee0765
|
121 |
end |
S |
122 |
|
|
123 |
local forcefield_receive_fields = function(pos, formname, fields, sender) |
|
124 |
local meta = minetest.get_meta(pos) |
830de4
|
125 |
local range = nil |
2d6f34
|
126 |
if fields.range then |
830de4
|
127 |
range = tonumber(fields.range) or 0 |
2d6f34
|
128 |
-- Smallest field is 5. Anything less is asking for trouble. |
Z |
129 |
-- Largest is 20. It is a matter of pratical node handling. |
|
130 |
-- At the maximim range updating the forcefield takes about 0.2s |
|
131 |
range = math.max(range, 5) |
|
132 |
range = math.min(range, 20) |
830de4
|
133 |
if range == meta:get_int("range") then range = nil end |
ee0765
|
134 |
end |
830de4
|
135 |
if fields.shape0 or fields.shape1 or range then |
Z |
136 |
update_forcefield(pos, meta, false) |
|
137 |
end |
|
138 |
if range then meta:set_int("range", range) end |
ef8bb3
|
139 |
if fields.channel then meta:set_string("channel", fields.channel) end |
D |
140 |
if fields.shape0 then meta:set_int("shape", 0) end |
|
141 |
if fields.shape1 then meta:set_int("shape", 1) end |
|
142 |
if fields.enable then meta:set_int("enabled", 1) end |
2d6f34
|
143 |
if fields.disable then meta:set_int("enabled", 0) end |
6a4cb1
|
144 |
if fields.mesecon_mode_0 then meta:set_int("mesecon_mode", 0) end |
Z |
145 |
if fields.mesecon_mode_1 then meta:set_int("mesecon_mode", 1) end |
2d6f34
|
146 |
set_forcefield_formspec(meta) |
ee0765
|
147 |
end |
S |
148 |
|
|
149 |
local mesecons = { |
|
150 |
effector = { |
|
151 |
action_on = function(pos, node) |
6a4cb1
|
152 |
minetest.get_meta(pos):set_int("mesecon_effect", 1) |
ee0765
|
153 |
end, |
S |
154 |
action_off = function(pos, node) |
6a4cb1
|
155 |
minetest.get_meta(pos):set_int("mesecon_effect", 0) |
ee0765
|
156 |
end |
S |
157 |
} |
ef8bb3
|
158 |
} |
D |
159 |
|
|
160 |
local digiline_def = { |
|
161 |
receptor = {action = function() end}, |
|
162 |
effector = { |
|
163 |
action = function(pos, node, channel, msg) |
|
164 |
local meta = minetest.get_meta(pos) |
|
165 |
if channel ~= meta:get_string("channel") then |
|
166 |
return |
|
167 |
end |
51f9df
|
168 |
local msgt = type(msg) |
D |
169 |
if msgt == "string" then |
|
170 |
local smsg = msg:lower() |
|
171 |
msg = {} |
|
172 |
if smsg == "get" then |
|
173 |
msg.command = "get" |
|
174 |
elseif smsg == "off" then |
|
175 |
msg.command = "off" |
|
176 |
elseif smsg == "on" then |
|
177 |
msg.command = "on" |
|
178 |
elseif smsg == "toggle" then |
|
179 |
msg.command = "toggle" |
|
180 |
elseif smsg:sub(1, 5) == "range" then |
|
181 |
msg.command = "range" |
|
182 |
msg.value = tonumber(smsg:sub(7)) |
|
183 |
elseif smsg:sub(1, 5) == "shape" then |
|
184 |
msg.command = "shape" |
|
185 |
msg.value = smsg:sub(7):lower() |
|
186 |
msg.value = tonumber(msg.value) or msg.value |
|
187 |
end |
|
188 |
elseif msgt ~= "table" then |
|
189 |
return |
|
190 |
end |
|
191 |
if msg.command == "get" then |
ef8bb3
|
192 |
digilines.receptor_send(pos, digilines.rules.default, channel, { |
D |
193 |
enabled = meta:get_int("enabled"), |
|
194 |
range = meta:get_int("range"), |
|
195 |
shape = meta:get_int("shape") |
|
196 |
}) |
|
197 |
return |
51f9df
|
198 |
elseif msg.command == "off" then |
ef8bb3
|
199 |
meta:set_int("enabled", 0) |
51f9df
|
200 |
elseif msg.command == "on" then |
ef8bb3
|
201 |
meta:set_int("enabled", 1) |
51f9df
|
202 |
elseif msg.command == "toggle" then |
ef8bb3
|
203 |
local onn = meta:get_int("enabled") |
D |
204 |
onn = 1-onn -- Mirror onn with pivot 0.5, so switch between 1 and 0. |
|
205 |
meta:set_int("enabled", onn) |
51f9df
|
206 |
elseif msg.command == "range" then |
D |
207 |
if type(msg.value) ~= "number" then |
ef8bb3
|
208 |
return |
D |
209 |
end |
51f9df
|
210 |
msg.value = math.max(msg.value, 5) |
D |
211 |
msg.value = math.min(msg.value, 20) |
ef8bb3
|
212 |
update_forcefield(pos, meta, false) |
51f9df
|
213 |
meta:set_int("range", msg.value) |
D |
214 |
elseif msg.command == "shape" then |
|
215 |
local valuet = type(msg.value) |
|
216 |
if valuet == "string" then |
|
217 |
if msg.value == "sphere" then |
|
218 |
msg.value = 0 |
|
219 |
elseif msg.value == "cube" then |
|
220 |
msg.value = 1 |
|
221 |
end |
|
222 |
elseif valuet ~= "number" then |
|
223 |
return |
ef8bb3
|
224 |
end |
51f9df
|
225 |
if not msg.value then |
ef8bb3
|
226 |
return |
D |
227 |
end |
|
228 |
update_forcefield(pos, meta, false) |
51f9df
|
229 |
meta:set_int("shape", msg.value) |
ef8bb3
|
230 |
else |
D |
231 |
return |
|
232 |
end |
|
233 |
set_forcefield_formspec(meta) |
|
234 |
end |
|
235 |
}, |
ee0765
|
236 |
} |
S |
237 |
|
30a37a
|
238 |
local function run(pos, node) |
563a4c
|
239 |
local meta = minetest.get_meta(pos) |
N |
240 |
local eu_input = meta:get_int("HV_EU_input") |
51f9df
|
241 |
local enabled = meta:get_int("enabled") ~= 0 and |
D |
242 |
(meta:get_int("mesecon_mode") == 0 or meta:get_int("mesecon_effect") ~= 0) |
563a4c
|
243 |
local machine_name = S("%s Forcefield Emitter"):format("HV") |
N |
244 |
|
830de4
|
245 |
local range = meta:get_int("range") |
Z |
246 |
local power_requirement |
|
247 |
if meta:get_int("shape") == 0 then |
|
248 |
power_requirement = math.floor(4 * math.pi * range * range) |
|
249 |
else |
|
250 |
power_requirement = 24 * range * range |
|
251 |
end |
|
252 |
power_requirement = power_requirement * forcefield_power_drain |
563a4c
|
253 |
|
6a4cb1
|
254 |
if not enabled then |
563a4c
|
255 |
if node.name == "technic:forcefield_emitter_on" then |
830de4
|
256 |
update_forcefield(pos, meta, false) |
563a4c
|
257 |
technic.swap_node(pos, "technic:forcefield_emitter_off") |
N |
258 |
meta:set_string("infotext", S("%s Disabled"):format(machine_name)) |
|
259 |
end |
849526
|
260 |
meta:set_int("HV_EU_demand", 0) |
Z |
261 |
return |
|
262 |
end |
|
263 |
meta:set_int("HV_EU_demand", power_requirement) |
|
264 |
if eu_input < power_requirement then |
563a4c
|
265 |
meta:set_string("infotext", S("%s Unpowered"):format(machine_name)) |
N |
266 |
if node.name == "technic:forcefield_emitter_on" then |
830de4
|
267 |
update_forcefield(pos, meta, false) |
563a4c
|
268 |
technic.swap_node(pos, "technic:forcefield_emitter_off") |
N |
269 |
end |
|
270 |
elseif eu_input >= power_requirement then |
|
271 |
if node.name == "technic:forcefield_emitter_off" then |
|
272 |
technic.swap_node(pos, "technic:forcefield_emitter_on") |
|
273 |
meta:set_string("infotext", S("%s Active"):format(machine_name)) |
|
274 |
end |
aa82fa
|
275 |
update_forcefield(pos, meta, true) |
563a4c
|
276 |
end |
N |
277 |
end |
|
278 |
|
ee0765
|
279 |
minetest.register_node("technic:forcefield_emitter_off", { |
7c4b70
|
280 |
description = S("%s Forcefield Emitter"):format("HV"), |
54004f
|
281 |
tiles = { |
VE |
282 |
"technic_forcefield_emitter_off.png", |
|
283 |
"technic_machine_bottom.png"..cable_entry, |
|
284 |
"technic_forcefield_emitter_off.png", |
|
285 |
"technic_forcefield_emitter_off.png", |
|
286 |
"technic_forcefield_emitter_off.png", |
|
287 |
"technic_forcefield_emitter_off.png" |
|
288 |
}, |
83c649
|
289 |
groups = {cracky = 1, technic_machine = 1, technic_hv = 1}, |
ee0765
|
290 |
on_receive_fields = forcefield_receive_fields, |
S |
291 |
on_construct = function(pos) |
|
292 |
local meta = minetest.get_meta(pos) |
|
293 |
meta:set_int("HV_EU_input", 0) |
|
294 |
meta:set_int("HV_EU_demand", 0) |
|
295 |
meta:set_int("range", 10) |
|
296 |
meta:set_int("enabled", 0) |
6a4cb1
|
297 |
meta:set_int("mesecon_mode", 0) |
Z |
298 |
meta:set_int("mesecon_effect", 0) |
ef8bb3
|
299 |
if digilines_path then |
D |
300 |
meta:set_string("channel", "forcefield"..minetest.pos_to_string(pos)) |
|
301 |
end |
7c4b70
|
302 |
meta:set_string("infotext", S("%s Forcefield Emitter"):format("HV")) |
2d6f34
|
303 |
set_forcefield_formspec(meta) |
ee0765
|
304 |
end, |
563a4c
|
305 |
mesecons = mesecons, |
ef8bb3
|
306 |
digiline = digiline_def, |
563a4c
|
307 |
technic_run = run, |
ee0765
|
308 |
}) |
S |
309 |
|
|
310 |
minetest.register_node("technic:forcefield_emitter_on", { |
7c4b70
|
311 |
description = S("%s Forcefield Emitter"):format("HV"), |
54004f
|
312 |
tiles = { |
VE |
313 |
"technic_forcefield_emitter_on.png", |
|
314 |
"technic_machine_bottom.png"..cable_entry, |
|
315 |
"technic_forcefield_emitter_on.png", |
|
316 |
"technic_forcefield_emitter_on.png", |
|
317 |
"technic_forcefield_emitter_on.png", |
|
318 |
"technic_forcefield_emitter_on.png" |
|
319 |
}, |
83c649
|
320 |
groups = {cracky = 1, technic_machine = 1, technic_hv = 1, |
S |
321 |
not_in_creative_inventory=1}, |
ee0765
|
322 |
drop = "technic:forcefield_emitter_off", |
S |
323 |
on_receive_fields = forcefield_receive_fields, |
|
324 |
on_destruct = function(pos) |
|
325 |
local meta = minetest.get_meta(pos) |
830de4
|
326 |
update_forcefield(pos, meta, false) |
ee0765
|
327 |
end, |
563a4c
|
328 |
mesecons = mesecons, |
ef8bb3
|
329 |
digiline = digiline_def, |
563a4c
|
330 |
technic_run = run, |
2a7ee1
|
331 |
technic_on_disable = function (pos, node) |
Z |
332 |
local meta = minetest.get_meta(pos) |
830de4
|
333 |
update_forcefield(pos, meta, false) |
2a7ee1
|
334 |
technic.swap_node(pos, "technic:forcefield_emitter_off") |
Z |
335 |
end, |
51f9df
|
336 |
on_blast = function(pos, intensity) |
D |
337 |
minetest.dig_node(pos) |
|
338 |
return {"technic:forcefield_emitter_off"} |
|
339 |
end, |
ee0765
|
340 |
}) |
S |
341 |
|
|
342 |
minetest.register_node("technic:forcefield", { |
7c4b70
|
343 |
description = S("%s Forcefield"):format("HV"), |
ee0765
|
344 |
sunlight_propagates = true, |
S |
345 |
drawtype = "glasslike", |
45919b
|
346 |
groups = {not_in_creative_inventory=1}, |
ee0765
|
347 |
paramtype = "light", |
51f9df
|
348 |
light_source = default.LIGHT_MAX, |
45919b
|
349 |
diggable = false, |
ee0765
|
350 |
drop = '', |
S |
351 |
tiles = {{ |
|
352 |
name = "technic_forcefield_animated.png", |
|
353 |
animation = { |
|
354 |
type = "vertical_frames", |
|
355 |
aspect_w = 16, |
|
356 |
aspect_h = 16, |
|
357 |
length = 1.0, |
|
358 |
}, |
|
359 |
}}, |
51f9df
|
360 |
on_blast = function(pos, intensity) |
D |
361 |
end, |
ee0765
|
362 |
}) |
S |
363 |
|
|
364 |
|
|
365 |
if minetest.get_modpath("mesecons_mvps") then |
8da4d0
|
366 |
mesecon.register_mvps_stopper("technic:forcefield") |
ee0765
|
367 |
end |
S |
368 |
|
|
369 |
technic.register_machine("HV", "technic:forcefield_emitter_on", technic.receiver) |
|
370 |
technic.register_machine("HV", "technic:forcefield_emitter_off", technic.receiver) |
|
371 |
|