diff options
Diffstat (limited to 'engines/mortevielle/utils.cpp')
-rw-r--r-- | engines/mortevielle/utils.cpp | 3405 |
1 files changed, 3405 insertions, 0 deletions
diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp new file mode 100644 index 0000000000..c4f2d5714b --- /dev/null +++ b/engines/mortevielle/utils.cpp @@ -0,0 +1,3405 @@ +/* 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 original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" + +#include "mortevielle/dialogs.h" +#include "mortevielle/menu.h" +#include "mortevielle/mouse.h" +#include "mortevielle/outtext.h" + +#include "common/scummsys.h" +#include "graphics/cursorman.h" + +namespace Mortevielle { + +/** + * Check is a key was pressed + * It also delays the engine and check if the screen has to be updated + * @remarks Originally called 'keypressed' + */ +bool MortevielleEngine::keyPressed() { + // Check for any pending key presses + handleEvents(); + + // Check if it's time to draw the next frame + if (g_system->getMillis() > (_lastGameFrame + GAME_FRAME_DELAY)) { + _lastGameFrame = g_system->getMillis(); + + _screenSurface.updateScreen(); + + _debugger.onFrame(); + } + + // Delay briefly to keep CPU usage down + g_system->delayMillis(5); + + // Return if there are any pending key presses + return !_keypresses.empty(); +} + +/** + * Wait for a keypress + * @remarks Originally called 'get_ch' + */ +int MortevielleEngine::getChar() { + bool end = false; + // If there isn't any pending keypress, wait until there is + while (!shouldQuit() && !end) { + end = keyPressed(); + } + + // Return the top keypress + return shouldQuit() ? 0 : _keypresses.pop(); +} + +/** + * Handle pending events + * @remarks Since the ScummVM screen surface is double height to handle 640x200 using 640x400, + * the mouse Y position is divided by 2 to keep the game thinking the Y goes from 0 - 199 + */ +bool MortevielleEngine::handleEvents() { + Common::Event event; + if (!g_system->getEventManager()->pollEvent(event)) + return false; + + switch (event.type) { + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + case Common::EVENT_MOUSEMOVE: + _mousePos = Common::Point(event.mouse.x, event.mouse.y / 2); + _mouse._pos.x = event.mouse.x; + _mouse._pos.y = event.mouse.y / 2; + + if (event.type == Common::EVENT_LBUTTONDOWN) + _mouseClick = true; + else if (event.type == Common::EVENT_LBUTTONUP) + _mouseClick = false; + + break; + case Common::EVENT_KEYDOWN: + addKeypress(event); + break; + default: + break; + } + + return true; +} + +/** + * Add the specified key to the pending keypress stack + */ +void MortevielleEngine::addKeypress(Common::Event &evt) { + // Character to add + char ch = evt.kbd.ascii; + + // Check for debugger + if ((evt.kbd.keycode == Common::KEYCODE_d) && (evt.kbd.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _debugger.attach(); + _debugger.onFrame(); + } else if ((evt.kbd.keycode >= Common::KEYCODE_a) && (evt.kbd.keycode <= Common::KEYCODE_z)) { + // Handle alphabetic keys + if (evt.kbd.hasFlags(Common::KBD_CTRL)) + ch = evt.kbd.keycode - Common::KEYCODE_a + 1; + else + ch = evt.kbd.keycode - Common::KEYCODE_a + 'A'; + } else if ((evt.kbd.keycode >= Common::KEYCODE_F1) && (evt.kbd.keycode <= Common::KEYCODE_F12)) { + // Handle function keys + ch = 59 + evt.kbd.keycode - Common::KEYCODE_F1; + } else { + // Series of special cases + switch (evt.kbd.keycode) { + case Common::KEYCODE_KP4: + case Common::KEYCODE_LEFT: + ch = '4'; + break; + case Common::KEYCODE_KP2: + case Common::KEYCODE_DOWN: + ch = '2'; + break; + case Common::KEYCODE_KP6: + case Common::KEYCODE_RIGHT: + ch = '6'; + break; + case Common::KEYCODE_KP8: + case Common::KEYCODE_UP: + ch = '8'; + break; + case Common::KEYCODE_KP7: + ch = '7'; + break; + case Common::KEYCODE_KP1: + ch = '1'; + break; + case Common::KEYCODE_KP9: + ch = '9'; + break; + case Common::KEYCODE_KP3: + ch = '3'; + break; + case Common::KEYCODE_KP5: + ch = '5'; + break; + case Common::KEYCODE_RETURN: + ch = '\13'; + break; + case Common::KEYCODE_ESCAPE: + ch = '\33'; + break; + default: + break; + } + } + + if (ch != 0) + _keypresses.push(ch); +} + + +static const byte CURSOR_ARROW_DATA[16 * 16] = { + 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +/** + * Initialize the mouse + */ +void MortevielleEngine::initMouse() { + CursorMan.replaceCursor(CURSOR_ARROW_DATA, 16, 16, 0, 0, 0xff); + CursorMan.showMouse(true); + + _mouse.initMouse(); +} + +/** + * Sets the mouse position + * @remarks Since the ScummVM screen surface is double height to handle 640x200 using 640x400, + * the mouse Y position is doubled to convert from 0-199 to 0-399 + */ +void MortevielleEngine::setMousePos(const Common::Point &pt) { + // Adjust the passed position from simulated 640x200 to 640x400 co-ordinates + Common::Point newPoint(pt.x, (pt.y == 199) ? 399 : pt.y * 2); + + if (newPoint != _mousePos) + // Warp the mouse to the new position + g_system->warpMouse(newPoint.x, newPoint.y); + + // Save the new position + _mousePos = newPoint; +} + +/** + * Delay by a given amount + */ +void MortevielleEngine::delay(int amount) { + uint32 endTime = g_system->getMillis() + amount; + + while (g_system->getMillis() < endTime) { + if (g_system->getMillis() > (_lastGameFrame + GAME_FRAME_DELAY)) { + _lastGameFrame = g_system->getMillis(); + _screenSurface.updateScreen(); + + _debugger.onFrame(); + } + + g_system->delayMillis(10); + } +} + +/** + * Waits for the user to select an action, and then handles it + * @remarks Originally called tecran + */ +void MortevielleEngine::handleAction() { + const int lim = 20000; + int temps = 0; + char inkey = '\0'; + bool funct = false; + + clearVerbBar(); + + bool handledOpcodeFl = false; + _controlMenu = 0; + if (!_keyPressedEsc) { + _menu.drawMenu(); + _menu._menuDisplayed = true; + temps = 0; + _key = 0; + funct = false; + inkey = '.'; + + _inMainGameLoop = true; + do { + _menu.updateMenu(); + prepareRoom(); + _mouse.moveMouse(funct, inkey); + if (shouldQuit()) + return; + ++temps; + if (keyPressed() || _mouseClick) { + _soundManager._mixer->stopHandle(_soundManager._soundHandle); + } + } while (!((_menu._menuSelected) || (temps > lim) || (funct) || (_anyone))); + _inMainGameLoop = false; + + _menu.eraseMenu(); + _menu._menuDisplayed = false; + if (_menu._menuSelected && (_currMenu == MENU_SAVE)) { + Common::String saveName = Common::String::format("Savegame #%d", _currAction & 15); + _savegameManager.saveGame(_currAction & 15, saveName); + } + if (_menu._menuSelected && (_currMenu == MENU_LOAD)) + _savegameManager.loadGame((_currAction & 15) - 1); + if (inkey == '\103') { /* F9 */ + temps = _dialogManager.show(_hintPctMessage); + return; + } else if (inkey == '\77') { + if ((_menuOpcode != OPCODE_NONE) && ((_currMenu == MENU_ACTION) || (_currMenu == MENU_SELF))) { + _currAction = _menuOpcode; + displayTextInVerbBar(getEngineString(S_IDEM)); + } else + return; + } else if (inkey == '\104') { + if ((_x != 0) && (_y != 0)) + _num = 9999; + return; + } + } + if (inkey == '\73') { + _quitGame = true; + hourToChar(); + } else { + if ((funct) && (inkey != '\77')) + return; + if (temps > lim) { + handleDescriptionText(2, 141); + if (_num == 9999) + _num = 0; + } else { + _menuOpcode = _currMenu; + if ((_currMenu == MENU_ACTION) || (_currMenu == MENU_SELF)) + _menuOpcode = _currAction; + if (!_anyone) { + if ((_heroSearching) || (_obpart)) { + if (_mouse._pos.y < 12) + return; + + if ((_currAction == _menu._opcodeSound) || (_currAction == _menu._opcodeLift)) { + handledOpcodeFl = true; + if ((_currAction == _menu._opcodeLift) || (_obpart)) { + endSearch(); + _caff = _coreVar._currPlace; + _crep = 998; + } else + prepareNextObject(); + menuUp(); + } + } + } + do { + if (!handledOpcodeFl) + handleOpcode(); + + if ((_controlMenu == 0) && (! _loseGame) && (! _endGame)) { + _text.taffich(); + if (_destinationOk) { + _destinationOk = false; + drawPicture(); + } + if ((!_syn) || (_col)) + handleDescriptionText(2, _crep); + } + } while (_syn); + if (_controlMenu != 0) + displayControlMenu(); + } + } +} + +/** + * Engine function - Init Places + * @remarks Originally called 'init_lieu' + */ +void MortevielleEngine::loadPlaces() { + Common::File f; + + if (!f.open("MXX.mor")) + if (!f.open("MFXX.mor")) + error("Missing file - MXX.mor"); + + for (int i = 0; i < 7; ++i) { + for (int j = 0; j < 25; ++j) + _destinationArray[i][j] = f.readByte(); + } + + f.close(); +} + +/** + * Set Text Color + * @remarks Originally called 'text_color' + */ +void MortevielleEngine::setTextColor(int col) { + _textColor = col; +} + +/** + * Prepare screen - Type 1! + * @remarks Originally called 'ecrf1' + */ +void MortevielleEngine::prepareScreenType1() { + // Large drawing + _screenSurface.drawBox(0, 11, 512, 164, 15); +} + +/** + * Prepare room - Type 2! + * @remarks Originally called 'ecrf2' + */ +void MortevielleEngine::prepareScreenType2() { + setTextColor(5); +} + +/** + * Prepare room - Type 3! + * @remarks Originally called 'ecrf7' + */ +void MortevielleEngine::prepareScreenType3() { + setTextColor(4); +} + +/** + * Engine function - Update hour + * @remarks Originally called 'calch' + */ +void MortevielleEngine::updateHour(int &day, int &hour, int &minute) { + int newTime = readclock(); + int th = _currentHourCount + ((newTime - _currentTime) / _inGameHourDuration); + minute = ((th % 2) + _currHalfHour) * 30; + hour = ((uint)th >> 1) + _currHour; + if (minute == 60) { + minute = 0; + ++hour; + } + day = (hour / 24) + _currDay; + hour = hour - ((day - _currDay) * 24); +} + +/** + * Engine function - Convert character index to bit index + * @remarks Originally called 'conv' + */ +int MortevielleEngine::convertCharacterIndexToBitIndex(int characterIndex) { + return 128 >> (characterIndex - 1); +} + +/** + * Engine function - Convert bit index to character index + * @remarks Originally called 'tip' + */ +int MortevielleEngine::convertBitIndexToCharacterIndex(int bitIndex) { + int retVal = 0; + + if (bitIndex == 128) + retVal = 1; + else if (bitIndex == 64) + retVal = 2; + else if (bitIndex == 32) + retVal = 3; + else if (bitIndex == 16) + retVal = 4; + else if (bitIndex == 8) + retVal = 5; + else if (bitIndex == 4) + retVal = 6; + else if (bitIndex == 2) + retVal = 7; + else if (bitIndex == 1) + retVal = 8; + + return retVal; +} + +/** + * Engine function - Reset presence in other rooms + * @remarks Originally called 't5' + */ +void MortevielleEngine::resetPresenceInRooms(int roomId) { + if (roomId == DINING_ROOM) + _blo = false; + + if (roomId != GREEN_ROOM) { + _roomPresenceLuc = false; + _roomPresenceIda = false; + } + + if (roomId != PURPLE_ROOM) + _purpleRoomPresenceLeo = false; + + if (roomId != DARKBLUE_ROOM) { + _roomPresenceGuy = false; + _roomPresenceEva = false; + } + + if (roomId != BLUE_ROOM) + _roomPresenceMax = false; + if (roomId != RED_ROOM) + _roomPresenceBob = false; + if (roomId != GREEN_ROOM2) + _roomPresencePat = false; + if (roomId != TOILETS) + _toiletsPresenceBobMax = false; + if (roomId != BATHROOM) + _bathRoomPresenceBobMax = false; + if (roomId != JULIA_ROOM) + _juliaRoomPresenceLeo = false; +} + +/** + * Engine function - Show the people present in the given room + * @remarks Originally called 'affper' + */ +void MortevielleEngine::showPeoplePresent(int bitIndex) { + int xp = 580 - (_screenSurface.getStringWidth("LEO") / 2); + + for (int i = 1; i <= 8; ++i) + _menu.disableMenuItem(_menu._discussMenu[i]); + + clearUpperRightPart(); + if ((bitIndex & 128) == 128) { + _screenSurface.putxy(xp, 24); + _screenSurface.drawString("LEO", 4); + _menu.enableMenuItem(_menu._discussMenu[1]); + } + if ((bitIndex & 64) == 64) { + _screenSurface.putxy(xp, 32); + _screenSurface.drawString("PAT", 4); + _menu.enableMenuItem(_menu._discussMenu[2]); + } + if ((bitIndex & 32) == 32) { + _screenSurface.putxy(xp, 40); + _screenSurface.drawString("GUY", 4); + _menu.enableMenuItem(_menu._discussMenu[3]); + } + if ((bitIndex & 16) == 16) { + _screenSurface.putxy(xp, 48); + _screenSurface.drawString("EVA", 4); + _menu.enableMenuItem(_menu._discussMenu[4]); + } + if ((bitIndex & 8) == 8) { + _screenSurface.putxy(xp, 56); + _screenSurface.drawString("BOB", 4); + _menu.enableMenuItem(_menu._discussMenu[5]); + } + if ((bitIndex & 4) == 4) { + _screenSurface.putxy(xp, 64); + _screenSurface.drawString("LUC", 4); + _menu.enableMenuItem(_menu._discussMenu[6]); + } + if ((bitIndex & 2) == 2) { + _screenSurface.putxy(xp, 72); + _screenSurface.drawString("IDA", 4); + _menu.enableMenuItem(_menu._discussMenu[7]); + } + if ((bitIndex & 1) == 1) { + _screenSurface.putxy(xp, 80); + _screenSurface.drawString("MAX", 4); + _menu.enableMenuItem(_menu._discussMenu[8]); + } + _currBitIndex = bitIndex; +} + +/** + * Engine function - Select random characters + * @remarks Originally called 'choix' + */ +int MortevielleEngine::selectCharacters(int min, int max) { + bool invertSelection = false; + int rand = getRandomNumber(min, max); + + if (rand > 4) { + rand = 8 - rand; + invertSelection = true; + } + + int i = 0; + int retVal = 0; + while (i < rand) { + int charIndex = getRandomNumber(1, 8); + int charBitIndex = convertCharacterIndexToBitIndex(charIndex); + if ((retVal & charBitIndex) != charBitIndex) { + ++i; + retVal |= charBitIndex; + } + } + if (invertSelection) + retVal = 255 - retVal; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Green Room + * @remarks Originally called 'cpl1' + */ +int MortevielleEngine::getPresenceStatsGreenRoom() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + // The original uses an || instead of an &&, resulting + // in an always true condition. Based on the other tests, + // and on other scenes, we use an && instead. + if ((hour > 7) && (hour < 11)) + retVal = 25; + else if ((hour > 10) && (hour < 14)) + retVal = 35; + else if ((hour > 13) && (hour < 16)) + retVal = 50; + else if ((hour > 15) && (hour < 18)) + retVal = 5; + else if ((hour > 17) && (hour < 22)) + retVal = 35; + else if ((hour > 21) && (hour < 24)) + retVal = 50; + else if ((hour >= 0) && (hour < 8)) + retVal = 70; + + _menu.updateMenu(); + + return retVal; +} +/** + * Engine function - Get Presence Statistics - Purple Room + * @remarks Originally called 'cpl2' + */ +int MortevielleEngine::getPresenceStatsPurpleRoom() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if ((hour > 7) && (hour < 11)) + retVal = -2; + else if (hour == 11) + retVal = 100; + else if ((hour > 11) && (hour < 23)) + retVal = 10; + else if (hour == 23) + retVal = 20; + else if ((hour >= 0) && (hour < 8)) + retVal = 50; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Toilets + * @remarks Originally called 'cpl3' + */ +int MortevielleEngine::getPresenceStatsToilets() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (((hour > 8) && (hour < 10)) || ((hour > 19) && (hour < 24))) + retVal = 34; + else if (((hour > 9) && (hour < 20)) || ((hour >= 0) && (hour < 9))) + retVal = 0; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Blue Room + * @remarks Originally called 'cpl5' + */ +int MortevielleEngine::getPresenceStatsBlueRoom() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if ((hour > 6) && (hour < 10)) + retVal = 0; + else if (hour == 10) + retVal = 100; + else if ((hour > 10) && (hour < 24)) + retVal = 15; + else if ((hour >= 0) && (hour < 7)) + retVal = 50; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Red Room + * @remarks Originally called 'cpl6' + */ +int MortevielleEngine::getPresenceStatsRedRoom() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (((hour > 7) && (hour < 13)) || ((hour > 17) && (hour < 20))) + retVal = -2; + else if (((hour > 12) && (hour < 17)) || ((hour > 19) && (hour < 24))) + retVal = 35; + else if (hour == 17) + retVal = 100; + else if ((hour >= 0) && (hour < 8)) + retVal = 60; + + return retVal; +} + +/** + * Shows the "you are alone" message in the status area + * on the right hand side of the screen + * @remarks Originally called 'person' + */ +void MortevielleEngine::displayAloneText() { + for (int i = 1; i <= 8; ++i) + _menu.disableMenuItem(_menu._discussMenu[i]); + + Common::String sYou = getEngineString(S_YOU); + Common::String sAre = getEngineString(S_ARE); + Common::String sAlone = getEngineString(S_ALONE); + + clearUpperRightPart(); + _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sYou) / 2), 30); + _screenSurface.drawString(sYou, 4); + _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sAre) / 2), 50); + _screenSurface.drawString(sAre, 4); + _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sAlone) / 2), 70); + _screenSurface.drawString(sAlone, 4); + + _currBitIndex = 0; +} + +/** + * Engine function - Get Presence Statistics - Room Bureau + * @remarks Originally called 'cpl10' + */ +int MortevielleEngine::getPresenceStatsDiningRoom(int &hour) { + int day, minute; + + int retVal = 0; + updateHour(day, hour, minute); + if (((hour > 7) && (hour < 11)) || ((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21))) + retVal = 100; + else if ((hour == 11) || ((hour > 20) && (hour < 24))) + retVal = 45; + else if (((hour > 13) && (hour < 17)) || (hour == 18)) + retVal = 35; + else if (hour == 17) + retVal = 60; + else if ((hour >= 0) && (hour < 8)) + retVal = 5; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Room Bureau + * @remarks Originally called 'cpl11' + */ +int MortevielleEngine::getPresenceStatsBureau(int &hour) { + int day, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (((hour > 8) && (hour < 12)) || ((hour > 20) && (hour < 24))) + retVal = 25; + else if (((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21))) + retVal = 5; + else if ((hour > 13) && (hour < 17)) + retVal = 55; + else if ((hour > 16) && (hour < 19)) + retVal = 45; + else if ((hour >= 0) && (hour < 9)) + retVal = 0; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Room Kitchen + * @remarks Originally called 'cpl12' + */ +int MortevielleEngine::getPresenceStatsKitchen() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (((hour > 8) && (hour < 15)) || ((hour > 16) && (hour < 22))) + retVal = 55; + else if (((hour > 14) && (hour < 17)) || ((hour > 21) && (hour < 24))) + retVal = 25; + else if ((hour >= 0) && (hour < 5)) + retVal = 0; + else if ((hour > 4) && (hour < 9)) + retVal = 15; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Room Attic + * @remarks Originally called 'cpl13' + */ +int MortevielleEngine::getPresenceStatsAttic() { + return 0; +} + +/** + * Engine function - Get Presence Statistics - Room Landing + * @remarks Originally called 'cpl15' + */ +int MortevielleEngine::getPresenceStatsLanding() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if ((hour > 7) && (hour < 12)) + retVal = 25; + else if ((hour > 11) && (hour < 14)) + retVal = 0; + else if ((hour > 13) && (hour < 18)) + retVal = 10; + else if ((hour > 17) && (hour < 20)) + retVal = 55; + else if ((hour > 19) && (hour < 22)) + retVal = 5; + else if ((hour > 21) && (hour < 24)) + retVal = 15; + else if ((hour >= 0) && (hour < 8)) + retVal = -15; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Room Chapel + * @remarks Originally called 'cpl20' + */ +int MortevielleEngine::getPresenceStatsChapel(int &hour) { + int day, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (hour == 10) + retVal = 65; + else if ((hour > 10) && (hour < 21)) + retVal = 5; + else if ((hour > 20) && (hour < 24)) + retVal = -15; + else if ((hour >= 0) && (hour < 5)) + retVal = -300; + else if ((hour > 4) && (hour < 10)) + retVal = -5; + + return retVal; +} + +/** + * Engine function - Check who is in the Green Room + * @remarks Originally called 'quelq1' + */ +void MortevielleEngine::setPresenceGreenRoom(int roomId) { + int rand = getRandomNumber(1, 2); + if (roomId == GREEN_ROOM) { + if (rand == 1) + _roomPresenceLuc = true; + else + _roomPresenceIda = true; + } else if (roomId == DARKBLUE_ROOM) { + if (rand == 1) + _roomPresenceGuy = true; + else + _roomPresenceEva = true; + } + + _currBitIndex = 10; +} + +/** + * Engine function - Check who is in the Purple Room + * @remarks Originally called 'quelq2' + */ +void MortevielleEngine::setPresencePurpleRoom() { + if (_place == PURPLE_ROOM) + _purpleRoomPresenceLeo = true; + else + _juliaRoomPresenceLeo = true; + + _currBitIndex = 10; +} + +/** + * Engine function - Check who is in the Blue Room + * @remarks Originally called 'quelq5' + */ +void MortevielleEngine::setPresenceBlueRoom() { + _roomPresenceMax = true; + _currBitIndex = 10; +} + +/** + * Engine function - Check who is in the Red Room + * @remarks Originally called 'quelq6' + */ +void MortevielleEngine::setPresenceRedRoom(int roomId) { + if (roomId == RED_ROOM) + _roomPresenceBob = true; + else if (roomId == GREEN_ROOM2) + _roomPresencePat = true; + + _currBitIndex = 10; +} + +/** + * Engine function - Check who is in the Dining Room + * @remarks Originally called 'quelq10' + */ +int MortevielleEngine::setPresenceDiningRoom(int hour) { + int retVal = 0; + + if ((hour >= 0) && (hour < 8)) + retVal = checkLeoMaxRandomPresence(); + else { + int min = 0, max = 0; + if ((hour > 7) && (hour < 10)) { + min = 5; + max = 7; + } else if ((hour > 9) && (hour < 12)) { + min = 1; + max = 4; + } else if (((hour > 11) && (hour < 15)) || ((hour > 18) && (hour < 21))) { + min = 6; + max = 8; + } else if (((hour > 14) && (hour < 19)) || ((hour > 20) && (hour < 24))) { + min = 1; + max = 5; + } + retVal = selectCharacters(min, max); + } + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Check who is in the Bureau + * @remarks Originally called 'quelq11' + */ +int MortevielleEngine::setPresenceBureau(int hour) { + int retVal = 0; + + if ((hour >= 0) && (hour < 8)) + retVal = checkLeoMaxRandomPresence(); + else { + int min = 0, max = 0; + if (((hour > 7) && (hour < 10)) || ((hour > 20) && (hour < 24))) { + min = 1; + max = 3; + } else if (((hour > 9) && (hour < 12)) || ((hour > 13) && (hour < 19))) { + min = 1; + max = 4; + } else if (((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21))) { + min = 1; + max = 2; + } + retVal = selectCharacters(min, max); + } + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Check who is in the Kitchen + * @remarks Originally called 'quelq12' + */ +int MortevielleEngine::setPresenceKitchen() { + int retVal = checkLeoMaxRandomPresence(); + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Check who is in the Landing + * @remarks Originally called 'quelq15' + */ +int MortevielleEngine::setPresenceLanding() { + bool test = false; + int rand = 0; + do { + rand = getRandomNumber(1, 8); + test = (((rand == 1) && (_purpleRoomPresenceLeo || _juliaRoomPresenceLeo)) || + ((rand == 2) && _roomPresencePat) || + ((rand == 3) && _roomPresenceGuy) || + ((rand == 4) && _roomPresenceEva) || + ((rand == 5) && _roomPresenceBob) || + ((rand == 6) && _roomPresenceLuc) || + ((rand == 7) && _roomPresenceIda) || + ((rand == 8) && _roomPresenceMax)); + } while (test); + + int retVal = convertCharacterIndexToBitIndex(rand); + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Check who is in the chapel + * @remarks Originally called 'quelq20' + */ +int MortevielleEngine::setPresenceChapel(int hour) { + int retVal = 0; + + if (((hour >= 0) && (hour < 10)) || ((hour > 18) && (hour < 24))) + retVal = checkLeoMaxRandomPresence(); + else { + int min = 0, max = 0; + if ((hour > 9) && (hour < 12)) { + min = 3; + max = 7; + } else if ((hour > 11) && (hour < 18)) { + min = 1; + max = 2; + } else if (hour == 18) { + min = 2; + max = 4; + } + retVal = selectCharacters(min, max); + } + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Get the answer after you known a door + * @remarks Originally called 'frap' + */ +void MortevielleEngine::getKnockAnswer() { + int day, hour, minute; + + updateHour(day, hour, minute); + if ((hour >= 0) && (hour < 8)) + _crep = 190; + else { + if (getRandomNumber(1, 100) > 70) + _crep = 190; + else + _crep = 147; + } +} + +/** + * Engine function - Get Room Presence Bit Index + * @remarks Originally called 'nouvp' + */ +int MortevielleEngine::getPresenceBitIndex(int roomId) { + int bitIndex = 0; + if (roomId == GREEN_ROOM) { + if (_roomPresenceLuc) + bitIndex = 4; // LUC + if (_roomPresenceIda) + bitIndex = 2; // IDA + } else if ( ((roomId == PURPLE_ROOM) && (_purpleRoomPresenceLeo)) + || ((roomId == JULIA_ROOM) && (_juliaRoomPresenceLeo))) + bitIndex = 128; // LEO + else if (roomId == DARKBLUE_ROOM) { + if (_roomPresenceGuy) + bitIndex = 32; // GUY + if (_roomPresenceEva) + bitIndex = 16; // EVA + } else if ((roomId == BLUE_ROOM) && (_roomPresenceMax)) + bitIndex = 1; // MAX + else if ((roomId == RED_ROOM) && (_roomPresenceBob)) + bitIndex = 8; // BOB + else if ((roomId == GREEN_ROOM2) && (_roomPresencePat)) + bitIndex = 64; // PAT + else if ( ((roomId == TOILETS) && (_toiletsPresenceBobMax)) + || ((roomId == BATHROOM) && (_bathRoomPresenceBobMax)) ) + bitIndex = 9; // BOB + MAX + + if (bitIndex != 9) + showPeoplePresent(bitIndex); + + return bitIndex; +} + +/** + * Engine function - initGame + * @remarks Originally called 'dprog' + */ +void MortevielleEngine::initGame() { + _place = MANOR_FRONT; + _currentHourCount = 0; + if (!_coreVar._alreadyEnteredManor) + _blo = true; + _inGameHourDuration = kTime1; + _currentTime = readclock(); +} + +/** + * Engine function - Set Random Presence - Green Room + * @remarks Originally called 'pl1' + */ +void MortevielleEngine::setRandomPresenceGreenRoom(int faithScore) { + if ( ((_place == GREEN_ROOM) && (!_roomPresenceLuc) && (!_roomPresenceIda)) + || ((_place == DARKBLUE_ROOM) && (!_roomPresenceGuy) && (!_roomPresenceEva)) ) { + int p = getPresenceStatsGreenRoom(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceGreenRoom(_place); + } +} + +/** + * Engine function - Set Random Presence - Purple Room + * @remarks Originally called 'pl2' + */ +void MortevielleEngine::setRandomPresencePurpleRoom(int faithScore) { + if (!_purpleRoomPresenceLeo) { + int p = getPresenceStatsPurpleRoom(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresencePurpleRoom(); + } +} + +/** + * Engine function - Set Random Presence - Blue Room + * @remarks Originally called 'pl5' + */ +void MortevielleEngine::setRandomPresenceBlueRoom(int faithScore) { + if (!_roomPresenceMax) { + int p = getPresenceStatsBlueRoom(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceBlueRoom(); + } +} + +/** + * Engine function - Set Random Presence - Red Room + * @remarks Originally called 'pl6' + */ +void MortevielleEngine::setRandomPresenceRedRoom(int faithScore) { + if ( ((_place == RED_ROOM) && (!_roomPresenceBob)) + || ((_place == GREEN_ROOM2) && (!_roomPresencePat)) ) { + int p = getPresenceStatsRedRoom(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceRedRoom(_place); + } +} + +/** + * Engine function - Set Random Presence - Room 9 + * @remarks Originally called 'pl9' + */ +void MortevielleEngine::setRandomPresenceJuliaRoom(int faithScore) { + if (!_juliaRoomPresenceLeo) { + faithScore = -10; + if (getRandomNumber(1, 100) > faithScore) // always true? + displayAloneText(); + else + setPresencePurpleRoom(); + } +} + +/** + * Engine function - Set Random Presence - Dining Room + * @remarks Originally called 'pl10' + */ +void MortevielleEngine::setRandomPresenceDiningRoom(int faithScore) { + int h; + int p = getPresenceStatsDiningRoom(h); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceDiningRoom(h); +} + +/** + * Engine function - Set Random Presence - Bureau + * @remarks Originally called 'pl11' + */ +void MortevielleEngine::setRandomPresenceBureau(int faithScore) { + int h; + + int p = getPresenceStatsBureau(h); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceBureau(h); +} + +/** + * Engine function - Set Random Presence - Kitchen + * @remarks Originally called 'pl12' + */ +void MortevielleEngine::setRandomPresenceKitchen(int faithScore) { + + int p = getPresenceStatsKitchen(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceKitchen(); +} + +/** + * Engine function - Set Random Presence - Attic / Cellar + * @remarks Originally called 'pl13' + */ +void MortevielleEngine::setRandomPresenceAttic(int faithScore) { + int p = getPresenceStatsAttic(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceKitchen(); +} + +/** + * Engine function - Set Random Presence - Landing + * @remarks Originally called 'pl15' + */ +void MortevielleEngine::setRandomPresenceLanding(int faithScore) { + int p = getPresenceStatsLanding(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceLanding(); +} + +/** + * Engine function - Set Random Presence - Chapel + * @remarks Originally called 'pl20' + */ +void MortevielleEngine::setRandomPresenceChapel(int faithScore) { + int h; + + int p = getPresenceStatsChapel(h); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceChapel(h); +} + +/** + * Start music or speech + * @remarks Originally called 'musique' + */ +void MortevielleEngine::startMusicOrSpeech(int so) { + if (so == 0) { + /* musik(0) */ + ; + } else if ((!_introSpeechPlayed) && (!_coreVar._alreadyEnteredManor)) { + // Type 1: Speech + _soundManager.startSpeech(10, 1, 1); + _introSpeechPlayed = true; + } else { + if (((_coreVar._currPlace == MOUNTAIN) || (_coreVar._currPlace == MANOR_FRONT) || (_coreVar._currPlace == MANOR_BACK)) && (getRandomNumber(1, 3) == 2)) + // Type 1: Speech + _soundManager.startSpeech(9, getRandomNumber(2, 4), 1); + else if ((_coreVar._currPlace == CHAPEL) && (getRandomNumber(1, 2) == 1)) + // Type 1: Speech + _soundManager.startSpeech(8, 1, 1); + else if ((_coreVar._currPlace == WELL) && (getRandomNumber(1, 2) == 2)) + // Type 1: Speech + _soundManager.startSpeech(12, 1, 1); + else if (_coreVar._currPlace == INSIDE_WELL) + // Type 1: Speech + _soundManager.startSpeech(13, 1, 1); + else + // Type 2 : music + _soundManager.startSpeech(getRandomNumber(1, 17), 1, 2); + } +} + +/** + * Engine function - You lose! + * @remarks Originally called 'tperd' + */ +void MortevielleEngine::loseGame() { + resetOpenObjects(); + _roomDoorId = OWN_ROOM; + _curSearchObjId = 0; + _menu.unsetSearchMenu(); + if (!_blo) + getPresence(MANOR_FRONT); + + _loseGame = true; + clearUpperLeftPart(); + _screenSurface.drawBox(60, 35, 400, 50, 15); + handleDescriptionText(9, _crep); + clearDescriptionBar(); + clearVerbBar(); + _col = false; + _syn = false; + _destinationOk = false; +} + +/** + * Engine function - Check inventory for a given object + * @remarks Originally called 'cherjer' + */ +bool MortevielleEngine::checkInventory(int objectId) { + bool retVal = false; + for (int i = 1; i <= 6; ++i) + retVal = (retVal || (_coreVar._inventory[i] == objectId)); + + if (_coreVar._selectedObjectId == objectId) + retVal = true; + + return retVal; +} + +/** + * Engine function - Display Dining Room + * @remarks Originally called 'st1sama' + */ +void MortevielleEngine::displayDiningRoom() { + _coreVar._currPlace = DINING_ROOM; + prepareDisplayText(); +} + +/** + * Engine function - Start non interactive Dialog + * @remarks Originally called 'sparl' + */ +void MortevielleEngine::startDialog(int16 rep) { + const int haut[9] = { 0, 0, 1, -3, 6, -2, 2, 7, -1 }; + int key; + + assert(rep >= 0); + + _mouse.hideMouse(); + Common::String dialogStr = getString(rep + kDialogStringIndex); + _text.displayStr(dialogStr, 230, 4, 65, 26, 5); + _dialogManager.drawF3F8(); + + key = 0; + do { + _soundManager.startSpeech(rep, haut[_caff - 69], 0); + key = _dialogManager.waitForF3F8(); + if (shouldQuit()) + return; + } while (key != 66); + clearScreen(); + _mouse.showMouse(); +} + +/** + * Engine function - End of Search: reset globals + * @remarks Originally called 'finfouill' + */ +void MortevielleEngine::endSearch() { + _heroSearching = false; + _obpart = false; + _searchCount = 0; + _menu.unsetSearchMenu(); +} + +/** + * Engine function - Go to Dining room + * @remarks Originally called 't1sama' + */ +void MortevielleEngine::gotoDiningRoom() { + int day, hour, minute; + + updateHour(day, hour, minute); + if ((hour < 5) && (_coreVar._currPlace > ROOM18)) { + if (!checkInventory(137)) { //You don't have the keys, and it's late + _crep = 1511; + loseGame(); + } else + displayDiningRoom(); + } else if (!_coreVar._alreadyEnteredManor) { //Is it your first time? + _currBitIndex = 255; // Everybody is present + showPeoplePresent(_currBitIndex); + _caff = 77; + drawPictureWithText(); + _screenSurface.drawBox(223, 47, 155, 92, 15); + handleDescriptionText(2, 33); + testKey(false); + menuUp(); + _mouse.hideMouse(); + clearScreen(); + drawDiscussionBox(); + startDialog(140); + drawRightFrame(); + drawClock(); + _mouse.showMouse(); + _coreVar._currPlace = OWN_ROOM; + prepareDisplayText(); + resetPresenceInRooms(DINING_ROOM); + if (!_blo) + getPresence(OWN_ROOM); + _currBitIndex = 0; + _savedBitIndex = 0; + _coreVar._alreadyEnteredManor = true; + } else + displayDiningRoom(); +} + +/** + * Engine function - Check Manor distance (in the mountains) + * @remarks Originally called 't1neig' + */ +void MortevielleEngine::checkManorDistance() { + ++_manorDistance; + if (_manorDistance > 2) { + _crep = 1506; + loseGame(); + } else { + _destinationOk = true; + _coreVar._currPlace = MOUNTAIN; + prepareDisplayText(); + } +} + +/** + * Engine function - Go to Manor front + * @remarks Originally called 't1deva' + */ +void MortevielleEngine::gotoManorFront() { + _manorDistance = 0; + _coreVar._currPlace = MANOR_FRONT; + prepareDisplayText(); +} + +/** + * Engine function - Go to Manor back + * @remarks Originally called 't1derr' + */ +void MortevielleEngine::gotoManorBack() { + _coreVar._currPlace = MANOR_BACK; + prepareDisplayText(); +} + +/** + * Engine function - Dead : Flooded in Well + * @remarks Originally called 't1deau' + */ +void MortevielleEngine::floodedInWell() { + _crep = 1503; + loseGame(); +} + +/** + * Called when a savegame has been loaded. + * @remarks Originally called 'antegame' + */ +void MortevielleEngine::gameLoaded() { + _mouse.hideMouse(); + _menu._menuDisplayed = false; + _loseGame = true; + _anyone = false; + _destinationOk = true; + _col = false; + _hiddenHero = false; + _uptodatePresence = false; + _maff = 68; + _menuOpcode = OPCODE_NONE; + _introSpeechPlayed = false; + _x = 0; + _y = 0; + _num = 0; + _startTime = 0; + _endTime = 0; + _searchCount = 0; + _roomDoorId = OWN_ROOM; + _syn = true; + _heroSearching = true; + _curSearchObjId = 0; + _manorDistance = 0; + resetOpenObjects(); + _takeObjCount = 0; + prepareDisplayText(); + _hintPctMessage = getString(580); + + _destinationOk = false; + _endGame = true; + _loseGame = false; + _heroSearching = false; + + displayAloneText(); + prepareRoom(); + drawClock(); + drawPictureWithText(); + handleDescriptionText(2, _crep); + clearVerbBar(); + _endGame = false; + _menu.setDestinationText(_coreVar._currPlace); + _menu.setInventoryText(); + if (_coreVar._selectedObjectId != 0) + displayItemInHand(_coreVar._selectedObjectId + 400); + _mouse.showMouse(); +} + +/** + * Engine function - Handle OpCodes + * @remarks Originally called 'tsitu' + */ +void MortevielleEngine::handleOpcode() { + if (!_col) + clearDescriptionBar(); + _syn = false; + _keyPressedEsc = false; + if (!_anyone) { + if (_uptodatePresence) { + if ((_currMenu == MENU_MOVE) || (_currAction == _menu._opcodeLeave) || (_currAction == _menu._opcodeSleep) || (_currAction == _menu._opcodeEat)) { + _controlMenu = 4; + menuUp(); + return; + } + } + + if (_currMenu == MENU_MOVE) + fctMove(); + else if (_currMenu == MENU_DISCUSS) + fctDiscuss(); + else if (_currMenu == MENU_INVENTORY) + fctInventoryTake(); + else if (_currAction == _menu._opcodeAttach) + fctAttach(); + else if (_currAction == _menu._opcodeWait) + fctWait(); + else if (_currAction == _menu._opcodeForce) + fctForce(); + else if (_currAction == _menu._opcodeSleep) + fctSleep(); + else if (_currAction == _menu._opcodeListen) + fctListen(); + else if (_currAction == _menu._opcodeEnter) + fctEnter(); + else if (_currAction == _menu._opcodeClose) + fctClose(); + else if (_currAction == _menu._opcodeSearch) + fctSearch(); + else if (_currAction == _menu._opcodeKnock) + fctKnock(); + else if (_currAction == _menu._opcodeScratch) + fctScratch(); + else if (_currAction == _menu._opcodeRead) + fctRead(); + else if (_currAction == _menu._opcodeEat) + fctEat(); + else if (_currAction == _menu._opcodePlace) + fctPlace(); + else if (_currAction == _menu._opcodeOpen) + fctOpen(); + else if (_currAction == _menu._opcodeTake) + fctTake(); + else if (_currAction == _menu._opcodeLook) + fctLook(); + else if (_currAction == _menu._opcodeSmell) + fctSmell(); + else if (_currAction == _menu._opcodeSound) + fctSound(); + else if (_currAction == _menu._opcodeLeave) + fctLeave(); + else if (_currAction == _menu._opcodeLift) + fctLift(); + else if (_currAction == _menu._opcodeTurn) + fctTurn(); + else if (_currAction == _menu._opcodeSSearch) + fctSelfSearch(); + else if (_currAction == _menu._opcodeSRead) + fctSelfRead(); + else if (_currAction == _menu._opcodeSPut) + fctSelfPut(); + else if (_currAction == _menu._opcodeSLook) + fctSelftLook(); + + _hiddenHero = false; + + if (_currAction == _menu._opcodeSHide) + fctSelfHide(); + } else if (_anyone) { + interactNPC(); + _anyone = false; + menuUp(); + return; + } + int hour, day, minute; + updateHour(day, hour, minute); + if ((((hour == 12) || (hour == 13) || (hour == 19)) && (_coreVar._currPlace != DINING_ROOM)) || + ((hour > 0) && (hour < 6) && (_coreVar._currPlace != OWN_ROOM))) + ++_coreVar._faithScore; + if (((_coreVar._currPlace < CRYPT) || (_coreVar._currPlace > MOUNTAIN)) && (_coreVar._currPlace != INSIDE_WELL) + && (_coreVar._currPlace != OWN_ROOM) && (_coreVar._selectedObjectId != 152) && (!_loseGame)) { + if ((_coreVar._faithScore > 99) && (hour > 8) && (hour < 16)) { + _crep = 1501; + loseGame(); + } else if ((_coreVar._faithScore > 99) && (hour > 0) && (hour < 9)) { + _crep = 1508; + loseGame(); + } else if ((day > 1) && (hour > 8) && (!_loseGame)) { + _crep = 1502; + loseGame(); + } + } + menuUp(); +} + +/** + * Engine function - Transform time into a char + * @remarks Originally called 'tmaj3' + */ +void MortevielleEngine::hourToChar() { + int day, hour, minute; + + updateHour(day, hour, minute); + if (minute == 30) + minute = 1; + hour += day * 24; + minute += hour * 2; + _coreVar._fullHour = (unsigned char)minute; +} + +/** + * Engine function - extract time from a char + * @remarks Originally called 'theure' + */ +void MortevielleEngine::charToHour() { + int fullHour = _coreVar._fullHour; + int tmpHour = fullHour % 48; + _currDay = fullHour / 48; + _currHalfHour = tmpHour % 2; + _currHour = tmpHour / 2; + _hour = _currHour; + if (_currHalfHour == 1) + _minute = 30; + else + _minute = 0; +} + +/** + * Engine function - Clear upper left part of Screen - Type 1 + * @remarks Originally called 'clsf1' + */ +void MortevielleEngine::clearUpperLeftPart() { + _mouse.hideMouse(); + _screenSurface.fillRect(0, Common::Rect(0, 11, 514, 175)); + _mouse.showMouse(); +} + +/** + * Engine function - Clear low bar used by description + * @remarks Originally called 'clsf2' + */ +void MortevielleEngine::clearDescriptionBar() { + _mouse.hideMouse(); + if (_largestClearScreen) { + _screenSurface.fillRect(0, Common::Rect(1, 176, 633, 199)); + _screenSurface.drawBox(0, 176, 634, 23, 15); + _largestClearScreen = false; + } else { + _screenSurface.fillRect(0, Common::Rect(1, 176, 633, 190)); + _screenSurface.drawBox(0, 176, 634, 14, 15); + } + _mouse.showMouse(); +} + +/** + * Engine function - Clear lowest bar used by verbs + * @remarks Originally called 'clsf3' + */ +void MortevielleEngine::clearVerbBar() { + _mouse.hideMouse(); + _screenSurface.fillRect(0, Common::Rect(1, 192, 633, 199)); + _screenSurface.drawBox(0, 191, 634, 8, 15); + _mouse.showMouse(); +} + +/** + * Engine function - Clear upper right part of the screen + * @remarks Originally called 'clsf10' + */ +void MortevielleEngine::clearUpperRightPart() { + Common::String st; + + _mouse.hideMouse(); + + // Clear ambiance description + _screenSurface.fillRect(15, Common::Rect(544, 93, 600, 98)); + if (_coreVar._faithScore < 33) + st = getEngineString(S_COOL); + else if (_coreVar._faithScore < 66) + st = getEngineString(S_LOURDE); + else if (_coreVar._faithScore > 65) + st = getEngineString(S_MALSAINE); + + int x1 = 580 - (_screenSurface.getStringWidth(st) / 2); + _screenSurface.putxy(x1, 92); + _screenSurface.drawString(st, 4); + + // Clear person list + _screenSurface.fillRect(15, Common::Rect(560, 24, 610, 86)); + _mouse.showMouse(); +} + +/** + * Engine function - Get a random number between two values + * @remarks Originally called 'get_random_number' and 'hazard' + */ +int MortevielleEngine::getRandomNumber(int minval, int maxval) { + return _randomSource.getRandomNumber(maxval - minval) + minval; +} + +/** + * Engine function - Show alert "use move menu" + * @remarks Originally called 'aldepl' + */ +void MortevielleEngine::showMoveMenuAlert() { + _dialogManager.show(getEngineString(S_USE_DEP_MENU)); +} + +/** + * The original engine used this method to display a starting text screen letting the player + * select the graphics mode to use + * @remarks Originally called 'dialpre' + */ +void MortevielleEngine::showConfigScreen() { + _crep = 998; +} + +/** + * Decodes a number of 64 byte blocks + * @param pStart Start of data + * @param count Number of 64 byte blocks + * @remarks Originally called 'zzuul' + */ +void MortevielleEngine::decodeNumber(byte *pStart, int count) { + while (count-- > 0) { + for (int idx = 0; idx < 64; ++pStart, ++idx) { + uint16 v = ((*pStart - 0x80) << 1) + 0x80; + + if (v & 0x8000) + *pStart = 0; + else if (v & 0xff00) + *pStart = 0xff; + else + *pStart = (byte)v; + } + } +} + +const byte cryptoArrDefaultFr[32] = { + 32, 101, 115, 97, 114, 105, 110, + 117, 116, 111, 108, 13, 100, 99, + 112, 109, 46, 118, 130, 39, 102, + 98, 44, 113, 104, 103, 33, 76, + 85, 106, 30, 31 +}; + +const byte cryptoArr30Fr[32] = { + 69, 67, 74, 138, 133, 120, 77, 122, + 121, 68, 65, 63, 73, 80, 83, 82, + 156, 45, 58, 79, 49, 86, 78, 84, + 71, 81, 64, 66, 135, 34, 136, 91 +}; + +const byte cryptoArr31Fr[32]= { + 93, 47, 48, 53, 50, 70, 124, 75, + 72, 147, 140, 150, 151, 57, 56, 51, + 107, 139, 55, 89, 131, 37, 54, 88, + 119, 0, 0, 0, 0, 0, 0, 0 +}; + +const byte cryptoArrDefaultDe[32] = { + 0x20, 0x65, 0x6E, 0x69, 0x73, 0x72, 0x74, + 0x68, 0x61, 0x75, 0x0D, 0x63, 0x6C, 0x64, + 0x6D, 0x6F, 0x67, 0x2E, 0x62, 0x66, 0x53, + 0x2C, 0x77, 0x45, 0x7A, 0x6B, 0x44, 0x76, + 0x9C, 0x47, 0x1E, 0x1F +}; + +const byte cryptoArr30De[32] = { + 0x49, 0x4D, 0x21, 0x42, 0x4C, 0x70, 0x41, 0x52, + 0x57, 0x4E, 0x48, 0x3F, 0x46, 0x50, 0x55, 0x4B, + 0x5A, 0x4A, 0x54, 0x31, 0x4F, 0x56, 0x79, 0x3A, + 0x6A, 0x5B, 0x5D, 0x40, 0x22, 0x2F, 0x30, 0x35 +}; + +const byte cryptoArr31De[32]= { + 0x78, 0x2D, 0x32, 0x82, 0x43, 0x39, 0x33, 0x38, + 0x7C, 0x27, 0x37, 0x3B, 0x25, 0x28, 0x29, 0x36, + 0x51, 0x59, 0x71, 0x81, 0x87, 0x88, 0x93, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const byte *cryptoArrDefault, *cryptoArr30, *cryptoArr31; +uint16 ctrlChar; + +/** + * Decrypt the next character + * @param c OUT, next decrypted char + * @param idx IN/OUT, current buffer index + * @param pt IN/OUT, current encryption point + * @return a boolean specifying if a stop character has been encountered + * @remarks Originally called 'cinq_huit' + */ +bool MortevielleEngine::decryptNextChar(char &c, int &idx, byte &pt) { + uint16 oct, ocd; + + /* 5-8 */ + oct = _dialogIndexArray[idx]; + oct = ((uint16)(oct << (16 - pt))) >> (16 - pt); + if (pt < 6) { + ++idx; + oct = oct << (5 - pt); + pt += 11; + oct = oct | ((uint)_dialogIndexArray[idx] >> pt); + } else { + pt -= 5; + oct = (uint)oct >> pt; + } + + if (oct == ctrlChar) { + c = '$'; + return true; + } else if (oct == 30 || oct == 31) { + ocd = _dialogIndexArray[idx]; + ocd = (uint16)(ocd << (16 - pt)) >> (16 - pt); + if (pt < 6) { + ++idx; + ocd = ocd << (5 - pt); + pt += 11; + ocd = ocd | ((uint)_dialogIndexArray[idx] >> pt); + } else { + pt -= 5; + ocd = (uint)ocd >> pt; + } + + if (oct == 30) + c = (unsigned char)cryptoArr30[ocd]; + else + c = (unsigned char)cryptoArr31[ocd]; + + if (c == '\0') { + c = '#'; + return true; + } + } else { + c = (unsigned char)cryptoArrDefault[oct]; + } + return false; +} + +/** + * Decode and extract the line with the given Id + * @remarks Originally called 'deline' + */ +Common::String MortevielleEngine::getString(int num) { + Common::String wrkStr = ""; + + if (num < 0) { + warning("getString(%d): num < 0! Skipping", num); + } else if (!_txxFileFl) { + wrkStr = getGameString(num); + } else { + int hint = _dialogHintArray[num]._hintId; + byte point = _dialogHintArray[num]._point; + int length = 0; + bool endFl = false; + char let; + do { + endFl = decryptNextChar(let, hint, point); + wrkStr += let; + ++length; + } while (!endFl); + } + + while (wrkStr.lastChar() == '$') + // Remove trailing '$'s + wrkStr.deleteLastChar(); + + return wrkStr; +} + +/** + * Reset object place + * @remarks Originally called 'copcha' + */ +void MortevielleEngine::resetObjectPlace() { + for (int i = kAcha; i < kAcha + 390; i++) + _tabdon[i] = _tabdon[i + 390]; +} + +/** + * Engine function - When restarting the game, reset the main variables used by the engine + * @remarks Originally called 'inzon' + */ +void MortevielleEngine::resetVariables() { + resetObjectPlace(); + + _coreVar._alreadyEnteredManor = false; + _coreVar._selectedObjectId = 0; + _coreVar._cellarObjectId = 0; + _coreVar._atticBallHoleObjectId = 0; + _coreVar._atticRodHoleObjectId = 0; + _coreVar._wellObjectId = 0; + _coreVar._secretPassageObjectId = 0; + _coreVar._purpleRoomObjectId = 136; + _coreVar._cryptObjectId = 141; + _coreVar._faithScore = getRandomNumber(4, 10); + _coreVar._currPlace = MANOR_FRONT; + + for (int i = 2; i <= 6; ++i) + _coreVar._inventory[i] = 0; + + // Only object in inventory: a gun + _coreVar._inventory[1] = 113; + + _coreVar._fullHour = (unsigned char)20; + + for (int i = 1; i <= 10; ++i) + _coreVar._pctHintFound[i] = ' '; + + for (int i = 1; i <= 6; ++i) + _coreVar._availableQuestion[i] = '*'; + + for (int i = 7; i <= 9; ++i) + _coreVar._availableQuestion[i] = ' '; + + for (int i = 10; i <= 28; ++i) + _coreVar._availableQuestion[i] = '*'; + + for (int i = 29; i <= 42; ++i) + _coreVar._availableQuestion[i] = ' '; + + _coreVar._availableQuestion[33] = '*'; + + for (int i = 1; i <= 8; ++i) + _charAnswerCount[i] = 0; + + initMaxAnswer(); +} + +/** + * Engine function - Set the palette + * @remarks Originally called 'writepal' + */ +void MortevielleEngine::setPal(int n) { + for (int i = 1; i <= 16; ++i) { + _curPict[(2 * i)] = _stdPal[n][i].x; + _curPict[(2 * i) + 1] = _stdPal[n][i].y; + } +} + +/** + * Engine function - Load Palette from File + * @remarks Originally called 'charpal' + */ +void MortevielleEngine::loadPalette() { + Common::File f; + + if (!f.open("fxx.mor")) { + if (f.open("mfxx.mor")) + f.seek(7 * 25); + else + error("Missing file - fxx.mor"); + } + + for (int i = 0; i < 108; ++i) + _drawingSizeArr[i] = f.readSint16LE(); + f.close(); + + if (!f.open("plxx.mor")) + error("Missing file - plxx.mor"); + for (int i = 0; i <= 90; ++i) { + for (int j = 1; j <= 16; ++j) { + _stdPal[i][j].x = f.readByte(); + _stdPal[i][j].y = f.readByte(); + } + } + f.close(); + + if (!f.open("cxx.mor")) + error("Missing file - cxx.mor"); + + // Skip CGA Palette and Patterns + + f.close(); +} + +/** + * Engine function - Load Texts from File + * @remarks Originally called 'chartex' + */ +void MortevielleEngine::loadTexts() { + Common::File inpFile; + Common::File ntpFile; + + _txxFileFl = false; + if (!useOriginalData()) { + warning("Using improved translation from DAT file"); + return; + } + + if (!inpFile.open("TXX.INP")) { + if (!inpFile.open("TXX.MOR")) { + warning("Missing file - TXX.INP or .MOR - Switching to DAT file"); + return; + } + } + if (ntpFile.open("TXX.NTP")) { + cryptoArr30 = cryptoArr30Fr; + cryptoArr31 = cryptoArr31Fr; + cryptoArrDefault = cryptoArrDefaultFr; + ctrlChar = 11; + } else if (ntpFile.open("TXX.IND")) { + cryptoArr30 = cryptoArr30De; + cryptoArr31 = cryptoArr31De; + cryptoArrDefault = cryptoArrDefaultDe; + ctrlChar = 10; + } else { + warning("Missing file - TXX.NTP or .IND - Switching to DAT file"); + return; + } + + if ((inpFile.size() > (kMaxDialogIndex * 2)) || (ntpFile.size() > (kMaxDialogHint * 3))) { + warning("TXX file - Unexpected format - Switching to DAT file"); + return; + } + + for (int i = 0; i < inpFile.size() / 2; ++i) + _dialogIndexArray[i] = inpFile.readUint16LE(); + + inpFile.close(); + _txxFileFl = true; + + for (int i = 0; i < (ntpFile.size() / 3); ++i) { + _dialogHintArray[i]._hintId = ntpFile.readSint16LE(); + _dialogHintArray[i]._point = ntpFile.readByte(); + } + + ntpFile.close(); + +} + +void MortevielleEngine::loadCFIEC() { + Common::File f; + + if (!f.open("cfiec.mor")) { + if (!f.open("alcfiec.mor")) + error("Missing file - *cfiec.mor"); + } + + _cfiecBufferSize = ((f.size() / 128) + 1) * 128; + int32 fileSize = f.size(); + + if (!_reloadCFIEC) + _cfiecBuffer = (byte *)malloc(sizeof(byte) * _cfiecBufferSize); + + for (int32 i = 0; i < fileSize; ++i) + _cfiecBuffer[i] = f.readByte(); + + for (int i = fileSize; i < _cfiecBufferSize; i++) + _cfiecBuffer[i] = 0; + + f.close(); + + _reloadCFIEC = false; +} + + +void MortevielleEngine::loadCFIPH() { + Common::File f; + + if (!f.open("cfiph.mor")) { + if (!f.open("alcfiph.mor")) + error("Missing file - *cfiph.mor"); + } + + _soundManager._cfiphBuffer = (uint16 *)malloc(sizeof(uint16) * (f.size() / 2)); + + for (int i = 0; i < (f.size() / 2); ++i) + _soundManager._cfiphBuffer[i] = f.readUint16BE(); + + f.close(); +} + +/** + * Engine function - Play Music + * @remarks Originally called 'music' + */ +void MortevielleEngine::music() { + if (_soundOff) + return; + + _reloadCFIEC = true; + + Common::File f; + if (!f.open("mort.img")) + error("Missing file - mort.img"); + + int size = f.size(); + byte *compMusicBuf = (byte *)malloc(sizeof(byte) * size); + byte *musicBuf = (byte *)malloc(sizeof(byte) * size * 2); + f.read(compMusicBuf, size); + f.close(); + + int musicSize = _soundManager.decodeMusic(compMusicBuf, musicBuf, size); + free(compMusicBuf); + + _soundManager.playSong(musicBuf, musicSize, 5); + while (keyPressed()) + getChar(); + + free(musicBuf); +} + +/** + * Engine function - Show title screen + * @remarks Originally called 'suite' + */ +void MortevielleEngine::showTitleScreen() { + clearScreen(); + handleDescriptionText(7, 2035); + _caff = 51; + _text.taffich(); + testKeyboard(); + clearScreen(); + draw(0, 0); + + Common::String cpr = "COPYRIGHT 1989 : LANKHOR"; + _screenSurface.putxy(104 + 72 * kResolutionScaler, 185); + _screenSurface.drawString(cpr, 0); +} + +/** + * Draw picture + * @remarks Originally called 'dessine' + */ +void MortevielleEngine::draw(int x, int y) { + _mouse.hideMouse(); + setPal(_numpal); + displayPicture(_curPict, x, y); + _mouse.showMouse(); +} + +/** + * Draw right frame + * @remarks Originally called 'dessine_rouleau' + */ +void MortevielleEngine::drawRightFrame() { + setPal(89); + _mouse.hideMouse(); + displayPicture(_rightFramePict, 0, 0); + _mouse.showMouse(); +} + +/** + * Read the current system time + */ +int MortevielleEngine::readclock() { + return (int)(g_system->getMillis() / 1000); +} + +/** + * Engine function - Prepare room and hint string + * @remarks Originally called 'tinke' + */ +void MortevielleEngine::prepareRoom() { + int day, hour, minute; + + _anyone = false; + updateHour(day, hour, minute); + if (day != _day) { + _day = day; + for (int i = 0; i < 9; i++) { + if (_charAnswerMax[i] > 0) + --_charAnswerMax[i]; + _charAnswerCount[i] = 0; + } + } + if ((hour > _hour) || ((hour == 0) && (_hour == 23))) { + _hour = hour; + _minute = 0; + drawClock(); + int hintCount = 0; + for (int i = 1; i <= 10; ++i) { + if (_coreVar._pctHintFound[i] == '*') + ++hintCount; + } + + Common::String pctStr; + if (hintCount == 10) + pctStr = "10"; + else + pctStr = (unsigned char)(hintCount + 48); + + _hintPctMessage = "[1]["; + _hintPctMessage += getEngineString(S_SHOULD_HAVE_NOTICED); + _hintPctMessage += pctStr; + _hintPctMessage += '0'; + _hintPctMessage += getEngineString(S_NUMBER_OF_HINTS); + _hintPctMessage += "]["; + _hintPctMessage += getEngineString(S_OKAY); + _hintPctMessage += ']'; + } + if (minute > _minute) { + _minute = 30; + drawClock(); + } + if (_mouse._pos.y < 12) + return; + + if (!_blo) { + if ((hour == 12) || ((hour > 18) && (hour < 21)) || ((hour >= 0) && (hour < 7))) + _inGameHourDuration = kTime2; + else + _inGameHourDuration = kTime1; + if ((_coreVar._faithScore > 33) && (_coreVar._faithScore < 66)) + _inGameHourDuration -= (_inGameHourDuration / 3); + + if (_coreVar._faithScore > 65) + _inGameHourDuration -= ((_inGameHourDuration / 3) * 2); + + int newTime = readclock(); + if ((newTime - _currentTime) > _inGameHourDuration) { + bool activeMenu = _menu._menuActive; + _menu.eraseMenu(); + _currentHourCount += ((newTime - _currentTime) / _inGameHourDuration); + _currentTime = newTime; + switch (_place) { + case GREEN_ROOM: + case DARKBLUE_ROOM: + setRandomPresenceGreenRoom(_coreVar._faithScore); + break; + case PURPLE_ROOM: + setRandomPresencePurpleRoom(_coreVar._faithScore); + break; + case BLUE_ROOM: + setRandomPresenceBlueRoom(_coreVar._faithScore); + break; + case RED_ROOM: + case GREEN_ROOM2: + setRandomPresenceRedRoom(_coreVar._faithScore); + break; + case JULIA_ROOM: + setRandomPresenceJuliaRoom(_coreVar._faithScore); + break; + case DINING_ROOM: + setRandomPresenceDiningRoom(_coreVar._faithScore); + break; + case BUREAU: + setRandomPresenceBureau(_coreVar._faithScore); + break; + case KITCHEN: + setRandomPresenceKitchen(_coreVar._faithScore); + break; + case ATTIC: + case CELLAR: + setRandomPresenceAttic(_coreVar._faithScore); + break; + case LANDING: + case ROOM26: + setRandomPresenceLanding(_coreVar._faithScore); + break; + case CHAPEL: + setRandomPresenceChapel(_coreVar._faithScore); + break; + } + if ((_savedBitIndex != 0) && (_currBitIndex != 10)) + _savedBitIndex = _currBitIndex; + + if ((_savedBitIndex == 0) && (_currBitIndex > 0)) { + if ((_coreVar._currPlace == ATTIC) || (_coreVar._currPlace == CELLAR)) { + initCaveOrCellar(); + } else if (_currBitIndex == 10) { + _currBitIndex = 0; + if (!_uptodatePresence) { + _uptodatePresence = true; + _startTime = readclock(); + if (getRandomNumber(1, 5) < 5) { + clearVerbBar(); + prepareScreenType2(); + displayTextInVerbBar(getEngineString(S_HEAR_NOISE)); + int rand = (getRandomNumber(0, 4)) - 2; + _soundManager.startSpeech(1, rand, 1); + _soundManager.waitSpeech(); + clearVerbBar(); + } + } + } + } + + if (activeMenu) + _menu.drawMenu(); + } + } + _endTime = readclock(); + if ((_uptodatePresence) && ((_endTime - _startTime) > 17)) { + getPresenceBitIndex(_place); + _uptodatePresence = false; + _startTime = 0; + if ((_coreVar._currPlace > OWN_ROOM) && (_coreVar._currPlace < DINING_ROOM)) + _anyone = true; + } +} + +/** + * Engine function - Draw Clock + * @remarks Originally called 'pendule' + */ +void MortevielleEngine::drawClock() { + const int cv[2][12] = { + { 5, 8, 10, 8, 5, 0, -5, -8, -10, -8, -5, 0 }, + { -5, -3, 0, 3, 5, 6, 5, 3, 0, -3, -5, -6 } + }; + const int x = 580; + const int y = 123; + const int rg = 9; + + _mouse.hideMouse(); + + _screenSurface.drawRectangle(570, 118, 20, 10); + _screenSurface.drawRectangle(578, 114, 6, 18); + + if (_minute == 0) + _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)x >> 1) * kResolutionScaler, (y - rg), 1); + else + _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)x >> 1) * kResolutionScaler, (y + rg), 1); + + int hour12 = _hour; + if (hour12 > 12) + hour12 -= 12; + if (hour12 == 0) + hour12 = 12; + + _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)(x + cv[0][hour12 - 1]) >> 1) * kResolutionScaler, y + cv[1][hour12 - 1], 1); + _mouse.showMouse(); + _screenSurface.putxy(568, 154); + + if (_hour > 11) + _screenSurface.drawString("PM ", 1); + else + _screenSurface.drawString("AM ", 1); + + _screenSurface.putxy(550, 160); + if ((_day >= 0) && (_day <= 8)) { + Common::String tmp = getEngineString(S_DAY); + tmp.insertChar((char)(_day + 49), 0); + _screenSurface.drawString(tmp, 1); + } +} + +void MortevielleEngine::palette(int v1) { + warning("TODO: palette"); +} + +/** + * Returns a substring of the given string + * @param s Source string + * @param idx Starting index (1 based) + * @param size Number of characters to return + */ + +Common::String MortevielleEngine::copy(const Common::String &s, int idx, size_t size) { + assert(idx + size < s.size()); + + // Copy the substring into a temporary buffer + char *tmp = new char[size + 1]; + Common::strlcpy(tmp, s.c_str() + idx - 1, size + 1); + + Common::String result(tmp); + delete[] tmp; + return result; +} + +/** + * Clear Screen + * @remarks Originally called 'hirs' + */ +void MortevielleEngine::clearScreen() { + _screenSurface.clearScreen(); +} + +/** + * Init room : Cave or Cellar + * @remarks Originally called 'cavegre' + */ +void MortevielleEngine::initCaveOrCellar() { + _coreVar._faithScore += 2; + if (_coreVar._faithScore > 69) + _coreVar._faithScore += (_coreVar._faithScore / 10); + clearVerbBar(); + prepareScreenType2(); + displayTextInVerbBar(getEngineString(S_SOMEONE_ENTERS)); + int rand = (getRandomNumber(0, 4)) - 2; + _soundManager.startSpeech(2, rand, 1); + _soundManager.waitSpeech(); + // The original was doing here a useless loop. + // It has been removed + + clearVerbBar(); + displayAloneText(); +} + +/** + * Display control menu string + * @remarks Originally called 'tctrm' + */ +void MortevielleEngine::displayControlMenu() { + handleDescriptionText(2, (3000 + _controlMenu)); + _controlMenu = 0; +} + +/** + * Display picture at a given coordinate + * @remarks Originally called 'pictout' + */ +void MortevielleEngine::displayPicture(const byte *pic, int x, int y) { + GfxSurface surface; + surface.decode(pic); + _screenSurface.drawPicture(surface, x, y); +} + +void MortevielleEngine::adzon() { + Common::File f; + + if (!f.open("don.mor")) + error("Missing file - don.mor"); + + f.read(_tabdon, 7 * 256); + f.close(); + + if (!f.open("bmor.mor")) + error("Missing file - bmor.mor"); + + f.read(&_tabdon[kFleche], 1916); + f.close(); + + // Read Right Frame Drawing + if (!f.open("dec.mor")) + error("Missing file - dec.mor"); + + free(_rightFramePict); + _rightFramePict = (byte *)malloc(sizeof(byte) * f.size()); + f.read(_rightFramePict, f.size()); + f.close(); +} + +/** + * Returns the offset within the compressed image data resource of the desired image + * @remarks Originally called 'animof' + */ +int MortevielleEngine::getAnimOffset(int frameNum, int animNum) { + int animCount = _curAnim[1]; + int aux = animNum; + if (frameNum != 1) + aux += animCount; + + return (animCount << 2) + 2 + READ_BE_UINT16(&_curAnim[aux << 1]); +} + +/** + * Display text in description bar + * @remarks Originally called 'text1' + */ +void MortevielleEngine::displayTextInDescriptionBar(int x, int y, int nb, int mesgId) { + Common::String tmpStr = getString(mesgId); + if ((y == 182) && ((int) tmpStr.size() > nb)) + y = 176; + _text.displayStr(tmpStr, x, y, nb, 20, _textColor); +} + +/** + * Display description text + * @remarks Originally called 'repon' + */ +void MortevielleEngine::handleDescriptionText(int f, int mesgId) { + if ((mesgId > 499) && (mesgId < 563)) { + Common::String tmpStr = getString(mesgId - 501 + kInventoryStringIndex); + + if ((int) tmpStr.size() > ((58 + (kResolutionScaler - 1) * 37) << 1)) + _largestClearScreen = true; + else + _largestClearScreen = false; + + clearDescriptionBar(); + _text.displayStr(tmpStr, 8, 176, 85, 3, 5); + } else { + mapMessageId(mesgId); + switch (f) { + case 2: + case 8: + clearDescriptionBar(); + prepareScreenType2(); + displayTextInDescriptionBar(8, 182, 103, mesgId); + if ((mesgId == 68) || (mesgId == 69)) + _coreVar._availableQuestion[40] = '*'; + else if ((mesgId == 104) && (_caff == CELLAR)) { + _coreVar._availableQuestion[36] = '*'; + if (_coreVar._availableQuestion[39] == '*') { + _coreVar._pctHintFound[3] = '*'; + _coreVar._availableQuestion[38] = '*'; + } + } + break; + case 1: + case 6: + case 9: { + int i; + if ((f == 1) || (f == 6)) + i = 4; + else + i = 5; + + Common::String tmpStr = getString(mesgId); + _text.displayStr(tmpStr, 80, 40, 60, 25, i); + + if (mesgId == 180) + _coreVar._pctHintFound[6] = '*'; + else if (mesgId == 179) + _coreVar._pctHintFound[10] = '*'; + } + break; + default: + break; + } + } +} + +/** + * Recompute message Id + * @remarks Originally called 'modif' + */ +void MortevielleEngine::mapMessageId(int &mesgId) { + if (mesgId == 26) + mesgId = 25; + else if ((mesgId > 29) && (mesgId < 36)) + mesgId -= 4; + else if ((mesgId > 69) && (mesgId < 78)) + mesgId -= 37; + else if ((mesgId > 99) && (mesgId < 194)) + mesgId -= 59; + else if ((mesgId > 996) && (mesgId < 1000)) + mesgId -= 862; + else if ((mesgId > 1500) && (mesgId < 1507)) + mesgId -= 1363; + else if ((mesgId > 1507) && (mesgId < 1513)) + mesgId -= 1364; + else if ((mesgId > 1999) && (mesgId < 2002)) + mesgId -= 1851; + else if (mesgId == 2010) + mesgId = 151; + else if ((mesgId > 2011) && (mesgId < 2025)) + mesgId -= 1860; + else if (mesgId == 2026) + mesgId = 165; + else if ((mesgId > 2029) && (mesgId < 2037)) + mesgId -= 1864; + else if ((mesgId > 3000) && (mesgId < 3005)) + mesgId -= 2828; + else if (mesgId == 4100) + mesgId = 177; + else if (mesgId == 4150) + mesgId = 178; + else if ((mesgId > 4151) && (mesgId < 4156)) + mesgId -= 3973; + else if (mesgId == 4157) + mesgId = 183; + else if ((mesgId == 4160) || (mesgId == 4161)) + mesgId -= 3976; +} + +/** + * Initialize open objects array + * @remarks Originally called 'initouv' + */ +void MortevielleEngine::resetOpenObjects() { + for (int i = 1; i <= 6; ++i) + _openObjects[i] = 0; + _openObjCount = 0; +} + +/** + * Display Text Block + * @remarks Originally called 'ecr2' + */ +void MortevielleEngine::displayTextBlock(Common::String text) { + // Some dead code was present in the original: removed + _screenSurface.putxy(8, 177); + int tlig = 59 + (kResolutionScaler - 1) * 36; + + if ((int)text.size() < tlig) + _screenSurface.drawString(text, 5); + else if ((int)text.size() < (tlig << 1)) { + _screenSurface.putxy(8, 176); + _screenSurface.drawString(copy(text, 1, (tlig - 1)), 5); + _screenSurface.putxy(8, 182); + _screenSurface.drawString(copy(text, tlig, tlig << 1), 5); + } else { + _largestClearScreen = true; + clearDescriptionBar(); + _screenSurface.putxy(8, 176); + _screenSurface.drawString(copy(text, 1, (tlig - 1)), 5); + _screenSurface.putxy(8, 182); + _screenSurface.drawString(copy(text, tlig, ((tlig << 1) - 1)), 5); + _screenSurface.putxy(8, 190); + _screenSurface.drawString(copy(text, tlig << 1, tlig * 3), 5); + } +} + +void MortevielleEngine::displayTextInVerbBar(Common::String text) { + clearVerbBar(); + _screenSurface.putxy(8, 192); + _screenSurface.drawString(text, 5); +} + +/** + * Display item in hand + * @remarks Originally called 'modobj' + */ +void MortevielleEngine::displayItemInHand(int objId) { + Common::String strp = Common::String(' '); + + if (objId != 500) + strp = getString(objId - 501 + kInventoryStringIndex); + + _menu.setText(_menu._inventoryMenu[8], strp); + _menu.disableMenuItem(_menu._inventoryMenu[8]); +} + +/** + * Display empty hand + * @remarks Originally called 'maivid' + */ +void MortevielleEngine::displayEmptyHand() { + _coreVar._selectedObjectId = 0; + displayItemInHand(500); +} + +/** + * Set a random presence: Leo or Max + * @remarks Originally called 'chlm' + */ +int MortevielleEngine::checkLeoMaxRandomPresence() { + int retval = getRandomNumber(1, 2); + if (retval == 2) + retval = 128; + + return retval; +} + +/** + * Reset room variables + * @remarks Originally called 'debloc' + */ +void MortevielleEngine::resetRoomVariables(int roomId) { + _num = 0; + _x = 0; + _y = 0; + if ((roomId != ROOM26) && (roomId != LANDING)) + resetPresenceInRooms(roomId); + _savedBitIndex = _currBitIndex; +} + +/** + * Compute presence stats + * @remarks Originally called 'ecfren' + */ +int MortevielleEngine::getPresenceStats(int &rand, int faithScore, int roomId) { + if (roomId == OWN_ROOM) + displayAloneText(); + int retVal = -500; + rand = 0; + if ( ((roomId == GREEN_ROOM) && (!_roomPresenceLuc) && (!_roomPresenceIda)) + || ((roomId == DARKBLUE_ROOM) && (!_roomPresenceGuy) && (!_roomPresenceEva)) ) + retVal = getPresenceStatsGreenRoom(); + if ((roomId == PURPLE_ROOM) && (!_purpleRoomPresenceLeo) && (!_juliaRoomPresenceLeo)) + retVal = getPresenceStatsPurpleRoom(); + if ( ((roomId == TOILETS) && (!_toiletsPresenceBobMax)) + || ((roomId == BATHROOM) && (!_bathRoomPresenceBobMax)) ) + retVal = getPresenceStatsToilets(); + if ((roomId == BLUE_ROOM) && (!_roomPresenceMax)) + retVal = getPresenceStatsBlueRoom(); + if ( ((roomId == RED_ROOM) && (!_roomPresenceBob)) + || ((roomId == GREEN_ROOM2) && (!_roomPresencePat))) + retVal = getPresenceStatsRedRoom(); + if ((roomId == JULIA_ROOM) && (!_juliaRoomPresenceLeo) && (!_purpleRoomPresenceLeo)) + retVal = 10; + if ( ((roomId == PURPLE_ROOM) && (_juliaRoomPresenceLeo)) + || ((roomId == JULIA_ROOM) && (_purpleRoomPresenceLeo))) + retVal = -400; + if (retVal != -500) { + retVal += faithScore; + rand = getRandomNumber(1, 100); + } + + return retVal; +} + +/** + * Set presence flags + * @remarks Originally called 'becfren' + */ +void MortevielleEngine::setPresenceFlags(int roomId) { + if ((roomId == GREEN_ROOM) || (roomId == DARKBLUE_ROOM)) { + int rand = getRandomNumber(1, 2); + if (roomId == GREEN_ROOM) { + if (rand == 1) + _roomPresenceLuc = true; + else + _roomPresenceIda = true; + } else { // roomId == DARKBLUE_ROOM + if (rand == 1) + _roomPresenceGuy = true; + else + _roomPresenceEva = true; + } + } else if (roomId == PURPLE_ROOM) + _purpleRoomPresenceLeo = true; + else if (roomId == TOILETS) + _toiletsPresenceBobMax = true; + else if (roomId == BLUE_ROOM) + _roomPresenceMax = true; + else if (roomId == RED_ROOM) + _roomPresenceBob = true; + else if (roomId == BATHROOM) + _bathRoomPresenceBobMax = true; + else if (roomId == GREEN_ROOM2) + _roomPresencePat = true; + else if (roomId == JULIA_ROOM) + _juliaRoomPresenceLeo = true; +} + +/** + * Initialize max answers per character + * @remarks Originally called 'init_nbrepm' + */ +void MortevielleEngine::initMaxAnswer() { + static const byte maxAnswer[9] = { 0, 4, 5, 6, 7, 5, 6, 5, 8 }; + + for (int idx = 0; idx < 9; ++idx) { + _charAnswerMax[idx] = maxAnswer[idx]; + _charAnswerCount[idx] = 0; + } +} + +/** + * Get Presence + * @remarks Originally called 't11' + */ +int MortevielleEngine::getPresence(int roomId) { + int retVal = 0; + int rand; + + int pres = getPresenceStats(rand, _coreVar._faithScore, roomId); + _place = roomId; + if ((roomId > OWN_ROOM) && (roomId < DINING_ROOM)) { + if (pres != -500) { + if (rand > pres) { + displayAloneText(); + retVal = 0; + } else { + setPresenceFlags(_place); + retVal = getPresenceBitIndex(_place); + } + } else + retVal = getPresenceBitIndex(_place); + } + + if (roomId > JULIA_ROOM) { + if ((roomId > LANDING) && (roomId != CHAPEL) && (roomId != ROOM26)) + displayAloneText(); + else { + int h = 0; + switch (roomId) { + case DINING_ROOM: + pres = getPresenceStatsDiningRoom(h); + break; + case BUREAU: + pres = getPresenceStatsBureau(h); + break; + case KITCHEN: + pres = getPresenceStatsKitchen(); + break; + case ATTIC: + case CELLAR: + pres = getPresenceStatsAttic(); + break; + case LANDING: + case ROOM26: + pres = getPresenceStatsLanding(); + break; + case CHAPEL: + pres = getPresenceStatsChapel(h); + break; + } + pres += _coreVar._faithScore; + rand = getRandomNumber(1, 100); + if (rand > pres) { + displayAloneText(); + retVal = 0; + } else { + switch (roomId) { + case DINING_ROOM: + pres = setPresenceDiningRoom(h); + break; + case BUREAU: + pres = setPresenceBureau(h); + break; + case KITCHEN: + case ATTIC: + case CELLAR: + pres = setPresenceKitchen(); + break; + case LANDING: + case ROOM26: + pres = setPresenceLanding(); + break; + case CHAPEL: + pres = setPresenceChapel(h); + break; + } + retVal = pres; + } + } + } + + return retVal; +} + +/** + * Display Question String + * @remarks Originally called 'writetp' + */ +void MortevielleEngine::displayQuestionText(Common::String s, int cmd) { + _screenSurface.drawString(s, cmd); +} + +/** + * Display animation frame + * @remarks Originally called 'aniof' + */ +void MortevielleEngine::displayAnimFrame(int frameNum, int animId) { + if ((_caff == BATHROOM) && ((animId == 4) || (animId == 5))) + return; + + if ((_caff == DINING_ROOM) && (animId == 7)) + animId = 6; + else if (_caff == KITCHEN) { + if (animId == 3) + animId = 4; + else if (animId == 4) + animId = 3; + } + + int offset = getAnimOffset(frameNum, animId); + + GfxSurface surface; + surface.decode(&_curAnim[offset]); + _screenSurface.drawPicture(surface, 0, 12); + + prepareScreenType1(); +} + +/** + * Draw Picture + * @remarks Originally called 'dessin' + */ +void MortevielleEngine::drawPicture() { + clearUpperLeftPart(); + if (_caff > 99) { + draw(60, 33); + _screenSurface.drawBox(118, 32, 291, 122, 15); // Medium box + } else if (_caff > 69) { + draw(112, 48); // Heads + _screenSurface.drawBox(222, 47, 155, 92, 15); + } else { + draw(0, 12); + prepareScreenType1(); + if ((_caff < 30) || (_caff > 32)) { + for (int i = 1; i <= 6; ++i) { + if (_openObjects[i] != 0) + displayAnimFrame(1, _openObjects[i]); + } + + switch (_caff) { + case ATTIC: + if (_coreVar._atticBallHoleObjectId == 141) + displayAnimFrame(1, 7); + + if (_coreVar._atticRodHoleObjectId == 159) + displayAnimFrame(1, 6); + break; + case CELLAR: + if (_coreVar._cellarObjectId == 151) + displayAnimFrame(1, 2); + break; + case SECRET_PASSAGE: + if (_coreVar._secretPassageObjectId == 143) + displayAnimFrame(1, 1); + break; + case WELL: + if (_coreVar._wellObjectId != 0) + displayAnimFrame(1, 1); + break; + } + } + + if (_caff < ROOM26) + startMusicOrSpeech(1); + } +} + +void MortevielleEngine::drawPictureWithText() { + _text.taffich(); + drawPicture(); + _destinationOk = false; +} + +/** + * Engine function - Place + * @remarks Originally called 'tkey1' + */ +void MortevielleEngine::testKey(bool d) { + bool quest = false; + int x, y; + bool click; + + _mouse.hideMouse(); + displayStatusInDescriptionBar('K'); + + // Wait for release from any key or mouse button + while (keyPressed()) + _key = gettKeyPressed(); + + do { + _mouse.getMousePosition(x, y, click); + quest = keyPressed(); + if (quest && shouldQuit()) + return; + } while (click); + + // Event loop + do { + if (d) + prepareRoom(); + quest = keyPressed(); + _mouse.getMousePosition(x, y, click); + if (shouldQuit()) + return; + } while (!(quest || (click) || (d && _anyone))); + if (quest) + gettKeyPressed(); + setMouseClick(false); + _mouse.showMouse(); +} + +/** + * Display Narrative Picture + * @remarks Originally called 'tlu' + */ +void MortevielleEngine::displayNarrativePicture(int af, int ob) { + _caff = 32; + drawPictureWithText(); + handleDescriptionText(6, ob + 4000); + handleDescriptionText(2, 999); + testKey(true); + _caff = af; + _currMenu = OPCODE_NONE; + _crep = 998; +} + +/** + * Prepare Display Text + * @remarks Originally called 'affrep' + */ +void MortevielleEngine::prepareDisplayText() { + _caff = _coreVar._currPlace; + _crep = _coreVar._currPlace; +} + +/** + * Exit room + * @remarks Originally called 'tsort' + */ +void MortevielleEngine::exitRoom() { + if ((_openObjCount > 0) && (_coreVar._currPlace != OWN_ROOM)) { + if (_coreVar._faithScore < 50) + _coreVar._faithScore += 2; + else + _coreVar._faithScore += (_coreVar._faithScore / 10); + } + + resetOpenObjects(); + + _roomDoorId = OWN_ROOM; + _curSearchObjId = 0; + resetRoomVariables(_coreVar._currPlace); +} + +/** + * get 'read' description + * @remarks Originally called 'st4' + */ +void MortevielleEngine::getReadDescription(int objId) { + _crep = 997; + + switch (objId) { + case 114 : + _crep = 109; + break; + case 110 : + _crep = 107; + break; + case 158 : + _crep = 113; + break; + case 152: + case 153: + case 154: + case 155: + case 156: + case 150: + case 100: + case 157: + case 160: + case 161 : + displayNarrativePicture(_caff, objId); + break; + default: + break; + } +} + +/** + * get 'search' description + * @remarks Originally called 'st7' + */ +void MortevielleEngine::getSearchDescription(int objId) { + switch (objId) { + case 116: + case 144: + _crep = 104; + break; + case 126: + case 111: + _crep = 108; + break; + case 132: + _crep = 111; + break; + case 142: + _crep = 112; + break; + default: + _crep = 183; + getReadDescription(objId); + } +} + +/** + * Menu up + * @remarks Originally called 'mennor' + */ +void MortevielleEngine::menuUp() { + _menu.menuUp(_currMenu); +} + +/** + * Draw discussion box + * @remarks Originally called 'premtet' + */ +void MortevielleEngine::drawDiscussionBox() { + draw(10, 80); + _screenSurface.drawBox(18, 79, 155, 92, 15); +} + +/** + * Try to put an object somewhere + * @remarks Originally called 'ajchai' + */ +void MortevielleEngine::putObject() { + int putId = kAcha + ((_curSearchObjId - 1) * 10) - 1; + int i; + for (i = 1; (i <= 9) && (_tabdon[putId + i] != 0); i++) + ; + + if (_tabdon[putId + i] == 0) + _tabdon[putId + i] = _coreVar._selectedObjectId; + else + _crep = 192; +} + +/** + * Check if inventory is full and, if not, add object in it. + * @remarks Originally called 'ajjer' + */ +void MortevielleEngine::addObjectToInventory(int objectId) { + int i; + + for (i = 1; (i <= 5) && (_coreVar._inventory[i] != 0); i++) + ; + + if (_coreVar._inventory[i] == 0) { + _coreVar._inventory[i] = objectId; + _menu.setInventoryText(); + } else + // Inventory is full + _crep = 139; +} + +/** + * Interact with NPC + * @remarks Originally called 'quelquun' + */ +void MortevielleEngine::interactNPC() { + if (_menu._menuDisplayed) + _menu.eraseMenu(); + + endSearch(); + _crep = 997; +L1: + if (!_hiddenHero) { + if (_crep == 997) + _crep = 138; + handleDescriptionText(2, _crep); + if (_crep == 138) + _soundManager.startSpeech(5, 2, 1); + else + _soundManager.startSpeech(4, 4, 1); + + if (_openObjCount == 0) + _coreVar._faithScore += 2; + else if (_coreVar._faithScore < 50) + _coreVar._faithScore += 4; + else + _coreVar._faithScore += 3 * (_coreVar._faithScore / 10); + exitRoom(); + _menu.setDestinationText(LANDING); + int charIdx = convertBitIndexToCharacterIndex(_currBitIndex); + _caff = 69 + charIdx; + _crep = _caff; + _currMenu = MENU_DISCUSS; + _currAction = (_menu._discussMenu[charIdx]._menuId << 8) | _menu._discussMenu[charIdx]._actionId; + _syn = true; + _col = true; + } else { + if (getRandomNumber(1, 3) == 2) { + _hiddenHero = false; + _crep = 137; + goto L1; + } else { + handleDescriptionText(2, 136); + int rand = (getRandomNumber(0, 4)) - 2; + _soundManager.startSpeech(3, rand, 1); + clearDescriptionBar(); + displayAloneText(); + resetRoomVariables(MANOR_FRONT); + prepareDisplayText(); + } + } + if (_menu._menuDisplayed) + _menu.drawMenu(); +} + +/** + * Search - Prepare next object + * @remarks Originally called 'tsuiv' + */ +void MortevielleEngine::prepareNextObject() { + int objId; + int tabIdx = kAcha + ((_curSearchObjId - 1) * 10) - 1; + int localSeearchCount = 0; + do { + ++localSeearchCount; + ++_searchCount; + objId = _tabdon[tabIdx + _searchCount]; + } while ((objId == 0) && (_searchCount <= 9)); + + if ((objId != 0) && (_searchCount < 11)) { + _caff = objId; + _crep = _caff + 400; + if (_currBitIndex != 0) + // Someone is present in the room + _coreVar._faithScore += 2; + } else { + prepareDisplayText(); + endSearch(); + if (localSeearchCount > 9) + _crep = 131; + } +} + +/** + * Display Arrow status + * @remarks Originally called 'tfleche' + */ +void MortevielleEngine::displayStatusArrow() { + bool qust; + char touch; + + if (_num == 9999) + return; + + displayStatusInDescriptionBar((unsigned char)152); + bool inRect = false; + do { + touch = '\0'; + + do { + _mouse.moveMouse(qust, touch); + if (shouldQuit()) + return; + + if (getMouseClick()) + inRect = (_mouse._pos.x < 256 * kResolutionScaler) && (_mouse._pos.y < 176) && (_mouse._pos.y > 12); + prepareRoom(); + } while (!(qust || inRect || _anyone)); + + if (qust && (touch == '\103')) + _dialogManager.show(_hintPctMessage); + } while (!((touch == '\73') || ((touch == '\104') && (_x != 0) && (_y != 0)) || (_anyone) || (inRect))); + + if (touch == '\73') + _keyPressedEsc = true; + + if (inRect) { + _x = _mouse._pos.x; + _y = _mouse._pos.y; + } +} + +/** + * Set coordinates + * @remarks Originally called 'tcoord' + */ +void MortevielleEngine::setCoordinates(int sx) { + int sy, ix, iy; + int ib; + + + _num = 0; + _crep = 999; + int a = 0; + int atdon = kAmzon + 3; + int cy = 0; + while (cy < _caff) { + a += _tabdon[atdon]; + atdon += 4; + ++cy; + } + + if (_tabdon[atdon] == 0) { + _crep = 997; + return; + } + + a += kFleche; + int cb = 0; + for (cy = 0; cy <= (sx - 2); ++cy) { + ib = (_tabdon[a + cb] << 8) + _tabdon[(a + cb + 1)]; + cb += (ib * 4) + 2; + } + ib = (_tabdon[a + cb] << 8) + _tabdon[(a + cb + 1)]; + if (ib == 0) { + _crep = 997; + return; + } + + cy = 1; + do { + cb += 2; + sx = _tabdon[a + cb] * kResolutionScaler; + sy = _tabdon[(a + cb + 1)]; + cb += 2; + ix = _tabdon[a + cb] * kResolutionScaler; + iy = _tabdon[(a + cb + 1)]; + ++cy; + } while (!(((_x >= sx) && (_x <= ix) && (_y >= sy) && (_y <= iy)) || (cy > ib))); + + if ((_x >= sx) && (_x <= ix) && (_y >= sy) && (_y <= iy)) { + _num = cy - 1; + return; + } + + _crep = 997; +} + +/** + * Display LOOK Screen + * @remarks Originally called 'treg' + */ +void MortevielleEngine::displayLookScreen(int objId) { + int mdes = _caff; + _caff = objId; + + if (((_caff > 29) && (_caff < 33)) || (_caff == 144) || (_caff == 147) || (_caff == 149) || (_currAction == _menu._opcodeSLook)) { + drawPictureWithText(); + if ((_caff > 29) && (_caff < 33)) + handleDescriptionText(2, _caff); + else + handleDescriptionText(2, _caff + 400); + testKey(true); + _caff = mdes; + _currMenu = MENU_NONE; + _crep = 998; + } else { + _obpart = true; + _crep = _caff + 400; + _menu.setSearchMenu(); + } +} + +/** + * Engine function - Put in hand + * @remarks Originally called 'avpoing' + */ +void MortevielleEngine::putInHand(int &objId) { + _crep = 999; + if (_coreVar._selectedObjectId != 0) + addObjectToInventory(_coreVar._selectedObjectId); + + // If inventory wasn't full + if (_crep != 139) { + displayItemInHand(objId + 400); + _coreVar._selectedObjectId = objId; + objId = 0; + } +} + +/** + * Search - Get the first object + * @remarks Originally called 'rechai' + */ +int MortevielleEngine::getFirstObject() { + int tmpPlace = _coreVar._currPlace; + + if (_coreVar._currPlace == CRYPT) + tmpPlace = CELLAR; + + return _tabdon[kAsearch + (tmpPlace * 7) + _num - 1]; +} + +/** + * Check before leaving the secret passage + * @remarks Originally called 't23coul' + */ +int MortevielleEngine::checkLeaveSecretPassage() { + if (!checkInventory(143)) { + _crep = 1512; + loseGame(); + } + + return CELLAR; +} + +/** + * Display status character in description bar + * @remarks Originally called 'fenat' + */ +void MortevielleEngine::displayStatusInDescriptionBar(char stat) { + _mouse.hideMouse(); + _screenSurface.writeCharacter(Common::Point(306, 193), stat, 12); + _screenSurface.drawBox(300, 191, 16, 8, 15); + _mouse.showMouse(); +} + +/** + * Test Keyboard + * @remarks Originally called 'teskbd' + */ +void MortevielleEngine::testKeyboard() { + if (keyPressed()) + gettKeyPressed(); +} + +/** + * Test Key Pressed + * @remarks Originally called 'testou' + */ +int MortevielleEngine::gettKeyPressed() { + char ch = getChar(); + + switch (ch) { + case '\23' : + _soundOff = !_soundOff; + break; + case '\26' : + if ((_x26KeyCount == 1) || (_x26KeyCount == 2)) { + decodeNumber(&_cfiecBuffer[161 * 16], (_cfiecBufferSize - (161 * 16)) / 64); + ++_x26KeyCount; + + return 61; + } + break; + case '\33' : + if (keyPressed()) + ch = getChar(); + break; + default: + break; + } + + return (int)ch; +} + +} // End of namespace Mortevielle |