2007-01-14 21:29:12 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
* Copyright (C) 2006 The ScummVM project
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "parallaction/defs.h"
|
|
|
|
#include "parallaction/parallaction.h"
|
|
|
|
#include "parallaction/commands.h"
|
|
|
|
#include "parallaction/graphics.h"
|
2007-03-12 22:52:27 +00:00
|
|
|
#include "parallaction/walk.h"
|
2007-01-14 21:29:12 +00:00
|
|
|
#include "parallaction/zone.h"
|
|
|
|
|
|
|
|
namespace Parallaction {
|
|
|
|
|
|
|
|
uint16 walkFunc1(int16, int16, WalkNode *);
|
2007-03-12 22:52:27 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-17 13:14:50 +00:00
|
|
|
WalkNode _NULL_WALKNODE();
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-12 22:52:27 +00:00
|
|
|
static byte *_buffer;
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
static uint16 _doorData1 = 1000;
|
|
|
|
static Zone *_zoneTrap = NULL;
|
|
|
|
|
|
|
|
static uint16 walkData1 = 0;
|
|
|
|
static uint16 walkData2 = 0; // next walk frame
|
|
|
|
static int16 walkData3 = -1000; // unused
|
|
|
|
|
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
int32 dotProduct(const Common::Point &p1, const Common::Point &p2) {
|
|
|
|
return p1.x * p2.x + p1.y * p2.y;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// x, y: mouse click (foot) coordinates
|
|
|
|
//
|
|
|
|
WalkNode *buildWalkPath(uint16 x, uint16 y) {
|
2007-01-17 11:12:02 +00:00
|
|
|
debugC(1, kDebugWalk, "buildWalkPath to (%i, %i)", x, y);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
Common::Point to(x, y);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
int16 left, bottom, right, top, close, closeY, closeX;
|
|
|
|
|
|
|
|
// looks for closest usable path Point
|
2007-03-18 17:03:07 +00:00
|
|
|
if (queryPath(to.x, to.y) == 0) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
right = left = to.x;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
right++;
|
2007-03-18 17:03:07 +00:00
|
|
|
} while ((queryPath(right, to.y) == 0) && (right < SCREEN_WIDTH));
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
left--;
|
2007-03-18 17:03:07 +00:00
|
|
|
} while ((queryPath(left, to.y) == 0) && (left > 0));
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
right = (right == SCREEN_WIDTH) ? 1000 : right - to.x;
|
|
|
|
left = (left == 0) ? 1000 : to.x - left;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
top = bottom = to.y;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
top--;
|
2007-03-18 17:03:07 +00:00
|
|
|
} while ((queryPath(to.x, top) == 0) && (top > 0));
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
bottom++;
|
2007-03-18 17:03:07 +00:00
|
|
|
} while ((queryPath(to.x, bottom) == 0) && (bottom < SCREEN_HEIGHT));
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
top = (top == 0) ? 1000 : to.y - top;
|
|
|
|
bottom = (bottom == SCREEN_HEIGHT) ? 1000 : bottom - to.y;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
closeX = (right >= left) ? left : right;
|
|
|
|
closeY = (top >= bottom) ? bottom : top;
|
|
|
|
|
|
|
|
close = (closeX >= closeY) ? closeY : closeX;
|
|
|
|
|
|
|
|
if (close == right) {
|
2007-03-18 17:03:07 +00:00
|
|
|
to.x += right;
|
2007-03-18 17:33:54 +00:00
|
|
|
walkData3 = (_vm->_char._ani.getFrameNum() == 20) ? 7 : 9;
|
2007-01-14 21:29:12 +00:00
|
|
|
} else
|
|
|
|
if (close == left) {
|
2007-03-18 17:03:07 +00:00
|
|
|
to.x -= left;
|
2007-01-14 21:29:12 +00:00
|
|
|
walkData3 = 0;
|
|
|
|
} else
|
|
|
|
if (close == top) {
|
2007-03-18 17:03:07 +00:00
|
|
|
to.y -= top;
|
2007-01-14 21:29:12 +00:00
|
|
|
} else
|
|
|
|
if (close == bottom) {
|
2007-03-18 17:03:07 +00:00
|
|
|
to.y += bottom;
|
2007-03-18 17:33:54 +00:00
|
|
|
walkData3 = (_vm->_char._ani.getFrameNum() == 20) ? 17 : 21;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2007-03-18 17:03:07 +00:00
|
|
|
debugC(1, kDebugWalk, "found closest path point at (%i, %i)", to.x, to.y);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 19:59:56 +00:00
|
|
|
WalkNode *v48 = new WalkNode(to.x - _vm->_char._ani.width() / 2, to.y - _vm->_char._ani.height());
|
|
|
|
WalkNode *v44 = new WalkNode(*v48);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
uint16 v38 = walkFunc1(to.x, to.y, v44);
|
2007-01-14 21:29:12 +00:00
|
|
|
if (v38 == 1) {
|
|
|
|
// destination directly reachable
|
2007-03-18 17:03:07 +00:00
|
|
|
debugC(1, kDebugWalk, "direct move to (%i, %i)", to.x, to.y);
|
2007-03-18 19:59:56 +00:00
|
|
|
delete v44;
|
2007-01-14 21:29:12 +00:00
|
|
|
return v48;
|
|
|
|
}
|
|
|
|
|
|
|
|
// path is obstructed: find alternative
|
2007-03-18 17:03:07 +00:00
|
|
|
debugC(1, kDebugWalk, "trying to build walk path to (%i, %i)", to.x, to.y);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
WalkNode v58;
|
|
|
|
|
|
|
|
int16 _si = v48->_x; // _si, _di: target top left coordinates
|
|
|
|
int16 _di = v48->_y;
|
2007-03-17 13:14:50 +00:00
|
|
|
addNode(&v58, v48);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
WalkNode *_closest_node = NULL;
|
|
|
|
|
|
|
|
int32 v30, v34, v2C, v28;
|
|
|
|
|
|
|
|
byte _closest_node_found = 1;
|
|
|
|
bool emptyList = true;
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
|
|
v48 = &v58;
|
|
|
|
|
2007-03-19 21:49:41 +00:00
|
|
|
Common::Point v20(_vm->_char._ani._left, _vm->_char._ani._top);
|
|
|
|
Common::Point v8(_si - _vm->_char._ani._left, _di - _vm->_char._ani._top);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
v34 = v30 = dotProduct(v8, v8); // square distance from current position and target
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
while (_closest_node_found != 0) {
|
|
|
|
|
|
|
|
_closest_node_found = 0;
|
2007-03-11 14:14:08 +00:00
|
|
|
WalkNode *location_node = (WalkNode*)_vm->_location._walkNodes._next;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
// scans location path nodes searching for the nearest Node
|
|
|
|
// which can't be farther than the target position
|
|
|
|
// otherwise no _closest_node is selected
|
|
|
|
while (location_node != NULL) {
|
2007-03-18 17:03:07 +00:00
|
|
|
v8.x = location_node->_x - _si;
|
|
|
|
v8.y = location_node->_y - _di;
|
|
|
|
v2C = dotProduct(v8, v8); // square distance from Node to target position
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
v8.x = location_node->_x - v20.x;
|
|
|
|
v8.y = location_node->_y - v20.y;
|
|
|
|
v28 = dotProduct(v8, v8); // square distance from Node to current position
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
if (v2C < v34 && v28 < v30) {
|
|
|
|
_closest_node_found = 1;
|
|
|
|
v30 = v28;
|
|
|
|
_closest_node = location_node;
|
|
|
|
}
|
|
|
|
|
2007-03-17 13:14:50 +00:00
|
|
|
location_node = (WalkNode*)location_node->_next;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_closest_node_found == 0) break;
|
|
|
|
|
2007-03-18 19:59:56 +00:00
|
|
|
WalkNode *_newnode = new WalkNode(*_closest_node);
|
|
|
|
_newnode->getPoint(v20);
|
2007-03-18 17:03:07 +00:00
|
|
|
|
|
|
|
Common::Point tmp(_si - v20.x, _di - v20.y);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
v34 = v30 = dotProduct(tmp, tmp);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-01-16 21:30:18 +00:00
|
|
|
|
2007-01-17 11:12:02 +00:00
|
|
|
debugC(1, kDebugWalk, "adding walk node (%i, %i) to path", _newnode->_x, _newnode->_y);
|
2007-01-16 21:30:18 +00:00
|
|
|
|
2007-03-17 13:14:50 +00:00
|
|
|
addNode(v48, _newnode);
|
2007-01-14 21:29:12 +00:00
|
|
|
v48 = _newnode;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!emptyList) break;
|
|
|
|
|
|
|
|
if (v38 != 0 && v34 > v38) {
|
|
|
|
// no alternative path (gap?)
|
2007-03-17 13:14:50 +00:00
|
|
|
freeNodeList(v58._next);
|
2007-01-17 11:12:02 +00:00
|
|
|
debugC(1, kDebugWalk, "can't find a path node: rejecting partial path");
|
2007-01-14 21:29:12 +00:00
|
|
|
return v44;
|
|
|
|
} else {
|
2007-03-17 13:14:50 +00:00
|
|
|
_si = ((WalkNode*)(v58._next))->_x;
|
|
|
|
_di = ((WalkNode*)(v58._next))->_y;
|
2007-01-14 21:29:12 +00:00
|
|
|
emptyList = false;
|
|
|
|
_closest_node_found = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (true);
|
|
|
|
|
2007-01-17 11:12:02 +00:00
|
|
|
debugC(1, kDebugWalk, "walk path completed");
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-01-18 21:25:02 +00:00
|
|
|
WalkNode* tmp = &v58;
|
|
|
|
uint16 i = 1;
|
2007-03-17 13:14:50 +00:00
|
|
|
while (tmp->_next) {
|
2007-02-17 15:37:49 +00:00
|
|
|
debugC(1, kDebugWalk, "node %i: %i, %i", i, tmp->_x, tmp->_y);
|
2007-03-17 13:14:50 +00:00
|
|
|
tmp = (WalkNode*)tmp->_next;
|
2007-02-17 15:37:49 +00:00
|
|
|
i++;
|
2007-01-18 21:25:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-18 19:59:56 +00:00
|
|
|
delete v44;
|
2007-03-17 13:14:50 +00:00
|
|
|
return (WalkNode*)v58._next;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// x,y : top left coordinates
|
|
|
|
//
|
|
|
|
// 0 : Point not reachable
|
|
|
|
// 1 : Point reachable
|
|
|
|
// other values: square distance to target (not reachable)
|
|
|
|
//
|
|
|
|
uint16 walkFunc1(int16 x, int16 y, WalkNode *Node) {
|
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
Common::Point arg(x, y);
|
|
|
|
|
|
|
|
Common::Point v4(0, 0);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
Common::Point foot(
|
2007-03-19 21:49:41 +00:00
|
|
|
_vm->_char._ani._left + _vm->_char._ani.width()/2,
|
|
|
|
_vm->_char._ani._top + _vm->_char._ani.height()
|
2007-03-18 17:03:07 +00:00
|
|
|
);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
Common::Point v8(foot);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
while (foot != arg) {
|
|
|
|
|
|
|
|
if (foot.x < x && queryPath(foot.x + 1, foot.y) != 0) foot.x++;
|
|
|
|
if (foot.x > x && queryPath(foot.x - 1, foot.y) != 0) foot.x--;
|
|
|
|
if (foot.y < y && queryPath(foot.x, foot.y + 1) != 0) foot.y++;
|
|
|
|
if (foot.y > y && queryPath(foot.x, foot.y - 1) != 0) foot.y--;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
if (foot == v8 && foot != arg) {
|
2007-01-14 21:29:12 +00:00
|
|
|
// foot couldn't move and still away from target
|
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
v4 = foot;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
while (foot != arg) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
if (foot.x < x && queryPath(foot.x + 1, foot.y) == 0) foot.x++;
|
|
|
|
if (foot.x > x && queryPath(foot.x - 1, foot.y) == 0) foot.x--;
|
|
|
|
if (foot.y < y && queryPath(foot.x, foot.y + 1) == 0) foot.y++;
|
|
|
|
if (foot.y > y && queryPath(foot.x, foot.y - 1) == 0) foot.y--;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
if (foot == v8 && foot != arg)
|
2007-01-14 21:29:12 +00:00
|
|
|
return 0;
|
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
v8 = foot;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
Node->_x = v4.x - _vm->_char._ani.width() / 2;
|
|
|
|
Node->_y = v4.y - _vm->_char._ani.height();
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
return (x - v4.x) * (x - v4.x) + (y - v4.y) * (y - v4.y);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
v8 = foot;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// there exists an unobstructed path
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void jobWalk(void *parm, Job *j) {
|
|
|
|
WalkNode *node = (WalkNode*)parm;
|
|
|
|
|
2007-03-19 21:49:41 +00:00
|
|
|
int16 _si = _vm->_char._ani._left;
|
|
|
|
int16 _di = _vm->_char._ani._top;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-17 20:48:23 +00:00
|
|
|
// debugC(1, kDebugWalk, "jobWalk to (%i, %i)", node->_x + _vm->_char._ani.width() / 2, node->_y + _vm->_char._ani.height());
|
2007-01-16 21:30:18 +00:00
|
|
|
|
2007-03-19 21:49:41 +00:00
|
|
|
_vm->_char._ani._oldLeft = _si;
|
|
|
|
_vm->_char._ani._oldTop = _di;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-01-18 21:25:02 +00:00
|
|
|
if ((node->_x == _si) && (node->_y == _di)) {
|
2007-03-17 13:14:50 +00:00
|
|
|
if (node->_next == NULL) {
|
2007-01-18 21:25:02 +00:00
|
|
|
|
|
|
|
debugC(1, kDebugWalk, "jobWalk reached last node");
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
j->_finished = 1;
|
|
|
|
checkDoor();
|
2007-03-04 08:58:23 +00:00
|
|
|
free(node);
|
2007-01-14 21:29:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-01-18 21:25:02 +00:00
|
|
|
|
2007-03-17 13:14:50 +00:00
|
|
|
WalkNode *tmp = (WalkNode*)node->_next;
|
|
|
|
j->_parm = node->_next;
|
2007-03-04 08:58:23 +00:00
|
|
|
free(node);
|
2007-01-18 21:25:02 +00:00
|
|
|
|
2007-02-17 15:37:49 +00:00
|
|
|
debugC(1, kDebugWalk, "jobWalk moving to next node (%i, %i)", tmp->_x, tmp->_y);
|
2007-01-18 21:25:02 +00:00
|
|
|
|
|
|
|
node = (WalkNode*)tmp;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-03-19 21:49:41 +00:00
|
|
|
Common::Point dist(node->_x - _vm->_char._ani._left, node->_y - _vm->_char._ani._top);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
if (dist.x < 0)
|
|
|
|
dist.x = -dist.x;
|
|
|
|
if (dist.y < 0)
|
|
|
|
dist.y = -dist.y;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
walkData1++;
|
|
|
|
|
|
|
|
// walk frame selection
|
|
|
|
int16 v16;
|
2007-03-18 17:33:54 +00:00
|
|
|
if (_vm->_char._ani.getFrameNum() == 20) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
if (dist.x > dist.y) {
|
2007-01-14 21:29:12 +00:00
|
|
|
walkData2 = (node->_x > _si) ? 0 : 7;
|
|
|
|
walkData1 %= 12;
|
|
|
|
v16 = walkData1 / 2;
|
|
|
|
} else {
|
|
|
|
walkData2 = (node->_y > _di) ? 14 : 17;
|
|
|
|
walkData1 %= 8;
|
|
|
|
v16 = walkData1 / 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2007-03-18 17:03:07 +00:00
|
|
|
if (dist.x > dist.y) {
|
2007-01-14 21:29:12 +00:00
|
|
|
walkData2 = (node->_x > _si) ? 0 : 9;
|
|
|
|
walkData1 %= 16;
|
|
|
|
v16 = walkData1 / 2;
|
|
|
|
} else {
|
|
|
|
walkData2 = (node->_y > _di) ? 18 : 21;
|
|
|
|
walkData1 %= 8;
|
|
|
|
v16 = walkData1 / 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// StaticCnv v14;
|
2007-03-17 20:48:23 +00:00
|
|
|
// v14._width = _vm->_char._ani.width();
|
|
|
|
// v14._height = _vm->_char._ani.height();
|
2007-03-17 07:55:16 +00:00
|
|
|
// v14._data0 = _vm->_char._ani._cnv._array[_vm->_char._ani._frame];
|
|
|
|
// v14._data1 = _vm->_char._ani._cnv.field_8[_vm->_char._ani._frame];
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-17 20:48:23 +00:00
|
|
|
if ((_si < node->_x) && (_si < SCREEN_WIDTH) && (queryPath(_vm->_char._ani.width()/2 + _si + 2, _vm->_char._ani.height() + _di) != 0)) {
|
2007-01-14 21:29:12 +00:00
|
|
|
// printf("walk right\n");
|
|
|
|
_si = (_si + 2 < node->_x) ? _si + 2 : node->_x;
|
|
|
|
}
|
|
|
|
|
2007-03-17 20:48:23 +00:00
|
|
|
if ((_si > node->_x) && (_si > -20) && (queryPath(_vm->_char._ani.width()/2 + _si - 2, _vm->_char._ani.height() + _di) != 0)) {
|
2007-01-14 21:29:12 +00:00
|
|
|
// printf("walk left\n");
|
|
|
|
_si = (_si - 2 > node->_x) ? _si - 2 :node->_x;
|
|
|
|
}
|
|
|
|
|
2007-03-17 20:48:23 +00:00
|
|
|
if ((_di < node->_y) && (_di < (SCREEN_HEIGHT - _vm->_char._ani.height())) && (queryPath(_vm->_char._ani.width()/2 + _si, _vm->_char._ani.height() + _di + 2) != 0)) {
|
2007-01-14 21:29:12 +00:00
|
|
|
// printf("walk down\n");
|
|
|
|
_di = (_di + 2 <= node->_y) ? _di + 2 : node->_y;
|
|
|
|
}
|
|
|
|
|
2007-03-17 20:48:23 +00:00
|
|
|
if ((_di > node->_y) && (_di > -20) && (queryPath(_vm->_char._ani.width()/2 + _si, _vm->_char._ani.height() + _di - 2) != 0)) {
|
2007-01-14 21:29:12 +00:00
|
|
|
// printf("walk up\n");
|
|
|
|
_di = (_di - 2 >= node->_y) ? _di - 2 : node->_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// printf("hitZone: %i, %i\n", _si, _di);
|
2007-03-19 21:49:41 +00:00
|
|
|
_vm->_char._ani._left = _si;
|
|
|
|
_vm->_char._ani._top = _di;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-19 21:49:41 +00:00
|
|
|
if ((_si == _vm->_char._ani._oldLeft) && (_di == _vm->_char._ani._oldTop)) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
j->_finished = 1;
|
|
|
|
checkDoor();
|
2007-03-17 13:14:50 +00:00
|
|
|
freeNodeList(node);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2007-03-17 07:55:16 +00:00
|
|
|
_vm->_char._ani._frame = v16 + walkData2 + 1;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint16 checkDoor() {
|
|
|
|
// printf("checkDoor()...");
|
|
|
|
|
|
|
|
if (_vm->_currentLocationIndex != _doorData1) {
|
|
|
|
_doorData1 = _vm->_currentLocationIndex;
|
|
|
|
_zoneTrap = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
_engineFlags &= ~kEngineWalking;
|
2007-03-19 21:49:41 +00:00
|
|
|
Zone *z = _vm->hitZone(kZoneDoor, _vm->_char._ani._left + _vm->_char._ani.width() / 2, _vm->_char._ani._top + _vm->_char._ani.height());
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
if (z != NULL) {
|
|
|
|
|
|
|
|
if ((z->_flags & kFlagsClosed) == 0) {
|
2007-03-18 17:17:21 +00:00
|
|
|
_vm->_location._startPosition.x = z->u.door->_startPos.x;
|
|
|
|
_vm->_location._startPosition.y = z->u.door->_startPos.y;
|
2007-03-11 14:14:08 +00:00
|
|
|
_vm->_location._startFrame = z->u.door->_startFrame;
|
|
|
|
strcpy( _vm->_location._name, z->u.door->_location );
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
_engineFlags |= kEngineChangeLocation;
|
|
|
|
_zoneTrap = NULL;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
runCommands(z->_commands, z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-19 21:49:41 +00:00
|
|
|
z = _vm->hitZone(kZoneTrap, _vm->_char._ani._left + _vm->_char._ani.width() / 2, _vm->_char._ani._top + _vm->_char._ani.height());
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
if (z != NULL) {
|
|
|
|
_localFlags[_vm->_currentLocationIndex] |= kFlagsEnter;
|
|
|
|
runCommands(z->_commands, z);
|
|
|
|
_localFlags[_vm->_currentLocationIndex] &= ~kFlagsEnter;
|
|
|
|
_zoneTrap = z;
|
|
|
|
} else
|
|
|
|
if (_zoneTrap != NULL) {
|
|
|
|
_localFlags[_vm->_currentLocationIndex] |= kFlagsExit;
|
|
|
|
runCommands(_zoneTrap->_commands, _zoneTrap);
|
|
|
|
_localFlags[_vm->_currentLocationIndex] &= ~kFlagsExit;
|
|
|
|
_zoneTrap = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// printf("done\n");
|
|
|
|
|
2007-03-17 07:55:16 +00:00
|
|
|
_vm->_char._ani._frame = walkData2;
|
|
|
|
return _vm->_char._ani._frame;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-03-12 22:52:27 +00:00
|
|
|
uint16 queryPath(uint16 x, uint16 y) {
|
|
|
|
|
|
|
|
byte _al = _buffer[y*40 + x/8];
|
|
|
|
byte _dl = 1 << (x % 8);
|
|
|
|
|
|
|
|
return _al & _dl;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void setPath(byte *path) {
|
|
|
|
memcpy(_buffer, path, SCREENPATH_WIDTH*SCREEN_HEIGHT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void initWalk() {
|
|
|
|
_buffer = (byte*)malloc(SCREENPATH_WIDTH * SCREEN_HEIGHT);
|
|
|
|
}
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
} // namespace Parallaction
|
|
|
|
|
2007-03-18 20:18:19 +00:00
|
|
|
|