Rename display_mode to alignment_pattern
[minetest_hudbars.git] / init.lua
blobe6dbe8b61088cf88fe945b14a5b3128d988d870e
1 hb = {}
3 hb.hudtables = {}
5 -- number of registered HUD bars
6 hb.hudbars_count = 0
8 -- table which recoreds which HUD bar slots have been “registered” so far; used for automatic positioning
9 hb.registered_slots = {}
11 hb.settings = {}
13 -- default settings
14 hb.settings.max_bar_length = 160
16 -- statbar positions
17 hb.settings.pos_left = { x=0.5, y=1 }
18 hb.settings.pos_right= { x = 0.5, y = 1 }
19 hb.settings.start_offset_left = { x = -175, y = -86 }
20 hb.settings.start_offset_right = { x = 15, y = -86 }
22 hb.settings.vmargin = 24
23 hb.settings.tick = 0.1
25 --[[
26 - hudbars_alignment_pattern: This setting changes the way the HUD bars are ordered on the display. You can choose
27 between a zig-zag pattern or a vertically stacked pattern.
28 The following values are allowed:
29 zigzag: Starting from the left bottom, the next is right from the first,
30 the next is above the first, the next is right of the third, etc.
31 This is the default.
32 stack_up: The HUD bars are stacked vertically, going upwards.
33 stack_down: The HUD bars are stacked vertically. going downwards.
35 hb.settings.alignment_pattern = "zigzag"
36 local alignment_pattern = minetest.setting_getbool("hudbars_alignment_pattern")
37 if alignment_pattern ~= nil then
38 hb.settings.alignment_pattern = alignment_pattern
39 if alignment_pattern ~= "zigzag" and alignment_pattern ~= "stack_up" and alignment_pattern ~= "stack_down" then
40 minetest.log("error", "[hudbars] Invalid value for hudbars_alignment_pattern! Using default (zigzag).")
41 end
42 end
44 hb.settings.autohide_breath = true
45 local autohide_breath = minetest.setting_getbool("hudbars_autohide_breath")
46 if autohide_breath ~= nil then
47 hb.settings.autohide_breath = autohide_breath
48 end
50 local sorting = minetest.setting_get("hudbars_sorting")
51 if sorting ~= nil then
52 hb.settings.sorting = {}
53 hb.settings.sorting_reverse = {}
54 for k,v in string.gmatch(sorting, "(%w+)=(%w+)") do
55 hb.settings.sorting[k] = tonumber(v)
56 hb.settings.sorting_reverse[tonumber(v)] = k
57 end
58 else
59 hb.settings.sorting = { ["health"] = 0, ["breath"] = 1 }
60 hb.settings.sorting_reverse = { [0] = "health", [1] = "breath" }
61 end
63 -- Table which contains all players with active default HUD bars (only for internal use)
64 hb.players = {}
66 function hb.value_to_barlength(value, max)
67 if max == 0 then
68 return 0
69 else
70 return math.ceil((value/max) * hb.settings.max_bar_length)
71 end
72 end
74 function hb.get_hudtable(identifier)
75 return hb.hudtables[identifier]
76 end
78 function hb.get_hudbar_position_index(identifier)
79 if hb.settings.sorting[identifier] ~= nil then
80 return hb.settings.sorting[identifier]
81 else
82 local i = 0
83 while true do
84 if hb.registered_slots[i] ~= true and hb.settings.sorting_reverse[i] == nil then
85 return i
86 end
87 i = i + 1
88 end
89 end
90 end
92 function hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string)
93 local hudtable = {}
94 local pos, offset
95 local index = math.floor(hb.get_hudbar_position_index(identifier))
96 hb.registered_slots[index] = true
97 if hb.settings.alignment_pattern == "stack_up" then
98 pos = hb.settings.pos_left
99 offset = {
100 x = hb.settings.start_offset_left.x,
101 y = hb.settings.start_offset_left.y - hb.settings.vmargin * index
103 elseif hb.settings.alignment_pattern == "stack_down" then
104 pos = hb.settings.pos_left
105 offset = {
106 x = hb.settings.start_offset_left.x,
107 y = hb.settings.start_offset_left.y + hb.settings.vmargin * index
109 else
110 if index % 2 == 0 then
111 pos = hb.settings.pos_left
112 offset = {
113 x = hb.settings.start_offset_left.x,
114 y = hb.settings.start_offset_left.y - hb.settings.vmargin * (index/2)
116 else
117 pos = hb.settings.pos_right
118 offset = {
119 x = hb.settings.start_offset_right.x,
120 y = hb.settings.start_offset_right.y - hb.settings.vmargin * ((index-1)/2)
124 if format_string == nil then
125 format_string = "%s: %d/%d"
128 hudtable.add_all = function(player, hudtable, start_value, start_max, start_hidden)
129 if start_value == nil then start_value = hudtable.default_start_value end
130 if start_max == nil then start_max = hudtable.default_start_max end
131 if start_hidden == nil then start_hidden = hudtable.default_start_hidden end
132 local ids = {}
133 local state = {}
134 local name = player:get_player_name()
135 local bgscale, iconscale, text, barnumber
136 if start_max == 0 or start_hidden then
137 bgscale = { x=0, y=0 }
138 else
139 bgscale = { x=1, y=1 }
141 if start_hidden then
142 iconscale = { x=0, y=0 }
143 barnumber = 0
144 text = ""
145 else
146 iconscale = { x=1, y=1 }
147 barnumber = hb.value_to_barlength(start_value, start_max)
148 text = string.format(format_string, label, start_value, start_max)
150 ids.bg = player:hud_add({
151 hud_elem_type = "image",
152 position = pos,
153 scale = bgscale,
154 text = "hudbars_bar_background.png",
155 alignment = {x=1,y=1},
156 offset = { x = offset.x - 1, y = offset.y - 1 },
158 if textures.icon ~= nil then
159 ids.icon = player:hud_add({
160 hud_elem_type = "image",
161 position = pos,
162 scale = iconscale,
163 text = textures.icon,
164 alignment = {x=-1,y=1},
165 offset = { x = offset.x - 3, y = offset.y },
168 ids.bar = player:hud_add({
169 hud_elem_type = "statbar",
170 position = pos,
171 text = textures.bar,
172 number = barnumber,
173 alignment = {x=-1,y=-1},
174 offset = offset,
176 ids.text = player:hud_add({
177 hud_elem_type = "text",
178 position = pos,
179 text = text,
180 alignment = {x=1,y=1},
181 number = text_color,
182 direction = 0,
183 offset = { x = offset.x + 2, y = offset.y },
185 -- Do not forget to update hb.get_hudbar_state if you add new fields to the state table
186 state.hidden = start_hidden
187 state.value = start_value
188 state.max = start_max
189 state.text = text
190 state.barlength = hb.value_to_barlength(start_value, start_max)
192 local main_error_text =
193 "[hudbars] Bad initial values of HUD bar identifier “"..tostring(identifier).."” for player "..name..". "
195 if start_max < start_value then
196 minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than start_value ("..start_value..")!")
198 if start_max < 0 then
199 minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than 0!")
201 if start_value < 0 then
202 minetest.log("error", main_error_text.."start_value ("..start_value..") is smaller than 0!")
205 hb.hudtables[identifier].hudids[name] = ids
206 hb.hudtables[identifier].hudstate[name] = state
209 hudtable.identifier = identifier
210 hudtable.format_string = format_string
211 hudtable.label = label
212 hudtable.hudids = {}
213 hudtable.hudstate = {}
214 hudtable.default_start_hidden = default_start_hidden
215 hudtable.default_start_value = default_start_value
216 hudtable.default_start_max = default_start_max
218 hb.hudbars_count= hb.hudbars_count + 1
220 hb.hudtables[identifier] = hudtable
223 function hb.init_hudbar(player, identifier, start_value, start_max, start_hidden)
224 local hudtable = hb.get_hudtable(identifier)
225 hb.hudtables[identifier].add_all(player, hudtable, start_value, start_max, start_hidden)
228 function hb.change_hudbar(player, identifier, new_value, new_max_value)
229 if new_value == nil and new_max_value == nil then
230 return
233 local name = player:get_player_name()
234 local hudtable = hb.get_hudtable(identifier)
235 local value_changed, max_changed = false, false
237 if new_value ~= nil then
238 if new_value ~= hudtable.hudstate[name].value then
239 hudtable.hudstate[name].value = new_value
240 value_changed = true
242 else
243 new_value = hudtable.hudstate[name].value
245 if new_max_value ~= nil then
246 if new_max_value ~= hudtable.hudstate[name].max then
247 hudtable.hudstate[name].max = new_max_value
248 max_changed = true
250 else
251 new_max_value = hudtable.hudstate[name].max
254 local main_error_text =
255 "[hudbars] Bad call to hb.change_hudbar, identifier: “"..tostring(identifier).."”, player name: “"..name.."”. "
256 if new_max_value < new_value then
257 minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than new_value ("..new_value..")!")
259 if new_max_value < 0 then
260 minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than 0!")
262 if new_value < 0 then
263 minetest.log("error", main_error_text.."new_value ("..new_value..") is smaller than 0!")
266 if hudtable.hudstate[name].hidden == false then
267 if max_changed then
268 if hudtable.hudstate[name].max == 0 then
269 player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0})
270 else
271 player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1})
275 if value_changed or max_changed then
276 local new_barlength = hb.value_to_barlength(new_value, new_max_value)
277 if new_barlength ~= hudtable.hudstate[name].barlength then
278 player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(new_value, new_max_value))
279 hudtable.hudstate[name].barlength = new_barlength
282 local new_text = string.format(hudtable.format_string, hudtable.label, new_value, new_max_value)
283 if new_text ~= hudtable.hudstate[name].text then
284 player:hud_change(hudtable.hudids[name].text, "text", new_text)
285 hudtable.hudstate[name].text = new_text
291 function hb.hide_hudbar(player, identifier)
292 local name = player:get_player_name()
293 local hudtable = hb.get_hudtable(identifier)
294 if(hudtable.hudstate[name].hidden == false) then
295 if hudtable.hudids[name].icon ~= nil then
296 player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0})
298 player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0})
299 player:hud_change(hudtable.hudids[name].bar, "number", 0)
300 player:hud_change(hudtable.hudids[name].text, "text", "")
301 hudtable.hudstate[name].hidden = true
305 function hb.unhide_hudbar(player, identifier)
306 local name = player:get_player_name()
307 local hudtable = hb.get_hudtable(identifier)
308 if(hudtable.hudstate[name].hidden) then
309 local name = player:get_player_name()
310 local value = hudtable.hudstate[name].value
311 local max = hudtable.hudstate[name].max
312 if hudtable.hudids[name].icon ~= nil then
313 player:hud_change(hudtable.hudids[name].icon, "scale", {x=1,y=1})
315 if hudtable.hudstate[name].max ~= 0 then
316 player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1})
318 player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(value, max))
319 player:hud_change(hudtable.hudids[name].text, "text", tostring(string.format(hudtable.format_string, hudtable.label, value, max)))
320 hudtable.hudstate[name].hidden = false
324 function hb.get_hudbar_state(player, identifier)
325 local ref = hb.get_hudtable(identifier).hudstate[player:get_player_name()]
326 -- Do not forget to update this chunk of code in case the state changes
327 local copy = {
328 hidden = ref.hidden,
329 value = ref.value,
330 max = ref.max,
331 text = ref.text,
332 barlength = ref.barlength,
334 return copy
337 --register built-in HUD bars
338 if minetest.setting_getbool("enable_damage") then
339 hb.register_hudbar("health", 0xFFFFFF, "Health", { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png" }, 20, 20, false)
340 hb.register_hudbar("breath", 0xFFFFFF, "Breath", { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png" }, 10, 10, true)
343 --load custom settings
344 local set = io.open(minetest.get_modpath("hudbars").."/hudbars.conf", "r")
345 if set then
346 dofile(minetest.get_modpath("hudbars").."/hudbars.conf")
347 set:close()
350 local function hide_builtin(player)
351 local flags = player:hud_get_flags()
352 flags.healthbar = false
353 flags.breathbar = false
354 player:hud_set_flags(flags)
358 local function custom_hud(player)
359 if minetest.setting_getbool("enable_damage") then
360 hb.init_hudbar(player, "health", player:get_hp())
361 local breath = player:get_breath()
362 local hide_breath
363 if breath == 11 and hb.settings.autohide_breath == true then hide_breath = true else hide_breath = false end
364 hb.init_hudbar(player, "breath", math.min(breath, 10), nil, hide_breath)
369 -- update built-in HUD bars
370 local function update_hud(player)
371 if minetest.setting_getbool("enable_damage") then
372 --air
373 local breath = player:get_breath()
375 if breath == 11 and hb.settings.autohide_breath == true then
376 hb.hide_hudbar(player, "breath")
377 else
378 hb.unhide_hudbar(player, "breath")
379 hb.change_hudbar(player, "breath", math.min(breath, 10))
382 --health
383 hb.change_hudbar(player, "health", player:get_hp())
387 minetest.register_on_joinplayer(function(player)
388 hide_builtin(player)
389 custom_hud(player)
390 hb.players[player:get_player_name()] = player
391 end)
393 minetest.register_on_leaveplayer(function(player)
394 hb.players[player:get_player_name()] = nil
395 end)
397 local main_timer = 0
398 local timer = 0
399 minetest.register_globalstep(function(dtime)
400 main_timer = main_timer + dtime
401 timer = timer + dtime
402 if main_timer > hb.settings.tick or timer > 4 then
403 if main_timer > hb.settings.tick then main_timer = 0 end
404 for playername, player in pairs(hb.players) do
405 -- only proceed if damage is enabled
406 if minetest.setting_getbool("enable_damage") then
407 -- update all hud elements
408 update_hud(player)
412 if timer > 4 then timer = 0 end
413 end)