diff --git a/README.md b/README.md index bbc1ddb..7970042 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,14 @@ Teleport Potion This minetest mod adds both a teleportation potion and pad to the game -https://forum.minetest.net/viewtopic.php?f=9&t=9234 \ No newline at end of file +https://forum.minetest.net/viewtopic.php?f=9&t=9234 + + +Changes: + +0.5 - Added throwable potions +0.4 - Code tidy and particle effects added +0.3 - Added Teleport Pad +0.2 - Bug fixes +0.1 - Added SFX +0.0 - Initial release \ No newline at end of file diff --git a/init (copy 1).lua b/init (copy 1).lua new file mode 100755 index 0000000..154aec5 --- /dev/null +++ b/init (copy 1).lua @@ -0,0 +1,307 @@ + +--= Teleport Potion mod 0.4 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... SFX are license Free... + +teleport = {} + +-- teleport portal recipe +minetest.register_craft({ + output = 'teleport_potion:potion', + type = "shapeless", + recipe = {'vessels:glass_bottle', 'default:diamondblock'} +}) + +-- 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"} + } +}) + +-- default coords (from static spawnpoint or default values at end) +teleport.default = (minetest.setting_get_pos("static_spawnpoint") or {x = 0, y = 2, z = 0}) + +-- 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 = default.LIGHT_MAX - 2, + walkable = false, + paramtype = "light", + pointable = false, + buildable_to = true, + waving = 1, + sunlight_propagates = true, + damage_per_second = 1, -- walking into portal also 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.set_node(pos, {name = "air"}) + end, +}) + +-- teleport potion +minetest.register_node("teleport_potion:potion", { + tiles = {"pad.png"}, + drawtype = "signlike", + paramtype = "light", + paramtype2 = "wallmounted", + walkable = false, + sunlight_propagates = true, + description="Teleport Potion (place and right-click to enchant location)", + inventory_image = "potion.png", + wield_image = "potion.png", + groups = {snappy = 3, dig_immediate = 3}, + selection_box = {type = "wallmounted"}, + + on_construct = function(pos) + + local meta = minetest.get_meta(pos) + + -- text entry formspec + meta:set_string("formspec", "field[text;;${text}]") + meta:set_string("infotext", "Enter teleport coords (e.g 200,20,-200)") + meta:set_string("text", teleport.default.x..","..teleport.default.y..","..teleport.default.z) + + -- set default coords + meta:set_float("x", teleport.default.x) + meta:set_float("y", teleport.default.y) + meta:set_float("z", teleport.default.z) + end, + + -- right-click to enter new coords + on_right_click = function(pos, placer) + local meta = minetest.get_meta(pos) + end, + + -- check if coords ok then open portal, otherwise return potion + on_receive_fields = function(pos, formname, fields, sender) + + local coords = teleport.coordinates(fields.text) + local meta = minetest.get_meta(pos) + local name = sender:get_player_name() + + if coords then + + minetest.set_node(pos, {name = "teleport_potion:portal"}) + + local newmeta = minetest.get_meta(pos) + + -- set portal destination + newmeta:set_float("x", coords.x) + newmeta:set_float("y", coords.y) + newmeta:set_float("z", coords.z) + newmeta:set_string("text", fields.text) + + -- 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, 'Potion failed!') + minetest.set_node(pos, {name = "air"}) + minetest.add_item(pos, 'teleport_potion:potion') + end + end, +}) + +-- teleport pad +minetest.register_node("teleport_potion:pad", { + tiles = {"padd.png"}, + drawtype = 'nodebox', + paramtype = "light", + paramtype2 = "wallmounted", + walkable = true, + sunlight_propagates = true, + description="Teleport Pad (place and right-click to enchant location)", + inventory_image = "padd.png", + wield_image = "padd.png", + light_source = 5, + groups = {snappy = 3}, + node_box = { + type = "wallmounted", + wall_top = {-0.5, 0.4375, -0.5, 0.5, 0.5, 0.5}, + wall_bottom = {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5}, + wall_side = {-0.5, -0.5, -0.5, -0.4375, 0.5, 0.5}, + }, + selection_box = {type = "wallmounted"}, + + on_construct = function(pos) + + local meta = minetest.get_meta(pos) + + -- text entry formspec + meta:set_string("formspec", "field[text;;${text}]") + meta:set_string("infotext", "Enter teleport coords (e.g 200,20,-200)") + meta:set_string("text", teleport.default.x..","..teleport.default.y..","..teleport.default.z) + + -- set default coords + meta:set_float("x", teleport.default.x) + meta:set_float("y", teleport.default.y) + meta:set_float("z", teleport.default.z) + end, + + -- right-click to enter new coords + on_right_click = function(pos, placer) + local meta = minetest.get_meta(pos) + end, + + -- once entered, check coords, if ok then return potion + on_receive_fields = function(pos, formname, fields, sender) + + local coords = teleport.coordinates(fields.text) + local meta = minetest.get_meta(pos) + local name = sender:get_player_name() + + if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return + end + + if coords then + + local newmeta = minetest.get_meta(pos) + + newmeta:set_float("x", coords.x) + newmeta:set_float("y", coords.y) + newmeta:set_float("z", coords.z) + newmeta:set_string("text", fields.text) + + meta:set_string("infotext", "Pad Active ("..coords.x..","..coords.y..","..coords.z..")") + minetest.sound_play("portal_open", { + pos = pos, + gain = 1.0, + max_hear_distance = 10 + }) + + else + minetest.chat_send_player(name, 'Teleport Pad coordinates failed!') + end + end, +}) + +teleport.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 > 30900 or x < -30900 + or y > 30900 or y < -30900 + or z > 30900 or z < -30900 then + return nil + end + + -- return ok coords + return {x = x, y = y, z = z} +end + +-- particle effects +function tp_effect(pos) + minetest.add_particlespawner({ + amount = 20, + time = 0.25, + minpos = pos, + maxpos = pos, + minvel = {x = -2, y = -2, z = -2}, + maxvel = {x = 2, y = 2, z = 2}, + minacc = {x = -4, y = -4, z = -4}, + maxacc = {x = 4, y = 4, z = 4}, + minexptime = 0.1, + maxexptime = 1, + minsize = 0.5, + maxsize = 1, + texture = "particle.png", + }) +end + +-- check pad and teleport objects on top +minetest.register_abm({ + nodenames = {"teleport_potion:portal", "teleport_potion:pad"}, + interval = 1, + chance = 1, + + 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) + local target_coords = { + x = meta:get_float("x"), + y = meta:get_float("y"), + z = meta:get_float("z") + } + + for k, player in pairs(objs) do + if player:get_player_name() then + + -- play sound on portal end + minetest.sound_play("portal_close", { + pos = pos, + gain = 1.0, + max_hear_distance = 5 + }) + + -- move player/object + player:moveto(target_coords, false) + + -- 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 + }) + end + end + end +}) \ No newline at end of file diff --git a/init.lua b/init.lua index 154aec5..7c17627 100755 --- a/init.lua +++ b/init.lua @@ -94,6 +94,16 @@ minetest.register_node("teleport_potion:potion", { meta:set_float("z", teleport.default.z) end, +on_use = function(itemstack, user) + + throw_potion(itemstack, user) + + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + return itemstack + end +end, + -- right-click to enter new coords on_right_click = function(pos, placer) local meta = minetest.get_meta(pos) @@ -304,4 +314,83 @@ minetest.register_abm({ end end end -}) \ No newline at end of file +}) + +-- Throwable potions + +local potion_entity = { + physical = false, + 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:getpos() + local node = minetest.get_node(pos) + + if self.lastpos.x ~= nil then + + if node.name ~= "air" then + + if self.player ~= "" then + self.player:setpos(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) + +function throw_potion(itemstack, player) + + local playerpos = player:getpos() + + 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:setvelocity({ + x = dir.x * velocity, + y = dir.y * velocity, + z = dir.z * velocity + }) + + obj:setacceleration({ + x = dir.x * -3, + y = -9.5, + z = dir.z * -3 + }) + + obj:setyaw(player:get_look_yaw() + math.pi) + obj:get_luaentity().player = player + +end \ No newline at end of file