diff options
Diffstat (limited to 'engines/kyra/text_mr.cpp')
-rw-r--r-- | engines/kyra/text_mr.cpp | 817 |
1 files changed, 817 insertions, 0 deletions
diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp new file mode 100644 index 0000000000..4f3c350099 --- /dev/null +++ b/engines/kyra/text_mr.cpp @@ -0,0 +1,817 @@ +/* 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 "kyra/text_mr.h" +#include "kyra/screen_mr.h" +#include "kyra/resource.h" + +namespace Kyra { + +TextDisplayer_MR::TextDisplayer_MR(KyraEngine_MR *vm, Screen_MR *screen) + : TextDisplayer(vm, screen), _vm(vm), _screen(screen) { +} + +char *TextDisplayer_MR::preprocessString(const char *str) { + debugC(9, kDebugLevelMain, "TextDisplayer_MR::preprocessString('%s')", str); + if (_talkBuffer != str) + strncpy(_talkBuffer, str, sizeof(_talkBuffer)); + + char *p = _talkBuffer; + while (*p) { + if (*p++ == '\r') + return _talkBuffer; + } + + p = _talkBuffer; + Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); + _screen->_charWidth = -2; + + const int maxTextWidth = (_vm->language() == 0) ? 176 : 240; + int textWidth = _screen->getTextWidth(p); + + if (textWidth > maxTextWidth) { + int count = 0, offs = 0; + if (textWidth > (3*maxTextWidth)) { + count = getCharLength(p, textWidth/4); + offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count); + p += count + offs; + } + + if (textWidth > (2*maxTextWidth)) { + count = getCharLength(p, textWidth/3); + offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count); + p += count + offs; + textWidth = _screen->getTextWidth(p); + } + + count = getCharLength(p, textWidth/2); + offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count); + p += count + offs; + textWidth = _screen->getTextWidth(p); + + if (textWidth > maxTextWidth) { + count = getCharLength(p, textWidth/2); + offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count); + } + } + + _screen->setFont(curFont); + return _talkBuffer; +} + +int TextDisplayer_MR::dropCRIntoString(char *str, int minOffs, int maxOffs) { + debugC(9, kDebugLevelMain, "TextDisplayer_MR::dropCRIntoString('%s', %d, %d)", str, maxOffs, minOffs); + + int offset = 0; + char *proc = str + minOffs; + + for (int i = minOffs; i < maxOffs; ++i) { + if (*proc == ' ') { + *proc = '\r'; + return offset; + } else if (*proc == '-') { + memmove(proc+1, proc, strlen(proc)+1); + *(++proc) = '\r'; + ++offset; + return offset; + } + + ++offset; + ++proc; + + if (!*proc) + return 0; + } + + offset = 0; + proc = str + minOffs; + for (int i = minOffs; i >= 0; --i) { + if (*proc == ' ') { + *proc = '\r'; + return offset; + } else if (*proc == '-') { + memmove(proc+1, proc, strlen(proc)+1); + *(++proc) = '\r'; + ++offset; + return offset; + } + + --offset; + --proc; + + if (!*proc) + return 0; + } + + *(str + minOffs) = '\r'; + return 0; +} + +void TextDisplayer_MR::printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font) { + debugC(9, kDebugLevelMain, "TextDisplayer_MR::printText('%s', %d, %d, %d, %d, %d)", str, x, y, c0, c1, c2); + uint8 colorMap[] = { 0, 255, 240, 240 }; + colorMap[3] = c1; + _screen->setTextColor(colorMap, 0, 3); + Screen::FontId curFont = _screen->setFont(font); + _screen->_charWidth = -2; + _screen->printText(str, x, y, c0, c2); + _screen->_charWidth = 0; + _screen->setFont(curFont); +} + +void TextDisplayer_MR::restoreScreen() { + debugC(9, kDebugLevelMain, "TextDisplayer_MR::restoreScreen()"); + _vm->restorePage3(); + _vm->drawAnimObjects(); + _screen->hideMouse(); + _screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, 2, 0, Screen::CR_NO_P_CHECK); + _screen->showMouse(); + _vm->flagAnimObjsForRefresh(); + _vm->refreshAnimObjects(0); +} + +void TextDisplayer_MR::calcWidestLineBounds(int &x1, int &x2, int w, int x) { + debugC(9, kDebugLevelMain, "TextDisplayer_MR::calcWidestLineBounds(%d, %d)", w, x); + x1 = x; + x1 -= (w >> 1); + x2 = x1 + w + 1; + + if (x1 + w >= 311) + x1 = 311 - w - 1; + + if (x1 < 8) + x1 = 8; + + x2 = x1 + w + 1; +} + +#pragma mark - + +int KyraEngine_MR::chatGetType(const char *str) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::chatGetType('%s')", str); + while (*str) + ++str; + --str; + switch (*str) { + case '!': + return 2; + + case ')': + return 3; + + case '?': + return 1; + + case '.': + default: + return 0; + } +} + +int KyraEngine_MR::chatCalcDuration(const char *str) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::chatCalcDuration('%s')", str); + return MAX<int>(120, strlen(str)*6); +} + +void KyraEngine_MR::objectChat(const char *str, int object, int vocHigh, int vocLow) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::objectChat('%s', %d, %d, %d)", str, object, vocHigh, vocLow); + + if (_mainCharacter.animFrame == 87 || _mainCharacter.animFrame == 0xFFFF || _mainCharacter.x1 <= 0 || _mainCharacter.y1 <= 0) + return; + + _chatVocLow = _chatVocHigh = -1; + objectChatInit(str, object, vocHigh, vocLow); + _chatText = str; + _chatObject = object; + int chatType = chatGetType(str); + + if (_mainCharacter.facing > 7) + _mainCharacter.facing = 5; + + static const uint8 talkScriptTable[] = { + 0x10, 0x11, 0x12, 0x13, + 0x0C, 0x0D, 0x0E, 0x0F, + 0x0C, 0x0D, 0x0E, 0x0F, + 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, + 0x00, 0x01, 0x02, 0x03, + 0x08, 0x09, 0x0A, 0x0B, + 0x08, 0x09, 0x0A, 0x0B + }; + + static const char *talkFilenameTable[] = { + "MTFL00S.EMC", "MTFL00Q.EMC", "MTFL00E.EMC", "MTFL00T.EMC", + "MTFR00S.EMC", "MTFR00Q.EMC", "MTFR00E.EMC", "MTFR00T.EMC", + "MTL00S.EMC", "MTL00Q.EMC", "MTL00E.EMC", "MTL00T.EMC", + "MTR00S.EMC", "MTR00Q.EMC", "MTR00E.EMC", "MTR00T.EMC", + "MTA00S.EMC", "MTA00Q.EMC", "MTA00Q.EMC", "MTA00T.EMC" + }; + + int chat = talkScriptTable[chatType + _mainCharacter.facing * 4]; + objectChatProcess(talkFilenameTable[chat]); + _text->restoreScreen(); + _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing]; + updateCharacterAnim(0); + _chatText = 0; + _chatObject = -1; + setNextIdleAnimTimer(); +} + +void KyraEngine_MR::objectChatInit(const char *str, int object, int vocHigh, int vocLow) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::objectChatInit('%s', %d, %d, %d)", str, object, vocHigh, vocLow); + str = _text->preprocessString(str); + int lineNum = _text->buildMessageSubstrings(str); + + int xPos = 0, yPos = 0; + + if (!object) { + int scale = getScale(_mainCharacter.x1, _mainCharacter.y1); + yPos = _mainCharacter.y1 - ((_mainCharacter.height * scale) >> 8) - 8; + xPos = _mainCharacter.x1; + } else { + yPos = _talkObjectList[object].y; + xPos = _talkObjectList[object].x; + } + + yPos -= lineNum * 10; + yPos = MAX(yPos, 0); + _text->_talkMessageY = yPos; + _text->_talkMessageH = lineNum*10; + + int width = _text->getWidestLineWidth(lineNum); + _text->calcWidestLineBounds(xPos, yPos, width, xPos); + _text->_talkCoords.x = xPos; + _text->_talkCoords.w = width + 2; + + restorePage3(); + + _screen->hideMouse(); + + if (textEnabled()) { + objectChatPrintText(str, object); + _chatEndTime = _system->getMillis() + chatCalcDuration(str) * _tickLength; + } else { + _chatEndTime = _system->getMillis(); + } + + if (speechEnabled()) { + _chatVocHigh = vocHigh; + _chatVocLow = vocLow; + } else { + _chatVocHigh = _chatVocLow = -1; + } + + _screen->showMouse(); +} + +void KyraEngine_MR::objectChatPrintText(const char *str, int object) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::objectChatPrintText('%s', %d)", str, object); + int c1 = _talkObjectList[object].color; + str = _text->preprocessString(str); + int lineNum = _text->buildMessageSubstrings(str); + int maxWidth = _text->getWidestLineWidth(lineNum); + int x = (object == 0) ? _mainCharacter.x1 : _talkObjectList[object].x; + int cX1 = 0, cX2 = 0; + _text->calcWidestLineBounds(cX1, cX2, maxWidth, x); + + for (int i = 0; i < lineNum; ++i) { + str = &_text->_talkSubstrings[i*_text->maxSubstringLen()]; + + int y = _text->_talkMessageY + i * 10; + x = _text->getCenterStringX(str, cX1, cX2); + + _text->printText(str, x, y, c1, 0xF0, 0); + } +} + +void KyraEngine_MR::objectChatProcess(const char *script) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::objectChatProcess('%s')", script); + + memset(&_chatScriptData, 0, sizeof(_chatScriptData)); + memset(&_chatScriptState, 0, sizeof(_chatScriptState)); + + _emc->load(script, &_chatScriptData, &_opcodesTemporary); + _emc->init(&_chatScriptState, &_chatScriptData); + _emc->start(&_chatScriptState, 0); + while (_emc->isValid(&_chatScriptState)) + _emc->run(&_chatScriptState); + + if (_chatVocHigh >= 0) { + playVoice(_chatVocHigh, _chatVocLow); + _chatVocHigh = _chatVocLow = -1; + } + + _useFrameTable = true; + objectChatWaitToFinish(); + _useFrameTable = false; + + _emc->unload(&_chatScriptData); +} + +void KyraEngine_MR::objectChatWaitToFinish() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::objectChatWaitToFinish()"); + int charAnimFrame = _mainCharacter.animFrame; + setCharacterAnimDim(_newShapeWidth, _newShapeHeight); + + _emc->init(&_chatScriptState, &_chatScriptData); + _emc->start(&_chatScriptState, 1); + + bool running = true; + const uint32 endTime = _chatEndTime; + resetSkipFlag(); + + while (running && !_quitFlag) { + if (!_emc->isValid(&_chatScriptState)) + _emc->start(&_chatScriptState, 1); + + _temporaryScriptExecBit = false; + while (!_temporaryScriptExecBit && _emc->isValid(&_chatScriptState)) { + musicUpdate(0); + _emc->run(&_chatScriptState); + } + + int curFrame = _newShapeAnimFrame; + uint32 delayTime = _newShapeDelay; + + _mainCharacter.animFrame = curFrame; + updateCharacterAnim(0); + + uint32 nextFrame = _system->getMillis() + delayTime * _tickLength; + + while (_system->getMillis() < nextFrame && !_quitFlag) { + updateWithText(); + + const uint32 curTime = _system->getMillis(); + if ((textEnabled() && !speechEnabled() && curTime > endTime) || (speechEnabled() && !snd_voiceIsPlaying()) || skipFlag()) { + snd_stopVoice(); + resetSkipFlag(); + nextFrame = curTime; + running = false; + } + + delay(10); + } + } + + _mainCharacter.animFrame = charAnimFrame; + updateCharacterAnim(0); + resetCharacterAnimDim(); +} + +void KyraEngine_MR::badConscienceChat(const char *str, int vocHigh, int vocLow) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::badConscienceChat('%s', %d, %d)", str, vocHigh, vocLow); + if (!_badConscienceShown) + return; + + setNextIdleAnimTimer(); + _chatVocHigh = _chatVocLow = -1; + objectChatInit(str, 1, vocHigh, vocLow); + _chatText = str; + _chatObject = 1; + badConscienceChatWaitToFinish(); + updateSceneAnim(0x0E, _badConscienceFrameTable[_badConscienceAnim+16]); + _text->restoreScreen(); + update(); + _chatText = 0; + _chatObject = -1; +} + +void KyraEngine_MR::badConscienceChatWaitToFinish() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::badConscienceChatWaitToFinish()"); + if (_chatVocHigh) { + playVoice(_chatVocHigh, _chatVocLow); + _chatVocHigh = _chatVocLow = -1; + } + + bool running = true; + const uint32 endTime = _chatEndTime; + resetSkipFlag(); + + uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; + + int frame = _badConscienceFrameTable[_badConscienceAnim+24]; + while (running && !_quitFlag) { + if (nextFrame < _system->getMillis()) { + ++frame; + if (_badConscienceFrameTable[_badConscienceAnim+32] < frame) + frame = _badConscienceFrameTable[_badConscienceAnim+24]; + + updateSceneAnim(0x0E, frame); + updateWithText(); + + nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; + } + + updateWithText(); + + const uint32 curTime = _system->getMillis(); + if ((textEnabled() && !speechEnabled() && curTime > endTime) || (speechEnabled() && !snd_voiceIsPlaying()) || skipFlag()) { + snd_stopVoice(); + resetSkipFlag(); + nextFrame = curTime; + running = false; + } + + delay(10); + } +} + +void KyraEngine_MR::goodConscienceChat(const char *str, int vocHigh, int vocLow) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::goodConscienceChat('%s', %d, %d)", str, vocHigh, vocLow); + if (!_goodConscienceShown) + return; + + setNextIdleAnimTimer(); + _chatVocHigh = _chatVocLow = -1; + objectChatInit(str, 87, vocHigh, vocLow); + _chatText = str; + _chatObject = 87; + goodConscienceChatWaitToFinish(); + updateSceneAnim(0x0F, _goodConscienceFrameTable[_goodConscienceAnim+10]); + _text->restoreScreen(); + update(); + _chatText = 0; + _chatObject = -1; +} + +void KyraEngine_MR::goodConscienceChatWaitToFinish() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::goodConscienceChatWaitToFinish()"); + if (_chatVocHigh) { + playVoice(_chatVocHigh, _chatVocLow); + _chatVocHigh = _chatVocLow = -1; + } + + bool running = true; + const uint32 endTime = _chatEndTime; + resetSkipFlag(); + + uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(3, 6) * _tickLength; + + int frame = _goodConscienceFrameTable[_goodConscienceAnim+15]; + while (running && !_quitFlag) { + if (nextFrame < _system->getMillis()) { + ++frame; + if (_goodConscienceFrameTable[_goodConscienceAnim+20] < frame) + frame = _goodConscienceFrameTable[_goodConscienceAnim+15]; + + updateSceneAnim(0x0F, frame); + updateWithText(); + + nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(3, 6) * _tickLength; + } + + updateWithText(); + + const uint32 curTime = _system->getMillis(); + if ((textEnabled() && !speechEnabled() && curTime > endTime) || (speechEnabled() && !snd_voiceIsPlaying()) || skipFlag()) { + snd_stopVoice(); + resetSkipFlag(); + nextFrame = curTime; + running = false; + } + + delay(10); + } +} + +void KyraEngine_MR::malcolmSceneStartupChat() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::malcolmSceneStartupChat()"); + + if (_noStartupChat) + return; + + int index = _mainCharacter.sceneId - _chapterLowestScene[_currentChapter]; + if (_newSceneDlgState[index]) + return; + + updateDlgBuffer(); + int vocHighBase = 0, vocHighIndex = 0, index1 = 0, index2 = 0; + loadDlgHeader(vocHighBase, vocHighIndex, index1, index2); + + _cnvFile->seek(index1*6, SEEK_CUR); + _cnvFile->seek(index2*4, SEEK_CUR); + _cnvFile->seek(index*2, SEEK_CUR); + _cnvFile->seek(_cnvFile->readUint16LE(), SEEK_SET); + + _isStartupDialog = true; + processDialog(vocHighIndex, vocHighBase, 0); + _isStartupDialog = false; + _newSceneDlgState[index] = true; +} + +void KyraEngine_MR::updateDlgBuffer() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::updateDlgBuffer()"); + char dlgFile[16]; + char cnvFile[16]; + + if (_cnvFile) + _cnvFile->seek(0, SEEK_SET); + + if (_curDlgIndex == _mainCharacter.dlgIndex && _curDlgChapter == _currentChapter && _curDlgLang == _lang) + return; + + snprintf(dlgFile, 16, "CH%.02d-S%.02d.", _currentChapter, _mainCharacter.dlgIndex); + appendLanguage(dlgFile, _lang, 16); + snprintf(cnvFile, 16, "CH%.02d-S%.02d.CNV", _currentChapter, _mainCharacter.dlgIndex); + + delete _cnvFile; + delete _dlgBuffer; + + _res->exists(cnvFile, true); + _res->exists(dlgFile, true); + _cnvFile = _res->getFileStream(cnvFile); + _dlgBuffer = _res->getFileStream(dlgFile); + assert(_cnvFile); + assert(_dlgBuffer); +} + +void KyraEngine_MR::loadDlgHeader(int &vocHighBase, int &vocHighIndex, int &index1, int &index2) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::loadDlgHeader(-, -, -, -)"); + assert(_cnvFile); + vocHighIndex = _cnvFile->readSint16LE(); + vocHighBase = _cnvFile->readSint16LE(); + index1 = _cnvFile->readSint16LE(); + index2 = _cnvFile->readSint16LE(); +} + +void KyraEngine_MR::setDlgIndex(uint16 index) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::setDlgIndex(%d)", index); + if (_mainCharacter.dlgIndex != index) { + Common::set_to(_newSceneDlgState, _newSceneDlgState+ARRAYSIZE(_newSceneDlgState), 0); + memset(_conversationState, -1, sizeof(_conversationState)); + _chatAltFlag = false; + _mainCharacter.dlgIndex = index; + } +} + +void KyraEngine_MR::updateDlgIndex() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::updateDlgIndex()"); + uint16 dlgIndex = _mainCharacter.dlgIndex; + + if (_currentChapter == 1) { + static const uint8 dlgIndexMoodNice[] = { 0x0C, 0x0E, 0x10, 0x0F, 0x11 }; + static const uint8 dlgIndexMoodNormal[] = { 0x00, 0x02, 0x04, 0x03, 0x05 }; + static const uint8 dlgIndexMoodEvil[] = { 0x06, 0x08, 0x0A, 0x09, 0x0B }; + + if (_malcolmsMood == 0) + dlgIndex = dlgIndexMoodNice[_malcolmShapes]; + else if (_malcolmsMood == 1) + dlgIndex = dlgIndexMoodNormal[_malcolmShapes]; + else if (_malcolmsMood == 2) + dlgIndex = dlgIndexMoodEvil[_malcolmShapes]; + } else if (_currentChapter == 2) { + if (dlgIndex >= 8) + dlgIndex -= 4; + if (dlgIndex >= 4) + dlgIndex -= 4; + + if (_malcolmsMood == 0) + dlgIndex += 8; + else if (_malcolmsMood == 2) + dlgIndex += 4; + } else if (_currentChapter == 4) { + if (dlgIndex >= 10) + dlgIndex -= 5; + if (dlgIndex >= 5) + dlgIndex -= 5; + + if (_malcolmsMood == 0) + dlgIndex += 10; + else if (_malcolmsMood == 2) + dlgIndex += 5; + } + + _mainCharacter.dlgIndex = dlgIndex; +} + +void KyraEngine_MR::processDialog(int vocHighIndex, int vocHighBase, int funcNum) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::processDialog(%d, %d, %d)", vocHighIndex, vocHighBase, funcNum); + bool running = true; + int script = -1; + int vocHigh = -1, vocLow = -1; + + while (running) { + uint16 cmd = _cnvFile->readUint16LE(); + int object = cmd - 12; + + if (cmd == 10) { + break; + } else if (cmd == 4) { + vocHighBase = _cnvFile->readUint16LE(); + setDlgIndex(vocHighBase); + } else if (cmd == 11) { + int strSize = _cnvFile->readUint16LE(); + vocLow = _cnvFile->readUint16LE(); + _cnvFile->read(_stringBuffer, strSize); + _stringBuffer[strSize] = 0; + } else { + vocHigh = _vocHighTable[vocHighIndex-1] + vocHighBase; + vocLow = _cnvFile->readUint16LE(); + getTableEntry(_dlgBuffer, vocLow, _stringBuffer); + + if (_isStartupDialog) { + delay(60*_tickLength, true); + _isStartupDialog = false; + } + + if (*_stringBuffer == 0) + continue; + + if (cmd != 12) { + if (object != script) { + if (script >= 0) { + dialogEndScript(script); + script = -1; + } + + dialogStartScript(object, funcNum); + script = object; + } + + npcChatSequence(_stringBuffer, object, vocHigh, vocLow); + } else { + if (script >= 0) { + dialogEndScript(script); + script = -1; + } + + objectChat(_stringBuffer, 0, vocHigh, vocLow); + playStudioSFX(_stringBuffer); + } + } + } + + if (script != -1) + dialogEndScript(script); +} + +void KyraEngine_MR::dialogStartScript(int object, int funcNum) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::dialogStartScript(%d, %d)", object, funcNum); + _dialogSceneAnim = _talkObjectList[object].sceneAnim; + _dialogSceneScript = _talkObjectList[object].sceneScript; + if (_dialogSceneAnim >= 0 && _dialogSceneScript >= 0) { + _specialSceneScriptStateBackup[_dialogSceneScript] = _specialSceneScriptState[_dialogSceneScript]; + _specialSceneScriptState[_dialogSceneScript] = true; + } + + _emc->init(&_dialogScriptState, &_dialogScriptData); + _emc->load(_talkObjectList[object].filename, &_dialogScriptData, &_opcodesDialog); + + _dialogScriptFuncStart = funcNum * 3 + 0; + _dialogScriptFuncProc = funcNum * 3 + 1; + _dialogScriptFuncEnd = funcNum * 3 + 2; + + _emc->start(&_dialogScriptState, _dialogScriptFuncStart); + while (_emc->isValid(&_dialogScriptState)) + _emc->run(&_dialogScriptState); +} + +void KyraEngine_MR::dialogEndScript(int object) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::dialogEndScript(%d)", object); + + _emc->init(&_dialogScriptState, &_dialogScriptData); + _emc->start(&_dialogScriptState, _dialogScriptFuncEnd); + + while (_emc->isValid(&_dialogScriptState)) + _emc->run(&_dialogScriptState); + + if (_dialogSceneAnim >= 0 && _dialogSceneScript >= 0) { + _specialSceneScriptState[_dialogSceneScript] = _specialSceneScriptStateBackup[_dialogSceneScript]; + _dialogSceneScript = _dialogSceneAnim = -1; + } + + _emc->unload(&_dialogScriptData); +} + +void KyraEngine_MR::npcChatSequence(const char *str, int object, int vocHigh, int vocLow) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::npcChatSequence('%s', %d, %d, %d)", str, object, vocHigh, vocLow); + + _chatText = str; + _chatObject = object; + _chatVocHigh = _chatVocLow = -1; + + objectChatInit(str, object, vocHigh, vocLow); + + if (_chatVocHigh >= 0 && _chatVocLow >= 0) { + playVoice(_chatVocHigh, _chatVocLow); + _chatVocHigh = _chatVocLow = -1; + } + + _emc->init(&_dialogScriptState, &_dialogScriptData); + _emc->start(&_dialogScriptState, _dialogScriptFuncProc); + + resetSkipFlag(); + + uint32 endTime = _chatEndTime; + bool running = true; + while (running) { + if (!_emc->run(&_dialogScriptState)) { + _emc->init(&_dialogScriptState, &_dialogScriptData); + _emc->start(&_dialogScriptState, _dialogScriptFuncProc); + } + + const uint32 curTime = _system->getMillis(); + if ((textEnabled() && !speechEnabled() && curTime > endTime) || (speechEnabled() && !snd_voiceIsPlaying()) || skipFlag()) { + snd_stopVoice(); + resetSkipFlag(); + running = false; + } + + delay(10); + } + _text->restoreScreen(); + _chatText = 0; + _chatObject= - 1; +} + +void KyraEngine_MR::malcolmRandomChat() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::malcolmRandomChat()"); + updateDlgBuffer(); + + int index = (_mainCharacter.sceneId - _chapterLowestScene[_currentChapter]) * 2; + + int vocHighBase = 0, vocHighIndex = 0, index1 = 0, index2 = 0; + loadDlgHeader(vocHighBase, vocHighIndex, index1, index2); + + if (_chatAltFlag) + index++; + _chatAltFlag = !_chatAltFlag; + + _cnvFile->seek(index1*6, SEEK_CUR); + _cnvFile->seek(index*2, SEEK_CUR); + _cnvFile->seek(_cnvFile->readUint16LE(), SEEK_SET); + + processDialog(vocHighIndex, vocHighBase, 0); +} + +void KyraEngine_MR::runDialog(int dlgIndex, int funcNum) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::runDialog(%d, %d)", dlgIndex, funcNum); + + switch (_currentChapter-2) { + case 0: + dlgIndex -= 34; + break; + + case 1: + dlgIndex -= 54; + break; + + case 2: + dlgIndex -= 55; + break; + + case 3: + dlgIndex -= 70; + break; + + default: + break; + } + + updateDlgBuffer(); + + int vocHighBase = 0, vocHighIndex = 0, index1 = 0, index2 = 0; + loadDlgHeader(vocHighBase, vocHighIndex, index1, index2); + + int convState = _conversationState[dlgIndex][vocHighBase]; + uint32 offset = ((vocHighIndex == 1) ? dlgIndex - 1 : dlgIndex) * 6; + if (convState == -1) { + _cnvFile->seek(offset, SEEK_CUR); + _conversationState[dlgIndex][vocHighBase] = 0; + } else if (convState == 0 || convState == 2) { + _cnvFile->seek(offset+2, SEEK_CUR); + _conversationState[dlgIndex][vocHighBase] = 1; + } else { + _cnvFile->seek(offset+4, SEEK_CUR); + _conversationState[dlgIndex][vocHighBase] = 2; + } + + _cnvFile->seek(_cnvFile->readUint16LE(), SEEK_SET); + + processDialog(vocHighIndex, vocHighBase, funcNum); +} + +} // end of namespace Kyra + |