From 5e9573d9b7687a52235c105d12de89a974e3e68b Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Sun, 16 Sep 2018 13:41:29 +0300 Subject: [PATCH] More work on fusion reactor.. --- elepower_machines/machines/electrolyzer.lua | 4 +- elepower_nuclear/fluids.lua | 124 ++++++- elepower_nuclear/machines/fusion_reactor.lua | 338 +++++++++++++++++- elepower_nuclear/machines/heat_exchanger.lua | 46 ++- .../textures/elenuclear_heavy_water.png | Bin 522 -> 597 bytes ...lenuclear_heavy_water_flowing_animated.png | Bin 0 -> 4491 bytes ...elenuclear_heavy_water_source_animated.png | Bin 0 -> 3463 bytes .../textures/elenuclear_helium_plasma.png | Bin 0 -> 1527 bytes 8 files changed, 477 insertions(+), 35 deletions(-) create mode 100644 elepower_nuclear/textures/elenuclear_heavy_water_flowing_animated.png create mode 100644 elepower_nuclear/textures/elenuclear_heavy_water_source_animated.png create mode 100644 elepower_nuclear/textures/elenuclear_helium_plasma.png diff --git a/elepower_machines/machines/electrolyzer.lua b/elepower_machines/machines/electrolyzer.lua index dc4a08f..b79d115 100644 --- a/elepower_machines/machines/electrolyzer.lua +++ b/elepower_machines/machines/electrolyzer.lua @@ -9,7 +9,7 @@ elepm.electrolyzer_recipes = { time = 20 }, { - recipe = "elepower_nuclear:heavy_water 1000", + recipe = "elepower_nuclear:heavy_water_source 1000", output = { "elepower_nuclear:deuterium 600", "elepower_dynamics:oxygen 400", @@ -167,7 +167,7 @@ ele.register_machine("elepower_machines:electrolyzer", { on_timer = electrolyzer_timer, fluid_buffers = { input = { - accepts = {"default:water_source", "elepower_nuclear:heavy_water", + accepts = {"default:water_source", "elepower_nuclear:heavy_water_source", "group:biomass", "group:electrolysis_recipe"}, drainable = false, capacity = 8000, diff --git a/elepower_nuclear/fluids.lua b/elepower_nuclear/fluids.lua index 0335fcc..c4dc680 100644 --- a/elepower_nuclear/fluids.lua +++ b/elepower_nuclear/fluids.lua @@ -6,12 +6,6 @@ -- These nodes are used as "fluids" -- They do not actually exist as nodes that should be placed. -minetest.register_node("elepower_nuclear:heavy_water", { - description = "Heavy Water", - groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, water = 1}, - tiles = {"elenuclear_heavy_water.png"}, -}) - minetest.register_node("elepower_nuclear:tritium", { description = "Tritium Gas", groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, gas = 1}, @@ -30,13 +24,112 @@ minetest.register_node("elepower_nuclear:helium", { tiles = {"elenuclear_helium.png"}, }) +minetest.register_node("elepower_nuclear:helium_plasma", { + description = "Helium Plasma\nSuperheated", + groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, gas = 1}, + tiles = {"elenuclear_helium_plasma.png"}, +}) + ele.register_gas(nil, "Tritium", "elepower_nuclear:tritium") ele.register_gas(nil, "Deuterium", "elepower_nuclear:deuterium") ele.register_gas(nil, "Helium", "elepower_nuclear:helium") +ele.register_gas(nil, "Helium Plasma", "elepower_nuclear:helium_plasma") + +------------- +-- Liquids -- +------------- + +-- Heavy Water +minetest.register_node("elepower_nuclear:heavy_water_source", { + description = "Heavy Water Source", + drawtype = "liquid", + tiles = { + { + name = "elenuclear_heavy_water_source_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + special_tiles = { + { + name = "elenuclear_heavy_water_source_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + backface_culling = false, + }, + }, + alpha = 160, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "source", + liquid_alternative_flowing = "elepower_nuclear:heavy_water_flowing", + liquid_alternative_source = "elepower_nuclear:heavy_water_source", + liquid_viscosity = 4, + post_effect_color = {a = 103, r = 13, g = 69, b = 121}, + groups = {heavy_water = 3, liquid = 3, puts_out_fire = 1, cools_lava = 1}, + sounds = default.node_sound_water_defaults(), +}) + +minetest.register_node("elepower_nuclear:heavy_water_flowing", { + description = "Flowing Heavy Water", + drawtype = "flowingliquid", + tiles = {"elenuclear_heavy_water.png"}, + special_tiles = { + { + name = "elenuclear_heavy_water_flowing_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.8, + }, + }, + { + name = "elenuclear_heavy_water_flowing_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.8, + }, + }, + }, + alpha = 160, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "elepower_nuclear:heavy_water_flowing", + liquid_alternative_source = "elepower_nuclear:heavy_water_source", + liquid_viscosity = 4, + post_effect_color = {a = 103, r = 13, g = 69, b = 121}, + groups = {heavy_water = 3, liquid = 3, puts_out_fire = 1, + not_in_creative_inventory = 1, cools_lava = 1}, + sounds = default.node_sound_water_defaults(), +}) ------------- --- Fluids -- ------------- -- Cold coolant @@ -136,8 +229,13 @@ minetest.register_node("elepower_nuclear:hot_coolant_flowing", { sounds = default.node_sound_water_defaults(), }) -bucket.register_liquid("elepower_nuclear:coolant_source", "elepower_nuclear:hot_coolant_flowing", - "elepower_nuclear:bucket_coolant", "#2497ff", "Coolant (Cold)") +if minetest.get_modpath("bucket") ~= nil then + bucket.register_liquid("elepower_nuclear:coolant_source", "elepower_nuclear:hot_coolant_flowing", + "elepower_nuclear:bucket_coolant", "#2497ff", "Coolant (Cold)") -bucket.register_liquid("elepower_nuclear:hot_coolant_source", "elepower_nuclear:hot_coolant_flowing", - "elepower_nuclear:bucket_hot_coolant", "#88649e", "Coolant (Hot)") + bucket.register_liquid("elepower_nuclear:hot_coolant_source", "elepower_nuclear:hot_coolant_flowing", + "elepower_nuclear:bucket_hot_coolant", "#88649e", "Coolant (Hot)") + + bucket.register_liquid("elepower_nuclear:heavy_water_source", "elepower_nuclear:heavy_water_flowing", + "elepower_nuclear:bucket_heavy_water", "#0d4579", "Heavy Water Bucket") +end diff --git a/elepower_nuclear/machines/fusion_reactor.lua b/elepower_nuclear/machines/fusion_reactor.lua index 26d9598..54846f1 100644 --- a/elepower_nuclear/machines/fusion_reactor.lua +++ b/elepower_nuclear/machines/fusion_reactor.lua @@ -1,4 +1,6 @@ +local struct_cache = {} + local iC = 1 -- Casing local iR = 2 -- Controller local iI = 3 -- Inputs @@ -55,9 +57,11 @@ local function determine_structure(pos, player) local scan_pos = vector.add(pos, {x = relX, y = y, z = relZ}) local index = area:indexp(scan_pos) if data[index] ~= ntype then - minetest.chat_send_player(player, ('Incorrect node at %d,%d,%d; expected %s, found %s'):format( - scan_pos.x,scan_pos.y,scan_pos.z,minetest.get_name_from_content_id(ntype), - minetest.get_name_from_content_id(data[index]))) + if player then + minetest.chat_send_player(player, ('Incorrect node at %d,%d,%d; expected %s, found %s'):format( + scan_pos.x,scan_pos.y,scan_pos.z,minetest.get_name_from_content_id(ntype), + minetest.get_name_from_content_id(data[index]))) + end success = false break end @@ -73,13 +77,180 @@ local function determine_structure(pos, player) end end - if success then + if success and player then minetest.chat_send_player(player, "Multi-node structure complete!") end return success, inputs, outputs, power end +local function notify_controller_presence(posi, posj) + for _, pos in pairs(posi) do + local meta = minetest.get_meta(pos) + meta:set_string("ctrl", posj) + + local t = minetest.get_node_timer(pos) + if not t:is_started() then + t:start(1.0) + end + end +end + +local function controller_formspec(in1, in2, out, power, time, state) + local bar = "image[3.5,1;1,1;gui_furnace_arrow_bg.png^[transformR270]" + + if time ~= nil then + bar = "image[3.5,1;1,1;gui_furnace_arrow_bg.png^[lowpart:".. + (time)..":gui_furnace_arrow_fg.png^[transformR270]" + end + + return "size[8,8.5]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + ele.formspec.power_meter(power).. + ele.formspec.fluid_bar(1, 0, in1).. + ele.formspec.fluid_bar(2, 0, in2).. + bar.. + ele.formspec.fluid_bar(7, 0, out).. + ele.formspec.state_switcher(7, 2.5, state) +end + +local function controller_timer(pos) + local refresh = false + local meta = minetest.get_meta(pos) + + -- Cache all reactor components + local cpos = minetest.pos_to_string(pos) + if not struct_cache[cpos] then + local st, i, o, p = determine_structure(pos) + if st then + struct_cache[cpos] = { + inputs = i, + outputs = o, + power = p, + } + + notify_controller_presence(i, cpos) + notify_controller_presence(o, cpos) + notify_controller_presence(p, cpos) + else + return false + end + end + + local in1_buffer = fluid_lib.get_buffer_data(pos, "in1") + local in2_buffer = fluid_lib.get_buffer_data(pos, "in2") + local out_buffer = fluid_lib.get_buffer_data(pos, "out") + + local capacity = ele.helpers.get_node_property(meta, pos, "capacity") + local storage = ele.helpers.get_node_property(meta, pos, "storage") + local pow_buffer = {capacity = capacity, storage = storage, usage = 0} + + meta:set_string("formspec", controller_formspec(in1_buffer, in2_buffer, out_buffer, pow_buffer, 0, 0)) + + -- Factors: + -- 1. Power. Power keeps these stats up: + -- 1. Field Strength + -- 2. Internal Temperature + -- 2. Fuel + + -- Deuterium + Tritium -> Helium Plasma + -- Ignition temperature: 2000K (70% scale) + -- Field strength: >90% + -- 1000 + 1000 mB of fuel : 2600 sec, 675 neutrons/s + -- Helium plasma will be used to create electricity via heat exchange. + + return refresh +end + +local function get_port_controller(pos) + local meta = minetest.get_meta(pos) + local ctrl = minetest.string_to_pos(meta:get_string("ctrl")) + local ctrl_node = minetest.get_node_or_nil(ctrl) + + if not ctrl_node or ctrl_node.name ~= "elepower_nuclear:reactor_controller" then + return nil + end + + return ctrl, minetest.get_meta(ctrl) +end + +local function port_destruct(pos) + local meta = minetest.get_meta(pos) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return nil end + + -- Remove controller's cache entry, forcing it to redetect its structure + local ctrl_name = minetest.pos_to_string(ctrl) + if struct_cache[ctrl_name] then + struct_cache[ctrl_name] = nil + end + + local t = minetest.get_node_timer(ctrl) + if not t:is_started() then + t:start(1.0) + end +end + +-- Transfer power from the power port to the controller +local function power_timer(pos) + local refresh = false + local meta = minetest.get_meta(pos) + local ctrl, ctrl_meta = get_port_controller(pos) + + if not ctrl then + meta:set_string("No controller found.") + return false + end + + local localc = ele.helpers.get_node_property(meta, pos, "capacity") + local locals = ele.helpers.get_node_property(meta, pos, "storage") + + local remotec = ele.helpers.get_node_property(ctrl_meta, ctrl, "capacity") + local remotes = ele.helpers.get_node_property(ctrl_meta, ctrl, "storage") + + if remotes ~= remotec then + if remotes + locals > remotec then + local add = remotec - remotes + locals = locals - add + remotes = remotes + add + else + remotes = remotes + locals + locals = 0 + end + refresh = true + end + + if refresh then + meta:set_int("storage", locals) + ctrl_meta:set_int("storage", remotes) + + local t = minetest.get_node_timer(ctrl) + if not t:is_started() then + t:start(1.0) + end + end + + meta:set_string("infotext", ("Feeding controller at %s\nLocal %s"):format( + minetest.pos_to_string(ctrl), ele.capacity_text(localc, locals))) + + return refresh +end + +local function port_timer(pos) + local meta = minetest.get_meta(pos) + local ctrl = get_port_controller(pos) + + if not ctrl then + meta:set_string("No controller found.") + return false + end + + meta:set_string("infotext", "Feeding controller at " .. minetest.pos_to_string(ctrl)) + return false +end + ----------- -- Nodes -- ----------- @@ -90,9 +261,30 @@ minetest.register_node("elepower_nuclear:reactor_controller", { "elepower_advblock_combined.png", "elepower_advblock_combined.png", "elepower_advblock_combined.png", "elepower_advblock_combined.png", "elepower_advblock_combined.png", "elepower_advblock_combined.png^elenuclear_fusion_controller.png", }, - groups = {cracky = 2}, + groups = { + cracky = 2, + }, + fluid_buffers = { + in1 = { + capacity = 16000, + accepts = {"elepower_nuclear:deuterium"}, + drainable = false, + }, + in2 = { + capacity = 16000, + accepts = {"elepower_nuclear:tritium", "elepower_nuclear:helium"}, + drainable = false, + }, + out = { + capacity = 16000, + accepts = nil, + drainable = true, + }, + }, + ele_capacity = 64000, + on_timer = controller_timer, on_punch = function (pos, node, puncher, pointed_thing) - print(determine_structure(pos, puncher:get_player_name())) + determine_structure(pos, puncher:get_player_name()) minetest.node_punch(pos, node, puncher, pointed_thing) end, }) @@ -104,7 +296,16 @@ minetest.register_node("elepower_nuclear:reactor_power", { "elepower_advblock_combined.png", "elepower_advblock_combined.png", "elepower_advblock_combined.png^elenuclear_power_port.png^elepower_power_port.png", }, paramtype2 = "facedir", - groups = {cracky = 2}, + groups = { + cracky = 2, + ele_machine = 1, + ele_user = 1, + }, + ele_capacity = 8000, + ele_usage = 0, + ele_inrush = 64, + on_timer = power_timer, + on_destruct = port_destruct, }) minetest.register_node("elepower_nuclear:reactor_fluid", { @@ -115,7 +316,66 @@ minetest.register_node("elepower_nuclear:reactor_fluid", { "elepower_advblock_combined.png^elenuclear_fluid_port.png^elepower_power_port.png", }, paramtype2 = "facedir", - groups = {cracky = 2}, + groups = { + cracky = 2, + fluid_container = 1, + tube = 1, + }, + fluid_buffers = {}, + on_timer = port_timer, + on_destruct = port_destruct, + node_io_can_put_liquid = function (pos, node, side) + return true + end, + node_io_can_take_liquid = function (pos, node, side) + return false + end, + node_io_get_liquid_size = function (pos, node, side) + return 2 + end, + node_io_get_liquid_name = function(pos, node, side, index) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return nil end + + return ctrl_meta:get_string("in" .. index .. "_fluid") + end, + node_io_get_liquid_stack = function(pos, node, side, index) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return ItemStack(nil) end + + return ItemStack(ctrl_meta:get_string("in" .. index .. "_fluid") .. " " .. + ctrl_meta:get_int("in" .. index .. "_fluid_storage")) + end, + node_io_accepts_millibuckets = function(pos, node, side) return true end, + node_io_put_liquid = function(pos, node, side, putter, liquid, millibuckets) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return nil end + + local buffers = fluid_lib.get_node_buffers(ctrl) + local leftovers = 0 + for buffer,data in pairs(buffers) do + if millibuckets == 0 then break end + local didnt_fit = fluid_lib.insert_into_buffer(ctrl, buffer, liquid, millibuckets) + millibuckets = millibuckets - (millibuckets - didnt_fit) + leftovers = leftovers + didnt_fit + end + return leftovers + end, + node_io_room_for_liquid = function(pos, node, side, liquid, millibuckets) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return nil end + + local buffers = fluid_lib.get_node_buffers(ctrl) + local insertable = 0 + for buffer,data in pairs(buffers) do + local insert = fluid_lib.can_insert_into_buffer(ctrl, buffer, liquid, millibuckets) + if insert > 0 then + insertable = insert + break + end + end + return insertable + end, }) minetest.register_node("elepower_nuclear:reactor_output", { @@ -126,7 +386,67 @@ minetest.register_node("elepower_nuclear:reactor_output", { "elepower_advblock_combined.png^elenuclear_fluid_port_out.png^elepower_power_port.png", }, paramtype2 = "facedir", - groups = {cracky = 2}, + groups = { + cracky = 2, + fluid_container = 1, + tube = 1, + }, + fluid_buffers = {}, + on_timer = port_timer, + on_destruct = port_destruct, + node_io_can_put_liquid = function (pos, node, side) + return false + end, + node_io_can_take_liquid = function (pos, node, side) + return true + end, + node_io_accepts_millibuckets = function(pos, node, side) return true end, + node_io_take_liquid = function(pos, node, side, taker, want_liquid, want_millibuckets) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return nil end + + local buffers = fluid_lib.get_node_buffers(ctrl) + local buffer = "out" + local took = 0 + local name = "" + + local bfdata = fluid_lib.get_buffer_data(ctrl, buffer) + local storage = bfdata.amount + local fluid = bfdata.fluid + if (fluid == want_liquid or want_liquid == "") and storage >= want_millibuckets then + name, took = fluid_lib.take_from_buffer(ctrl, buffer, want_millibuckets) + end + + return {name = name, millibuckets = took} + end, + node_io_get_liquid_size = function (pos, node, side) + return 1 + end, + node_io_get_liquid_name = function(pos, node, side, index) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return "" end + return ctrl_meta:get_string("out_fluid") + end, + node_io_get_liquid_stack = function(pos, node, side, index) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return ItemStack(nil) end + + return ItemStack(ctrl_meta:get_string("out_fluid") .. " " .. + ctrl_meta:get_int("out_fluid_storage")) + end, +}) + +minetest.register_lbm({ + label = "Enable Fusion Reactors on load", + name = "elepower_nuclear:fusion_reactors", + nodenames = {"elepower_nuclear:reactor_controller"}, + run_at_every_load = true, + action = function (pos) + local t = minetest.get_node_timer(pos) + if not t:is_started() then + t:start(1.0) + end + end, }) -- Define reactor structure with Content IDs diff --git a/elepower_nuclear/machines/heat_exchanger.lua b/elepower_nuclear/machines/heat_exchanger.lua index ad265a0..0ffbff4 100644 --- a/elepower_nuclear/machines/heat_exchanger.lua +++ b/elepower_nuclear/machines/heat_exchanger.lua @@ -15,6 +15,17 @@ local function get_formspec(heat, cold, water, steam) default.get_hotbar_bg(0, 4.25) end +local heat_recipes = { + ["elepower_nuclear:hot_coolant_source"] = { + out = "elepower_nuclear:coolant_source", + factor = 1, + }, + ["elepower_nuclear:helium_plasma"] = { + out = "elepower_nuclear:helium", + factor = 8, + }, +} + local function heat_exchanger_timer(pos) local meta = minetest.get_meta(pos) local change = false @@ -24,15 +35,25 @@ local function heat_exchanger_timer(pos) local water = fluid_lib.get_buffer_data(pos, "water") local steam = fluid_lib.get_buffer_data(pos, "steam") - -- See if we have enough hot coolant - if heat.amount >= 1000 then - local water_convert = math.min(water.amount, 1000) - if steam.amount + water_convert > steam.capacity then - water_convert = steam.capacity - steam.amount + while true do + if heat.amount < 1000 or heat.fluid == "" or not heat_recipes[heat.fluid] then + break end - if water_convert > 0 then - if cold.amount + 1000 < cold.capacity then + -- See if we have enough hot coolant + if heat.amount >= 1000 and heat.fluid ~= "" then + local damnt = heat_recipes[heat.fluid] + local water_convert = math.min(water.amount, 1000 * damnt.factor) + + if cold.fluid ~= damnt.fluid and cold.fluid ~= "" then + break + end + + if steam.amount + water_convert > steam.capacity then + water_convert = steam.capacity - steam.amount + end + + if water_convert > 0 and cold.amount + 1000 < cold.capacity then -- Conversion heat.amount = heat.amount - 1000 cold.amount = cold.amount + 1000 @@ -40,13 +61,16 @@ local function heat_exchanger_timer(pos) water.amount = water.amount - water_convert steam.amount = steam.amount + water_convert + cold.fluid = damnt.out change = true end end + + break end if change then - meta:set_string("cold_fluid", "elepower_nuclear:coolant_source") + meta:set_string("cold_fluid", cold.fluid) meta:set_string("steam_fluid", "elepower_dynamics:steam") meta:set_int("heat_fluid_storage", heat.amount) @@ -58,7 +82,7 @@ local function heat_exchanger_timer(pos) meta:set_string("formspec", get_formspec(heat, cold, water, steam)) - return false + return change end ele.register_machine("elepower_nuclear:heat_exchanger", { @@ -71,12 +95,12 @@ ele.register_machine("elepower_nuclear:heat_exchanger", { fluid_buffers = { heat = { capacity = 8000, - accepts = {"elepower_nuclear:hot_coolant_source"}, + accepts = {"elepower_nuclear:hot_coolant_source", "elepower_nuclear:helium_plasma"}, drainable = false, }, cold = { capacity = 8000, - accepts = {"elepower_nuclear:coolant_source"}, + accepts = {"elepower_nuclear:coolant_source", "elepower_nuclear:helium"}, drainable = true, }, water = { diff --git a/elepower_nuclear/textures/elenuclear_heavy_water.png b/elepower_nuclear/textures/elenuclear_heavy_water.png index 692913403d48bc2aad6fc2b881f6593ee6399763..717879e8e24b7ea04637d6da17d509ef0f035747 100644 GIT binary patch delta 489 zcmV1l0tPQV9tV3I_^kQs2mtTPT0MNkl|QO=w&41_;B4zT)ZIaJTo z!}OFDDq7ftBz%QckW!lo$=7 zk+Zj#i`z>%$r|TMpeY2t*H$q}fLo(sg#D z)sD?rHN65q*|TER{sSc^F`f8~i+N8K{4r!ln=j*J0#7TWI=jH@XhPcjD#kfj_etcYp|{ z`X+BL07QTpiM%R&rjm4Lq}l(c^BRk+g|dq~*$;(E#uP4B4s934eXmERkGXb?J0LfS z%jbx$nOm7{X)}AZUtTdYqP9~ve~*0iEf$gazS4ES6-xdB?$7MoVu&2+000UA07*qo IM6N<$f|u7TS{W=e90arWgFR*FlNS58pezm%Fvf&ouMKmAw*NQ z38CyIOJ6%t8pb-d|D}Ha*L~gRKCkoK=bX=T&ilOPzJ_FDWpapDlotd79lB&{WD7h6 zKp-{{Hy1FgwOzFW9$fC`CPtv$y^H#;;9tPP6J&Y~4FW02?A>f(&vZioBN%hZ(il9> zBf!heH61}d1DK9sjIUx018?2(3c!F2gT1a}ygVgC{V=|gCYLO29Ps?YKse?lBYpd@ z!R$<@M-v*sddln#v8TMQTzT-0qqKE?(STNW?5$6&R`FT8ymb&;B*!J~ORHt?=lU+k zpAbL^ay!@Vu6ORT0*`>}%N|(l?o_}`4Z-z8?x+qJF?~qgjTT0;5_B%VVI!+iix+!57%Vh7 z7ss=+C}?VE;(t>_vv2B-vuk-fQ3UGBw^}2!mgphI){-mG*3lh9)M$}}edLvOek z45EvkvCN91tE&>IVip_K24G5unnVXBW&{|4WT zPIOosjoPLhxgHKj#U~>(awROK|D`+0ZapUoKvfMa^u#_UJX8p!`}TgtD9ZnnHSok- zy}2cjB98UJ_Z=dYR&aLTl*dS+e*XNH-I?r8ZVw4l?9wr?;88ZSV6>p9WU5}O)|`@U zDCs1J?blbu{Baf)T&%ltbWi3@CVz;7*@!HQTT3^n^|)Mhf%sv04l{&6Y*8!{>mG69 z^NL_pV5#!+`@Na8ZR8IDu%!ThjUmT!MOpDO^7n+Aw}#-jfNx$8KPgQ$xt5K;W}=dI zKl6*FA@4Ta*otVOJ<|ZqP!8$G_ll5WLXT@bf1C65Y*RuW;#$u=_9&^>Vd5THdb-P5 z^D`Ld^XzU1k{(k z&t)wOd{~ji;ubyNH(OYTv;Clv zt&2o2eKt{v@sQLv#1A~^p7{1)BF}w!p(W@GYhJFuJ+xSpYki{0JyJm_xH4H7j8N)x zd3`K_w6okB)kBQJq8K`!0A_pG*%di7Lwvk`0`atDTD+B$L;p9Nh3 z8#_(cdruF@4!)cjXs)622%2GO2=~W@!R@h>mc*!sJf3-R8hp1FQ)&+9rG^$v2usxO zFrs(19TLzvb%>n1>D?=MoQi+tWuMk**ymf;L)fPc(rcJ4gKTD;T2IPcToKWe@W#Oj zT)$NRX5iDj+<153GiTdx*QhDSCWghDzt5Zgcb;3tH&Mf>gzxvkq7gTTE$qUKJOW=D zawc>_FF!}8F*nFaF6D+WG^$j+=N=KAgO)gyUvGYWN=Z*5*Tx!iJGJtvQXJX?F)m_o z)0v^wHBfmKIX^i+^4@T0~Tm430sSbE|gP zGJ0eA1p#E@6w5a97MwEjsYR<6g~-sO<6hHUhS&9R6lZD>uvJg-tlYRX+w8QWv~^EgtO>LRu*`oysU$O9_mg0R2}+>AWuh{pX!fK(pb{_ zRde{QbOlNTtuyWeqx&W-2)(x(N7TG!Q29t?R^x#nVHilK6o}13B3nCs2nb``mGk`G zAYdvu$nAO`oIbEl6!5*{wA$PC-;$)!^Z5HGPgrG_;HQp28bL?`1#MhDei71!`i>Z; zB@Hw5;8y4?CK+gIZB&-64EDsK5!$+@U_4xonFxp4H|uYS+G(D&zHo1~+BQs{Xy>3p zzphk8^CmuS{T=Sc`4sU}I%oLKW}`TSmreY1l^AS!0$0|W0=F};pzYQ&^yuSLeX?h3 zCiE>xY!DepV#yKlLaoaekXcOa%_cs?bk|aOyS7l{uu#xv!g^tI<~Q9>8yq=){TUZA zr-;EXdJN9|Fld~)SIG^rj16#eT_WG2am6RizkwYLveNRT$;>b>mY7#+{*brH_&grL zZl=!u?D!K^2a{eo$?e@J;75)6W6+CgU&H35Fe67jH^weR=h|dDWl7;iy||*4iRU?0 zQ@yIUAU>sXB=4J|O%Y0_JEo9frDk)2lTNP8z0fzc!+#1ZeDT7e%e-gVj?M4z*}!cF zwjyD_c8hKV>MiEcgc7Cg2H$(db&X0y9foGL9ExR=6}8E?G|7?gmcM0c&*Dz;5c|=> zdxdu>>9d|+H0Q^$c%$oYKwh_nKxt`YJ(4Qw2K#1DzUnH8Jbm;O$jc8^ewyy>!_KQ` z*7ap|s@i20Bt)O^%&mX*>!k|ud(za19X0OihY&kAPZ67V3;Fhg;%Sw#RC<}^QIB)f zWx>4m-0Cl#cPOSV9(q5VK4aAn81uF#Jnp%Rm%uWfqpBC1O;1B0*m)&ozlUL!7 z$sBT#PE_j*SBc%K*M=OXJV-4CIl=`ei3yS9?|)1VK8fHz62IpAKIl-r$z@py20%(5EHq7uDO(#6~Knn%p=qQhn~ zx_5NtBE-3BV$*7tohDJzRXf&z%WCx74$NCghJ|&lRx#*d@+$GD+=1U_8Q-Ou@9Q6H zWqf)z!>T7Jh=rE&^r($-Z-Cqr~HOjTdBOv{*igw zH;y!mS@?GcC#v*ICn|ShebGwnJ=0cW@MR0B=a6~`tN&z5{k&B5v|-TeNmF%!f|Ivg z9e1BvtJ%kP9e`!uZndQNUpSe_KI?M+g0w5|h5te>3^eog?Ue4YJ_hWvU)>J9gt<7*UMi+VW1N?WSrqe{Dw1>P?kp9pz0j5uvN ziT5rxoP);b*;`9+eO~Fl?bqwW3Wk=~cz}V0xHX&%yMLTXlTnj!3eCeM8z zj8T>C=@QJ!_17eK+m;|PZ!}HHVYS%cQZgjN#`Oap@4z2(d3LQ=r8)Xn>h5v!fym8m z>%{Ds4I$I1g9B4L%(GX<#^Rt2Q*~Y2o7!tVdt|+9)`Eg^N z{dw3xgT4Fgjka>fN&PrR9p!-G!DbG`oGB)725i_(l(ZnHHuZE@x#DZ|EC7M24^5kdZ%RA70f; z2qz~UL2qa=M=LwHFHeiJ=!7~%W7%76D~t}saECk*W#z+J`s~BTO2LobPnUzCKU+`b z(>u|Vn^s*?uZdSb#|E!C-5ui95V?pNF$~jHZ+(P(H6`~vW~Lkodcoqk?eayJ$#;@^ zW`n18N_d!ks@wXNChCLo8?H7rUH$5<=$lkH6N+j7Yd{ub>)hI{lN9&HE?{JDdq|;5 zSURroRcA|mQWkJ-H3<``MxTfhhZmh&AODcXxS`v|FWM8q5yZN+>yDeS+&Q$Dpf zvK-rrkc@hQmacvQHu9r#*l0sGh3bTBP=h&d@@QsPC~t7CaW=o(w`oHb_8p&u0b*H> zC7Ya1xM=^4y)giI4gO{gy8Pr)F|Oeeg_{0qPIw^y&bK{{qqmzDJFL43xm=g_L;})Y zhBE*Iuwv6%M4{T+|JhTDsF@R9el;gI+qZgciSI>#^D6W;pI^UnP|k_hm=3sidNju;m7W)%g~)2 z*HRYeBW(NsMB`2axl!?xO~5t2HU|O%+DhthFIk*+X+9tKliO}>BVUBrPxaR#=M}#F zlWUe(075zlF%$H3Ffcn0$=Tr1JdXgP`3a-}=Ue9U9NFJK-T>4FNG6>is|$Q}Km1#W zpiTl^!@T-6HL~f(|l{KnR{eMet z6Y+j-uW)KMe-4K%4(|Vh#u(SB&aLP=j+FCtqoTl+L+h8*;$N_S2)EYmE8$3y-A_pE zX@_m17(mwFf&l!nc)sd|PYYYJjr4*oE z7+%`s9#sHa`?3d?pxyu%oWd~p8Wi}d>iENw3eydsYEplrm2ke!O_UCVzp%}IZEcU} z^~*JgeKjN?jg1`y*}qJWW`M1?iF?L|z6*|j{i3d}{Rset9Ni|K1n>f~aC<8ZxxyD* zx3H&#QIY~w9VhPhQ5g_p-`=zjKAe__`MpooFfDPpLpf>gR=@R|aP7r(B*S)(J|`T$ zviZ?I*xwbdtw5*0CjUP-|5PA!$L3b(GkZ)2F*SSC0Aycm?sX~Bd$sI64UF===lT zgQThnfhcpG?XYJFBP9>d=TFtE+asi<_8SDgZ4VVZXx#O(_hPt;vlHKrMXFh*z3#@K5rq>D~Nkj+Vz4bqT8*lJ@CL<_>>oWK|{1|T*N*O{1f z!Ic2W{=`8wTGJof+<2nEnRPqetm6lX@l_kW!~}Gi z?LHpL(lhUr`t6I;HPd@pW!u@DPe}`!3tr3WghnCs?+^h~@epw7jdjtK6@Bo&a*k-Df;b8f4B>Ek>JxbL*$|pm%XbBFc*9)jy-#Z6-)y||K4^BIrzjGJ zuV9pK&`y_TT|l0Hk2g@fM@ia+b-@OA2~!l1?>Ka3^EQ$W(0Ax(}UWMb9dw*(d)ag9v9Qi&=| zNYPDuR0@S(mpv%71WL2{Q?|!5o8v&F@t@ul^C6L>QMy*elY=vkKgtn1Z6&VYCHFO#o@W~mZqw4<^=_Wy12hb1T5<-(-eW9JXVxaEmh+q zM9Tf_fl<1(PvzH|9JdatKBIG+TLz&!PNlY{y*4ZCQ_cI$g##w2^ry(hYPVQ6y>nZ9 zn_*1&HUi!~bWo%|&yV?>4prTq6uVuEhkU=NB zcw(b&*6N7rA)MNK<$yN)a_y1gF9+bYrwLZ0$@ZiRjYCtaMe0XY(@=#w*u=kh4paP6 zFSX}!k-3PDaaP6t+w({lU(;^#aO*W99_?x9-c7bDdW~Y8Blc`QoM>H8Iyniewd^G% zNdfcejhte?p_`B3=xOY8e7md(s;8-2=0mZP7Gp1vzdN2LgXpPf6kWa#h4` zTl@G1T18|ZhxbPxtF%bM)lNwT*bIMuqr+J{95tDqTYRT3-0CHH%!OtP;+tojVNun@?=6YS-`P<(uWvgGRO}Na@wl}`Oq6x&PJ}+lO7hN zo%=<=yrz_|1E}%Sng<@Ql!jQpnk2cUbT8Z#zcj27*_ya%1KW#U*SuBpYOGVJL1BIj z)M@Gd$%lZij5OiC7GX_ZD|4cc+c)w2wsXDUOR)h28hLRov4!0JgMA~9byfTlRn>X` z2+#NX-5907)O~=S<3-1`%2e$3xHmC;Yu{?lPI&E2zqgx+evL}h+yW_VGv`1&c9jiP34!pY&Ql%tnqO? z0>`n0ehY3v+36ZKPik--jLmgR0Ys`h;j$D;1Rl7$aHoLTsh~!W>IA4f^U7;Co5>G6 z8}JTKFoag}Y3m*#OQq#gh&Odf(;YRpF5@D67J3f1Q)6o8Fi^}TP#1xv>c3tzMYhOP z3qQO{^Emq9*@UO|ur=T=CWU|X8;vMV_(R;Du@}Jfucdmy3C-q4B|M}&vV2*|5mgmC zN}w(&ky1K0=}#tB*96bQz4@#vbYy?T<&)GgJ}uJbmo~CsSO-wnFm+j6OHCLopX*iZ z-T@f$NjDK*(Uo78b^u#CMd^spl?jbD)ap)ESpH=`P0a!n<6J7KBq-7 zW$f39?5YWiX{^rr;wHA6+?rRpT9U-+=hL)&ZZ^~FjKi5Sa^ymV#6N^pNs54X+X>4F zHvJjJGk9zT*fa%3Ht8_HxGUrrU13=yu{M!9gMC-#&k*+#A{#07GuY1F1l>k&Hul8@ z1x2!$+)13iq-esA?@omtI%qFnv_SRoY|@9%JWx}>ap9KN)ECt>~!LcQ%ibI+S4 z;Jf#~GO||I?^pvNeZ=9P?Plo%(|h+U8is$-8?`w@L7YV;+=gDi`~gqk6*7LUt{cXo zCZ$4?uFhbW7RFXnpkm@QXW%lt_LI+HU7)zzL^wwN9M{wN>k;@yl>F5ojC+ zPHiOX!Ox=Eqo|K-u!C!IxfG-be9)fKrrXSR@yotwXaU(9$tJ*SqO>!SG;L_^L|K!& zA|gFJiRO2hSxjP=H9Q4M`e>5AWI=gUk1lW%O)_XI<9^KCkbQP`d=`2`T(BXVyCMB2 z4*929&PK|)cf7Z#Iq_C2!g39%bDB=Xcho9nxfzJ?GgG-8|G{=ATK@jrOuE}j7IDc$=yg~x8eLGq-FCZb5`Ba*QO1r)0#`D zT_RYuIF*RL_JKT(3xW+9lXk6wWWK?IpK85-74cjG#lcDx^6w^R`BEq8G@K{jZ(6g4 zV9wKUl634{hZ+*;bp)Q*dX~0CJ5b224*zB{$ZZ`8u4T~VHz2)d^;>RW^3-LGG?ax9 zoXzfWd`7RGqPO5Y*P$|!xu6a;(}qrxYJnhI(4AzGZ%*I4OaGFJ0jmv?rGB}4jED{G zDiJwdk&Fftb0RXjaARw7)&MB{Ng_$QWbJ?SqzdoXNrwMJY@#lM3_x-;mv04RJbejn z(lHMkzLGKMn{QPQLRoB)SYA)P>x)03?YOn_zk)L|pn6R#uRjEBW^4}|-ExvOaBM3};sl6rff&j9Rz$|%TJ#QG96Cqu(!GGSIOD{6B&?+n=&~ J@x5R2e*n*Um2dz6 literal 0 HcmV?d00001 diff --git a/elepower_nuclear/textures/elenuclear_helium_plasma.png b/elepower_nuclear/textures/elenuclear_helium_plasma.png new file mode 100644 index 0000000000000000000000000000000000000000..7103ef1a40f5a538a8165edc4dc580037a43ebbf GIT binary patch literal 1527 zcmV zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1bHaFQ zYYY}b67NZJ4{iVa-RLh|qP&o?KDg+d!eyd~k}wJCxYGV)W%lQIQFC&U(^?RSG)8^A z1~=pz4o8{~2Wl9mGz@7Op3U)|k7FqpgFhdk z4E;9NcNp+T{b95hXB~TkrvY@{Ma+XJ6~rW)X07maJwlD} zb@_ZsI|C1<9fd z(m_KiD;D0}#@$`v0LPUBA$u6c7+e0+P2VWB)(eVRg@qO3l3r&_ZjW#*$dWAXXUGJ#LYj3>u&U+tx^ofEFCfMMD4mqC}03Ya{A0h8SZ? zaGGE_VRwQ;N?EebCfn??&mqU0icrzT6kA;JC6riFm8vW1xVq|VsIjJvH>A>LHoLja zZ()mDYDl%Fn`ySW=38iyT3W0PS|9fxu*QQm*_rB!ez69r_tOOTc49kcU`z~yaNikV zO(LB$71$W*%yrIG6jX&31Zg`tl{;f#&}=NW@#5~qoF(o4AKnN=$p66{b?Uxg?#bIv ztktxC==9D|FT)P1(x|>>bCQrGZ?0^K`!pow#Imvd3%Kp8z_`+wh1^$c|3Dri5Z-lz z8HO50zE9mv3 zDRs4F)Cjt$Y3mVlosdkF=;7v_+Yb@b7d95~s?5;qw7!hd*c8l+bqbEt#EB+;K};*R z^B&01S(Wp2G(4`&pGNNVUsG(3!{#D>;eH=S9*`=29_F@mS~0g2QBPHRXJuyphf@KV z!wbc*PVrXt4);$ZeFNn;mgzYAELol2f-ve&EsEt*esr$C1@60wH={YAWyfo`(Dcas z)f{F1A{tHG%J;})F!-c4Ra(TshDs<#g)%}gbET2_t1~s_<_wdG7tU)p6)&W%Gslj|IqLbC-g$#i{kwSJo*(~bNg65n%fI7 z`ZLDfkMw1lT;iLb5d0f?E80hS5A)>-+_Dz0bxx-*??<9Oejq;;?l-pS)927P{8~W^ zpnn1R)U!8aTzdcj000SaNLh0L04^f{04^f|c%?sf00007bV*G`2jU433LFZ-WE4^W z000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0002uNkle*yJ5sI z3_~B_+rP+$sc(gtNI_9nE-q|K1o4rm_xBe`f~-^|05ty+N$&sM4K#;=}si*B?u(1!eR6-4jl$d=l0{c8!LTQ zsUe=Ow&aKSCude!3pxpVO1yPHPUD2``pjz{a^MplbJZ!a6