diff options
| -rw-r--r-- | sword2/console.cpp | 7 | ||||
| -rw-r--r-- | sword2/controls.cpp | 4 | ||||
| -rw-r--r-- | sword2/driver/rdwin.cpp | 2 | ||||
| -rw-r--r-- | sword2/interpreter.cpp | 114 | ||||
| -rw-r--r-- | sword2/mouse.cpp | 16 | ||||
| -rw-r--r-- | sword2/sword2.cpp | 37 | ||||
| -rw-r--r-- | sword2/sword2.h | 7 | 
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(); | 
