init.lua 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. bandages = bandages or {}
  2. bandages.modpath = minetest.get_modpath("bandages")
  3. bandages.players = bandages.players or {}
  4. -- Localize vector.distance() for performance.
  5. local vector_distance = vector.distance
  6. if minetest.get_modpath("reload") then
  7. local c = "bandages:core"
  8. local f = bandages.modpath .. "/init.lua"
  9. if not reload.file_registered(c) then
  10. reload.register_file(c, f, false)
  11. end
  12. end
  13. bandages.movement_limit_from_level = function(level)
  14. if level == 1 then
  15. return 20
  16. elseif level == 2 then
  17. return 5
  18. elseif level == 3 then
  19. return 2
  20. end
  21. return 0
  22. end
  23. bandages.hp_from_level = function(level)
  24. if level == 1 then
  25. return 2
  26. elseif level == 2 then
  27. return 3
  28. elseif level == 3 then
  29. return 6
  30. end
  31. return 0
  32. end
  33. bandages.delay_from_level = function(level)
  34. if level == 1 then
  35. return 1.5
  36. elseif level == 2 then
  37. return 2.0
  38. elseif level == 3 then
  39. return 2.5
  40. end
  41. return 0
  42. end
  43. bandages.target_not_player = function(pname)
  44. minetest.chat_send_player(pname, "# Server: Target is not a player.")
  45. --easyvend.sound_error(pname)
  46. end
  47. bandages.target_not_hurt = function(pname, tname)
  48. minetest.chat_send_player(pname, "# Server: Player <" .. rename.gpn(tname) .. "> is not wounded.")
  49. --easyvend.sound_error(pname)
  50. end
  51. bandages.player_not_hurt = function(pname)
  52. minetest.chat_send_player(pname, "# Server: You are not harmed.")
  53. --easyvend.sound_error(pname)
  54. end
  55. bandages.player_bandages_self = function(pname, hp, hp_max)
  56. minetest.chat_send_player(pname, "# Server: You use bandages on yourself. Your health is now " .. hp .. "/" .. hp_max .. " HP.")
  57. end
  58. bandages.target_is_dead = function(pname, tname)
  59. minetest.chat_send_player(pname, "# Server: Player <" .. rename.gpn(tname) .. "> is dead!")
  60. --easyvend.sound_error(pname)
  61. end
  62. bandages.player_is_dead = function(pname)
  63. minetest.chat_send_player(pname, "# Server: You are dead!")
  64. --easyvend.sound_error(pname)
  65. end
  66. bandages.player_bandages_target = function(pname, tname, hp, hp_max)
  67. minetest.chat_send_player(tname, "# Server: Player <" .. rename.gpn(pname) .. "> used a bandage on you.")
  68. minetest.chat_send_player(pname, "# Server: <" .. rename.gpn(tname) .. ">'s health improves to " .. hp .. "/" .. hp_max .. " HP.")
  69. end
  70. bandages.medkit_already_in_use = function(pname)
  71. minetest.chat_send_player(pname, "# Server: You are already using a medkit; wait to be done.")
  72. --easyvend.sound_error(pname)
  73. end
  74. bandages.player_moved_too_much = function(pname)
  75. minetest.chat_send_player(pname, "# Server: You must hold still while using a medkit!")
  76. --easyvend.sound_error(pname)
  77. end
  78. bandages.target_moved_too_much = function(pname, tname)
  79. minetest.chat_send_player(pname, "# Server: Player <" .. rename.gpn(tname) .. "> must hold still for you to use medkit!")
  80. minetest.chat_send_player(tname, "# Server: Player <" .. rename.gpn(pname) .. "> is trying to use a medkit on you; hold still!")
  81. --easyvend.sound_error(pname)
  82. end
  83. bandages.get_sound_range_from_level = function(level)
  84. if level == 1 then
  85. return 8
  86. elseif level == 2 then
  87. return 16
  88. elseif level == 3 then
  89. return 24
  90. end
  91. return 0
  92. end
  93. bandages.get_sound_gain_from_level = function(level)
  94. if level == 1 then
  95. return 0.5
  96. elseif level == 2 then
  97. return 0.7
  98. elseif level == 3 then
  99. return 1.0
  100. end
  101. return 0
  102. end
  103. bandages.play_sound_effects = function(pos, level)
  104. local range = bandages.get_sound_range_from_level(level)
  105. local gain = bandages.get_sound_gain_from_level(level)
  106. ambiance.sound_play("bandages_bandaging", pos, gain, range)
  107. -- Increase length of sound effect for higher levels.
  108. if level >= 2 then
  109. minetest.after(1.0, function()
  110. ambiance.sound_play("bandages_bandaging", pos, gain, range)
  111. end)
  112. end
  113. if level >= 3 then
  114. minetest.after(2.0, function()
  115. ambiance.sound_play("bandages_bandaging", pos, gain, range)
  116. end)
  117. end
  118. end
  119. bandages.get_max_damage_for_level = function(level, hp, hp_max)
  120. if level == 3 then
  121. return 1
  122. elseif level == 2 then
  123. return (hp_max / 3)
  124. elseif level == 1 then
  125. return (hp_max / 5) * 4
  126. end
  127. return 0
  128. end
  129. bandages.target_too_hurt = function(pname, tname, level)
  130. minetest.chat_send_player(pname, "# Server: Player <" .. rename.gpn(tname) .. "> is too severely hurt for a level " .. level .. " medkit.")
  131. --easyvend.sound_error(pname)
  132. end
  133. bandages.player_too_hurt = function(pname, level)
  134. minetest.chat_send_player(pname, "# Server: You are too severely hurt for a level " .. level .. " medkit.")
  135. --easyvend.sound_error(pname)
  136. end
  137. bandages.use_bandage = function(itemstack, user, pointed_thing, level)
  138. if not user or not user:is_player() then return end
  139. local pname = user:get_player_name()
  140. if pointed_thing.type == "object" then
  141. local target = pointed_thing.ref
  142. if not target or not target:is_player() then
  143. return bandages.target_not_player(pname)
  144. end
  145. local tname = target:get_player_name()
  146. local hp = target:get_hp()
  147. local hp_max = target:get_properties().hp_max
  148. if hp >= hp_max then
  149. return bandages.target_not_hurt(pname, tname)
  150. end
  151. if hp <= 0 then
  152. return bandages.target_is_dead(pname, tname)
  153. end
  154. if hp < bandages.get_max_damage_for_level(level, hp, hp_max) then
  155. return bandages.target_too_hurt(pname, tname, level)
  156. end
  157. if bandages.players[pname] or bandages.players[tname] then
  158. return bandages.medkit_already_in_use(pname)
  159. end
  160. bandages.play_sound_effects(target:get_pos(), level)
  161. bandages.players[tname] = {pos=target:get_pos()}
  162. bandages.players[pname] = {pos=user:get_pos()}
  163. minetest.after(bandages.delay_from_level(level), function()
  164. local pos = bandages.players[tname].pos
  165. bandages.players[tname] = nil
  166. bandages.players[pname] = nil
  167. local target = minetest.get_player_by_name(tname)
  168. if not target or not target:is_player() then return end
  169. if vector_distance(target:get_pos(), pos) > bandages.movement_limit_from_level(level) then
  170. return bandages.target_moved_too_much(pname, tname)
  171. end
  172. -- Don't heal target if already dead.
  173. -- This solves an exploit people have found.
  174. if target:get_hp() == 0 then return end
  175. target:set_hp(hp + bandages.hp_from_level(level))
  176. bandages.player_bandages_target(pname, tname, target:get_hp(), hp_max)
  177. end)
  178. itemstack:take_item()
  179. return itemstack
  180. else
  181. -- Otherwise, try to heal self.
  182. local hp = user:get_hp()
  183. local hp_max = user:get_properties().hp_max
  184. if hp >= hp_max then
  185. return bandages.player_not_hurt(pname)
  186. end
  187. if hp <= 0 then
  188. return bandages.player_is_dead(pname)
  189. end
  190. if hp < bandages.get_max_damage_for_level(level, hp, hp_max) then
  191. return bandages.player_too_hurt(pname, level)
  192. end
  193. if bandages.players[pname] then
  194. return bandages.medkit_already_in_use(pname)
  195. end
  196. bandages.play_sound_effects(user:get_pos(), level)
  197. bandages.players[pname] = {pos=user:get_pos()}
  198. minetest.after(bandages.delay_from_level(level), function()
  199. local pos = bandages.players[pname].pos
  200. bandages.players[pname] = nil
  201. local user = minetest.get_player_by_name(pname)
  202. if not user or not user:is_player() then return end
  203. if vector_distance(user:get_pos(), pos) > bandages.movement_limit_from_level(level) then
  204. return bandages.player_moved_too_much(pname)
  205. end
  206. -- Don't heal user if already dead.
  207. -- This solves an exploit people have found.
  208. if user:get_hp() == 0 then return end
  209. user:set_hp(hp + bandages.hp_from_level(level))
  210. bandages.player_bandages_self(pname, user:get_hp(), hp_max)
  211. end)
  212. itemstack:take_item()
  213. return itemstack
  214. end
  215. end
  216. -- Execute registrations once only.
  217. if not bandages.registered then
  218. minetest.register_craftitem("bandages:bandage_1", {
  219. description = "Simple Bandage\n\nHeals light scrapes and scratches.\nUse on yourself or another.",
  220. inventory_image = "bandage_1.png",
  221. on_use = function(itemstack, user, pointed_thing)
  222. return bandages.use_bandage(itemstack, user, pointed_thing, 1)
  223. end,
  224. })
  225. minetest.register_craftitem("bandages:bandage_2", {
  226. description = "Basic Medkit\n\nHeals wounds.\nUse on yourself or another.",
  227. inventory_image = "bandage_2.png",
  228. on_use = function(itemstack, user, pointed_thing)
  229. return bandages.use_bandage(itemstack, user, pointed_thing, 2)
  230. end,
  231. })
  232. minetest.register_craftitem("bandages:bandage_3", {
  233. description = "Trauma Medkit\n\nHeals player from severe wounds.\nUse on yourself or another.",
  234. inventory_image = "bandage_3.png",
  235. on_use = function(itemstack, user, pointed_thing)
  236. return bandages.use_bandage(itemstack, user, pointed_thing, 3)
  237. end,
  238. })
  239. minetest.register_craft({
  240. output = 'bandages:bandage_1 2',
  241. recipe = {
  242. {'default:paper', 'default:paper', 'default:paper'},
  243. }
  244. })
  245. minetest.register_craft({
  246. output = 'bandages:bandage_2 2',
  247. recipe = {
  248. {'default:paper', 'wool:white', 'default:paper'},
  249. }
  250. })
  251. minetest.register_craft({
  252. output = 'bandages:bandage_3 2',
  253. recipe = {
  254. {'default:paper', 'wool:green', 'default:paper'},
  255. }
  256. })
  257. bandages.registered = true
  258. end