diff options
Diffstat (limited to 'engines/sludge/speech.cpp')
-rw-r--r-- | engines/sludge/speech.cpp | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/engines/sludge/speech.cpp b/engines/sludge/speech.cpp new file mode 100644 index 0000000000..1d342a1b65 --- /dev/null +++ b/engines/sludge/speech.cpp @@ -0,0 +1,311 @@ +/* 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. + * + */ + +#include "sludge/allfiles.h" +#include "sludge/backdrop.h" +#include "sludge/fonttext.h" +#include "sludge/freeze.h" +#include "sludge/graphics.h" +#include "sludge/moreio.h" +#include "sludge/newfatal.h" +#include "sludge/objtypes.h" +#include "sludge/people.h" +#include "sludge/region.h" +#include "sludge/sludge.h" +#include "sludge/sludger.h" +#include "sludge/sound.h" +#include "sludge/speech.h" +#include "sludge/sprbanks.h" +#include "sludge/sprites.h" + +namespace Sludge { + +void SpeechManager::init() { + _speechMode = 0; + _speechSpeed = 1; + _speech = new SpeechStruct; + if (checkNew(_speech)) { + _speech->currentTalker = NULL; + _speech->allSpeech = NULL; + _speech->speechY = 0; + _speech->lastFile = -1; + } +} + +void SpeechManager::kill() { + if (!_speech) + return; + + if (_speech->lastFile != -1) { + _vm->_soundMan->huntKillSound(_speech->lastFile); + _speech->lastFile = -1; + } + + if (_speech->currentTalker) { + makeSilent(*(_speech->currentTalker)); + _speech->currentTalker = NULL; + } + + SpeechLine *killMe; + while (_speech->allSpeech) { + killMe = _speech->allSpeech; + _speech->allSpeech = _speech->allSpeech->next; + delete killMe; + } +} + +void SpeechManager::setObjFontColour(ObjectType *t) { + setFontColour(_speech->talkCol, t->r, t->g, t->b); +} + +void SpeechManager::addSpeechLine(const Common::String &theLine, int x, int &offset) { + float cameraZoom = g_sludge->_gfxMan->getCamZoom(); + int halfWidth = (g_sludge->_txtMan->stringWidth(theLine) >> 1) / cameraZoom; + int xx1 = x - (halfWidth); + int xx2 = x + (halfWidth); + SpeechLine *newLine = new SpeechLine; + checkNew(newLine); + + newLine->next = _speech->allSpeech; + newLine->textLine.clear(); + newLine->textLine = theLine; + newLine->x = xx1; + _speech->allSpeech = newLine; + if ((xx1 < 5) && (offset < (5 - xx1))) { + offset = 5 - xx1; + } else if ((xx2 >= ((float) g_system->getWidth() / cameraZoom) - 5) + && (offset > (((float) g_system->getWidth() / cameraZoom) - 5 - xx2))) { + offset = ((float) g_system->getWidth() / cameraZoom) - 5 - xx2; + } +} + +int SpeechManager::isThereAnySpeechGoingOn() { + return _speech->allSpeech ? _speech->lookWhosTalking : -1; +} + +int SpeechManager::getLastSpeechSound() { + return _vm->_soundMan->findInSoundCache(_speech->lastFile); +} + +int SpeechManager::wrapSpeechXY(const Common::String &theText, int x, int y, int wrap, int sampleFile) { + float cameraZoom = g_sludge->_gfxMan->getCamZoom(); + int fontHeight = g_sludge->_txtMan->getFontHeight(); + int cameraY = g_sludge->_gfxMan->getCamY(); + + int a, offset = 0; + + kill(); + + int speechTime = (theText.size() + 20) * _speechSpeed; + if (speechTime < 1) + speechTime = 1; + if (sampleFile != -1) { + if (_speechMode >= 1) { + if (g_sludge->_soundMan->startSound(sampleFile, false)) { + speechTime = -10; + _speech->lastFile = sampleFile; + if (_speechMode == 2) return -10; + } + + } + } + _speech->speechY = y; + + char *tmp, *txt; + tmp = txt = createCString(theText); + while ((int)strlen(txt) > wrap) { + a = wrap; + while (txt[a] != ' ') { + a--; + if (a == 0) { + a = wrap; + break; + } + } + txt[a] = 0; + addSpeechLine(txt, x, offset); + txt[a] = ' '; + txt += a + 1; + y -= fontHeight / cameraZoom; + } + addSpeechLine(txt, x, offset); + y -= fontHeight / cameraZoom; + delete []tmp; + + if (y < 0) + _speech->speechY -= y; + else if (_speech->speechY > cameraY + (float) (g_system->getHeight() - fontHeight / 3) / cameraZoom) + _speech->speechY = cameraY + + (float) (g_system->getHeight() - fontHeight / 3) / cameraZoom; + + if (offset) { + SpeechLine *viewLine = _speech->allSpeech; + while (viewLine) { + viewLine->x += offset; + viewLine = viewLine->next; + } + } + return speechTime; +} + +int SpeechManager::wrapSpeechPerson(const Common::String &theText, OnScreenPerson &thePerson, int sampleFile, bool animPerson) { + int cameraX = g_sludge->_gfxMan->getCamX(); + int cameraY = g_sludge->_gfxMan->getCamY(); + int i = wrapSpeechXY(theText, thePerson.x - cameraX, + thePerson.y - cameraY + - (thePerson.scale * (thePerson.height - thePerson.floaty)) + - thePerson.thisType->speechGap, + thePerson.thisType->wrapSpeech, sampleFile); + if (animPerson) { + makeTalker(thePerson); + _speech->currentTalker = &thePerson; + } + return i; +} + +int SpeechManager::wrapSpeech(const Common::String &theText, int objT, int sampleFile, bool animPerson) { + int i; + int cameraX = g_sludge->_gfxMan->getCamX(); + int cameraY = g_sludge->_gfxMan->getCamY(); + + _speech->lookWhosTalking = objT; + OnScreenPerson *thisPerson = findPerson(objT); + if (thisPerson) { + setObjFontColour(thisPerson->thisType); + i = wrapSpeechPerson(theText, *thisPerson, sampleFile, animPerson); + } else { + ScreenRegion *thisRegion = getRegionForObject(objT); + if (thisRegion) { + setObjFontColour(thisRegion->thisType); + i = wrapSpeechXY(theText, + ((thisRegion->x1 + thisRegion->x2) >> 1) - cameraX, + thisRegion->y1 - thisRegion->thisType->speechGap - cameraY, + thisRegion->thisType->wrapSpeech, sampleFile); + } else { + ObjectType *temp = g_sludge->_objMan->findObjectType(objT); + setObjFontColour(temp); + i = wrapSpeechXY(theText, g_system->getWidth() >> 1, 10, temp->wrapSpeech, + sampleFile); + } + } + return i; +} + +void SpeechManager::display() { + float cameraZoom = g_sludge->_gfxMan->getCamZoom(); + int fontHeight = g_sludge->_txtMan->getFontHeight(); + int viewY = _speech->speechY; + SpeechLine *viewLine = _speech->allSpeech; + while (viewLine) { + g_sludge->_txtMan->pasteString(viewLine->textLine, viewLine->x, viewY, _speech->talkCol); + viewY -= fontHeight / cameraZoom; + viewLine = viewLine->next; + } +} + +void SpeechManager::save(Common::WriteStream *stream) { + stream->writeByte(_speechMode); + + SpeechLine *viewLine = _speech->allSpeech; + + stream->writeByte(_speech->talkCol.originalRed); + stream->writeByte(_speech->talkCol.originalGreen); + stream->writeByte(_speech->talkCol.originalBlue); + + stream->writeFloatLE(_speechSpeed); + + // Write y co-ordinate + stream->writeUint16BE(_speech->speechY); + + // Write which character's talking + stream->writeUint16BE(_speech->lookWhosTalking); + if (_speech->currentTalker) { + stream->writeByte(1); + stream->writeUint16BE(_speech->currentTalker->thisType->objectNum); + } else { + stream->writeByte(0); + } + + // Write what's being said + while (viewLine) { + stream->writeByte(1); + writeString(viewLine->textLine, stream); + stream->writeUint16BE(viewLine->x); + viewLine = viewLine->next; + } + stream->writeByte(0); +} + +bool SpeechManager::load(Common::SeekableReadStream *stream) { + // read speech mode + _speechMode = stream->readByte(); + + _speech->currentTalker = nullptr; + kill(); + byte r = stream->readByte(); + byte g = stream->readByte(); + byte b = stream->readByte(); + setFontColour(_speech->talkCol, r, g, b); + + _speechSpeed = stream->readFloatLE(); + + // Read y co-ordinate + _speech->speechY = stream->readUint16BE(); + + // Read which character's talking + _speech->lookWhosTalking = stream->readUint16BE(); + + if (stream->readByte()) { + _speech->currentTalker = findPerson(stream->readUint16BE()); + } else { + _speech->currentTalker = NULL; + } + + // Read what's being said + SpeechLine **viewLine = &_speech->allSpeech; + SpeechLine *newOne; + _speech->lastFile = -1; + while (stream->readByte()) { + newOne = new SpeechLine; + if (!checkNew(newOne)) + return false; + newOne->textLine = readString(stream); + newOne->x = stream->readUint16BE(); + newOne->next = NULL; + (*viewLine) = newOne; + viewLine = &(newOne->next); + } + return true; +} + +void SpeechManager::freeze(FrozenStuffStruct *frozenStuff) { + frozenStuff->speech = _speech; + init(); +} + +void SpeechManager::restore(FrozenStuffStruct *frozenStuff) { + kill(); + delete _speech; + _speech = frozenStuff->speech; +} + +} // End of namespace Sludge |