aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--saga/actionmap.cpp159
-rw-r--r--saga/actionmap.h26
-rw-r--r--saga/actor.cpp33
-rw-r--r--saga/gfx.cpp25
-rw-r--r--saga/gfx.h2
-rw-r--r--saga/interface.cpp4
-rw-r--r--saga/objectmap.cpp30
-rw-r--r--saga/objectmap.h22
-rw-r--r--saga/saga.h5
-rw-r--r--saga/xref.txt11
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
=======