Vanessa Ezekowitz
2014-07-23 29c7ff5228864bcf5456f391b122c9eb477c754b
commit | author | age
ee0765 1 -- The enriched uranium rod driven EU generator.
S 2 -- A very large and advanced machine providing vast amounts of power.
30adc3 3 -- Very efficient but also expensive to run as it needs uranium. (10000EU 86400 ticks (one week))
ee0765 4 -- Provides HV EUs that can be down converted as needed.
S 5 --
6 -- The nuclear reactor core needs water and a protective shield to work.
7 -- This is checked now and then and if the machine is tampered with... BOOM!
8
9 local burn_ticks   = 7 * 24 * 60 * 60       -- (seconds).
10 local power_supply = 100000                 -- EUs
11 local fuel_type    = "technic:uranium_fuel" -- The reactor burns this stuff
12
be2f30 13 local S = technic.getter
ee0765 14
S 15 -- FIXME: recipe must make more sense like a rod recepticle, steam chamber, HV generator?
16 minetest.register_craft({
17     output = 'technic:hv_nuclear_reactor_core',
18     recipe = {
5e4a87 19         {'technic:carbon_plate',          'default:obsidian_glass', 'technic:carbon_plate'},
Z 20         {'technic:composite_plate',       'technic:machine_casing', 'technic:composite_plate'},
21         {'technic:stainless_steel_ingot',      'technic:hv_cable0', 'technic:stainless_steel_ingot'},
ee0765 22     }
S 23 })
24
25 local generator_formspec =
26     "invsize[8,9;]"..
be2f30 27     "label[0,0;"..S("Nuclear Reactor Rod Compartment").."]"..
ee0765 28     "list[current_name;src;2,1;3,2;]"..
S 29     "list[current_player;main;0,5;8,4;]"
30
31 -- "Boxy sphere"
32 local nodebox = {
33     { -0.353, -0.353, -0.353, 0.353, 0.353, 0.353 }, -- Box
34     { -0.495, -0.064, -0.064, 0.495, 0.064, 0.064 }, -- Circle +-x
35     { -0.483, -0.128, -0.128, 0.483, 0.128, 0.128 },
36     { -0.462, -0.191, -0.191, 0.462, 0.191, 0.191 },
37     { -0.433, -0.249, -0.249, 0.433, 0.249, 0.249 },
38     { -0.397, -0.303, -0.303, 0.397, 0.303, 0.303 },
39     { -0.305, -0.396, -0.305, 0.305, 0.396, 0.305 }, -- Circle +-y
40     { -0.250, -0.432, -0.250, 0.250, 0.432, 0.250 },
41     { -0.191, -0.461, -0.191, 0.191, 0.461, 0.191 },
42     { -0.130, -0.482, -0.130, 0.130, 0.482, 0.130 },
43     { -0.066, -0.495, -0.066, 0.066, 0.495, 0.066 },
44     { -0.064, -0.064, -0.495, 0.064, 0.064, 0.495 }, -- Circle +-z
45     { -0.128, -0.128, -0.483, 0.128, 0.128, 0.483 },
46     { -0.191, -0.191, -0.462, 0.191, 0.191, 0.462 },
47     { -0.249, -0.249, -0.433, 0.249, 0.249, 0.433 },
48     { -0.303, -0.303, -0.397, 0.303, 0.303, 0.397 },
49 }
50
51 local check_reactor_structure = function(pos)
52     -- The reactor consists of a 9x9x9 cube structure
53     -- A cross section through the middle:
54     --  CCCC CCCC
55     --  CBBB BBBC
56     --  CBSS SSBC
57     --  CBSWWWSBC
58     --  CBSW#WSBC
59     --  CBSW|WSBC
60     --  CBSS|SSBC
61     --  CBBB|BBBC
62     --  CCCC|CCCC
63     --  C = Concrete, B = Blast resistant concrete, S = Stainless Steel,
64     --  W = water node, # = reactor core, | = HV cable
65     --  The man-hole and the HV cable is only in the middle
66     --  The man-hole is optional
67
68     local vm = VoxelManip()
69     local pos1 = vector.subtract(pos, 4)
70     local pos2 = vector.add(pos, 4)
71     local MinEdge, MaxEdge = vm:read_from_map(pos1, pos2)
72     local data = vm:get_data()
73     local area = VoxelArea:new({MinEdge=MinEdge, MaxEdge=MaxEdge})
74
75     local c_concrete = minetest.get_content_id("technic:concrete")
76     local c_blast_concrete = minetest.get_content_id("technic:blast_resistant_concrete")
77     local c_stainless_steel = minetest.get_content_id("technic:stainless_steel_block")
78     local c_water_source = minetest.get_content_id("default:water_source")
79     local c_water_flowing = minetest.get_content_id("default:water_flowing")
80
81     local concretelayer, blastlayer, steellayer, waterlayer = 0, 0, 0, 0
82
83     for z = pos1.z, pos2.z do
84     for y = pos1.y, pos2.y do
85     for x = pos1.x, pos2.x do
86         -- If the position is in the outer layer
87         if x == pos1.x or x == pos2.x or
88            y == pos1.y or y == pos2.y or
89            z == pos1.z or z == pos2.z then
90             if data[area:index(x, y, z)] == c_concrete then
91                 concretelayer = concretelayer + 1
92             end
93         elseif x == pos1.x+1 or x == pos2.x-1 or
94            y == pos1.y+1 or y == pos2.y-1 or
95            z == pos1.z+1 or z == pos2.z-1 then
96             if data[area:index(x, y, z)] == c_blast_concrete then
97                 blastlayer = blastlayer + 1
98             end
99         elseif x == pos1.x+2 or x == pos2.x-2 or
100            y == pos1.y+2 or y == pos2.y-2 or
101            z == pos1.z+2 or z == pos2.z-2 then
102             if data[area:index(x, y, z)] == c_stainless_steel then
103                 steellayer = steellayer + 1
104             end
105         elseif x == pos1.x+3 or x == pos2.x-3 or
106            y == pos1.y+3 or y == pos2.y-3 or
107            z == pos1.z+3 or z == pos2.z-3 then
108                local cid = data[area:index(x, y, z)]
109             if cid == c_water_source or cid == c_water_flowing then
110                 waterlayer = waterlayer + 1
111             end
112         end
113     end
114     end
115     end
116     if waterlayer >= 25 and
117        steellayer >= 96 and
118        blastlayer >= 216 and
119        concretelayer >= 384 then
120         return true
121     end
122 end
123
124 local explode_reactor = function(pos)
125     print("A reactor exploded at "..minetest.pos_to_string(pos))
126 end
127
128 local function damage_nearby_players(pos)
129     local objs = minetest.get_objects_inside_radius(pos, 4)
130     for _, o in pairs(objs) do
131         if o:is_player() then
132             o:set_hp(math.max(o:get_hp() - 2, 0))
133         end
134     end
135 end
136
563a4c 137 local run = function(pos, node)
N 138     local meta = minetest.get_meta(pos)
139     local machine_name = S("Nuclear %s Generator Core"):format("HV")
140     local burn_time = meta:get_int("burn_time") or 0
ee0765 141
563a4c 142     if burn_time >= burn_ticks or burn_time == 0 then
N 143         local inv = meta:get_inventory()
144         if not inv:is_empty("src") then 
145             local srclist = inv:get_list("src")
146             local correct_fuel_count = 0
147             for _, srcstack in pairs(srclist) do
148                 if srcstack then
149                     if  srcstack:get_name() == fuel_type then
150                         correct_fuel_count = correct_fuel_count + 1
ee0765 151                     end
S 152                 end
563a4c 153             end
N 154             -- Check that the reactor is complete as well
155             -- as the correct number of correct fuel
156             if correct_fuel_count == 6 and
157                check_reactor_structure(pos) then
158                 meta:set_int("burn_time", 1)
159                 technic.swap_node(pos, "technic:hv_nuclear_reactor_core_active") 
160                 meta:set_int("HV_EU_supply", power_supply)
161                 for idx, srcstack in pairs(srclist) do
162                     srcstack:take_item()
163                     inv:set_stack("src", idx, srcstack)
ee0765 164                 end
563a4c 165                 return
ee0765 166             end
S 167         end
563a4c 168         meta:set_int("HV_EU_supply", 0)
N 169         meta:set_int("burn_time", 0)
170         meta:set_string("infotext", S("%s Idle"):format(machine_name))
171         technic.swap_node(pos, "technic:hv_nuclear_reactor_core")
172     elseif burn_time > 0 then
173         damage_nearby_players(pos)
174         if not check_reactor_structure(pos) then
175             explode_reactor(pos)
176         end
177         burn_time = burn_time + 1
178         meta:set_int("burn_time", burn_time)
179         local percent = math.floor(burn_time / burn_ticks * 100)
180         meta:set_string("infotext", machine_name.." ("..percent.."%)")
181         meta:set_int("HV_EU_supply", power_supply)
ee0765 182     end
563a4c 183 end
N 184
185 minetest.register_node("technic:hv_nuclear_reactor_core", {
186     description = S("Nuclear %s Generator Core"):format("HV"),
187     tiles = {"technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
188              "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
189              "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png"},
190     groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1},
191     legacy_facedir_simple = true,
192     sounds = default.node_sound_wood_defaults(),
193     drawtype="nodebox",
194     paramtype = "light",
195     stack_max = 1,
196     node_box = {
197         type = "fixed",
198         fixed = nodebox
199     },
200     on_construct = function(pos)
201         local meta = minetest.get_meta(pos)
202         meta:set_string("infotext", S("Nuclear %s Generator Core"):format("HV"))
203         meta:set_int("HV_EU_supply", 0)
204         -- Signal to the switching station that this device burns some
205         -- sort of fuel and needs special handling
206         meta:set_int("HV_EU_from_fuel", 1)
207         meta:set_int("burn_time", 0)
208         meta:set_string("formspec", generator_formspec)
209         local inv = meta:get_inventory()
210         inv:set_size("src", 6)
211     end,    
212     can_dig = technic.machine_can_dig,
213     allow_metadata_inventory_put = technic.machine_inventory_put,
214     allow_metadata_inventory_take = technic.machine_inventory_take,
215     allow_metadata_inventory_move = technic.machine_inventory_move,
216     technic_run = run,
217 })
218
219 minetest.register_node("technic:hv_nuclear_reactor_core_active", {
220     tiles = {"technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
221              "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
222          "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png"},
223     groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1, not_in_creative_inventory=1},
224     legacy_facedir_simple = true,
225     sounds = default.node_sound_wood_defaults(),
226     drop="technic:hv_nuclear_reactor_core",
227     drawtype="nodebox",
228     light_source = 15,
229     paramtype = "light",
230     node_box = {
231         type = "fixed",
232         fixed = nodebox
233     },
234     can_dig = technic.machine_can_dig,
235     allow_metadata_inventory_put = technic.machine_inventory_put,
236     allow_metadata_inventory_take = technic.machine_inventory_take,
237     allow_metadata_inventory_move = technic.machine_inventory_move,
238     technic_run = run,
1c617f 239     technic_on_disable = function(pos, node)
N 240         local timer = minetest.get_node_timer(pos)
241             timer:start(1)
242         end,
243     on_timer = function(pos, node)
244         local meta = minetest.get_meta(pos)
245         
246         -- Connected back?
247         if meta:get_int("HV_EU_timeout") > 0 then return end    
248         
249         local burn_time = meta:get_int("burn_time") or 0
250
251         if burn_time >= burn_ticks or burn_time == 0 then
252             meta:set_int("HV_EU_supply", 0)
253             meta:set_int("burn_time", 0)
254             technic.swap_node(pos, "technic:hv_nuclear_reactor_core")
255             return
256         end
257         
258         meta:set_int("burn_time", burn_time + 1)
259         local timer = minetest.get_node_timer(pos)
260             timer:start(1)
261     end,
ee0765 262 })
S 263
264 technic.register_machine("HV", "technic:hv_nuclear_reactor_core",        technic.producer)
265 technic.register_machine("HV", "technic:hv_nuclear_reactor_core_active", technic.producer)
266