diff options
author | Eugene Sandulenko | 2004-10-08 01:22:39 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2004-10-08 01:22:39 +0000 |
commit | 94d9a2149b8b757ed36cb0f315cd281d1447d1a0 (patch) | |
tree | a01681619e95b1125ec5488176c75a8b1329b9cd /saga | |
parent | 0850dbdaf2ad79cf296f79a001b4b60e82f481cd (diff) | |
download | scummvm-rg350-94d9a2149b8b757ed36cb0f315cd281d1447d1a0.tar.gz scummvm-rg350-94d9a2149b8b757ed36cb0f315cd281d1447d1a0.tar.bz2 scummvm-rg350-94d9a2149b8b757ed36cb0f315cd281d1447d1a0.zip |
Implement scene change via exits. You still cannot leave first scene
because it goes to now buggy isometric level. Use debugger to switch
to some word, say, in Dog Castle and there you may go between rooms.
svn-id: r15462
Diffstat (limited to 'saga')
-rw-r--r-- | saga/actionmap.cpp | 159 | ||||
-rw-r--r-- | saga/actionmap.h | 26 | ||||
-rw-r--r-- | saga/actor.cpp | 33 | ||||
-rw-r--r-- | saga/gfx.cpp | 25 | ||||
-rw-r--r-- | saga/gfx.h | 2 | ||||
-rw-r--r-- | saga/interface.cpp | 4 | ||||
-rw-r--r-- | saga/objectmap.cpp | 30 | ||||
-rw-r--r-- | saga/objectmap.h | 22 | ||||
-rw-r--r-- | saga/saga.h | 5 | ||||
-rw-r--r-- | saga/xref.txt | 11 |
10 files changed, 201 insertions, 116 deletions
diff --git a/saga/actionmap.cpp b/saga/actionmap.cpp index b3e647f0e0..613aa5e0b1 100644 --- a/saga/actionmap.cpp +++ b/saga/actionmap.cpp @@ -35,112 +35,157 @@ namespace Saga { ActionMap::ActionMap(SagaEngine *vm, const byte * exmap_res, size_t exmap_res_len) : _vm(vm) { // Loads exit map data from specified exit map resource R_ACTIONMAP_ENTRY *exmap_entry; - Point *exmap_pt_tbl; - - int exit_ct; - int i, pt; + R_CLICKAREA *clickarea; + Point *point; assert(exmap_res != NULL); MemoryReadStream readS(exmap_res, exmap_res_len); // Load exits - exit_ct = readS.readSint16LE(); - if (exit_ct < 0) { + _nExits = readS.readSint16LE(); + if (_nExits < 0) { return; } - exmap_entry = (R_ACTIONMAP_ENTRY *)malloc(exit_ct * sizeof *exmap_entry); - if (exmap_entry == NULL) { + _exitsTbl = (R_ACTIONMAP_ENTRY *)malloc(_nExits * sizeof *_exitsTbl); + if (_exitsTbl == NULL) { warning("Memory allocation failure"); return; } - for (i = 0; i < exit_ct; i++) { - exmap_entry[i].unknown00 = readS.readSint16LE(); - exmap_entry[i].unknown02 = readS.readSint16LE(); - exmap_entry[i].exitScene = readS.readSint16LE(); - exmap_entry[i].unknown06 = readS.readSint16LE(); + for (int i = 0; i < _nExits; i++) { + exmap_entry = &_exitsTbl[i]; + exmap_entry->flags = readS.readByte(); + exmap_entry->nClickareas = readS.readByte(); + exmap_entry->defaultVerb = readS.readByte(); + readS.readByte(); + exmap_entry->exitScene = readS.readUint16LE(); + exmap_entry->entranceNum = readS.readUint16LE(); - exmap_entry[i].pt_count = readS.readSint16LE(); - if (exmap_entry[i].pt_count < 0) { - free(exmap_entry); - return; - } + exmap_entry->clickareas = (R_CLICKAREA *)malloc(exmap_entry->nClickareas * sizeof *(exmap_entry->clickareas)); - exmap_pt_tbl = (Point *)malloc(exmap_entry[i].pt_count * sizeof *exmap_pt_tbl); - if (exmap_pt_tbl == NULL) { - warning("Memory allocation failure"); + if (exmap_entry->clickareas == NULL) { + warning("Error: Memory allocation failed"); return; } - for (pt = 0; pt < exmap_entry[i].pt_count; pt++) { - exmap_pt_tbl[pt].x = readS.readSint16LE(); - exmap_pt_tbl[pt].y = readS.readSint16LE(); + // Load all clickareas for this object + for (int k = 0; k < exmap_entry->nClickareas; k++) { + clickarea = &exmap_entry->clickareas[k]; + clickarea->n_points = readS.readUint16LE(); + assert(clickarea->n_points != 0); + + clickarea->points = (Point *)malloc(clickarea->n_points * sizeof *(clickarea->points)); + if (clickarea->points == NULL) { + warning("Error: Memory allocation failed"); + return; + } + + // Load all points for this clickarea + for (int m = 0; m < clickarea->n_points; m++) { + point = &clickarea->points[m]; + point->x = readS.readSint16LE(); + point->y = readS.readSint16LE(); + } } - - exmap_entry[i].pt_tbl = exmap_pt_tbl; } - - _nExits = exit_ct; - _exitsTbl = exmap_entry; } ActionMap::~ActionMap(void) { // Frees the currently loaded exit map data R_ACTIONMAP_ENTRY *exmap_entry; + R_CLICKAREA *clickarea; int i; if (_exitsTbl) { for (i = 0; i < _nExits; i++) { exmap_entry = &_exitsTbl[i]; - if (exmap_entry != NULL) - free(exmap_entry->pt_tbl); + for (int k = 0; k < exmap_entry->nClickareas; k++) { + clickarea = &exmap_entry->clickareas[k]; + free(clickarea->points); + } + free(exmap_entry->clickareas); } free(_exitsTbl); } } -int ActionMap::draw(R_SURFACE *ds, int color) { - int i; +const int ActionMap::getExitScene(int exitNum) { + assert(exitNum < _nExits); + return _exitsTbl[exitNum].exitScene; +} + + +int ActionMap::hitTest(Point imouse) { + R_ACTIONMAP_ENTRY *exmap_entry; + R_CLICKAREA *clickarea; + Point *points; + int n_points; + + int i, k; + + // Loop through all scene objects for (i = 0; i < _nExits; i++) { - if (_exitsTbl[i].pt_count == 2) { - _vm->_gfx->drawFrame(ds, - &_exitsTbl[i].pt_tbl[0], - &_exitsTbl[i].pt_tbl[1], color); - } else if (_exitsTbl[i].pt_count > 2) { - _vm->_gfx->drawPolyLine(ds, _exitsTbl[i].pt_tbl, - _exitsTbl[i].pt_count, color); + exmap_entry = &_exitsTbl[i]; + + // Hit-test all clickareas for this object + for (k = 0; k < exmap_entry->nClickareas; k++) { + clickarea = &exmap_entry->clickareas[k]; + n_points = clickarea->n_points; + points = clickarea->points; + + if (n_points == 2) { + // Hit-test a box region + if ((imouse.x > points[0].x) && (imouse.x <= points[1].x) && + (imouse.y > points[0].y) && + (imouse.y <= points[1].y)) { + return i; + } + } else if (n_points > 2) { + // Hit-test a polygon + if (_vm->_gfx->hitTestPoly(points, n_points, imouse)) { + return i; + } + } } } - return R_SUCCESS; + return -1; } -void ActionMap::info(void) { - Point *pt; - - int i; - int pt_i; +int ActionMap::draw(R_SURFACE *ds, int color) { + R_ACTIONMAP_ENTRY *exmap_entry; + R_CLICKAREA *clickarea; - _vm->_console->print("%d exits loaded.\n", _nExits); + int i, k; for (i = 0; i < _nExits; i++) { - _vm->_console->print ("Action %d: Exit to: %d; Pts: %d; Unk0: %d Unk2: %d Scr_N: %d", - i, _exitsTbl[i].exitScene, - _exitsTbl[i].pt_count, - _exitsTbl[i].unknown00, - _exitsTbl[i].unknown02, - _exitsTbl[i].unknown06); + exmap_entry = &_exitsTbl[i]; + + for (k = 0; k < exmap_entry->nClickareas; k++) { + clickarea = &exmap_entry->clickareas[k]; + if (clickarea->n_points == 2) { + // 2 points represent a box + _vm->_gfx->drawFrame(ds, &clickarea->points[0], &clickarea->points[1], color); + } else if (clickarea->n_points > 2) { + // Otherwise draw a polyline + _vm->_gfx->drawPolyLine(ds, clickarea->points, clickarea->n_points, color); + } + } + } - for (pt_i = 0; pt_i < _exitsTbl[i].pt_count; pt_i++) { - pt = &_exitsTbl[i].pt_tbl[pt_i]; + return R_SUCCESS; +} - _vm->_console->print(" pt: %d (%d, %d)", pt_i, pt->x, pt->y); - } +void ActionMap::info(void) { + _vm->_console->print("%d exits loaded.\n", _nExits); + + for (int i = 0; i < _nExits; i++) { + _vm->_console->print ("Action %d: Exit to: %d", i, _exitsTbl[i].exitScene); } } diff --git a/saga/actionmap.h b/saga/actionmap.h index 594ce24006..f9b3e643e2 100644 --- a/saga/actionmap.h +++ b/saga/actionmap.h @@ -28,14 +28,28 @@ namespace Saga { +enum ACTION_FLAGS { + ACTION_ENABLED = (1<<0), // Zone is enabled + ACTION_EXIT = (1<<1), // Causes char to exit + + // The following flag causes the zone to act differently. + // When the actor hits the zone, it will immediately begin walking + // in the specified direction, and the actual specified effect of + // the zone will be delayed until the actor leaves the zone. + ACTION_AUTOWALK = (1<<2), + + // zone activates only when character stops walking + ACTION_TERMINUS = (1<<3) +}; + struct R_ACTIONMAP_ENTRY { - int unknown00; - int unknown02; + int flags; + int nClickareas; + int defaultVerb; int exitScene; - int unknown06; + int entranceNum; - int pt_count; - Point *pt_tbl; + R_CLICKAREA *clickareas; }; class ActionMap { @@ -44,6 +58,8 @@ class ActionMap { ActionMap(SagaEngine *vm, const byte *exmap_res, size_t exmap_res_len); ~ActionMap(void); + const int getExitScene(int exitNum); + int hitTest(Point imousePt); int draw(R_SURFACE *ds, int color); void info(void); diff --git a/saga/actor.cpp b/saga/actor.cpp index 94793ac5e1..8afafdc3b2 100644 --- a/saga/actor.cpp +++ b/saga/actor.cpp @@ -35,6 +35,8 @@ #include "saga/font.h" #include "saga/text.h" #include "saga/sound.h" +#include "saga/scene.h" +#include "saga/actionmap.h" #include "saga/actor.h" #include "saga/actordata.h" @@ -908,19 +910,28 @@ int Actor::handleWalkIntent(R_ACTOR *actor, R_WALKINTENT *a_walkint, int *comple if (((a_walkint->x_dir == 1) && new_a_x >= node_p->node_pt.x) || ((a_walkint->x_dir != 1) && (new_a_x <= node_p->node_pt.x))) { - debug(2, "Path complete."); - ys_dll_delete(walk_p); - a_walkint->wi_active = 0; + Point endpoint; + int exitNum; - // Release path semaphore - if (a_walkint->sem != NULL) { - _vm->_script->SThreadReleaseSem(a_walkint->sem); - } + debug(2, "Path complete."); + ys_dll_delete(walk_p); + a_walkint->wi_active = 0; - actor->action_frame = 0; - actor->action = ACTION_IDLE; - *complete_p = 1; - return R_FAILURE; + // Release path semaphore + if (a_walkint->sem != NULL) { + _vm->_script->SThreadReleaseSem(a_walkint->sem); + } + + actor->action_frame = 0; + actor->action = ACTION_IDLE; + + endpoint.x = (int)new_a_x / R_ACTOR_LMULT; + endpoint.y = (int)new_a_y / R_ACTOR_LMULT; + if ((exitNum = _vm->_scene->_actionMap->hitTest(endpoint)) != -1) { + _vm->_scene->changeScene(_vm->_scene->_actionMap->getExitScene(exitNum)); + } + *complete_p = 1; + return R_FAILURE; } actor_x = (int)new_a_x; diff --git a/saga/gfx.cpp b/saga/gfx.cpp index 78712dc485..978cfc29e6 100644 --- a/saga/gfx.cpp +++ b/saga/gfx.cpp @@ -1076,4 +1076,29 @@ void Gfx::setCursor(int best_white) { _system->setMouseCursor(cursor_img, R_CURSOR_W, R_CURSOR_H, 4, 4, keycolor); } +bool Gfx::hitTestPoly(Point *points, unsigned int npoints, Point test_point) { + int yflag0; + int yflag1; + bool inside_flag = false; + unsigned int pt; + + Point *vtx0 = &points[npoints - 1]; + Point *vtx1 = &points[0]; + + yflag0 = (vtx0->y >= test_point.y); + for (pt = 0; pt < npoints; pt++, vtx1++) { + yflag1 = (vtx1->y >= test_point.y); + if (yflag0 != yflag1) { + if (((vtx1->y - test_point.y) * (vtx0->x - vtx1->x) >= + (vtx1->x - test_point.x) * (vtx0->y - vtx1->y)) == yflag1) { + inside_flag = !inside_flag; + } + } + yflag0 = yflag1; + vtx0 = vtx1; + } + + return inside_flag; +} + } // End of namespace Saga diff --git a/saga/gfx.h b/saga/gfx.h index 24247a3507..e70b0c077d 100644 --- a/saga/gfx.h +++ b/saga/gfx.h @@ -107,6 +107,8 @@ public: int getCurrentPal(PALENTRY *src_pal); int palToBlack(R_SURFACE *surface, PALENTRY *src_pal, double percent); int blackToPal(R_SURFACE *surface, PALENTRY *src_pal, double percent); + bool hitTestPoly(Point *points, unsigned int npoints, Point test_point); + private: void setCursor(int best_white); int _init; diff --git a/saga/interface.cpp b/saga/interface.cpp index 9abfc01de2..3d999658f3 100644 --- a/saga/interface.cpp +++ b/saga/interface.cpp @@ -492,7 +492,7 @@ int Interface::handlePlayfieldClick(R_SURFACE *ds, Point imousePt) { object_flags = _vm->_scene->_objectMap->getFlags(objectNum); - if (object_flags & R_OBJECT_NORMAL) { + if (object_flags & OBJECT_EXIT) { // FIXME. This is wrong if ((script_num = _vm->_scene->_objectMap->getEPNum(objectNum)) != -1) { // Set active verb in script module _vm->_sdata->putWord(4, 4, I_VerbData[_activeVerb].s_verb); @@ -532,7 +532,7 @@ int Interface::handlePlayfieldUpdate(R_SURFACE *ds, Point imousePt) { object_name = _vm->_scene->_objectMap->getName(objectNum); - if (object_flags & R_OBJECT_NORMAL) { + if (object_flags & OBJECT_EXIT) { // FIXME. This is wrong // Normal scene object - display as subject of verb snprintf(new_status, R_STATUS_TEXT_LEN, "%s %s", I_VerbData[_activeVerb].verb_str, object_name); } else { diff --git a/saga/objectmap.cpp b/saga/objectmap.cpp index 47a20ee175..7f943577f9 100644 --- a/saga/objectmap.cpp +++ b/saga/objectmap.cpp @@ -214,7 +214,6 @@ const uint16 ObjectMap::getFlags(int object) { int i; assert(_namesLoaded); - debug(0, "object: %d nnames: %d", object, _nNames); assert((object > 0) && (object <= _nNames)); for (i = 0; i < _nObjects; i++) { @@ -259,7 +258,6 @@ int ObjectMap::draw(R_SURFACE *ds, Point imousePt, int color, int color2) { bool hitObject = false; int objectNum = 0; - int pointcount = 0; int i, k; if (!_objectsLoaded) { @@ -285,7 +283,6 @@ int ObjectMap::draw(R_SURFACE *ds, Point imousePt, int color, int color2) { for (k = 0; k < object_map->nClickareas; k++) { clickarea = &object_map->clickareas[k]; - pointcount = 0; if (clickarea->n_points == 2) { // 2 points represent a box _vm->_gfx->drawFrame(ds, &clickarea->points[0], &clickarea->points[1], draw_color); @@ -304,31 +301,6 @@ int ObjectMap::draw(R_SURFACE *ds, Point imousePt, int color, int color2) { return R_SUCCESS; } -static bool MATH_HitTestPoly(Point *points, unsigned int npoints, Point test_point) { - int yflag0; - int yflag1; - bool inside_flag = false; - unsigned int pt; - - Point *vtx0 = &points[npoints - 1]; - Point *vtx1 = &points[0]; - - yflag0 = (vtx0->y >= test_point.y); - for (pt = 0; pt < npoints; pt++, vtx1++) { - yflag1 = (vtx1->y >= test_point.y); - if (yflag0 != yflag1) { - if (((vtx1->y - test_point.y) * (vtx0->x - vtx1->x) >= - (vtx1->x - test_point.x) * (vtx0->y - vtx1->y)) == yflag1) { - inside_flag = !inside_flag; - } - } - yflag0 = yflag1; - vtx0 = vtx1; - } - - return inside_flag; -} - int ObjectMap::hitTest(Point imousePt) { Point imouse; R_OBJECTMAP_ENTRY *object_map; @@ -360,7 +332,7 @@ int ObjectMap::hitTest(Point imousePt) { } } else if (n_points > 2) { // Hit-test a polygon - if (MATH_HitTestPoly(points, n_points, imouse)) { + if (_vm->_gfx->hitTestPoly(points, n_points, imouse)) { return object_map->objectNum; } } diff --git a/saga/objectmap.h b/saga/objectmap.h index cdeaa2823f..dff64993b6 100644 --- a/saga/objectmap.h +++ b/saga/objectmap.h @@ -28,14 +28,18 @@ namespace Saga { -enum R_OBJECT_FLAGS { - R_OBJECT_EXIT = 0x01, - R_OBJECT_NORMAL = 0x02 -}; - -struct R_CLICKAREA { - int n_points; - Point *points; +enum OBJECT_FLAGS { + OBJECT_ENABLED = (1<<0), // Object is enabled + OBJECT_EXIT = (1<<1), // Causes char to exit + + // Causes the character not to walk to the object (but they will + // look at it). + OBJECT_NOWALK = (1<<2), + + // When the object is clicked on it projects the + // click point downwards from the middle of the object until it + // reaches the lowest point in the zone. + OBJECT_PROJECT = (1<<3) }; struct R_OBJECTMAP_ENTRY { @@ -49,8 +53,6 @@ struct R_OBJECTMAP_ENTRY { R_CLICKAREA *clickareas; }; -class Gfx; - class ObjectMap{ public: int reg(void); diff --git a/saga/saga.h b/saga/saga.h index d5c906917c..e1fd36763e 100644 --- a/saga/saga.h +++ b/saga/saga.h @@ -78,6 +78,11 @@ enum SAGAGameId { GID_IHNM }; +struct R_CLICKAREA { + int n_points; + Point *points; +}; + class SagaEngine : public Engine { void errorString(const char *buf_input, char *buf_output); diff --git a/saga/xref.txt b/saga/xref.txt index 4668e3a067..4a26f4a2d3 100644 --- a/saga/xref.txt +++ b/saga/xref.txt @@ -35,8 +35,15 @@ Sceneres.h LOADREQ_FACES SAGA_FACES LOADREQ_PALETTE - HZONE_EXIT R_OBJECT_EXIT - HZONEF_AUTOWALK R_OBJECT_NORMAL + hitZone ObjectMap + stepZone ActionMap + + HZONEF_EXIT OBJECT_EXIT (in Verb.c), ACTION_EXIT (in Actor.c) + HZONEF_ENABLED OBJECT_ENABLED (in Verb.c), ACTION_ENABLED (in Actor.c) + HZONEF_NOWALK OBJECT_NOWALK + HZONEF_PROJECT OBJECT_PROJECT + HZONEF_AUTOWALK ACTION_AUTOWALK + HZONEF_TERMINUS ACTION_TERMINUS Scene.c ======= |