init.lua 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. -- Adds health bars above players.
  2. -- Code by 4aiman, textures by Calinou. Licensed under CC0.
  3. -- Note: code is called from wield3d to update, etc.
  4. gauges = {}
  5. local player_wielding = {}
  6. local function update_textures(gauge, player)
  7. local props = player:get_properties()
  8. local hp = math.floor((player:get_hp() / props.hp_max) * 20)
  9. local breath = math.floor((player:get_breath() / props.breath_max) * 11)
  10. -- Clamp values to ensure they're in range.
  11. hp = math.max(math.min(hp, 20), 0)
  12. breath = math.max(math.min(breath, 11), 0)
  13. gauge.object:set_properties({
  14. textures = {
  15. "health_" .. tostring(hp) .. ".png^breath_" .. tostring(breath) .. ".png"
  16. },
  17. })
  18. end
  19. local function add_gauge(player)
  20. rc.check_position(player) -- Check position before calling `add_entity'.
  21. local pname = player:get_player_name()
  22. local pos = player:get_pos()
  23. local ent = minetest.add_entity(pos, "gauges:hp_bar")
  24. if ent then
  25. ent:set_attach(player, "", {x = 0, y = 20, z = 0}, {x = 0, y = 0, z = 0})
  26. -- Set initial gauge values.
  27. local data = ent:get_luaentity()
  28. data.wielder = player
  29. data.chp = player:get_hp()
  30. data.cbreath = player:get_breath()
  31. update_textures(data, player)
  32. player_wielding[pname] = {}
  33. player_wielding[pname].object = ent
  34. end
  35. end
  36. function gauges.on_teleport()
  37. local plyrs = minetest.get_connected_players()
  38. -- Just clear all the wield entities. They will be restored shortly.
  39. for k, v in ipairs(plyrs) do
  40. local name = v:get_player_name()
  41. local wield = player_wielding[name]
  42. if wield and wield.object then
  43. wield.object:set_detach()
  44. wield.object:remove()
  45. end
  46. player_wielding[name] = nil
  47. end
  48. end
  49. function gauges.on_global_step()
  50. local active_players = {}
  51. -- Add gauges to players without them.
  52. for _, player in ipairs(minetest.get_connected_players()) do
  53. local name = player:get_player_name()
  54. if not gdac_invis.is_invisible(name) and not cloaking.is_cloaked(name) then
  55. local wield = player_wielding[name]
  56. if not wield then
  57. add_gauge(player)
  58. end
  59. active_players[name] = true
  60. end
  61. end
  62. -- Remove expired player entries.
  63. for name, wield in pairs(player_wielding) do
  64. if not active_players[name] or gdac_invis.is_invisible(name) or cloaking.is_cloaked(name) then
  65. if wield.object then
  66. wield.object:remove()
  67. end
  68. player_wielding[name] = nil
  69. end
  70. end
  71. end
  72. function gauges.on_leaveplayer(player)
  73. local name = player:get_player_name()
  74. local wield = player_wielding[name] or {}
  75. if wield.object then
  76. wield.object:remove()
  77. end
  78. player_wielding[name] = nil
  79. end
  80. local bar_scalar = 0.8
  81. local hp_bar = {
  82. physical = false,
  83. collisionbox = {x = 0, y = 0, z = 0},
  84. visual = "sprite",
  85. textures = {"health_20.png"}, -- The texture is changed later in the code.
  86. visual_size = {
  87. x = 1.5*bar_scalar,
  88. y = 0.09375*bar_scalar,
  89. z = 1.5*bar_scalar,
  90. }, -- Y value is (1 / 16) * 1.5.
  91. wielder = nil,
  92. glow = -1,
  93. -- Cached values.
  94. chp = 0,
  95. cbreath = 0,
  96. -- Timer.
  97. timer = 0,
  98. on_activate = function(self, staticdata)
  99. if staticdata == "expired" then
  100. self.object:remove()
  101. end
  102. end,
  103. get_staticdata = function(self)
  104. return "expired"
  105. end,
  106. on_step = function(self, dtime)
  107. self.timer = self.timer + dtime
  108. if self.timer < 1 then
  109. return
  110. end
  111. self.timer = 0
  112. local wielder = self.wielder
  113. if wielder == nil then
  114. self.object:remove()
  115. return
  116. elseif minetest.get_player_by_name(wielder:get_player_name()) == nil then
  117. self.object:remove()
  118. return
  119. end
  120. local hp = wielder:get_hp()
  121. local breath = wielder:get_breath()
  122. if hp ~= self.chp or breath ~= self.cbreath then
  123. update_textures(self, wielder)
  124. self.chp = hp
  125. self.cbreath = breath
  126. end
  127. end,
  128. }
  129. minetest.register_entity("gauges:hp_bar", hp_bar)