00aa460942
- Player hp_max is 8 now, so most injuries will block a whole slot each time. - Player can be reduced to 1 slot, not 2. The 2 slots was from back in the day when players needed to go to the surface to heal faster, to help them get up there. Now the 1 slot is only needed in case the player is trapped in fire or something. - Damage effects now don't stop playing just because the player has reached maximum injury, and healing is also delayed by continued injury.
113 lines
2.7 KiB
Lua
113 lines
2.7 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local math, minetest, nodecore, pairs, table
|
|
= math, minetest, nodecore, pairs, table
|
|
local math_floor, math_random, table_remove, table_sort
|
|
= math.floor, math.random, table.remove, table.sort
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
nodecore.register_healthfx,
|
|
nodecore.registered_healthfx
|
|
= nodecore.mkreg()
|
|
|
|
local function pickend(q)
|
|
for i = q, 1, -1 do
|
|
if math_random() < 0.5 then return i end
|
|
end
|
|
return pickend(q)
|
|
end
|
|
|
|
local function rounddist(n)
|
|
n = n - math_floor(n)
|
|
if n < 0.5 then return n end
|
|
return 1 - n
|
|
end
|
|
|
|
local function checkinv(player)
|
|
local dmg = minetest.settings:get_bool("enable_damage")
|
|
local inv = player:get_inventory()
|
|
local size = inv:get_size("main")
|
|
local max = size - 1
|
|
|
|
local items = {}
|
|
for _, def in pairs(nodecore.registered_healthfx) do
|
|
items[def.item] = {}
|
|
end
|
|
|
|
local reg = {}
|
|
for i = 1, size do
|
|
local name = inv:get_stack("main", i):get_name()
|
|
local tbl = items[name]
|
|
if tbl then
|
|
tbl[#tbl + 1] = i
|
|
else
|
|
reg[#reg + 1] = i
|
|
end
|
|
end
|
|
|
|
local slots = {}
|
|
local total = 0
|
|
for _, def in pairs(nodecore.registered_healthfx) do
|
|
local q = dmg and (def.getqty(player) * (max + 1) - 1) or 0
|
|
if q > max then q = max end
|
|
if q < 0 then q = 0 end
|
|
slots[#slots + 1] = {item = def.item, qty = size - q}
|
|
total = total + 1
|
|
end
|
|
if total > max then
|
|
for _, v in pairs(slots) do
|
|
v.qty = v.qty * max / total
|
|
end
|
|
table_sort(slots, function(a, b) return rounddist(a.qty) < rounddist(b.qty) end)
|
|
local resid = 0
|
|
for _, v in pairs(slots) do
|
|
resid = resid + v.qty - math_floor(v.qty)
|
|
if resid > 0.5 then
|
|
v.qty = v.qty + 1
|
|
resid = resid - 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local slotidx = {}
|
|
for _, v in pairs(slots) do slotidx[v.item] = math_floor(v.qty) end
|
|
|
|
for _, def in pairs(nodecore.registered_healthfx) do
|
|
local need = slotidx[def.item]
|
|
|
|
if #reg > need then
|
|
local pos = player:get_pos()
|
|
while #reg > need do
|
|
local n = pickend(#reg)
|
|
local i = reg[n]
|
|
table_remove(reg, n)
|
|
local stack = inv:get_stack("main", i)
|
|
if not nodecore.item_is_virtual(stack) then
|
|
nodecore.item_eject(pos, stack, 5)
|
|
end
|
|
inv:set_stack("main", i, def.item)
|
|
end
|
|
return
|
|
end
|
|
|
|
local inj = items[def.item]
|
|
local fill = size - need
|
|
if #inj > fill then
|
|
for i = 1, #inj / 2 do
|
|
inj[i], inj[#inj + 1 - i] = inj[#inj + 1 - i], inj[i]
|
|
end
|
|
while #inj > fill do
|
|
local n = pickend(#inj)
|
|
local i = inj[n]
|
|
table_remove(inj, n)
|
|
inv:set_stack("main", i, "")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_globalstep(function()
|
|
for _, p in pairs(minetest.get_connected_players()) do
|
|
if p:get_hp() > 0 then checkinv(p) end
|
|
end
|
|
end)
|