Added target selection. Cashe teleporters.
parent
789ab2c485
commit
32f9d0b8c1
170
init.lua
170
init.lua
|
@ -1,4 +1,110 @@
|
|||
teleports = {}
|
||||
teleports.teleports = {}
|
||||
teleports.lastplayername =""
|
||||
teleports.filename = minetest.get_worldpath() .. "/teleports.txt"
|
||||
|
||||
function teleports:save()
|
||||
local datastring = minetest.serialize(self.teleports)
|
||||
if not datastring then
|
||||
return
|
||||
end
|
||||
local file, err = io.open(self.filename, "w")
|
||||
if err then
|
||||
return
|
||||
end
|
||||
file:write(datastring)
|
||||
file:close()
|
||||
end
|
||||
function teleports:load()
|
||||
local file, err = io.open(self.filename, "r")
|
||||
if err then
|
||||
self.teleports = {}
|
||||
return
|
||||
end
|
||||
self.teleports = minetest.deserialize(file:read("*all"))
|
||||
if type(self.teleports) ~= "table" then
|
||||
self.teleports = {}
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
function teleports:find_nearby(pos, count)
|
||||
local nearby = {}
|
||||
for i = #teleports.teleports, 1, -1 do
|
||||
local EachTeleport = teleports.teleports[i]
|
||||
if not vector.equals(EachTeleport.pos, pos) and vector.distance(EachTeleport.pos, pos) < 260 then
|
||||
table.insert(nearby, EachTeleport)
|
||||
if #nearby>count then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return nearby
|
||||
end
|
||||
teleports.set_formspec = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
local buttons = "";
|
||||
for i, EachTeleport in ipairs( teleports:find_nearby(pos, 5) ) do
|
||||
buttons = buttons.."button_exit[3,"..(i)..";2,0.5;tp"..i..";GO>"..EachTeleport.pos.x..","..EachTeleport.pos.y..","..EachTeleport.pos.z.."]";
|
||||
end
|
||||
|
||||
meta:set_string("formspec", "size[8,10;]"
|
||||
.."label[0,0;" .. 'Go to available teleports! Use mossy cobble as fuel!' .. "]"
|
||||
.."list[current_name;price;0,1;1,1;]"
|
||||
|
||||
..buttons
|
||||
|
||||
.."button_exit[1,5;2,0.5;cancel;Cancel]"
|
||||
.."list[current_player;main;0,6;8,4;]")
|
||||
end
|
||||
teleports.on_receive_fields = function(pos, formname, fields, player)
|
||||
local meta = minetest.env:get_meta(pos);
|
||||
local inv = meta:get_inventory();
|
||||
local price = {name="default:mossycobble", count=1, wear=0, metadata=""}
|
||||
if fields.tp1 or fields.tp2 or fields.tp3 or fields.tp4 or fields.tp5 or fields.tp6 then
|
||||
if inv:contains_item("price", price) then
|
||||
inv:remove_item("price", price);
|
||||
local available = teleports:find_nearby(pos, 5)
|
||||
if player ~= nil and player:is_player() then
|
||||
if fields.tp1 and #available>0 then
|
||||
player:setpos({x=available[1].pos.x,y=available[1].pos.y+0.5,z=available[1].pos.z})
|
||||
teleports.lastplayername = player:get_player_name()
|
||||
elseif fields.tp2 and #available>1 then
|
||||
player:setpos({x=available[2].pos.x,y=available[2].pos.y+0.5,z=available[2].pos.z})
|
||||
teleports.lastplayername = player:get_player_name()
|
||||
elseif fields.tp3 and #available>2 then
|
||||
player:setpos({x=available[3].pos.x,y=available[3].pos.y+0.5,z=available[3].pos.z})
|
||||
teleports.lastplayername = player:get_player_name()
|
||||
elseif fields.tp4 and #available>3 then
|
||||
player:setpos({x=available[3].pos.x,y=available[3].pos.y+0.5,z=available[3].pos.z})
|
||||
teleports.lastplayername = player:get_player_name()
|
||||
elseif fields.tp5 and #available>4 then
|
||||
player:setpos({x=available[5].pos.x,y=available[5].pos.y+0.5,z=available[5].pos.z})
|
||||
teleports.lastplayername = player:get_player_name()
|
||||
elseif fields.tp6 and #available>5 then
|
||||
player:setpos({x=available[6].pos.x,y=available[6].pos.y+0.5,z=available[6].pos.z})
|
||||
teleports.lastplayername = player:get_player_name()
|
||||
end
|
||||
end
|
||||
|
||||
teleports.set_formspec(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
teleports.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
if listname=="price" and stack:get_name()=="default:mossycobble" then
|
||||
return 99
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
teleports.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
return 0
|
||||
end
|
||||
|
||||
teleports:load()
|
||||
|
||||
|
||||
minetest.register_node("teleports:teleport", {
|
||||
description = "Teleport",
|
||||
|
@ -9,7 +115,32 @@ minetest.register_node("teleports:teleport", {
|
|||
groups = {cracky=1, level=3},
|
||||
drop = 'default:diamond',
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
after_place_node = function(pos, placer)
|
||||
if placer and placer:is_player() then
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("price", 1)
|
||||
local initialcharge = {name="default:mossycobble", count=30, wear=0, metadata=""}
|
||||
inv:add_item("price", initialcharge)
|
||||
teleports.set_formspec(pos)
|
||||
table.insert(teleports.teleports, {pos=vector.round(pos)} )
|
||||
teleports:save()
|
||||
end
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
for i, EachTeleport in ipairs(teleports.teleports) do
|
||||
if vector.equals(EachTeleport.pos, pos) then
|
||||
table.remove(teleports.teleports, i)
|
||||
teleports:save()
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_receive_fields = teleports.on_receive_fields,
|
||||
allow_metadata_inventory_put = teleports.allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = teleports.allow_metadata_inventory_take,
|
||||
})
|
||||
|
||||
|
||||
--redefine diamond
|
||||
minetest.register_node(":default:diamondblock", {
|
||||
description = "Diamond Block",
|
||||
|
@ -46,38 +177,23 @@ minetest.register_abm({
|
|||
interval = 10,
|
||||
chance = 1,
|
||||
action = function(pos)
|
||||
local objectsnear=minetest.get_objects_inside_radius({x=pos.x,y=pos.y+0.5,z=pos.z}, 0.52)
|
||||
local r=80
|
||||
local objectsnear=minetest.get_objects_inside_radius({x=pos.x,y=pos.y+0.5,z=pos.z}, 0.52);
|
||||
if #objectsnear>0 then
|
||||
local player = objectsnear[1]
|
||||
if player:is_player() then
|
||||
local power = minetest.find_nodes_in_area(
|
||||
{x=pos.x-1, y=pos.y, z=pos.z-1},
|
||||
{x=pos.x+1, y=pos.y, z=pos.z+1},
|
||||
{"default:diamondblock"})
|
||||
r=r+#power*20 --diamond blocks around teleport increase its range
|
||||
local positions = minetest.find_nodes_in_area(
|
||||
{x=pos.x-r, y=pos.y-r, z=pos.z-r},
|
||||
{x=pos.x+r, y=pos.y+r, z=pos.z+r},
|
||||
{"teleports:teleport"})
|
||||
while #positions>1 do
|
||||
local player = objectsnear[1];
|
||||
if player:is_player() and player:get_player_name()~=teleports.lastplayername then
|
||||
local positions = teleports:find_nearby(pos, 10)
|
||||
if #positions>0 then
|
||||
local key = math.random(1, #positions)
|
||||
local pos2 = positions[key] --choose teleport randomly
|
||||
if (pos.x == pos2.x and pos.y == pos2.y and pos.z == pos2.z) or -- any better way to compare?
|
||||
minetest.get_node({x=pos2.x,y=pos2.y+1,z=pos2.z}).name~="air" or
|
||||
minetest.get_node({x=pos2.x,y=pos2.y+2,z=pos2.z}).name~="air"
|
||||
then
|
||||
table.remove(positions, key)
|
||||
else
|
||||
minetest.after(0.2, function()
|
||||
if player ~= nil and player:is_player() then --still is player, just in case
|
||||
local pos2 = positions[key].pos
|
||||
teleports.lastplayername = player:get_player_name()
|
||||
if math.random(1, 100) > 5 then
|
||||
player:setpos({x=pos2.x,y=pos2.y+0.5,z=pos2.z})
|
||||
minetest.log("info", "Player teleported from "..pos.x..","..pos.y..","..pos.z.." to "..pos2.x..","..pos2.y..","..pos2.z)
|
||||
end
|
||||
end)
|
||||
break
|
||||
else
|
||||
player:setpos({x=pos2.x-5+math.random(1, 10),y=pos2.y+3,z=pos2.z-5+math.random(1, 10)})
|
||||
end
|
||||
end
|
||||
else
|
||||
teleports.lastplayername = ""
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
|
Loading…
Reference in New Issue