Further implementation of dialog/message script language

svn-id: r46418
This commit is contained in:
Paul Gilbert 2009-12-19 05:47:31 +00:00
parent ae50fdca72
commit 63350a0ecc
3 changed files with 153 additions and 28 deletions

View File

@ -364,13 +364,15 @@ bool Console::cmdMessage(int argc, const char **argv) {
if (argc == 1)
DebugPrintf("message 'objnum'\n");
else {
int messageId = strToInt(argv[1]);
int idx = _vm->_globals->messageIndexOf(messageId);
if (idx == -1)
int messageIdx = strToInt(argv[1]);
if ((argc == 3) && !strcmp(argv[2], "id"))
messageIdx = _vm->_globals->messageIndexOf(messageIdx);
if (messageIdx == -1)
DebugPrintf("Unknown message");
else
{
const char *msg = _vm->_globals->loadMessage(idx);
const char *msg = _vm->_globals->loadMessage(messageIdx);
Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG");
_vm->_viewManager->addView(dlg);

View File

@ -35,6 +35,13 @@ static void strToUpper(char *s) {
}
}
static void strToLower(char *s) {
while (*s) {
*s = tolower(*s);
++s;
}
}
const RGB8 DIALOG_PALETTE[8] = {
{0x80, 0x80, 0x80, 0xff}, {0x90, 0x90, 0x90, 0xff}, {0x70, 0x70, 0x70, 0xff}, {0x9c, 0x9c, 0x9c, 0xff},
{0x80, 0x80, 0x80, 0xff}, {0x90, 0x90, 0x90, 0xff}, {0xDC, 0xDC, 0xDC, 0xff}, {0x00, 0x00, 0x00, 0xff}
@ -44,10 +51,16 @@ const RGB8 DIALOG_PALETTE[8] = {
const int DIALOG_SPACING = 1;
/**
* Handles any dialog initialisation
*/
void Dialog::initDialog() {
incLine();
}
/**
* Adds a new line to the dialog output
*/
void Dialog::incLine() {
_lineX = 0;
_widthX = 0;
@ -56,6 +69,10 @@ void Dialog::incLine() {
assert(_lines.size() <= 20);
}
/**
* Writes some text to the dialog output, taking care of word wrapping if the text size
* exceeds the dialog's width
*/
void Dialog::writeChars(const char *srcLine) {
char wordStr[80];
char line[80];
@ -124,6 +141,9 @@ void Dialog::writeChars(const char *srcLine) {
}
}
/**
* Appends some text to the current dialog line
*/
void Dialog::appendText(const char *line) {
_lineX += strlen(line);
_widthX += _vm->_font->getWidth(line, DIALOG_SPACING);
@ -131,6 +151,9 @@ void Dialog::appendText(const char *line) {
strcat(_lines[_lines.size() - 1].data, line);
}
/**
* Adds a line of text to the dialog lines list
*/
void Dialog::addLine(const char *line, bool underlineP) {
if ((_widthX > 0) || (_lineX > 0))
incLine();
@ -141,7 +164,7 @@ void Dialog::addLine(const char *line, bool underlineP) {
if ((lineWidth > _dialogWidth) || (lineLen >= _widthChars))
writeChars(line);
else {
_lines[_lines.size() - 1].xp = (_dialogWidth - lineWidth) / 2;
_lines[_lines.size() - 1].xp = (_dialogWidth - 10 - lineWidth) / 2;
strcpy(_lines[_lines.size() - 1].data, line);
}
@ -151,12 +174,97 @@ void Dialog::addLine(const char *line, bool underlineP) {
incLine();
}
/**
* Adds a bar separation line to the dialog lines list
*/
void Dialog::addBarLine() {
if ((_widthX > 0) || (_lineX > 0))
incLine();
// Flag the line as being a bar separator
_lines[_lines.size() - 1].barLine = true;
incLine();
}
/**
* Retrieves a specified vocab entry
*/
void Dialog::getVocab(int vocabId, char **line) {
assert(vocabId > 0);
const char *vocabStr = _vm->_globals->getVocab(vocabId);
strcpy(*line, vocabStr);
if (_commandCase)
strToUpper(*line);
else
strToLower(*line);
// Move the string pointer to after the added string
while (!**line)
++*line;
}
bool Dialog::handleNounSuffix(char *destP, int nounNum, const char *srcP) {
char srcLine[40];
// The next source character must be a colon in front of the first verb
if (*srcP != ':')
return false;
// Copy the remainder of the line into a temporary buffer to get the seperate verbs
strcpy(srcLine, ++srcP);
char *altP = strchr(srcLine, ':');
if (altP)
*altP = '\0';
if (*srcP != '\0') {
while (*srcP != ':') {
++srcP;
if (!*srcP) break;
}
}
if (*srcP != '\0')
++srcP;
//
char var_FC[40];
char tempLine[40];
strcpy(var_FC, srcP);
char *tmpP = &tempLine[0];
char *tmp2P = tmpP;
uint16 _vocabIds[2] = {1, 1}; // FIXME/TODO: Proper vocab ids
getVocab(_vocabIds[nounNum], &tmpP);
if ((*(tmpP - 1) != 'S') && (*(tmpP - 1) != 's')) {
// Singular object
tmpP = &var_FC[0];
} else if (!strcmp(tempLine, "a ")) {
// Pontially plural
char ch = tolower(*tmp2P);
if (!((ch > 'U') || ((ch != 'A') && (ch != 'E') && (ch != 'I') && (ch != 'O'))))
strcpy(tempLine, "an ");
}
strcpy(destP, tmpP);
return true;
}
/**
* Checks whether the start of an extracted command matches a specified given command constant
*/
bool Dialog::matchCommand(const char *s1, const char *s2) {
return strncmp(s1, s2, strlen(s2)) == 0;
bool result = scumm_strnicmp(s1, s2, strlen(s2)) == 0;
_commandCase = isupper(*s1);
return result;
}
Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, Common::Rect(0, 0, 0, 0)) {
assert(msgData);
_vm->_font->setFont(FONT_INTERFACE_MADS);
const char *srcP = msgData;
bool skipLine = false;
bool initFlag = false;
@ -172,6 +280,7 @@ Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, C
_lineX = 0;
_widthX = 0;
_dialogWidth = 0;
_commandCase = false;
char dialogLine[256];
char cmdText[80];
@ -226,7 +335,7 @@ Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, C
if (id > 0) {
// Suffix provided - specifies the dialog width in number of chars
_widthChars = id * 2;
_dialogWidth = id * (_vm->_font->getMaxWidth() + 1) + 10;
_dialogWidth = id * (_vm->_font->getMaxWidth() + DIALOG_SPACING) + 10;
}
} else if (matchCommand(cmdText, "SENTENCE")) {
// Sentence command - loads the title into the line buffer
@ -234,31 +343,45 @@ Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, C
strToUpper(dialogLine);
lineP += strlen(dialogLine) + 1;
} else if (matchCommand(cmdText, "BAR")) {
// Adds a full-width line instead of normal text
addBarLine();
} else if (matchCommand(cmdText, "CENTER")) {
// Center command
skipLine = true;
} else if (matchCommand(cmdText, "CR")) {
// CR command
if (skipLine)
crFlag = true;
else {
else if (!initFlag) {
initDialog();
initFlag = true;
}
} else if (matchCommand(cmdText, "NOUN1")) {
// Noun command 1
handleNounSuffix(lineP, 1, cmdText + 5);
} else if (matchCommand(cmdText, "NOUN1")) {
// Noun command 2
handleNounSuffix(lineP, 2, cmdText + 5);
} else if (matchCommand(cmdText, "VERB")) {
// Verb/vocab retrieval
int verbId = 1; // TODO: Get correct vocab
getVocab(verbId, &lineP);
} else if (matchCommand(cmdText, "UNDER")) {
// Underline command
underline = true;
} else if (matchCommand(cmdText, "ASK")) {
// doAsk();
} else if (matchCommand(cmdText, "CENTER")) {
// Center command
skipLine = true;
} else if (matchCommand(cmdText, "VERB")) {
// Verb/vocab retrieval
/*getVocab(); */
} else if (matchCommand(cmdText, "INDEX")) {
// Index command
_dialogIndex = atoi(cmdText + 5);
} else if (matchCommand(cmdText, "NOUN")) {
// Noun command
} else {
error("Unknown dialog command '%s' encountered", cmdText);
}
@ -279,19 +402,13 @@ Dialog::~Dialog() {
}
void Dialog::draw() {
_vm->_font->setFont(FONT_INTERFACE_MADS);
assert(_widthChars != 0);
// Set up the palette for this view
_palette = new RGBList(8, NULL);
_palette->setRange(0, 8, DIALOG_PALETTE);
_vm->_palette->addRange(_palette);
// Validation
if (_widthChars == 0) {
warning("Dialog being shown without TITLE specified");
_widthChars = 30;
}
// Calculate bounds
int dlgWidth = _dialogWidth;
int dlgHeight = _lines.size() * (_vm->_font->getHeight() + 1) + 10;
@ -338,10 +455,12 @@ void Dialog::draw() {
for (uint lineCtr = 0, yp = 5; lineCtr < _lines.size(); ++lineCtr, yp += _vm->_font->getHeight() + 1) {
if (_lines[lineCtr].xp == 0xff) {
hLine(2, width() - 6, ((_vm->_font->getHeight() + 1) >> 1) + yp);
if (_lines[lineCtr].barLine) {
// Bar separation line
hLine(5, width() - 6, ((_vm->_font->getHeight() + 1) >> 1) + yp);
} else {
Common::Point pt((_lines[lineCtr].xp & 0x7f) + 5, yp);
// Standard line
Common::Point pt(_lines[lineCtr].xp + 5, yp);
if (_lines[lineCtr].xp & 0x40)
++pt.y;

View File

@ -37,8 +37,9 @@ public:
char data[100];
uint8 xp;
bool underline;
bool barLine;
DialogLine() { data[0] = '\0'; xp = 0; underline = false; }
DialogLine() { data[0] = '\0'; xp = 0; underline = barLine = false; }
};
class Dialog: public View {
@ -51,7 +52,7 @@ private:
RGBList *_palette;
int _lineX;
int _widthX;
bool _commandCase;
void initDialog();
void incLine();
@ -59,6 +60,9 @@ private:
void writeChars(const char *line);
void addLine(const char *line, bool underlineP = false);
void appendText(const char *line);
void addBarLine();
void getVocab(int vocabId, char **line);
bool handleNounSuffix(char *destP, int nounNum, const char *srcP);
void draw();
public:
Dialog(M4Engine *vm, const char *msgData, const char *title = NULL);