[Scummvm-cvs-logs] CVS: scummvm/queen talk.cpp,NONE,1.1 talk.h,NONE,1.1 cutaway.cpp,1.9,1.10 cutaway.h,1.5,1.6 module.mk,1.6,1.7
David Eriksson
twogood at users.sourceforge.net
Mon Oct 6 22:03:40 CEST 2003
Update of /cvsroot/scummvm/scummvm/queen
In directory sc8-pr-cvs1:/tmp/cvs-serv12137
Modified Files:
cutaway.cpp cutaway.h module.mk
Added Files:
talk.cpp talk.h
Log Message:
- Add Talk class and begin to use it from Cutaway class
- Move getString() helper function to Talk class
--- NEW FILE: talk.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/queen/talk.cpp,v 1.1 2003/10/07 03:58:44 twogood Exp $
*
*/
#include "stdafx.h"
#include "talk.h"
#include "graphics.h"
namespace Queen {
/*
Functions needed:
Data needed:
*/
void Talk::run(
const char *filename,
char *cutawayFilename,
Logic *logic,
Resource *resource) {
Talk *talk = new Talk(logic, resource);
talk->talk(filename, cutawayFilename);
delete talk;
}
Talk::Talk(
Logic *logic,
Resource *resource)
: _logic(logic), _resource(resource), _fileData(NULL), _quit(false) {
//! TODO Move this to the Logic class later!
memset(_talkSelected, 0, sizeof(_talkSelected));
}
Talk::~Talk() {
delete[] _fileData;
}
void Talk::talk(const char *filename, char *cutawayFilename) {
_oldSelectedSentenceIndex = 0;
_oldSelectedSentenceValue = 0;
debug(0, "----- talk(\"%s\") -----", filename);
cutawayFilename[0] = '\0';
load(filename);
char personName[MAX_STRING_SIZE];
// XXX SET_PERSON_DATA(N,NAMEstr,0);
int bobNum = 0; // XXX P_BNUM;
// XXX strcpy(PERstr,P_NAMEstr);
personName[0] = '\0';
int16 oldLevel = 0;
bool personWalking = false; // OWALK in talk.c
// Lines 828-846 in talk.c
for (int i = 1; i <= 4; i++) {
if (talkSelected()->values[i-1] > 0) {
// This option has been redefined so display new dialogue option
_dialogueTree[1][i].head = talkSelected()->values[i-1];
}
else if (talkSelected()->values[i-1] == -1) {
// Already selected so don't redisplay
if (_dialogueTree[1][i].gameStateIndex >= 0) {
_dialogueTree[1][i].head = -1;
_dialogueTree[1][i].dialogueNodeValue1 = -1;
_dialogueTree[1][i].gameStateIndex = -1;
_dialogueTree[1][i].gameStateValue = -1;
}
}
}
initialTalk();
// Lines 906-? in talk.c
// XXX drawmouseflag=1;
int16 level=1, retval=0, type=1;
int16 head = _dialogueTree[level][0].head;
while(retval != -1) {
debug(0, "retval = %i", retval);
char otherVoiceFilePrefix [MAX_STRING_SIZE];
char joeVoiceFilePrefix [5][MAX_STRING_SIZE];
char talkString [5][MAX_STRING_SIZE];
talkString[0][0] = '\0';
if(talkSelected()->hasTalkedTo == 1 && head == 1)
strcpy(talkString[0], _person2String);
else
findDialogueString(_person1Ptr, head, talkString[0]);
if(talkSelected()->hasTalkedTo == 1 && head == 1)
sprintf(otherVoiceFilePrefix, "%2dXXXXP", _talkKey);
else
sprintf(otherVoiceFilePrefix, "%2d%4xP", _talkKey, head);
if (talkString[0][0] == '\0' && retval > 1) {
findDialogueString(_person1Ptr, retval, talkString[0]);
sprintf(otherVoiceFilePrefix,"%2d%4xP", _talkKey, retval);
}
// Joe dialogue
for (int i = 1; i <= 4; i++) {
findDialogueString(_joePtr, _dialogueTree[level][i].head, talkString[i]);
int16 index = _dialogueTree[level][i].gameStateIndex;
if (index < 0 && _logic->gameState(abs(index)) != _dialogueTree[level][i].gameStateValue)
talkString[i][0] = '\0';
sprintf(joeVoiceFilePrefix[i], "%2d%4xJ", _talkKey, _dialogueTree[level][i].head);
}
// Check to see if(all the dialogue options have been selected.
// if this is the case, and the last one left is the exit option,
// then automatically set S to that and exit.
int choicesLeft = 0;
int selectedSentence = 0;
for (int i = 1; i <= 4; i++) {
if (talkString[i][0] != '\0') {
choicesLeft++;
selectedSentence = i;
}
}
debug(0, "choicesLeft = %i", choicesLeft);
if (1 == choicesLeft) {
// Automatically run the final dialogue option
if (speak(talkString[0], personName, otherVoiceFilePrefix))
personWalking = true;
if (_quit)
break;
speak(talkString[selectedSentence], personName, joeVoiceFilePrefix[selectedSentence]);
}
else {
// XXX if (bobNum > 0)
// XXX selectedSentence = bobTalk(personName);
for (int i = 1; i <= 4; i++) {
if (talkString[i][0] != '\0') {
selectedSentence = i;
break;
}
}
}
if (_quit)
break;
retval = _dialogueTree[level][selectedSentence].dialogueNodeValue1;
head = _dialogueTree[level][selectedSentence].head;
oldLevel = level;
level = 0;
// Set LEVEL to the selected child in dialogue tree
for (int i = 1; i <= _levelMax; i++)
if (_dialogueTree[i][0].head == head)
level = i;
if (0 == level) {
// No new level has been selected, so lets set LEVEL to the
// tree path pointed to by the RETVAL
for (int i = 1; i <= _levelMax; i++)
for (int j = 0; j <= 5; j++)
if (_dialogueTree[i][j].head == retval)
level = i;
disableSentence(oldLevel, selectedSentence);
}
else { // 0 != level
// Check to see if Person Return value is positive, if it is, then
// change the selected dialogue option to the Return value
if (_dialogueTree[level][0].dialogueNodeValue1 > 0) {
if (1 == oldLevel) {
_oldSelectedSentenceIndex = selectedSentence;
_oldSelectedSentenceValue = talkSelected()->values[selectedSentence-1];
talkSelected()->values[selectedSentence-1] = _dialogueTree[level][0].dialogueNodeValue1;
}
_dialogueTree[oldLevel][selectedSentence].head = _dialogueTree[level][0].dialogueNodeValue1;
_dialogueTree[level][0].dialogueNodeValue1 = -1;
}
else {
disableSentence(oldLevel, selectedSentence);
}
}
// Check selected person to see if any Gamestates need setting
int16 index = _dialogueTree[level][0].gameStateIndex;
if (index > 0)
_logic->gameState(index, _dialogueTree[level][0].gameStateValue);
// if the selected dialogue line has a POSITIVE game state value
// then set gamestate to Value = TALK(OLDLEVEL,S,3)
index = _dialogueTree[oldLevel][selectedSentence].gameStateIndex;
if (index > 0)
_logic->gameState(index, _dialogueTree[oldLevel][selectedSentence].gameStateValue);
// if(RETVAL = -1, then before we exit, check to see if(person
// has something final to say!
// XXX debug
//break;
}
}
void Talk::disableSentence(int oldLevel, int selectedSentence) {
// Mark off selected option
if (1 == oldLevel) {
if (_dialogueTree[oldLevel][selectedSentence].dialogueNodeValue1 != -1) {
// Make sure choice is not exit option
_oldSelectedSentenceIndex = selectedSentence;
_oldSelectedSentenceValue = talkSelected()->values[selectedSentence-1];
talkSelected()->values[selectedSentence-1] = -1;
}
}
// Cancel selected dialogue line, so that its no longer displayed
_dialogueTree[oldLevel][selectedSentence].head = -1;
_dialogueTree[oldLevel][selectedSentence].dialogueNodeValue1 = -1;
}
void Talk::findDialogueString(byte *ptr, int16 id, char *str) {
str[0] = '\0';
for (int i = 1; i <= _pMax; i++) {
ptr += 2;
int16 currentId = (int16)READ_BE_UINT16(ptr); ptr += 2;
if (id == currentId) {
ptr = getString(ptr, str, MAX_STRING_LENGTH, 4);
debug(0, "Found string with ID %i: '%s'", id, str);
break;
}
else
ptr = getString(ptr, NULL, MAX_STRING_LENGTH, 4);
}
if (str[0] == '\0')
warning("Failed to find string with ID %i", id);
}
void Talk::load(const char *filename) {
byte *ptr = _fileData = _resource->loadFile(filename, 20);
if (!_fileData) {
error("Failed to load resource data file '%s'", filename);
}
bool canQuit;
//
// Load talk header
//
_levelMax = (int16)READ_BE_UINT16(ptr); ptr += 2;
debug(0, "levelMax = %i", _levelMax);
if (_levelMax < 0) {
_levelMax = -_levelMax;
canQuit = false;
}
else
canQuit = true;
_uniqueKey = (int16)READ_BE_UINT16(ptr); ptr += 2;
_talkKey = (int16)READ_BE_UINT16(ptr); ptr += 2;
int16 jMax = (int16)READ_BE_UINT16(ptr); ptr += 2;
_pMax = (int16)READ_BE_UINT16(ptr); ptr += 2;
int16 gameState1 = (int16)READ_BE_UINT16(ptr); ptr += 2;
int16 testValue1 = (int16)READ_BE_UINT16(ptr); ptr += 2;
int16 itemToInsert1 = (int16)READ_BE_UINT16(ptr); ptr += 2;
int16 gameState2 = (int16)READ_BE_UINT16(ptr); ptr += 2;
int16 testValue2 = (int16)READ_BE_UINT16(ptr); ptr += 2;
int16 itemToInsert2 = (int16)READ_BE_UINT16(ptr); ptr += 2;
debug(0, "uniqueKey = %i", _uniqueKey);
debug(0, "talkKey = %i", _talkKey);
_person1Ptr = _fileData + READ_BE_UINT16(ptr); ptr += 2;
byte *cutawayPtr = _fileData + READ_BE_UINT16(ptr); ptr += 2;
_person2Ptr = _fileData + READ_BE_UINT16(ptr); ptr += 2;
if (ptr != (_fileData + 28))
error("ptr != (_fileData + 28))");
byte *dataPtr = _fileData + 32;
_joePtr = dataPtr + _levelMax * 96;
//
// Load dialogue tree
//
ptr = dataPtr;
for (int i = 1; i <= _levelMax; i++)
for (int j = 0; j <= 5; j++) {
ptr += 2;
_dialogueTree[i][j].head = (int16)READ_BE_UINT16(ptr); ptr += 2;
ptr += 2;
_dialogueTree[i][j].dialogueNodeValue1 = (int16)READ_BE_UINT16(ptr); ptr += 2;
ptr += 2;
_dialogueTree[i][j].gameStateIndex = (int16)READ_BE_UINT16(ptr); ptr += 2;
ptr += 2;
_dialogueTree[i][j].gameStateValue = (int16)READ_BE_UINT16(ptr); ptr += 2;
}
}
void Talk::initialTalk() {
// Lines 848-903 in talk.c
byte *ptr = _joePtr + 2;
uint16 hasString = READ_BE_UINT16(ptr); ptr += 2;
char joeString[MAX_STRING_SIZE];
if (hasString) {
ptr = getString(ptr, joeString, MAX_STRING_LENGTH);
debug(0, "joeString = '%s'", joeString);
}
else
joeString[0] = '\0';
ptr = _person2Ptr;
ptr = getString(ptr, _person2String, MAX_STRING_LENGTH);
debug(0, "person2String = '%s'", _person2String);
char joe2String[MAX_STRING_SIZE];
ptr = getString(ptr, joe2String, MAX_STRING_LENGTH);
debug(0, "joe2String = '%s'", joe2String);
if (talkSelected()->hasTalkedTo == 0) {
// Not yet talked to this person
if (joeString[0] != '0') {
char voiceFilePrefix[MAX_STRING_SIZE];
sprintf(voiceFilePrefix, "%2dSSSSJ", _talkKey);
speak(joeString, "JOE", voiceFilePrefix);
}
}
else {
// Already spoken to them, choose second response
if (joe2String[0] != '0') {
char voiceFilePrefix[MAX_STRING_SIZE];
sprintf(voiceFilePrefix, "%2dSSSSJ", _talkKey);
speak(joe2String, "JOE", voiceFilePrefix);
}
}
}
bool Talk::speak(const char *sentence, const char *person, const char *voiceFilePrefix) {
debug(0, "Sentence '%s' is said by person '%s' and voice files with prefix '%s' played",
sentence, person, voiceFilePrefix);
return false; // XXX
}
byte *Talk::getString(byte *ptr, char *str, int maxLength, int align) {
int length = *ptr;
ptr++;
if (length > maxLength) {
error("String too long. Length = %i, maxLength = %i, str = '%*s'",
length, maxLength, length, (const char*)ptr);
}
else if (length) {
if (str)
memcpy(str, (const char*)ptr, length);
ptr += length;
while ((int)ptr % align)
ptr++;
}
if (str)
str[length] = '\0';
return ptr;
}
Talk::TalkSelected *Talk::talkSelected() {
return _talkSelected + _uniqueKey;
}
} // End of namespace Queen
--- NEW FILE: talk.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/queen/talk.h,v 1.1 2003/10/07 03:58:44 twogood Exp $
*
*/
#ifndef QUEEN_TALK_H
#define QUEEN_TALK_H
#include "queen/queen.h"
namespace Queen {
class Resource;
class Logic;
class Talk {
public:
//! Public interface to run a talk from a file
static void run(
const char *filename,
char *cutawayFilename,
Logic *logic,
Resource *resource);
//! Public interface to speak a sentence
#if 0
static void run(
const char *sentence,
const char *person,
int noun,
Logic *logic,
Resource *resource);
#endif
//! Read a string from ptr and return new ptr
static byte *getString(byte *ptr, char *str, int maxLength, int align = 2);
private:
//! Collection of constants used by Talk
enum {
MAX_STRING_LENGTH = 255,
MAX_STRING_SIZE = (MAX_STRING_LENGTH + 1),
TALK_SELECTED_COUNT = 86
};
//! TODO Move this to struct.h later!
struct TalkSelected {
int16 hasTalkedTo;
int16 values[4];
};
struct DialogueNode {
int16 head;
int16 dialogueNodeValue1;
int16 gameStateIndex;
int16 gameStateValue;
};
Logic *_logic;
Resource *_resource;
//! Raw .dog file data (without 20 byte header)
byte *_fileData;
//! Number of dialogue levels
int16 _levelMax;
//! Unique key for this dialogue
int16 _uniqueKey;
//! Used to select voice files
int16 _talkKey;
//! Used by findDialogueString
int16 _pMax;
//! String data
byte *_person1Ptr;
//! Data used if we have talked to the person before
byte *_person2Ptr;
//! Data used if we haven't talked to the person before
byte *_joePtr;
//! Set to true to quit talking
bool _quit;
//! IDs for sentences
DialogueNode _dialogueTree[18][6];
//! TODO Move this to the Logic class later!
TalkSelected _talkSelected[TALK_SELECTED_COUNT];
//! Greeting from person Joe has talked to before
char _person2String[MAX_STRING_SIZE];
int _oldSelectedSentenceIndex;
int _oldSelectedSentenceValue;
Talk(Logic *logic, Resource *resource);
~Talk();
//! Perform talk in file and return a cutaway filename
void talk(const char *filename, char *cutawayFilename);
//! Load talk data from .dog file
void load(const char *filename);
//! First things spoken
void initialTalk();
//! Find a string in the dialogue tree
void findDialogueString(byte *ptr, int16 id, char *str);
//! Speak sentence
bool speak(const char *sentence, const char *person, const char *voiceFilePrefix);
//! Get TalkSelected struct for this talk
TalkSelected *talkSelected();
//! The sentence will not be displayed again
void disableSentence(int oldLevel, int selectedSentence);
};
} // End of namespace Queen
#endif
Index: cutaway.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/queen/cutaway.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cutaway.cpp 6 Oct 2003 14:01:41 -0000 1.9
+++ cutaway.cpp 7 Oct 2003 03:58:44 -0000 1.10
@@ -22,6 +22,7 @@
#include "stdafx.h"
#include "cutaway.h"
#include "graphics.h"
+#include "talk.h"
namespace Queen {
@@ -46,7 +47,6 @@
Data needed:
CURRSONG
- GAMESTATE
JOEF (Joe's face direction)
JX,JY (Joe's coordintes)
PERSON_FACE
@@ -68,11 +68,11 @@
const char *filename,
Logic *logic,
Resource *resource)
-: _logic(logic), _quit(false), _lastSong(0), _songBeforeComic(0) {
+: _logic(logic), _resource(resource), _quit(false), _lastSong(0), _songBeforeComic(0) {
// XXX should not create this object ourselves
_graphics = new Graphics(resource);
memset(&_bankNames, 0, sizeof(_bankNames));
- load(filename, resource);
+ load(filename);
}
Cutaway::~Cutaway() {
@@ -81,14 +81,12 @@
delete[] _fileData;
}
-void Cutaway::load(const char *filename, Resource *resource) {
+void Cutaway::load(const char *filename) {
byte *ptr;
- ptr = _fileData = resource->loadFile(filename, 20);
+ ptr = _fileData = _resource->loadFile(filename, 20);
if (!_fileData) {
error("Failed to load resource data file '%s'", filename);
- _quit = true;
- return;
}
if (0 == scumm_stricmp(filename, "comic.cut"))
@@ -149,7 +147,7 @@
}
char entryString[MAX_STRING_SIZE];
- _nextSentence = getString(_nextSentence, entryString, MAX_STRING_LENGTH);
+ _nextSentence = Talk::getString(_nextSentence, entryString, MAX_STRING_LENGTH);
debug(0, "Entry string = '%s'", entryString);
if (entryString[0] == '*' &&
@@ -173,27 +171,6 @@
}
-byte *Cutaway::getString(byte *ptr, char *str, int maxLength) {
- int length = *ptr;
- ptr++;
-
- if (length > maxLength) {
- error("String too long. Length = %i, maxLength = %i, str = '%*s'",
- length, maxLength, length, (const char*)ptr);
- }
- else if (length) {
- memcpy(str, (const char*)ptr, length);
- ptr += length;
-
- while ((int)ptr % 2)
- ptr++;
- }
-
- str[length] = '\0';
-
- return ptr;
-}
-
void Cutaway::loadStrings(byte *ptr) {
int i,j;
@@ -208,7 +185,7 @@
*/
for (i = 0, j = 0; i < bankNameCount; i++) {
- ptr = getString(ptr, _bankNames[j], MAX_FILENAME_LENGTH);
+ ptr = Talk::getString(ptr, _bankNames[j], MAX_FILENAME_LENGTH);
if (_bankNames[j][0]) {
debug(0, "Bank name %i = '%s'", _bankNames[j]);
@@ -217,7 +194,7 @@
}
debug(0, "Getting talk file");
- ptr = getString(ptr, _talkFile, MAX_FILENAME_LENGTH);
+ ptr = Talk::getString(ptr, _talkFile, MAX_FILENAME_LENGTH);
debug(0, "Talk file = '%s'", _talkFile);
int TALKTO = READ_BE_UINT16(ptr);
@@ -268,6 +245,7 @@
switch (object.objectNumber) {
case -1: objectNumberStr = "MESSAGE"; break;
case 0: objectNumberStr = "Joe"; break;
+ case 196: objectNumberStr = "Chef"; break;
case 548: objectNumberStr = "Anderson"; break;
default: objectNumberStr = "unknown"; break;
}
@@ -731,7 +709,7 @@
limitBob(object);
char sentence[MAX_STRING_SIZE];
- _nextSentence = getString(_nextSentence, sentence, MAX_STRING_LENGTH);
+ _nextSentence = Talk::getString(_nextSentence, sentence, MAX_STRING_LENGTH);
debug(0, "Sentence = '%s'", sentence);
if (OBJECT_ROOMFADE == object.objectNumber) {
@@ -1006,11 +984,11 @@
// Turn area on or off
if (areaSubIndex > 0) {
- int16* area = _logic->area(areaIndex, areaSubIndex);
+ int16 *area = _logic->area(areaIndex, areaSubIndex);
area[0] = abs(area[0]);
}
else {
- int16* area = _logic->area(areaIndex, abs(areaSubIndex));
+ int16 *area = _logic->area(areaIndex, abs(areaSubIndex));
area[0] = -abs(area[0]);
}
}
@@ -1033,8 +1011,10 @@
// Lines 2119-2131 in cutaway.c
if (0 == scumm_stricmp(right(_talkFile, 4), ".dog")) {
- warning("Cutaway::talk() needed but not yet implemented");
+ warning("Cutaway::talk() used but not fully implemented");
nextFilename[0] = '\0';
+
+ Talk::run(_talkFile, nextFilename, _logic, _resource);
}
}
Index: cutaway.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/queen/cutaway.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cutaway.h 5 Oct 2003 16:07:07 -0000 1.5
+++ cutaway.h 7 Oct 2003 03:58:44 -0000 1.6
@@ -121,6 +121,7 @@
};
Logic *_logic;
+ Resource *_resource;
Graphics *_graphics;
//! Raw .cut file data (without 20 byte header)
@@ -188,7 +189,7 @@
void run(char *nextFilename);
//! Load cutaway data from file
- void load(const char *filename, Resource *resource);
+ void load(const char *filename);
//! Used by load to read string data
void loadStrings(byte *ptr);
@@ -234,9 +235,6 @@
//! Get CutawayAnim data from ptr and return new ptr
byte *getCutawayAnim(byte *ptr, int header, CutawayAnim &anim);
-
- //! Read a string from ptr and return new ptr
- static byte *getString(byte *ptr, char *str, int maxLength);
//! Read a CutawayObject from ptr and return new ptr
static byte *getCutawayObject(byte *ptr, CutawayObject &object);
Index: module.mk
===================================================================
RCS file: /cvsroot/scummvm/scummvm/queen/module.mk,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- module.mk 6 Oct 2003 23:04:00 -0000 1.6
+++ module.mk 7 Oct 2003 03:58:44 -0000 1.7
@@ -7,6 +7,7 @@
queen/queen.o \
queen/resource.o \
queen/restables.o \
+ queen/talk.o
# This module can be built as a plugin
ifdef BUILD_PLUGINS
More information about the Scummvm-git-logs
mailing list