minetest_hudbars/init.lua

414 lines
13 KiB
Lua
Raw Normal View History

hb = {}
2013-06-28 22:58:06 +02:00
hb.hudtables = {}
2015-02-04 17:26:43 +01:00
-- number of registered HUD bars
hb.hudbars_count = 0
2015-02-04 17:26:43 +01:00
2015-05-19 21:40:54 +02:00
-- table which recoreds which HUD bar slots have been “registered” so far; used for automatic positioning
hb.registered_slots = {}
2015-02-12 05:22:08 +01:00
hb.settings = {}
-- default settings
2015-02-12 05:22:08 +01:00
hb.settings.max_bar_length = 160
2015-02-12 03:00:58 +01:00
-- statbar positions
2015-02-12 05:22:08 +01:00
hb.settings.pos_left = { x=0.5, y=1 }
hb.settings.pos_right= { x = 0.5, y = 1 }
hb.settings.start_offset_left = { x = -175, y = -86 }
hb.settings.start_offset_right = { x = 15, y = -86 }
2015-02-04 17:26:43 +01:00
2015-02-12 05:22:08 +01:00
hb.settings.vmargin = 24
hb.settings.tick = 0.1
--[[
- hudbars_display_mode: This setting changes the way the HUD bars are ordered on the display. You can choose
between a zig-zag pattern or a vertically stacked pattern.
The following values are allowed:
zigzag: Starting from the left bottom, the next is right from the first,
the next is above the first, the next is right of the third, etc.
This is the default.
stack_up: The HUD bars are stacked vertically, going upwards.
stack_down: The HUD bars are stacked vertically. going downwards.
]]
hb.settings.display_mode = "zigzag"
local display_mode = minetest.setting_getbool("hudbars_display_mode")
if display_mode ~= nil then
hb.settings.display_mode = display_mode
if display_mode ~= "zigzag" and display_mode ~= "stack_up" and display_mode ~= "stack_down" then
minetest.log("error", "[hudbars] Invalid value for hudbars_display_mode! Using default (zigzag).")
end
end
hb.settings.autohide_breath = true
local autohide_breath = minetest.setting_getbool("hudbars_autohide_breath")
if autohide_breath ~= nil then
hb.settings.autohide_breath = autohide_breath
end
2015-05-19 21:40:54 +02:00
local sorting = minetest.setting_get("hudbars_sorting")
if sorting ~= nil then
hb.settings.sorting = {}
hb.settings.sorting_reverse = {}
for k,v in string.gmatch(sorting, "(%w+)=(%w+)") do
hb.settings.sorting[k] = tonumber(v)
hb.settings.sorting_reverse[tonumber(v)] = k
end
else
hb.settings.sorting = { ["health"] = 0, ["breath"] = 1 }
hb.settings.sorting_reverse = { [0] = "health", [1] = "breath" }
end
2015-02-14 09:49:13 +01:00
-- Table which contains all players with active default HUD bars (only for internal use)
hb.players = {}
function hb.value_to_barlength(value, max)
if max == 0 then
return 0
else
2015-02-12 05:22:08 +01:00
return math.ceil((value/max) * hb.settings.max_bar_length)
end
end
function hb.get_hudtable(identifier)
return hb.hudtables[identifier]
end
2015-05-19 21:40:54 +02:00
function hb.get_hudbar_position_index(identifier)
if hb.settings.sorting[identifier] ~= nil then
return hb.settings.sorting[identifier]
else
local i = 0
while true do
if hb.registered_slots[i] ~= true and hb.settings.sorting_reverse[i] == nil then
return i
end
i = i + 1
end
end
end
function hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string)
local hudtable = {}
2015-02-04 17:26:43 +01:00
local pos, offset
2015-05-19 21:40:54 +02:00
local index = math.floor(hb.get_hudbar_position_index(identifier))
hb.registered_slots[index] = true
if hb.settings.display_mode == "stack_up" then
2015-02-12 05:22:08 +01:00
pos = hb.settings.pos_left
2015-02-04 17:26:43 +01:00
offset = {
2015-02-12 05:22:08 +01:00
x = hb.settings.start_offset_left.x,
y = hb.settings.start_offset_left.y - hb.settings.vmargin * index
2015-02-04 17:26:43 +01:00
}
elseif hb.settings.display_mode == "stack_down" then
pos = hb.settings.pos_left
2015-02-04 17:26:43 +01:00
offset = {
x = hb.settings.start_offset_left.x,
y = hb.settings.start_offset_left.y + hb.settings.vmargin * index
2015-02-04 17:26:43 +01:00
}
else
if index % 2 == 0 then
pos = hb.settings.pos_left
offset = {
x = hb.settings.start_offset_left.x,
y = hb.settings.start_offset_left.y - hb.settings.vmargin * (index/2)
}
else
pos = hb.settings.pos_right
offset = {
x = hb.settings.start_offset_right.x,
y = hb.settings.start_offset_right.y - hb.settings.vmargin * ((index-1)/2)
}
end
2015-02-04 17:26:43 +01:00
end
if format_string == nil then
format_string = "%s: %d/%d"
end
2015-02-12 19:50:23 +01:00
hudtable.add_all = function(player, hudtable, start_value, start_max, start_hidden)
if start_value == nil then start_value = hudtable.default_start_value end
if start_max == nil then start_max = hudtable.default_start_max end
if start_hidden == nil then start_hidden = hudtable.default_start_hidden end
local ids = {}
2015-02-04 16:16:48 +01:00
local state = {}
local name = player:get_player_name()
2015-02-12 03:15:00 +01:00
local bgscale, iconscale, text, barnumber
if start_max == 0 or start_hidden then
2015-02-04 21:39:52 +01:00
bgscale = { x=0, y=0 }
else
bgscale = { x=1, y=1 }
end
2015-02-12 03:15:00 +01:00
if start_hidden then
iconscale = { x=0, y=0 }
barnumber = 0
text = ""
else
iconscale = { x=1, y=1 }
barnumber = hb.value_to_barlength(start_value, start_max)
text = string.format(format_string, label, start_value, start_max)
end
ids.bg = player:hud_add({
hud_elem_type = "image",
position = pos,
2015-02-04 21:39:52 +01:00
scale = bgscale,
text = "hudbars_bar_background.png",
alignment = {x=1,y=1},
offset = { x = offset.x - 1, y = offset.y - 1 },
})
if textures.icon ~= nil then
ids.icon = player:hud_add({
hud_elem_type = "image",
position = pos,
2015-02-12 03:15:00 +01:00
scale = iconscale,
text = textures.icon,
alignment = {x=-1,y=1},
offset = { x = offset.x - 3, y = offset.y },
})
end
ids.bar = player:hud_add({
hud_elem_type = "statbar",
position = pos,
text = textures.bar,
2015-02-12 03:15:00 +01:00
number = barnumber,
alignment = {x=-1,y=-1},
offset = offset,
})
ids.text = player:hud_add({
hud_elem_type = "text",
position = pos,
text = text,
alignment = {x=1,y=1},
number = text_color,
direction = 0,
offset = { x = offset.x + 2, y = offset.y },
})
2015-02-12 04:26:39 +01:00
-- Do not forget to update hb.get_hudbar_state if you add new fields to the state table
state.hidden = start_hidden
2015-02-04 16:16:48 +01:00
state.value = start_value
state.max = start_max
state.text = text
state.barlength = hb.value_to_barlength(start_value, start_max)
2015-02-12 05:49:30 +01:00
local main_error_text =
"[hudbars] Bad initial values of HUD bar identifier “"..tostring(identifier).."” for player "..name..". "
if start_max < start_value then
2015-02-12 05:49:30 +01:00
minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than start_value ("..start_value..")!")
end
if start_max < 0 then
2015-02-12 05:49:30 +01:00
minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than 0!")
end
if start_value < 0 then
2015-02-12 05:49:30 +01:00
minetest.log("error", main_error_text.."start_value ("..start_value..") is smaller than 0!")
end
hb.hudtables[identifier].hudids[name] = ids
hb.hudtables[identifier].hudstate[name] = state
end
hudtable.identifier = identifier
hudtable.format_string = format_string
hudtable.label = label
hudtable.hudids = {}
2015-02-04 16:16:48 +01:00
hudtable.hudstate = {}
2015-02-12 19:50:23 +01:00
hudtable.default_start_hidden = default_start_hidden
hudtable.default_start_value = default_start_value
hudtable.default_start_max = default_start_max
2015-02-04 17:26:43 +01:00
hb.hudbars_count= hb.hudbars_count + 1
hb.hudtables[identifier] = hudtable
end
function hb.init_hudbar(player, identifier, start_value, start_max, start_hidden)
2015-02-12 19:50:23 +01:00
local hudtable = hb.get_hudtable(identifier)
hb.hudtables[identifier].add_all(player, hudtable, start_value, start_max, start_hidden)
end
function hb.change_hudbar(player, identifier, new_value, new_max_value)
if new_value == nil and new_max_value == nil then
return
end
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
local value_changed, max_changed = false, false
if new_value ~= nil then
if new_value ~= hudtable.hudstate[name].value then
hudtable.hudstate[name].value = new_value
value_changed = true
end
else
new_value = hudtable.hudstate[name].value
end
if new_max_value ~= nil then
if new_max_value ~= hudtable.hudstate[name].max then
hudtable.hudstate[name].max = new_max_value
max_changed = true
end
else
new_max_value = hudtable.hudstate[name].max
end
2015-02-12 05:49:30 +01:00
local main_error_text =
"[hudbars] Bad call to hb.change_hudbar, identifier: “"..tostring(identifier).."”, player name: “"..name.."”. "
if new_max_value < new_value then
2015-02-12 05:49:30 +01:00
minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than new_value ("..new_value..")!")
end
if new_max_value < 0 then
2015-02-12 05:49:30 +01:00
minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than 0!")
end
if new_value < 0 then
2015-02-12 05:49:30 +01:00
minetest.log("error", main_error_text.."new_value ("..new_value..") is smaller than 0!")
end
2015-02-04 16:16:48 +01:00
if hudtable.hudstate[name].hidden == false then
if max_changed then
if hudtable.hudstate[name].max == 0 then
player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0})
else
player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1})
end
end
if value_changed or max_changed then
local new_barlength = hb.value_to_barlength(new_value, new_max_value)
if new_barlength ~= hudtable.hudstate[name].barlength then
player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(new_value, new_max_value))
hudtable.hudstate[name].barlength = new_barlength
end
local new_text = string.format(hudtable.format_string, hudtable.label, new_value, new_max_value)
if new_text ~= hudtable.hudstate[name].text then
player:hud_change(hudtable.hudids[name].text, "text", new_text)
hudtable.hudstate[name].text = new_text
end
end
2015-02-04 16:16:48 +01:00
end
end
function hb.hide_hudbar(player, identifier)
2015-02-04 16:16:48 +01:00
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
2015-02-04 16:16:48 +01:00
if(hudtable.hudstate[name].hidden == false) then
2015-02-12 03:18:58 +01:00
if hudtable.hudids[name].icon ~= nil then
player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0})
end
2015-02-04 16:16:48 +01:00
player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0})
player:hud_change(hudtable.hudids[name].bar, "number", 0)
player:hud_change(hudtable.hudids[name].text, "text", "")
hudtable.hudstate[name].hidden = true
end
end
function hb.unhide_hudbar(player, identifier)
2015-02-04 16:16:48 +01:00
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
2015-02-04 16:16:48 +01:00
if(hudtable.hudstate[name].hidden) then
local name = player:get_player_name()
local value = hudtable.hudstate[name].value
local max = hudtable.hudstate[name].max
2015-02-12 03:18:58 +01:00
if hudtable.hudids[name].icon ~= nil then
player:hud_change(hudtable.hudids[name].icon, "scale", {x=1,y=1})
end
2015-02-04 21:39:52 +01:00
if hudtable.hudstate[name].max ~= 0 then
player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1})
end
player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(value, max))
2015-02-04 16:16:48 +01:00
player:hud_change(hudtable.hudids[name].text, "text", tostring(string.format(hudtable.format_string, hudtable.label, value, max)))
hudtable.hudstate[name].hidden = false
end
end
2015-02-12 04:26:39 +01:00
function hb.get_hudbar_state(player, identifier)
local ref = hb.get_hudtable(identifier).hudstate[player:get_player_name()]
-- Do not forget to update this chunk of code in case the state changes
local copy = {
hidden = ref.hidden,
value = ref.value,
max = ref.max,
text = ref.text,
barlength = ref.barlength,
}
return copy
end
2015-02-12 03:00:58 +01:00
--register built-in HUD bars
if minetest.setting_getbool("enable_damage") then
hb.register_hudbar("health", 0xFFFFFF, "Health", { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png" }, 20, 20, false)
hb.register_hudbar("breath", 0xFFFFFF, "Breath", { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png" }, 10, 10, true)
end
--load custom settings
2015-02-09 23:42:56 +01:00
local set = io.open(minetest.get_modpath("hudbars").."/hudbars.conf", "r")
2013-07-20 22:07:24 +02:00
if set then
2015-02-09 23:42:56 +01:00
dofile(minetest.get_modpath("hudbars").."/hudbars.conf")
2013-07-20 22:07:24 +02:00
set:close()
end
2013-06-28 22:58:06 +02:00
local function hide_builtin(player)
local flags = player:hud_get_flags()
flags.healthbar = false
flags.breathbar = false
player:hud_set_flags(flags)
2013-06-28 22:58:06 +02:00
end
2013-06-28 23:03:54 +02:00
local function custom_hud(player)
2015-02-12 03:00:58 +01:00
if minetest.setting_getbool("enable_damage") then
hb.init_hudbar(player, "health", player:get_hp())
local breath = player:get_breath()
local hide_breath
if breath == 11 and hb.settings.autohide_breath == true then hide_breath = true else hide_breath = false end
hb.init_hudbar(player, "breath", math.min(breath, 10), nil, hide_breath)
2015-02-04 04:53:29 +01:00
end
2013-06-28 22:58:06 +02:00
end
2015-02-12 03:00:58 +01:00
-- update built-in HUD bars
2013-06-28 22:58:06 +02:00
local function update_hud(player)
if minetest.setting_getbool("enable_damage") then
--air
local breath = player:get_breath()
if breath == 11 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, 10))
end
--health
hb.change_hudbar(player, "health", player:get_hp())
end
2013-06-28 22:58:06 +02:00
end
minetest.register_on_joinplayer(function(player)
hide_builtin(player)
custom_hud(player)
hb.players[player:get_player_name()] = player
2013-06-28 22:58:06 +02:00
end)
2015-02-14 09:49:13 +01:00
minetest.register_on_leaveplayer(function(player)
hb.players[player:get_player_name()] = nil
end)
2014-04-14 06:51:28 +02:00
local main_timer = 0
2013-06-28 22:58:06 +02:00
local timer = 0
minetest.register_globalstep(function(dtime)
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
for playername, player in pairs(hb.players) do
-- only proceed if damage is enabled
if minetest.setting_getbool("enable_damage") then
-- update all hud elements
update_hud(player)
2013-06-28 22:58:06 +02:00
end
2014-04-14 06:51:28 +02:00
end
end
if timer > 4 then timer = 0 end
2013-06-28 22:58:06 +02:00
end)