--= Teleport Book (paper) mod by jaandrle --! based on Teleport Potion mod by TenPlus1 (SFX are license free) -- -- !!! Mainly tested inside LOTT game !!! -- support for MT game translation. local S = default.get_translator -- max teleport distance local dist = tonumber(minetest.settings:get("map_generation_limit") or 31000) local function check_coordinates(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 add_particlespawner(src, teleport_type) local amount, xz, y, minexptime, maxexptime local sound_name, max_hear_distance= "teleport", 30 if teleport_type=="teleport_to" then amount= 100 xz= 0.4 y= 0.3 minexptime= 6 maxexptime= 12 else amount= 50 xz= 0.2 y= 0.2 minexptime= 3 maxexptime= 4.5 end minetest.sound_play({name=sound_name, gain=1}, {pos=src, max_hear_distance=max_hear_distance}) minetest.add_particlespawner({ amount= amount, 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=-xz, y=-y, z=-xz}, maxvel= {x=xz, y=y, z=xz}, minexptime= minexptime, maxexptime= maxexptime, minsize=1, maxsize=1.25, texture= "particle.png", glow= 15 }) end local teleport_paper_entity = { physical = true, visual = "sprite", visual_size = {x = 1.0, y = 1.0}, textures = {"teleport_paper.png"}, collisionbox = {-0.1,-0.1,-0.1,0.1,0.1,0.1}, lastpos = {}, player = "", } teleport_paper_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) add_particlespawner(self.lastpos, "teleport_to") end self.object:remove() return end end self.lastpos = pos end minetest.register_entity("teleport_book:teleport_paper_entity", teleport_paper_entity) local book_writers = {} minetest.register_on_leaveplayer(function(player) book_writers[player:get_player_name()] = nil end) local name_book= "Teleport book" local id_book= "teleport_book:book" minetest.register_craftitem(id_book, { description= name_book, inventory_image= "teleport_book.png", stack_max= 1, range= 2, groups= { book= 1 }, on_use= function(itemstack, user) local meta= itemstack:get_meta() local dest= minetest.string_to_pos(meta:get_string("_dest")) local src= user:getpos() if dest == nil then meta:set_string("_dest", minetest.pos_to_string(src)) meta:set_int("_usages", math.random(25, 75)) meta:set_string("description", name_book.." for "..minetest.pos_to_string(src, 2)) local player_name = user:get_player_name() book_writers[player_name] = {wield_index = user:get_wield_index()} minetest.show_formspec(player_name, id_book, "size[5,3]" .. "field[0.25,1.5;4.75,1;name;"..S("Write a description of the book (optional):")..";]" .. "button_exit[1.5,2;2,1;exit;Save]") add_particlespawner(src, "teleport_from") return itemstack end local usages= meta:get_int("_usages") - 1 --minetest.chat_send_player(user:get_player_name(), usages) if usages==1 then meta:set_string("description", meta:get_string("description").." – almost destroyed!") end meta:set_int("_usages", usages) add_particlespawner(src, "teleport_from") user:setpos(dest) add_particlespawner(dest, "teleport_to") if usages==0 then itemstack:take_item() end return itemstack end }) minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= id_book then return end local player_name = player:get_player_name() local inv = player:get_inventory() if not book_writers[player_name] or not fields.name or fields.name == "" then return end local wield_index = book_writers[player_name].wield_index local wield_list = player:get_wield_list() local stack = inv:get_stack(wield_list, wield_index) if stack:get_name() ~= id_book then -- No book in the wield slot, abort & inform the player minetest.chat_send_player(player_name, S("The book you were writing to mysteriously disappeared.")) return end local meta= stack:get_meta() meta:set_string("description", name_book .. " – " .. fields.name) inv:set_stack(wield_list, wield_index, stack) end) minetest.register_node("teleport_book:paper", { tiles = {"teleport_paper.png"}, drawtype = "signlike", paramtype = "light", paramtype2 = "wallmounted", walkable = true, sunlight_propagates = true, description = "Teleport paper plane", inventory_image = "teleport_paper.png", wield_image = "teleport_paper.png", selection_box = {type = "wallmounted"}, groups= { snappy = 2, flammable = 3, oddly_breakable_by_hand = 3, choppy = 2, carpet = 1 }, after_place_node= function(_1, _2, itemstack) itemstack:take_item() return itemstack end, on_dig= function(pos, node, player) minetest.remove_node(pos) player:get_inventory():add_item("main", "teleport_book:paper") end, on_drop= function(itemstack, player) local playerpos = player:get_pos() local obj = minetest.add_entity({ x = playerpos.x, y = playerpos.y + 1.5, z = playerpos.z }, "teleport_book:teleport_paper_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_horizontal()) obj:get_luaentity().player = player if math.random(0,6) > 5 then itemstack:set_count(itemstack:get_count()-1) end return itemstack end, }) -- Recipes minetest.register_craft({ output = "teleport_book:paper 27", recipe = { {"teleport_book:book"}, }, }) minetest.register_craft({ output = "teleport_book:book", recipe = { {"default:mese_crystal"}, {"default:book"}, }, }) print("[MOD] Teleport Book loaded")