aboutsummaryrefslogtreecommitdiff
path: root/engines/toon/toon.cpp
diff options
context:
space:
mode:
authorEugene Sandulenko2010-10-08 22:30:39 +0000
committerEugene Sandulenko2010-10-08 22:30:39 +0000
commitcf82bef02ee2941ddad6664e34f3c94e35e015a3 (patch)
treed39e339d032b45f705bcb3383139184c507c1a7f /engines/toon/toon.cpp
parent741e7c7f5ec800bf0209e93da3d6f9ec2869cdb3 (diff)
downloadscummvm-rg350-cf82bef02ee2941ddad6664e34f3c94e35e015a3.tar.gz
scummvm-rg350-cf82bef02ee2941ddad6664e34f3c94e35e015a3.tar.bz2
scummvm-rg350-cf82bef02ee2941ddad6664e34f3c94e35e015a3.zip
TOON: Merged Toon engine to ScummVM trunk
svn-id: r53087
Diffstat (limited to 'engines/toon/toon.cpp')
-rw-r--r--engines/toon/toon.cpp4276
1 files changed, 4276 insertions, 0 deletions
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
new file mode 100644
index 0000000000..dc96be9c34
--- /dev/null
+++ b/engines/toon/toon.cpp
@@ -0,0 +1,4276 @@
+/* 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.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#include "common/system.h"
+#include "common/events.h"
+#include "common/debug-channels.h"
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/EventRecorder.h"
+#include "engines/util.h"
+#include "graphics/surface.h"
+#include "graphics/thumbnail.h"
+#include "gui/saveload.h"
+#include "gui/about.h"
+#include "gui/message.h"
+#include "resource.h"
+#include "toon.h"
+#include "anim.h"
+#include "picture.h"
+#include "hotspot.h"
+#include "flux.h"
+#include "drew.h"
+#include "path.h"
+
+namespace Toon {
+
+
+void ToonEngine::init() {
+ _currentScriptRegion = 0;
+ _resources = new Resources(this);
+ _animationManager = new AnimationManager(this);
+ _moviePlayer = new Movie(this, new ToonstruckSmackerDecoder(_mixer));
+ _hotspots = new Hotspots(this);
+
+ _mainSurface = new Graphics::Surface();
+ _mainSurface->create(1280, 400, 1);
+
+ _finalPalette = new uint8[768];
+ _backupPalette = new uint8[768];
+ _additionalPalette1 = new uint8[69];
+ _additionalPalette2 = new uint8[69];
+ _cutawayPalette = new uint8[768];
+ _universalPalette = new uint8[96];
+ _fluxPalette = new uint8[24];
+
+ memset(_finalPalette, 0, 768);
+ memset(_backupPalette, 0, 768);
+ memset(_additionalPalette1, 0, 69);
+ memset(_additionalPalette2, 0, 69);
+ memset(_cutawayPalette, 0, 768);
+ memset(_universalPalette, 0, 96);
+ memset(_fluxPalette, 0, 24);
+
+ _conversationData = new int16[4096];
+ memset(_conversationData, 0, 4096 * sizeof(int16));
+
+ _cursorOffsetX = 0;
+ _cursorOffsetY = 0;
+ _currentHotspotItem = 0;
+
+ _currentTextLine = 0;
+ _currentTextLineId = -1;
+ _currentTextLineX = 0;
+ _currentTextLineY = 0 ;
+ _currentTextLineCharacterId = 0;
+
+ _saveBufferStream = new Common::MemoryWriteStreamDynamic();
+
+ _firstFrame = false;
+
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ SearchMan.addSubDirectoryMatching(gameDataDir, "misc");
+
+ syncSoundSettings();
+
+ _pathFinding = new PathFinding(this);
+
+ resources()->openPackage("misc/local.pak", true);
+ resources()->openPackage("misc/onetime.pak", true);
+ resources()->openPackage("misc/drew.pak", true);
+
+ for (int32 i = 0; i < 32; i++)
+ _characters[i] = 0;
+
+ _characters[0] = new CharacterDrew(this);
+ _characters[1] = new CharacterFlux(this);
+ _drew = _characters[0];
+ _flux = _characters[1];
+
+ // preload walk anim for flux and drew
+ _drew->loadWalkAnimation("stndwalk.caf");
+ _drew->setupPalette();
+ _drew->loadShadowAnimation("shadow.caf");
+
+ _flux->loadWalkAnimation("fxstwalk.caf");
+ _flux->loadShadowAnimation("shadow.caf");
+
+ loadAdditionalPalette("universe.pal", 3);
+ loadAdditionalPalette("flux.pal", 4);
+ setupGeneralPalette();
+
+ _script_func = new ScriptFunc(this);
+ _gameState = new State();
+ _gameState->_conversationData = _conversationData;
+
+ memset(_sceneAnimations, 0, sizeof(_sceneAnimations));
+ memset(_sceneAnimationScripts, 0, sizeof(_sceneAnimationScripts));
+
+
+ _gameState->_currentChapter = 1;
+ initChapter();
+ loadCursor();
+ initFonts();
+
+ _dialogIcons = new Animation(this);
+ _dialogIcons->loadAnimation("dialogue.caf");
+
+ _inventoryIcons = new Animation(this);
+ _inventoryIcons->loadAnimation("inventry.caf");
+
+ _inventoryIconSlots = new Animation(this);
+ _inventoryIconSlots->loadAnimation("iconslot.caf");
+
+ _genericTexts = new TextResource(this);
+ _genericTexts->loadTextResource("generic.tre");
+
+ _audioManager = new AudioManager(this, _mixer);
+ _audioManager->loadAudioPack(0, "generic.svi", "misc/generic.svl");
+ _audioManager->loadAudioPack(2, "generic.sei", "generic.sel");
+
+ _lastMouseButton = 0;
+ _mouseButton = 0;
+}
+
+void ToonEngine::parseInput() {
+
+ Common::EventManager *_event = _system->getEventManager();
+
+ _mouseX = _event->getMousePos().x;
+ _mouseY = _event->getMousePos().y;
+ _mouseButton = _event->getButtonState();
+
+ Common::Event event;
+ while (_event->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYUP:
+ if (event.kbd.ascii == 27 || event.kbd.ascii == 32) {
+ _audioManager->stopCurrentVoice();
+ }
+ if (event.kbd.keycode == Common::KEYCODE_F5) {
+ saveGame(-1);
+ }
+ if (event.kbd.keycode == Common::KEYCODE_F6) {
+ loadGame(-1);
+ }
+
+ if (event.kbd.flags & Common::KBD_ALT) {
+ int32 slotNum = event.kbd.ascii - '0';
+ if (slotNum >= 0 && slotNum <= 9) {
+ if (saveGame(slotNum)) {
+ // ok
+ char buf[256];
+ snprintf(buf, 256, "Saved game in slot #%d ",slotNum);
+ GUI::TimedMessageDialog dialog(Common::String(buf), 1000);
+ dialog.runModal();
+ }
+ else {
+ char buf[256];
+ snprintf(buf, 256, "Could not quick save into slot #%d", slotNum);
+ GUI::MessageDialog dialog2(Common::String(buf), "OK", 0);
+ //warning("%s", buf);
+ dialog2.runModal();
+
+ }
+ }
+ }
+
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ int32 slotNum = event.kbd.ascii - '0';
+ if (slotNum >= 0 && slotNum <= 9) {
+ if (loadGame(slotNum)) {
+ // ok
+ char buf[256];
+ snprintf(buf, 256, "Savegame #%d quick loaded", slotNum);
+ GUI::TimedMessageDialog dialog(Common::String(buf), 1000);
+ dialog.runModal();
+ }
+ else {
+ char buf[256];
+ snprintf(buf, 256, "Could not quick load the savegame #%d", slotNum);
+ GUI::MessageDialog dialog(Common::String(buf), "OK", 0);
+ warning("%s", buf);
+ dialog.runModal();
+ }
+ }
+ }
+ break;
+// Strangerke - Commented (not used)
+// case Common::EVENT_LBUTTONDOWN:
+// break;
+// case Common::EVENT_RBUTTONDOWN:
+// break;
+// case Common::EVENT_LBUTTONUP:
+// break;
+// case Common::EVENT_RBUTTONUP:
+// break;
+// case Common::EVENT_WHEELUP:
+// break;
+// case Common::EVENT_WHEELDOWN:
+// break;
+ default:
+ break;
+ }
+ }
+
+ if (!_gameState->_inConversation && !_gameState->_mouseHidden && !_gameState->_inInventory) {
+ selectHotspot();
+ clickEvent();
+ }
+
+}
+
+void ToonEngine::enableTimer(int32 timerId) {
+ _gameState->_timerEnabled[timerId] = true;
+}
+void ToonEngine::setTimer(int32 timerId, int32 timerWait) {
+ _gameState->_timerTimeout[timerId] = getOldMilli() + timerWait * getTickLength();
+ _gameState->_timerDelay[timerId] = timerWait;
+}
+void ToonEngine::disableTimer(int32 timerId) {
+ _gameState->_timerEnabled[timerId] = false;
+}
+void ToonEngine::updateTimers() {
+ for (int32 i = 0; i < 2; i++) {
+ if (_gameState->_timerEnabled[i]) {
+ if (_gameState->_timerDelay[i] > -1 && getOldMilli() > _gameState->_timerTimeout[i]) {
+ if (i == 0) {
+
+ EMCState *status = &_scriptState[_currentScriptRegion];
+ _script->init(status, &_scriptData);
+
+ // setup registers
+ status->regs[0] = _mouseX;
+ status->regs[1] = _mouseY;
+ status->regs[2] = 0;
+
+ _currentScriptRegion++;
+
+ _script->start(status, 7);
+ while (_script->run(status))
+ ;
+
+ _currentScriptRegion--;
+
+ _gameState->_timerTimeout[i] = getOldMilli() + _gameState->_timerDelay[i] * getTickLength();
+
+ return;
+
+ }
+ }
+ }
+ }
+}
+
+void ToonEngine::updateScrolling(bool force, int32 timeIncrement) {
+ static int32 lastScrollOffset = 320;
+ if (!_audioManager->voiceStillPlaying() && !_gameState->_currentScrollLock && (_drew->getFlag() & 1) == 0) {
+ if (_drew->getFacing() & 3) {
+ if (_drew->getFacing() <= 4)
+ lastScrollOffset = 200;
+ else
+ lastScrollOffset = 440;
+ }
+
+ if (_gameState->_inCutaway || _gameState->_inInventory || _gameState->_inCloseUp)
+ return;
+
+ int32 desiredScrollValue = _drew->getX() - lastScrollOffset;
+
+ if ((_gameState->_locations[_gameState->_currentScene]._flags & 0x80) == 0) {
+ if (desiredScrollValue < 0)
+ desiredScrollValue = 0;
+ if (desiredScrollValue >= _currentPicture->getWidth() - 640)
+ desiredScrollValue = _currentPicture->getWidth() - 640;
+
+ if (force) {
+ _gameState->_currentScrollValue = desiredScrollValue;
+ return;
+ } else {
+ if (_gameState->_currentScrollValue < desiredScrollValue) {
+ _gameState->_currentScrollValue += timeIncrement / 2;
+
+ if (_gameState->_currentScrollValue > desiredScrollValue)
+ _gameState->_currentScrollValue = desiredScrollValue;
+ } else if (_gameState->_currentScrollValue > desiredScrollValue) {
+ _gameState->_currentScrollValue -= timeIncrement / 2;
+
+ if (_gameState->_currentScrollValue < desiredScrollValue)
+ _gameState->_currentScrollValue = desiredScrollValue;
+ }
+ }
+ }
+ }
+}
+
+void ToonEngine::update(int32 timeIncrement) {
+ // to make sure we're updating the game at 5fps at least
+ if (timeIncrement > 200)
+ timeIncrement = 200;
+
+ updateAnimationSceneScripts(timeIncrement);
+ updateCharacters(timeIncrement);
+ updateTimer(timeIncrement);
+ updateTimers();
+ updateScrolling(false,timeIncrement);
+ _animationManager->update(timeIncrement);
+ _cursorAnimationInstance->update(timeIncrement);
+
+ if (!_audioManager->voiceStillPlaying()) {
+ _currentTextLine = 0;
+ _currentTextLineId = -1;
+ }
+}
+
+void ToonEngine::updateTimer(int32 timeIncrement) {
+ if (_gameState->_gameTimer > 0) {
+ debugC(0, 0xfff,"updateTimer(%d)", timeIncrement);
+ _gameState->_gameTimer -= timeIncrement;
+ if (_gameState->_gameTimer < 0)
+ _gameState->_gameTimer = 0;
+ }
+}
+
+void ToonEngine::render() {
+ if (_gameState->_inCutaway)
+ _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
+ else
+ _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
+
+ //_currentMask->drawMask(*_mainSurface,0,0,0,0);
+ _animationManager->render();
+
+ drawInfoLine();
+ drawConversationLine();
+ drawConversationIcons();
+ drawSack();
+ //drawPalette();
+
+#if 0
+ char test[256];
+ if (_mouseX > 0 && _mouseX < 640 && _mouseY > 0 && _mouseY < 400) {
+ sprintf(test, "%d %d / mask %d layer %d z %d", _mouseX, _mouseY, getMask()->getData(_mouseX,_mouseY), getLayerAtPoint(_mouseX,_mouseY), getZAtPoint(_mouseX,_mouseY));
+
+ int32 c = *(uint8*)_mainSurface->getBasePtr(_mouseX,_mouseY);
+ sprintf(test, "%d %d / color id %d %d,%d,%d", _mouseX, _mouseY, c, _finalPalette[c*3+0],_finalPalette[c*3+1],_finalPalette[c*3+2]);
+
+ _fontRenderer->setFont(_fontToon);
+ _fontRenderer->renderText(40, 150, Common::String(test), 0);
+ }
+#endif
+
+ if (_firstFrame) {
+ copyToVirtualScreen(false);
+ fadeIn(5);
+ _firstFrame = false;
+ } else {
+ copyToVirtualScreen(true);
+ }
+}
+
+void ToonEngine::copyToVirtualScreen(bool updateScreen) {
+ // render cursor last
+ if (!_gameState->_mouseHidden) {
+ _cursorAnimationInstance->setPosition(_mouseX - 40 + state()->_currentScrollValue - _cursorOffsetX, _mouseY - 40 - _cursorOffsetY, 0, false);
+ _cursorAnimationInstance->render();
+ }
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, 1280, 0, 0, 640, 400);
+ if (updateScreen)
+ _system->updateScreen();
+}
+
+void ToonEngine::doFrame() {
+
+ if (_gameState->_inInventory) {
+ renderInventory();
+ } else {
+ render();
+
+ int32 currentTimer = _system->getMillis();
+// Strangerke - Commented (not used)
+// int32 elapsedTime = currentTimer - _oldTimer;
+
+ update(currentTimer - _oldTimer);
+ _oldTimer = currentTimer;
+ _oldTimer2 = currentTimer;
+ }
+ parseInput();
+}
+
+enum MainMenuSelections {
+ MAINMENUHOTSPOT_NONE = 0,
+ MAINMENUHOTSPOT_START = 1,
+ MAINMENUHOTSPOT_INTRO = 2,
+ MAINMENUHOTSPOT_LOADGAME = 3,
+ MAINMENUHOTSPOT_HOTKEYS = 4,
+ MAINMENUHOTSPOT_CREDITS = 5,
+ MAINMENUHOTSPOT_QUIT = 6,
+ MAINMENUHOTSPOT_HOTKEYSCLOSE = 7
+};
+
+enum MainMenuMasks {
+ MAINMENUMASK_BASE = 1,
+ MAINMENUMASK_HOTKEYS = 2,
+ MAINMENUMASK_EVERYWHERE = 3
+};
+
+struct MainMenuFile {
+ int menuMask;
+ int id;
+ const char *animationFile;
+ int animateOnFrame;
+};
+
+#define MAINMENU_ENTRYCOUNT 12
+static const MainMenuFile mainMenuFiles[] = {
+ { MAINMENUMASK_BASE, MAINMENUHOTSPOT_START, "STARTBUT.CAF", 0 }, // "Start" button
+ { MAINMENUMASK_BASE, MAINMENUHOTSPOT_INTRO, "INTROBUT.CAF", 0 }, // "Intro" button
+ { MAINMENUMASK_BASE, MAINMENUHOTSPOT_LOADGAME, "LOADBUT.CAF", 0 }, // "Load Game" button
+ { MAINMENUMASK_BASE, MAINMENUHOTSPOT_HOTKEYS, "HOTBUT.CAF", 0 }, // "Hot Keys" button
+ { MAINMENUMASK_BASE, MAINMENUHOTSPOT_CREDITS, "CREDBUT.CAF", 0 }, // "Credits" button
+ { MAINMENUMASK_BASE, MAINMENUHOTSPOT_QUIT, "QUITBUT.CAF", 0 }, // "Quit" button
+ { MAINMENUMASK_BASE, MAINMENUHOTSPOT_NONE, "LEGALTXT.CAF", 0 }, // Legal Text
+
+ { MAINMENUMASK_EVERYWHERE, MAINMENUHOTSPOT_NONE, "TOONGLOW.CAF", 6 }, // Clown glow
+ { MAINMENUMASK_EVERYWHERE, MAINMENUHOTSPOT_NONE, "TOONSTRK.CAF", 6 }, // Toonstruck title
+ { MAINMENUMASK_EVERYWHERE, MAINMENUHOTSPOT_NONE, "EYEGLOW.CAF", 4 }, // Clown eye glow
+ { MAINMENUMASK_EVERYWHERE, MAINMENUHOTSPOT_NONE, "PROPHEAD.CAF", 4 }, // Clown propellor head
+ { MAINMENUMASK_HOTKEYS, MAINMENUHOTSPOT_HOTKEYSCLOSE, "HOTKEYS.CAF", 0 } // Hotkeys display - clicking on it will close hotkeys
+};
+
+struct MainMenuEntry {
+ int menuMask;
+ int id;
+ Animation *animation;
+ Common::Rect rect;
+ int animateOnFrame;
+ int animateCurFrame;
+ int activeFrame;
+};
+
+bool ToonEngine::showMainmenu(bool& loadedGame) {
+ Picture *mainmenuPicture = new Picture(this);
+ mainmenuPicture->loadPicture("TITLESCR.CPS", true);
+ mainmenuPicture->setupPalette();
+
+ MainMenuEntry entries[MAINMENU_ENTRYCOUNT];
+
+ for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++) {
+ entries[entryNr].menuMask = mainMenuFiles[entryNr].menuMask;
+ entries[entryNr].id = mainMenuFiles[entryNr].id;
+ entries[entryNr].animation = new Animation(this);
+ entries[entryNr].animation->loadAnimation(mainMenuFiles[entryNr].animationFile);
+ if (entries[entryNr].id != MAINMENUHOTSPOT_NONE)
+ entries[entryNr].rect = entries[entryNr].animation->getRect();
+ entries[entryNr].animateOnFrame = mainMenuFiles[entryNr].animateOnFrame;
+ entries[entryNr].animateCurFrame = 0;
+ entries[entryNr].activeFrame = 0;
+ }
+
+ setCursor(1);
+
+ bool doExit = false;
+ bool exitGame = false;
+ int clickingOn, clickRelease;
+ int menuMask = MAINMENUMASK_BASE;
+ AudioStreamInstance *mainmenuMusic = NULL;
+ bool musicPlaying = false;
+
+ while (!doExit) {
+ clickingOn = MAINMENUHOTSPOT_NONE;
+ clickRelease = false;
+
+ if (!musicPlaying) {
+ Common::SeekableReadStream *mainmenuMusicFile = resources()->openFile("misc/BR091013.MUS");
+ mainmenuMusic = new AudioStreamInstance(_audioManager, _mixer, mainmenuMusicFile, true);
+ mainmenuMusic->play(false);
+ musicPlaying = true;
+ }
+
+ while (!clickRelease) {
+ mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+
+ for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++) {
+ if (entries[entryNr].menuMask & menuMask) {
+ if (entries[entryNr].animateOnFrame) {
+ entries[entryNr].animateCurFrame++;
+ if (entries[entryNr].animateOnFrame <= entries[entryNr].animateCurFrame) {
+ entries[entryNr].activeFrame++;
+ if (entries[entryNr].activeFrame >= entries[entryNr].animation->_numFrames)
+ entries[entryNr].activeFrame = 0;
+ entries[entryNr].animateCurFrame = 0;
+ }
+ }
+ int32 frameNr = entries[entryNr].activeFrame;
+ if ((entries[entryNr].id == clickingOn) && (clickingOn != MAINMENUHOTSPOT_NONE))
+ frameNr = 1;
+ entries[entryNr].animation->drawFrame(*_mainSurface, frameNr, 0, 0);
+ }
+ }
+
+ parseInput();
+ copyToVirtualScreen(true);
+ _system->delayMillis(17);
+
+ if (_mouseButton & 1) {
+ // left mouse button pushed down
+ clickingOn = MAINMENUHOTSPOT_NONE;
+ for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++) {
+ if (entries[entryNr].menuMask & menuMask) {
+ if (entries[entryNr].id != MAINMENUHOTSPOT_NONE) {
+ if (entries[entryNr].rect.contains(_mouseX, _mouseY))
+ clickingOn = entries[entryNr].id;
+ }
+ }
+ }
+ } else {
+ // left mouse button released/not pushed down
+ if (clickingOn != MAINMENUHOTSPOT_NONE)
+ clickRelease = true;
+ }
+ if (shouldQuit()) {
+ clickingOn = MAINMENUHOTSPOT_NONE;
+ clickRelease = true;
+ doExit = true;
+ }
+ }
+
+ if (clickingOn != MAINMENUHOTSPOT_NONE) {
+ _audioManager->playSFX(10, 128, true);
+ }
+
+ switch (clickingOn) {
+ case MAINMENUHOTSPOT_HOTKEYS:
+ menuMask = MAINMENUMASK_HOTKEYS;
+ continue;
+ case MAINMENUHOTSPOT_HOTKEYSCLOSE:
+ menuMask = MAINMENUMASK_BASE;
+ continue;
+ }
+
+ if (musicPlaying) {
+ //stop music
+ mainmenuMusic->stop(false);
+ musicPlaying = false;
+ }
+
+
+
+ switch (clickingOn) {
+ case MAINMENUHOTSPOT_START:
+ // Start game (actually exit main menu)
+ loadedGame = false;
+ doExit = true;
+ break;
+ case MAINMENUHOTSPOT_INTRO:
+ // Play intro movies
+ getMoviePlayer()->play("MISC/209_1M.SMK", 0x10);
+ getMoviePlayer()->play("MISC/209_2M.SMK", 0x10);
+ getMoviePlayer()->play("MISC/209_3M.SMK", 0x10);
+ break;
+ case MAINMENUHOTSPOT_LOADGAME:
+ doExit = loadGame(-1);
+ loadedGame = doExit;
+ exitGame = false;
+ break;
+ case MAINMENUHOTSPOT_CREDITS:
+ // Play credits movie
+ getMoviePlayer()->play("MISC/CREDITS.SMK", 0x0);
+ break;
+ case MAINMENUHOTSPOT_QUIT:
+ exitGame = true;
+ doExit = true;
+ break;
+ }
+ }
+
+ return !exitGame;
+}
+
+Common::Error ToonEngine::run() {
+
+ if (!loadToonDat())
+ return Common::kUnknownError;
+
+ g_eventRec.registerRandomSource(_rnd, "toon");
+
+ initGraphics(640, 400, true);
+ init();
+
+ // play producer intro
+ getMoviePlayer()->play("MISC/VIELOGOM.SMK", 0x10);
+
+ // show mainmenu
+ bool loadedGame = false;
+ if(!showMainmenu(loadedGame)) {
+ return Common::kNoError;
+ }
+
+ //loadScene(17);
+ //loadScene(37);
+ if (!loadedGame) {
+ newGame();
+ }
+
+// Strangerke - Commented (not used)
+// int32 oldTimer = _system->getMillis();
+ while (!shouldQuit() && _gameState->_currentScene != -1)
+ doFrame();
+ return Common::kNoError;
+}
+
+ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
+ : Engine(syst), _gameDescription(gameDescription), _language(gameDescription->language) {
+ _system = syst;
+ _tickLength = 16;
+ _currentMask = 0;
+ _currentPicture = 0;
+ _roomScaleData = 0;
+ _shadowLUT = 0;
+ _isDemo = _gameDescription->flags & ADGF_DEMO;
+
+ DebugMan.addDebugChannel(kDebugAnim, "Anim", "Animation debug level");
+ DebugMan.addDebugChannel(kDebugCharacter, "Character", "Character debug level");
+ DebugMan.addDebugChannel(kDebugAudio, "Audio", "Audio debug level");
+ DebugMan.addDebugChannel(kDebugHotspot, "Hotspot", "Hotspot debug level");
+ DebugMan.addDebugChannel(kDebugFont, "Font", "Font debug level");
+ DebugMan.addDebugChannel(kDebugPath, "Path", "Path debug level");
+ DebugMan.addDebugChannel(kDebugMovie, "Movie", "Movie debug level");
+ DebugMan.addDebugChannel(kDebugPicture, "Picture", "Picture debug level");
+ DebugMan.addDebugChannel(kDebugResource, "Resource", "Resource debug level");
+ DebugMan.addDebugChannel(kDebugState, "State", "State debug level");
+ DebugMan.addDebugChannel(kDebugTools, "Tools", "Tools debug level");
+ DebugMan.addDebugChannel(kDebugText, "Text", "Text debug level");
+
+ switch (_language) {
+ case Common::EN_GRB:
+ case Common::EN_USA:
+ case Common::EN_ANY:
+ _gameVariant = 0;
+ break;
+ case Common::FR_FRA:
+ _gameVariant = 1;
+ break;
+ case Common::DE_DEU:
+ _gameVariant = 2;
+ break;
+ case Common::RU_RUS:
+ _gameVariant = 3;
+ break;
+ case Common::ES_ESP:
+ _gameVariant = 3;
+ break;
+ default:
+ // 0 - english
+ _gameVariant = 0;
+ break;
+ }
+}
+
+ToonEngine::~ToonEngine() {
+
+}
+
+void ToonEngine::flushPalette() {
+
+ uint8 vmpalette[1024];
+ for (int32 i = 0; i < 256; i++) {
+ vmpalette[i*4+0] = _finalPalette[i*3+0];
+ vmpalette[i*4+1] = _finalPalette[i*3+1];
+ vmpalette[i*4+2] = _finalPalette[i*3+2];
+ vmpalette[i*4+3] = 0;
+ }
+ _system->setPalette(vmpalette, 0, 256);
+}
+void ToonEngine::setPaletteEntries(uint8 *palette, int32 offset, int32 num) {
+ memcpy(_finalPalette + offset * 3, palette, num * 3);
+ uint8 vmpalette[1024];
+ for (int32 i = 0; i < num; i++) {
+ vmpalette[i*4+0] = palette[i*3+0];
+ vmpalette[i*4+1] = palette[i*3+1];
+ vmpalette[i*4+2] = palette[i*3+2];
+ vmpalette[i*4+3] = 0;
+ }
+ _system->setPalette(vmpalette, offset, num);
+}
+
+void ToonEngine::simpleUpdate() {
+ updateCharacters(_tickLength);
+ updateAnimationSceneScripts(_tickLength);
+ updateTimer(getTickLength());
+ render();
+
+ if (!_audioManager->voiceStillPlaying()) {
+ _currentTextLine = 0;
+ _currentTextLineId = -1;
+ }
+ _oldTimer2 = _system->getMillis();
+ _oldTimer = _oldTimer2;
+}
+
+void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
+ // some color values are coded on 6bits ( for old 6bits DAC )
+ for (int32 i = 0; i < num * 3; i++) {
+ int32 a = palette[i];
+ a = a * 4;
+ if (a > 255)
+ a = 255;
+ palette[i] = a;
+ }
+}
+
+// adapted from KyraEngine
+void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
+
+
+ static int32 numReentrant = 0;
+ numReentrant++;
+
+// Strangerke - Commented (not used)
+// uint32 nextTime = _system->getMillis() + _tickLength;
+ const int startScript = _lastProcessedSceneScript;
+
+ _updatingSceneScriptRunFlag = true;
+
+ do {
+ if (_sceneAnimationScripts[_lastProcessedSceneScript]._lastTimer <= _system->getMillis() &&
+ !_sceneAnimationScripts[_lastProcessedSceneScript]._frozen) {
+ _animationSceneScriptRunFlag = true;
+
+ while (_animationSceneScriptRunFlag && _sceneAnimationScripts[_lastProcessedSceneScript]._lastTimer <= _system->getMillis() && !shouldQuit()) {
+ if (!_script->run(&_sceneAnimationScripts[_lastProcessedSceneScript]._state))
+ _animationSceneScriptRunFlag = false;
+
+ if (_sceneAnimationScripts[_lastProcessedSceneScript]._frozen)
+ break;
+ }
+
+ }
+
+ if (!_script->isValid(&_sceneAnimationScripts[_lastProcessedSceneScript]._state)) {
+ _script->start(&_sceneAnimationScripts[_lastProcessedSceneScript]._state, 9 + _lastProcessedSceneScript);
+ _animationSceneScriptRunFlag = false;
+ }
+
+ ++_lastProcessedSceneScript;
+ if (_lastProcessedSceneScript >= state()->_locations[state()->_currentScene]._numSceneAnimations)
+ _lastProcessedSceneScript = 0;
+
+ } while (_lastProcessedSceneScript != startScript && !shouldQuit());
+
+
+ _updatingSceneScriptRunFlag = false;
+ numReentrant--;
+
+}
+
+void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
+ char temp[256];
+ char temp2[256];
+
+
+ _firstFrame = true;
+
+ _gameState->_lastVisitedScene = _gameState->_currentScene;
+ _gameState->_currentScene = SceneId;
+
+ _saveBufferStream->seek(0);
+
+ if (SceneId == -1) {
+ // this scene -1 is loaded at the very end of the game
+ getAudioManager()->stopMusic();
+ getMoviePlayer()->play("CREDITS.SMK");
+ return;
+ }
+
+ // find out in what chapter we are (the script function ProcessToNextChapter is actually not called )
+ // the location flag has the chapter info in it
+ int32 flag = _gameState->_locations[SceneId]._flags;
+ if (flag) {
+ _gameState->_currentChapter = 0;
+ do {
+ _gameState->_currentChapter++;
+ flag >>= 1;
+ } while((flag & 1) == 0);
+ }
+
+ for (int32 i = 0; i < 8; i++) {
+ if (_characters[i]) _characters[i]->setFlag(0);
+ }
+ _drew->playStandingAnim();
+ _drew->setVisible(true);
+
+ // hide flux in chapter 2
+ if ( _gameState->_currentChapter == 1) {
+ _flux->playStandingAnim();
+ _flux->setVisible(true);
+ } else {
+ _flux->setVisible(false);
+ }
+
+ _lastMouseButton = 0;
+ _mouseButton = 0;
+ _currentHotspotItem = -1;
+ _gameState->_sackVisible = true;
+ _gameState->_inCloseUp = false;
+ _gameState->_inConversation = false;
+ _gameState->_inInventory = false;
+ _gameState->_inCutaway = false;
+ _gameState->_currentScrollValue = 0;
+ _gameState->_currentScrollLock = false;
+ _gameState->_inCloseUp = false;
+
+
+ if (_gameState->_mouseState >= 0)
+ addItemToInventory(_gameState->_mouseState);
+
+ _gameState->_mouseState = -1;
+
+
+ // load package
+ strcpy(temp, createRoomFilename(Common::String::printf("%s.pak", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
+ resources()->openPackage(temp, true);
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".npp");
+ loadAdditionalPalette(temp, 0);
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".np2");
+ loadAdditionalPalette(temp, 1);
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".cup");
+ loadAdditionalPalette(temp, 2);
+
+ // load artwork
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".cps");
+ _currentPicture = new Picture(this);
+ _currentPicture->loadPicture(temp);
+ _currentPicture->setupPalette();
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".msc");
+ _currentMask = new Picture(this);
+ if (_currentMask->loadPicture(temp))
+ _pathFinding->init(_currentMask);
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".tre");
+ _roomTexts = new TextResource(this);
+ _roomTexts->loadTextResource(temp);
+
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".dat");
+ uint32 fileSize;
+ uint8 *sceneData = resources()->getFileData(temp, &fileSize);
+ if (sceneData) {
+ _roomScaleData = new uint8[fileSize];
+ memcpy(_roomScaleData, sceneData, fileSize);
+ }
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".svi");
+ strcpy(temp2, createRoomFilename(Common::String::printf("%s.svl", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
+ _audioManager->loadAudioPack(1, temp, temp2);
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcpy(temp2, state()->_locations[SceneId]._name);
+ strcat(temp, ".sei");
+ strcat(temp2, ".sel");
+ _audioManager->loadAudioPack(3, temp, temp2);
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".ric");
+ if (state()->_locations[SceneId]._flags & 0x40) {
+ strcpy(temp2, state()->_locations[SceneId]._cutaway);
+ strcat(temp2, ".ric");
+ } else {
+ strcpy(temp2, "");
+ }
+ _hotspots->LoadRif(temp, temp2);
+ restoreRifFlags(_gameState->_currentScene);
+
+
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".cnv");
+ uint32 convfileSize;
+ uint8 *convData = resources()->getFileData(temp, &convfileSize);
+ if (convData) {
+ assert(convfileSize < 4096 * sizeof(int16));
+ memcpy(_conversationData , convData, convfileSize);
+ prepareConversations();
+ }
+
+ // load script
+ strcpy(temp, state()->_locations[SceneId]._name);
+ strcat(temp, ".emc");
+
+ _oldTimer = _system->getMillis();
+ _oldTimer2 = _oldTimer;
+
+ // fix the weird scaling issue during one frame when entering new scene
+ _drew->update(0);
+ _flux->update(0);
+
+
+ _script->load(temp, &_scriptData, &_script_func->_opcodes);
+ _script->init(&_scriptState[0], &_scriptData);
+ _script->init(&_scriptState[1], &_scriptData);
+ _script->init(&_scriptState[2], &_scriptData);
+ _script->init(&_scriptState[3], &_scriptData);
+
+ //_script->RoomScript->Decompile("decomp.txt");
+ //RoomScript->Decompile2("decomp2.txt");
+
+ for (int i = 0; i < state()->_locations[SceneId]._numSceneAnimations; i++) {
+ _sceneAnimationScripts[i]._data = &_scriptData;
+ _script->init(&_sceneAnimationScripts[i]._state, _sceneAnimationScripts[i]._data);
+ if (!forGameLoad) {
+ _script->start(&_sceneAnimationScripts[i]._state, 9 + i);
+ _sceneAnimationScripts[i]._lastTimer = getSystem()->getMillis();
+ _sceneAnimationScripts[i]._frozen = false;
+ }
+ }
+
+ // launch mus
+#if 0
+ SoundManager.StopMusic();
+ SoundManager.UnloadMusic();
+ SoundManager.LoadMusic(GameLocations[Scene].name, GameLocations[Scene].mus);
+ SoundManager.PlayMusic();
+#endif
+
+ _audioManager->playMusic(_gameState->_locations[SceneId]._name, _gameState->_locations[SceneId]._music);
+
+ _lastProcessedSceneScript = 0;
+ _gameState->_locations[SceneId]._visited = true;
+
+
+ setupGeneralPalette();
+ createShadowLUT();
+
+
+
+ if (!forGameLoad) {
+
+ _script->start(&_scriptState[0], 0);
+
+ while (_script->run(&_scriptState[0]))
+ ;
+
+ _script->start(&_scriptState[0], 8);
+
+ while (_script->run(&_scriptState[0]))
+ ;
+
+ if (_gameState->_nextSpecialEnterX != -1 && _gameState->_nextSpecialEnterY != -1) {
+ _drew->setPosition(_gameState->_nextSpecialEnterX, _gameState->_nextSpecialEnterY);
+ _gameState->_nextSpecialEnterX = -1;
+ _gameState->_nextSpecialEnterY = -1;
+ }
+
+ _script->start(&_scriptState[0], 3);
+
+ while (_script->run(&_scriptState[0]))
+ ;
+
+ _script->start(&_scriptState[0], 4);
+
+ while (_script->run(&_scriptState[0]))
+ ;
+
+ }
+
+ state()->_mouseHidden = false;
+}
+
+void ToonEngine::setupGeneralPalette() {
+ setPaletteEntries(_additionalPalette1, 232, 23);
+ setPaletteEntries(_universalPalette, 200, 32);
+ setPaletteEntries(_fluxPalette, 192, 8);
+
+ if (_drew)
+ _drew->setupPalette();
+}
+
+void ToonEngine::loadAdditionalPalette(Common::String fileName, int32 mode) {
+
+ uint32 size = 0;
+ uint8 *palette = resources()->getFileData(fileName, &size);
+ if (!palette)
+ return;
+
+ switch (mode) {
+ case 0:
+ memcpy(_additionalPalette1, palette, 69);
+ fixPaletteEntries(_additionalPalette1, 23);
+ break;
+ case 1:
+ memcpy(_additionalPalette2, palette, 69);
+ fixPaletteEntries(_additionalPalette2, 23);
+ break;
+ case 2:
+ memcpy(_cutawayPalette, palette, 768);
+ fixPaletteEntries(_cutawayPalette, 256);
+ break;
+ case 3:
+ memcpy(_universalPalette, palette, 96);
+ fixPaletteEntries(_universalPalette, 32);
+ break;
+ case 4:
+ memcpy(_fluxPalette, palette, 24);
+ fixPaletteEntries(_fluxPalette , 8);
+ break;
+ default:
+ warning("loadAdditionalPalette() - Unknown mode");
+ }
+}
+
+void ToonEngine::initChapter() {
+
+ EMCData data;
+ EMCState status;
+ memset(&data, 0, sizeof(data));
+ memset(&status, 0, sizeof(status));
+
+ _script = new EMCInterpreter(this);
+
+ _script->load("_START01.EMC", &data, &_script_func->_opcodes);
+ _script->init(&status, &data);
+ _script->start(&status, 0);
+ while (_script->run(&status))
+ ;
+
+ setupGeneralPalette();
+
+}
+
+void ToonEngine::loadCursor() {
+ _cursorAnimation = new Animation(this);
+ _cursorAnimation->loadAnimation("MOUSE.CAF");
+ _cursorAnimationInstance = _animationManager->createNewInstance(kAnimationCursor);
+ _cursorAnimationInstance->setAnimation(_cursorAnimation);
+ _cursorAnimationInstance->setVisible(true);
+ _cursorAnimationInstance->setFrame(0);
+ _cursorAnimationInstance->setAnimationRange(0, 0);
+ _cursorAnimationInstance->setFps(8);
+
+ setCursor(5);
+}
+
+void ToonEngine::setCursor(int32 type, bool inventory, int32 offsetX, int32 offsetY) {
+
+ static int32 offsets[] = {
+ 0, 1, 1, 6, 7, 1, 8, 10, 18, 10,
+ 28, 8, 36, 10, 46, 10, 56, 10, 66, 10,
+ 76, 10, 86, 10, 96, 10, 106, 10, 116, 10,
+ 126, 10
+ };
+
+ if (!inventory) {
+ _cursorAnimationInstance->setAnimation(_cursorAnimation);
+ _cursorAnimationInstance->setAnimationRange(offsets[type * 2 + 0], offsets[type * 2 + 0] + offsets[type * 2 + 1] - 1);
+ _cursorAnimationInstance->playAnimation();
+ } else {
+ _cursorAnimationInstance->setAnimation(_inventoryIcons);
+ _cursorAnimationInstance->setAnimationRange(type, type);
+ _cursorAnimationInstance->playAnimation();
+ }
+
+ _cursorOffsetX = offsetX;
+ _cursorOffsetY = offsetY;
+}
+
+void ToonEngine::setSceneAnimationScriptUpdate(bool enable) {
+ _animationSceneScriptRunFlag = enable;
+}
+
+bool ToonEngine::isUpdatingSceneAnimation() {
+ return _updatingSceneScriptRunFlag;
+}
+
+int32 ToonEngine::getCurrentUpdatingSceneAnimation() {
+ return _lastProcessedSceneScript;
+}
+
+int32 ToonEngine::randRange(int32 minStart, int32 maxStart) {
+ return _rnd.getRandomNumberRng(minStart, maxStart);
+}
+
+int32 ToonEngine::runEventScript(int32 x, int32 y, int32 mode, int32 id, int32 scriptId) {
+
+ assert(_currentScriptRegion < 4);
+
+ EMCState *status = &_scriptState[_currentScriptRegion];
+ _script->init(status, &_scriptData);
+
+ // setup registers
+ status->regs[0] = x;
+ status->regs[1] = y;
+ status->regs[2] = 0;
+ status->regs[3] = 0;
+ status->regs[4] = _gameState->_mouseState; //
+ status->regs[5] = 0;
+ status->regs[6] = scriptId;
+ status->regs[7] = mode;
+ status->regs[8] = id;
+
+ _currentScriptRegion++;
+
+ _script->start(status, 1);
+ while (_script->run(status))
+ ;
+
+ _currentScriptRegion--;
+
+ return status->regs[2];
+}
+
+void ToonEngine::clickEvent() {
+ bool leftButton = false;
+ bool rightButton = false;
+
+ if ((_lastMouseButton & 0x1) == 1 && (_mouseButton & 0x1) == 0)
+ leftButton = true;
+ if ((_lastMouseButton & 0x2) == 2 && (_mouseButton & 0x2) == 0)
+ rightButton = true;
+
+ _lastMouseButton = _mouseButton;
+ if (!leftButton && !rightButton)
+ return;
+
+ if (_gameState->_sackVisible) {
+ if (_mouseX > 0 && _mouseX < 40 && _mouseY > 356 && _mouseY < 396) {
+ showInventory();
+ return;
+ }
+ }
+
+ // with inventory
+ if (rightButton && _gameState->_mouseState >= 0) {
+ addItemToInventory(_gameState->_mouseState);
+ setCursor(0, false, 0, 0);
+ _currentHotspotItem = -1;
+ return;
+ }
+
+
+ int32 mouseX = _mouseX;
+ if (_gameState->_inCutaway) {
+ mouseX += 1280;
+ }
+
+ // find hotspot
+ int32 hot = _hotspots->Find(mouseX + state()->_currentScrollValue , _mouseY);
+ HotspotData *currentHot = 0;
+ if (hot > -1) {
+ currentHot = _hotspots->Get(hot);
+ }
+
+ if (_currentHotspotItem == -3) {
+ if (_gameState->_mouseState <= 0) {
+ if (leftButton)
+ createMouseItem(104);
+ else
+ characterTalk(518);
+ }
+ }
+ if (_currentHotspotItem == -4) {
+ if (_gameState->_mouseState >= 0) {
+ if (leftButton)
+ handleInventoryOnInventory(0, _gameState->_mouseState);
+ return;
+ }
+ }
+
+
+ if (!currentHot) {
+ int32 xx, yy;
+
+ if (_gameState->_inCutaway || _gameState->_inInventory || _gameState->_inCloseUp)
+ return;
+
+ if (_pathFinding->findClosestWalkingPoint(_mouseX + _gameState->_currentScrollValue , _mouseY, &xx, &yy))
+ _drew->walkTo(xx, yy);
+ return;
+ }
+
+ int commandId = 0;
+ if (_gameState->_mouseState < 0) {
+ // left or right click
+ if (rightButton)
+ commandId = 2 + 8;
+ else
+ commandId = 0 + 8;
+ } else {
+ commandId = 2 * (_gameState->_mouseState - 1) + 16;
+ }
+
+
+ int16 command = currentHot->getData(commandId);
+ int16 argument = currentHot->getData(commandId + 1);
+ int16 priority = currentHot->getPriority();
+// Strangerke - Commented (not used)
+// int16 ref = currentHot->getRef();
+// int16 pad1 = currentHot->getData(6);
+
+ if (!_gameState->_inCutaway && !_gameState->_inCloseUp) {
+ if (leftButton && (currentHot->getData(4) != 2 || _gameState->_mouseState >= 0) && currentHot->getData(5) != -1) {
+ if (currentHot->getData(5)) {
+ if (!_drew->walkTo(currentHot->getData(5), currentHot->getData(6))) {
+ // walk was canceled ?
+ return;
+ }
+ }
+ else {
+ if (!_drew->walkTo(_mouseX, _mouseY)) {
+ // walk was canceled ?
+ return;
+ }
+ }
+ }
+ }
+
+ int32 result = 0;
+
+ switch (command) {
+ case 1:
+ sayLines(1, argument);
+ break;
+ case 2:
+ result = runEventScript(_mouseX, _mouseY, command, argument, priority);
+ break;
+ case 3:
+ runEventScript(_mouseX, _mouseY, command, argument, priority);
+ result = 0;
+ break;
+ case 4:
+ playSFX(argument, 128);
+ break;
+ case 5:
+ break;
+ case 6:
+ createMouseItem(argument);
+ currentHot->setData(7,-1);
+ break;
+ case 7:
+ // switch to CloseUp
+// Strangerke - Commented (not used)
+// int closeup = 1;
+ break;
+ case 8:
+ // face flux
+ sayLines(1, argument);
+ break;
+ case 9:
+ case 10:
+// Strangerke - Commented (not used)
+// if (rand() % 1 == 1) {
+// } else {
+// }
+ // setFluxFacingPoint(x,y)
+ sayLines(2, argument);
+ break;
+ case 11:
+ sayLines(3, argument);
+ break;
+ }
+
+ if (result == 3) {
+ int32 val = _scriptState[_currentScriptRegion].regs[4];
+ currentHot->setData(4, currentHot->getData(4) & val);
+ }
+ if (result == 2 || result == 3) {
+ int32 val = _scriptState[_currentScriptRegion].regs[6];
+ currentHot->setData(7, val);
+ }
+
+ if (result == 1) {
+ int32 val = _scriptState[_currentScriptRegion].regs[4];
+ currentHot->setData(4, currentHot->getData(4) & val);
+ }
+
+}
+
+void ToonEngine::selectHotspot() {
+ int32 x1 = 0;
+ int32 x2 = 0;
+ int32 y1 = 0;
+ int32 y2 = 0;
+
+ int32 mouseX = _mouseX;
+
+ if (_gameState->_inCutaway)
+ mouseX += 1280;
+
+ if (_gameState->_sackVisible) {
+ if (_mouseX > 0 && _mouseX < 40 && _mouseY > 356 && _mouseY < 396) {
+ _currentHotspotItem = -2;
+
+ if (_gameState->_mouseState < 0) {
+ int mode = 3;
+ setCursor(mode);
+ } else {
+ setCursor(_gameState->_mouseState, true, -18, -14);
+ }
+
+ return;
+ }
+ }
+
+ if (_gameState->_mouseState > 0) {
+ // picked drew?
+ getDrew()->getAnimationInstance()->getRect(&x1, &y1, &x2, &y2);
+ if (_mouseX + _gameState->_currentScrollValue >= x1 && _mouseX + _gameState->_currentScrollValue <= x2 && _mouseY >= y1 && _mouseY <= y2) {
+ _currentHotspotItem = -4;
+ return;
+ }
+ }
+
+ if (getFlux()->getVisible()) {
+ getFlux()->getAnimationInstance()->getRect(&x1, &y1, &x2, &y2);
+ if (_mouseX + _gameState->_currentScrollValue >= x1 && _mouseX + _gameState->_currentScrollValue <= x2 && _mouseY >= y1 && _mouseY <= y2) {
+ _currentHotspotItem = -3;
+
+ if (_gameState->_mouseState < 0) {
+ int mode = 3;
+ setCursor(mode);
+ } else {
+ setCursor(_gameState->_mouseState, true, -18, -14);
+ }
+
+ return;
+ }
+ }
+
+ int32 hot = _hotspots->Find(mouseX + state()->_currentScrollValue, _mouseY);
+ if (hot != -1) {
+ HotspotData *hotspot = _hotspots->Get(hot);
+ int32 item = hotspot->getData(14);
+ if (hotspot->getType() == 3)
+ item += 2000;
+
+ // update palette based on ticks if we're in "use from inventory mode"
+ if (_gameState->_mouseState >= 0) {
+
+ int32 tick = _system->getMillis() / _tickLength;
+ int32 animReverse = tick & 0x10;
+ int32 animStep = tick & 0xf;
+
+ byte color[3];
+ if (animReverse == 0) {
+ color[0] = 16 * animStep;
+ color[1] = 0;
+ color[2] = 0;
+ } else {
+ color[0] = 16 * (15 - animStep);
+ color[1] = 0;
+ color[2] = 0;
+ }
+ setPaletteEntries(color, 255, 1);
+ }
+
+#if 0
+ if (item == _currentHotspotItem)
+ return;
+#endif
+ _currentHotspotItem = item;
+ if (_gameState->_mouseState < 0) {
+ int mode = hotspot->getMode();
+ setCursor(mode);
+ } else {
+ setCursor(_gameState->_mouseState, true, -18, -14);
+ }
+ } else {
+ _currentHotspotItem = 0;
+
+ if (_gameState->_mouseState < 0) {
+ setCursor(0);
+ } else {
+ byte color[3];
+ color[0] = 0;
+ color[1] = 0;
+ color[2] = 0;
+ setCursor(_gameState->_mouseState, true, -18, -14);
+ setPaletteEntries(color, 255, 1);
+ }
+ }
+}
+
+void ToonEngine::exitScene() {
+
+ fadeOut(5);
+
+ // disable all scene animation
+ for (int32 i = 0; i < 64; i++) {
+ if (_sceneAnimations[i]._active) {
+ delete _sceneAnimations[i]._animation;
+ _sceneAnimations[i]._active = false;
+ _animationManager->removeInstance(_sceneAnimations[i]._animInstance);
+ _sceneAnimations[i]._animInstance = 0;
+ _sceneAnimations[i]._animation = 0;
+ }
+ }
+ for (int32 i = 0; i < 64; i++) {
+ _sceneAnimationScripts[i]._frozen = true;
+ _sceneAnimationScripts[i]._active = false;
+ }
+
+ // remove all characters except drew and flux
+ for (int32 i = 0; i < 8; i++) {
+ if (_characters[i] != _drew && _characters[i] != _flux) {
+ if (_characters[i]) {
+ delete _characters[i];
+ _characters[i] = 0;
+ }
+ }
+ else {
+ _characters[i]->stopSpecialAnim();
+ }
+ }
+
+ for (int32 i = 0; i < 2; i++) {
+ _gameState->_timerEnabled[i] = false;
+ }
+
+ // put back our item if inventory if needed
+ if (_gameState->_mouseState >= 0) {
+ addItemToInventory(_gameState->_mouseState);
+ _gameState->_mouseState = -1;
+ }
+
+ char temp[256];
+ strcpy(temp, createRoomFilename(Common::String::printf("%s.pak", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
+ resources()->closePackage(temp);
+
+ _drew->stopWalk();
+ _flux->stopWalk();
+
+ storeRifFlags(_gameState->_currentScene);
+}
+
+// flip between the cutaway scene and the normal scene
+void ToonEngine::flipScreens() {
+ _gameState->_inCloseUp = !_gameState->_inCloseUp;
+
+ if (_gameState->_inCloseUp) {
+ _gameState->_currentScrollValue = 640;
+ setPaletteEntries(_cutawayPalette, 1, 128);
+ setPaletteEntries(_additionalPalette2, 232, 23);
+ } else {
+ _gameState->_currentScrollValue = 0;
+ _currentPicture->setupPalette();
+ setupGeneralPalette();
+ }
+ flushPalette();
+}
+
+void ToonEngine::fadeIn(int32 numFrames) {
+ for (int32 f = 0; f < numFrames; f++) {
+
+ uint8 vmpalette[1024];
+ for (int32 i = 0; i < 256; i++) {
+ vmpalette[i*4+0] = f * _finalPalette[i*3+0] / (numFrames - 1);
+ vmpalette[i*4+1] = f * _finalPalette[i*3+1] / (numFrames - 1);
+ vmpalette[i*4+2] = f * _finalPalette[i*3+2] / (numFrames - 1);
+ vmpalette[i*4+3] = 0;
+ }
+ _system->setPalette(vmpalette, 0, 256);
+ _system->updateScreen();
+ _system->delayMillis(_tickLength);;
+ }
+}
+
+void ToonEngine::fadeOut(int32 numFrames) {
+ for (int32 f = 0; f < numFrames; f++) {
+
+ uint8 vmpalette[1024];
+ for (int32 i = 0; i < 256; i++) {
+ vmpalette[i*4+0] = (numFrames - f - 1) * _finalPalette[i*3+0] / (numFrames - 1);
+ vmpalette[i*4+1] = (numFrames - f - 1) * _finalPalette[i*3+1] / (numFrames - 1);
+ vmpalette[i*4+2] = (numFrames - f - 1) * _finalPalette[i*3+2] / (numFrames - 1);
+ vmpalette[i*4+3] = (numFrames - f - 1);
+ }
+ _system->setPalette(vmpalette, 0, 256);
+ _system->updateScreen();
+ _system->delayMillis(_tickLength);;
+ }
+}
+
+void ToonEngine::initFonts() {
+ _fontRenderer = new FontRenderer(this);
+ _fontToon = new Animation(this);
+ _fontToon->loadAnimation("misc/toonfont.caf");
+
+ _fontEZ = new Animation(this);
+ _fontEZ->loadAnimation("misc/ezfont.caf");
+}
+
+void ToonEngine::drawInfoLine() {
+ if (_currentHotspotItem != 0 && !_gameState->_mouseHidden && !_gameState->_inConversation) {
+ const char *infoTool = NULL;
+ if (_currentHotspotItem >= 0 && _currentHotspotItem < 2000) {
+ infoTool = _roomTexts->getText(_currentHotspotItem);
+ } else if (_currentHotspotItem <= -1) {
+// static char *specialInfoLine[] = { "Exit non defined", "Bottomless Bag", "Flux", "Drew Blanc" };
+ infoTool = _specialInfoLine[-1-_currentHotspotItem ];
+ } else {
+ int32 loc = _currentHotspotItem - 2000;
+ // location names are hardcoded ...
+ infoTool = getLocationString(loc, _gameState->_locations[loc]._visited);
+ }
+ if (infoTool) {
+ _fontRenderer->setFontColor(0xc8, 0xdd, 0xe3);
+ _fontRenderer->setFont(_fontToon);
+ _fontRenderer->renderText(320 + _gameState->_currentScrollValue, 398, infoTool, 5);
+ }
+ }
+}
+
+const char *ToonEngine::getLocationString(int32 locationId, bool alreadyVisited) {
+ if (alreadyVisited)
+ return _locationDirVisited[locationId];
+ else
+ return _locationDirNotVisited[locationId];
+}
+
+int32 ToonEngine::getScaleAtPoint(int32 x, int32 y) {
+ if (!_currentMask)
+ return 1024;
+
+ int32 maskData = _currentMask->getData(x, y) & 0x1f;
+ return _roomScaleData[maskData+2] * 1024 / 100;
+}
+
+int32 ToonEngine::getLayerAtPoint(int32 x, int32 y) {
+ if (!_currentMask)
+ return 0;
+
+ int32 maskData = _currentMask->getData(x, y) & 0x1f;
+ return _roomScaleData[maskData+130] << 5;
+}
+
+int32 ToonEngine::getZAtPoint(int32 x, int32 y) {
+ if (!_currentMask)
+ return 0;
+ return _currentMask->getData(x, y) & 0x1f;
+}
+
+void ToonEngine::storeRifFlags(int32 location) {
+
+ if (_gameState->_locations[location]._numRifBoxes != _hotspots->getCount()) {
+ _gameState->_locations[location]._numRifBoxes = _hotspots->getCount();
+ }
+
+ for (int32 i = 0; i < _hotspots->getCount(); i++) {
+ _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0] = _hotspots->Get(i)->getData(4);
+ _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1] = _hotspots->Get(i)->getData(7);
+ }
+}
+
+void ToonEngine::restoreRifFlags(int32 location) {
+ if (_hotspots) {
+ if (!_gameState->_locations[location]._visited) {
+ for (int32 i = 0; i < _hotspots->getCount(); i++) {
+ _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0] = _hotspots->Get(i)->getData(4);
+ _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1] = _hotspots->Get(i)->getData(7);
+ }
+ _gameState->_locations[location]._numRifBoxes = _hotspots->getCount();
+ } else {
+ if (_gameState->_locations[location]._numRifBoxes != _hotspots->getCount())
+ return;
+
+ for (int32 i = 0; i < _hotspots->getCount(); i++) {
+ _hotspots->Get(i)->setData(4, _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0]);
+ _hotspots->Get(i)->setData(7, _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1]);
+ }
+ }
+ }
+}
+
+void ToonEngine::sayLines(int numLines, int dialogId) {
+ // exit conversation state
+
+ // if (inInventory)
+ // character_talks(dialogid, -1, 0, 0);
+ // else
+
+#if 0
+ int oldShowMouse = 0;
+
+ if (Game.MouseHiddenCount <= 0) {
+ Game.MouseHiddenCount = 1;
+ oldShowMouse = 1;
+ }
+#endif
+
+ int32 currentLine = dialogId;
+
+ for (int32 i = 0; i < numLines; i++) {
+ if (!characterTalk(currentLine))
+ break;
+
+ while (_audioManager->voiceStillPlaying() && !shouldQuit())
+ doFrame();
+
+ // find next line
+ if (currentLine < 1000)
+ currentLine = _roomTexts->getNext(currentLine);
+ else
+ currentLine = _genericTexts->getNext(currentLine-1000) + 1000;
+ }
+
+#if 0
+ if (oldShowMouse)
+ Game.MouseHiddenCount = 0;
+#endif
+
+}
+
+int32 ToonEngine::simpleCharacterTalk(int32 dialogid) {
+ int32 myId = 0;
+
+// Strangerke - Commented (not used)
+#if 0
+ char *myLine;
+ if (dialogid < 1000) {
+ myLine = _roomTexts->getText(dialogid);
+ myId = dialogid;
+ } else {
+ myLine = _genericTexts->getText(dialogid - 1000);
+ myId = dialogid - 1000;
+ }
+ debugC(0, 0xfff, "Talker = %d will say '%s' \n", READ_LE_UINT16(c-2), myLine);
+#endif
+
+ if (_audioManager->voiceStillPlaying())
+ _audioManager->stopCurrentVoice();
+
+ if (dialogid < 1000) {
+ myId = _roomTexts->getId(dialogid);
+ _audioManager->playVoice(myId, false);
+ } else {
+ myId = _genericTexts->getId(dialogid - 1000);
+ _audioManager->playVoice(myId, true);
+ }
+
+ return 1;
+}
+
+void ToonEngine::playTalkAnimOnCharacter(int32 animID, int32 characterId, bool talker) {
+ if (animID || talker) {
+// Strangerke - Commented (not used)
+#if 0
+ if (_gameState->_inCutaway || _gameState->_inInventory) {
+ if (talker) {
+ // character talks
+ }
+ } else
+#endif
+ if (characterId == 0) {
+ _drew->playAnim(animID, 0, (talker ? 8 : 0) + 2);
+ } else if (characterId == 1) {
+ // stop flux if he is walking
+ if(_flux->getFlag() & 1) {
+ _flux->stopWalk();
+ }
+ _flux->playAnim(animID, 0, (talker ? 8 : 0) + 2);
+ _flux->setFlag( _flux->getFlag() | 1 );
+ } else {
+ Character *character = getCharacterById(characterId);
+ if (character) {
+ character->playAnim(animID, 0, (talker ? 8 : 0) + 2);
+ }
+ }
+ } else {
+ Character *character = getCharacterById(characterId);
+ if (character)
+ character->setAnimFlag(character->getAnimFlag() | 1);
+ }
+}
+
+int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
+ if(blocking == false && _audioManager->voiceStillPlaying()) {
+ // someone is already talking, and this voice is not important
+ // skip it
+ return 0;
+ }
+
+ int32 myId = 0;
+ char *myLine;
+ if (dialogid < 1000) {
+ myLine = _roomTexts->getText(dialogid);
+ myId = dialogid;
+ } else {
+ myLine = _genericTexts->getText(dialogid - 1000);
+ myId = dialogid - 1000;
+ }
+
+ if (!myLine)
+ return 0;
+
+ bool oldMouseHidden = _gameState->_mouseHidden;
+ if (blocking) {
+ _gameState->_mouseHidden = true;
+ }
+
+
+ // get what is before the string
+ int a = READ_LE_UINT16(myLine - 2);
+ char *b = myLine - 2 - 4 * a;
+
+ char *c = b - 2; // v6
+ int numParticipants = READ_LE_UINT16(c); // num dialogue participants
+
+ char *e = c - 2 - 4 * numParticipants;
+ READ_LE_UINT16(e);
+
+// Strangerke - Commented (not used)
+// char *g = e - 2 * f;
+
+ // flag as talking
+// Strangerke - Commented (not used)
+// char *h = c;
+
+
+ // if one voice is still playing, wait !
+ if (blocking) {
+ while (_audioManager->voiceStillPlaying() && !shouldQuit())
+ doFrame();
+
+ char *cc = c;
+ Character *waitChar;
+ for (int32 i = 0; i < numParticipants - 1; i++) {
+ // listener
+ int32 listenerId = READ_LE_UINT16(cc - 2);
+ cc -= 4;
+ waitChar = getCharacterById(listenerId);
+ if (waitChar) {
+ while ((waitChar->getAnimFlag() & 0x10) == 0x10 && !shouldQuit())
+ doFrame();
+ }
+
+ }
+ int32 talkerId = READ_LE_UINT16(cc - 2);
+
+ waitChar = getCharacterById(talkerId);
+ if (waitChar && !_gameState->_inInventory) {
+ while ((waitChar->getAnimFlag() & 0x10) == 0x10 && !shouldQuit())
+ doFrame();
+ }
+ } else {
+ if (_audioManager->voiceStillPlaying())
+ _audioManager->stopCurrentVoice();
+ }
+
+ for (int32 i = 0; i < numParticipants - 1; i++) {
+ // listener
+ int32 listenerId = READ_LE_UINT16(c - 2);
+ int32 listenerAnimId = READ_LE_UINT16(c - 4);
+ if (blocking) playTalkAnimOnCharacter(listenerAnimId, listenerId, false);
+ c -= 4;
+ }
+
+ int32 talkerId = READ_LE_UINT16(c - 2);
+ int32 talkerAnimId = READ_LE_UINT16(c - 4);
+
+ _currentTextLine = myLine;
+ _currentTextLineCharacterId = talkerId;
+ _currentTextLineId = dialogid;
+
+ if (blocking) {
+ playTalkAnimOnCharacter(talkerAnimId, talkerId, true);
+ } else {
+ Character *character = getCharacterById(talkerId);
+ if (character)
+ character->stopSpecialAnim();
+ }
+
+ debugC(0, 0xfff, "Talker = %d (num participants : %d) will say '%s'", talkerId , numParticipants, myLine);
+
+
+ getTextPosition(talkerId, &_currentTextLineX, &_currentTextLineY);
+
+ if (dialogid < 1000) {
+ myId = _roomTexts->getId(dialogid);
+ _audioManager->playVoice(myId, false);
+ } else {
+ myId = _genericTexts->getId(dialogid - 1000);
+ _audioManager->playVoice(myId, true);
+ }
+
+ if (blocking) {
+ while (_audioManager->voiceStillPlaying() && !shouldQuit())
+ doFrame();
+ _gameState->_mouseHidden = oldMouseHidden && _gameState->_mouseHidden;
+ }
+
+
+ return 1;
+}
+
+void ToonEngine::haveAConversation(int32 convId) {
+ setCursor(0);
+
+ _gameState->_inConversation = true;
+ _gameState->_showConversationIcons = false;
+ _gameState->_exitConversation = false;
+ _gameState->_sackVisible = false;
+
+ // in conversation = 12
+ // exit conversation state = 0
+ Conversation *conv = &state()->_conversationState[convId];
+ _gameState->_currentConversationId = convId;
+ if (conv->_enable) {
+ // fix dialog script based on new flags
+ for (int32 i = 0; i < 10; i++) {
+ if (conv->state[i]._data2 == 1 || conv->state[i]._data2 == 3) {
+ if (getConversationFlag(_gameState->_currentScene, conv->state[i]._data3))
+ conv->state[i]._data2 = 1;
+ else
+ conv->state[i]._data2 = 3;
+ }
+ }
+
+ // if current voice stream sub 15130
+ processConversationClick(conv , 2);
+ doFrame();
+ }
+
+
+ _mouseButton = 0;
+ _gameState->_firstConverstationLine = true;
+
+ while (!_gameState->_exitConversation && !shouldQuit()) {
+ _gameState->_mouseHidden = false;
+ _gameState->_showConversationIcons = true;
+ int32 oldMouseButton = _mouseButton;
+ while (!shouldQuit()) {
+ doFrame();
+
+ if (_mouseButton != 0) {
+ if (!oldMouseButton)
+ break;
+ } else {
+ oldMouseButton = 0;
+ }
+ }
+ int selected = -1;
+ int a = 0;
+ for (int i = 0; i < 10; i++) {
+ if (conv->state[i]._data2 == 1) {
+ if (_mouseX > 50 + a * 60 && _mouseX < 100 + a * 60 && _mouseY >= 336 && _mouseY <= 386) {
+ selected = i;
+ break;
+ }
+ a++;
+ }
+ }
+ if(shouldQuit()) return;
+ _gameState->_showConversationIcons = false;
+ _gameState->_mouseHidden = 1;
+
+
+ if (selected < 0 || selected == 1 || selected == 3) {
+ if (_gameState->_firstConverstationLine)
+ processConversationClick(conv, 3);
+ else
+ processConversationClick(conv, 1);
+ break;
+ } else {
+ processConversationClick(conv, selected);
+ }
+ }
+
+// Strangerke - Commented (not used)
+// int cur = 0;
+
+ for (int i = 0; i < 10; i++) {
+ if (conv->state[i]._data2 == 2) {
+ if (i != 3)
+ conv->state[i]._data2 = 1;
+ }
+ }
+
+ _gameState->_exitConversation = false;
+ _gameState->_inConversation = false;
+ _gameState->_currentConversationId = -1;
+ _gameState->_mouseHidden = false;
+ _gameState->_sackVisible = true;
+
+}
+
+void ToonEngine::drawConversationIcons() {
+ if (!_gameState->_inConversation || !_gameState->_showConversationIcons)
+ return;
+ int32 aa = 50 + _gameState->_currentScrollValue;
+ for (int32 i = 0; i < 10; i++) {
+ if (_gameState->_conversationState[_gameState->_currentConversationId].state[i]._data2 == 1) {
+ _dialogIcons->drawFrame(*_mainSurface, (i + _gameState->_currentScene) & 7, aa, 336);
+ _dialogIcons->drawFrame(*_mainSurface, 7 + _gameState->_conversationState[_gameState->_currentConversationId].state[i]._data3, aa, 339);
+ aa += 60;
+ }
+ }
+}
+
+void ToonEngine::prepareConversations() {
+ Conversation *allConvs = _gameState->_conversationState;
+ for (int32 i = 0; i < 60; i++) {
+
+ allConvs[i].state[0]._data2 = 1;
+ if (!allConvs[i].state[0]._data3) {
+ allConvs[i].state[0]._data3 = 1;
+ }
+ allConvs[i].state[1]._data2 = 1;
+ allConvs[i].state[1]._data3 = 6;
+ allConvs[i].state[3]._data2 = 2;
+
+ }
+ int numConversations = READ_LE_UINT16(_conversationData + 1);
+ int16 *curConversation = _conversationData + 3;
+ for (int i = 0; i < numConversations; i++) {
+ Conversation *conv = &allConvs[ READ_LE_UINT16(curConversation)];
+ if (!conv->_enable) {
+
+ conv->_enable = 1;
+
+ int16 offset1 = READ_LE_UINT16(curConversation + 1);
+ void *convData1 = (char *)_conversationData + offset1;
+ conv->state[0]._data4 = convData1;
+
+ int16 offset2 = READ_LE_UINT16(curConversation + 2);
+ void *convData2 = (char *)_conversationData + offset2;
+ conv->state[1]._data4 = convData2;
+
+ int16 offset3 = READ_LE_UINT16(curConversation + 3);
+ void *convData3 = (char *)_conversationData + offset3;
+ conv->state[2]._data4 = convData3;
+
+ int16 offset4 = READ_LE_UINT16(curConversation + 4);
+ void *convData4 = (char *)_conversationData + offset4;
+ conv->state[3]._data4 = convData4;
+ }
+ curConversation += 5;
+ }
+}
+
+void ToonEngine::processConversationClick(Conversation *conv, int32 status) {
+ Conversation::ConvState *v2 = (Conversation::ConvState *)&conv->state[status];
+
+ int16 *i = (int16 *)((char *)v2->_data4 + 2);
+
+ _gameState->_firstConverstationLine = false;
+ while (*i >= 0) {
+ if (*i < 100) {
+ if (_gameState->_exitConversation == false) {
+ characterTalk(i[1]);
+ }
+ } else {
+ runConversationCommand(&i);
+ }
+ i += 2;
+ }
+
+ int16 command = i[0];
+ int16 value = i[1];
+
+ if (command == -1) {
+ v2->_data2 = 0;
+ } else if (command == -2) {
+ v2->_data4 = (char *)_conversationData + value;
+ v2->_data3 = *(int16 *)v2->_data4;
+ } else if (command == -3) {
+ v2->_data2 = 2;
+ v2->_data4 = (char *)_conversationData + value;
+ v2->_data3 = *(int16 *)v2->_data4;
+ }
+
+ int16 *v7 = i + 2;
+// Strangerke - Commented (not used)
+// int16 v6 = conv->state[0].data2;
+ int16 v8 = *v7;
+ if (v8 == -1) {
+ _gameState->_mouseHidden = false;
+ } else {
+retry:
+ while (1) {
+ v7 += 1;
+ int16 *v14 = (int16 *)((char *)_conversationData + v8);
+
+ // find free dialogue slot
+ for (int j = 0; j < 10; j++) {
+ if (!conv->state[j]._data2) {
+ conv->state[j]._data3 = *v14;
+ conv->state[j]._data4 = v14;
+ if (getConversationFlag(_gameState->_currentScene, conv->state[j]._data3))
+ conv->state[j]._data2 = 1;
+ else
+ conv->state[j]._data2 = 3;
+
+ v8 = *v7;
+ if (v8 == -1)
+ return;
+
+ goto retry;
+ }
+ }
+
+ if (v8 != -1)
+ continue;
+
+ break;
+ }
+ }
+
+}
+
+// hardcoded conversation flag to know if one dialogue icon must be displayed or not
+// based on game events...
+int32 ToonEngine::getConversationFlag(int32 locationId, int32 param) {
+ if (locationId == 1) {
+ if (param == 0x34)
+ return _gameState->getGameFlag(93);
+
+ if (param != 55)
+ return 1;
+
+ if (!_gameState->getGameFlag(262))
+ return 1;
+
+ return 0;
+ } else if (locationId == 2) {
+ if (param == 36 && _gameState->getGameFlag(149))
+ return 0;
+ return 1;
+ } else if (locationId == 7) {
+ if (param == 30)
+ return _gameState->getGameFlag(132);
+ else
+ return 1;
+ } else if (locationId == 8) {
+ if (param == 0x20) {
+ if (!_gameState->getGameFlag(73) && !_gameState->getGameFlag(151) && !_gameState->getGameFlag(152) && !_gameState->getGameFlag(153))
+ return 1;
+ return 0;
+ }
+ if (param == 33) {
+ if (!_gameState->getGameFlag(73) && !_gameState->getGameFlag(151) && !_gameState->getGameFlag(152) && !_gameState->getGameFlag(153))
+ return 0;
+ return 1;
+ }
+ } else if (locationId == 0xb) {
+ if (param == 0x12) {
+ if (!_gameState->hasItemInInventory(71))
+ return 1;
+ else
+ return 0;
+ }
+ if (param == 74) {
+ if (_gameState->hasItemInInventory(71))
+ return 1;
+ else
+ return 0;
+ }
+ return 1;
+ } else if (locationId == 0xc) {
+ if (param == 0x3d && _gameState->getGameFlag(154)) {
+ return 0;
+ }
+ if (param == 76 && !_gameState->getGameFlag(79)) {
+ return 0;
+ }
+ if (param == 0x4e && !_gameState->hasItemInInventory(32)) {
+ return 0;
+ }
+ if (param == 0x4f && !_gameState->hasItemInInventory(92)) {
+ return 0;
+ }
+ if (param == 80 && !_gameState->hasItemInInventory(91)) {
+ return 0;
+ }
+ if (param == 0x4d && _gameState->getGameFlag(79)) {
+ return 0;
+ }
+ } else if (locationId == 0xd) {
+ if (param == 0x2f && _gameState->getGameFlag(81)) {
+ return 0;
+ }
+ if (param == 48 && _gameState->getGameFlag(81)) {
+ return 0;
+ }
+ } else if (locationId == 0x10) {
+ switch (param) {
+ case 0x3e8:
+ if (!(_gameState->_gameGlobalData[83] & 1))
+ return 0;
+ break;
+ case 0x3e9:
+ if (!(_gameState->_gameGlobalData[83] & 2))
+ return 0;
+ break;
+ case 0x3ea:
+ if (!(_gameState->_gameGlobalData[83] & 4))
+ return 0;
+ break;
+ case 0x3eb:
+ if (!(_gameState->_gameGlobalData[83] & 8))
+ return 0;
+ break;
+ case 0x3ec:
+ if (!(_gameState->_gameGlobalData[83] & 16))
+ return 0;
+ break;
+ case 0x3ed:
+ if (!(_gameState->_gameGlobalData[83] & 32))
+ return 0;
+ break;
+ case 0x3ee:
+ if (!(_gameState->_gameGlobalData[83] & 64))
+ return 0;
+ break;
+ default:
+ break;
+ };
+ return 1;
+ } else if (locationId == 0x12) {
+ if (param == 0x28 && _gameState->getGameFlag(91)) {
+ return 0;
+ }
+ if (param == 41 && (!_gameState->getGameFlag(96) || _gameState->getGameFlag(91))) {
+ return 0;
+ }
+ } else if (locationId == 0x13) {
+ if (param == 0x32 && _gameState->getGameFlag(107)) {
+ return 0;
+ }
+ if (param == 68 && !_gameState->getGameFlag(107)) {
+ return 0;
+ }
+ } else if (locationId == 0x14) {
+ if (param == 1000 && !_gameState->getGameFlag(82)) {
+ return 0;
+ }
+ } else if (locationId == 0x25) {
+ if (param == 7 && _gameState->_gameGlobalData[28] != 1) {
+ return 0;
+ }
+ if (param == 8 && _gameState->_gameGlobalData[28] != 1) {
+ return 0;
+ }
+ if (param == 9 && _gameState->_gameGlobalData[28] != 1) {
+ return 0;
+ }
+ if (param == 75 && _gameState->_gameGlobalData[28] != 2) {
+ return 0;
+ }
+ } else if (locationId == 72) {
+ if (param == 63 && _gameState->getGameFlag(105)) {
+ return 0;
+ }
+ if (param == 67 && !_gameState->getGameFlag(105)) {
+ return 0;
+ }
+ if (param == 0x40 && !_gameState->getGameFlag(105)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int ToonEngine::runConversationCommand(int16 **command) {
+
+// Strangerke - Commented (not used)
+// int16 com = **command;
+ int16 *v5 = *command;
+
+ int v2 = v5[0];
+ int v4 = v5[1];
+ int result = v2 - 100;
+ switch (v2) {
+ case 100:
+ result = runEventScript(_mouseX, _mouseY, 2, v4, 0);
+ break;
+ case 101:
+ _gameState->_exitConversation = true;
+ break;
+ case 102:
+ playSoundWrong();
+ break;
+ case 104:
+ *command = (int16 *)((char *)_conversationData + v4);
+ *command = (int16 *)((char *)_conversationData + v4 - 4);
+ break;
+ //
+ case 105:
+ if ( getConversationFlag( _gameState->_currentScene, v4)) {
+ result = *(int16*)(*command + 4);
+ *command = (int16 *)((char *)_conversationData + result);
+ *command = (int16 *)((char *)_conversationData + result - 4);
+ } else {
+ int16* newPtr = *command + 1;
+ *command = newPtr;
+ }
+ break;
+ case 103:
+ return result;
+ break;
+ }
+ return result;
+}
+
+int32 ToonEngine::waitTicks(int32 numTicks, bool breakOnMouseClick) {
+// Strangerke - Commented (not used)
+// Common::EventManager *_event = _system->getEventManager();
+
+ uint32 nextTime = _system->getMillis() + numTicks * _tickLength;
+ while (_system->getMillis() < nextTime || numTicks == -1) {
+ //if (!_animationSceneScriptRunFlag)
+ // break;
+ updateAnimationSceneScripts(0);
+ getMouseEvent();
+ simpleUpdate();
+
+ if (breakOnMouseClick && (_mouseButton & 0x2))
+ break;
+ }
+ return 0;
+}
+
+void ToonEngine::renderInventory() {
+ if (!_gameState->_inInventory)
+ return;
+
+ _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+
+ // draw items on screen
+ for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+ int32 x = 57 * (i % 7) + 114;
+ int32 y = ((9 * (i % 7)) & 0xf) + 56 * (i / 7) + 80;
+ _inventoryIconSlots->drawFrame(*_mainSurface, i % 12, x + _gameState->_currentScrollValue, y);
+ if (_gameState->_inventory[i])
+ _inventoryIcons->drawFrame(*_mainSurface, _gameState->_inventory[i], x + _gameState->_currentScrollValue + 2, y + 2);
+ }
+
+ drawConversationLine();
+ if (!_audioManager->voiceStillPlaying()) {
+ _currentTextLineCharacterId = -1;
+ _currentTextLine = 0;
+ _currentTextLineId = -1;
+ }
+
+ if (_firstFrame) {
+ copyToVirtualScreen(false);
+ _firstFrame = false;
+ fadeIn(5);
+ }
+ copyToVirtualScreen();
+}
+
+int32 ToonEngine::showInventory() {
+ int32 oldScrollValue = _gameState->_currentScrollValue;
+// Strangerke - Commented (not used)
+// Common::EventManager *_event = _system->getEventManager();
+ _inventoryPicture = new Picture(this);
+ fadeOut(5);
+ _inventoryPicture->loadPicture("SACK128.CPS", true);
+ _inventoryPicture->setupPalette();
+
+ if (_gameState->_mouseState >= 0)
+ setCursor(_gameState->_mouseState, true, -18, -14);
+ else
+ setCursor(0);
+
+
+ _gameState->_inInventory = true;
+ _gameState->_currentScrollValue = 0;
+
+ int32 oldMouseButton = 0;
+ int32 justPressedButton = 0;
+ _firstFrame = true;
+
+ while (!shouldQuit()) {
+ getMouseEvent();
+
+ justPressedButton = _mouseButton & ~oldMouseButton;
+ oldMouseButton = _mouseButton;
+
+ if (justPressedButton & 0x3) {
+ // find out what object we're on
+ int32 foundObj = -1;
+ for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+ int32 x = 57 * (i % 7) + 114;
+ int32 y = ((9 * (i % 7)) & 0xf) + 56 * (i / 7) + 80;
+ if (_mouseX >= (_gameState->_currentScrollValue + x - 6) &&
+ _mouseX <= (_gameState->_currentScrollValue + x + 44 + 7) &&
+ _mouseY >= y - 6 && _mouseY <= y + 50) {
+ foundObj = i;
+ break;
+ }
+ }
+
+ if (justPressedButton & 0x1) {
+ if (_gameState->_mouseState < 0) {
+ if (foundObj >= 0) {
+ // take an object
+ int32 item = _gameState->_inventory[foundObj];
+
+ int32 modItem = getSpecialInventoryItem(item);
+ if (modItem) {
+
+ if (modItem == -1) {
+ _gameState->_mouseState = item;
+ _gameState->_inventory[foundObj] = 0;
+ } else
+ _gameState->_mouseState = modItem;
+
+ setCursor(_gameState->_mouseState, true, -18, -14);
+ }
+
+ } else {
+ break;
+ }
+ } else {
+ if (foundObj >= 0 && _gameState->_inventory[foundObj] == 0) { // empty place
+ _gameState->_inventory[foundObj] = _gameState->_mouseState;
+ setCursor(0, false);
+ _gameState->_mouseState = -1;
+ } else if (foundObj >= 0 && _gameState->_inventory[foundObj] > 0) {
+ if (!handleInventoryOnInventory(_gameState->_mouseState, _gameState->_inventory[foundObj]))
+ playSoundWrong();
+ } else {
+ // quit the inventory mode with the icon
+ break;
+ }
+ }
+
+ } else if (justPressedButton & 0x2) { // right button
+ if (foundObj >= 0) {
+ // talk about the object
+ if (!handleInventoryOnInventory(_gameState->_inventory[foundObj], -1))
+ characterTalk(1000 + _gameState->_inventory[foundObj]);
+ } else {
+ // go out
+ break;
+ }
+ }
+ }
+
+ renderInventory();
+
+ }
+
+ _gameState->_currentScrollValue = oldScrollValue;
+ _gameState->_inInventory = false;
+
+ fadeOut(5);
+ if (_gameState->_inCloseUp) {
+ _gameState->_inCloseUp = false;
+ flipScreens();
+ }
+ else if (_gameState->_inCutaway) {
+ _currentCutaway->setupPalette();
+ setupGeneralPalette();
+ } else {
+ _currentPicture->setupPalette();
+ setupGeneralPalette();
+ }
+ flushPalette();
+ _firstFrame = true;
+
+ return 0;
+}
+
+void ToonEngine::getMouseEvent() {
+ Common::EventManager *_event = _system->getEventManager();
+
+ Common::Event event;
+ while (_event->pollEvent(event) && !shouldQuit())
+ ;
+
+ _mouseX = _event->getMousePos().x;
+ _mouseY = _event->getMousePos().y;
+ _mouseButton = _event->getButtonState();
+}
+
+void ToonEngine::drawSack() {
+ if (_gameState->_sackVisible) {
+ _inventoryIcons->drawFrame(*_mainSurface, 0, _gameState->_currentScrollValue, 356);
+ }
+}
+
+void ToonEngine::addItemToInventory(int32 item) {
+
+ if (item == 103 || item == 104 || item == 89 || item == 82) {
+ // can't add that to inventory
+ _gameState->_mouseState = -1;
+ return;
+ }
+
+ if (item == 41) {
+ // confiscated inventory
+ for (int32 i = 0; i < _gameState->_numConfiscatedInventoryItems; i++)
+ addItemToInventory(_gameState->_confiscatedInventory[i]);
+
+ _gameState->_numConfiscatedInventoryItems = 0;
+ _gameState->_mouseState = -1;
+ return;
+ }
+
+ for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+ if (_gameState->_inventory[i] == 0) {
+ _gameState->_inventory[i] = item;
+ _gameState->_mouseState = -1;
+ return;
+ }
+ }
+ _gameState->_inventory[_gameState->_numInventoryItems] = item;
+ _gameState->_numInventoryItems++;
+ _gameState->_mouseState = -1;
+}
+
+void ToonEngine::createMouseItem(int32 item) {
+ _gameState->_mouseState = item;
+ setCursor(_gameState->_mouseState, true, -18, -14);
+}
+
+void ToonEngine::deleteMouseItem() {
+ _gameState->_mouseState = -1;
+ rearrangeInventory();
+ setCursor(0);
+}
+
+void ToonEngine::showCutaway(Common::String cutawayPicture) {
+ _gameState->_inCutaway = true;
+ _currentCutaway = new Picture(this);
+ if (cutawayPicture == "") {
+ cutawayPicture = Common::String(_gameState->_locations[_gameState->_currentScene]._cutaway) + ".CPS";
+ }
+ _currentCutaway->loadPicture(cutawayPicture, false);
+ _currentCutaway->setupPalette();
+ _oldScrollValue = _gameState->_currentScrollValue;
+ _gameState->_currentScrollValue = 0;
+ flushPalette();
+}
+
+void ToonEngine::hideCutaway() {
+ _gameState->_inCutaway = false;
+ _gameState->_sackVisible = true;
+ delete _currentCutaway;
+ _gameState->_currentScrollValue = _oldScrollValue;
+ _currentCutaway = 0;
+ _currentPicture->setupPalette();
+ flushPalette();
+}
+
+void ToonEngine::updateCharacters(int32 timeElapsed) {
+ for (int32 i = 0; i < 8; i++) {
+ if (_characters[i]) {
+ _characters[i]->update(timeElapsed);
+ }
+ }
+}
+
+void ToonEngine::drawPalette() {
+ for (int32 i = 0; i < 256; i++) {
+ int32 x = i % 32;
+ int32 y = i / 32;
+ _mainSurface->fillRect(Common::Rect(x * 16, y * 16, x * 16 + 16, y * 16 + 16), i);
+ }
+}
+
+void ToonEngine::rearrangeInventory() {
+ for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+ if (_gameState->_inventory[i] == 0) {
+ // move all the following items from one
+ for (int32 j = i + 1; j < _gameState->_numInventoryItems; j++) {
+ _gameState->_inventory[j-1] = _gameState->_inventory[j];
+ }
+ _gameState->_numInventoryItems--;
+ }
+ }
+}
+
+void ToonEngine::newGame() {
+
+ if (_isDemo) {
+ addItemToInventory(59);
+ addItemToInventory(67);
+ addItemToInventory(11);
+ addItemToInventory(19);
+ loadScene(_gameState->_currentScene);
+ } else {
+ //loadScene(4);
+ loadScene(_gameState->_currentScene);
+ }
+}
+
+void ToonEngine::playSFX(int32 id, int32 volume) {
+ if (id < 0)
+ _audioManager->playSFX(-id + 1, volume, true);
+ else
+ _audioManager->playSFX(id , volume, false);
+}
+
+void ToonEngine::playSoundWrong() {
+ _audioManager->playSFX(rand() & 7, 128, true);
+}
+
+void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
+
+ if (characterId < 0)
+ characterId = 0;
+
+ // default position is the center of current screen
+ *retX = _gameState->_currentScrollValue + 320;
+ *retY = 70;
+
+ // hardcoded special cases...
+ if (characterId == 0) {
+ // drew
+ int32 x = _drew->getX();
+ int32 y = _drew->getY();
+ if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + 640) {
+ if (!_gameState->_inCutaway && !_gameState->_inInventory) {
+ *retX = x;
+ *retY = y - ((_drew->getScale() * 256 / 1024) >> 1) - 45;
+ }
+ }
+ } else if (characterId == 1) {
+ // flux
+ int32 x = _flux->getX();
+ int32 y = _flux->getY();
+ if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + 640) {
+ if (!_gameState->_inCutaway) {
+ *retX = x;
+ *retY = y - ((_drew->getScale() * 100 / 1024) >> 1) - 30;
+ }
+ }
+ } else if (characterId == 5 || characterId == 39) {
+ *retX = 80;
+ *retY = 120;
+ } else if (characterId == 14) {
+ *retX = 257;
+ *retY = 132;
+ } else if (characterId == 18) {
+ *retX = 80;
+ *retY = 180;
+ } else if (characterId == 21) {
+ *retX = 363;
+ *retY = 193;
+ } else if (characterId == 23) {
+ *retX = 532;
+ *retY = 178;
+ } else if (characterId == 33) {
+ *retX = 167;
+ *retY = 172;
+ } else {
+
+ // more "standard" code by character
+ Character *character = getCharacterById(characterId);
+ if (character && !_gameState->_inCutaway) {
+ if (character->getAnimationInstance()) {
+ if (character->getX() >= _gameState->_currentScrollValue && character->getX() <= _gameState->_currentScrollValue + 640) {
+ int32 x1, y1, x2, y2;
+ character->getAnimationInstance()->getRect(&x1, &y1, &x2, &y2);
+ *retX = (x1 + x2) / 2;
+ *retY = y1;
+ }
+ }
+ }
+ }
+}
+
+Character *ToonEngine::getCharacterById(int32 charId) {
+
+ for (int32 i = 0; i < 8; i++) {
+ if (_characters[i] && _characters[i]->getId() == charId)
+ return _characters[i];
+ }
+ return 0;
+}
+
+void ToonEngine::drawConversationLine() {
+ if (_currentTextLine) {
+ _fontRenderer->setFontColorByCharacter(_currentTextLineCharacterId);
+ _fontRenderer->setFont(_fontToon);
+ _fontRenderer->renderMultiLineText(_currentTextLineX, _currentTextLineY, Common::String(_currentTextLine), 0);
+ }
+}
+
+Common::String ToonEngine::getSavegameName(int nr) {
+ return _targetName + Common::String::printf(".%03d", nr);
+}
+
+bool ToonEngine::saveGame(int32 slot) {
+ const EnginePlugin *plugin = NULL;
+ int16 savegameId;
+ Common::String savegameDescription;
+ EngineMan.findGame(_gameDescription->gameid, &plugin);
+
+ if (slot == -1) {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save");
+ dialog->setSaveMode(true);
+ savegameId = dialog->runModal(plugin, ConfMan.getActiveDomainName());
+ savegameDescription = dialog->getResultString();
+ delete dialog;
+ }
+ else {
+ savegameId = slot;
+ savegameDescription = Common::String::printf("Quick save #%d", slot);
+ }
+
+ if (savegameId < 0)
+ return false; // dialog aborted
+
+ Common::String savegameFile = getSavegameName(savegameId);
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::OutSaveFile *saveFile = saveMan->openForSaving(savegameFile);
+ if (!saveFile)
+ return false;
+
+ // save savegame header
+ saveFile->writeSint32BE(TOON_SAVEGAME_VERSION);
+
+ if (savegameDescription == "") {
+ savegameDescription = "Untitled savegame";
+ }
+
+ saveFile->writeSint16BE(savegameDescription.size()+1);
+ saveFile->write(savegameDescription.c_str(), savegameDescription.size()+1);
+
+ Graphics::saveThumbnail(*saveFile);
+
+ TimeDate curTime;
+ _system->getTimeAndDate(curTime);
+
+ uint32 saveDate = (curTime.tm_mday & 0xFF) << 24 | ((curTime.tm_mon + 1) & 0xFF) << 16 | ((curTime.tm_year + 1900) & 0xFFFF);
+ uint16 saveTime = (curTime.tm_hour & 0xFF) << 8 | ((curTime.tm_min) & 0xFF);
+
+ saveFile->writeUint32BE(saveDate);
+ saveFile->writeUint16BE(saveTime);
+
+
+ // save global state
+ _gameState->save(saveFile);
+ _gameState->saveConversations(saveFile);
+ _hotspots->save(saveFile);
+
+ // save current time to be able to patch the time when loading
+ saveFile->writeSint32BE(getOldMilli());
+
+ // save script states
+ for (int32 i = 0; i < 4; i++) {
+ _script->saveState(&_scriptState[i], saveFile);
+ }
+
+ // save animation script states
+ for (int32 i = 0; i < state()->_locations[_gameState->_currentScene]._numSceneAnimations; i++) {
+ saveFile->writeByte(_sceneAnimationScripts[i]._active);
+ saveFile->writeByte(_sceneAnimationScripts[i]._frozen);
+ saveFile->writeSint32BE(_sceneAnimationScripts[i]._lastTimer);
+ _script->saveState(&_sceneAnimationScripts[i]._state, saveFile);
+ }
+
+ // save scene animations
+ for (int32 i = 0; i < 64; i++) {
+ _sceneAnimations[i].save(this, saveFile);
+ }
+
+
+ for (int32 i = 0; i < 8; i++) {
+ if (_characters[i]) {
+ saveFile->writeSByte(i);
+ _characters[i]->save(saveFile);
+ }
+ }
+ saveFile->writeSByte(-1);
+
+ // save "command buffer"
+ saveFile->writeSint16BE(_saveBufferStream->pos());
+ if (_saveBufferStream->pos() > 0) {
+ saveFile->write(_saveBufferStream->getData(), _saveBufferStream->pos());
+ saveFile->writeSint16BE(0);
+ }
+
+ delete saveFile;
+
+ return true;
+}
+
+bool ToonEngine::loadGame(int32 slot) {
+ const EnginePlugin *plugin = NULL;
+ int16 savegameId;
+ EngineMan.findGame(_gameDescription->gameid, &plugin);
+
+ if (slot == -1) {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore");
+ dialog->setSaveMode(false);
+ savegameId = dialog->runModal(plugin, ConfMan.getActiveDomainName());
+ delete dialog;
+ }
+ else {
+ savegameId = slot;
+ }
+ if (savegameId < 0)
+ return false; // dialog aborted
+
+ Common::String savegameFile = getSavegameName(savegameId);
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *loadFile = saveMan->openForLoading(savegameFile);
+ if (!loadFile)
+ return false;
+
+ int32 saveGameVersion = loadFile->readSint32BE();
+ if (saveGameVersion != TOON_SAVEGAME_VERSION) {
+ delete loadFile;
+ return false;
+ }
+ int32 saveGameNameSize = loadFile->readSint16BE();
+ loadFile->skip(saveGameNameSize);
+
+ // We don't need the thumbnail here, so just read it and discard it
+ Graphics::skipThumbnail(*loadFile);
+
+ loadFile->skip(6); // date & time skip
+
+ if (_gameState->_currentScene != -1) {
+ exitScene();
+ }
+
+
+ _gameState->load(loadFile);
+ loadScene(_gameState->_currentScene, true);
+ _gameState->loadConversations(loadFile);
+ _hotspots->load(loadFile);
+
+ // read the old time
+ int32 savedTime = loadFile->readSint32BE();
+ int32 timerDiff = _system->getMillis() - savedTime;
+
+ // load script states
+ for (int32 i = 0; i < 4; i++) {
+ _script->loadState(&_scriptState[i], loadFile);
+ }
+
+ // load animation script states
+ for (int32 i = 0; i < state()->_locations[_gameState->_currentScene]._numSceneAnimations; i++) {
+ _sceneAnimationScripts[i]._active = loadFile->readByte();
+ _sceneAnimationScripts[i]._frozen = loadFile->readByte();
+ _sceneAnimationScripts[i]._lastTimer = loadFile->readSint32BE() + timerDiff;
+ _script->loadState(&_sceneAnimationScripts[i]._state, loadFile);
+ }
+
+ // load scene animations
+ for (int32 i = 0; i < 64; i++) {
+ _sceneAnimations[i].load(this, loadFile);
+ }
+
+ _gameState->_timerTimeout[0] += timerDiff;
+ _gameState->_timerTimeout[1] += timerDiff;
+
+ /*
+ int32 diff = _conversationData - _gameState->_conversationData;
+
+ for (int32 i = 0; i < 60; i++) {
+ if (_gameState->_conversationState[i]._enable) {
+ // we have to fix up our pointers...
+ for (int32 a = 0; a < 10; a++) {
+ if (_gameState->_conversationState[i].state[a]._data4)
+ _gameState->_conversationState[i].state[a]._data4 = (int16*)_gameState->_conversationState[i].state[a]._data4 + diff;
+ }
+ }
+ }
+ */
+
+ _gameState->_conversationData = _conversationData;
+ _firstFrame = true;
+
+ // read characters info
+ while (1) {
+ int8 c = loadFile->readSByte();
+ if (c < 0)
+ break;
+
+ if (!_characters[c]) {
+ _characters[c] = new Character(this);
+ }
+ _characters[c]->load(loadFile);
+ //_characters[c]->setVisible(true);
+ _characters[c]->update(0);
+ }
+
+ // load "command buffer"
+ int32 size = loadFile->readSint16BE();
+ if (size) {
+ uint8* buf = new uint8[size+2];
+ loadFile->read(buf, size+2);
+
+ Common::MemoryReadStream rStr(buf, size+2);
+ while (1) {
+ int16 command = rStr.readSint16BE();
+ if (!command) break;
+ switch (command) {
+ case 1: {
+ int16 frame = rStr.readSint16BE();
+ int16 animLen = rStr.readSint16BE();
+ char animName[32];
+ rStr.read(animName,animLen);
+ int16 x = rStr.readSint16BE();
+ int16 y = rStr.readSint16BE();
+// int16 z = rStr.readSint16BE();
+// int16 layerZ = rStr.readSint16BE();
+ rStr.readSint16BE();
+ rStr.readSint16BE();
+
+ Animation* anim = new Animation(this);
+ anim->loadAnimation(animName);
+ anim->drawFrameOnPicture(frame,x,y);
+ delete anim;
+ break;
+ }
+ case 2: {
+ int16 x = rStr.readSint16BE();
+ int16 y = rStr.readSint16BE();
+ int16 x1 = rStr.readSint16BE();
+ int16 y1 = rStr.readSint16BE();
+ makeLineNonWalkable(x,y,x1,y1);
+ break;
+ }
+ case 3: {
+ int16 x = rStr.readSint16BE();
+ int16 y = rStr.readSint16BE();
+ int16 x1 = rStr.readSint16BE();
+ int16 y1 = rStr.readSint16BE();
+ makeLineWalkable(x,y,x1,y1);
+ break;
+ }
+ case 4: {
+ int16 x = rStr.readSint16BE();
+ int16 y = rStr.readSint16BE();
+ getMask()->floodFillNotWalkableOnMask(x,y);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ _saveBufferStream->write(buf,size);
+ delete loadFile;
+ }
+ return true;
+}
+
+// another special case for inventory
+int32 ToonEngine::getSpecialInventoryItem(int32 item) {
+
+ // butter
+ if (item == 12) {
+ for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+ if (_gameState->_inventory[i] == 12)
+ _gameState->_inventory[i] = 11;
+ }
+ return 11;
+
+ } else if (item == 84) {
+ if (_gameState->getGameFlag(26)) {
+ characterTalk(1726);
+ return 0;
+ } else {
+ if (!_gameState->hasItemInInventory(102) && !_gameState->hasItemInInventory(90) && !_gameState->hasItemInInventory(89)) {
+ characterTalk(1416);
+ return 102;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+void ToonEngine::initCharacter(int32 characterId, int32 animScriptId, int32 sceneAnimationId, int32 animToPlayId) {
+ // find a new index
+ int32 characterIndex = -1;
+ for (int32 i = 0; i < 8; i++) {
+ if (_characters[i] && _characters[i]->getId() == characterId) {
+ characterIndex = i;
+ break;
+ }
+
+ if (!_characters[i]) {
+ characterIndex = i;
+ break;
+ }
+ }
+
+ if (characterIndex == -1) {
+ return;
+ }
+
+// Strangerke - Commented (not used)
+// if (_characters[characterIndex])
+ //delete current char
+
+ _characters[characterIndex] = new Character(this);
+ _characters[characterIndex]->setId(characterId);
+ _characters[characterIndex]->setAnimScript(animScriptId);
+ _characters[characterIndex]->setDefaultSpecialAnimationId(animToPlayId);
+ _characters[characterIndex]->setSceneAnimationId(sceneAnimationId);
+ _characters[characterIndex]->setFlag(0);
+ _characters[characterIndex]->setVisible(true);
+ if (sceneAnimationId != -1)
+ _characters[characterIndex]->setAnimationInstance(_sceneAnimations[sceneAnimationId]._animInstance);
+}
+
+int32 ToonEngine::handleInventoryOnFlux(int32 itemId) {
+
+ switch (itemId) {
+ case 8:
+ sayLines(1, 1332);
+ break;
+ case 0x14:
+ case 0x15:
+ case 0x45:
+ sayLines(1, 1304);
+ break;
+ case 0x68:
+ _gameState->_mouseState = 0;
+ setCursor(0, false, 0, 0);
+ break;
+ case 116:
+ sayLines(1, 1306);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+void ToonEngine::storePalette() {
+ memcpy(_backupPalette, _finalPalette, 768);
+}
+
+void ToonEngine::restorePalette() {
+ memcpy(_finalPalette, _backupPalette, 768);
+ flushPalette();
+}
+
+void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemDest) {
+ storePalette();
+ fadeOut(5);
+
+ Picture* pic = new Picture(this);
+ pic->loadPicture(str, false);
+ pic->setupPalette();
+ flushPalette();
+
+ if (lineId) {
+ characterTalk(lineId, false);
+ }
+
+ uint32 oldMouseButton = _mouseButton;
+ uint32 justPressedButton = 0;
+ _firstFrame = true;
+
+ int32 oldScrollValue = _gameState->_currentScrollValue;
+ _gameState->_currentScrollValue = 0;
+
+ while (!shouldQuit()) {
+ getMouseEvent();
+
+ justPressedButton = _mouseButton & ~oldMouseButton;
+ oldMouseButton = _mouseButton;
+
+ if (justPressedButton) {
+ break;
+ }
+
+ pic->draw(*_mainSurface, 0, 0, 0, 0);
+
+ drawConversationLine();
+ if (!_audioManager->voiceStillPlaying()) {
+ _currentTextLineCharacterId = -1;
+ _currentTextLine = 0;
+ _currentTextLineId = -1;
+ }
+
+ if (_firstFrame) {
+ copyToVirtualScreen(false);
+ _firstFrame = false;
+ fadeIn(5);
+ }
+
+ copyToVirtualScreen();
+ }
+
+ fadeOut(5);
+ restorePalette();
+ _firstFrame = true;
+ _gameState->_currentScrollValue= oldScrollValue;
+ delete pic;
+
+}
+
+int32 ToonEngine::handleInventoryOnInventory(int32 itemDest, int32 itemSrc) {
+ switch (itemDest) {
+ case 0:
+ return handleInventoryOnDrew(itemSrc);
+ case 1:
+ if (itemSrc == 71) {
+ sayLines(2, 1212);
+ return 1;
+ }
+ break;
+ case 5:
+ if (itemSrc == 15) {
+ characterTalk(1492);
+ } else if (itemSrc == 0x2f) {
+ characterTalk(1488);
+ } else if (itemSrc == 88) {
+ sayLines(2, 1478);
+ } else {
+ return 0;
+ }
+ break;
+ case 6:
+ if (itemSrc == -1) {
+ viewInventoryItem("BLUEPRNT.CPS", 1006, itemDest);
+ return 1;
+ } else
+ return 0;
+ break;
+ case 8:
+ if (itemSrc == -1) {
+ viewInventoryItem("BOOK.CPS", 0, itemDest);
+ return 1;
+ } else {
+ return 0;
+ }
+ break;
+ case 11:
+ if (itemSrc == 0xb) {
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ return 1;
+ //
+ } else if (itemSrc == 24) {
+ characterTalk(1244);
+ return 1;
+ } else if (itemSrc == 0x1a || itemSrc == 0x40 || itemSrc == 71) {
+ sayLines(2, 1212);
+ return 1;
+ }
+ break;
+ case 12:
+ if (itemSrc == 24) {
+ characterTalk(1244);
+ return 1;
+ } else if (itemSrc == 0x1a || itemSrc == 0x40 || itemSrc == 71) {
+ sayLines(2, 1212);
+ return 1;
+ }
+ break;
+ case 13:
+ if (itemSrc == 0x35 || itemSrc == 0x36) {
+ characterTalk(1204);
+ return 1;
+ } else if (itemSrc >= 0x6b && itemSrc <= 0x72) {
+ characterTalk(1312);
+ return 1;
+ }
+ break;
+ case 14:
+ if (itemSrc == -1) {
+ deleteItemFromInventory(14);
+ addItemToInventory(15);
+ addItemToInventory(42);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 43) {
+ characterTalk(1410);
+ return 1;
+ } else if (itemSrc == 49) {
+ characterTalk(1409);
+ return 1;
+ }
+ break;
+ case 16:
+ if (itemSrc == 55) {
+ characterTalk(1400);
+ replaceItemFromInventory(55, 98);
+ return 1;
+ }
+ break;
+ case 19:
+ if (itemSrc == 0x34) {
+ characterTalk(1322);
+ return 1;
+ } else if (itemSrc == 107) {
+ sayLines(2 , 1300);
+ replaceItemFromInventory(107, 111);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x6c) {
+ sayLines(2, 1300);
+ replaceItemFromInventory(108, 112);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x6d) {
+ sayLines(2, 1300);
+ replaceItemFromInventory(109, 113);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 110) {
+ sayLines(2, 1300);
+ replaceItemFromInventory(110, 114);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ }
+ break;
+ case 20:
+ if (itemSrc == 35) {
+ createMouseItem(21);
+ replaceItemFromInventory(35, 36);
+ return 1;
+ } else if (itemSrc == 0x24) {
+ createMouseItem(21);
+ replaceItemFromInventory(36, 37);
+ return 1;
+ } else if (itemSrc == 37) {
+ deleteItemFromInventory(37);
+ createMouseItem(21);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x6b || itemSrc == 0x6c || itemSrc == 0x6f || itemSrc == 108 || itemSrc == 112) {
+ sayLines(2, 1292);
+ return 1;
+ }
+ break;
+ case 21:
+ switch (itemSrc) {
+
+ case 107:
+ characterTalk(1296);
+ replaceItemFromInventory(107, 109);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);;
+ rearrangeInventory();
+ return 1;
+ case 108:
+ characterTalk(1298);
+ replaceItemFromInventory(108, 110);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ case 111:
+ characterTalk(1296);
+ replaceItemFromInventory(111, 113);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ case 112:
+ characterTalk(1298);
+ replaceItemFromInventory(112, 114);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ }
+ break;
+ case 22:
+ if (itemSrc == 32) {
+ characterTalk(1252);
+ return 1;
+ }
+ break;
+ case 24:
+ if (itemSrc == 0xc) {
+ characterTalk(1244);
+ return 1;
+ } else if (itemSrc == 79) {
+ characterTalk(1280);
+ return 1;
+ }
+ break;
+ case 26:
+ if (itemSrc == 0x5e) {
+ characterTalk(1316);
+ return 1;
+ } else if (itemSrc == 95) {
+ characterTalk(1320);
+ return 1;
+ }
+ break;
+ case 31:
+ if (itemSrc == 61) {
+ characterTalk(1412);
+ deleteItemFromInventory(61);
+ createMouseItem(62);
+ rearrangeInventory();
+ return 1;
+ }
+ break;
+ case 32:
+ if (itemSrc == 22) {
+ characterTalk(1252);
+ return 1;
+ }
+ break;
+ case 33:
+ if (itemSrc == 117) {
+ characterTalk(1490);
+ return 1;
+ }
+ break;
+ case 34:
+ if (itemSrc == 61) {
+ characterTalk(1414);
+ return 1;
+ }
+ break;
+ case 35:
+ if (itemSrc == -1) {
+ characterTalk(1035);
+ return 1;
+ } else if (itemSrc == 20) {
+ replaceItemFromInventory(20, 21);
+ createMouseItem(36);
+ return 1;
+ } else if (itemSrc == 68) {
+ replaceItemFromInventory(68, 69);
+ createMouseItem(36);
+ return 1;
+ } else if (itemSrc >= 107 && itemSrc <= 114) {
+ characterTalk(1314);
+ return 1;
+ } else {
+ characterTalk(1208);
+ return 1;
+ }
+ break;
+ case 36:
+ if (itemSrc == -1) {
+ characterTalk(1035);
+ return 1;
+ } else if (itemSrc == 20) {
+ replaceItemFromInventory(20, 21);
+ createMouseItem(37);
+ return 1;
+ } else if (itemSrc == 68) {
+ replaceItemFromInventory(68, 69);
+ createMouseItem(37);
+ return 1;
+ } else if (itemSrc >= 107 && itemSrc <= 114) {
+ characterTalk(1314);
+ return 1;
+ } else {
+ characterTalk(1208);
+ return 1;
+ }
+ break;
+ case 37:
+ if (itemSrc == -1) {
+ characterTalk(1035);
+ return 1;
+ } else if (itemSrc == 20) {
+ replaceItemFromInventory(20, 21);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 68) {
+ replaceItemFromInventory(68, 69);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc >= 107 && itemSrc <= 114) {
+ characterTalk(1314);
+ return 1;
+ } else {
+ characterTalk(1208);
+ return 1;
+ }
+ break;
+ case 38:
+ if (itemSrc == 15) {
+ characterTalk(1492);
+ return 1;
+ } else if (itemSrc == 0x2f) {
+ characterTalk(1488);
+ return 1;
+ } else if (itemSrc == 88) {
+ sayLines(2, 1478);
+ return 1;
+ }
+ break;
+ case 40:
+ if (itemSrc == 53) {
+ replaceItemFromInventory(53, 54);
+ characterTalk(1222);
+ return 1;
+ } else if (itemSrc == 0x36) {
+ characterTalk(1228);
+ return 1;
+ } else if (itemSrc == 0x5b) {
+ characterTalk(1230);
+ return 1;
+ } else if (itemSrc == 92) {
+ characterTalk(1220);
+ return 1;
+ }
+ break;
+ case 43:
+ if (itemSrc == 14) {
+ characterTalk(1410);
+ return 1;
+ }
+ break;
+ case 47:
+ if (itemSrc == -1)
+ characterTalk(1047);
+ else
+ characterTalk(1488);
+
+ return 1;
+ case 49:
+ if (itemSrc == 0xe) {
+ characterTalk(1409);
+ return 1;
+ } else if (itemSrc == 38 || itemSrc == 5 || itemSrc == 0x42) {
+ characterTalk(1476);
+ return 1;
+ } else if (itemSrc == 0x34) {
+ characterTalk(1260);
+ return 1;
+ } else if (itemSrc == 0x47) {
+ characterTalk(1246);
+ return 1;
+ } else if (itemSrc == 0x36) {
+ sayLines(2, 1324);
+ return 1;
+ }
+ break;
+ case 52:
+ if (itemSrc == 0x13) {
+ characterTalk(1322);
+ return 1;
+ } else if (itemSrc == 94) {
+ characterTalk(1282);
+ return 1;
+ }
+ break;
+ case 53:
+ if (itemSrc == 40) {
+ createMouseItem(54);
+ characterTalk(1222);
+ return 1;
+ } else if (itemSrc == 0x31) {
+ sayLines(2, 1324);
+ return 1;
+ } else if (itemSrc == 0x34) {
+ characterTalk(1310);
+ return 1;
+ } else if (itemSrc == 91) {
+ characterTalk(1218);
+ return 1;
+ }
+
+ break;
+ case 54:
+ if (itemSrc == 40) {
+ characterTalk(1228);
+ return 1;
+ } else if (itemSrc == 0x34) {
+ characterTalk(1310);
+ return 1;
+ } else if (itemSrc == 0x5b) {
+ characterTalk(1226);
+ replaceItemFromInventory(91, 92);
+ return 1;
+ } else if (itemSrc == 92) {
+ characterTalk(1220);
+ return 1;
+ }
+
+ break;
+ case 55:
+ if (itemSrc == 16) {
+ createMouseItem(98);
+ characterTalk(1400);
+ return 1;
+ }
+ break;
+ case 61:
+ if (itemSrc == 0x1f) {
+ characterTalk(1412);
+ deleteItemFromInventory(31);
+ createMouseItem(62);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x21 || itemSrc == 0x22) {
+ characterTalk(1414);
+ return 1;
+ }
+ break;
+ case 64:
+ if (itemSrc == 0xb) {
+ sayLines(2, 1212);
+ return 1;
+ } else if (itemSrc == 0x5e || itemSrc == 0x5f) {
+ characterTalk(1318);
+ return 1;
+ }
+ break;
+ case 66:
+ if (itemSrc == 15) {
+ characterTalk(1492);
+ return 1;
+ } else if (itemSrc == 0x2f) {
+ characterTalk(1488);
+ return 1;
+ } else if (itemSrc == 88) {
+ sayLines(2, 1478);
+ characterTalk(1478);
+ return 1;
+ }
+ break;
+ case 67:
+ if (itemSrc == 79) {
+ sayLines(2, 1212);
+ return 1;
+ }
+ break;
+ case 68:
+ if (itemSrc == 35) {
+ createMouseItem(69);
+ replaceItemFromInventory(35, 36);
+ return 1;
+ } else if (itemSrc == 0x24) {
+ createMouseItem(69);
+ replaceItemFromInventory(36, 37);
+ return 1;
+ } else if (itemSrc == 37) {
+ deleteItemFromInventory(37);
+ createMouseItem(69);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x6b || itemSrc == 113 || itemSrc == 0x6f || itemSrc == 109) {
+ sayLines(2, 1288);
+ return 1;
+ }
+ break;
+ case 69:
+ switch (itemSrc) {
+ case 107:
+ characterTalk(1296);
+ replaceItemFromInventory(107, 108);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);;
+ rearrangeInventory();
+ return 1;
+ case 109:
+ characterTalk(1298);
+ replaceItemFromInventory(109, 110);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ case 111:
+ characterTalk(1296);
+ replaceItemFromInventory(111, 112);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ case 113:
+ characterTalk(1298);
+ replaceItemFromInventory(113, 114);
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ return 1;
+ }
+ break;
+ case 71:
+ if (itemSrc == 0xc || itemSrc == 1 || itemSrc == 0x41 || itemSrc == 67 || itemSrc == 0x4c || itemSrc == 57) {
+ sayLines(2, 1212);
+ return 1;
+ } else if (itemSrc == 79) {
+ characterTalk(1238);
+ return 1;
+ }
+ break;
+ case 79:
+ if (itemSrc == 1 || itemSrc == 67 || itemSrc == 76 || itemSrc == 57 || itemSrc == 0x41) {
+ sayLines(2, 1212);
+ return 1;
+ } else if (itemSrc == 0x18) {
+ characterTalk(1280);
+ return 1;
+ } else if (itemSrc == 0x47) {
+ characterTalk(1238);
+ return 1;
+ }
+ break;
+ case 82:
+ if (itemSrc == 84) {
+ sayLines(2, 1424);
+ return 1;
+ } else if (itemSrc == 0x58) {
+ deleteItemFromInventory(88);
+ createMouseItem(89);
+ rearrangeInventory();
+ characterTalk(1428);
+ return 1;
+ } else if (itemSrc == 117) {
+ sayLines(2, 1496);
+ return 1;
+ }
+ break;
+ case 84:
+ if (itemSrc == 0x58) {
+ replaceItemFromInventory(88, 90);
+ characterTalk(1090);
+ return 1;
+ } else if (itemSrc == 117) {
+ characterTalk(1494);
+ return 1;
+ }
+ break;
+ case 88:
+ if (itemSrc == 82) {
+ deleteItemFromInventory(82);
+ createMouseItem(89);
+ rearrangeInventory();
+ characterTalk(1428);
+ return 1;
+ } else if (itemSrc == 0x54) {
+ createMouseItem(90);
+ characterTalk(1090);
+ return 1;
+ } else if (itemSrc == 102) {
+ deleteItemFromInventory(102);
+ createMouseItem(90);
+ rearrangeInventory();
+ characterTalk(1090);
+ return 1;
+ }
+ break;
+ case 89:
+ if (itemSrc == 117) {
+ sayLines(2, 1496);
+ return 1;
+ }
+ break;
+ case 90:
+ if (itemSrc == 117) {
+ sayLines(2, 1494);
+ return 1;
+ }
+ break;
+ case 91:
+ if (itemSrc == 0x28) {
+ characterTalk(1230);
+ return 1;
+ } else if (itemSrc == 54) {
+ createMouseItem(92);
+ return 1;
+ }
+ break;
+ case 92:
+ if (itemSrc == 0x28 || itemSrc == 54) {
+ characterTalk(1220);
+ return 1;
+ }
+ break;
+ case 94:
+ if (itemSrc == 26) {
+ characterTalk(1316);
+ return 1;
+ } else if (itemSrc == 0x34) {
+ characterTalk(1282);
+ return 1;
+ } else if (itemSrc == 64) {
+ characterTalk(1318);
+ return 1;
+ }
+ break;
+ case 95:
+ if (itemSrc == 26) {
+ characterTalk(1320);
+ return 1;
+ } else if (itemSrc == 0x40) {
+ characterTalk(1318);
+ return 1;
+ } else if (itemSrc == 115) {
+ characterTalk(1284);
+ replaceItemFromInventory(115, 116);
+ createMouseItem(93);
+ return 1;
+ }
+ break;
+ case 96:
+ if (itemSrc == 0x34) {
+ characterTalk(1234);
+ return 1;
+ } else if (itemSrc == 71) {
+ sayLines(2, 1212);
+ return 1;
+ }
+ break;
+ case 97:
+ if (itemSrc == 15) {
+ characterTalk(1492);
+ return 1;
+ } else if (itemSrc == 0x2f) {
+ characterTalk(1488);
+ return 1;
+ } else if (itemSrc == 88) {
+ sayLines(2, 1478);
+ return 1;
+ }
+ break;
+ case 100:
+ if (itemSrc == 117) {
+ characterTalk(1490);
+ return 1;
+ }
+ break;
+ case 102:
+ if (itemSrc == -1) {
+ characterTalk(1102);
+ return 1;
+ } else if (itemSrc == 84) {
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ rearrangeInventory();
+ characterTalk(1418);
+ return 1;
+ } else if (itemSrc == 88) {
+ deleteItemFromInventory(88);
+ createMouseItem(90);
+ rearrangeInventory();
+ characterTalk(1090);
+ return 1;
+ } else if (itemSrc == 117) {
+ characterTalk(1494);
+ return 1;
+ } else {
+ characterTalk(1426);
+ return 1;
+ }
+ break;
+ case 106:
+ if (itemSrc == 13) {
+ characterTalk(1308);
+ return 1;
+ }
+ break;
+ case 107:
+ if (itemSrc == 19) {
+ sayLines(2, 1300);
+ deleteItemFromInventory(19);
+ createMouseItem(111);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x15) {
+ characterTalk(1296);
+ deleteItemFromInventory(21);
+ createMouseItem(109);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x23) {
+ characterTalk(1314);
+ return 1;
+ } else if (itemSrc == 69) {
+ characterTalk(1296);
+ deleteItemFromInventory(69);
+ createMouseItem(108);
+ rearrangeInventory();
+ return 1;
+ }
+ break;
+ case 108:
+ if (itemSrc == 19) {
+ sayLines(2, 1300);
+ deleteItemFromInventory(19);
+ createMouseItem(112);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x15) {
+ characterTalk(1298);
+ deleteItemFromInventory(21);
+ createMouseItem(110);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 35) {
+ characterTalk(1314);
+ return 1;
+ }
+ break;
+ case 109:
+ if (itemSrc == 19) {
+ sayLines(2, 1300);
+ deleteItemFromInventory(19);
+ createMouseItem(113);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x23) {
+ characterTalk(1314);
+ return 1;
+ } else if (itemSrc == 69) {
+ characterTalk(1298);
+ deleteItemFromInventory(69);
+ createMouseItem(110);
+ rearrangeInventory();
+ return 1;
+ }
+ break;
+ case 110:
+ if (itemSrc == 0x13) {
+ sayLines(2, 1300);
+ deleteItemFromInventory(19);
+ createMouseItem(114);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 35) {
+ characterTalk(1314);
+ return 1;
+ }
+ break;
+ case 111:
+ if (itemSrc == 21) {
+ characterTalk(1296);
+ deleteItemFromInventory(21);
+ createMouseItem(113);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 0x23) {
+ characterTalk(1314);
+ return 1;
+ } else if (itemSrc == 69) {
+ characterTalk(1296);
+ deleteItemFromInventory(69);
+ createMouseItem(112);
+ rearrangeInventory();
+ return 1;
+ }
+ break;
+ case 112:
+ if (itemSrc == 0x15) {
+ characterTalk(1298);
+ deleteItemFromInventory(21);
+ createMouseItem(114);
+ rearrangeInventory();
+ return 1;
+ } else if (itemSrc == 35) {
+ characterTalk(1314);
+ return 1;
+ }
+ break;
+ case 113:
+ if (itemSrc == 0x23) {
+ characterTalk(1314);
+ return 1;
+ } else if (itemSrc == 69) {
+ characterTalk(1298);
+ deleteItemFromInventory(69);
+ createMouseItem(114);
+ rearrangeInventory();
+ return 1;
+ }
+ break;
+ case 114:
+ if (itemSrc == 35) {
+ characterTalk(1314);
+ return 1;
+ }
+ break;
+ case 115:
+ if (itemSrc == 95) {
+ replaceItemFromInventory(95, 93);
+ createMouseItem(116);
+ return 1;
+ }
+ break;
+ case 117:
+ if (itemSrc == 90 || itemSrc == 33) {
+ characterTalk(1490);
+ } else if (itemSrc == 102 || itemSrc == 84) {
+ characterTalk(1494);
+ } else if (itemSrc == 0x59 || itemSrc == 0x52) {
+ characterTalk(1496);
+ }
+ }
+ return 0;
+}
+int32 ToonEngine::handleInventoryOnDrew(int32 itemId) {
+ switch (itemId) {
+ case 1:
+ sayLines(1, 1232);
+ return 1;
+ case 2:
+ sayLines(2, 1202);
+ return 1;
+ case 7:
+ if (_gameState->_currentScene == 32) {
+ runEventScript(_mouseX, _mouseY, 2, 107, 0);
+ } else if (_gameState->_currentScene < 37) {
+ sayLines(2, 1258);
+ } else {
+ sayLines(2, 1462);
+ }
+ return 1;
+ case 8:
+ sayLines(2, 1328);
+ return 1;
+ case 0xc:
+ sayLines(1, 1266);
+ return 1;
+ case 0xd:
+ sayLines(1, 1206);
+ return 1;
+ case 16:
+ sayLines(1, 1438);
+ return 1;
+ case 0x12:
+ if (_gameState->_currentScene == 30) {
+ runEventScript(_mouseX, _mouseY, 2, 106, 0);
+ _gameState->_mouseState = -1;
+ } else {
+ sayLines(2, 1200);
+ }
+ return 1;
+ case 0x14:
+ sayLines(1, 1216);
+ return 1;
+ case 22:
+ if (_gameState->_currentScene != 39 && _gameState->_currentScene != 50 && _gameState->_currentScene != 49) {
+ if (_gameState->_currentScene < 37) {
+ sayLines(1, 1256);
+ } else {
+ sayLines(1, 1456);
+ }
+ } else {
+ runEventScript(_mouseX, _mouseY, 2, 100 , 0);
+ }
+ return 1;
+ case 0x18:
+ sayLines(1, 1216);
+ return 1;
+ case 0x23:
+ sayLines(1, 1210);
+ return 1;
+ case 0x31:
+ sayLines(1, 1262);
+ return 1;
+ case 50:
+ if (_gameState->_currentScene == 37) {
+ runEventScript(_mouseX, _mouseY, 2, 103, 0);
+ return 1;
+ };
+ break;
+ case 0x36:
+ if (_gameState->_currentScene == 46) {
+ runEventScript(_mouseX, _mouseY, 2, 102, 0);
+ } else {
+ sayLines(1, 1224);
+ }
+ return 1;
+ case 0x37:
+ sayLines(1, 1408);
+ return 1;
+ case 0x20:
+ sayLines(1, 1254);
+ return 1;
+ case 0x21:
+ sayLines(1, 1268);
+ return 1;
+ case 0x22:
+ if (_gameState->_currentScene == 52) {
+ runEventScript(_mouseX, _mouseY, 2, 104, 0);
+ return 1;
+ } else {
+ _gameState->_mouseHidden = true;
+ _drew->setFacing(4);
+ sayLines(1, 1465);
+ sayLines(1, randRange(0, 1) + 1468);
+ createMouseItem(33);
+ _gameState->_mouseHidden = false;
+ return 1;
+ }
+ break;
+ case 31:
+ sayLines(1, 1436);
+ return 1;
+ case 0x1a:
+ sayLines(1, 1216);
+ return 1;
+ case 0x39:
+ sayLines(1, 1270);
+ return 1;
+ case 0x3a:
+ sayLines(1, 1444);
+ return 1;
+ case 0x3b:
+ sayLines(1, 1272);
+ return 1;
+ case 0x3f:
+ if (_gameState->_currentScene != 10 && _gameState->_currentScene != 30 && _gameState->_currentScene != 22) {
+ sayLines(1, 1274);
+ } else {
+ runEventScript(_mouseX, _mouseY, 2, 109, 0);
+ }
+ return 1;
+ case 0x41:
+ sayLines(1, 1232);
+ return 1;
+
+ case 0x4b:
+ if (_gameState->_currentScene != 53) {
+ _gameState->_mouseHidden = true;
+ _drew->setFacing(4);
+ sayLines(1, 1437);
+ sayLines(2, 1440);
+ _gameState->_mouseHidden = false;
+ } else {
+ runEventScript(_mouseX, _mouseY, 2 , 101, 0);
+ }
+ return 1;
+ case 79:
+ sayLines(1, 1242);
+ return 1;
+ case 0x4c:
+ sayLines(1, 1232);
+ return 1;
+ case 71:
+ sayLines(1, 1250);
+ return 1;
+ case 0x43:
+ sayLines(1, 1216);
+ return 1;
+ case 0x60:
+ sayLines(2, 1236);
+ return 1;
+ case 99:
+ if (_gameState->_currentScene == 43) {
+ runEventScript(_mouseX, _mouseY, 2, 105, 0);
+ }
+ _gameState->_mouseState = -1;
+ setCursor(0, false, 0, 0);
+ sayLines(1, 1555);
+ return 1;
+ case 0x5a:
+ sayLines(1, 1432);
+ return 1;
+ case 0x58:
+ sayLines(1, 1432);
+ return 1;
+ case 0x65:
+ if (_gameState->_currentScene == 52) {
+ runEventScript(_mouseX, _mouseY, 2, 104, 0);
+ } else {
+ _gameState->_mouseHidden = true;
+ _drew->setFacing(4);
+ sayLines(1, 1464);
+ sayLines(1, 1468 + randRange(0, 1));
+ createMouseItem(100);
+ _gameState->_mouseHidden = false;
+ }
+ return 1;
+ case 0x74:
+ sayLines(1, 1286);
+ return 1;
+ case 0x75:
+ sayLines(1, 1482);
+ return 1;
+ case 118:
+ sayLines(2, 1500);
+ return 1;
+ case 115:
+ sayLines(1, 1216);
+ return 1;
+ case 0x67:
+ if (_gameState->_currentScene == 52 || _gameState->_currentScene == 53) {
+ runEventScript(_mouseX, _mouseY, 2, 108, 0);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+void ToonEngine::deleteItemFromInventory(int32 item) {
+ for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+ if (_gameState->_inventory[i] == item) {
+ _gameState->_inventory[i] = 0;
+ rearrangeInventory();
+ return;
+ }
+ }
+}
+
+void ToonEngine::replaceItemFromInventory(int32 item, int32 newitem) {
+ for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+ if (_gameState->_inventory[i] == item) {
+ _gameState->_inventory[i] = newitem;
+ return;
+ }
+ }
+}
+
+int32 ToonEngine::pauseSceneAnimationScript(int32 animScriptId, int32 tickToWait) {
+ int32 nextTicks = getTickLength() * tickToWait + getSceneAnimationScript(animScriptId)->_lastTimer;
+ if (nextTicks < getOldMilli()) {
+ getSceneAnimationScript(animScriptId)->_lastTimer = getOldMilli() + getTickLength() * tickToWait;
+ } else {
+ getSceneAnimationScript(animScriptId)->_lastTimer = nextTicks;
+ }
+ return nextTicks;
+}
+
+Common::String ToonEngine::createRoomFilename(Common::String name) {
+ Common::String file = Common::String::printf("ACT%d/%s/%s", _gameState->_currentChapter, _gameState->_locations[_gameState->_currentScene]._name, name.c_str());
+ return file;
+}
+
+void ToonEngine::createShadowLUT() {
+ // here we create the redirection table that will be used to draw shadows
+ // for each color of the palette we find the closest color in the palette that could be used for shadowed color.
+
+ // In the original program, the scale factor is 0.77f
+ // we will use 77 / 100 here.
+
+ if (!_shadowLUT) {
+ _shadowLUT = new uint8[256];
+ }
+
+ uint32 scaleNum = 77;
+ uint32 scaleDenom = 100;
+
+ for (int32 i = 0; i < 255; i++) {
+
+ // goal color
+ uint32 destR = _finalPalette[i*3+0] * scaleNum / scaleDenom;
+ uint32 destG = _finalPalette[i*3+1] * scaleNum / scaleDenom;
+ uint32 destB = _finalPalette[i*3+2] * scaleNum / scaleDenom;
+
+ // search only in the "picture palette" which is in colors 1-128 and 200-255
+ int32 colorDist = 0xffffff;
+ int32 foundColor = 0;
+
+ for (int32 c = 1; c < 129; c++) {
+
+ int32 diffR = _finalPalette[c*3+0] - destR;
+ int32 diffG = _finalPalette[c*3+1] - destG;
+ int32 diffB = _finalPalette[c*3+2] - destB;
+
+ if (colorDist > diffR * diffR + diffG * diffG + diffB * diffB) {
+ colorDist = diffR * diffR + diffG * diffG + diffB * diffB;
+ foundColor = c;
+ }
+ }
+
+ for (int32 c = 200; c < 256; c++) {
+
+ int32 diffR = _finalPalette[c*3+0] - destR;
+ int32 diffG = _finalPalette[c*3+1] - destG;
+ int32 diffB = _finalPalette[c*3+2] - destB;
+
+ if (colorDist > diffR * diffR + diffG * diffG + diffB * diffB) {
+ colorDist = diffR * diffR + diffG * diffG + diffB * diffB;
+ foundColor = c;
+ }
+ }
+
+ _shadowLUT[i] = foundColor;
+
+ }
+}
+
+bool ToonEngine::loadToonDat() {
+ Common::File in;
+ char buf[256];
+ int majVer, minVer;
+
+ in.open("toon.dat");
+
+ if (!in.isOpen()) {
+ Common::String errorMessage = "You're missing the 'toon.dat' file. Get it from the ScummVM website";
+ GUIErrorMessage(errorMessage);
+ warning("%s", errorMessage.c_str());
+ return false;
+ }
+
+ // Read header
+ in.read(buf, 4);
+ buf[4] = '\0';
+
+ if (strcmp(buf, "TOON")) {
+ Common::String errorMessage = "File 'toon.dat' is corrupt. Get it from the ScummVM website";
+ GUIErrorMessage(errorMessage);
+ warning("%s", errorMessage.c_str());
+ return false;
+ }
+
+ majVer = in.readByte();
+ minVer = in.readByte();
+
+ if ((majVer != TOON_DAT_VER_MAJ) || (minVer != TOON_DAT_VER_MIN)) {
+ snprintf(buf, 256, "File 'toon.dat' is wrong version. Expected %d.%d but got %d.%d. Get it from the ScummVM website", TOON_DAT_VER_MAJ, TOON_DAT_VER_MIN, majVer, minVer);
+ GUIErrorMessage(buf);
+ warning("%s", buf);
+
+ return false;
+ }
+
+ _numVariant = in.readUint16BE();
+
+ _locationDirNotVisited = loadTextsVariante(in);
+ _locationDirVisited = loadTextsVariante(in);
+ _specialInfoLine = loadTextsVariante(in);
+
+ return true;
+}
+
+char **ToonEngine::loadTextsVariante(Common::File &in) {
+ int numTexts;
+ int entryLen;
+ int len;
+ char **res = 0;
+ char *pos = 0;
+
+ for (int varnt = 0; varnt < _numVariant; varnt++) {
+ numTexts = in.readUint16BE();
+ entryLen = in.readUint16BE();
+ pos = (char *)malloc(entryLen);
+ if (varnt == _gameVariant) {
+ res = (char **)malloc(sizeof(char *) * numTexts);
+ res[0] = pos;
+ in.read(res[0], entryLen);
+ res[0] += DATAALIGNMENT;
+ } else {
+ in.read(pos, entryLen);
+ }
+
+ pos += DATAALIGNMENT;
+
+ for (int i = 1; i < numTexts; i++) {
+ pos -= 2;
+
+ len = READ_BE_UINT16(pos);
+ pos += 2 + len;
+
+ if (varnt == _gameVariant)
+ res[i] = pos;
+ }
+ }
+
+ return res;
+}
+
+void ToonEngine::makeLineNonWalkable( int32 x, int32 y, int32 x2, int32 y2 ) {
+ _currentMask->drawLineOnMask(x,y,x2,y2,false);
+}
+
+void ToonEngine::makeLineWalkable( int32 x, int32 y, int32 x2, int32 y2 ) {
+ _currentMask->drawLineOnMask(x,y,x2,y2,true);
+}
+
+void SceneAnimation::save(ToonEngine* vm, Common::WriteStream *stream) {
+ stream->writeByte(_active);
+ stream->writeSint32BE(_id);
+
+ if (!_active)
+ return;
+
+ if (_animInstance) {
+ stream->writeByte(1);
+ _animInstance->save(stream);
+ }
+ else {
+ stream->writeByte(0);
+ }
+
+ if (!_animation) {
+ stream->writeByte(0);
+ }
+ else {
+ stream->writeByte(strlen(_animation->_name)+1);
+ stream->write(_animation->_name, strlen(_animation->_name)+1);
+ }
+}
+void SceneAnimation::load(ToonEngine* vm,Common::ReadStream *stream) {
+
+ _active = stream->readByte();
+ _id = stream->readSint32BE();
+
+
+ if (!_active)
+ return;
+
+ if (stream->readByte() == 1) {
+ _animInstance = vm->getAnimationManager()->createNewInstance(kAnimationScene);
+ _animInstance->load(stream);
+ vm->getAnimationManager()->addInstance(_animInstance);
+ }
+
+ // load animation if any
+ char animationName[256];
+ *animationName = 0;
+ int8 strSize = stream->readByte();
+ if (!strSize) {
+ _animation = 0;
+ if(_animInstance)
+ _animInstance->setAnimation(0);
+ }
+ else {
+ stream->read(animationName, strSize);
+ animationName[strSize] = 0;
+
+ _animation = new Animation(vm);
+ _animation->loadAnimation(animationName);
+
+ if(_animInstance)
+ _animInstance->setAnimation(_animation, false);
+
+ printf("load animation instance %d / %s / visible %d \n", _id, _animation->_name, _animInstance->getVisible());
+ }
+}
+
+} // End of namespace Toon