This week I continued to work on MacVenture engine. I managed to fix a few blocking bugs and complete to the end Déjà Vu, Uninvited and Shadowgate. I also improved text input dialogs, made exit buttons clickable (as a shortcut to “Go” and “Open” commands), fixed the bug where titles are not displayed at saves. There are still a few things that needs to be implemented: diploma window, clean/mess up functionality and to fix how certain item bitmaps are displayed.
The first Déjà Vu went fairly well, and at the start of the week I managed to get through the end of it. After that, I went with playtesting Uninvited, and this is were I encountered the first problem. To progress further in the game, I needed to go through the door, but two deadly dogs were in front of it, blocking the path.
To pass them, you need use the “Speak” action to say the magic words and thus use the spell. The magic words are: “Instantum Illuminaris Abraxas”. I typed the words, however, that did not help and I died:
I tried over and over, with lowercase variants, checked if I needed some other item in inventory, however, everything was right according to walkthrough guides. This is when I started checking the scripts, as clearly, something wasn’t triggering. Luckily, there are only three opcodes involving strings: ScriptEngine::opadEQS
, ScriptEngine::opaeCONT
and ScriptEngine::opafCONTW
. The one responsible for the situation is opafCONTW
, which checks for the containing word. So I looked up, I discovered it was checking for the lowercase variant of the magic word: “instantum illuminaris abraxas”. So, fortunately, this turned out to be one line fix. Interestingly, when I debugged and printed out the strings from that method, as I discovered the game (apparently all games made with the engine) was containing a very huge variety of curse words. I won’t write them down here, but it has every word you can think of 🤪.
At the same time, I changed the way input text dialog worked. Before the changes, it was essentially an ordinary dialog, with no cursor of the text, and contained the same hardcoded title for all dialogs – “What would you like to say?”. This was also easy to fix, as the I essentially copied the code for cursor from MacTextWindow, and I added a line to fetch the text from the object, not from the hardcoded global table. The end result looks like this:
Another feature I finished was pressing on the exit buttons to go between the rooms. This is optional feature, as you could use “Open” command to open the doors and “Go” to actually go through the door. However, when playing the games this quality of life feature really comes handy, and was worthwhile implementing. Especially, when the code was all there, and I just had to copy it from Webventure repository.
After finishing Uninvited to the end, I went with playtesting Shadowgate. This game took a little longer, as there is a slightly annoying game mechanic with disposable torches, which are needed to be managed. There was one little blocking element, when reaching the room with the sphynx. Essentially, you have to solve the riddle of the sphynx by giving him the right item. However, when I operated the item on it, the game kept crashing. After looking for the cause a bit, I figured that the reason was dead simple: the engine had two versions of focusObjWin(ObjID objID)
function. The safe version focusObjectWindow(ObjID objID)
that checked if objID really referred to existing window, and unsafe that did not have this check. And of the course, when the code related to sphynx was executed, the unsafe version was run. The fix was just get rid of the unsafe version.
Lastly, I made sure the main game window and inventory windows kept their titles preserved when loading a save file. This took a bit of rewiring and adding for methods, as the code for managing the windows we have now is a little different from the original sources. In the original, main game window and all inventory windows where closing and opening at the start of the game, winning, losing, and save loading. I added back things for the inventory window, however kept the main game window unchanged for the most part. I make a workaround fix to set it’s objID to zero, so that when script executes, it updates the window info. The reason was that a decent portion of code needed to altered to adhere to the change, but since that one line fixes the issue I decided to leave it as is.