123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- --= Teleport Potion mod by TenPlus1
- -- Create teleport potion or pad, place then right-click to enter coords
- -- and step onto pad or walk into the blue portal light, portal closes after
- -- 10 seconds, pad remains, potions are throwable... SFX are license Free...
- -- Load support for intllib.
- local MP = minetest.get_modpath(minetest.get_current_modname())
- local S, NS = dofile(MP.."/intllib.lua")
- -- max teleport distance
- local dist = tonumber(minetest.settings:get("map_generation_limit") or 31000)
- -- creative check
- local creative_mode_cache = minetest.settings:get_bool("creative_mode")
- local function is_creative(name)
- return creative_mode_cache or minetest.check_player_privs(name, {creative = true})
- end
- local check_coordinates = function(str)
- if not str or str == "" then
- return nil
- end
- -- get coords from string
- local x, y, z = string.match(str, "^(-?%d+),(-?%d+),(-?%d+)$")
- -- check coords
- if x == nil or string.len(x) > 6
- or y == nil or string.len(y) > 6
- or z == nil or string.len(z) > 6 then
- return nil
- end
- -- convert string coords to numbers
- x = tonumber(x)
- y = tonumber(y)
- z = tonumber(z)
- -- are coords in map range ?
- if x > dist or x < -dist
- or y > dist or y < -dist
- or z > dist or z < -dist then
- return nil
- end
- -- return ok coords
- return {x = x, y = y, z = z}
- end
- -- particle effects
- local function tp_effect(pos)
- minetest.add_particlespawner({
- amount = 20,
- time = 0.25,
- minpos = pos,
- maxpos = pos,
- minvel = {x = -2, y = 1, z = -2},
- maxvel = {x = 2, y = 2, z = 2},
- minacc = {x = 0, y = -2, z = 0},
- maxacc = {x = 0, y = -4, z = 0},
- minexptime = 0.1,
- maxexptime = 1,
- minsize = 0.5,
- maxsize = 1.5,
- texture = "particle.png",
- glow = 15,
- })
- end
- local teleport_destinations = {}
- local function set_teleport_destination(playername, dest)
- teleport_destinations[playername] = dest
- tp_effect(dest)
- minetest.sound_play("portal_open", {
- pos = dest,
- gain = 1.0,
- max_hear_distance = 10
- })
- end
- --------------------------------------------------------------------------------
- --- Teleport portal
- --------------------------------------------------------------------------------
- minetest.register_node("teleport_potion:portal", {
- drawtype = "plantlike",
- tiles = {
- {name="portal.png",
- animation = {
- type = "vertical_frames",
- aspect_w = 16,
- aspect_h = 16,
- length = 1.0
- }
- }
- },
- light_source = 13,
- walkable = false,
- paramtype = "light",
- pointable = false,
- buildable_to = true,
- waving = 1,
- sunlight_propagates = true,
- damage_per_second = 1, -- walking into portal hurts player
- -- start timer when portal appears
- on_construct = function(pos)
- minetest.get_node_timer(pos):start(10)
- end,
- -- remove portal after 10 seconds
- on_timer = function(pos)
- minetest.sound_play("portal_close", {
- pos = pos,
- gain = 1.0,
- max_hear_distance = 10
- })
- minetest.remove_node(pos)
- end,
- on_blast = function() end,
- drop = {},
- })
- -- Throwable potion
- local function throw_potion(itemstack, player)
- local playerpos = player:get_pos()
- local obj = minetest.add_entity({
- x = playerpos.x,
- y = playerpos.y + 1.5,
- z = playerpos.z
- }, "teleport_potion:potion_entity")
- local dir = player:get_look_dir()
- local velocity = 20
- obj:set_velocity({
- x = dir.x * velocity,
- y = dir.y * velocity,
- z = dir.z * velocity
- })
- obj:set_acceleration({
- x = dir.x * -3,
- y = -9.5,
- z = dir.z * -3
- })
- obj:set_yaw(player:get_look_yaw() + math.pi)
- obj:get_luaentity().player = player
- end
- local potion_entity = {
- physical = true,
- visual = "sprite",
- visual_size = {x = 1.0, y = 1.0},
- textures = {"potion.png"},
- collisionbox = {0,0,0,0,0,0},
- lastpos = {},
- player = "",
- }
- potion_entity.on_step = function(self, dtime)
- if not self.player then
- self.object:remove()
- return
- end
- local pos = self.object:get_pos()
- if self.lastpos.x ~= nil then
- local vel = self.object:get_velocity()
- -- only when potion hits something physical
- if vel.x == 0
- or vel.y == 0
- or vel.z == 0 then
- if self.player ~= "" then
- -- round up coords to fix glitching through doors
- self.lastpos = vector.round(self.lastpos)
- self.player:set_pos(self.lastpos)
- minetest.sound_play("portal_close", {
- pos = self.lastpos,
- gain = 1.0,
- max_hear_distance = 5
- })
- tp_effect(self.lastpos)
- end
- self.object:remove()
- return
- end
- end
- self.lastpos = pos
- end
- minetest.register_entity("teleport_potion:potion_entity", potion_entity)
- --------------------------------------------------------------------------------
- --- Teleport potion
- --------------------------------------------------------------------------------
- minetest.register_node("teleport_potion:potion", {
- tiles = {"pad.png"},
- drawtype = "signlike",
- paramtype = "light",
- paramtype2 = "wallmounted",
- walkable = false,
- sunlight_propagates = true,
- description = S("Teleport Potion (use to set destination; place to open portal)"),
- inventory_image = "potion.png",
- wield_image = "potion.png",
- groups = {dig_immediate = 3, vessel = 1},
- selection_box = {type = "wallmounted"},
- on_use = function(itemstack, user, pointed_thing)
- if pointed_thing.type == "node" then
- set_teleport_destination(user:get_player_name(), pointed_thing.above)
- else
- throw_potion(itemstack, user)
- if not is_creative(user:get_player_name()) then
- itemstack:take_item()
- return itemstack
- end
- end
- end,
- after_place_node = function(pos, placer, itemstack, pointed_thing)
- local name = placer:get_player_name()
- local dest = teleport_destinations[name]
- if dest then
- minetest.set_node(pos, {name = "teleport_potion:portal"})
- local meta = minetest.get_meta(pos)
- -- Set portal destination
- meta:set_int("x", dest.x)
- meta:set_int("y", dest.y)
- meta:set_int("z", dest.z)
- -- Portal open effect and sound
- tp_effect(pos)
- minetest.sound_play("portal_open", {
- pos = pos,
- gain = 1.0,
- max_hear_distance = 10
- })
- else
- minetest.chat_send_player(name, S("Potion failed!"))
- minetest.remove_node(pos)
- minetest.add_item(pos, "teleport_potion:potion")
- end
- end,
- })
- -- teleport potion recipe
- minetest.register_craft({
- output = "teleport_potion:potion",
- recipe = {
- {"", "default:diamond", ""},
- {"default:diamond", "vessels:glass_bottle", "default:diamond"},
- {"", "default:diamond", ""},
- },
- })
- --------------------------------------------------------------------------------
- --- Teleport pad
- --------------------------------------------------------------------------------
- local teleport_formspec_context = {}
- minetest.register_node("teleport_potion:pad", {
- tiles = {"padd.png", "padd.png^[transformFY"},
- drawtype = "nodebox",
- paramtype = "light",
- paramtype2 = "facedir",
- legacy_wallmounted = true,
- walkable = true,
- sunlight_propagates = true,
- description = S("Teleport Pad (use to set destination; place to open portal)"),
- inventory_image = "padd.png",
- wield_image = "padd.png",
- light_source = 5,
- groups = {snappy = 3},
- node_box = {
- type = "fixed",
- fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
- },
- selection_box = {
- type = "fixed",
- fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
- },
- -- Save pointed nodes coordinates as destination for further portals
- on_use = function(itemstack, user, pointed_thing)
- if pointed_thing.type == "node" then
- set_teleport_destination(user:get_player_name(), pointed_thing.above)
- end
- end,
- -- Initialize teleport to saved location or the current position
- after_place_node = function(pos, placer, itemstack, pointed_thing)
- local meta = minetest.get_meta(pos)
- local name = placer:get_player_name()
- local dest = teleport_destinations[name]
- if not dest then
- dest = pos
- end
- -- Set coords
- meta:set_int("x", dest.x)
- meta:set_int("y", dest.y)
- meta:set_int("z", dest.z)
- meta:set_string("infotext", S("Pad Active (@1,@2,@3)",
- dest.x, dest.y, dest.z))
- minetest.sound_play("portal_open", {
- pos = pos,
- gain = 1.0,
- max_hear_distance = 10
- })
- end,
- -- Show formspec depending on the players privileges.
- on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
- local name = clicker:get_player_name()
- if minetest.is_protected(pos, name) then
- minetest.record_protection_violation(pos, name)
- return
- end
- local meta = minetest.get_meta(pos)
- local coords = {
- x = meta:get_int("x"),
- y = meta:get_int("y"),
- z = meta:get_int("z")
- }
- local coords = coords.x .. "," .. coords.y .. "," .. coords.z
- local desc = meta:get_string("desc")
- formspec = "field[desc;" .. S("Description") .. ";"
- .. minetest.formspec_escape(desc) .. "]"
- -- Only allow privileged players to change coordinates
- if minetest.check_player_privs(name, "teleport") then
- formspec = formspec ..
- "field[coords;" .. S("Teleport coordinates") .. ";" .. coords .. "]"
- end
- teleport_formspec_context[name] = {
- pos = pos,
- coords = coords,
- desc = desc,
- }
- minetest.show_formspec(name, "teleport_potion:set_destination", formspec)
- end,
- })
- -- Check and set coordinates
- minetest.register_on_player_receive_fields(function(player, formname, fields)
- if formname ~= "teleport_potion:set_destination" then
- return false
- end
- local name = player:get_player_name()
- local context = teleport_formspec_context[name]
- if not context then return false end
- teleport_formspec_context[name] = nil
- local meta = minetest.get_meta(context.pos)
- -- Coordinates were changed
- if fields.coords and fields.coords ~= context.coords then
- local coords = check_coordinates(fields.coords)
- if coords then
- meta:set_int("x", coords.x)
- meta:set_int("y", coords.y)
- meta:set_int("z", coords.z)
- else
- minetest.chat_send_player(name, S("Teleport Pad coordinates failed!"))
- end
- end
- -- Update infotext
- if fields.desc and fields.desc ~= "" then
- meta:set_string("desc", fields.desc)
- meta:set_string("infotext", S("Teleport to @1", fields.desc))
- else
- local coords = minetest.string_to_pos("(" .. context.coords .. ")")
- meta:set_string("infotext", S("Pad Active (@1,@2,@3)",
- coords.x, coords.y, coords.z))
- end
- return true
- end)
- -- teleport pad recipe
- minetest.register_craft({
- output = "teleport_potion:pad",
- recipe = {
- {"teleport_potion:potion", "default:glass", "teleport_potion:potion"},
- {"default:glass", "default:mese", "default:glass"},
- {"teleport_potion:potion", "default:glass", "teleport_potion:potion"}
- }
- })
- -- check portal & pad, teleport any entities on top
- minetest.register_abm({
- label = "Potion/Pad teleportation",
- nodenames = {"teleport_potion:portal", "teleport_potion:pad"},
- interval = 2,
- chance = 1,
- catch_up = false,
- action = function(pos, node, active_object_count, active_object_count_wider)
- -- check objects inside pad/portal
- local objs = minetest.get_objects_inside_radius(pos, 1)
- if #objs == 0 then
- return
- end
- -- get coords from pad/portal
- local meta = minetest.get_meta(pos)
- if not meta then return end -- errorcheck
- local target_coords = {
- x = meta:get_int("x"),
- y = meta:get_int("y"),
- z = meta:get_int("z")
- }
- for n = 1, #objs do
- if objs[n]:is_player() then
- -- play sound on portal end
- minetest.sound_play("portal_close", {
- pos = pos,
- gain = 1.0,
- max_hear_distance = 5
- })
- -- move player
- objs[n]:set_pos(target_coords)
- -- paricle effects on arrival
- tp_effect(target_coords)
- -- play sound on destination end
- minetest.sound_play("portal_close", {
- pos = target_coords,
- gain = 1.0,
- max_hear_distance = 5
- })
- -- rotate player to look in pad placement direction
- local rot = node.param2
- local yaw = 0
- if rot == 0 or rot == 20 then
- yaw = 0 -- north
- elseif rot == 2 or rot == 22 then
- yaw = 3.14 -- south
- elseif rot == 1 or rot == 23 then
- yaw = 4.71 -- west
- elseif rot == 3 or rot == 21 then
- yaw = 1.57 -- east
- end
- objs[n]:set_look_yaw(yaw)
- end
- end
- end
- })
- -- add lucky blocks
- -- Teleport Potion mod
- if minetest.get_modpath("lucky_block") then
- lucky_block:add_blocks({
- {"dro", {"teleport_potion:potion"}, 2},
- {"tel"},
- {"dro", {"teleport_potion:pad"}, 1},
- {"lig"},
- })
- end
- print ("[MOD] Teleport Potion loaded")
|