224 lines
7.6 KiB
Lua
224 lines
7.6 KiB
Lua
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:get_pos()
|
|
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:set_pos(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:get_pos(), 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:get_pos(), 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:get_pos(), 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")
|