aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorVhati2018-12-16 22:05:45 -0500
committerFilippos Karapetis2018-12-23 20:17:25 +0200
commitf731760292c79180517dc3147c32afa62169e4e2 (patch)
treed9d4bcf8ce070210f78f9927090b63c8fc9e185a /engines
parent4f761d60028a3bc5263e199993cacf3605921ced (diff)
downloadscummvm-rg350-f731760292c79180517dc3147c32afa62169e4e2.tar.gz
scummvm-rg350-f731760292c79180517dc3147c32afa62169e4e2.tar.bz2
scummvm-rg350-f731760292c79180517dc3147c32afa62169e4e2.zip
SCI32: QFG4 Fix null scaler, climbing by monolith
Fixes an exception casting Trigger after using grapnel, bug #10837
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/engine/script_patches.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index a8d24d2f2b..592293ee0e 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -8995,6 +8995,49 @@ static const uint16 qfg4RestartPatch[] = {
PATCH_END
};
+// At the squid monolith (room 800), using the grapnel on the eastern ledge
+// disposes hero's scaler to freeze hero's size. A scaler dynamically shrinks
+// hero into the horizon as y-pos increases. It makes sense that hero should
+// maintain their size while climbing a vertical rope.
+//
+// Problem: After climbing the rope, both standing on the ledge and back on the
+// ground, hero's scaler will remain null. An exception will occur if a script
+// calls Prop::setScaler(hero) while hero's scaler is null. Casting Trigger on
+// the monolith, from either location, does it. As will climbing down, then
+// casting Levitate. Both spells have auras intended to fit hero's size. They
+// expect hero to have a scaler, not null.
+//
+// Ideally the climb script would've swapped in a dummy scaler, then swapped
+// the original scaler back upon return to ground level. Implementing that with
+// patches would be messy. There's no room to patch setScaler() itself to
+// broadly tolerate nulls. That'd avoid exceptions but wouldn't restore normal
+// scaling after a climb.
+//
+// As last resort, we simply leave the original scaler on hero, erasing the
+// setScale() call that would freeze hero's size. hero shrinks/grows a little
+// while climbing as a side effect.
+//
+// Applies to at least: English CD, English floppy, German floppy
+// Responsible method: sUseTheGrapnel::changeState(5) in script 800
+// Fixes bug: #10837
+static const uint16 qfg4RopeScalerSignature[] = {
+ SIG_MAGICDWORD,
+ 0x38, SIG_SELECTOR16(setScale), // pushi setScale
+ 0x76, // push0 (no args, disposes scaler & freezes size)
+ SIG_ADDTOOFFSET(+14), // ...
+ 0x81, 0x00, // lag global[0] (hero)
+ 0x4a, SIG_UINT16(0x0026), // send 38d
+ SIG_END
+};
+
+static const uint16 qfg4RopeScalerPatch[] = {
+ 0x35, 0x01, // ldi 0 (erase 2 bytes)
+ 0x35, 0x01, // ldi 0 (erase 2 bytes)
+ PATCH_ADDTOOFFSET(+14+2), // ...
+ 0x4a, PATCH_UINT16(0x0022), // send 34d
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry qfg4Signatures[] = {
{ true, 0, "prevent autosave from deleting save games", 1, qg4AutosaveSignature, qg4AutosavePatch },
@@ -9030,6 +9073,7 @@ static const SciScriptPatcherEntry qfg4Signatures[] = {
{ false, 663, "Floppy: fix crest bookshelf", 1, qfg4CrestBookshelfFloppySignature, qfg4CrestBookshelfFloppyPatch },
{ true, 663, "CD/Floppy: fix crest bookshelf motion", 1, qfg4CrestBookshelfMotionSignature, qfg4CrestBookshelfMotionPatch },
{ true, 800, "fix setScaler calls", 1, qfg4SetScalerSignature, qfg4SetScalerPatch },
+ { true, 800, "fix grapnel removing hero's scaler", 1, qfg4RopeScalerSignature, qfg4RopeScalerPatch },
{ true, 803, "fix sliding down slope", 1, qfg4SlidingDownSlopeSignature, qfg4SlidingDownSlopePatch },
{ true, 810, "fix conditional void calls", 1, qfg4ConditionalVoidSignature, qfg4ConditionalVoidPatch },
{ true, 830, "fix conditional void calls", 2, qfg4ConditionalVoidSignature, qfg4ConditionalVoidPatch },