New lua breath system, respiration enchant and water breating support

This commit is contained in:
WillConker 2024-06-07 16:20:44 +01:00
parent 65d6cb1d83
commit 69bb75036e
5 changed files with 95 additions and 27 deletions

View File

@ -52,3 +52,5 @@ else
hb.settings.sorting_reverse[tonumber(v)] = k
end
end
hb.settings.breath_max = hb.load_setting("mcl_breath_max", "number", 10)

View File

@ -16,6 +16,7 @@ hb = {
settings = {},
-- Table which contains all players with active default HUD bars (only for internal use)
players = {},
breath_time = {},
}
function hb.load_setting(sname, stype, defaultval, valid_values)
@ -499,6 +500,17 @@ local function hide_builtin(player)
player:hud_set_flags(flags)
end
function hb.get_breath(player)
local breath = tonumber(player:get_meta():get_string("mcl_hudbars:breath")) or hb.settings.breath_max
return breath
end
function hb.set_breath(player, value, update_hudbar)
player:get_meta():set_string("mcl_hudbars:breath", tostring(value))
if update_hudbar == true then
update_breath(player)
end
end
local function custom_hud(player)
if minetest.settings:get_bool("enable_damage") or hb.settings.forceload_default_hudbars then
@ -511,8 +523,9 @@ local function custom_hud(player)
local hp = player:get_hp()
local hp_max = player:get_properties().hp_max
hb.init_hudbar(player, "health", math.min(hp, hp_max), hp_max, hide)
local breath = player:get_breath()
local breath_max = player:get_properties().breath_max
local breath = hb.get_breath(player)
local breath_max = hb.settings.breath_max
hb.set_breath(player, math.min(breath_max, math.max(0, breath)))
local hide_breath
if breath >= breath_max and hb.settings.autohide_breath == true then hide_breath = true else hide_breath = false end
hb.init_hudbar(player, "breath", math.min(breath, breath_max), breath_max, hide_breath or hide)
@ -526,23 +539,66 @@ local function update_health(player)
hb.change_hudbar(player, "health", hp, hp_max)
end
local function update_breath(player, in_water)
local breath = hb.get_breath(player)
local breath_max = hb.settings.breath_max
if breath >= breath_max and hb.settings.autohide_breath == true and not in_water then
hb.hide_hudbar(player, "breath")
else
hb.unhide_hudbar(player, "breath")
hb.change_hudbar(player, "breath", math.min(breath, breath_max), breath_max)
end
end
local function do_breath_tick(player, dtime)
-- don't use default breath
player:set_breath(player:get_properties().breath_max)
local breath_max = hb.settings.breath_max
local player_name = player:get_player_name()
local node_head = mcl_playerinfo[player_name].node_head
local in_water = node_head and minetest.get_item_group(node_head, "water") > 0
local current_breath = hb.get_breath(player)
local helmet = player:get_inventory():get_stack("armor", 2)
local respiration = mcl_enchanting.get_enchantment(helmet, "respiration") or 0
local scaled_dtime = dtime / (respiration + 1)
if in_water and not mcl_potions.has_effect(player, "water_breathing") then
-- in water, use respiration scaled_dtime
hb.breath_time[player] = (hb.breath_time[player] or 0) + scaled_dtime
if current_breath > 0 and hb.breath_time[player] > 1.5 then
-- min used to stop breath changing rapidly after extreme server lag
hb.breath_time[player] = math.min(hb.breath_time[player] - 1.5, 1.5)
hb.set_breath(player, current_breath - 1)
elseif current_breath == 0 and hb.breath_time[player] > 1 then
hb.breath_time[player] = math.min(hb.breath_time[player] - 1, 1)
if player:get_hp() > 0 then
mcl_util.deal_damage(player, 2, {type = "drown"})
end
end
else
-- out of water/has water breathing, use normal dtime
hb.breath_time[player] = (hb.breath_time[player] or 0) + dtime
if current_breath == breath_max then hb.breath_time[player] = 0
elseif hb.breath_time[player] > 0.2 then
-- no min here as players should be able to regen breath fast despite server lag
hb.breath_time[player] = hb.breath_time[player] - 0.2
hb.set_breath(player, current_breath + 1)
end
end
return in_water
end
-- update built-in HUD bars
local function update_hud(player, has_damage)
local function update_hud(player, has_damage, in_water)
if not player_exists(player) then return end
if has_damage then
if hb.settings.forceload_default_hudbars then
hb.unhide_hudbar(player, "health")
end
--air
local breath_max = player:get_properties().breath_max
local breath = player:get_breath()
if breath >= breath_max and hb.settings.autohide_breath == true then
hb.hide_hudbar(player, "breath")
else
hb.unhide_hudbar(player, "breath")
hb.change_hudbar(player, "breath", math.min(breath, breath_max), breath_max)
end
update_breath(player, in_water)
--health
update_health(player)
elseif hb.settings.forceload_default_hudbars then
@ -559,10 +615,15 @@ end)
minetest.register_on_respawnplayer(function(player)
update_health(player)
hb.hide_hudbar(player, "breath")
local breath_max = hb.settings.breath_max
hb.breath_time[player] = 0
hb.set_breath(player, breath_max)
update_breath(player)
end)
minetest.register_on_joinplayer(function(player)
-- minetest.debug("Player joined:", player)
hide_builtin(player)
custom_hud(player)
hb.players[player:get_player_name()] = player
@ -570,23 +631,30 @@ end)
minetest.register_on_leaveplayer(function(player)
hb.players[player:get_player_name()] = nil
hb.breath_time[player] = nil
end)
local main_timer = 0
local timer = 0
minetest.register_globalstep(function(dtime)
local is_hud_step = false
local has_dmg
main_timer = main_timer + dtime
timer = timer + dtime
if main_timer > hb.settings.tick or timer > 4 then
if main_timer > hb.settings.tick then main_timer = 0 end
-- only proceed if damage is enabled
local has_dmg = minetest.settings:get_bool("enable_damage")
has_dmg = minetest.settings:get_bool("enable_damage")
if has_dmg or hb.settings.forceload_default_hudbars then
for _, player in pairs(hb.players) do
-- update all hud elements
update_hud(player, has_dmg)
end
is_hud_step = true
end
end
if timer > 4 then timer = 0 end
for _, player in pairs(hb.players) do
-- update all hud elements
local in_water = do_breath_tick(player, dtime)
if is_hud_step then
update_hud(player, has_dmg, in_water)
end
end
end)

View File

@ -586,8 +586,8 @@ mcl_enchanting.enchantments.quick_charge = {
inv_tool_tab = false,
}
-- unimplemented
--[[mcl_enchanting.enchantments.respiration = {
-- implemented in mcl_hudbars
mcl_enchanting.enchantments.respiration = {
name = S("Respiration"),
max_level = 3,
primary = {armor_head = true},
@ -603,7 +603,7 @@ mcl_enchanting.enchantments.quick_charge = {
power_range_table = {{10, 40}, {20, 50}, {30, 60}},
inv_combat_tab = true,
inv_tool_tab = false,
}]]--
}
-- requires missing MineClone2 feature
--[[mcl_enchanting.enchantments.riptide = {

View File

@ -303,12 +303,6 @@ mcl_potions.register_effect({
res_condition = function(object)
return (not object:is_player()) -- TODO add support for breath setting for mobs
end,
on_step = function(dtime, object, factor, duration)
if object:get_breath() then
hb.hide_hudbar(object, "breath")
if object:get_breath() < 10 then object:set_breath(10) end
end
end,
particle_color = "#2E5299",
uses_factor = false,
})

View File

@ -109,6 +109,10 @@ mcl_health_regen_delay (Health regen delay) float 0.5 0
# Default: 1.61 s
mcl_eating_delay (Eating delay) float 1.61 0
# Default breath of players
# Default: 10
mcl_breath_max (Maximum breath) int 10 0
[Mobs]
# If enabled, mobs will spawn naturally. This does not affect
# affect mob spawners.