2019-10-13 11:37:36 -04:00
|
|
|
-- LUALOCALS < ---------------------------------------------------------
|
2020-09-12 16:27:15 -04:00
|
|
|
local math, minetest, nodecore, pairs, setmetatable, vector
|
|
|
|
= math, minetest, nodecore, pairs, setmetatable, vector
|
|
|
|
local math_cos, math_floor, math_pi, math_pow, math_random, math_sin,
|
|
|
|
math_sqrt
|
|
|
|
= math.cos, math.floor, math.pi, math.pow, math.random, math.sin,
|
|
|
|
math.sqrt
|
2019-10-13 11:37:36 -04:00
|
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
|
2020-09-12 16:27:15 -04:00
|
|
|
local radlevel
|
|
|
|
do
|
|
|
|
local radcache = {}
|
|
|
|
local metakey = "rad"
|
|
|
|
radlevel = function(player, setto)
|
|
|
|
local pname = player:get_player_name()
|
|
|
|
local meta = player:get_meta()
|
|
|
|
local found = radcache[pname]
|
|
|
|
if setto and found ~= setto then
|
|
|
|
radcache[pname] = setto
|
|
|
|
meta:set_float(metakey, setto)
|
|
|
|
return setto
|
|
|
|
end
|
|
|
|
if found then return found end
|
|
|
|
found = meta:get_float(metakey) or 0
|
|
|
|
radcache[pname] = found
|
|
|
|
return found
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-10-13 11:37:36 -04:00
|
|
|
local irradiated = modname .. ":irradiated"
|
2020-02-24 21:45:13 -05:00
|
|
|
nodecore.register_virtual_item(irradiated, {
|
2020-09-04 13:58:46 -04:00
|
|
|
description = "",
|
2019-12-31 11:06:35 -05:00
|
|
|
inventory_image = "[combine:1x1",
|
|
|
|
hotbar_type = "burn",
|
2019-10-13 11:37:36 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
nodecore.register_healthfx({
|
|
|
|
item = irradiated,
|
2020-09-12 16:27:15 -04:00
|
|
|
getqty = function(player) return radlevel(player) end
|
2019-10-13 11:37:36 -04:00
|
|
|
})
|
|
|
|
|
2020-09-12 12:09:37 -04:00
|
|
|
local rad_lut = {}
|
2020-09-12 16:27:15 -04:00
|
|
|
do
|
|
|
|
local rad_default = {absorb = 1/64, scatter = 1/32}
|
|
|
|
local rad_init
|
|
|
|
setmetatable(rad_lut, {
|
|
|
|
__index = function(_, k)
|
|
|
|
if rad_init then rad_lut[k] = rad_default end
|
|
|
|
return rad_default
|
|
|
|
end
|
|
|
|
}
|
|
|
|
)
|
|
|
|
minetest.after(0, function()
|
|
|
|
for k, v in pairs(minetest.registered_items) do
|
|
|
|
local g = v.groups or {}
|
|
|
|
local rad = {
|
|
|
|
stack = g.visinv,
|
|
|
|
|
|
|
|
emit = g.lux_emit,
|
|
|
|
|
|
|
|
absorb = (g.lux_absorb and g.lux_absorb / 64)
|
|
|
|
or (g.metallic and 1)
|
|
|
|
or ((v.liquidtype ~= "none" or g.water or g.moist) and 7/8)
|
|
|
|
or (g.cracky and 1 - 1 / (g.cracky + 2))
|
|
|
|
or (g.flammeble and (not g.fire_fuel) and rad_default.absorb)
|
|
|
|
or (v.walkable and 1/4)
|
|
|
|
or rad_default.absorb,
|
|
|
|
|
|
|
|
scatter = (g.lux_scatter and g.lux_scatter / 64)
|
|
|
|
or (v.liquidtype ~= "none" and 1)
|
|
|
|
or (v.walkable and 1/8)
|
|
|
|
or rad_default.scatter
|
|
|
|
}
|
|
|
|
if rad.absorb < rad_default.absorb then
|
|
|
|
rad.absorb = rad_default.absorb
|
|
|
|
end
|
|
|
|
rad_lut[k] = rad
|
|
|
|
end
|
|
|
|
rad_init = true
|
|
|
|
end)
|
|
|
|
end
|
2020-09-12 12:09:37 -04:00
|
|
|
|
|
|
|
local function randdir()
|
|
|
|
-- https://math.stackexchange.com/a/44691
|
|
|
|
local z = math_random() * 2 - 1
|
|
|
|
local k = math_sqrt(1 - z * z)
|
|
|
|
local theta = math_random() * math_pi * 2
|
|
|
|
return {
|
|
|
|
x = k * math_cos(theta),
|
|
|
|
y = k * math_sin(theta),
|
|
|
|
z = z
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2020-09-12 16:43:00 -04:00
|
|
|
local function nodescan(player)
|
2020-09-12 12:09:37 -04:00
|
|
|
local emit = 0
|
|
|
|
local pos = player:get_pos()
|
|
|
|
pos.y = pos.y + player:get_properties().eye_height
|
|
|
|
local dir
|
2020-09-12 16:27:15 -04:00
|
|
|
while true do
|
2020-09-12 12:09:37 -04:00
|
|
|
local nn = minetest.get_node(pos).name
|
|
|
|
if nn == "ignore" then break end
|
2020-09-12 16:27:15 -04:00
|
|
|
local rad = rad_lut[nn]
|
2020-09-12 12:09:37 -04:00
|
|
|
if rad.emit then emit = emit + rad.emit end
|
|
|
|
if math_random() < rad.absorb then break end
|
|
|
|
if math_random() < rad.scatter then dir = randdir() end
|
2020-09-12 16:27:15 -04:00
|
|
|
if rad.stack then
|
|
|
|
local stack = nodecore.stack_get(pos)
|
|
|
|
rad = (not stack:is_empty()) and rad_lut[stack:get_name()]
|
|
|
|
if rad then
|
|
|
|
if rad.emit then emit = emit + rad.emit end
|
|
|
|
if math_random() < rad.absorb then break end
|
|
|
|
if math_random() < rad.scatter then dir = randdir() end
|
|
|
|
end
|
|
|
|
end
|
2020-09-12 12:09:37 -04:00
|
|
|
dir = dir or randdir()
|
2020-09-12 16:27:15 -04:00
|
|
|
pos = vector.add(pos, vector.multiply(dir, math_random()))
|
2019-10-13 11:37:36 -04:00
|
|
|
end
|
2020-09-12 16:27:15 -04:00
|
|
|
return emit
|
2019-10-13 11:37:36 -04:00
|
|
|
end
|
|
|
|
|
2020-09-12 16:43:00 -04:00
|
|
|
local function itemscan(player)
|
|
|
|
local list = player:get_inventory():get_list("main")
|
|
|
|
for k, v in pairs(list) do list[k] = rad_lut[v:get_name()] end
|
|
|
|
for i = #list, 1, -1 do
|
|
|
|
local j = math_random(1, i)
|
|
|
|
list[i], list[j] = list[j], list[i]
|
|
|
|
end
|
|
|
|
local emit = 0
|
|
|
|
for _, rad in pairs(list) do
|
|
|
|
if rad.emit then emit = emit + rad.emit end
|
|
|
|
if math_random() < rad.absorb then break end
|
|
|
|
if math_random() < rad.scatter then break end
|
|
|
|
end
|
2020-09-12 18:30:28 -04:00
|
|
|
return emit / 8
|
2020-09-12 16:43:00 -04:00
|
|
|
end
|
|
|
|
|
2020-09-12 12:09:37 -04:00
|
|
|
nodecore.register_playerstep({
|
|
|
|
label = "lux rad scan",
|
|
|
|
action = function(player, data, dtime)
|
2020-09-12 16:27:15 -04:00
|
|
|
local rad = radlevel(player)
|
|
|
|
|
|
|
|
data.unradtime = (data.unradtime or 0) + dtime
|
|
|
|
if data.unradtime > 1 then
|
|
|
|
local pos = player:get_pos()
|
|
|
|
local stand = minetest.registered_items[minetest.get_node({
|
|
|
|
x = pos.x + math_random() - 0.5,
|
|
|
|
y = pos.y + math_random() * 2 - 0.5,
|
|
|
|
z = pos.z + math_random() - 0.5,
|
|
|
|
}).name] or {}
|
|
|
|
local use = math_floor(data.unradtime)
|
|
|
|
if (stand.groups or {}).water then
|
|
|
|
rad = rad * math_pow(15/16, use)
|
|
|
|
end
|
|
|
|
data.unradtime = data.unradtime - use
|
|
|
|
end
|
|
|
|
|
2020-09-12 12:09:37 -04:00
|
|
|
data.radtime = (data.radtime or 0) + dtime
|
|
|
|
if data.radtime > 1 then data.radtime = 1 end
|
|
|
|
while data.radtime > 1/16 do
|
|
|
|
data.radtime = data.radtime - 1/16
|
2020-09-12 18:30:28 -04:00
|
|
|
local prob = (nodescan(player) + itemscan(player)) / 128
|
2020-09-12 16:27:15 -04:00
|
|
|
if prob > 0 and math_random() < prob then
|
|
|
|
rad = 1 - (1 - rad) * 7/8
|
|
|
|
end
|
2020-09-12 12:09:37 -04:00
|
|
|
end
|
2020-09-12 16:27:15 -04:00
|
|
|
|
|
|
|
return radlevel(player, rad)
|
Active ItemStack Modifier overhaul.
AISM's now tick against stacks, including in piles, shelves,
and player inventories, (hopefully) efficiently compared to
the old way with separate ABMs. Item entity support is also
possible, but not necessary yet.
This started out as a bugfix for being able to put a torch inside a
shelf, which didn't make much sense gameplay-wise. It ended up
going quite a bit further.
- Aggregate now gets wet in stack form. Swimming with dry
concrete now has consequences.
- Lux reactions, radiation, and infusion should now behave more
consistently.
- Sponges can now wet or dry in stack form, including inside
containers.
- Torch ignition, quenching, and extinguishing is now more
consistent regardless of context, and torches are now more
dangerous, and can ignite things in more contexts.
2019-10-29 20:03:00 -04:00
|
|
|
end
|
2019-10-13 11:37:36 -04:00
|
|
|
})
|