aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/text_hof.cpp
diff options
context:
space:
mode:
authorJohannes Schickel2008-05-02 14:46:30 +0000
committerJohannes Schickel2008-05-02 14:46:30 +0000
commit4b5f3266cffa778b52f51a5a8cc39b16bac89584 (patch)
tree833f91d6f643e8d6b3b4c14ec18883a58cde28ac /engines/kyra/text_hof.cpp
parent3f44977885d33ea694df399a83cf198dd85b5fed (diff)
downloadscummvm-rg350-4b5f3266cffa778b52f51a5a8cc39b16bac89584.tar.gz
scummvm-rg350-4b5f3266cffa778b52f51a5a8cc39b16bac89584.tar.bz2
scummvm-rg350-4b5f3266cffa778b52f51a5a8cc39b16bac89584.zip
Started to refactor kyra2/kyra3 code to a common base. (regressions possible, compiling currently broken)
svn-id: r31817
Diffstat (limited to 'engines/kyra/text_hof.cpp')
-rw-r--r--engines/kyra/text_hof.cpp690
1 files changed, 690 insertions, 0 deletions
diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp
new file mode 100644
index 0000000000..43f28f9a00
--- /dev/null
+++ b/engines/kyra/text_hof.cpp
@@ -0,0 +1,690 @@
+/* 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_hof.h"
+#include "kyra/kyra_hof.h"
+#include "kyra/script_tim.h"
+#include "kyra/resource.h"
+
+#include "common/endian.h"
+
+namespace Kyra {
+
+TextDisplayer_v2::TextDisplayer_v2(KyraEngine_HoF *vm, Screen_v2 *screen)
+ : TextDisplayer(vm, screen), _vm(vm) {
+}
+
+void TextDisplayer_v2::backupTalkTextMessageBkgd(int srcPage, int dstPage) {
+ _screen->copyRegion(_talkCoords.x, _talkMessageY, 0, 144, _talkCoords.w, _talkMessageH, srcPage, dstPage);
+}
+
+void TextDisplayer_v2::restoreTalkTextMessageBkgd(int srcPage, int dstPage) {
+ _screen->copyRegion(0, 144, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, srcPage, dstPage);
+}
+
+void TextDisplayer_v2::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_v2::printCustomCharacterText(const char *text, int x, int y, uint8 c1, int srcPage, int dstPage) {
+ text = preprocessString(text);
+ int lineCount = buildMessageSubstrings(text);
+ int w = getWidestLineWidth(lineCount);
+ int h = lineCount * 10;
+ y = MAX(0, y - (lineCount * 10));
+ int x1 = 0, x2 = 0;
+ calcWidestLineBounds(x1, x2, w, x);
+
+ _screen->hideMouse();
+
+ _talkCoords.x = x1;
+ _talkCoords.w = w+2;
+ _talkCoords.y = y;
+ _talkMessageY = y;
+ _talkMessageH = h;
+
+ backupTalkTextMessageBkgd(srcPage, dstPage);
+ int curPageBackUp = _screen->_curPage;
+ _screen->_curPage = srcPage;
+
+ if (_vm->textEnabled()) {
+ for (int i = 0; i < lineCount; ++i) {
+ const char *msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN];
+ printText(msg, getCenterStringX(msg, x1, x2), i * 10 + _talkMessageY, c1, 0xCF, 0);
+ }
+ }
+
+ _screen->_curPage = curPageBackUp;
+ _screen->showMouse();
+}
+
+char *TextDisplayer_v2::preprocessString(const char *str) {
+ debugC(9, kDebugLevelMain, "TextDisplayer_v2::preprocessString('%s')", str);
+
+ if (str != _talkBuffer) {
+ assert(strlen(str) < sizeof(_talkBuffer) - 1);
+ strcpy(_talkBuffer, str);
+ }
+
+ char *p = _talkBuffer;
+ while (*p) {
+ if (*p == '\r')
+ return _talkBuffer;
+ ++p;
+ }
+
+ p = _talkBuffer;
+ Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT);
+ _screen->_charWidth = -2;
+ int textWidth = _screen->getTextWidth(p);
+ _screen->_charWidth = 0;
+
+ // longer text strings for German versions
+ int maxTextWidth = (_vm->language() == 2 ? 240 : 176);
+
+ if (textWidth > maxTextWidth) {
+ if (textWidth > (maxTextWidth*2)) {
+ int count = getCharLength(p, textWidth / 3);
+ int offs = dropCRIntoString(p, count);
+ p += count + offs;
+ _screen->_charWidth = -2;
+ textWidth = _screen->getTextWidth(p);
+ _screen->_charWidth = 0;
+ count = getCharLength(p, textWidth / 2);
+ dropCRIntoString(p, count);
+ } else {
+ int count = getCharLength(p, textWidth / 2);
+ dropCRIntoString(p, count);
+ }
+ }
+ _screen->setFont(curFont);
+ return _talkBuffer;
+}
+
+void TextDisplayer_v2::calcWidestLineBounds(int &x1, int &x2, int w, int x) {
+ debugC(9, kDebugLevelMain, "TextDisplayer_v2::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_HoF::chatGetType(const char *str) {
+ str += strlen(str);
+ --str;
+ switch (*str) {
+ case '!':
+ return 2;
+
+ case ')':
+ return -1;
+
+ case '?':
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+int KyraEngine_HoF::chatCalcDuration(const char *str) {
+ static const uint8 durationMultiplicator[] = { 16, 14, 12, 10, 8, 8, 7, 6, 5, 4 };
+
+ int duration = strlen(str);
+ duration *= _flags.isTalkie ? 8 : durationMultiplicator[(_configTextspeed / 10)];
+ return MAX<int>(duration, 120);
+}
+
+void KyraEngine_HoF::objectChat(const char *str, int object, int vocHigh, int vocLow) {
+ setNextIdleAnimTimer();
+
+ _chatVocHigh = _chatVocLow = -1;
+
+ objectChatInit(str, object, vocHigh, vocLow);
+ _chatText = str;
+ _chatObject = object;
+ int chatType = chatGetType(str);
+ if (chatType == -1) {
+ _chatIsNote = true;
+ chatType = 0;
+ }
+
+ if (_mainCharacter.facing > 7)
+ _mainCharacter.facing = 5;
+
+ static const uint8 talkScriptTable[] = {
+ 6, 7, 8,
+ 3, 4, 5,
+ 3, 4, 5,
+ 0, 1, 2,
+ 0, 1, 2,
+ 0, 1, 2,
+ 3, 4, 5,
+ 3, 4, 5
+ };
+
+ assert(_mainCharacter.facing * 3 + chatType < ARRAYSIZE(talkScriptTable));
+ int script = talkScriptTable[_mainCharacter.facing * 3 + chatType];
+
+ static const char *chatScriptFilenames[] = {
+ "_Z1FSTMT.EMC",
+ "_Z1FQUES.EMC",
+ "_Z1FEXCL.EMC",
+ "_Z1SSTMT.EMC",
+ "_Z1SQUES.EMC",
+ "_Z1SEXCL.EMC",
+ "_Z1BSTMT.EMC",
+ "_Z1BQUES.EMC",
+ "_Z1BEXCL.EMC"
+ };
+
+ objectChatProcess(chatScriptFilenames[script]);
+ _chatIsNote = false;
+
+ _text->restoreScreen();
+
+ _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
+ updateCharacterAnim(0);
+
+ _chatText = 0;
+ _chatObject = -1;
+
+ setNextIdleAnimTimer();
+}
+
+void KyraEngine_HoF::objectChatInit(const char *str, int object, int vocHigh, int vocLow) {
+ str = _text->preprocessString(str);
+ int lineNum = _text->buildMessageSubstrings(str);
+
+ int yPos = 0, xPos = 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();
+ _text->backupTalkTextMessageBkgd(2, 2);
+
+ _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_HoF::objectChatPrintText(const char *str, int 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, 0xCF, 0);
+ }
+}
+
+void KyraEngine_HoF::objectChatProcess(const char *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);
+
+ _newShapeFilename[2] = _loadedZTable + '0';
+ uint8 *shapeBuffer = _res->fileData(_newShapeFilename, 0);
+ if (shapeBuffer) {
+ int shapeCount = initNewShapes(shapeBuffer);
+
+ if (_chatVocHigh >= 0) {
+ playVoice(_chatVocHigh, _chatVocLow);
+ _chatVocHigh = _chatVocLow = -1;
+ }
+
+ objectChatWaitToFinish();
+
+ resetNewShapes(shapeCount, shapeBuffer);
+ } else {
+ warning("couldn't load file '%s'", _newShapeFilename);
+ }
+
+ _emc->unload(&_chatScriptData);
+}
+
+void KyraEngine_HoF::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))
+ _emc->run(&_chatScriptState);
+
+ int curFrame = _newShapeAnimFrame;
+ uint32 delayTime = _newShapeDelay;
+
+ if (!_chatIsNote)
+ _mainCharacter.animFrame = 33 + curFrame;
+
+ updateCharacterAnim(0);
+
+ uint32 nextFrame = _system->getMillis() + delayTime * _tickLength;
+
+ while (_system->getMillis() < nextFrame && !_quitFlag) {
+ updateWithText();
+
+ const uint32 curTime = _system->getMillis();
+ if ((textEnabled() && curTime > endTime) || (speechEnabled() && !textEnabled() && !snd_voiceIsPlaying()) || skipFlag()) {
+ resetSkipFlag();
+ nextFrame = curTime;
+ running = false;
+ }
+
+ delay(10);
+ }
+ }
+
+ _mainCharacter.animFrame = charAnimFrame;
+ updateCharacterAnim(0);
+ resetCharacterAnimDim();
+}
+
+void KyraEngine_HoF::startDialogue(int dlgIndex) {
+ updateDlgBuffer();
+ int csEntry, vocH, unused1, unused2;
+ loadDlgHeader(csEntry, vocH, unused1, unused2);
+ int s = _conversationState[dlgIndex][csEntry];
+ uint8 bufferIndex = 8;
+
+ if (s == -1) {
+ bufferIndex += (dlgIndex * 6);
+ _conversationState[dlgIndex][csEntry] = 0;
+ } else if (!s || s == 2) {
+ bufferIndex += (dlgIndex * 6 + 2);
+ _conversationState[dlgIndex][csEntry] = 1;
+ } else {
+ bufferIndex += (dlgIndex * 6 + 4);
+ _conversationState[dlgIndex][csEntry] = 2;
+ }
+
+ int offs = READ_LE_UINT16(_dlgBuffer + bufferIndex);
+ processDialogue(offs, vocH, csEntry);
+}
+
+void KyraEngine_HoF::zanthSceneStartupChat() {
+ int lowest = _flags.isTalkie ? 6 : 5;
+ int tableIndex = _mainCharacter.sceneId - READ_LE_UINT16(&_ingameTalkObjIndex[lowest + _newChapterFile]);
+ if (queryGameFlag(0x159) || _newSceneDlgState[tableIndex])
+ return;
+
+ int csEntry, vocH, scIndex1, scIndex2;
+ updateDlgBuffer();
+ loadDlgHeader(csEntry, vocH, scIndex1, scIndex2);
+
+ uint8 bufferIndex = 8 + scIndex1 * 6 + scIndex2 * 4 + tableIndex * 2;
+ int offs = READ_LE_UINT16(_dlgBuffer + bufferIndex);
+ processDialogue(offs, vocH, csEntry);
+
+ _newSceneDlgState[tableIndex] = 1;
+}
+
+void KyraEngine_HoF::zanthRandomIdleChat() {
+ int lowest = _flags.isTalkie ? 6 : 5;
+ int tableIndex = (_mainCharacter.sceneId - READ_LE_UINT16(&_ingameTalkObjIndex[lowest + _newChapterFile])) << 2;
+ if (queryGameFlag(0x164))
+ return;
+
+ int csEntry, vocH, scIndex1, unused;
+ updateDlgBuffer();
+ loadDlgHeader(csEntry, vocH, scIndex1, unused);
+
+ if (_chatAltFlag) {
+ _chatAltFlag = 0;
+ tableIndex += 2;
+ } else {
+ _chatAltFlag = 1;
+ }
+
+ uint8 bufferIndex = 8 + scIndex1 * 6 + tableIndex;
+ int offs = READ_LE_UINT16(_dlgBuffer + bufferIndex);
+ processDialogue(offs, vocH, csEntry);
+}
+
+void KyraEngine_HoF::updateDlgBuffer() {
+ static const char suffixTalkie[] = "EFG";
+ static const char suffixTowns[] = "G J";
+
+ if (_currentChapter == _npcTalkChpIndex && _mainCharacter.dlgIndex == _npcTalkDlgIndex)
+ return;
+
+ _npcTalkChpIndex = _currentChapter;
+ _npcTalkDlgIndex = _mainCharacter.dlgIndex;
+
+ char filename[13];
+ snprintf(filename, 13, "CH%.02d-S%.02d.DLG", _currentChapter, _npcTalkDlgIndex);
+
+ const char *suffix = _flags.isTalkie ? suffixTalkie : suffixTowns;
+ if (_flags.platform != Common::kPlatformPC || _flags.isTalkie)
+ filename[11] = suffix[_lang];
+
+ if (_dlgBuffer)
+ delete [] _dlgBuffer;
+
+ _dlgBuffer = _res->fileData(filename, 0);
+}
+
+void KyraEngine_HoF::loadDlgHeader(int &csEntry, int &vocH, int &scIndex1, int &scIndex2) {
+ csEntry = READ_LE_UINT16(_dlgBuffer);
+ vocH = READ_LE_UINT16(_dlgBuffer + 2);
+ scIndex1 = READ_LE_UINT16(_dlgBuffer + 4);
+ scIndex2 = READ_LE_UINT16(_dlgBuffer + 6);
+}
+
+void KyraEngine_HoF::processDialogue(int dlgOffset, int vocH, int csEntry) {
+ int activeTimSequence = -1;
+ int nextTimSequence = -1;
+ int cmd = 0;
+ int vocHi = -1;
+ int vocLo = -1;
+ bool loop = true;
+ int offs = dlgOffset;
+
+ _screen->hideMouse();
+
+ while (loop) {
+ cmd = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+
+ nextTimSequence = READ_LE_UINT16(&_ingameTalkObjIndex[cmd]);
+
+ if (nextTimSequence == 10) {
+ if (queryGameFlag(0x3e))
+ nextTimSequence = 14;
+ if (queryGameFlag(0x3f))
+ nextTimSequence = 15;
+ if (queryGameFlag(0x40))
+ nextTimSequence = 16;
+ }
+
+ if (nextTimSequence == 27 && _mainCharacter.sceneId == 34)
+ nextTimSequence = 41;
+
+ if (queryGameFlag(0x72)) {
+ if (nextTimSequence == 18)
+ nextTimSequence = 43;
+ else if (nextTimSequence == 19)
+ nextTimSequence = 44;
+ }
+
+ if (_mainCharacter.x1 > 160) {
+ if (nextTimSequence == 4)
+ nextTimSequence = 46;
+ else if (nextTimSequence == 5)
+ nextTimSequence = 47;
+ }
+
+ if (cmd == 10) {
+ loop = false;
+
+ } else if (cmd == 4) {
+ csEntry = READ_LE_UINT16(_dlgBuffer + offs);
+ setNewDlgIndex(csEntry);
+ offs += 2;
+
+ } else {
+ if (!_flags.isTalkie || cmd == 11) {
+ int len = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+ if (_flags.isTalkie) {
+ vocLo = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+ }
+ memcpy(_unkBuf500Bytes, _dlgBuffer + offs, len);
+ _unkBuf500Bytes[len] = 0;
+ offs += len;
+ if (_flags.isTalkie)
+ continue;
+
+ } else if (_flags.isTalkie) {
+ int len = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+ static const int irnv[] = { 91, 105, 110, 114, 118 };
+ vocHi = irnv[vocH - 1] + csEntry;
+ vocLo = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+ memcpy(_unkBuf500Bytes, _dlgBuffer + offs, len);
+ _unkBuf500Bytes[len] = 0;
+ offs += len;
+ }
+
+ if (_unkBuf500Bytes[0]) {
+ if ((!_flags.isTalkie && cmd == 11) || (_flags.isTalkie && cmd == 12)) {
+ if (activeTimSequence > -1) {
+ deinitTalkObject(activeTimSequence);
+ activeTimSequence = -1;
+ }
+ objectChat((const char*) _unkBuf500Bytes, 0, vocHi, vocLo);
+ } else {
+ if (activeTimSequence != nextTimSequence ) {
+ if (activeTimSequence > -1) {
+ deinitTalkObject(activeTimSequence);
+ activeTimSequence = -1;
+ }
+ initTalkObject(nextTimSequence);
+ activeTimSequence = nextTimSequence;
+ }
+ npcChatSequence((const char *)_unkBuf500Bytes, nextTimSequence, vocHi, vocLo);
+ }
+ }
+ }
+ }
+
+ if (activeTimSequence > -1)
+ deinitTalkObject(activeTimSequence);
+
+ _screen->showMouse();
+}
+
+void KyraEngine_HoF::initTalkObject(int index) {
+ TalkObject &object = _talkObjectList[index];
+
+ char STAFilename[13];
+ char ENDFilename[13];
+
+ strcpy(STAFilename, object.filename);
+ strcpy(_TLKFilename, object.filename);
+ strcpy(ENDFilename, object.filename);
+
+ strcat(STAFilename + 4, "_STA.TIM");
+ strcat(_TLKFilename + 4, "_TLK.TIM");
+ strcat(ENDFilename + 4, "_END.TIM");
+
+ _currentTalkSections.STATim = _tim->load(STAFilename, &_timOpcodes);
+ _currentTalkSections.TLKTim = _tim->load(_TLKFilename, &_timOpcodes);
+ _currentTalkSections.ENDTim = _tim->load(ENDFilename, &_timOpcodes);
+
+ if (object.scriptId != -1) {
+ _specialSceneScriptStateBackup[object.scriptId] = _specialSceneScriptState[object.scriptId];
+ _specialSceneScriptState[object.scriptId] = 1;
+ }
+
+ if (_currentTalkSections.STATim) {
+ _tim->resetFinishedFlag();
+ while (!_quitFlag && !_tim->finished()) {
+ _tim->exec(_currentTalkSections.STATim, false);
+ if (_chatText)
+ updateWithText();
+ else
+ update();
+ delay(10);
+ }
+ }
+}
+
+void KyraEngine_HoF::deinitTalkObject(int index) {
+ TalkObject &object = _talkObjectList[index];
+
+ if (_currentTalkSections.ENDTim) {
+ _tim->resetFinishedFlag();
+ while (!_quitFlag && !_tim->finished()) {
+ _tim->exec(_currentTalkSections.ENDTim, false);
+ if (_chatText)
+ updateWithText();
+ else
+ update();
+ delay(10);
+ }
+ }
+
+ if (object.scriptId != -1)
+ _specialSceneScriptState[object.scriptId] = _specialSceneScriptStateBackup[object.scriptId];
+
+ _tim->unload(_currentTalkSections.STATim);
+ _tim->unload(_currentTalkSections.TLKTim);
+ _tim->unload(_currentTalkSections.ENDTim);
+}
+
+void KyraEngine_HoF::npcChatSequence(const char *str, int objectId, int vocHigh, int vocLow) {
+ _chatText = str;
+ _chatObject = objectId;
+ objectChatInit(str, objectId, vocHigh, vocLow);
+
+ if (!_currentTalkSections.TLKTim)
+ _currentTalkSections.TLKTim = _tim->load(_TLKFilename, &_timOpcodes);
+
+ setNextIdleAnimTimer();
+
+ uint32 ct = chatCalcDuration(str);
+ uint32 time = _system->getMillis();
+ _chatEndTime = time + (3 + ct) * _tickLength;
+ uint32 chatAnimEndTime = time + (3 + (ct >> 1)) * _tickLength;
+
+ if (_chatVocHigh >= 0) {
+ playVoice(_chatVocHigh, _chatVocLow);
+ _chatVocHigh = _chatVocLow = -1;
+ }
+
+ while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quitFlag || skipFlag())) {
+ if (!speechEnabled() && chatAnimEndTime > _system->getMillis() || speechEnabled() && snd_voiceIsPlaying()) {
+ _tim->resetFinishedFlag();
+ while (!_tim->finished() && !skipFlag() && !_quitFlag) {
+ if (_currentTalkSections.TLKTim)
+ _tim->exec(_currentTalkSections.TLKTim, false);
+ else
+ _tim->resetFinishedFlag();
+
+ updateWithText();
+ delay(10);
+ }
+
+ if (_currentTalkSections.TLKTim)
+ _tim->stopCurFunc();
+ }
+ updateWithText();
+ }
+
+ resetSkipFlag();
+
+ _tim->unload(_currentTalkSections.TLKTim);
+
+ _text->restoreScreen();
+ _chatText = 0;
+ _chatObject = -1;
+ setNextIdleAnimTimer();
+}
+
+void KyraEngine_HoF::setNewDlgIndex(int dlgIndex) {
+ if (dlgIndex == _mainCharacter.dlgIndex)
+ return;
+ memset(_newSceneDlgState, 0, 32);
+ for (int i = 0; i < 19; i++)
+ memset(_conversationState[i], -1, 14);
+ _chatAltFlag = false;
+ _mainCharacter.dlgIndex = dlgIndex;
+}
+
+} // end of namespace Kyra