I was trying to implement a highscore system into my game but when i try to declare my highscore loadFile I get this error.
Attempt to call global 'loadFile' (a nil value)
Here is my code.
highscore = loadFile ("highscore.txt")
local function checkForFile ()
if highscore == "empty" then
highscore = 0
saveFile("highscore.txt", highscore)
end
end
checkForFile()
print ("Highscore is", highscore)
local function onSystemEvent ()
if playerScore > tonumber(highscore) then
--We use tonumber as highscore is a string when loaded
saveFile("highscore.txt", score)
end
end
Runtime:addEventListener( "system", onSystemEvent )
I am using Corona SDK.
The developers of the corona ask published a nice guide about saving and writing to files, which should fulfill your needs.
Basically you get the path via system.pathForFile and then open it using io.open.
You would do it like this:
local path = system.pathForFile( "highscore.txt", system.DocumentsDirectory )
local file = io.open(path, 'w+')
And then, to get the content of the file:
local content = file:read('*a')
local highscore
if (content ~= null)
highscore = tonumber(content)
// do stuff with the loaded highscore
end
And to write to the file:
file:write(highscore)
The file you are loading is not a Lua file but a text file. So there is no point in using loadfile even if it existed. Use instead io.read with file:read or file:lines (where file is the object returned by io.open()).
Related
Script:
local ToolFolder = game:GetService("ServerStorage"):FindFirstChild("SavedItems")
local DataStoreService = game:GetService("DataStoreService")
local SaveData = DataStoreService:GetDataStore("SaveData")
game.Players.PlayerAdded:Connect(function(player)
local ToolData = SaveData:GetAsync(player.UserId)
local BackPack = player:WaitForChild("Backpack")
local StarterGear = player:WaitForChild("StarterGear")
if ToolData ~= nil then
for i, v in pairs(ToolData) do
if ToolFolder:FindFirstChild(v) and BackPack:FindFirstChild(v) == nil and StarterGear:FindFirstChild(v) == nil then
ToolFolder[v]:Clone().Parent = BackPack
ToolFolder[v]:Clone().Parent = StarterGear
end
end
end
player.CharacterRemoving:Connect(function(Character)
Character:WaitForChild("Humanoid"):UnequipTools()
end)
end)
game.Players.PlayerRemoving:Connect(function(player)
local ToolTable = {}
for i,v in pairs(player.Backpack:GetChildren()) do
table.insert(ToolTable, v.Name)
end
if ToolTable ~= nil then
SaveData:SetAsync(player.UserId, ToolTable)
end
end)
Issue:
ServerScriptService.SaveTools:12: attempt to index nil with 'FindFirstChild'
Couldn't find a solution. Appreciate any help. :)
Any time you see "attempt to index nil with x" you need to look at where you are asking for "x" and realize that the object holding "x" doesn't exist. The job then becomes figuring out why that object doesn't exist.
In your case, whatever object that you are calling "FindFirstChild" on line 12 doesn't exist. Sadly, line 12 uses this three times :
if ToolFolder:FindFirstChild(v) and
BackPack:FindFirstChild(v) == nil and
StarterGear:FindFirstChild(v) == nil then
So let's look at where ToolFolder, BackPack, and StarterGear were created and see if that gives any clues.
local ToolFolder = game:GetService("ServerStorage"):FindFirstChild("SavedItems")
...
local BackPack = player:WaitForChild("Backpack")
local StarterGear = player:WaitForChild("StarterGear")
Backpack and StarterGear looks correct, they are both children of the Player, and both look to be spelled correctly.
ToolFolder is probably the culprit, you should make sure there is actually an object named SavedItems in ServerStorage. Double check that the spelling and capitalization are correct.
My goal here is to send the player object and the object name through to the client script to display the object name on a text label.
When I run this, it prints nil and nil. I want player.Name and name as you will see in the second code sample. Another error I get is "attempt to concatenate nil with string" from the client script.
Here is my server-side code:
script.onTouch.OnInvoke = function(button, sellObj, sellObjValue, buyObj, buyObjValue, afterWave, isLoadedPart)
if isLoadedPart == true then
local info = script.Parent.Parent.info
local player = info.player.Value
local owner = info.owner.Value
local savedItems = info.savedItems.Value
local builds = script.Parent.Parent.activeBuilds
if afterWave > info.activeWave.Value then
info.activeWave.Value = afterWave
end
button.Parent = savedItems.buttons
button.jobDone.Value = true
if sellObj ~= nil then
sellObj.Parent = savedItems.builds
end
if buyObj ~= nil then
buyObj.Parent = builds
end
local td = require(script.Parent.tycoonDictionary)
if not table.find(td.boughtButtons, button.objectId.Value) then
table.insert(td.boughtButtons, button.objectId.Value)
end
local ui = game.ReplicatedStorage:FindFirstChild('onPartLoad')
if ui then
ui:FireClient(player, 'buyObj.Name')
print('yes')
else
print('no')
end
else
local info = script.Parent.Parent.info
local player = info.player.Value
local owner = info.owner.Value
local money = info.player.Value.leaderstats.Money
local savedItems = info.savedItems.Value
local builds = script.Parent.Parent.activeBuilds
if money.Value >= buyObjValue or money.Value == buyObjValue then
if afterWave > info.activeWave.Value then
info.activeWave.Value = afterWave
end
button.Parent = savedItems.buttons
button.jobDone.Value = true
if sellObj ~= nil then
sellObj.Parent = savedItems.builds
money.Value += sellObjValue
end
if buyObj ~= nil then
buyObj.Parent = builds
money.Value -= buyObjValue
end
local td = require(script.Parent.tycoonDictionary)
if not table.find(td.boughtButtons, button.objectId.Value) then
table.insert(td.boughtButtons, button.objectId.Value)
warn(td.boughtButtons)
end
else
player.PlayerGui.inGame.error.label.invokeScript.errorInvoke:Invoke("Insufficient Funds")
end
end
script.Parent.waveChecker.afterRun:Invoke()
end
And here is my client-side code:
game.ReplicatedStorage.onPartLoad.OnClientEvent:Connect(function(player, name)
print(player.Name, name)
print(script.Parent.Text)
script.Parent.Text = name .. 'is loaded.'
print(script.Parent.Text)
end)
Here I will tell you a little about this game. It is a tycoon that saves data using a table with all button Ids in it. When it loads, it gets the button associated with the id and fires the server code for every button. If the button is a load button, it fires the client with the player and the buyObj.Name.
Is there just a little mistake or can I not send arguments to the client at all? Any help will be appreciated!
The OnInvoke callback's first argument is always the player that fired it, so you should change line 1 of the first script to:
script.onTouch.OnInvoke = function(playerFired, button, sellObj, sellObjValue, buyObj, buyObjValue, afterWave, isLoadedPart)
And :FireClient() requires a player argument as its first argument, so you should change
ui:FireClient(player, 'buyObj.Name')
to
ui:FireClient(playerFired, player, 'buyObj.Name')
Here is the solution I came up with;
First, I read through some Roblox documentation to find that the first argument I had to send when using :FireClient was the player, and because I already had the player there, it was just sending the function to that player. Now, I had 2 choices, I could send the player twice, or delete the player variable from the script. I chose the second one.
Here is what the :FireClient line in the server script looks like now:
game.ReplicatedStorage:WaitForChild('onPartLoad'):FireClient(player, buyObj.Name)
And here is what the client function script looks like now:
game.ReplicatedStorage.onPartLoad.OnClientEvent:Connect(function(name)
if name ~= 'starterFoundation' then
script.Parent.Text = name .. ' is loaded.'
end
end)
Thank you #TypeChecked for helping me realize this!
I am currently making an app in corona SDK. My goal for now is to create something (like a string or Boolean) that could be stored in a .txt file. What I want to do is in one, let us say for example scores.lua file have all the values and then, when in need use them in the main.lua file. The problem is that the main.lua does not get the files that I saved in scores.lua.
I am using something called ego.lua
function saveFile( fileName, fileData )
local path = system.pathForFile( fileName, system.DocumentsDirectory )
local file = io.open( path, "w+" )
if file then
file:write( fileData )
io.close( file )
end
end
function loadFile( fileName )
local path = system.pathForFile( fileName, system.DocumentsDirectory )
local file = io.open( path, "r" )
if file then
local fileData = file:read( "*a" )
io.close( file )
return fileData
else
file = io.open( path, "w" )
file:write( "empty" )
io.close( file )
return "empty"
end
end
and what I save in my main.lua file:
ego = require "ego"
saveFile = ego.saveFile
loadFile = ego.loadFile
valueName = loadFile( "gucci.txt" )
local money = display.newText(tostring(valueName), 200, 100, "Helvetica", 20)
and my score.lua file :
ego = require "ego"
saveFile = ego.saveFile
loadFile = ego.loadFile
saveFile( "gucci.txt", "This works")
I recommended you Simple-Table-Load-Save-Functions-for-Corona-SDK - Two very simple load and save function to store a Lua Table and Read it back in. Requires the Corona SDK JSON Library.
i am new to lua. actually this script use for game server but i need help for getting the value from my store .txt file. so my store system is each players will be save on one file.
Store File
my syntax data from text file
[name]:[points]:[which var point earned on index]
my example data (this var point actually the written data from lua file that sended to text file)
jack:60:4
ronald:40:1
jack:30:1
so when i got from above is the list of
local player = {{(name),(points),(which var point earned on index)},
{(name),(points),(which var point earned on index)},...};
My own code
local line_data = {}
local point_file = io.open("points.txt", "r")
for line in point_file:lines() do
local playername, playerpoint, playervarpointname = line:match("(%d+):(%d+):(%d+)")
local player_data = {playername, playerpoint, playervarpointname}
for i = 1, #line do
player_data = [#player_data + 1] = line[i];
end
line_data[#line_data + 1] = player_data
end
is this the correct code ?
local line_data = {}
local point_file = io.open("points.txt", "r")
for line in point_file:lines() do
local playername, playerpoint, playervarpointname = line:match("([^:]+):(%d+):(%d+)")
local player_data = {playername, playerpoint, playervarpointname}
table.insert(line_data, player_data)
end
Or , imho, '[a-zA-Z0-9]+ ' , may be used instead of '[^:]+'
Json parsing is not working on devices while works perfect on simulator, that scene could not be open where I read or write some data.
I have made a class for Json parsing
Here it is,
module(..., package.seeall)
local json=require ("json")
function saveTable(t,filename)
local path = system.pathForFile(filename, system.DocumentsDirectory)
local file = io.open(path,"w")
if file then
local contents = json.encode(t)
file:write(contents)
io.close(file)
return true
else
return false
end
end
function loadTable(filename)
local path = system.pathForFile(filename, system.DocumentsDirectory)
local contents = ""
local myTable = {}
local file = io.open(path,"r")
if file then
local contents = file:read("*a")
myTable = json.decode(contents)
io.close(file)
return myTable
end
return nil
end
I actually want an alternative of NSUserDefaults on Corona.
Any help?
Yea, I got it, I used to loadTable first, without saving table, so it would be a problem, never call loadTable before save table :)