aboutsummaryrefslogtreecommitdiff
path: root/saga
diff options
context:
space:
mode:
authorAndrew Kurushin2005-01-18 15:01:21 +0000
committerAndrew Kurushin2005-01-18 15:01:21 +0000
commitb4b2e52df78fd309613d8df73f090b98e834969b (patch)
tree7e79ad73fbb11d0755e2c3e4926d99ab3653bb95 /saga
parentc1ce30b0bfa69aee3c91602536da8d2c5fa72e8b (diff)
downloadscummvm-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.h6
-rw-r--r--saga/interface.cpp78
-rw-r--r--saga/interface.h2
-rw-r--r--saga/objectmap.cpp22
-rw-r--r--saga/objectmap.h21
-rw-r--r--saga/saga.cpp42
-rw-r--r--saga/saga.h17
-rw-r--r--saga/scene.h2
-rw-r--r--saga/script.cpp61
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;