62cedd9267
* Fix medkits preventing kills or score from being given on death * Remove HUD
160 lines
4.2 KiB
Lua
160 lines
4.2 KiB
Lua
-- Table of tables indexed by player names, each having three fields:
|
|
-- {
|
|
-- hp: HP at time of left-click + regen_max,
|
|
-- pos: Position of player while initiating the healing process
|
|
-- hud: ID of "healing effect" HUD element
|
|
-- }
|
|
local players = {}
|
|
|
|
local regen_interval = 0.5 -- Time in seconds between each step
|
|
local regen_timer = 0 -- Timer to keep track of regen_interval
|
|
local regen_step = 1 -- Number of HP added every step
|
|
|
|
-- Boolean function for use by other mods to check if a player is healing
|
|
medkits = {}
|
|
function medkits.is_healing(name)
|
|
return players[name] and true or false
|
|
end
|
|
|
|
-- Called when player uses a medkit
|
|
-- Aborts if player is already healing
|
|
local function start_healing(stack, player)
|
|
if not player then
|
|
return
|
|
end
|
|
local name = player:get_player_name()
|
|
local hp = player:get_hp()
|
|
|
|
local hp_max = player:get_properties().hp_max
|
|
if players[name] or hp == hp_max then
|
|
return
|
|
end
|
|
|
|
players[name] = {
|
|
regen_max = hp_max,
|
|
hp = hp,
|
|
pos = player:get_pos(),
|
|
hud = player:hud_add({
|
|
hud_elem_type = "image",
|
|
position = {x = 0.5, y = 0.5},
|
|
scale = {x = -100, y = -100},
|
|
text = "medkit_hud.png"
|
|
})
|
|
}
|
|
|
|
stack:take_item()
|
|
return stack
|
|
end
|
|
|
|
|
|
-- Interrupt reasons:
|
|
-- attack: Attacked another player
|
|
-- move: Moved 1m away from initial healing pos
|
|
-- damage: Damaged by another player
|
|
local function reason_handler(reason)
|
|
if reason == "attack" then
|
|
return " because you attacked other player!"
|
|
elseif reason == "move" then
|
|
return " because you moved!"
|
|
elseif reason == "damage" then
|
|
return " because someone damaged you!"
|
|
else
|
|
return "!"
|
|
end
|
|
end
|
|
|
|
-- Called after regen is complete. Remove additional effects
|
|
-- If interrupted == true, revert to original HP and give back one medkit.
|
|
local function stop_healing(player, interrupted)
|
|
local name = player:get_player_name()
|
|
local info = players[name]
|
|
|
|
players[name] = nil
|
|
if interrupted then
|
|
minetest.chat_send_player(name, minetest.colorize("#FF4444",
|
|
"Your healing was interrupted"..reason_handler(interrupted)))
|
|
player:set_hp(info.hp)
|
|
player:get_inventory():add_item("main", ItemStack("medkits:medkit 1"))
|
|
end
|
|
|
|
player:hud_remove(info.hud)
|
|
end
|
|
|
|
ctf_flag.register_on_precapture(function()
|
|
-- Reset all player states at the end of the match
|
|
for name, info in pairs(players) do
|
|
players[name]=nil
|
|
local player = minetest.get_player_by_name(name)
|
|
if player then
|
|
player:hud_remove(info.hud)
|
|
end
|
|
end
|
|
return true
|
|
end)
|
|
|
|
-- Called after left-click every n seconds (determined by
|
|
-- regen_interval); heals player until player's hp_max
|
|
minetest.register_globalstep(function(dtime)
|
|
regen_timer = regen_timer + dtime
|
|
if regen_timer < regen_interval then
|
|
return
|
|
end
|
|
|
|
for name, info in pairs(players) do
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then
|
|
players[name] = nil
|
|
else
|
|
-- Abort if player moves more than 1m in any direction to
|
|
-- allow players to manually interrupt healing if necessary
|
|
local pos = player:get_pos()
|
|
if vector.distance(pos, info.pos) >= 1 then
|
|
stop_healing(player, "move")
|
|
end
|
|
|
|
-- Stop healing if target reached
|
|
local pstat = players[name]
|
|
if pstat then
|
|
local hp = player:get_hp()
|
|
if hp < pstat.regen_max then
|
|
player:set_hp(math.min(hp + regen_step, pstat.regen_max))
|
|
else
|
|
stop_healing(player)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
regen_timer = 0
|
|
end)
|
|
|
|
-- If player takes damage while healing,
|
|
-- stop regen and revert back to original state
|
|
minetest.register_on_player_hpchange(function(player, hp, reason)
|
|
local name = player:get_player_name()
|
|
if hp < 0 then
|
|
if players[name] then
|
|
player:hud_remove(players[name].hud)
|
|
players[name] = nil -- Don't use stop_healing(), it uses set_hp() and won't allocate deaths or score properly
|
|
end
|
|
if reason and reason.type == "punch" then
|
|
local hitter = reason.object
|
|
if hitter and players[hitter:get_player_name()] then
|
|
stop_healing(hitter, "attack")
|
|
end
|
|
end
|
|
end
|
|
return hp
|
|
end, true)
|
|
|
|
minetest.register_on_leaveplayer(function(player)
|
|
players[player:get_player_name()] = nil
|
|
end)
|
|
|
|
minetest.register_craftitem("medkits:medkit", {
|
|
description = "Medkit",
|
|
inventory_image = "medkit_medkit.png",
|
|
wield_image = "medkit_medkit.png",
|
|
stack_max = 10,
|
|
|
|
on_use = start_healing
|
|
})
|