From 06dec2032628b475c4f02dfc9e92a58788d0912d Mon Sep 17 00:00:00 2001
From: ShadowNinja <shadowninja@minetest.net>
Date: Sat, 28 Jan 2017 23:51:14 +0100
Subject: [PATCH] Add longer-term radiation damage

---
 technic/machines/HV/nuclear_reactor.lua |    2 
 technic/radiation.lua                   |   74 +++++++++++++++++++++++++++----------
 2 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/technic/machines/HV/nuclear_reactor.lua b/technic/machines/HV/nuclear_reactor.lua
index 235d03c..16bb928 100644
--- a/technic/machines/HV/nuclear_reactor.lua
+++ b/technic/machines/HV/nuclear_reactor.lua
@@ -318,7 +318,7 @@
 minetest.register_node("technic:hv_nuclear_reactor_core_active", {
 	tiles = {"technic_hv_nuclear_reactor_core.png"},
 	groups = {cracky=1, technic_machine=1, technic_hv=1,
-		radioactive=6, not_in_creative_inventory=1},
+		radioactive=4, not_in_creative_inventory=1},
 	legacy_facedir_simple = true,
 	sounds = default.node_sound_wood_defaults(),
 	drop = "technic:hv_nuclear_reactor_core",
diff --git a/technic/radiation.lua b/technic/radiation.lua
index 2dec38b..ac3f166 100644
--- a/technic/radiation.lua
+++ b/technic/radiation.lua
@@ -230,30 +230,19 @@
 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
+Damage is processed at rates down to 0.2 HP/s, which in the absence of
 shielding is attained at the distance specified by the "radioactive"
-group value.  Computed damage rates below 0.25 HP/s result in no
+group value.  Computed damage rates below 0.2 HP/s result in no
 damage at all to the player.  This gives the player an opportunity
 to be safe, and limits the range at which source/player interactions
 need to be considered.
 --]]
 local abdomen_offset = 1
 local cache_scaled_shielding = {}
-local rad_dmg_cutoff = 0.25
+local rad_dmg_cutoff = 0.2
+local radiated_players = {}
 
-local function dmg_player(pos, o, strength)
-	local pl_pos = o:getpos()
-	pl_pos.y = pl_pos.y + abdomen_offset
-	local shielding = 0
-	local dist = vector.distance(pos, pl_pos)
-	for ray_pos in technic.trace_node_ray(pos,
-			vector.direction(pos, pl_pos), dist) do
-		local shield_name = minetest.get_node(ray_pos).name
-		shielding = shielding + node_radiation_resistance(shield_name) * 0.1
-	end
-	local dmg = (strength * strength) /
-		(math.max(0.75, dist * dist) * math.exp(shielding))
-	if dmg < rad_dmg_cutoff then return end
+local function apply_fractional_damage(o, dmg)
 	local dmg_int = math.floor(dmg)
 	-- The closer you are to getting one more damage point,
 	-- the more likely it will be added.
@@ -261,8 +250,33 @@
 		dmg_int = dmg_int + 1
 	end
 	if dmg_int > 0 then
-		o:set_hp(math.max(o:get_hp() - dmg_int, 0))
+		local new_hp = math.max(o:get_hp() - dmg_int, 0)
+		o:set_hp(new_hp)
+		return new_hp == 0
 	end
+	return false
+end
+
+local function dmg_player(pos, player, strength)
+	local pl_pos = player:getpos()
+	pl_pos.y = pl_pos.y + abdomen_offset
+	local shielding = 0
+	local dist = vector.distance(pos, pl_pos)
+
+	for ray_pos in technic.trace_node_ray(pos,
+			vector.direction(pos, pl_pos), dist) do
+		local shield_name = minetest.get_node(ray_pos).name
+		shielding = shielding + node_radiation_resistance(shield_name) * 0.1
+	end
+
+	local dmg = (strength * strength) /
+		(math.max(0.75, dist * dist) * math.exp(shielding))
+
+	if dmg < rad_dmg_cutoff then return end
+	apply_fractional_damage(player, dmg)
+
+	local pn = player:get_player_name()
+	radiated_players[pn] = (radiated_players[pn] or 0) + dmg
 end
 
 local rad_dmg_mult_sqrt = math.sqrt(1 / rad_dmg_cutoff)
@@ -277,7 +291,6 @@
 	end
 end
 
-
 if minetest.setting_getbool("enable_damage") then
 	minetest.register_abm({
 		nodenames = {"group:radioactive"},
@@ -285,6 +298,27 @@
 		chance = 1,
 		action = dmg_abm,
 	})
+
+	minetest.register_globalstep(function(dtime)
+		for pn, dmg in pairs(radiated_players) do
+			dmg = dmg - (dtime / 8)
+			local player = minetest.get_player_by_name(pn)
+			local killed
+			if player and dmg > rad_dmg_cutoff then
+				killed = apply_fractional_damage(player, (dmg * dtime) / 8)
+			else
+				dmg = nil
+			end
+			-- on_dieplayer will have already set this if the player died
+			if not killed then
+				radiated_players[pn] = dmg
+			end
+		end
+	end)
+
+	minetest.register_on_dieplayer(function(player)
+		radiated_players[player:get_player_name()] = nil
+	end)
 end
 
 -- Radioactive materials that can result from destroying a reactor
@@ -323,7 +357,7 @@
 			liquid = 2,
 			hot = 3,
 			igniter = (griefing and 1 or 0),
-			radioactive = (state == "source" and 16 or 8),
+			radioactive = (state == "source" and 12 or 6),
 			not_in_creative_inventory = (state == "flowing" and 1 or nil),
 		},
 	})
@@ -343,7 +377,7 @@
         description = S("Chernobylite Block"),
 	tiles = {"technic_chernobylite_block.png"},
 	is_ground_content = true,
-	groups = {cracky=1, radioactive=6, level=2},
+	groups = {cracky=1, radioactive=4, level=2},
 	sounds = default.node_sound_stone_defaults(),
 	light_source = 2,
 })

--
Gitblit v1.8.0