Stats is not a valid member of Player “Players.Player2” - Server - ServerScript:113
Here is where I declare the stats for the player (server script).
game:GetService("Players").PlayerAdded:Connect(function(player)
local statsFolder = Instance.new("Folder")
statsFolder.Parent = player
statsFolder.Name = "Stats"
local strength = Instance.new("IntValue")
strength.Parent = statsFolder
strength.Value = 10
strength.Name = "Strength"
local agility = Instance.new("IntValue")
agility.Parent = statsFolder
agility.Value = 10
agility.Name = "Agility"
local defense = Instance.new("IntValue")
defense.Parent = statsFolder
defense.Value = 10
defense.Name = "Defense"
local speed = Instance.new("IntValue")
speed.Parent = statsFolder
speed.Value = 10
speed.Name = "Speed"
local hp = Instance.new("IntValue")
hp.Parent = statsFolder
hp.Value = 10
hp.Name = "HP"
local mana = Instance.new("IntValue")
mana.Parent = statsFolder
mana.Value = 10
mana.Name = "Mana"
local level = Instance.new("IntValue")
level.Parent = statsFolder
level.Value = 1
level.Name = "Level"
local xp = Instance.new("IntValue")
xp.Parent = statsFolder
xp.Value = 0
xp.Name = "XP"
local gold = Instance.new("IntValue")
gold.Parent = statsFolder
gold.Value = 0
gold.Name = "Gold"
local gems = Instance.new("IntValue")
gems.Parent = statsFolder
gems.Value = 0
gems.Name = "Gems"
local weapon = Instance.new("IntValue")
weapon.Parent = statsFolder
weapon.Value = "sword"
weapon.Name = "Weapon"
end)
A few lines later I define a function wherein I call upon the stats I have already created when the player joined:
local function turnHandler()
repeat
Players.PlayerAdded:Wait()
until #Players:GetPlayers() == 2 -- CHANGE TO 2
local player1 = Players:GetChildren()[1]
local player2 = Players:GetChildren()[2]
local attacker
local turnActive = ReplicatedStorage:WaitForChild("Player1Turn")
--initiative scoring
local player1Init = player1.Stats.Speed.Value
local player2Init = player2.Stats.Speed.Value -- line 113
print(player1Init, player2Init)
At first I figured the stats folder just didn’t load in yet so I used WaitForChild like this:
--initiative scoring
local player1Init = player1:WaitForChild("Stats").Speed.Value
local player2Init = player2:WaitForChild("Stats").Speed.Value -- line 113
But after doing this and running the game the players would no longer spawn in at all, but they did previously. No errors, but the players would fail to spawn into the workspace at all. I’m not sure what to do here, as I have no idea why WaitForChild isn’t working and I don’t know why I’m receiving the original error in the first place. It also seems odd that only line 113 is throwing and error and not 112, despite them basically being the same thing.
First thing’s first:
Parenting stuff before all of its properties are defined is bad practice, and it’s not that difficult to adapt to doing it “properly” (I could go into the details but that’s a different topic.)
Now, before I can fix your code, where are you calling “turnHandler”?
I assume it’s just called in the global scope and not under anything else. If I’m wrong please clarify, but if so, you will indeed need to wait for the stats folder since it’ll start executing immediately when the 2nd player joins. So use WaitForChild.
To add on to my first point: If we fix your code and do it properly here,
game:GetService("Players").PlayerAdded:Connect(function(player)
local statsFolder = Instance.new("Folder")
statsFolder.Name = "Stats"
local strength = Instance.new("IntValue")
strength.Value = 10
strength.Name = "Strength"
local agility = Instance.new("IntValue")
agility.Value = 10
agility.Name = "Agility"
local defense = Instance.new("IntValue")
defense.Value = 10
defense.Name = "Defense"
local speed = Instance.new("IntValue")
speed.Value = 10
speed.Name = "Speed"
local hp = Instance.new("IntValue")
hp.Value = 10
hp.Name = "HP"
local mana = Instance.new("IntValue")
mana.Value = 10
mana.Name = "Mana"
local level = Instance.new("IntValue")
level.Value = 1
level.Name = "Level"
local xp = Instance.new("IntValue")
xp.Value = 0
xp.Name = "XP"
local gold = Instance.new("IntValue")
gold.Value = 0
gold.Name = "Gold"
local gems = Instance.new("IntValue")
gems.Value = 0
gems.Name = "Gems"
local weapon = Instance.new("IntValue")
weapon.Value = "sword"
weapon.Name = "Weapon"
strength.Parent = statsFolder
agility.Parent = statsFolder
defense.Parent = statsFolder
speed.Parent = statsFolder
hp.Parent = statsFolder
mana.Parent = statsFolder
level.Parent = statsFolder
xp.Parent = statsFolder
gold.Parent = statsFolder
gems.Parent = statsFolder
weapon.Parent = statsFolder
statsFolder.Parent = player
end)
We now ensure that each stat value exists when the stats folder is parented.
If you parent it beforehand, it would require an extra WaitForChild for the Speed value.
This is a good example of why we should only parent things after its properties and children (and their properties, etc…) exist/are set.
No, that’s dedicated support for adding leaderstat values. It’s a good thought, but he’s trying to define a folder that strictly holds data values that would clutter the leaderboard and are rather for instantiating (objectifying) the data values for later use.
Thank you for this tip, I had no idea this was bad practice. I have rewritten some stuff and realized my problem is that the player1 and player2 variables are nil, because I assigned their values inside a local scope and am trying to use the variables outside of that scope, but they’re just nil because I haven’t assigned a value outside of a local scope.
This is the first part of the turnHandler() function:
local function turnHandler()
player1 = nil
player2 = nil
repeat
task.wait()
print("Waiting")
until #Players:GetChildren() == 2
for i, player in ipairs(Players:GetChildren()) do
if player.Stats.PlayerNumber == 1 then
player1 = player
print("Player 1: ", player1)
elseif player.Stats.PlayerNumber == 2 then
player2 = player
print("Player 2: ", player2)
else
print("ERROR")
end
end
--local player1 = Players:GetChildren()[1]
--local player2 = Players:GetChildren()[2]
local attacker
local turnActive = ReplicatedStorage:WaitForChild("Player1Turn")
--initiative scoring
print("Player 1: ",player1) -- returns nil because of scope
local player1Init = player1:WaitForChild("Stats"):WaitForChild("Speed").Value
local player2Init = player2:WaitForChild("Stats"):WaitForChild("Speed").Value
How can I update those player1 and player2 variables for outside access? Or is there an easier way for me to do this?