Herman Doesn’t Want to Talk

When Guybrush enters Herman Toothrot’s camp (the set toc) for the first time, Guybrush should be able to trigger a conversation with Herman by walking up towards him. In ResidualVM, this conversation is never triggered! Let’s find out why.

Guybrush can’t get Herman’s attention!

In this scene, there’s a function to control the setup changes, including the closeup for the conversation Herman. This function checks if Guybrush is in the setup toc_log and if the conversation has already happened. So, why doesn’t the standard “Talk to Herman” come up when we approach? In this script, the range for this pop-up is reduced to 0, which prevents it from coming up. Setting it with:

  • toc.herman_obj.range = 4.3

Makes this behavior work as intended, and indeed, the script does this after Guybrush has the initial conversation with Herman. We can also check the state of the conversation, just to make sure this isn’t the problem either (using my pop up lua injector):

  • dd = glob.herman_talk_status

And as expected, it has the correct value, 0. Let’s check Guybrush’s current setup now:

  • dd = toc:current_setup()

Which returns 1, the ID for toc_wide. So it seems that Guybrush never enters the setup toc_log, which is required to trigger the conversation.

First of all, are we sure that the setup_change function is being run? Yes! We can prove this by checking the range on Herman’s note in this scene. If we check from the setup toc_wide, the interaction range for the note is 0, but when we change to the setup toc_close, the interaction range is changed to 1.8. This change is implemented in the setup_change function, so it’s certainly being run.

How about if we force the current setup to toc_log?

  • toc:current_setup(toc_log)
Talking to Herman, with a bit of hackery…

That works, and we’re treated to the conversation with Herman. So, it seems that Guybrush isn’t moving into the setup toc_log. As with the previous bug at Pegnose Pete’s House, there is a problem moving between setups, but this time, it’s impossible to move into the setup toc_log.

Let’s check to see what sector Guybrush is in with find_sector_type:

  • system.currentActor:find_sector_type(CAMERA)

We find that the sector reported when we’re near the log is actually toc_log.

How about IsActorInSector()? Both toc_wide and toc_log both are matched as valid setups when Guybrush is near the log. However, in the retail version, only toc_log matches, with IsActorInSector(ActorHandle, “toc_wide”) returning a nil, even when the setup toc_wide is showing! Trying this test again with the set gpt also resulted in nil values for IsActorInSector when in setups gtp_arial and gpt_dock, while ResidualVM reported that Guybrush was in the sectors of the same name.

First, let’s see if the sectors actually overlap. To visualize the sectors in a set, I rewrote a utility in perl from residualvm-tools to work with EMI and GRIM. This new version can be found here. The input of this tool is a text based set (so you’ll have to convert binary sets with setb2set first), and the output is a fig file, compatible with xfig. I also added the ability to filter by sector type.

For the set toc, I filtered by type camera, which is the type used to pick the view and got the following result:

Camera Sectors in the Set toc

From this, we can easily see that the sector toc_log (sector 19), overlaps one of the toc_wide (sector 0) sectors. After going through all of the sets, I found that this set is the only set in which the camera sector is almost completely overlapped, aside from the set cpt. In the set cpt, the two overlapping sectors have the same name.

So, why does this bug arise? When the camera change function is called, it checks to see if Guybrush is still in the same sector by calling IsActorInSector(). This call succeeds when it should fail because the sectors are overlapped, so the camera change function thinks Guybrush hasn’t left the sector.

This post is going on a bit long, so in the next post, we’ll come up with a solution to this problem.