init.lua 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 = pova.get_active_modifier(player, "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. --------------------------------------------------------------------------------
  41. -- Note: this is only to be called inside wield3d.on_teleport().
  42. function gauges.on_teleport()
  43. local plyrs = minetest.get_connected_players()
  44. -- Just clear all the wield entities. They will be restored shortly.
  45. for k, v in ipairs(plyrs) do
  46. local name = v:get_player_name()
  47. local wield = player_wielding[name]
  48. if wield and wield.object then
  49. wield.object:set_detach()
  50. wield.object:remove()
  51. end
  52. player_wielding[name] = nil
  53. end
  54. end
  55. --------------------------------------------------------------------------------
  56. function gauges.on_global_step()
  57. local active_players = {}
  58. -- Add gauges to players without them.
  59. for _, player in ipairs(minetest.get_connected_players()) do
  60. if not gdac.player_is_admin(player) then
  61. local name = player:get_player_name()
  62. local nametag = player_labels.query_nametag_onoff(name)
  63. local invisible = gdac_invis.is_invisible(name)
  64. local cloaked = cloaking.is_cloaked(name)
  65. if not invisible and not cloaked and nametag then
  66. local wield = player_wielding[name]
  67. if not wield then
  68. add_gauge(player)
  69. end
  70. active_players[name] = true
  71. end
  72. end
  73. end
  74. -- Remove expired player entries.
  75. for name, wield in pairs(player_wielding) do
  76. local nametag = player_labels.query_nametag_onoff(name)
  77. local invisible = gdac_invis.is_invisible(name)
  78. local cloaked = cloaking.is_cloaked(name)
  79. if not active_players[name] or invisible or cloaked or not nametag then
  80. if wield.object then
  81. wield.object:remove()
  82. end
  83. player_wielding[name] = nil
  84. end
  85. end
  86. end
  87. function gauges.on_leaveplayer(player)
  88. local name = player:get_player_name()
  89. local wield = player_wielding[name] or {}
  90. if wield.object then
  91. wield.object:remove()
  92. end
  93. player_wielding[name] = nil
  94. end
  95. local bar_scalar = 0.8
  96. local hp_bar = {
  97. physical = false,
  98. collisionbox = {x = 0, y = 0, z = 0},
  99. visual = "sprite",
  100. textures = {"blank.png"}, -- The texture is changed later in the code.
  101. visual_size = {
  102. x = 1.5*bar_scalar,
  103. y = 0.09375*bar_scalar,
  104. z = 1.5*bar_scalar,
  105. }, -- Y value is (1 / 16) * 1.5.
  106. wielder = nil,
  107. glow = -1,
  108. static_save = false,
  109. -- Cached values.
  110. chp = 0,
  111. cbreath = 0,
  112. -- Timer.
  113. timer = 0,
  114. on_activate = function(self, staticdata)
  115. if staticdata == "expired" then
  116. self.object:remove()
  117. end
  118. end,
  119. get_staticdata = function(self)
  120. return "expired"
  121. end,
  122. on_step = function(self, dtime)
  123. self.timer = self.timer + dtime
  124. if self.timer < 1 then
  125. return
  126. end
  127. self.timer = 0
  128. local wielder = self.wielder
  129. if wielder == nil then
  130. self.object:remove()
  131. return
  132. elseif minetest.get_player_by_name(wielder:get_player_name()) == nil then
  133. self.object:remove()
  134. return
  135. end
  136. local hp = wielder:get_hp()
  137. local breath = wielder:get_breath()
  138. if hp ~= self.chp or breath ~= self.cbreath then
  139. update_textures(self, wielder)
  140. self.chp = hp
  141. self.cbreath = breath
  142. end
  143. end,
  144. on_blast = function(self, damage)
  145. -- No damage (punching), no knockback, no drops.
  146. return false, false, {}
  147. end,
  148. }
  149. minetest.register_entity("gauges:hp_bar", hp_bar)