Tuesday, April 1, 2014

Fixing the Positions

One of the requirements for the 2014 GSoC is to write a patch and complete a pull request. While we've finished a small fix with the segfault, I wanted to take on something a bit bigger for this pull request. Unfortunately, I didn't have enough time to figure out all of the Actor offsets, embedded functions and structures to complete the SetActorLocalAlpha function for this deadline. Instead, I decided to try and figure out why the chandelier lights were being rendered in the wrong place inside the Governor's Mansion. Unfortunately, this ended up being a much bigger problem than anticipated. Here's what I've found, along with more information about what the original engine does.
Guybrush burns, burns, burns, in a ring of fire
To start with, it was tedious to replay the same part of the game over and over again to get into the mansion. To avoid this in ResidualVM, we can use the debug console to run a script to change the current setup. To do this, we must first load the file that contains this script. Bring up the console with CTRL-D and type:
  • lua_do dofile("_jumpscripts.lua")
Press ESC, to close the console, and this code will be executed. Getting back into the console again, we run the jump_script function:
  •  lua_do jump_script("mansion interior")
Press ESC, and we'll be warped into the Governor's Mansion setup, cool! The jump_script  takes care of setting all of the game states as well, you can consider them to be like bookmarks in story. From one of these bookmarks, we can also jump to specific setups using the switch_to_set("setname"), where setname is the name of the set you'd like to switch to.

Unfortunately, this trick doesn't work in the retail build because we don't have a console to type Lua into. Thanks to klusark, who recently fixed mklab, we can now unpack and repack the .m4b file and insert our own code into the game's data. I'm using two scripts, one which extracts a Lua script, and another that pushes in the new script and rebuilds the .m4b file.

I used these scripts to unpack the _control.lua script and wrote this patch (containing only my own code, so it should be okay to post) to add a dialog box for typing in Lua to be executed directly. This mimics the console in ResidualVM, but works in the retail build as well. You enter this console by pressing the z key. We can  also print variables as the message line for the dialog box by assigning a value to the dd variable.

Now, let's take a look at what's going wrong with the chandelier lights. Examining gmi.lua, the script that contains the setup for the Governor's mansion, we see that the main chandelier actor is located in the variable gmi.chandelier. There's another actor called gmi.chandelier2 that is attached to the first chandelier variable that actually has all of the candle actors attached to it. So, let's explore these variables and see if we can figure out what the problem is.

Using the new console tool, we can press z to bring up our debug console, switch into the Governor's Mansion setup and print out the position for the chandeliers:
  • dofile("_jumpscripts.lua")
  • jump_script("mansion interior")
  • dd = gmi.chandelier:getpos()
  • dd = gmi.chandelier2:getpos() 
Here's the output from the retail version for gmi.chandelier2:
Debug output showing the position vector for chandelier2
Here's the output from ResidualVM:
Debug output showing the position vector for chandelier2
So, the chandelier2 variable is in the wrong position, with the y axis being -1 instead of 1 as in the retail version. Let's see if just moving chandelier2 to the right place fixes the problem:
  • gmi.chandelier2:setpos(0.0, 1.0, 0.0)
The chandelier lights are in the right place!
Indeed it does! So, what broke it? After inserting some more debugging print outs, I found that the actor.attach method was the culprit that was adjusting the position. Specifically, the call to the AttachActor lua method was causing the problem, which leads us to the method:Actor::attachToActor. In this function, the attached actor's position is modified by subtracting the base object's position from the attached actor's position. Checking against the retail version, it seems that the subtraction should be reversed, with the attached actor's position subtracted from the object it's being attached to.

I injected a new lua script with a series of attachments and compared those results with the retail engine and things looked perfect! Or did they...

No comments:

Post a Comment