LOL: some more work on the text displayer so that it handles longer texts (needed for some library books)

svn-id: r39249
This commit is contained in:
Florian Kagerer 2009-03-08 23:28:19 +00:00
parent 2abfb968a6
commit 6cb3f665af
9 changed files with 197 additions and 53 deletions

View File

@ -190,7 +190,8 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
memset(_activeTim, 0, sizeof(_activeTim));
memset(_activeVoiceFile, 0, sizeof(_activeVoiceFile));
memset(_openDoorState, 0, sizeof(_openDoorState));
_activeVoiceFileTotalTime = 0;
_pageBuffer1 = _pageBuffer2 = 0;
memset(_charStatsTemp, 0, sizeof(_charStatsTemp));
@ -359,8 +360,7 @@ Common::Error LoLEngine::init() {
_pageBuffer2 = new uint8[0xfa00];
memset(_pageBuffer2, 0, 0xfa00);
// FIXME: Why do we allocate a 401 entry array, if only 400 entries are used?
_itemsInPlay = new ItemInPlay[401];
_itemsInPlay = new ItemInPlay[400];
memset(_itemsInPlay, 0, sizeof(ItemInPlay) * 400);
_characters = new LoLCharacter[4];
@ -416,7 +416,7 @@ Common::Error LoLEngine::init() {
memset(_tmpData136, 0, 136);
memset(_gameFlags, 0, 16 * sizeof(uint16));
memset(_unkEMC46, 0, 16 * sizeof(uint16));
memset(_globalScriptVars, 0, 16 * sizeof(uint16));
_levelFileData = 0;
_lvlShpFileHandle = 0;
@ -1167,9 +1167,44 @@ void LoLEngine::restoreAfterAnimatedDialogue(int redraw) {
}
void LoLEngine::initNonAnimatedDialogue(int controlMode, int pageNum) {
if (controlMode) {
_timer->disable(11);
_fadeText = false;
int cp = _screen->setCurPage(pageNum);
_screen->fillRect(0, 128, 319, 199, 1);
gui_drawBox(0, 129, 320, 71, 136, 251, -1);
gui_drawBox(1, 130, 318, 69, 136, 251, 252);
_screen->modifyScreenDim(5, 8, 131, 304, 66);
_screen->modifyScreenDim(4, 1, 133, 38, 60);
_screen->clearDim(4);
_updateFlags |= 2;
_hideControls = controlMode;
calcCharPortraitXpos();
if (!textEnabled() && (!(controlMode & 2))) {
int nc = countActiveCharacters();
for (int i = 0; i < nc; i++) {
_portraitSpeechAnimMode = 2;
_updateCharNum = i;
_screen->drawShape(0, _gameShapes[88], _activeCharsXpos[_updateCharNum] + 8, 142, 0, 0);
updatePortraits();
}
}
_screen->setCurPage(cp);
} else {
_txt->setupField(true);
_txt->expandField();
setupScreenDims();
_screen->clearDim(4);
}
_dialogueField = true;
_hideControls = controlMode;
_dialogueField = true;
}
void LoLEngine::restoreAfterNonAnimatedDialogue(int controlMode) {
@ -1327,7 +1362,7 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) {
};
strcpy(_activeVoiceFile, *playList.begin());
_sound->voicePlayFromList(playList);
_activeVoiceFileTotalTime = _sound->voicePlayFromList(playList);
for (Common::List<const char*>::iterator i = playList.begin(); i != playList.end(); i++)
delete []*i;
@ -1343,6 +1378,7 @@ int LoLEngine::snd_characterSpeaking() {
return 2;
_lastSpeechId = _lastSpeaker = -1;
_activeVoiceFileTotalTime = 0;
return 1;
}
@ -1353,11 +1389,16 @@ void LoLEngine::snd_stopSpeech(bool setFlag) {
//_dlgTimer = 0;
_sound->voiceStop(_activeVoiceFile);
_activeVoiceFileTotalTime = 0;
if (setFlag)
_tim->_abortFlag = 1;
}
uint32 LoLEngine::snd_getElapsedSpeechTime() {
return _sound->voicePlayedTime(_activeVoiceFile);
}
void LoLEngine::snd_playSoundEffect(int track, int volume) {
debugC(9, kDebugLevelMain | kDebugLevelSound, "LoLEngine::snd_playSoundEffect(%d, %d)", track, volume);

View File

@ -327,6 +327,7 @@ private:
bool snd_playCharacterSpeech(int id, int8 speaker, int);
int snd_characterSpeaking();
void snd_stopSpeech(bool setFlag);
uint32 snd_getElapsedSpeechTime();
void snd_playSoundEffect(int track, int volume);
void snd_processEnvironmentalSoundEffect(int soundId, int block);
void snd_loadSoundFile(int track);
@ -336,6 +337,7 @@ private:
int _lastSpeechId;
int _lastSpeaker;
char _activeVoiceFile[13];
uint32 _activeVoiceFileTotalTime;
int _lastSfxTrack;
int _lastMusicTrack;
int _curMusicFileIndex;
@ -494,7 +496,7 @@ private:
bool _sceneUpdateRequired;
int16 _currentBlockPropertyIndex[18];
uint16 _gameFlags[16];
uint16 _unkEMC46[16];
uint16 _globalScriptVars[16];
// emc opcode
int olol_drawScene(EMCState *script);
@ -519,8 +521,8 @@ private:
int olol_getDirection(EMCState *script);
int olol_setMusicTrack(EMCState *script);
int olol_clearDialogueField(EMCState *script);
int olol_getUnkArrayVal(EMCState *script);
int olol_setUnkArrayVal(EMCState *script);
int olol_getGlobalScriptVar(EMCState *script);
int olol_setGlobalScriptVar(EMCState *script);
int olol_getGlobalVar(EMCState *script);
int olol_setGlobalVar(EMCState *script);
int olol_triggerDoorSwitch(EMCState *script);

View File

@ -92,11 +92,6 @@ void Screen_LoL::clearDim(int dim) {
fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 1, (tmp->sy + tmp->h) - 1, tmp->unkA);
}
void Screen_LoL::clearCurDim() {
fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _curDim->unkA);
_dimLineCount = 0;
}
void Screen_LoL::fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...) {
debugC(9, kDebugLevelScreen, "Screen_LoL::fprintString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags);
if (!format)

View File

@ -44,7 +44,6 @@ public:
int curDimIndex() { return _curDimIndex; }
void modifyScreenDim(int dim, int x, int y, int w, int h);
void clearDim(int dim);
void clearCurDim();
void fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...);
void fprintStringIntro(const char *format, int x, int y, uint8 c1, uint8 c2, uint8 c3, uint16 flags, ...);

View File

@ -452,12 +452,16 @@ int LoLEngine::olol_clearDialogueField(EMCState *script) {
return 1;
}
int LoLEngine::olol_getUnkArrayVal(EMCState *script) {
return _unkEMC46[stackPos(0)];
int LoLEngine::olol_getGlobalScriptVar(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getGlobalScriptVar(%p) (%d)", (const void *)script, stackPos(0));
assert(stackPos(0) < 16);
return _globalScriptVars[stackPos(0)];
}
int LoLEngine::olol_setUnkArrayVal(EMCState *script) {
_unkEMC46[stackPos(0)] = stackPos(1);
int LoLEngine::olol_setGlobalScriptVar(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setGlobalScriptVar(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
assert(stackPos(0) < 16);
_globalScriptVars[stackPos(0)] = stackPos(1);
return 1;
}
@ -1194,8 +1198,8 @@ void LoLEngine::setupOpcodeTable() {
// 0x2C
OpcodeUnImpl();
Opcode(olol_getUnkArrayVal);
Opcode(olol_setUnkArrayVal);
Opcode(olol_getGlobalScriptVar);
Opcode(olol_setGlobalScriptVar);
Opcode(olol_getGlobalVar);
// 0x30

View File

@ -115,21 +115,22 @@ int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx) {
return audioStream->getTotalPlayTime();
}
void Sound::voicePlayFromList(Common::List<const char*> fileList) {
uint32 Sound::voicePlayFromList(Common::List<const char*> fileList) {
int h = 0;
while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles)
h++;
if (h >= kNumChannelHandles)
return;
return 0;
Audio::AppendableAudioStream *out = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED);
for (Common::List<const char*>::iterator i = fileList.begin(); i != fileList.end(); i++) {
Common::SeekableReadStream *file = _vm->resource()->createReadStream(*i);
// TODO: Maybe output an warning like "file not found"?
if (!file)
if (!file) {
warning("Couldn't load voice file: %s", *i);
continue;
}
int size, rate;
uint8 *data = Audio::loadVOCFromStream(*file, size, rate);
@ -151,6 +152,7 @@ void Sound::voicePlayFromList(Common::List<const char*> fileList) {
_soundChannels[h].file = *fileList.begin();
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, out);
return out->getTotalPlayTime();
}
void Sound::voiceStop(const char *file) {

View File

@ -203,7 +203,7 @@ public:
*
* @param fileList: files to be played
*/
virtual void voicePlayFromList(Common::List<const char*> fileList);
virtual uint32 voicePlayFromList(Common::List<const char*> fileList);
/**
* Checks if a voice is being played.

View File

@ -31,7 +31,7 @@
namespace Kyra {
TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen),
_scriptParameter(0), _stringLength(0), _animWidth(0), _animColour1(0), _animColour2(0), _animFlag(true),
_scriptParameter(0), _animWidth(0), _animColour1(0), _animColour2(0), _animFlag(true),
_printFlag(false), _lineWidth(0), _numChars(0), _numCharsPrinted(0), _posX(0), _posY(0), _colour1(0), _colour2(0) {
memset(_stringParameters, 0, 15 * sizeof(char*));
@ -184,10 +184,10 @@ void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) {
if (_vm->_updateFlags & 2) {
_screen->setScreenDim(4);
_screen->clearCurDim();
clearCurDim();
} else {
_screen->setScreenDim(3);
_screen->clearCurDim();
clearCurDim();
_screen->copyColour(192, col);
_vm->enableTimer(11);
}
@ -360,10 +360,7 @@ void TextDisplayer_LoL::displayText(char *str, ...) {
switch (c - 1) {
case 0:
printLine(_currentLine);
//if (!_dlgAnimCallback)
// break;
portraitAnimation2();
textPageBreak();
_numCharsPrinted = 0;
break;
@ -478,10 +475,8 @@ void TextDisplayer_LoL::printLine(char *str) {
while (_posY >= lines) {
if (lines <= _screen->_dimLineCount && _animFlag) {
_screen->_dimLineCount = 0;
//if (_dlgAnimCallback) {
portraitAnimation2();
_numCharsPrinted = 0;
//}
textPageBreak();
_numCharsPrinted = 0;
}
int h1 = ((sd->h / fh) - 1) * fh;
@ -490,9 +485,9 @@ void TextDisplayer_LoL::printLine(char *str) {
if (h2)
_screen->copyRegion(sd->sx << 3, sd->sy + fh, sd->sx << 3, sd->sy, sd->w << 3, h2, _screen->_curPage, _screen->_curPage, Screen::CR_NO_P_CHECK);
_screen->fillRect(sd->sx << 3, sd->sy + h1, (sd->sx + sd->w - 1) << 3, sd->sy + sd->h - 1, _colour2);
_posY--;
_screen->fillRect(sd->sx << 3, sd->sy + h1, (sd->sx + sd->w - 1) << 3, sd->sy + sd->h - 1, _colour2);
if (_posY)
_posY--;
}
int x1 = (sd->sx << 3) + _posX;
@ -567,12 +562,122 @@ void TextDisplayer_LoL::printLine(char *str) {
printLine(str);
}
/*void TextDisplayer_LoL::portraitAnimation1(const char *str, uint16 lineWidth, uint8 col1, uint8 col2, uint16 numCharsPrinted) {
}*/
void TextDisplayer_LoL::textPageBreak() {
int cp = _screen->setCurPage(0);
Screen::FontId cf = _screen->setFont(Screen::FID_6_FNT);
void TextDisplayer_LoL::portraitAnimation2() {
// TODO
_vm->_timer->pauseSingleTimer(11, true);
_vm->_fadeText = false;
int updateCharV3 = 0;
int updatePortraitSpeechAnimDuration = 0;
if (_vm->_updateCharNum != -1) {
updateCharV3 = _vm->_updateCharV3;
_vm->_updateCharV3 = 0;
updatePortraitSpeechAnimDuration = _vm->_updatePortraitSpeechAnimDuration;
if (_vm->_updatePortraitSpeechAnimDuration > 36)
_vm->_updatePortraitSpeechAnimDuration = 36;
}
uint32 speechPartTime = 0;
if (_vm->_speechFlag && _vm->_activeVoiceFileTotalTime && _numChars)
speechPartTime = _vm->_system->getMillis() + ((_numCharsPrinted * _vm->_activeVoiceFileTotalTime) / _numChars);
const ScreenDim *dim = _screen->getScreenDim(_screen->curDimIndex());
int x = ((dim->sx + dim->w) << 3) - 77;
int y = 0;
if (_vm->_hideInventory && (_vm->_updateFlags & 2)) {
if (_vm->_hideControls || !(_vm->_updateFlags & 2)) {
y = dim->sy + dim->h - 5;
} else {
x += 6;
y = dim->sy + dim->h - 2;
}
} else {
y = dim->sy + dim->h - 10;
}
_vm->gui_drawBox(x, y, 74, 9, 136, 251, -1);
char *txt = _vm->getLangString(0x4073);
_vm->_screen->printText(txt, x + 37 - (_vm->_screen->getTextWidth(txt) >> 1), y + 2, 144, 0);
_vm->removeInputTop();
bool loop = true;
bool target = false;
do {
int inputFlag = _vm->checkInput(0, false) & 0xFF;
_vm->removeInputTop();
while (!inputFlag) {
_vm->update();
if (_vm->_speechFlag) {
if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_characterSpeaking() != 2)) && speechPartTime) {
loop = false;
inputFlag = 43;
break;
}
}
inputFlag = _vm->checkInput(0, false) & 0xFF;
_vm->removeInputTop();
}
_vm->gui_notifyButtonListChanged();
switch (inputFlag) {
case 43:
case 61:
loop = false;
break;
case 199:
case 201:
if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, y, x + 74, y + 9))
target = true;
break;
case 200:
case 202:
if (target)
loop = false;
break;
default:
break;
}
} while (loop);
_screen->fillRect(x, y, x + 74, y + 9, _colour2);
clearCurDim();
_vm->_timer->pauseSingleTimer(11, false);
if (_vm->_updateCharNum != -1) {
_vm->_updateCharV3 = updateCharV3;
if (updatePortraitSpeechAnimDuration > 36)
updatePortraitSpeechAnimDuration -= 36;
else
updatePortraitSpeechAnimDuration >>= 1;
_vm->_updatePortraitSpeechAnimDuration = updatePortraitSpeechAnimDuration;
}
_screen->setFont(cf);
_screen->setCurPage(cp);
_vm->removeInputTop();
}
void TextDisplayer_LoL::clearCurDim() {
const ScreenDim *tmp = _screen->getScreenDim(_screen->curDimIndex());
_screen->fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 1, (tmp->sy + tmp->h) - 1, _colour2);
_screen->_dimLineCount = 0;
_posX = _posY = 0;
}
} // end of namespace Kyra

View File

@ -55,12 +55,9 @@ private:
void readNextPara();
void printLine(char *str);
void preprocessString(char *str, EMCState *script, const uint16 *paramList, int16 paramIndex);
//typedef void (LoLEngine::*DialogueAnimCallback)(const char *str, uint16 lineWidth, uint8 col1, uint8 col2);
//DialogueAnimCallback _dlgAnimCallback;
//void portraitAnimation1(const char *str);
void portraitAnimation2();
void textPageBreak();
void clearCurDim();
char *_stringParameters[15];
char *_buffer;
@ -71,7 +68,6 @@ private:
char _ctrl[3];
char _scriptParaString[11];
uint32 _stringLength;
uint16 _lineWidth;
uint32 _numChars;