diff options
-rw-r--r-- | sword2/interpreter.cpp | 33 | ||||
-rw-r--r-- | sword2/mouse.cpp | 21 |
2 files changed, 40 insertions, 14 deletions
diff --git a/sword2/interpreter.cpp b/sword2/interpreter.cpp index 92cf4bdbf4..d30ecee760 100644 --- a/sword2/interpreter.cpp +++ b/sword2/interpreter.cpp @@ -212,6 +212,8 @@ void Logic::setGlobalInterpreterVariables(int32 *vars) { } int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) { + bool checkPyramidBug = false; + #define STACK_SIZE 10 _standardHeader *header = (_standardHeader *) scriptData; @@ -256,6 +258,27 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) { debug(5, "Start script with offset %d", ip); } + // WORKAROUND: The dreaded pyramid makes the torch untakeable when you + // speak to Titipoco. This is because one of the conditions for the + // torch to be takeable is that Titipoco isn't doing anything out of + // the ordinary. Global variable 913 has to be 0 to signify that he is + // in his "idle" state. + // + // Unfortunately, simply the act of speaking to him sets variable 913 + // to 1 (probably to stop him from turning around every now and then). + // The script may then go on to set the variable to different values + // to trigger various behaviours in him, but if you have run out of + // these cases the script won't ever set it back to 0 again. + // + // So if his click hander (action script number 2) finishes, and + // variable 913 is 1, we set it back to 0 manually. + + if (strcmp((char *) header->name, "titipoco_81") == 0 && + ip >= (int32) READ_LE_UINT32((const int *) code + 3) && + ip < (int32) READ_LE_UINT32((const int *) code + 4)) { + checkPyramidBug = true; + } + code += noScripts * sizeof(int32) + sizeof(int32); #ifdef DONTPROCESSSCRIPTCHECKSUM @@ -290,8 +313,16 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) { switch (curCommand) { case CP_END_SCRIPT: // End the script - debug(5, "End script",0); + debug(5, "End script"); runningScript = 0; + + // WORKAROUND: Pyramid Bug. See explanation above. + + if (checkPyramidBug && _globals[913] == 1) { + warning("Working around Titipoco script bug (the \"Pyramid Bug\")"); + _globals[913] = 0; + } + break; case CP_PUSH_LOCAL_VAR32: // Push the contents of a local variable diff --git a/sword2/mouse.cpp b/sword2/mouse.cpp index 5cb6d784dd..852ba364c7 100644 --- a/sword2/mouse.cpp +++ b/sword2/mouse.cpp @@ -648,23 +648,18 @@ void Sword2Engine::normalMouse(void) { EXIT_FADING = 0; // WORKAROUND: Examining the lift while at the top of the - // pyramid causes the game to hang. It looks like a script - // bug to me: the script hides the mouse cursor, checks if the - // player pressed the left mouse button and, if not, jumps to - // an end of script instruction. + // pyramid causes the game to hang. // - // One idea would be to redirect the action to the elevator - // object at the bottom of the pyramid instead, but I don't - // know if that's a safe thing to do so for now I've disabled - // it. Maybe we could find a better workaround if we had a - // script decompiler... + // Actually, what happens is that the elevator's click handler + // (action script 2) disables the mouse cursor. Then it checks + // if the user clicked the left button, in which case it + // triggers the "going down" animation. // - // I'm checking the status of the left button rather than the - // right button because that's what I think the script does. + // If the user didn't click the left button, the script will + // terminate. With the mouse cursor still disabled. Ouch! if (_mouseTouching == 2773 && !LEFT_BUTTON) { - warning("Ignoring action to work around script bug at pyramid top"); - // _logic->setPlayerActionEvent(CUR_PLAYER_ID, 2737); + warning("Working around elevator script bug"); } else _logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching); |