hp_boost.lua 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. -- Max HP boost.
  2. -- Note: HP boost does not admit multiplier modifiers; HP boost always uses
  3. -- fixed values!
  4. -- Localize for performance.
  5. local vector_round = vector.round
  6. local math_floor = math.floor
  7. local math_min = math.min
  8. -- Return the player's current HP boost.
  9. -- Needed for compatibility with XP code, since that also changes player's max HP.
  10. function hunger.get_health_boost(pname)
  11. local tab = hunger.players[pname]
  12. if tab then
  13. -- Calc sum of all active HP boosts.
  14. local total = 0
  15. for k, v in pairs(tab) do
  16. if k:find("^effect_data_health_boost_") then
  17. total = total + v.health
  18. end
  19. end
  20. -- Clamp to prevent overflow in engine.
  21. total = math_min(total, 30*500)
  22. return total
  23. end
  24. return 0
  25. end
  26. -- Apply a health boost to player.
  27. -- 'data' = {health=10000, time=60}
  28. -- 'health' is additive. Must not exceed 30*500.
  29. function hunger.apply_health_boost(pname, key, data)
  30. local pref = minetest.get_player_by_name(pname)
  31. if not pref then
  32. return
  33. end
  34. local tab = hunger.players[pname]
  35. if not tab then
  36. return
  37. end
  38. local keyname = "effect_time_health_boost_" .. key
  39. local datname = "effect_data_health_boost_" .. key
  40. local already_boosted = false
  41. if tab[keyname] then
  42. already_boosted = true
  43. end
  44. local oldboost = hunger.get_health_boost(pname)
  45. -- Boost max HP, time-additive.
  46. tab[keyname] = (tab[keyname] or 0) + data.time
  47. tab[datname] = tab[datname] or data
  48. -- Don't stack 'minetest.after' chains.
  49. -- Also don't stack 'hp_max'.
  50. if already_boosted then
  51. return
  52. end
  53. local hp = pref:get_hp()
  54. local hp_max = pova.get_active_modifier(pref, "properties").hp_max
  55. local perc = (hp / hp_max)
  56. if perc > 1 then perc = 1 end
  57. local new_hp_max = hp_max + data.health
  58. local new_hp = new_hp_max * perc
  59. -- Note: must manually notify HP change reason here.
  60. armor.notify_set_hp_reason({reason="hp_boost_start"})
  61. pova.set_modifier(pref, "properties", {hp_max=data.health}, "hp_boost_" .. key, "add")
  62. pref:set_hp(new_hp)
  63. if oldboost == 0 then
  64. minetest.chat_send_player(pname, "# Server: Max health boosted for " .. tab[keyname] .. " seconds.")
  65. hud.change_item(pref, "health", {text="hud_heart_fg_boost.png"})
  66. end
  67. armor:update_inventory(pref)
  68. hunger.time_health_boost(pname, key)
  69. end
  70. -- Private function!
  71. function hunger.time_health_boost(pname, key)
  72. local pref = minetest.get_player_by_name(pname)
  73. if not pref then
  74. return
  75. end
  76. local tab = hunger.players[pname]
  77. if not tab then
  78. return
  79. end
  80. local keyname = "effect_time_health_boost_" .. key
  81. local datname = "effect_data_health_boost_" .. key
  82. if tab[keyname] <= 0 then
  83. -- Get currently active health boost.
  84. local cboost = hunger.get_health_boost(pname)
  85. tab[keyname] = nil
  86. tab[datname] = nil
  87. -- Get remaining health boost from any other effects.
  88. local nboost = hunger.get_health_boost(pname)
  89. if nboost == 0 then
  90. if pref:get_hp() > 0 then
  91. minetest.chat_send_player(pname, "# Server: Max health boost expired.")
  92. end
  93. hud.change_item(pref, "health", {text="hud_heart_fg.png"})
  94. end
  95. local hp_max = pova.get_active_modifier(pref, "properties").hp_max
  96. local hp = pref:get_hp()
  97. local perc = (hp / hp_max)
  98. if perc > 1 then perc = 1 end
  99. -- Note: must manually notify HP change reason here.
  100. armor.notify_set_hp_reason({reason="hp_boost_end"})
  101. pova.remove_modifier(pref, "properties", "hp_boost_" .. key)
  102. -- Restore baseline HP level.
  103. local new_hp_max = pova.get_active_modifier(pref, "properties").hp_max
  104. local new_hp = perc * new_hp_max
  105. -- Note: must manually notify HP change reason here.
  106. armor.notify_set_hp_reason({reason="hp_boost_end"})
  107. pref:set_hp(new_hp)
  108. armor:update_inventory(pref)
  109. -- Manually update HUD.
  110. hud.player_event(pref, "health_changed")
  111. return
  112. end
  113. -- Check again soon.
  114. tab[keyname] = tab[keyname] - 1
  115. minetest.after(1, hunger.time_health_boost, pname, key)
  116. end