SHERLOCK: action processing uses fixed text class

action error messages are now localized too
This commit is contained in:
Martin Kiewitz 2015-06-14 17:52:11 +02:00
parent b26bc29619
commit 1b6a60f359
8 changed files with 229 additions and 59 deletions

View file

@ -85,10 +85,12 @@ static const Common::String fixedTextDE[] = {
// Journal search
"Zur\201ck",
"R\201ckw\204rts", // original: "Backward"
"V\224rw\204rts", // original: "Forward"
"Vorw\204rts", // original: "Forward"
"Text nicht gefunden!"
};
// up-side down exclamation mark - 0xAD / octal 255
// up-side down question mark - 0xA8 / octal 250
static const Common::String fixedTextES[] = {
// Window buttons
"Exit",
@ -119,31 +121,191 @@ static const Common::String fixedTextES[] = {
"Texto no encontrado!"
};
static const SherlockFixedTextLanguageEntry fixedTextLanguages[] = {
{ Common::DE_DEU, fixedTextDE },
{ Common::ES_ESP, fixedTextES },
{ Common::EN_ANY, fixedTextEN },
{ Common::UNK_LANG, fixedTextEN }
// =========================================
static const Common::String fixedTextEN_ActionOpen[] = {
"This cannot be opened",
"It is already open",
"It is locked",
"Wait for Watson",
" ",
"."
};
static const Common::String fixedTextDE_ActionOpen[] = {
"Das kann man nicht \224ffnen",
"Ist doch schon offen!",
"Leider verschlossen",
"Warte auf Watson",
" ",
"."
};
static const Common::String fixedTextES_ActionOpen[] = {
"No puede ser abierto",
"Ya esta abierto",
"Esta cerrado",
"Espera a Watson",
" ",
"."
};
static const Common::String fixedTextEN_ActionClose[] = {
"This cannot be closed",
"It is already closed",
"The safe door is in the way"
};
static const Common::String fixedTextDE_ActionClose[] = {
"Das kann man nicht schlie\341en",
"Ist doch schon zu!",
"Die safet\201r ist Weg"
};
static const Common::String fixedTextES_ActionClose[] = {
"No puede ser cerrado",
"Ya esta cerrado",
"La puerta de seguridad esta entre medias"
};
static const Common::String fixedTextEN_ActionMove[] = {
"This cannot be moved",
"It is bolted to the floor",
"It is too heavy",
"The other crate is in the way"
};
static const Common::String fixedTextDE_ActionMove[] = {
"L\204\341t sich nicht bewegen",
"Festged\201belt in der Erde...",
"Oha, VIEL zu schwer",
"Der andere Kiste ist im Weg" // [sic]
};
static const Common::String fixedTextES_ActionMove[] = {
"No puede moverse",
"Esta sujeto a la pared",
"Es demasiado pesado",
"El otro cajon esta en mitad"
};
static const Common::String fixedTextEN_ActionPick[] = {
"Nothing of interest here",
"It is bolted down",
"It is too big to carry",
"It is too heavy",
"I think a girl would be more your type",
"Those flowers belong to Penny",
"She's far too young for you!",
"I think a girl would be more your type!",
"Government property for official use only"
};
static const Common::String fixedTextDE_ActionPick[] = {
"Nichts Interessantes da",
"Zu gut befestigt",
"Ist ja wohl ein bi\341chen zu gro\341, oder ?",
"Ich denke, Du stehst mehr auf M\204dchen ?",
"Diese Blumen geh\224ren Penny",
"Sie ist doch viel zu jung f\201r Dich!",
"Staatseigentum - Nur für den Dienstgebrauch !"
};
static const Common::String fixedTextES_ActionPick[] = {
"No hay nada interesante",
"Esta anclado al suelo",
"Es muy grande para llevarlo",
"Pesa demasiado",
"Creo que una chica sera mas tu tipo",
"Esas flores pertenecen a Penny",
"\255Es demasiado joven para ti!"
"\255Creo que una chica sera mas tu tipo!",
"Propiedad del gobierno para uso oficial"
};
static const Common::String fixedTextEN_ActionUse[] = {
"You can't do that",
"It had no effect",
"You can't reach it",
"OK, the door looks bigger! Happy?"
"Doors don't smoke"
};
static const Common::String fixedTextDE_ActionUse[] = {
"Nein, das geht wirklich nicht",
"Tja keinerlei Wirkung",
"Da kommst du nicht dran",
"Na gut, die Tür sieht jetzt gr\224\341er aus. Zufrieden?"
"Türen sind Nichtraucher!"
};
static const Common::String fixedTextES_ActionUse[] = {
"No puedes hacerlo",
"No tuvo ningun efecto",
"No puedes alcanzarlo",
"Bien, \255es enorme! \250Feliz?"
"Las puertas no fuman"
};
static const FixedTextActionEntry fixedTextEN_Actions[] = {
{ fixedTextEN_ActionOpen },
{ fixedTextEN_ActionClose },
{ fixedTextEN_ActionMove },
{ fixedTextEN_ActionPick },
{ fixedTextEN_ActionUse }
};
static const FixedTextActionEntry fixedTextDE_Actions[] = {
{ fixedTextDE_ActionOpen },
{ fixedTextDE_ActionClose },
{ fixedTextDE_ActionMove },
{ fixedTextDE_ActionPick },
{ fixedTextDE_ActionUse }
};
static const FixedTextActionEntry fixedTextES_Actions[] = {
{ fixedTextES_ActionOpen },
{ fixedTextES_ActionClose },
{ fixedTextES_ActionMove },
{ fixedTextES_ActionPick },
{ fixedTextES_ActionUse }
};
// =========================================
static const FixedTextLanguageEntry fixedTextLanguages[] = {
{ Common::DE_DEU, fixedTextDE, fixedTextDE_Actions },
{ Common::ES_ESP, fixedTextES, fixedTextES_Actions },
{ Common::EN_ANY, fixedTextEN, fixedTextEN_Actions },
{ Common::UNK_LANG, fixedTextEN, fixedTextEN_Actions }
};
// =========================================
// =========================================
FixedText::FixedText(SherlockEngine *vm) : _vm(vm) {
// Figure out which fixed texts to use
Common::Language curLanguage = _vm->getLanguage();
const SherlockFixedTextLanguageEntry *curLanguageEntry = fixedTextLanguages;
const FixedTextLanguageEntry *curLanguageEntry = fixedTextLanguages;
while (curLanguageEntry->language != Common::UNK_LANG) {
if (curLanguageEntry->language == curLanguage)
break; // found current language
curLanguageEntry++;
}
_fixedText = curLanguageEntry->fixedTextArray;
_curLanguageEntry = curLanguageEntry;
}
const Common::String FixedText::getText(FixedTextId fixedTextId) {
return _fixedText[fixedTextId];
return _curLanguageEntry->fixedTextArray[fixedTextId];
}
const Common::String FixedText::getActionMessage(FixedTextActionId actionId, int messageIndex) {
assert(actionId >= 0);
return _curLanguageEntry->actionArray[actionId].fixedTextArray[messageIndex];
}
} // End of namespace Sherlock

View file

@ -24,6 +24,7 @@
#define SHERLOCK_FIXED_TEXT_H
#include "common/scummsys.h"
#include "common/language.h"
namespace Sherlock {
@ -57,16 +58,30 @@ enum FixedTextId {
kFixedText_JournalSearch_NotFound
};
struct SherlockFixedTextLanguageEntry {
enum FixedTextActionId {
kFixedTextAction_Invalid = -1,
kFixedTextAction_Open = 0,
kFixedTextAction_Close,
kFixedTextAction_Move,
kFixedTextAction_Pick,
kFixedTextAction_Use
};
struct FixedTextActionEntry {
const Common::String *fixedTextArray;
};
struct FixedTextLanguageEntry {
Common::Language language;
const Common::String *fixedTextArray;
const FixedTextActionEntry *actionArray;
};
class FixedText {
private:
SherlockEngine *_vm;
const Common::String *_fixedText;
const FixedTextLanguageEntry *_curLanguageEntry;
public:
FixedText(SherlockEngine *vm);
@ -76,6 +91,8 @@ public:
* Gets hardcoded text
*/
const Common::String getText(FixedTextId fixedTextId);
const Common::String getActionMessage(FixedTextActionId actionId, int messageIndex);
};
} // End of namespace Sherlock

View file

@ -348,7 +348,7 @@ void BaseObject::checkObject() {
} else if (v < USE_COUNT) {
for (int idx = 0; idx < NAMES_COUNT; ++idx) {
checkNameForCodes(_use[v]._names[idx], nullptr);
checkNameForCodes(_use[v]._names[idx]);
}
if (_use[v]._useFlag)
@ -488,7 +488,8 @@ void BaseObject::setObjSequence(int seq, bool wait) {
}
}
int BaseObject::checkNameForCodes(const Common::String &name, const char *const messages[]) {
int BaseObject::checkNameForCodes(const Common::String &name, FixedTextActionId fixedTextActionId) {
FixedText &fixedText = *_vm->_fixedText;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
@ -571,7 +572,8 @@ int BaseObject::checkNameForCodes(const Common::String &name, const char *const
int messageNum = atoi(name.c_str() + 1);
ui._infoFlag = true;
ui.clearInfo();
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[messageNum]);
Common::String errorMessage = fixedText.getActionMessage(fixedTextActionId, messageNum);
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, errorMessage.c_str());
ui._menuCounter = 25;
} else if (name.hasPrefix("@")) {
// Message attached to canimation
@ -1413,7 +1415,8 @@ void Object::adjustObject() {
}
}
int Object::pickUpObject(const char *const messages[]) {
int Object::pickUpObject(FixedTextActionId fixedTextActionId) {
FixedText &fixedText = *_vm->_fixedText;
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
@ -1426,7 +1429,7 @@ int Object::pickUpObject(const char *const messages[]) {
if (pickup == 99) {
for (int idx = 0; idx < NAMES_COUNT && !talk._talkToAbort; ++idx) {
if (checkNameForCodes(_use[0]._names[idx], nullptr)) {
if (checkNameForCodes(_use[0]._names[idx], kFixedTextAction_Invalid)) {
if (!talk._talkToAbort)
printed = true;
}
@ -1442,7 +1445,8 @@ int Object::pickUpObject(const char *const messages[]) {
ui._infoFlag = true;
ui.clearInfo();
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[message]);
Common::String errorMessage = fixedText.getActionMessage(fixedTextActionId, message);
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, errorMessage.c_str());
ui._menuCounter = 30;
} else {
// Pick it up
@ -1473,7 +1477,7 @@ int Object::pickUpObject(const char *const messages[]) {
}
for (int idx = 0; idx < NAMES_COUNT && !talk._talkToAbort; ++idx) {
if (checkNameForCodes(_use[0]._names[idx], nullptr)) {
if (checkNameForCodes(_use[0]._names[idx], kFixedTextAction_Invalid)) {
if (!talk._talkToAbort)
printed = true;
}

View file

@ -28,6 +28,7 @@
#include "common/str-array.h"
#include "common/str.h"
#include "sherlock/image_file.h"
#include "sherlock/fixed_text.h"
namespace Sherlock {
@ -248,7 +249,7 @@ public:
* @param messages Provides a lookup list of messages that can be printed
* @returns 0 if no codes are found, 1 if codes were found
*/
int checkNameForCodes(const Common::String &name, const char *const messages[]);
int checkNameForCodes(const Common::String &name, FixedTextActionId fixedTextActionId = kFixedTextAction_Invalid);
/**
* Adjusts the frame and sequence variables of a sprite that corresponds to the current speaker
@ -400,7 +401,7 @@ public:
* Handles trying to pick up an object. If allowed, plays an y necessary animation for picking
* up the item, and then adds it to the player's inventory
*/
int pickUpObject(const char *const messages[]);
int pickUpObject(FixedTextActionId fixedTextActionId = kFixedTextAction_Invalid);
/**
* Return the frame width

View file

@ -62,25 +62,6 @@ const char INVENTORY_COMMANDS[9] = { "ELUG-+,." };
const char *const PRESS_KEY_FOR_MORE = "Press any Key for More.";
const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue.";
const char *const MOPEN[] = {
"This cannot be opened", "It is already open", "It is locked", "Wait for Watson", " ", "."
};
const char *const MCLOSE[] = {
"This cannot be closed", "It is already closed", "The safe door is in the way"
};
const char *const MMOVE[] = {
"This cannot be moved", "It is bolted to the floor", "It is too heavy", "The other crate is in the way"
};
const char *const MPICK[] = {
"Nothing of interest here", "It is bolted down", "It is too big to carry", "It is too heavy",
"I think a girl would be more your type", "Those flowers belong to Penny", "She's far too young for you!",
"I think a girl would be more your type!", "Government property for official use only"
};
const char *const MUSE[] = {
"You can't do that", "It had no effect", "You can't reach it", "OK, the door looks bigger! Happy?",
"Doors don't smoke"
};
/*----------------------------------------------------------------*/
@ -1196,10 +1177,10 @@ void ScalpelUserInterface::doInvControl() {
bool giveFl = (tempMode >= INVMODE_GIVE);
if (_selector >= 0)
// Use/Give inv object with scene object
checkUseAction(&scene._bgShapes[_find]._use[0], inv[_selector]._name, MUSE, _find, giveFl);
checkUseAction(&scene._bgShapes[_find]._use[0], inv[_selector]._name, kFixedTextAction_Use, _find, giveFl);
else
// Now inv object has been highlighted
checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF*", MUSE, _find, giveFl);
checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF*", kFixedTextAction_Use, _find, giveFl);
_selector = _oldSelector = -1;
}
@ -1422,7 +1403,7 @@ void ScalpelUserInterface::doMiscControl(int allowed) {
switch (allowed) {
case ALLOW_OPEN:
checkAction(obj._aOpen, _temp, MOPEN);
checkAction(obj._aOpen, _temp, kFixedTextAction_Open);
if (_menuMode != TALK_MODE && !talk._talkToAbort) {
_menuMode = STD_MODE;
restoreButton(OPEN_MODE - 1);
@ -1431,7 +1412,7 @@ void ScalpelUserInterface::doMiscControl(int allowed) {
break;
case ALLOW_CLOSE:
checkAction(obj._aClose, _temp, MCLOSE);
checkAction(obj._aClose, _temp, kFixedTextAction_Close);
if (_menuMode != TALK_MODE && !talk._talkToAbort) {
_menuMode = STD_MODE;
restoreButton(CLOSE_MODE - 1);
@ -1440,7 +1421,7 @@ void ScalpelUserInterface::doMiscControl(int allowed) {
break;
case ALLOW_MOVE:
checkAction(obj._aMove, _temp, MMOVE);
checkAction(obj._aMove, _temp, kFixedTextAction_Move);
if (_menuMode != TALK_MODE && !talk._talkToAbort) {
_menuMode = STD_MODE;
restoreButton(MOVE_MODE - 1);
@ -1467,7 +1448,7 @@ void ScalpelUserInterface::doPickControl() {
// Don't allow characters to be picked up
if (_bgFound < 1000) {
scene._bgShapes[_bgFound].pickUpObject(MPICK);
scene._bgShapes[_bgFound].pickUpObject(kFixedTextAction_Pick);
if (!talk._talkToAbort && _menuMode != TALK_MODE) {
_key = _oldKey = -1;
@ -2082,13 +2063,14 @@ void ScalpelUserInterface::banishWindow(bool slideUp) {
}
void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::String &invName,
const char *const messages[], int objNum, bool giveMode) {
FixedTextActionId fixedTextActionId, int objNum, bool giveMode) {
Events &events = *_vm->_events;
FixedText &fixedText = *_vm->_fixedText;
Inventory &inv = *_vm->_inventory;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
bool printed = messages == nullptr;
bool printed = fixedTextActionId == kFixedTextAction_Invalid;
if (objNum >= 1000) {
// Holmes was specified, so do nothing
@ -2140,7 +2122,7 @@ void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::Stri
if (!talk._talkToAbort) {
Object &obj = scene._bgShapes[objNum];
for (int idx = 0; idx < NAMES_COUNT && !talk._talkToAbort; ++idx) {
if (obj.checkNameForCodes(action._names[idx], messages)) {
if (obj.checkNameForCodes(action._names[idx], fixedTextActionId)) {
if (!talk._talkToAbort)
printed = true;
}
@ -2161,10 +2143,11 @@ void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::Stri
if (giveMode) {
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "No, thank you.");
} else if (messages == nullptr) {
} else if (fixedTextActionId == kFixedTextAction_Invalid) {
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that.");
} else {
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[0]);
Common::String errorMessage = fixedText.getActionMessage(fixedTextActionId, 0);
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, errorMessage.c_str());
}
_infoFlag = true;

View file

@ -136,7 +136,7 @@ private:
/**
* Checks to see whether a USE action is valid on the given object
*/
void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[],
void checkUseAction(const UseType *use, const Common::String &invName, FixedTextActionId fixedTextActionId,
int objNum, bool giveMode);
/**

View file

@ -54,8 +54,9 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
}
void UserInterface::checkAction(ActionType &action, int objNum, const char *const messages[]) {
void UserInterface::checkAction(ActionType &action, int objNum, FixedTextActionId fixedTextActionId) {
Events &events = *_vm->_events;
FixedText &fixedText = *_vm->_fixedText;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
@ -70,7 +71,8 @@ void UserInterface::checkAction(ActionType &action, int objNum, const char *cons
// Invalid action, to print error message
_infoFlag = true;
clearInfo();
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[action._cAnimNum]);
Common::String errorMessage = fixedText.getActionMessage(fixedTextActionId, action._cAnimNum);
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, errorMessage.c_str());
_infoFlag = true;
// Set how long to show the message
@ -111,7 +113,7 @@ void UserInterface::checkAction(ActionType &action, int objNum, const char *cons
for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2
&& toupper(action._names[nameIdx][1]) == 'W') {
if (obj.checkNameForCodes(Common::String(action._names[nameIdx].c_str() + 2), messages)) {
if (obj.checkNameForCodes(Common::String(action._names[nameIdx].c_str() + 2), fixedTextActionId)) {
if (!talk._talkToAbort)
printed = true;
}
@ -152,7 +154,7 @@ void UserInterface::checkAction(ActionType &action, int objNum, const char *cons
for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2
&& toupper(action._names[nameIdx][1]) == 'F') {
if (obj.checkNameForCodes(action._names[nameIdx].c_str() + 2, messages)) {
if (obj.checkNameForCodes(action._names[nameIdx].c_str() + 2, fixedTextActionId)) {
if (!talk._talkToAbort)
printed = true;
}
@ -164,7 +166,7 @@ void UserInterface::checkAction(ActionType &action, int objNum, const char *cons
if (!talk._talkToAbort) {
for (int nameIdx = 0; nameIdx < NAMES_COUNT && !talk._talkToAbort; ++nameIdx) {
if (obj.checkNameForCodes(action._names[nameIdx], messages)) {
if (obj.checkNameForCodes(action._names[nameIdx], fixedTextActionId)) {
if (!talk._talkToAbort)
printed = true;
}

View file

@ -28,6 +28,7 @@
#include "sherlock/surface.h"
#include "sherlock/objects.h"
#include "sherlock/resources.h"
#include "sherlock/fixed_text.h"
namespace Sherlock {
@ -64,7 +65,7 @@ protected:
/**
* Called for OPEN, CLOSE, and MOVE actions are being done
*/
void checkAction(ActionType &action, int objNum, const char *const messages[] = nullptr);
void checkAction(ActionType &action, int objNum, FixedTextActionId fixedTextActionId = kFixedTextAction_Invalid);
public:
MenuMode _menuMode;
int _menuCounter;