Vanessa Ezekowitz
2015-01-17 d6b0deb989e649e2800932d4a587c3ba9e3e24c7
technic/machines/HV/nuclear_reactor.lua
@@ -259,7 +259,7 @@
   tiles = {"technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
            "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
            "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png"},
   groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1},
   groups = {cracky=1, technic_machine=1},
   legacy_facedir_simple = true,
   sounds = default.node_sound_wood_defaults(),
   drawtype="nodebox",
@@ -293,7 +293,7 @@
   tiles = {"technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
            "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png",
       "technic_hv_nuclear_reactor_core.png", "technic_hv_nuclear_reactor_core.png"},
   groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_machine=1, radioactive=7, not_in_creative_inventory=1},
   groups = {cracky=1, technic_machine=1, radioactive=11000, not_in_creative_inventory=1},
   legacy_facedir_simple = true,
   sounds = default.node_sound_wood_defaults(),
   drop="technic:hv_nuclear_reactor_core",
@@ -541,21 +541,25 @@
--
-- A radioactive node is identified by being in the "radioactive" group,
-- and the group value signifies the strength of the radiation source.
-- The group value is the distance in metres from a node at which an
-- unshielded player will be damaged by 0.25 HP/s.  Or, equivalently, it
-- is half the square root of the damage rate in HP/s that an unshielded
-- player 1 m away will take.
-- The group value is the distance in millimetres from a node at which
-- an unshielded player will be damaged by 0.25 HP/s.  Or, equivalently,
-- it is 2000 times the square root of the damage rate in HP/s that an
-- unshielded player 1 m away will take.
--
-- Shielding is assessed by sampling every 0.25 m along the path
-- from the source to the player, ignoring the source node itself.
-- The summed radiation resistance values from the sampled nodes yield
-- a measure of the total amount of radiation resistance on the path.
-- As in reality, shielding causes exponential attenuation of radiation.
-- However, the effect is scaled down relative to real life: each
-- metre-point of shielding, corresponding to a real-life halving of
-- radiation, reduces radiation by 0.01 nepers (a factor of about 1.01).
-- This scales down the difference between shielded and unshielded safe
-- distances, avoiding the latter becoming impractically large.
-- The summed shielding values from the sampled nodes yield a measure
-- of the total amount of shielding on the path.  As in reality,
-- shielding causes exponential attenuation of radiation.  However, the
-- effect is scaled down relative to real life.  A metre of a node with
-- radiation resistance value R yields attenuation of sqrt(R)*0.1 nepers.
-- (In real life it would be about R*0.69 nepers, by the definition
-- of the radiation resistance values.)  The sqrt part of this formula
-- scales down the differences between shielding types, reflecting the
-- game's simplification of making expensive materials such as gold
-- readily available in cubic metres.  The multiplicative factor in the
-- formula scales down the difference between shielded and unshielded
-- safe distances, avoiding the latter becoming impractically large.
--
-- Damage is processed at rates down to 0.25 HP/s, which in the absence of
-- shielding is attained at the distance specified by the "radioactive"
@@ -565,28 +569,35 @@
-- need to be considered.
local assumed_abdomen_offset = vector.new(0, 1, 0)
local assumed_abdomen_offset_length = vector.length(assumed_abdomen_offset)
local cache_scaled_shielding = {}
minetest.register_abm({
   nodenames = {"group:radioactive"},
   interval = 1,
   chance = 1,
   action = function (pos, node)
      local strength = minetest.registered_nodes[node.name].groups.radioactive
      for _, o in ipairs(minetest.get_objects_inside_radius(pos, strength + assumed_abdomen_offset_length)) do
      for _, o in ipairs(minetest.get_objects_inside_radius(pos, strength*0.001 + assumed_abdomen_offset_length)) do
         if o:is_player() then
            local rel = vector.subtract(vector.add(o:getpos(), assumed_abdomen_offset), pos)
            local dist_sq = vector.length_square(rel)
            local dist = math.sqrt(dist_sq)
            local dirstep = dist == 0 and vector.new(0,0,0) or vector.divide(rel, dist*4)
            local intpos = pos
            local resistance = 0
            local shielding = 0
            for intdist = 0.25, dist, 0.25 do
               intpos = vector.add(intpos, dirstep)
               local intnodepos = vector.round(intpos)
               if not vector.equals(intnodepos, pos) then
                  resistance = resistance + node_radiation_resistance(minetest.get_node(intnodepos).name)
                  local sname = minetest.get_node(intnodepos).name
                  local sval = cache_scaled_shielding[sname]
                  if not sval then
                     sval = math.sqrt(node_radiation_resistance(sname)) * -0.025
                     cache_scaled_shielding[sname] = sval
                  end
                  shielding = shielding + sval
               end
            end
            local dmg_rate = 0.25 * strength*strength * math.exp(-0.0025*resistance) / math.max(0.75, dist_sq)
            local dmg_rate = 0.25e-6 * strength*strength * math.exp(shielding) / math.max(0.75, dist_sq)
            if dmg_rate >= 0.25 then
               local dmg_int = math.floor(dmg_rate)
               if math.random() < dmg_rate-dmg_int then
@@ -636,7 +647,7 @@
         liquid = 2,
         hot = 3,
         igniter = 1,
         radioactive = (state == "source" and 32 or 16),
         radioactive = (state == "source" and 32000 or 16000),
         not_in_creative_inventory = (state == "flowing" and 1 or nil),
      },
   })
@@ -656,7 +667,7 @@
        description = S("Chernobylite Block"),
   tiles = { "technic_chernobylite_block.png" },
   is_ground_content = true,
   groups = { cracky=1, radioactive=5, level=2 },
   groups = { cracky=1, radioactive=5000, level=2 },
   sounds = default.node_sound_stone_defaults(),
   light_source = 2,