[Scummvm-cvs-logs] scummvm master -> 71296d6461bd8346793ff939b5d2e84d22c58dfa

dreammaster dreammaster at scummvm.org
Thu Jul 23 02:27:29 CEST 2015


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
71296d6461 SHERLOCK: RT: Split TattooEngine code into separate widget classes


Commit: 71296d6461bd8346793ff939b5d2e84d22c58dfa
    https://github.com/scummvm/scummvm/commit/71296d6461bd8346793ff939b5d2e84d22c58dfa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-07-22T20:26:28-04:00

Commit Message:
SHERLOCK: RT: Split TattooEngine code into separate widget classes

Changed paths:
  A engines/sherlock/tattoo/widget_credits.cpp
  A engines/sherlock/tattoo/widget_credits.h
  A engines/sherlock/tattoo/widget_hangman.cpp
  A engines/sherlock/tattoo/widget_hangman.h
    engines/sherlock/module.mk
    engines/sherlock/tattoo/tattoo.cpp
    engines/sherlock/tattoo/tattoo.h
    engines/sherlock/tattoo/tattoo_scene.cpp
    engines/sherlock/tattoo/tattoo_user_interface.cpp
    engines/sherlock/tattoo/tattoo_user_interface.h



diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk
index 32c5d3a..4c12fc7 100644
--- a/engines/sherlock/module.mk
+++ b/engines/sherlock/module.mk
@@ -33,6 +33,8 @@ MODULE_OBJS = \
 	tattoo/tattoo_talk.o \
 	tattoo/tattoo_user_interface.o \
 	tattoo/widget_base.o \
+	tattoo/widget_credits.o \
+	tattoo/widget_hangman.o \
 	tattoo/widget_inventory.o \
 	tattoo/widget_lab.o \
 	tattoo/widget_talk.o \
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 90d2e5d..920bef1 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -34,13 +34,11 @@ namespace Sherlock {
 namespace Tattoo {
 
 TattooEngine::TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc) :
-		SherlockEngine(syst, gameDesc), _darts(this) {
-	_creditsActive = false;
+		SherlockEngine(syst, gameDesc), _darts(this), _hangmanWidget(this) {
 	_runningProlog = false;
 	_fastMode = false;
 	_allowFastMode = true;
 	_transparentMenus = true;
-	_creditSpeed = 4;
 }
 
 TattooEngine::~TattooEngine() {
@@ -175,400 +173,8 @@ void TattooEngine::loadInventory() {
 	inv.push_back(InventoryItem(0, inv8, invDesc8, "_LANT02I"));
 }
 
-void TattooEngine::initCredits() {
-	Common::SeekableReadStream *stream = _res->load("credits.txt");
-	int spacing = _screen->fontHeight() * 2;
-	int yp = _screen->h();
-
-	_creditsActive = true;
-	_creditLines.clear();
-
-	while (stream->pos() < stream->size()) {
-		Common::String line = stream->readLine();
-
-		if (line.hasPrefix("Scroll Speed")) {
-			const char *p = line.c_str() + 12;
-			while ((*p < '0') || (*p > '9'))
-				p++;
-			
-			_creditSpeed = atoi(p);
-		} else if (line.hasPrefix("Y Spacing")) {
-			const char *p = line.c_str() + 12;
-			while ((*p < '0') || (*p > '9'))
-				p++;
-
-			spacing = atoi(p) + _screen->fontHeight() + 1;
-		} else {
-			int width = _screen->stringWidth(line) + 2;
-
-			_creditLines.push_back(CreditLine(line, Common::Point((_screen->w() - width) / 2 + 1, yp), width));
-			yp += spacing;
-		}
-	}
-
-	// Post-processing for finding split lines
-	for (int l = 0; l < (int)_creditLines.size(); ++l) {
-		CreditLine &cl = _creditLines[l];
-		const char *p = strchr(cl._line.c_str(), '-');
-
-		if (p != nullptr && p[1] == '>') {
-			cl._line2 = Common::String(p + 3);
-			cl._line = Common::String(cl._line.c_str(), p);
-			
-			int width = cl._width;
-			int width1 = _screen->stringWidth(cl._line);
-			int width2 = _screen->stringWidth(cl._line2);
-
-			int c = 1;
-			for (int l1 = l + 1; l1 < (int)_creditLines.size(); ++l1) {
-				if ((p = strchr(_creditLines[l1]._line.c_str(), '-')) != nullptr) {
-					if (p[1] == '>') {
-						Common::String line1 = Common::String(_creditLines[l1]._line.c_str(), p);
-						Common::String line2 = Common::String(p + 3);
-
-						width1 = MAX(width1, _screen->stringWidth(line1));
-
-						if (_screen->stringWidth(line2) > width2)
-							width2 = _screen->stringWidth(line2);
-						++c;
-					} else {
-						break;
-					}
-				} else {
-					break;
-				}
-			}
-
-			width = width1 + width2 + _screen->widestChar();
-			width1 += _screen->widestChar();
-
-			for (int l1 = l; l1 < l + c; ++l1) {
-				_creditLines[l1]._width = width;
-				_creditLines[l1]._xOffset = width1;
-			}
-
-			l += c - 1;
-		}
-	}
-
-	delete stream;
-}
-
-void TattooEngine::drawCredits() {
-	Common::Rect screenRect(0, 0, _screen->w(), _screen->h());
-	Surface &bb1 = _screen->_backBuffer1;
-
-	for (uint idx = 0; idx < _creditLines.size() && _creditLines[idx]._position.y < _screen->h(); ++idx) {
-		if (screenRect.contains(_creditLines[idx]._position)) {
-			if (!_creditLines[idx]._line2.empty()) {
-				int x1 = _creditLines[idx]._position.x;
-				int x2 = x1 + _creditLines[idx]._xOffset;
-				const Common::String &line1 = _creditLines[idx]._line;
-				const Common::String &line2 = _creditLines[idx]._line2;
-
-				bb1.writeString(line1, Common::Point(x1 - 1, _creditLines[idx]._position.y - 1), 0);
-				bb1.writeString(line1, Common::Point(x1, _creditLines[idx]._position.y - 1), 0);
-				bb1.writeString(line1, Common::Point(x1 + 1, _creditLines[idx]._position.y - 1), 0);
-
-				bb1.writeString(line1, Common::Point(x1 - 1, _creditLines[idx]._position.y), 0);
-				bb1.writeString(line1, Common::Point(x1 + 1, _creditLines[idx]._position.y), 0);
-
-				bb1.writeString(line1, Common::Point(x1 - 1, _creditLines[idx]._position.y + 1), 0);
-				bb1.writeString(line1, Common::Point(x1, _creditLines[idx]._position.y + 1), 0);
-				bb1.writeString(line1, Common::Point(x1 + 1, _creditLines[idx]._position.y + 1), 0);
-
-				bb1.writeString(line1, Common::Point(x1, _creditLines[idx]._position.y), INFO_TOP);
-
-				bb1.writeString(line2, Common::Point(x2 - 1, _creditLines[idx]._position.y - 1), 0);
-				bb1.writeString(line2, Common::Point(x2, _creditLines[idx]._position.y - 1), 0);
-				bb1.writeString(line2, Common::Point(x2 + 1, _creditLines[idx]._position.y - 1), 0);
-
-				bb1.writeString(line2, Common::Point(x2 - 1, _creditLines[idx]._position.y), 0);
-				bb1.writeString(line2, Common::Point(x2 + 1, _creditLines[idx]._position.y), 0);
-
-				bb1.writeString(line2, Common::Point(x2 - 1, _creditLines[idx]._position.y + 1), 0);
-				bb1.writeString(line2, Common::Point(x2, _creditLines[idx]._position.y + 1), 0);
-				bb1.writeString(line2, Common::Point(x2 + 1, _creditLines[idx]._position.y + 1), 0);
-
-				bb1.writeString(line2, Common::Point(x2, _creditLines[idx]._position.y), INFO_TOP);
-			} else {
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x - 1, _creditLines[idx]._position.y - 1), 0);
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x, _creditLines[idx]._position.y - 1), 0);
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x + 1, _creditLines[idx]._position.y - 1), 0);
-
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x - 1, _creditLines[idx]._position.y), 0);
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x + 1, _creditLines[idx]._position.y), 0);
-
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x - 1, _creditLines[idx]._position.y + 1), 0);
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x, _creditLines[idx]._position.y + 1), 0);
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x + 1, _creditLines[idx]._position.y + 1), 0);
-
-				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x, _creditLines[idx]._position.y), INFO_TOP);
-			}
-		}
-	}
-}
-
-void TattooEngine::blitCredits() {
-	Common::Rect screenRect(0, -_creditSpeed, _screen->w(), _screen->h() + _creditSpeed);
-
-	for (uint idx = 0; idx < _creditLines.size(); ++idx) {
-		if (screenRect.contains(_creditLines[idx]._position)) {
-			Common::Rect r(_creditLines[idx]._width, _screen->fontHeight() + 2);
-			r.moveTo(_creditLines[idx]._position.x, _creditLines[idx]._position.y - 1);
-
-			_screen->slamRect(r);
-		}
-
-		_creditLines[idx]._position.y -= _creditSpeed;
-	}
-}
-
-void TattooEngine::eraseCredits() {
-	Common::Rect screenRect(0, -_creditSpeed, _screen->w(), _screen->h() + _creditSpeed);
-
-	for (uint idx = 0; idx < _creditLines.size(); ++idx) {
-		if (screenRect.contains(_creditLines[idx]._position)) {
-			Common::Rect r(_creditLines[idx]._width, _screen->fontHeight() + 3);
-			r.moveTo(_creditLines[idx]._position.x, _creditLines[idx]._position.y - 1 + _creditSpeed);
-
-			_screen->restoreBackground(r);
-		}
-	}
-
-	if (_creditLines[_creditLines.size() - 1]._position.y < -_creditSpeed) {
-		_creditLines.clear();
-		_creditsActive = false;
-		setFlags(!3000);
-	}
-}
-
 void TattooEngine::doHangManPuzzle() {
-	char answers[3][10];
-	Common::Point lines[3];
-	const char *solutions[3];
-	int numWide, spacing;
-	ImageFile *paper;
-	Common::Point cursorPos;
-	byte cursorColor = 254;
-	bool solved = false;
-	bool done = false;
-	bool flag = false;
-	size_t i = 0;
-
-	switch (getLanguage()) {
-	case Common::FR_FRA:
-		lines[0] = Common::Point(34, 210);
-		lines[1] = Common::Point(72, 242);
-		lines[2] = Common::Point(34, 276);
-		numWide = 8;
-		spacing = 19;
-		paper = new ImageFile("paperf.vgs");
-		break;
-
-	case Common::DE_DEU:
-		lines[0] = Common::Point(44, 73);
-		lines[1] = Common::Point(56, 169);
-		lines[2] = Common::Point(47, 256);
-		numWide = 7;
-		spacing = 19;
-		paper = new ImageFile("paperg.vgs");
-		break;
-
-	default:
-		// English
-		lines[0] = Common::Point(65, 84);
-		lines[1] = Common::Point(65, 159);
-		lines[2] = Common::Point(75, 234);
-		numWide = 5;
-		spacing = 20;
-		paper = new ImageFile("paper.vgs");
-		break;
-	}
-	
-	ImageFrame &paperFrame = (*paper)[0];
-	Common::Rect paperBounds(paperFrame._width, paperFrame._height);
-	paperBounds.moveTo((_screen->w() - paperFrame._width) / 2, (_screen->h() - paperFrame._height) / 2);
-
-	for (int line = 0; line<3; ++line) {
-		lines[line].x += paperBounds.left;
-		lines[line].y += paperBounds.top;
-
-		for (i = 0; i <= (size_t)numWide; ++i)
-			answers[line][i] = 0;
-	}
-
-	_screen->_backBuffer1.blitFrom(paperFrame, Common::Point(paperBounds.left + _screen->_currentScroll.x, 0));
-
-	// If they have already solved the puzzle, put the answer on the graphic
-	if (readFlags(299)) {
-		for (int line = 0; line < 3; ++line) {
-			cursorPos.y = lines[line].y - _screen->fontHeight() - 2;
-
-			for (i = 0; i < strlen(solutions[line]); ++i) {
-				cursorPos.x = lines[line].x + 8 - _screen->widestChar() / 2 + i * spacing;
-				_screen->gPrint(Common::Point(cursorPos.x + _screen->widestChar() / 2 - 
-					_screen->charWidth(solutions[line][i]) / 2, cursorPos.y), 0, "%c", solutions[line][i]);
-			}
-		}
-	}
-
-	_screen->slamRect(paperBounds);
-	cursorPos = Common::Point(lines[0].x + 8 - _screen->widestChar() / 2, lines[0].y - _screen->fontHeight() - 2);
-	int line = 0;
-
-	// If they have not solved the puzzle, let them solve it here
-	if (!readFlags(299)) {
-		do {
-			while (!_events->kbHit()) {
-				// See if a key or a mouse button is pressed
-				_events->pollEventsAndWait();
-				_events->setButtonState();
-
-				flag = !flag;
-				if (flag) {
-					_screen->_backBuffer1.fillRect(Common::Rect(cursorPos.x + _screen->_currentScroll.x, cursorPos.y, 
-						cursorPos.x + _screen->widestChar() + _screen->_currentScroll.x - 1, cursorPos.y + _screen->fontHeight() - 1), cursorColor);
-					if (answers[line][i])
-						_screen->gPrint(Common::Point(cursorPos.x + _screen->widestChar() / 2 - _screen->charWidth(answers[line][i]) / 2, 
-							cursorPos.y), 0, "%c", answers[line][i]);
-					_screen->slamArea(cursorPos.x, cursorPos.y, _screen->widestChar(), _screen->fontHeight());
-				} else {
-					_screen->setDisplayBounds(Common::Rect(cursorPos.x + _screen->_currentScroll.x, cursorPos.y, 
-						cursorPos.x + _screen->widestChar() + _screen->_currentScroll.x, cursorPos.y + _screen->fontHeight()));
-					_screen->_backBuffer->blitFrom(paperFrame, Common::Point(paperBounds.left + _screen->_currentScroll.x, paperBounds.top));
-					_screen->resetDisplayBounds();
-
-					if (answers[line][i])
-						_screen->gPrint(Common::Point(cursorPos.x + _screen->widestChar() / 2 - _screen->charWidth(answers[line][i]) / 2, 
-							cursorPos.y), 0, "%c", answers[line][i]);
-					_screen->slamArea(cursorPos.x, cursorPos.y, _screen->widestChar(), _screen->fontHeight());
-				}
-
-				if (!_events->kbHit())
-					_events->wait(2);
-			}
-
-			if (_events->kbHit()) {
-				Common::KeyState keyState = _events->getKey();
-
-				if (((toupper(keyState.ascii) >= 'A') && (toupper(keyState.ascii) <= 'Z')) ||
-					((keyState.ascii >= 128) && ((keyState.ascii <= 168) || (keyState.ascii == 225)))) {
-					answers[line][i] = keyState.ascii;
-					keyState.keycode = Common::KEYCODE_RIGHT;
-				}
-
-				_screen->setDisplayBounds(Common::Rect(cursorPos.x + _screen->_currentScroll.x, cursorPos.y, 
-					cursorPos.x + _screen->widestChar() + _screen->_currentScroll.x, cursorPos.y + _screen->fontHeight()));
-				_screen->_backBuffer->blitFrom(paperFrame, Common::Point(paperBounds.left + _screen->_currentScroll.x, paperBounds.top));
-				_screen->resetDisplayBounds();
-
-				if (answers[line][i])
-					_screen->gPrint(Common::Point(cursorPos.x + _screen->widestChar() / 2 - _screen->charWidth(answers[line][i]) / 2,
-						cursorPos.y), 0, "%c", answers[line][i]);
-				_screen->slamArea(cursorPos.x, cursorPos.y, _screen->widestChar(), _screen->fontHeight());
-
-				switch (keyState.keycode) {
-				case Common::KEYCODE_ESCAPE:
-					done = true;
-					break;
-
-				case Common::KEYCODE_UP:
-				case Common::KEYCODE_KP8:
-					if (line) {
-						line--;
-						if (i >= strlen(solutions[line]))
-							i = strlen(solutions[line]) - 1;
-					}
-					break;
-
-				case Common::KEYCODE_DOWN:
-				case Common::KEYCODE_KP2:
-					if (line < 2) {
-						++line;
-						if (i >= strlen(solutions[line]))
-							i = strlen(solutions[line]) - 1;
-					}
-					break;
-
-				case Common::KEYCODE_BACKSPACE:
-				case Common::KEYCODE_LEFT:
-				case Common::KEYCODE_KP4:
-					if (i)
-						--i;
-					else if (line) {
-						--line;
-						
-						i = strlen(solutions[line]) - 1;
-					}
-
-					if (keyState.keycode == Common::KEYCODE_BACKSPACE)
-						answers[line][i] = ' ';
-					break;
-
-				case Common::KEYCODE_RIGHT:
-				case Common::KEYCODE_KP6:
-					if (i < strlen(solutions[line]) - 1)
-						i++;
-					else if (line < 2) {
-						++line;
-						i = 0;
-					}
-					break;
-
-				case Common::KEYCODE_DELETE:
-					answers[line][i] = ' ';
-					break;
-
-				default:
-					break;
-				}
-			}
-
-			cursorPos.x = lines[line].x + 8 - _screen->widestChar() / 2 + i * spacing;
-			cursorPos.y = lines[line].y - _screen->fontHeight() - 2;
-
-			// See if all of their anwers are correct
-			if (!scumm_stricmp(answers[0], solutions[0]) && !scumm_stricmp(answers[1], solutions[1]) && 
-					!scumm_stricmp(answers[2], solutions[2])) {
-				done = true;
-				solved = true;
-			}
-		} while (!done && !shouldQuit());
-	} else {
-		// They have already solved the puzzle, so just display the solution and wait for a mouse or key click
-		do {
-			_events->pollEventsAndWait();
-			_events->setButtonState();
-
-			if ((_events->kbHit()) || (_events->_released) || (_events->_rightReleased)) {
-				done = true;
-				_events->clearEvents();
-			}
-		} while (!done && !shouldQuit());
-	}
-
-	delete paper;
-	_screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(paperBounds.left + _screen->_currentScroll.x, paperBounds.top),
-		Common::Rect(paperBounds.left + _screen->_currentScroll.x, paperBounds.top,
-		paperBounds.right + _screen->_currentScroll.x, paperBounds.bottom));
-	_scene->doBgAnim();
-
-	_screen->slamArea(paperBounds.left + _screen->_currentScroll.x, paperBounds.top,
-		paperBounds.width(), paperBounds.height());
-
-	// Don't call the talk files if the puzzle has already been solved
-	if (readFlags(299))
-		return;
-
-	// If they solved the puzzle correctly, set the solved flag and run the appropriate talk scripts
-	if (solved) {
-		_talk->talkTo("SLVE12S.TLK");
-		_talk->talkTo("WATS12X.TLK");
-		setFlags(299);
-	} else {
-		_talk->talkTo("HOLM12X.TLK");
-	}
+	_hangmanWidget.show();
 }
 
 } // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h
index a9798dc..774e243 100644
--- a/engines/sherlock/tattoo/tattoo.h
+++ b/engines/sherlock/tattoo/tattoo.h
@@ -25,6 +25,7 @@
 
 #include "sherlock/sherlock.h"
 #include "sherlock/tattoo/tattoo_darts.h"
+#include "sherlock/tattoo/widget_hangman.h"
 
 namespace Sherlock {
 
@@ -51,21 +52,10 @@ enum {
 	FLAG_ALT_MAP_MUSIC		= 525
 };
 
-struct CreditLine {
-	Common::Point _position;
-	int _xOffset;
-	int _width;
-	Common::String _line, _line2;
-
-	CreditLine(const Common::String &line, const Common::Point &pt, int width) :
-		_line(line), _position(pt), _width(width), _xOffset(0) {}
-};
-
 class TattooEngine : public SherlockEngine {
 private:
 	Darts _darts;
-	Common::Array<CreditLine> _creditLines;
-	int _creditSpeed;
+	WidgetHangman _hangmanWidget;
 
 	/**
 	 * Loads the initial palette for the game
@@ -89,7 +79,6 @@ protected:
 	 */
 	virtual void startScene();
 public:
-	bool _creditsActive;
 	bool _runningProlog;
 	bool _fastMode, _allowFastMode;
 	bool _transparentMenus;
@@ -97,26 +86,6 @@ public:
 	TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
 	virtual ~TattooEngine();
 
-	/**
-	 * Initialize and load credit data for display
-	 */
-	void initCredits();
-
-	/**
-	 * Draw credits on the screen
-	 */
-	void drawCredits();
-
-	/**
-	 * Blit the drawn credits to the screen
-	 */
-	void blitCredits();
-
-	/**
-	 * Erase any area of the screen covered by credits
-	 */
-	void eraseCredits();
-
 	void doHangManPuzzle();
 };
 
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index ba462ca..9b5c5b2 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -350,8 +350,8 @@ void TattooScene::doBgAnim() {
 
 	ui.drawInterface();
 
-	if (vm._creditsActive)
-		vm.blitCredits();
+	if (ui._creditsWidget.active())
+		ui._creditsWidget.blitCredits();
 
 	if (!vm._fastMode)
 		events.wait(3);
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index ae09ba5..731c215 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -31,7 +31,7 @@ namespace Tattoo {
 
 TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm),
 		_inventoryWidget(vm), _messageWidget(vm), _textWidget(vm), _tooltipWidget(vm), _verbsWidget(vm),
-		_labWidget(vm) {
+		_labWidget(vm), _creditsWidget(vm) {
 	Common::fill(&_lookupTable[0], &_lookupTable[PALETTE_COUNT], 0);
 	Common::fill(&_lookupTable1[0], &_lookupTable1[PALETTE_COUNT], 0);
 	_scrollSize = 0;
@@ -239,8 +239,8 @@ void TattooUserInterface::handleInput() {
 	_keyState.keycode = Common::KEYCODE_INVALID;
 
 	// Check for credits starting
-	if (_vm->readFlags(3000) && !vm._creditsActive)
-		vm.initCredits();
+	if (_vm->readFlags(3000) && !_creditsWidget.active())
+		_creditsWidget.initCredits();
 
 	// Check the mouse positioning
 	if (events.isCursorVisible())
@@ -294,15 +294,14 @@ void TattooUserInterface::handleInput() {
 
 void TattooUserInterface::drawInterface(int bufferNum) {
 	Screen &screen = *_vm->_screen;
-	TattooEngine &vm = *(TattooEngine *)_vm;
 
 	// Draw any active on-screen widgets
 	for (Common::List<WidgetBase *>::iterator i = _widgets.begin(); i != _widgets.end(); ++i)
 		(*i)->draw();
 
 	// Handle drawing credits
-	if (vm._creditsActive)
-		vm.drawCredits();
+	if (_creditsWidget.active())
+		_creditsWidget.drawCredits();
 
 	// Bring the widgets to the screen
 	if (_mask != nullptr)
@@ -649,7 +648,6 @@ void TattooUserInterface::setupBGArea(const byte cMap[PALETTE_SIZE]) {
 }
 
 void TattooUserInterface::doBgAnimEraseBackground() {
-	TattooEngine &vm = *((TattooEngine *)_vm);
 	People &people = *_vm->_people;
 	Scene &scene = *_vm->_scene;
 	Screen &screen = *_vm->_screen;
@@ -714,8 +712,8 @@ void TattooUserInterface::doBgAnimEraseBackground() {
 		}
 
 		// If credits are active, erase the area they cover
-		if (vm._creditsActive)
-			vm.eraseCredits();
+		if (_creditsWidget.active())
+			_creditsWidget.eraseCredits();
 	}
 
 	for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h
index 1cefec6..b16f911 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.h
+++ b/engines/sherlock/tattoo/tattoo_user_interface.h
@@ -28,6 +28,7 @@
 #include "sherlock/saveload.h"
 #include "sherlock/screen.h"
 #include "sherlock/user_interface.h"
+#include "sherlock/tattoo/widget_credits.h"
 #include "sherlock/tattoo/widget_inventory.h"
 #include "sherlock/tattoo/widget_lab.h"
 #include "sherlock/tattoo/widget_text.h"
@@ -106,10 +107,11 @@ public:
 	Common::Point _maskOffset;
 	int _maskCounter;
 	ImageFile *_interfaceImages;
-	WidgetText _textWidget;
+	WidgetCredits _creditsWidget;
 	WidgetLab _labWidget;
-	WidgetVerbs _verbsWidget;
+	WidgetText _textWidget;
 	WidgetSceneTooltip _tooltipWidget;
+	WidgetVerbs _verbsWidget;
 public:
 	TattooUserInterface(SherlockEngine *vm);
 	virtual ~TattooUserInterface();
diff --git a/engines/sherlock/tattoo/widget_credits.cpp b/engines/sherlock/tattoo/widget_credits.cpp
new file mode 100644
index 0000000..dcb73b5
--- /dev/null
+++ b/engines/sherlock/tattoo/widget_credits.cpp
@@ -0,0 +1,210 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "sherlock/tattoo/widget_credits.h"
+#include "sherlock/tattoo/tattoo.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+WidgetCredits::WidgetCredits(SherlockEngine *vm) : _vm(vm) {
+	_creditSpeed = 4;
+	_creditsActive = false;
+}
+
+void WidgetCredits::initCredits() {
+	Resources &res = *_vm->_res;
+	Screen &screen = *_vm->_screen;
+	Common::SeekableReadStream *stream = res.load("credits.txt");
+	int spacing = screen.fontHeight() * 2;
+	int yp = screen.h();
+
+	_creditsActive = true;
+	_creditLines.clear();
+
+	while (stream->pos() < stream->size()) {
+		Common::String line = stream->readLine();
+
+		if (line.hasPrefix("Scroll Speed")) {
+			const char *p = line.c_str() + 12;
+			while ((*p < '0') || (*p > '9'))
+				p++;
+			
+			_creditSpeed = atoi(p);
+		} else if (line.hasPrefix("Y Spacing")) {
+			const char *p = line.c_str() + 12;
+			while ((*p < '0') || (*p > '9'))
+				p++;
+
+			spacing = atoi(p) + screen.fontHeight() + 1;
+		} else {
+			int width = screen.stringWidth(line) + 2;
+
+			_creditLines.push_back(CreditLine(line, Common::Point((screen.w() - width) / 2 + 1, yp), width));
+			yp += spacing;
+		}
+	}
+
+	// Post-processing for finding split lines
+	for (int l = 0; l < (int)_creditLines.size(); ++l) {
+		CreditLine &cl = _creditLines[l];
+		const char *p = strchr(cl._line.c_str(), '-');
+
+		if (p != nullptr && p[1] == '>') {
+			cl._line2 = Common::String(p + 3);
+			cl._line = Common::String(cl._line.c_str(), p);
+			
+			int width = cl._width;
+			int width1 = screen.stringWidth(cl._line);
+			int width2 = screen.stringWidth(cl._line2);
+
+			int c = 1;
+			for (int l1 = l + 1; l1 < (int)_creditLines.size(); ++l1) {
+				if ((p = strchr(_creditLines[l1]._line.c_str(), '-')) != nullptr) {
+					if (p[1] == '>') {
+						Common::String line1 = Common::String(_creditLines[l1]._line.c_str(), p);
+						Common::String line2 = Common::String(p + 3);
+
+						width1 = MAX(width1, screen.stringWidth(line1));
+
+						if (screen.stringWidth(line2) > width2)
+							width2 = screen.stringWidth(line2);
+						++c;
+					} else {
+						break;
+					}
+				} else {
+					break;
+				}
+			}
+
+			width = width1 + width2 + screen.widestChar();
+			width1 += screen.widestChar();
+
+			for (int l1 = l; l1 < l + c; ++l1) {
+				_creditLines[l1]._width = width;
+				_creditLines[l1]._xOffset = width1;
+			}
+
+			l += c - 1;
+		}
+	}
+
+	delete stream;
+}
+
+void WidgetCredits::drawCredits() {
+	Screen &screen = *_vm->_screen;
+	Common::Rect screenRect(0, 0, screen.w(), screen.h());
+	Surface &bb1 = screen._backBuffer1;
+
+	for (uint idx = 0; idx < _creditLines.size() && _creditLines[idx]._position.y < screen.h(); ++idx) {
+		if (screenRect.contains(_creditLines[idx]._position)) {
+			if (!_creditLines[idx]._line2.empty()) {
+				int x1 = _creditLines[idx]._position.x;
+				int x2 = x1 + _creditLines[idx]._xOffset;
+				const Common::String &line1 = _creditLines[idx]._line;
+				const Common::String &line2 = _creditLines[idx]._line2;
+
+				bb1.writeString(line1, Common::Point(x1 - 1, _creditLines[idx]._position.y - 1), 0);
+				bb1.writeString(line1, Common::Point(x1, _creditLines[idx]._position.y - 1), 0);
+				bb1.writeString(line1, Common::Point(x1 + 1, _creditLines[idx]._position.y - 1), 0);
+
+				bb1.writeString(line1, Common::Point(x1 - 1, _creditLines[idx]._position.y), 0);
+				bb1.writeString(line1, Common::Point(x1 + 1, _creditLines[idx]._position.y), 0);
+
+				bb1.writeString(line1, Common::Point(x1 - 1, _creditLines[idx]._position.y + 1), 0);
+				bb1.writeString(line1, Common::Point(x1, _creditLines[idx]._position.y + 1), 0);
+				bb1.writeString(line1, Common::Point(x1 + 1, _creditLines[idx]._position.y + 1), 0);
+
+				bb1.writeString(line1, Common::Point(x1, _creditLines[idx]._position.y), INFO_TOP);
+
+				bb1.writeString(line2, Common::Point(x2 - 1, _creditLines[idx]._position.y - 1), 0);
+				bb1.writeString(line2, Common::Point(x2, _creditLines[idx]._position.y - 1), 0);
+				bb1.writeString(line2, Common::Point(x2 + 1, _creditLines[idx]._position.y - 1), 0);
+
+				bb1.writeString(line2, Common::Point(x2 - 1, _creditLines[idx]._position.y), 0);
+				bb1.writeString(line2, Common::Point(x2 + 1, _creditLines[idx]._position.y), 0);
+
+				bb1.writeString(line2, Common::Point(x2 - 1, _creditLines[idx]._position.y + 1), 0);
+				bb1.writeString(line2, Common::Point(x2, _creditLines[idx]._position.y + 1), 0);
+				bb1.writeString(line2, Common::Point(x2 + 1, _creditLines[idx]._position.y + 1), 0);
+
+				bb1.writeString(line2, Common::Point(x2, _creditLines[idx]._position.y), INFO_TOP);
+			} else {
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x - 1, _creditLines[idx]._position.y - 1), 0);
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x, _creditLines[idx]._position.y - 1), 0);
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x + 1, _creditLines[idx]._position.y - 1), 0);
+
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x - 1, _creditLines[idx]._position.y), 0);
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x + 1, _creditLines[idx]._position.y), 0);
+
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x - 1, _creditLines[idx]._position.y + 1), 0);
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x, _creditLines[idx]._position.y + 1), 0);
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x + 1, _creditLines[idx]._position.y + 1), 0);
+
+				bb1.writeString(_creditLines[idx]._line, Common::Point(_creditLines[idx]._position.x, _creditLines[idx]._position.y), INFO_TOP);
+			}
+		}
+	}
+}
+
+void WidgetCredits::blitCredits() {
+	Screen &screen = *_vm->_screen;
+	Common::Rect screenRect(0, -_creditSpeed, screen.w(), screen.h() + _creditSpeed);
+
+	for (uint idx = 0; idx < _creditLines.size(); ++idx) {
+		if (screenRect.contains(_creditLines[idx]._position)) {
+			Common::Rect r(_creditLines[idx]._width, screen.fontHeight() + 2);
+			r.moveTo(_creditLines[idx]._position.x, _creditLines[idx]._position.y - 1);
+
+			screen.slamRect(r);
+		}
+
+		_creditLines[idx]._position.y -= _creditSpeed;
+	}
+}
+
+void WidgetCredits::eraseCredits() {
+	Screen &screen = *_vm->_screen;
+	Common::Rect screenRect(0, -_creditSpeed, screen.w(), screen.h() + _creditSpeed);
+
+	for (uint idx = 0; idx < _creditLines.size(); ++idx) {
+		if (screenRect.contains(_creditLines[idx]._position)) {
+			Common::Rect r(_creditLines[idx]._width, screen.fontHeight() + 3);
+			r.moveTo(_creditLines[idx]._position.x, _creditLines[idx]._position.y - 1 + _creditSpeed);
+
+			screen.restoreBackground(r);
+		}
+	}
+
+	if (_creditLines[_creditLines.size() - 1]._position.y < -_creditSpeed) {
+		_creditLines.clear();
+		_creditsActive = false;
+		_vm->setFlags(!3000);
+	}
+}
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/widget_credits.h b/engines/sherlock/tattoo/widget_credits.h
new file mode 100644
index 0000000..5c05049
--- /dev/null
+++ b/engines/sherlock/tattoo/widget_credits.h
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SHERLOCK_TATTOO_CREDITS_H
+#define SHERLOCK_TATTOO_CREDITS_H
+
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace Sherlock {
+
+	class SherlockEngine;
+
+namespace Tattoo {
+
+struct CreditLine {
+	Common::Point _position;
+	int _xOffset;
+	int _width;
+	Common::String _line, _line2;
+
+	CreditLine(const Common::String &line, const Common::Point &pt, int width) :
+		_line(line), _position(pt), _width(width), _xOffset(0) {}
+};
+
+class WidgetCredits {
+private:
+	SherlockEngine *_vm;
+	Common::Array<CreditLine> _creditLines;
+	int _creditSpeed;
+	bool _creditsActive;
+public:
+	WidgetCredits(SherlockEngine *vm);
+
+	/**
+	 * Returns true if the credits are active
+	 */
+	bool active() const { return _creditsActive; }
+
+	/**
+	 * Initialize and load credit data for display
+	 */
+	void initCredits();
+
+	/**
+	 * Draw credits on the screen
+	 */
+	void drawCredits();
+
+	/**
+	 * Blit the drawn credits to the screen
+	 */
+	void blitCredits();
+
+	/**
+	 * Erase any area of the screen covered by credits
+	 */
+	void eraseCredits();
+};
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/tattoo/widget_hangman.cpp b/engines/sherlock/tattoo/widget_hangman.cpp
new file mode 100644
index 0000000..84cfb02
--- /dev/null
+++ b/engines/sherlock/tattoo/widget_hangman.cpp
@@ -0,0 +1,264 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "sherlock/tattoo/widget_hangman.h"
+#include "sherlock/tattoo/tattoo.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+void WidgetHangman::show() {
+	Events &events = *_vm->_events;
+	Scene &scene = *_vm->_scene;
+	Screen &screen = *_vm->_screen;
+	Talk &talk = *_vm->_talk;
+	char answers[3][10];
+	Common::Point lines[3];
+	const char *solutions[3];
+	int numWide, spacing;
+	ImageFile *paper;
+	Common::Point cursorPos;
+	byte cursorColor = 254;
+	bool solved = false;
+	bool done = false;
+	bool flag = false;
+	size_t i = 0;
+
+	switch (_vm->getLanguage()) {
+	case Common::FR_FRA:
+		lines[0] = Common::Point(34, 210);
+		lines[1] = Common::Point(72, 242);
+		lines[2] = Common::Point(34, 276);
+		numWide = 8;
+		spacing = 19;
+		paper = new ImageFile("paperf.vgs");
+		break;
+
+	case Common::DE_DEU:
+		lines[0] = Common::Point(44, 73);
+		lines[1] = Common::Point(56, 169);
+		lines[2] = Common::Point(47, 256);
+		numWide = 7;
+		spacing = 19;
+		paper = new ImageFile("paperg.vgs");
+		break;
+
+	default:
+		// English
+		lines[0] = Common::Point(65, 84);
+		lines[1] = Common::Point(65, 159);
+		lines[2] = Common::Point(75, 234);
+		numWide = 5;
+		spacing = 20;
+		paper = new ImageFile("paper.vgs");
+		break;
+	}
+	
+	ImageFrame &paperFrame = (*paper)[0];
+	Common::Rect paperBounds(paperFrame._width, paperFrame._height);
+	paperBounds.moveTo((screen.w() - paperFrame._width) / 2, (screen.h() - paperFrame._height) / 2);
+
+	for (int line = 0; line<3; ++line) {
+		lines[line].x += paperBounds.left;
+		lines[line].y += paperBounds.top;
+
+		for (i = 0; i <= (size_t)numWide; ++i)
+			answers[line][i] = 0;
+	}
+
+	screen._backBuffer1.blitFrom(paperFrame, Common::Point(paperBounds.left + screen._currentScroll.x, 0));
+
+	// If they have already solved the puzzle, put the answer on the graphic
+	if (_vm->readFlags(299)) {
+		for (int line = 0; line < 3; ++line) {
+			cursorPos.y = lines[line].y - screen.fontHeight() - 2;
+
+			for (i = 0; i < strlen(solutions[line]); ++i) {
+				cursorPos.x = lines[line].x + 8 - screen.widestChar() / 2 + i * spacing;
+				screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - 
+					screen.charWidth(solutions[line][i]) / 2, cursorPos.y), 0, "%c", solutions[line][i]);
+			}
+		}
+	}
+
+	screen.slamRect(paperBounds);
+	cursorPos = Common::Point(lines[0].x + 8 - screen.widestChar() / 2, lines[0].y - screen.fontHeight() - 2);
+	int line = 0;
+
+	// If they have not solved the puzzle, let them solve it here
+	if (!_vm->readFlags(299)) {
+		do {
+			while (!events.kbHit()) {
+				// See if a key or a mouse button is pressed
+				events.pollEventsAndWait();
+				events.setButtonState();
+
+				flag = !flag;
+				if (flag) {
+					screen._backBuffer1.fillRect(Common::Rect(cursorPos.x + screen._currentScroll.x, cursorPos.y, 
+						cursorPos.x + screen.widestChar() + screen._currentScroll.x - 1, cursorPos.y + screen.fontHeight() - 1), cursorColor);
+					if (answers[line][i])
+						screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - screen.charWidth(answers[line][i]) / 2, 
+							cursorPos.y), 0, "%c", answers[line][i]);
+					screen.slamArea(cursorPos.x, cursorPos.y, screen.widestChar(), screen.fontHeight());
+				} else {
+					screen.setDisplayBounds(Common::Rect(cursorPos.x + screen._currentScroll.x, cursorPos.y, 
+						cursorPos.x + screen.widestChar() + screen._currentScroll.x, cursorPos.y + screen.fontHeight()));
+					screen._backBuffer->blitFrom(paperFrame, Common::Point(paperBounds.left + screen._currentScroll.x, paperBounds.top));
+					screen.resetDisplayBounds();
+
+					if (answers[line][i])
+						screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - screen.charWidth(answers[line][i]) / 2, 
+							cursorPos.y), 0, "%c", answers[line][i]);
+					screen.slamArea(cursorPos.x, cursorPos.y, screen.widestChar(), screen.fontHeight());
+				}
+
+				if (!events.kbHit())
+					events.wait(2);
+			}
+
+			if (events.kbHit()) {
+				Common::KeyState keyState = events.getKey();
+
+				if (((toupper(keyState.ascii) >= 'A') && (toupper(keyState.ascii) <= 'Z')) ||
+					((keyState.ascii >= 128) && ((keyState.ascii <= 168) || (keyState.ascii == 225)))) {
+					answers[line][i] = keyState.ascii;
+					keyState.keycode = Common::KEYCODE_RIGHT;
+				}
+
+				screen.setDisplayBounds(Common::Rect(cursorPos.x + screen._currentScroll.x, cursorPos.y, 
+					cursorPos.x + screen.widestChar() + screen._currentScroll.x, cursorPos.y + screen.fontHeight()));
+				screen._backBuffer->blitFrom(paperFrame, Common::Point(paperBounds.left + screen._currentScroll.x, paperBounds.top));
+				screen.resetDisplayBounds();
+
+				if (answers[line][i])
+					screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - screen.charWidth(answers[line][i]) / 2,
+						cursorPos.y), 0, "%c", answers[line][i]);
+				screen.slamArea(cursorPos.x, cursorPos.y, screen.widestChar(), screen.fontHeight());
+
+				switch (keyState.keycode) {
+				case Common::KEYCODE_ESCAPE:
+					done = true;
+					break;
+
+				case Common::KEYCODE_UP:
+				case Common::KEYCODE_KP8:
+					if (line) {
+						line--;
+						if (i >= strlen(solutions[line]))
+							i = strlen(solutions[line]) - 1;
+					}
+					break;
+
+				case Common::KEYCODE_DOWN:
+				case Common::KEYCODE_KP2:
+					if (line < 2) {
+						++line;
+						if (i >= strlen(solutions[line]))
+							i = strlen(solutions[line]) - 1;
+					}
+					break;
+
+				case Common::KEYCODE_BACKSPACE:
+				case Common::KEYCODE_LEFT:
+				case Common::KEYCODE_KP4:
+					if (i)
+						--i;
+					else if (line) {
+						--line;
+						
+						i = strlen(solutions[line]) - 1;
+					}
+
+					if (keyState.keycode == Common::KEYCODE_BACKSPACE)
+						answers[line][i] = ' ';
+					break;
+
+				case Common::KEYCODE_RIGHT:
+				case Common::KEYCODE_KP6:
+					if (i < strlen(solutions[line]) - 1)
+						i++;
+					else if (line < 2) {
+						++line;
+						i = 0;
+					}
+					break;
+
+				case Common::KEYCODE_DELETE:
+					answers[line][i] = ' ';
+					break;
+
+				default:
+					break;
+				}
+			}
+
+			cursorPos.x = lines[line].x + 8 - screen.widestChar() / 2 + i * spacing;
+			cursorPos.y = lines[line].y - screen.fontHeight() - 2;
+
+			// See if all of their anwers are correct
+			if (!scumm_stricmp(answers[0], solutions[0]) && !scumm_stricmp(answers[1], solutions[1]) && 
+					!scumm_stricmp(answers[2], solutions[2])) {
+				done = true;
+				solved = true;
+			}
+		} while (!done && !_vm->shouldQuit());
+	} else {
+		// They have already solved the puzzle, so just display the solution and wait for a mouse or key click
+		do {
+			events.pollEventsAndWait();
+			events.setButtonState();
+
+			if ((events.kbHit()) || (events._released) || (events._rightReleased)) {
+				done = true;
+				events.clearEvents();
+			}
+		} while (!done && !_vm->shouldQuit());
+	}
+
+	delete paper;
+	screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(paperBounds.left + screen._currentScroll.x, paperBounds.top),
+		Common::Rect(paperBounds.left + screen._currentScroll.x, paperBounds.top,
+		paperBounds.right + screen._currentScroll.x, paperBounds.bottom));
+	scene.doBgAnim();
+
+	screen.slamArea(paperBounds.left + screen._currentScroll.x, paperBounds.top,
+		paperBounds.width(), paperBounds.height());
+
+	// Don't call the talk files if the puzzle has already been solved
+	if (_vm->readFlags(299))
+		return;
+
+	// If they solved the puzzle correctly, set the solved flag and run the appropriate talk scripts
+	if (solved) {
+		talk.talkTo("SLVE12S.TLK");
+		talk.talkTo("WATS12X.TLK");
+		_vm->setFlags(299);
+	} else {
+		talk.talkTo("HOLM12X.TLK");
+	}
+}
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/widget_hangman.h b/engines/sherlock/tattoo/widget_hangman.h
new file mode 100644
index 0000000..daa5987
--- /dev/null
+++ b/engines/sherlock/tattoo/widget_hangman.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SHERLOCK_TATTOO_HANGMAN_H
+#define SHERLOCK_TATTOO_HANGMAN_H
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+class TattooEngine;
+
+class WidgetHangman {
+private:
+	TattooEngine *_vm;
+public:
+	WidgetHangman(TattooEngine *vm) : _vm(vm) {}
+
+	/**
+	 * Show the hangman puzzle
+	 */
+	void show();
+};
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
+
+#endif






More information about the Scummvm-git-logs mailing list