Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

This pathfinding code using the C* algorithm isn't working, and getting no errors?

Asked by
Nickelz 37
5 years ago

I admittedly got this code from a youtube video ( link ) and it was made in 2016 meaning it's a bit outdated, but I thought it was still useful to try and get the C* algorithm, except when I tested it, the NPC did not move, at all. It produces no errors and still prints "Connected". I have no idea what is causing this. If anybody knows the solutions PLEASE help

Workspace Script:

local workSpace = game:GetService("Workspace")
local nodes = workSpace:WaitForChild("Nodes")
local Table = nodes:GetChildren()

function Connect()
    print("Connected")
    for _,A in ipairs(Table) do
        if #A:GetChildren() <= 0 then
            for _,B in ipairs(Table) do
                if B ~= A then
                    local P = workSpace:FindPartOnRay(Ray.new(A.Position), B.Position - A.Position)

                    if P == B then
                        local neigbor = Instance.new("ObjectValue")
                        neigbor.Value = B
                        neigbor.Name = "Neighbor"
                        neigbor.Parent = A
                    end
                end
            end
        end
    end
end

Connect()

Script inside of NPC:

local pathfinder = require(game:GetService("ReplicatedStorage"):WaitForChild("A*"))

local torso = script.Parent:WaitForChild("HumanoidRootPart")
local humanoid = script.Parent:WaitForChild("Humanoid")

function follow_path(goal)
    if not goal then return end
    local path = pathfinder(torso.Position, goal)
    for _,node in ipairs(path) do
        repeat wait()
            humanoid:MoveTo(node)
        until (node - torso.Position).Magnitude <= 4
    end
end

function getClosestPlayer(to)
    local distance = math.huge
    local output = nil
    for _,player in ipairs(game:GetService("Players"):GetPlayers()) do
        local diff = player:DistanceFromCharacter(to)
        if diff < distance and player.Character then
            distance = diff
            output = player.Character   
        end 
    end
    return output
end

while wait() do

    local player = getClosestPlayer(torso.Position)
    if player and player:FindFirstChild("Torso") then
        follow_path(player.Torso.Position)
    end
end

script inside of replicated storage:

local Nodes = workspace:WaitForChild("Nodes")
local Table = Nodes:GetChildren()
local index = {}

local Parent    = {}
local gScore    = {}
local fScore    = {}

function Dec(Number)
    local Ceil = math.ceil(Number)

    if Ceil - Number <= .5 then
        return Ceil
    else
        return math.floor(Number)
    end
end

function SortUp(Table, Index)
    while true do
        local parentIndex = Dec((Index-1) / 2)
        if parentIndex == 0 then return Table end
        if fScore[Table[parentIndex]] > fScore[Table[Index]] then
            Table[parentIndex], Table[Index] = Table[Index], Table[parentIndex]
            Index = parentIndex
        else
            return Table
        end
    end
end

function Length(A, B)
    if not A or not B then return math.huge end
    return (A.Position - B.Position).Magnitude
end

function ClosestNode(Coord)
    local Output = nil
    local Cap = math.huge
    for _,v in ipairs(Table)do
        local Distance = (v.Position - Coord).Magnitude
        if Distance < Cap then
            Output = v
            Cap = Distance
        end
    end

    return Output
end

function FindIndexOf(Value, In)
    local Directory = index[In]
    if not Directory then
        index[In] = {}
        -- No reason to look for it if the table doesn't even exist.
        return index[In]
    end

    return Directory
end

function A_Star(A, B)
    local A = ClosestNode(A)
    local B = ClosestNode(B)

    local ClosedList    = {}
    local OpenList      = {A}
    local Current

    Parent  = {}
    gScore  = {}
    fScore  = {}

    gScore[A] = 0
    fScore[A] = Length(A, B)
    Parent[A] = A

    repeat
        Current = OpenList[1]

        if Current == B then
            break
        end

        table.remove(OpenList, 1)
        ClosedList[Current] = Parent[Current]

        for _,v in ipairs(Current:GetChildren())do
            if v:IsA("ObjectValue") then
                local Node = v.Value

                local H = Length(Node, B)
                local G = gScore[Current] + Length(Current, Node)
                local F = G + H

                if not Parent[Node] and not ClosedList[Node] then
                    Parent[Node] = Current
                    fScore[Node] = F
                    gScore[Node] = G
                    table.insert(OpenList, Node)
                    OpenList = SortUp(OpenList, #OpenList)
                end
                if G < gScore[Node] then
                    Parent[Node] = Current
                    gScore[Node] = G
                    fScore[Node] = F
                end
            end
        end
    until #OpenList <= 0

    if #OpenList <= 0 then
        -- No path.
        return {}
    end

    -- Retrace path.
    local Path = {Current}
    Current = Parent[Current]
    repeat
        if Current then
            table.insert(Path, Current)
            if Parent[Current] == Current then
                break
            end
            Current = Parent[Current]
        end
    until not Current

    local Output = {}
    -- Reverse path.
    for i = #Path, 1, -1 do
        table.insert(Output, Path[i].Position)
    end
    if Current then
        return Output
    end
end

return A_Star

Answer this question