mirror of
https://github.com/minetest-mods/technic.git
synced 2024-08-21 14:04:05 +02:00
Add longer-term radiation damage
Radiation now slowly damages you for a while after exposure, with the effect's time and intensity proportional to the amount of radiation received. The radioactivity of some items is reduced to account for the increased damage.
This commit is contained in:
parent
1da213a5e4
commit
06dec20326
@ -318,7 +318,7 @@ minetest.register_node("technic:hv_nuclear_reactor_core", {
|
||||
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",
|
||||
|
@ -230,30 +230,19 @@ readily available in cubes. 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
|
||||
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 @@ local function dmg_player(pos, o, strength)
|
||||
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 @@ local function dmg_abm(pos, node)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if minetest.setting_getbool("enable_damage") then
|
||||
minetest.register_abm({
|
||||
nodenames = {"group:radioactive"},
|
||||
@ -285,6 +298,27 @@ if minetest.setting_getbool("enable_damage") then
|
||||
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 @@ for _, state in pairs({"flowing", "source"}) do
|
||||
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 @@ minetest.register_node("technic:chernobylite_block", {
|
||||
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,
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user