diff options
48 files changed, 922 insertions, 190 deletions
diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp index 84774742c6..30896d7514 100644 --- a/common/EventMapper.cpp +++ b/common/EventMapper.cpp @@ -37,11 +37,17 @@ List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) { #ifdef ENABLE_VKEYBD else if (ev.kbd.keycode == KEYCODE_F7 && ev.kbd.hasFlags(0)) { mappedEvent.type = EVENT_VIRTUAL_KEYBOARD; + + // Avoid blocking F7 events from engine. + addDelayedEvent(100, ev); } #endif #ifdef ENABLE_KEYMAPPER else if (ev.kbd.keycode == KEYCODE_F8 && ev.kbd.hasFlags(0)) { mappedEvent.type = EVENT_KEYMAPPER_REMAP; + + // Avoid blocking F8 events from engine. + addDelayedEvent(100, ev); } #endif } diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp index c26fbe3331..392ee08ea1 100644 --- a/engines/agos/midi.cpp +++ b/engines/agos/midi.cpp @@ -235,6 +235,10 @@ void MidiPlayer::startTrack(int track) { _music.parser = parser; // That plugs the power cord into the wall } else if (_music.parser) { if (!_music.parser->setTrack(track)) { + // The Roland MT32 music in Simon the Sorcerer 2 + // is missing the extra tracks in many scenes, + // like the introduction sequence. + stop(); return; } _currentTrack = (byte)track; diff --git a/engines/avalanche/animation.cpp b/engines/avalanche/animation.cpp index 86ca4c8541..451b4a1c68 100644 --- a/engines/avalanche/animation.cpp +++ b/engines/avalanche/animation.cpp @@ -764,7 +764,7 @@ void Animation::catacombMove(byte ped) { spr1->init(5, true); // ...Load Geida. appearPed(1, geidaPed(ped)); spr1->_callEachStepFl = true; - spr1->_eachStepProc = kProcGeida; + spr1->_eachStepProc = kProcFollowAvvy; } } @@ -1121,7 +1121,7 @@ void Animation::spin(Direction dir, byte &tripnum) { } } -void Animation::geidaProcs(byte tripnum) { +void Animation::follow(byte tripnum) { AnimationType *tripSpr = _sprites[tripnum]; AnimationType *avvy = _sprites[0]; @@ -1132,14 +1132,14 @@ void Animation::geidaProcs(byte tripnum) { } if (tripSpr->_y < (avvy->_y - 2)) { - // Geida is further from the screen than Avvy. + // The following NPC is further from the screen than Avvy. spin(kDirDown, tripnum); tripSpr->_moveY = 1; tripSpr->_moveX = 0; takeAStep(tripnum); return; } else if (tripSpr->_y > (avvy->_y + 2)) { - // Avvy is further from the screen than Geida. + // Avvy is further from the screen than the following NPC. spin(kDirUp, tripnum); tripSpr->_moveY = -1; tripSpr->_moveX = 0; @@ -1205,8 +1205,9 @@ void Animation::drawSprites() { * @remarks Originally called 'trippancy_link' */ void Animation::animLink() { - if (_vm->_dropdown->isActive() || _vm->_seeScroll) + if (_vm->_dropdown->isActive() || !_vm->_animationsEnabled) return; + for (int16 i = 0; i < kSpriteNumbMax; i++) { AnimationType *curSpr = _sprites[i]; if (curSpr->_quick && curSpr->_visible) @@ -1235,8 +1236,8 @@ void Animation::animLink() { case kProcGrabAvvy : grabAvvy(i); break; - case kProcGeida : - geidaProcs(i); + case kProcFollowAvvy : + follow(i); break; default: break; diff --git a/engines/avalanche/animation.h b/engines/avalanche/animation.h index 375d117893..d1ee4a3ebd 100644 --- a/engines/avalanche/animation.h +++ b/engines/avalanche/animation.h @@ -102,9 +102,8 @@ public: kProcBackAndForth, kProcFaceAvvy, kProcArrow, - kProcSpludwick, // Unused kProcGrabAvvy, - kProcGeida // Spludwick uses it as well for homing! TODO: Unify it with kProcSpludwick. + kProcFollowAvvy }; AnimationType *_sprites[kSpriteNumbMax]; @@ -167,7 +166,7 @@ private: // Movements for Homing NPCs: Spludwick and Geida. void spin(Direction dir, byte &tripnum); void takeAStep(byte &tripnum); - void geidaProcs(byte tripnum); + void follow(byte tripnum); void drawSprites(); }; diff --git a/engines/avalanche/avalanche.cpp b/engines/avalanche/avalanche.cpp index 1bc4c5348d..6cfe4dfdb6 100644 --- a/engines/avalanche/avalanche.cpp +++ b/engines/avalanche/avalanche.cpp @@ -57,6 +57,7 @@ AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription * _nim = nullptr; _ghostroom = nullptr; _help = nullptr; + _highscore = nullptr; _platform = gd->desc.platform; initVariables(); @@ -81,6 +82,7 @@ AvalancheEngine::~AvalancheEngine() { delete _nim; delete _ghostroom; delete _help; + delete _highscore; for (int i = 0; i < 31; i++) { for (int j = 0; j < 2; j++) { @@ -142,7 +144,7 @@ void AvalancheEngine::initVariables() { _letMeOut = false; _thinks = 2; _thinkThing = true; - _seeScroll = false; + _animationsEnabled = true; _currentMouse = 177; _holdLeftMouse = false; @@ -165,6 +167,7 @@ Common::ErrorCode AvalancheEngine::initialize() { _nim = new Nim(this); _ghostroom = new GhostRoom(this); _help = new Help(this); + _highscore = new HighScore(this); _graphics->init(); _dialogs->init(); @@ -200,7 +203,7 @@ void AvalancheEngine::synchronize(Common::Serializer &sz) { sz.syncAsByte(_carryNum); for (int i = 0; i < kObjectNum; i++) sz.syncAsByte(_objects[i]); - sz.syncAsSint16LE(_dnascore); + sz.syncAsSint16LE(_score); sz.syncAsSint32LE(_money); sz.syncAsByte(_room); if (sz.isSaving()) @@ -336,8 +339,8 @@ void AvalancheEngine::synchronize(Common::Serializer &sz) { } -bool AvalancheEngine::canSaveGameStateCurrently() { // TODO: Refine these!!! - return (!_seeScroll && _alive); +bool AvalancheEngine::canSaveGameStateCurrently() { + return (_animationsEnabled && _alive); } Common::Error AvalancheEngine::saveGameState(int slot, const Common::String &desc) { @@ -381,8 +384,8 @@ Common::String AvalancheEngine::getSaveFileName(const int slot) { return Common::String::format("%s.%03d", _targetName.c_str(), slot); } -bool AvalancheEngine::canLoadGameStateCurrently() { // TODO: Refine these!!! - return (!_seeScroll); +bool AvalancheEngine::canLoadGameStateCurrently() { + return (_animationsEnabled); } Common::Error AvalancheEngine::loadGameState(int slot) { @@ -432,7 +435,7 @@ bool AvalancheEngine::loadGame(const int16 slot) { _isLoaded = true; - _seeScroll = true; // This prevents display of the new sprites before the new picture is loaded. + _animationsEnabled = false; if (_holdTheDawn) { _holdTheDawn = false; diff --git a/engines/avalanche/avalanche.h b/engines/avalanche/avalanche.h index 146065ad63..6eb5e675cc 100644 --- a/engines/avalanche/avalanche.h +++ b/engines/avalanche/avalanche.h @@ -46,6 +46,7 @@ #include "avalanche/help.h" #include "avalanche/shootemup.h" #include "avalanche/mainmenu.h" +#include "avalanche/highscore.h" #include "common/serializer.h" @@ -91,6 +92,7 @@ public: Nim *_nim; GhostRoom *_ghostroom; Help *_help; + HighScore *_highscore; OSystem *_system; @@ -150,7 +152,7 @@ public: // Former DNA structure byte _carryNum; // How many objects you're carrying... bool _objects[kObjectNum]; // ...and which ones they are. - int16 _dnascore; // your score, of course + int16 _score; // your score, of course int32 _money; // your current amount of dosh Room _room; // your current room bool _wonNim; // Have you *won* Nim? (That's harder.) @@ -210,7 +212,7 @@ public: bool _letMeOut; byte _thinks; bool _thinkThing; - bool _seeScroll; // TODO: maybe this means we're interacting with the toolbar / a scroll? + bool _animationsEnabled; // If set to TRUE, it stops the animation system working. This prevents display of the new sprites before the new picture is loaded or during the display of a scroll. Original name: seescroll. char _objectList[10]; // Called .free() for them in ~Gyro(). diff --git a/engines/avalanche/avalot.cpp b/engines/avalanche/avalot.cpp index 1cb2f186a5..c8f5599687 100644 --- a/engines/avalanche/avalot.cpp +++ b/engines/avalanche/avalot.cpp @@ -249,8 +249,6 @@ void AvalancheEngine::runAvalot() { _system->delayMillis(55 - delay); // Replaces slowdown(); 55 comes from 18.2 Hz (B Flight). }; - warning("STUB: run()"); - _closing->exitGame(); } @@ -464,7 +462,7 @@ void AvalancheEngine::findPeople(byte room) { void AvalancheEngine::exitRoom(byte x) { _sound->stopSound(); _background->release(); - _seeScroll = true; // This stops the trippancy system working over the length of this procedure. + _animationsEnabled = false; switch (x) { case kRoomSpludwicks: @@ -487,7 +485,7 @@ void AvalancheEngine::exitRoom(byte x) { } _interrogation = 0; // Leaving the room cancels all the questions automatically. - _seeScroll = false; // Now it can work again! + _animationsEnabled = true; _lastRoom = _room; if (_room != kRoomMap) @@ -534,11 +532,11 @@ void AvalancheEngine::putGeidaAt(byte whichPed, byte ped) { spr1->init(5, false); // load Geida _animation->appearPed(1, whichPed); spr1->_callEachStepFl = true; - spr1->_eachStepProc = Animation::kProcGeida; + spr1->_eachStepProc = Animation::kProcFollowAvvy; } void AvalancheEngine::enterRoom(Room roomId, byte ped) { - _seeScroll = true; // This stops the trippancy system working over the length of this procedure. + _animationsEnabled = false; findPeople(roomId); _room = roomId; @@ -619,7 +617,7 @@ void AvalancheEngine::enterRoom(Room roomId, byte ped) { } spr1->_callEachStepFl = true; - spr1->_eachStepProc = Animation::kProcGeida; + spr1->_eachStepProc = Animation::kProcFollowAvvy; } else _whereIs[kPeopleSpludwick - 150] = kRoomNowhere; break; @@ -922,7 +920,7 @@ void AvalancheEngine::enterRoom(Room roomId, byte ped) { break; } - _seeScroll = false; // Now it can work again! + _animationsEnabled = true; } void AvalancheEngine::thinkAbout(byte object, bool type) { @@ -957,7 +955,7 @@ void AvalancheEngine::drawToolbar() { } void AvalancheEngine::drawScore() { - uint16 score = _dnascore; + uint16 score = _score; int8 numbers[3] = {0, 0, 0}; for (int i = 0; i < 2; i++) { byte divisor = 1; @@ -983,15 +981,14 @@ void AvalancheEngine::drawScore() { void AvalancheEngine::incScore(byte num) { for (int i = 1; i <= num; i++) { - _dnascore++; + _score++; if (_soundFx) { for (int j = 1; j <= 97; j++) - // Length os 2 is a guess, the original doesn't have a delay specified - _sound->playNote(177 + _dnascore * 3, 2); + // Length of 2 is a guess, the original doesn't have a delay specified + _sound->playNote(177 + _score * 3, 2); } } - warning("STUB: points()"); drawScore(); } @@ -1336,7 +1333,7 @@ void AvalancheEngine::resetVariables() { for (int i = 0; i < kObjectNum; i++) _objects[i] = false; - _dnascore = 0; + _score = 0; _money = 0; _room = kRoomNowhere; _saveNum = 0; @@ -1442,7 +1439,7 @@ void AvalancheEngine::newGame() { _thinkThing = true; _thinks = 2; refreshObjectList(); - _seeScroll = false; + _animationsEnabled = true; avvy->appear(300, 117, kDirRight); // Needed to initialize Avalot. //for (gd = 0; gd <= 30; gd++) for (gm = 0; gm <= 1; gm++) also[gd][gm] = nil; diff --git a/engines/avalanche/dialogs.cpp b/engines/avalanche/dialogs.cpp index b7b03e86dc..e843d17c5b 100644 --- a/engines/avalanche/dialogs.cpp +++ b/engines/avalanche/dialogs.cpp @@ -157,7 +157,7 @@ void Dialogs::scrollModeNormal() { Common::String e = "(c) 1994"; setReadyLight(3); - _vm->_seeScroll = true; + _vm->_animationsEnabled = false; _vm->_graphics->loadMouse(kCurFletch); _vm->_graphics->saveScreen(); @@ -216,10 +216,8 @@ void Dialogs::scrollModeNormal() { #endif setReadyLight(0); - _vm->_seeScroll = false; + _vm->_animationsEnabled = true; _vm->_holdLeftMouse = false; // Used in Lucerna::checkclick(). - - warning("STUB: Scrolls::scrollModeNormal()"); } /** @@ -290,7 +288,7 @@ bool Dialogs::theyMatch(TuneType &played) { */ void Dialogs::scrollModeMusic() { setReadyLight(3); - _vm->_seeScroll = true; + _vm->_animationsEnabled = false; CursorMan.showMouse(false); _vm->_graphics->loadMouse(kCurFletch); @@ -299,7 +297,7 @@ void Dialogs::scrollModeMusic() { played[i] = kPitchInvalid; int8 lastOne = -1, thisOne = -1; // Invalid values. - _vm->_seeScroll = true; + _vm->_animationsEnabled = false; _vm->_graphics->saveScreen(); _vm->_graphics->showScroll(); @@ -393,7 +391,7 @@ void Dialogs::scrollModeMusic() { _vm->_graphics->restoreScreen(); _vm->_graphics->removeBackup(); - _vm->_seeScroll = false; + _vm->_animationsEnabled = true; CursorMan.showMouse(true); } @@ -646,9 +644,6 @@ void Dialogs::solidify(byte n) { * 'calldriver' and 'display' by using Common::String instead of a private buffer. */ void Dialogs::displayText(Common::String text) { -// bool was_virtual; // Was the mouse cursor virtual on entry to this proc? - warning("STUB: Scrolls::calldrivers()"); - _vm->_sound->stopSound(); setReadyLight(0); diff --git a/engines/avalanche/dropdown.cpp b/engines/avalanche/dropdown.cpp index 7c0529811e..97adfc2581 100644 --- a/engines/avalanche/dropdown.cpp +++ b/engines/avalanche/dropdown.cpp @@ -678,7 +678,7 @@ void DropDownMenu::setup() { _menuBar.draw(); } -void DropDownMenu::update() { // TODO: Optimize it ASAP!!! It really needs it... +void DropDownMenu::update() { _vm->_graphics->saveScreen(); Common::Point cursorPos = _vm->getMousePos(); diff --git a/engines/avalanche/enums.h b/engines/avalanche/enums.h index 998c96a131..0ba39321bc 100644 --- a/engines/avalanche/enums.h +++ b/engines/avalanche/enums.h @@ -30,6 +30,7 @@ namespace Avalanche { +enum MonsterType { kMonsterTypeGhost, kMonsterTypeGlerk }; enum Flavour { kFlavourEga, kFlavourBgi, kFlavourNatural, kFlavourTwo, kFlavourOne }; diff --git a/engines/avalanche/ghostroom.cpp b/engines/avalanche/ghostroom.cpp index 1419a0cbab..16c79fdee0 100644 --- a/engines/avalanche/ghostroom.cpp +++ b/engines/avalanche/ghostroom.cpp @@ -70,6 +70,30 @@ GhostRoom::~GhostRoom() { for (int j = 0; j < 6; j++) _greldet[j][i].free(); } + + if (_wasLoaded) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 2; j++) { + for (int y = 0; y < 66; y++) { + delete[] _ghost[i][j][y]; + } + delete[] _ghost[i][j]; + } + delete[] _ghost[i]; + } + delete[] _ghost; + + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 4; j++) { + for (int y = 0; y < 35; y++) { + delete[] _glerk[i][j][y]; + } + delete[] _glerk[i][j]; + } + delete[] _glerk[i]; + } + delete[] _glerk; + } } void GhostRoom::wait(uint16 howLong) { @@ -141,9 +165,13 @@ void GhostRoom::loadPictures() { file.seek(44); // Initializing ghost's array. + _ghost = new byte***[5]; for (int i = 0; i < 5; i++) { + _ghost[i] = new byte**[2]; for (int j = 0; j < 2; j++) { + _ghost[i][j] = new byte*[66]; for (int y = 0; y < 66; y++) { + _ghost[i][j][y] = new byte[26]; for (int x = 0; x < 26; x++) _ghost[i][j][y][x] = 0; } @@ -171,11 +199,14 @@ void GhostRoom::loadPictures() { for (int i = 0; i < 3; i++) _bat[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord); - // Initializing glerk's array. + _glerk = new byte***[6]; for (int i = 0; i < 6; i++) { + _glerk[i] = new byte**[4]; for (int j = 0; j < 4; j++) { + _glerk[i][j] = new byte*[35]; for (int y = 0; y < 35; y++) { + _glerk[i][j][y] = new byte[9]; for (int x = 0; x < 9; x++) _glerk[i][j][y][x] = 0; } @@ -245,7 +276,7 @@ void GhostRoom::run() { if (_glerkStage > 25) break; - _vm->_graphics->ghostDrawGlerk(_glerk[kGlerkFade[_glerkStage]], 456, 14); + _vm->_graphics->ghostDrawMonster(_glerk[kGlerkFade[_glerkStage]], 456, 14, kMonsterTypeGlerk); _glerkStage++; } @@ -263,7 +294,7 @@ void GhostRoom::run() { // Here comes the descending ghost: for (int y = -64; y <= 103; y++) { - _vm->_graphics->ghostDrawGhost(_ghost[1 + (abs(y / 7) % 2) * 3], 0, y); + _vm->_graphics->ghostDrawMonster(_ghost[1 + (abs(y / 7) % 2) * 3], 0, y, kMonsterTypeGhost); if (y > 0) _vm->_graphics->drawFilledRectangle(Common::Rect(0, y - 1, 26 * 8 + 1, y + 1), kColorBlack); _vm->_graphics->refreshScreen(); @@ -277,7 +308,7 @@ void GhostRoom::run() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 5; j++) { _vm->_graphics->drawFilledRectangle(Common::Rect(0, 96, 26 * 8, 170), kColorBlack); - _vm->_graphics->ghostDrawGhost(_ghost[kWaveOrder[j]], 0, 96 + kAdjustment[j]); + _vm->_graphics->ghostDrawMonster(_ghost[kWaveOrder[j]], 0, 96 + kAdjustment[j], kMonsterTypeGhost); _aarghCount++; diff --git a/engines/avalanche/ghostroom.h b/engines/avalanche/ghostroom.h index ebb02f7aac..4c659128ce 100644 --- a/engines/avalanche/ghostroom.h +++ b/engines/avalanche/ghostroom.h @@ -58,11 +58,11 @@ private: static const byte kGreldetFade[18]; Common::Point dummyCoord; - byte _ghost[5][2][66][26]; + byte ****_ghost;// [5][2][66][26] Graphics::Surface _eyes[2]; Graphics::Surface _exclamation; Graphics::Surface _bat[3]; - byte _glerk[6][4][35][9]; + byte ****_glerk; // [6][4][35][9] Graphics::Surface _aargh[6]; Common::Point _aarghWhere[6]; Graphics::Surface _greenEyes[5]; diff --git a/engines/avalanche/graphics.cpp b/engines/avalanche/graphics.cpp index ae53f3e034..513cd72c8c 100644 --- a/engines/avalanche/graphics.cpp +++ b/engines/avalanche/graphics.cpp @@ -527,64 +527,65 @@ void GraphicManager::nimFree() { _nimLogo.free(); } -void GraphicManager::ghostDrawGhost(byte ghostArr[2][66][26], uint16 destX, int16 destY) { +void GraphicManager::ghostDrawMonster(byte ***picture, uint16 destX, int16 destY, MonsterType type) { + uint16 height = 0; + uint16 width = 0; + // Only for the Ghost: const byte kPlaneToUse[4] = { 0, 0, 0, 1 }; - // Constants from the original code: - uint16 height = 66; - const uint16 width = 26 * 8; - - // We have to mess around with the coords and the sizes since - // the ghost isn't always placed fully on the screen. int yStart = 0; - if (destY < 0) { - yStart = abs(destY); - height -= yStart; - destY = 0; - } - - Graphics::Surface ghostPic; - ghostPic.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - - for (int y = 0; y < height; y++) { - for (int plane = 0; plane < 4; plane++) { - for (uint16 x = 0; x < width / 8; x ++) { - byte pixel = ghostArr[kPlaneToUse[plane]][y + yStart][x]; - for (int bit = 0; bit < 8; bit++) { - byte pixelBit = (pixel >> bit) & 1; - *(byte *)ghostPic.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane); - } - } + + // Constants from the original code: + switch (type) { + case kMonsterTypeGhost: + height = 66; + width = 208; // 26 * 8 + + // We have to mess around with the coords and the sizes since + // the ghost isn't always placed fully on the screen. + if (destY < 0) { + yStart = abs(destY); + height -= yStart; + destY = 0; } + break; + case kMonsterTypeGlerk: + height = 35; + width = 72; // 9 * 8 + break; + default: + break; } - drawPicture(_surface, ghostPic, destX, destY); - - ghostPic.free(); -} - -void GraphicManager::ghostDrawGlerk(byte glerkArr[4][35][9], uint16 destX, uint16 destY) { - // Constants from the original code: - const uint16 height = 35; - const uint16 width = 9 * 8; - - Graphics::Surface glerkPic; - glerkPic.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + Graphics::Surface monsterPicture; + monsterPicture.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); for (int y = 0; y < height; y++) { for (int plane = 0; plane < 4; plane++) { for (uint16 x = 0; x < width / 8; x++) { - byte pixel = glerkArr[plane][y][x]; + byte pixel = 0; + + switch (type) { + case kMonsterTypeGhost: + pixel = picture[kPlaneToUse[plane]][y + yStart][x]; + break; + case kMonsterTypeGlerk: + pixel = picture[plane][y][x]; + break; + default: + break; + } + for (int bit = 0; bit < 8; bit++) { byte pixelBit = (pixel >> bit) & 1; - *(byte *)glerkPic.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane); + *(byte *)monsterPicture.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane); } } } } - drawPicture(_surface, glerkPic, destX, destY); + drawPicture(_surface, monsterPicture, destX, destY); - glerkPic.free(); + monsterPicture.free(); } /** diff --git a/engines/avalanche/graphics.h b/engines/avalanche/graphics.h index 7e0ed64b5f..bd8fc6c8ff 100644 --- a/engines/avalanche/graphics.h +++ b/engines/avalanche/graphics.h @@ -97,8 +97,7 @@ public: void drawWinningPic(); // Ghostroom's functions: - void ghostDrawGhost(byte ghostArr[2][66][26], uint16 destX, int16 destY); // Very similar to loadPictureSign(). TODO: Unify the two later if possible. - void ghostDrawGlerk(byte glerkArr[4][35][9], uint16 destX, uint16 destY); // Very similar to ghostDrawGhost(), but not enough to unify the two. + void ghostDrawMonster(byte ***picture, uint16 destX, int16 destY, MonsterType type); Graphics::Surface ghostLoadPicture(Common::File &file, Common::Point &coord); void ghostDrawPicture(const Graphics::Surface &picture, uint16 destX, uint16 destY); void ghostDrawBackgroundItems(Common::File &file); @@ -106,7 +105,7 @@ public: // Help's function: void helpDrawButton(int y, byte which); void helpDrawHighlight(byte which, Color color); - void helpDrawBigText(const Common::String text, int16 x, int16 y, Color color); // Very similar to drawText. TODO: Try to unify the two. + void helpDrawBigText(const Common::String text, int16 x, int16 y, Color color); // Shoot em' up's functions: void seuDrawTitle(); @@ -199,12 +198,11 @@ private: Graphics::Surface loadPictureSign(Common::File &file, uint16 width, uint16 height); // Reads a tricky type of picture used for the "game over"/"about" scrolls and in the mini-game Nim. void drawText(Graphics::Surface &surface, const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); - void drawBigText(Graphics::Surface &surface, const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); // Very similar to drawText. TODO: Try to unify the two. + void drawBigText(Graphics::Surface &surface, const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); void drawPicture(Graphics::Surface &target, const Graphics::Surface picture, uint16 destX, uint16 destY); // Taken from Free Pascal's Procedure InternalEllipseDefault. Used to replace Pascal's procedure arc. // Returns the end point of the arc. (Needed in Clock.) - // TODO: Make it more accurate later. Common::Point drawArc(Graphics::Surface &surface, int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color); }; diff --git a/engines/avalanche/highscore.cpp b/engines/avalanche/highscore.cpp new file mode 100644 index 0000000000..bbe92e7f8a --- /dev/null +++ b/engines/avalanche/highscore.cpp @@ -0,0 +1,110 @@ +/* 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 the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman. +*/ + +#include "avalanche/avalanche.h" +#include "avalanche/highscore.h" + +#include "common/savefile.h" + +namespace Avalanche { + +HighScore::HighScore(AvalancheEngine *vm) { + _vm = vm; +} + +void HighScore::displayHighScores() { + warning("STUB: HighScore::displayHighScores("); +} + +void HighScore::saveHighScores() { + int firstSmaller = 0; + while ((_data[firstSmaller]._score >= _vm->_score) && (firstSmaller < 12)) + firstSmaller++; + + if (firstSmaller < 12) { + // Shift all the lower scores down a space: + for (int i = firstSmaller; i < 11; i++) + _data[i + 1] = _data[i]; + // Set the new high score: + _data[firstSmaller]._name = "Player"; // TODO: Come up with something for that. In the original it wasn't implemented at all... + _data[firstSmaller]._rank = _vm->_parser->rank(); + _data[firstSmaller]._score = _vm->_score; + } + + Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving("scores.avd"); + if (!f) { + warning("Can't create file 'scores.avd', high scores are not saved."); + return; + } + Common::Serializer sz(NULL, f); + syncHighScores(sz); + f->finalize(); + delete f; +} + +void HighScore::loadHighScroes() { + Common::File file; + if (!file.exists("scores.avd")) { + produceDefaultHighScores(); + } else { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading("scores.avd"); + if (!f) + return; + Common::Serializer sz(f, NULL); + syncHighScores(sz); + delete f; + } +} + +void HighScore::produceDefaultHighScores() { + for (int i = 0; i < 12; i++) { + _data[i]._score = 32 - (i + 1) * 2; + _data[i]._rank = "..."; + } + _data[0]._name = "Mike"; + _data[1]._name = "Liz"; + _data[2]._name = "Thomas"; + _data[3]._name = "Mark"; + _data[4]._name = "Mandy"; + _data[5]._name = "Andrew"; + _data[6]._name = "Lucy Tryphena"; + _data[7]._name = "Tammy the dog"; + _data[8]._name = "Avaricius"; + _data[9]._name = "Spellchick"; + _data[10]._name = "Caddelli"; + _data[11]._name = "Spludwick"; +} + +void HighScore::syncHighScores(Common::Serializer &sz) { + for (int i = 0; i < 12; i++) { + sz.syncString(_data[i]._name); + sz.syncAsUint16LE(_data[i]._score); + sz.syncString(_data[i]._rank); + } +} + +} // End of namespace Avalanche diff --git a/engines/avalanche/highscore.h b/engines/avalanche/highscore.h new file mode 100644 index 0000000000..de7ec36ed5 --- /dev/null +++ b/engines/avalanche/highscore.h @@ -0,0 +1,59 @@ +/* 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 the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman. +*/ + +#ifndef AVALANCHE_HIGHSCORE_H +#define AVALANCHE_HIGHSCORE_H + +namespace Avalanche { +class AvalancheEngine; + +struct HighScoreData { + Common::String _name; + uint16 _score; + Common::String _rank; +}; + +class HighScore { +public: + HighScore(AvalancheEngine *vm); + + void displayHighScores(); + void saveHighScores(); + void loadHighScroes(); + +private: + AvalancheEngine *_vm; + + HighScoreData _data[12]; + + void produceDefaultHighScores(); + void syncHighScores(Common::Serializer &sz); +}; + +} // End of namespace Avalanche + +#endif // AVALANCHE_HIGHSCORE_H diff --git a/engines/avalanche/module.mk b/engines/avalanche/module.mk index d31fd0d91a..29bc039b42 100644 --- a/engines/avalanche/module.mk +++ b/engines/avalanche/module.mk @@ -20,7 +20,8 @@ MODULE_OBJS = \ ghostroom.o \ help.o \ shootemup.o \ - mainmenu.o + mainmenu.o \ + highscore.o # This module can be built as a plugin ifeq ($(ENABLE_AVALANCHE), DYNAMIC_PLUGIN) diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp index da365fe93f..b152747ab0 100644 --- a/engines/avalanche/parser.cpp +++ b/engines/avalanche/parser.cpp @@ -602,7 +602,7 @@ Common::String Parser::rank() { }; for (int i = 0; i < 8; i++) { - if ((_vm->_dnascore >= ranks[i]._score) && (_vm->_dnascore < ranks[i + 1]._score)) + if ((_vm->_score >= ranks[i]._score) && (_vm->_score < ranks[i + 1]._score)) return Common::String(ranks[i]._title); } return ""; @@ -2306,7 +2306,7 @@ void Parser::doThat() { break; case kVerbCodeScore: { Common::String tmpStr = Common::String::format("Your score is %d,%c%cout of a possible 128.%c%c " \ - "This gives you a rank of %s.%c%c%s", _vm->_dnascore, kControlCenter, kControlNewLine, kControlNewLine, + "This gives you a rank of %s.%c%c%s", _vm->_score, kControlCenter, kControlNewLine, kControlNewLine, kControlNewLine, rank().c_str(), kControlNewLine, kControlNewLine, totalTime().c_str()); _vm->_dialogs->displayText(tmpStr); } diff --git a/engines/avalanche/parser.h b/engines/avalanche/parser.h index 6a15fb2387..6133c41442 100644 --- a/engines/avalanche/parser.h +++ b/engines/avalanche/parser.h @@ -72,13 +72,11 @@ public: byte _wearing; // what you're wearing Parser(AvalancheEngine *vm); - void init(); void parse(); void doThat(); void verbOpt(byte verb, Common::String &answer, char &ansKey); void drink(); - void handleInputText(const Common::Event &event); void handleBackspace(); void handleReturn(); @@ -89,7 +87,7 @@ public: void tryDropdown(); int16 getPos(const Common::String &crit, const Common::String &src); void doVerb(VerbCode id); - + Common::String rank(); void resetVariables(); void synchronize(Common::Serializer &sz); @@ -112,10 +110,7 @@ private: byte wordNum(Common::String word); void replace(Common::String oldChars, byte newChar); - - Common::String rank(); Common::String totalTime(); - void clearWords(); void cheatParse(Common::String codes); void stripPunctuation(Common::String &word); diff --git a/engines/fullpipe/constants.h b/engines/fullpipe/constants.h index 741a55f74c..c0b7ed906c 100644 --- a/engines/fullpipe/constants.h +++ b/engines/fullpipe/constants.h @@ -267,6 +267,7 @@ namespace Fullpipe { #define TrubaUp 680 // Main Menu +#define PIC_MEX_BGR 5300 #define PIC_MNU_AUTHORS_L 4624 #define PIC_MNU_CONTINUE_L 4626 #define PIC_MNU_DEBUG_L 4632 diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp index 2b4c90b576..c6cc270b67 100644 --- a/engines/fullpipe/fullpipe.cpp +++ b/engines/fullpipe/fullpipe.cpp @@ -191,6 +191,10 @@ void FullpipeEngine::initialize() { _mgm = new MGM; } +void FullpipeEngine::restartGame() { + warning("STUB: FullpipeEngine::restartGame()"); +} + Common::Error FullpipeEngine::run() { const Graphics::PixelFormat format(2, 5, 6, 5, 0, 11, 5, 0, 0); // Initialize backend diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h index 11d7585fa2..9ba5da3726 100644 --- a/engines/fullpipe/fullpipe.h +++ b/engines/fullpipe/fullpipe.h @@ -91,6 +91,7 @@ public: GUI::Debugger *getDebugger() { return _console; } void initialize(); + void restartGame(); void setMusicAllowed(int val) { _musicAllowed = val; } diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp index 137af86f48..26ac4ab824 100644 --- a/engines/fullpipe/gfx.cpp +++ b/engines/fullpipe/gfx.cpp @@ -90,7 +90,16 @@ Background::Background() { } Background::~Background() { - warning("STUB: Background::~Background()"); + _picObjList.clear(); + + for (int i = 0; i < _bigPictureArray1Count; i++) { + for (int j = 0; j < _bigPictureArray2Count; j++) + delete _bigPictureArray[i][j]; + + free(_bigPictureArray[i]); + } + + free(_bigPictureArray); } bool Background::load(MfcArchive &file) { diff --git a/engines/fullpipe/messagehandlers.cpp b/engines/fullpipe/messagehandlers.cpp index b8e7b5c1db..17af2bf4fd 100644 --- a/engines/fullpipe/messagehandlers.cpp +++ b/engines/fullpipe/messagehandlers.cpp @@ -528,9 +528,9 @@ int global_messageHandler4(ExCommand *cmd) { ExCommand2 *cmd2 = (ExCommand2 *)cmd; if (cmd->_excFlags & 1) { - ani->startAnimSteps(cmd->_messageNum, 0, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize >> 3, flags); + ani->startAnimSteps(cmd->_messageNum, 0, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize, flags); } else { - ani->startAnimSteps(cmd->_messageNum, cmd->_parId, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize >> 3, flags); + ani->startAnimSteps(cmd->_messageNum, cmd->_parId, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize, flags); } break; } diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp index 833d47fde1..5cdc449d91 100644 --- a/engines/fullpipe/modal.cpp +++ b/engines/fullpipe/modal.cpp @@ -752,11 +752,12 @@ void ModalCredits::update() { ModalMainMenu::ModalMainMenu() { _areas.clear(); - _mfield_2C = 0; - _mfield_C = 0; + _lastArea = 0; + _hoverAreaId = 0; _mfield_34 = 0; _scene = g_fp->accessScene(SC_MAINMENU); - _mfield_50 = 0; + _debugKeyCount = 0; + _sliderOffset = 0; _screct.left = g_fp->_sceneRect.left; _screct.top = g_fp->_sceneRect.top; _screct.right = g_fp->_sceneRect.right; @@ -780,7 +781,7 @@ ModalMainMenu::ModalMainMenu() { area = new MenuArea(); area->picIdL = PIC_MNU_EXIT_L; area->picObjD = 0; - area->picObjL = _scene->getPictureObjectById(PIC_MNU_EXIT_L, 0); + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); area->picObjL->_flags &= 0xFFFB; _areas.push_back(area); @@ -837,7 +838,7 @@ ModalMainMenu::ModalMainMenu() { area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); area->picObjL->_flags &= 0xFFFB; _areas.push_back(area); - _musicSliderIdx = _areas.size(); + _musicSliderIdx = _areas.size() - 1; if (g_fp->_mainMenu_debugEnabled) enableDebugMenuButton(); @@ -845,14 +846,267 @@ ModalMainMenu::ModalMainMenu() { setSliderPos(); } +void ModalMainMenu::update() { + _scene->draw(); +} + +bool ModalMainMenu::handleMessage(ExCommand *message) { + if (message->_messageKind != 17) + return false; + + Common::Point point; + + if (message->_messageNum == 29) { + point.x = message->_x; + point.y = message->_y; + + int numarea = checkHover(point); + + if (numarea >= 0) { + if (numarea == _menuSliderIdx) { + _lastArea = _areas[_menuSliderIdx]; + _sliderOffset = _lastArea->picObjL->_ox - point.x; + + return false; + } + + if (numarea == _musicSliderIdx) { + _lastArea = _areas[_musicSliderIdx]; + _sliderOffset = _lastArea->picObjL->_ox - point.x; + + return false; + } + + _hoverAreaId = _areas[numarea]->picIdL; + } + + return false; + } + + if (message->_messageNum == 30) { + if (_lastArea) + _lastArea = 0; + + return false; + } + + if (message->_messageNum != 36) + return false; + + if (message->_keyCode == 27) + _hoverAreaId = PIC_MNU_CONTINUE_L; + else + enableDebugMenu(message->_keyCode); + + return false; +} + +bool ModalMainMenu::init(int counterdiff) { + switch (_hoverAreaId) { + case PIC_MNU_RESTART_L: + g_fp->restartGame(); + + if (this == g_fp->_modalObject) + return false; + + delete this; + break; + + case PIC_MNU_EXIT_L: + { + ModalQuery *mq = new ModalQuery(); + + g_fp->_modalObject = mq; + + mq->_parentObj = this; + mq->create(_scene, PIC_MEX_BGR); + + _hoverAreaId = 0; + + return true; + } + + case PIC_MNU_DEBUG_L: + g_fp->_gameLoader->unloadScene(SC_MAINMENU); + g_fp->_sceneRect = _screct; + + if (!g_fp->_currentScene) + error("ModalMainMenu::init: Bad state"); + + g_fp->_currentScene->_x = _bgX; + g_fp->_currentScene->_y = _bgY; + + g_fp->_gameLoader->preloadScene(g_fp->_currentScene->_sceneId, SC_DBGMENU); + + return false; + + case PIC_MNU_CONTINUE_L: + if (!_mfield_34) { + g_fp->_gameLoader->unloadScene(SC_MAINMENU); + g_fp->_sceneRect = _screct; + + if (g_fp->_currentScene) { + g_fp->_currentScene->_x = _bgX; + g_fp->_currentScene->_y = _bgY; + } + + return false; + } + + g_fp->restartGame(); + + if (this == g_fp->_modalObject) + return false; + + delete this; + break; + + case PIC_MNU_AUTHORS_L: + g_fp->_modalObject = new ModalCredits(); + g_fp->_modalObject->_parentObj = this; + + _hoverAreaId = 0; + + return true; + + case PIC_MNU_SAVE_L: + case PIC_MNU_LOAD_L: + { + ModalSaveGame *sg = new ModalSaveGame(); + + g_fp->_modalObject = sg; + g_fp->_modalObject->_parentObj = _parentObj; + + int mode = 0; + if (_hoverAreaId == PIC_MNU_SAVE_L) + mode = 1; + + sg->setup(g_fp->accessScene(SC_MAINMENU), mode); + sg->setScene(g_fp->accessScene(SC_MAINMENU)); + + sg->_rect = _screct; + sg->_oldBgX = _bgX; + sg->_oldBgY = _bgY; + + delete this; + } + + break; + + default: + if (_lastArea) { + updateSliderPos(); + } else { + g_fp->_cursorId = PIC_CSR_DEFAULT; + + int idx = checkHover(g_fp->_mouseScreenPos); + + if (idx < 0) + goto LABEL_40; + + g_fp->_cursorId = PIC_CSR_DEFAULT; + + if (idx != this->_menuSliderIdx && idx != this->_musicSliderIdx ) + goto LABEL_40; + } + + g_fp->_cursorId = PIC_CSR_LIFT; + + LABEL_40: + g_fp->setCursor(g_fp->_cursorId); + + updateVolume(); + + return true; + } + + return true; +} + +void ModalMainMenu::updateVolume() { + warning("STUB: ModalMainMenu::updateVolume()"); +} + +void ModalMainMenu::updateSliderPos() { + warning("STUB: ModalMainMenu::updateSliderPos()"); +} + +int ModalMainMenu::checkHover(Common::Point &point) { + for (uint i = 0; i < _areas.size(); i++) { + if (_areas[i]->picObjL->isPixelHitAtPos(point.x, point.y)) { + _areas[i]->picObjL->_flags |= 4; + + return i; + } else { + _areas[i]->picObjL->_flags &= 0xFFFB; + } + } + + if (isOverArea(_areas[_menuSliderIdx]->picObjL, &point)) { + _areas[_menuSliderIdx]->picObjL->_flags |= 4; + + return _menuSliderIdx; + } + + if (isOverArea(_areas[_musicSliderIdx]->picObjL, &point)) { + _areas[_musicSliderIdx]->picObjL->_flags |= 4; + + return _musicSliderIdx; + } + + return -1; +} + +bool ModalMainMenu::isOverArea(PictureObject *obj, Common::Point *point) { + Common::Point p; + + obj->getDimensions(&p); + + int left = point->x - 8; + int right = point->x + 12; + int down = point->y - 11; + int up = point->y + 9; + + if (left >= obj->_ox && right < obj->_ox + p.x && down >= obj->_oy && up < obj->_oy + p.y) + return true; + + return false; +} + bool ModalMainMenu::isSaveAllowed() { warning("STUB: ModalMainMenu::isSaveAllowed()"); return true; } +void ModalMainMenu::enableDebugMenu(char c) { + const char deb[] = "DEBUGER"; + + if (c == deb[_debugKeyCount]) { + _debugKeyCount++; + + if (deb[_debugKeyCount] ) + return; + + enableDebugMenuButton(); + } + + _debugKeyCount = 0; +} + void ModalMainMenu::enableDebugMenuButton() { - warning("STUB: ModalMainMenu::enableDebugMenuButton()"); + MenuArea *area; + + for (uint i = 0; i < _areas.size(); i++) + if (_areas[i]->picIdL == PIC_MNU_DEBUG_L) + return; + + area = new MenuArea(); + area->picIdL = PIC_MNU_DEBUG_L; + area->picObjD = 0; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); } void ModalMainMenu::setSliderPos() { @@ -920,6 +1174,18 @@ void ModalHelp::launch() { } } +void ModalQuery::create(Scene *sc, int picId) { + warning("STUB: ModalQuery::create()"); +} + +void ModalSaveGame::setScene(Scene *sc) { + warning("STUB: ModalSaveGame::setScene()"); +} + +void ModalSaveGame::setup(Scene *sc, int mode) { + warning("STUB: ModalSaveGame::setup()"); +} + void FullpipeEngine::openHelp() { if (!_modalObject) { ModalHelp *help = new ModalHelp; diff --git a/engines/fullpipe/modal.h b/engines/fullpipe/modal.h index 532d145c2c..78ddf71f54 100644 --- a/engines/fullpipe/modal.h +++ b/engines/fullpipe/modal.h @@ -156,32 +156,37 @@ struct MenuArea { class ModalMainMenu : public BaseModalObject { public: Scene *_scene; - int _mfield_C; + int _hoverAreaId; Common::Array<MenuArea *> _areas; int _menuSliderIdx; int _musicSliderIdx; - int _mfield_2C; - int _mfield_30; + MenuArea *_lastArea; + int _sliderOffset; int _mfield_34; Common::Rect _screct; int _bgX; int _bgY; - int _mfield_50; + int _debugKeyCount; public: ModalMainMenu(); virtual ~ModalMainMenu() {} virtual bool pollEvent() { return true; } - virtual bool handleMessage(ExCommand *message) { return false; } - virtual bool init(int counterdiff) { return true; } - virtual void update() {} + virtual bool handleMessage(ExCommand *message); + virtual bool init(int counterdiff); + virtual void update(); virtual void saveload() {} private: bool isSaveAllowed(); void enableDebugMenuButton(); void setSliderPos(); + void enableDebugMenu(char c); + int checkHover(Common::Point &point); + void updateVolume(); + void updateSliderPos(); + bool isOverArea(PictureObject *obj, Common::Point *point); }; class ModalHelp : public BaseModalObject { @@ -208,7 +213,7 @@ public: class ModalQuery : public BaseModalObject { public: - ModalQuery(); + ModalQuery() {} virtual ~ModalQuery() {} virtual bool pollEvent() { return true; } @@ -216,11 +221,13 @@ public: virtual bool init(int counterdiff) { return true; } virtual void update() {} virtual void saveload() {} + + void create(Scene *sc, int picId); }; class ModalSaveGame : public BaseModalObject { public: - ModalSaveGame(); + ModalSaveGame() {} virtual ~ModalSaveGame() {} virtual bool pollEvent() { return true; } @@ -228,6 +235,13 @@ public: virtual bool init(int counterdiff) { return true; } virtual void update() {} virtual void saveload() {} + + void setScene(Scene *sc); + void setup(Scene *sc, int mode); + + Common::Rect _rect; + int _oldBgX; + int _oldBgY; }; diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp index 3abb03d1ae..47c6a3c8cd 100644 --- a/engines/fullpipe/scenes.cpp +++ b/engines/fullpipe/scenes.cpp @@ -1465,8 +1465,30 @@ Ball *BallChain::sub04(Ball *ballP, Ball *ballN) { return pTail; } -void BallChain::sub05(Ball *ball) { - warning("STUB: BallChain::sub05"); +void BallChain::removeBall(Ball *ball) { + if (ball == pHead) + pHead = ball->p0; + else + ball->p1->p0 = ball->p0; + + if (ball == field_8) + field_8 = ball->p1; + else + ball->p0->p1 = ball->p1; + + ball->p0 = pTail; + pTail = ball; + + numBalls--; + + if (!numBalls) { + numBalls = 0; + pTail = 0; + field_8 = 0; + pHead = 0; + free(cPlex); + cPlex = 0; + } } diff --git a/engines/fullpipe/scenes.h b/engines/fullpipe/scenes.h index 517576c6f3..0b7c4e7c8f 100644 --- a/engines/fullpipe/scenes.h +++ b/engines/fullpipe/scenes.h @@ -232,7 +232,7 @@ struct BallChain { void init(Ball **ball); Ball *sub04(Ball *ballP, Ball *ballN); - void sub05(Ball *ball); + void removeBall(Ball *ball); void reset() { pHead = 0; pTail = 0; field_8 = 0; numBalls = 0; free(cPlex); cPlex = 0; cPlexLen = 0; } }; diff --git a/engines/fullpipe/scenes/scene29.cpp b/engines/fullpipe/scenes/scene29.cpp index dbd753a133..2d5127137d 100644 --- a/engines/fullpipe/scenes/scene29.cpp +++ b/engines/fullpipe/scenes/scene29.cpp @@ -641,7 +641,7 @@ void sceneHandler29_ballHitCheck() { g_vars->scene29_redBalls.field_8 = newball; - g_vars->scene29_flyingRedBalls.sub05(ball); + g_vars->scene29_flyingRedBalls.removeBall(ball); sceneHandler29_manHit(); diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 75c1c7d1ea..a3a160b5b2 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -105,6 +105,19 @@ bool StepArray::gotoNextPoint() { } } +void StepArray::insertPoints(Common::Point **points, int pointsCount) { + if (_currPointIndex + pointsCount >= _pointsCount) + _points = (Common::Point **)realloc(_points, sizeof(Common::Point *) * (_currPointIndex + pointsCount)); + + _maxPointIndex = _currPointIndex + pointsCount; + + for (int i = 0; i < pointsCount; i++) { + _points[_currPointIndex + i] = new Common::Point; + + *_points[_currPointIndex + i] = *points[i]; + } +} + StaticANIObject::StaticANIObject() { _shadowsOn = 1; _field_30 = 0; @@ -330,7 +343,35 @@ bool StaticANIObject::trySetMessageQueue(int msgNum, int qId) { } void StaticANIObject::startMQIfIdle(int qId, int flag) { - warning("STUB: StaticANIObject::startMQIfIdle()"); + MessageQueue *msg = g_fp->_currentScene->getMessageQueueById(qId); + + if (msg && isIdle() && !(_flags & 0x100)) { + MessageQueue *mq = new MessageQueue(msg, 0, 0); + + mq->setFlags(mq->getFlags() | flag); + + ExCommand *ex = mq->getExCommandByIndex(0); + + if (ex) { + while (ex->_messageKind != 1 || ex->_parentId != _id) { + ex->_parId = 0; + ex->_excFlags |= 2; + ex->handleMessage(); + + mq->deleteExCommandByIndex(0, 0); + + ex = mq->getExCommandByIndex(0); + + if (!ex) + return; + } + + if (ex) { + startAnim(ex->_messageNum, mq->_id, -1); + mq->deleteExCommandByIndex(0, 1); + } + } + } } bool StaticANIObject::isIdle() { @@ -1060,7 +1101,47 @@ void StaticANIObject::show1(int x, int y, int movId, int mqId) { } void StaticANIObject::show2(int x, int y, int movementId, int mqId) { - warning("STUB: StaticANIObject::show2(%d, %d, %d, %d)", x, y, movementId, mqId); + if (movementId == -1) { + _flags |= 4u; + return; + } + + if (!_messageQueueId) { + _messageQueueId = mqId; + + Movement *mov = getMovementById(movementId); + + if (mov) { + _statics = mov->_staticsObj1; + _movement = mov; + mov->gotoLastFrame(); + mov->setOXY(x, y); + mov->gotoFirstFrame(); + + Common::Point point; + + mov->getCurrDynamicPhaseXY(point); + _statics->_x = mov->_ox - point.x - mov->_mx; + _statics->_y = mov->_oy - point.y - mov->_my; + + _statics->getSomeXY(point); + _flags |= 4; + _ox = _statics->_x + point.x; + _oy = _statics->_y + point.y; + + if (mov->_currMovement) { + _flags |= 8; + } else { + if (_flags & 8) + _flags ^= 8; + } + + if (_flags & 1) + _flags ^= 1; + + _flags |= 0x20; + } + } } void StaticANIObject::playIdle() { @@ -1069,7 +1150,85 @@ void StaticANIObject::playIdle() { } void StaticANIObject::startAnimSteps(int movementId, int messageQueueId, int x, int y, Common::Point **points, int pointsCount, int someDynamicPhaseIndex) { - warning("STUB: StaticANIObject::startAnimSteps()"); + Movement *mov = 0; + + if (!(_flags & 0x80)) { + if (!_messageQueueId) + for (uint i = 0; i < _movements.size(); i++) { + if (((Movement *)_movements[i])->_id == movementId) { + mov = (Movement *)_movements[i]; + break; + } + } + } + + if (!mov) { + updateGlobalMessageQueue(messageQueueId, _id); + + return; + } + + + if (_movement || !_statics) + return; + + Common::Point point; + + _statics->getSomeXY(point); + + int newx = _ox - point.x; + int newy = _oy - point.y; + + _movement = mov; + + if (_flags & 0x40) + _movement->gotoLastFrame(); + else + _movement->gotoFirstFrame(); + + _stepArray.clear(); + _stepArray.insertPoints(points, pointsCount); + + if (!(_flags & 0x40)) { + if (!_movement->_currDynamicPhaseIndex) { + _stepArray.getCurrPoint(&point); + newx += point.x + _movement->_mx; + newy += point.y + _movement->_my; + _stepArray.gotoNextPoint(); + + ExCommand *ex = _movement->_currDynamicPhase->getExCommand(); + + if (ex) { + if (ex->_messageKind == 35) { + ExCommand *newEx = ex->createClone(); + + newEx->_excFlags |= 2u; + newEx->sendMessage(); + } + } + } + } + + _movement->getCurrDynamicPhaseXY(point); + setOXY(point.x + newx, point.y + newy); + + if ((_movement->_staticsObj2->_staticsId >> 8) & 0x40) + _flags |= 8; + else + _flags &= 0xFFF7; + + _flags |= 1; + _messageQueueId = messageQueueId; + _movement->_currDynamicPhase->_countdown = _movement->_currDynamicPhase->_initialCountdown; + _movement->_counter = 0; + _counter = _initialCounter; + _someDynamicPhaseIndex = someDynamicPhaseIndex; + + ExCommand *ex = new ExCommand(_id, 17, 23, 0, 0, movementId, 1, 0, 0, 0); + + ex->_keyCode = _okeyCode; + ex->_excFlags = 2; + ex->postMessage(); } bool StaticANIObject::startAnimEx(int movid, int parId, int flag1, int flag2) { diff --git a/engines/fullpipe/statics.h b/engines/fullpipe/statics.h index 8328e7679b..89703965cd 100644 --- a/engines/fullpipe/statics.h +++ b/engines/fullpipe/statics.h @@ -47,6 +47,7 @@ class StepArray : public CObject { Common::Point *getCurrPoint(Common::Point *point); Common::Point *getPoint(Common::Point *point, int index, int offset); bool gotoNextPoint(); + void insertPoints(Common::Point **points, int pointsCount); }; class StaticPhase : public Picture { diff --git a/engines/neverhood/modules/module2200.cpp b/engines/neverhood/modules/module2200.cpp index f9033a9dbe..6618cb3ab0 100644 --- a/engines/neverhood/modules/module2200.cpp +++ b/engines/neverhood/modules/module2200.cpp @@ -885,7 +885,7 @@ void Scene2205::update() { } else if (_isLightOn && !getGlobalVar(V_LIGHTS_ON)) { _palette->addPalette(0xD00A028D, 0, 256, 0); changeBackground(0xD00A028D); - _ssLightSwitch->setFileHashes(0x2D339030, 0xDAC86E84); + _ssLightSwitch->setFileHashes(0xD6C86E84, 0xDAC86E84); sendMessage(_ssDoorFrame, 0x2000, 0); changeMouseCursor(0xA0289D08); _isKlaymenInLight = true; diff --git a/engines/neverhood/modules/module2300.cpp b/engines/neverhood/modules/module2300.cpp index c0edc95873..68ae07f2bb 100644 --- a/engines/neverhood/modules/module2300.cpp +++ b/engines/neverhood/modules/module2300.cpp @@ -31,14 +31,14 @@ static const uint32 kModule2300SoundList[] = { }; Module2300::Module2300(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundVolume(0) { + : Module(vm, parentModule), _waterfallSoundVolume(0) { _vm->_soundMan->addSoundList(0x1A214010, kModule2300SoundList); _vm->_soundMan->setSoundListParams(kModule2300SoundList, true, 50, 600, 10, 150); - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + _isWaterfallRunning = getGlobalVar(V_WALL_BROKEN) != 1; - if (_isWallBroken) { + if (_isWaterfallRunning) { _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); _vm->_soundMan->playSoundLooping(0x90F0D1C3); } else { @@ -78,8 +78,8 @@ void Module2300::createScene(int sceneNum, int which) { case 1: _vm->gameState().sceneNum = 1; createNavigationScene(0x004B67E8, which); - if (_isWallBroken) { - _soundVolume = 15; + if (_isWaterfallRunning) { + _waterfallSoundVolume = 15; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 15); } break; @@ -92,10 +92,10 @@ void Module2300::createScene(int sceneNum, int which) { if (getGlobalVar(V_WALL_BROKEN)) createNavigationScene(0x004B68F0, which); else { - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); createNavigationScene(0x004B68A8, which); - if (_isWallBroken) { - _soundVolume = 87; + if (_isWaterfallRunning) { + _waterfallSoundVolume = 87; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 87); } } @@ -161,10 +161,10 @@ void Module2300::updateScene() { } else { switch (_sceneNum) { case 1: - if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 && + if (_isWaterfallRunning && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 && navigationScene()->getFrameNumber() % 2) { - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + _waterfallSoundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0 && navigationScene()->getFrameNumber() == 50) { @@ -174,9 +174,9 @@ void Module2300::updateScene() { } break; case 3: - if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getFrameNumber() % 2) { - _soundVolume--; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + if (_isWaterfallRunning && navigationScene()->isWalkingForward() && navigationScene()->getFrameNumber() % 2) { + _waterfallSoundVolume--; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } break; } diff --git a/engines/neverhood/modules/module2300.h b/engines/neverhood/modules/module2300.h index 57235986d9..58bffb710c 100644 --- a/engines/neverhood/modules/module2300.h +++ b/engines/neverhood/modules/module2300.h @@ -37,8 +37,8 @@ public: virtual ~Module2300(); protected: int _sceneNum; - bool _isWallBroken; - int _soundVolume; + int _waterfallSoundVolume; + bool _isWaterfallRunning; void createScene(int sceneNum, int which); void updateScene(); }; diff --git a/engines/neverhood/modules/module3000.cpp b/engines/neverhood/modules/module3000.cpp index 59b2df260e..d4809611ad 100644 --- a/engines/neverhood/modules/module3000.cpp +++ b/engines/neverhood/modules/module3000.cpp @@ -39,7 +39,7 @@ static const uint32 kModule3000SoundList[] = { }; Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundVolume(0) { + : Module(vm, parentModule), _waterfallSoundVolume(0) { _vm->_soundMan->addSoundList(0x81293110, kModule3000SoundList); _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 50, 600, 5, 150); @@ -48,9 +48,9 @@ Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which) _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + _isWaterfallRunning = getGlobalVar(V_WALL_BROKEN) != 1; - if (!_isWallBroken) { + if (_isWaterfallRunning) { _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); _vm->_soundMan->playSoundLooping(0x90F0D1C3); } @@ -78,12 +78,11 @@ void Module3000::createScene(int sceneNum, int which) { static const byte kNavigationTypes06[] = {5}; debug(1, "Module3000::createScene(%d, %d)", sceneNum, which); _vm->gameState().sceneNum = sceneNum; - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; switch (_vm->gameState().sceneNum) { case 1: if (!getGlobalVar(V_BOLT_DOOR_OPEN)) { createNavigationScene(0x004B7C80, which); - } else if (_isWallBroken) { + } else if (getGlobalVar(V_WALL_BROKEN)) { createNavigationScene(0x004B7CE0, which); } else { createNavigationScene(0x004B7CB0, which); @@ -91,11 +90,11 @@ void Module3000::createScene(int sceneNum, int which) { break; case 2: _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); - if (!_isWallBroken) { - _soundVolume = 90; + if (_isWaterfallRunning) { + _waterfallSoundVolume = 90; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 90); } - if (_isWallBroken) { + if (getGlobalVar(V_WALL_BROKEN)) { createNavigationScene(0x004B7D58, which); } else { createNavigationScene(0x004B7D10, which); @@ -104,7 +103,7 @@ void Module3000::createScene(int sceneNum, int which) { case 3: if (getGlobalVar(V_STAIRS_DOWN)) createNavigationScene(0x004B7E60, which); - else if (_isWallBroken) + else if (getGlobalVar(V_WALL_BROKEN)) createNavigationScene(0x004B7DA0, which); else createNavigationScene(0x004B7E00, which); @@ -152,12 +151,12 @@ void Module3000::createScene(int sceneNum, int which) { // NOTE: Newly introduced sceneNums case 1001: if (!getGlobalVar(V_BOLT_DOOR_OPEN)) - if (_isWallBroken) + if (getGlobalVar(V_WALL_BROKEN)) createSmackerScene(0x00940021, true, true, false); else createSmackerScene(0x01140021, true, true, false); else - if (_isWallBroken) + if (getGlobalVar(V_WALL_BROKEN)) createSmackerScene(0x001011B1, true, true, false); else createSmackerScene(0x001021B1, true, true, false); @@ -195,8 +194,8 @@ void Module3000::updateScene() { break; case 2: _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); - if (_isWallBroken) { - _soundVolume = 0; + if (_isWaterfallRunning) { + _waterfallSoundVolume = 0; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); } if (_moduleResult == 0) { @@ -240,7 +239,7 @@ void Module3000::updateScene() { createScene(8, -1); break; case 8: - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + _isWaterfallRunning = getGlobalVar(V_WALL_BROKEN) != 1; if (_moduleResult != 1) { _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 0, 0, 0, 0); createScene(4, 1); @@ -301,12 +300,12 @@ void Module3000::updateScene() { } else if (frameNumber == 10) { _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); } - if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) { + if (_isWaterfallRunning && _waterfallSoundVolume < 90 && frameNumber % 2) { if (frameNumber == 0) - _soundVolume = 40; + _waterfallSoundVolume = 40; else - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + _waterfallSoundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } } } @@ -315,9 +314,9 @@ void Module3000::updateScene() { if (navigationScene()->isWalkingForward()) { uint32 frameNumber = navigationScene()->getFrameNumber(); int navigationIndex = navigationScene()->getNavigationIndex(); - if (!_isWallBroken && _soundVolume > 1 && frameNumber % 2) { - _soundVolume--; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + if (_isWaterfallRunning && _waterfallSoundVolume > 1 && frameNumber % 2) { + _waterfallSoundVolume--; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } if (navigationIndex == 0) { if (frameNumber == 35) { @@ -340,12 +339,12 @@ void Module3000::updateScene() { if (frameNumber == 40) { _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); } - if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) { + if (_isWaterfallRunning && _waterfallSoundVolume < 90 && frameNumber % 2) { if (frameNumber == 0) - _soundVolume = 40; + _waterfallSoundVolume = 40; else - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + _waterfallSoundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } } } diff --git a/engines/neverhood/modules/module3000.h b/engines/neverhood/modules/module3000.h index e5c251f828..3d895b8d8a 100644 --- a/engines/neverhood/modules/module3000.h +++ b/engines/neverhood/modules/module3000.h @@ -34,8 +34,8 @@ public: Module3000(NeverhoodEngine *vm, Module *parentModule, int which); virtual ~Module3000(); protected: - int _soundVolume; - bool _isWallBroken; + int _waterfallSoundVolume; + bool _isWaterfallRunning; void createScene(int sceneNum, int which); void updateScene(); }; diff --git a/engines/pegasus/items/item.cpp b/engines/pegasus/items/item.cpp index 8089f2b93d..830d3f2f34 100644 --- a/engines/pegasus/items/item.cpp +++ b/engines/pegasus/items/item.cpp @@ -39,9 +39,9 @@ namespace Pegasus { Item::Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) : IDObject(id) { - _itemNeighborhood = neighborhood; - _itemRoom = room; - _itemDirection = direction; + _originalNeighborhood = _itemNeighborhood = neighborhood; + _originalRoom = _itemRoom = room; + _originalDirection = _itemDirection = direction; _itemWeight = 1; _itemOwnerID = kNoActorID; _itemState = 0; @@ -131,6 +131,14 @@ Item::~Item() { delete[] _itemExtras.entries; } +void Item::reset() { + _itemNeighborhood = _originalNeighborhood; + _itemRoom = _originalRoom; + _itemDirection = _originalDirection; + _itemOwnerID = kNoActorID; + _itemState = 0; +} + void Item::writeToStream(Common::WriteStream *stream) { stream->writeUint16BE(_itemNeighborhood); stream->writeUint16BE(_itemRoom); diff --git a/engines/pegasus/items/item.h b/engines/pegasus/items/item.h index a1451b2a58..26cccf043c 100644 --- a/engines/pegasus/items/item.h +++ b/engines/pegasus/items/item.h @@ -339,6 +339,9 @@ public: void findItemExtra(const uint32 extraID, ItemExtraEntry &entry); + // Reset to its original state at the beginning of the game + void reset(); + protected: NeighborhoodID _itemNeighborhood; RoomID _itemRoom; @@ -347,6 +350,10 @@ protected: WeightType _itemWeight; ItemState _itemState; + NeighborhoodID _originalNeighborhood; + RoomID _originalRoom; + DirectionConstant _originalDirection; + JMPItemInfo _itemInfo; ItemStateInfo _sharedAreaInfo; ItemExtraInfo _itemExtras; diff --git a/engines/pegasus/items/itemlist.cpp b/engines/pegasus/items/itemlist.cpp index ff8cae546b..4b58d9ad78 100644 --- a/engines/pegasus/items/itemlist.cpp +++ b/engines/pegasus/items/itemlist.cpp @@ -64,4 +64,9 @@ Item *ItemList::findItemByID(const ItemID id) { return 0; } +void ItemList::resetAllItems() { + for (ItemIterator it = begin(); it != end(); it++) + (*it)->reset(); +} + } // End of namespace Pegasus diff --git a/engines/pegasus/items/itemlist.h b/engines/pegasus/items/itemlist.h index 9b59206ab3..22bef2c96e 100644 --- a/engines/pegasus/items/itemlist.h +++ b/engines/pegasus/items/itemlist.h @@ -48,6 +48,7 @@ public: virtual void readFromStream(Common::ReadStream *stream); Item *findItemByID(const ItemID id); + void resetAllItems(); }; typedef ItemList::iterator ItemIterator; diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp index 0707a83e87..7977c17f12 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp @@ -1916,10 +1916,13 @@ uint Caldoria::getNumHints() { numHints = 1; } break; +#if 0 + // The hint file is missing case MakeRoomView(kCaldoria49, kEast): case MakeRoomView(kCaldoria54, kEast): numHints = 1; break; +#endif case MakeRoomView(kCaldoria49, kNorth): numHints = 1; break; @@ -1950,9 +1953,12 @@ Common::String Caldoria::getHintMovie(uint hintNum) { } return "Images/AI/Globals/XGLOB1A"; +#if 0 + // The hint file is missing case MakeRoomView(kCaldoria49, kEast): case MakeRoomView(kCaldoria54, kEast): return "Images/AI/Caldoria/X49E"; +#endif case MakeRoomView(kCaldoria49, kNorth): return "Images/AI/Caldoria/X49NB2"; } diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp index 435bcd4c9e..a83b7802f5 100644 --- a/engines/pegasus/neighborhood/mars/mars.cpp +++ b/engines/pegasus/neighborhood/mars/mars.cpp @@ -535,6 +535,10 @@ void Mars::doorOpened() { } void Mars::setUpReactorEnergyDrain() { + // If there's no energy monitor, there's nothing to do + if (!g_energyMonitor) + return; + switch (GameState.getCurrentRoomAndView()) { case MakeRoomView(kMars51, kEast): if (GameState.isCurrentDoorOpen()) { diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp index 75f652ad56..c0fa3c4fe6 100644 --- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp +++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp @@ -2643,6 +2643,7 @@ void FullTSA::receiveNotification(Notification *notification, const Notification GameState.setMarsReadyForShuttleTransport(false); GameState.setMarsFinishedCanyonChase(false); GameState.setMarsThreadedMaze(false); + GameState.setMarsSawRobotLeave(false); break; case kPlayerOnWayToWSC: _vm->jumpToNewEnvironment(kWSCID, kWSC01, kWest); diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp index 0326c7f2ee..c808325b0f 100644 --- a/engines/pegasus/neighborhood/tsa/tinytsa.cpp +++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp @@ -327,6 +327,7 @@ void TinyTSA::receiveNotification(Notification *notification, const Notification GameState.setMarsReadyForShuttleTransport(false); GameState.setMarsFinishedCanyonChase(false); GameState.setMarsThreadedMaze(false); + GameState.setMarsSawRobotLeave(false); break; case kPlayerOnWayToWSC: _vm->jumpToNewEnvironment(kWSCID, kWSC01, kWest); diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index c5edd34a01..2062fe6847 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -36,6 +36,7 @@ #include "backends/keymapper/keymapper.h" #include "base/plugins.h" #include "base/version.h" +#include "gui/message.h" #include "gui/saveload.h" #include "video/theora_decoder.h" #include "video/qt_decoder.h" @@ -379,20 +380,21 @@ Common::Error PegasusEngine::showSaveDialog() { int slot = slc.runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); - Common::Error result; + if (slot >= 0) + return saveGameState(slot, slc.getResultString()); - if (slot >= 0) { - if (saveGameState(slot, slc.getResultString()).getCode() == Common::kNoError) - result = Common::kNoError; - else - result = Common::kUnknownError; - } else { - result = Common::kUserCanceled; - } + return Common::kUserCanceled; +} - return result; +void PegasusEngine::showSaveFailedDialog(const Common::Error &status) { + Common::String failMessage = Common::String::format(_("Gamestate save failed (%s)! " + "Please consult the README for basic information, and for " + "instructions on how to obtain further assistance."), status.getDesc().c_str()); + GUI::MessageDialog dialog(failMessage); + dialog.runModal(); } + GUI::Debugger *PegasusEngine::getDebugger() { return _console; } @@ -969,8 +971,14 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) { resetIntroTimer(); break; case kMenuCmdPauseSave: - if (showSaveDialog().getCode() != Common::kUserCanceled) + result = showSaveDialog(); + + if (result.getCode() != Common::kUserCanceled) { + if (result.getCode() != Common::kNoError) + showSaveFailedDialog(result); + pauseMenu(false); + } break; case kMenuCmdPauseContinue: pauseMenu(false); @@ -1021,7 +1029,12 @@ void PegasusEngine::handleInput(const Input &input, const Hotspot *cursorSpot) { // Can only save during a game and not in the demo if (g_neighborhood && !isDemo()) { pauseEngine(true); - showSaveDialog(); + + Common::Error result = showSaveDialog(); + + if (result.getCode() != Common::kNoError && result.getCode() != Common::kUserCanceled) + showSaveFailedDialog(result); + pauseEngine(false); } } @@ -1669,6 +1682,9 @@ void PegasusEngine::startNewGame() { removeAllItemsFromInventory(); removeAllItemsFromBiochips(); + // Properly reset all items to their original state + g_allItems.resetAllItems(); + BiochipItem *biochip = (BiochipItem *)_allItems.findItemByID(kAIBiochip); addItemToBiochips(biochip); diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h index fb66eb7586..d88545a4d1 100644 --- a/engines/pegasus/pegasus.h +++ b/engines/pegasus/pegasus.h @@ -257,6 +257,7 @@ private: bool _saveAllowed, _loadAllowed; // It's so nice that this was in the original code already :P Common::Error showLoadDialog(); Common::Error showSaveDialog(); + void showSaveFailedDialog(const Common::Error &status); bool _saveRequested, _loadRequested; // Misc. diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp index c5a1e91ef5..df9a8648db 100644 --- a/engines/wintermute/base/font/base_font_truetype.cpp +++ b/engines/wintermute/base/font/base_font_truetype.cpp @@ -625,6 +625,8 @@ bool BaseFontTT::initFont() { warning("Looking for %s", fontName.c_str()); _font = FontMan.getFontByName(fontName); } +#else + warning("BaseFontTT::InitFont - FreeType2-support not compiled in, TTF-fonts will not be loaded"); #endif // USE_FREETYPE2 // Fallback4: Just use the Big GUI-font. (REALLY undesireable) diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp index b0c469c440..e1553580ec 100644 --- a/engines/wintermute/video/video_theora_player.cpp +++ b/engines/wintermute/video/video_theora_player.cpp @@ -127,6 +127,7 @@ bool VideoTheoraPlayer::initialize(const Common::String &filename, const Common: #if defined (USE_THEORADEC) _theoraDecoder = new Video::TheoraDecoder(); #else + warning("VideoTheoraPlayer::initialize - Theora support not compiled in, video will be skipped: %s", filename.c_str()); return STATUS_FAILED; #endif _theoraDecoder->loadStream(_file); |