2 if minetest
.global_exists("intllib") then
3 if intllib
.make_gettext_pair
then
4 S
= intllib
.make_gettext_pair()
9 S
= function ( s
) return s
end
16 -- number of registered HUD bars
19 -- table which records which HUD bar slots have been “registered” so far; used for automatic positioning
20 hb
.registered_slots
= {}
24 function hb
.load_setting(sname
, stype
, defaultval
, valid_values
)
26 if stype
== "string" then
27 sval
= minetest
.settings
:get(sname
)
28 elseif stype
== "bool" then
29 sval
= minetest
.settings
:get_bool(sname
)
30 elseif stype
== "number" then
31 sval
= tonumber(minetest
.settings
:get(sname
))
34 if valid_values
~= nil then
36 for i
=1,#valid_values
do
37 if sval
== valid_values
[i
] then
42 minetest
.log("error", "[hudbars] Invalid value for "..sname
.."! Using default value ("..tostring(defaultval
)..").")
55 -- Load default settings
56 dofile(minetest
.get_modpath("hudbars").."/default_settings.lua")
58 local function player_exists(player
)
59 return player
~= nil and player
:is_player()
62 -- Table which contains all players with active default HUD bars (only for internal use)
65 function hb
.value_to_barlength(value
, max)
69 if hb
.settings
.bar_type
== "progress_bar" then
71 if value
< 0 then x
=-0.5 else x
= 0.5 end
72 local ret
= math
.modf((value
/max) * hb
.settings
.max_bar_length
+ x
)
76 if value
< 0 then x
=-0.5 else x
= 0.5 end
77 local ret
= math
.modf((value
/max) * hb
.settings
.statbar_length
+ x
)
83 function hb
.get_hudtable(identifier
)
84 return hb
.hudtables
[identifier
]
87 function hb
.get_hudbar_position_index(identifier
)
88 if hb
.settings
.sorting
[identifier
] ~= nil then
89 return hb
.settings
.sorting
[identifier
]
93 if hb
.registered_slots
[i
] ~= true and hb
.settings
.sorting_reverse
[i
] == nil then
101 function hb
.register_hudbar(identifier
, text_color
, label
, textures
, default_start_value
, default_start_max
, default_start_hidden
, format_string
)
102 minetest
.log("action", "hb.register_hudbar: "..tostring(identifier
))
105 local index
= math
.floor(hb
.get_hudbar_position_index(identifier
))
106 hb
.registered_slots
[index
] = true
107 if hb
.settings
.alignment_pattern
== "stack_up" then
108 pos
= hb
.settings
.pos_left
110 x
= hb
.settings
.start_offset_left
.x
,
111 y
= hb
.settings
.start_offset_left
.y
- hb
.settings
.vmargin
* index
113 elseif hb
.settings
.alignment_pattern
== "stack_down" then
114 pos
= hb
.settings
.pos_left
116 x
= hb
.settings
.start_offset_left
.x
,
117 y
= hb
.settings
.start_offset_left
.y
+ hb
.settings
.vmargin
* index
120 if index
% 2 == 0 then
121 pos
= hb
.settings
.pos_left
123 x
= hb
.settings
.start_offset_left
.x
,
124 y
= hb
.settings
.start_offset_left
.y
- hb
.settings
.vmargin
* (index
/2)
127 pos
= hb
.settings
.pos_right
129 x
= hb
.settings
.start_offset_right
.x
,
130 y
= hb
.settings
.start_offset_right
.y
- hb
.settings
.vmargin
* ((index
-1)/2)
134 if format_string
== nil then
135 format_string
= S("%s: %d/%d")
138 hudtable
.add_all
= function(player
, hudtable
, start_value
, start_max
, start_hidden
)
139 if start_value
== nil then start_value
= hudtable
.default_start_value
end
140 if start_max
== nil then start_max
= hudtable
.default_start_max
end
141 if start_hidden
== nil then start_hidden
= hudtable
.default_start_hidden
end
144 local name
= player
:get_player_name()
145 local bgscale
, iconscale
, text
, barnumber
, bgiconnumber
146 if start_max
== 0 or start_hidden
then
147 bgscale
= { x
=0, y
=0 }
149 bgscale
= { x
=1, y
=1 }
152 iconscale
= { x
=0, y
=0 }
157 iconscale
= { x
=1, y
=1 }
158 barnumber
= hb
.value_to_barlength(start_value
, start_max
)
159 bgiconnumber
= hb
.settings
.statbar_length
160 text
= string.format(format_string
, label
, start_value
, start_max
)
162 if hb
.settings
.bar_type
== "progress_bar" then
163 ids
.bg
= player
:hud_add({
164 hud_elem_type
= "image",
167 text
= "hudbars_bar_background.png",
168 alignment
= {x
=1,y
=1},
169 offset
= { x
= offset
.x
- 1, y
= offset
.y
- 1 },
171 if textures
.icon
~= nil then
172 ids
.icon
= player
:hud_add({
173 hud_elem_type
= "image",
176 text
= textures
.icon
,
177 alignment
= {x
=-1,y
=1},
178 offset
= { x
= offset
.x
- 3, y
= offset
.y
},
181 elseif hb
.settings
.bar_type
== "statbar_modern" then
182 if textures
.bgicon
~= nil then
183 ids
.bg
= player
:hud_add({
184 hud_elem_type
= "statbar",
186 text
= textures
.bgicon
,
187 number = bgiconnumber
,
188 alignment
= {x
=-1,y
=-1},
189 offset
= { x
= offset
.x
, y
= offset
.y
},
195 local bar_image
, bar_size
196 if hb
.settings
.bar_type
== "progress_bar" then
197 bar_image
= textures
.bar
199 elseif hb
.settings
.bar_type
== "statbar_classic" or hb
.settings
.bar_type
== "statbar_modern" then
200 bar_image
= textures
.icon
201 bar_size
= {x
=24, y
=24}
203 ids
.bar
= player
:hud_add({
204 hud_elem_type
= "statbar",
208 alignment
= {x
=-1,y
=-1},
213 if hb
.settings
.bar_type
== "progress_bar" then
214 ids
.text
= player
:hud_add({
215 hud_elem_type
= "text",
218 alignment
= {x
=1,y
=1},
221 offset
= { x
= offset
.x
+ 2, y
= offset
.y
- 1},
224 -- Do not forget to update hb.get_hudbar_state if you add new fields to the state table
225 state
.hidden
= start_hidden
226 state
.value
= start_value
227 state
.max = start_max
229 state
.barlength
= hb
.value_to_barlength(start_value
, start_max
)
231 local main_error_text
=
232 "[hudbars] Bad initial values of HUD bar identifier “"..tostring(identifier
).."” for player "..name
..". "
234 if start_max
< start_value
then
235 minetest
.log("error", main_error_text
.."start_max ("..start_max
..") is smaller than start_value ("..start_value
..")!")
237 if start_max
< 0 then
238 minetest
.log("error", main_error_text
.."start_max ("..start_max
..") is smaller than 0!")
240 if start_value
< 0 then
241 minetest
.log("error", main_error_text
.."start_value ("..start_value
..") is smaller than 0!")
244 hb
.hudtables
[identifier
].hudids
[name
] = ids
245 hb
.hudtables
[identifier
].hudstate
[name
] = state
248 hudtable
.identifier
= identifier
249 hudtable
.format_string
= format_string
250 hudtable
.label
= label
252 hudtable
.hudstate
= {}
253 hudtable
.default_start_hidden
= default_start_hidden
254 hudtable
.default_start_value
= default_start_value
255 hudtable
.default_start_max
= default_start_max
257 hb
.hudbars_count
= hb
.hudbars_count
+ 1
259 hb
.hudtables
[identifier
] = hudtable
262 function hb
.init_hudbar(player
, identifier
, start_value
, start_max
, start_hidden
)
263 if not player_exists(player
) then return false end
264 local hudtable
= hb
.get_hudtable(identifier
)
265 hb
.hudtables
[identifier
].add_all(player
, hudtable
, start_value
, start_max
, start_hidden
)
269 function hb
.change_hudbar(player
, identifier
, new_value
, new_max_value
, new_icon
, new_bgicon
, new_bar
, new_label
, new_text_color
)
270 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
273 if not player_exists(player
) then
277 local name
= player
:get_player_name()
278 local hudtable
= hb
.get_hudtable(identifier
)
279 local value_changed
, max_changed
= false, false
281 if new_value
~= nil then
282 if new_value
~= hudtable
.hudstate
[name
].value
then
283 hudtable
.hudstate
[name
].value
= new_value
287 new_value
= hudtable
.hudstate
[name
].value
289 if new_max_value
~= nil then
290 if new_max_value
~= hudtable
.hudstate
[name
].max then
291 hudtable
.hudstate
[name
].max = new_max_value
295 new_max_value
= hudtable
.hudstate
[name
].max
298 if hb
.settings
.bar_type
== "progress_bar" then
299 if new_icon
~= nil and hudtable
.hudids
[name
].icon
~= nil then
300 player
:hud_change(hudtable
.hudids
[name
].icon
, "text", new_icon
)
302 if new_bgicon
~= nil and hudtable
.hudids
[name
].bgicon
~= nil then
303 player
:hud_change(hudtable
.hudids
[name
].bgicon
, "text", new_bgicon
)
305 if new_bar
~= nil then
306 player
:hud_change(hudtable
.hudids
[name
].bar
, "text", new_bar
)
308 if new_label
~= nil then
309 hudtable
.label
= new_label
310 local new_text
= string.format(hudtable
.format_string
, new_label
, hudtable
.hudstate
[name
].value
, hudtable
.hudstate
[name
].max)
311 player
:hud_change(hudtable
.hudids
[name
].text
, "text", new_text
)
313 if new_text_color
~= nil then
314 player
:hud_change(hudtable
.hudids
[name
].text
, "number", new_text_color
)
317 if new_icon
~= nil and hudtable
.hudids
[name
].bar
~= nil then
318 player
:hud_change(hudtable
.hudids
[name
].bar
, "text", new_icon
)
320 if new_bgicon
~= nil and hudtable
.hudids
[name
].bg
~= nil then
321 player
:hud_change(hudtable
.hudids
[name
].bg
, "text", new_bgicon
)
325 local main_error_text
=
326 "[hudbars] Bad call to hb.change_hudbar, identifier: “"..tostring(identifier
).."”, player name: “"..name
.."”. "
327 if new_max_value
< new_value
then
328 minetest
.log("error", main_error_text
.."new_max_value ("..new_max_value
..") is smaller than new_value ("..new_value
..")!")
330 if new_max_value
< 0 then
331 minetest
.log("error", main_error_text
.."new_max_value ("..new_max_value
..") is smaller than 0!")
333 if new_value
< 0 then
334 minetest
.log("error", main_error_text
.."new_value ("..new_value
..") is smaller than 0!")
337 if hudtable
.hudstate
[name
].hidden
== false then
338 if max_changed
and hb
.settings
.bar_type
== "progress_bar" then
339 if hudtable
.hudstate
[name
].max == 0 then
340 player
:hud_change(hudtable
.hudids
[name
].bg
, "scale", {x
=0,y
=0})
342 player
:hud_change(hudtable
.hudids
[name
].bg
, "scale", {x
=1,y
=1})
346 if value_changed
or max_changed
then
347 local new_barlength
= hb
.value_to_barlength(new_value
, new_max_value
)
348 if new_barlength
~= hudtable
.hudstate
[name
].barlength
then
349 player
:hud_change(hudtable
.hudids
[name
].bar
, "number", hb
.value_to_barlength(new_value
, new_max_value
))
350 hudtable
.hudstate
[name
].barlength
= new_barlength
353 if hb
.settings
.bar_type
== "progress_bar" then
354 local new_text
= string.format(hudtable
.format_string
, hudtable
.label
, new_value
, new_max_value
)
355 if new_text
~= hudtable
.hudstate
[name
].text
then
356 player
:hud_change(hudtable
.hudids
[name
].text
, "text", new_text
)
357 hudtable
.hudstate
[name
].text
= new_text
365 function hb
.hide_hudbar(player
, identifier
)
366 if not player_exists(player
) then return false end
367 local name
= player
:get_player_name()
368 local hudtable
= hb
.get_hudtable(identifier
)
369 if hudtable
== nil then return false end
370 if(hudtable
.hudstate
[name
].hidden
== false) then
371 if hb
.settings
.bar_type
== "progress_bar" then
372 if hudtable
.hudids
[name
].icon
~= nil then
373 player
:hud_change(hudtable
.hudids
[name
].icon
, "scale", {x
=0,y
=0})
375 player
:hud_change(hudtable
.hudids
[name
].bg
, "scale", {x
=0,y
=0})
376 player
:hud_change(hudtable
.hudids
[name
].text
, "text", "")
377 elseif hb
.settings
.bar_type
== "statbar_modern" then
378 player
:hud_change(hudtable
.hudids
[name
].bg
, "number", 0)
380 player
:hud_change(hudtable
.hudids
[name
].bar
, "number", 0)
381 hudtable
.hudstate
[name
].hidden
= true
386 function hb
.unhide_hudbar(player
, identifier
)
387 if not player_exists(player
) then return false end
388 local name
= player
:get_player_name()
389 local hudtable
= hb
.get_hudtable(identifier
)
390 if hudtable
== nil then return false end
391 if(hudtable
.hudstate
[name
].hidden
) then
392 local value
= hudtable
.hudstate
[name
].value
393 local max = hudtable
.hudstate
[name
].max
394 if hb
.settings
.bar_type
== "progress_bar" then
395 if hudtable
.hudids
[name
].icon
~= nil then
396 player
:hud_change(hudtable
.hudids
[name
].icon
, "scale", {x
=1,y
=1})
398 if hudtable
.hudstate
[name
].max ~= 0 then
399 player
:hud_change(hudtable
.hudids
[name
].bg
, "scale", {x
=1,y
=1})
401 player
:hud_change(hudtable
.hudids
[name
].text
, "text", tostring(string.format(hudtable
.format_string
, hudtable
.label
, value
, max)))
402 elseif hb
.settings
.bar_type
== "statbar_modern" then
403 player
:hud_change(hudtable
.hudids
[name
].bg
, "number", hb
.settings
.statbar_length
)
405 player
:hud_change(hudtable
.hudids
[name
].bar
, "number", hb
.value_to_barlength(value
, max))
406 hudtable
.hudstate
[name
].hidden
= false
411 function hb
.get_hudbar_state(player
, identifier
)
412 if not player_exists(player
) then return nil end
413 local ref
= hb
.get_hudtable(identifier
).hudstate
[player
:get_player_name()]
414 -- Do not forget to update this chunk of code in case the state changes
420 barlength
= ref
.barlength
,
425 function hb
.get_hudbar_identifiers()
427 for id
, _
in pairs(hb
.hudtables
) do
428 table.insert(ids
, id
)
433 --register built-in HUD bars
434 if minetest
.settings
:get_bool("enable_damage") or hb
.settings
.forceload_default_hudbars
then
435 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)
436 hb
.register_hudbar("breath", 0xFFFFFF, S("Breath"), { bar
= "hudbars_bar_breath.png", icon
= "hudbars_icon_breath.png", bgicon
= "hudbars_bgicon_breath.png" }, 10, 10, true)
439 local function hide_builtin(player
)
440 local flags
= player
:hud_get_flags()
441 flags
.healthbar
= false
442 flags
.breathbar
= false
443 player
:hud_set_flags(flags
)
447 local function custom_hud(player
)
448 if minetest
.settings
:get_bool("enable_damage") or hb
.settings
.forceload_default_hudbars
then
450 if minetest
.settings
:get_bool("enable_damage") then
455 hb
.init_hudbar(player
, "health", player
:get_hp(), nil, hide
)
456 local breath
= player
:get_breath()
458 if breath
== 11 and hb
.settings
.autohide_breath
== true then hide_breath
= true else hide_breath
= false end
459 hb
.init_hudbar(player
, "breath", math
.min(breath
, 10), nil, hide_breath
or hide
)
463 local function update_health(player
)
464 hb
.change_hudbar(player
, "health", player
:get_hp())
467 -- update built-in HUD bars
468 local function update_hud(player
)
469 if not player_exists(player
) then return end
470 if minetest
.settings
:get_bool("enable_damage") then
471 if hb
.settings
.forceload_default_hudbars
then
472 hb
.unhide_hudbar(player
, "health")
475 local breath
= player
:get_breath()
477 if breath
== 11 and hb
.settings
.autohide_breath
== true then
478 hb
.hide_hudbar(player
, "breath")
480 hb
.unhide_hudbar(player
, "breath")
481 hb
.change_hudbar(player
, "breath", math
.min(breath
, 10))
484 update_health(player
)
485 elseif hb
.settings
.forceload_default_hudbars
then
486 hb
.hide_hudbar(player
, "health")
487 hb
.hide_hudbar(player
, "breath")
491 minetest
.register_on_player_hpchange(function(player
)
492 if hb
.players
[player
:get_player_name()] ~= nil then
493 update_health(player
)
497 minetest
.register_on_respawnplayer(function(player
)
498 update_health(player
)
499 hb
.hide_hudbar(player
, "breath")
502 minetest
.register_on_joinplayer(function(player
)
505 hb
.players
[player
:get_player_name()] = player
508 minetest
.register_on_leaveplayer(function(player
)
509 hb
.players
[player
:get_player_name()] = nil
514 minetest
.register_globalstep(function(dtime
)
515 main_timer
= main_timer
+ dtime
516 timer
= timer
+ dtime
517 if main_timer
> hb
.settings
.tick
or timer
> 4 then
518 if main_timer
> hb
.settings
.tick
then main_timer
= 0 end
519 -- only proceed if damage is enabled
520 if minetest
.settings
:get_bool("enable_damage") or hb
.settings
.forceload_default_hudbars
then
521 for _
, player
in pairs(hb
.players
) do
522 -- update all hud elements
527 if timer
> 4 then timer
= 0 end