/* 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 3 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, see . * */ #include "bagel/spacebar/baglib/master_win.h" #include "bagel/spacebar/baglib/button_object.h" #include "bagel/spacebar/dialogs/credits_dialog.h" #include "bagel/spacebar/dialogs/quit_dialog.h" #include "bagel/spacebar/baglib/help.h" #include "bagel/spacebar/baglib/menu_dlg.h" #include "bagel/spacebar/dialogs/opt_window.h" #include "bagel/spacebar/dialogs/restore_dialog.h" #include "bagel/spacebar/dialogs/restart_dialog.h" #include "bagel/spacebar/dialogs/save_dialog.h" #include "bagel/spacebar/dialogs/start_dialog.h" #include "bagel/spacebar/baglib/storage_dev_win.h" #include "bagel/spacebar/baglib/wield.h" #include "bagel/spacebar/boflib/app.h" #include "bagel/boflib/event_loop.h" #include "bagel/spacebar/boflib/file.h" #include "bagel/boflib/palette.h" #include "bagel/spacebar/baglib/pan_window.h" #include "bagel/boflib/rect.h" #include "bagel/bagel.h" #include "bagel/boflib/file_functions.h" #include "bagel/boflib/log.h" #include "bagel/spacebar/boflib/std_keys.h" namespace Bagel { namespace SpaceBar { #define STARTWORLD "$SBARDIR\\WLD\\BAR.WLD" #define GLOBALWORLD "$SBARDIR\\WLD\\GLOBAL.WLD" #define LOADINGBMP "$SBARDIR\\GENERAL\\SYSTEM\\LOADING.BMP" #define USER_OPTIONS "UserOptions" #define WAVE_VOLUME "WaveVolume" // Global vars // extern CBofWindow *g_hackWindow; static bool g_allowRestoreFl = false; bool g_restoreObjectListFl = true; #define NUM_MSG_STRINGS 3 static int g_string = 0; static char g_stringArray[NUM_MSG_STRINGS][512]; // static initializations bool CBagMasterWin::_objSaveFl = false; StObj *CBagMasterWin::_objList = nullptr; CBagCursor *CBagMasterWin::_cursorList[MAX_CURSORS]; int CBagMasterWin::_menuCount = 0; int CBagMasterWin::_curCursor = 0; // // // CBagMasterWin // CBagMasterWin::CBagMasterWin() { CBofRect screenRect(0, 0, 640 - 1, 480 - 1); const char *appName = "BAGEL Application"; CBofApp *app = CBofApp::getApp(); if (app != nullptr) { screenRect.setRect(0, 0, app->screenWidth() - 1, app->screenHeight() - 1); appName = app->getAppName(); } screenRect.setRect(0, 0, 640 - 1, 480 - 1); _fadeIn = 0; _gameWindow = nullptr; _storageDeviceList = nullptr; _gameSDevList = nullptr; _variableList = nullptr; _diskId = 1; create(appName, &screenRect, nullptr); // Assume default system screen _sysScreen = "$SBARDIR\\GENERAL\\SYSTEM\\GAMBHALL.BMP"; fixPathName(_sysScreen); // Load wait sound for when user hits the spacebar CBofString waitName("$SBARDIR\\GENERAL\\WAIT.WAV"); fixPathName(waitName); _waitSound = new CBofSound(this, waitName, SOUND_MIX); } CBagMasterWin::~CBagMasterWin() { assert(isValidObject(this)); delete _waitSound; _waitSound = nullptr; CBofApp *app = CBofApp::getApp(); if (app != nullptr) { app->setPalette(nullptr); } // Delete any remaining cursors for (int i = 0; i < MAX_CURSORS; i++) { delete _cursorList[i]; _cursorList[i] = nullptr; } delete _gameWindow; _gameWindow = nullptr; delete _storageDeviceList; _storageDeviceList = nullptr; delete _variableList; _variableList = nullptr; delete _gameSDevList; _gameSDevList = nullptr; // We can get rid of this buffer since the game is shutting down if (_objList != nullptr) { bofFree(_objList); _objList = nullptr; } } ErrorCode CBagMasterWin::showSystemDialog(bool bSaveBackground) { assert(isValidObject(this)); if (g_engine->isDemo()) return ERR_NONE; CBagStorageDevWnd *sdev = getCurrentStorageDev(); if ((sdev == nullptr) || (sdev->getDeviceType() == SDEV_GAMEWIN) || (sdev->getDeviceType() == SDEV_ZOOMPDA)) { logInfo("Showing System Screen"); // Use specified bitmap as this dialog's image CBofBitmap *dialogBmp = SpaceBar::loadBitmap(_sysScreen.getBuffer()); CBagOptWindow optionDialog; optionDialog.setBackdrop(dialogBmp); const CBofRect dialogRect = optionDialog.getBackdrop()->getRect(); if (!bSaveBackground) { optionDialog.setFlags(optionDialog.getFlags() & ~BOFDLG_SAVEBACKGND); } // Create the dialog box optionDialog.create("System Dialog", dialogRect.left, dialogRect.top, dialogRect.width(), dialogRect.height(), this); CBofWindow *lastWin = g_hackWindow; g_hackWindow = &optionDialog; g_pauseTimerFl = true; const int dialogReturnValue = optionDialog.doModal(); g_pauseTimerFl = false; optionDialog.detach(); g_hackWindow = lastWin; logInfo("Exiting System Screen"); // User chose to Quit if (dialogReturnValue == 0) { close(); } } return _errCode; } ErrorCode CBagMasterWin::showCreditsDialog(CBofWindow *win, bool bSaveBkg) { assert(isValidObject(this)); logInfo("Showing Credits Screen"); // Use specified bitmap as this dialog's image CBofBitmap *barBmp = SpaceBar::loadBitmap(buildSysDir("BARAREA.BMP")); CBagCreditsDialog creditsDialog; creditsDialog.setBackdrop(barBmp); const CBofRect dialogRect = creditsDialog.getBackdrop()->getRect(); // Don't allow save of background? if (!bSaveBkg) { const int flags = creditsDialog.getFlags(); creditsDialog.setFlags(flags & ~BOFDLG_SAVEBACKGND); } // Use CBagMasterWin if no parent specified if (win == nullptr) { win = this; } // Create the dialog box creditsDialog.create("Save Dialog", dialogRect.left, dialogRect.top, dialogRect.width(), dialogRect.height(), win); const bool saveTimerFl = g_pauseTimerFl; g_pauseTimerFl = true; creditsDialog.doModal(); g_pauseTimerFl = saveTimerFl; logInfo("Exiting Credits Screen"); return _errCode; } bool CBagMasterWin::showQuitDialog(CBofWindow *win, bool bSaveBackground) { assert(isValidObject(this)); CBagStorageDevWnd *sdev = getCurrentStorageDev(); bool quitFl = false; if ((sdev == nullptr) || (sdev->getDeviceType() == SDEV_GAMEWIN) || (sdev->getDeviceType() == SDEV_ZOOMPDA)) { logInfo("Showing Quit Screen"); CBofSound::pauseSounds(); if (win == nullptr) { win = this; } // Use specified bitmap as this dialog's image CBofBitmap *dialogBmp = SpaceBar::loadBitmap(_sysScreen.getBuffer()); CBagQuitDialog quitDialog; quitDialog.setBackdrop(dialogBmp); const CBofRect dialogRect = quitDialog.getBackdrop()->getRect(); if (!bSaveBackground) { quitDialog.setFlags(quitDialog.getFlags() & ~BOFDLG_SAVEBACKGND); } // Create the dialog box quitDialog.create("Quit Dialog", dialogRect.left, dialogRect.top, dialogRect.width(), dialogRect.height(), win); const bool saveTimerFl = g_pauseTimerFl; g_pauseTimerFl = true; const int dialogReturnValue = quitDialog.doModal(); g_pauseTimerFl = saveTimerFl; switch (dialogReturnValue) { case SAVE_BTN: // Quit as as well. Saving already done within dialog itself quitFl = true; break; case QUIT_BTN: quitFl = true; break; case CANCEL_BTN: quitFl = false; break; default: break; } if (!quitFl) { CBofSound::resumeSounds(); } logInfo("Exiting Quit Screen"); } return quitFl; } ErrorCode CBagMasterWin::newGame() { assert(isValidObject(this)); char workStr[256]; char cInit[256]; workStr[0] = '\0'; cInit[0] = '\0'; CBofString initWld(cInit, 256); CBagPanWindow::flushInputEvents(); // Inits for a New Game _objSaveFl = false; CBagel *app = CBagel::getBagApp(); // Find the starting .WLD file name if (app != nullptr) { app->getOption("Startup", "WLDFile", workStr, STARTWORLD, 255); initWld = workStr; fixPathName(initWld); } loadGlobalVars(GLOBALWORLD); loadFile(initWld, "", true); return _errCode; } ErrorCode CBagMasterWin::loadFile(const CBofString &wldName, const CBofString &startWldName, bool restartFl, bool setStartFl) { char localBuffer[256]; localBuffer[0] = '\0'; Common::strcpy_s(localBuffer, "$SBARDIR\\GENERAL\\SYSTEM\\LEGAL.BMP"); CBofString wldFileName(localBuffer, 256); static bool paintedFl = false; // Make sure we get a new set of vildroid filter variables g_engine->g_getVilVarsFl = true; // Reset the Queued sound slot volumes back to default CBofSound::resetQVolumes(); if (!paintedFl) { paintedFl = true; fixPathName(wldFileName); CBofRect cRect; cRect.left = (640 - 520) / 2; cRect.top = (480 - 240) / 2; cRect.right = cRect.left + 520 - 1; cRect.bottom = cRect.top + 240 - 1; paintBitmap(this, wldFileName.getBuffer(), &cRect); } wldFileName = wldName; // Reset unique ID for menus _menuCount = 0; // Keep track of what script we are in _wldScript = wldName; // This palette will be deleted so don't let anyone use it, until it is // replaced with a new one. CBofApp *app = CBofApp::getApp(); if (app != nullptr) { app->setPalette(nullptr); } // Save all used objects (if going to another .WLD file) bool restoreFl = false; if ((_storageDeviceList != nullptr) && !restartFl) { if (!_objSaveFl) { _objSaveFl = true; // Only allocate the object list when we really need it... if (_objList == nullptr) { // Allocate a buffer filled with 0s _objList = (StObj *)bofCleanAlloc(MAX_OBJS * sizeof(StObj)); } _storageDeviceList->saveObjList(_objList, MAX_OBJS); // xxx // Save our SDEV location, so we can restore it from Kerpupu saveSDevStack(); } else { restoreFl = true; } } if (_variableList != nullptr) { _variableList->releaseVariables(false); } delete _gameSDevList; _gameSDevList = nullptr; delete _gameWindow; _gameWindow = nullptr; delete _storageDeviceList; _storageDeviceList = nullptr; // Unload all current cursors for (int i = 0; i < MAX_CURSORS; i++) { delete _cursorList[i]; _cursorList[i] = nullptr; } CBagMenu::setUniversalObjectList(nullptr); _storageDeviceList = new CBagStorageDevManager(); if (!_variableList) { _variableList = new CBagVarManager(); } _gameSDevList = new CBofList; fixPathName(wldFileName); timerStart(); if (fileExists(wldFileName) && (fileLength(wldFileName) > 0)) { // Force buffer to be big enough so that the entire script // is pre-loaded const int length = fileLength(wldFileName); char *fileBuf = (char *)bofAlloc(length); CBagIfstream fpInput(fileBuf, length); CBofFile file; file.open(wldFileName); file.read(fileBuf, length); file.close(); loadFileFromStream(fpInput, startWldName); bofFree(fileBuf); // Possibly need to switch CDs CBagel *bagApp = CBagel::getBagApp(); if (bagApp != nullptr) { _errCode = bagApp->verifyCDInDrive(_diskId, _cdChangeAudio.getBuffer()); if (_errCode != ERR_NONE || g_engine->shouldQuit()) { close(); return _errCode; } } // Now that we know we are on the correct CD, we can load the cursors // Only load the cursors that are not wield cursors for (int i = 0; i < MAX_CURSORS; i++) { if (_cursorList[i] != nullptr) { _cursorList[i]->load(); } } setActiveCursor(0); CBagWield::setWieldCursor(-1); if (g_restoreObjectListFl) { if (restoreFl && _objSaveFl) { assert(_storageDeviceList != nullptr); if (_storageDeviceList != nullptr) { // Use a preallocated buffer, trash it when we're done. assert(_objList != nullptr); _storageDeviceList->restoreObjList(_objList, MAX_OBJS); // All done with this list, can trash it now bofFree(_objList); _objList = nullptr; } _objSaveFl = false; } } g_restoreObjectListFl = true; // If a start wld is passed in then use it if (!startWldName.isEmpty()) { _startWld = startWldName; } if (setStartFl && !_startWld.isEmpty()) { setStorageDev(_startWld); } restoreActiveMessages(_storageDeviceList); } else { reportError(ERR_FFIND, "Could not find World Script: %s", wldFileName.getBuffer()); } logInfo(buildString("Time to Load %s, %u ms", wldFileName.getBuffer(), timerStop())); return _errCode; } void CBagMasterWin::saveSDevStack() { assert(isValidObject(this)); // Save our SDEV location, so we can restore it from Kerpupu char locStack[MAX_CLOSEUP_DEPTH][MAX_VAR_VALUE]; char tempBuf[256]; memset(&locStack[0][0], 0, sizeof(char) * MAX_CLOSEUP_DEPTH * MAX_VAR_VALUE); tempBuf[0] = '\0'; CBagStorageDevWnd *sdevWin = getCurrentStorageDev(); if (sdevWin != nullptr) { int i = 0; CBofString curStr = sdevWin->getName(); if (!curStr.isEmpty()) { Common::strcpy_s(locStack[i], curStr.getBuffer()); curStr = sdevWin->getPrevSDev(); i++; } while ((i < MAX_CLOSEUP_DEPTH) && !curStr.isEmpty()) { sdevWin = (CBagStorageDevWnd *)_storageDeviceList->getStorageDevice(curStr); if (sdevWin != nullptr) { Common::strcpy_s(locStack[i], curStr.getBuffer()); i++; curStr = sdevWin->getPrevSDev(); } else { break; } } i--; for (int j = i; j >= 0; j--) { if (locStack[j][0] != '\0') { Common::strcat_s(tempBuf, locStack[j]); if (j != 0) { Common::strcat_s(tempBuf, "~~"); } } } // Variables cannot exceed MAX_VAR_VALUE characters in length (for Save/Restore) assert(strlen(tempBuf) < MAX_VAR_VALUE); // Store our current sdev location stack in a global variable. CBagVar *var = g_VarManager->getVariable("$LASTWORLD"); if (var != nullptr) { curStr = tempBuf; var->setValue(curStr); } } } ErrorCode CBagMasterWin::loadGlobalVars(const CBofString &wldName) { assert(isValidObject(this)); char localBuff[256]; localBuff[0] = '\0'; CBofString wldFileName(localBuff, 256); wldFileName = wldName; delete _variableList; _variableList = new CBagVarManager(); fixPathName(wldFileName); if (fileExists(wldFileName) && (fileLength(wldFileName) > 0)) { // Force buffer to be big enough so that the entire script // is pre-loaded const int length = fileLength(wldFileName); char *buffer = (char *)bofAlloc(length); CBagIfstream fpInput(buffer, length); CBofFile file; file.open(wldFileName); file.read(buffer, length); file.close(); while (!fpInput.eof()) { fpInput.eatWhite(); if (!fpInput.eatWhite()) { break; } KEYWORDS keyword; getKeywordFromStream(fpInput, keyword); switch (keyword) { case VARIABLE: { CBagVar *var = new CBagVar; fpInput.eatWhite(); var->setInfo(fpInput); var->setGlobal(); break; } case REMARK: { char dummyStr[256]; fpInput.getCh(dummyStr, 255); break; } case STORAGEDEV: case START_WLD: case SYSSCREEN: case DISKID: case DISKAUDIO: case SHAREDPAL: case PDASTATE: default: { parseAlertBox(fpInput, "Syntax Error: Unexpected Type in Global Var Wld:", __FILE__, __LINE__); break; } } } bofFree(buffer); } return _errCode; } ErrorCode CBagMasterWin::loadFileFromStream(CBagIfstream &input, const CBofString &wldName) { char localStr[256]; localStr[0] = 0; bool isWieldCursorFl = false; memset(localStr, 0, 256); CBofString workStr(localStr, 256); _startWld = wldName; while (!input.eof()) { input.eatWhite(); int filter = 0; CBofRect curRect; curRect.right = curRect.left - 1; curRect.bottom = curRect.top - 1; KEYWORDS keyword; if (!input.eatWhite()) { break; } getKeywordFromStream(input, keyword); switch (keyword) { case STORAGEDEV: { char nameBuff[256]; char typeBuff[256]; nameBuff[0] = 0; typeBuff[0] = 0; memset(nameBuff, 0, 256); memset(typeBuff, 0, 256); CBofString nameStr(nameBuff, 256); CBofString typeStr(typeBuff, 256); input.eatWhite(); getAlphaNumFromStream(input, nameStr); input.eatWhite(); int fadeId = 0; while (input.peek() != '{') { getAlphaNumFromStream(input, workStr); input.eatWhite(); if (!workStr.find("AS")) { input.eatWhite(); getAlphaNumFromStream(input, typeStr); } else if (!workStr.find("RECT")) { input.eatWhite(); getRectFromStream(input, curRect); } else if (!workStr.find("FILTER")) { input.eatWhite(); getIntFromStream(input, filter); } else if (!workStr.find("FADE")) { // Note that this should usually be set in the link input.eatWhite(); getIntFromStream(input, fadeId); } else { // There is an error here logError(buildString("FAILED on argument of storage device %s : %s", nameStr.getBuffer(), typeStr.getBuffer())); return ERR_UNKNOWN; } input.eatWhite(); } CBagStorageDev *sdev = onNewStorageDev(typeStr); if (!sdev) { logError(buildString("FAILED on open of storage device %s : %s", nameStr.getBuffer(), typeStr.getBuffer())); return ERR_UNKNOWN; } // Default DISK ID for this storage device is the same // as the ID specified for this .WLD script file. sdev->setDiskID(_diskId); if (curRect.width() && curRect.height()) sdev->setRect(curRect); sdev->loadFileFromStream(input, nameStr, false); if (filter) { sdev->setFilterId((uint16)filter); // Set the filter on the window. onNewFilter(sdev, typeStr); } if (fadeId != 0) { sdev->setFadeId((uint16)fadeId); } _gameSDevList->addToTail(sdev); break; } case START_WLD: { char strBuf[256]; strBuf[0] = '\0'; CBofString str(strBuf, 256); input.eatWhite(); if (input.peek() == '=') { input.getCh(); input.eatWhite(); getAlphaNumFromStream(input, str); // Only use the start wld if not specified elsewhere _startWld = str; logInfo(buildString("START_WLD set to %s", _startWld.getBuffer())); } break; } case WIELDCURSOR: isWieldCursorFl = true; // fallthrough case CURSOR: { char strBuf[256]; strBuf[0] = 0; CBofString str(strBuf, 256); int id; input.eatWhite(); getIntFromStream(input, id); input.eatWhite(); if (input.peek() == '=') { int x, y; input.getCh(); input.eatWhite(); getIntFromStream(input, x); input.eatWhite(); getIntFromStream(input, y); input.eatWhite(); getAlphaNumFromStream(input, str); fixPathName(str); // Specify if we have a shared palette or not, look for // the USESHAREDPAL token after the full cursor specification bool bUseShared = false; input.eatWhite(); if (input.peek() == '=') { char sharedPalTokenBuf[256]; CBofString sharedPalToken(sharedPalTokenBuf, 256); input.getCh(); input.eatWhite(); // Check for shared pal token, if there, then create our cursor // with the shared palette bit set getAlphaNumFromStream(input, sharedPalToken); if (sharedPalToken.find("USESHAREDPAL") != -1) { bUseShared = true; } } CBagCursor *cursor = new CBagCursor(str, bUseShared); cursor->setHotspot(x, y); assert(id >= 0 && id < MAX_CURSORS); // Delete any previous cursor delete _cursorList[id]; _cursorList[id] = cursor; // Set the wielded cursor status (needed for // a load time optimization) cursor->setWieldCursor(isWieldCursorFl); } else { reportError(ERR_UNKNOWN, "Bad cursor syntax"); } break; } case PDASTATE: { char pdaStateBuf[256]; pdaStateBuf[0] = '\0'; CBofString pdaState(pdaStateBuf, 256); input.eatWhite(); if (input.peek() == '=') { input.getCh(); input.eatWhite(); getAlphaNumFromStream(input, pdaState); if (pdaState.find("MAP") != -1) { SBBasePda::setPdaMode(PDA_MAP_MODE); } else if (pdaState.find("INV") != -1) { SBBasePda::setPdaMode(PDA_INV_MODE); } else if (pdaState.find("LOG") != -1) { SBBasePda::setPdaMode(PDA_LOG_MODE); } logInfo(buildString("PDASTATE = %s", pdaStateBuf)); } break; } // Implement shared palettes case SHAREDPAL: { char bmpFileNameBuf[256]; bmpFileNameBuf[0] = '\0'; CBofString bmpFileName(bmpFileNameBuf, 256); input.eatWhite(); if (input.peek() == '=') { input.getCh(); input.eatWhite(); getAlphaNumFromStream(input, bmpFileName); fixPathName(bmpFileName); // Read the palette in and keep it hanging around for later use CBofPalette::setSharedPalette(bmpFileName); logInfo(buildString("SHAREDPAL = %s", bmpFileName.getBuffer())); } break; } case SYSSCREEN: { input.eatWhite(); if (input.peek() == '=') { input.getCh(); input.eatWhite(); getAlphaNumFromStream(input, _sysScreen); fixPathName(_sysScreen); logInfo(buildString("SYSSCREEN = %s", _sysScreen.getBuffer())); } break; } // What audio file should play for this disk swap case DISKAUDIO: { char diskIdBuf[256]; diskIdBuf[0] = '\0'; CBofString diskId(diskIdBuf, 256); input.eatWhite(); if (input.peek() == '=') { input.getCh(); input.eatWhite(); getAlphaNumFromStream(input, _cdChangeAudio); fixPathName(_cdChangeAudio); logInfo(buildString("DISKAUDIO = %s", _cdChangeAudio.getBuffer())); } break; } case DISKID: { input.eatWhite(); if (input.peek() == '=') { input.getCh(); input.eatWhite(); int n; getIntFromStream(input, n); _diskId = (uint16)n; logInfo(buildString("DISKID = %d", _diskId)); } else { } break; } case VARIABLE: { CBagVar *var = new CBagVar; input.eatWhite(); var->setInfo(input); break; } case REMARK: { char s[255]; input.getCh(s, 255); break; } default: { parseAlertBox(input, "Syntax Error:", __FILE__, __LINE__); break; } } } // While not eof // Add everything to the window return _errCode; } ErrorCode CBagMasterWin::setStorageDev(const CBofString &wldName, bool entry) { assert(CBofObject::isValidObject(&wldName)); char localBuff[256]; localBuff[0] = '\0'; CBofString extension(localBuff, 256); extension = wldName.right(4); if (_gameWindow) _gameWindow->setOnUpdate(false); if (!extension.find(".wld") || !extension.find(".WLD") || (wldName.find(".WLD~~") > 0) || (wldName.find(".wld~~") > 0)) { // This is to stop it from going out of scope before // the message is received. assert(g_string >= 0 && g_string < NUM_MSG_STRINGS); assert(wldName.getLength() < 512); strncpy(g_stringArray[g_string], wldName, 511); postUserMessage(WM_ENTER_NEW_WLD, (uint32)g_string); if (++g_string >= NUM_MSG_STRINGS) { g_string = 0; } } else if (entry) { gotoNewWindow(&wldName); } else { // This is to stop the string from going out of scope before // the message is received. assert(g_string >= 0 && g_string < NUM_MSG_STRINGS); assert(wldName.getLength() < 512); Common::strcpy_s(g_stringArray[g_string], wldName); postUserMessage(WM_EXIT_CLOSE_UP_WINDOW, (uint32)g_string); if (++g_string >= NUM_MSG_STRINGS) { g_string = 0; } } return ERR_NONE; } ErrorCode CBagMasterWin::onHelp(const CBofString &helpFile, bool /*bSaveBkg*/, CBofWindow *parent) { assert(isValidObject(this)); if (g_engine->isDemo()) return ERR_NONE; if (!helpFile.isEmpty()) { char localBuffer[256]; localBuffer[0] = '\0'; CBofString fileName(localBuffer, 256); fileName = helpFile; fixPathName(fileName); // use specified bitmap as this dialog's image char backGroundBuffer[256]; backGroundBuffer[0] = '\0'; CBofString backGround(backGroundBuffer, 256); backGround = buildString("$SBARDIR%sGENERAL%sRULES%sHELPSCRN.BMP", PATH_DELIMETER, PATH_DELIMETER, PATH_DELIMETER); fixPathName(backGround); CBofBitmap *bmp = SpaceBar::loadBitmap(backGround); CBagHelp help; help.setBackdrop(bmp); const CBofRect backRect = help.getBackdrop()->getRect(); if (parent == nullptr) parent = this; // create the dialog box help.create("HelpDialog", backRect.left, backRect.top, backRect.width(), backRect.height(), parent); help.SetHelpFile(fileName.getBuffer()); help.doModal(); help.detach(); } return _errCode; } bool g_waitOKFl = false; void CBagMasterWin::onKeyHit(uint32 keyCode, uint32 repCount) { assert(isValidObject(this)); int volume; switch (keyCode) { // Dynamic Midi Volume increase case BKEY_ALT_UP: volume = getMidiVolume(); if (volume < 12) { volume++; setMidiVolume(volume); } break; // Dynamic Midi Volume decrease case BKEY_ALT_DOWN: volume = getMidiVolume(); if (volume > 0) { volume--; setMidiVolume(volume); } break; case BKEY_SPACE: if (g_waitOKFl) { g_waitOKFl = false; // Play the tick-tock sound if (_waitSound != nullptr) { _waitSound->play(); } g_VarManager->incrementTimers(); // Prefilter this guy, could cause something to change in the // pan or the PDA or a closeup. _gameWindow->setPreFilterPan(true); _gameWindow->attachActiveObjects(); } break; // Quit case BKEY_ALT_q: case BKEY_ALT_F4: if (g_engine->isDemo() || showQuitDialog(this, false)) { close(); g_engine->quitGame(); } break; // Help case BKEY_F1: if (_gameWindow != nullptr) { onHelp(_gameWindow->getHelpFilename(), false); } break; // Save a Game case BKEY_ALT_s: case BKEY_SAVE: showSaveDialog(this, false); break; // Restore Game case BKEY_RESTORE: showRestoreDialog(this, false); break; // System options dialog case BKEY_ALT_o: case BKEY_F4: showSystemDialog(false); break; // Toggle sound On/Off case BKEY_ALT_m: muteToggle(); break; // Restart the game case BKEY_F12: showRestartDialog(this, false); break; // Default action default: if (_gameWindow) _gameWindow->onKeyHit(keyCode, repCount); break; } CBofWindow::onKeyHit(keyCode, repCount); } void CBagMasterWin::onClose() { assert(isValidObject(this)); if (_gameWindow) _gameWindow->onClose(); g_engine->quitGame(); } ErrorCode CBagMasterWin::gotoNewWindow(const CBofString *str) { assert(isValidObject(this)); assert(str != nullptr); assert(CBofObject::isValidObject(str)); CBagStorageDev *sdev; char workStringBuffer[256]; char sprevSDevBuffer[256]; char curSDevBuffer[256]; workStringBuffer[0] = '\0'; sprevSDevBuffer[0] = '\0'; curSDevBuffer[0] = '\0'; CBofString workString(workStringBuffer, 256); CBofString prevSDevString(sprevSDevBuffer, 256); CBofString currSDevString(curSDevBuffer, 256); int n = str->find("~~"); workString = *str; bool prevFl = false; while (n > 0) { prevSDevString = workString.left(n); workString = workString.mid(n + 2); n = workString.find("~~"); if (n > 0) { currSDevString = workString.left(n); sdev = _storageDeviceList->getStorageDevice(currSDevString); if (sdev != nullptr) { sdev->setPrevSDev(prevSDevString); prevFl = true; } } else { currSDevString = workString; sdev = _storageDeviceList->getStorageDevice(currSDevString); if (sdev != nullptr) { sdev->setPrevSDev(prevSDevString); prevFl = true; } } } sdev = _storageDeviceList->getStorageDevice(workString); if (sdev != nullptr) { logInfo(buildString("Switching to SDEV: %s", workString.getBuffer())); if (_gameWindow) { _gameWindow->detach(); // If the new storage device is equal to the last windows previous // lets not go in a circle // If the current game window did not have a previous win if ((_gameWindow->getPrevSDev().isEmpty()) || (_gameWindow->getPrevSDev() != sdev->getName())) { if (!prevFl) { sdev->setPrevSDev(_gameWindow->getName()); } } } // Don't allow recursion if (!sdev->getPrevSDev().isEmpty() && sdev->getPrevSDev().compareNoCase(sdev->getName()) == 0) { sdev->setPrevSDev(""); } _gameWindow = (CBagStorageDevWnd *)sdev; setCICStatus(sdev); const uint16 oldFadeId = sdev->getFadeId(); if (_fadeIn != 0) sdev->setFadeId((uint16)_fadeIn); // Reset paints g_allowPaintFl = true; sdev->attach(); sdev->setFadeId(oldFadeId); _fadeIn = 0; } return _errCode; } bool CBagMasterWin::showRestartDialog(CBofWindow *win, bool saveBkgFl) { assert(isValidObject(this)); if (g_engine->isDemo()) return false; CBagStorageDevWnd *sdev = getCurrentStorageDev(); if ((sdev == nullptr) || (sdev->getDeviceType() == SDEV_GAMEWIN) || (sdev->getDeviceType() == SDEV_ZOOMPDA)) { logInfo("Showing Restart Screen"); if (win == nullptr) { win = this; } CBagRestartDialog restartDialog(_sysScreen.getBuffer(), win); CBofWindow *pLastWin = g_hackWindow; g_hackWindow = &restartDialog; // Don't allow save of background if (!saveBkgFl) { const int lFlags = restartDialog.getFlags(); restartDialog.setFlags(lFlags & ~BOFDLG_SAVEBACKGND); } const bool saveTimerFl = g_pauseTimerFl; g_pauseTimerFl = true; const int dialogReturn = restartDialog.doModal(); g_pauseTimerFl = saveTimerFl; g_hackWindow = pLastWin; logInfo("Exiting Restart Screen"); return dialogReturn == RESTART_BTN; } return false; } void CBagMasterWin::onUserMessage(uint32 message, uint32 param) { assert(isValidObject(this)); switch (message) { case WM_SHOW_SYSTEM_DLG: showSystemDialog(); break; // Ask user if they want to restart or restore a game case WM_DIE: { // This was causing a hang if you die while // there is a background audio looping. So, I am going // to kill all audio. This will probably break when you die // with audio only (i.e. no smacker), but that can be fixed in // script. // CBofSound::stopSounds(); // Kill any waiting PDA messages that are queued up... CBagPDA::removeFromMovieQueue(nullptr); CBofBitmap bmp(width(), height(), CBagel::getApp()->getPalette()); bmp.fillRect(nullptr, COLOR_BLACK); bmp.fadeLines(this); char buffer[MAX_FNAME]; Common::strcpy_s(buffer, buildSysDir("DIED2.BMP")); if (param == 2) { Common::strcpy_s(buffer, buildSysDir("START.BMP")); } CBagStartDialog dialog(buffer, this); CBofWindow *lastWin = g_hackWindow; g_hackWindow = &dialog; g_allowRestoreFl = true; int dialogRet = dialog.doModal(); g_allowRestoreFl = false; g_hackWindow = lastWin; // Hide that dialog bmp.paint(this, 0, 0); switch (dialogRet) { case RESTORE_BTN: break; case RESTART_BTN: newGame(); break; case QUIT_BTN: close(); g_engine->quitGame(); break; } return; } case WM_ENTER_NEW_WLD: { char localBuff[256]; localBuff[0] = '\0'; CBofString wldScript(localBuff, 256); // User info is an index into an array of temporary string buffers assert(param < NUM_MSG_STRINGS); wldScript = g_stringArray[(int)param]; char startWldBuf[256]; startWldBuf[0] = '\0'; CBofString startWld(startWldBuf, 256); int n = wldScript.find("~~"); if (n > 0) { startWld = wldScript.mid(n + 2); wldScript = wldScript.left(n); } loadFile(wldScript, startWld); break; } case WM_ENTER_PAN_WINDOW: case WM_ENTER_CLOSE_UP_WINDOW: // Should never be called assert(false); break; case WM_EXIT_CLOSE_UP_WINDOW: { CBofString deviceStr; // User info is an index into an array of temporary string buffers assert(param < NUM_MSG_STRINGS); deviceStr = g_stringArray[(int)param]; CBagStorageDev *sdev = _storageDeviceList->getStorageDevice(deviceStr); if (sdev) { if (_gameWindow) { _gameWindow->detach(); } sdev->attach(); sdev->setPreFilterPan(true); _gameWindow = (CBagStorageDevWnd *)sdev; // Reset the CIC var setCICStatus(sdev); } else { // Report error } break; } default: break; } if (_gameWindow) _gameWindow->setOnUpdate(true); } ErrorCode CBagMasterWin::Run() { return _errCode; } void CBagMasterWin::setActiveCursor(int cursorId) { assert(cursorId >= 0 && cursorId < MAX_CURSORS); if (_cursorList[cursorId] != nullptr) { _cursorList[cursorId]->setCurrent(); _curCursor = cursorId; } } void CBagMasterWin::fillSaveBuffer(StBagelSave *saveBuf) { assert(isValidObject(this)); assert(saveBuf != nullptr); // // Fill the save game buffer with all the info we need to restore this game // // 1st, wipe it memset(saveBuf, 0, sizeof(StBagelSave)); CBagel *app = CBagel::getBagApp(); if (app != nullptr) { CBagMasterWin *masterWin = app->getMasterWnd(); if (masterWin != nullptr) { // Save Global variables CBagVarManager *varManager = getVariableManager(); if (varManager != nullptr) { // Walk variable list and save each global variable int j = 0; int n = varManager->getNumVars(); for (int i = 0; i < n; i++) { CBagVar *curVar = varManager->getVariable(i); if (curVar != nullptr) { // Need to save local variables in flashbacks. // Let me know if this breaks anything. // // If it's a global variable, then we need to store it if (!curVar->getName().isEmpty()) { assert(strlen(curVar->getName()) < MAX_VAR_NAME); Common::strcpy_s(saveBuf->_stVarList[j]._szName, curVar->getName()); } if (!curVar->getValue().isEmpty()) { assert(strlen(curVar->getValue()) < MAX_VAR_VALUE); Common::strcpy_s(saveBuf->_stVarList[j]._szValue, curVar->getValue()); } saveBuf->_stVarList[j]._nType = (uint16)curVar->getType(); saveBuf->_stVarList[j]._bGlobal = (byte)curVar->isGlobal(); saveBuf->_stVarList[j]._bConstant = (byte)curVar->isConstant(); saveBuf->_stVarList[j]._bReference = (byte)curVar->isReference(); saveBuf->_stVarList[j]._bTimer = (byte)curVar->isTimer(); saveBuf->_stVarList[j]._bRandom = (byte)curVar->isRandom(); saveBuf->_stVarList[j]._bNumeric = (byte)curVar->isNumeric(); saveBuf->_stVarList[j]._bAttached = (byte)curVar->isAttached(); saveBuf->_stVarList[j]._bUsed = 1; j++; // Can't exceed MAX_VARS assert(j < MAX_VARS); //} } } } // Remember current script file strncpy(saveBuf->_szScript, getWldScript().getBuffer(), MAX_FNAME - 1); CBagStorageDevWnd *sdevWin = getCurrentStorageDev(); if (sdevWin != nullptr) { char stringBuffer[256]; stringBuffer[0] = 0; CBofString curString(stringBuffer, 256); saveBuf->_nLocType = sdevWin->getDeviceType(); // Remember the pan's position if (saveBuf->_nLocType == SDEV_GAMEWIN) { CBagPanWindow *panWin = (CBagPanWindow *)sdevWin; const CBofRect cPos = panWin->getViewPort(); saveBuf->_nLocX = (uint16)cPos.left; saveBuf->_nLocY = (uint16)cPos.top; } CBagStorageDevManager *sdevManager = getStorageDevManager(); if (sdevManager != nullptr) { sdevManager->saveObjList(&saveBuf->_stObjList[0], MAX_OBJS); if (isObjSave()) { assert(_objList != nullptr); memcpy(&saveBuf->_stObjListEx[0], _objList, sizeof(StObj) * MAX_OBJS); saveBuf->_bUseEx = 1; } // Save current storage device location (stack) int i = 0; curString = sdevWin->getName(); while ((i < MAX_CLOSEUP_DEPTH) && !curString.isEmpty()) { sdevWin = (CBagStorageDevWnd *)sdevManager->getStorageDevice(curString); Common::strcpy_s(saveBuf->_szLocStack[i], curString.getBuffer()); i++; curString.free(); if (sdevWin != nullptr) { curString = sdevWin->getPrevSDev(); } } } } } } } bool CBagMasterWin::showSaveDialog(CBofWindow *win, bool bSaveBkg) { assert(isValidObject(this)); if (g_engine->isDemo()) return false; if (!g_engine->_useOriginalSaveLoad) { return g_engine->saveGameDialog(); } bool savedFl = false; CBagStorageDevWnd *sdev = getCurrentStorageDev(); if ((sdev == nullptr) || (sdev->getDeviceType() == SDEV_GAMEWIN) || (sdev->getDeviceType() == SDEV_ZOOMPDA)) { logInfo("Showing Save Screen"); CBofSound::pauseSounds(); StBagelSave *saveBuf = (StBagelSave *)bofAlloc(sizeof(StBagelSave)); fillSaveBuffer(saveBuf); CBagSaveDialog saveDialog; saveDialog.setSaveGameBuffer((byte *)saveBuf, sizeof(StBagelSave)); // Use specified bitmap as this dialog's image CBofBitmap *bmp = SpaceBar::loadBitmap(_sysScreen.getBuffer()); saveDialog.setBackdrop(bmp); const CBofRect backRect = saveDialog.getBackdrop()->getRect(); // Don't allow save of background if (!bSaveBkg) { const int dlgFlags = saveDialog.getFlags(); saveDialog.setFlags(dlgFlags & ~BOFDLG_SAVEBACKGND); } // Create the dialog box saveDialog.create("Save Dialog", backRect.left, backRect.top, backRect.width(), backRect.height(), win); const bool saveTimerFl = g_pauseTimerFl; g_pauseTimerFl = true; const int btnId = saveDialog.doModal(); g_pauseTimerFl = saveTimerFl; savedFl = (btnId == SAVE_BTN); saveDialog.detach(); bofFree(saveBuf); CBofSound::resumeSounds(); logInfo("Exiting Save Screen"); } return savedFl; } void CBagMasterWin::doRestore(StBagelSave *saveBuf) { assert(isValidObject(this)); assert(saveBuf != nullptr); char scriptBuf[256]; scriptBuf[0] = '\0'; CBofString script(scriptBuf, 256); script = saveBuf->_szScript; char workBuf[60], closeUpBuf[256]; char stringBuf[256]; stringBuf[0] = 0; CBofString closeUpString(stringBuf, 256); int i; // Rebuild the stack of locations (Could be 3 closeups deep) closeUpBuf[0] = '\0'; for (i = MAX_CLOSEUP_DEPTH - 1; i >= 0; i--) { if (saveBuf->_szLocStack[i][0] != '\0') { Common::sprintf_s(workBuf, "%s~~", saveBuf->_szLocStack[i]); Common::strcat_s(closeUpBuf, workBuf); } } int n = strlen(closeUpBuf); if (n > 2 && closeUpBuf[n - 1] == '~') { closeUpBuf[n - 1] = '\0'; closeUpBuf[n - 2] = '\0'; } // Designate closeups if (saveBuf->_nLocType == SDEV_CLOSEP) { Common::strcat_s(closeUpBuf, " AS CLOSEUP"); } closeUpString = closeUpBuf; // Don't allow a local restore setSaveObjs(false); // Make sure that all global variables are loaded and available loadGlobalVars(GLOBALWORLD); // Tell BAGEL to start over with this script loadFile(script, closeUpString, false, false); if (!errorOccurred()) { // Restore all variables // CBagVarManager *varManager = getVariableManager(); if (varManager != nullptr) { // Reset the Global Vars with these new settings for (i = 0; i < MAX_VARS; i++) { // If this entry is actually used to store Var info if (saveBuf->_stVarList[i]._bUsed) { // Find the Global Var (already in memory) CBagVar *var = varManager->getVariable(saveBuf->_stVarList[i]._szName); if (var != nullptr) { var->setValue(saveBuf->_stVarList[i]._szValue); } else { logError(buildString("Global Variable NOT found: %s", saveBuf->_stVarList[i]._szName)); } } } } CBagStorageDevManager *sdevManager = getStorageDevManager(); if (sdevManager != nullptr) { // Restore any extra obj list info (for .WLD swapping) if (_objList == nullptr) { // Allocate a buffer filled with 0s _objList = (StObj *)bofCleanAlloc(MAX_OBJS * sizeof(StObj)); } memcpy(getObjList(), &saveBuf->_stObjListEx[0], sizeof(StObj) * MAX_OBJS); if (saveBuf->_bUseEx) { setSaveObjs(true); } else { setSaveObjs(false); } sdevManager->restoreObjList(&saveBuf->_stObjList[0], MAX_OBJS); } // If it's a Panorama, the set it's View position. if (saveBuf->_nLocType == SDEV_GAMEWIN) { g_engine->g_cInitLoc.x = saveBuf->_nLocX; g_engine->g_cInitLoc.y = saveBuf->_nLocY; g_engine->g_bUseInitLoc = true; } // Now set the start storage device and let the game start if (!_startWld.isEmpty()) { setStorageDev(_startWld); } restoreActiveMessages(sdevManager); } } bool CBagMasterWin::showRestoreDialog(CBofWindow *win, bool bSaveBkg) { assert(isValidObject(this)); if (g_engine->isDemo()) return false; if (!g_engine->_useOriginalSaveLoad) { return g_engine->loadGameDialog(); } bool restoredFl = false; CBagStorageDevWnd *sdev; if (g_allowRestoreFl || ((sdev = getCurrentStorageDev()) == nullptr) || (sdev->getDeviceType() == SDEV_GAMEWIN) || (sdev->getDeviceType() == SDEV_ZOOMPDA)) { logInfo("Showing Restore Screen"); CBofSound::pauseSounds(); CBagRestoreDialog restoreDialog; // Use specified bitmap as this dialog's image CBofBitmap *pBmp = SpaceBar::loadBitmap(_sysScreen.getBuffer()); restoreDialog.setBackdrop(pBmp); const CBofRect backRect = restoreDialog.getBackdrop()->getRect(); // Don't allow save of background if (!bSaveBkg) { const int flags = restoreDialog.getFlags(); restoreDialog.setFlags(flags & ~BOFDLG_SAVEBACKGND); } // Create the dialog box restoreDialog.create("Restore Dialog", backRect.left, backRect.top, backRect.width(), backRect.height(), win); CBofWindow *lastWin = g_hackWindow; g_hackWindow = &restoreDialog; const bool saveTimerFl = g_pauseTimerFl; g_pauseTimerFl = true; restoreDialog.doModal(); g_pauseTimerFl = saveTimerFl; restoreDialog.detach(); restoredFl = (!restoreDialog.errorOccurred() && restoreDialog.restored()); restoreDialog.destroy(); g_hackWindow = lastWin; CBofSound::resumeSounds(); logInfo("Exiting Restore Screen"); } return restoredFl; } // User options #define DEFAULT_CORRECTION 2 bool CBagMasterWin::getFlyThru() { bool flyThrusOnFl = true; CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->getOption(USER_OPTIONS, "FlyThroughs", &flyThrusOnFl, true); } return flyThrusOnFl; } int CBagMasterWin::getMidiVolume() { int midiVol = VOLUME_INDEX_DEFAULT; CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->getOption(USER_OPTIONS, "MidiVolume", &midiVol, VOLUME_INDEX_DEFAULT); if (midiVol < VOLUME_INDEX_MIN || midiVol > VOLUME_INDEX_MAX) { midiVol = VOLUME_INDEX_DEFAULT; } } return midiVol; } void CBagMasterWin::setMidiVolume(int vol) { assert(vol >= VOLUME_INDEX_MIN && vol <= VOLUME_INDEX_MAX); CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->setOption(USER_OPTIONS, "MidiVolume", vol); } // We will let the sound subsystem do our volume control... CBofSound::setVolume(vol, getWaveVolume()); } int CBagMasterWin::getWaveVolume() { int waveVol = VOLUME_INDEX_DEFAULT; CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->getOption(USER_OPTIONS, WAVE_VOLUME, &waveVol, VOLUME_INDEX_DEFAULT); if (waveVol < VOLUME_INDEX_MIN || waveVol > VOLUME_INDEX_MAX) { waveVol = VOLUME_INDEX_DEFAULT; } } return waveVol; } void CBagMasterWin::setWaveVolume(int vol) { assert(vol >= VOLUME_INDEX_MIN && vol <= VOLUME_INDEX_MAX); CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->setOption(USER_OPTIONS, WAVE_VOLUME, vol); } // We will let the sound subsystem do our volume control... CBofSound::setVolume(getMidiVolume(), vol); } int CBagMasterWin::getCorrection() { int correction = DEFAULT_CORRECTION; CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->getOption(USER_OPTIONS, "Correction", &correction, DEFAULT_CORRECTION); if (correction < 0 || correction > 6) { correction = DEFAULT_CORRECTION; } } if (correction == 6) { correction = 0; } else { correction = (1 << correction); } return correction; } void CBagMasterWin::setCorrection(int correction) { assert(correction >= 0 && correction <= 32); int actualCorr; switch (correction) { case 0: actualCorr = 6; break; case 1: actualCorr = 0; break; case 2: actualCorr = 1; break; case 4: actualCorr = 2; break; case 8: actualCorr = 3; break; case 16: actualCorr = 4; break; case 32: actualCorr = 5; break; default: actualCorr = DEFAULT_CORRECTION; break; } CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->setOption(USER_OPTIONS, "Correction", actualCorr); } } int CBagMasterWin::getPanSpeed() { int n = 1; CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->getOption(USER_OPTIONS, "PanSpeed", &n, 1); if (n < 0 || n > 5) { n = 1; } } return n; } void CBagMasterWin::setPanSpeed(int speed) { assert(speed >= 0 && speed <= 5); CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->setOption(USER_OPTIONS, "PanSpeed", speed); } } bool CBagMasterWin::getPanimations() { bool panims = 0; CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->getOption(USER_OPTIONS, "Panimations", &panims, true); } return panims; } void CBagMasterWin::setPanimations(bool panimsFl) { CBagel *app = CBagel::getBagApp(); if (app != nullptr) { app->setOption(USER_OPTIONS, "Panimations", panimsFl); } } void CBagMasterWin::muteToggle() { static int midiVol = VOLUME_INDEX_MIN; static int waveVol = VOLUME_INDEX_MIN; static bool muteFl = false; if (muteFl) { // Restore settings setMidiVolume(midiVol); setWaveVolume(waveVol); } else { // Save current settings midiVol = getMidiVolume(); waveVol = getWaveVolume(); // Mute setMidiVolume(VOLUME_INDEX_MIN); setWaveVolume(VOLUME_INDEX_MIN); } // Toggle mute-ness muteFl = !muteFl; } void CBagMasterWin::forcePaintScreen() { CBagel *app = CBagel::getBagApp(); if (app != nullptr) { CBagMasterWin *win = app->getMasterWnd(); if (win != nullptr) { CBagStorageDevWnd *sdev = win->getCurrentStorageDev(); if (sdev != nullptr) { sdev->paintScreen(nullptr); } } } } ErrorCode waitForInput() { EventLoop eventLoop; while (!g_engine->shouldQuit() && !eventLoop.frame()) { } return ERR_NONE; } ErrorCode CBagMasterWin::close() { assert(isValidObject(this)); g_allowPaintFl = false; return ERR_NONE; } void CBagMasterWin::restoreActiveMessages(CBagStorageDevManager *sdevManager) { assert(sdevManager != nullptr); if (sdevManager != nullptr) { // Make sure the Message Log light will flash if user has // waiting messages. int n = sdevManager->getNumStorageDevices(); for (int i = 0; i < n; i++) { CBagStorageDev *sdev = sdevManager->getStorageDevice(i); if (sdev != nullptr) { int m = sdev->getObjectCount(); for (int j = 0; j < m; j++) { CBagObject *curObj = sdev->getObjectByPos(j); if (curObj != nullptr && curObj->isMsgWaiting()) { sdev->activateLocalObject(curObj); } } } } } } // Set the CIC var to either true or false so that our scripting // code can tell whether or not to play certain movies (primarily flashbacks). void setCICStatus(CBagStorageDev *sdev) { char workBuff[256]; CBofString workStr(workBuff, 256); // If the new game window is a CIC, then set the global var indicating // that this is the case. Don't reset when we're zooming the PDA. if (sdev && sdev->getName() != "BPDAZ_WLD") { workStr = "IN_CIC"; CBagVar *cicVar = g_VarManager->getVariable(workStr); if (cicVar) { workStr = sdev->isCIC() ? "true" : "false"; cicVar->setValue(workStr); } } } bool getCICStatus() { char workBuff[256]; CBofString workStr(workBuff, 256); bool retValFl = false; workStr = "IN_CIC"; CBagVar *cicVar = g_VarManager->getVariable(workStr); if (cicVar) { retValFl = (cicVar->getValue() == "true"); } return retValFl; } } // namespace SpaceBar } // namespace Bagel