TheReiindeer
TheReiindeer

Reputation: 13

Why do I keep getting the error "attempt to index nil with 'Cash' in my script?

For a bit of context, I'm making a Tycoon on Roblox to test my knowledge in lua. Everything was working fine until I tried making leaderstats. The first script, which is what makes the Tycoon function, is here:



     local TycoonInfo = script.Parent:WaitForChild("TycoonInfo")
        local OwnerValue = TycoonInfo:WaitForChild("Owner")
        local Buttons = script.Parent:WaitForChild("Buttons")
        local Purchases = script.Parent:WaitForChild("Purchases")

        local Objects = {}

        function validateHitByOwner(Hit)
            if Hit and Hit.Parent and Hit.Parent:FindFirstChild("Humanoid") then
                local Player = game.Players:GetPlayerFromCharacter(Hit.Parent)
                if Player and OwnerValue.Value==  Player then
                    return true
                end
            end
            return false
        end

        for i,v in pairs(Buttons:GetChildren()) do
            local Object = Purchases:FindFirstChild(v.Object.Value)
            if Object then
                Objects[Object.Name] = Object:Clone()
                Object:Destroy()

                if v:FindFirstChild("Dependency") then
                    coroutine.resume(coroutine.create(function()
                        v.Button.Transparency = 1
                        v.Button.BillboardGui.Enabled = false
                        v.Button.CanCollide = false
                        if Purchases:WaitForChild(v.Dependency.Value,90000) then
                            v.Button.Transparency = 0
                            v.Button.CanCollide = true
                            v.Button.BillboardGui.Enabled = true
                        end
                    end))
                end
                local DB = false
                v.Button.Touched:Connect(function(Hit)
                    if validateHitByOwner(Hit)then
                        if DB == false then
                            DB = true
                            if v.Button.Transparency == 0 then
                                local Purchased = DoPurchase(Hit,v,v.Price.Value,Objects[v.Object.Value])
                                if Purchased then
                                    warn("Purchased")
                                else
                                    warn("Can't purchase")
                                end
                            end
                            DB = false
                        end
                    end
                end)
            end
        end

        function DoPurchase(Hit,Button,Cost,Object)
            if Hit and Hit.Parent and Hit.Parent:FindFirstChild("Humanoid") then
                local Player = game.Players:GetPlayerFromCharacter(Hit.Parent)
                if Player and OwnerValue.Value == Player then
                    local name = game.Players:GetChildren()
                    local CashValue = game.Players.name.leaderstats.Cash -- Error here
                    if CashValue then
                        if CashValue.Value >= Cost then
                            CashValue.Value = CashValue.Value - Cost
                            Object.Parent = Purchases
                            Button:Destroy()
                            return true 
                        end 
                    end
                end
            end
            return false
        end

The next script, which makes the leaderboard and assigns a player that has recently joined to a random available Tycoon, is here:



     function FindEmptyTycoon()
            for i,v in pairs(workspace.Tycoons:GetChildren()) do
                if v.TycoonInfo.Owner.Value == nil then
                    return v
                end
            end
            return nil
        end


        game.Players.PlayerAdded:Connect(function(Player)
            local Tycoon = FindEmptyTycoon()
            Tycoon.TycoonInfo.Owner.Value = Player 


            local stats = Instance.new("Folder",Player)
            stats.Name = "leaderstats"

            local Cash = Instance.new("IntValue",stats)
            Cash.Name = "Cash"
        end)

And then, the script that is stored in all purchasable items to give the Player money, is here:


function giveCash(player)
    wait(3.33)
    local Cash = player.leaderstats.Cash
    Cash.Value = Cash.Value + 2
end

By the way, these scripts are versions of the original scripts that I've been trying to edit so they can actually work, and I think I've been getting close to fixing the errors. The original scripts can be found here (in order of appearance):

local TycoonInfo = script.Parent:WaitForChild("TycoonInfo")
local OwnerValue = TycoonInfo:WaitForChild("Owner")
local Buttons = script.Parent:WaitForChild("Buttons")
local Purchases = script.Parent:WaitForChild("Purchases")

local Objects = {}

function validateHitByOwner(Hit)
    if Hit and Hit.Parent and Hit.Parent:FindFirstChild("Humanoid") then
        local Player = game.Players:GetPlayerFromCharacter(Hit.Parent)
        if Player and OwnerValue.Value==  Player then
            return true
        end
    end
    return false
end

for i,v in pairs(Buttons:GetChildren()) do
    local Object = Purchases:FindFirstChild(v.Object.Value)
    if Object then
        Objects[Object.Name] = Object:Clone()
        Object:Destroy()

        if v:FindFirstChild("Dependency") then
            coroutine.resume(coroutine.create(function()
                v.Button.Transparency = 1
                v.Button.BillboardGui.Enabled = false
                v.Button.CanCollide = false
                if Purchases:WaitForChild(v.Dependency.Value,90000) then
                    v.Button.Transparency = 0
                    v.Button.CanCollide = true
                    v.Button.BillboardGui.Enabled = true
                end
            end))
        end
        local DB = false
        v.Button.Touched:Connect(function(Hit)
            if validateHitByOwner(Hit)then
                if DB == false then
                    DB = true
                    if v.Button.Transparency == 0 then
                        local Purchased = DoPurchase(Hit,v,v.Price.Value,Objects[v.Object.Value])
                        if Purchased then
                            warn("Purchased")
                        else
                            warn("Can't purchase")
                        end
                    end
                    DB = false
                end
            end
        end)
    end
end

function DoPurchase(Hit,Button,Cost,Object)
    if Hit and Hit.Parent and Hit.Parent:FindFirstChild("Humanoid") then
        local Player = game.Players:GetPlayerFromCharacter(Hit.Parent)
        if Player and OwnerValue.Value == Player then
            local CashValue = game.ServerStorage.PlayerCash:FindFirstChild(Player.Name)
            if CashValue then
                if CashValue.Value >= Cost then
                    CashValue.Value = CashValue.Value - Cost
                    Object.Parent = Purchases
                    Button:Destroy()
                    return true
                end
            end
        end
    end
    return false
end
function FindEmptyTycoon()
    for i,v in pairs(workspace.Tycoons:GetChildren()) do
        if v.TycoonInfo.Owner.Value == nil then
            return v
        end
    end
    return nil
end


game.Players.PlayerAdded:Connect(function(Player)
    local Tycoon = FindEmptyTycoon()
    Tycoon.TycoonInfo.Owner.Value = Player


    local stats = Instance.new("BoolValue",Player)
    stats.Name = "leaderstats"
    stats.Parent = game.ServerStorage

    local Cash = Instance.new("IntValue",stats)
    Cash.Name = Player.Name
    Cash.Value = 0
    Cash.Parent = game.ServerStorage.PlayerCash
end)
local amount = 2
local timedelay = 2.33
local currencyname = "Cash"
wait(1)
while true do
    wait(timedelay)
    for i,v in pairs(game.ServerStorage.PlayerCash:GetChildren()) do
        if v:FindFirstChild("leaderstats") and v then
            v.leaderstats[currencyname].Value = v.leaderstats[currencyname].Value + amount
        end
    end
end

Upvotes: 1

Views: 1839

Answers (1)

Piglet
Piglet

Reputation: 28974

local name = game.Players:GetChildren()

Why do you store the list of Players's children in a variable called name? This function returns a table. name would be more suitable for a string.

local CashValue = game.Players.name.leaderstats.Cash -- Error here

game.Players is https://developer.roblox.com/en-us/api-reference/class/Players

I cannot make sense of game.Players.name and even less of game.Players.name.leaderstats

Did you mean Player.leaderstats?

I would expect an error message for Players.name.leaderstats before facing an error for game.Players.name.leaderstats.Cash

name is not a Property of Players so you should not be allowed to index Players.name

I'm no Roblox expert but from what I see your code is so off that you really should start with simple tutorials rather than with fixing this code.

I think you should start over and make sure you understand how Instance.new is used properly and such things.

Using better variable names will also help.

Upvotes: 1

Related Questions