mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-30 14:14:43 +00:00
b53fe83695
svn-id: r31956
691 lines
18 KiB
C++
691 lines
18 KiB
C++
/* 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_HoF::TextDisplayer_HoF(KyraEngine_HoF *vm, Screen_v2 *screen)
|
|
: TextDisplayer(vm, screen), _vm(vm) {
|
|
}
|
|
|
|
void TextDisplayer_HoF::backupTalkTextMessageBkgd(int srcPage, int dstPage) {
|
|
_screen->copyRegion(_talkCoords.x, _talkMessageY, 0, 144, _talkCoords.w, _talkMessageH, srcPage, dstPage);
|
|
}
|
|
|
|
void TextDisplayer_HoF::restoreTalkTextMessageBkgd(int srcPage, int dstPage) {
|
|
_screen->copyRegion(0, 144, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, srcPage, dstPage);
|
|
}
|
|
|
|
void TextDisplayer_HoF::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_HoF::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_HoF::preprocessString(const char *str) {
|
|
debugC(9, kDebugLevelMain, "TextDisplayer_HoF::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_HoF::calcWidestLineBounds(int &x1, int &x2, int w, int x) {
|
|
debugC(9, kDebugLevelMain, "TextDisplayer_HoF::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, &_opcodesAnimation);
|
|
_emc->init(&_chatScriptState, &_chatScriptData);
|
|
_emc->start(&_chatScriptState, 0);
|
|
while (_emc->isValid(&_chatScriptState))
|
|
_emc->run(&_chatScriptState);
|
|
|
|
_animShapeFilename[2] = _characterShapeFile + '0';
|
|
uint8 *shapeBuffer = _res->fileData(_animShapeFilename, 0);
|
|
if (shapeBuffer) {
|
|
int shapeCount = initAnimationShapes(shapeBuffer);
|
|
|
|
if (_chatVocHigh >= 0) {
|
|
playVoice(_chatVocHigh, _chatVocLow);
|
|
_chatVocHigh = _chatVocLow = -1;
|
|
}
|
|
|
|
objectChatWaitToFinish();
|
|
|
|
uninitAnimationShapes(shapeCount, shapeBuffer);
|
|
} else {
|
|
warning("couldn't load file '%s'", _animShapeFilename);
|
|
}
|
|
|
|
_emc->unload(&_chatScriptData);
|
|
}
|
|
|
|
void KyraEngine_HoF::objectChatWaitToFinish() {
|
|
int charAnimFrame = _mainCharacter.animFrame;
|
|
setCharacterAnimDim(_animShapeWidth, _animShapeHeight);
|
|
|
|
_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);
|
|
|
|
_animNeedUpdate = false;
|
|
while (!_animNeedUpdate && _emc->isValid(&_chatScriptState))
|
|
_emc->run(&_chatScriptState);
|
|
|
|
int curFrame = _animNewFrame;
|
|
uint32 delayTime = _animDelayTime;
|
|
|
|
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::randomSceneChat() {
|
|
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);
|
|
setDlgIndex(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::setDlgIndex(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
|