init.lua 9.0 KB

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