From 3a326e4734cc161259f7626da241a288fc8cec97 Mon Sep 17 00:00:00 2001
From: TenPlus1 <kinsellaja@yahoo.com>
Date: Wed, 4 Nov 2015 19:34:58 +0000
Subject: [PATCH] Added throwable potions

---
 README.md         |  12 +-
 init (copy 1).lua | 307 ++++++++++++++++++++++++++++++++++++++++++++++
 init.lua          |  91 +++++++++++++-
 3 files changed, 408 insertions(+), 2 deletions(-)
 create mode 100755 init (copy 1).lua

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
-- 
GitLab