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

NPC Follow system works but after death it stops working [?]

Asked by 7 years ago
Edited 6 years ago

Goal:

My goal is to create an NPC follow system (I already have the damage system completed). What it should do it if you are within a certain range measured by magnitude you are chased by some NPC's that are within range.

Problem:

The problem is when a Player first spawns in the NPC chases the player and everything but when the player Dies by something (NPC, another player) the NPC's stop chasing the player. The code works but it stops working sometimes.

Script:

Note that this is a ServerScript in ServerScriptService

local RunService = game:GetService("RunService")
local Settings = require(game:GetService("ReplicatedStorage").ModuleScripts.SETTINGS)
local Respawn_Time = Settings.BANDIT.RESPAWN_TIME
local plrServ = game:GetService('Players')
local NPCBackup = game:GetService('ServerStorage').NPCBackup.Bandit

local function getClosestPlayer(myPos)
    local pos, tor = Settings.BANDIT.RANGE
    for _, plr in pairs(plrServ:GetPlayers()) do
        if plr.Character then
            if (plr.Character.PrimaryPart.Position - myPos).Magnitude < pos then
                pos = (plr.Character.PrimaryPart.Position - myPos).Magnitude
                tor = plr.Character.PrimaryPart
            end
        end
    end
    return tor
end

local function setupNPC(Bandit, BanditPosition)

    local hum = Bandit.Humanoid
    local npcPrimaryPart = Bandit.PrimaryPart
    local targetTorso
    spawn(function() 
        while wait(1) do
            targetTorso = getClosestPlayer(npcPrimaryPart.Position)
            if targetTorso then
                hum:MoveTo(targetTorso.Position, targetTorso)
            else
                return
            end
        end
    end)

    hum.Died:Connect(function()
        wait(Settings.BANDIT.RESPAWN_TIME)
        local cln = NPCBackup:Clone()
        cln:SetPrimaryPartCFrame(BanditPosition)
        cln.Parent = workspace.Bandits
        Bandit:Destroy()
        setupNPC(cln, BanditPosition)
        if not cln:FindFirstChild('RobloxAnimation') then
            local Animation = game:GetService('ServerStorage').Effects.RobloxAnimation:Clone()
            Animation.Disabled = false
            Animation.Parent = cln
            cln.Humanoid.WalkSpeed = Settings.BANDIT.WALKSPEED
        end
    end)
end

for _, Bandit in pairs(workspace.Bandits:GetChildren()) do
    spawn(function() setupNPC(Bandit, Bandit.PrimaryPart.CFrame) end)
end

Hopefully, this problem gets solved, I appreciate any feedback that fixes this issue or improves the code. I try avoiding loops and RunService mostly because I do not know when is the correct time to use a while true do loop and I know that using a loop incorrectly can be studio crashing and game breaking. Thank you for reading.

0
Correct me if I'm wrong, but it seems like you only call the setup for each NPC once. That means when the player dies, the NPC can't find the torso and calls "return" in the else function. That would make the NPC stop moving towards the player. Creeperman1524 120 — 6y
0
I do believe that someone had said this as well on the discord Creeperman1524 120 — 6y
0
How could I fix this? BlackOrange3343 2676 — 6y
0
I would think just removing it would work. If it finds the target it will move. If it doesn't instead of never moving, it will constantly look for a new target. Creeperman1524 120 — 6y

2 answers

Log in to vote
1
Answered by 6 years ago

Although this may no be correct, here is my answer on it

local RunService = game:GetService("RunService")
local Settings = require(game:GetService("ReplicatedStorage").ModuleScripts.SETTINGS)
local Respawn_Time = Settings.BANDIT.RESPAWN_TIME
local plrServ = game:GetService('Players')
local NPCBackup = game:GetService('ServerStorage').NPCBackup.Bandit

local function getClosestPlayer(myPos)
    local pos, tor = Settings.BANDIT.RANGE
    for _, plr in pairs(plrServ:GetPlayers()) do
        if plr.Character then
            if (plr.Character.PrimaryPart.Position - myPos).Magnitude < pos then
                pos = (plr.Character.PrimaryPart.Position - myPos).Magnitude
                tor = plr.Character.PrimaryPart
            end
    else
       tor = nil --Added this here so if it can't find the player, it will return nil
        end
    end
    return tor
end

local function setupNPC(Bandit, BanditPosition)

    local hum = Bandit.Humanoid
    local npcPrimaryPart = Bandit.PrimaryPart
    local targetTorso
    spawn(function() 
        while wait(1) do
            targetTorso = getClosestPlayer(npcPrimaryPart.Position)
            if targetTorso then
                hum:MoveTo(targetTorso.Position, targetTorso)
        --Removed the else here
            end
        end
    end)

    hum.Died:Connect(function()
        wait(Settings.BANDIT.RESPAWN_TIME)
        local cln = NPCBackup:Clone()
        cln:SetPrimaryPartCFrame(BanditPosition)
        cln.Parent = workspace.Bandits
        Bandit:Destroy()
        setupNPC(cln, BanditPosition)
        if not cln:FindFirstChild('RobloxAnimation') then
            local Animation = game:GetService('ServerStorage').Effects.RobloxAnimation:Clone()
            Animation.Disabled = false
            Animation.Parent = cln
            cln.Humanoid.WalkSpeed = Settings.BANDIT.WALKSPEED
        end
    end)
end

for _, Bandit in pairs(workspace.Bandits:GetChildren()) do
    spawn(function() setupNPC(Bandit, Bandit.PrimaryPart.CFrame) end)
end

You may have to return the torso's position from the getClosestPlayer function, but I don't know for sure. Hopefully this works (which it probably doesn't)! :D

0
Thank you BlackOrange3343 2676 — 6y
Ad
Log in to vote
-1
Answered by 6 years ago

Use this:

local larm = script.Parent:FindFirstChild("Left Arm")
local rarm = script.Parent:FindFirstChild("Right Arm")

function findNearestTorso(pos)
    local list = game.Workspace:children()
    local torso = nil
    local dist = 10
    local temp = nil
    local human = nil
    local temp2 = nil
    for x = 1, #list do
        temp2 = list[x]
        if (temp2.className == "Model") and (temp2 ~= script.Parent) then
            temp = temp2:findFirstChild("Torso")
            human = temp2:findFirstChild("Humanoid")
            if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
                if (temp.Position - pos).magnitude < dist then
                    torso = temp
                    dist = (temp.Position - pos).magnitude
                end
            end
        end
    end
    return torso
end

while true do
    wait(0.1)
    local target = findNearestTorso(script.Parent.Torso.Position)
    if target ~= nil then
        script.Parent.Enemy:MoveTo(target.Position, target)
    end
end
0
Really... You 1 took a free model, 2. Used a loop when I said I wish to prevent that, 3. Didn't even bother explaining anything (probably because you stole it) but still. Thanks for trying though I gotta give you that BlackOrange3343 2676 — 6y
0
Boy, I've been using this in RPG's for years. Zerixa_RBLX -2 — 6y
0
Lmao search up zombie in workspace and look at the script. BlackOrange3343 2676 — 6y

Answer this question