diff options
author | Andrew Kurushin | 2005-01-18 15:01:21 +0000 |
---|---|---|
committer | Andrew Kurushin | 2005-01-18 15:01:21 +0000 |
commit | b4b2e52df78fd309613d8df73f090b98e834969b (patch) | |
tree | 7e79ad73fbb11d0755e2c3e4926d99ab3653bb95 /saga | |
parent | c1ce30b0bfa69aee3c91602536da8d2c5fa72e8b (diff) | |
download | scummvm-rg350-b4b2e52df78fd309613d8df73f090b98e834969b.tar.gz scummvm-rg350-b4b2e52df78fd309613d8df73f090b98e834969b.tar.bz2 scummvm-rg350-b4b2e52df78fd309613d8df73f090b98e834969b.zip |
another step in verb implementation:
- objectMap responds to mouse move (but respond script not run well ?)
loadStrings add some special count check
- so all other LUT based resource should implement this technique
svn-id: r16594
Diffstat (limited to 'saga')
-rw-r--r-- | saga/actor.h | 6 | ||||
-rw-r--r-- | saga/interface.cpp | 78 | ||||
-rw-r--r-- | saga/interface.h | 2 | ||||
-rw-r--r-- | saga/objectmap.cpp | 22 | ||||
-rw-r--r-- | saga/objectmap.h | 21 | ||||
-rw-r--r-- | saga/saga.cpp | 42 | ||||
-rw-r--r-- | saga/saga.h | 17 | ||||
-rw-r--r-- | saga/scene.h | 2 | ||||
-rw-r--r-- | saga/script.cpp | 61 |
9 files changed, 111 insertions, 140 deletions
diff --git a/saga/actor.h b/saga/actor.h index 6deb87b9d2..4e18ca23ae 100644 --- a/saga/actor.h +++ b/saga/actor.h @@ -276,9 +276,9 @@ public: void cmdActorWalkTo(int argc, const char **argv); - bool validActorId(uint16 id) { return (id == 1) || ((id >= 0x2000) && (id < (0x2000 | _actorsCount))); } - int actorIdToIndex(uint16 id) { return (id == 1 ) ? 0 : (id & ~0x2000); } - uint16 actorIndexToId(int index) { return (index == 0 ) ? 1 : (index | 0x2000); } + bool validActorId(uint16 id) { return (id == ID_PROTAG) || ((id > OBJECT_TYPE_MASK) && (id < objectIndexToId(kGameObjectActor, _actorsCount))); } + int actorIdToIndex(uint16 id) { return (id == ID_PROTAG ) ? 0 : objectIdToIndex(id); } + uint16 actorIndexToId(int index) { return (index == 0 ) ? ID_PROTAG : objectIndexToId(kGameObjectActor, index); } int direct(int msec); int drawActors(); diff --git a/saga/interface.cpp b/saga/interface.cpp index 8bb72e9843..1b6aabece7 100644 --- a/saga/interface.cpp +++ b/saga/interface.cpp @@ -478,84 +478,6 @@ void Interface::handleCommandUpdate(SURFACE *ds, const Point& mousePoint) { } -int Interface::handlePlayfieldClick(SURFACE *ds, const Point& imousePt) { -// return SUCCESS; - - int objectNum; - uint16 object_flags = 0; - -// int script_num; - Location location; - - objectNum = _vm->_scene->_objectMap->hitTest(imousePt); - - if (objectNum == -1) { - // Player clicked on empty spot - walk here regardless of verb - location.fromScreenPoint(imousePt); - - _vm->_actor->actorWalkTo(ID_PROTAG, location); - return SUCCESS; - } - -// object_flags = _vm->_scene->_objectMap->getFlags(objectNum); - - if (object_flags & kHitZoneExit) { // FIXME. This is wrong -/* if ((script_num = _vm->_scene->_objectMap->getEPNum(objectNum)) != -1) { - // Set active verb in script module - _vm->_script->putWord(4, 4, I_VerbData[_activeVerb].s_verb); - - // Execute object script if present - if (script_num != 0) { - _vm->_script->SThreadExecute(_iThread, script_num); - } - }*/ - } else { - // Not a normal scene object - walk to it as if it weren't there - location.fromScreenPoint(imousePt); - - _vm->_actor->actorWalkTo(ID_PROTAG, location); - } - - return SUCCESS; -} - -int Interface::handlePlayfieldUpdate(SURFACE *ds, const Point& imousePt) { - return SUCCESS; - /* - const char *object_name; - int objectNum; - uint16 object_flags = 0; - - char new_status[STATUS_TEXT_LEN]; - - new_status[0] = 0; - - objectNum = _vm->_scene->_objectMap->hitTest(imousePt); - - if (objectNum == -1) { - // Cursor over nothing - just display current verb - setStatusText(I_VerbData[_activeVerb].verb_str); - return SUCCESS; - } - - object_flags = _vm->_scene->_objectMap->getFlags(objectNum); - object_name = _vm->_scene->_objectMap->getName(objectNum); - - if (object_flags & OBJECT_EXIT) { // FIXME. This is wrong - // Normal scene object - display as subject of verb - snprintf(new_status, STATUS_TEXT_LEN, "%s %s", I_VerbData[_activeVerb].verb_str, object_name); - } else { - // Not normal scene object - override verb as we can only - // walk to this object - snprintf(new_status, STATUS_TEXT_LEN, "%s %s", I_VerbData[I_VERB_WALKTO].verb_str, object_name); - } - - setStatusText(new_status); - - return SUCCESS; - */ -} - PanelButton *Interface::verbHitTest(const Point& mousePoint) { PanelButton *panelButton; Rect rect; diff --git a/saga/interface.h b/saga/interface.h index f0d562e830..4781b84b69 100644 --- a/saga/interface.h +++ b/saga/interface.h @@ -124,8 +124,6 @@ private: PanelButton *verbHitTest(const Point& mousePoint); void handleCommandUpdate(SURFACE *ds, const Point& mousePoint); void handleCommandClick(SURFACE *ds, const Point& mousePoint); - int handlePlayfieldUpdate(SURFACE *ds, const Point& imousePt); - int handlePlayfieldClick(SURFACE *ds, const Point& imousePt); void lockMode() { _lockedMode = _panelMode; } void unlockMode() { _panelMode = _lockedMode; } diff --git a/saga/objectmap.cpp b/saga/objectmap.cpp index 7333ea7e18..7b104c6d24 100644 --- a/saga/objectmap.cpp +++ b/saga/objectmap.cpp @@ -36,7 +36,7 @@ namespace Saga { -HitZone::HitZone(MemoryReadStreamEndian *readStream) { +HitZone::HitZone(MemoryReadStreamEndian *readStream, int index): _index(index) { int i, j; HitZone::ClickArea *clickArea; Point *point; @@ -45,7 +45,7 @@ HitZone::HitZone(MemoryReadStreamEndian *readStream) { _clickAreasCount = readStream->readByte(); _rightButtonVerb = readStream->readByte(); readStream->readByte(); // pad - _nameNumber = readStream->readUint16(); + _nameIndex = readStream->readUint16(); _scriptNumber = readStream->readUint16(); _clickAreas = (HitZone::ClickArea *)malloc(_clickAreasCount * sizeof(*_clickAreas)); @@ -80,6 +80,22 @@ HitZone::~HitZone() { free(_clickAreas); } +bool HitZone::getSpecialPoint(Point &specialPoint) const { + int i, pointsCount; + HitZone::ClickArea *clickArea; + Point *points; + + for (i = 0; i < _clickAreasCount; i++) { + clickArea = &_clickAreas[i]; + pointsCount = clickArea->pointsCount; + points = clickArea->points; + if (pointsCount == 1) { + specialPoint = points[0]; + return true; + } + } + return false; +} bool HitZone::hitTest(const Point &testPoint) { int i, pointsCount; HitZone::ClickArea *clickArea; @@ -157,7 +173,7 @@ void ObjectMap::load(const byte *resourcePointer, size_t resourceLength) { } for (i = 0; i < _hitZoneListCount; i++) { - _hitZoneList[i] = new HitZone(&readS); + _hitZoneList[i] = new HitZone(&readS, i); } } diff --git a/saga/objectmap.h b/saga/objectmap.h index 4571e77a1c..dc97271912 100644 --- a/saga/objectmap.h +++ b/saga/objectmap.h @@ -39,11 +39,14 @@ private: }; public: - HitZone(MemoryReadStreamEndian *readStream); + HitZone(MemoryReadStreamEndian *readStream, int index); ~HitZone(); - + + int getNameIndex() const { + return _nameIndex; + } int getSceneNumber() const { - return _nameNumber; + return _nameIndex; } int getActorsEntrance() const { return _scriptNumber; @@ -60,14 +63,22 @@ public: int getDirection() const { return ((_flags >> 4) & 0xF); } + uint16 getHitZoneId() const { + return objectIndexToId(kGameObjectHitZone, _index); + } + uint16 getStepZoneId() const { + return objectIndexToId(kGameObjectStepZone, _index); + } + bool getSpecialPoint(Point &specialPoint) const; void draw(SURFACE *ds, int color); bool hitTest(const Point &testPoint); private: - int _flags; // HitZoneFlags + int _flags; // Saga::HitZoneFlags int _clickAreasCount; int _rightButtonVerb; - int _nameNumber; + int _nameIndex; int _scriptNumber; + int _index; ClickArea *_clickAreas; }; diff --git a/saga/saga.cpp b/saga/saga.cpp index 6d06a149d7..c792ee0454 100644 --- a/saga/saga.cpp +++ b/saga/saga.cpp @@ -51,6 +51,7 @@ #include "saga/sound.h" #include "saga/music.h" #include "saga/palanim.h" +#include "saga/objectmap.h" static const GameSettings saga_games[] = { {"ite", "Inherit the Earth", 0}, @@ -316,45 +317,46 @@ int SagaEngine::go() { void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPointer, size_t stringsLength) { uint16 stringsCount; - uint16 i; size_t offset; + int i; - stringsTable.stringsPointer = (byte*)malloc(stringsLength); memcpy(stringsTable.stringsPointer, stringsPointer, stringsLength); + MemoryReadStreamEndian scriptS(stringsTable.stringsPointer, stringsLength, IS_BIG_ENDIAN); offset = scriptS.readUint16(); - if (offset > stringsLength) { - error("Invalid string offset"); - } - - stringsCount = offset / 2 - 2; - stringsTable.stringsCount = stringsCount; - - stringsTable.strings = (const char **)malloc(stringsCount * sizeof(const char *)); - if (stringsTable.strings == NULL) { - error("No enough memory for strings Table"); - } - + stringsCount = offset / 2; + stringsTable.strings = (const char **)malloc(stringsCount * sizeof(*stringsTable.strings)); + i = 0; scriptS.seek(0); - for (i = 0; i < stringsCount; i++) { + while (i < stringsCount) { offset = scriptS.readUint16(); + if (offset == stringsLength) { + stringsCount = i; + stringsTable.strings = (const char **)realloc(stringsTable.strings, stringsCount * sizeof(*stringsTable.strings)); + break; + } if (offset > stringsLength) { - error("invalid string offset"); + error("SagaEngine::loadStrings wrong strings table"); } stringsTable.strings[i] = (const char *)stringsTable.stringsPointer + offset; debug(9, "string[%i]=%s", i, stringsTable.strings[i]); + i++; } + stringsTable.stringsCount = stringsCount; } const char *SagaEngine::getObjectName(uint16 objectId) { - - switch (objectIdType(objectId)) { + const HitZone *hitZone; + switch (objectTypeId(objectId)) { case kGameObjectActor: return _actor->getActorName(objectId); break; + case kGameObjectHitZone: + hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(objectId)); + return _vm->_scene->_sceneStrings.getString(hitZone->getNameIndex()); } //todo: object name & etc return NULL; @@ -362,7 +364,7 @@ const char *SagaEngine::getObjectName(uint16 objectId) { int SagaEngine::getObjectScriptEntrypointNumber(uint16 objectId) { ActorData *actor; - switch (objectIdType(objectId)) { + switch (objectTypeId(objectId)) { case kGameObjectActor: actor = _vm->_actor->getActor(objectId); return actor->scriptEntrypointNumber; @@ -374,7 +376,7 @@ int SagaEngine::getObjectScriptEntrypointNumber(uint16 objectId) { int SagaEngine::getObjectFlags(uint16 objectId) { ActorData *actor; - if (objectIdType(objectId) == kGameObjectActor) { + if (objectTypeId(objectId) == kGameObjectActor) { actor = _vm->_actor->getActor(objectId); return actor->flags; } diff --git a/saga/saga.h b/saga/saga.h index b3b32aaae5..346ea2a4d0 100644 --- a/saga/saga.h +++ b/saga/saga.h @@ -72,6 +72,8 @@ class PalAnim; #define ID_NOTHING 0 #define ID_PROTAG 1 +#define OBJECT_TYPE_SHIFT 13 +#define OBJECT_TYPE_MASK ((1 << OBJECT_TYPE_SHIFT) - 1) struct RSCFILE_CONTEXT; struct StringList; @@ -195,7 +197,7 @@ struct StringsTable { const char **strings; const char *getString(int index) const { - if (stringsCount <= index) + if ((stringsCount <= index) || (index < 0)) error("StringList::getString wrong index 0x%X", index); return strings[index]; } @@ -393,10 +395,19 @@ inline int integerCompare(int i1, int i2) { return ((i1) > (i2) ? 1 : ((i1) < (i2) ? -1 : 0)); } -inline int objectIdType(uint16 objectId) { - return objectId >> 13; +inline int objectTypeId(uint16 objectId) { + return objectId >> OBJECT_TYPE_SHIFT; } +inline int objectIdToIndex(uint16 objectId) { + return OBJECT_TYPE_MASK & objectId; +} + +inline uint16 objectIndexToId(int type, int index) { + return (type << OBJECT_TYPE_SHIFT) | (OBJECT_TYPE_MASK & index); +} + + DetectedGameList GAME_ProbeGame(const FSList &fslist); class SagaEngine : public Engine { diff --git a/saga/scene.h b/saga/scene.h index 705c05c871..490b390dba 100644 --- a/saga/scene.h +++ b/saga/scene.h @@ -292,7 +292,6 @@ class Scene { SCENE_IMAGE _bg; SCENE_IMAGE _bgMask; - StringsTable _sceneStrings; int _sceneDoors[SCENE_DOORS_MAX]; static int SC_defaultScene(int param, SCENE_INFO *scene_info, void *refCon); @@ -302,6 +301,7 @@ class Scene { ObjectMap *_actionMap; ObjectMap *_objectMap; SceneEntryList _entryList; + StringsTable _sceneStrings; private: int IHNMStartProc(); diff --git a/saga/script.cpp b/saga/script.cpp index 81f7410e8a..f9a13f2475 100644 --- a/saga/script.cpp +++ b/saga/script.cpp @@ -577,7 +577,7 @@ void Script::showVerb() { verbName = _mainStrings.getString(_leftButtonVerb - 1); - if (objectIdType(_currentObject[0]) == kGameObjectNone) { + if (objectTypeId(_currentObject[0]) == kGameObjectNone) { _vm->_interface->setStatusText(verbName); return; } @@ -591,7 +591,7 @@ void Script::showVerb() { } - if (objectIdType(_currentObject[1]) != kGameObjectNone) { + if (objectTypeId(_currentObject[1]) != kGameObjectNone) { object2Name = _vm->getObjectName(_currentObject[1]); } else { object2Name = ""; @@ -638,7 +638,7 @@ void Script::setLeftButtonVerb(int verb) { } void Script::setRightButtonVerb(int verb) { - int oldVerb = _currentVerb; + int oldVerb = _rightButtonVerb; _rightButtonVerb = verb; @@ -658,8 +658,9 @@ void Script::doVerb() { EVENT event; const char *excuseText; int excuseSampleResourceId; + const HitZone *hitZone; - objectType = objectIdType(_pendingObject[0]); + objectType = objectTypeId(_pendingObject[0]); if (_pendingVerb == kVerbGive) { scriptEntrypointNumber = _vm->getObjectScriptEntrypointNumber(_pendingObject[1]); @@ -670,15 +671,19 @@ void Script::doVerb() { } } else { if (_pendingVerb == kVerbUse) { - if ((objectIdType(_pendingObject[1]) > kGameObjectNone) && (objectType < objectIdType(_pendingObject[1]))) { + if ((objectTypeId(_pendingObject[1]) > kGameObjectNone) && (objectType < objectTypeId(_pendingObject[1]))) { SWAP(_pendingObject[0], _pendingObject[1]); - objectType = objectIdType(_pendingObject[0]); + objectType = objectTypeId(_pendingObject[0]); } } if (objectType == kGameObjectHitZone) { scriptModuleNumber = _vm->_scene->getScriptModuleNumber(); - //TODO: check HitZone Exit + hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(_pendingObject[0])); + if ((hitZone->getFlags() & kHitZoneExit) == 0) { + scriptEntrypointNumber = hitZone->getScriptNumber(); + } + } else { if (objectType & (kGameObjectActor | kGameObjectObject)) { scriptEntrypointNumber = _vm->getObjectScriptEntrypointNumber(_pendingObject[0]); @@ -794,6 +799,7 @@ void Script::hitObject(bool leftButton) { void Script::playfieldClick(const Point& mousePoint, bool leftButton) { Location pickLocation; const HitZone *hitZone; + Point specialPoint; _vm->_actor->abortSpeech(); @@ -826,11 +832,11 @@ void Script::playfieldClick(const Point& mousePoint, bool leftButton) { hitZone = NULL; - if (objectIdType(_pendingObject[0]) == kGameObjectHitZone) { - // hitZone = _vm->_scene->_objectMap _pendingObject[0]; //TODO: + if (objectTypeId(_pendingObject[0]) == kGameObjectHitZone) { + hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(_pendingObject[0])); } else { - if ((_pendingVerb == kVerbUse) && (objectIdType(_pendingObject[1]) == kGameObjectHitZone)) { - // hitZone = _vm->_scene->_objectMap _pendingObject[1]; //TODO: + if ((_pendingVerb == kVerbUse) && (objectTypeId(_pendingObject[1]) == kGameObjectHitZone)) { + hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(_pendingObject[1])); } } @@ -842,7 +848,16 @@ void Script::playfieldClick(const Point& mousePoint, bool leftButton) { } if (hitZone->getFlags() & kHitZoneProject) { - //TODO: do it + if (!hitZone->getSpecialPoint(specialPoint)) { + error("Script::playfieldClick SpecialPoint not found"); + } + + // tiled stuff + if (_vm->_scene->getFlags() & kSceneFlagISO) { + //todo: it + } else { + pickLocation.fromScreenPoint(specialPoint); + } } } @@ -856,7 +871,7 @@ void Script::playfieldClick(const Point& mousePoint, bool leftButton) { break; case kVerbLookAt: - if (objectIdType(_pendingObject[0]) != kGameObjectActor ) { + if (objectTypeId(_pendingObject[0]) != kGameObjectActor ) { _vm->_actor->actorWalkTo(ID_PROTAG, pickLocation); } else { doVerb(); @@ -879,8 +894,8 @@ void Script::whichObject(const Point& mousePoint) { uint16 newObjectId; ActorData *actor; Location pickLocation; - int hitZoneId; - HitZone * hitZone; + int hitZoneIndex; + const HitZone * hitZone; objectId = ID_NOTHING; objectFlags = 0; @@ -892,7 +907,7 @@ void Script::whichObject(const Point& mousePoint) { newObjectId = _vm->_actor->testHit(mousePoint); if (newObjectId != ID_NOTHING) { - if (objectIdType(newObjectId) == kGameObjectObject) { + if (objectTypeId(newObjectId) == kGameObjectObject) { objectId = newObjectId; objectFlags = 0; newRightButtonVerb = kVerbLookAt; @@ -918,11 +933,7 @@ void Script::whichObject(const Point& mousePoint) { } } - if (newObjectId == ID_NOTHING) { -/* struct HitZone far *newZone = NULL; - UWORD zone;*/ - - + if (newObjectId == ID_NOTHING) { if (_vm->_scene->getFlags() & kSceneFlagISO) { //todo: it } else { @@ -931,11 +942,11 @@ void Script::whichObject(const Point& mousePoint) { pickLocation.z = 0; } - hitZoneId = _vm->_scene->_objectMap->hitTest(mousePoint); + hitZoneIndex = _vm->_scene->_objectMap->hitTest(mousePoint); - if ((hitZoneId != -1) && 0) { //TODO: do it - //hitZone = _vm->_scene->_objectMap->getZone(hitZoneId); - //objectId = hitZone->objectId; + if ((hitZoneIndex != -1)) { + hitZone = _vm->_scene->_objectMap->getHitZone(hitZoneIndex); + objectId = hitZone->getHitZoneId(); objectFlags = 0; newRightButtonVerb = hitZone->getRightButtonVerb() & 0x7f; |