PixelPest wrote: ↑Wed Jun 20, 2018 9:34 pm
The first error is a syntax error which prevents the code from running at all. The second error is the result of a nil value, which means that at least part of the code has run up to that point. Your code which produces the second error is almost correct, you just need to set the value for loognpc in onStart instead of at the beginning. NPCs, players, etc. aren't accessible until onStart, and before then, NPC.get(101) is just returning an empty table
PixelPest your explanation is embarassingly bad.
1) Care to explain "<eof> expected near end"? Might've been some LunaLua General Help if you did.
<eof> is the error window's way of saying "end of file". So the error "<eof> expected near end" reads as "I found an 'end' statement when I was expecting the file to end", which explains why removing the last "end" fixed it.
These errors are pretty easy to avoid with proper indenting. You're doing a pretty good effort in your code, but it falls apart a bit in the onEvent function.
To be precise: After the line
Code: Select all
if loognpc:mem(0x00, FIELD_STRING) == "luigi1.exe" then
you seem to indent twice, and then indent back by one for the next end, as you should. But as you can see in your post, the "if" and its "end" don't line up, leading to a jarring gap between the third- and second-to-last "end"s in the code.
This might've happened because the code was written with a mix of spaces and tabs for indenting (the lengths of each indent is inconsistent). It's pretty easy to keep track of indents if you press tab once whenever you wanna move in, and press backspace whenever you wanna move out by one. Here's a comparison of your indenting and proper one, for visualisation:
Code: Select all
local loognpc = NPC.get(101)[1]
function onStart()
loognpc:mem(0x44, FIELD_BOOL)
loognpc:mem(0x00, FIELD_STRING)
end
function onEvent(illegal2)
if loognpc:mem(0x44, FIELD_BOOL) == 1 then
if loognpc:mem(0x00, FIELD_STRING) == "luigi1.exe" then
player.character = CHARACTER_MEGAMAN
end
end
end
end
Code: Select all
local loognpc = NPC.get(101)[1]
function onStart()
loognpc:mem(0x44, FIELD_BOOL)
loognpc:mem(0x00, FIELD_STRING)
end
function onEvent(illegal2)
if loognpc:mem(0x44, FIELD_BOOL) == 1 then
if loognpc:mem(0x00, FIELD_STRING) == "luigi1.exe" then
player.character = CHARACTER_MEGAMAN
end
end
end
Note how easy it is to imagine a vertical line from the "if"s to their corresponding "end"s. Making sure that these always line up should make identifying, fixing and avoiding the <eof> error in the future easier.
Back to PixelPest's explanation:
2) You don't point out that MegaCDFan235 uses onEvent wrong.
onEvent isn't supposed to have its argument filled in. To clarify:
"eventName" is a variable which contains a string whenever ANY event is called. There can only be one onEvent per lua file, which will handle all events.
For example, if the event you wanna watch for is called "myEvent", you would check for it like this:
Code: Select all
function onEvent(eventName)
if eventName == "myEvent" then
--do stuff
end
end
Back to PixelPest:
3) While your explanation here is sound, the original approach to the problem is way wrong. Did you forget that the NPC array reshuffles? Grabbing a vanilla npc reference in the first frame is bound to error a few frames later.
There are a few ways to fix this, MegaCDFan235:
1. You can load the pnpc library to grab a persistent reference of your npc. Here's an example:
Code: Select all
local pnpc = API.load("pnpc")
local myNPC
function onStart()
local firstNPC = NPC.get(101)[1]
myNPC = pnpc.wrap(firstNPC)
end
After the pnpc.wrap line you will be able to use myNPC as a persistent reference. However, the reference will persist if the NPC dies and won't work if the NPC is a generator. Grabbing the first NPC in a table is generally a bit unsafe as soon as you have more than one. Not a problem in this situation, but it's something to watch out for.
2. You can load the NPC in onEvent directly.
Code: Select all
function onEvent(eventname)
if eventName == "illegal2" then
local luigi = NPC.get(101)[1]
if luigi.layerName == "luigi1.exe" then
--do stuff
end
end
end
The NPC won't expire while you're in onEvent, usually. So doing this is safer than trying to store a reference across frames.
luigi.layerName contains the same value as luigi:mem(0x00, FIELD_STRING) btw. It's easier to work with, though.
I don't quite know what "When the player approaches Luigi" means, but I'm guessing it means "when the player talks to luigi", because as far as I know 0x44 is the offset for when the exclamation mark is displayed, and I think the illegal2 event would run when talking to Luigi then. If this is the case, there's an even easier way to handle all this:
3. You can use onMessageBox(eventObj, messageName) if this event happens when talking to the NPC:
Code: Select all
function onMessageBox(eventObj, messageName)
if (messageName == "luigiTalk") then
eventObj.cancelled = true
Text.showMessageBox("Luigi: You are MegaMan now!")
player.character = CHARACTER_MEGAMAN
end
end
Let's run through this real quick:
onMessageBox runs just before ANY talk message appears on screen. It passes the event of the message appearing, as well as the contents of the message.
Code: Select all
if (messageName == "luigiTalk") then
If you set your Luigi NPC to say "luigiTalk", that message will passed to onMessageBox in the messageName argument and the code within this if statement will run.
This cancels the eventObj. This means that the act of showing the message will be cancelled. In short: The message "luigiTalk" will not appear on screen if this line runs.
Code: Select all
Text.showMessageBox("Luigi: You are MegaMan now!")
Since Luigi's vanilla message is a placeholder in this method, you can use showMessageBox to show an alternative message. Only if you want, though. This line is optional.
If you have any further questions about any part of this admittedly long explanation, don't hesitate to ask. I tried to make it as easily understandable as possible, but I wouldn't be surprised if I slipped up one way or another.