ResidualVM: Week 6

Not much update this week. The conversation log menu is still under review at this point, but it should be merged very soon.
The recent plan is to finish some small things left that are related to all the newly implemented menus. I have included all of them in the project on ResidualVM’s GitHub page. Right now I have finished implementing two of them:
Task 1: Improve the debug console. Basically, this is a task about fixing issues. There is a debug console, which I have shown in week 1, provided in ResidualVM’s The Longest Journey, where a number of commands are provided for users to look at the game’s data and probably mess up with it. In the previous implementation, the console will crash if the user types improper commands in improper locations. Fixing this is not that hard, just add a bunch of checking beforehand and you are done with it.
Task 2: Add the version info text in the main menu. The lacking of the version info text was aware of weeks ago. I just want to tackle it later, and it’s right to do so since now, with the previous experience, I am crystal clear about how to deal with this: the “VERSION INFO HERE” widget is used for the text, so I just need to access its RenderEntry, get the VisualText it contains, and reset the text, plus twisting the position. It took me some time to think of a way to display the copyright symbol ©, but the rest is a piece of cake.
The Version Info Text
Before I wrote this blog I opened the pull request for the debug console and I intended to do the same for the version info one, but in order to avoid potential conflict, I created those two branches based on the branch of the conversation log menu, which hasn’t been merged yet, so the commit history of both of them is not clean and they will be rebased soon after the merging. I don’t like putting things that I deem unclean here. Anyway, if you are interested in the development, feel free to take a look at my GitHub.
All code images are generated through Carbon.

ResidualVM: Week 5

This week’s work nearly blew my mind…
So, it is finally the time to bring the conversation log back to The Longest Journey, which is another pretty complex menu in the game. In the conversation log, players may view all the past conversations they encountered. What makes this menu extremely complex is that it is completely dynamically data-driven generated. Based on your previous action, the conversations could be different. This means that retrieving all widgets of the current page at once is not working since you don’t know for sure how many widgets there will be.

Worse still, this menu actually contains two submenus: the Index and the Content, which means I am actually implementing two menus on one trail. And just when I am typing this blog I suddenly realize that it won’t be difficult to actually separate them as two distinct menus, damn…

The Index of Conversation Log
The Content of a Dialog

The mechanism of recording conversations has been implemented in the existing engine, so my job is just to retrieve them and properly render them on the screen. Wrapping the texts as classes and widgets has become handy for me, but the hard part is that I need to find a way to dynamically generate the layout of those texts.

In the game’s data, there are two entities called IndexFrame and LogFrame, which contains damn only the bounding box of the layout. My way of using them is simple: A Point is used as the rendering position of the current manipulated text. The height of the built text will be used to check whether rendering this text in the current position will exceed the box. If not, put it in an array for rendering, update the next position and go to the next round, otherwise, this page is finished. It sounds simple, but it needs more efforts than before to make the logic clear and maintain a good structure.

No code pic this time, for the reason that it is really not something that can be shown with a few lines of codes. Anyway, implementing this conversation log menu is really a hard bone, way more complex than last week’s work. But challenges make things interesting, aren’t they? Although my brain nearly exploded and I literally dropped one commit to rewrite it in the process, I actually enjoyed myself and found the feeling of accomplishment. That’s what makes GSoC valuable, I believe.

Well, it looks like the task of implementing the menu of The Longest Journey is in its last phrase. I am still not sure what to do next. We’ll see.

By the way, tomorrow (June 18th) is the Dragon Boat Festival in China. If you see this, go have some Zongzi, will you?

For the detailed development of the codes, please refers to the Pull Request on GitHub.

ResidualVM: Week 4

Not many things to update this week. I just started doing the internship, so I am still getting used to the new schedule. There is one thing I found out though: GSoC is like a million million million time more interesting than my internship. So sad that I cannot use GSoC to cover the credit requirement of my university.
OK, back to business. There are two focuses in this week: one is the video replay menu, the place where you can replay the video you have seen in the game, and the other is the diary pages menu, where you can read April’s diary. These two menus are both pretty easy, so I actually didn’t work heavy on them. The overall logic for them is pretty straightforward and is basically the same as what we have done previously. Get the widgets, render them, put actions on them, done.

The video replay menu
A diary page

Although pretty simple, there are still some small things that need to be treated specifically in these two menus.

For the video replay menu, the widgets for videos behave slightly differently from other normal widgets: the cursor will not change when you move your mouse on it. Since the mouse changing mechanism is controlled by other entities, it just felt silly to change the existing mechanism to deal with this case, plus the behaviours of video widgets are all very simple. Therefore, I decided to build a new class called FMVWidget, specifically built for this menu. It’s like a simplified version of the previous StaticLocationWidget, with fields and functions that just covers the need of the video replay menu.

See, it’s so simple that I inline many functions
For the diary pages menu, although the texts of the diary can be retrieved with the class RenderEntry, like the classic StaticLocationWidget,  the game identifies them not through their own names, but the names of resource layers that they belong to. So we need to go to the Layer class to retrieve the text we want.

The DiaryWidget

Well, that basically is it. After these two menus are fully polished and on the trail, it shall be the time to move to a hard bone: the dialogue menu. Let’s see what will happen there.

For the detailed development of the codes, please refers to this and this Pull Request on GitHub.
All code images are generated through Carbon.

ResidualVM: Week 3

Time flies, isn’t it?
This week’s focus is on the save & load menu. Similar to the settings menu, the most important part of implementing the save & load menu is to implementing the widget that shows the save data.

I created a new class called SaveDataWidget for this purpose. A SaveDataWidget consists of three parts: the screenshot thumbnail, the text, and a blue outline that shows up when you move the mouse on it.


The save menu of the original game

The thumbnail and (most of) the text are already saved in the original save data. All I need to do is to extract them out and properly store and render them. The thumbnail will be read as a Surface, which will then be bound to a Texture and then got rendered by a SurfaceRenderer.

Load the content

The text further consists of two parts: the title of the chapter and the saving time. The title will be saved and loaded through the description field of the original save data, while the time is already saved in other fields, well, almost. The original version of the save data lacks the “seconds” part, which needs to be added on. For this reason, some version checking needs to be done so as to preserve the compatibility of old save data.

Version checking in the metadata

Since the titles of the chapters will be stored in the save data as well, there needs a way to obtain them. It cannot be hard-coded since there are versions of The Longest Journey that are in different language (like French, the language of my best mentor bgK). In the game’s data, names of the chapters are all stored in the file called “chapters.ini”. For a better modularity (and because I foresee the need from the conversation dialogue), I created a new service called GameChapter, which loads all the chapters’ name in the beginning and provides them to other entities when needed.

The GameChapter service

After all these were done, the rest of implementing the actions performed by widgets were trivial. The save menu and load menu use the same location for resources, so they are greatly benefited from the use of inheritance.

Very soon, the The Longest Journey on ResidualVM shall fully support saving and loading through its original menu!

For the detailed development of the codes, please refers to the pull request on GitHub.
All code images are generated through Carbon.