1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
/* 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 "mutationofjb/commands/saycommand.h"
#include "mutationofjb/game.h"
#include "mutationofjb/gamedata.h"
#include "mutationofjb/script.h"
#include "mutationofjb/tasks/saytask.h"
#include "mutationofjb/tasks/taskmanager.h"
#include "common/str.h"
#include "common/debug.h"
#include "common/debug-channels.h"
/** @file
* <firstLine> { <CRLF> <additionalLine> }
*
* firstLine ::= ("SM" | "SLM" | "NM" | "NLM") " " <lineToSay> [ "<" <voiceFile> | "<!" ]
* additionalLine ::= <skipped> " " <lineToSay> ( "<" <voiceFile> | "<!" )
*
* Say command comes in four variants: SM, SLM, NM and NLM.
* Note: In script files, they are usually written as *SM.
* The asterisk is ignored by the readLine function.
*
* Each of them plays a voice file (if present) and/or shows a message
* (if voice file not present or subtitles are enabled).
*
* The difference between versions starting with "S" and "N" is that
* the "N" version does not show talking animation.
*
* The "L" versions are "blocking", i.e. they wait for the previous say command to finish.
*
* If the line ends with "<!", it means the message continues to the next line.
* Next line usually has "SM" (or other variant) repeated, but it does not have to.
* Then we have the rest of the string to say (which is concatenated with the previous line)
* and possibly the voice file or "<!" again.
*/
namespace MutationOfJB {
bool SayCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
bool waitForPrevious = false;
bool talkingAnimation = false;
if (line.hasPrefix("SM")) {
waitForPrevious = false;
talkingAnimation = true;
} else if (line.hasPrefix("SLM")) {
waitForPrevious = true;
talkingAnimation = true;
} else if (line.hasPrefix("NM")) {
waitForPrevious = false;
talkingAnimation = false;
} else if (line.hasPrefix("NLM")) {
waitForPrevious = true;
talkingAnimation = false;
} else {
return false;
}
Common::String currentLine = line;
Common::String lineToSay;
Common::String voiceFile;
bool cont = false;
bool firstPass = true;
do {
cont = false;
uint startPos;
for (startPos = 0; startPos < currentLine.size(); ++startPos) {
if (currentLine[startPos] == ' ') {
break;
}
}
if (startPos == currentLine.size()) {
if (!firstPass) {
warning("Unable to parse line '%s'", currentLine.c_str());
break;
}
}
if (startPos != currentLine.size()) {
startPos++;
}
uint endPos;
for (endPos = startPos; endPos < currentLine.size(); ++endPos) {
if (currentLine[endPos] == '<') {
break;
}
}
Common::String talkStr(currentLine.c_str() + startPos, endPos - startPos);
if (endPos != currentLine.size()) {
const char *end = currentLine.c_str() + endPos + 1;
if (end[0] == '!') {
cont = true;
} else {
voiceFile = end;
}
}
if (talkStr.lastChar() == '~') {
debug("Found say command ending with '~'. Please take a look.");
}
if (lineToSay.empty()) {
lineToSay = talkStr;
} else {
lineToSay += " " + talkStr;
}
if (cont) {
if (!parseCtx.readLine(currentLine)) {
cont = false;
}
}
firstPass = false;
} while (cont);
command = new SayCommand(lineToSay, voiceFile, waitForPrevious, talkingAnimation);
return true;
}
Command::ExecuteResult SayCommand::execute(ScriptExecutionContext &scriptExecCtx) {
Game &game = scriptExecCtx.getGame();
if (_waitForPrevious) {
if (game.getActiveSayTask()) {
return InProgress;
}
}
TaskPtr task(new SayTask(_lineToSay, game.getGameData()._color));
game.getTaskManager().startTask(task);
return Finished;
}
Common::String SayCommand::debugString() const {
return Common::String::format("SHOWMSG%s%s '%s' '%s'", _waitForPrevious ? "+WAIT" : "", _talkingAnimation ? "+TALKANIM" : "", _lineToSay.c_str(), _voiceFile.c_str());
}
}
|