- remove old stuff

- work on "walking" in progress

svn-id: r16298
This commit is contained in:
Andrew Kurushin 2004-12-24 20:44:39 +00:00
parent f0bc27f11c
commit 2289ea371b
15 changed files with 350 additions and 744 deletions

View File

@ -32,125 +32,60 @@
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
ACTIONMAP_ENTRY *exmap_entry;
CLICKAREA *clickarea;
Point *point;
assert(exmap_res != NULL);
MemoryReadStreamEndian readS(exmap_res, exmap_res_len, IS_BIG_ENDIAN);
// Load exits
_nExits = readS.readSint16();
if (_nExits < 0) {
return;
}
_exitsTbl = (ACTIONMAP_ENTRY *)malloc(_nExits * sizeof *_exitsTbl);
if (_exitsTbl == NULL) {
warning("Memory allocation failure");
return;
}
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.readUint16();
exmap_entry->entranceNum = readS.readUint16();
exmap_entry->clickareas = (CLICKAREA *)malloc(exmap_entry->nClickareas * sizeof *(exmap_entry->clickareas));
if (exmap_entry->clickareas == NULL) {
warning("Error: Memory allocation failed");
return;
}
// Load all clickareas for this object
for (int k = 0; k < exmap_entry->nClickareas; k++) {
clickarea = &exmap_entry->clickareas[k];
clickarea->n_points = readS.readUint16();
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.readSint16();
point->y = readS.readSint16();
}
}
}
}
ActionMap::~ActionMap(void) {
// Frees the currently loaded exit map data
ACTIONMAP_ENTRY *exmap_entry;
CLICKAREA *clickarea;
void ActionMap::load(const byte *resourcePointer, size_t resourceLength) {
int i;
if (_exitsTbl) {
for (i = 0; i < _nExits; i++) {
exmap_entry = &_exitsTbl[i];
if (resourceLength < 4) {
error("ActionMap::load wrong resourceLength");
}
for (int k = 0; k < exmap_entry->nClickareas; k++) {
clickarea = &exmap_entry->clickareas[k];
free(clickarea->points);
}
free(exmap_entry->clickareas);
}
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
free(_exitsTbl);
_stepZoneListCount = readS.readSint16();
if (_stepZoneListCount < 0) {
error("ActionMap::load _stepZoneListCount < 0");
}
if (_stepZoneList)
error("ActionMap::load _stepZoneList != NULL");
_stepZoneList = (HitZone **) malloc(_stepZoneListCount * sizeof (HitZone *));
if (_stepZoneList == NULL) {
error("ActionMap::load Memory allocation failure");
}
for (i = 0; i < _stepZoneListCount; i++) {
_stepZoneList[i] = new HitZone(&readS);
}
}
const int ActionMap::getExitScene(int exitNum) {
assert(exitNum < _nExits);
void ActionMap::freeMem() {
int i;
return _exitsTbl[exitNum].exitScene;
if (_stepZoneList) {
for (i = 0; i < _stepZoneListCount; i++) {
delete _stepZoneList[i];
}
free(_stepZoneList);
}
}
int ActionMap::getExitSceneNumber(int index) const {
if (index >= _stepZoneListCount)
error("ActionMap::getExitSceneNumber wrong index");
int ActionMap::hitTest(const Point& imouse) {
ACTIONMAP_ENTRY *exmap_entry;
CLICKAREA *clickarea;
Point *points;
int n_points;
return _stepZoneList[index]->getSceneNumber();
}
int i, k;
int ActionMap::hitTest(const Point &testPoint) {
int i;
// Loop through all scene objects
for (i = 0; i < _nExits; i++) {
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 (hitTestPoly(points, n_points, imouse)) {
return i;
}
}
for (i = 0; i < _stepZoneListCount; i++) {
if (_stepZoneList[i]->hitTest(testPoint)) {
return i;
}
}
@ -158,34 +93,20 @@ int ActionMap::hitTest(const Point& imouse) {
}
int ActionMap::draw(SURFACE *ds, int color) {
ACTIONMAP_ENTRY *exmap_entry;
CLICKAREA *clickarea;
int i;
int i, k;
for (i = 0; i < _nExits; i++) {
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
drawFrame(ds, &clickarea->points[0], &clickarea->points[1], color);
} else if (clickarea->n_points > 2) {
// Otherwise draw a polyline
drawPolyLine(ds, clickarea->points, clickarea->n_points, color);
}
}
for (i = 0; i < _stepZoneListCount; i++) {
_stepZoneList[i]->draw(ds, color);
}
return SUCCESS;
}
void ActionMap::info(void) {
_vm->_console->DebugPrintf("%d exits loaded.\n\n", _nExits);
void ActionMap::cmdInfo() {
_vm->_console->DebugPrintf("%d step zone(s) loaded.\n\n", _stepZoneListCount);
for (int i = 0; i < _nExits; i++) {
_vm->_console->DebugPrintf("Action %d: Exit to: %d\n", i, _exitsTbl[i].exitScene);
for (int i = 0; i < _stepZoneListCount; i++) {
_vm->_console->DebugPrintf("StepZone %d: Exit to Scene number: %d\n", i, _stepZoneList[i]->getSceneNumber());
}
}

View File

@ -26,49 +26,35 @@
#ifndef SAGA_ACTIONMAP_H_
#define SAGA_ACTIONMAP_H_
#include "saga/objectmap.h"
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 ACTIONMAP_ENTRY {
int flags;
int nClickareas;
int defaultVerb;
int exitScene;
int entranceNum;
CLICKAREA *clickareas;
};
class ActionMap {
public:
int reg(void);
ActionMap(SagaEngine *vm, const byte *exmap_res, size_t exmap_res_len);
~ActionMap(void);
ActionMap(SagaEngine *vm): _vm(vm) {
_stepZoneList = NULL;
_stepZoneListCount = 0;
}
~ActionMap(void) {
freeMem();
}
void load(const byte *resourcePointer, size_t resourceLength);
void freeMem();
const int getExitScene(int exitNum);
int hitTest(const Point& imousePt);
int getExitSceneNumber(int index) const;
int hitTest(const Point &testPoint);
int draw(SURFACE *ds, int color);
void info(void);
void cmdInfo();
private:
SagaEngine *_vm;
int _nExits;
ACTIONMAP_ENTRY *_exitsTbl;
int _stepZoneListCount;
HitZone **_stepZoneList;
};
} // End of namespace Saga

View File

@ -53,11 +53,6 @@ static int actorCompare(const ActorDataPointer& actor1, const ActorDataPointer&
}
}
ACTIONTIMES ActionTDeltas[] = {
{ ACTION_IDLE, 80 },
{ ACTION_WALK, 80 },
{ ACTION_SPEAK, 200 }
};
// Lookup table to convert 8 cardinal directions to 4
int ActorDirectectionsLUT[8] = {
@ -495,74 +490,6 @@ void Actor::handleActions(int msec, bool setup) {
}
int Actor::direct(int msec) {
/* int i;
ActorData *actor;
ActorIntentList::iterator actorIntentIterator;
ACTORINTENT *a_intent;
int o_idx;
int action_tdelta;
// Walk down the actor list and direct each actor
for (i = 0; i < ACTORCOUNT; i++) {
actor = &_actors[i];
if (actor->disabled) continue;
// Process the actor intent list
actorIntentIterator = actor->a_intentlist.begin();
if (actorIntentIterator != actor->a_intentlist.end()) {
a_intent = actorIntentIterator.operator->();
switch (a_intent->a_itype) {
case INTENT_NONE:
// Actor doesn't really feel like doing anything at all
break;
case INTENT_PATH:
// Actor intends to go somewhere. Well good for him
{
handleWalkIntent(actor, &a_intent->walkIntent, &a_intent->a_idone, msec);
}
break;
default:
break;
}
// If this actor intent was flagged as completed, remove it.
if (a_intent->a_idone) {
actor->a_intentlist.erase(actorIntentIterator);
actor->action = actor->def_action;
actor->action_flags = actor->def_action_flags;
actor->action_frame = 0;
actor->action_time = 0;
}
} else {
// Actor has no intent, idle?
}
// Process actor actions
actor->action_time += msec;
if (actor->action >= ACTION_COUNT) {
action_tdelta = ACTOR_ACTIONTIME;
} else {
action_tdelta = ActionTDeltas[actor->action].time;
}
if (actor->action_time >= action_tdelta) {
actor->action_time -= action_tdelta;
actor->action_frame++;
o_idx = ActorOrientationLUT[actor->orient];
if (actor->frames[actor->action].dir[o_idx].frameCount <= actor->action_frame) {
if (actor->action_flags & ACTION_LOOP) {
actor->action_frame = 0;
} else {
actor->action_frame--;
}
}
}
}
*/
// FIXME: HACK. This should be turned into cycle event.
_lastTickMsec += msec;
@ -591,26 +518,31 @@ void Actor::createDrawOrderList() {
_drawOrderList.pushBack(actor, actorCompare);
middle = ITE_STATUS_Y - actor->location.y / ACTOR_LMULT,
_vm->_scene->getSlopes(beginSlope, endSlope);
actor->screenDepth = (14 * middle) / endSlope + 1;
if (middle <= beginSlope) {
actor->screenScale = 256;
} else {
if (middle >= endSlope) {
actor->screenScale = 1;
} else {
middle -= beginSlope;
endSlope -= beginSlope;
actor->screenScale = 256 - (middle * 256) / endSlope;
}
// tiled stuff
{
}
{
middle = ITE_STATUS_Y - actor->location.y / ACTOR_LMULT,
actor->screenPosition.x = (actor->location.x / ACTOR_LMULT);
actor->screenPosition.y = (actor->location.y / ACTOR_LMULT) - actor->location.z;
_vm->_scene->getSlopes(beginSlope, endSlope);
actor->screenDepth = (14 * middle) / endSlope + 1;
if (middle <= beginSlope) {
actor->screenScale = 256;
} else {
if (middle >= endSlope) {
actor->screenScale = 1;
} else {
middle -= beginSlope;
endSlope -= beginSlope;
actor->screenScale = 256 - (middle * 256) / endSlope;
}
}
actor->screenPosition.x = (actor->location.x / ACTOR_LMULT);
actor->screenPosition.y = (actor->location.y / ACTOR_LMULT) - actor->location.z;
}
}
}
@ -645,7 +577,10 @@ int Actor::drawActors() {
warning("Actor::drawActors frameNumber invalid for actorId 0x%X", actor->actorId);
continue;
}
// tiled stuff
{
}
_vm->_sprite->drawOccluded(back_buf, spriteList, frameNumber, actor->screenPosition, actor->screenScale, actor->screenDepth);
}
@ -694,264 +629,38 @@ int Actor::drawActors() {
return SUCCESS;
}
/*
void Actor::setOrientation(uint16 actorId, int orient) {
ActorData *actor;
actor = getActor(actorId);
if ((orient < 0) || (orient > 7)) {
error("Actor::setOrientation wrong orientation 0x%X", orient);
}
actor->orient = orient;
}
void Actor::setAction(uint16 actorId, int action_n, uint16 action_flags) {
ActorData *actor;
actor = getActor(actorId);
if ((action_n < 0) || (action_n >= actor->framesCount)) {
error("Actor::setAction wrong action_n 0x%X", action_n);
}
actor->action = action_n;
actor->action_flags = action_flags;
actor->action_frame = 0;
actor->action_time = 0;
}
void Actor::setDefaultAction(uint16 actorId, int action_n, uint16 action_flags) {
ActorData *actor;
actor = getActor(actorId);
if ((action_n < 0) || (action_n >= actor->framesCount)) {
error("Actor::setDefaultAction wrong action_n 0x%X", action_n);
}
actor->def_action = action_n;
actor->def_action_flags = action_flags;
}
void Actor::walkTo(uint16 actorId, const Point *walk_pt, uint16 flags, SEMAPHORE *sem) {
ACTORINTENT actor_intent;
ActorData *actor;
assert(walk_pt != NULL);
actor = getActor(actorId);
actor_intent.a_itype = INTENT_PATH;
actor_intent.a_iflags = 0;
actor_intent.walkIntent.wi_flags = flags;
actor_intent.walkIntent.sem_held = 1;
actor_intent.walkIntent.sem = sem;
// handleWalkIntent() will create path on initialization
actor_intent.walkIntent.wi_init = 0;
actor_intent.walkIntent.dst_pt = *walk_pt;
actor->a_intentlist.push_back(actor_intent);
int is = actor->a_intentlist.size();
debug(9, "actor->a_intentlist.size() %i", is);
if (sem != NULL) {
_vm->_script->SThreadHoldSem(sem);
}
}
*/
int Actor::setPathNode(WALKINTENT *walk_int, const Point &src_pt, Point *dst_pt, SEMAPHORE *sem) {
WALKNODE new_node;
walk_int->wi_active = 1;
walk_int->org = src_pt;
assert((walk_int != NULL) && (dst_pt != NULL));
new_node.node_pt = *dst_pt;
new_node.calc_flag = 0;
walk_int->nodelist.push_back(new_node);
return SUCCESS;
}
/*
int Actor::handleWalkIntent(ActorData *actor, WALKINTENT *a_walkint, int *complete_p, int delta_time) {
WalkNodeList::iterator walkNodeIterator;
WalkNodeList::iterator nextWalkNodeIterator;
WALKNODE *node_p;
int dx;
int dy;
double path_a;
double path_b;
double path_slope;
double path_x;
double path_y;
int path_time;
double new_a_x;
double new_a_y;
int actor_x;
int actor_y;
char buf[100];
// Initialize walk intent
if (!a_walkint->wi_init) {
setPathNode(a_walkint, Point(actor->actorX,actor->actorY), &a_walkint->dst_pt, a_walkint->sem);
setDefaultAction(actor->actorId, ACTION_IDLE, ACTION_NONE);
a_walkint->wi_init = 1;
}
assert(a_walkint->wi_active);
walkNodeIterator = a_walkint->nodelist.begin();
nextWalkNodeIterator = walkNodeIterator;
node_p = walkNodeIterator.operator->();
if (node_p->calc_flag == 0) {
debug(2, "Calculating new path vector to point (%d, %d)", node_p->node_pt.x, node_p->node_pt.y);
dx = a_walkint->org.x - node_p->node_pt.x;
dy = a_walkint->org.y - node_p->node_pt.y;
if (dx == 0) {
debug(0, "Vertical paths not implemented.");
a_walkint->nodelist.erase(walkNodeIterator);
a_walkint->wi_active = 0;
// Release path semaphore
if ((a_walkint->sem != NULL) && a_walkint->sem_held) {
_vm->_script->SThreadReleaseSem(a_walkint->sem);
}
*complete_p = 1;
return FAILURE;
}
a_walkint->slope = (float)dy / dx;
if (dx > 0) {
a_walkint->x_dir = -1;
if (!(a_walkint->wi_flags & WALK_NOREORIENT)) {
if (a_walkint->slope > 1.0) {
actor->orient = ORIENT_N;
} else if (a_walkint->slope < -1.0) {
actor->orient = ORIENT_S;
} else {
actor->orient = ORIENT_W;
}
}
} else {
a_walkint->x_dir = 1;
if (!(a_walkint->wi_flags & WALK_NOREORIENT)) {
if (a_walkint->slope > 1.0) {
actor->orient = ORIENT_S;
} else if (a_walkint->slope < -1.0) {
actor->orient = ORIENT_N;
} else {
actor->orient = ORIENT_E;
}
}
}
sprintf(buf, "%f", a_walkint->slope);
debug(2, "Path slope: %s.", buf);
actor->action = ACTION_WALK;
actor->action_flags = ACTION_LOOP;
a_walkint->time = 0;
node_p->calc_flag = 1;
}
a_walkint->time += delta_time;
path_time = a_walkint->time;
path_a = ACTOR_BASE_SPEED * path_time;
path_b = ACTOR_BASE_SPEED * path_time * ACTOR_BASE_ZMOD;
path_slope = a_walkint->slope * a_walkint->x_dir;
path_x = (path_a * path_b) / sqrt((path_a * path_a) * (path_slope * path_slope) + (path_b * path_b));
path_y = path_slope * path_x;
path_x = path_x * a_walkint->x_dir;
new_a_x = path_x + a_walkint->org.x;
new_a_y = path_y + a_walkint->org.y;
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))) {
Point endpoint;
int exitNum;
debug(2, "Path complete.");
a_walkint->nodelist.erase(walkNodeIterator);
a_walkint->wi_active = 0;
// 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 / ACTOR_LMULT;
endpoint.y = (int)new_a_y / ACTOR_LMULT;
if ((exitNum = _vm->_scene->_actionMap->hitTest(endpoint)) != -1) {
if (actor->flags & kProtagonist)
_vm->_scene->changeScene(_vm->_scene->_actionMap->getExitScene(exitNum));
}
*complete_p = 1;
return FAILURE;
}
actor_x = (int)new_a_x;
actor_y = (int)new_a_y;
actor->actorX = (int)new_a_x;
actor->actorY = (int)new_a_y;
return SUCCESS;
}
void Actor::move(uint16 actorId, const Point &movePoint) {
ActorData *actor;
actor = getActor(actorId);
actor->actorX = movePoint.x;
actor->actorY = movePoint.y;
}
void Actor::moveRelative(uint16 actorId, const Point &movePoint) {
ActorData *actor;
actor = getActor(actorId);
actor->actorX += movePoint.x;
actor->actorY += movePoint.y;
}
*/
void Actor::StoA(Point &actorPoint, const Point &screenPoint) {
actorPoint.x = (screenPoint.x * ACTOR_LMULT);
actorPoint.y = (screenPoint.y * ACTOR_LMULT);
}
bool Actor::actorWalkTo(uint16 actorId, const ActorLocation &actorLocation) {
BOOL result = TRUE;
ActorData *actor;
actor = getActor(actorId);
/* if (a == protag)
{
sceneDoors[ 2 ] = 0xff; // closed
sceneDoors[ 3 ] = 0; // open
}
else
{
sceneDoors[ 2 ] = 0; // open
sceneDoors[ 3 ] = 0xff; // closed
}*/
// tiled stuff
{
}
{
}
return false;
}
void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount, uint16 sampleResourceId, int speechFlags) {
ActorData *actor;
int i;

View File

@ -83,17 +83,6 @@ enum SpeechFlags {
kSpeakSlow = 4
};
enum ActorDirections {
kDirUp = 0,
kDirUpRight = 1,
kDirRight = 2,
kDirDownRight = 3,
kDirDown = 4,
kDirDownLeft = 5,
kDirLeft = 6,
kDirUpLeft = 7
};
enum ActorFrameTypes {
kFrameStand = 0,
kFrameWalk = 1,
@ -121,38 +110,6 @@ enum ActorFlagsEx {
kActorRandom = (1 << 10)
};
enum ACTOR_INTENTS {
INTENT_NONE = 0,
INTENT_PATH = 1
};
enum ACTOR_WALKFLAGS {
WALK_NONE = 0x00,
WALK_NOREORIENT = 0x01
};
enum ACTOR_ORIENTATIONS {
ORIENT_N = 0,
ORIENT_NE = 1,
ORIENT_E = 2,
ORIENT_SE = 3,
ORIENT_S = 4,
ORIENT_SW = 5,
ORIENT_W = 6,
ORIENT_NW = 7
};
enum ACTOR_ACTIONS {
ACTION_IDLE = 0,
ACTION_WALK = 1,
ACTION_SPEAK = 2,
ACTION_COUNT
};
enum ACTOR_ACTIONFLAGS {
ACTION_NONE = 0x00,
ACTION_LOOP = 0x01
};
struct ActorFrameRange {
int frameIndex;
@ -163,63 +120,6 @@ struct ActorFrameSequence {
ActorFrameRange directions[ACTOR_DIRECTIONS_COUNT];
};
struct WALKNODE {
int calc_flag;
Point node_pt;
WALKNODE() {
calc_flag = 0;
}
};
typedef Common::List<WALKNODE> WalkNodeList;
struct WALKINTENT {
int wi_active;
uint16 wi_flags;
int wi_init;
int time;
float slope;
int x_dir;
Point org;
Point cur;
Point dst_pt;
WalkNodeList nodelist;
int sem_held;
SEMAPHORE *sem;
WALKINTENT() {
wi_active = 0;
wi_flags = 0;
wi_init = 0;
time = 0;
slope = 0;
x_dir = 0;
sem_held = 0;
sem = NULL;
}
};
struct ACTORINTENT {
int a_itype;
uint16 a_iflags;
int a_idone;
WALKINTENT walkIntent;
ACTORINTENT() {
a_itype = 0;
a_iflags = 0;
a_idone = 0;
}
};
typedef Common::List<ACTORINTENT> ActorIntentList;
struct ActorLocation {
int x; // Actor's logical coordinates
int y; //
@ -261,20 +161,6 @@ struct ActorData {
int framesCount; // Actor's frames count
int frameListResourceId; // Actor's frame list resource id
///old stuff
int idle_time;
int orient;
int speaking;
ActorIntentList a_intentlist;
int def_action;
uint16 def_action_flags;
int action;
uint16 action_flags;
int action_frame;
int action_time;
/// end old stuff
void cycleWrap(int cycleLimit) {
if (actionCycle >= cycleLimit)
@ -315,27 +201,12 @@ struct ActorData {
cycleTimeCount = 0;
cycleFlags = 0;
idle_time = 0;
orient = 0;
speaking = 0;
def_action = 0;
def_action_flags = 0;
action = 0;
action_flags = 0;
action_frame = 0;
action_time = 0;
}
};
typedef ActorData* ActorDataPointer;
typedef SortedList<ActorDataPointer> ActorOrderList;
struct ACTIONTIMES {
int action;
int time;
};
struct SpeechData {
int speechColor;
int outlineColor;
@ -373,13 +244,9 @@ public:
void StoA(Point &actorPoint, const Point &screenPoint);
void move(uint16 actorId, const Point &movePoint){}
void moveRelative(uint16 actorId, const Point &movePoint){}
void walkTo(uint16 actorId, const Point *walk_pt, uint16 flags, SEMAPHORE *sem) {}
bool actorWalkTo(uint16 actorId, const ActorLocation &actorLocation);
ActorData *getActor(uint16 actorId);
// action
ActorFrameRange *getActorFrameRange(uint16 actorId, int frameType);
// speech
@ -397,9 +264,6 @@ public:
}
private:
int handleWalkIntent(ActorData *actor, WALKINTENT *a_walk_int, int *complete_p, int msec);
int setPathNode(WALKINTENT *walk_int, const Point &src_pt, Point *dst_pt, SEMAPHORE *sem);
bool loadActorResources(ActorData * actor);
void createDrawOrderList();

View File

@ -68,10 +68,10 @@ Console::Console(SagaEngine *vm) : Common::Debugger<Console>() {
#endif
// Scene commands
DCmd_Register("scene_change", &Console::Cmd_SceneChange);
DCmd_Register("scene_info", &Console::Cmd_SceneInfo);
DCmd_Register("action_info", &Console::Cmd_ActionInfo);
DCmd_Register("object_info", &Console::Cmd_ObjectInfo);
DCmd_Register("scene_change", &Console::cmdSceneChange);
DCmd_Register("scene_info", &Console::cmdSceneInfo);
DCmd_Register("action_map_info", &Console::cmdActionMapInfo);
DCmd_Register("object_map_info", &Console::cmdObjectMapInfo);
// CVAR_Register_I(&_sceneNumber, "scene", NULL, CVAR_READONLY, 0, 0);
// Script commands
@ -187,26 +187,26 @@ bool Console::Cmd_AnimInfo(int argc, const char **argv) {
return true;
}
bool Console::Cmd_SceneChange(int argc, const char **argv) {
bool Console::cmdSceneChange(int argc, const char **argv) {
if (argc != 2)
DebugPrintf("Usage: %s <Scene number>\n", argv[0]);
else
_vm->_scene->sceneChangeCmd(argc, argv);
_vm->_scene->cmdSceneChange(argc, argv);
return true;
}
bool Console::Cmd_SceneInfo(int argc, const char **argv) {
_vm->_scene->sceneInfoCmd();
bool Console::cmdSceneInfo(int argc, const char **argv) {
_vm->_scene->cmdSceneInfo();
return true;
}
bool Console::Cmd_ActionInfo(int argc, const char **argv) {
_vm->_scene->CF_actioninfo();
bool Console::cmdActionMapInfo(int argc, const char **argv) {
_vm->_scene->cmdActionMapInfo();
return true;
}
bool Console::Cmd_ObjectInfo(int argc, const char **argv) {
_vm->_scene->CF_objectinfo();
bool Console::cmdObjectMapInfo(int argc, const char **argv) {
_vm->_scene->cmdObjectMapInfo();
return true;
}

View File

@ -52,10 +52,10 @@ private:
bool Cmd_AnimInfo(int argc, const char **argv);
bool Cmd_SceneChange(int argc, const char **argv);
bool Cmd_SceneInfo(int argc, const char **argv);
bool Cmd_ActionInfo(int argc, const char **argv);
bool Cmd_ObjectInfo(int argc, const char **argv);
bool cmdSceneChange(int argc, const char **argv);
bool cmdSceneInfo(int argc, const char **argv);
bool cmdActionMapInfo(int argc, const char **argv);
bool cmdObjectMapInfo(int argc, const char **argv);
bool Cmd_ScriptInfo(int argc, const char **argv);
bool Cmd_ScriptExec(int argc, const char **argv);

View File

@ -555,6 +555,8 @@ int Interface::handleCommandUpdate(SURFACE *ds, const Point& imousePt) {
}
int Interface::handlePlayfieldClick(SURFACE *ds, const Point& imousePt) {
return FALSE;
/*
int objectNum;
uint16 object_flags = 0;
@ -566,6 +568,8 @@ int Interface::handlePlayfieldClick(SURFACE *ds, const Point& imousePt) {
if (objectNum == -1) {
// Player clicked on empty spot - walk here regardless of verb
_vm->_actor->StoA(iactor_pt, imousePt);
error("!");
_vm->_actor->walkTo(1, &iactor_pt, 0, NULL);
return SUCCESS;
}
@ -585,13 +589,17 @@ int Interface::handlePlayfieldClick(SURFACE *ds, const Point& imousePt) {
} else {
// Not a normal scene object - walk to it as if it weren't there
_vm->_actor->StoA(iactor_pt, imousePt);
_vm->_actor->walkTo(1, &iactor_pt, 0, NULL);
// _vm->_actor->walkTo(1, &iactor_pt, 0, NULL);
error("!");
}
return SUCCESS;
return SUCCESS;*/
}
int Interface::handlePlayfieldUpdate(SURFACE *ds, const Point& imousePt) {
return FALSE;
/*
const char *object_name;
int objectNum;
uint16 object_flags = 0;
@ -623,6 +631,7 @@ int Interface::handlePlayfieldUpdate(SURFACE *ds, const Point& imousePt) {
setStatusText(new_status);
return SUCCESS;
*/
}
int Interface::hitTest(const Point& imousePt, int *ibutton) {

View File

@ -36,6 +36,103 @@
namespace Saga {
HitZone::HitZone(MemoryReadStreamEndian *readStream) {
int i, j;
HitZone::ClickArea *clickArea;
Point *point;
_flags = readStream->readByte();
_clickAreasCount = readStream->readByte();
_defaultVerb = readStream->readByte();
readStream->readByte(); // pad
_nameNumber = readStream->readUint16();
_scriptNumber = readStream->readUint16();
_clickAreas = (HitZone::ClickArea *)malloc(_clickAreasCount * sizeof *_clickAreas);
if (_clickAreas == NULL) {
error("HitZone::HitZone Memory allocation failed");
}
for (i = 0; i < _clickAreasCount; i++) {
clickArea = &_clickAreas[i];
clickArea->pointsCount = readStream->readUint16();
assert(clickArea->pointsCount);
clickArea->points = (Point *)malloc(clickArea->pointsCount * sizeof *(clickArea->points));
if (clickArea->points == NULL) {
error("HitZone::HitZone Memory allocation failed");
}
for (j = 0; j < clickArea->pointsCount; j++) {
point = &clickArea->points[j];
point->x = readStream->readSint16();
point->y = readStream->readSint16();
}
}
}
HitZone::~HitZone() {
for (int i = 0; i < _clickAreasCount; i++) {
free(_clickAreas[i].points);
}
free(_clickAreas);
}
bool HitZone::hitTest(const Point &testPoint) {
int i, pointsCount;
HitZone::ClickArea *clickArea;
Point *points;
if (_flags & kHitZoneEnabled) {
for (i = 0; i < _clickAreasCount; i++) {
clickArea = &_clickAreas[i];
pointsCount = clickArea->pointsCount;
points = clickArea->points;
if (pointsCount == 2) {
// Hit-test a box region
if ((testPoint.x >= points[0].x) &&
(testPoint.x <= points[1].x) &&
(testPoint.y >= points[0].y) &&
(testPoint.y <= points[1].y)) {
return true;
}
} else {
if (pointsCount > 2) {
// Hit-test a polygon
if (hitTestPoly(points, pointsCount, testPoint)) {
return true;
}
}
}
}
}
return false;
}
void HitZone::draw(SURFACE *ds, int color) {
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 == 2) {
// 2 points represent a box
drawFrame(ds, &points[0], &points[1], color);
} else {
if (pointsCount > 2) {
// Otherwise draw a polyline
drawPolyLine(ds, points, pointsCount, color);
}
}
}
}
// Initializes the object map module, creates module allocation context
ObjectMap::ObjectMap(SagaEngine *vm) : _vm(vm) {
_objectsLoaded = false;
@ -225,6 +322,7 @@ const uint16 ObjectMap::getFlags(int object) {
return 0;
}
// If 'object' is a valid object number in the currently loaded object
// name list resource, the funciton sets '*ep_num' to the entrypoint number
// corresponding to 'object' and returns SUCCESS. Otherwise, it returns
@ -342,7 +440,7 @@ int ObjectMap::hitTest(const Point& imousePt) {
return -1;
}
void ObjectMap::info(void) {
void ObjectMap::cmdInfo(void) {
int i;
_vm->_console->DebugPrintf("%d objects loaded.\n", _nObjects);

View File

@ -26,22 +26,43 @@
#ifndef SAGA_OBJECTMAP_H_
#define SAGA_OBJECTMAP_H_
#include "saga/stream.h"
namespace Saga {
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),
class HitZone {
private:
struct ClickArea {
int pointsCount;
Point *points;
};
public:
HitZone(MemoryReadStreamEndian *readStream);
~HitZone();
// 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)
int getSceneNumber() const {
return _nameNumber;
}
int getEntranceNumber() const {
return _scriptNumber;
}
void draw(SURFACE *ds, int color);
bool hitTest(const Point &testPoint);
private:
int _flags; // HitZoneFlags
int _clickAreasCount;
int _defaultVerb;
int _nameNumber;
int _scriptNumber;
ClickArea *_clickAreas;
};
struct OBJECTMAP_ENTRY {
byte flags;
byte defaultVerb;
@ -55,7 +76,6 @@ struct OBJECTMAP_ENTRY {
class ObjectMap{
public:
int reg(void);
ObjectMap(SagaEngine *vm);
~ObjectMap(void);
int load(const byte *om_res, size_t om_res_len);
@ -67,7 +87,7 @@ public:
const int getEPNum(int object);
int draw(SURFACE *draw_surface, const Point& imousePt, int color, int color2);
int hitTest(const Point& imousePt);
void info(void);
void cmdInfo(void);
private:

View File

@ -64,7 +64,6 @@ class PalAnim;
#define MAXPATH 512
struct RSCFILE_CONTEXT;
struct SEMAPHORE;
struct SPRITELIST;
enum ERRORCODE {
@ -82,6 +81,31 @@ enum scriptTimings {
kScriptTimeTicksPerSecond = (728L/10L)
};
enum Directions {
kDirUp = 0,
kDirUpRight = 1,
kDirRight = 2,
kDirDownRight = 3,
kDirDown = 4,
kDirDownLeft = 5,
kDirLeft = 6,
kDirUpLeft = 7
};
enum HitZoneFlags {
kHitZoneEnabled = (1 << 0), // Zone is enabled
kHitZoneExit = (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.
kHitZoneAutoWalk = (1 << 2),
// zone activates only when character stops walking
kHitZoneTerminus = (1 << 3)
};
struct CLICKAREA {
int n_points;
Point *points;

View File

@ -119,7 +119,7 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) {
_animEntries = 0;
_sceneProc = NULL;
_objectMap = NULL;
_actionMap = NULL;
_actionMap = new ActionMap(_vm);
memset(&_bg, 0, sizeof(_bg));
memset(&_bgMask, 0, sizeof(_bgMask));
@ -129,6 +129,7 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) {
Scene::~Scene() {
if (_initialized) {
endScene();
delete _actionMap;
free(_sceneLUT);
}
}
@ -684,7 +685,7 @@ int Scene::processSceneResources() {
break;
case SAGA_ACTION_MAP:
debug(0, "Loading exit map resource...");
_actionMap = new ActionMap(_vm, res_data, res_data_len);
_actionMap->load(res_data, res_data_len);
break;
case SAGA_ISO_TILESET:
if (_sceneMode == SCENE_MODE_NORMAL) {
@ -850,10 +851,9 @@ int Scene::endScene() {
_vm->_palanim->freePalAnim();
delete _objectMap;
delete _actionMap;
_objectMap = NULL;
_actionMap = NULL;
_actionMap->freeMem();
_animList.clear();
@ -867,7 +867,7 @@ int Scene::endScene() {
return SUCCESS;
}
void Scene::sceneChangeCmd(int argc, const char **argv) {
void Scene::cmdSceneChange(int argc, const char **argv) {
int scene_num = 0;
scene_num = atoi(argv[1]);
@ -886,7 +886,7 @@ void Scene::sceneChangeCmd(int argc, const char **argv) {
}
}
void Scene::sceneInfoCmd() {
void Scene::cmdSceneInfo() {
const char *fmt = "%-20s %d\n";
_vm->_console->DebugPrintf(fmt, "Scene number:", _sceneNumber);
@ -906,12 +906,12 @@ int Scene::SC_defaultScene(int param, SCENE_INFO *scene_info, void *refCon) {
return ((Scene *)refCon)->defaultScene(param, scene_info);
}
void Scene::CF_actioninfo() {
_actionMap->info();
void Scene::cmdActionMapInfo() {
_actionMap->cmdInfo();
}
void Scene::CF_objectinfo() {
_objectMap->info();
void Scene::cmdObjectMapInfo() {
_objectMap->cmdInfo();
}
int Scene::defaultScene(int param, SCENE_INFO *scene_info) {

View File

@ -214,8 +214,12 @@ class Scene {
Scene(SagaEngine *vm);
~Scene();
void CF_actioninfo();
void CF_objectinfo();
// Console functions
void cmdSceneInfo();
void cmdActionMapInfo();
void cmdObjectMapInfo();
void cmdSceneChange(int argc, const char **argv);
int startScene();
int nextScene();
@ -236,8 +240,6 @@ class Scene {
bool initialized() { return _initialized; }
void sceneInfoCmd();
void sceneChangeCmd(int argc, const char **argv);
int getSceneLUT(int num);
int currentSceneNumber() { return _sceneNumber; }

View File

@ -64,10 +64,6 @@ enum SCRIPT_VERBS {
#define STHREAD_TIMESLICE 8
struct SEMAPHORE {
int hold_count;
};
enum {
kVarObject = 0,
kVarWithObject,
@ -109,6 +105,7 @@ enum CycleFlags {
kCycleRandom = (1 << 2),
kCycleReverse = (1 << 3)
};
struct SCRIPT_THREAD {
int flags; // ThreadFlags
int waitType; // ThreadWaitTypes
@ -119,8 +116,6 @@ struct SCRIPT_THREAD {
unsigned long ep_offset; // Entrypoint offset
unsigned long i_offset; // Instruction offset
SEMAPHORE sem; // FIXME: no equivalent. should be replaced with flags
// The scripts are allowed to access the stack like any other memory
// area. It's therefore probably quite important that our stacks work
// the same as in the original interpreter.
@ -157,6 +152,16 @@ struct SCRIPT_THREAD {
flags |= kTFlagWaiting;
}
void waitWalk(void *aThreadObj) {
wait(kWaitTypeWalk);
threadObj = aThreadObj;
}
void waitDelay(int aSleepTime) {
wait(kWaitTypeDelay);
sleepTime = aSleepTime;
}
SCRIPT_THREAD() { memset(this, 0, sizeof(*this)); }
};
@ -257,8 +262,6 @@ public:
SCRIPT_THREAD *SThreadCreate();
int SThreadExecute(SCRIPT_THREAD *thread, int ep_num);
int executeThreads(uint msec);
int SThreadHoldSem(SEMAPHORE *sem);
int SThreadReleaseSem(SEMAPHORE *sem);
int SThreadDebugStep();
void SThreadCompleteThread(void);
int SThreadDestroy(SCRIPT_THREAD *thread);
@ -293,7 +296,7 @@ private:
int SF_objectIsCarried(SCRIPTFUNC_PARAMS);
int SF_setStatusText(SCRIPTFUNC_PARAMS);
int SF_commandMode(SCRIPTFUNC_PARAMS);
int SF_actorWalkTo(SCRIPTFUNC_PARAMS);
int sfScriptWalkTo(SCRIPTFUNC_PARAMS);
int SF_doAction(SCRIPTFUNC_PARAMS);
int sfSetActorFacing(SCRIPTFUNC_PARAMS);
int SF_startBgdAnim(SCRIPTFUNC_PARAMS);

View File

@ -51,7 +51,7 @@ void Script::setupScriptFuncList(void) {
OPCODE(SF_objectIsCarried),
OPCODE(SF_setStatusText),
OPCODE(SF_commandMode),
OPCODE(SF_actorWalkTo),
OPCODE(sfScriptWalkTo),
OPCODE(SF_doAction),
OPCODE(sfSetActorFacing),
OPCODE(SF_startBgdAnim),
@ -143,8 +143,7 @@ int Script::sfWait(SCRIPTFUNC_PARAMS) {
time = getUWord(thread->pop());
if (!_skipSpeeches) {
thread->wait(kWaitTypeDelay); // put thread to sleep
thread->sleepTime = ticksToMSec(time);
thread->waitDelay(ticksToMSec(time)); // put thread to sleep
}
return SUCCESS;
}
@ -198,26 +197,25 @@ int Script::SF_commandMode(SCRIPTFUNC_PARAMS) {
// Script function #6 (0x06) blocking
// Commands the specified actor to walk to the given position
// Param1: actor id
// Param2: actor destination x
// Param3: actor destination y
int Script::SF_actorWalkTo(SCRIPTFUNC_PARAMS) {
ScriptDataWord actor_parm;
ScriptDataWord x_parm;
ScriptDataWord y_parm;
// Param2: actor x
// Param3: actor y
int Script::sfScriptWalkTo(SCRIPTFUNC_PARAMS) {
uint16 actorId;
Point pt;
ActorLocation actorLocation;
ActorData *actor;
actor_parm = thread->pop();
x_parm = thread->pop();
y_parm = thread->pop();
actorId = getSWord(actor_parm);
pt.x = getSWord(x_parm);
pt.y = getSWord(y_parm);
_vm->_actor->walkTo(actorId, &pt, 0, &thread->sem);
actorId = getSWord(thread->pop());
actorLocation.x = getSWord(thread->pop());
actorLocation.y = getSWord(thread->pop());
actor = _vm->_actor->getActor(actorId);
actorLocation.z = actor->location.z;
actor->flags &= ~kFollower;
if (_vm->_actor->actorWalkTo(actorId, actorLocation)) {
thread->waitWalk(actor);
}
return SUCCESS;
}
@ -493,7 +491,7 @@ int Script::SF_actorWalkToAsync(SCRIPTFUNC_PARAMS) {
pt.x = getSWord(x_parm);
pt.y = getSWord(y_parm);
_vm->_actor->walkTo(actorId, &pt, 0, NULL);
// error("!");
return SUCCESS;
}
@ -683,11 +681,7 @@ int Script::SF_actorWalk(SCRIPTFUNC_PARAMS) {
pt.x = getSWord(x_parm);
pt.y = getSWord(y_parm);
#if 1
_vm->_actor->walkTo(actorId, &pt, 0, NULL);
#else
_vm->_actor->walkTo(actorId, &pt, 0, &thread->sem);
#endif
// error("!");
return SUCCESS;
}

View File

@ -206,28 +206,7 @@ size_t Script::SThreadGetReadLen(SCRIPT_THREAD *thread) {
}
int Script::SThreadHoldSem(SEMAPHORE *sem) {
if (sem == NULL) {
return FAILURE;
}
sem->hold_count++;
return SUCCESS;
}
int Script::SThreadReleaseSem(SEMAPHORE *sem) {
if (sem == NULL) {
return FAILURE;
}
sem->hold_count--;
if (sem->hold_count < 0) {
sem->hold_count = 0;
}
return SUCCESS;
}
int Script::SThreadDebugStep() {
if (_dbg_singlestep) {
@ -278,13 +257,10 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) {
if (thread->flags & kTFlagWaiting)
break;
if (thread->sem.hold_count) //TODO: remove it
break;
saved_offset = thread->i_offset;
operandChar = scriptS.readByte();
debug(2, "Executing thread offset: %lu (%x) stack: %d", thread->i_offset, operandChar, thread->stackSize());
// debug(2, "Executing thread offset: %lu (%x) stack: %d", thread->i_offset, operandChar, thread->stackSize());
switch (operandChar) {
case 0x01: // nextblock
// Some sort of "jump to the start of the next memory