33
33
// Find shortest route from hero to destination
35
#include "common/debug.h"
35
36
#include "common/system.h"
37
38
#include "hugo/hugo.h"
38
39
#include "hugo/game.h"
39
40
#include "hugo/route.h"
40
#include "hugo/global.h"
41
#include "hugo/object.h"
42
#include "hugo/inventory.h"
43
#include "hugo/mouse.h"
43
Route::Route(HugoEngine &vm) : _vm(vm) {
46
// Face hero in new direction, based on cursor key input by user.
47
void Route::setDirection(uint16 keyCode) {
48
object_t *obj = _vm._hero; // Pointer to hero object
46
Route::Route(HugoEngine *vm) : _vm(vm) {
47
_oldWalkDirection = 0;
48
_routeIndex = -1; // Hero not following a route
49
_routeType = kRouteSpace; // Hero walking to space
50
_routeObjId = -1; // Hero not walking to anything
53
void Route::resetRoute() {
57
int16 Route::getRouteIndex() const {
62
* Face hero in new direction, based on cursor key input by user.
64
void Route::setDirection(const uint16 keyCode) {
50
65
debugC(1, kDebugRoute, "setDirection(%d)", keyCode);
67
object_t *obj = _vm->_hero; // Pointer to hero object
52
69
// Set first image in sequence
54
71
case Common::KEYCODE_UP:
72
case Common::KEYCODE_KP8:
55
73
obj->currImagePtr = obj->seqList[_UP].seqPtr;
57
75
case Common::KEYCODE_DOWN:
76
case Common::KEYCODE_KP2:
58
77
obj->currImagePtr = obj->seqList[DOWN].seqPtr;
60
79
case Common::KEYCODE_LEFT:
80
case Common::KEYCODE_KP4:
61
81
obj->currImagePtr = obj->seqList[LEFT].seqPtr;
63
83
case Common::KEYCODE_RIGHT:
84
case Common::KEYCODE_KP6:
64
85
obj->currImagePtr = obj->seqList[RIGHT].seqPtr;
66
87
case Common::KEYCODE_HOME:
88
case Common::KEYCODE_KP7:
67
89
obj->currImagePtr = obj->seqList[LEFT].seqPtr;
69
91
case Common::KEYCODE_END:
92
case Common::KEYCODE_KP1:
70
93
obj->currImagePtr = obj->seqList[LEFT].seqPtr;
72
// case Common::KEYCODE_PRIOR:
73
// obj->currImagePtr = obj->seqList[RIGHT].seqPtr;
75
// case Common::KEYCODE_NEXT:
76
// obj->currImagePtr = obj->seqList[RIGHT].seqPtr;
95
case Common::KEYCODE_PAGEUP:
96
case Common::KEYCODE_KP9:
97
obj->currImagePtr = obj->seqList[RIGHT].seqPtr;
99
case Common::KEYCODE_PAGEDOWN:
100
case Common::KEYCODE_KP3:
101
obj->currImagePtr = obj->seqList[RIGHT].seqPtr;
81
// Set hero walking, based on cursor key input by user.
82
// Hitting same key twice will stop hero.
83
void Route::setWalk(uint16 direction) {
84
object_t *obj = _vm._hero; // Pointer to hero object
85
static uint16 oldDirection = 0; // Last direction char
107
* Set hero walking, based on cursor key input by user.
108
* Hitting same key twice will stop hero.
110
void Route::setWalk(const uint16 direction) {
87
111
debugC(1, kDebugRoute, "setWalk(%d)", direction);
89
if (_vm.getGameStatus().storyModeFl || obj->pathType != USER) // Make sure user has control
113
object_t *obj = _vm->_hero; // Pointer to hero object
115
if (_vm->getGameStatus().storyModeFl || obj->pathType != kPathUser) // Make sure user has control
92
118
if (!obj->vx && !obj->vy)
93
oldDirection = 0; // Fix for consistant restarts
119
_oldWalkDirection = 0; // Fix for consistant restarts
95
if (direction != oldDirection) {
121
if (direction != _oldWalkDirection) {
96
122
// Direction has changed
97
123
setDirection(direction); // Face new direction
98
124
obj->vx = obj->vy = 0;
99
125
switch (direction) { // And set correct velocity
100
126
case Common::KEYCODE_UP:
127
case Common::KEYCODE_KP8:
103
130
case Common::KEYCODE_DOWN:
131
case Common::KEYCODE_KP2:
106
134
case Common::KEYCODE_LEFT:
135
case Common::KEYCODE_KP4:
109
138
case Common::KEYCODE_RIGHT:
139
case Common::KEYCODE_KP6:
112
142
case Common::KEYCODE_HOME:
143
case Common::KEYCODE_KP7:
145
// Note: in v1 Dos and v2 Dos, obj->vy is set to DY
146
obj->vy = -kStepDy / 2;
116
148
case Common::KEYCODE_END:
120
// case Common::KEYCODE_PRIOR:
122
// obj->vy = -DY / 2;
124
// case Common::KEYCODE_NEXT:
149
case Common::KEYCODE_KP1:
151
// Note: in v1 Dos and v2 Dos, obj->vy is set to -DY
152
obj->vy = kStepDy / 2;
154
case Common::KEYCODE_PAGEUP:
155
case Common::KEYCODE_KP9:
157
// Note: in v1 Dos and v2 Dos, obj->vy is set to -DY
158
obj->vy = -kStepDy / 2;
160
case Common::KEYCODE_PAGEDOWN:
161
case Common::KEYCODE_KP3:
163
// Note: in v1 Dos and v2 Dos, obj->vy is set to DY
164
obj->vy = kStepDy / 2;
129
oldDirection = direction;
130
obj->cycling = CYCLE_FORWARD;
167
_oldWalkDirection = direction;
168
obj->cycling = kCycleForward;
132
170
// Same key twice - halt hero
136
obj->cycling = NOT_CYCLING;
173
_oldWalkDirection = 0;
174
obj->cycling = kCycleNotCycling;
140
// Recursive algorithm! Searches from hero to dest_x, dest_y
141
// Find horizontal line segment about supplied point and recursively
142
// find line segments for each point above and below that segment.
143
// When destination point found in segment, start surfacing and leave
144
// a trail in segment[] from destination back to hero.
146
// Note: there is a bug which allows a route through a 1-pixel high
147
// narrow gap if between 2 segments wide enough for hero. To work
148
// around this, make sure any narrow gaps are 2 or more pixels high.
149
// An example of this was the blocking guard in Hugo1/Dead-End.
179
* Recursive algorithm! Searches from hero to dest_x, dest_y
180
* Find horizontal line segment about supplied point and recursively
181
* find line segments for each point above and below that segment.
182
* When destination point found in segment, start surfacing and leave
183
* a trail in segment[] from destination back to hero.
185
* Note: there is a bug which allows a route through a 1-pixel high
186
* narrow gap if between 2 segments wide enough for hero. To work
187
* around this, make sure any narrow gaps are 2 or more pixels high.
188
* An example of this was the blocking guard in Hugo1/Dead-End.
150
190
void Route::segment(int16 x, int16 y) {
151
int16 x1, x2; // Range of segment
152
// Note use of static - can't waste stack
191
debugC(1, kDebugRoute, "segment(%d, %d)", x, y);
193
// Note: use of static - can't waste stack
153
194
static image_pt p; // Ptr to _boundaryMap[y]
154
195
static segment_t *seg_p; // Ptr to segment
156
debugC(1, kDebugRoute, "segment(%d, %d)", x, y);
158
197
// Bomb out if stack exhausted
159
198
// Vinterstum: Is this just a safeguard, or actually used?
160
199
//_fullStackFl = _stackavail () < 256;
184
228
_routeFoundFl = true;
186
230
// Bounds check y in case no boundary around screen
187
if (y <= 0 || y >= YPIX - 1)
231
if (y <= 0 || y >= kYPix - 1)
190
if (_vm._hero->x < x1) {
191
// Hero x not in segment, search x1..x2
192
// Find all segments above current
193
for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++)
194
if (_boundaryMap[y - 1][x] == 0)
197
// Find all segments below current
198
for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++)
199
if (_boundaryMap[y + 1][x] == 0)
201
} else if (_vm._hero->x + HERO_MAX_WIDTH > x2) {
202
// Hero x not in segment, search x1..x2
203
// Find all segments above current
204
for (x = x2; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x >= x1; x--)
205
if (_boundaryMap[y - 1][x] == 0)
208
// Find all segments below current
209
for (x = x2; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x >= x1; x--)
210
if (_boundaryMap[y + 1][x] == 0)
234
if (_vm->_hero->x < x1) {
235
// Hero x not in segment, search x1..x2
236
// Find all segments above current
237
for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) {
238
if (_boundaryMap[y - 1][x] == 0)
242
// Find all segments below current
243
for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) {
244
if (_boundaryMap[y + 1][x] == 0)
247
} else if (_vm->_hero->x + kHeroMaxWidth > x2) {
248
// Hero x not in segment, search x1..x2
249
// Find all segments above current
250
for (x = x2; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x >= x1; x--) {
251
if (_boundaryMap[y - 1][x] == 0)
255
// Find all segments below current
256
for (x = x2; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x >= x1; x--) {
257
if (_boundaryMap[y + 1][x] == 0)
213
261
// Organize search around hero x position - this gives
214
262
// better chance for more direct route.
215
for (x = _vm._hero->x; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++)
216
if (_boundaryMap[y - 1][x] == 0)
218
for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x < _vm._hero->x; x++)
219
if (_boundaryMap[y - 1][x] == 0)
221
for (x = _vm._hero->x; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++)
222
if (_boundaryMap[y + 1][x] == 0)
224
for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x < _vm._hero->x; x++)
225
if (_boundaryMap[y + 1][x] == 0)
263
for (x = _vm->_hero->x; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) {
264
if (_boundaryMap[y - 1][x] == 0)
268
for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x < _vm->_hero->x; x++) {
269
if (_boundaryMap[y - 1][x] == 0)
273
for (x = _vm->_hero->x; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) {
274
if (_boundaryMap[y + 1][x] == 0)
278
for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x < _vm->_hero->x; x++) {
279
if (_boundaryMap[y + 1][x] == 0)
229
284
// If found, surface, leaving trail back to hero
230
285
if (_routeFoundFl) {
231
286
// Bomb out if too many segments (leave one spare)
232
if (_segmentNumb >= kMaxSeg - 1)
287
if (_segmentNumb >= kMaxSeg - 1) {
233
288
_fullSegmentFl = true;
235
290
// Create segment
236
291
seg_p = &_segment[_segmentNumb];
245
// Create and return ptr to new node. Initialize with previous node.
246
// Returns NULL if MAX_NODES exceeded
301
* Create and return ptr to new node. Initialize with previous node.
302
* Returns 0 if MAX_NODES exceeded
247
304
Point *Route::newNode() {
248
305
debugC(1, kDebugRoute, "newNode");
250
308
if (_routeListIndex >= kMaxNodes) // Too many nodes
251
return(NULL); // Incomplete route - failure
309
return 0; // Incomplete route - failure
253
311
_route[_routeListIndex] = _route[_routeListIndex - 1]; // Initialize with previous node
254
return(&_route[_routeListIndex]);
312
return &_route[_routeListIndex];
257
// Construct route to cx, cy. Return TRUE if successful.
258
// 1. Copy boundary bitmap to local byte map (include object bases)
259
// 2. Construct list of segments segment[] from hero to destination
260
// 3. Compress to shortest route in route[]
261
bool Route::findRoute(int16 cx, int16 cy) {
262
int16 i, j, x, y; // Loop on coordinates
263
int16 x1, x2, dx; // Overlap between segments
264
int16 herox1, herox2, heroy; // Current hero baseline
265
object_t *obj; // Ptr to object
266
segment_t *seg_p; // Ptr to segment
267
Point *routeNode; // Ptr to route node
316
* Construct route to cx, cy. Return TRUE if successful.
317
* 1. Copy boundary bitmap to local byte map (include object bases)
318
* 2. Construct list of segments segment[] from hero to destination
319
* 3. Compress to shortest route in route[]
321
bool Route::findRoute(const int16 cx, const int16 cy) {
269
322
debugC(1, kDebugRoute, "findRoute(%d, %d)", cx, cy);
271
324
// Initialize for search
273
326
_fullStackFl = false; // Stack not exhausted
274
327
_fullSegmentFl = false; // Segments not exhausted
275
328
_segmentNumb = 0; // Segment index
276
_heroWidth = HERO_MIN_WIDTH; // Minimum width of hero
329
_heroWidth = kHeroMinWidth; // Minimum width of hero
277
330
_destY = cy; // Destination coords
278
331
_destX = cx; // Destination coords
279
herox1 = _vm._hero->x + _vm._hero->currImagePtr->x1; // Hero baseline
280
herox2 = _vm._hero->x + _vm._hero->currImagePtr->x2; // Hero baseline
281
heroy = _vm._hero->y + _vm._hero->currImagePtr->y2; // Hero baseline
333
int16 herox1 = _vm->_hero->x + _vm->_hero->currImagePtr->x1; // Hero baseline
334
int16 herox2 = _vm->_hero->x + _vm->_hero->currImagePtr->x2; // Hero baseline
335
int16 heroy = _vm->_hero->y + _vm->_hero->currImagePtr->y2; // Hero baseline
283
337
// Store all object baselines into objbound (except hero's = [0])
284
for (i = 1, obj = &_vm._objects[i]; i < _vm._numObj; i++, obj++)
285
if ((obj->screenIndex == *_vm._screen_p) && (obj->cycling != INVISIBLE) && (obj->priority == FLOATING))
286
_vm.storeBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2);
338
object_t *obj; // Ptr to object
340
for (i = 1, obj = &_vm->_object->_objects[i]; i < _vm->_object->_numObj; i++, obj++) {
341
if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling != kCycleInvisible) && (obj->priority == kPriorityFloating))
342
_vm->_object->storeBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2);
288
345
// Combine objbound and boundary bitmaps to local byte map
289
for (y = 0; y < YPIX; y++)
290
for (x = 0; x < XBYTES; x++)
346
for (uint16 y = 0; y < kYPix; y++) {
347
for (uint16 x = 0; x < kCompLineSize; x++) {
348
uint16 boundIdx = y * kCompLineSize + x;
291
349
for (i = 0; i < 8; i++)
292
_boundaryMap[y][x * 8 + i] = ((_vm.getObjectBoundaryOverlay()[y * XBYTES + x] | _vm.getBoundaryOverlay()[y * XBYTES + x]) & (0x80 >> i)) ? kMapBound : 0;
350
_boundaryMap[y][x * 8 + i] = ((_vm->_object->getObjectBoundary(boundIdx) | _vm->_object->getBoundaryOverlay(boundIdx)) & (0x80 >> i)) ? kMapBound : 0;
294
354
// Clear all object baselines from objbound
295
for (i = 0, obj = _vm._objects; i < _vm._numObj; i++, obj++)
296
if ((obj->screenIndex == *_vm._screen_p) && (obj->cycling != INVISIBLE) && (obj->priority == FLOATING))
297
_vm.clearBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2);
355
for (i = 0, obj = _vm->_object->_objects; i < _vm->_object->_numObj; i++, obj++) {
356
if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling != kCycleInvisible) && (obj->priority == kPriorityFloating))
357
_vm->_object->clearBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2);
299
360
// Search from hero to destination
300
361
segment(herox1, heroy);
302
363
// Not found or not enough stack or MAX_SEG exceeded
303
364
if (!_routeFoundFl || _fullStackFl || _fullSegmentFl) {
307
368
// Now find the route of nodes from destination back to hero
315
376
_segment[_segmentNumb].x2 = herox2;
379
Point *routeNode; // Ptr to route node
318
380
// Look in segments[] for straight lines from destination to hero
319
381
for (i = 0, _routeListIndex = 0; i < _segmentNumb - 1; i++) {
320
if ((routeNode = newNode()) == NULL) // New node for new segment
321
return(false); // Too many nodes
382
if ((routeNode = newNode()) == 0) // New node for new segment
383
return false; // Too many nodes
322
384
routeNode->y = _segment[i].y;
324
386
// Look ahead for furthest straight line
325
for (j = i + 1; j < _segmentNumb; j++) {
326
seg_p = &_segment[j];
387
for (int16 j = i + 1; j < _segmentNumb; j++) {
388
segment_t *seg_p = &_segment[j];
327
389
// Can we get to this segment from previous node?
328
if (seg_p->x1 <= routeNode->x && seg_p->x2 >= routeNode->x + _heroWidth - 1)
390
if (seg_p->x1 <= routeNode->x && seg_p->x2 >= routeNode->x + _heroWidth - 1) {
329
391
routeNode->y = seg_p->y; // Yes, keep updating node
331
393
// No, create another node on previous segment to reach it
332
if ((routeNode = newNode()) == NULL) // Add new route node
333
return (false); // Too many nodes
394
if ((routeNode = newNode()) == 0) // Add new route node
395
return false; // Too many nodes
335
397
// Find overlap between old and new segments
336
x1 = MAX(_segment[j - 1].x1, seg_p->x1);
337
x2 = MIN(_segment[j - 1].x2, seg_p->x2);
398
int16 x1 = MAX(_segment[j - 1].x1, seg_p->x1);
399
int16 x2 = MIN(_segment[j - 1].x2, seg_p->x2);
339
401
// If room, add a little offset to reduce staircase effect
340
dx = HERO_MAX_WIDTH >> 1;
402
int16 dx = kHeroMaxWidth >> 1;
341
403
if (x2 - x1 < _heroWidth + dx)
365
// Process hero in route mode - called from Move_objects()
428
* Process hero in route mode - called from Move_objects()
366
430
void Route::processRoute() {
367
int16 herox, heroy; // Hero position
368
Point *routeNode; // Ptr to current route node
431
debugC(1, kDebugRoute, "processRoute");
369
433
static bool turnedFl = false; // Used to get extra cylce for turning
371
status_t &gameStatus = _vm.getGameStatus();
373
debugC(1, kDebugRoute, "processRoute");
375
438
// Current hero position
376
herox = _vm._hero->x + _vm._hero->currImagePtr->x1;
377
heroy = _vm._hero->y + _vm._hero->currImagePtr->y2;
378
routeNode = &_route[gameStatus.routeIndex];
439
int16 herox = _vm->_hero->x + _vm->_hero->currImagePtr->x1;
440
int16 heroy = _vm->_hero->y + _vm->_hero->currImagePtr->y2;
441
Point *routeNode = &_route[_routeIndex];
380
443
// Arrived at node?
381
if (abs(herox - routeNode->x) < DX + 1 && abs(heroy - routeNode->y) < DY) {
444
if (abs(herox - routeNode->x) < kStepDx + 1 && abs(heroy - routeNode->y) < kStepDy) {
383
446
// Close enough - position hero exactly
384
_vm._hero->x = _vm._hero->oldx = routeNode->x - _vm._hero->currImagePtr->x1;
385
_vm._hero->y = _vm._hero->oldy = routeNode->y - _vm._hero->currImagePtr->y2;
386
_vm._hero->vx = _vm._hero->vy = 0;
387
_vm._hero->cycling = NOT_CYCLING;
447
_vm->_hero->x = _vm->_hero->oldx = routeNode->x - _vm->_hero->currImagePtr->x1;
448
_vm->_hero->y = _vm->_hero->oldy = routeNode->y - _vm->_hero->currImagePtr->y2;
449
_vm->_hero->vx = _vm->_hero->vy = 0;
450
_vm->_hero->cycling = kCycleNotCycling;
389
452
// Arrived at final node?
390
if (--gameStatus.routeIndex < 0) {
453
if (--_routeIndex < 0) {
391
454
// See why we walked here
392
switch (gameStatus.go_for) {
393
case GO_EXIT: // Walked to an exit, proceed into it
394
setWalk(_vm._hotspots[gameStatus.go_id].direction);
396
case GO_LOOK: // Look at an object
398
_vm.lookObject(&_vm._objects[gameStatus.go_id]);
401
setDirection(_vm._objects[gameStatus.go_id].direction);
402
gameStatus.routeIndex++; // Come round again
406
case GO_GET: // Get (or use) an object
408
_vm.useObject(gameStatus.go_id);
411
setDirection(_vm._objects[gameStatus.go_id].direction);
412
gameStatus.routeIndex++; // Come round again
417
warning("Unhandled gameStatus.go_for GO_STATUS");
455
switch (_routeType) {
456
case kRouteExit: // Walked to an exit, proceed into it
457
setWalk(_vm->_mouse->getDirection(_routeObjId));
459
case kRouteLook: // Look at an object
461
_vm->_object->lookObject(&_vm->_object->_objects[_routeObjId]);
464
setDirection(_vm->_object->_objects[_routeObjId].direction);
465
_routeIndex++; // Come round again
469
case kRouteGet: // Get (or use) an object
471
_vm->_object->useObject(_routeObjId);
474
setDirection(_vm->_object->_objects[_routeObjId].direction);
475
_routeIndex++; // Come round again
421
} else if (_vm._hero->vx == 0 && _vm._hero->vy == 0) {
483
} else if (_vm->_hero->vx == 0 && _vm->_hero->vy == 0) {
422
484
// Set direction of travel if at a node
423
485
// Note realignment when changing to (thinner) up/down sprite,
424
486
// otherwise hero could bump into boundaries along route.
425
if (herox < routeNode->x)
487
if (herox < routeNode->x) {
426
488
setWalk(Common::KEYCODE_RIGHT);
427
else if (herox > routeNode->x)
489
} else if (herox > routeNode->x) {
428
490
setWalk(Common::KEYCODE_LEFT);
429
else if (heroy < routeNode->y) {
491
} else if (heroy < routeNode->y) {
430
492
setWalk(Common::KEYCODE_DOWN);
431
_vm._hero->x = _vm._hero->oldx = routeNode->x - _vm._hero->currImagePtr->x1;
493
_vm->_hero->x = _vm->_hero->oldx = routeNode->x - _vm->_hero->currImagePtr->x1;
432
494
} else if (heroy > routeNode->y) {
433
495
setWalk(Common::KEYCODE_UP);
434
_vm._hero->x = _vm._hero->oldx = routeNode->x - _vm._hero->currImagePtr->x1;
496
_vm->_hero->x = _vm->_hero->oldx = routeNode->x - _vm->_hero->currImagePtr->x1;
439
// Start a new route from hero to cx, cy
440
// go_for is the purpose, id indexes the exit or object to walk to
441
// Returns FALSE if route not found
442
bool Route::startRoute(go_t go_for, int16 id, int16 cx, int16 cy) {
443
bool foundFl = false; // TRUE if route found ok
445
status_t &gameStatus = _vm.getGameStatus();
447
debugC(1, kDebugRoute, "startRoute(%d, %d, %d, %d)", go_for, id, cx, cy);
502
* Start a new route from hero to cx, cy
503
* go_for is the purpose, id indexes the exit or object to walk to
504
* Returns FALSE if route not found
506
bool Route::startRoute(const go_t routeType, const int16 objId, int16 cx, int16 cy) {
507
debugC(1, kDebugRoute, "startRoute(%d, %d, %d, %d)", routeType, objId, cx, cy);
449
509
// Don't attempt to walk if user does not have control
450
if (_vm._hero->pathType != USER)
510
if (_vm->_hero->pathType != kPathUser)
453
513
// if inventory showing, make it go away
454
if (gameStatus.inventoryState != I_OFF)
455
gameStatus.inventoryState = I_UP;
514
if (_vm->_inventory->getInventoryState() != kInventoryOff)
515
_vm->_inventory->setInventoryState(kInventoryUp);
457
gameStatus.go_for = go_for; // Purpose of trip
458
gameStatus.go_id = id; // Index of exit/object
517
_routeType = routeType; // Purpose of trip
518
_routeObjId = objId; // Index of exit/object
460
520
// Adjust destination to center hero if walking to cursor
461
if (gameStatus.go_for == GO_SPACE)
462
cx -= HERO_MIN_WIDTH / 2;
521
if (_routeType == kRouteSpace)
522
cx -= kHeroMinWidth / 2;
524
bool foundFl = false; // TRUE if route found ok
464
525
if ((foundFl = findRoute(cx, cy))) { // Found a route?
465
gameStatus.routeIndex = _routeListIndex; // Node index
466
_vm._hero->vx = _vm._hero->vy = 0; // Stop manual motion
526
_routeIndex = _routeListIndex; // Node index
527
_vm->_hero->vx = _vm->_hero->vy = 0; // Stop manual motion