]> git.lizzy.rs Git - pathfinding.git/blob - init.lua
Initial commit
[pathfinding.git] / init.lua
1 local positions, index, global_goal
2
3 local function roundvec(v, d)
4         return vector.divide(vector.round(vector.multiply(v, d)), d)
5 end
6
7 local function findpath(pos)
8         global_goal = pos
9         index = 2
10         positions = minetest.find_path(
11                 minetest.localplayer:get_pos(),
12                 pos,
13                 tonumber(minetest.settings:get("goto_max_distance") or 25),
14                 tonumber(minetest.settings:get("goto_max_jump") or 1),
15                 tonumber(minetest.settings:get("goto_max_drop") or minetest.settings:get_bool("prevent_natural_damage") and 1000 or 5)
16         )
17 end
18
19 minetest.register_chatcommand("goto", {
20         description = "Go to a position (use pathfinding).",
21         param = "<pos>",
22         func = function(param)
23                 if positions then
24                         return false, "Goto is still active. Use .gotoabort to abort it."
25                 end
26                 local success, pos = minetest.parse_pos(param)
27                 if not success then
28                         return false, pos
29                 end
30                 findpath(pos)
31         end,
32 })
33
34 minetest.register_chatcommand("gotoabort", {
35         description = "Abort goto.",
36         param = "<pos>",
37         func = function(param)
38                 if not positions then
39                         return false, "Goto is currently not running (and also not walking haha)"
40                 end
41                 minetest.set_keypress("forward", false)
42                 minetest.set_keypress("sneak", false)
43                 positions, index, global_goal = nil
44                 return true, "Aborted."
45         end,
46 })
47
48 minetest.register_globalstep(function(dtime)
49         if positions then
50                 minetest.set_keypress("forward", true)
51                 minetest.set_keypress("sneak", false)
52                 local player = minetest.localplayer
53                 local pos = player:get_pos()
54                 local goal, next_goal = positions[index], positions[index+1]
55                 if not goal then
56                         positions, index, global_goal = nil
57                         minetest.set_keypress("forward", false)
58                         minetest.display_chat_message("Reached goal.")
59                         return
60                 end
61                 if next_goal then
62                         local d, dn = vector.subtract(pos, goal), vector.subtract(next_goal, goal)
63                         for k, v in pairs(dn) do
64                                 if v ~= 0 and k ~= "y" then
65                                         local cv = d[k]
66                                         if v > 0 and cv > 0 or v < 0 and cv < 0 then
67                                                 index = index + 1
68                                                 goal = next_goal
69                                         end
70                                         break
71                                 end     
72                         end
73                 end
74                 local npos = vector.add(goal, {x = 0, y = 1, z = 0})
75                 local node =  minetest.get_node_or_nil(npos)
76                 if node and node.name ~= air then
77                         minetest.dig_node(npos)
78                 end
79                 local velocity = player:get_velocity()
80                 velocity.y = 0
81                 if vector.length(velocity) < 0.1 then
82                         findpath(global_goal)
83                         return
84                 end
85                 local distance = vector.distance(pos, goal)
86                 if not next_goal and distance < 1 then
87                         index = index + 1
88                 end
89                 local direction = vector.direction(pos, vector.new(goal.x, 0, goal.z))
90                 local yaw = player:get_yaw() % 360
91                 local goal_yaw = math.deg(math.atan2(-direction.x, direction.z)) % 360
92                 local diff = math.abs(goal_yaw - yaw)
93                 if diff > 175 and diff < 185 and distance < 1 then
94                         index = index + 1
95                 elseif diff > 10 and diff < 350 then
96                         if yaw < goal_yaw and diff < 180 or yaw > goal_yaw and diff > 180 then
97                                 yaw = yaw + 10
98                         elseif yaw < goal_yaw and diff > 180 or yaw > goal_yaw and diff < 180 then
99                                 yaw = yaw - 10
100                         end
101                         if diff >= 90 and diff <= 270 then
102                                 minetest.set_keypress("sneak", true)
103                         end
104                         player:set_yaw(yaw)
105                 else
106                         player:set_yaw(goal_yaw)
107                 end
108         end
109 end)