Nahrát soubory do 'teleport_potion'

This commit is contained in:
Milan2018 2020-02-27 15:25:16 +01:00
parent 161f584846
commit 9b9ad3f41e
5 changed files with 573 additions and 0 deletions

View file

@ -0,0 +1,3 @@
default
intllib?
lucky_block?

View file

@ -0,0 +1 @@
Adds craftable teleport potions (throwable) and teleport pads.

503
teleport_potion/init.lua Normal file
View file

@ -0,0 +1,503 @@
--= 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_horizontal())
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")

View file

@ -0,0 +1,45 @@
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.
-- Get the latest version of this file at:
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
local function format(str, ...)
local args = { ... }
local function repl(escape, open, num, close)
if escape == "" then
local replacement = tostring(args[tonumber(num)])
if open == "" then
replacement = replacement..close
end
return replacement
else
return "@"..open..num..close
end
end
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end
local gettext, ngettext
if minetest.get_modpath("intllib") then
if intllib.make_gettext_pair then
-- New method using gettext.
gettext, ngettext = intllib.make_gettext_pair()
else
-- Old method using text files.
gettext = intllib.Getter()
end
end
-- Fill in missing functions.
gettext = gettext or function(msgid, ...)
return format(msgid, ...)
end
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
return format(n==1 and msgid or msgid_plural, ...)
end
return gettext, ngettext

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 TenPlus1
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.