scummvm/engines/lab/engine.cpp

1237 lines
29 KiB
C++
Raw Normal View History

2014-10-06 12:50:05 +00:00
/* 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.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
2014-12-25 18:13:52 +00:00
#include "lab/lab.h"
2015-12-08 20:10:54 +00:00
#include "lab/anim.h"
#include "lab/dispman.h"
#include "lab/eventman.h"
#include "lab/image.h"
2015-11-20 19:17:30 +00:00
#include "lab/intro.h"
#include "lab/labsets.h"
#include "lab/music.h"
#include "lab/processroom.h"
2015-12-08 20:10:54 +00:00
#include "lab/resource.h"
#include "lab/tilepuzzle.h"
#include "lab/utils.h"
2014-10-06 12:50:05 +00:00
namespace Lab {
2015-12-08 10:27:34 +00:00
// LAB: Labyrinth specific code for the special puzzles
2014-10-06 12:50:05 +00:00
#define SPECIALLOCK 100
#define SPECIALBRICK 101
#define SPECIALBRICKNOMOUSE 102
enum Items {
kItemHelmet = 1,
kItemBelt = 3,
kItemPithHelmet = 7,
kItemJournal = 9,
kItemNotes = 12,
kItemWestPaper = 18,
kItemWhiskey = 25,
kItemLamp = 27,
kItemMap = 28,
kItemQuarter = 30
};
#define kCondLampOn 151
#define kCondBeltGlowing 70
#define kCondUsedHelmet 184
enum Monitors {
kMonitorMuseum = 71,
kMonitorGramophone = 72,
kMonitorUnicycle = 73,
kMonitorStatue = 74,
kMonitorTalisman = 75,
kMonitorLute = 76,
kMonitorClock = 77,
kMonitorWindow = 78,
//kMonitorBelt = 79,
kMonitorLibrary = 80,
kMonitorTerminal = 81
//kMonitorLevers = 82
};
2014-10-06 12:50:05 +00:00
static char initcolors[] = { '\x00', '\x00', '\x00', '\x30',
'\x30', '\x30', '\x10', '\x10',
'\x10', '\x14', '\x14', '\x14',
'\x20', '\x20', '\x20', '\x24',
'\x24', '\x24', '\x2c', '\x2c',
2015-12-08 21:00:19 +00:00
'\x2c', '\x08', '\x08', '\x08' };
2014-10-06 12:50:05 +00:00
uint16 LabEngine::getQuarters() {
return _inventory[kItemQuarter]._many;
}
void LabEngine::setQuarters(uint16 quarters) {
_inventory[kItemQuarter]._many = quarters;
}
/**
* Draws the message for the room.
*/
void LabEngine::drawRoomMessage(uint16 curInv, CloseDataPtr closePtr) {
2015-12-01 09:35:31 +00:00
if (_lastTooLong) {
_lastTooLong = false;
2014-10-06 12:50:05 +00:00
return;
}
if (_alternate) {
2015-12-06 20:53:57 +00:00
if ((curInv <= _numInv) && _conditions->in(curInv) && _inventory[curInv]._bitmapName) {
if ((curInv == kItemLamp) && _conditions->in(kCondLampOn))
2015-12-08 10:27:34 +00:00
// LAB: Labyrinth specific
drawStaticMessage(kTextkLampOn);
2015-12-06 20:53:57 +00:00
else if (_inventory[curInv]._many > 1) {
Common::String roomMessage = Common::String(_inventory[curInv]._name) + " (" + Common::String::format("%d", _inventory[curInv]._many) + ")";
_graphics->drawMessage(roomMessage.c_str());
2014-10-06 12:50:05 +00:00
} else
2015-12-06 20:53:57 +00:00
_graphics->drawMessage(_inventory[curInv]._name);
2014-10-06 12:50:05 +00:00
}
} else
drawDirection(closePtr);
2014-10-06 12:50:05 +00:00
_lastTooLong = _graphics->_lastMessageLong;
2014-10-06 12:50:05 +00:00
}
2015-12-02 19:32:06 +00:00
void LabEngine::freeScreens() {
for (uint16 i = 0; i < 20; i++) {
2015-12-02 19:32:06 +00:00
delete _moveImages[i];
_moveImages[i] = nullptr;
}
2015-12-02 19:32:06 +00:00
for (uint16 imgIdx = 0; imgIdx < 10; imgIdx++) {
delete _invImages[imgIdx];
_invImages[imgIdx] = nullptr;
2015-12-02 19:32:06 +00:00
}
}
/**
2015-12-13 17:36:56 +00:00
* Permanently flips the imagery of a button.
*/
2015-12-13 17:36:56 +00:00
void LabEngine::perFlipButton(uint16 buttonId) {
for (ButtonList::iterator button = _moveButtonList.begin(); button != _moveButtonList.end(); ++button) {
Button *topButton = *button;
if (topButton->_buttonID == buttonId) {
Image *tmpImage = topButton->_image;
topButton->_image = topButton->_altImage;
topButton->_altImage = tmpImage;
2014-10-06 12:50:05 +00:00
if (!_alternate) {
_event->mouseHide();
2015-12-13 19:15:24 +00:00
topButton->_image->drawImage(topButton->_x, topButton->_y);
_event->mouseShow();
2014-10-06 12:50:05 +00:00
}
break;
}
2014-10-06 12:50:05 +00:00
}
}
/**
* Eats all the available messages.
*/
void LabEngine::eatMessages() {
IntuiMessage *msg;
2014-10-06 12:50:05 +00:00
do {
2015-12-13 13:37:39 +00:00
msg = _event->getMsg();
} while (msg);
2014-10-06 12:50:05 +00:00
}
/**
* Checks whether the close up is one of the special case closeups.
*/
bool LabEngine::doCloseUp(CloseDataPtr closePtr) {
if (!closePtr)
2014-10-06 12:50:05 +00:00
return false;
2014-12-27 13:18:40 +00:00
int monltmargin, monrtmargin, montopmargin, lutertmargin;
2015-11-29 22:34:35 +00:00
if (getPlatform() != Common::kPlatformWindows) {
2014-12-27 13:18:40 +00:00
monltmargin = 0;
monrtmargin = 319;
montopmargin = 0;
lutertmargin = 124;
} else {
monltmargin = 2;
monrtmargin = 317;
montopmargin = 2;
lutertmargin = 128;
}
2015-12-06 20:53:57 +00:00
switch (closePtr->_closeUpType) {
case kMonitorMuseum:
case kMonitorLibrary:
case kMonitorWindow:
2015-12-06 20:53:57 +00:00
doMonitor(closePtr->_graphicName, closePtr->_message, false, monltmargin, montopmargin, monrtmargin, 165);
break;
case kMonitorGramophone:
2015-12-06 20:53:57 +00:00
doMonitor(closePtr->_graphicName, closePtr->_message, false, monltmargin, montopmargin, 171, 165);
break;
case kMonitorUnicycle:
2015-12-06 20:53:57 +00:00
doMonitor(closePtr->_graphicName, closePtr->_message, false, 100, montopmargin, monrtmargin, 165);
break;
case kMonitorStatue:
2015-12-06 20:53:57 +00:00
doMonitor(closePtr->_graphicName, closePtr->_message, false, 117, montopmargin, monrtmargin, 165);
break;
case kMonitorTalisman:
2015-12-06 20:53:57 +00:00
doMonitor(closePtr->_graphicName, closePtr->_message, false, monltmargin, montopmargin, 184, 165);
break;
case kMonitorLute:
2015-12-06 20:53:57 +00:00
doMonitor(closePtr->_graphicName, closePtr->_message, false, monltmargin, montopmargin, lutertmargin, 165);
break;
case kMonitorClock:
2015-12-06 20:53:57 +00:00
doMonitor(closePtr->_graphicName, closePtr->_message, false, monltmargin, montopmargin, 206, 165);
break;
case kMonitorTerminal:
2015-12-06 20:53:57 +00:00
doMonitor(closePtr->_graphicName, closePtr->_message, true, monltmargin, montopmargin, monrtmargin, 165);
break;
default:
2014-10-06 12:50:05 +00:00
return false;
}
2014-10-06 12:50:05 +00:00
_curFileName = " ";
_graphics->drawPanel();
2014-10-06 12:50:05 +00:00
return true;
}
/**
* Gets the current inventory name.
*/
const char *LabEngine::getInvName(uint16 curInv) {
if (_mainDisplay)
2015-12-06 20:53:57 +00:00
return _inventory[curInv]._bitmapName;
2014-10-06 12:50:05 +00:00
if ((curInv == kItemLamp) && _conditions->in(kCondLampOn))
2014-10-06 12:50:05 +00:00
return "P:Mines/120";
if ((curInv == kItemBelt) && _conditions->in(kCondBeltGlowing))
return "P:Future/kCondBeltGlowing";
2014-10-06 12:50:05 +00:00
if (curInv == kItemWestPaper) {
2015-12-06 20:53:57 +00:00
_curFileName = _inventory[curInv]._bitmapName;
_anim->_noPalChange = true;
_graphics->readPict(_curFileName, false);
_anim->_noPalChange = false;
2014-10-06 12:50:05 +00:00
doWestPaper();
} else if (curInv == kItemNotes) {
2015-12-06 20:53:57 +00:00
_curFileName = _inventory[curInv]._bitmapName;
_anim->_noPalChange = true;
_graphics->readPict(_curFileName, false);
_anim->_noPalChange = false;
2014-10-06 12:50:05 +00:00
doNotes();
}
2015-12-06 20:53:57 +00:00
return _inventory[curInv]._bitmapName;
2014-10-06 12:50:05 +00:00
}
/**
* Turns the interface off.
*/
void LabEngine::interfaceOff() {
if (!_interfaceOff) {
2015-12-13 17:36:56 +00:00
_event->attachButtonList(nullptr);
_event->mouseHide();
_interfaceOff = true;
2014-10-06 12:50:05 +00:00
}
}
/**
* Turns the interface on.
*/
void LabEngine::interfaceOn() {
if (_interfaceOff) {
_interfaceOff = false;
_event->mouseShow();
2014-10-06 12:50:05 +00:00
}
if (_graphics->_longWinInFront)
2015-12-13 17:36:56 +00:00
_event->attachButtonList(nullptr);
else if (_alternate)
2015-12-13 17:36:56 +00:00
_event->attachButtonList(&_invButtonList);
2014-10-06 12:50:05 +00:00
else
2015-12-13 17:36:56 +00:00
_event->attachButtonList(&_moveButtonList);
2014-10-06 12:50:05 +00:00
}
/**
2015-12-13 17:36:56 +00:00
* If the user hits the "Use" button; things that can get used on themselves.
*/
bool LabEngine::doUse(uint16 curInv) {
switch (curInv) {
case kItemMap:
drawStaticMessage(kTextUseMap);
2014-10-06 12:50:05 +00:00
interfaceOff();
2015-12-01 19:10:42 +00:00
_anim->stopDiff();
_curFileName = " ";
_closeDataPtr = nullptr;
2015-11-30 00:42:12 +00:00
doMap(_roomNum);
2015-12-06 13:36:49 +00:00
_graphics->setPalette(initcolors, 8);
_graphics->drawMessage(nullptr);
_graphics->drawPanel();
return true;
case kItemJournal:
drawStaticMessage(kTextUseJournal);
2014-10-06 12:50:05 +00:00
interfaceOff();
2015-12-01 19:10:42 +00:00
_anim->stopDiff();
_curFileName = " ";
_closeDataPtr = nullptr;
2014-12-25 18:13:52 +00:00
doJournal();
_graphics->drawPanel();
_graphics->drawMessage(nullptr);
return true;
case kItemLamp:
2014-10-06 12:50:05 +00:00
interfaceOff();
if (_conditions->in(kCondLampOn)) {
drawStaticMessage(kTextTurnLampOff);
_conditions->exclElement(kCondLampOn);
}
else {
drawStaticMessage(kTextTurnkLampOn);
_conditions->inclElement(kCondLampOn);
2014-10-06 12:50:05 +00:00
}
2015-12-01 23:34:51 +00:00
_anim->_doBlack = false;
_anim->_waitForEffect = true;
_graphics->readPict("Music:Click", true);
2015-12-01 23:34:51 +00:00
_anim->_waitForEffect = false;
2014-10-06 12:50:05 +00:00
2015-12-01 23:34:51 +00:00
_anim->_doBlack = false;
_nextFileName = getInvName(curInv);
return true;
case kItemBelt:
if (!_conditions->in(kCondBeltGlowing))
_conditions->inclElement(kCondBeltGlowing);
2014-10-06 12:50:05 +00:00
2015-12-01 23:34:51 +00:00
_anim->_doBlack = false;
_nextFileName = getInvName(curInv);
return true;
case kItemWhiskey:
_conditions->inclElement(kCondUsedHelmet);
drawStaticMessage(kTextUseWhiskey);
return true;
case kItemPithHelmet:
_conditions->inclElement(kCondUsedHelmet);
drawStaticMessage(kTextUsePith);
return true;
case kItemHelmet:
_conditions->inclElement(kCondUsedHelmet);
drawStaticMessage(kTextUseHelmet);
return true;
default:
2014-10-06 12:50:05 +00:00
return false;
}
2014-10-06 12:50:05 +00:00
}
/**
* Decrements the current inventory number.
*/
void LabEngine::decIncInv(uint16 *curInv, bool decreaseFl) {
2014-10-06 12:50:05 +00:00
interfaceOff();
if (decreaseFl)
(*curInv)--;
2014-10-06 12:50:05 +00:00
else
(*curInv)++;
2014-10-06 12:50:05 +00:00
while (*curInv && (*curInv <= _numInv)) {
2015-12-06 20:53:57 +00:00
if (_conditions->in(*curInv) && _inventory[*curInv]._bitmapName) {
_nextFileName = getInvName(*curInv);
2014-10-06 12:50:05 +00:00
break;
}
if (decreaseFl)
(*curInv)--;
2014-10-06 12:50:05 +00:00
else
(*curInv)++;
2014-10-06 12:50:05 +00:00
}
if ((*curInv == 0) || (*curInv > _numInv)) {
if (decreaseFl)
*curInv = _numInv;
2014-10-06 12:50:05 +00:00
else
*curInv = 1;
2014-10-06 12:50:05 +00:00
while (*curInv && (*curInv <= _numInv)) {
2015-12-06 20:53:57 +00:00
if (_conditions->in(*curInv) && _inventory[*curInv]._bitmapName) {
_nextFileName = getInvName(*curInv);
2014-10-06 12:50:05 +00:00
break;
}
if (decreaseFl)
(*curInv)--;
2014-10-06 12:50:05 +00:00
else
(*curInv)++;
2014-10-06 12:50:05 +00:00
}
}
}
/**
* The main game loop.
*/
2015-11-24 22:59:30 +00:00
void LabEngine::mainGameLoop() {
2015-11-30 12:09:36 +00:00
uint16 actionMode = 4;
uint16 curInv = kItemMap;
2014-10-06 12:50:05 +00:00
bool forceDraw = false;
bool gotMessage = true;
2014-10-06 12:50:05 +00:00
2015-12-06 13:36:49 +00:00
_graphics->setPalette(initcolors, 8);
2014-10-06 12:50:05 +00:00
_closeDataPtr = nullptr;
2015-11-30 00:42:12 +00:00
_roomNum = 1;
2015-12-06 16:24:25 +00:00
_direction = NORTH;
2014-10-06 12:50:05 +00:00
_resource->readRoomData("LAB:Doors");
2015-12-03 18:49:55 +00:00
if (!(_inventory = _resource->readInventory("LAB:Inventor")))
return;
2014-10-06 12:50:05 +00:00
2015-12-06 16:24:25 +00:00
if (!(_conditions = new LargeSet(_highestCondition + 1, this)))
2014-10-06 12:50:05 +00:00
return;
2015-12-06 16:24:25 +00:00
if (!(_roomsFound = new LargeSet(_manyRooms + 1, this)))
2014-10-06 12:50:05 +00:00
return;
2015-11-29 22:34:35 +00:00
_conditions->readInitialConditions("LAB:Conditio");
2014-10-06 12:50:05 +00:00
_graphics->_longWinInFront = false;
_graphics->drawPanel();
2014-10-06 12:50:05 +00:00
2015-12-13 17:36:56 +00:00
perFlipButton(actionMode);
2014-10-06 12:50:05 +00:00
2015-12-08 10:27:34 +00:00
// Set up initial picture.
2014-10-06 12:50:05 +00:00
while (1) {
_event->processInput(true);
2014-10-06 12:50:05 +00:00
if (gotMessage) {
2015-12-06 16:24:25 +00:00
if (_quitLab || g_engine->shouldQuit()) {
2015-12-01 19:10:42 +00:00
_anim->stopDiff();
2014-10-06 12:50:05 +00:00
break;
}
_music->resumeBackMusic();
2014-10-06 12:50:05 +00:00
2015-12-08 10:27:34 +00:00
// Sees what kind of close up we're in and does the appropriate stuff, if any.
if (doCloseUp(_closeDataPtr)) {
_closeDataPtr = nullptr;
2014-10-06 12:50:05 +00:00
mayShowCrumbIndicator();
_graphics->screenUpdate();
2014-10-06 12:50:05 +00:00
}
2015-12-08 10:27:34 +00:00
// Sets the current picture properly on the screen
if (_mainDisplay)
_nextFileName = getPictName(&_closeDataPtr);
2014-10-06 12:50:05 +00:00
2015-12-06 16:24:25 +00:00
if (_noUpdateDiff) {
2015-12-08 10:27:34 +00:00
// Potentially entered another room
_roomsFound->inclElement(_roomNum);
forceDraw |= (strcmp(_nextFileName, _curFileName) != 0);
2014-10-06 12:50:05 +00:00
2015-12-06 16:24:25 +00:00
_noUpdateDiff = false;
_curFileName = _nextFileName;
} else if (strcmp(_nextFileName, _curFileName) != 0) {
2014-10-06 12:50:05 +00:00
interfaceOff();
2015-12-08 10:27:34 +00:00
// Potentially entered another room
_roomsFound->inclElement(_roomNum);
_curFileName = _nextFileName;
2014-10-06 12:50:05 +00:00
if (_closeDataPtr) {
switch (_closeDataPtr->_closeUpType) {
case SPECIALLOCK:
if (_mainDisplay)
_tilePuzzle->showCombination(_curFileName);
break;
case SPECIALBRICK:
case SPECIALBRICKNOMOUSE:
if (_mainDisplay)
_tilePuzzle->showTile(_curFileName, (_closeDataPtr->_closeUpType == SPECIALBRICKNOMOUSE));
break;
default:
_graphics->readPict(_curFileName, false);
break;
}
2014-10-06 12:50:05 +00:00
} else
_graphics->readPict(_curFileName, false);
2014-10-06 12:50:05 +00:00
drawRoomMessage(curInv, _closeDataPtr);
2015-11-30 12:09:36 +00:00
forceDraw = false;
2014-10-06 12:50:05 +00:00
mayShowCrumbIndicator();
_graphics->screenUpdate();
2014-10-06 12:50:05 +00:00
if (!_followingCrumbs)
2014-10-06 12:50:05 +00:00
eatMessages();
}
2015-11-30 12:09:36 +00:00
if (forceDraw) {
drawRoomMessage(curInv, _closeDataPtr);
2015-11-30 12:09:36 +00:00
forceDraw = false;
_graphics->screenUpdate();
2014-10-06 12:50:05 +00:00
}
}
2015-12-08 10:27:34 +00:00
// Make sure we check the music at least after every message
_music->updateMusic();
2014-10-06 12:50:05 +00:00
interfaceOn();
2015-12-13 13:37:39 +00:00
IntuiMessage *curMsg = _event->getMsg();
2014-10-06 12:50:05 +00:00
if (!curMsg) {
2015-12-08 10:27:34 +00:00
// Does music load and next animation frame when you've run out of messages
gotMessage = false;
_music->checkRoomMusic();
_music->updateMusic();
2015-12-01 19:10:42 +00:00
_anim->diffNextFrame();
2014-10-06 12:50:05 +00:00
if (_followingCrumbs) {
2014-10-06 12:50:05 +00:00
int result = followCrumbs();
if (result != 0) {
2015-11-30 12:09:36 +00:00
uint16 code = 0;
switch (result) {
case VKEY_UPARROW:
2015-11-30 12:09:36 +00:00
code = 7;
break;
case VKEY_LTARROW:
2015-11-30 12:09:36 +00:00
code = 6;
break;
case VKEY_RTARROW:
2015-11-30 12:09:36 +00:00
code = 8;
break;
default:
break;
}
2014-10-06 12:50:05 +00:00
gotMessage = true;
2014-10-06 12:50:05 +00:00
mayShowCrumbIndicator();
_graphics->screenUpdate();
2015-12-13 17:36:56 +00:00
if (!fromCrumbs(BUTTONUP, code, 0, _event->updateAndGetMousePos(), curInv, curMsg, forceDraw, code, actionMode))
2015-11-30 12:09:36 +00:00
break;
2014-10-06 12:50:05 +00:00
}
}
mayShowCrumbIndicator();
_graphics->screenUpdate();
2014-10-06 12:50:05 +00:00
} else {
gotMessage = true;
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
Common::Point curPos;
curPos.x = curMsg->_mouseX;
curPos.y = curMsg->_mouseY;
2014-10-06 12:50:05 +00:00
_followingCrumbs = false;
2015-12-13 17:36:56 +00:00
if (!fromCrumbs(curMsg->_msgClass, curMsg->_code, curMsg->_qualifier, curPos, curInv, curMsg, forceDraw, curMsg->_buttonID, actionMode))
2015-11-30 12:09:36 +00:00
break;
}
}
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
delete _conditions;
delete _roomsFound;
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
if (_rooms) {
delete[] _rooms;
2015-11-30 12:09:36 +00:00
_rooms = nullptr;
}
2014-10-06 12:50:05 +00:00
2015-12-03 18:49:55 +00:00
if (_inventory) {
2015-12-06 16:24:25 +00:00
for (int i = 1; i <= _numInv; i++) {
2015-12-06 20:53:57 +00:00
if (_inventory[i]._name)
delete _inventory[i]._name;
2015-11-30 12:09:36 +00:00
2015-12-06 20:53:57 +00:00
if (_inventory[i]._bitmapName)
delete _inventory[i]._bitmapName;
2015-11-30 12:09:36 +00:00
}
delete[] _inventory;
2015-11-30 12:09:36 +00:00
}
}
void LabEngine::showLab2Teaser() {
_graphics->blackAllScreen();
_graphics->readPict("P:End/L2In.1", true);
for (uint16 i = 0; i < 120; i++) {
_music->updateMusic();
waitTOF();
}
_graphics->readPict("P:End/L2In.9", true);
_graphics->readPict("P:End/Lost", true);
warning("STUB: waitForPress");
while (!1) { // 1 means ignore SDL_ProcessInput calls
_music->updateMusic();
_anim->diffNextFrame();
waitTOF();
}
}
bool LabEngine::fromCrumbs(uint32 tmpClass, uint16 code, uint16 qualifier, Common::Point tmpPos,
2015-12-13 17:36:56 +00:00
uint16 &curInv, IntuiMessage *curMsg, bool &forceDraw, uint16 buttonId, uint16 &actionMode) {
2015-11-30 12:09:36 +00:00
uint32 msgClass = tmpClass;
Common::Point curPos = tmpPos;
2015-12-06 16:24:25 +00:00
uint16 oldDirection = 0;
uint16 lastInv = kItemMap;
CloseDataPtr wrkClosePtr = nullptr;
2015-11-30 12:09:36 +00:00
bool doit;
2015-12-01 23:34:51 +00:00
_anim->_doBlack = false;
2015-11-30 12:09:36 +00:00
if ((msgClass == RAWKEY) && (!_graphics->_longWinInFront)) {
2015-12-13 14:59:52 +00:00
byte codeLower = tolower(code);
2015-12-08 10:27:34 +00:00
if (code == 13) {
// The return key
2015-12-08 08:19:00 +00:00
msgClass = MOUSEBUTTONS;
2015-12-08 20:53:42 +00:00
qualifier = IEQUALIFIER_LEFTBUTTON;
2015-11-30 12:09:36 +00:00
curPos = _event->getMousePos();
2015-12-13 14:59:52 +00:00
} else if (getPlatform() == Common::kPlatformWindows && codeLower == 'b') {
2015-12-08 10:27:34 +00:00
// Start bread crumbs
2015-11-30 12:09:36 +00:00
_breadCrumbs[0]._roomNum = 0;
_numCrumbs = 0;
_droppingCrumbs = true;
mayShowCrumbIndicator();
_graphics->screenUpdate();
2015-12-13 14:59:52 +00:00
} else if (codeLower == 'f' || codeLower == 'r') {
2015-12-08 10:27:34 +00:00
// Follow bread crumbs
2015-11-30 12:09:36 +00:00
if (_droppingCrumbs) {
if (_numCrumbs > 0) {
_followingCrumbs = true;
2015-12-13 14:59:52 +00:00
_followCrumbsFast = (codeLower == 'r');
2015-11-30 12:09:36 +00:00
_isCrumbTurning = false;
_isCrumbWaiting = false;
2015-12-13 18:27:34 +00:00
_crumbTimestamp = g_system->getMillis();
2015-11-30 12:09:36 +00:00
if (_alternate) {
2015-11-30 12:09:36 +00:00
eatMessages();
_alternate = false;
2015-12-01 23:34:51 +00:00
_anim->_doBlack = true;
2015-12-06 16:24:25 +00:00
_graphics->_doNotDrawMessage = false;
2015-11-30 12:09:36 +00:00
_mainDisplay = true;
2015-12-13 17:36:56 +00:00
// Sets the correct button list
2015-12-08 10:27:34 +00:00
interfaceOn();
_graphics->drawPanel();
drawRoomMessage(curInv, _closeDataPtr);
_graphics->screenUpdate();
2014-10-06 12:50:05 +00:00
}
2015-11-30 12:09:36 +00:00
} else {
_breadCrumbs[0]._roomNum = 0;
_droppingCrumbs = false;
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
// Need to hide indicator!!!!
mayShowCrumbIndicatorOff();
_graphics->screenUpdate();
2015-11-30 12:09:36 +00:00
}
}
2015-12-13 14:59:52 +00:00
} else if (code == 315 || codeLower == 'x' || codeLower == 'q') {
2015-12-08 10:27:34 +00:00
// Quit?
2015-12-06 16:24:25 +00:00
_graphics->_doNotDrawMessage = false;
_graphics->drawMessage("Do you want to quit? (Y/N)");
2015-11-30 12:09:36 +00:00
eatMessages();
interfaceOff();
while (1) {
2015-12-08 10:27:34 +00:00
// Make sure we check the music at least after every message
_music->updateMusic();
2015-12-13 13:37:39 +00:00
curMsg = _event->getMsg();
2015-11-30 12:09:36 +00:00
if (!curMsg) {
2015-12-08 10:27:34 +00:00
// Does music load and next animation frame when you've run out of messages
2015-11-30 12:09:36 +00:00
_music->updateMusic();
2015-12-01 19:10:42 +00:00
_anim->diffNextFrame();
2015-11-30 12:09:36 +00:00
} else {
if (curMsg->_msgClass == RAWKEY) {
2015-12-13 14:59:52 +00:00
codeLower = tolower(curMsg->_code);
if (codeLower == 'y' || codeLower == 'q') {
_anim->stopDiff();
return false;
} else if (curMsg->_code < 128) {
2015-11-30 12:09:36 +00:00
break;
}
} else if (curMsg->_msgClass == MOUSEBUTTONS) {
2014-10-06 12:50:05 +00:00
break;
}
}
2015-11-30 12:09:36 +00:00
}
2014-10-06 12:50:05 +00:00
2015-12-13 14:59:52 +00:00
forceDraw = true;
interfaceOn();
2015-12-08 10:27:34 +00:00
} else if (code == 9) {
// TAB key
2015-11-30 12:09:36 +00:00
msgClass = DELTAMOVE;
2015-12-08 10:27:34 +00:00
} else if (code == 27) {
// ESC key
_closeDataPtr = nullptr;
2015-11-30 12:09:36 +00:00
}
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
eatMessages();
}
2014-10-06 12:50:05 +00:00
if (_graphics->_longWinInFront) {
2015-12-08 08:19:00 +00:00
if ((msgClass == RAWKEY) || ((msgClass == MOUSEBUTTONS) &&
2015-12-08 20:53:42 +00:00
((IEQUALIFIER_LEFTBUTTON & qualifier) ||
(IEQUALIFIER_RIGHTBUTTON & qualifier)))) {
_graphics->_longWinInFront = false;
2015-12-06 16:24:25 +00:00
_graphics->_doNotDrawMessage = false;
_graphics->drawPanel();
drawRoomMessage(curInv, _closeDataPtr);
_graphics->screenUpdate();
2015-11-30 12:09:36 +00:00
}
2015-12-13 17:36:56 +00:00
} else if ((msgClass == BUTTONUP) && !_alternate) {
uint16 newDir;
switch (buttonId) {
case 0:
case 1:
case 2:
case 3:
case 4:
2015-12-13 17:36:56 +00:00
if ((actionMode == 4) && (buttonId == 4) && _closeDataPtr) {
doMainView(&_closeDataPtr);
2014-10-06 12:50:05 +00:00
2015-12-01 23:34:51 +00:00
_anim->_doBlack = true;
wrkClosePtr = nullptr;
_closeDataPtr = nullptr;
2015-11-30 12:09:36 +00:00
mayShowCrumbIndicator();
} else {
2015-12-06 16:24:25 +00:00
uint16 oldActionMode = actionMode;
2015-12-13 17:36:56 +00:00
actionMode = buttonId;
2015-11-30 12:09:36 +00:00
2015-12-06 16:24:25 +00:00
if (oldActionMode < 5)
2015-12-13 17:36:56 +00:00
perFlipButton(oldActionMode);
2015-11-30 12:09:36 +00:00
2015-12-13 17:36:56 +00:00
perFlipButton(actionMode);
2015-12-14 08:43:17 +00:00
drawStaticMessage(kTextTakeWhat + buttonId);
2015-11-30 12:09:36 +00:00
}
break;
case 5:
eatMessages();
_alternate = true;
_anim->_doBlack = true;
_graphics->_doNotDrawMessage = false;
// Sets the correct button list
interfaceOn();
_mainDisplay = false;
if (lastInv && _conditions->in(lastInv)) {
curInv = lastInv;
_nextFileName = getInvName(curInv);
} else
decIncInv(&curInv, false);
_graphics->drawPanel();
drawRoomMessage(curInv, _closeDataPtr);
mayShowCrumbIndicator();
break;
case 9:
doUse(kItemMap);
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
mayShowCrumbIndicator();
break;
case 6:
case 8:
2015-12-13 17:36:56 +00:00
// Arrow Buttons
_closeDataPtr = nullptr;
wrkClosePtr = nullptr;
if (buttonId == 6)
drawStaticMessage(kTextTurnLeft);
else
drawStaticMessage(kTextTurnRight);
2014-10-06 12:50:05 +00:00
_curFileName = " ";
2014-10-06 12:50:05 +00:00
oldDirection = _direction;
2014-12-27 13:18:40 +00:00
newDir = processArrow(_direction, buttonId - 6);
doTurn(_direction, newDir, &_closeDataPtr);
_anim->_doBlack = true;
_direction = newDir;
forceDraw = true;
2014-10-06 12:50:05 +00:00
mayShowCrumbIndicator();
break;
2014-10-06 12:50:05 +00:00
case 7:
_closeDataPtr = nullptr;
wrkClosePtr = nullptr;
uint16 oldRoomNum = _roomNum;
2014-12-27 13:18:40 +00:00
if (doGoForward(&_closeDataPtr)) {
if (oldRoomNum == _roomNum)
_anim->_doBlack = true;
} else {
_anim->_doBlack = true;
_direction = processArrow(_direction, buttonId - 6);
if (oldRoomNum != _roomNum) {
drawStaticMessage(kTextGoForward);
// Potentially entered a new room
_roomsFound->inclElement(_roomNum);
_curFileName = " ";
forceDraw = true;
2015-11-30 12:09:36 +00:00
} else {
2015-12-01 23:34:51 +00:00
_anim->_doBlack = true;
drawStaticMessage(kTextNoPath);
2015-11-30 12:09:36 +00:00
}
}
2014-12-27 13:18:40 +00:00
if (_followingCrumbs) {
if (_isCrumbTurning) {
if (_direction == oldDirection) {
_followingCrumbs = false;
2015-11-30 12:09:36 +00:00
}
} else {
if (_roomNum == oldRoomNum) { // didn't get there?
2015-11-30 12:09:36 +00:00
_followingCrumbs = false;
}
}
} else if (_droppingCrumbs && oldRoomNum != _roomNum) {
// If in surreal maze, turn off DroppingCrumbs.
if (_roomNum >= 245 && _roomNum <= 280) {
_followingCrumbs = false;
_droppingCrumbs = false;
_numCrumbs = 0;
_breadCrumbs[0]._roomNum = 0;
} else {
bool intersect = false;
for (int idx = 0; idx < _numCrumbs; idx++) {
if (_breadCrumbs[idx]._roomNum == _roomNum) {
_numCrumbs = idx + 1;
_breadCrumbs[_numCrumbs]._roomNum = 0;
intersect = true;
2014-10-06 12:50:05 +00:00
}
}
2014-10-06 12:50:05 +00:00
if (!intersect) {
if (_numCrumbs == MAX_CRUMBS) {
_numCrumbs = MAX_CRUMBS - 1;
memcpy(&_breadCrumbs[0], &_breadCrumbs[1], _numCrumbs * sizeof _breadCrumbs[0]);
2015-11-30 12:09:36 +00:00
}
_breadCrumbs[_numCrumbs]._roomNum = _roomNum;
_breadCrumbs[_numCrumbs++]._direction = _direction;
2014-10-06 12:50:05 +00:00
}
}
2015-11-30 12:09:36 +00:00
}
mayShowCrumbIndicator();
break;
2015-11-30 12:09:36 +00:00
}
2015-12-14 08:28:30 +00:00
_graphics->screenUpdate();
2015-12-13 17:36:56 +00:00
} else if ((msgClass == BUTTONUP) && _alternate) {
2015-12-01 23:34:51 +00:00
_anim->_doBlack = true;
2014-10-06 12:50:05 +00:00
2015-12-14 08:34:13 +00:00
switch (buttonId) {
case 0:
2015-11-30 12:09:36 +00:00
eatMessages();
_alternate = false;
2015-12-01 23:34:51 +00:00
_anim->_doBlack = true;
2015-12-06 16:24:25 +00:00
_graphics->_doNotDrawMessage = false;
2014-10-06 12:50:05 +00:00
_mainDisplay = true;
2015-12-13 17:36:56 +00:00
// Sets the correct button list
2015-12-08 10:27:34 +00:00
interfaceOn();
_graphics->drawPanel();
drawRoomMessage(curInv, _closeDataPtr);
2015-12-14 08:34:13 +00:00
break;
2014-10-06 12:50:05 +00:00
2015-12-14 08:34:13 +00:00
case 1:
2015-11-30 12:09:36 +00:00
interfaceOff();
2015-12-01 19:10:42 +00:00
_anim->stopDiff();
_curFileName = " ";
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
doit = !saveRestoreGame();
_closeDataPtr = nullptr;
_mainDisplay = true;
2014-10-06 12:50:05 +00:00
curInv = kItemMap;
lastInv = kItemMap;
2014-12-27 13:18:40 +00:00
_nextFileName = getInvName(curInv);
2014-10-06 12:50:05 +00:00
_graphics->drawPanel();
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
if (doit) {
_graphics->drawMessage("Disk operation failed.");
2015-12-06 13:36:49 +00:00
_graphics->setPalette(initcolors, 8);
2015-11-30 12:09:36 +00:00
g_system->delayMillis(1000);
}
2015-12-14 08:26:55 +00:00
break;
2015-12-14 08:34:13 +00:00
case 2:
2015-11-30 12:09:36 +00:00
if (!doUse(curInv)) {
2015-12-06 16:24:25 +00:00
uint16 oldActionMode = actionMode;
2015-12-08 10:27:34 +00:00
// Use button
actionMode = 5;
2014-10-06 12:50:05 +00:00
2015-12-06 16:24:25 +00:00
if (oldActionMode < 5)
2015-12-13 17:36:56 +00:00
perFlipButton(oldActionMode);
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
drawStaticMessage(kTextUseOnWhat);
_mainDisplay = true;
2015-11-30 12:09:36 +00:00
}
2015-12-14 08:26:55 +00:00
break;
2015-12-14 08:34:13 +00:00
case 3:
_mainDisplay = !_mainDisplay;
2014-10-06 12:50:05 +00:00
2015-12-06 16:24:25 +00:00
if ((curInv == 0) || (curInv > _numInv)) {
2015-11-30 12:09:36 +00:00
curInv = 1;
2014-10-06 12:50:05 +00:00
2015-12-06 16:24:25 +00:00
while ((curInv <= _numInv) && (!_conditions->in(curInv)))
2015-11-30 12:09:36 +00:00
curInv++;
}
2014-10-06 12:50:05 +00:00
2015-12-08 08:19:00 +00:00
if ((curInv <= _numInv) && _conditions->in(curInv) && _inventory[curInv]._bitmapName)
_nextFileName = getInvName(curInv);
2014-10-06 12:50:05 +00:00
2015-12-14 08:26:55 +00:00
break;
2015-12-14 08:34:13 +00:00
case 4:
2015-12-13 17:36:56 +00:00
// Left button
2015-11-30 12:09:36 +00:00
decIncInv(&curInv, true);
2015-12-06 16:24:25 +00:00
lastInv = curInv;
_graphics->_doNotDrawMessage = false;
drawRoomMessage(curInv, _closeDataPtr);
2015-12-14 08:26:55 +00:00
break;
2015-12-14 08:34:13 +00:00
case 5:
2015-12-13 17:36:56 +00:00
// Right button
2015-11-30 12:09:36 +00:00
decIncInv(&curInv, false);
2015-12-06 16:24:25 +00:00
lastInv = curInv;
_graphics->_doNotDrawMessage = false;
drawRoomMessage(curInv, _closeDataPtr);
2015-12-14 08:26:55 +00:00
break;
2015-12-14 08:34:13 +00:00
case 6:
2015-12-08 10:27:34 +00:00
// bread crumbs
2015-11-30 12:09:36 +00:00
_breadCrumbs[0]._roomNum = 0;
_numCrumbs = 0;
_droppingCrumbs = true;
mayShowCrumbIndicator();
2015-12-14 08:26:55 +00:00
break;
2015-12-14 08:34:13 +00:00
case 7:
2015-12-08 10:27:34 +00:00
// follow crumbs
2015-11-30 12:09:36 +00:00
if (_droppingCrumbs) {
if (_numCrumbs > 0) {
_followingCrumbs = true;
_followCrumbsFast = false;
_isCrumbTurning = false;
_isCrumbWaiting = false;
2015-12-13 18:27:34 +00:00
_crumbTimestamp = g_system->getMillis();
2014-10-06 12:50:05 +00:00
eatMessages();
_alternate = false;
2015-12-01 23:34:51 +00:00
_anim->_doBlack = true;
2015-12-06 16:24:25 +00:00
_graphics->_doNotDrawMessage = false;
2014-10-06 12:50:05 +00:00
_mainDisplay = true;
2015-12-13 17:36:56 +00:00
// Sets the correct button list
2015-12-08 10:27:34 +00:00
interfaceOn();
_graphics->drawPanel();
drawRoomMessage(curInv, _closeDataPtr);
2015-11-30 12:09:36 +00:00
} else {
_breadCrumbs[0]._roomNum = 0;
_droppingCrumbs = false;
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
// Need to hide indicator!!!!
mayShowCrumbIndicatorOff();
2014-10-06 12:50:05 +00:00
}
2015-11-30 12:09:36 +00:00
}
2015-12-14 08:26:55 +00:00
break;
2015-11-30 12:09:36 +00:00
}
2015-12-14 08:28:30 +00:00
_graphics->screenUpdate();
2015-12-08 20:53:42 +00:00
} else if ((msgClass == MOUSEBUTTONS) && (IEQUALIFIER_LEFTBUTTON & qualifier) && _mainDisplay) {
2015-11-30 12:09:36 +00:00
interfaceOff();
_mainDisplay = true;
2014-10-06 12:50:05 +00:00
2015-11-30 12:09:36 +00:00
doit = false;
2014-10-06 12:50:05 +00:00
if (_closeDataPtr) {
switch (_closeDataPtr->_closeUpType) {
case SPECIALLOCK:
if (_mainDisplay)
_tilePuzzle->mouseCombination(curPos);
break;
case SPECIALBRICK:
if (_mainDisplay)
_tilePuzzle->mouseTile(curPos);
break;
default:
2015-11-30 12:09:36 +00:00
doit = true;
break;
}
2015-11-30 12:09:36 +00:00
} else
doit = true;
if (doit) {
wrkClosePtr = nullptr;
2015-11-30 12:09:36 +00:00
eatMessages();
switch (actionMode) {
case 0:
2015-12-08 10:27:34 +00:00
// Take something.
if (doActionRule(Common::Point(curPos.x, curPos.y), actionMode, _roomNum, &_closeDataPtr))
_curFileName = _newFileName;
else if (takeItem(curPos.x, curPos.y, &_closeDataPtr))
2015-11-30 12:09:36 +00:00
drawStaticMessage(kTextTakeItem);
else if (doActionRule(curPos, TAKEDEF - 1, _roomNum, &_closeDataPtr))
_curFileName = _newFileName;
else if (doActionRule(curPos, TAKE - 1, 0, &_closeDataPtr))
_curFileName = _newFileName;
else if (curPos.y < (_utils->vgaScaleY(149) + _utils->svgaCord(2)))
2015-11-30 12:09:36 +00:00
drawStaticMessage(kTextNothing);
break;
case 1:
case 2:
case 3:
2015-12-08 10:27:34 +00:00
// Manipulate an object, Open up a "door" or Close a "door"
if (doActionRule(curPos, actionMode, _roomNum, &_closeDataPtr))
_curFileName = _newFileName;
else if (!doActionRule(curPos, actionMode, 0, &_closeDataPtr)) {
if (curPos.y < (_utils->vgaScaleY(149) + _utils->svgaCord(2)))
2015-11-30 12:09:36 +00:00
drawStaticMessage(kTextNothing);
2014-10-06 12:50:05 +00:00
}
break;
2015-11-30 12:09:36 +00:00
case 4: {
// Look at closeups
CloseDataPtr tmpClosePtr = _closeDataPtr;
setCurrentClose(curPos, &tmpClosePtr, true);
if (_closeDataPtr == tmpClosePtr) {
if (curPos.y < (_utils->vgaScaleY(149) + _utils->svgaCord(2)))
drawStaticMessage(kTextNothing);
} else if (tmpClosePtr->_graphicName) {
if (*(tmpClosePtr->_graphicName)) {
_anim->_doBlack = true;
_closeDataPtr = tmpClosePtr;
} else if (curPos.y < (_utils->vgaScaleY(149) + _utils->svgaCord(2)))
drawStaticMessage(kTextNothing);
} else if (curPos.y < (_utils->vgaScaleY(149) + _utils->svgaCord(2)))
2015-11-30 12:09:36 +00:00
drawStaticMessage(kTextNothing);
}
break;
2015-11-30 12:09:36 +00:00
case 5:
if (_conditions->in(curInv)) {
// Use an item on something else
if (doOperateRule(curPos, curInv, &_closeDataPtr)) {
_curFileName = _newFileName;
if (!_conditions->in(curInv))
decIncInv(&curInv, false);
} else if (curPos.y < (_utils->vgaScaleY(149) + _utils->svgaCord(2)))
drawStaticMessage(kTextNothing);
}
2014-10-06 12:50:05 +00:00
}
}
2015-11-30 12:09:36 +00:00
mayShowCrumbIndicator();
_graphics->screenUpdate();
2015-11-30 12:09:36 +00:00
} else if (msgClass == DELTAMOVE) {
2015-12-08 21:00:19 +00:00
ViewData *vptr = getViewData(_roomNum, _direction);
CloseDataPtr oldClosePtr = vptr->_closeUps;
2015-11-30 12:09:36 +00:00
if (!wrkClosePtr) {
CloseDataPtr tmpClosePtr = _closeDataPtr;
setCurrentClose(curPos, &tmpClosePtr, true);
2015-11-30 12:09:36 +00:00
if (!tmpClosePtr || (tmpClosePtr == _closeDataPtr)) {
if (!_closeDataPtr)
wrkClosePtr = oldClosePtr;
2015-11-30 12:09:36 +00:00
else
wrkClosePtr = _closeDataPtr->_subCloseUps;
2015-11-30 12:09:36 +00:00
} else
wrkClosePtr = tmpClosePtr->_nextCloseUp;
2015-11-30 12:09:36 +00:00
} else
wrkClosePtr = wrkClosePtr->_nextCloseUp;
2014-10-06 12:50:05 +00:00
if (!wrkClosePtr) {
if (!_closeDataPtr)
wrkClosePtr = oldClosePtr;
2015-11-30 12:09:36 +00:00
else
wrkClosePtr = _closeDataPtr->_subCloseUps;
2015-11-30 12:09:36 +00:00
}
2014-10-06 12:50:05 +00:00
if (wrkClosePtr)
_event->setMousePos(Common::Point(_utils->scaleX((wrkClosePtr->_x1 + wrkClosePtr->_x2) / 2), _utils->scaleY((wrkClosePtr->_y1 + wrkClosePtr->_y2) / 2)));
} else if ((msgClass == MOUSEBUTTONS) && (IEQUALIFIER_RIGHTBUTTON & qualifier)) {
2015-11-30 12:09:36 +00:00
eatMessages();
_alternate = !_alternate;
2015-12-01 23:34:51 +00:00
_anim->_doBlack = true;
2015-12-06 16:24:25 +00:00
_graphics->_doNotDrawMessage = false;
_mainDisplay = true;
2015-12-13 17:36:56 +00:00
// Sets the correct button list
2015-12-08 10:27:34 +00:00
interfaceOn();
2015-11-30 12:09:36 +00:00
if (_alternate) {
2015-12-06 16:24:25 +00:00
if (lastInv && _conditions->in(lastInv))
curInv = lastInv;
2015-11-30 12:09:36 +00:00
else
decIncInv(&curInv, false);
2014-10-06 12:50:05 +00:00
}
_graphics->drawPanel();
drawRoomMessage(curInv, _closeDataPtr);
2015-11-30 12:09:36 +00:00
mayShowCrumbIndicator();
_graphics->screenUpdate();
2014-10-06 12:50:05 +00:00
}
2015-11-30 12:09:36 +00:00
return true;
2014-10-06 12:50:05 +00:00
}
2014-12-27 13:18:40 +00:00
void LabEngine::go() {
2015-11-29 23:12:01 +00:00
_isHiRes = ((getFeatures() & GF_LOWRES) == 0);
2015-12-08 15:19:08 +00:00
_graphics->setUpScreens();
2014-10-06 12:50:05 +00:00
_event->initMouse();
2015-12-03 10:01:50 +00:00
_msgFont = _resource->getFont("P:AvanteG.12");
_event->mouseHide();
2015-12-04 20:10:07 +00:00
Intro *intro = new Intro(this);
intro->introSequence();
delete intro;
2014-10-06 12:50:05 +00:00
_event->mouseShow();
mainGameLoop();
2014-10-06 12:50:05 +00:00
_graphics->closeFont(_msgFont);
_graphics->freePict();
2014-10-06 12:50:05 +00:00
2015-12-02 19:32:06 +00:00
freeScreens();
_music->freeMusic();
2014-10-06 12:50:05 +00:00
}
/**
* New code to allow quick(er) return navigation in game.
*/
int LabEngine::followCrumbs() {
2014-10-06 12:50:05 +00:00
// NORTH, SOUTH, EAST, WEST
2015-12-13 03:00:10 +00:00
int movement[4][4] = {
2014-12-27 13:18:40 +00:00
{ VKEY_UPARROW, VKEY_RTARROW, VKEY_RTARROW, VKEY_LTARROW },
{ VKEY_RTARROW, VKEY_UPARROW, VKEY_LTARROW, VKEY_RTARROW },
{ VKEY_LTARROW, VKEY_RTARROW, VKEY_UPARROW, VKEY_RTARROW },
{ VKEY_RTARROW, VKEY_LTARROW, VKEY_RTARROW, VKEY_UPARROW }
2014-10-06 12:50:05 +00:00
};
if (_isCrumbWaiting) {
2015-12-13 18:27:34 +00:00
if (g_system->getMillis() <= _crumbTimestamp)
2014-10-06 12:50:05 +00:00
return 0;
_isCrumbWaiting = false;
2014-10-06 12:50:05 +00:00
}
if (!_isCrumbTurning)
_breadCrumbs[_numCrumbs--]._roomNum = 0;
2014-10-06 12:50:05 +00:00
// Is the current crumb this room? If not, logic error.
2015-12-06 17:31:57 +00:00
if (_roomNum != _breadCrumbs[_numCrumbs]._roomNum) {
_numCrumbs = 0;
_breadCrumbs[0]._roomNum = 0;
_droppingCrumbs = false;
_followingCrumbs = false;
2014-10-06 12:50:05 +00:00
return 0;
}
int exitDir;
2014-10-06 12:50:05 +00:00
// which direction is last crumb
if (_breadCrumbs[_numCrumbs]._direction == EAST)
exitDir = WEST;
else if (_breadCrumbs[_numCrumbs]._direction == WEST)
exitDir = EAST;
else if (_breadCrumbs[_numCrumbs]._direction == NORTH)
exitDir = SOUTH;
2014-10-06 12:50:05 +00:00
else
exitDir = NORTH;
2014-10-06 12:50:05 +00:00
2015-12-06 16:24:25 +00:00
int moveDir = movement[_direction][exitDir];
2014-10-06 12:50:05 +00:00
if (_numCrumbs == 0) {
_isCrumbTurning = false;
_breadCrumbs[0]._roomNum = 0;
_droppingCrumbs = false;
_followingCrumbs = false;
2014-10-06 12:50:05 +00:00
} else {
_isCrumbTurning = (moveDir != VKEY_UPARROW);
_isCrumbWaiting = true;
2014-10-06 12:50:05 +00:00
2015-12-13 18:27:34 +00:00
int theDelay = (_followCrumbsFast ? 1000 / 4 : 1000);
_crumbTimestamp = theDelay + g_system->getMillis();
2014-10-06 12:50:05 +00:00
}
return moveDir;
2014-10-06 12:50:05 +00:00
}
2015-11-24 22:59:30 +00:00
void LabEngine::mayShowCrumbIndicator() {
2015-12-13 21:51:23 +00:00
static byte dropCrumbs[] = { 0x00 };
static Image dropCrumbsImage(24, 24, dropCrumbs, this);
2015-11-24 22:59:30 +00:00
if (getPlatform() != Common::kPlatformWindows)
2014-12-27 13:18:40 +00:00
return;
if (_droppingCrumbs && _mainDisplay) {
_event->mouseHide();
dropCrumbsImage.drawMaskImage(612, 4);
_event->mouseShow();
2014-10-06 12:50:05 +00:00
}
}
2015-11-24 22:59:30 +00:00
void LabEngine::mayShowCrumbIndicatorOff() {
2015-12-13 21:51:23 +00:00
static byte dropCrumbsOff[] = { 0x00 };
static Image dropCrumbsOffImage(24, 24, dropCrumbsOff, this);
2015-11-24 22:59:30 +00:00
if (getPlatform() != Common::kPlatformWindows)
2014-12-27 13:18:40 +00:00
return;
if (_mainDisplay) {
_event->mouseHide();
dropCrumbsOffImage.drawMaskImage(612, 4);
_event->mouseShow();
2014-10-06 12:50:05 +00:00
}
}
} // End of namespace Lab