local S = minetest.get_translator("teletool") local REACH = 20.0 teletool = {} --[[ Load settings, apply default settings ]] teletool.settings = {} teletool.settings.avoid_collisions = true teletool.settings.adjust_head = true teletool.settings.cost_mana = 20 local avoid_collisions = minetest.settings:get_bool("teletool_avoid_collisions") if avoid_collisions ~= nil then teletool.settings.avoid_collision = avoid_collisions end local adjust_head = minetest.settings:get_bool("teletool_adjust_head") if adjust_head ~= nil then teletool.settings.adjust_head = adjust_head end local cost_mana = tonumber(minetest.settings:get("teletool_cost_mana")) if cost_mana ~= nil then teletool.settings.cost_mana = cost_mana end function teletool.teleport(player, pointed_thing) local pos = pointed_thing.above local src = player:getpos() local dest = {x=pos.x, y=math.ceil(pos.y)-0.5, z=pos.z} local over = {x=dest.x, y=dest.y+1, z=dest.z} local destnode = minetest.get_node({x=dest.x, y=math.ceil(dest.y), z=dest.z}) local overnode = minetest.get_node({x=over.x, y=math.ceil(over.y), z=over.z}) if teletool.settings.adjust_head then -- This trick prevents the player's head to spawn in a walkable node if the player clicked on the lower side of a node -- NOTE: This piece of code must be updated as soon the collision boxes of players become configurable if minetest.registered_nodes[overnode.name].walkable then dest.y = dest.y - 1 end end if teletool.settings.avoid_collisions then -- The destination must be collision free destnode = minetest.get_node({x=dest.x, y=math.ceil(dest.y), z=dest.z}) if minetest.registered_nodes[destnode.name].walkable then return false end end minetest.add_particlespawner({ amount = 25, time = 0.1, minpos = {x=src.x-0.4, y=src.y+0.25, z=src.z-0.4}, maxpos = {x=src.x+0.4, y=src.y+0.75, z=src.z+0.4}, minvel = {x=-0.1, y=-0.1, z=-0.1}, maxvel = {x=0, y=0.1, z=0}, minexptime=1, maxexptime=1.5, minsize=1, maxsize=1.25, texture = "teletool_particle_departure.png", }) minetest.sound_play( {name="teletool_teleport1", gain=1}, {pos=src, max_hear_distance=12}, true) player:setpos(dest) minetest.add_particlespawner({ amount = 25, time = 0.1, minpos = {x=dest.x-0.4, y=dest.y+0.25, z=dest.z-0.4}, maxpos = {x=dest.x+0.4, y=dest.y+0.75, z=dest.z+0.4}, minvel = {x=0, y=-0.1, z=0}, maxvel = {x=0.1, y=0.1, z=0.1}, minexptime=1, maxexptime=1.5, minsize=1, maxsize=1.25, texture = "teletool_particle_arrival.png", }) minetest.after(0.5, function(dest) minetest.sound_play( {name="teletool_teleport2", gain=1}, {pos=dest, max_hear_distance=12}, true) end, dest) return true end -- doc_items help texts local base = S("Point teleporters are short-range teleportation devices which allow the user to teleport instantly towards a block they point at.") local inf = S("Infinite point teleporters are very powerful, they can be used without limits.") local baseuse = S("To use this tool, point to a face of a block and punch to teleport in front of it. The target location must have a minimum amount of space for you to stand in, otherwise, teleportation will fail.") local desc_inf = base .. "\n" .. inf local use_inf = baseuse minetest.register_tool("teletool:teletool_infinite", { description = S("Infinite point teleporter"), _doc_items_longdesc = desc_inf, _doc_items_usagehelp = use_inf, range = REACH, tool_capabilities = {}, wield_image = "teletool_teletool_infinite.png", inventory_image = "teletool_teletool_infinite.png", on_use = function(itemstack, user, pointed_thing) local failure = false if(pointed_thing.type == "node") then failure = not teletool.teleport(user, pointed_thing) else failure = true end if failure then minetest.sound_play( {name="teletool_fail", gain=0.5}, {pos=user:getpos(), max_hear_distance=4}, true) end return itemstack end, groups = { teletool = 1, disable_repair = 1 }, }) if(minetest.get_modpath("technic")) then technic.register_power_tool("teletool:teletool_technic", 50000) local technic = S("Electronic point teleporters run on electricity and must be charged initially. Fully charged, they can be used about 50 times.") local technicuse = S("To recharge this tool, place it in a powered battery box.") local desc_technic = base .. "\n" .. technic local use_technic = technicuse .. " " .. baseuse minetest.register_tool("teletool:teletool_technic", { description = S("Electronic point teleporter"), _doc_items_longdesc = desc_technic, _doc_items_usagehelp = use_technic, range = REACH, tool_capabilities = {}, wield_image = "teletool_teletool_technic.png", inventory_image = "teletool_teletool_technic.png", on_use = function(itemstack, user, pointed_thing) local failure = false if(pointed_thing.type == "node") then local meta = minetest.deserialize(itemstack:get_metadata()) if not meta or not meta.charge then failure = true elseif meta.charge >= 1000 then meta.charge = meta.charge - 1000 failure = not teletool.teleport(user, pointed_thing) if not failure then technic.set_RE_wear(itemstack, meta.charge, 50000) itemstack:set_metadata(minetest.serialize(meta)) end else failure = true end else failure = true end if failure then minetest.sound_play( {name="teletool_fail", gain=0.5}, {pos=user:getpos(), max_hear_distance=4}, true) end return itemstack end, groups = { teletool = 1, disable_repair = 1 }, -- Technic data wear_represents = "technic_RE_charge", on_refill = technic.refill_RE_charge }) end if(minetest.get_modpath("mana") ~= nil) then local dmana = string.format(S("Magical point teleporters are fueled by mana and require %d mana per teleportation."), teletool.settings.cost_mana) local manause = string.format(S("First make sure you have at least %d mana."), teletool.settings.cost_mana) local desc_mana = base .. "\n" .. dmana local use_mana = manause .. " " .. baseuse minetest.register_tool("teletool:teletool_mana", { description = S("Magical point teleporter"), _doc_items_longdesc = desc_mana, _doc_items_usagehelp = use_mana, range = REACH, tool_capabilities = {}, wield_image = "teletool_teletool_mana.png", inventory_image = "teletool_teletool_mana.png", on_use = function(itemstack, user, pointed_thing) local failure = false if(pointed_thing.type == "node") then if(mana.get(user:get_player_name()) >= teletool.settings.cost_mana) then failure = not teletool.teleport(user, pointed_thing) if not failure then failure = not mana.subtract(user:get_player_name(), teletool.settings.cost_mana) end else failure = true end else failure = true end if failure then minetest.sound_play( {name="teletool_fail", gain=0.5}, {pos=user:getpos(), max_hear_distance=4}, true) end return itemstack end, groups = { teletool = 1, disable_repair = 1 }, }) end if(minetest.get_modpath("default") ~= nil and minetest.get_modpath("technic") ~= nil) then minetest.register_craft({ output = "teletool:teletool_technic", recipe = { {"", "default:mese_crystal", ""}, {"technic:stainless_steel_ingot", "technic:red_energy_crystal", "technic:stainless_steel_ingot"}, {"technic:stainless_steel_ingot", "technic:battery", "technic:stainless_steel_ingot"} } }) if(minetest.get_modpath("awards") ~= nil) then awards.register_achievement("teletool_technic", { title = S("What an awesome device!"), description = S("Craft an electronic point teleporter."), icon = "teletool_teletool_technic.png", trigger = { type = "craft", item = "teletool:teletool_technic", target = 1, }, }) end end minetest.register_alias("teletool:teletool", "teletool:teletool_infinite")