From 12d0c6522bbca906910aae0321cbaa7eb48db8c2 Mon Sep 17 00:00:00 2001 From: Zefram <zefram@fysh.org> Date: Wed, 30 Jul 2014 21:28:30 +0200 Subject: [PATCH] Correct breakability of sandstone CNC nodes --- technic/machines/HV/nuclear_reactor.lua | 126 ++++++++++++++++++++++++++++++----------- 1 files changed, 92 insertions(+), 34 deletions(-) diff --git a/technic/machines/HV/nuclear_reactor.lua b/technic/machines/HV/nuclear_reactor.lua index 7bed4df..e5d7a1b 100644 --- a/technic/machines/HV/nuclear_reactor.lua +++ b/technic/machines/HV/nuclear_reactor.lua @@ -54,64 +54,117 @@ { -0.303, -0.303, -0.397, 0.303, 0.303, 0.397 }, } -local reactor_structure_badness = function(pos) - -- The reactor consists of a 9x9x9 cube structure - -- A cross section through the middle: - -- CCCC CCCC - -- CBBB BBBC - -- CBSS SSBC - -- CBSWWWSBC - -- CBSW#WSBC - -- CBSW|WSBC - -- CBSS|SSBC - -- CBBB|BBBC - -- CCCC|CCCC - -- C = Concrete, B = Blast resistant concrete, S = Stainless Steel, - -- W = water node, # = reactor core, | = HV cable - -- The man-hole and the HV cable is only in the middle - -- The man-hole is optional +local reactor_siren = {} +local function siren_set_state(pos, newstate) + local hpos = minetest.hash_node_position(pos) + local siren = reactor_siren[hpos] + if not siren then + if newstate == "off" then return end + siren = {state="off"} + reactor_siren[hpos] = siren + end + if newstate == "danger" and siren.state ~= "danger" then + if siren.handle then minetest.sound_stop(siren.handle) end + siren.handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_danger_loop", {pos=pos, gain=1.5, loop=true, max_hear_distance=48}) + siren.state = "danger" + elseif newstate == "clear" then + if siren.handle then minetest.sound_stop(siren.handle) end + local clear_handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_clear", {pos=pos, gain=1.5, loop=false, max_hear_distance=48}) + siren.handle = clear_handle + siren.state = "clear" + minetest.after(10, function () + if siren.handle == clear_handle then + minetest.sound_stop(clear_handle) + if reactor_siren[hpos] == siren then + reactor_siren[hpos] = nil + end + end + end) + elseif newstate == "off" and siren.state ~= "off" then + if siren.handle then minetest.sound_stop(siren.handle) end + siren.handle = nil + reactor_siren[hpos] = nil + end +end +local function siren_danger(pos, meta) + meta:set_int("siren", 1) + siren_set_state(pos, "danger") +end +local function siren_clear(pos, meta) + if meta:get_int("siren") ~= 0 then + siren_set_state(pos, "clear") + meta:set_int("siren", 0) + end +end +-- The standard reactor structure consists of a 9x9x9 cube. A cross +-- section through the middle: +-- +-- CCCC CCCC +-- CBBB BBBC +-- CBSS SSBC +-- CBSWWWSBC +-- CBSW#WSBC +-- CBSW|WSBC +-- CBSS|SSBC +-- CBBB|BBBC +-- CCCC|CCCC +-- C = Concrete, B = Blast-resistant concrete, S = Stainless Steel, +-- W = water node, # = reactor core, | = HV cable +-- +-- The man-hole and the HV cable are only in the middle, and the man-hole +-- is optional. +-- +-- For the reactor to operate and not melt down, it insists on the inner +-- 7x7x7 portion (from the core out to the blast-resistant concrete) +-- being intact. Intactness only depends on the number of nodes of the +-- right type in each layer. The water layer must have water in all but +-- at most one node; the steel and blast-resistant concrete layers must +-- have the right material in all but at most two nodes. The permitted +-- gaps are meant for the cable and man-hole, but can actually be anywhere +-- and contain anything. For the reactor to be useful, a cable must +-- connect to the core, but it can go in any direction. +-- +-- The outer concrete layer of the standard structure is not required +-- for the reactor to operate. It is noted here because it used to +-- be mandatory, and for historical reasons (that it predates the +-- implementation of radiation) it needs to continue being adequate +-- shielding of legacy reactors. If it ever ceases to be adequate +-- shielding for new reactors, legacy ones should be grandfathered. +local reactor_structure_badness = function(pos) local vm = VoxelManip() - local pos1 = vector.subtract(pos, 4) - local pos2 = vector.add(pos, 4) + local pos1 = vector.subtract(pos, 3) + local pos2 = vector.add(pos, 3) local MinEdge, MaxEdge = vm:read_from_map(pos1, pos2) local data = vm:get_data() local area = VoxelArea:new({MinEdge=MinEdge, MaxEdge=MaxEdge}) - local c_concrete = minetest.get_content_id("technic:concrete") local c_blast_concrete = minetest.get_content_id("technic:blast_resistant_concrete") local c_stainless_steel = minetest.get_content_id("technic:stainless_steel_block") local c_water_source = minetest.get_content_id("default:water_source") local c_water_flowing = minetest.get_content_id("default:water_flowing") - local concretelayer, blastlayer, steellayer, waterlayer = 0, 0, 0, 0 + local blastlayer, steellayer, waterlayer = 0, 0, 0 for z = pos1.z, pos2.z do for y = pos1.y, pos2.y do for x = pos1.x, pos2.x do - -- If the position is in the outer layer + local cid = data[area:index(x, y, z)] if x == pos1.x or x == pos2.x or y == pos1.y or y == pos2.y or z == pos1.z or z == pos2.z then - if data[area:index(x, y, z)] == c_concrete then - concretelayer = concretelayer + 1 + if cid == c_blast_concrete then + blastlayer = blastlayer + 1 end elseif x == pos1.x+1 or x == pos2.x-1 or y == pos1.y+1 or y == pos2.y-1 or z == pos1.z+1 or z == pos2.z-1 then - if data[area:index(x, y, z)] == c_blast_concrete then - blastlayer = blastlayer + 1 + if cid == c_stainless_steel then + steellayer = steellayer + 1 end elseif x == pos1.x+2 or x == pos2.x-2 or y == pos1.y+2 or y == pos2.y-2 or z == pos1.z+2 or z == pos2.z-2 then - if data[area:index(x, y, z)] == c_stainless_steel then - steellayer = steellayer + 1 - end - elseif x == pos1.x+3 or x == pos2.x-3 or - y == pos1.y+3 or y == pos2.y-3 or - z == pos1.z+3 or z == pos2.z-3 then - local cid = data[area:index(x, y, z)] if cid == c_water_source or cid == c_water_flowing then waterlayer = waterlayer + 1 end @@ -122,8 +175,7 @@ if waterlayer > 25 then waterlayer = 25 end if steellayer > 96 then steellayer = 96 end if blastlayer > 216 then blastlayer = 216 end - if concretelayer > 384 then concretelayer = 384 end - return (25 - waterlayer) + (96 - steellayer) + (216 - blastlayer) + (384 - concretelayer) + return (25 - waterlayer) + (96 - steellayer) + (216 - blastlayer) end local function meltdown_reactor(pos) @@ -142,8 +194,10 @@ if badness == 0 then if accum_badness ~= 0 then meta:set_int("structure_accumulated_badness", accum_badness - 1) + siren_clear(pos, meta) end else + siren_danger(pos, meta) accum_badness = accum_badness + badness if accum_badness >= 100 then meltdown_reactor(pos) @@ -190,6 +244,7 @@ meta:set_string("infotext", S("%s Idle"):format(machine_name)) technic.swap_node(pos, "technic:hv_nuclear_reactor_core") meta:set_int("structure_accumulated_badness", 0) + siren_clear(pos, meta) elseif burn_time > 0 then burn_time = burn_time + 1 meta:set_int("burn_time", burn_time) @@ -227,6 +282,7 @@ inv:set_size("src", 6) end, can_dig = technic.machine_can_dig, + on_destruct = function(pos) siren_set_state(pos, "off") end, allow_metadata_inventory_put = technic.machine_inventory_put, allow_metadata_inventory_take = technic.machine_inventory_take, allow_metadata_inventory_move = technic.machine_inventory_move, @@ -250,6 +306,7 @@ }, can_dig = technic.machine_can_dig, after_dig_node = meltdown_reactor, + on_destruct = function(pos) siren_set_state(pos, "off") end, allow_metadata_inventory_put = technic.machine_inventory_put, allow_metadata_inventory_take = technic.machine_inventory_take, allow_metadata_inventory_move = technic.machine_inventory_move, @@ -271,6 +328,7 @@ meta:set_int("burn_time", 0) technic.swap_node(pos, "technic:hv_nuclear_reactor_core") meta:set_int("structure_accumulated_badness", 0) + siren_clear(pos, meta) return end -- Gitblit v1.8.0