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
This commit is contained in:
Andrew Kurushin 2005-01-18 15:01:21 +00:00
parent c1ce30b0bf
commit b4b2e52df7
9 changed files with 111 additions and 140 deletions

View file

@ -276,9 +276,9 @@ public:
void cmdActorWalkTo(int argc, const char **argv); void cmdActorWalkTo(int argc, const char **argv);
bool validActorId(uint16 id) { return (id == 1) || ((id >= 0x2000) && (id < (0x2000 | _actorsCount))); } bool validActorId(uint16 id) { return (id == ID_PROTAG) || ((id > OBJECT_TYPE_MASK) && (id < objectIndexToId(kGameObjectActor, _actorsCount))); }
int actorIdToIndex(uint16 id) { return (id == 1 ) ? 0 : (id & ~0x2000); } int actorIdToIndex(uint16 id) { return (id == ID_PROTAG ) ? 0 : objectIdToIndex(id); }
uint16 actorIndexToId(int index) { return (index == 0 ) ? 1 : (index | 0x2000); } uint16 actorIndexToId(int index) { return (index == 0 ) ? ID_PROTAG : objectIndexToId(kGameObjectActor, index); }
int direct(int msec); int direct(int msec);
int drawActors(); int drawActors();

View file

@ -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 *Interface::verbHitTest(const Point& mousePoint) {
PanelButton *panelButton; PanelButton *panelButton;
Rect rect; Rect rect;

View file

@ -124,8 +124,6 @@ private:
PanelButton *verbHitTest(const Point& mousePoint); PanelButton *verbHitTest(const Point& mousePoint);
void handleCommandUpdate(SURFACE *ds, const Point& mousePoint); void handleCommandUpdate(SURFACE *ds, const Point& mousePoint);
void handleCommandClick(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 lockMode() { _lockedMode = _panelMode; }
void unlockMode() { _panelMode = _lockedMode; } void unlockMode() { _panelMode = _lockedMode; }

View file

@ -36,7 +36,7 @@
namespace Saga { namespace Saga {
HitZone::HitZone(MemoryReadStreamEndian *readStream) { HitZone::HitZone(MemoryReadStreamEndian *readStream, int index): _index(index) {
int i, j; int i, j;
HitZone::ClickArea *clickArea; HitZone::ClickArea *clickArea;
Point *point; Point *point;
@ -45,7 +45,7 @@ HitZone::HitZone(MemoryReadStreamEndian *readStream) {
_clickAreasCount = readStream->readByte(); _clickAreasCount = readStream->readByte();
_rightButtonVerb = readStream->readByte(); _rightButtonVerb = readStream->readByte();
readStream->readByte(); // pad readStream->readByte(); // pad
_nameNumber = readStream->readUint16(); _nameIndex = readStream->readUint16();
_scriptNumber = readStream->readUint16(); _scriptNumber = readStream->readUint16();
_clickAreas = (HitZone::ClickArea *)malloc(_clickAreasCount * sizeof(*_clickAreas)); _clickAreas = (HitZone::ClickArea *)malloc(_clickAreasCount * sizeof(*_clickAreas));
@ -80,6 +80,22 @@ HitZone::~HitZone() {
free(_clickAreas); 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) { bool HitZone::hitTest(const Point &testPoint) {
int i, pointsCount; int i, pointsCount;
HitZone::ClickArea *clickArea; HitZone::ClickArea *clickArea;
@ -157,7 +173,7 @@ void ObjectMap::load(const byte *resourcePointer, size_t resourceLength) {
} }
for (i = 0; i < _hitZoneListCount; i++) { for (i = 0; i < _hitZoneListCount; i++) {
_hitZoneList[i] = new HitZone(&readS); _hitZoneList[i] = new HitZone(&readS, i);
} }
} }

View file

@ -39,11 +39,14 @@ private:
}; };
public: public:
HitZone(MemoryReadStreamEndian *readStream); HitZone(MemoryReadStreamEndian *readStream, int index);
~HitZone(); ~HitZone();
int getNameIndex() const {
return _nameIndex;
}
int getSceneNumber() const { int getSceneNumber() const {
return _nameNumber; return _nameIndex;
} }
int getActorsEntrance() const { int getActorsEntrance() const {
return _scriptNumber; return _scriptNumber;
@ -60,14 +63,22 @@ public:
int getDirection() const { int getDirection() const {
return ((_flags >> 4) & 0xF); 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); void draw(SURFACE *ds, int color);
bool hitTest(const Point &testPoint); bool hitTest(const Point &testPoint);
private: private:
int _flags; // HitZoneFlags int _flags; // Saga::HitZoneFlags
int _clickAreasCount; int _clickAreasCount;
int _rightButtonVerb; int _rightButtonVerb;
int _nameNumber; int _nameIndex;
int _scriptNumber; int _scriptNumber;
int _index;
ClickArea *_clickAreas; ClickArea *_clickAreas;
}; };

View file

@ -51,6 +51,7 @@
#include "saga/sound.h" #include "saga/sound.h"
#include "saga/music.h" #include "saga/music.h"
#include "saga/palanim.h" #include "saga/palanim.h"
#include "saga/objectmap.h"
static const GameSettings saga_games[] = { static const GameSettings saga_games[] = {
{"ite", "Inherit the Earth", 0}, {"ite", "Inherit the Earth", 0},
@ -316,45 +317,46 @@ int SagaEngine::go() {
void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPointer, size_t stringsLength) { void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPointer, size_t stringsLength) {
uint16 stringsCount; uint16 stringsCount;
uint16 i;
size_t offset; size_t offset;
int i;
stringsTable.stringsPointer = (byte*)malloc(stringsLength); stringsTable.stringsPointer = (byte*)malloc(stringsLength);
memcpy(stringsTable.stringsPointer, stringsPointer, stringsLength); memcpy(stringsTable.stringsPointer, stringsPointer, stringsLength);
MemoryReadStreamEndian scriptS(stringsTable.stringsPointer, stringsLength, IS_BIG_ENDIAN); MemoryReadStreamEndian scriptS(stringsTable.stringsPointer, stringsLength, IS_BIG_ENDIAN);
offset = scriptS.readUint16(); offset = scriptS.readUint16();
if (offset > stringsLength) { stringsCount = offset / 2;
error("Invalid string offset"); stringsTable.strings = (const char **)malloc(stringsCount * sizeof(*stringsTable.strings));
} i = 0;
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");
}
scriptS.seek(0); scriptS.seek(0);
for (i = 0; i < stringsCount; i++) { while (i < stringsCount) {
offset = scriptS.readUint16(); offset = scriptS.readUint16();
if (offset == stringsLength) {
stringsCount = i;
stringsTable.strings = (const char **)realloc(stringsTable.strings, stringsCount * sizeof(*stringsTable.strings));
break;
}
if (offset > stringsLength) { if (offset > stringsLength) {
error("invalid string offset"); error("SagaEngine::loadStrings wrong strings table");
} }
stringsTable.strings[i] = (const char *)stringsTable.stringsPointer + offset; stringsTable.strings[i] = (const char *)stringsTable.stringsPointer + offset;
debug(9, "string[%i]=%s", i, stringsTable.strings[i]); debug(9, "string[%i]=%s", i, stringsTable.strings[i]);
i++;
} }
stringsTable.stringsCount = stringsCount;
} }
const char *SagaEngine::getObjectName(uint16 objectId) { const char *SagaEngine::getObjectName(uint16 objectId) {
const HitZone *hitZone;
switch (objectIdType(objectId)) { switch (objectTypeId(objectId)) {
case kGameObjectActor: case kGameObjectActor:
return _actor->getActorName(objectId); return _actor->getActorName(objectId);
break; break;
case kGameObjectHitZone:
hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(objectId));
return _vm->_scene->_sceneStrings.getString(hitZone->getNameIndex());
} }
//todo: object name & etc //todo: object name & etc
return NULL; return NULL;
@ -362,7 +364,7 @@ const char *SagaEngine::getObjectName(uint16 objectId) {
int SagaEngine::getObjectScriptEntrypointNumber(uint16 objectId) { int SagaEngine::getObjectScriptEntrypointNumber(uint16 objectId) {
ActorData *actor; ActorData *actor;
switch (objectIdType(objectId)) { switch (objectTypeId(objectId)) {
case kGameObjectActor: case kGameObjectActor:
actor = _vm->_actor->getActor(objectId); actor = _vm->_actor->getActor(objectId);
return actor->scriptEntrypointNumber; return actor->scriptEntrypointNumber;
@ -374,7 +376,7 @@ int SagaEngine::getObjectScriptEntrypointNumber(uint16 objectId) {
int SagaEngine::getObjectFlags(uint16 objectId) { int SagaEngine::getObjectFlags(uint16 objectId) {
ActorData *actor; ActorData *actor;
if (objectIdType(objectId) == kGameObjectActor) { if (objectTypeId(objectId) == kGameObjectActor) {
actor = _vm->_actor->getActor(objectId); actor = _vm->_actor->getActor(objectId);
return actor->flags; return actor->flags;
} }

View file

@ -72,6 +72,8 @@ class PalAnim;
#define ID_NOTHING 0 #define ID_NOTHING 0
#define ID_PROTAG 1 #define ID_PROTAG 1
#define OBJECT_TYPE_SHIFT 13
#define OBJECT_TYPE_MASK ((1 << OBJECT_TYPE_SHIFT) - 1)
struct RSCFILE_CONTEXT; struct RSCFILE_CONTEXT;
struct StringList; struct StringList;
@ -195,7 +197,7 @@ struct StringsTable {
const char **strings; const char **strings;
const char *getString(int index) const { const char *getString(int index) const {
if (stringsCount <= index) if ((stringsCount <= index) || (index < 0))
error("StringList::getString wrong index 0x%X", index); error("StringList::getString wrong index 0x%X", index);
return strings[index]; return strings[index];
} }
@ -393,10 +395,19 @@ inline int integerCompare(int i1, int i2) {
return ((i1) > (i2) ? 1 : ((i1) < (i2) ? -1 : 0)); return ((i1) > (i2) ? 1 : ((i1) < (i2) ? -1 : 0));
} }
inline int objectIdType(uint16 objectId) { inline int objectTypeId(uint16 objectId) {
return objectId >> 13; 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); DetectedGameList GAME_ProbeGame(const FSList &fslist);
class SagaEngine : public Engine { class SagaEngine : public Engine {

View file

@ -292,7 +292,6 @@ class Scene {
SCENE_IMAGE _bg; SCENE_IMAGE _bg;
SCENE_IMAGE _bgMask; SCENE_IMAGE _bgMask;
StringsTable _sceneStrings;
int _sceneDoors[SCENE_DOORS_MAX]; int _sceneDoors[SCENE_DOORS_MAX];
static int SC_defaultScene(int param, SCENE_INFO *scene_info, void *refCon); static int SC_defaultScene(int param, SCENE_INFO *scene_info, void *refCon);
@ -302,6 +301,7 @@ class Scene {
ObjectMap *_actionMap; ObjectMap *_actionMap;
ObjectMap *_objectMap; ObjectMap *_objectMap;
SceneEntryList _entryList; SceneEntryList _entryList;
StringsTable _sceneStrings;
private: private:
int IHNMStartProc(); int IHNMStartProc();

View file

@ -577,7 +577,7 @@ void Script::showVerb() {
verbName = _mainStrings.getString(_leftButtonVerb - 1); verbName = _mainStrings.getString(_leftButtonVerb - 1);
if (objectIdType(_currentObject[0]) == kGameObjectNone) { if (objectTypeId(_currentObject[0]) == kGameObjectNone) {
_vm->_interface->setStatusText(verbName); _vm->_interface->setStatusText(verbName);
return; return;
} }
@ -591,7 +591,7 @@ void Script::showVerb() {
} }
if (objectIdType(_currentObject[1]) != kGameObjectNone) { if (objectTypeId(_currentObject[1]) != kGameObjectNone) {
object2Name = _vm->getObjectName(_currentObject[1]); object2Name = _vm->getObjectName(_currentObject[1]);
} else { } else {
object2Name = ""; object2Name = "";
@ -638,7 +638,7 @@ void Script::setLeftButtonVerb(int verb) {
} }
void Script::setRightButtonVerb(int verb) { void Script::setRightButtonVerb(int verb) {
int oldVerb = _currentVerb; int oldVerb = _rightButtonVerb;
_rightButtonVerb = verb; _rightButtonVerb = verb;
@ -658,8 +658,9 @@ void Script::doVerb() {
EVENT event; EVENT event;
const char *excuseText; const char *excuseText;
int excuseSampleResourceId; int excuseSampleResourceId;
const HitZone *hitZone;
objectType = objectIdType(_pendingObject[0]); objectType = objectTypeId(_pendingObject[0]);
if (_pendingVerb == kVerbGive) { if (_pendingVerb == kVerbGive) {
scriptEntrypointNumber = _vm->getObjectScriptEntrypointNumber(_pendingObject[1]); scriptEntrypointNumber = _vm->getObjectScriptEntrypointNumber(_pendingObject[1]);
@ -670,15 +671,19 @@ void Script::doVerb() {
} }
} else { } else {
if (_pendingVerb == kVerbUse) { 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]); SWAP(_pendingObject[0], _pendingObject[1]);
objectType = objectIdType(_pendingObject[0]); objectType = objectTypeId(_pendingObject[0]);
} }
} }
if (objectType == kGameObjectHitZone) { if (objectType == kGameObjectHitZone) {
scriptModuleNumber = _vm->_scene->getScriptModuleNumber(); 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 { } else {
if (objectType & (kGameObjectActor | kGameObjectObject)) { if (objectType & (kGameObjectActor | kGameObjectObject)) {
scriptEntrypointNumber = _vm->getObjectScriptEntrypointNumber(_pendingObject[0]); scriptEntrypointNumber = _vm->getObjectScriptEntrypointNumber(_pendingObject[0]);
@ -794,6 +799,7 @@ void Script::hitObject(bool leftButton) {
void Script::playfieldClick(const Point& mousePoint, bool leftButton) { void Script::playfieldClick(const Point& mousePoint, bool leftButton) {
Location pickLocation; Location pickLocation;
const HitZone *hitZone; const HitZone *hitZone;
Point specialPoint;
_vm->_actor->abortSpeech(); _vm->_actor->abortSpeech();
@ -826,11 +832,11 @@ void Script::playfieldClick(const Point& mousePoint, bool leftButton) {
hitZone = NULL; hitZone = NULL;
if (objectIdType(_pendingObject[0]) == kGameObjectHitZone) { if (objectTypeId(_pendingObject[0]) == kGameObjectHitZone) {
// hitZone = _vm->_scene->_objectMap _pendingObject[0]; //TODO: hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(_pendingObject[0]));
} else { } else {
if ((_pendingVerb == kVerbUse) && (objectIdType(_pendingObject[1]) == kGameObjectHitZone)) { if ((_pendingVerb == kVerbUse) && (objectTypeId(_pendingObject[1]) == kGameObjectHitZone)) {
// hitZone = _vm->_scene->_objectMap _pendingObject[1]; //TODO: hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(_pendingObject[1]));
} }
} }
@ -842,7 +848,16 @@ void Script::playfieldClick(const Point& mousePoint, bool leftButton) {
} }
if (hitZone->getFlags() & kHitZoneProject) { 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; break;
case kVerbLookAt: case kVerbLookAt:
if (objectIdType(_pendingObject[0]) != kGameObjectActor ) { if (objectTypeId(_pendingObject[0]) != kGameObjectActor ) {
_vm->_actor->actorWalkTo(ID_PROTAG, pickLocation); _vm->_actor->actorWalkTo(ID_PROTAG, pickLocation);
} else { } else {
doVerb(); doVerb();
@ -879,8 +894,8 @@ void Script::whichObject(const Point& mousePoint) {
uint16 newObjectId; uint16 newObjectId;
ActorData *actor; ActorData *actor;
Location pickLocation; Location pickLocation;
int hitZoneId; int hitZoneIndex;
HitZone * hitZone; const HitZone * hitZone;
objectId = ID_NOTHING; objectId = ID_NOTHING;
objectFlags = 0; objectFlags = 0;
@ -892,7 +907,7 @@ void Script::whichObject(const Point& mousePoint) {
newObjectId = _vm->_actor->testHit(mousePoint); newObjectId = _vm->_actor->testHit(mousePoint);
if (newObjectId != ID_NOTHING) { if (newObjectId != ID_NOTHING) {
if (objectIdType(newObjectId) == kGameObjectObject) { if (objectTypeId(newObjectId) == kGameObjectObject) {
objectId = newObjectId; objectId = newObjectId;
objectFlags = 0; objectFlags = 0;
newRightButtonVerb = kVerbLookAt; newRightButtonVerb = kVerbLookAt;
@ -918,11 +933,7 @@ void Script::whichObject(const Point& mousePoint) {
} }
} }
if (newObjectId == ID_NOTHING) { if (newObjectId == ID_NOTHING) {
/* struct HitZone far *newZone = NULL;
UWORD zone;*/
if (_vm->_scene->getFlags() & kSceneFlagISO) { if (_vm->_scene->getFlags() & kSceneFlagISO) {
//todo: it //todo: it
} else { } else {
@ -931,11 +942,11 @@ void Script::whichObject(const Point& mousePoint) {
pickLocation.z = 0; pickLocation.z = 0;
} }
hitZoneId = _vm->_scene->_objectMap->hitTest(mousePoint); hitZoneIndex = _vm->_scene->_objectMap->hitTest(mousePoint);
if ((hitZoneId != -1) && 0) { //TODO: do it if ((hitZoneIndex != -1)) {
//hitZone = _vm->_scene->_objectMap->getZone(hitZoneId); hitZone = _vm->_scene->_objectMap->getHitZone(hitZoneIndex);
//objectId = hitZone->objectId; objectId = hitZone->getHitZoneId();
objectFlags = 0; objectFlags = 0;
newRightButtonVerb = hitZone->getRightButtonVerb() & 0x7f; newRightButtonVerb = hitZone->getRightButtonVerb() & 0x7f;