HUGO: Enable the use of the icon based inventory
In Win versions, F6 now opens the directory. Not perfect yet... svn-id: r54853
This commit is contained in:
parent
e6366d4972
commit
f8fa960cfd
6 changed files with 358 additions and 282 deletions
|
@ -73,7 +73,7 @@ void InventoryHandler::constructInventory(int16 imageTotNumb, int displayNumb, b
|
||||||
// Copy inventory icons to remaining positions
|
// Copy inventory icons to remaining positions
|
||||||
int16 displayed = 0;
|
int16 displayed = 0;
|
||||||
int16 carried = 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])) {
|
if (_vm->_object->isCarried(_vm->_invent[i])) {
|
||||||
// Check still room to display and past first scroll index
|
// Check still room to display and past first scroll index
|
||||||
if (displayed < displayNumb && carried >= firstObjId) {
|
if (displayed < displayNumb && carried >= firstObjId) {
|
||||||
|
|
|
@ -113,7 +113,7 @@ void ObjectHandler::useObject(int16 objId) {
|
||||||
} else {
|
} else {
|
||||||
// Use status.objid on objid
|
// Use status.objid on objid
|
||||||
// Default to first cmd verb
|
// 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[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0],
|
||||||
_vm->_arrayNouns[obj->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
|
// Look for secondary object, if found use matching verb
|
||||||
bool foundFl = false;
|
bool foundFl = false;
|
||||||
for (target_t *target = use->targets; _vm->_arrayNouns[target->nounIndex] != 0; target++)
|
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;
|
foundFl = true;
|
||||||
sprintf(_line, "%s %s %s", _vm->_arrayVerbs[target->verbIndex][0],
|
sprintf(_line, "%s %s %s", _vm->_arrayVerbs[target->verbIndex][0],
|
||||||
_vm->_arrayNouns[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0],
|
_vm->_arrayNouns[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0],
|
||||||
|
|
|
@ -86,12 +86,6 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) {
|
||||||
_vm->_screen->userHelp();
|
_vm->_screen->userHelp();
|
||||||
_checkDoubleF1Fl = !_checkDoubleF1Fl;
|
_checkDoubleF1Fl = !_checkDoubleF1Fl;
|
||||||
break;
|
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
|
case Common::KEYCODE_F2: // Toggle sound
|
||||||
_vm->_sound->toggleSound();
|
_vm->_sound->toggleSound();
|
||||||
_vm->_sound->toggleMusic();
|
_vm->_sound->toggleMusic();
|
||||||
|
@ -108,6 +102,12 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) {
|
||||||
_vm->_scheduler->restoreScreen(*_vm->_screen_p);
|
_vm->_scheduler->restoreScreen(*_vm->_screen_p);
|
||||||
gameStatus.viewState = V_PLAY;
|
gameStatus.viewState = V_PLAY;
|
||||||
break;
|
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
|
case Common::KEYCODE_F9: // Boss button
|
||||||
warning("STUB: F9 (DOS) - BossKey");
|
warning("STUB: F9 (DOS) - BossKey");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -47,11 +47,12 @@ public:
|
||||||
Parser(HugoEngine *vm);
|
Parser(HugoEngine *vm);
|
||||||
virtual ~Parser();
|
virtual ~Parser();
|
||||||
|
|
||||||
bool isWordPresent(char **wordArr);
|
bool isWordPresent(char **wordArr);
|
||||||
|
|
||||||
void charHandler();
|
void charHandler();
|
||||||
void command(const char *format, ...);
|
void command(const char *format, ...);
|
||||||
void keyHandler(uint16 nChar, uint16 nFlags);
|
|
||||||
|
virtual void keyHandler(uint16 nChar, uint16 nFlags);
|
||||||
virtual void lineHandler() = 0;
|
virtual void lineHandler() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -60,33 +61,13 @@ protected:
|
||||||
protected:
|
protected:
|
||||||
char *findNoun();
|
char *findNoun();
|
||||||
char *findVerb();
|
char *findVerb();
|
||||||
|
bool _checkDoubleF1Fl; // Flag used to display user help or instructions
|
||||||
private:
|
|
||||||
char _ringBuffer[32]; // Ring buffer
|
|
||||||
uint16 _putIndex;
|
uint16 _putIndex;
|
||||||
uint16 _getIndex; // Index into ring buffer
|
uint16 _getIndex; // Index into ring buffer
|
||||||
bool _checkDoubleF1Fl; // Flag used to display user help or instructions
|
char _ringBuffer[32]; // Ring buffer
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isNear(object_t *obj, char *verb, char *comment);
|
void showDosInventory();
|
||||||
void dropObject(object_t *obj);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Parser_v1d : public Parser {
|
class Parser_v1d : public Parser {
|
||||||
|
@ -115,12 +96,31 @@ public:
|
||||||
void lineHandler();
|
void lineHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Parser_v3d : public Parser_v1w {
|
class Parser_v3d : public Parser {
|
||||||
public:
|
public:
|
||||||
Parser_v3d(HugoEngine *vm);
|
Parser_v3d(HugoEngine *vm);
|
||||||
~Parser_v3d();
|
~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
|
} // End of namespace Hugo
|
||||||
|
|
|
@ -38,264 +38,91 @@
|
||||||
#include "hugo/parser.h"
|
#include "hugo/parser.h"
|
||||||
#include "hugo/file.h"
|
#include "hugo/file.h"
|
||||||
#include "hugo/schedule.h"
|
#include "hugo/schedule.h"
|
||||||
|
#include "hugo/route.h"
|
||||||
|
#include "hugo/display.h"
|
||||||
#include "hugo/util.h"
|
#include "hugo/util.h"
|
||||||
#include "hugo/sound.h"
|
#include "hugo/sound.h"
|
||||||
#include "hugo/object.h"
|
#include "hugo/object.h"
|
||||||
|
|
||||||
namespace Hugo {
|
namespace Hugo {
|
||||||
Parser_v1w::Parser_v1w(HugoEngine *vm) : Parser(vm) {
|
Parser_v1w::Parser_v1w(HugoEngine *vm) : Parser_v3d(vm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser_v1w::~Parser_v1w() {
|
Parser_v1w::~Parser_v1w() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void Parser_v1w::keyHandler(uint16 nChar, uint16 nFlags) {
|
||||||
* Test whether command line contains a verb allowed by this object.
|
debugC(1, kDebugParser, "keyHandler(%d, %d)", nChar, nFlags);
|
||||||
* 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
|
status_t &gameStatus = _vm->getGameStatus();
|
||||||
uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands
|
bool repeatedFl = (nFlags & 0x4000); // TRUE if key is a repeat
|
||||||
if (cmdIndex == 0) // No commands for this obj
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int i;
|
// Process key down event - called from OnKeyDown()
|
||||||
for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd
|
switch (nChar) { // Set various toggle states
|
||||||
if (isWordPresent(_vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex])) // Was this verb used?
|
case Common::KEYCODE_ESCAPE: // Escape key, may want to QUIT
|
||||||
break;
|
if (gameStatus.inventoryState == I_ACTIVE) // Remove inventory, if displayed
|
||||||
}
|
gameStatus.inventoryState = I_UP;
|
||||||
|
gameStatus.inventoryObjId = -1; // Deselect any dragged icon
|
||||||
if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No verbs used.
|
break;
|
||||||
return false;
|
case Common::KEYCODE_END:
|
||||||
|
case Common::KEYCODE_HOME:
|
||||||
// Verb match found. Check if object is Near
|
case Common::KEYCODE_LEFT:
|
||||||
char *verb = *_vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex];
|
case Common::KEYCODE_RIGHT:
|
||||||
if (!isNear(obj, verb, comment))
|
case Common::KEYCODE_UP:
|
||||||
return false;
|
case Common::KEYCODE_DOWN:
|
||||||
|
if (!repeatedFl) {
|
||||||
// Check all required objects are being carried
|
gameStatus.routeIndex = -1; // Stop any automatic route
|
||||||
cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd
|
_vm->_route->setWalk(nChar); // Direction of hero travel
|
||||||
if (cmnd->reqIndex) { // At least 1 thing in list
|
}
|
||||||
uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects
|
break;
|
||||||
for (i = 0; reqs[i]; i++) { // for each obj
|
case Common::KEYCODE_F1: // User Help (DOS)
|
||||||
if (!_vm->_object->isCarrying(reqs[i])) {
|
if (_checkDoubleF1Fl)
|
||||||
Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataNoCarryIndex]);
|
_vm->_file->instructions();
|
||||||
return true;
|
else
|
||||||
|
_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 (_checkDoubleF1Fl && (nChar != Common::KEYCODE_F1))
|
||||||
// Required objects are present, now check state is correct
|
_checkDoubleF1Fl = false;
|
||||||
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_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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} 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_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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
namespace Hugo {
|
namespace Hugo {
|
||||||
|
|
||||||
Parser_v3d::Parser_v3d(HugoEngine *vm) : Parser_v1w(vm) {
|
Parser_v3d::Parser_v3d(HugoEngine *vm) : Parser(vm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser_v3d::~Parser_v3d() {
|
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
|
} // End of namespace Hugo
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue