123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- if not minetest.global_exists("bandages") then bandages = {} end
- bandages.modpath = minetest.get_modpath("bandages")
- bandages.players = bandages.players or {}
- -- Localize vector.distance() for performance.
- local vector_distance = vector.distance
- local math_floor = math.floor
- if minetest.get_modpath("reload") then
- local c = "bandages:core"
- local f = bandages.modpath .. "/init.lua"
- if not reload.file_registered(c) then
- reload.register_file(c, f, false)
- end
- end
- bandages.movement_limit_from_level = function(level)
- if level == 1 then
- return 20
- elseif level == 2 then
- return 6
- elseif level == 3 then
- return 1
- end
- return 0
- end
- bandages.hp_from_level = function(level, hp, hp_max)
- local heal = 0
- -- Hmm hmm hmmm, I'm a genius.
- local function mod1(hp, max)
- local a = (hp / hp_max)
- return a * a
- end
- -- This function is proof that I failed algebra.
- -- There's a way to do this in one line with no conditional, I just can't
- -- figure out what it is.
- local function mod2(hp, max)
- local a = hp / max
- local b
- if a <= 0.5 then
- b = a / 0.5
- else
- b = ((a - 0.5) / 0.5) * -1 + 1
- end
- return b * b
- end
- -- But this function makes me feel better.
- local function mod3(hp, max)
- local a = ((hp / hp_max) * -1 + 1)
- return a * a
- end
- if level == 1 then
- -- You receive the maximum heal bonus if you are only slightly hurt.
- -- Simple bandages become worse for the job the more hurt you are.
- heal = hp_max * 0.1 * mod1(hp, hp_max)
- elseif level == 2 then
- -- You get the most benefit from the basic medkit when used to heal
- -- non-lifethreatening wounds which need more care than a simple bandaging.
- heal = hp_max * 0.15 * mod2(hp, hp_max)
- elseif level == 3 then
- -- Trama medkits are best used on severe injuries. Using them for light
- -- scrapes is wasteful, and provides little benefit.
- heal = hp_max * 0.3 * mod3(hp, hp_max)
- end
- return heal
- end
- bandages.delay_from_level = function(level)
- if level == 1 then
- return 1.5
- elseif level == 2 then
- return 2.0
- elseif level == 3 then
- return 2.5
- end
- return 0
- end
- bandages.target_not_hurt = function(pname, tname)
- minetest.chat_send_player(pname, "# Server: <" .. rename.gpn(tname) .. "> is not wounded.")
- --easyvend.sound_error(pname)
- end
- bandages.player_not_hurt = function(pname)
- minetest.chat_send_player(pname, "# Server: You are not wounded.")
- --easyvend.sound_error(pname)
- end
- bandages.player_bandages_self = function(pname, hp, hp_max)
- local pc = math_floor((hp / hp_max) * 100)
- minetest.chat_send_player(pname, "# Server: You use bandages on yourself. Your health is now " .. pc .. "%.")
- end
- bandages.target_is_dead = function(pname, tname)
- minetest.chat_send_player(pname, "# Server: <" .. rename.gpn(tname) .. "> is dead!")
- --easyvend.sound_error(pname)
- end
- bandages.player_is_dead = function(pname)
- minetest.chat_send_player(pname, "# Server: You are dead!")
- --easyvend.sound_error(pname)
- end
- bandages.player_bandages_target = function(pname, tname, hp, hp_max)
- local pc = math_floor((hp / hp_max) * 100)
- minetest.chat_send_player(tname, "# Server: Player <" .. rename.gpn(pname) .. "> used a bandage on you.")
- minetest.chat_send_player(pname, "# Server: <" .. rename.gpn(tname) .. ">'s health improves to " .. pc .. "%.")
- end
- bandages.medkit_already_in_use = function(pname)
- minetest.chat_send_player(pname, "# Server: You are already using a medkit; wait to be done.")
- --easyvend.sound_error(pname)
- end
- bandages.player_moved_too_much = function(pname)
- minetest.chat_send_player(pname, "# Server: You must hold still while using a medkit!")
- --easyvend.sound_error(pname)
- end
- bandages.target_moved_too_much = function(pname, tname)
- minetest.chat_send_player(pname, "# Server: Player <" .. rename.gpn(tname) .. "> must hold still for you to use medkit!")
- minetest.chat_send_player(tname, "# Server: Player <" .. rename.gpn(pname) .. "> is trying to use a medkit on you; hold still!")
- --easyvend.sound_error(pname)
- end
- bandages.get_sound_range_from_level = function(level)
- if level == 1 then
- return 8
- elseif level == 2 then
- return 16
- elseif level == 3 then
- return 32
- end
- return 0
- end
- bandages.get_sound_gain_from_level = function(level)
- if level == 1 then
- return 0.5
- elseif level == 2 then
- return 0.7
- elseif level == 3 then
- return 1.0
- end
- return 0
- end
- bandages.play_sound_effects = function(pos, level)
- local range = bandages.get_sound_range_from_level(level)
- local gain = bandages.get_sound_gain_from_level(level)
- ambiance.sound_play("bandages_bandaging", pos, gain, range)
- -- Increase length of sound effect for higher levels.
- if level >= 2 then
- minetest.after(1.0, function()
- ambiance.sound_play("bandages_bandaging", pos, gain, range)
- end)
- end
- if level >= 3 then
- minetest.after(2.0, function()
- ambiance.sound_play("bandages_bandaging", pos, gain, range)
- end)
- end
- end
- function bandages.heal_target(itemstack, user, target, level)
- local pname = user:get_player_name()
- local tname = target:get_player_name()
- local hp = target:get_hp()
- local hp_max = pova.get_active_modifier(target, "properties").hp_max
- if hp >= hp_max then
- return bandages.target_not_hurt(pname, tname)
- end
- if hp <= 0 then
- return bandages.target_is_dead(pname, tname)
- end
- if bandages.players[pname] or bandages.players[tname] then
- return bandages.medkit_already_in_use(pname)
- end
- bandages.play_sound_effects(target:get_pos(), level)
- bandages.players[tname] = {pos=target:get_pos()}
- bandages.players[pname] = {pos=user:get_pos()}
- minetest.after(bandages.delay_from_level(level), function()
- local pos = bandages.players[tname].pos
- bandages.players[tname] = nil
- bandages.players[pname] = nil
- local target = minetest.get_player_by_name(tname)
- if not target or not target:is_player() then return end
- if vector_distance(target:get_pos(), pos) > bandages.movement_limit_from_level(level) then
- return bandages.target_moved_too_much(pname, tname)
- end
- -- Don't heal target if already dead.
- -- This solves an exploit people have found.
- local hp = target:get_hp()
- if hp == 0 then return end
- armor.notify_set_hp_reason({reason="bandage"})
- target:set_hp(hp + bandages.hp_from_level(level, hp, hp_max))
- bandages.player_bandages_target(pname, tname, target:get_hp(), hp_max)
- end)
- itemstack:take_item()
- return itemstack
- end
- function bandages.heal_self(itemstack, user, level)
- local pname = user:get_player_name()
- local hp = user:get_hp()
- local hp_max = pova.get_active_modifier(user, "properties").hp_max
- if hp >= hp_max then
- return bandages.player_not_hurt(pname)
- end
- if hp <= 0 then
- return bandages.player_is_dead(pname)
- end
- if bandages.players[pname] then
- return bandages.medkit_already_in_use(pname)
- end
- bandages.play_sound_effects(user:get_pos(), level)
- bandages.players[pname] = {pos=user:get_pos()}
- minetest.after(bandages.delay_from_level(level), function()
- local pos = bandages.players[pname].pos
- bandages.players[pname] = nil
- local user = minetest.get_player_by_name(pname)
- if not user or not user:is_player() then return end
- if vector_distance(user:get_pos(), pos) > bandages.movement_limit_from_level(level) then
- return bandages.player_moved_too_much(pname)
- end
- -- Don't heal user if already dead.
- -- This solves an exploit people have found.
- local hp = user:get_hp()
- if hp == 0 then return end
- user:set_hp(hp + bandages.hp_from_level(level, hp, hp_max))
- bandages.player_bandages_self(pname, user:get_hp(), hp_max)
- end)
- itemstack:take_item()
- return itemstack
- end
- bandages.use_bandage = function(itemstack, user, pointed_thing, level)
- if not user or not user:is_player() then return end
-
- if pointed_thing.type == "object" then
- local target = pointed_thing.ref
- if not target or not target:is_player() then
- return bandages.heal_self(itemstack, user, level)
- end
- return bandages.heal_target(itemstack, user, target, level)
- else
- return bandages.heal_self(itemstack, user, level)
- end
- end
- -- Execute registrations once only.
- if not bandages.registered then
- minetest.register_craftitem("bandages:bandage_1", {
- description = "Simple Bandage\n\nBest used for light scrapes and scratches.\nUse on yourself or another.",
- inventory_image = "bandage_1.png",
- on_use = function(itemstack, user, pointed_thing)
- return bandages.use_bandage(itemstack, user, pointed_thing, 1)
- end,
- })
- minetest.register_craftitem("bandages:bandage_2", {
- description = "Basic Medkit\n\nHeals moderate wounds (best around 50% health).\nUse on yourself or another.",
- inventory_image = "bandage_2.png",
- on_use = function(itemstack, user, pointed_thing)
- return bandages.use_bandage(itemstack, user, pointed_thing, 2)
- end,
- })
- minetest.register_craftitem("bandages:bandage_3", {
- description = "Trauma Medkit\n\nAids in recovery from severe, debilitating injuries.\nUse on yourself or another.",
- inventory_image = "bandage_3.png",
- on_use = function(itemstack, user, pointed_thing)
- return bandages.use_bandage(itemstack, user, pointed_thing, 3)
- end,
- })
- minetest.register_craft({
- output = 'bandages:bandage_1 3',
- recipe = {
- {'default:paper', 'farming:string', 'default:paper'},
- }
- })
- minetest.register_craft({
- output = 'bandages:bandage_2 3',
- recipe = {
- {'default:paper', 'farming:cloth', 'default:paper'},
- }
- })
- minetest.register_craft({
- output = 'bandages:bandage_3 3',
- recipe = {
- {'', 'aloevera:aloe_gel', ''},
- {'default:paper', 'farming:cloth', 'default:paper'},
- {'', 'dye:green', ''},
- }
- })
-
- bandages.registered = true
- end
|