Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCUMM: Fix Captain Dread's head when Guybrush says "It's me again." #3929

Merged

Conversation

dwatteau
Copy link
Contributor

@dwatteau dwatteau commented May 30, 2022

This fixes an original, small and absolutely non-critical bug of Monkey2, so it can be safely ignored for the 2.6.0 release if necessary.

Original bug

This one comes from https://www.moviemistakes.com/main7214 (eh!).

When Guybrush interacts with Dread, Dread should turn and face him if he's not already looking at him. But the original script forgot to do this check, if Guybrush already met him, tries giving him an object and then immediately talks to him.

scummvm-monkey2-mac-00000

Indeed, this is what happens in script 201 (room 22) if it's the first time you talk to Dread and know his name (= OK):

[006C] (1D)   if (classOfIs(243,[147])) {
[0075] (D8)     printEgo([Text("Are you Captain Dread?")]);
[008E] (AE)     WaitForMessage();
[0090] (28)     if (!Bit[129]) {  # <==
[0095] (05)       drawObject(237setImage(,1));
[009B] (2E)       delay(60);
[009F] (05)       drawObject(235setImage(,2));
[00A5] (80)       breakHere();
[00A6] (05)       drawObject(235setImage(,3));
[00AC] (05)       drawObject(236setImage(,1));
[00B2] (2E)       delay(30);
[00B6] (1A)       Bit[129] = 1;
[00BB] (**)     }
[00BB] (14)     print(4,[Text("Ya mon, I'm Captain Dread." + wait() + "What can I do for ya?")]);
[00F0] (AE)     WaitForMessage();

(descumm has a bit of trouble decoding drawObject() it seems)

This is if you met him for the first time and don't know his name (= OK):

[00F2] (18)   } else {
[00F5] (D8)     printEgo([Text("Hello?!?")]);
[0100] (AE)     WaitForMessage();
[0102] (28)     if (!Bit[129]) {  # <==
[0107] (05)       drawObject(237setImage(,1));
[010D] (2E)       delay(60);
[0111] (05)       drawObject(235setImage(,2));
[0117] (80)       breakHere();
[0118] (05)       drawObject(235setImage(,3));
[011E] (05)       drawObject(236setImage(,1));
[0124] (2E)       delay(30);
[0128] (1A)       Bit[129] = 1;
[012D] (**)     }
[012D] (14)     print(4,[Text("Hello mon." + wait() + "My name's Captain Dread." + wait() + "What can I do for ya?")]);
[016C] (AE)     WaitForMessage();
[016E] (**)   }

And this is if you talk to him again (= bug):

[016E] (18) } else {
[0171] (D8)   printEgo([Text("It's me again.")]);
[0182] (AE)   WaitForMessage();
[0184] (05)   drawObject(237setImage(,1));
[018A] (2E)   delay(12);
[018E] (05)   drawObject(235setImage(,2));
[0194] (80)   breakHere();
[0195] (05)   drawObject(235setImage(,3));
[019B] (05)   drawObject(236setImage(,1));
[01A1] (2E)   delay(30);
[01A5] (1A)   Bit[129] = 1;
[01AA] (14)   print(4,[Text("So I see.  What can I do for ya this time, mon?")]);
[01DD] (AE)   WaitForMessage();
[01DF] (**) }

Notice that the if (!Bit[129]) condition is missing, this time. So Dread will always turn and face Guybrush, even if he's already facing him, hence the glitch with his head.

Since Dread's movement is always done by 32 bytes of opcodes, I think we can just skip that if its first drawObject() call was done although Bit[129] was set. This is inspired by what commit 9b56d7c did.

I could maybe just ignore all the drawObject() calls in that script if Bit[129] is set, but then I'd also have to ignore the delay() calls, otherwise Dread is a bit slow at reacting… I'm not a big fan of just moving the pointer with a static value, but I can't see why a particular version of Monkey2 would do these drawObject() calls differently. I tested various versions and Dread's full reaction is always 32-byte long with nothing in-between.

How to test

  1. Start a new game (or use boot param 456 which saves you time). Note that the Lite Mode can't trigger this bug.
  2. Pick up any object, such as the shovel on Woodtick's sign
  3. Go to the peninsula, go inside Dread's ship, talk to him once
  4. Go back inside his boat, try giving him the previous object. Then, talk to him again.

Dread should always turn and face you when reacting, but his head should never glitch.

I've tested this with:

  • the original DOS version, English
  • the original DOS version, French
  • the original Amiga version, English
  • the original Macintosh version, English
  • the Ultimate Talkie Edition: this script has been rewritten and it looks like it's already fixed this bug.

When Guybrush interacts with Dread, Dread should turn and face him if
he's not already looking at him. But the original script forgot to do
this check on Bit[129] if Guybrush already met him, tries giving him
an object and then immediately talks to him.

Since Dread's movement is always done by 32 bytes of opcodes, we can
just skip that if its first drawObject() call was done although
Bit[129] was set.
@bluegr
Copy link
Member

@bluegr bluegr commented Jun 11, 2022

Nice! This fixes the glitch in a clean manner. Thanks!

@bluegr bluegr merged commit e5601d3 into scummvm:master Jun 11, 2022
8 checks passed
@dwatteau dwatteau deleted the fix/scumm-monkey2-captain-dread-head-glitch branch Jun 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants