Hello developers!
I’m making a drawing game and what i want to achieve here is if the user have the face in Inventory it will change the face image to other one. The script that i made is
local CharacterFaces = {
HappyFace = {
Inventory = true,
AssetId = "rbxassetid://8207825395"
},
HoldingLaugh = {
Inventory = true,
AssetId = "rbxassetid://8210528464"
},
NeutralFace = {
Inventory = true,
AssetId = "rbxassetid://8210529936"
},
Expressionless = {
Inventory = true,
AssetId = "rbxassetid://8210532122"
},
Furious = {
Inventory = true,
AssetId = "rbxassetid://8210533587"
},
}
local function NextFace()
local CurNum = 1
local MaxNum = 5
CurNum = CurNum + 1
print(CharacterFaces[CurNum].Inventory)
if CharacterFaces[CurNum].Inventory then -- Error is here
script.Parent.Character.Face.Image = CharacterFaces[CurNum].AssetId
else
CurNum = 1
end
end
script.Parent.NextFace.MouseButton1Click:Connect(NextFace)
But what happen is Attempt to index nil with 'Inventory'.
The table you’re trying to access is a dictionary without numerical indexes. To access the value, you have to do something such as this:
local faces = {--array to hold the index values
"HappyFace",
"HoldingLaugh",
"NeutralFace",
"Expressionless",
"Furious"
}
local chosenFace = CharacterFaces[faces[CurNum]]
--gets the value of the index from the dictionary
local dictionary = {
index = "value"
}
local array = {
"value"
}
print(dictionary[1]) -- prints "nil"
print(array[1]) -- prints "value"
print(dictionary.index) -- prints "value"
--^^ this is what the code I provided does
As @HugeCoolboy2007 mentioned, you are trying to use a dictionary as an array. If you want to, you can convert your dictionary into an array but keep the names. You don’t have to use two Tables | Roblox Creator Documentation.
Your new code should be something like this:
local CharacterFaces = {
{
Name = "HappyFace",
Inventory = true,
AssetId = "rbxassetid://8207825395"
},
{
Name = "HoldingLaugh",
Inventory = true,
AssetId = "rbxassetid://8210528464"
},
{
Name = "NeutralFace",
Inventory = true,
AssetId = "rbxassetid://8210529936"
},
{
Name = "Expressionless",
Inventory = true,
AssetId = "rbxassetid://8210532122"
},
{
Name = "Furious",
Inventory = true,
AssetId = "rbxassetid://8210533587"
},
}
local CurrentFace = 1
local function NextFace()
CurrentFace += if (CurrentFace+1 > #CharacterFaces) then ((CurrentFace+1)%#CharacterFaces) else CurrentFace+1
if not CharacterFaces[CurrentFace].Inventory then CurrentFace = 1 end
script.Parent.Character.Face.Image = CharacterFaces[CurrentFace].AssetId
end
script.Parent.NextFace.MouseButton1Click:Connect(NextFace)
Note: I did slightly improve (change) your code, but it should work as intended.
Comments
Also know that if you don’t actually need the name property then you can use comments in your code for keeping track of what each face id should be. For example, you can’t really tell what face "rbxassetid://8210533587" is supposed to be. However, you can make a note of what it’s supposed to be using a comment. They are made using two hyphens (-) together and then anything you want to make a note of after.
For example, we can write it like this:
"rbxassetid://8210533587" -- Furious
The comment won’t have any effect on the actual code, it is merely there for helping document things people reading the code should know.
Oh thank you so much!! I gained knowledge in LUA. I’ll test this tomorrow at computer and since i think its a solution because thats how we get the variables inside the tables in module script. Then i think its a solution!
The original code you provided would just iterate through the table selecting the last face which has its “Inventory” field set to a Boolean value of true (it wasn’t selecting a face randomly), if you want the function to select a random face then you’ll need to implement random selection.
local function NextFace()
for faceName, faceData in pairs(CharacterFaces) do
if faceData["Inventory"] then
print("Player owns "..faceName.."face!")
script.Parent.Character.Face.Image = faceData["AssetId"]
local num = math.random(1, 2)
if num == 1 then --50% chance of loop breaking (can be changed easily)
break
end
end
end
end
This for example would essentially perform a coin-toss after each iteration of an owned face and either select the face and break the loop or ignore the face and continue the loop.
well that works! but it usually select “HoldingLaugh”/ “HappyFace”/ “NeutralFace”. But it’ll be ok since there will be alot of face, i just didn’t put everything, Thanks btw! Do you want me to solution you? Cause i already did on someone?
local function NextFace()
local ownedFaces = {}
for faceName, faceData in pairs(CharacterFaces) do
if faceData["Inventory"] then
table.insert(ownedFaces, faceName)
print("Player owns "..faceName.."face!")
end
end
if #ownedFaces >= 1 then
local random = math.random(1, #ownedFaces)
local faceName = ownedFaces[random]
script.Parent.Character.Face.Image = CharacterFaces[faceName]["AssetId"]
end
end