110 lines
3.1 KiB
Lua
110 lines
3.1 KiB
Lua
local positions, index, global_goal
|
|
|
|
local function roundvec(v, d)
|
|
return vector.divide(vector.round(vector.multiply(v, d)), d)
|
|
end
|
|
|
|
local function findpath(pos)
|
|
global_goal = pos
|
|
index = 2
|
|
positions = minetest.find_path(
|
|
minetest.localplayer:get_pos(),
|
|
pos,
|
|
tonumber(minetest.settings:get("goto_max_distance") or 25),
|
|
tonumber(minetest.settings:get("goto_max_jump") or 1),
|
|
tonumber(minetest.settings:get("goto_max_drop") or minetest.settings:get_bool("prevent_natural_damage") and 1000 or 5)
|
|
)
|
|
end
|
|
|
|
minetest.register_chatcommand("goto", {
|
|
description = "Go to a position (use pathfinding).",
|
|
param = "<pos>",
|
|
func = function(param)
|
|
if positions then
|
|
return false, "Goto is still active. Use .gotoabort to abort it."
|
|
end
|
|
local success, pos = minetest.parse_pos(param)
|
|
if not success then
|
|
return false, pos
|
|
end
|
|
findpath(pos)
|
|
end,
|
|
})
|
|
|
|
minetest.register_chatcommand("gotoabort", {
|
|
description = "Abort goto.",
|
|
param = "<pos>",
|
|
func = function(param)
|
|
if not positions then
|
|
return false, "Goto is currently not running (and also not walking haha)"
|
|
end
|
|
minetest.set_keypress("forward", false)
|
|
minetest.set_keypress("sneak", false)
|
|
positions, index, global_goal = nil
|
|
return true, "Aborted."
|
|
end,
|
|
})
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
if positions then
|
|
minetest.set_keypress("forward", true)
|
|
minetest.set_keypress("sneak", false)
|
|
local player = minetest.localplayer
|
|
local pos = player:get_pos()
|
|
local goal, next_goal = positions[index], positions[index+1]
|
|
if not goal then
|
|
positions, index, global_goal = nil
|
|
minetest.set_keypress("forward", false)
|
|
minetest.display_chat_message("Reached goal.")
|
|
return
|
|
end
|
|
if next_goal then
|
|
local d, dn = vector.subtract(pos, goal), vector.subtract(next_goal, goal)
|
|
for k, v in pairs(dn) do
|
|
if v ~= 0 and k ~= "y" then
|
|
local cv = d[k]
|
|
if v > 0 and cv > 0 or v < 0 and cv < 0 then
|
|
index = index + 1
|
|
goal = next_goal
|
|
end
|
|
break
|
|
end
|
|
end
|
|
end
|
|
local npos = vector.add(goal, {x = 0, y = 1, z = 0})
|
|
local node = minetest.get_node_or_nil(npos)
|
|
if node and node.name ~= air then
|
|
minetest.dig_node(npos)
|
|
end
|
|
local velocity = player:get_velocity()
|
|
velocity.y = 0
|
|
if vector.length(velocity) < 0.1 then
|
|
findpath(global_goal)
|
|
return
|
|
end
|
|
local distance = vector.distance(pos, goal)
|
|
if not next_goal and distance < 1 then
|
|
index = index + 1
|
|
end
|
|
local direction = vector.direction(pos, vector.new(goal.x, 0, goal.z))
|
|
local yaw = player:get_yaw() % 360
|
|
local goal_yaw = math.deg(math.atan2(-direction.x, direction.z)) % 360
|
|
local diff = math.abs(goal_yaw - yaw)
|
|
if diff > 175 and diff < 185 and distance < 1 then
|
|
index = index + 1
|
|
elseif diff > 10 and diff < 350 then
|
|
if yaw < goal_yaw and diff < 180 or yaw > goal_yaw and diff > 180 then
|
|
yaw = yaw + 10
|
|
elseif yaw < goal_yaw and diff > 180 or yaw > goal_yaw and diff < 180 then
|
|
yaw = yaw - 10
|
|
end
|
|
if diff >= 90 and diff <= 270 then
|
|
minetest.set_keypress("sneak", true)
|
|
end
|
|
player:set_yaw(yaw)
|
|
else
|
|
player:set_yaw(goal_yaw)
|
|
end
|
|
end
|
|
end)
|