init.lua 3.9 KB

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