Aaron Suen 828312d452 Cache to account for metadata jitteriness.
It seems that when we access metadata too rapidly
it pulls data out of order or something, so that the
player damage time stuff is unstable, and healing can
start immediately, or more than 8 seconds later.

Caching this stuff manually seems to work around the
issue, and it seems that the metadata system is at
least EVENTUALLY consistent, so it's still good for
long-term use or across world unloads.
2020-02-19 21:05:20 -05:00

71 lines
2.1 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs
= minetest, nodecore, pairs
-- LUALOCALS > ---------------------------------------------------------
local hurtcache = {}
minetest.register_on_player_hpchange(function(player, hp, reason)
local orig = player:get_hp()
if reason and reason.type == "drown" then hp = hp * 2 end
if player:get_armor_groups().immortal then
return orig
end
local pname
if hp < 0 then
pname = player:get_player_name()
hurtcache[pname] = nodecore.gametime
player:get_meta():set_float("hurttime", nodecore.gametime)
if nodecore.player_visible(player) then
minetest.after(0, function()
local now = player:get_hp()
if now >= orig then return end
nodecore.sound_play_except("player_damage", {
pos = player:get_pos(),
gain = 0.5
}, player)
end)
end
end
if hp + orig <= 0 then
hp = 2 - orig
player:get_meta():set_float("dhp", -2)
pname = pname or player:get_player_name()
minetest.after(0, function()
player = minetest.get_player_by_name(pname)
if player then return nodecore.addphealth(player, 0) end
end)
end
return hp
end,
true
)
minetest.register_on_dieplayer(function(player)
player:set_hp(1)
player:get_meta():set_float("dhp", -1)
end)
local full = {}
local function heal(player, dtime)
local hpmax = player:get_properties().hp_max
if player:get_hp() <= 0 then return end
if player:get_breath() <= 0 then return end
local pname = player:get_player_name()
if full[pname] and player:get_hp() >= hpmax then return end
full[pname] = nil
local hurt = hurtcache[pname] or player:get_meta():get_float("hurttime")
if hurt >= nodecore.gametime - 4 then return end
nodecore.addphealth(player, dtime * 2)
if nodecore.getphealth(player) >= hpmax then full[pname] = true end
end
minetest.register_globalstep(function(dtime)
for _, player in pairs(minetest.get_connected_players()) do
heal(player, dtime)
end
end)
minetest.register_on_joinplayer(function(player)
player:set_properties({hp_max = 8})
end)