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

Attempt to index upvalue 'v'?

Asked by 9 years ago
repeat wait() until workspace.WalkPositions:findFirstChild("WalkPos_1")
local WalkPositions = workspace.WalkPositions:GetChildren()
local human         = script.Parent.Humanoid
local Torso         = script.Parent.Torso
local positions     = {}
local manginute     = 25
local i,v

spawn(function() while wait() do
     i = math.random(1,#WalkPositions)
     v = WalkPositions[i] 
end end)
    while (v.Value - Torso.Position).magnitude < manginute and not positions[i] do
        human:MoveTo(v.Value)
        human.MoveToFinished:wait()
        table.insert(positions, i, v.Name)
        table.remove(positions, i - 1)
    end

Error:

--[[
14:01:53.802 - Workspace.NPCs.NPC.Pathfinder:14: attempt to index local 'v' (a nil value)
14:01:53.802 - Stack Begin
14:01:53.802 - Script 'Workspace.NPCs.NPC.Pathfinder', Line 14
14:01:53.803 - Stack End
]]--

When the NPC gets in range of a value to follow, it doesn't respond and returns this error.

0
Have you tried adding a condition to the second while loop on line 13 to check if v (and/or i) is nil? GoldenPhysics 474 — 9y

1 answer

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

Use good, meaningful variable names. v is a bad name for a target. mangitude is misspelled -- it's harder to type the correct misspelling than it is to just type the word. positions is a bad name for something which just tells you if you can walk somewhere, e.g., dontWalk.

spawn doesn't start immediately, so i and v won't be set immediately -- thus they're nil the first time around in the loop. A simple solution is to make the second loop the one you spawn. It would be better to eliminate the spawn altogether, and use only one loop.

In particular, you're just using it to generate a random target. There's no reason to do that in the background -- just grab it when you check things about target:

Your second loop doesn't ever stop and doesn't ever break, so it will crash the game. You probably want

while wait() do
    local target = WalkPositions[math.random(#WalkPositions)]
    if (target.Value - torso.Position).magnitude < magnitude and not dontWalk[i] then
        .. do stuff ..
    end
end

I'm not sure what you're trying to accomplish with table.insert and table.remove from positions. Since it starts empty, table.remove(positions, i - 1) is likely to act strange...

Is your goal to not revisit the same spot twice in a short period? You could just do a simple debounce with spawn, then. Also, there's no reason to expose i at all. You can just use a dictionary using v:

repeat wait() until workspace.WalkPositions:FindFirstChild("WalkPos_1")
local WalkPositions = workspace.WalkPositions:GetChildren()
local human         = script.Parent.Humanoid
local Torso         = script.Parent.Torso
local dontWalk      = {}
local magnitude     = 25


while wait() do
    local target = WalkPositions[math.random(#WalkPositions)]
    if (target.Value - torso.Position).magnitude < magnitude and not dontWalk[v] then
        human:MoveTo(target.Value)
        human.MoveToFinished:wait()
        dontWalk[target] = true
        -- Allow the humanoid to revisit this spot in 2 seconds:
        delay(2, function() dontWalk[target] = false end)
    end
end

Being destructive to the WalkPositions list, you could even eliminate the dontWalk dictionary:

while wait() do
    local target = table.remove( WalkPositions, math.random(#WalkPositions) )
    if (target.Value - torso.Position).magnitude < magnitude then
        -- (do the same stuff)

        delay(2, function() table.insert(WalkPositions, target) end)
    else
        table.insert(WalkPositions, target)
        -- put it back, since we didn't use it
    end
end

alternatively, for slightly simpler code, you could always take the things out for 2 seconds, even if they weren't used. Unfortunately, this has the possibility of emptying the list, which would cause errors, so a new check has to be put in place:

while wait() do
    if #WalkPositions >= 1 then
        -- Only proceed if the list isn't empty
        local target = table.remove(WalkPositions, math.random(#WalkPositions))
        if (target.Value - torso.Position).magnitude < magnitude then
            -- do the same stuff, except for the delay
        end
        delay(2, function() table.insert(WalkPositions, target) end)
    end
end
Ad

Answer this question