ServerScriptService.leaderstats:87: attempt to index nil with 'leaderstats - error-handling

So basically I'm making a roblox clicker simulator game and sometimes when I test the save data for clicks it sometimes gives me this error ServerScriptService.leaderstats:87: attempt to index nil with 'leaderstats'
local success, errormessage = pcall(function()
rebirthsDataStore:SetAsync(playerUserId, rebirthsValue)
end)
-- Saving Gems Data
local gemsValue = player.leaderstats.Gems.Value
local success, errormessage = pcall(function()
gemsDataStore:SetAsync(playerUserId, gemsValue)
end)
end)
game:BindToClose(function(player)
for _, Player in pairs(game.Players:GetPlayers()) do
local playerUserId = "player"..Player.UserId
-- Saving Clicks
local clicksValue = player.leaderstats.Clicks.Value
local success, errormessage = pcall(function()
clicksDataStore:SetAsync(playerUserId, clicksValue)
end)
-- Saving Rebirths
local rebirthsValue = player.leaderstats.Rebirths.Value
local success, errormessage = pcall(function()
rebirthsDataStore:SetAsync(playerUserId, rebirthsValue)
end)
-- Saving Gems Data
local gemsValue = player.leaderstats.Gems.Value
local success, errormessage = pcall(function()
gemsDataStore:SetAsync(playerUserId, gemsValue)
end)
end
end)

Your error is telling you that when you try to access player.leaderstats, the player variable doesn't have a value. And this is because the game:BindToClose function does not provide a Player as an argument.
But you are iterating over all of the Players left in the server in a for-loop, just set the name of that iterator variable to be player and make sure the capitalization is correct in the rest of your code.
game:BindToClose(function()
for _, player in ipairs(game.Players:GetPlayers()) do
local playerUserId = "player" .. player.UserId

Related

Roblox Studio- attempt to index nil with 'leaderstats' error in output

so i want to make this so when i click it gives me a "Coin" but it does not work & says attempt to index nil with 'leaderstats'
`game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new('Folder', player)
leaderstats.Name = 'leaderstats'
local coins = Instance.new('IntValue', leaderstats)
coins.Name = 'Coins'
coins.Value = 0
end)
game.ReplicatedStorage.Remotes.Add.OnServerEvent:Connect(function()
local currency = 'Coins'
local amount = 5
player.leaderstats[currency].Value = player.leaderstats[currency].Value + amount
end)``
You forgot the "player" parameter in OnServerEvent which is why it's nil
fix:
game.ReplicatedStorage.Remotes.Add.OnServerEvent:Connect(function(player) --added player parameter
local currency = 'Coins'
local amount = 5
player.leaderstats[currency].Value = player.leaderstats[currency].Value + amount
end)

How do I Make a double jump Script that makes the power of the second Jump the Value of the players leader stat value

I made this code thinking it would allow the player to jump Twice and the second Jump be the power of its leader stat but Instead it doesn't even allow the player to Jump a second time.
local UIS = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local character
local humanoid
local canDoubleJump = false
local hasDoubleJumped = false
local oldPower
local time_delay = 0.2
local jump_multiplier = player.leaderstats.JumpBoost.Value
function onJumpRequest()
if not character or not humanoid or not
character:IsDescendantOf(workspace) or humanoid:GetState() ==
Enum.HumanoidStateType.Dead then
return
end
if canDoubleJump and not hasDoubleJumped then
hasDoubleJumped = true
humanoid.JumpPower = oldPower * jump_multiplier
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
end
local function characterAdded(new)
character = new
humanoid = new:WaitForChild("Humanoid")
hasDoubleJumped = false
canDoubleJump = false
oldPower = humanoid.JumpPower
humanoid.StateChanged:connect(function(old, new)
if new == Enum.HumanoidStateType.Landed then
canDoubleJump = false
hasDoubleJumped = false
humanoid.JumpPower = oldPower
elseif new == Enum.HumanoidStateType.Freefall then
wait(time_delay)
canDoubleJump = true
end
end)
end
if player.Character then
characterAdded(player.Character)
end
player.CharacterAdded:connect(characterAdded)
UIS.JumpRequest:connect(onJumpRequest)
I expected the player to Jump Twice with the second Jump having the power of the leader stat(I only put that and this because it says it wants more detail)
LocalScripts do not execute in game.Workspace: they only run on clients, hence the term 'local'; Scripts, on the other hand, are server-side.
You could use a Script to place your double-jump script--a LocalScript--into incoming players' character models.
-- Server-side Script
local players = game:GetService("Players")
local jumpScript = script:WaitForChild("JumpScript") -- Assume the double-jump script is a LocalScript called 'JumpScript'.
players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(char)
-- Check to make sure the character model does not already contain the double-jump script, just in case.
local clone = char:FindFirstChild("JumpScript")
if (not clone) then
clone = jumpScript:Clone()
clone.Parent = char
end
end)
end)
As a note, it is good practice to put server-side scripts like this into ServerScriptStorage instead of workspace or Lighting. (You can read about the safety of ServerScriptStoragehere.)

How do I make a save system for a leader board with more than 3 stats

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!

How would I rotate a character based on their camera? (Roblox)

In Roblox, your camera has a CFrame with a lookVector and so on. What I'm trying to accomplish is to detect when a player has pressed their right mouse button, and through a loop, rotate their character based on the CFrame of the camera until the button is released.
I've pretty much got it, but instead of rotating the character model, it turns the screen black and kills the player. I've seen this done in RPGs on Roblox before, so I know it's possible, and probably fairly easy. I've worked with CFrames quite a bit in the past, so I'm not sure why I'm having such a hard time with this.
After a couple hours of playing around with ideas and checking online, I thought I'd just ask the question to save time. What's the correct way to achieve this?
Edit: My bad, this is what I have so far. I fixed the black screen, but the player still just dies.
local UIS,Player,Camera,Character,MB2Down = game:GetService('UserInputService'),game.Players.LocalPlayer,workspace.Camera,script.Parent,false
local Torso = Character:FindFirstChild('Torso') or Character:FindFirstChild('UpperTorso')
UIS.InputEnded:Connect(function(Input)
if Input.UserInputType == Enum.UserInputType.MouseButton2 and MB2Down then
MB2Down = false
Character.Humanoid.AutoRotate = true
end
end)
UIS.InputBegan:connect(function(Input,onGui)
if Input.UserInputType == Enum.UserInputType.MouseButton2 and not onGui then
MB2Down = true
Character.Humanoid.AutoRotate = false
while MB2Down and wait() do
Torso.CFrame = CFrame.new(Vector3.new(Torso.CFrame),Vector3.new(Camera.CFrame.p))
end
end
end)
You've almost got it, but let me take a slightly different approach to my solution. When the player presses the right mouse button, let's connect a function to the Heartbeat event that will update the character's rotation to the camera's. Also, we will rotate the HumanoidRootPart instead of the Torso/UpperTorso. The HumanoidRootPart is the PrimaryPart of the character model, and thus is the part we should manipulate if we want to manipulate the model as a whole.
The way we will lock the player's rotation to the camera is as follows:
Get the position of the character.
Get the rotation of the camera (by using arc-tangent and camera's look-vector).
Construct the new CFrame for the player using the position and rotation from steps 1 and 2.
Apply the CFrame to the character's HumanoidRootPart.
The following code is in a LocalScript and is placed under StarterCharacterScripts:
local userInput = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local character = script.Parent
local root = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")
local camera = workspace.CurrentCamera
local dead = false
local heartbeat = nil
function LockToCamera()
local pos = root.Position
local camLv = camera.CFrame.lookVector
local camRotation = math.atan2(-camLv.X, -camLv.Z)
root.CFrame = CFrame.new(root.Position) * CFrame.Angles(0, camRotation, 0)
end
userInput.InputEnded:Connect(function(input)
if (input.UserInputType == Enum.UserInputType.MouseButton2 and heartbeat) then
heartbeat:Disconnect()
heartbeat = nil
humanoid.AutoRotate = true
end
end)
userInput.InputBegan:Connect(function(input, processed)
if (processed or dead) then return end
if (input.UserInputType == Enum.UserInputType.MouseButton2) then
humanoid.AutoRotate = false
heartbeat = game:GetService("RunService").Heartbeat:Connect(LockToCamera)
end
end)
humanoid.Died:Connect(function()
dead = true
if (heartbeat) then
heartbeat:Disconnect()
heartbeat = nil
end
end)
Let me know if you need any clarification.

Issues with saving high scores in lua

function saveScore()
local path = system.pathForFile("scoredata001.txt", system.DocumentsDirectory)
local file = io.open(path, "w")
if file then
local score=get_score() --The get_score() returns the value of current score which is saved in 'score'.
local newScore = compareScore()
local contents = tostring( newScore )
file:write( contents )
io.close( file )
return true
else
print("Error: could not write Score")
return false
end
end
function loadScore()
local path = system.pathForFile("scoredata001.txt", system.DocumentsDirectory)
local contents = ""
local file = io.open( path, "r" )
if file then
local contents = file:read( "*a" )
local score = tonumber(contents);
io.close( file )
return score
end
print("Could not read scores from scoredata.txt")
return nil
end
function return_highScore()
local highscore=loadScore()
if highscore==nil then
highscore=0
end
return highscore
end
function compareScore()
local highscore=return_highScore()
if highscore then
local currscore=get_score()
if highscore==0 then
return highscore
elseif currscore>highscore then
return currscore
end
end
return true
end
function disp_permScore()
local display_score=return_highScore()
text_display2= display.newText("GAME OVER!\n BEST: " ..display_score, 0, 0, "Helvetica", 80)
text_display2.x = centerX
text_display2.y = centerY
text_display2.alpha=1
function gameOver()
mainScreen()
saveScore()
disp_permScore()
end
(This is with refernce to previous question Permission issues in lua )
Basically I'm trying to build a game in lua (This is my first ever game)
But, I'm unable to save highscore to file. If it gets saved, then I'm unable to retrieve them. (In short, I always some or the other error/problem in executing the code.
Please have a look at the code above. I want to display both high score and current score. Current score is being displayed perfect. This is something I tried yesterday night. But now, the high score is not being saved in file. (i.e. the best always displays 0) Also, the cmd says "unable to read scores form scoredata.txt) I'm unable to find where I went wrong.
Please help with this?
Please tell where do I go wrong?
Also, if possible, provide (or edit) the correct code please?
There seems to be a problem on this line
if highscore==0
then
return highscore
Meaning you check if the highscore is 0 and if it is then you return it instead of the actual higher score.
Also, I don't know if your code was just pasting error, but without indenting your code it becomes really hard to read. Try and look again I indentet it and now the error becomes really easy to spot.