void DrasculaEngine::enterName() { Common::KeyCode key; flushKeyBuffer(); int v = 0, h = 0; char select2[23]; strcpy(select2, " "); for (;;) { select2[v] = '-'; copyBackground(115, 14, 115, 14, 176, 9, bgSurface, screenSurface); print_abc(select2, 117, 15); updateScreen(); key = getScan(); if (key != 0) { if (key >= 0 && key <= 0xFF && isalpha(key)) select2[v] = tolower(key); else if ((key >= Common::KEYCODE_0 && key <= Common::KEYCODE_9) || key == Common::KEYCODE_SPACE) select2[v] = key; else if (key == Common::KEYCODE_ESCAPE) break; else if (key == Common::KEYCODE_RETURN) { select2[v] = '\0'; h = 1; break; } else if (key == Common::KEYCODE_BACKSPACE) select2[v] = '\0'; else v--; if (key == Common::KEYCODE_BACKSPACE) v--; else v++; } if (v == 22) v = 21; else if (v == -1) v = 0; } if (h == 1) { strcpy(select, select2); selectionMade = 1; } }
void DrasculaEngine::showMenu() { int h, n, x; char textIcon[13]; byte *srcSurface = (currentChapter == 6) ? tableSurface : frontSurface; x = whichObject(); strcpy(textIcon, iconName[x]); for (n = 1; n < ARRAYSIZE(inventoryObjects); n++) { h = inventoryObjects[n]; if (h != 0) { copyBackground(_polX[n], _polY[n], _itemLocations[n].x, _itemLocations[n].y, OBJWIDTH, OBJHEIGHT, srcSurface, screenSurface); } copyRect(_x1d_menu[h], _y1d_menu[h], _itemLocations[n].x, _itemLocations[n].y, OBJWIDTH, OBJHEIGHT, cursorSurface, screenSurface); } if (x < 7) print_abc(textIcon, _itemLocations[x].x - 2, _itemLocations[x].y - 7); }
void DrasculaEngine::centerText(const char *message, int textX, int textY) { char msg[200]; char messageLine[200]; char tmpMessageLine[200]; *messageLine = 0; *tmpMessageLine = 0; char *curWord; int curLine = 0; int x = 0; // original starts printing 4 lines above textY int y = CLIP<int>(textY - (4 * CHAR_HEIGHT), 0, 320); Common::strlcpy(msg, message, 200); // If the message fits on screen as-is, just print it here if (textFitsCentered(msg, textX)) { x = CLIP<int>(textX - strlen(msg) * CHAR_WIDTH / 2, 60, 255); print_abc(msg, x, y); return; } // If it's a one-word message it can't be broken up. It's probably a // mouse-over text, so try just sliding it to the side a bit to make it // fit. This happens with the word "TOTENKOPF" in the very first room // with the German translation. if (!strchr(msg, ' ')) { int len = strlen(msg); x = CLIP<int>(textX - len * CHAR_WIDTH / 2, 0, 319 - len * CHAR_WIDTH); print_abc(msg, x, y); return; } // Message doesn't fit on screen, split it // Get a word from the message curWord = strtok(msg, " "); while (curWord != NULL) { // Check if the word and the current line fit on screen if (tmpMessageLine[0] != '\0') Common::strlcat(tmpMessageLine, " ", 200); Common::strlcat(tmpMessageLine, curWord, 200); if (textFitsCentered(tmpMessageLine, textX)) { // Line fits, so add the word to the current message line strcpy(messageLine, tmpMessageLine); } else { // Line doesn't fit, so show the current line on screen and // create a new one // If it goes off screen, print_abc will adjust it x = CLIP<int>(textX - strlen(messageLine) * CHAR_WIDTH / 2, 60, 255); print_abc(messageLine, x, y + curLine * CHAR_HEIGHT); Common::strlcpy(messageLine, curWord, 200); Common::strlcpy(tmpMessageLine, curWord, 200); curLine++; } // Get next word curWord = strtok(NULL, " "); if (curWord == NULL) { x = CLIP<int>(textX - strlen(messageLine) * CHAR_WIDTH / 2, 60, 255); print_abc(messageLine, x, y + curLine * CHAR_HEIGHT); } } }
bool DrasculaEngine::runCurrentChapter() { int n; rightMouseButton = 0; previousMusic = -1; if (currentChapter != 2) { int soc = 0; for (n = 0; n < 6; n++) { soc = soc + CHARACTER_WIDTH; _frameX[n] = soc; } } for (n = 1; n < ARRAYSIZE(inventoryObjects); n++) inventoryObjects[n] = 0; for (n = 0; n < NUM_FLAGS; n++) flags[n] = 0; if (currentChapter == 2) { flags[16] = 1; flags[17] = 1; flags[27] = 1; } for (n = 1; n < 7; n++) inventoryObjects[n] = n; if (currentChapter == 1) { pickObject(28); if (loadedDifferentChapter == 0) animation_1_1(); selectVerb(kVerbNone); loadPic("2aux62.alg", drawSurface2); trackProtagonist = 1; objExit = 104; if (loadedDifferentChapter != 0) { if (!loadGame(saveName)) { return true; } } else { enterRoom(62); curX = -20; curY = 56; gotoObject(65, 145); } } else if (currentChapter == 2) { addObject(kItemPhone); trackProtagonist = 3; objExit = 162; if (loadedDifferentChapter == 0) enterRoom(14); else { if (!loadGame(saveName)) { return true; } } } else if (currentChapter == 3) { addObject(kItemPhone); addObject(kItemEarplugs); addObject(kItemSickle); addObject(kItemHandbag); addObject(kItemCross); addObject(kItemReefer); addObject(kItemOneCoin); flags[1] = 1; trackProtagonist = 1; objExit = 99; if (loadedDifferentChapter == 0) enterRoom(20); else { if (!loadGame(saveName)) { return true; } } // From here onwards the items have different IDs } else if (currentChapter == 4) { addObject(kItemPhone2); addObject(kItemCross2); addObject(kItemReefer2); addObject(kItemOneCoin2); objExit = 100; if (loadedDifferentChapter == 0) { enterRoom(21); trackProtagonist = 0; curX = 235; curY = 164; } else { if (!loadGame(saveName)) { return true; } } } else if (currentChapter == 5) { addObject(28); addObject(7); addObject(9); addObject(11); addObject(13); addObject(14); addObject(15); addObject(17); addObject(20); trackProtagonist = 1; objExit = 100; if (loadedDifferentChapter == 0) { enterRoom(45); } else { if (!loadGame(saveName)) { return true; } } } else if (currentChapter == 6) { addObject(28); addObject(9); trackProtagonist = 1; objExit = 104; if (loadedDifferentChapter == 0) { enterRoom(58); animation_1_6(); } else { if (!loadGame(saveName)) { return true; } loadPic("auxdr.alg", drawSurface2); } } showCursor(); while (!shouldQuit()) { if (characterMoved == 0) { stepX = STEP_X; stepY = STEP_Y; } if (characterMoved == 0 && walkToObject == 1) { trackProtagonist = trackFinal; walkToObject = 0; } if (currentChapter == 2) { // NOTE: the checks for room number 14 below are a hack used in the original // game, and move the character to a place where his feet are not drawn above // the pianist's head. Originally, walkToObject was not updated properly, which // lead to an incorrect setting of the protagonist's tracking flag (above). This // made the character start walking off screen, as his actual position was // different than the displayed one if (roomNumber == 3 && (curX == 279) && (curY + curHeight == 101)) { gotoObject(178, 121); gotoObject(169, 135); } else if (roomNumber == 14 && (curX == 214) && (curY + curHeight == 121)) { walkToObject = 1; gotoObject(190, 130); } else if (roomNumber == 14 && (curX == 246) && (curY + curHeight == 112)) { walkToObject = 1; gotoObject(190, 130); } } moveCursor(); updateScreen(); if (currentChapter == 2) { if (musicStatus() == 0 && roomMusic != 0) playMusic(roomMusic); } else { if (musicStatus() == 0) playMusic(roomMusic); } delay(25); #ifndef _WIN32_WCE // FIXME // This and the following #ifndefs disable the excess updateEvents() calls *within* the game loop. // Events such as keypresses or mouse clicks are dropped on the ground with no processing // by these calls. They are properly handled by the implicit call through getScan() below. // It is not a good practice to not process events and indeed this created problems with synthesized // events in the wince port. updateEvents(); #endif if (!_menuScreen && takeObject == 1) checkObjects(); #ifdef _WIN32_WCE if (rightMouseButton) if (_menuScreen) { #else if (rightMouseButton == 1 && _menuScreen) { #endif rightMouseButton = 0; delay(100); if (currentChapter == 2) { loadPic(menuBackground, cursorSurface); loadPic(menuBackground, backSurface); } else { loadPic(99, cursorSurface); loadPic(99, backSurface); } setPalette((byte *)&gamePalette); _menuScreen = false; #ifndef _WIN32_WCE // FIXME: This call here is in hope that it will catch the rightmouseup event so the // next if block won't be executed. This too is not a good coding practice. I've recoded it // with a mutual exclusive if block for the menu. I would commit this properly but I cannot test // for other (see Desktop) ports right now. updateEvents(); #endif #ifdef _WIN32_WCE } else { #else } // Do not show the inventory screen in chapter 5, if the right mouse button is clicked // while the plug (object 16) is held // Fixes bug #2059621 - "DRASCULA: Plug bug" if (rightMouseButton == 1 && !_menuScreen && !(currentChapter == 5 && pickedObject == 16)) { #endif rightMouseButton = 0; delay(100); characterMoved = 0; if (trackProtagonist == 2) trackProtagonist = 1; if (currentChapter == 4) { loadPic("icons2.alg", backSurface); loadPic("icons2.alg", cursorSurface); } else if (currentChapter == 5) { loadPic("icons3.alg", backSurface); loadPic("icons3.alg", cursorSurface); } else if (currentChapter == 6) { loadPic("iconsp.alg", backSurface); loadPic("iconsp.alg", cursorSurface); } else { loadPic("icons.alg", backSurface); loadPic("icons.alg", cursorSurface); } _menuScreen = true; #ifndef _WIN32_WCE updateEvents(); #endif selectVerb(kVerbNone); } if (leftMouseButton == 1 && _menuBar) { delay(100); selectVerbFromBar(); } else if (leftMouseButton == 1 && takeObject == 0) { delay(100); if (verify1()) return true; } else if (leftMouseButton == 1 && takeObject == 1) { if (verify2()) return true; } _menuBar = (mouseY < 24 && !_menuScreen) ? true : false; Common::KeyCode key = getScan(); if (key == Common::KEYCODE_F1 && !_menuScreen) { selectVerb(kVerbLook); } else if (key == Common::KEYCODE_F2 && !_menuScreen) { selectVerb(kVerbPick); } else if (key == Common::KEYCODE_F3 && !_menuScreen) { selectVerb(kVerbOpen); } else if (key == Common::KEYCODE_F4 && !_menuScreen) { selectVerb(kVerbClose); } else if (key == Common::KEYCODE_F5 && !_menuScreen) { selectVerb(kVerbTalk); } else if (key == Common::KEYCODE_F6 && !_menuScreen) { selectVerb(kVerbMove); } else if (key == Common::KEYCODE_F9) { volumeControls(); } else if (key == Common::KEYCODE_F10) { if (!saveLoadScreen()) return true; } else if (key == Common::KEYCODE_F8) { selectVerb(kVerbNone); } else if (key == Common::KEYCODE_v) { _subtitlesDisabled = true; ConfMan.setBool("subtitles", !_subtitlesDisabled); print_abc(_textsys[2], 96, 86); updateScreen(); delay(1410); } else if (key == Common::KEYCODE_t) { _subtitlesDisabled = false; ConfMan.setBool("subtitles", !_subtitlesDisabled); print_abc(_textsys[3], 94, 86); updateScreen(); delay(1460); } else if (key == Common::KEYCODE_ESCAPE) { if (!confirmExit()) return false; } else if (key == Common::KEYCODE_TILDE || key == Common::KEYCODE_BACKQUOTE) { _console->attach(); _console->onFrame(); } else if (currentChapter == 6 && key == Common::KEYCODE_0 && roomNumber == 61) { loadPic("alcbar.alg", bgSurface, 255); } if (leftMouseButton != 0 || rightMouseButton != 0 || key != 0) if (currentChapter != 3) framesWithoutAction = 0; if (framesWithoutAction == 15000) { screenSaver(); if (currentChapter != 3) framesWithoutAction = 0; } if (currentChapter != 3) framesWithoutAction++; } return false; } bool DrasculaEngine::verify1() { int l; if (_menuScreen) removeObject(); else { for (l = 0; l < numRoomObjs; l++) { if (mouseX >= x1[l] && mouseY >= y1[l] && mouseX <= x2[l] && mouseY <= y2[l] && doBreak == 0) { if (exitRoom(l)) return true; if (doBreak == 1) break; } } if (mouseX > curX && mouseY > curY && mouseX < curX + curWidth && mouseY < curY + curHeight) doBreak = 1; for (l = 0; l < numRoomObjs; l++) { if (mouseX > x1[l] && mouseY > y1[l] && mouseX < x2[l] && mouseY < y2[l] && doBreak == 0) { roomX = roomObjX[l]; roomY = roomObjY[l]; trackFinal = trackObj[l]; doBreak = 1; walkToObject = 1; startWalking(); } } if (doBreak == 0) { roomX = CLIP(mouseX, floorX1, floorX2); roomY = CLIP(mouseY, floorY1 + feetHeight, floorY2); startWalking(); } doBreak = 0; } return false; }
bool DrasculaEngine::saveLoadScreen() { char names[10][23]; char file[50]; char fileEpa[50]; int n, n2, num_sav = 0, y = 27; Common::InSaveFile *sav; clearRoom(); snprintf(fileEpa, 50, "%s.epa", _targetName.c_str()); if (!(sav = _saveFileMan->openForLoading(fileEpa))) { Common::OutSaveFile *epa; if (!(epa = _saveFileMan->openForSaving(fileEpa))) error("Can't open %s file", fileEpa); for (n = 0; n < NUM_SAVES; n++) epa->writeString("*\n"); epa->finalize(); delete epa; if (!(sav = _saveFileMan->openForLoading(fileEpa))) { error("Can't open %s file", fileEpa); } } for (n = 0; n < NUM_SAVES; n++) { strncpy(names[n], sav->readLine().c_str(), 23); names[n][22] = '\0'; // make sure the savegame name is 0-terminated } delete sav; loadPic("savescr.alg", bgSurface, HALF_PAL); color_abc(kColorLightGreen); select[0] = 0; _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); setCursor(kCursorCrosshair); while (!shouldQuit()) { y = 27; copyBackground(); for (n = 0; n < NUM_SAVES; n++) { print_abc(names[n], 116, y); y = y + 9; } print_abc(select, 117, 15); updateScreen(); y = 27; updateEvents(); if (leftMouseButton == 1) { delay(50); for (n = 0; n < NUM_SAVES; n++) { if (mouseX > 115 && mouseY > y + (9 * n) && mouseX < 115 + 175 && mouseY < y + 10 + (9 * n)) { strcpy(select, names[n]); if (strcmp(select, "*")) selectionMade = 1; else { enterName(); strcpy(names[n], select); if (selectionMade == 1) { snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); saveGame(file); Common::OutSaveFile *tsav; if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { error("Can't open %s file", fileEpa); } for (n = 0; n < NUM_SAVES; n++) { tsav->writeString(names[n]); tsav->writeString("\n"); } tsav->finalize(); delete tsav; } } print_abc(select, 117, 15); y = 27; for (n2 = 0; n2 < NUM_SAVES; n2++) { print_abc(names[n2], 116, y); y = y + 9; } if (selectionMade == 1) { snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); } num_sav = n; } } if (mouseX > 117 && mouseY > 15 && mouseX < 295 && mouseY < 24 && selectionMade == 1) { enterName(); strcpy(names[num_sav], select); print_abc(select, 117, 15); y = 27; for (n2 = 0; n2 < NUM_SAVES; n2++) { print_abc(names[n2], 116, y); y = y + 9; } if (selectionMade == 1) { snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); saveGame(file); Common::OutSaveFile *tsav; if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { error("Can't open %s file", fileEpa); } for (n = 0; n < NUM_SAVES; n++) { tsav->writeString(names[n]); tsav->writeString("\n"); } tsav->finalize(); delete tsav; } } if (mouseX > 125 && mouseY > 123 && mouseX < 199 && mouseY < 149 && selectionMade == 1) { if (!loadGame(file)) { _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); return false; } break; } else if (mouseX > 208 && mouseY > 123 && mouseX < 282 && mouseY < 149 && selectionMade == 1) { saveGame(file); Common::OutSaveFile *tsav; if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { error("Can't open %s file", fileEpa); } for (n = 0; n < NUM_SAVES; n++) { tsav->writeString(names[n]); tsav->writeString("\n"); } tsav->finalize(); delete tsav; } else if (mouseX > 168 && mouseY > 154 && mouseX < 242 && mouseY < 180) break; else if (selectionMade == 0) { print_abc("Please select a slot", 117, 15); } updateScreen(); delay(200); } y = 26; delay(5); } selectVerb(kVerbNone); clearRoom(); loadPic(roomNumber, bgSurface, HALF_PAL); selectionMade = 0; _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); return true; }