aboutsummaryrefslogtreecommitdiff
path: root/sword2
diff options
context:
space:
mode:
authorTorbjörn Andersson2005-07-09 13:21:21 +0000
committerTorbjörn Andersson2005-07-09 13:21:21 +0000
commitf7a6729a01ce8c07dddf4a7f7c0b25f8690e2c1a (patch)
treed14d72b8cc3acabeb0877fd00a0f358f01812306 /sword2
parent866d3e3db357293aea3e70a55b3944bf3dccd5ac (diff)
downloadscummvm-rg350-f7a6729a01ce8c07dddf4a7f7c0b25f8690e2c1a.tar.gz
scummvm-rg350-f7a6729a01ce8c07dddf4a7f7c0b25f8690e2c1a.tar.bz2
scummvm-rg350-f7a6729a01ce8c07dddf4a7f7c0b25f8690e2c1a.zip
This should really be two or three different commits, but I'm too lazy for
that: * Re-worked the elevator script bug workaround so that it's more consistent with the other two script bug workarounds. * Some renamings to make it more clear that game events and input events are two completely different things. * Added function for clearing pending input events, and used that to fix an annoying keyboard repeat bug when closing the debug console. (The console would keep re-opening because the key press to open it kept repeating even though the key had been released.) svn-id: r18522
Diffstat (limited to 'sword2')
-rw-r--r--sword2/console.cpp7
-rw-r--r--sword2/controls.cpp4
-rw-r--r--sword2/driver/rdwin.cpp2
-rw-r--r--sword2/interpreter.cpp114
-rw-r--r--sword2/mouse.cpp16
-rw-r--r--sword2/sword2.cpp37
-rw-r--r--sword2/sword2.h7
7 files changed, 103 insertions, 84 deletions
diff --git a/sword2/console.cpp b/sword2/console.cpp
index f09d268731..76a96ea7fb 100644
--- a/sword2/console.cpp
+++ b/sword2/console.cpp
@@ -154,6 +154,7 @@ void Debugger::postEnter() {
bool Debugger::Cmd_Exit(int argc, const char **argv) {
_detach_now = true;
+ _vm->clearInputEvents();
return false;
}
@@ -584,15 +585,15 @@ bool Debugger::Cmd_Var(int argc, const char **argv) {
}
bool Debugger::Cmd_Rect(int argc, const char **argv) {
- uint32 filter = _vm->setEventFilter(0);
+ uint32 filter = _vm->setInputEventFilter(0);
_definingRectangles = !_definingRectangles;
if (_definingRectangles) {
- _vm->setEventFilter(filter & ~(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP));
+ _vm->setInputEventFilter(filter & ~(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP));
DebugPrintf("Mouse rectangles enabled\n");
} else {
- _vm->setEventFilter(filter | RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP);
+ _vm->setInputEventFilter(filter | RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP);
DebugPrintf("Mouse rectangles disabled\n");
}
diff --git a/sword2/controls.cpp b/sword2/controls.cpp
index d4817153b8..c677e3f4b2 100644
--- a/sword2/controls.cpp
+++ b/sword2/controls.cpp
@@ -280,7 +280,7 @@ void Dialog::setResult(int result) {
}
int Dialog::runModal() {
- uint32 oldFilter = _vm->setEventFilter(0);
+ uint32 oldFilter = _vm->setInputEventFilter(0);
int i;
@@ -386,7 +386,7 @@ int Dialog::runModal() {
setResult(0);
}
- _vm->setEventFilter(oldFilter);
+ _vm->setInputEventFilter(oldFilter);
return _result;
}
diff --git a/sword2/driver/rdwin.cpp b/sword2/driver/rdwin.cpp
index d5c2a1b54f..bfdeb4ad3d 100644
--- a/sword2/driver/rdwin.cpp
+++ b/sword2/driver/rdwin.cpp
@@ -57,7 +57,7 @@ void Screen::markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1) {
*/
void Screen::updateDisplay(bool redrawScene) {
- _vm->parseEvents();
+ _vm->parseInputEvents();
fadeServer();
if (redrawScene) {
diff --git a/sword2/interpreter.cpp b/sword2/interpreter.cpp
index 171c13dbf2..3f979220db 100644
--- a/sword2/interpreter.cpp
+++ b/sword2/interpreter.cpp
@@ -21,6 +21,7 @@
#include "common/stdafx.h"
#include "common/util.h"
#include "sword2/sword2.h"
+#include "sword2/defs.h"
#include "sword2/interpreter.h"
#include "sword2/logic.h"
#include "sword2/memory.h"
@@ -256,54 +257,20 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
debug(4, "Resume script %d with offset %d", scriptNumber, ip);
}
- // WORKAROUND: The dreaded pyramid bug 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.
-
- bool checkPyramidBug = false;
-
- // WORKAROUND for bug #1214168: The not-at-all dreaded mop bug.
- //
- // At the London Docks, global variable 1003 keeps track of Nico:
- //
- // 0: Hiding behind the first crate.
- // 1: Hiding behind the second crate.
- // 2: Standing in plain view on the deck.
- // 3: Hiding on the roof.
- //
- // The bug happens when trying to pick up the mop while hiding on the
- // roof. Nico climbs down, the mop is picked up, but the variable
- // remains set to 3. Visually, everything looks ok. But as far as the
- // scripts are concerned, she's still hiding up on the roof. This is
- // not fatal, but leads to a number of glitches until the state is
- // corrected. E.g. trying to climb back up the ladder will cause Nico
- // to climb down again.
- //
- // Global variable 1017 keeps track of the mop. Setting it to 2 means
- // that the mop has been picked up. We should be able to use that as
- // the signal that Nico's state needs to be updated as well. There are
- // a number of other possible workarounds, but this is the closest
- // point I've found to where Nico's state should have been updated, had
- // the script been correct.
+ // There are a couple of known script bugs related to interacting with
+ // certain objects. We try to work around a few of them.
bool checkMopBug = false;
+ bool checkPyramidBug = false;
+ bool checkElevatorBug = false;
if (scriptNumber == 2) {
- if (strcmp((char *)header->name, "titipoco_81") == 0)
- checkPyramidBug = true;
- else if (strcmp((char *)header->name, "mop_73") == 0)
+ if (strcmp((char *)header->name, "mop_73") == 0)
checkMopBug = true;
+ else if (strcmp((char *)header->name, "titipoco_81") == 0)
+ checkPyramidBug = true;
+ else if (strcmp((char *)header->name, "lift_82") == 0)
+ checkElevatorBug = true;
}
code += noScripts * sizeof(int32);
@@ -356,13 +323,42 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
// End the script
runningScript = false;
- // WORKAROUND: Pyramid Bug. See explanation above.
+ // WORKAROUND: The dreaded pyramid bug 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 finishes, and variable 913 is
+ // 1, we set it back to 0 manually.
if (checkPyramidBug && _scriptVars[913] == 1) {
- warning("Working around Titipoco script bug (the \"Pyramid Bug\")");
+ warning("Working around pyramid bug: Resetting Titipoco's state");
_scriptVars[913] = 0;
}
+ // WORKAROUND: The not-so-known-but-should-be-dreaded
+ // elevator bug.
+ //
+ // The click handler for the top of the elevator only
+ // handles using the elevator, not examining it. When
+ // examining it, the mouse cursor is removed but never
+ // restored.
+
+ if (checkElevatorBug && Logic::_scriptVars[RIGHT_BUTTON]) {
+ warning("Working around elevator bug: Restoring mouse pointer");
+ fnAddHuman(NULL);
+ }
+
debug(9, "CP_END_SCRIPT");
break;
case CP_QUIT:
@@ -450,10 +446,34 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
Read16ip(parameter);
value = pop();
- // WORKAROUND: Mop bug. See explanation above.
+ // WORKAROUND for bug #1214168: The not-at-all dreaded
+ // mop bug.
+ //
+ // At the London Docks, global variable 1003 keeps
+ // track of Nico:
+ //
+ // 0: Hiding behind the first crate.
+ // 1: Hiding behind the second crate.
+ // 2: Standing in plain view on the deck.
+ // 3: Hiding on the roof.
+ //
+ // The bug happens when trying to pick up the mop while
+ // hiding on the roof. Nico climbs down, the mop is
+ // picked up, but the variable remains set to 3.
+ // Visually, everything looks ok. But as far as the
+ // scripts are concerned, she's still hiding up on the
+ // roof. This is not fatal, but leads to a number of
+ // glitches until the state is corrected. E.g. trying
+ // to climb back up the ladder will cause Nico to climb
+ // down again.
+ //
+ // Global variable 1017 keeps track of the mop. Setting
+ // it to 2 means that the mop has been picked up. We
+ // use that as the signal that Nico's state needs to be
+ // updated as well.
if (checkMopBug && parameter == 1017 && _scriptVars[1003] != 2) {
- warning("Working around Mop script bug: Setting Nico state");
+ warning("Working around mop bug: Setting Nico's state");
_scriptVars[1003] = 2;
}
diff --git a/sword2/mouse.cpp b/sword2/mouse.cpp
index 176ae7579a..c12258c07b 100644
--- a/sword2/mouse.cpp
+++ b/sword2/mouse.cpp
@@ -794,21 +794,7 @@ void Mouse::normalMouse() {
Logic::_scriptVars[EXIT_CLICK_ID] = 0;
Logic::_scriptVars[EXIT_FADING] = 0;
- // WORKAROUND: Examining the lift while at the top of the
- // pyramid causes the game to hang.
- //
- // 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.
- //
- // If the user didn't click the left button, the script will
- // terminate. With the mouse cursor still disabled. Ouch!
-
- if (_mouseTouching == 2773 && !Logic::_scriptVars[LEFT_BUTTON]) {
- warning("Working around elevator script bug");
- } else
- _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
byte buf1[NAME_LEN], buf2[NAME_LEN];
diff --git a/sword2/sword2.cpp b/sword2/sword2.cpp
index 06363f51f5..a0d8d27d22 100644
--- a/sword2/sword2.cpp
+++ b/sword2/sword2.cpp
@@ -260,7 +260,7 @@ int Sword2Engine::init(GameDetector &detector) {
// During normal gameplay, we care neither about mouse button releases
// nor the scroll wheel.
- setEventFilter(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP | RD_WHEELUP | RD_WHEELDOWN);
+ setInputEventFilter(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP | RD_WHEELUP | RD_WHEELDOWN);
setupPersistentResources();
initialiseFontResourceFlags();
@@ -463,18 +463,29 @@ KeyboardEvent *Sword2Engine::keyboardEvent() {
return &_keyboardEvent;
}
-uint32 Sword2Engine::setEventFilter(uint32 filter) {
- uint32 oldFilter = _eventFilter;
+uint32 Sword2Engine::setInputEventFilter(uint32 filter) {
+ uint32 oldFilter = _inputEventFilter;
- _eventFilter = filter;
+ _inputEventFilter = filter;
return oldFilter;
}
/**
+ * Clear the input events. This is so that we won't get any keyboard repeat
+ * right after using the debugging console.
+ */
+
+void Sword2Engine::clearInputEvents() {
+ _keyboardEvent.pending = false;
+ _keyboardEvent.repeat = 0;
+ _mouseEvent.pending = false;
+}
+
+/**
* OSystem Event Handler. Full of cross platform goodness and 99% fat free!
*/
-void Sword2Engine::parseEvents() {
+void Sword2Engine::parseInputEvents() {
OSystem::Event event;
uint32 now = _system->getMillis();
@@ -482,7 +493,7 @@ void Sword2Engine::parseEvents() {
while (_system->pollEvent(event)) {
switch (event.type) {
case OSystem::EVENT_KEYDOWN:
- if (!(_eventFilter & RD_KEYDOWN)) {
+ if (!(_inputEventFilter & RD_KEYDOWN)) {
_keyboardEvent.pending = true;
_keyboardEvent.repeat = now + 400;
_keyboardEvent.ascii = event.kbd.ascii;
@@ -494,42 +505,42 @@ void Sword2Engine::parseEvents() {
_keyboardEvent.repeat = 0;
break;
case OSystem::EVENT_MOUSEMOVE:
- if (!(_eventFilter & RD_KEYDOWN)) {
+ if (!(_inputEventFilter & RD_KEYDOWN)) {
_mouse->setPos(event.mouse.x, event.mouse.y - MENUDEEP);
}
break;
case OSystem::EVENT_LBUTTONDOWN:
- if (!(_eventFilter & RD_LEFTBUTTONDOWN)) {
+ if (!(_inputEventFilter & RD_LEFTBUTTONDOWN)) {
_mouseEvent.pending = true;
_mouseEvent.buttons = RD_LEFTBUTTONDOWN;
}
break;
case OSystem::EVENT_RBUTTONDOWN:
- if (!(_eventFilter & RD_RIGHTBUTTONDOWN)) {
+ if (!(_inputEventFilter & RD_RIGHTBUTTONDOWN)) {
_mouseEvent.pending = true;
_mouseEvent.buttons = RD_RIGHTBUTTONDOWN;
}
break;
case OSystem::EVENT_LBUTTONUP:
- if (!(_eventFilter & RD_LEFTBUTTONUP)) {
+ if (!(_inputEventFilter & RD_LEFTBUTTONUP)) {
_mouseEvent.pending = true;
_mouseEvent.buttons = RD_LEFTBUTTONUP;
}
break;
case OSystem::EVENT_RBUTTONUP:
- if (!(_eventFilter & RD_RIGHTBUTTONUP)) {
+ if (!(_inputEventFilter & RD_RIGHTBUTTONUP)) {
_mouseEvent.pending = true;
_mouseEvent.buttons = RD_RIGHTBUTTONUP;
}
break;
case OSystem::EVENT_WHEELUP:
- if (!(_eventFilter & RD_WHEELUP)) {
+ if (!(_inputEventFilter & RD_WHEELUP)) {
_mouseEvent.pending = true;
_mouseEvent.buttons = RD_WHEELUP;
}
break;
case OSystem::EVENT_WHEELDOWN:
- if (!(_eventFilter & RD_WHEELDOWN)) {
+ if (!(_inputEventFilter & RD_WHEELDOWN)) {
_mouseEvent.pending = true;
_mouseEvent.buttons = RD_WHEELDOWN;
}
diff --git a/sword2/sword2.h b/sword2/sword2.h
index ffbe086b24..370046beee 100644
--- a/sword2/sword2.h
+++ b/sword2/sword2.h
@@ -97,7 +97,7 @@ struct StartUp {
class Sword2Engine : public Engine {
private:
- uint32 _eventFilter;
+ uint32 _inputEventFilter;
// The event "buffers"
MouseEvent _mouseEvent;
@@ -161,9 +161,10 @@ public:
uint32 _controlsFontId;
uint32 _redFontId;
- uint32 setEventFilter(uint32 filter);
+ uint32 setInputEventFilter(uint32 filter);
- void parseEvents();
+ void clearInputEvents();
+ void parseInputEvents();
bool checkForMouseEvents();
MouseEvent *mouseEvent();