Remember this and check out book.script
of book.go
:
I see, I’m still slightly a bit confused by this. So does that mean that it doesn’t matter when on_message
is called? What I’m understanding when you say lua is top down is that it means the functions get built in order and has to be called from the top down? Should I be making self.book_id
somewhere else.
I ended up debugging it, the typing works, the sound for it works. You seem to be right though, it’s got to do with the
book.script
so I tried reordering the init
to be last. Wait, shouldn’t generate_book_code
be run first, before even creating the book? Wait that doesn’t make sense. When you create the book, you’re running the initialising method.
The issue you’re having right now is not because of ordering, you already fixed that. You need to fix the errors you’re getting in the console. Nothing will work if your script crashes. Start from the very first one and fix what it tells you is wrong.
book.script:7: attempt to index global 'self' (a nil value)
I see, thank you. About that error though, if the problem is that self.book_code = ""
is nil, then I’m either thinking that my goal is to make it either a local variable or to reorder when I create that variable. With local variables, can you pass them through msg.post
? I’m slightly confused on how to use it. I was thinking of passing it to my computer.script
but I don’t know if message call the book_code variable? I did read the documentation, I’m just confused about the message parameter. Yea no, reordering it wouldn’t work I think, I also just tried that.
No no, back up. Read the error message more carefully.
attempt to index
Attempting to index something means you’re trying to use it as a table and access a value inside it using a key.
attempt to index global
This means that the error is happening when your script attempts to access a global variable.
attempt to index global 'self'
The global variable that you’re trying to use is named: ‘self’.
'self' (a nil value)
The value of the global variable that you were trying to use is nil.
Since you were trying to get a value from the variable using a key, the variable was expected to be a table. Instead of a table, it was nil, hence the error.
[Edit]: Looking for a global variable means that no local variable was found with that name, in the current scope.
I see. Oh I see, I’m reading your previous post on Explanation of the “self” argument for dummies and I think I’m somewhat understanding it. I originally used self
to make it so the variable be different for every instance so I think I’m doing it right.So line 7 is self.book_code = ""
. So I’m debugging it again, reaching to the original error, clicking the triangle to forward it and jumping to here.
So if self
is a table, and I’m indexing a global self
from my book.script
, then does that mean I was trying to access the self
table inside of insert-book-code.script
or vice versa?
Sorry, I’m just having a hard time grasping this.
I guess another question would be, what is the key in this case.
Wait, so I’m using the factory to create an instance of a game object, and I’m using self
to make sure each variable of each instance of it is unique and not shared, but then inside of that game object, I have a script that’s also attempting to use self
to make sure each instance of it has unique variable values.
Wait a minute, if I’m already making a new instance of book.go
inside of insert-book-code.script
, why would I need self.book_code
inside of book.script
.
Line 7 from the error is:
self.book_code = ""
So the key in this case is: "book_code"
, since
self.book_code
is just shorthand for:
self["book_code"]
The one and only problem is: no local variable named ‘self
’ exists in the context where you expected it to. Just take a look at these few lines:
function init(self)
generate_book_appearance()
generate_book_code()
end
local function generate_book_code()
self.book_code = ""
Where’s self?
OK, I’ll stop being annoying and just explain it : ‘self’ is always given as a function argument. In other words, a local variable inside a function. The problem is, you are not passing ‘self’ on to the “generate_book_code()” function, so ‘self’ doesn’t exist inside that function when it runs. You want to do this:
function init(self)
generate_book_appearance(self)
generate_book_code(self)
end
local function generate_book_code(self)
self.book_code = ""
HOLY CRAP, I FEEL DUMB. Also I was having dinner and that popped into my head, I was thinking about how I had arguments inside of insert-book-code.script
and they all passed self
. THAT MAKES SENSE NOW.
Wait though, would I even need to make the variables inside of book.script
unique? Considering I’m using the factory to make a unique instance each time?
Thanks by the way for sticking it out with me.
Ok, I’m making progress though, managed to fix another error, it was the msg.post
one, I was passing a string instead of a table and it didn’t like that, and I fixed it, still got a few errors to go though.
It’s spawning a book at least.
ERROR:GAMEOBJECT: Component '/instance0#random_book_code_label' could not be found when dispatching message 'set_text' sent from default:/instance0#random-book
ERROR:GAMEOBJECT: Instance '<unknown>' could not be found when dispatching message 'play_sound' sent from default:/minigame_go#insert-book-code
INFO:DLIB: SSDP: Started on address 10.0.0.78
ERROR:SCRIPT: ...games/inventory/insert-book-code/insert-book-code.script:25: Could not send message 'game_over' from 'default:/minigame_go#insert-book-code' to 'main:/main'.
stack traceback:
[C]:-1: in function post
...games/inventory/insert-book-code/insert-book-code.script:25: in function <...games/inventory/insert-book-code/insert-book-code.script:24>
Ah ok, I’d probably have to pass in that instance for the url then.
local function generate_book_code(self)
self.book_code = ""
local charset = {} do
-- Ký tự [0-9a-zA-Z] dưới dạng mã ASCII: https://www.rapidtables.com/code/text/ascii-table.html
for c = 48, 57 do table.insert(charset, string.char(c)) end
for c = 65, 90 do table.insert(charset, string.char(c)) end
for c = 97, 122 do table.insert(charset, string.char(c)) end
end
-- [0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}
while (string.len(self.book_code) <= 19) do
if (#self.book_code % 5 == 0) then
self.book_code = self.book_code .."-"
else
self.book_code = self.book_code .. charset[math.random(1, #charset)]
end
end
-- Ok, this is the issue here. I already tried to pass self"#random_book_code_label" but that didn't work
label.set_text("#random_book_code_label", self.book_code)
msg.post("/computer#computer", "actual_book_code", {book_code = self.book_code})
end
Wait nope, fixed that issue too, turns out I got the wrong name for the label. There’s still the play_sound
issue, will try to figure that out, in fact I’m trying to find where it is. Got the sound to work. Gotta figure out how to make my spawned game object bigger, I’ll figure that out, I think you can specify scale with factory. Unless there’s a way to do that in the game object itself. Another one is to figure out how to check to see if your typed input matches the book code, hm. Oh yea, and trying to figure out how to return to the main collection and then loading the next minigame. We’ll get to that when we get to that.
Alright, it sort of works, just one odd problem now, with the timer, after it’s done it’s giving me an error where it can’t find the main collection.
What is the code you are running in the timer?
// timer
timer.delay(1, false, function()
msg.post("main:/main#main", "game_over")
end)
// main
function on_message(self, message_id, message, sender)
if message_id == hash("game_over") then
pprint("Create nested function for loading and unloading minigames?")
end
end
ERROR:SCRIPT: ...games/inventory/insert-book-code/insert-book-code.script:24: Could not send message 'game_over' from 'default:/minigame_go#insert-book-code' to 'main:/main#main'.
stack traceback:
I wonder if it has to do with the directory.
No no no. The way you have arranged stuff in your Assets (the panel on the left) in terms of filenames and folder structure has nothing to do with the url used in msg.post
. It is the structure in the Outline that matter, and the ids you have assigned there.
I see, I think I might know the issue, I’d have to load the main collection before sending message posts to it, and probably unload the current collection I’m in. Thank Britzl. Or I start from main.collection, then load in the current collection I’m on then unload the latter when the timer goes down, i.e. unload current collection then it should call inside of main
if message_id == hash("proxy_unloaded") then
pprint("Cycle through the minigames again.")
end
Hate to revive a thread, solved one scenario but now have a similar scenario to this one. Basically I’m now trying to spawn a bunch of game objects that have a different sprite for each instance (basically they’re just alphabetical letters) and am using Factory and Properties as an example, however I don’t think I need to add functionality to the game object I’m spawning in its own script since it’s just being used in this specific collection. I would assume that me using self.letter
would make each instance unique, so I don’t understand why it wouldn’t recognise the id, and since self.letter
is an instance of the spawned game object, shouldn’t go.animate
recognise that path? Thanks to anyone who responds.
local function random_position()
return vmath.vector3(math.random(1, sys.get_config("display.width")), math.random(1, sys.get_config("display.height")), 0)
end
local function spawn_letters(self)
local charset = {} do
-- Ký tự [0-9a-zA-Z] dưới dạng mã ASCII: https://www.rapidtables.com/code/text/ascii-table.html
for c = 97, 122 do table.insert(charset, string.char(c)) end
end
for i,v in ipairs(charset) do
self.letter = factory.create("#alphabet_factory", random_position())
sprite.play_flipbook(self.letter.."#alphabet_sprite","keyboard_"..v)
go.animate(self.letter.."#alphabet_sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, self.color, go.EASING_INOUTCIRC, 2)
end
end
function init(self)
msg.post(".", "acquire_input_focus")
spawn_letters(self)
timer.delay(8, false, function()
print("Failed.")
msg.post("main:/main#main", "game_over", {score = 0})
end)
end
function on_input(self, action_id, action)
end
function final(self)
msg.post(".", "release_input_focus")
end
Errors below:
ERROR:SCRIPT: ...est-service/where-to-find-book/where_to_find_book.script:14: Could not find any instance with id '<unknown>'.
stack traceback:
[C]:-1: in function animate
...est-service/where-to-find-book/where_to_find_book.script:14: in function spawn_letters
...est-service/where-to-find-book/where_to_find_book.script:20: in function <...est-service/where-to-find-book/where_to_find_book.script:18>
You can’t use string concatenation. Use:
msg.url(nil, self.letter, “alphabet_sprite”)
Thanks for replying britzl, but how would I determine what image the sprite should be set to?
Is this not what you are looking for as Britzl suggested?
local sprite_url = msg.url(nil, self.letter, “alphabet_sprite”)
sprite.play_flipbook(sprite_url,"keyboard_"..v)
Ah I see, yea I realise I made a typo on my variable name (and now I feel dumb). Thanks selimanac for replying.
I guess the problem is the animating part now.
ERROR:GAMEOBJECT: Properties can not be of type 'nil'.
ERROR:SCRIPT: ...est-service/where-to-find-book/where_to_find_book.script:14: only numerical values can be used as target values for animation
stack traceback:
[C]:-1: in function animate
...est-service/where-to-find-book/where_to_find_book.script:14: in function spawn_letters
...est-service/where-to-find-book/where_to_find_book.script:20: in function <...est-service/where-to-find-book/where_to_find_book.script:18>