diff options
Diffstat (limited to 'engines/hugo')
-rw-r--r-- | engines/hugo/inventory.cpp | 2 | ||||
-rw-r--r-- | engines/hugo/object.cpp | 4 | ||||
-rw-r--r-- | engines/hugo/parser.cpp | 12 | ||||
-rw-r--r-- | engines/hugo/parser.h | 58 | ||||
-rw-r--r-- | engines/hugo/parser_v1w.cpp | 311 | ||||
-rw-r--r-- | engines/hugo/parser_v3d.cpp | 251 |
6 files changed, 357 insertions, 281 deletions
diff --git a/engines/hugo/inventory.cpp b/engines/hugo/inventory.cpp index 19aa69c1fa..43a05d1d86 100644 --- a/engines/hugo/inventory.cpp +++ b/engines/hugo/inventory.cpp @@ -73,7 +73,7 @@ void InventoryHandler::constructInventory(int16 imageTotNumb, int displayNumb, b // Copy inventory icons to remaining positions int16 displayed = 0; int16 carried = 0; - for (int16 i = 0; i < imageTotNumb; i++) { + for (int16 i = 0; (i < imageTotNumb) && (displayed < displayNumb); i++) { if (_vm->_object->isCarried(_vm->_invent[i])) { // Check still room to display and past first scroll index if (displayed < displayNumb && carried >= firstObjId) { diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp index 550d803bfb..464e408b40 100644 --- a/engines/hugo/object.cpp +++ b/engines/hugo/object.cpp @@ -113,7 +113,7 @@ void ObjectHandler::useObject(int16 objId) { } else { // Use status.objid on objid // Default to first cmd verb - sprintf(_line, "%s %s %s", _vm->_arrayVerbs[_vm->_cmdList[_objects[_vm->getGameStatus().inventoryObjId].cmdIndex][1].verbIndex][0], + sprintf(_line, "%s %s %s", _vm->_arrayVerbs[_vm->_cmdList[_objects[_vm->getGameStatus().inventoryObjId].cmdIndex][0].verbIndex][0], _vm->_arrayNouns[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0], _vm->_arrayNouns[obj->nounIndex][0]); @@ -123,7 +123,7 @@ void ObjectHandler::useObject(int16 objId) { // Look for secondary object, if found use matching verb bool foundFl = false; for (target_t *target = use->targets; _vm->_arrayNouns[target->nounIndex] != 0; target++) - if (_vm->_arrayNouns[target->nounIndex][0] == _vm->_arrayNouns[obj->nounIndex][0]) { + if (target->nounIndex == obj->nounIndex) { foundFl = true; sprintf(_line, "%s %s %s", _vm->_arrayVerbs[target->verbIndex][0], _vm->_arrayNouns[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0], diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 19d496dfd4..720b8e3305 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -86,12 +86,6 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { _vm->_screen->userHelp(); _checkDoubleF1Fl = !_checkDoubleF1Fl; break; - case Common::KEYCODE_F6: // Inventory - showDosInventory(); - break; - case Common::KEYCODE_F8: // Turbo mode - _config.turboFl = !_config.turboFl; - break; case Common::KEYCODE_F2: // Toggle sound _vm->_sound->toggleSound(); _vm->_sound->toggleMusic(); @@ -108,6 +102,12 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { _vm->_scheduler->restoreScreen(*_vm->_screen_p); gameStatus.viewState = V_PLAY; break; + case Common::KEYCODE_F6: // Inventory + showDosInventory(); + break; + case Common::KEYCODE_F8: // Turbo mode + _config.turboFl = !_config.turboFl; + break; case Common::KEYCODE_F9: // Boss button warning("STUB: F9 (DOS) - BossKey"); break; diff --git a/engines/hugo/parser.h b/engines/hugo/parser.h index b98813c7bc..d25b1434e6 100644 --- a/engines/hugo/parser.h +++ b/engines/hugo/parser.h @@ -47,11 +47,12 @@ public: Parser(HugoEngine *vm); virtual ~Parser(); - bool isWordPresent(char **wordArr); + bool isWordPresent(char **wordArr); - void charHandler(); - void command(const char *format, ...); - void keyHandler(uint16 nChar, uint16 nFlags); + void charHandler(); + void command(const char *format, ...); + + virtual void keyHandler(uint16 nChar, uint16 nFlags); virtual void lineHandler() = 0; protected: @@ -60,33 +61,13 @@ protected: protected: char *findNoun(); char *findVerb(); - -private: - char _ringBuffer[32]; // Ring buffer + bool _checkDoubleF1Fl; // Flag used to display user help or instructions uint16 _putIndex; uint16 _getIndex; // Index into ring buffer - bool _checkDoubleF1Fl; // Flag used to display user help or instructions - - void showDosInventory(); -}; - -class Parser_v1w : public Parser { -public: - Parser_v1w(HugoEngine *vm); - ~Parser_v1w(); - - virtual void lineHandler(); - -protected: - bool isBackgroundWord(objectList_t obj); - bool isCatchallVerb(objectList_t obj); - bool isGenericVerb(object_t *obj, char *comment); - bool isObjectVerb(object_t *obj, char *comment); - void takeObject(object_t *obj); + char _ringBuffer[32]; // Ring buffer private: - bool isNear(object_t *obj, char *verb, char *comment); - void dropObject(object_t *obj); + void showDosInventory(); }; class Parser_v1d : public Parser { @@ -115,12 +96,31 @@ public: void lineHandler(); }; -class Parser_v3d : public Parser_v1w { +class Parser_v3d : public Parser { public: Parser_v3d(HugoEngine *vm); ~Parser_v3d(); - void lineHandler(); + virtual void lineHandler(); +protected: + bool isBackgroundWord(objectList_t obj); + bool isCatchallVerb(objectList_t obj); + bool isGenericVerb(object_t *obj, char *comment); + bool isObjectVerb(object_t *obj, char *comment); + void takeObject(object_t *obj); + +private: + bool isNear(object_t *obj, char *verb, char *comment); + void dropObject(object_t *obj); +}; + +class Parser_v1w : public Parser_v3d { +public: + Parser_v1w(HugoEngine *vm); + ~Parser_v1w(); + + void keyHandler(uint16 nChar, uint16 nFlags); + void lineHandler(); }; } // End of namespace Hugo diff --git a/engines/hugo/parser_v1w.cpp b/engines/hugo/parser_v1w.cpp index 236d24b61b..2de173712e 100644 --- a/engines/hugo/parser_v1w.cpp +++ b/engines/hugo/parser_v1w.cpp @@ -38,264 +38,91 @@ #include "hugo/parser.h" #include "hugo/file.h" #include "hugo/schedule.h" +#include "hugo/route.h" +#include "hugo/display.h" #include "hugo/util.h" #include "hugo/sound.h" #include "hugo/object.h" namespace Hugo { -Parser_v1w::Parser_v1w(HugoEngine *vm) : Parser(vm) { +Parser_v1w::Parser_v1w(HugoEngine *vm) : Parser_v3d(vm) { } Parser_v1w::~Parser_v1w() { } -/** -* Test whether command line contains a verb allowed by this object. -* If it does, and the object is near and passes the tests in the command -* list then carry out the actions in the action list and return TRUE -*/ -bool Parser_v1w::isObjectVerb(object_t *obj, char *comment) { - debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s)", comment); - - // First, find matching verb in cmd list - uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands - if (cmdIndex == 0) // No commands for this obj - return false; - - int i; - for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd - if (isWordPresent(_vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex])) // Was this verb used? - break; - } - - if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. - return false; - - // Verb match found. Check if object is Near - char *verb = *_vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex]; - if (!isNear(obj, verb, comment)) - return false; - - // Check all required objects are being carried - cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd - if (cmnd->reqIndex) { // At least 1 thing in list - uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects - for (i = 0; reqs[i]; i++) { // for each obj - if (!_vm->_object->isCarrying(reqs[i])) { - Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataNoCarryIndex]); - return true; - } - } - } - - // Required objects are present, now check state is correct - if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { - Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataWrongIndex]); - return true; - } - - // Everything checked. Change the state and carry out any actions - if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care - obj->state = cmnd->newState; - Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataDoneIndex]); - _vm->_scheduler->insertActionList(cmnd->actIndex); +void Parser_v1w::keyHandler(uint16 nChar, uint16 nFlags) { + debugC(1, kDebugParser, "keyHandler(%d, %d)", nChar, nFlags); - // See if any additional generic actions - if ((verb == _vm->_arrayVerbs[_vm->_look][0]) || (verb == _vm->_arrayVerbs[_vm->_take][0]) || (verb == _vm->_arrayVerbs[_vm->_drop][0])) - isGenericVerb(obj, comment); - return true; -} - -/** -* Test whether command line contains one of the generic actions -*/ -bool Parser_v1w::isGenericVerb(object_t *obj, char *comment) { - debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s)", comment); - - if (!obj->genericCmd) - return false; - - // Following is equivalent to switch, but couldn't do one - if (isWordPresent(_vm->_arrayVerbs[_vm->_look]) && isNear(obj, _vm->_arrayVerbs[_vm->_look][0], comment)) { - // Test state-dependent look before general look - if ((obj->genericCmd & LOOK_S) == LOOK_S) { - Utils::Box(BOX_ANY, "%s", _vm->_textData[obj->stateDataIndex[obj->state]]); - } else { - if ((LOOK & obj->genericCmd) == LOOK) { - if (_vm->_textData[obj->dataIndex]) - Utils::Box(BOX_ANY, "%s", _vm->_textData[obj->dataIndex]); - else - return false; - } else { - Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBUnusual]); - } + status_t &gameStatus = _vm->getGameStatus(); + bool repeatedFl = (nFlags & 0x4000); // TRUE if key is a repeat + +// Process key down event - called from OnKeyDown() + switch (nChar) { // Set various toggle states + case Common::KEYCODE_ESCAPE: // Escape key, may want to QUIT + if (gameStatus.inventoryState == I_ACTIVE) // Remove inventory, if displayed + gameStatus.inventoryState = I_UP; + gameStatus.inventoryObjId = -1; // Deselect any dragged icon + break; + case Common::KEYCODE_END: + case Common::KEYCODE_HOME: + case Common::KEYCODE_LEFT: + case Common::KEYCODE_RIGHT: + case Common::KEYCODE_UP: + case Common::KEYCODE_DOWN: + if (!repeatedFl) { + gameStatus.routeIndex = -1; // Stop any automatic route + _vm->_route->setWalk(nChar); // Direction of hero travel } - } else if (isWordPresent(_vm->_arrayVerbs[_vm->_take]) && isNear(obj, _vm->_arrayVerbs[_vm->_take][0], comment)) { - if (obj->carriedFl) - Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBHave]); - else if ((TAKE & obj->genericCmd) == TAKE) - takeObject(obj); - else if (obj->cmdIndex != 0) // No comment if possible commands - return false; - else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! - Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoUse]); - else - return false; - } else if (isWordPresent(_vm->_arrayVerbs[_vm->_drop])) { - if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBDontHave]); - else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - dropObject(obj); - else if (obj->cmdIndex == 0) - Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNeed]); + break; + case Common::KEYCODE_F1: // User Help (DOS) + if (_checkDoubleF1Fl) + _vm->_file->instructions(); else - return false; - } else { // It was not a generic cmd - return false; - } - - return true; -} - -/** -* Test whether hero is close to object. Return TRUE or FALSE -* If object not near, return suitable comment; may be another object close -* If radius is -1, treat radius as infinity -* Verb is included to determine correct comment if not near -*/ -bool Parser_v1w::isNear(object_t *obj, char *verb, char *comment) { - debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); - - if (obj->carriedFl) // Object is being carried - return true; - - if (obj->screenIndex != *_vm->_screen_p) { - // Not in same screen - if (obj->objValue) - strcpy(comment, _vm->_textParser[kCmtAny1]); - else - strcpy(comment, _vm->_textParser[kCmtAny2]); - return false; - } - - if (obj->cycling == INVISIBLE) { - if (obj->seqNumb) { - // There is an image - strcpy(comment, _vm->_textParser[kCmtAny3]); - return false; - } else { - // No image, assume visible - if ((obj->radius < 0) || - ((abs(obj->x - _vm->_hero->x) <= obj->radius) && - (abs(obj->y - _vm->_hero->y - _vm->_hero->currImagePtr->y2) <= obj->radius))) { - return true; - } else { - // User is not close enough - if (obj->objValue && (verb != _vm->_arrayVerbs[_vm->_take][0])) - strcpy(comment, _vm->_textParser[kCmtAny1]); - else - strcpy(comment, _vm->_textParser[kCmtClose]); - return false; + _vm->_screen->userHelp(); + _checkDoubleF1Fl = !_checkDoubleF1Fl; + break; + case Common::KEYCODE_F2: // Toggle sound + _vm->_sound->toggleSound(); + _vm->_sound->toggleMusic(); + break; + case Common::KEYCODE_F3: // Repeat last line + gameStatus.recallFl = true; + break; + case Common::KEYCODE_F4: // Save game + if (gameStatus.viewState == V_PLAY) + _vm->_file->saveGame(-1, Common::String()); + break; + case Common::KEYCODE_F5: // Restore game + _vm->_file->restoreGame(-1); + _vm->_scheduler->restoreScreen(*_vm->_screen_p); + gameStatus.viewState = V_PLAY; + break; + case Common::KEYCODE_F6: // Inventory + gameStatus.inventoryState = I_DOWN; + gameStatus.viewState = V_INVENT; + break; + case Common::KEYCODE_F8: // Turbo mode + _config.turboFl = !_config.turboFl; + break; + case Common::KEYCODE_F9: // Boss button + warning("STUB: F9 (DOS) - BossKey"); + break; + default: // Any other key + if (!gameStatus.storyModeFl) { // Keyboard disabled + // Add printable keys to ring buffer + uint16 bnext = _putIndex + 1; + if (bnext >= sizeof(_ringBuffer)) + bnext = 0; + if (bnext != _getIndex) { + _ringBuffer[_putIndex] = nChar; + _putIndex = bnext; } } + break; } - - if ((obj->radius < 0) || - ((abs(obj->x - _vm->_hero->x) <= obj->radius) && - (abs(obj->y + obj->currImagePtr->y2 - _vm->_hero->y - _vm->_hero->currImagePtr->y2) <= obj->radius))) { - return true; - } else { - // User is not close enough - if (obj->objValue && (verb != _vm->_arrayVerbs[_vm->_take][0])) - strcpy(comment, _vm->_textParser[kCmtAny1]); - else - strcpy(comment, _vm->_textParser[kCmtClose]); - return false; - } - return true; -} - -/** -* Do all things necessary to carry an object -*/ -void Parser_v1w::takeObject(object_t *obj) { - debugC(1, kDebugParser, "takeObject(object_t *obj)"); - - obj->carriedFl = true; - if (obj->seqNumb) { // Don't change if no image to display - obj->cycling = INVISIBLE; - } - _vm->adjustScore(obj->objValue); - - if (obj->seqNumb > 0) // If object has an image, force walk to dropped - obj->viewx = -1; // (possibly moved) object next time taken! - Utils::Box(BOX_ANY, TAKE_TEXT, _vm->_arrayNouns[obj->nounIndex][TAKE_NAME]); -} - -/** -* Do all necessary things to drop an object -*/ -void Parser_v1w::dropObject(object_t *obj) { - debugC(1, kDebugParser, "dropObject(object_t *obj)"); - - obj->carriedFl = false; - obj->screenIndex = *_vm->_screen_p; - if ((obj->seqNumb > 1) || (obj->seqList[0].imageNbr > 1)) - obj->cycling = CYCLE_FORWARD; - else - obj->cycling = NOT_CYCLING; - obj->x = _vm->_hero->x - 1; - obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; - obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; - _vm->adjustScore(-obj->objValue); - Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBOk]); -} - -/** -* Search for matching verbs in background command list. -* Noun is not required. Return TRUE if match found -* Note that if the background command list has match set TRUE then do not -* print text if there are any recognizable nouns in the command line -*/ -bool Parser_v1w::isCatchallVerb(objectList_t obj) { - debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)"); - - for (int i = 0; obj[i].verbIndex != 0; i++) { - if (isWordPresent(_vm->_arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && - (!obj[i].matchFl || !findNoun()) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) { - Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(obj[i].commentIndex)); - _vm->_scheduler->processBonus(obj[i].bonusIndex); - - // If this is LOOK (without a noun), show any takeable objects - if (*(_vm->_arrayVerbs[obj[i].verbIndex]) == _vm->_arrayVerbs[_vm->_look][0]) - _vm->_object->showTakeables(); - - return true; - } - } - return false; -} - -/** -* Search for matching verb/noun pairs in background command list -* Print text for possible background object. Return TRUE if match found -*/ -bool Parser_v1w::isBackgroundWord(objectList_t obj) { - debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)"); - - for (int i = 0; obj[i].verbIndex != 0; i++) { - if (isWordPresent(_vm->_arrayVerbs[obj[i].verbIndex]) && - isWordPresent(_vm->_arrayNouns[obj[i].nounIndex]) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) { - Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(obj[i].commentIndex)); - _vm->_scheduler->processBonus(obj[i].bonusIndex); - return true; - } - } - return false; + if (_checkDoubleF1Fl && (nChar != Common::KEYCODE_F1)) + _checkDoubleF1Fl = false; } /** diff --git a/engines/hugo/parser_v3d.cpp b/engines/hugo/parser_v3d.cpp index ca78307a44..c78af20ef3 100644 --- a/engines/hugo/parser_v3d.cpp +++ b/engines/hugo/parser_v3d.cpp @@ -44,7 +44,7 @@ namespace Hugo { -Parser_v3d::Parser_v3d(HugoEngine *vm) : Parser_v1w(vm) { +Parser_v3d::Parser_v3d(HugoEngine *vm) : Parser(vm) { } Parser_v3d::~Parser_v3d() { @@ -204,4 +204,253 @@ void Parser_v3d::lineHandler() { } } +/** +* Test whether command line contains a verb allowed by this object. +* If it does, and the object is near and passes the tests in the command +* list then carry out the actions in the action list and return TRUE +*/ +bool Parser_v3d::isObjectVerb(object_t *obj, char *comment) { + debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s)", comment); + + // First, find matching verb in cmd list + uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands + if (cmdIndex == 0) // No commands for this obj + return false; + + int i; + for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd + if (isWordPresent(_vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex])) // Was this verb used? + break; + } + + if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. + return false; + + // Verb match found. Check if object is Near + char *verb = *_vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex]; + if (!isNear(obj, verb, comment)) + return false; + + // Check all required objects are being carried + cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd + if (cmnd->reqIndex) { // At least 1 thing in list + uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + for (i = 0; reqs[i]; i++) { // for each obj + if (!_vm->_object->isCarrying(reqs[i])) { + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataNoCarryIndex]); + return true; + } + } + } + + // Required objects are present, now check state is correct + if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataWrongIndex]); + return true; + } + + // Everything checked. Change the state and carry out any actions + if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care + obj->state = cmnd->newState; + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataDoneIndex]); + _vm->_scheduler->insertActionList(cmnd->actIndex); + + // See if any additional generic actions + if ((verb == _vm->_arrayVerbs[_vm->_look][0]) || (verb == _vm->_arrayVerbs[_vm->_take][0]) || (verb == _vm->_arrayVerbs[_vm->_drop][0])) + isGenericVerb(obj, comment); + return true; +} + +/** +* Test whether command line contains one of the generic actions +*/ +bool Parser_v3d::isGenericVerb(object_t *obj, char *comment) { + debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s)", comment); + + if (!obj->genericCmd) + return false; + + // Following is equivalent to switch, but couldn't do one + if (isWordPresent(_vm->_arrayVerbs[_vm->_look]) && isNear(obj, _vm->_arrayVerbs[_vm->_look][0], comment)) { + // Test state-dependent look before general look + if ((obj->genericCmd & LOOK_S) == LOOK_S) { + Utils::Box(BOX_ANY, "%s", _vm->_textData[obj->stateDataIndex[obj->state]]); + } else { + if ((LOOK & obj->genericCmd) == LOOK) { + if (_vm->_textData[obj->dataIndex]) + Utils::Box(BOX_ANY, "%s", _vm->_textData[obj->dataIndex]); + else + return false; + } else { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBUnusual]); + } + } + } else if (isWordPresent(_vm->_arrayVerbs[_vm->_take]) && isNear(obj, _vm->_arrayVerbs[_vm->_take][0], comment)) { + if (obj->carriedFl) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBHave]); + else if ((TAKE & obj->genericCmd) == TAKE) + takeObject(obj); + else if (obj->cmdIndex != 0) // No comment if possible commands + return false; + else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoUse]); + else + return false; + } else if (isWordPresent(_vm->_arrayVerbs[_vm->_drop])) { + if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBDontHave]); + else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + dropObject(obj); + else if (obj->cmdIndex == 0) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNeed]); + else + return false; + } else { // It was not a generic cmd + return false; + } + + return true; +} + +/** +* Test whether hero is close to object. Return TRUE or FALSE +* If object not near, return suitable comment; may be another object close +* If radius is -1, treat radius as infinity +* Verb is included to determine correct comment if not near +*/ +bool Parser_v3d::isNear(object_t *obj, char *verb, char *comment) { + debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); + + if (obj->carriedFl) // Object is being carried + return true; + + if (obj->screenIndex != *_vm->_screen_p) { + // Not in same screen + if (obj->objValue) + strcpy(comment, _vm->_textParser[kCmtAny1]); + else + strcpy(comment, _vm->_textParser[kCmtAny2]); + return false; + } + + if (obj->cycling == INVISIBLE) { + if (obj->seqNumb) { + // There is an image + strcpy(comment, _vm->_textParser[kCmtAny3]); + return false; + } else { + // No image, assume visible + if ((obj->radius < 0) || + ((abs(obj->x - _vm->_hero->x) <= obj->radius) && + (abs(obj->y - _vm->_hero->y - _vm->_hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is not close enough + if (obj->objValue && (verb != _vm->_arrayVerbs[_vm->_take][0])) + strcpy(comment, _vm->_textParser[kCmtAny1]); + else + strcpy(comment, _vm->_textParser[kCmtClose]); + return false; + } + } + } + + if ((obj->radius < 0) || + ((abs(obj->x - _vm->_hero->x) <= obj->radius) && + (abs(obj->y + obj->currImagePtr->y2 - _vm->_hero->y - _vm->_hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is not close enough + if (obj->objValue && (verb != _vm->_arrayVerbs[_vm->_take][0])) + strcpy(comment, _vm->_textParser[kCmtAny1]); + else + strcpy(comment, _vm->_textParser[kCmtClose]); + return false; + } + return true; +} + +/** +* Do all things necessary to carry an object +*/ +void Parser_v3d::takeObject(object_t *obj) { + debugC(1, kDebugParser, "takeObject(object_t *obj)"); + + obj->carriedFl = true; + if (obj->seqNumb) { // Don't change if no image to display + obj->cycling = INVISIBLE; + } + _vm->adjustScore(obj->objValue); + + if (obj->seqNumb > 0) // If object has an image, force walk to dropped + obj->viewx = -1; // (possibly moved) object next time taken! + Utils::Box(BOX_ANY, TAKE_TEXT, _vm->_arrayNouns[obj->nounIndex][TAKE_NAME]); +} + +/** +* Do all necessary things to drop an object +*/ +void Parser_v3d::dropObject(object_t *obj) { + debugC(1, kDebugParser, "dropObject(object_t *obj)"); + + obj->carriedFl = false; + obj->screenIndex = *_vm->_screen_p; + if ((obj->seqNumb > 1) || (obj->seqList[0].imageNbr > 1)) + obj->cycling = CYCLE_FORWARD; + else + obj->cycling = NOT_CYCLING; + obj->x = _vm->_hero->x - 1; + obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; + obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; + _vm->adjustScore(-obj->objValue); + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBOk]); +} + +/** +* Search for matching verbs in background command list. +* Noun is not required. Return TRUE if match found +* Note that if the background command list has match set TRUE then do not +* print text if there are any recognizable nouns in the command line +*/ +bool Parser_v3d::isCatchallVerb(objectList_t obj) { + debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)"); + + for (int i = 0; obj[i].verbIndex != 0; i++) { + if (isWordPresent(_vm->_arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && + (!obj[i].matchFl || !findNoun()) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) { + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + _vm->_scheduler->processBonus(obj[i].bonusIndex); + + // If this is LOOK (without a noun), show any takeable objects + if (*(_vm->_arrayVerbs[obj[i].verbIndex]) == _vm->_arrayVerbs[_vm->_look][0]) + _vm->_object->showTakeables(); + + return true; + } + } + return false; +} + +/** +* Search for matching verb/noun pairs in background command list +* Print text for possible background object. Return TRUE if match found +*/ +bool Parser_v3d::isBackgroundWord(objectList_t obj) { + debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)"); + + for (int i = 0; obj[i].verbIndex != 0; i++) { + if (isWordPresent(_vm->_arrayVerbs[obj[i].verbIndex]) && + isWordPresent(_vm->_arrayNouns[obj[i].nounIndex]) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) { + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + _vm->_scheduler->processBonus(obj[i].bonusIndex); + return true; + } + } + return false; +} + } // End of namespace Hugo |