mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
- remove old stuff
- work on "walking" in progress svn-id: r16298
This commit is contained in:
parent
f0bc27f11c
commit
2289ea371b
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
397
saga/actor.cpp
397
saga/actor.cpp
@ -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;
|
||||
|
140
saga/actor.h
140
saga/actor.h
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
||||
|
26
saga/saga.h
26
saga/saga.h
@ -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;
|
||||
|
@ -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) {
|
||||
|
10
saga/scene.h
10
saga/scene.h
@ -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; }
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user