mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-28 04:34:50 +00:00
239275c608
svn-id: r12658
1949 lines
51 KiB
C++
1949 lines
51 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2003-2004 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$
|
|
*
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "queen/talk.h"
|
|
|
|
#include "queen/bankman.h"
|
|
#include "queen/display.h"
|
|
#include "queen/graphics.h"
|
|
#include "queen/grid.h"
|
|
#include "queen/input.h"
|
|
#include "queen/logic.h"
|
|
#include "queen/queen.h"
|
|
#include "queen/resource.h"
|
|
#include "queen/sound.h"
|
|
#include "queen/state.h"
|
|
#include "queen/walk.h"
|
|
|
|
#include "common/file.h"
|
|
|
|
namespace Queen {
|
|
|
|
void Talk::talk(
|
|
const char *filename,
|
|
int personInRoom,
|
|
char *cutawayFilename,
|
|
QueenEngine *vm) {
|
|
Talk *talk = new Talk(vm);
|
|
talk->talk(filename, personInRoom, cutawayFilename);
|
|
delete talk;
|
|
}
|
|
|
|
bool Talk::speak(
|
|
const char *sentence,
|
|
Person *person,
|
|
const char *voiceFilePrefix,
|
|
QueenEngine *vm) {
|
|
Talk *talk = new Talk(vm);
|
|
bool result;
|
|
if (sentence)
|
|
result = talk->speak(sentence, person, voiceFilePrefix);
|
|
else
|
|
result = false;
|
|
delete talk;
|
|
return result;
|
|
}
|
|
|
|
Talk::Talk(QueenEngine *vm)
|
|
: _vm(vm), _fileData(NULL) {
|
|
_vm->input()->talkQuitReset();
|
|
}
|
|
|
|
Talk::~Talk() {
|
|
delete[] _fileData;
|
|
}
|
|
|
|
void Talk::talk(const char *filename, int personInRoom, char *cutawayFilename) {
|
|
int i;
|
|
_oldSelectedSentenceIndex = 0;
|
|
_oldSelectedSentenceValue = 0;
|
|
|
|
debug(6, "----- talk(\"%s\") -----", filename);
|
|
|
|
cutawayFilename[0] = '\0';
|
|
|
|
// XXX S=SUBJECT[1];
|
|
|
|
int roomStart = _vm->logic()->currentRoomData();
|
|
ObjectData *data = _vm->logic()->objectData(roomStart + personInRoom);
|
|
|
|
if (data->name <= 0) // disabled!
|
|
return;
|
|
|
|
if (data->entryObj > 0)
|
|
return;
|
|
|
|
if (State::findTalk(data->state) == STATE_TALK_MUTE) {
|
|
// 'I can't talk to that'
|
|
_vm->logic()->makeJoeSpeak(24 + _vm->randomizer.getRandomNumber(2));
|
|
return;
|
|
}
|
|
|
|
load(filename);
|
|
|
|
Person person;
|
|
memset(&person, 0, sizeof(Person));
|
|
_vm->logic()->initPerson(personInRoom, "", false, &person);
|
|
|
|
if (NULL == person.name) {
|
|
error("Invalid person object");
|
|
}
|
|
|
|
int16 oldLevel = 0;
|
|
bool personWalking = false; // OWALK in talk.c
|
|
|
|
// Lines 828-846 in talk.c
|
|
for (i = 1; i <= 4; i++) {
|
|
if (selectedValue(i) > 0) {
|
|
// This option has been redefined so display new dialogue option
|
|
_dialogueTree[1][i].head = selectedValue(i);
|
|
}
|
|
else if (selectedValue(i) == -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
|
|
_vm->display()->showMouseCursor(true);
|
|
|
|
int16 level=1, retval=0;
|
|
int16 head = _dialogueTree[level][0].head;
|
|
|
|
// TODO: split this loop in several functions
|
|
while(retval != -1) {
|
|
// debug(6, "retval = %i", retval);
|
|
|
|
char otherVoiceFilePrefix [MAX_STRING_SIZE];
|
|
|
|
_talkString[0][0] = '\0';
|
|
|
|
if (hasTalkedTo() && head == 1)
|
|
strcpy(_talkString[0], _person2String);
|
|
else
|
|
findDialogueString(_person1Ptr, head, _pMax, _talkString[0]);
|
|
|
|
if (hasTalkedTo() && head == 1)
|
|
sprintf(otherVoiceFilePrefix, "%2dXXXXP", _talkKey);
|
|
else
|
|
sprintf(otherVoiceFilePrefix, "%2d%4xP", _talkKey, head);
|
|
|
|
if (_talkString[0][0] == '\0' && retval > 1) {
|
|
findDialogueString(_person1Ptr, retval, _pMax, _talkString[0]);
|
|
sprintf(otherVoiceFilePrefix,"%2d%4xP", _talkKey, retval);
|
|
}
|
|
|
|
// Joe dialogue
|
|
|
|
for (i = 1; i <= 4; i++) {
|
|
findDialogueString(_joePtr, _dialogueTree[level][i].head, _jMax, _talkString[i]);
|
|
|
|
int16 index = _dialogueTree[level][i].gameStateIndex;
|
|
|
|
if (index < 0 && _vm->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 (i = 1; i <= 4; i++) {
|
|
if (_talkString[i][0] != '\0') {
|
|
choicesLeft++;
|
|
selectedSentence = i;
|
|
}
|
|
}
|
|
|
|
debug(6, "choicesLeft = %i", choicesLeft);
|
|
|
|
if (1 == choicesLeft) {
|
|
// Automatically run the final dialogue option
|
|
if (speak(_talkString[0], &person, otherVoiceFilePrefix))
|
|
personWalking = true;
|
|
|
|
if (_vm->input()->talkQuit())
|
|
break;
|
|
|
|
speak(_talkString[selectedSentence], NULL, _joeVoiceFilePrefix[selectedSentence]);
|
|
}
|
|
else {
|
|
if (person.actor->bobNum > 0) {
|
|
speak(_talkString[0], &person, otherVoiceFilePrefix);
|
|
selectedSentence = selectSentence();
|
|
}
|
|
else {
|
|
warning("bobBum is %i", person.actor->bobNum);
|
|
selectedSentence = 0;
|
|
}
|
|
}
|
|
|
|
if (_vm->input()->talkQuit())
|
|
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 (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 (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 = selectedValue(selectedSentence);
|
|
selectedValue(selectedSentence, _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)
|
|
_vm->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)
|
|
_vm->logic()->gameState(index, _dialogueTree[oldLevel][selectedSentence].gameStateValue);
|
|
|
|
|
|
// if(RETVAL = -1, then before we exit, check to see if(person
|
|
// has something final to say!
|
|
|
|
if (-1 == retval) {
|
|
findDialogueString(_person1Ptr, head, _pMax, _talkString[0]);
|
|
if (_talkString[0][0] != '\0') {
|
|
sprintf(otherVoiceFilePrefix, "%2d%4xP", _talkKey, head);
|
|
if (speak(_talkString[0], &person, otherVoiceFilePrefix))
|
|
personWalking = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// TALK_PROC_EXIT:
|
|
|
|
cutawayFilename[0] = '\0';
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (_gameState[i] > 0) {
|
|
if (_vm->logic()->gameState(_gameState[i]) == _testValue[i]) {
|
|
if (_itemNumber[i] > 0)
|
|
_vm->logic()->inventoryInsertItem(_itemNumber[i]);
|
|
else
|
|
_vm->logic()->inventoryDeleteItem(ABS(_itemNumber[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
_vm->grid()->setupPanel();
|
|
|
|
uint8 *ptr = _cutawayPtr;
|
|
|
|
int16 cutawayGameState = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
int16 cutawayTestValue = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
|
|
if (_vm->logic()->gameState(cutawayGameState) == cutawayTestValue) {
|
|
getString(ptr, cutawayFilename, 20);
|
|
if (cutawayFilename[0]) {
|
|
//CR 2 - 7/3/95, If we're executing a cutaway scene, then make sure
|
|
// Joe can talk, so set TALKQUIT to 0 just in case we exit on the
|
|
// line that set's the cutaway game states.
|
|
_vm->input()->talkQuitReset();
|
|
}
|
|
}
|
|
if (_vm->input()->talkQuit()) {
|
|
if (_oldSelectedSentenceIndex > 0)
|
|
selectedValue(_oldSelectedSentenceIndex, _oldSelectedSentenceValue);
|
|
_vm->input()->talkQuitReset();
|
|
_vm->display()->clearTexts(0, 198);
|
|
_vm->logic()->makeJoeSpeak(15, false);
|
|
}
|
|
else {
|
|
setHasTalkedTo();
|
|
}
|
|
|
|
_vm->logic()->joeFace();
|
|
|
|
if (cutawayFilename[0] == '\0') {
|
|
BobSlot *pbs = _vm->graphics()->bob(person.actor->bobNum);
|
|
|
|
pbs->x = person.actor->x;
|
|
pbs->y = person.actor->y;
|
|
|
|
// Better kick start the persons anim sequence
|
|
_vm->graphics()->resetPersonAnim(person.actor->bobNum);
|
|
}
|
|
|
|
_vm->logic()->joeWalk(JWM_NORMAL);
|
|
}
|
|
|
|
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 = selectedValue(selectedSentence);
|
|
selectedValue(selectedSentence, -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, int16 max, char *str) {
|
|
str[0] = '\0';
|
|
|
|
for (int i = 1; i <= max; i++) {
|
|
ptr += 2;
|
|
int16 currentId = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
if (id == currentId) {
|
|
ptr = getString(ptr, str, MAX_STRING_LENGTH, 4);
|
|
//debug(6, "Found string with ID %i: '%s'", id, str);
|
|
break;
|
|
}
|
|
else
|
|
ptr = getString(ptr, NULL, MAX_STRING_LENGTH, 4);
|
|
}
|
|
}
|
|
|
|
byte *Talk::loadDialogFile(const char *filename) {
|
|
static const struct {
|
|
const char *filename;
|
|
Language lang;
|
|
} dogFiles[] = {
|
|
{ "chief1.dog", FRENCH },
|
|
{ "chief2.dog", FRENCH },
|
|
{ "bud1.dog", ITALIAN }
|
|
};
|
|
for (int i = 0; i < ARRAYSIZE(dogFiles); ++i) {
|
|
if (!scumm_stricmp(filename, dogFiles[i].filename) &&
|
|
_vm->resource()->getLanguage() == dogFiles[i].lang) {
|
|
File fdog;
|
|
fdog.open(filename, _vm->getGameDataPath());
|
|
if (fdog.isOpen()) {
|
|
debug(6, "Loading dog file '%s' from game data path", filename);
|
|
uint32 size = fdog.size() - DOG_HEADER_SIZE;
|
|
byte *buf = new byte[size];
|
|
fdog.seek(DOG_HEADER_SIZE);
|
|
fdog.read(buf, size);
|
|
return buf;
|
|
}
|
|
}
|
|
}
|
|
return _vm->resource()->loadFile(filename, DOG_HEADER_SIZE);
|
|
}
|
|
|
|
void Talk::load(const char *filename) {
|
|
int i;
|
|
|
|
byte *ptr = _fileData = loadDialogFile(filename);
|
|
|
|
bool canQuit;
|
|
|
|
//
|
|
// Load talk header
|
|
//
|
|
|
|
_levelMax = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
|
|
//debug(6, "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;
|
|
_jMax = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
_pMax = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
_gameState [i] = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
_testValue [i] = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
_itemNumber[i] = (int16)READ_BE_UINT16(ptr); ptr += 2;
|
|
}
|
|
|
|
//debug(6, "uniqueKey = %i", _uniqueKey);
|
|
//debug(6, "talkKey = %i", _talkKey);
|
|
|
|
_person1Ptr = _fileData + READ_BE_UINT16(ptr); ptr += 2;
|
|
_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;
|
|
|
|
memset(&_dialogueTree[0], 0, sizeof(_dialogueTree[0]));
|
|
for (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 hasNotString = READ_BE_UINT16(ptr); ptr += 2;
|
|
|
|
char joeString[MAX_STRING_SIZE];
|
|
if (!hasNotString) {
|
|
ptr = getString(ptr, joeString, MAX_STRING_LENGTH);
|
|
//debug(6, "joeString = '%s'", joeString);
|
|
}
|
|
else
|
|
joeString[0] = '\0';
|
|
|
|
ptr = _person2Ptr;
|
|
ptr = getString(ptr, _person2String, MAX_STRING_LENGTH);
|
|
//debug(6, "person2String = '%s'", _person2String);
|
|
|
|
char joe2String[MAX_STRING_SIZE];
|
|
ptr = getString(ptr, joe2String, MAX_STRING_LENGTH);
|
|
//debug(6, "joe2String = '%s'", joe2String);
|
|
|
|
if (!hasTalkedTo()) {
|
|
|
|
// Not yet talked to this person
|
|
|
|
if (joeString[0] != '0') {
|
|
char voiceFilePrefix[MAX_STRING_SIZE];
|
|
sprintf(voiceFilePrefix, "%2dSSSSJ", _talkKey);
|
|
speak(joeString, NULL, voiceFilePrefix);
|
|
}
|
|
}
|
|
else {
|
|
// Already spoken to them, choose second response
|
|
|
|
if (joe2String[0] != '0') {
|
|
char voiceFilePrefix[MAX_STRING_SIZE];
|
|
sprintf(voiceFilePrefix, "%2dXXXXJ", _talkKey);
|
|
speak(joe2String, NULL, voiceFilePrefix);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int Talk::getSpeakCommand(const Person *person, const char *sentence, unsigned &index) {
|
|
// Lines 1299-1362 in talk.c
|
|
int commandCode = SPEAK_DEFAULT;
|
|
|
|
// cyx: what about something like:
|
|
// uint16 id = (sentence[index] << 8) | sentence[index + 1];
|
|
// switch(id) { case 'AO': ... }
|
|
switch (sentence[index]) {
|
|
case 'A':
|
|
if (sentence[index + 1] == 'O')
|
|
commandCode = SPEAK_AMAL_ON;
|
|
else
|
|
warning("Unknown command string: '%2s'", sentence + index);
|
|
break;
|
|
|
|
case 'F':
|
|
switch (sentence[index + 1]) {
|
|
case 'L':
|
|
commandCode = SPEAK_FACE_LEFT;
|
|
break;
|
|
case 'F':
|
|
commandCode = SPEAK_FACE_FRONT;
|
|
break;
|
|
case 'B':
|
|
commandCode = SPEAK_FACE_BACK;
|
|
break;
|
|
case 'R':
|
|
commandCode = SPEAK_FACE_RIGHT;
|
|
break;
|
|
default:
|
|
warning("Unknown command string: '%2s'", sentence + index);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'G':
|
|
switch (sentence[index + 1]) {
|
|
case 'D':
|
|
_vm->logic()->joeGrab(STATE_GRAB_DOWN);
|
|
break;
|
|
case 'M':
|
|
_vm->logic()->joeGrab(STATE_GRAB_MID);
|
|
break;
|
|
default:
|
|
warning("Unknown command string: '%2s'", sentence + index);
|
|
break;
|
|
}
|
|
commandCode = SPEAK_NONE;
|
|
break;
|
|
|
|
case 'W':
|
|
if (sentence[index + 1] == 'T')
|
|
commandCode = SPEAK_PAUSE;
|
|
else
|
|
warning("Unknown command string: '%2s'", sentence + index);
|
|
break;
|
|
|
|
case 'X':
|
|
// For example *XY00(237,112)
|
|
if (sentence[index + 1] == 'Y') {
|
|
commandCode = atoi(sentence + index + 2);
|
|
int x = atoi(sentence + index + 5);
|
|
int y = atoi(sentence + index + 9);
|
|
if (0 == strcmp(person->name, "JOE"))
|
|
_vm->walk()->moveJoe(0, x, y, _vm->input()->cutawayRunning());
|
|
else
|
|
_vm->walk()->movePerson(person, x, y, _vm->graphics()->numFrames(), 0);
|
|
index += 11;
|
|
// if(JOEWALK==3) CUTQUIT=0;
|
|
// XXX personWalking = true;
|
|
}
|
|
else
|
|
warning("Unknown command string: '%2s'", sentence + index);
|
|
break;
|
|
|
|
default:
|
|
if (sentence[index + 0] >= '0' && sentence[index + 0] <= '9' &&
|
|
sentence[index + 1] >= '0' && sentence[index + 1] <= '9') {
|
|
commandCode = (sentence[index] - '0') * 10 + (sentence[index + 1] - '0');
|
|
}
|
|
else
|
|
warning("Unknown command string: '%2s'", sentence + index);
|
|
}
|
|
|
|
index += 2;
|
|
|
|
return commandCode;
|
|
}
|
|
|
|
|
|
bool Talk::speak(const char *sentence, Person *person, const char *voiceFilePrefix) {
|
|
// Function SPEAK, lines 1266-1384 in talk.c
|
|
bool personWalking = false;
|
|
unsigned segmentIndex = 0;
|
|
unsigned segmentStart = 0;
|
|
unsigned i;
|
|
|
|
Person joe_person;
|
|
ActorData joe_actor;
|
|
|
|
_vm->logic()->joeWalk(JWM_SPEAK);
|
|
|
|
if (!person) {
|
|
// Fill in values for use by speakSegment() etc.
|
|
memset(&joe_person, 0, sizeof(Person));
|
|
memset(&joe_actor, 0, sizeof(ActorData));
|
|
|
|
joe_actor.bobNum = 0;
|
|
joe_actor.color = 14;
|
|
joe_actor.bankNum = 7;
|
|
|
|
joe_person.actor = &joe_actor;
|
|
joe_person.name = "JOE";
|
|
|
|
person = &joe_person;
|
|
}
|
|
|
|
//debug(6, "Sentence '%s' is said by person '%s' and voice files with prefix '%s' played",
|
|
// sentence, person->name, voiceFilePrefix);
|
|
|
|
if (sentence[0] == '\0') {
|
|
goto exit;
|
|
}
|
|
|
|
if (0 == strcmp(person->name, "FAYE-H" ) ||
|
|
0 == strcmp(person->name, "FRANK-H") ||
|
|
0 == strcmp(person->name, "AZURA-H") ||
|
|
0 == strcmp(person->name, "X3_RITA") ||
|
|
(0 == strcmp(person->name, "JOE") && _vm->logic()->currentRoom() == FAYE_HEAD ) ||
|
|
(0 == strcmp(person->name, "JOE") && _vm->logic()->currentRoom() == AZURA_HEAD) ||
|
|
(0 == strcmp(person->name, "JOE") && _vm->logic()->currentRoom() == FRANK_HEAD))
|
|
_talkHead = true;
|
|
else
|
|
_talkHead = false;
|
|
|
|
// XXX CLEAR_COMMAND(false)
|
|
|
|
for (i = 0; i < strlen(sentence); ) {
|
|
if (sentence[i] == '*') {
|
|
int segmentLength = i - segmentStart;
|
|
|
|
i++;
|
|
int command = getSpeakCommand(person, sentence, i);
|
|
|
|
if (SPEAK_NONE != command) {
|
|
speakSegment(
|
|
sentence + segmentStart,
|
|
segmentLength,
|
|
person,
|
|
command,
|
|
voiceFilePrefix,
|
|
segmentIndex);
|
|
// XXX if (JOEWALK == 2) break
|
|
}
|
|
|
|
segmentIndex++;
|
|
segmentStart = i;
|
|
}
|
|
else
|
|
i++;
|
|
|
|
if (_vm->input()->cutawayQuit() || _vm->input()->talkQuit())
|
|
goto exit;
|
|
}
|
|
|
|
if (segmentStart != i) {
|
|
speakSegment(
|
|
sentence + segmentStart,
|
|
i - segmentStart,
|
|
person,
|
|
0,
|
|
voiceFilePrefix,
|
|
segmentIndex);
|
|
}
|
|
|
|
exit:
|
|
return personWalking;
|
|
}
|
|
|
|
// cyx : there is a similar function in Cutaway, what about merging them ?
|
|
int Talk::countSpaces(const char *segment) {
|
|
int tmp = 0;
|
|
|
|
while (*segment++)
|
|
tmp++;
|
|
|
|
if (tmp < 10)
|
|
tmp = 10;
|
|
|
|
return (tmp * 2) / (_vm->talkSpeed() / 3);
|
|
}
|
|
|
|
void Talk::headStringAnimation(const SpeechParameters *parameters, int bobNum, int bankNum) {
|
|
// talk.c lines 1612-1635
|
|
BobSlot *bob2 = _vm->graphics()->bob(2);
|
|
|
|
if (parameters->animation[0] == 'E') {
|
|
int offset = 1;
|
|
|
|
BobSlot *bob = _vm->graphics()->bob(bobNum);
|
|
|
|
int16 x = bob->x;
|
|
int16 y = bob->y;
|
|
|
|
for (;;) {
|
|
uint16 frame;
|
|
|
|
frame = atoi(parameters->animation + offset);
|
|
if (!frame)
|
|
break;
|
|
|
|
offset += 4;
|
|
|
|
_vm->bankMan()->unpack(frame, _vm->graphics()->numFrames(), bankNum);
|
|
|
|
bob2->frameNum = _vm->graphics()->numFrames();
|
|
bob2->scale = 100;
|
|
bob2->active = true;
|
|
bob2->x = x;
|
|
bob2->y = y;
|
|
|
|
_vm->update();
|
|
}
|
|
}
|
|
else
|
|
bob2->active = false;
|
|
}
|
|
|
|
void Talk::stringAnimation(const SpeechParameters *parameters, int startFrame, int bankNum) {
|
|
// lines 1639-1690 in talk.c
|
|
|
|
int offset = 0;
|
|
bool torso;
|
|
|
|
if (parameters->animation[0] == 'T') {
|
|
// Torso animation
|
|
torso = true;
|
|
_vm->bankMan()->overpack(parameters->body, startFrame, bankNum);
|
|
offset++;
|
|
}
|
|
else if (parameters->animation[0] == 'E') {
|
|
// Talking head animation
|
|
return;
|
|
}
|
|
else if (!isdigit(parameters->animation[0])) {
|
|
debug(6, "Error in speak string animation: '%s'", parameters->animation);
|
|
return;
|
|
}
|
|
else
|
|
torso = false;
|
|
|
|
for (;;) {
|
|
uint16 frame;
|
|
|
|
frame = atoi(parameters->animation + offset);
|
|
if (!frame)
|
|
break;
|
|
|
|
offset += 4;
|
|
|
|
if (frame > 500) {
|
|
frame -= 500;
|
|
_vm->sound()->playSfx(_vm->logic()->currentRoomSfx(), false);
|
|
}
|
|
|
|
if (torso) {
|
|
_vm->bankMan()->overpack(frame, startFrame, bankNum);
|
|
}
|
|
else {
|
|
_vm->bankMan()->unpack(frame, startFrame, bankNum);
|
|
// XXX bobs[BNUM].scale=SF;
|
|
}
|
|
|
|
_vm->update();
|
|
}
|
|
|
|
// XXX #ifdef __DOS__
|
|
// XXX if (VOICETOGGLE && (sfxflag==0))
|
|
// XXX while (sfxbusy() && KEYVERB!=101)
|
|
// XXX update();
|
|
// XXX #endif
|
|
}
|
|
|
|
void Talk::defaultAnimation(
|
|
const char *segment,
|
|
bool isJoe,
|
|
const SpeechParameters *parameters,
|
|
int startFrame,
|
|
int bankNum) {
|
|
// lines 1730-1823 in talk.c
|
|
|
|
#if 0
|
|
debug(6, "Talk::defaultAnimation(\"%s\", %s, {\"%s\", %i, ...}, %i, %i)",
|
|
segment,
|
|
isJoe ? "true" : "false",
|
|
parameters->name,
|
|
parameters->state,
|
|
startFrame,
|
|
bankNum);
|
|
#endif
|
|
|
|
if (segment[0] != 0) {
|
|
|
|
// XXX #ifdef __DOS__
|
|
// XXX // 02-21-95 03:44pm DOn't talk until sfx finished
|
|
// XXX if(SFXTOGGLE && VOICETOGGLE) {
|
|
// XXX if(TEXTTOGGLE==0)
|
|
// XXX blanktexts(0,150);
|
|
// XXX while(sfxbusy() && KEYVERB!=101)
|
|
// XXX update();
|
|
// XXX }
|
|
|
|
// XXX sfxflag=VOICETOGGLE ? sfxplay(SPKstr) : 1;
|
|
// XXX if((sfxflag==0) && (TEXTTOGGLE==0))
|
|
// XXX blanktexts(0,150);
|
|
// XXX #endif
|
|
|
|
// Why on earth would someone name a variable qzx?
|
|
short qzx = 0;
|
|
|
|
int spaces = countSpaces(segment);
|
|
|
|
int i;
|
|
for (i = 0; i < (spaces + 1) /* || sfxflag == 0*/; i++) {
|
|
// XXX #ifdef __DOS__
|
|
// XXX if(sfxflag==0 && sfxbusy())
|
|
// XXX break;
|
|
// XXX #endif
|
|
|
|
if (parameters != NULL) {
|
|
|
|
int bf;
|
|
if (segment[0] == ' ')
|
|
bf = 0;
|
|
else
|
|
bf = parameters->bf;
|
|
|
|
int head;
|
|
if (parameters->rf > 0)
|
|
head = bf + _vm->randomizer.getRandomNumber(parameters->rf);
|
|
else
|
|
head = bf;
|
|
|
|
if (bf > 0) {
|
|
// Make the head move
|
|
qzx ^= 1;
|
|
if (parameters->af && qzx)
|
|
_vm->bankMan()->overpack(parameters->af + head, startFrame, bankNum);
|
|
else {
|
|
_vm->bankMan()->overpack(head, startFrame, bankNum);
|
|
}
|
|
}
|
|
else {
|
|
debug(6, "[Talk::defaultAnimation] Body action!");
|
|
// Just do a body action
|
|
_vm->bankMan()->overpack(parameters->body, startFrame, bankNum);
|
|
}
|
|
|
|
if (!_talkHead)
|
|
_vm->update();
|
|
}
|
|
else { // (_talkHead && isJoe)
|
|
_vm->update();
|
|
}
|
|
|
|
if (_vm->logic()->joeWalk() == JWM_SPEAK) {
|
|
if (_vm->input()->talkQuit())
|
|
break;
|
|
|
|
_vm->update();
|
|
}
|
|
else {
|
|
if (_vm->input()->talkQuit())
|
|
break;
|
|
|
|
_vm->update(true);
|
|
if (_vm->logic()->joeWalk() == JWM_EXECUTE)
|
|
// Selected a command, so exit
|
|
break;
|
|
}
|
|
|
|
// Skip through text more quickly
|
|
if (_vm->input()->keyVerb() == VERB_SKIP_TEXT) {
|
|
_vm->input()->clearKeyVerb();
|
|
_vm->sound()->stopSpeech();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make sure that Person closes their mouths
|
|
if (!isJoe && parameters->ff > 0)
|
|
_vm->bankMan()->overpack(parameters->ff, startFrame, bankNum);
|
|
}
|
|
|
|
|
|
void Talk::speakSegment(
|
|
const char *segmentStart,
|
|
int length,
|
|
Person *person,
|
|
int command,
|
|
const char *voiceFilePrefix,
|
|
int index)
|
|
{
|
|
// Function SPEAK_SUB, lines 1406-1870 in talk.a
|
|
|
|
int i;
|
|
char segment[MAX_STRING_SIZE];
|
|
memcpy(segment, segmentStart, length);
|
|
segment[length] = '\0';
|
|
|
|
char voiceFileName[MAX_STRING_SIZE];
|
|
snprintf(voiceFileName, sizeof(voiceFileName), "%s%1x", voiceFilePrefix, index + 1);
|
|
|
|
// debug(6, "Sentence segment '%*s' is said by person '%s' and voice file '%s' is played",
|
|
// length, segment, person->name, voiceFileName);
|
|
|
|
// FIXME - it seems the french talkie version has a useless voice file ;
|
|
// the c30e_102 file is very similar to c30e_101, so there is no need to
|
|
// play it. This voice was used in room 30 (N8) when talking to Klunk.
|
|
if (!(_vm->resource()->getLanguage() == FRENCH && !strcmp(voiceFileName, "c30e_102"))
|
|
&& _vm->sound()->speechOn())
|
|
_vm->sound()->playSfx(voiceFileName, true);
|
|
|
|
int faceDirectionCommand = 0;
|
|
|
|
switch (command) {
|
|
case SPEAK_PAUSE:
|
|
for (i = 0; i < 10; i++) {
|
|
if (_vm->input()->talkQuit())
|
|
break;
|
|
_vm->update();
|
|
}
|
|
return;
|
|
|
|
case SPEAK_FACE_LEFT:
|
|
case SPEAK_FACE_RIGHT:
|
|
case SPEAK_FACE_FRONT:
|
|
case SPEAK_FACE_BACK:
|
|
faceDirectionCommand = command;
|
|
command = 0;
|
|
break;
|
|
}
|
|
|
|
bool isJoe = (0 == person->actor->bobNum);
|
|
|
|
int16 bobNum = person->actor->bobNum;
|
|
uint16 color = person->actor->color;
|
|
uint16 bankNum = person->actor->bankNum;
|
|
|
|
BobSlot *bob = _vm->graphics()->bob(bobNum);
|
|
|
|
bool oracle = false;
|
|
int textX = 0;
|
|
int textY = 0;
|
|
|
|
if (!isJoe) {
|
|
if (SPEAK_AMAL_ON == command) {
|
|
// It's the oracle!
|
|
// Dont turn AMAL animation off, and dont manually anim person
|
|
command = SPEAK_ORACLE;
|
|
oracle = true;
|
|
uint16 frameNum = _vm->graphics()->personFrames(bobNum);
|
|
for (i = 5; i <= 8; ++i) {
|
|
_vm->bankMan()->unpack(i, frameNum, bankNum);
|
|
++frameNum;
|
|
}
|
|
}
|
|
else {
|
|
bob->animating = false;
|
|
bob->frameNum = 29 + bobNum + FRAMES_JOE_XTRA;
|
|
}
|
|
}
|
|
|
|
if (_talkHead) {
|
|
// talk.c lines 1491-1533
|
|
if (isJoe) {
|
|
switch (_vm->logic()->currentRoom()) {
|
|
case FAYE_HEAD:
|
|
case AZURA_HEAD:
|
|
textX = 15;
|
|
break;
|
|
|
|
default:
|
|
textX = 150;
|
|
break;
|
|
}
|
|
textY = 30;
|
|
}
|
|
else {
|
|
// XXX spaces = (spaces * 5) / 2;
|
|
switch (_vm->logic()->currentRoom()) {
|
|
case FAYE_HEAD:
|
|
case AZURA_HEAD:
|
|
textX = 15;
|
|
textY = 60;
|
|
break;
|
|
|
|
default: // Frank
|
|
textX = 150;
|
|
textY = 60;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
textX = bob->x;
|
|
textY = bob->y;
|
|
}
|
|
|
|
//int SF = _vm->grid()->findScale(textX, textY);
|
|
|
|
const SpeechParameters *parameters = NULL;
|
|
int startFrame = 0;
|
|
|
|
if (_talkHead && isJoe) {
|
|
if (_vm->subtitles())
|
|
_vm->graphics()->setBobText(bob, segment, textX, textY, color, true);
|
|
defaultAnimation(segment, isJoe, parameters, startFrame, bankNum);
|
|
}
|
|
else {
|
|
if (SPEAK_UNKNOWN_6 == command)
|
|
return;
|
|
|
|
if (isJoe) {
|
|
if (_vm->logic()->currentRoom() == 108)
|
|
parameters = findSpeechParameters("JOE-E", command, 0);
|
|
else
|
|
parameters = findSpeechParameters("JOE", command, _vm->logic()->joeFacing());
|
|
}
|
|
else
|
|
parameters = findSpeechParameters(person->name, command, 0);
|
|
|
|
startFrame = 29 + bobNum + FRAMES_JOE_XTRA;
|
|
int faceDirection = 0;
|
|
|
|
if (isJoe && _vm->logic()->joeFacing() == DIR_LEFT)
|
|
faceDirection = DIR_LEFT;
|
|
else if (!isJoe) {
|
|
ObjectData *data = _vm->logic()->objectData(_vm->logic()->objectForPerson(bobNum));
|
|
|
|
if (data->image == -3)
|
|
faceDirection = DIR_LEFT;
|
|
|
|
if (faceDirectionCommand == SPEAK_FACE_LEFT)
|
|
data->image = -3;
|
|
else if (faceDirectionCommand == SPEAK_FACE_RIGHT)
|
|
data->image = -4;
|
|
}
|
|
|
|
if (faceDirectionCommand) {
|
|
switch (faceDirectionCommand) {
|
|
case SPEAK_FACE_LEFT: faceDirection = DIR_LEFT; break;
|
|
case SPEAK_FACE_RIGHT: faceDirection = DIR_RIGHT; break;
|
|
case SPEAK_FACE_FRONT: faceDirection = DIR_FRONT; break;
|
|
case SPEAK_FACE_BACK: faceDirection = DIR_BACK; break;
|
|
}
|
|
if (isJoe)
|
|
_vm->logic()->joeFacing(faceDirection);
|
|
}
|
|
|
|
if (!isJoe) {
|
|
bob->xflip = (faceDirection == DIR_LEFT);
|
|
}
|
|
|
|
// Run animated sequence if SANIMstr is primed
|
|
|
|
if (_talkHead) {
|
|
// talk.c lines 1612-1635
|
|
headStringAnimation(parameters, bobNum, bankNum);
|
|
}
|
|
|
|
if (_vm->subtitles())
|
|
_vm->graphics()->setBobText(bob, segment, textX, textY, color, _talkHead);
|
|
|
|
if (parameters->animation[0] != '\0' && parameters->animation[0] != 'E') {
|
|
stringAnimation(parameters, startFrame, bankNum);
|
|
}
|
|
else {
|
|
_vm->bankMan()->unpack(parameters->body, startFrame, bankNum);
|
|
|
|
if (length == 0 && !isJoe && parameters->bf > 0) {
|
|
_vm->bankMan()->overpack(parameters->bf, startFrame, bankNum);
|
|
_vm->update();
|
|
}
|
|
|
|
/* A12 = the frame pointer for the full body frame, well use this */
|
|
/* for Hot Spot reference, before we have to set up a Torso frame. */
|
|
/* This way the hot spot is at bottom of body */
|
|
|
|
// XXX A12=A1;
|
|
|
|
if (-1 == parameters->rf) {
|
|
// Setup the Torso frames
|
|
_vm->bankMan()->overpack(parameters->bf, startFrame, bankNum);
|
|
if (isJoe)
|
|
parameters = findSpeechParameters(person->name, 0, _vm->logic()->joeFacing());
|
|
else
|
|
parameters = findSpeechParameters(person->name, 0, 0);
|
|
}
|
|
|
|
if (-2 == parameters->rf) {
|
|
// Setup the Torso frames
|
|
_vm->bankMan()->overpack(parameters->bf, startFrame, bankNum);
|
|
if (isJoe)
|
|
parameters = findSpeechParameters(person->name, 14, _vm->logic()->joeFacing());
|
|
else
|
|
parameters = findSpeechParameters(person->name, 14, 0);
|
|
}
|
|
|
|
defaultAnimation(segment, isJoe, parameters, startFrame, bankNum);
|
|
}
|
|
}
|
|
|
|
// Moved here so that Text is cleared when a Torso command done!
|
|
_vm->display()->clearTexts(0,198);
|
|
|
|
if (oracle) {
|
|
uint16 frameNum = _vm->graphics()->personFrames(bobNum);
|
|
for (i = 1; i <= 4; ++i) {
|
|
_vm->bankMan()->unpack(i, frameNum, bankNum);
|
|
++frameNum;
|
|
}
|
|
}
|
|
|
|
// Ensure that the correct buffer frame is selected
|
|
|
|
if (isJoe && !_talkHead) {
|
|
if (_vm->logic()->joeFacing() == DIR_FRONT ||
|
|
_vm->logic()->joeFacing() == DIR_BACK) {
|
|
// Joe is facing either Front or Back!
|
|
// - Don't FACE_JOE in room 69, because Joe is probably
|
|
// holding the Dino Ray gun.
|
|
if (_vm->logic()->currentRoom() != 69)
|
|
_vm->logic()->joeFace();
|
|
}
|
|
else {
|
|
if (command == SPEAK_DEFAULT ||
|
|
command == 6 ||
|
|
command == 7) {
|
|
_vm->logic()->joeFace();
|
|
}
|
|
else if (command != 5) {
|
|
// 7/11/94, Ensure that correct mouth closed frame is used!
|
|
if (parameters->rf != -1)
|
|
// XXX should really be just "bf", but it is not always calculated... :-(
|
|
_vm->bankMan()->overpack(parameters->bf, startFrame, bankNum);
|
|
|
|
if (parameters->ff == 0)
|
|
_vm->bankMan()->overpack(10, startFrame, bankNum);
|
|
else
|
|
_vm->bankMan()->overpack(parameters->ff, startFrame, bankNum);
|
|
}
|
|
}
|
|
}
|
|
|
|
_vm->update();
|
|
}
|
|
|
|
const Talk::SpeechParameters *Talk::findSpeechParameters(
|
|
const char *name,
|
|
int state,
|
|
int faceDirection) {
|
|
// function FIND_SACTION in queen.c
|
|
const SpeechParameters *iterator = _speechParameters;
|
|
if (faceDirection == DIR_RIGHT)
|
|
faceDirection = DIR_LEFT;
|
|
|
|
while (iterator->name[0] != '*') {
|
|
if (0 == scumm_stricmp(iterator->name, name) &&
|
|
iterator->state == state &&
|
|
iterator->faceDirection == faceDirection)
|
|
break;
|
|
iterator++;
|
|
}
|
|
|
|
return iterator;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
TalkSelected *Talk::talkSelected() {
|
|
return _vm->logic()->talkSelected(_uniqueKey);
|
|
}
|
|
|
|
int Talk::splitOption(const char *str, char optionText[5][MAX_STRING_SIZE]) {
|
|
debug(6, "Talk::splitOption(%s)", str);
|
|
// Check to see if option fits on one line, and exit early
|
|
if (_vm->resource()->getLanguage() == ENGLISH ||
|
|
_vm->display()->textWidth(str) <= MAX_TEXT_WIDTH) {
|
|
strcpy(optionText[0], str);
|
|
return 1;
|
|
}
|
|
|
|
// Split up multiple line option at closest space character
|
|
memset(optionText, 0, 5 * MAX_STRING_SIZE);
|
|
uint16 spaceCharWidth = _vm->display()->textWidth(" ");
|
|
uint16 width = 0;
|
|
uint16 optionLines = 0;
|
|
uint16 maxTextLen = MAX_TEXT_WIDTH;
|
|
const char *p = str;
|
|
while (p) {
|
|
p = strchr(str, ' ');
|
|
if (p) {
|
|
uint16 len = p - str;
|
|
uint16 wordWidth = _vm->display()->textWidth(str, len);
|
|
width += wordWidth;
|
|
if (width> maxTextLen) {
|
|
++optionLines;
|
|
strncpy(optionText[optionLines], str, len + 1);
|
|
width = wordWidth;
|
|
maxTextLen = MAX_TEXT_WIDTH - OPTION_TEXT_MARGIN;
|
|
} else {
|
|
strncat(optionText[optionLines], str, len + 1);
|
|
}
|
|
width += spaceCharWidth;
|
|
str = p + 1;
|
|
} else {
|
|
if (str[0]) {
|
|
if (width + _vm->display()->textWidth(str) > maxTextLen) {
|
|
++optionLines;
|
|
}
|
|
strcat(optionText[optionLines], str);
|
|
}
|
|
++optionLines;
|
|
}
|
|
}
|
|
return optionLines;
|
|
}
|
|
|
|
static char *removeStar(char *str) {
|
|
|
|
// The remove_star function in talk.c uses a static variable, but this
|
|
// modifies the string instead, so the caller should use a copy of the
|
|
// string.
|
|
|
|
char *p = strchr(str, '*');
|
|
if (p)
|
|
*p = '\0';
|
|
|
|
return str;
|
|
}
|
|
|
|
int16 Talk::selectSentence() {
|
|
// Function TALK_BOB (lines 577-739) in talk.c
|
|
int selectedSentence = 0;
|
|
|
|
int scrollX = _vm->display()->horizontalScroll();
|
|
int startOption = 1;
|
|
int optionLines = 0;
|
|
char optionText[5][MAX_STRING_SIZE];
|
|
int talkZone[5];
|
|
int i;
|
|
|
|
// Change NORMAL_INK -> TALK_NORMAL_INK
|
|
|
|
_vm->display()->textCurrentColor(INK_TALK_NORMAL);
|
|
|
|
// These bobs are up and down arrows
|
|
|
|
BobSlot *arrowBobUp = _vm->graphics()->bob(ARROW_BOB_UP);
|
|
BobSlot *arrowBobDown = _vm->graphics()->bob(ARROW_BOB_DOWN);
|
|
|
|
arrowBobUp->x = 303 + 8 + scrollX;
|
|
arrowBobUp->y = 150 + 1;
|
|
arrowBobUp->frameNum = 3;
|
|
arrowBobUp->active = false;
|
|
|
|
arrowBobDown->x = 303 + scrollX;
|
|
arrowBobDown->y = 175;
|
|
arrowBobDown->frameNum = 4;
|
|
arrowBobDown->active = false;
|
|
|
|
bool rezone = true;
|
|
|
|
while (rezone) {
|
|
rezone = false;
|
|
|
|
// Set zones for UP/DOWN text arrows when not English version
|
|
|
|
_vm->grid()->clear(GS_PANEL);
|
|
|
|
if (_vm->resource()->getLanguage() != ENGLISH) {
|
|
_vm->grid()->setZone(GS_PANEL, ARROW_ZONE_UP, MAX_TEXT_WIDTH + 1, 0, 319, 24);
|
|
_vm->grid()->setZone(GS_PANEL, ARROW_ZONE_DOWN, MAX_TEXT_WIDTH + 1, 25, 319, 49);
|
|
}
|
|
|
|
_vm->display()->clearTexts(151,199);
|
|
|
|
int sentenceCount = 0;
|
|
int yOffset = 1;
|
|
|
|
for (i = startOption; i <= 4; i++) {
|
|
talkZone[i] = 0;
|
|
|
|
if (_talkString[i][0] != '\0') {
|
|
sentenceCount++;
|
|
|
|
char temp[MAX_STRING_SIZE];
|
|
strcpy(temp, _talkString[i]);
|
|
optionLines = splitOption(removeStar(temp), optionText);
|
|
|
|
if (yOffset < 5) {
|
|
_vm->grid()->setZone(
|
|
GS_PANEL,
|
|
i,
|
|
0,
|
|
yOffset * LINE_HEIGHT - PUSHUP,
|
|
(_vm->resource()->getLanguage() == ENGLISH) ? 319 : MAX_TEXT_WIDTH,
|
|
(yOffset + optionLines) * LINE_HEIGHT - PUSHUP);
|
|
}
|
|
|
|
int j;
|
|
for (j = 0; j < optionLines; j++) {
|
|
if (yOffset < 5) {
|
|
//debug(6, "Draw text '%s'", optionText[j]);
|
|
_vm->display()->setText(
|
|
(j == 0) ? 0 : OPTION_TEXT_MARGIN,
|
|
150 - PUSHUP + yOffset * LINE_HEIGHT,
|
|
optionText[j]);
|
|
}
|
|
yOffset++;
|
|
}
|
|
|
|
talkZone[i] = sentenceCount;
|
|
}
|
|
}
|
|
|
|
yOffset--;
|
|
|
|
// Up and down dialogue arrows
|
|
|
|
if (_vm->resource()->getLanguage() != ENGLISH) {
|
|
arrowBobUp->active = (startOption > 1);
|
|
arrowBobDown->active = (yOffset > 4);
|
|
}
|
|
|
|
_vm->input()->clearKeyVerb();
|
|
|
|
if (sentenceCount > 0) {
|
|
int zone = 0;
|
|
int oldZone = 0;
|
|
|
|
while (0 == selectedSentence) {
|
|
|
|
if (_vm->input()->talkQuit())
|
|
break;
|
|
|
|
_vm->update();
|
|
|
|
zone = _vm->grid()->findZoneForPos(GS_PANEL, _vm->input()->mousePosX(), _vm->input()->mousePosY());
|
|
|
|
int mouseButton = _vm->input()->mouseButton();
|
|
_vm->input()->clearMouseButton();
|
|
|
|
if (ARROW_ZONE_UP == zone || ARROW_ZONE_DOWN == zone) {
|
|
if (oldZone > 0) {
|
|
int16 y;
|
|
const Box *b = _vm->grid()->zone(GS_PANEL, oldZone);
|
|
for (y = b->y1; y < b->y2; y += 10)
|
|
_vm->display()->textColor(150 + y, INK_TALK_NORMAL);
|
|
oldZone = 0;
|
|
}
|
|
if (mouseButton != 0) {
|
|
if (zone == ARROW_ZONE_UP && arrowBobUp->active) {
|
|
startOption--;
|
|
} else if (zone == ARROW_ZONE_DOWN && arrowBobDown->active) {
|
|
startOption++;
|
|
}
|
|
}
|
|
rezone = true;
|
|
break;
|
|
}
|
|
else {
|
|
if (oldZone != zone) {
|
|
// Changed zone, change text colors
|
|
int y;
|
|
|
|
debug(6, "Changed zone. oldZone = %i, zone = %i",
|
|
oldZone, zone);
|
|
|
|
if (zone > 0) {
|
|
const Box *b = _vm->grid()->zone(GS_PANEL, zone);
|
|
for (y = b->y1; y < b->y2; y += 10)
|
|
_vm->display()->textColor(150 + y, INK_JOE);
|
|
}
|
|
|
|
if (oldZone > 0) {
|
|
const Box *b = _vm->grid()->zone(GS_PANEL, oldZone);
|
|
for (y = b->y1; y < b->y2; y += 10)
|
|
_vm->display()->textColor(150 + y, INK_TALK_NORMAL);
|
|
}
|
|
|
|
oldZone = zone;
|
|
}
|
|
|
|
}
|
|
|
|
Verb v = _vm->input()->keyVerb();
|
|
if (v >= VERB_DIGIT_FIRST && v <= VERB_DIGIT_LAST) {
|
|
int n = v - VERB_DIGIT_FIRST + 1;
|
|
for (i = 1; i <= 4; i++) {
|
|
if (talkZone[i] == n) {
|
|
selectedSentence = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
_vm->input()->clearKeyVerb();
|
|
}
|
|
else if (mouseButton) {
|
|
selectedSentence = zone;
|
|
}
|
|
|
|
} // while()
|
|
}
|
|
}
|
|
|
|
debug(6, "Selected sentence %i", selectedSentence);
|
|
|
|
arrowBobUp->active = false;
|
|
arrowBobDown->active = false;
|
|
|
|
if (selectedSentence > 0) {
|
|
_vm->display()->clearTexts(0, 198);
|
|
|
|
speak(_talkString[selectedSentence], NULL, _joeVoiceFilePrefix[selectedSentence]);
|
|
}
|
|
|
|
_vm->display()->clearTexts(151, 151);
|
|
|
|
return selectedSentence;
|
|
}
|
|
|
|
const Talk::SpeechParameters Talk::_speechParameters[] = {
|
|
{ "JOE",0,1,1,10,2,3,"",0},
|
|
{ "JOE",0,3,3,28,2,3,"",0},
|
|
{ "JOE",0,4,5,38,1,0,"",0},
|
|
{ "JOE",1,1,1,45,-1,0,"",0},
|
|
{ "JOE",1,3,3,28,2,3,"",0},
|
|
{ "JOE",1,4,5,38,1,0,"",0},
|
|
{ "JOE",2,1,1,46,-1,0,"",0},
|
|
{ "JOE",2,3,3,28,2,3,"",0},
|
|
{ "JOE",2,4,5,38,1,0,"",0},
|
|
{ "JOE",3,1,1,47,-1,0,"",0},
|
|
{ "JOE",3,3,3,28,2,3,"",0},
|
|
{ "JOE",3,4,5,38,1,0,"",0},
|
|
{ "JOE",4,1,1,50,-1,0,"",0},
|
|
{ "JOE",4,3,3,28,2,3,"",0},
|
|
{ "JOE",4,4,5,38,1,0,"",0},
|
|
{ "JOE",5,1,2,0,0,0,"",0},
|
|
{ "JOE",5,3,4,0,0,0,"",0},
|
|
{ "JOE",5,4,6,0,0,0,"",0},
|
|
//CR - Change 48,1,0 -> 48,0,1
|
|
{ "JOE",6,1,1,48,0,1,"",0},
|
|
{ "JOE",6,3,3,28,2,3,"",0},
|
|
{ "JOE",6,4,5,38,1,0,"",0},
|
|
//CR - Change 51,1,0 -> 51,0,1
|
|
{ "JOE",7,1,1,51,0,1,"",0},
|
|
{ "JOE",7,3,3,28,2,3,"",0},
|
|
{ "JOE",7,4,5,38,1,0,"",0},
|
|
{ "JOE",8,1,1,26,0,0,"",0},
|
|
{ "JOE",8,3,3,28,2,3,"",0},
|
|
{ "JOE",8,4,5,38,1,0,"",0},
|
|
{ "JOE",9,1,1,29,0,0,"",0},
|
|
{ "JOE",9,3,3,28,0,0,"",0},
|
|
{ "JOE",9,4,5,38,0,0,"",0},
|
|
// - Look down, sad. 10,12,46
|
|
{ "JOE",10,1,1,12,0,0,"T046,010,010,010,012,012,012,012,012,012,012,012,012,012,012,012,012,012,010,000",0},
|
|
{ "JOE",10,3,3,18,0,0,"",0},
|
|
{ "JOE",10,4,5,44,0,0,"",0},
|
|
{ "JOE",11,1,1,53,-1,0,"",0},
|
|
{ "JOE",11,3,3,28,2,3,"",0},
|
|
{ "JOE",11,4,5,38,1,0,"",0},
|
|
{ "JOE",12,1,1,10,2,3,"",0},
|
|
{ "JOE",12,3,3,28,2,0,"",0},
|
|
{ "JOE",12,4,5,38,1,0,"",0},
|
|
{ "JOE",13,1,1,10,2,3,"T012,013,019,019,019,019,019,019,019,019,019,019,013,010,000",0},
|
|
{ "JOE",13,3,3,28,2,3,"",0},
|
|
{ "JOE",13,4,5,38,1,0,"",0},
|
|
// - 7/11/94, Make Joe look front
|
|
{ "JOE",14,1,1,16,2,3,"",16},
|
|
{ "JOE",14,3,3,28,2,3,"",0},
|
|
{ "JOE",14,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",15,1,1,58,-1,0,"",0},
|
|
{ "JOE",15,3,3,28,2,3,"",0},
|
|
{ "JOE",15,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",16,1,1,59,-1,0,"",0},
|
|
{ "JOE",16,3,3,28,2,3,"",0},
|
|
{ "JOE",16,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",17,1,1,56,-1,0,"",0},
|
|
{ "JOE",17,3,3,28,2,3,"",0},
|
|
{ "JOE",17,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",18,1,56,16,2,3,"T056,057,057,057,056,056,000",0},
|
|
{ "JOE",18,3,3,28,2,3,"",0},
|
|
{ "JOE",18,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",19,1,54,16,2,3,"T054,055,057,056,000",0},
|
|
{ "JOE",19,3,3,28,2,3,"",0},
|
|
{ "JOE",19,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",20,1,56,16,2,3,"T056,057,055,054,001,000",0},
|
|
{ "JOE",20,3,3,28,2,3,"",0},
|
|
{ "JOE",20,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",21,1,1,60,-1,0,"",0},
|
|
{ "JOE",21,3,3,28,2,3,"",0},
|
|
{ "JOE",21,4,61,38,1,0,"",0},
|
|
|
|
{ "JOE",22,1,1,16,2,3,"T063,060,000",0},
|
|
{ "JOE",22,3,3,28,2,3,"",0},
|
|
{ "JOE",22,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",23,1,1,16,2,3,"T060,063,001,000",0},
|
|
{ "JOE",23,3,3,28,2,3,"",0},
|
|
{ "JOE",23,4,5,38,1,0,"",0},
|
|
|
|
{ "JOE",24,1,1,47,-2,0,"",0},
|
|
{ "JOE",24,3,3,28,2,3,"",0},
|
|
{ "JOE",24,4,5,38,1,0,"",0},
|
|
|
|
{ "RICO",0,0,1,7,1,3,"",7},
|
|
{ "RICO",1,0,1,5,-1,0,"",7},
|
|
{ "RICO",2,0,1,9,0,3,"",7},
|
|
{ "RICO",3,0,1,4,-1,0,"",7},
|
|
|
|
{ "EDDY",0,0,14,18,1,3,"",18},
|
|
{ "EDDY",1,0,14,0,0,0,"T016,017,017,016,016,017,017,016,016,017,017,000",18},
|
|
|
|
{ "MIKE",0,0,1,2,2,3,"",2},
|
|
|
|
{ "LOLA",0,0,30,33,2,3,"",33},
|
|
{ "LOLA",1,0,9,10,2,3,"",33},
|
|
{ "LOLA",2,0,30,33,2,3,"",33},
|
|
{ "LOLA",3,0,32,33,2,3,"",33},
|
|
//CR 2 - 22/2/95,
|
|
{ "LOLA",4,0,8,0,0,0,"",33},
|
|
{ "LOLA",5,0,31,0,0,0,"",0},
|
|
{ "LOLA",6,0,31,0,0,0,"047,048,049,050,000",33},
|
|
|
|
{ "LOLA_SHOWER",0,0,7,10,2,3,"",10},
|
|
{ "LOLA_SHOWER",1,0,9,10,2,3,"",10},
|
|
{ "LOLA_SHOWER",2,0,30,33,2,3,"",10},
|
|
{ "LOLA_SHOWER",3,0,32,33,2,3,"",10},
|
|
{ "LOLA_SHOWER",4,0,8,0,0,0,"",0},
|
|
{ "LOLA_SHOWER",5,0,61,0,0,0,"",0},
|
|
{ "LOLA_SHOWER",6,0,64,10,2,3,"",0},
|
|
{ "LOLA_SHOWER",7,0,31,0,0,0,"062,063,064,000",0},
|
|
|
|
// { "SECRETARY",0,0,1,12,2,0,"",12},
|
|
// Change Secretary
|
|
{ "SECRETARY",0,0,1,12,2,3,"",12},
|
|
{ "SECRETARY",1,0,1,12,2,0,"",12},
|
|
{ "SECRETARY",2,0,1,12,2,0,"",12},
|
|
|
|
// { "SPARKY",0,0,21,23,5,0,"",23},
|
|
// Change Sparky talk code
|
|
{ "SPARKY",0,0,21,23,2,3,"",23},
|
|
{ "SPARKY",1,0,21,22,0,0,"",0},
|
|
{ "SPARKY",2,0,21,22,0,0,"021,042,043,000",0},
|
|
{ "SPARKY",3,0,21,22,0,0,"043,042,021,000",0},
|
|
{ "SPARKY",4,0,43,43,1,0,"",0},
|
|
{ "SPARKY",14,0,21,29,5,0,"",29},
|
|
|
|
{ "SPARKY-F",0,0,45,23,5,0,"",23},
|
|
{ "SPARKY-F",1,0,45,47,0,0,"",0},
|
|
{ "SPARKY-F",2,0,45,23,5,0,"045,046,046,045,000",23},
|
|
{ "SPARKY-F",14,0,45,29,5,0,"",29},
|
|
|
|
{ "FAYE",0,0,19,35,2,3,"",35},
|
|
{ "FAYE",1,0,19,41,2,3,"",35},
|
|
{ "FAYE",2,0,19,28,-1,0,"",35},
|
|
{ "FAYE",3,0,19,20,0,0,"",0},
|
|
{ "FAYE",4,0,19,27,-1,0,"",35},
|
|
{ "FAYE",5,0,19,29,-1,0,"",35},
|
|
{ "FAYE",6,0,59,35,2,3,"",35},
|
|
{ "FAYE",7,0,19,30,-1,0,"",35},
|
|
{ "FAYE",8,0,19,31,-1,0,"",35},
|
|
|
|
{ "BOB",0,0,27,34,2,3,"",34},
|
|
{ "BOB",1,0,27,28,-1,0,"",34},
|
|
{ "BOB",2,0,30,0,0,0,"",0},
|
|
{ "BOB",3,0,31,0,0,0,"",0},
|
|
{ "BOB",4,0,27,61,-1,0,"",34},
|
|
{ "BOB",5,0,27,42,1,0,"",42},
|
|
|
|
{ "PYGMY",0,0,20,21,2,6,"",0},
|
|
{ "PYGMY",1,0,20,21,2,6,"020,068,068,068,068,068,068,068,068,020,000",0},
|
|
{ "PYGMY",2,0,20,21,2,6,"T028,029,030,031,031,031,031,030,029,028,035,000",0},
|
|
{ "PYGMY",3,0,20,21,2,6,"T035,036,037,038,037,038,037,038,036,035,000",0},
|
|
{ "PYGMY",4,0,20,21,2,6,"T032,033,032,033,032,033,035,000",0},
|
|
{ "PYGMY",5,0,20,21,2,6,"T023,022,021,022,023,024,025,026,027,026,025,024,023,000",0},
|
|
{ "PYGMY",6,0,20,21,2,6,"T034,034,034,035,000",0},
|
|
|
|
{ "WITCH",0,0,39,40,2,6,"",40},
|
|
{ "WITCH",1,0,39,40,2,6,"073,074,000",40},
|
|
{ "WITCH",2,0,39,40,2,6,"074,073,000",40},
|
|
{ "WITCH",3,0,39,40,2,6,"T047,048,049,050,051,000",40},
|
|
{ "WITCH",4,0,39,40,2,6,"T052,053,054,055,056,057,058,057,056,056,056,055,054,053,052,000",40},
|
|
{ "WITCH",5,0,39,40,2,6,"069,070,071,072,073,074,000",40},
|
|
{ "WITCH",6,0,39,40,2,6,"074,073,072,071,070,069,070,000",40},
|
|
{ "WITCH",7,0,39,51,-1,0,"",40},
|
|
{ "WITCH",8,0,39,40,2,6,"T051,050,049,048,047,000",40},
|
|
|
|
{ "CHIEF",0,0,1,7,1,7,"",3},
|
|
{ "CHIEF",1,0,1,2,2,6,"062,063,064,065,066,000",0},
|
|
{ "CHIEF",2,0,1,2,2,6,"066,065,064,063,062,000",0},
|
|
{ "CHIEF",3,0,1,17,-1,0,"",3},
|
|
{ "CHIEF",4,0,1,18,-1,0,"",3},
|
|
{ "CHIEF",5,0,1,19,-1,0,"",3},
|
|
|
|
{ "NAOMI",0,0,1,2,2,3,"",2},
|
|
{ "NAOMI",1,0,1,2,2,6,"048,049,050,051,052,053,054,055,000",0},
|
|
{ "NAOMI",2,0,1,2,2,6,"055,054,053,052,051,050,049,048,000",0},
|
|
{ "NAOMI",3,0,1,13,-1,0,"",2},
|
|
{ "NAOMI",4,0,1,14,-1,0,"",2},
|
|
{ "NAOMI",5,0,1,10,-1,0,"",2},
|
|
{ "NAOMI",6,0,1,12,-1,0,"",2},
|
|
{ "NAOMI",7,0,1,12,-1,0,"T008,008,008,002,000",2},
|
|
|
|
{ "WEDGEWOOD",0,0,8,1,2,0,"",8},
|
|
{ "WEDGEWOOD",1,0,1,1,3,0,"",1},
|
|
|
|
// { "BUD",0,0,1,2,4,2,"",2},
|
|
// Change Buds talk code
|
|
{ "BUD",0,0,1,2,3,2,"",2},
|
|
{ "BUD",1,0,1,2,4,2,"T017,018,000",2},
|
|
{ "BUD",2,0,1,21,-1,0,"",2},
|
|
{ "BUD",3,0,1,14,-1,0,"",2},
|
|
{ "BUD",4,0,1,15,-1,0,"",2},
|
|
{ "BUD",5,0,1,20,-1,0,"",2},
|
|
{ "BUD",6,0,1,16,-1,0,"",2},
|
|
{ "BUD",7,0,1,19,-1,0,"",2},
|
|
{ "BUD",8,0,1,17,-1,0,"",2},
|
|
{ "BUD",9,0,1,14,-1,0,"T014,008,008,003,003,008,008,003,003,010,010,012,012,000",2},
|
|
|
|
//CR 2 - Change 4,2 -> 2,3, End Frames 8 -> 2
|
|
{ "LOU",0,0,1,2,2,3,"",2},
|
|
{ "LOU",1,0,1,2,4,2,"013,014,015,016,017,018,000",2},
|
|
{ "LOU",2,0,1,2,4,2,"018,017,016,015,014,013,000",2},
|
|
|
|
{ "JIMMY",0,0,16,17,2,3,"",17},
|
|
{ "JIMMY",1,0,16,25,-1,0,"",17},
|
|
{ "JIMMY",2,0,16,26,-1,0,"",17},
|
|
{ "JIMMY",3,0,16,27,-1,0,"",17},
|
|
{ "JIMMY",4,0,16,28,-1,0,"",17},
|
|
{ "JIMMY",5,0,16,29,-1,0,"",17},
|
|
|
|
{ "TAMMY",0,0,1,2,2,3,"",2},
|
|
{ "TAMMY",1,0,1,2,2,3,"T008,008,009,009,008,008,009,009,008,008,009,009,002,000",2},
|
|
{ "TAMMY",2,0,1,2,2,3,"T002,010,010,010,002,000",2},
|
|
{ "TAMMY",3,0,1,2,2,3,"T011,011,011,011,011,002,000",2},
|
|
{ "TAMMY",4,0,1,2,2,3,"T013,014,015,013,014,015,013,009,001,000",2},
|
|
|
|
{ "SKULL",0,0,9,9,4,0,"",0},
|
|
{ "SKULL",1,0,1,9,4,0,"001,002,003,004,005,006,007,008,009,000",0},
|
|
{ "SKULL",2,0,1,9,4,0,"009,008,007,006,005,004,003,002,001,000",0},
|
|
|
|
{ "APE",0,0,1,6,7,0,"",6},
|
|
{ "APE",1,0,1,6,7,0,"002,001,000",6},
|
|
{ "APE",2,0,1,6,7,0,"002,003,001,000",6},
|
|
{ "APE",3,0,1,6,7,0,"004,005,004,005,004,001,000",6},
|
|
{ "APE",4,0,1,6,7,0,"001,003,005,004,005,004,001,000",6},
|
|
|
|
{ "APE1",0,0,15,16,7,0,"",16},
|
|
{ "APE2",0,0,14,6,7,0,"",6},
|
|
|
|
{ "SHOWERAM",0,0,1,2,3,0,"",2},
|
|
{ "SHOWERAM",1,0,1,2,3,0,"026,027,028,029,001,000",2},
|
|
{ "SHOWERAM",2,0,1,2,3,0,"001,029,028,027,026,000",2},
|
|
|
|
{ "PRINCESS1",0,0,19,23,2,3,"",23},
|
|
{ "PRINCESS1",1,0,19,41,-1,0,"",23},
|
|
{ "PRINCESS1",2,0,19,42,-1,0,"",23},
|
|
{ "PRINCESS1",3,0,19,45,-1,0,"",23},
|
|
{ "PRINCESS1",4,0,19,40,-1,0,"",23},
|
|
{ "PRINCESS1",5,0,19,45,2,3,"T40,043,044,045,000",45},
|
|
{ "PRINCESS1",6,0,19,45,-1,0,"T041,038,000",38},
|
|
{ "PRINCESS1",7,0,22,0,0,0,"",0},
|
|
{ "PRINCESS1",8,0,19,45,2,3,"T045,044,043,040,039,000",39},
|
|
|
|
{ "PRINCESS2",0,0,46,23,2,3,"",23},
|
|
{ "PRINCESS2",1,0,46,29,2,3,"",29},
|
|
{ "PRINCESS2",2,0,46,29,2,3,"T029,036,035,000",35},
|
|
|
|
{ "GUARDS",0,0,7,7,0,0,"",7},
|
|
|
|
{ "AMGUARD",0,0,19,22,2,3,"",22},
|
|
|
|
{ "MAN1",0,0,2,3,2,3,"",3},
|
|
{ "MAN2",0,0,9,10,1,2,"",10},
|
|
|
|
{ "DOG",0,0,6,6,1,0,"",0},
|
|
{ "DOG",1,0,6,6,1,0,"010,009,008,000",0},
|
|
{ "DOG",2,0,6,6,1,0,"008,009,010,000",0},
|
|
|
|
{ "CHEF",0,0,5,6,2,3,"",6},
|
|
|
|
{ "HENRY",0,0,7,9,2,3,"",9},
|
|
{ "HENRY",1,0,7,21,-1,0,"",9},
|
|
{ "HENRY",2,0,7,19,-1,0,"",9},
|
|
{ "HENRY",3,0,7,20,-1,0,"",9},
|
|
{ "HENRY",4,0,8,9,2,3,"",9},
|
|
{ "HENRY",5,0,23,9,-1,0,"",9},
|
|
{ "HENRY",6,0,7,9,2,3,"T019,015,017,017,017,017,017,017,017,015,009,000",9},
|
|
{ "HENRY",7,0,7,9,2,3,"T018,010,000",10},
|
|
{ "HENRY",8,0,7,9,2,3,"T018,016,000",16},
|
|
{ "HENRY",9,0,7,9,2,3,"T018,011,000",11},
|
|
{ "HENRY",10,0,29,33,1,1,"",33},
|
|
{ "HENRY",11,0,7,30,2,0,"",9},
|
|
{ "HENRY",12,0,7,9,2,3,"025,026,000",26},
|
|
{ "HENRY",13,0,7,9,2,3,"027,028,027,028,000",28},
|
|
{ "HENRY",14,0,7,9,2,3,"026,025,007,000",9},
|
|
|
|
{ "JOHAN",0,0,1,15,2,3,"",15},
|
|
{ "JOHAN",1,0,1,0,0,0,"T006,007,008,000",15},
|
|
{ "JOHAN",2,0,1,15,2,3,"T002,003,004,005,004,005,004,005,004,005,004,005,004,003,002,000",15},
|
|
{ "JOHAN",3,0,1,8,-1,0,"",15},
|
|
{ "JOHAN",4,0,1,0,0,0,"T008,007,006,001,000",15},
|
|
|
|
{ "KLUNK",0,0,1,2,2,3,"",2},
|
|
{ "KLUNK",1,0,1,2,2,3,"019,020,021,022,001,000",2},
|
|
//CR 4 - 22/2/95, Change 017 -> 517
|
|
{ "KLUNK",2,0,1,2,2,3,"001,022,021,020,019,016,517,000",2},
|
|
{ "KLUNK",3,0,1,2,2,3,"T010,011,010,011,010,011,009,000",2},
|
|
|
|
{ "FRANK",0,0,13,14,2,3,"",14},
|
|
//CR 2 - 21/2/95, Change from Torso to normal
|
|
{ "FRANK",1,0,13,20,0,1,"",14},
|
|
{ "FRANK",2,0,13,14,2,3,"025,026,027,027,027,026,026,026,027,027,026,026,027,025,013,000",14},
|
|
{ "FRANK",3,0,28,14,2,3,"",14},
|
|
|
|
{ "DEATH",0,0,1,2,2,3,"",2},
|
|
{ "DEATH",1,0,1,2,2,3,"013,014,015,016,017,001,000",0},
|
|
{ "DEATH",2,0,1,2,2,3,"001,017,016,015,014,013,000",0},
|
|
//CR 2 - Change 024 -> 524
|
|
{ "DEATH",3,0,1,2,2,3,"T018,019,020,021,021,022,022,020,021,022,020,021,022,023,024,524,000",2},
|
|
{ "DEATH",4,0,1,2,2,3,"T025,026,027,028,028,028,028,028,028,028,028,028,029,035,000",2},
|
|
{ "DEATH",5,0,1,2,2,3,"T030,031,032,033,033,033,033,033,033,033,033,033,034,035,000",2},
|
|
{ "DEATH",6,0,1,2,2,3,"T023,022,020,019,018,001,000",2},
|
|
|
|
{ "JASPAR",0,0,1,1,22,0,"026,027,028,029,028,029,028,029,030,023,000",0},
|
|
{ "JASPAR",1,0,1,1,22,0,"023,026,000",0},
|
|
|
|
{ "ORACLE",0,0,1,5,3,0,"",0},
|
|
|
|
{ "ZOMBIE",0,0,1,5,2,3,"",5},
|
|
{ "ZOMBIE",1,0,1,12,-1,0,"",5},
|
|
{ "ZOMBIE",2,0,1,13,-1,0,"",5},
|
|
{ "ZOMBIE",3,0,1,1,5,5,"",5},
|
|
|
|
{ "ZOMBIE2",0,0,14,14,0,0,"",0},
|
|
{ "ZOMBIE3",0,0,18,18,0,0,"",0},
|
|
|
|
{ "ANDERSON",0,0,7,8,2,3,"",8},
|
|
{ "ANDERSON",1,0,7,8,1,0,"",8},
|
|
{ "ANDERSON",2,0,7,16,-1,0,"",8},
|
|
{ "ANDERSON",3,0,7,18,-1,0,"",8},
|
|
{ "ANDERSON",4,0,7,19,-1,0,"",8},
|
|
{ "ANDERSON",5,0,7,20,-1,0,"",8},
|
|
{ "ANDERSON",6,0,7,21,1,0,"",8},
|
|
|
|
{ "COMPY",0,0,12,12,-1,0,"",0},
|
|
{ "COMPY",1,0,10,10,10,0,"010,011,012,012,013,014,014,000",0},
|
|
{ "COMPY",2,0,10,10,10,0,"014,013,012,000",0},
|
|
|
|
{ "DEINO",0,0,13,13,-1,0,"",0},
|
|
{ "DEINO",1,0,9,9,9,0,"009,010,000",0},
|
|
|
|
{ "TMPD",0,0,19,22,2,3,"",22},
|
|
|
|
{ "IAN",0,0,7,9,2,3,"",9},
|
|
{ "IAN",1,0,8,25,3,0,"",25},
|
|
{ "IAN",2,0,7,21,-1,0,"",9},
|
|
{ "IAN",3,0,7,22,1,0,"",9},
|
|
{ "IAN",4,0,7,22,-1,0,"",9},
|
|
{ "IAN",5,0,7,24,-1,0,"",9},
|
|
{ "IAN",6,0,7,9,2,3,"034,034,034,035,035,036,036,035,035,036,035,036,035,000",9},
|
|
{ "IAN",7,0,7,31,-1,0,"",9},
|
|
|
|
{ "FAYE-H",0,0,1,1,4,1,"",1},
|
|
{ "FAYE-H",1,0,1,1,4,1,"007,000",7},
|
|
{ "FAYE-H",2,0,1,1,4,1,"009,010,011,009,001,000",1},
|
|
{ "FAYE-H",3,0,1,1,4,1,"E012,013,000",1},
|
|
{ "FAYE-H",4,0,1,1,4,1,"E015,000",1},
|
|
{ "FAYE-H",5,0,1,1,4,1,"E014,000",1},
|
|
|
|
{ "AZURA-H",0,0,1,1,4,1,"",1},
|
|
{ "AZURA-H",1,0,1,1,4,1,"007,000",7},
|
|
{ "AZURA-H",2,0,1,1,4,1,"009,010,011,009,001,000",1},
|
|
{ "AZURA-H",3,0,1,1,4,1,"E012,013,000",1},
|
|
{ "AZURA-H",4,0,1,1,4,1,"E015,000",1},
|
|
{ "AZURA-H",5,0,1,1,4,1,"E014,000",1},
|
|
|
|
{ "FRANK-H",0,0,1,1,4,1,"",1},
|
|
{ "FRANK-H",1,0,1,1,4,1,"E009,000",1},
|
|
{ "FRANK-H",2,0,1,1,4,1,"E007,000",1},
|
|
{ "FRANK-H",3,0,1,1,4,1,"010,011,012,013,014,015,010,000",1},
|
|
|
|
{ "JOE-E",0,0,1,2,4,1,"",2},
|
|
{ "JOE-E",6,0,1,2,4,1,"008,009,008,002,000",2},
|
|
|
|
{ "AZURA-E",0,0,1,1,5,1,"",1},
|
|
{ "AZURA-E",1,0,1,1,5,1,"009,010,009,008,000",1},
|
|
|
|
{ "FAYE-E",0,0,1,4,4,1,"",1},
|
|
{ "FAYE-E",1,0,1,4,4,1,"002,003,002,001,000",1},
|
|
|
|
{ "ANDSON-E",0,0,1,3,4,1,"",1},
|
|
{ "ANDSON-E",1,0,1,3,4,1,"002,001,000",1},
|
|
|
|
//#ifdef __DOS__
|
|
|
|
{ "JOE-H",0,0,1,1,4,4,"",1},
|
|
{ "JOE-H",1,0,1,1,2,3,"012,013,014,000",14},
|
|
{ "JOE-H",2,0,1,1,2,3,"010,011,000",11},
|
|
{ "JOE-H",3,0,1,1,2,3,"014,013,012,001,000",1},
|
|
{ "JOE-H",4,0,1,13,1,0,"",13},
|
|
|
|
{ "RITA-H",0,0,7,1,2,3,"",1},
|
|
{ "RITA-H",1,0,7,0,0,0,"009,010,011,012,013,000",13},
|
|
{ "RITA-H",2,0,7,0,0,0,"014,015,016,000",16},
|
|
{ "RITA-H",3,0,7,0,0,0,"013,012,011,010,000",10},
|
|
{ "RITA-H",4,0,7,0,0,0,"009,007,008,007,009,000",9},
|
|
{ "RITA-H",5,0,7,0,0,0,"016,015,014,000",14},
|
|
|
|
{ "RITA",0,0,1,4,2,3,"",4},
|
|
{ "RITA",1,0,2,4,2,3,"",4},
|
|
|
|
{ "SPARKY-H",0,0,1,1,2,3,"",1},
|
|
|
|
{ "HUGH",0,0,1,1,2,3,"",1},
|
|
{ "HUGH",1,0,7,7,2,3,"",7},
|
|
|
|
// New CD-Rom intro persons
|
|
// *01 Blink
|
|
{ "X2_JOE",0,0,1,1,2,3,"",1},
|
|
{ "X2_JOE",1,0,1,1,2,3,"001,007,008,008,007,001,000",1},
|
|
|
|
// *01 Blink
|
|
{ "X2_RITA",0,0,1,1,2,3,"",1},
|
|
{ "X2_RITA",1,0,1,1,2,3,"001,007,008,008,007,001,000",1},
|
|
|
|
// *01 Smile, *02 Blink, *03 Raise Eyebrow, *04 Anger, *05 Surprise
|
|
{ "X3_RITA",0,0,1,1,4,1,"",1},
|
|
{ "X3_RITA",1,0,1,1,4,1,"007,000",7},
|
|
{ "X3_RITA",2,0,1,1,4,1,"009,010,011,009,001,000",1},
|
|
{ "X3_RITA",3,0,1,1,4,1,"E012,013,000",1},
|
|
{ "X3_RITA",4,0,1,1,4,1,"E015,000",1},
|
|
{ "X3_RITA",5,0,1,1,4,1,"E014,000",1},
|
|
|
|
// *01 Talk to Sparky, *02 Turn to Sparky, *03 Turn to Rita, *04 Close Eyes
|
|
{ "X4_JOE",0,0,1,1,3,4,"",1},
|
|
{ "X4_JOE",1,0,1,13,2,3,"",13},
|
|
{ "X4_JOE",2,0,1,1,3,4,"009,010,011,012,013,000",13},
|
|
{ "X4_JOE",3,0,1,1,3,4,"012,011,010,009,000",9},
|
|
{ "X4_JOE",4,0,1,1,3,4,"001,019,000",19},
|
|
|
|
// *01 Talk to Sparky, *02 Turn to Sparky, *03 Turn to Joe, *04 Close Eyes
|
|
{ "X4_RITA",0,0,1,1,0,1,"",1},
|
|
{ "X4_RITA",1,0,1,7,0,1,"",7},
|
|
{ "X4_RITA",2,0,1,1,3,4,"004,005,006,006,006,006,007,000",7},
|
|
{ "X4_RITA",3,0,1,1,3,4,"005,004,001,000",1},
|
|
{ "X4_RITA",4,0,1,1,3,4,"001,003,000",3},
|
|
|
|
// *01 Blink, *02 Look Right
|
|
{ "X5_SPARKY",0,0,1,1,2,3,"",1},
|
|
{ "X5_SPARKY",1,0,1,1,2,3,"001,010,011,011,001,000",1},
|
|
{ "X5_SPARKY",2,0,1,1,2,3,"001,007,008,009,000",9},
|
|
|
|
// *01 Eyes Bulge Once, *02 Eyes Bulge Big Time
|
|
{ "X6_HUGH",0,0,1,1,2,3,"",1},
|
|
{ "X6_HUGH",1,0,1,1,2,3,"007,007,007,007,,001,000",1},
|
|
{ "X6_HUGH",2,0,1,1,2,3,"008,008,008,008,008,009,009,008,008,008,009,008,000",8},
|
|
|
|
// *01 Talk to Sparky, Rub Head
|
|
{ "X10_JOE",0,0,1,2,2,3,"",2},
|
|
{ "X10_JOE",1,0,1,8,2,3,"",8},
|
|
//CR 2 - 21/2/95, Cut down rub head anim
|
|
{ "X10_JOE",2,0,1,2,2,3,"014,014,014,015,015,014,014,015,015,000",2},
|
|
|
|
{ "X10_RITA",0,0,1,2,2,3,"",2},
|
|
|
|
{ "X11_JOE",0,0,1,2,0,1,"",2},
|
|
|
|
// *01 Look at Joe
|
|
{ "X11_RITA",0,0,1,2,0,1,"",2},
|
|
{ "X11_RITA",1,0,1,2,1,0,"003,004,000",4},
|
|
|
|
//#endif
|
|
|
|
// Interview
|
|
{ "JOHN", 0, 0, 1, 2, 2, 3, "", 1 },
|
|
{ "JOHN", 1, 0, 1, 15, -1, 0, "", 1 },
|
|
{ "JOHN", 2, 0, 1, 16, -1, 0, "", 1 },
|
|
{ "JOHN", 3, 0, 1, 17, -1, 0, "", 1 },
|
|
|
|
{ "STEVE", 0, 0, 8, 2, 2, 3, "", 2 },
|
|
{ "STEVE", 1, 0, 8, 16, -1, 0, "", 2 },
|
|
{ "STEVE", 2, 0, 9, 18, -1, 0, "T016,017,017,016,008,000", 2 },
|
|
{ "STEVE", 3, 0, 8, 18, -1, 0, "", 2 },
|
|
|
|
{ "TONY", 0, 0, 1, 2, 2, 3, "", 1 },
|
|
{ "TONY", 1, 0, 1, 12, -1, 0, "", 1 },
|
|
|
|
{ "*",0,0,0,0,0,0,"",0}
|
|
};
|
|
|
|
|
|
} // End of namespace Queen
|