"Attempt to call a nil value" with data stores - lua

I called the moduleScript and I did everything correctly I think
I also tried with a normal script but it didnt work
Pls help I tried lots of things but nothing works Im creating a new game and I cant continue the game because the data doesnt save
Im putting so much text because if not I cant publish this :)
local PlayerStatManager = {}
local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetChildren("DataPlayer")
game.Players.PlayerAdded:Connect(function(player)
local stats = Instance.new("Folder")
stats.Parent = player
stats.Name = "leaderstats"
local clicks = Instance.new("NumberValue")
clicks.Name = "Clicks"
clicks.Parent = stats
local coins = Instance.new("NumberValue")
coins.Name = "Coins"
coins.Parent = stats
local rebirths = Instance.new("NumberValue")
rebirths.Name = "Rebirths"
rebirths.Parent = stats
local id = player.UserId
clicks.Value = playerData:GetAsync(player.UserId)
end)
game.Players.PlayerRemoving:Connect(function(player)
local id = player.UserId
playerData:SetAsync(id, player.leaderstats.Clicks.Value)
end)
return PlayerStatManager

local playerData = DataStoreService:GetChildren("DataPlayer")
This line causes the problem.
First of all, GetChildren doesn't get a child of an instance, it returns an array-like table of all children. In that case, FindFirstChild makes more sense.
Well, even FindFirstChild isn't correct! DataStoreService shouldn't have any children - if it does, you shouldn't care about them. You probably wanted to use GetDataStore.
About the error message, it says that you're trying to call a nil value, which means that you're trying to call something that doesn't exist. It's this line that causes the error:
clicks.Value = playerData:GetAsync(player.UserId)
You are using GetChildren, which returns a table. playerData is a table. You're trying to get GetAsync and then call it. In the table, we don't have the key GetAsync (we only have number keys, because it's an array-like table). So you're trying to call a nil value.

Related

How do I make a leader board that saves and counts every single kill? (I'm just starting out by the way!) [duplicate]

I want to make a save system so that people don't have to restart every single time they play
I don't really know what to do so I will show you the code for my leader stats this is located in the work space
local function onPlayerJoin(player)
local leaderstats = Instance.new("Model")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local gold = Instance.new("IntValue")
gold.Name = "JumpBoost"
gold.Value = 150
gold.Parent = leaderstats
local speed = Instance.new("IntValue")
speed.Name = "Speed"
speed.Value = 20
speed.Parent = leaderstats
local coin = Instance.new("IntValue")
coin.Name = "CloudCoins"
coin.Value = 0
coin.Parent = leaderstats
local rebirths = Instance.new("IntValue")
rebirths.Name = "Rebirths"
rebirths.Value = 0
rebirths.Parent = leaderstats
end
game.Players.PlayerAdded:Connect(onPlayerJoin)
Again I don't really know what to do so, please help.
The documentation for Data Stores is pretty good. An important warning for testing :
DataStoreService cannot be used in Studio if a game is not configured to allow access to API services.
So you will have to publish the game and configure it online to allow you to make HTTP requests and access the Data Store APIs. So be sure to look at the section in that link titled, Using Data Stores in Studio, it will walk you through the menus.
Anyways, right now, you are creating the player's starting values when they join the game. DataStores allow you save the values from the last session and then load those in the next time they join.
Roblox DataStores allow you to store key-value tables. Let's make a helper object for managing the loading and saving of data.
Make a ModuleScript called PlayerDataStore :
-- Make a database called PlayerExperience, we will store all of our data here
local DataStoreService = game:GetService("DataStoreService")
local playerStore = DataStoreService:GetDataStore("PlayerExperience")
local PlayerDataStore = {}
function PlayerDataStore.getDataForPlayer(player, defaultData)
-- attempt to get the data for a player
local playerData
local success, err = pcall(function()
playerData = playerStore:GetAsync(player.UserId)
end)
-- if it fails, there are two possibilities:
-- a) the player has never played before
-- b) the network request failed for some reason
-- either way, give them the default data
if not success or not playerData then
print("Failed to fetch data for ", player.Name, " with error ", err)
playerData = defaultData
else
print("Found data : ", playerData)
end
-- give the data back to the caller
return playerData
end
function PlayerDataStore.saveDataForPlayer(player, saveData)
-- since this call is asyncronous, it's possible that it could fail, so pcall it
local success, err = pcall(function()
-- use the player's UserId as the key to store data
playerStore:SetAsync(player.UserId, saveData)
end)
if not success then
print("Something went wrong, losing player data...")
print(err)
end
end
return PlayerDataStore
Now we can use this module to handle all of our loading and saving.
At the end of the day, your player join code will look very similar to your example, it will just try to first load the data. It is also important to listen for when the player leaves, so you can save their data for next time.
In a Script next to PlayerDataStore :
-- load in the PlayerDataStore module
local playerDataStore = require(script.Parent.PlayerDataStore)
local function onPlayerJoin(player)
-- get the player's information from the data store,
-- and use it to initialize the leaderstats
local defaultData = {
gold = 150,
speed = 0,
coins = 0,
rebirths = 0,
}
local loadedData = playerDataStore.getDataForPlayer(player, defaultData)
-- make the leaderboard
local leaderstats = Instance.new("Model")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local gold = Instance.new("IntValue")
gold.Name = "JumpBoost"
gold.Value = loadedData.gold
gold.Parent = leaderstats
local speed = Instance.new("IntValue")
speed.Name = "Speed"
speed.Value = loadedData.speed
speed.Parent = leaderstats
local coin = Instance.new("IntValue")
coin.Name = "CloudCoins"
coin.Value = loadedData.coins
coin.Parent = leaderstats
local rebirths = Instance.new("IntValue")
rebirths.Name = "Rebirths"
rebirths.Value = loadedData.rebirths
rebirths.Parent = leaderstats
end
local function onPlayerExit(player)
-- when a player leaves, save their data
local playerStats = player:FindFirstChild("leaderstats")
local saveData = {
gold = playerStats.JumpBoost.Value,
speed = playerStats.Speed.Value,
coins = playerStats.CloudCoins.Value,
rebirths = playerStats.Rebirths.Value,
}
playerDataStore.saveDataForPlayer(player, saveData)
end
game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
Hope this helps!

Data Store not saving the Player's Boolean Value

I was making a game that when the Player dies, then the Player will get banned but isn't working (The part of Saving the Bool Value that checks if the player was banned already been banned). How i can fix that? No errors in output.
Code:
local DataStoreService = game:GetService("DataStoreService")
local BANS = DataStoreService:GetDataStore("BANNED")
game.Players.PlayerAdded:Connect(function(Player)
local Char = Player.CharacterAdded:Wait() or Player.Character
local Hum = Char:WaitForChild("Humanoid") or Char.Humanoid
local banornot = Instance.new("Folder")
banornot.Name = "Banned"
banornot.Parent = Player
local banned = Instance.new("BoolValue", banornot)
banned.Name = "Banido"
banned.Value = false
local PlayerId = Player.UserId
local BANIDO = BANS:GetAsync(PlayerId)
Hum.Died:Connect(function()
if not BANIDO then
BANS:SetAsync(PlayerId, banned.Value)
Player:Kick("You can't join the game.")
end
end)
end)
game.Players.PlayerAdded:Connect(function(Player)
local PlayerId = Player.UserId
local banidovalue = Player:WaitForChild("Banned"):WaitForChild("Banido").Value
local BANIDO = BANS:GetAsync(PlayerId, banidovalue)
if BANIDO then
banidovalue = true
if banidovalue == true then
Player:Kick("You can't join the game. Sorry you know the rules.")
else print("erro")
end
end
end)
There are multiple issues with this.
The main issue is that BANIDO will never change. It will always have the value false, no matter what you do. Why? The only use of SetAsync takes the BoolValue's value, which also does not change. So, it's always false. There is a point in which you "set" it to true, except you don't. You take the value, put it into a variable, and set the variable to true. The actual BoolValue doesn't change. Even if you were to fix that, you kick the user right after that, which makes it useless.
Second, you don't need a BoolValue. I don't know why you used it, so I can't explain this part.
Here is a commented version of an improved script, in which I go through all of the issues:
local DataStoreService = game:GetService("DataStoreService")
local BANS = DataStoreService:GetDataStore("BANNED")
game.Players.PlayerAdded:Connect(function(Player)
local Char = Player.CharacterAdded:Wait() or Player.Character
local Hum = Char:WaitForChild("Humanoid") --No "or Char.Humanoid" is needed, WaitForChild waits until it finds the thing which makes that part useless.
--We don't need a BoolValue
local PlayerId = Player.UserId
local BANIDO = BANS:GetAsync(PlayerId)
if BANIDO then --I moved the check from the other connection to this one. Do not connect to an event twice in the same script if the necessities are the same.
Player:Kick("You can't join the game. Sorry you know the rules.")
end
--I did not do a check like this: BANIDO == true
--This is because BANIDO is already a boolean, true or false, and you're essentially saying "if this is true, give me true, if it's false, give me false" which is just the value
Hum.Died:Connect(function()
if not BANIDO then
BANS:SetAsync(PlayerId, true) --true instead of banned.Value. We got rid of the BoolValue, and also, even if we didn't, it wouldn't change.
Player:Kick("You can't join the game.")
end
end)
end)

Attempt to call a nil value when changing an IntValue for leaderstats

I'm trying to make an admin panel, everytime I want to change the value with a username
Code:
leaderstats Script;
--// Set up folder
local AdminModule = require(game:GetService('ServerScriptService').leaderstats.MainModule)
game.Players.PlayerAdded:Connect(function(plr)
local leaderstats = Instance.new('Folder', plr)
leaderstats.Name = 'leaderstats'
local Playtime = Instance.new('IntValue', leaderstats)
Playtime.Name = 'Playtime'
end)
AdminModule.GivePoints('happy_speler', 500)
MainModule:
local module = {
GivePoints = function(plr, amount)
plr:WaitForChild('leaderstats'):WaitForChild('Playtime').Value = amount
end,
}
return module
The error is telling you that you have tried to call a function that doesn't exist.
Looking at the AdminModule.GivePoints function, it looks like it expects a Player object for the plr argument, but you have passed in a string. The string library does not have a WaitForChild function, so calling plr:WaitForChild is throwing the error.
The way to fix this is to properly pass in a Player object :
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local AdminModule = require(ServerScriptService.leaderstats.MainModule)
Players.PlayerAdded:Connect( function(plr)
local leaderstats = Instance.new('Folder', plr)
leaderstats.Name = 'leaderstats'
local Playtime = Instance.new('IntValue', leaderstats)
Playtime.Name = 'Playtime'
if plr.Name == 'happy_speler' then
AdminModule.GivePoints(plr, 500)
end
end)

What does "attempt to index nil with 'WaitForChild'" mean?

script.Parent.MouseButton1Click:connect(function()
local RS = game:GetService("ReplicatedStorage")
local item = RS:WaitForChild("Pencil")
local price = 350
local player = game.Players.LocalPlayer
local stats = player:WaitForChild("leaderstats")
if stats.Strength.Value>=price then
stats.Strength.Value = stats.Strength.Value - price
local cloned = item:Clone()
cloned.Parent = player.Backpack
cloned.Parent = player.StarterGear
end
end)
I am trying to make a shop and it comes up with "attempt to index nil with 'WaitForChild'" on line 6:
local stats = player:WaitForChild("leaderstats")
I copied it exactly how the video had it and the video had no problem and apparently player has no value even though we set it up just one line above
It means that you are indexing a nil value, which means that player value is nil, which means that game.Players.LocalPlayer on the previous like returns nil. Why that is you need to figure out, as there is not much to go by.
The example shows that it should be local player = game:GetService("Players").LocalPlayer, so you may want to try that.

How do I make a Leaderboard on roblox?

How do I make a Leaderboard on roblox?
In every player needs to be inserted a value called 'leaderstats', using a script with the PlayerAdded event. Inside the leaderstats value, you can place IntValues - their name is what will show as the heading, and their value is what will appear as the player's stat.
To make those stats change, you need to add different functions and/or events to the script that created the leaderstats values.
Insert a script into workspace, then in the code type this:
function Onplayerentered(player)
local leaderstats = Instance.new("IntValue")
leaderstats.Parent = player
leaderstats.Value = 0
leaderstats.Name = "leaderstats"
local stat = Instance.new("IntValue")
stat.Name = "" -- Put name here in between the quotations
stat.Value = -- Put the starting Value#
end
game:GetService("Players").ChildAdded:Connect(Onplayerentered)
Bring up to roblox insert toolbar.
Select Leaderbord.
You can customize the script to fit your needs!
Roblox leaderboards is a very long script, thankfully, the script allow us to easily add and remove leaderstats. To add a leaderboard insert a IntValue inside of the player object, to add a stat insert a IntValue inside the leadestats.
Most games on Roblox want every player to have the same leaderboard. So most people use a PlayerAdded event and create the leaderboard
Insert a script into ServerScriptService and paste down the following code:
plrEntered = function(plr)
local ls = Instance.new('IntValue') --Leaderstats
ls.Parent = plr
ls.Value = 0
ls.Name = 'leaderstats'
local stat = Instance.new('IntValue')
stat.Name = 'Money' -- Change to the value you want
stat.Value = 0 -- Add the starting value
end
game:GetService'Players'.PlayerAdded(plrEntered)
ROBLOX defines a leaderboard as an object that is named as 'leaderstats' and is located in the player object. A leaderboard statistic is defined as a value object inside the leaderstats object (Player>leaderstats>ValueObject). So lets write a function that creates a leaderboard with a 'cash' statistic for a player.
local function createLeaderboard(player)
local stats = Instance.new("Folder")
stats.Name = "leaderstats"
local cash = Instance.new("IntValue", stats)
cash.Name = "Cash"
stats.Parent = player
end
Then we need to make this work. We need to connect this function to the 'PlayerAdded' event from the 'Players' object.
local players = game:WaitForChild("Players")
players.PlayerAdded:connect(createLeaderboard)
And that is basically it.
Note that line 3 in the code shown directly above is the equivalent of:
players.PlayerAdded:connect(function(player)
createLeaderboard(player)
end)
The entire script would look like this:
local players = game:WaitForChild("Players")
local function createLeaderboard(player)
local stats = Instance.new("Folder")
stats.Name = "leaderstats"
local cash = Instance.new("IntValue", stats)
cash.Name = "Cash"
stats.Parent = player
end
players.PlayerAdded:connect(createLeaderboard)
It is recommended to put the script in the 'ServerScriptService'.
function Onplayererntered(player)
local leaderstats = Instance.new("IntValue")
leaderstats.Pareny = player
leaderstats.Value = 0
leaderstats.Name = "leaderboard"
local stat = Instance.new("IntValue")
statname = "Cash"
stat.Value = 100
end
you first have to make a script inside the server script service and name it what ever you want, and write this in the script (make sure its normal script not local)
game:GetService("Players").PlayerAdded:Connect(function() --make the function start when new player joins
local player = game.Players.PlayerAdded --make player variable
local leaderstats = instance.new("Folder", player) --make new folder and set it's parent to the player
local money = instance.new("IntValue", leaderstats) --create new value for the stat and set it's parent to the leaderstats folder (you can create as many as u want)
money.name = "Money" --make the name of the value
money.Value = 0 --make the value's value
end)
this block of code is simple and has many comments to explain it I wish it was helpful.
function stats(plr)
local leaderstats = Instance.new("IntValue")
leaderstats.Name = "leaderstats"
leaderstats.Parent = plr
local coins = Instance.new("IntValue")
Coins.Name = "coins"
Coins.Parent = leaderstats
end)
game.Players.PlayyerAdded:Connect(stats)

Resources