What do you want to achieve? Keep it simple and clear!
So i’m making an chance system, which use exact table.Array to store amount and name. By default table.Array is
local success, data = LoadData(player)
sessionData[player.UserId] = success and data or {
Power = 0,
--Main Array
LuckAmounts = {
}
--End of MainArray
}
What is the issue? Include screenshots / videos if possible!
It sends me nil error about id
function PlayerManager.AddLuck(player, id)
local data = sessionData[player.UserId]
print(id)
if not table.find(data.LuckAmounts, id) then
table.insert(data.LuckAmounts, id)
end
end
seems like id is nil, but when i print it it says "Gen1"same as it should do
3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I tryed to use few checks for id, but idk why that happens, also wait because was thinking what array is nil
Here is code where everything get’s added:
local ChancesModule = require(game:GetService("ServerScriptService").MainModules.ChanceModule)
local Players = game.Players
local PlayerManager = require(game:GetService("ServerScriptService").PlayerManager)
local LuckTrigger = workspace:FindFirstChild("RemoteEvents"):FindFirstChild("LuckTrigger")
local function GetRandomGenSet(player)
for genName, odds in pairs(ChancesModule) do
if math.random() < 1/odds then
print(genName)
PlayerManager.AddLuck(player, genName)
local LuckTable = PlayerManager.GetLuckAmounts(player)
print(LuckTable)
if table.find(LuckTable, genName) then
if odds >= 1 then
LuckTable.genName.Value += 1 * (odds/10)
elseif odds < 1 then
LuckTable.genName.Value += 1
end
LuckTrigger:FireClient(player, LuckTable)
end
end
end
end
local function InfiniteCall(player)
GetRandomGenSet(player)
task.wait(1)
InfiniteCall()
end
Players.PlayerAdded:Connect(function(plr)
print("Plr Added")
plr.CharacterAdded:Connect(function(Char)
print("Char Added")
local pHead = Char:FindFirstChild("Head")
if pHead:FindFirstChild("AdvancedGameGUI") then
InfiniteCall(plr)
print("Advanced GUI Found")
--[[else
if pHead:WaitForChild("AdvancedGameGUI") then
InfiniteCall(plr)
end]]--
end
end)
end)
Probably has to do with the LoadData function. Success isn’t returning false or nil so the player session data is becoming the nil variable data. That, or you require the module from different scripts which will reset the data. You can fix this with BindableFunctions to get the variable from the main script.
it is not, that script used in a different games with similiar params and function, everything commented is not usable in this game, but those should work fine. Here is same script from different game
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerData = DataStoreService:GetDataStore("PlayerData")
local MarketplaceService = game:GetService("MarketplaceService")
local Gamepasses = require(script.Parent.Gamepasses)
local BanHammerId = 67822412
local RainbowCarpetId = 67822809
local SparklingSwordId = 67823158
local BadgeHandlerEvent = workspace.Events.BadgeHandlerEvent
local DonateStuffFolder = game:GetService("ServerStorage").DonateStuff
local function LeaderboardSetup(value)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
local Cash = Instance.new("NumberValue")
Cash.Name = "Cash"
Cash.Value = value
Cash.Parent = leaderstats
return leaderstats
end
local function LoadData(player)
local success, result = pcall(function()
print("Data Loading...")
return PlayerData:GetAsync(player.UserId)
end)
if not success then
warn("LOADING DATASTORE ERROR, PLEASE FIX IT")
end
return success, result
end
local function SaveData(player, data)
local success, result = pcall(function()
print("Data Saving...")
PlayerData:SetAsync(player.UserId, data)
end)
if not success then
warn("SAVING DATASTORE ERROR, PLEASE FIX IT")
end
return success
end
local sessionData = {}
local playerAdded = Instance.new("BindableEvent")
local playerRemoving = Instance.new("BindableEvent")
local PlayerManager = {}
PlayerManager.PlayerAdded = playerAdded.Event
PlayerManager.PlayerRemoving = playerRemoving.Event
function PlayerManager.Start()
for _,player in ipairs(Players:GetPlayers()) do
coroutine.wrap(PlayerManager.OnPlayerAdded)(player)
end
Players.PlayerAdded:Connect(PlayerManager.OnPlayerAdded)
Players.PlayerRemoving:Connect(PlayerManager.OnPlayerRemoving)
game:BindToClose(PlayerManager.OnClose)
end
function PlayerManager.OnPlayerAdded(player)
PlayerManager.RegisterGamepasses(player)
PlayerManager.RegisterDonateStuff(player)
BadgeHandlerEvent:Fire(player, 2129182596)
player.CharacterAdded:Connect(function(character)
PlayerManager.OnCharacterAdded(player, character)
end)
local success, data = LoadData(player)
sessionData[player.UserId] = success and data or {
Cash = 0,
UnlockIds = {}
}
local leaderstats = LeaderboardSetup(PlayerManager.GetMoney(player))
leaderstats.Parent = player
playerAdded:Fire(player)
end
function PlayerManager.OnCharacterAdded(player, character)
local humanoid = character:FindFirstChild("Humanoid")
if humanoid then
humanoid.Died:Connect(function()
wait(1)
player:LoadCharacter()
end)
end
end
function PlayerManager.GetMoney(player)
return sessionData[player.UserId].Cash
end
function PlayerManager.SetMoney(player, value)
if value then
sessionData[player.UserId].Cash = value
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
local Cash = leaderstats:FindFirstChild("Cash")
if Cash then
Cash.Value = value
end
end
end
end
function PlayerManager.AddUnlockId(player, id)
local data = sessionData[player.UserId]
if not table.find(data.UnlockIds, id) then
table.insert(data.UnlockIds, id)
end
end
function PlayerManager.GetUnlockIds(player)
return sessionData[player.UserId].UnlockIds
end
function PlayerManager.OnPlayerRemoving(player)
SaveData(player, sessionData[player.UserId])
playerRemoving:Fire(player)
end
function PlayerManager.OnClose()
for _, player in ipairs(Players:GetPlayers()) do
coroutine.wrap(PlayerManager.OnPlayerRemoving(player))()
end
end
function PlayerManager.RegisterDonateStuff(player)
if MarketplaceService:UserOwnsGamePassAsync(player.UserId, BanHammerId) then
local BanHammer = DonateStuffFolder:FindFirstChild("BanHammer")
local BanHammerClone1 = BanHammer:Clone()
BanHammerClone1.Parent = player.Backpack
local BanHammerClone2 = BanHammer:Clone()
BanHammerClone2.Parent = player.StarterGear
end
if MarketplaceService:UserOwnsGamePassAsync(player.UserId, RainbowCarpetId) then
local RainbowCarpet = DonateStuffFolder:FindFirstChild("RainbowCarpet")
local RainbowCarpetClone1 = RainbowCarpet:Clone()
RainbowCarpetClone1.Parent = player.Backpack
local RainbowCarpetClone2 = RainbowCarpet:Clone()
RainbowCarpetClone2.Parent = player.StarterGear
end
if MarketplaceService:UserOwnsGamePassAsync(player.UserId, SparklingSwordId) then
local SparklingSword = DonateStuffFolder:FindFirstChild("SparklingSword")
local SparklingSwordClone1 = SparklingSword:Clone()
SparklingSwordClone1.Parent = player.Backpack
local SparklingSwordClone2 = SparklingSword:Clone()
SparklingSwordClone2.Parent = player.StarterGear
end
end
function PlayerManager.RegisterGamepasses(player)
for id, passFunction in pairs(Gamepasses) do
if MarketplaceService:UserOwnsGamePassAsync(player.UserId, id) then
passFunction(player)
end
end
end
return PlayerManager
So it’s getting something… From what I can see, when PlayerManager.AddLuck() is being called, sessionData[player.UserId] does not exist yet. Maybe you call it before properly loading player data? You can get around that easily by converting your dot syntax to colon syntax (. to : ) and returning self. That way, you can do things like PlayerManager:Start():AddLuck(Player, 10).
Example:
local PlayerManager = {};
function PlayerManager:Start()
self.__dataTable = {};
setmetatable(self.__dataTable,{ __newindex = function(t,k,v) rawset(t,k,v) print(" Player added to data table.") });
function self.__dataTable:Add(index, val)
self[index] = val;
end
function self.__dataTable:Update(player, index, newVal)
return self.__dataTable[player] ~= nil and pcall(self.__dataTable.Add, self, player[index], newVal);
end
local function OnPlayerAdded(Player)
self.__dataTable:Add(Player.UserId, LoadData(Player))
end
local function OnPlayerRemoving(Player)
SaveData(Player);
end
for i,v in pairs(Players:GetPlayers()) do
OnPlayerAdded(v);
end
game:BindToClose(function() for i,v in pairs(Players:GetPlayers()) do OnPlayerRemoving(v) end end);
return self;
end
function PlayerManager:AddLuck(Player, amount)
self.__dataTable:Update(player, "Luck", amount);
return self;
end
return PlayerManager
Exactly what could i say, i was thinking about that, i added task.wait(5),task.wait(10) to script where LuckAdd getting called and it literally was giving same result as without task.wait, data 100% loaded in 10 seconds
EDIT: Plus script where LuckAdd being called is too being called after CharacterAdded same as DS one, so i’m sure it have time to load correctly
EDIT:Also tryed giving even more time, but after 30,60 and etc. seconds happens same.
Yeah, but you don’t load the data at all in that function anywhere. You don’t call PlayerManager anywhere in your PlayerAdded, and InfiniteCall triggers the luck system. Since PlayerManager isnt called in the PlayerAdded, the table is never generated.
Well i use those lines to add genName first to table and then only give it a value
PlayerManager.AddLuck(player, genName)
local LuckTable = PlayerManager.GetLuckAmounts(player)
print(LuckTable)
if table.find(LuckTable, genName) then
if odds >= 1 then
LuckTable.genName.Value += 1 * (odds/10)
elseif odds < 1 then
LuckTable.genName.Value += 1
end
It works fully with player manager functions, and they get data, as in script firstly Luck if it is not in table already get’s added to table
function PlayerManager.AddLuck(player, id)
local data = sessionData[player.UserId]
if not table.find(data.LuckAmounts, id) then
table.insert(data.LuckAmounts, id)
end
end
And then it gets an new luck table by this code
function PlayerManager.GetLuckAmounts(player)
return sessionData[player.UserId].LuckAmounts
end
And then get’s gen name, in example it is Gen1 and it name will match to Name in Array.
Maybe that because when i’m adding it first time i don’t add any value to it?
EDIT: By default that script was used in tycoon where id is an number like “1542354” and there it is string, so i defenitely need to make it like that “Gen1 = 0” as i understand if it will just add “Gen1” i can’t add it to value, but idk how to add value to it