97 lines
3.1 KiB
Lua
97 lines
3.1 KiB
Lua
-- Maximum nodes that can be travelled with one usage.
|
|
local max_moves = tonumber(minetest.setting_get("sneakladder.max_moves")) or 3
|
|
-- Minimum moves before action is taken.
|
|
local min_moves = tonumber(minetest.setting_get("sneakladder.min_moves")) or 0
|
|
-- Maximum distance from the target, in single coordinates.
|
|
local max_dist = tonumber(minetest.setting_get("sneakladder.max_dist")) or 3
|
|
local max_y_dist = tonumber(minetest.setting_get("sneakladder.max_y_dist")) or 2
|
|
-- Allow "sneakladdering" down.
|
|
local down = minetest.setting_getbool("sneakladder.down") or true
|
|
-- Number of moves before complete wear. 0 for no wear at all.
|
|
local all_moves = tonumber(minetest.setting_get("sneakladder.all_moves")) or 3000
|
|
|
|
local f = function(itemstack, user, pointed_thing)
|
|
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
|
if not user or not pos then
|
|
return
|
|
end
|
|
local pitch = user:get_look_vertical()
|
|
local change = (pitch < 0) and 1 or -1
|
|
|
|
if (not down) and (change == -1) then
|
|
return
|
|
end
|
|
|
|
local target = vector.new(pos)
|
|
local last = vector.new(user:get_pos())
|
|
local diff = vector.apply(vector.round(vector.subtract(last, target)), function(n)
|
|
if n == 0 then
|
|
return 0
|
|
elseif n < 0 then
|
|
return -1
|
|
else
|
|
return 1
|
|
end
|
|
end)
|
|
local used_moves = 0
|
|
|
|
local function can_sneak_over(pos)
|
|
local node = minetest.get_node_or_nil(pos)
|
|
if not node then return false end
|
|
return not minetest.registered_nodes[node.name].walkable
|
|
end
|
|
|
|
local function can_stand_on(pos)
|
|
local node = minetest.get_node_or_nil(pos)
|
|
if not node then return false end
|
|
return minetest.registered_nodes[node.name].walkable
|
|
end
|
|
|
|
if math.abs(target.x - last.x) > max_dist or math.abs(target.y - last.y) > max_y_dist or math.abs(target.z - last.z) > max_dist then
|
|
return
|
|
end
|
|
|
|
local canlast = false
|
|
|
|
while used_moves < max_moves do
|
|
if not can_stand_on(target) then break end
|
|
target.y = target.y + change
|
|
if not can_sneak_over(target) then break end
|
|
last = vector.add(target, vector.divide(diff, {x=1.2, y=2, z=1.2}))
|
|
if not can_sneak_over(last) or not can_sneak_over(vector.add(last, {x=0, y=change, z=0})) then break end
|
|
canlast = true
|
|
target.y = target.y + change
|
|
used_moves = used_moves + 1
|
|
end
|
|
if canlast and used_moves >= min_moves then
|
|
user:set_pos(last)
|
|
else
|
|
return
|
|
end
|
|
|
|
if all_moves > 0 then
|
|
if 65536 - itemstack:get_wear() <= (65536 / all_moves) then
|
|
itemstack:clear()
|
|
else
|
|
itemstack:add_wear(65536 / all_moves)
|
|
end
|
|
end
|
|
return itemstack
|
|
end
|
|
|
|
minetest.register_tool("sneakladder:tool", {
|
|
description = "Sneakladder Tool",
|
|
inventory_image = "sneakladder_item.png",
|
|
on_place = f,
|
|
on_use = f,
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "sneakladder:tool",
|
|
recipe = {
|
|
{"", "group:wood", ""},
|
|
{"group:stick", "group:leaves", "group:stick"},
|
|
{"group:leaves", "group:stick", "group:leaves"}
|
|
},
|
|
})
|