Cat_in_the_hat

Npc pathfindg

Nov 24th, 2025
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.01 KB | None | 0 0
  1. local start = Vector3.new(345, 69, 339)
  2. local step = 3
  3. local size = Vector3.new(3, 3, 3)
  4. local spawned = {}
  5.  
  6. local function key(p)
  7. return p.X..","..p.Y..","..p.Z
  8. end
  9.  
  10. local function snap(p)
  11. return Vector3.new(math.floor(p.X/step + 0.5)*step, p.Y, math.floor(p.Z/step + 0.5)*step)
  12. end
  13.  
  14. local function getRandomGoal()
  15. local players = PlayerService.getPlayers()
  16. if #players == 0 then return start end
  17. local p = players[math.random(1,#players)]
  18. local e = p:getEntity()
  19. if not e then return start end
  20. local pos = e:getPosition()
  21. if not pos then return start end
  22. local gx = ((pos.X+1)//3*3)
  23. local gy = ((pos.Y+1)//3*3)
  24. local gz = ((pos.Z+1)//3*3)
  25. return Vector3.new(gx,gy,gz), pos
  26. end
  27.  
  28. local goal, rawGoalPos = getRandomGoal()
  29.  
  30. local function free(p)
  31. return BlockService.getBlockAt(p) == nil
  32. end
  33.  
  34. local function hasBlockBelow(p)
  35. local below = Vector3.new(p.X, p.Y-step, p.Z)
  36. return BlockService.getBlockAt(below) ~= nil
  37. end
  38.  
  39. local function place(p, color)
  40. if not hasBlockBelow(p) then return false end
  41. local k = key(p)
  42. if spawned[k] then return false end
  43. spawned[k] = true
  44. local part = PartService.createPart(color or ItemType.CLAY_WHITE, p)
  45. part:setSize(size)
  46. part:setAnchored(true)
  47. part:setCollidable(false)
  48. return true
  49. end
  50.  
  51. local function equal(a,b)
  52. return a.X==b.X and a.Y==b.Y and a.Z==b.Z
  53. end
  54.  
  55. local function getNeighbors(p)
  56. local n = {}
  57. local dirs = {Vector3.new(step,0,0), Vector3.new(-step,0,0), Vector3.new(0,0,step), Vector3.new(0,0,-step)}
  58. for i = #dirs, 2, -1 do
  59. local j = math.random(1,i)
  60. dirs[i], dirs[j] = dirs[j], dirs[i]
  61. end
  62. for _, d in ipairs(dirs) do
  63. for dy=-step,step,step do
  64. local np = Vector3.new(p.X+d.X, p.Y+dy, p.Z+d.Z)
  65. if free(np) and hasBlockBelow(np) then
  66. table.insert(n, np)
  67. break
  68. end
  69. end
  70. end
  71. return n
  72. end
  73.  
  74. local function buildPath(s,g)
  75. local queue = {s}
  76. local came = {[key(s)]=s}
  77. local found,nodes,maxNodes = false,0,4000
  78.  
  79. while #queue>0 do
  80. local p = table.remove(queue,1)
  81. if equal(p,g) then found=true break end
  82. nodes=nodes+1
  83. if nodes>maxNodes then
  84. place(rawGoalPos, ItemType.CLAY_RED)
  85. print("UNREACHABLE:",rawGoalPos)
  86. return
  87. end
  88. for _, np in ipairs(getNeighbors(p)) do
  89. local k = key(np)
  90. if not came[k] then
  91. came[k]=p
  92. table.insert(queue,np)
  93. end
  94. end
  95. end
  96.  
  97. if not found then
  98. place(rawGoalPos, ItemType.CLAY_RED)
  99. print("UNREACHABLE:",rawGoalPos)
  100. return
  101. end
  102.  
  103. local path={}
  104. local cur=g
  105. while true do
  106. table.insert(path,cur)
  107. if equal(cur,s) then break end
  108. cur = came[key(cur)]
  109. end
  110.  
  111. for i=#path,1,-1 do
  112. place(path[i])
  113. end
  114. end
  115.  
  116. buildPath(start,goal)
Advertisement
Add Comment
Please, Sign In to add comment