statbars.lua 4.7 KB

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