statbars.lua 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. -- cache setting
  2. local enable_damage = core.settings:get_bool("enable_damage")
  3. local bar_definitions = {
  4. hp = {
  5. hud_elem_type = "statbar",
  6. position = {x = 0.5, y = 1},
  7. text = "heart.png",
  8. text2 = "heart_gone.png",
  9. number = core.PLAYER_MAX_HP_DEFAULT,
  10. item = core.PLAYER_MAX_HP_DEFAULT,
  11. direction = 0,
  12. size = {x = 24, y = 24},
  13. offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)},
  14. },
  15. breath = {
  16. hud_elem_type = "statbar",
  17. position = {x = 0.5, y = 1},
  18. text = "bubble.png",
  19. text2 = "bubble_gone.png",
  20. number = core.PLAYER_MAX_BREATH_DEFAULT * 2,
  21. item = core.PLAYER_MAX_BREATH_DEFAULT * 2,
  22. direction = 0,
  23. size = {x = 24, y = 24},
  24. offset = {x = 25, y= -(48 + 24 + 16)},
  25. },
  26. }
  27. local hud_ids = {}
  28. local function scaleToHudMax(player, field)
  29. -- Scale "hp" or "breath" to the hud maximum dimensions
  30. local current = player["get_" .. field](player)
  31. local nominal = bar_definitions[field].item
  32. local max_display = math.max(player:get_properties()[field .. "_max"], current)
  33. return math.ceil(current / max_display * nominal)
  34. end
  35. local function update_builtin_statbars(player)
  36. local name = player:get_player_name()
  37. if name == "" then
  38. return
  39. end
  40. local flags = player:hud_get_flags()
  41. if not hud_ids[name] then
  42. hud_ids[name] = {}
  43. -- flags are not transmitted to client on connect, we need to make sure
  44. -- our current flags are transmitted by sending them actively
  45. player:hud_set_flags(flags)
  46. end
  47. local hud = hud_ids[name]
  48. local immortal = player:get_armor_groups().immortal == 1
  49. if flags.healthbar and enable_damage and not immortal then
  50. local number = scaleToHudMax(player, "hp")
  51. if hud.id_healthbar == nil then
  52. local hud_def = table.copy(bar_definitions.hp)
  53. hud_def.number = number
  54. hud.id_healthbar = player:hud_add(hud_def)
  55. else
  56. player:hud_change(hud.id_healthbar, "number", number)
  57. end
  58. elseif hud.id_healthbar then
  59. player:hud_remove(hud.id_healthbar)
  60. hud.id_healthbar = nil
  61. end
  62. local show_breathbar = flags.breathbar and enable_damage and not immortal
  63. local breath = player:get_breath()
  64. local breath_max = player:get_properties().breath_max
  65. if show_breathbar and breath <= breath_max then
  66. local number = scaleToHudMax(player, "breath")
  67. if not hud.id_breathbar and breath < breath_max then
  68. local hud_def = table.copy(bar_definitions.breath)
  69. hud_def.number = number
  70. hud.id_breathbar = player:hud_add(hud_def)
  71. elseif hud.id_breathbar then
  72. player:hud_change(hud.id_breathbar, "number", number)
  73. end
  74. end
  75. if hud.id_breathbar and (not show_breathbar or breath == breath_max) then
  76. core.after(1, function(player_name, breath_bar)
  77. local player = core.get_player_by_name(player_name)
  78. if player then
  79. player:hud_remove(breath_bar)
  80. end
  81. end, name, hud.id_breathbar)
  82. hud.id_breathbar = nil
  83. end
  84. end
  85. local function cleanup_builtin_statbars(player)
  86. local name = player:get_player_name()
  87. if name == "" then
  88. return
  89. end
  90. hud_ids[name] = nil
  91. end
  92. local function player_event_handler(player,eventname)
  93. assert(player:is_player())
  94. local name = player:get_player_name()
  95. if name == "" or not hud_ids[name] then
  96. return
  97. end
  98. if eventname == "health_changed" then
  99. update_builtin_statbars(player)
  100. if hud_ids[name].id_healthbar then
  101. return true
  102. end
  103. end
  104. if eventname == "breath_changed" then
  105. update_builtin_statbars(player)
  106. if hud_ids[name].id_breathbar then
  107. return true
  108. end
  109. end
  110. if eventname == "hud_changed" or eventname == "properties_changed" then
  111. update_builtin_statbars(player)
  112. return true
  113. end
  114. return false
  115. end
  116. function core.hud_replace_builtin(hud_name, definition)
  117. if type(definition) ~= "table" or
  118. definition.hud_elem_type ~= "statbar" then
  119. return false
  120. end
  121. definition = table.copy(definition)
  122. if hud_name == "health" then
  123. definition.item = definition.item or definition.number or core.PLAYER_MAX_HP_DEFAULT
  124. bar_definitions.hp = definition
  125. for name, ids in pairs(hud_ids) do
  126. local player = core.get_player_by_name(name)
  127. if player and ids.id_healthbar then
  128. player:hud_remove(ids.id_healthbar)
  129. ids.id_healthbar = nil
  130. update_builtin_statbars(player)
  131. end
  132. end
  133. return true
  134. end
  135. if hud_name == "breath" then
  136. definition.item = definition.item or definition.number or core.PLAYER_MAX_BREATH_DEFAULT
  137. bar_definitions.breath = definition
  138. for name, ids in pairs(hud_ids) do
  139. local player = core.get_player_by_name(name)
  140. if player and ids.id_breathbar then
  141. player:hud_remove(ids.id_breathbar)
  142. ids.id_breathbar = nil
  143. update_builtin_statbars(player)
  144. end
  145. end
  146. return true
  147. end
  148. return false
  149. end
  150. -- Append "update_builtin_statbars" as late as possible
  151. -- This ensures that the HUD is hidden when the flags are updated in this callback
  152. core.register_on_mods_loaded(function()
  153. core.register_on_joinplayer(update_builtin_statbars)
  154. end)
  155. core.register_on_leaveplayer(cleanup_builtin_statbars)
  156. core.register_playerevent(player_event_handler)