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

NPCs dont attack unless they reach their goal but also error when going for attack?

Asked by
5xephos 15
4 years ago

Testing Style - Studio Local Server with 2 players.

Script Location/Type - Regular script in the NPC

Output - https://ibb.co/8r5BN1m

Outcome - The NPC will spawn, and walk to its goal as expected, however, I want them to break their path if they detect another humanoid and go to attack it, and then continue down its path. Once it reaches its goal however it will stop and then the game will freeze and they'll move slightly and the output shows what I posted in the screenshot and they will stand there without doing anything

Code -

--Main body parts
local myRoot = script.Parent:WaitForChild("Torso")
local myHuman = script.Parent:WaitForChild("Humanoid")
local rightHand = script.Parent:WaitForChild("Right Arm")
local upperTorso = script.Parent:WaitForChild("Torso")
local team = myHuman.Team.Value

--Weapon
local sword = script.Parent:WaitForChild("Sword")
local swordWeld = sword:WaitForChild("SwordWeld")

--Sounds
local lungeSound = sword:WaitForChild("Lunge")
local slashSound = sword:WaitForChild("Slash")
local unsheathSound = sword:WaitForChild("Unsheath")

--AI Booleans
local attackCool = true
local swordHolstered = false
local chasing = false
local pathFailCount = 0 

--Animation
local leftSlash = script.Parent:WaitForChild("LeftSlash")
local leftSlashAnimation = myHuman:LoadAnimation(leftSlash)
leftSlashAnimation.Priority = Enum.AnimationPriority.Action

local rightSlash = script.Parent:WaitForChild("RightSlash")
local rightSlashAnimation = myHuman:LoadAnimation(rightSlash)
rightSlashAnimation.Priority = Enum.AnimationPriority.Action

--Respawn
local clone = script.Parent:Clone()

function getUnstuck()
    myHuman:Move(Vector3.new(math.random(-1,1),0,math.random(-1,1)))
    wait(0.3)
end

function wander()
    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)
    if path.Status == Enum.PathStatus.Success then
        pathFailCount = 0
        myHuman.WalkSpeed = 10
        local waypoints = path:GetWaypoints()
        for i,v in ipairs(waypoints) do
            if v.Action == Enum.PathWaypointAction.Jump then
                myHuman.Jump = true
            end
            myHuman:MoveTo(v.Position)
            if i % 5 == 0 then
                if findTarget() then
                    break
                end
            end
            local moveSuccess = myHuman.MoveToFinished:Wait()
            if not moveSuccess then
                break
            end
        end
    else
        pathFailCount = pathFailCount + 1 
        if pathFailCount > 10 then
            pathFailCount = 0
            getUnstuck()
        end
    end
end

function findTarget()
    local dist = 200
    local target = nil 
    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 and v.Humanoid.Team.Value ~= team then
            if (myRoot.Position - torso.Position).Magnitude < dist and human.Health > 0 then
                target = torso
                dist = (myRoot.Position - torso.Position).Magnitude
            end
        end
    end
    return target
end

function checkSight(target)
    local ray = Ray.new(myRoot.Position, (target.Position - myRoot.Position).Unit * 200)
    local hit,position = workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent})
    if hit then
        if hit:IsDescendantOf(target.Parent) then
            return true
        end
    end
    return false
end

function checkHeight(target)
    if math.abs(myRoot.Position.Y - target.Position.Y) < 1 then
        return true
    end
    return false
end

function checkDirect(target)
    if checkSight(target) and checkHeight(target) and (myRoot.Position - target.Position).Magnitude < 30 then
        return true
    end
    return false
end

function attack(target)
    if attackCool == true then
        attackCool = false
        myHuman:MoveTo(target.Position)

        local attackAnim = math.random(2)
        if attackAnim == 1 then
            slashSound:Play()
            leftSlashAnimation:Play()
        else
            lungeSound:Play()
            rightSlashAnimation:Play()
        end

        local human = target.Parent.Humanoid
        human:TakeDamage(math.random(20,30))

        if human.Health < 1 then
            wait(0.3)
        end

        spawn(function() wait(1) attackCool = true end)
    end
end

function holsterSword()
    if swordHolstered == false then
        swordHolstered = true

        unsheathSound:Play()

        swordWeld.Part1 = nil
        sword.CFrame = upperTorso.CFrame * CFrame.new(0,0,0.7) * CFrame.Angles(math.rad(90),math.rad(-45),math.rad(0))
        swordWeld.Part1 = upperTorso
    end
end

function drawSword()
    if swordHolstered == true then
        swordHolstered = false

        unsheathSound:Play()

        swordWeld.Part1 = nil
        sword.CFrame = rightHand.CFrame * CFrame.new(0,0,-2) * CFrame.Angles(0,math.rad(180),math.rad(90))
        swordWeld.Part1 = rightHand
    end
end

function pathToTarget(target)
    local path = game:GetService("PathfindingService"):CreatePath()
    path:ComputeAsync(myRoot.Position,target.Position)
    if path.Status == Enum.PathStatus.Success then
        pathFailCount = 0
        local waypoints = path:GetWaypoints()
        for i,v in ipairs(waypoints) do
            if v.Action == Enum.PathWaypointAction.Jump then
                myHuman.Jump = true
            end
            spawn(function()
                wait(0.5)
            myHuman:MoveTo(v.Position)
            local moveSuccess = myHuman.MoveToFinished:Wait()
            if not moveSuccess then 
            end
            if i % 5 == 0 then
                if checkDirect(target) then
                end
                if target ~= findTarget() then
                end
            end
            if (waypoints[#waypoints].Position - target.Position).Magnitude > 30 then
            end
            end)
        end
    end
end


function chase(target)
    myHuman.WalkSpeed = 20
    chasing = true
    myHuman:MoveTo(target.Position)
end

myHuman.Died:Connect(function()
    sword.CanCollide = true
    wait(15)
    clone.Parent = workspace
    game:GetService("Debris"):AddItem(script.Parent,0.1)
end)

function WalkTargetDestination()
    local destination = game.Workspace:FindFirstChild("map1").DestinationWB.Position
    local goal = destination
    local path = game:GetService("PathfindingService"):CreatePath()

    path.Blocked:Connect(function()
    print("Break!")
    breakPath = true
end)

path:ComputeAsync(myRoot.Position, destination)
if path.Status == Enum.PathStatus.Success then
    breakPath = false

    local waypoints = path:GetWaypoints()
        local wastedTime = 0
    for _, waypoint in pairs(waypoints) do  
        repeat
                        wastedTime = wastedTime + 0.25
            if(waypoint.Action == Enum.PathWaypointAction.Jump) then
                myHuman.Jump = true
            end

             if breakPath == true then break end
            myHuman:MoveTo(waypoint.Position)
            wait()
        until (myRoot.Position - waypoint.Position).magnitude < 8 or breakPath == true
    end
end
end

function main()
    chasing = false 
    myHuman.WalkSpeed = 16
    local target = findTarget()
    if target then
        local targetDistance = (myRoot.Position - target.Position).Magnitude
        if targetDistance > 30 then
            holsterSword()
        else
            drawSword()
        end
        if checkDirect(target) then
            if targetDistance > 3 then
                chase(target)
            end
            if targetDistance < 6 then
                attack(target)
            end
        elseif checkSight(target) and math.abs(myRoot.Position.X - target.Position.X) < 1 and 
            math.abs(myRoot.Position.Z - target.Position.Z) < 1 then
        else
            pathToTarget(target)
        end
    else
        holsterSword()
        WalkTargetDestination()
        repeat until target
        end
    end

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


Any help is appreciated! Thank you in advance.

0
I think you might be calling the function main() while defining it. You need to add another end. jalbraek 29 — 4y
0
It says it expected <eof> but instead got end. Perhaps you could specify where in case i'm doing this wrong? 5xephos 15 — 4y

Answer this question