diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/depends.txt @@ -0,0 +1 @@ +default diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..d642738 --- /dev/null +++ b/init.lua @@ -0,0 +1,243 @@ +--= 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") diff --git a/sounds/fail.ogg b/sounds/fail.ogg new file mode 100644 index 0000000..55c45cc Binary files /dev/null and b/sounds/fail.ogg differ diff --git a/sounds/teleport.ogg b/sounds/teleport.ogg new file mode 100644 index 0000000..4886853 Binary files /dev/null and b/sounds/teleport.ogg differ diff --git a/textures/particle.png b/textures/particle.png new file mode 100644 index 0000000..3a45d15 Binary files /dev/null and b/textures/particle.png differ diff --git a/textures/teleport_book.png b/textures/teleport_book.png new file mode 100644 index 0000000..7e3a827 Binary files /dev/null and b/textures/teleport_book.png differ diff --git a/textures/teleport_paper.png b/textures/teleport_paper.png new file mode 100644 index 0000000..282f1c4 Binary files /dev/null and b/textures/teleport_paper.png differ