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

How would I make it so when the target is not close enough it goes to a certain part? (zombie ai)

Asked by 3 years ago
Edited 3 years ago

I know nothing about stuff f like this, so help would be appreciated :)

I am making a zombie that goes to a certain part when it has no target Note: most of this script is not mine, some of it is though Part of the script:

local myHuman = script.Parent:WaitForChild("Humanoid")
local myRoot = script.Parent:WaitForChild("HumanoidRootPart")
local head = script.Parent:WaitForChild("Head")
local lowerTorso = script.Parent:WaitForChild("LowerTorso")

local grab = script.Parent:WaitForChild("Grab")
local grabAnim = myHuman:LoadAnimation(grab)
grabAnim.Priority = Enum.AnimationPriority.Action

local grabSound = head:WaitForChild("Attack")
local screamSound = head:WaitForChild("Scream")

local clone = script.Parent:Clone()

function walkRandomly()
    local xRand = math.random(-50,50)
    local zRand = math.random(-50,50)
    local goal = myRoot.Position + Vector3.new(xRand,0,zRand)

    local path = game:GetService("PathfindingService"):CreatePath()
    path:ComputeAsync(myRoot.Position, goal)
    local waypoints = path:GetWaypoints()

    if path.Status == Enum.PathStatus.Success then
        for _, waypoint in ipairs(waypoints) do
            if waypoint.Action == Enum.PathWaypointAction.Jump then
                myHuman.Jump = true
            end
            myHuman:MoveTo(waypoint.Position)
            local timeOut = myHuman.MoveToFinished:Wait(1)
            if not timeOut then
                print("Got stuck")
                myHuman.Jump = true
                walkRandomly()
            end
        end
    else
        print("Path failed")
        wait(1)
        walkRandomly()
    end
end

function findPath(target)
    local path = game:GetService("PathfindingService"):CreatePath()
    path:ComputeAsync(myRoot.Position,target.Position)
    local waypoints = path:GetWaypoints()

    if path.Status == Enum.PathStatus.Success then
        for _, waypoint in ipairs(waypoints) do
            if waypoint.Action == Enum.PathWaypointAction.Jump then
                myHuman.Jump = true
            end
            myHuman:MoveTo(waypoint.Position)
            local timeOut = myHuman.MoveToFinished:Wait(1)
            if not timeOut then
                myHuman.Jump = true
                print("Path too long!")
                findPath(target)
                break
            end
            if checkSight(target) then
                repeat
                    print("Moving directly to the target")
                    myHuman:MoveTo(target.Position)
                    attack(target)
                    wait(0.1)
                    if target == nil then
                        break
                    elseif target.Parent == nil then
                        break
                    end
                until checkSight(target) == false or myHuman.Health < 1 or target.Parent.Humanoid.Health < 1
                break
            end
            if (myRoot.Position - waypoints[1].Position).magnitude > 20 then
                print("Target has moved, generating new path")
                findPath(target)
                break
            end
        end
    end
end

function checkSight(target)
    local ray = Ray.new(myRoot.Position, (target.Position - myRoot.Position).Unit * 40)
    local hit,position = workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent})
    if hit then
        if hit:IsDescendantOf(target.Parent) and math.abs(hit.Position.Y - myRoot.Position.Y) < 3 then
            print("I can see the target")
            return true
        end
    end
    return false
end

function findTarget()
    local dist = 50
    local target = nil
    local potentialTargets = {}
    local seeTargets = {}
    for i,v in ipairs(workspace:GetChildren()) do
        local human = v:FindFirstChild("Humanoid")
        local torso = v:FindFirstChild("Torso") or v:FindFirstChild("HumanoidRootPart")
        if human and torso and v.Name ~= script.Parent.Name then
            if (myRoot.Position - torso.Position).magnitude < dist and human.Health > 0 then
                table.insert(potentialTargets,torso)
            end
        end
    end
    if #potentialTargets > 0 then
        for i,v in ipairs(potentialTargets) do
            if checkSight(v) then
                table.insert(seeTargets, v)
            elseif #seeTargets == 0 and (myRoot.Position - v.Position).magnitude < dist then
                target = v
                dist = (myRoot.Position - v.Position).magnitude
            end
        end
    end
    if #seeTargets > 0 then
        dist = 200
        for i,v in ipairs(seeTargets) do
            if (myRoot.Position - v.Position).magnitude < dist then
                target = v
                dist = (myRoot.Position - v.Position).magnitude
            end
        end
    end
    if target then
        if math.random(20) == 1 then
            screamSound:Play()
        end
    end
    return target
end

function attack(target)
    if (myRoot.Position - target.Position).magnitude < 5 then
        grabAnim:Play()
        grabSound:Play()
        if target.Parent ~= nil then
            target.Parent.Humanoid:TakeDamage(25)
        end
        wait(0.4)
    end
end

function died()
    wait(5)
    clone.Parent = workspace
    game:GetService("Debris"):AddItem(script.Parent,0.1)
end

myHuman.Died:Connect(died)

lowerTorso.Touched:Connect(function(obj)
    if not obj.Parent:FindFirstChild("Humanoid") then
        myHuman.Jump = true
    end
end)

function main()
    local target = findTarget()
    if target then
        myHuman.WalkSpeed = 16
        findPath(target)
    else
        myHuman.WalkSpeed = 8
        walkRandomly()
    end
end

while wait(0.1) do
    if myHuman.Health < 1 then
        break
    end
    main()
end

This is the script that makes it walk randomly when the target is not close enough I think this is the most helpful script from the main script if you're trying to answer this question:

function walkRandomly()
    local xRand = math.random(-50,50)
    local zRand = math.random(-50,50)
    local goal = myRoot.Position + Vector3.new(xRand,0,zRand)

    local path = game:GetService("PathfindingService"):CreatePath() path:ComputeAsync(myRoot.Position, goal)
    local waypoints = path:GetWaypoints()

    if path.Status == Enum.PathStatus.Success then
    for _, waypoint in ipairs(waypoints) do
    if waypoint.Action == Enum.PathWaypointAction.Jump then
    myHuman.Jump = true
    end

0
You only have one end when there should be 4 ends, to close the function, if statement, for loop, and last if statement. I don't know if that was intentional, but at least I think I've done something. PoWerofThEePg 43 — 3y
0
Oh thats only part of the script, the full script is at the top, and the script works fine I just want it so if theres no target it goes to a certain place instead of walking randomly RenDevelopment 15 — 3y

Answer this question