Add intllib support
[minetest_hudbars.git] / init.lua
blob969dd784cbc8f26b9d7aaaf90dfa98bf72631ea3
1 local S
2 if (minetest.get_modpath("intllib")) then
3 dofile(minetest.get_modpath("intllib").."/intllib.lua")
4 S = intllib.Getter(minetest.get_current_modname())
5 else
6 S = function ( s ) return s end
7 end
9 hb = {}
11 hb.hudtables = {}
13 -- number of registered HUD bars
14 hb.hudbars_count = 0
16 -- table which records which HUD bar slots have been “registered” so far; used for automatic positioning
17 hb.registered_slots = {}
19 hb.settings = {}
21 function hb.load_setting(sname, stype, defaultval, valid_values)
22 local sval
23 if stype == "string" then
24 sval = minetest.setting_get(sname)
25 elseif stype == "bool" then
26 sval = minetest.setting_getbool(sname)
27 elseif stype == "number" then
28 sval = tonumber(minetest.setting_get(sname))
29 end
30 if sval ~= nil then
31 if valid_values ~= nil then
32 local valid = false
33 for i=1,#valid_values do
34 if sval == valid_values[i] then
35 valid = true
36 end
37 end
38 if not valid then
39 minetest.log("error", "[hudbars] Invalid value for "..sname.."! Using default value ("..tostring(defaultval)..").")
40 return defaultval
41 else
42 return sval
43 end
44 else
45 return sval
46 end
47 else
48 return defaultval
49 end
50 end
52 -- (hardcoded) default settings
53 hb.settings.max_bar_length = 160
54 hb.settings.statbar_length = 20
56 -- statbar positions
57 hb.settings.pos_left = {}
58 hb.settings.pos_right = {}
59 hb.settings.start_offset_left = {}
60 hb.settings.start_offset_right= {}
61 hb.settings.pos_left.x = hb.load_setting("hudbars_pos_left_x", "number", 0.5)
62 hb.settings.pos_left.y = hb.load_setting("hudbars_pos_left_y", "number", 1)
63 hb.settings.pos_right.x = hb.load_setting("hudbars_pos_right_x", "number", 0.5)
64 hb.settings.pos_right.y = hb.load_setting("hudbars_pos_right_y", "number", 1)
65 hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_offset_left_x", "number", -175)
66 hb.settings.start_offset_left.y = hb.load_setting("hudbars_start_offset_left_y", "number", -86)
67 hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_offset_right_x", "number", 15)
68 hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_offset_right_y", "number", -86)
70 hb.settings.vmargin = hb.load_setting("hudbars_vmargin", "number", 24)
71 hb.settings.tick = hb.load_setting("hudbars_tick", "number", 0.1)
73 -- experimental setting: Changing this setting is not officially supported, do NOT rely on it!
74 hb.settings.forceload_default_hudbars = hb.load_setting("hudbars_forceload_default_hudbars", "bool", true)
76 -- Misc. settings
77 hb.settings.alignment_pattern = hb.load_setting("hudbars_alignment_pattern", "string", "zigzag", {"zigzag", "stack_up", "stack_down"})
78 hb.settings.bar_type = hb.load_setting("hudbars_bar_type", "string", "progress_bar", {"progress_bar", "statbar_classic", "statbar_modern"})
79 hb.settings.autohide_breath = hb.load_setting("hudbars_autohide_breath", "bool", true)
81 local sorting = minetest.setting_get("hudbars_sorting")
82 if sorting ~= nil then
83 hb.settings.sorting = {}
84 hb.settings.sorting_reverse = {}
85 for k,v in string.gmatch(sorting, "(%w+)=(%w+)") do
86 hb.settings.sorting[k] = tonumber(v)
87 hb.settings.sorting_reverse[tonumber(v)] = k
88 end
89 else
90 hb.settings.sorting = { ["health"] = 0, ["breath"] = 1 }
91 hb.settings.sorting_reverse = { [0] = "health", [1] = "breath" }
92 end
94 -- Table which contains all players with active default HUD bars (only for internal use)
95 hb.players = {}
97 function hb.value_to_barlength(value, max)
98 if max == 0 then
99 return 0
100 else
101 if hb.settings.bar_type == "progress_bar" then
102 local x
103 if value < 0 then x=-0.5 else x = 0.5 end
104 local ret = math.modf((value/max) * hb.settings.max_bar_length + x)
105 return ret
106 else
107 local x
108 if value < 0 then x=-0.5 else x = 0.5 end
109 local ret = math.modf((value/max) * hb.settings.statbar_length + x)
110 return ret
115 function hb.get_hudtable(identifier)
116 return hb.hudtables[identifier]
119 function hb.get_hudbar_position_index(identifier)
120 if hb.settings.sorting[identifier] ~= nil then
121 return hb.settings.sorting[identifier]
122 else
123 local i = 0
124 while true do
125 if hb.registered_slots[i] ~= true and hb.settings.sorting_reverse[i] == nil then
126 return i
128 i = i + 1
133 function hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string)
134 minetest.log("action", "hb.register_hudbar: "..tostring(identifier))
135 local hudtable = {}
136 local pos, offset
137 local index = math.floor(hb.get_hudbar_position_index(identifier))
138 hb.registered_slots[index] = true
139 if hb.settings.alignment_pattern == "stack_up" then
140 pos = hb.settings.pos_left
141 offset = {
142 x = hb.settings.start_offset_left.x,
143 y = hb.settings.start_offset_left.y - hb.settings.vmargin * index
145 elseif hb.settings.alignment_pattern == "stack_down" then
146 pos = hb.settings.pos_left
147 offset = {
148 x = hb.settings.start_offset_left.x,
149 y = hb.settings.start_offset_left.y + hb.settings.vmargin * index
151 else
152 if index % 2 == 0 then
153 pos = hb.settings.pos_left
154 offset = {
155 x = hb.settings.start_offset_left.x,
156 y = hb.settings.start_offset_left.y - hb.settings.vmargin * (index/2)
158 else
159 pos = hb.settings.pos_right
160 offset = {
161 x = hb.settings.start_offset_right.x,
162 y = hb.settings.start_offset_right.y - hb.settings.vmargin * ((index-1)/2)
166 if format_string == nil then
167 format_string = "%s: %d/%d"
170 hudtable.add_all = function(player, hudtable, start_value, start_max, start_hidden)
171 if start_value == nil then start_value = hudtable.default_start_value end
172 if start_max == nil then start_max = hudtable.default_start_max end
173 if start_hidden == nil then start_hidden = hudtable.default_start_hidden end
174 local ids = {}
175 local state = {}
176 local name = player:get_player_name()
177 local bgscale, iconscale, text, barnumber
178 if start_max == 0 or start_hidden then
179 bgscale = { x=0, y=0 }
180 else
181 bgscale = { x=1, y=1 }
183 if start_hidden then
184 iconscale = { x=0, y=0 }
185 barnumber = 0
186 text = ""
187 else
188 iconscale = { x=1, y=1 }
189 barnumber = hb.value_to_barlength(start_value, start_max)
190 text = string.format(format_string, label, start_value, start_max)
192 if hb.settings.bar_type == "progress_bar" then
193 ids.bg = player:hud_add({
194 hud_elem_type = "image",
195 position = pos,
196 scale = bgscale,
197 text = "hudbars_bar_background.png",
198 alignment = {x=1,y=1},
199 offset = { x = offset.x - 1, y = offset.y - 1 },
201 if textures.icon ~= nil then
202 ids.icon = player:hud_add({
203 hud_elem_type = "image",
204 position = pos,
205 scale = iconscale,
206 text = textures.icon,
207 alignment = {x=-1,y=1},
208 offset = { x = offset.x - 3, y = offset.y },
211 elseif hb.settings.bar_type == "statbar_modern" then
212 if textures.bgicon ~= nil then
213 ids.bg = player:hud_add({
214 hud_elem_type = "statbar",
215 position = pos,
216 scale = bgscale,
217 text = textures.bgicon,
218 number = hb.settings.statbar_length,
219 alignment = {x=-1,y=-1},
220 offset = { x = offset.x, y = offset.y },
224 local bar_image
225 if hb.settings.bar_type == "progress_bar" then
226 bar_image = textures.bar
227 elseif hb.settings.bar_type == "statbar_classic" or hb.settings.bar_type == "statbar_modern" then
228 bar_image = textures.icon
230 ids.bar = player:hud_add({
231 hud_elem_type = "statbar",
232 position = pos,
233 text = bar_image,
234 number = barnumber,
235 alignment = {x=-1,y=-1},
236 offset = offset,
238 if hb.settings.bar_type == "progress_bar" then
239 ids.text = player:hud_add({
240 hud_elem_type = "text",
241 position = pos,
242 text = text,
243 alignment = {x=1,y=1},
244 number = text_color,
245 direction = 0,
246 offset = { x = offset.x + 2, y = offset.y },
249 -- Do not forget to update hb.get_hudbar_state if you add new fields to the state table
250 state.hidden = start_hidden
251 state.value = start_value
252 state.max = start_max
253 state.text = text
254 state.barlength = hb.value_to_barlength(start_value, start_max)
256 local main_error_text =
257 "[hudbars] Bad initial values of HUD bar identifier “"..tostring(identifier).."” for player "..name..". "
259 if start_max < start_value then
260 minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than start_value ("..start_value..")!")
262 if start_max < 0 then
263 minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than 0!")
265 if start_value < 0 then
266 minetest.log("error", main_error_text.."start_value ("..start_value..") is smaller than 0!")
269 hb.hudtables[identifier].hudids[name] = ids
270 hb.hudtables[identifier].hudstate[name] = state
273 hudtable.identifier = identifier
274 hudtable.format_string = format_string
275 hudtable.label = label
276 hudtable.hudids = {}
277 hudtable.hudstate = {}
278 hudtable.default_start_hidden = default_start_hidden
279 hudtable.default_start_value = default_start_value
280 hudtable.default_start_max = default_start_max
282 hb.hudbars_count= hb.hudbars_count + 1
284 hb.hudtables[identifier] = hudtable
287 function hb.init_hudbar(player, identifier, start_value, start_max, start_hidden)
288 local hudtable = hb.get_hudtable(identifier)
289 hb.hudtables[identifier].add_all(player, hudtable, start_value, start_max, start_hidden)
292 function hb.change_hudbar(player, identifier, new_value, new_max_value, new_icon, new_bgicon, new_bar, new_label, new_text_color)
293 if new_value == nil and new_max_value == nil and new_icon == nil and new_bgicon == nil and new_bar == nil and new_label == nil and new_text_color == nil then
294 return
297 local name = player:get_player_name()
298 local hudtable = hb.get_hudtable(identifier)
299 local value_changed, max_changed = false, false
301 if new_value ~= nil then
302 if new_value ~= hudtable.hudstate[name].value then
303 hudtable.hudstate[name].value = new_value
304 value_changed = true
306 else
307 new_value = hudtable.hudstate[name].value
309 if new_max_value ~= nil then
310 if new_max_value ~= hudtable.hudstate[name].max then
311 hudtable.hudstate[name].max = new_max_value
312 max_changed = true
314 else
315 new_max_value = hudtable.hudstate[name].max
318 if hb.settings.bar_type == "progress_bar" then
319 if new_icon ~= nil and hudtable.hudids[name].icon ~= nil then
320 player:hud_change(hudtable.hudids[name].icon, "text", new_icon)
322 if new_bgicon ~= nil and hudtable.hudids[name].bgicon ~= nil then
323 player:hud_change(hudtable.hudids[name].bgicon, "text", new_bgicon)
325 if new_bar ~= nil then
326 player:hud_change(hudtable.hudids[name].bar , "text", new_bar)
328 if new_label ~= nil then
329 hudtable.label = new_label
330 local new_text = string.format(hudtable.format_string, new_label, hudtable.hudstate[name].value, hudtable.hudstate[name].max)
331 player:hud_change(hudtable.hudids[name].text, "text", new_text)
333 if new_text_color ~= nil then
334 player:hud_change(hudtable.hudids[name].text, "number", new_text_color)
336 else
337 if new_icon ~= nil and hudtable.hudids[name].bar ~= nil then
338 player:hud_change(hudtable.hudids[name].bar, "text", new_icon)
340 if new_bgicon ~= nil and hudtable.hudids[name].bg ~= nil then
341 player:hud_change(hudtable.hudids[name].bg, "text", new_bgicon)
345 local main_error_text =
346 "[hudbars] Bad call to hb.change_hudbar, identifier: “"..tostring(identifier).."”, player name: “"..name.."”. "
347 if new_max_value < new_value then
348 minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than new_value ("..new_value..")!")
350 if new_max_value < 0 then
351 minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than 0!")
353 if new_value < 0 then
354 minetest.log("error", main_error_text.."new_value ("..new_value..") is smaller than 0!")
357 if hudtable.hudstate[name].hidden == false then
358 if max_changed and hb.settings.bar_type == "progress_bar" then
359 if hudtable.hudstate[name].max == 0 then
360 player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0})
361 else
362 player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1})
366 if value_changed or max_changed then
367 local new_barlength = hb.value_to_barlength(new_value, new_max_value)
368 if new_barlength ~= hudtable.hudstate[name].barlength then
369 player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(new_value, new_max_value))
370 hudtable.hudstate[name].barlength = new_barlength
373 if hb.settings.bar_type == "progress_bar" then
374 local new_text = string.format(hudtable.format_string, hudtable.label, new_value, new_max_value)
375 if new_text ~= hudtable.hudstate[name].text then
376 player:hud_change(hudtable.hudids[name].text, "text", new_text)
377 hudtable.hudstate[name].text = new_text
384 function hb.hide_hudbar(player, identifier)
385 local name = player:get_player_name()
386 local hudtable = hb.get_hudtable(identifier)
387 if(hudtable.hudstate[name].hidden == false) then
388 if hb.settings.bar_type == "progress_bar" then
389 if hudtable.hudids[name].icon ~= nil then
390 player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0})
392 player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0})
393 player:hud_change(hudtable.hudids[name].text, "text", "")
395 player:hud_change(hudtable.hudids[name].bar, "number", 0)
396 hudtable.hudstate[name].hidden = true
400 function hb.unhide_hudbar(player, identifier)
401 local name = player:get_player_name()
402 local hudtable = hb.get_hudtable(identifier)
403 if(hudtable.hudstate[name].hidden) then
404 local name = player:get_player_name()
405 local value = hudtable.hudstate[name].value
406 local max = hudtable.hudstate[name].max
407 if hb.settings.bar_type == "progress_bar" then
408 if hudtable.hudids[name].icon ~= nil then
409 player:hud_change(hudtable.hudids[name].icon, "scale", {x=1,y=1})
411 if hudtable.hudstate[name].max ~= 0 then
412 player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1})
414 player:hud_change(hudtable.hudids[name].text, "text", tostring(string.format(hudtable.format_string, hudtable.label, value, max)))
416 player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(value, max))
417 hudtable.hudstate[name].hidden = false
421 function hb.get_hudbar_state(player, identifier)
422 local ref = hb.get_hudtable(identifier).hudstate[player:get_player_name()]
423 -- Do not forget to update this chunk of code in case the state changes
424 local copy = {
425 hidden = ref.hidden,
426 value = ref.value,
427 max = ref.max,
428 text = ref.text,
429 barlength = ref.barlength,
431 return copy
434 --register built-in HUD bars
435 if minetest.setting_getbool("enable_damage") or hb.settings.forceload_default_hudbars then
436 hb.register_hudbar("health", 0xFFFFFF, S("Health"), { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png", bgicon = "hudbars_bgicon_health.png" }, 20, 20, false)
437 hb.register_hudbar("breath", 0xFFFFFF, S("Breath"), { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png" }, 10, 10, true)
440 local function hide_builtin(player)
441 local flags = player:hud_get_flags()
442 flags.healthbar = false
443 flags.breathbar = false
444 player:hud_set_flags(flags)
448 local function custom_hud(player)
449 if minetest.setting_getbool("enable_damage") or hb.settings.forceload_default_hudbars then
450 local hide
451 if minetest.setting_getbool("enable_damage") then
452 hide = false
453 else
454 hide = true
456 hb.init_hudbar(player, "health", player:get_hp(), nil, hide)
457 local breath = player:get_breath()
458 local hide_breath
459 if breath == 11 and hb.settings.autohide_breath == true then hide_breath = true else hide_breath = false end
460 hb.init_hudbar(player, "breath", math.min(breath, 10), nil, hide_breath or hide)
465 -- update built-in HUD bars
466 local function update_hud(player)
467 if minetest.setting_getbool("enable_damage") then
468 if hb.settings.forceload_default_hudbars then
469 hb.unhide_hudbar(player, "health")
471 --air
472 local breath = player:get_breath()
474 if breath == 11 and hb.settings.autohide_breath == true then
475 hb.hide_hudbar(player, "breath")
476 else
477 hb.unhide_hudbar(player, "breath")
478 hb.change_hudbar(player, "breath", math.min(breath, 10))
481 --health
482 hb.change_hudbar(player, "health", player:get_hp())
483 elseif hb.settings.forceload_default_hudbars then
484 hb.hide_hudbar(player, "health")
485 hb.hide_hudbar(player, "breath")
489 minetest.register_on_joinplayer(function(player)
490 hide_builtin(player)
491 custom_hud(player)
492 hb.players[player:get_player_name()] = player
493 end)
495 minetest.register_on_leaveplayer(function(player)
496 hb.players[player:get_player_name()] = nil
497 end)
499 local main_timer = 0
500 local timer = 0
501 minetest.register_globalstep(function(dtime)
502 main_timer = main_timer + dtime
503 timer = timer + dtime
504 if main_timer > hb.settings.tick or timer > 4 then
505 if main_timer > hb.settings.tick then main_timer = 0 end
506 -- only proceed if damage is enabled
507 if minetest.setting_getbool("enable_damage") or hb.settings.forceload_default_hudbars then
508 for playername, player in pairs(hb.players) do
509 -- update all hud elements
510 update_hud(player)
514 if timer > 4 then timer = 0 end
515 end)