1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11 
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16 
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/events.h"
24 #include "common/stream.h"
25 #include "graphics/cursorman.h"
26 
27 #include "startrek/graphics.h"
28 
29 namespace StarTrek {
30 
getMenuButtonAt(Sprite * sprites,int numSprites,int x,int y)31 int StarTrekEngine::getMenuButtonAt(Sprite *sprites, int numSprites, int x, int y) {
32 	for (int i = 0; i < numSprites; i++) {
33 		const Sprite &spr = sprites[i];
34 
35 		if (spr.drawMode != 2)
36 			continue;
37 
38 		int left = spr.pos.x - spr.bitmap->xoffset;
39 		int top = spr.pos.y - spr.bitmap->yoffset;
40 
41 		// Oddly, this doesn't account for x/yoffset...
42 		int right = spr.pos.x + spr.bitmap->width - 1;
43 		int bottom = spr.pos.y + spr.bitmap->height - 1;
44 
45 		if (x >= left && x <= right && y >= top && y <= bottom)
46 			return i;
47 	}
48 
49 	return -1;
50 }
51 
chooseMousePositionFromSprites(Sprite * sprites,int numSprites,int containMouseSprite,int mode)52 void StarTrekEngine::chooseMousePositionFromSprites(Sprite *sprites, int numSprites, int containMouseSprite, int mode) {
53 	uint16 mouseX1 = 0x7fff; // Candidate positions to warp mouse to
54 	uint16 mouseY1 = 0x7fff;
55 	uint16 mouseX2 = 0x7fff;
56 	uint16 mouseY2 = 0x7fff;
57 
58 	Common::Point mousePos = _gfx->getMousePos();
59 
60 	// Ensure the cursor is contained within one of the sprites
61 	if (containMouseSprite >= 0 && containMouseSprite < numSprites) {
62 		Common::Rect rect = sprites[containMouseSprite].getRect();
63 
64 		if (mousePos.x < rect.left || mousePos.x >= rect.right
65 		        || mousePos.y < rect.top || mousePos.y >= rect.bottom) {
66 			mousePos.x = (rect.left + rect.right) / 2;
67 			mousePos.y = (rect.top + rect.bottom) / 2;
68 		}
69 	}
70 
71 	// Choose a sprite to warp the cursor to
72 	for (int i = 0; i < numSprites; i++) {
73 		Sprite *sprite = &sprites[i];
74 		if (sprite->drawMode != 2) // Skip hidden buttons
75 			continue;
76 
77 		Common::Rect rect = sprite->getRect();
78 
79 		int hCenter = (rect.left + rect.right) / 2;
80 		int vCenter = (rect.top + rect.bottom) / 2;
81 
82 		// Choose which sprite is closest based on certain criteria?
83 		switch (mode) {
84 		case 0: // Choose topmost, leftmost sprite that's below the cursor
85 			if (((vCenter == mousePos.y && hCenter > mousePos.x) || vCenter > mousePos.y)
86 			        && (vCenter < mouseY1 || (vCenter == mouseY1 && hCenter < mouseX1))) {
87 				mouseX1 = hCenter;
88 				mouseY1 = vCenter;
89 			}
90 		// fall through
91 
92 		case 4: // Choose topmost, leftmost sprite
93 			if (vCenter < mouseY2 || (vCenter == mouseY2 && hCenter < mouseX2)) {
94 				mouseX2 = hCenter;
95 				mouseY2 = vCenter;
96 			}
97 			break;
98 
99 		case 1: // Choose bottommost, rightmost sprite that's above the cursor
100 			if (((vCenter == mousePos.y && hCenter < mousePos.x) || vCenter < mousePos.y)
101 			        && (mouseY1 == 0x7fff || vCenter > mouseY1
102 			            || (vCenter == mouseY1 && hCenter > mouseX1))) {
103 				mouseX1 = hCenter;
104 				mouseY1 = vCenter;
105 			}
106 		// fall through
107 
108 		case 5: // Choose bottommost, rightmost sprite
109 			if (mouseY2 == 0x7fff || vCenter > mouseY2
110 			        || (vCenter == mouseY2 && hCenter > mouseX2)) {
111 				mouseX2 = hCenter;
112 				mouseY2 = vCenter;
113 			}
114 			break;
115 
116 		case 2:
117 			// This seems broken... OR condition on first line has no affect on the logic...
118 			if ((vCenter < mousePos.y || (vCenter == mouseY1 && hCenter == mousePos.x))
119 			        && (mouseX1 == 0x7fff || vCenter >= mouseY1)) {
120 				mouseX1 = hCenter;
121 				mouseY1 = vCenter;
122 			}
123 			if (mouseX2 == 0x7fff || vCenter > mouseY2
124 			        || (hCenter == mouseX2 && vCenter == mouseY2)) {
125 				mouseX2 = hCenter;
126 				mouseY2 = vCenter;
127 			}
128 			break;
129 
130 		case 3:
131 			// Similar to above...
132 			if ((vCenter > mousePos.y || (vCenter == mouseY1 && hCenter == mousePos.x))
133 			        && (mouseX1 == 0x7fff || vCenter <= mouseY1)) {
134 				mouseX1 = hCenter;
135 				mouseY1 = vCenter;
136 			}
137 			if (mouseX2 == 0x7fff || vCenter < mouseY2
138 			        || (hCenter == mouseX2 && vCenter == mouseY2)) {
139 				mouseX2 = hCenter;
140 				mouseY2 = vCenter;
141 			}
142 			break;
143 		}
144 	}
145 
146 	// Warp mouse to one of the coordinates, if one is valid
147 	if (mouseX1 != 0x7fff) {
148 		mousePos.x = mouseX1;
149 		mousePos.y = mouseY1;
150 	} else if (mouseX2 != 0x7fff) {
151 		mousePos.x = mouseX2;
152 		mousePos.y = mouseY2;
153 	}
154 
155 	_gfx->warpMouse(mousePos.x, mousePos.y);
156 
157 }
158 
drawMenuButtonOutline(SharedPtr<Bitmap> bitmap,byte color)159 void StarTrekEngine::drawMenuButtonOutline(SharedPtr<Bitmap> bitmap, byte color) {
160 	int lineWidth = bitmap->width - 2;
161 	int offsetToBottom = (bitmap->height - 3) * bitmap->width;
162 
163 	byte *dest = bitmap->pixels + bitmap->width + 1;
164 
165 	while (lineWidth--) {
166 		*dest = color;
167 		*(dest + offsetToBottom) = color;
168 		dest++;
169 	}
170 
171 	int lineHeight = bitmap->height - 2;
172 	int offsetToRight = bitmap->width - 3;
173 
174 	dest = bitmap->pixels + bitmap->width + 1;
175 
176 	while (lineHeight--) {
177 		*dest = color;
178 		*(dest + offsetToRight) = color;
179 		dest += bitmap->width;
180 	}
181 }
182 
showOptionsMenu(int x,int y)183 void StarTrekEngine::showOptionsMenu(int x, int y) {
184 	bool tmpMouseControllingShip = _mouseControllingShip;
185 	_mouseControllingShip = false;
186 
187 	Common::Point oldMousePos = _gfx->getMousePos();
188 	SharedPtr<Bitmap> oldMouseBitmap = _gfx->getMouseBitmap();
189 
190 	_gfx->setMouseBitmap(_gfx->loadBitmap("options"));
191 	loadMenuButtons("options", x, y);
192 
193 	uint32 disabledButtons = 0;
194 	if (_musicWorking) {
195 		if (_musicEnabled)
196 			disabledButtons |= (1 << OPTIONBUTTON_ENABLEMUSIC);
197 		else
198 			disabledButtons |= (1 << OPTIONBUTTON_DISABLEMUSIC);
199 	} else
200 		disabledButtons |= (1 << OPTIONBUTTON_ENABLEMUSIC) | (1 << OPTIONBUTTON_DISABLEMUSIC);
201 
202 	if (_sfxWorking) {
203 		if (_sfxEnabled)
204 			disabledButtons |= (1 << OPTIONBUTTON_ENABLESFX);
205 		else
206 			disabledButtons |= (1 << OPTIONBUTTON_DISABLESFX);
207 	} else
208 		disabledButtons |= (1 << OPTIONBUTTON_ENABLESFX) | (1 << OPTIONBUTTON_DISABLESFX);
209 
210 	disableMenuButtons(disabledButtons);
211 	chooseMousePositionFromSprites(_activeMenu->sprites, _activeMenu->numButtons, -1, 4);
212 	int event = handleMenuEvents(0, false);
213 
214 	unloadMenuButtons();
215 	_mouseControllingShip = tmpMouseControllingShip;
216 	_gfx->setMouseBitmap(oldMouseBitmap);
217 
218 	if (event != MENUEVENT_LCLICK_OFFBUTTON && event != MENUEVENT_RCLICK_OFFBUTTON)
219 		_gfx->warpMouse(oldMousePos.x, oldMousePos.y);
220 
221 
222 	// Can't use OPTIONBUTTON constants since the button retvals differ from the button
223 	// indices...
224 	switch (event) {
225 	case 0: // Save
226 		showSaveMenu();
227 		break;
228 	case 1: // Load
229 		showLoadMenu();
230 		_resetGameMode = true;
231 		break;
232 	case 2: // Enable music
233 		_sound->setMusicEnabled(true);
234 		break;
235 	case 3: // Disable music
236 		_sound->setMusicEnabled(false);
237 		break;
238 	case 4: // Enable sfx
239 		_sound->setSfxEnabled(true);
240 		break;
241 	case 5: // Disable sfx
242 		_sound->setSfxEnabled(false);
243 		break;
244 	case 6: // Quit
245 		showQuitGamePrompt(20, 20);
246 		break;
247 	case 7: // Text
248 		showTextConfigurationMenu(true);
249 		break;
250 	default:
251 		break;
252 	}
253 }
254 
showActionMenu()255 int StarTrekEngine::showActionMenu() {
256 	const int actionMappingUp[] = { // Actions to jump to when up is pressed
257 		ACTION_TALK,    // <- ACTION_WALK
258 		ACTION_TALK,    // <- ACTION_USE
259 		ACTION_OPTIONS, // <- ACTION_GET
260 		ACTION_LOOK,    // <- ACTION_LOOK
261 		ACTION_LOOK,    // <- ACTION_TALK
262 		ACTION_OPTIONS  // <- ACTION_OPTIONS
263 	};
264 	const int actionMappingRight[] = { // Actions to jump to when right is pressed
265 		ACTION_GET,     // <- ACTION_WALK
266 		ACTION_WALK,    // <- ACTION_USE
267 		ACTION_GET,     // <- ACTION_GET
268 		ACTION_OPTIONS, // <- ACTION_LOOK
269 		ACTION_OPTIONS, // <- ACTION_TALK
270 		ACTION_OPTIONS  // <- ACTION_OPTIONS
271 	};
272 	const int actionMappingDown[] = { // Actions to jump to when down is pressed
273 		ACTION_GET,  // <- ACTION_WALK
274 		ACTION_WALK, // <- ACTION_USE
275 		ACTION_GET,  // <- ACTION_GET
276 		ACTION_TALK, // <- ACTION_LOOK
277 		ACTION_WALK, // <- ACTION_TALK
278 		ACTION_GET   // <- ACTION_OPTIONS
279 	};
280 	const int actionMappingLeft[] = { // Actions to jump to when left is pressed
281 		ACTION_USE,  // <- ACTION_WALK
282 		ACTION_USE,  // <- ACTION_USE
283 		ACTION_WALK, // <- ACTION_GET
284 		ACTION_USE,  // <- ACTION_LOOK
285 		ACTION_USE,  // <- ACTION_TALK
286 		ACTION_LOOK  // <- ACTION_OPTIONS
287 	};
288 
289 	const Common::Point pos(50, 50); // Top-left position to put action menu at
290 
291 	// Positions to put mouse cursor at to select actions (when using arrow keys)
292 	const Common::Point actionPositions[] = {
293 		Common::Point(7, 21),  // ACTION_USE
294 		Common::Point(48, 38), // ACTION_GET
295 		Common::Point(28, 5),  // ACTION_LOOK
296 		Common::Point(28, 14), // ACTION_TALK
297 		Common::Point(45, 9)   // ACTION_OPTIONS
298 	};
299 
300 	TrekEvent event;
301 	Sprite menuSprite;
302 
303 	bool keyboardControlledMouse = _keyboardControlsMouse;
304 	Common::Point oldMousePos = _gfx->getMousePos();
305 
306 	bool addEventBack = false;
307 	int action = ACTION_WALK;
308 
309 	menuSprite.bitmap = _gfx->loadBitmap("action");
310 	int menuWidth = menuSprite.bitmap->width;
311 	int menuHeight = menuSprite.bitmap->height;
312 
313 	_gfx->warpMouse(pos.x + menuWidth / 2, pos.y + menuHeight / 2);
314 
315 	_gfx->addSprite(&menuSprite);
316 	menuSprite.pos = pos;
317 	menuSprite.drawPriority = 15;
318 
319 	chooseMouseBitmapForAction(action, false);
320 
321 	_gfx->drawAllSprites();
322 
323 	menuSprite.drawPriority2 = 8;
324 	bool displayMenu = true;
325 
326 	while (displayMenu) {
327 		_sound->checkLoopMusic();
328 
329 		if (!popNextEvent(&event))
330 			continue;
331 
332 		switch (event.type) {
333 
334 		case TREKEVENT_TICK:
335 			_gfx->incPaletteFadeLevel();
336 			_gfx->drawAllSprites();
337 			break;
338 
339 		case TREKEVENT_LBUTTONDOWN:
340 			displayMenu = false;
341 			addEventBack = true;
342 			break;
343 
344 		case TREKEVENT_MOUSEMOVE:
345 mousePosChanged: {
346 				Common::Point mouse = _gfx->getMousePos();
347 				Common::Point relMouse(mouse.x - pos.x, mouse.y - pos.y);
348 
349 				Common::String bitmapName;
350 				Common::Point lockMousePoint(-1, -1);
351 
352 				// Check if the mouse is hovering over one of the selectable actions
353 				if (relMouse.x >= 39 && relMouse.x <= 50 && relMouse.y >= 2 && relMouse.y <= 17) {
354 					action = ACTION_OPTIONS;
355 					bitmapName = "options";
356 					lockMousePoint = Common::Point(pos.x + 44, pos.y + 2);
357 				} else if (relMouse.x >= 18 && relMouse.x <= 38 && relMouse.y >= 2 && relMouse.y <= 9) {
358 					action = ACTION_LOOK;
359 					bitmapName = "look";
360 					lockMousePoint = Common::Point(pos.x + 28, pos.y + 6);
361 				} else if (relMouse.x >= 18 && relMouse.x <= 38 && relMouse.y >= 11 && relMouse.y <= 17) {
362 					action = ACTION_TALK;
363 					bitmapName = "talk";
364 					lockMousePoint = Common::Point(pos.x + 27, pos.y + 14);
365 				} else if (relMouse.x >= 2 && relMouse.x <= 13 && relMouse.y >= 16 && relMouse.y <= 26) {
366 					action = ACTION_USE;
367 					bitmapName = "use";
368 					lockMousePoint = Common::Point(pos.x + 7, pos.y + 19);
369 				} else if (relMouse.x >= 40 && relMouse.x <= 53 && relMouse.y >= 34 && relMouse.y <= 43) {
370 					action = ACTION_GET;
371 					bitmapName = "get";
372 					lockMousePoint = Common::Point(pos.x + 44, pos.y + 38);
373 				} else {
374 					action = ACTION_WALK;
375 					bitmapName = "walk";
376 				}
377 
378 				_gfx->setMouseBitmap(_gfx->loadBitmap(bitmapName));
379 
380 				if (lockMousePoint.x != -1)
381 					_gfx->lockMousePosition(lockMousePoint.x, lockMousePoint.y);
382 				else
383 					_gfx->unlockMousePosition();
384 			}
385 			break;
386 
387 		case TREKEVENT_RBUTTONDOWN:
388 exitMenu:
389 			displayMenu = false;
390 			action = ACTION_WALK;
391 			break;
392 
393 		case TREKEVENT_KEYDOWN: {
394 			int nextAction = action;
395 			const int *lookupArray;
396 
397 			switch (event.kbd.keycode) {
398 			case Common::KEYCODE_ESCAPE:
399 			case Common::KEYCODE_SPACE:
400 			case Common::KEYCODE_F2: // Exit menu without selecting anything
401 				goto exitMenu;
402 
403 			case Common::KEYCODE_RETURN:
404 			case Common::KEYCODE_KP_ENTER:
405 			case Common::KEYCODE_F1: // Exit menu with whatever is selected
406 				displayMenu = false;
407 				addEventBack = true;
408 				break;
409 
410 			case Common::KEYCODE_PAGEUP:
411 			case Common::KEYCODE_KP9:
412 				nextAction = ACTION_OPTIONS;
413 				break;
414 
415 			case Common::KEYCODE_PAGEDOWN:
416 			case Common::KEYCODE_KP3:
417 				nextAction = ACTION_GET;
418 				break;
419 
420 			// Direction buttons
421 			case Common::KEYCODE_UP:
422 			case Common::KEYCODE_KP8:
423 				lookupArray = actionMappingUp;
424 				goto lookupNextAction;
425 
426 			case Common::KEYCODE_RIGHT:
427 			case Common::KEYCODE_KP6:
428 				lookupArray = actionMappingRight;
429 				goto lookupNextAction;
430 
431 			case Common::KEYCODE_DOWN:
432 			case Common::KEYCODE_KP2:
433 				lookupArray = actionMappingDown;
434 				goto lookupNextAction;
435 
436 			case Common::KEYCODE_LEFT:
437 			case Common::KEYCODE_KP4:
438 				lookupArray = actionMappingLeft;
439 				goto lookupNextAction;
440 
441 lookupNextAction:
442 				// Use a lookup table to decide which action is next after a direction
443 				// button is pressed.
444 				assert((action >= ACTION_WALK && action <= ACTION_TALK) || action == ACTION_OPTIONS);
445 				nextAction = lookupArray[action == ACTION_OPTIONS ? 5 : action - 1];
446 				break;
447 
448 			default:
449 				break;
450 			}
451 
452 			if (nextAction == action)
453 				break;
454 
455 			action = nextAction;
456 
457 			// Warp mouse to the position of the selected action
458 			if (nextAction == ACTION_WALK)
459 				_gfx->warpMouse(pos.x + menuWidth / 2, pos.y + menuHeight / 2);
460 			else {
461 				assert((action >= ACTION_WALK && action <= ACTION_TALK) || action == ACTION_OPTIONS);
462 				const Common::Point &p = actionPositions[action == ACTION_OPTIONS ? 4 : action - 2];
463 				_gfx->warpMouse(pos.x + p.x, pos.y + p.y);
464 			}
465 
466 			goto mousePosChanged;
467 		}
468 
469 		default:
470 			break;
471 		}
472 	}
473 
474 	playSoundEffectIndex(SND_SELECTION);
475 
476 	menuSprite.dontDrawNextFrame();
477 	_gfx->drawAllSprites();
478 	_gfx->delSprite(&menuSprite);
479 
480 	_gfx->unlockMousePosition();
481 
482 	if (action == ACTION_OPTIONS) {
483 		showOptionsMenu(50, 50);
484 		action = ACTION_WALK;
485 	}
486 
487 	Common::Point mouse = _gfx->getMousePos();
488 	if (mouse.x < pos.x || mouse.x >= pos.x + menuWidth || mouse.y < pos.y || mouse.y >= pos.y + menuHeight) {
489 		if (action == ACTION_WALK && addEventBack)
490 			addEventToQueue(event); // Add left-click event back to queue so Kirk can walk there
491 	} else
492 		_gfx->warpMouse(oldMousePos.x, oldMousePos.y);
493 
494 	chooseMouseBitmapForAction(action, false);
495 	_keyboardControlsMouse = keyboardControlledMouse;
496 	return action;
497 }
498 
loadMenuButtons(String mnuFilename,int xpos,int ypos)499 void StarTrekEngine::loadMenuButtons(String mnuFilename, int xpos, int ypos) {
500 	if (_activeMenu == nullptr)
501 		_keyboardControlsMouseOutsideMenu = _keyboardControlsMouse;
502 
503 	Menu *oldMenu = _activeMenu;
504 	_activeMenu = new Menu();
505 	_activeMenu->nextMenu = oldMenu;
506 
507 	Common::MemoryReadStreamEndian *stream = loadFile(mnuFilename + ".MNU");
508 
509 	_activeMenu->numButtons = stream->size() / 16;
510 
511 	for (int i = 0; i < _activeMenu->numButtons; i++) {
512 		_activeMenu->sprites[i] = Sprite();
513 		_gfx->addSprite(&_activeMenu->sprites[i]);
514 		_activeMenu->sprites[i].drawMode = 2;
515 
516 		char bitmapBasename[11];
517 		stream->seek(i * 16, SEEK_SET);
518 		stream->read(bitmapBasename, 10);
519 		for (int j = 0; j < 10; j++) {
520 			if (bitmapBasename[j] == ' ')
521 				bitmapBasename[j] = '\0';
522 		}
523 		bitmapBasename[10] = '\0';
524 
525 		_activeMenu->sprites[i].bitmap = _gfx->loadBitmap(bitmapBasename);
526 		_activeMenu->sprites[i].pos.x = stream->readUint16() + xpos;
527 		_activeMenu->sprites[i].pos.y = stream->readUint16() + ypos;
528 		_activeMenu->retvals[i] = stream->readUint16();
529 
530 		_activeMenu->sprites[i].drawPriority = 15;
531 		_activeMenu->sprites[i].drawPriority2 = 8;
532 	}
533 
534 	delete stream;
535 
536 	if (_activeMenu->retvals[_activeMenu->numButtons - 1] == 0) {
537 		// Set default retvals for buttons
538 		for (int i = 0; i < _activeMenu->numButtons; i++)
539 			_activeMenu->retvals[i] = i;
540 	}
541 
542 	_activeMenu->selectedButton = -1;
543 	_activeMenu->disabledButtons = 0;
544 	_keyboardControlsMouse = false;
545 }
546 
setVisibleMenuButtons(uint32 bits)547 void StarTrekEngine::setVisibleMenuButtons(uint32 bits) {
548 	for (int i = 0; i < _activeMenu->numButtons; i++) {
549 		Sprite *sprite = &_activeMenu->sprites[i];
550 		uint32 spriteBitmask = (1 << i);
551 		if (spriteBitmask == 0)
552 			break;
553 
554 		if ((bits & spriteBitmask) == 0 || sprite->drawMode != 0) {
555 			if ((bits & spriteBitmask) == 0 && sprite->drawMode == 2) {
556 				if (i == _activeMenu->selectedButton) {
557 					drawMenuButtonOutline(sprite->bitmap, 0x00);
558 					_activeMenu->selectedButton = -1;
559 				}
560 
561 				sprite->field16 = true;
562 				sprite->bitmapChanged = true;
563 			}
564 		} else {
565 			_gfx->addSprite(sprite);
566 			sprite->drawMode = 2;
567 			sprite->bitmapChanged = true;
568 		}
569 	}
570 
571 	_gfx->drawAllSprites();
572 
573 	for (int i = 0; i < _activeMenu->numButtons; i++) {
574 		Sprite *sprite = &_activeMenu->sprites[i];
575 		uint32 spriteBitmask = (1 << i);
576 		if (spriteBitmask == 0)
577 			break;
578 
579 		if ((bits & spriteBitmask) == 0 && sprite->drawMode == 2) {
580 			_gfx->delSprite(sprite);
581 
582 			// Setting drawMode to 0 is the game's way of saying that the menu button is
583 			// hidden (since it would normally be 2).
584 			sprite->drawMode = 0;
585 		}
586 	}
587 }
588 
disableMenuButtons(uint32 bits)589 void StarTrekEngine::disableMenuButtons(uint32 bits) {
590 	_activeMenu->disabledButtons |= bits;
591 	if (_activeMenu->selectedButton != -1
592 	        && (_activeMenu->disabledButtons & (1 << _activeMenu->selectedButton))) {
593 		Sprite *sprite = &_activeMenu->sprites[_activeMenu->selectedButton];
594 		drawMenuButtonOutline(sprite->bitmap, 0x00);
595 
596 		sprite->bitmapChanged = true;
597 		_activeMenu->selectedButton = -1;
598 	}
599 }
600 
enableMenuButtons(uint32 bits)601 void StarTrekEngine::enableMenuButtons(uint32 bits) {
602 	_activeMenu->disabledButtons &= ~bits;
603 }
604 
handleMenuEvents(uint32 ticksUntilClickingEnabled,bool inTextbox)605 int StarTrekEngine::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool inTextbox) {
606 	uint32 tickWhenClickingEnabled = _clockTicks + ticksUntilClickingEnabled;
607 
608 	while (true) {
609 		TrekEvent event;
610 		while (popNextEvent(&event)) {
611 			switch (event.type) {
612 
613 			case TREKEVENT_TICK: {
614 				Common::Point mousePos = _gfx->getMousePos();
615 				int buttonIndex = getMenuButtonAt(_activeMenu->sprites, _activeMenu->numButtons, mousePos.x, mousePos.y);
616 				if (buttonIndex != -1) {
617 					if (_activeMenu->disabledButtons & (1 << buttonIndex))
618 						buttonIndex = -1;
619 				}
620 
621 				if (buttonIndex != _activeMenu->selectedButton) {
622 					if (_activeMenu->selectedButton != -1) {
623 						Sprite &spr = _activeMenu->sprites[_activeMenu->selectedButton];
624 						drawMenuButtonOutline(spr.bitmap, 0x00);
625 						spr.bitmapChanged = true;
626 					}
627 					if (buttonIndex != -1) {
628 						Sprite &spr = _activeMenu->sprites[buttonIndex];
629 						drawMenuButtonOutline(spr.bitmap, 0xda);
630 						spr.bitmapChanged = true;
631 					}
632 					_activeMenu->selectedButton = buttonIndex;
633 				}
634 				// Not added: updating mouse position (scummvm handles that)
635 
636 				updateActorAnimations();
637 				renderBanBelowSprites();
638 				_gfx->drawAllSprites(false);
639 				renderBanAboveSprites();
640 				_gfx->updateScreen();
641 
642 				_sound->checkLoopMusic();
643 
644 				if (_finishedPlayingSpeech != 0) {
645 					_finishedPlayingSpeech = 0;
646 					if (_textDisplayMode != TEXTDISPLAY_WAIT) {
647 						return TEXTBUTTON_SPEECH_DONE;
648 					}
649 				}
650 				_gfx->incPaletteFadeLevel();
651 				_frameIndex++;
652 
653 				if (ticksUntilClickingEnabled != 0 && _clockTicks >= tickWhenClickingEnabled)
654 					return MENUEVENT_ENABLEINPUT;
655 				break;
656 			}
657 
658 			case TREKEVENT_LBUTTONDOWN:
659 lclick:
660 				if (_activeMenu->selectedButton != -1) {
661 					playSoundEffectIndex(SND_SELECTION);
662 					return _activeMenu->retvals[_activeMenu->selectedButton];
663 				} else {
664 					Common::Point mouse = _gfx->getMousePos();
665 					if (getMenuButtonAt(_activeMenu->sprites, _activeMenu->numButtons, mouse.x, mouse.y) == -1) {
666 						playSoundEffectIndex(SND_SELECTION);
667 						return MENUEVENT_LCLICK_OFFBUTTON;
668 					}
669 				}
670 				break;
671 
672 			case TREKEVENT_RBUTTONDOWN:
673 rclick:
674 				playSoundEffectIndex(SND_SELECTION);
675 				if (_activeMenu->selectedButton == -1)
676 					return MENUEVENT_RCLICK_OFFBUTTON;
677 				else
678 					return MENUEVENT_RCLICK_ONBUTTON;
679 				break;
680 
681 			case TREKEVENT_KEYDOWN:
682 				if (inTextbox) {
683 					switch (event.kbd.keycode) {
684 					case Common::KEYCODE_ESCAPE:
685 					case Common::KEYCODE_F2:
686 						goto rclick;
687 
688 					case Common::KEYCODE_RETURN:
689 					case Common::KEYCODE_KP_ENTER:
690 					case Common::KEYCODE_F1:
691 						playSoundEffectIndex(SND_SELECTION);
692 						return TEXTBUTTON_CONFIRM;
693 
694 					case Common::KEYCODE_SPACE:
695 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_NEXTCHOICE))
696 						        && _activeMenu->sprites[TEXTBUTTON_NEXTCHOICE].drawMode == 2) {
697 							playSoundEffectIndex(SND_SELECTION);
698 							return TEXTBUTTON_NEXTCHOICE;
699 						}
700 						break;
701 
702 					case Common::KEYCODE_HOME:
703 					case Common::KEYCODE_KP7:
704 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_SCROLLUP))
705 						        && _activeMenu->sprites[TEXTBUTTON_SCROLLUP].drawMode == 2) {
706 							playSoundEffectIndex(SND_SELECTION);
707 							return TEXTBUTTON_GOTO_TOP;
708 						}
709 						break;
710 
711 					case Common::KEYCODE_UP:
712 					case Common::KEYCODE_KP8:
713 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_SCROLLUP))
714 						        && _activeMenu->sprites[TEXTBUTTON_SCROLLUP].drawMode == 2) {
715 							playSoundEffectIndex(SND_SELECTION);
716 							return TEXTBUTTON_SCROLLUP_ONELINE;
717 						}
718 						break;
719 
720 					case Common::KEYCODE_PAGEUP:
721 					case Common::KEYCODE_KP9:
722 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_SCROLLUP))
723 						        && _activeMenu->sprites[TEXTBUTTON_SCROLLUP].drawMode == 2) {
724 							playSoundEffectIndex(SND_SELECTION);
725 							return TEXTBUTTON_SCROLLUP;
726 						}
727 						break;
728 
729 					case Common::KEYCODE_LEFT:
730 					case Common::KEYCODE_KP4:
731 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_PREVCHOICE))
732 						        && _activeMenu->sprites[TEXTBUTTON_PREVCHOICE].drawMode == 2) {
733 							playSoundEffectIndex(SND_SELECTION);
734 							return TEXTBUTTON_PREVCHOICE;
735 						}
736 						break;
737 
738 					case Common::KEYCODE_RIGHT:
739 					case Common::KEYCODE_KP6:
740 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_NEXTCHOICE))
741 						        && _activeMenu->sprites[TEXTBUTTON_NEXTCHOICE].drawMode == 2) {
742 							playSoundEffectIndex(SND_SELECTION);
743 							return TEXTBUTTON_NEXTCHOICE;
744 						}
745 						break;
746 
747 					case Common::KEYCODE_END:
748 					case Common::KEYCODE_KP1:
749 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_SCROLLDOWN))
750 						        && _activeMenu->sprites[TEXTBUTTON_SCROLLDOWN].drawMode == 2) {
751 							playSoundEffectIndex(SND_SELECTION);
752 							return TEXTBUTTON_GOTO_BOTTOM;
753 						}
754 						break;
755 
756 					case Common::KEYCODE_DOWN:
757 					case Common::KEYCODE_KP2:
758 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_SCROLLDOWN))
759 						        && _activeMenu->sprites[TEXTBUTTON_SCROLLDOWN].drawMode == 2) {
760 							playSoundEffectIndex(SND_SELECTION);
761 							return TEXTBUTTON_SCROLLDOWN_ONELINE;
762 						}
763 						break;
764 
765 					case Common::KEYCODE_PAGEDOWN:
766 					case Common::KEYCODE_KP3:
767 						if (!(_activeMenu->disabledButtons & (1 << TEXTBUTTON_SCROLLDOWN))
768 						        && _activeMenu->sprites[TEXTBUTTON_SCROLLDOWN].drawMode == 2) {
769 							playSoundEffectIndex(SND_SELECTION);
770 							return TEXTBUTTON_SCROLLDOWN;
771 						}
772 						break;
773 
774 					default:
775 						break;
776 					}
777 				} else { // Not in textbox
778 					switch (event.kbd.keycode) {
779 					case Common::KEYCODE_ESCAPE:
780 					case Common::KEYCODE_F2:
781 						goto rclick;
782 
783 					case Common::KEYCODE_RETURN:
784 					case Common::KEYCODE_KP_ENTER:
785 					case Common::KEYCODE_F1:
786 						goto lclick;
787 
788 					case Common::KEYCODE_HOME:
789 					case Common::KEYCODE_KP7:
790 						chooseMousePositionFromSprites(_activeMenu->sprites, _activeMenu->numButtons, _activeMenu->selectedButton, 4);
791 						break;
792 
793 					case Common::KEYCODE_UP:
794 					case Common::KEYCODE_KP8:
795 					case Common::KEYCODE_PAGEUP:
796 					case Common::KEYCODE_KP9:
797 						chooseMousePositionFromSprites(_activeMenu->sprites, _activeMenu->numButtons, _activeMenu->selectedButton, 2);
798 						break;
799 
800 					case Common::KEYCODE_LEFT:
801 					case Common::KEYCODE_KP4:
802 						chooseMousePositionFromSprites(_activeMenu->sprites, _activeMenu->numButtons, _activeMenu->selectedButton, 1);
803 						break;
804 
805 					case Common::KEYCODE_RIGHT:
806 					case Common::KEYCODE_KP6:
807 						chooseMousePositionFromSprites(_activeMenu->sprites, _activeMenu->numButtons, _activeMenu->selectedButton, 0);
808 						break;
809 
810 					case Common::KEYCODE_END:
811 					case Common::KEYCODE_KP1:
812 						chooseMousePositionFromSprites(_activeMenu->sprites, _activeMenu->numButtons, _activeMenu->selectedButton, 5);
813 						break;
814 
815 					case Common::KEYCODE_DOWN:
816 					case Common::KEYCODE_KP2:
817 					case Common::KEYCODE_PAGEDOWN:
818 					case Common::KEYCODE_KP3:
819 						chooseMousePositionFromSprites(_activeMenu->sprites, _activeMenu->numButtons, _activeMenu->selectedButton, 3);
820 						break;
821 
822 					default:
823 						break;
824 					}
825 					break;
826 
827 				default:
828 					break;
829 				}
830 			}
831 		}
832 	}
833 }
834 
unloadMenuButtons()835 void StarTrekEngine::unloadMenuButtons() {
836 	if (_activeMenu->selectedButton != -1)
837 		drawMenuButtonOutline(_activeMenu->sprites[_activeMenu->selectedButton].bitmap, 0x00);
838 
839 	for (int i = 0; i < _activeMenu->numButtons; i++) {
840 		Sprite *sprite = &_activeMenu->sprites[i];
841 		if (sprite->drawMode == 2) {
842 			sprite->field16 = true;
843 			sprite->bitmapChanged = true;
844 		}
845 	}
846 
847 	_gfx->drawAllSprites();
848 
849 	for (int i = 0; i < _activeMenu->numButtons; i++) {
850 		Sprite *sprite = &_activeMenu->sprites[i];
851 		sprite->bitmap.reset();
852 		if (sprite->drawMode == 2)
853 			_gfx->delSprite(sprite);
854 	}
855 
856 	Menu *prevMenu = _activeMenu;
857 	_activeMenu = _activeMenu->nextMenu;
858 	delete prevMenu;
859 
860 	if (_activeMenu == nullptr)
861 		_keyboardControlsMouse = _keyboardControlsMouseOutsideMenu;
862 }
863 
chooseMouseBitmapForAction(int action,bool withRedOutline)864 void StarTrekEngine::chooseMouseBitmapForAction(int action, bool withRedOutline) {
865 	const char *lookActionBitmaps[] = {
866 		"lookh0", // The "look" action randomly animates with these images
867 		"lookh0",
868 		"lookh0",
869 		"lookh0",
870 		"lookh0",
871 		"lookh1",
872 		"lookh2",
873 		"lookh3"
874 	};
875 
876 	Common::String bitmapName;
877 
878 	switch (action) {
879 
880 	case ACTION_USE:
881 		if (withRedOutline)
882 			bitmapName = "useh";
883 		else
884 			bitmapName = "usen";
885 		break;
886 
887 	case ACTION_GET:
888 		if (withRedOutline)
889 			bitmapName = "geth";
890 		else
891 			bitmapName = "getn";
892 		break;
893 
894 	case ACTION_LOOK:
895 		if (withRedOutline) {
896 			if ((getRandomWord() & 7) == 0)
897 				_lookActionBitmapIndex = getRandomWord() & 7; // Choose an image randomly
898 			bitmapName = lookActionBitmaps[_lookActionBitmapIndex];
899 		} else
900 			bitmapName = "lookn";
901 		break;
902 
903 	case ACTION_TALK:
904 		if (withRedOutline) {
905 			if (getRandomWord() & 3)
906 				bitmapName = "talkh0";
907 			else
908 				bitmapName = "talkh1";
909 		} else
910 			bitmapName = "talkn";
911 		break;
912 
913 	case ACTION_OPTIONS:
914 		bitmapName = "options";
915 		break;
916 
917 	case ACTION_WALK:
918 	default:
919 		bitmapName = "walk";
920 		break;
921 	}
922 
923 	_gfx->setMouseBitmap(_gfx->loadBitmap(bitmapName));
924 }
925 
showQuitGamePrompt(int x,int y)926 void StarTrekEngine::showQuitGamePrompt(int x, int y) {
927 	const char *options[] = {
928 		"Quit Game",
929 		"#GENE\\GENER028#Yes, quit the game.",
930 		"#GENE\\GENER008#No, do not quit the game.",
931 		""
932 	};
933 
934 	if (_inQuitGameMenu)
935 		return;
936 
937 	_inQuitGameMenu = true;
938 	int val = showText(&StarTrekEngine::readTextFromArray, (uintptr)options, x, y, TEXTCOLOR_YELLOW, true, 0, true);
939 	_inQuitGameMenu = false;
940 
941 	if (val == 0) {
942 		// sub_1e70d();
943 		_system->quit();
944 	}
945 }
946 
showGameOverMenu()947 void StarTrekEngine::showGameOverMenu() {
948 	const char *options[] = {
949 		"Game Over",
950 		"#GENE\\GENER006#Load a previously saved game.",
951 		"#GENE\\GENER020#Restart the game.",
952 		"#GENE\\GENER018#Quit the game.",
953 		""
954 	};
955 
956 	while (true) {
957 		_inQuitGameMenu = true;
958 		int selected = showText(&StarTrekEngine::readTextFromArray, (uintptr)options, 20, 20, TEXTCOLOR_YELLOW, true, false, true);
959 		_inQuitGameMenu = false;
960 
961 		switch (selected) {
962 		case 0: // Load game
963 			_gfx->fadeoutScreen();
964 			showLoadMenu(); // TODO: this probably manipulates the stack to jump out of this function...
965 			_resetGameMode = true;
966 			return;
967 		case 1: // Restart
968 			_gfx->fadeoutScreen();
969 			// TODO
970 			_resetGameMode = true;
971 			return;
972 		case 2: // Quit
973 			_gfx->fadeoutScreen();
974 			_system->quit();
975 			return;
976 		default:
977 			break;
978 		}
979 	}
980 }
981 
showTextConfigurationMenu(bool fromOptionMenu)982 void StarTrekEngine::showTextConfigurationMenu(bool fromOptionMenu) {
983 	const char *options[] = { // TODO: languages...
984 		"Text display",
985 		"Text subtitles.",
986 		"Display text until you press enter.",
987 		"No text displayed.",
988 		""
989 	};
990 
991 	int val;
992 	if (fromOptionMenu || (val = loadTextDisplayMode()) == -1) {
993 		val = showText(&StarTrekEngine::readTextFromArray, (uintptr)options, 20, 30, TEXTCOLOR_YELLOW, true, 0, true);
994 		saveTextDisplayMode(val);
995 	}
996 
997 	switch (val) {
998 	case 0:
999 		_textDisplayMode = TEXTDISPLAY_SUBTITLES;
1000 		break;
1001 	case 1:
1002 		_textDisplayMode = TEXTDISPLAY_WAIT;
1003 		break;
1004 	case 2:
1005 		_textDisplayMode = TEXTDISPLAY_NONE;
1006 		break;
1007 	}
1008 }
1009 
loadTextDisplayMode()1010 int StarTrekEngine::loadTextDisplayMode() {
1011 	return -1; // TODO
1012 }
saveTextDisplayMode(int value)1013 void StarTrekEngine::saveTextDisplayMode(int value) {
1014 	// TODO;
1015 }
1016 
showRepublicMap(int16 arg0,int16 turbolift)1017 void StarTrekEngine::showRepublicMap(int16 arg0, int16 turbolift) {
1018 	_gfx->fadeoutScreen();
1019 	_sound->stopAllVocSounds();
1020 
1021 	bool spriteLoaded = false;
1022 	int16 clickedArea = 0;
1023 
1024 	actorFunc1();
1025 	_gfx->pushSprites();
1026 
1027 	if (!_awayMission.veng.showedRepublicMapFirstTime) {
1028 		_gfx->setBackgroundImage(_gfx->loadBitmap("veng9b"));
1029 		_gfx->copyBackgroundScreen();
1030 		_system->updateScreen();
1031 		_system->delayMillis(10);
1032 		_gfx->setPri(15);
1033 		_gfx->fadeinScreen();
1034 
1035 		// TODO: hide mouse sprite?
1036 
1037 		bool exitLoop = 0;
1038 		int16 var54 = 0x2d;
1039 
1040 		while (!exitLoop) {
1041 			TrekEvent event;
1042 			if (!popNextEvent(&event))
1043 				continue;
1044 
1045 			switch (event.type) {
1046 			case TREKEVENT_TICK:
1047 				if (--var54 == 0)
1048 					exitLoop = true;
1049 				break;
1050 
1051 			case TREKEVENT_LBUTTONDOWN:
1052 			case TREKEVENT_RBUTTONDOWN:
1053 				exitLoop = true;
1054 				break;
1055 
1056 			case TREKEVENT_KEYDOWN:
1057 				switch (event.kbd.keycode) {
1058 				case Common::KEYCODE_ESCAPE:
1059 				case Common::KEYCODE_RETURN:
1060 				case Common::KEYCODE_KP_ENTER:
1061 				case Common::KEYCODE_SPACE:
1062 					exitLoop = true;
1063 					break;
1064 
1065 				default:
1066 					break;
1067 				}
1068 				break;
1069 
1070 			default:
1071 				break;
1072 			}
1073 		}
1074 
1075 		// BUGFIX: Original game used variable "scannedComputerBank" (0x32) instead of
1076 		// "showedRepublicMapFirstTime" (0x33), which is used elsewhere. Byte 0x33 is
1077 		// otherwise unused, so maybe this is a weird off-by-1 error.
1078 		// The effective result is that scanning the computer bank would cause the preview
1079 		// of the map screen to not appear.
1080 		_awayMission.veng.showedRepublicMapFirstTime = true;
1081 
1082 		_gfx->fadeoutScreen();
1083 	}
1084 
1085 	_gfx->setBackgroundImage(_gfx->loadBitmap("veng9"));
1086 	_gfx->copyBackgroundScreen();
1087 	_system->updateScreen();
1088 	_system->delayMillis(10);
1089 	_gfx->setPri(15);
1090 
1091 	Sprite someSprite;
1092 	_gfx->drawAllSprites();
1093 	_gfx->warpMouse(_gfx->getMousePos().x, 96);
1094 	_gfx->fadeinScreen();
1095 
1096 	bool exitLoop = false;
1097 
1098 	while (!exitLoop) {
1099 		TrekEvent event;
1100 		if (!popNextEvent(&event))
1101 			continue;
1102 
1103 		switch (event.type) {
1104 		case TREKEVENT_TICK:
1105 			_frameIndex++;
1106 			// sub_12fff(); // TODO
1107 			_gfx->drawAllSprites();
1108 			break;
1109 
1110 		case TREKEVENT_LBUTTONDOWN: {
1111 lclick:
1112 			clickedArea = getRepublicMapAreaOrFailure(turbolift);
1113 			if (clickedArea == 0) {
1114 			} else if (clickedArea == 6) {
1115 				Common::String text = "#GENE\\GENE_F14#Turbolift access is blocked by an extremely high radiation level.";
1116 				showTextbox("Mr. Spock", text, 50, 50, TEXTCOLOR_YELLOW, 0); // ENHANCEMENT: Speaker is Spock
1117 			} else if (clickedArea == 7) {
1118 				Common::String text = "#GENE\\GENE_F15#This turbolift cannot reach that area of the ship.";
1119 				showTextbox("Mr. Spock", text, 50, 50, TEXTCOLOR_YELLOW, 0); // ENHANCEMENT: Speaker is Spock
1120 			} else
1121 				exitLoop = true;
1122 			break;
1123 		}
1124 
1125 		case TREKEVENT_MOUSEMOVE: {
1126 			if (_gfx->getMousePos().y < 96) // TODO: more elegant solution
1127 				_gfx->warpMouse(_gfx->getMousePos().x, 96);
1128 
1129 			clickedArea = getRepublicMapAreaAtMouse();
1130 			if (clickedArea != 0) {
1131 				if (!spriteLoaded) {
1132 					_gfx->addSprite(&someSprite);
1133 					someSprite.setXYAndPriority(3, 168, 15);
1134 					someSprite.bitmap = _gfx->loadBitmap(Common::String::format("turbo%d", clickedArea));
1135 					spriteLoaded = true;
1136 				}
1137 			} else {
1138 				if (spriteLoaded) {
1139 					someSprite.dontDrawNextFrame();
1140 					_gfx->drawAllSprites();
1141 					_gfx->delSprite(&someSprite);
1142 					someSprite.bitmap.reset();
1143 					spriteLoaded = false;
1144 				}
1145 			}
1146 			break;
1147 		}
1148 
1149 		case TREKEVENT_KEYDOWN:
1150 			switch (event.kbd.keycode) {
1151 			case Common::KEYCODE_RETURN:
1152 			case Common::KEYCODE_KP_ENTER:
1153 			case Common::KEYCODE_F1:
1154 				goto lclick;
1155 
1156 			default:
1157 				break;
1158 			}
1159 			break;
1160 
1161 		default:
1162 			break;
1163 		}
1164 	}
1165 
1166 	_gfx->fadeoutScreen();
1167 	someSprite.bitmap.reset();
1168 	_gfx->popSprites();
1169 
1170 	_gfx->loadPri(getScreenName());
1171 	_gfx->setBackgroundImage(_gfx->loadBitmap(getScreenName()));
1172 	_gfx->copyBackgroundScreen();
1173 	_system->updateScreen();
1174 	_system->delayMillis(10);
1175 
1176 	_gfx->drawAllSprites();
1177 
1178 	int16 roomIndex, spawnIndex;
1179 	if (clickedArea == 1) {
1180 		roomIndex = 0;
1181 		spawnIndex = 1;
1182 	} else if (clickedArea == 2) {
1183 		roomIndex = 1;
1184 		spawnIndex = 1;
1185 	} else if (clickedArea == 3 && turbolift == 0) {
1186 		roomIndex = 3;
1187 		spawnIndex = 1;
1188 	} else if (clickedArea == 3 && turbolift == 1) {
1189 		roomIndex = 3;
1190 		spawnIndex = 0;
1191 	} else if (clickedArea == 4) {
1192 		roomIndex = 5;
1193 		spawnIndex = 1;
1194 	} else if (clickedArea == 5) {
1195 		roomIndex = 7;
1196 		spawnIndex = 1;
1197 	} else {
1198 		warning("Unknown room selected");
1199 		roomIndex = 0;
1200 		spawnIndex = 1;
1201 	}
1202 
1203 	_roomIndexToLoad = roomIndex;
1204 	_spawnIndexToLoad = spawnIndex;
1205 }
1206 
getRepublicMapAreaAtMouse()1207 int StarTrekEngine::getRepublicMapAreaAtMouse() {
1208 	Common::Point mouse = _gfx->getMousePos();
1209 
1210 	if (mouse.x >= 0x7f && mouse.x <= 0x91 && mouse.y >= 0x78 && mouse.y <= 0x7b)
1211 		return 1;
1212 	else if (mouse.x >= 0x6e && mouse.x <= 0x7e && mouse.y >= 0x83 && mouse.y <= 0x87)
1213 		return 2;
1214 	else if (mouse.x >= 0x95 && mouse.x <= 0xad && mouse.y >= 0x8f && mouse.y <= 0x93)
1215 		return 3;
1216 	else if (mouse.x >= 0xef && mouse.x <= 0xfd && mouse.y >= 0x98 && mouse.y <= 0xa0)
1217 		return 4;
1218 	else if (mouse.x >= 0x6b && mouse.x <= 0x80 && mouse.y >= 0xa3 && mouse.y <= 0xa7)
1219 		return 5;
1220 	else if (mouse.x >= 0x6e && mouse.x <= 0x88 && mouse.y >= 0xab && mouse.y <= 0xaf)
1221 		return 6;
1222 	else
1223 		return 0;
1224 }
1225 
getRepublicMapAreaOrFailure(int16 turbolift)1226 int StarTrekEngine::getRepublicMapAreaOrFailure(int16 turbolift) {
1227 	Common::Point mouse = _gfx->getMousePos();
1228 
1229 	if (mouse.x >= 0x7f && mouse.x <= 0x91 && mouse.y >= 0x78 && mouse.y <= 0x7b)
1230 		return turbolift == 0 ? 1 : 7;
1231 	else if (mouse.x >= 0x6e && mouse.x <= 0x7e && mouse.y >= 0x83 && mouse.y <= 0x87)
1232 		return turbolift == 0 ? 2 : 7;
1233 	else if (mouse.x >= 0x95 && mouse.x <= 0xad && mouse.y >= 0x8f && mouse.y <= 0x93)
1234 		return 3;
1235 	else if (mouse.x >= 0xef && mouse.x <= 0xfd && mouse.y >= 0x98 && mouse.y <= 0xa0)
1236 		return turbolift == 1 ? 4 : 7;
1237 	else if (mouse.x >= 0x6b && mouse.x <= 0x80 && mouse.y >= 0xa3 && mouse.y <= 0xa7)
1238 		return turbolift == 1 ? 5 : 7;
1239 	else if (mouse.x >= 0x6e && mouse.x <= 0x88 && mouse.y >= 0xab && mouse.y <= 0xaf)
1240 		return 6;
1241 	return 0;
1242 }
1243 
1244 } // End of namespace StarTrek
1245