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

Why does this zombie script only target a single player?

Asked by 7 years ago

The Problem

The zombie can move and target the player correctly but it only targets that specific player throughout the whole game. Even when the player dies it waits and ignores all other players and when the specific player respawns it starts attacking that same player again.


My Code

The "zombie" is a single part that is a zombie body mesh.

local me = script.Parent
function FindNearestTorso() --Problem function
    local on = false
    for _,plyr in pairs(game:GetService("Players"):GetPlayers()) do
        if plyr then
            on = true
            local char = plyr.Character
            local h = char:FindFirstChild("Humanoid")
            local t = char:FindFirstChild("Torso")
            local max = 1000
            closest = 0
            if h and t and h.Health > 0 then
                local mag = (me.Position - t.Position).magnitude
                if mag < max then --Problem here maybe??
                    closest = t
                    max = mag
                end
            end
        end
    end
    if on then
        return closest
    else
        return 0 --No Torso
    end
end

while wait() do
    if type(FindNearestTorso()) ~= "number" then
        me.CFrame = me.CFrame:lerp(FindNearestTorso().CFrame,.1) --Not the best way to move it... Any ideas?
    end
end


Hope it helps!

1 answer

Log in to vote
0
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
7 years ago

First, a tiny bit of cleanup:

You should use nil to represent absence (as opposed to 0).

plyr can't be nil on line 5; tables don't store nil values. On the other hand, char can be nil and you aren't checking for that case.

Use real names! There's no point in taking the vowels out of player, especially when it will appear only twice in your code. Use humanoid instead of h and torso instead of t. You just make your code harder to read when you compress it to single letters.

Try a name like distance instead of mag since it more accurately describes what the variable means ("magnitude of what?")

The problem

local max is defined for each player. What you want is the closest player overall, which means max should be defined outside of the loop.

Similarly, closest should be defined as a local variable -- don't use global variables!

You've also forgotten to set on. But on is pointless since closest begins as 0 in the error case anyway.

local me = script.Parent
function FindNearestTorso()
    local closestTorso = nil
    local closestDistance = 1000
    for _, player in pairs(game:GetService("Players"):GetPlayers()) do
        local char = player.Character
        if char then
            local humanoid = char:FindFirstChild("Humanoid")
            local torso = char:FindFirstChild("Torso")
            if humanoid and torso and humanoid.Health > 0 then
                local distance = (me.Position - torso.Position).magnitude
                if distance < closestDistance then
                    closestTorso = torso
                    closestDistance = distance
                end
            end
        end
    end
    return closestTorso
end

while wait() do
    local target = FindNearestTorso()
    if target then
        me.CFrame = me.CFrame:lerp(target.CFrame, .1) --Not the best way to move it... Any ideas?
    end
end

If this is a humanoid, try looking up pathfinding and moveto.

Ad

Answer this question