chen399d

巡路模組

Jul 23rd, 2025 (edited)
377
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.72 KB | Source Code | 0 0
  1. -- Module: TDS_PathfindingModule
  2. local PathfindingService = game:GetService("PathfindingService")
  3. local Players = game:GetService("Players")
  4. local Workspace = game:GetService("Workspace")
  5. local Debris = game:GetService("Debris")
  6.  
  7. local player = Players.LocalPlayer
  8. local character = player.Character or player.CharacterAdded:Wait()
  9. local humanoid = character:WaitForChild("Humanoid")
  10. local rootPart = character:WaitForChild("HumanoidRootPart")
  11.  
  12. -- === 模組表 ===
  13. local TDS = {}
  14.  
  15. -- === 參數設定 ===
  16. local MAX_RETRIES = 3
  17. local PATHFINDING_TIMEOUT = 5
  18. local PATH_VISUALIZATION_DURATION = 30
  19. local MAX_DEVIATION = 10 -- 偏離距離
  20.  
  21. -- === 路徑顏色策略 ===
  22. local PATH_COLORS = {
  23.     [1] = { point = BrickColor.new("Bright red"), connection = BrickColor.new("Really red") },
  24.     [2] = { point = BrickColor.new("Bright green"), connection = BrickColor.new("Earth green") },
  25.     [3] = { point = BrickColor.new("Bright blue"), connection = BrickColor.new("Really blue") }
  26. }
  27.  
  28. local isNavigating = false
  29. local pathParts = {}
  30. local attemptColor = 1
  31.  
  32. -- === 清除之前路徑顯示 ===
  33. local function clearPathVisualization()
  34.     for _, part in pairs(pathParts) do
  35.         if part and part.Parent then part:Destroy() end
  36.     end
  37.     pathParts = {}
  38. end
  39.  
  40. -- === 可視化路徑 ===
  41. local function visualizePath(waypoints, colorSet)
  42.     clearPathVisualization()
  43.     for i, waypoint in ipairs(waypoints) do
  44.         local pathPart = Instance.new("Part")
  45.         pathPart.Name = "PathPoint_" .. i
  46.         pathPart.Anchored = true
  47.         pathPart.CanCollide = false
  48.         pathPart.Material = Enum.Material.Neon
  49.         pathPart.BrickColor = colorSet.point
  50.         pathPart.Size = Vector3.new(1, 0.2, 1)
  51.         pathPart.Position = waypoint.Position
  52.         pathPart.Parent = Workspace
  53.  
  54.         local light = Instance.new("PointLight")
  55.         light.Brightness = 2
  56.         light.Range = 5
  57.         light.Color = colorSet.point.Color
  58.         light.Parent = pathPart
  59.  
  60.         if i > 1 then
  61.             local prev = waypoints[i-1]
  62.             local distance = (waypoint.Position - prev.Position).Magnitude
  63.             local connection = Instance.new("Part")
  64.             connection.Name = "PathConnection_" .. (i-1) .. "_to_" .. i
  65.             connection.Anchored = true
  66.             connection.CanCollide = false
  67.             connection.Material = Enum.Material.ForceField
  68.             connection.BrickColor = colorSet.connection
  69.             connection.Size = Vector3.new(0.2, 0.2, distance)
  70.             connection.CFrame = CFrame.lookAt((waypoint.Position + prev.Position) / 2, waypoint.Position)
  71.             connection.Parent = Workspace
  72.             table.insert(pathParts, connection)
  73.         end
  74.         table.insert(pathParts, pathPart)
  75.     end
  76.     for _, part in pairs(pathParts) do
  77.         Debris:AddItem(part, PATH_VISUALIZATION_DURATION)
  78.     end
  79. end
  80.  
  81. -- === 將目標調整到地面 ===
  82. local function snapToGround(position)
  83.     local params = RaycastParams.new()
  84.     params.FilterType = Enum.RaycastFilterType.Exclude
  85.     params.FilterDescendantsInstances = {character}
  86.  
  87.     local result = Workspace:Raycast(position + Vector3.new(0, 50, 0), Vector3.new(0, -100, 0), params)
  88.     if result then
  89.         return result.Position + Vector3.new(0, humanoid.HipHeight + 0.5, 0)
  90.     end
  91.     return nil
  92. end
  93.  
  94. -- === 偏移檢測 ===
  95. local function monitorDeviation(expectedPos)
  96.     local currentPos = rootPart.Position
  97.     return (currentPos - expectedPos).Magnitude <= MAX_DEVIATION
  98. end
  99.  
  100. -- === 三階段策略尋路 ===
  101. local function tryPathfindingWithStrategies(target)
  102.     for attempt = 1, 3 do
  103.         attemptColor = attempt
  104.         local path = PathfindingService:CreatePath({
  105.             AgentHeight = 5,
  106.             AgentRadius = 2,
  107.             AgentCanJump = true,
  108.             WaypointSpacing = (attempt == 1 and 4) or (attempt == 2 and 2) or 1
  109.         })
  110.         local success, err = pcall(function()
  111.             path:ComputeAsync(rootPart.Position, target)
  112.         end)
  113.         if success and path.Status == Enum.PathStatus.Success then
  114.             print("✅ 成功找到路徑(策略:" .. attempt .. ")")
  115.             return path
  116.         else
  117.             warn("❌ 策略 " .. attempt .. " 失敗:" .. (err or path.Status.Name))
  118.         end
  119.     end
  120.     return nil
  121. end
  122.  
  123. -- === 移動到單一路徑點 ===
  124. local function moveToWaypoint(waypoint, index, total)
  125.     local start = tick()
  126.     humanoid:MoveTo(waypoint.Position)
  127.     local done = false
  128.     local connection
  129.     connection = humanoid.MoveToFinished:Connect(function()
  130.         done = true
  131.         connection:Disconnect()
  132.     end)
  133.     while not done and tick() - start < PATHFINDING_TIMEOUT do
  134.         wait(0.1)
  135.     end
  136.     if connection then connection:Disconnect() end
  137.     return done
  138. end
  139.  
  140. -- === 核心導航函數 ===
  141. local function navigateTo(targetPos)
  142.     if isNavigating then return false end
  143.     isNavigating = true
  144.     local adjustedTarget = snapToGround(targetPos)
  145.     if not adjustedTarget then
  146.         warn("❌ 無法找到地面")
  147.         isNavigating = false
  148.         return false
  149.     end
  150.  
  151.     local path = tryPathfindingWithStrategies(adjustedTarget)
  152.     if not path then
  153.         warn("❌ 所有策略失敗")
  154.         isNavigating = false
  155.         return false
  156.     end
  157.  
  158.     local waypoints = path:GetWaypoints()
  159.     if #waypoints == 0 then
  160.         warn("❌ 路徑點為空")
  161.         isNavigating = false
  162.         return false
  163.     end
  164.  
  165.     visualizePath(waypoints, PATH_COLORS[attemptColor])
  166.  
  167.     for i, wp in ipairs(waypoints) do
  168.         if not isNavigating then return false end
  169.  
  170.         -- 偏移檢測
  171.         if not monitorDeviation(wp.Position) then
  172.             warn("⚠️ 偵測到偏移,重新尋路...")
  173.             isNavigating = false
  174.             return navigateTo(targetPos)
  175.         end
  176.  
  177.         -- 移動
  178.         if wp.Action == Enum.PathWaypointAction.Walk then
  179.             if not moveToWaypoint(wp, i, #waypoints) then
  180.                 warn("❌ 無法到達節點,重新尋路...")
  181.                 isNavigating = false
  182.                 return navigateTo(targetPos)
  183.             end
  184.         elseif wp.Action == Enum.PathWaypointAction.Jump then
  185.             humanoid.Jump = true
  186.             wait(0.5)
  187.         end
  188.  
  189.         -- ✅ 走完該節點 → 刪除對應的方塊 & 連線
  190.         local pointName = "PathPoint_" .. i
  191.         local connectionName = "PathConnection_" .. (i-1) .. "_to_" .. i
  192.         for index, part in ipairs(pathParts) do
  193.             if part.Name == pointName or part.Name == connectionName then
  194.                 if part and part.Parent then
  195.                     part:Destroy()
  196.                 end
  197.                 table.remove(pathParts, index)
  198.             end
  199.         end
  200.     end
  201.  
  202.  
  203.     print("🎉 成功抵達目標!")
  204.     isNavigating = false
  205.     return true
  206. end
  207.  
  208. -- === 對外 API ===
  209. function TDS:NavigateToPosition(x, y, z)
  210.     spawn(function()
  211.         navigateTo(Vector3.new(x, y, z))
  212.     end)
  213. end
  214.  
  215. function TDS:NavigateToPlayer(playerName)
  216.     local targetPlayer = Players:FindFirstChild(playerName)
  217.     if targetPlayer and targetPlayer.Character and targetPlayer.Character:FindFirstChild("HumanoidRootPart") then
  218.         local pos = targetPlayer.Character.HumanoidRootPart.Position
  219.         self:NavigateToPosition(pos.X, pos.Y, pos.Z)
  220.     else
  221.         warn("❌ 找不到玩家:" .. playerName)
  222.     end
  223. end
  224.  
  225. function TDS:StopCurrentNavigation()
  226.     if isNavigating then
  227.         isNavigating = false
  228.         humanoid:MoveTo(rootPart.Position)
  229.         clearPathVisualization()
  230.         print("⏹️ 導航已停止")
  231.     else
  232.         print("ℹ️ 無進行中的導航")
  233.     end
  234. end
  235. --TDS:NavigateToPosition(7, 129, 151)
  236. return TDS
  237.  
Advertisement
Add Comment
Please, Sign In to add comment