aboutsummaryrefslogtreecommitdiff
path: root/sword2/router.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sword2/router.cpp')
-rw-r--r--sword2/router.cpp2506
1 files changed, 0 insertions, 2506 deletions
diff --git a/sword2/router.cpp b/sword2/router.cpp
deleted file mode 100644
index bbca609e3c..0000000000
--- a/sword2/router.cpp
+++ /dev/null
@@ -1,2506 +0,0 @@
-/* Copyright (C) 1994-1998 Revolution Software Ltd.
- * Copyright (C) 2003-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$
- */
-
-// ---------------------------------------------------------------------------
-// ROUTER.CPP by James
-//
-// A rehash of Jeremy's original jrouter.c, containing low-level system
-// routines for calculating routes between points inside a walk-grid, and
-// constructing walk animations from mega-sets.
-//
-// jrouter.c underwent 2 major reworks from the original:
-// (1) Restructured to allow more flexibility in the mega-sets, ie. more info
-// taken from the walk-data
-// - the new George & Nico mega-sets & walk-data were then tested &
-// tweaked in the Sword1 system
-// (2) Updated for the new Sword2 system, ie. new object structures
-// - now compatible with Sword2, the essential code already having been
-// tested
-//
-// ---------------------------------------------------------------------------
-
-/****************************************************************************
- * JROUTER.C polygon router with modular walks
- * using a tree of modules
- * 21 july 94
- * 3 november 94
- * System currently works by scanning grid data and coming up with a ROUTE
- * as a series of way points(nodes), the smoothest eight directional PATH
- * through these nodes is then found, and a WALK created to fit the PATH.
- *
- * Two funtions are called by the user, RouteFinder creates a route as a
- * module list, HardWalk creates an animation list from the module list.
- * The split is only provided to allow the possibility of turning the
- * autorouter over two game cycles.
- ****************************************************************************
- *
- * Routine timings on osborne 486
- *
- * Read floor resource (file already loaded) 112 pixels
- *
- * Read mega resource (file already loaded) 112 pixels
- *
- *
- *
- ****************************************************************************
- *
- * Modified 12 Oct 95
- *
- * Target Points within 1 pixel of a line are ignored ???
- *
- * Modules split into Points within 1 pixel of a line are ignored ???
- *
- ****************************************************************************
- *
- * TOTALLY REHASHED BY JAMES FOR NEW MEGAS USING OLD SYSTEM
- * THEN REINCARNATED BY JAMES FOR NEW MEGAS USING NEW SYSTEM
- *
- ****************************************************************************/
-
-#include "common/stdafx.h"
-#include "common/stream.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-
-namespace Sword2 {
-
-//----------------------------------------------------------
-// (4) WALK-GRID FILES
-//----------------------------------------------------------
-// a walk-grid file consists of:
-//
-// standard file header
-// walk-grid file header
-// walk-grid data
-
-// Walk-Grid Header - taken directly from old "header.h" in STD_INC
-
-struct WalkGridHeader {
- int32 numBars; // number of bars on the floor
- int32 numNodes; // number of nodes
-};
-
-uint8 Router::returnSlotNo(uint32 megaId) {
- if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) {
- // George (8)
- return 0;
- } else {
- // One of Nico's mega id's
- return 1;
- }
-}
-
-void Router::allocateRouteMem() {
- uint8 slotNo;
-
- // Player character always always slot 0, while the other mega
- // (normally Nico) always uses slot 1
- // Better this way, so that if mega object removed from memory while
- // in middle of route, the old route will be safely cleared from
- // memory just before they create a new one
-
- slotNo = returnSlotNo(_vm->_logic->readVar(ID));
-
- // if this slot is already used, then it can't be needed any more
- // because this id is creating a new route!
-
- if (_routeSlots[slotNo])
- freeRouteMem();
-
- _routeSlots[slotNo] = (WalkData *)malloc(sizeof(WalkData) * O_WALKANIM_SIZE);
-
- // 12000 bytes were used for this in Sword1 mega compacts, based on
- // 20 bytes per 'WalkData' frame
- // ie. allowing for 600 frames including end-marker
- // Now 'WalkData' is 8 bytes, so 8*600 = 4800 bytes.
- // Note that a 600 frame walk lasts about 48 seconds!
- // (600fps / 12.5s = 48s)
-
- // mega keeps note of which slot contains the pointer to it's walk
- // animation mem block
- // +1 so that '0' can mean "not walking"
- // megaObject->route_slot_id = slotNo + 1;
-}
-
-WalkData *Router::getRouteMem() {
- uint8 slotNo = returnSlotNo(_vm->_logic->readVar(ID));
-
- return (WalkData *)_routeSlots[slotNo];
-}
-
-void Router::freeRouteMem() {
- uint8 slotNo = returnSlotNo(_vm->_logic->readVar(ID));
-
- free(_routeSlots[slotNo]);
- _routeSlots[slotNo] = NULL;
-}
-
-void Router::freeAllRouteMem() {
- for (int i = 0; i < TOTAL_ROUTE_SLOTS; i++) {
- free(_routeSlots[i]);
- _routeSlots[i] = NULL;
- }
-}
-
-int32 Router::routeFinder(byte *ob_mega, byte *ob_walkdata, int32 x, int32 y, int32 dir) {
- /*********************************************************************
- * RouteFinder.C polygon router with modular walks
- * 21 august 94
- * 3 november 94
- * routeFinder creates a list of modules that enables HardWalk to
- * create an animation list.
- *
- * routeFinder currently works by scanning grid data and coming up
- * with a ROUTE as a series of way points(nodes), the smoothest eight
- * directional PATH through these nodes is then found, this
- * information is made available to HardWalk for a WALK to be created
- * to fit the PATH.
- *
- * 30 november 94 return values modified
- *
- * return 0 = failed to find a route
- *
- * 1 = found a route
- *
- * 2 = mega already at target
- *
- *********************************************************************/
-
- int32 routeFlag = 0;
- int32 solidFlag = 0;
- WalkData *walkAnim;
-
- // megaId = id;
-
- setUpWalkGrid(ob_mega, x, y, dir);
- loadWalkData(ob_walkdata);
-
- walkAnim = getRouteMem();
-
- // All route data now loaded start finding a route
-
- // Check if we can get a route through the floor. changed 12 Oct95 JPS
-
- routeFlag = getRoute();
-
- switch (routeFlag) {
- case 2:
- // special case for zero length route
-
- // if target direction specified as any
- if (_targetDir > 7)
- _targetDir = _startDir;
-
- // just a turn on the spot is required set an end module for
- // the route let the animator deal with it
- // modularPath is normally set by extractRoute
-
- _modularPath[0].dir = _startDir;
- _modularPath[0].num = 0;
- _modularPath[0].x = _startX;
- _modularPath[0].y = _startY;
- _modularPath[1].dir = _targetDir;
- _modularPath[1].num = 0;
- _modularPath[1].x = _startX;
- _modularPath[1].y = _startY;
- _modularPath[2].dir = 9;
- _modularPath[2].num = ROUTE_END_FLAG;
-
- slidyWalkAnimator(walkAnim);
- routeFlag = 2;
- break;
- case 1:
- // A normal route. Convert the route to an exact path
- smoothestPath();
-
- // The Route had waypoints and direction options
-
- // The Path is an exact set of lines in 8 directions that
- // reach the target.
-
- // The path is in module format, but steps taken in each
- // direction are not accurate
-
- // if target dir = 8 then the walk isn't linked to an anim so
- // we can create a route without sliding and miss the exact
- // target
-
-#ifndef FORCE_SLIDY
- if (_targetDir == 8) {
- // can end facing ANY direction (ie. exact end
- // position not vital) - so use SOLID walk to
- // avoid sliding to exact position
-
- solidPath();
- solidFlag = solidWalkAnimator(walkAnim);
- }
-#endif
-
- if (!solidFlag) {
- // if we failed to create a SOLID route, do a SLIDY
- // one instead
-
- slidyPath();
- slidyWalkAnimator(walkAnim);
- }
-
- break;
- default:
- // Route didn't reach target so assume point was off the floor
- // routeFlag = 0;
- break;
- }
-
- return routeFlag; // send back null route
-}
-
-int32 Router::getRoute() {
- /*********************************************************************
- * GetRoute.C extract a path from walk grid
- * 12 october 94
- *
- * GetRoute currently works by scanning grid data and coming up with
- * a ROUTE as a series of way points(nodes).
- *
- * static routeData _route[O_ROUTE_SIZE];
- *
- * return 0 = failed to find a route
- *
- * 1 = found a route
- *
- * 2 = mega already at target
- *
- * 3 = failed to find a route because target was on a line
- *
- *********************************************************************/
-
- int32 routeGot = 0;
-
- if (_startX == _targetX && _startY == _targetY)
- routeGot = 2;
- else {
- // 'else' added by JEL (23jan96) otherwise 'routeGot' affected
- // even when already set to '2' above - causing some 'turns'
- // to walk downwards on the spot
-
- // returns 3 if target on a line ( +- 1 pixel )
- routeGot = checkTarget(_targetX, _targetY);
- }
-
- if (routeGot == 0) {
- // still looking for a route check if target is within a pixel
- // of a line
-
- // scan through the nodes linking each node to its nearest
- // neighbour until no more nodes change
-
- // This is the routine that finds a route using scan()
-
- int32 level = 1;
-
- while (scan(level))
- level++;
-
- // Check to see if the route reached the target
-
- if (_node[_nNodes].dist < 9999) {
- // it did so extract the route as nodes and the
- // directions to go between each node
-
- routeGot = 1;
- extractRoute();
-
- // route.X,route.Y and route.Dir now hold all the
- // route infomation with the target dir or route
- // continuation
- }
- }
-
- return routeGot;
-}
-
-// THE SLIDY PATH ROUTINES
-
-int32 Router::smoothestPath() {
- // This is the second big part of the route finder and the the only
- // bit that tries to be clever (the other bits are clever).
- //
- // This part of the autorouter creates a list of modules from a set of
- // lines running across the screen. The task is complicated by two
- // things:
- //
- // Firstly in choosing a route through the maze of nodes the routine
- // tries to minimise the amount of each individual turn avoiding 90
- // degree and greater turns (where possible) and reduces the total
- // number of turns (subject to two 45 degree turns being better than
- // one 90 degree turn).
- //
- // Secondly when walking in a given direction the number of steps
- // required to reach the end of that run is not calculated accurately.
- // This is because I was unable to derive a function to relate number
- // of steps taken between two points to the shrunken step size
-
- int i;
- int32 steps = 0;
- int32 lastDir;
- int32 tempturns[4];
- int32 turns[4];
- int32 turntable[NO_DIRECTIONS] = { 0, 1, 3, 5, 7, 5, 3, 1 };
-
- // route.X route.Y and route.Dir start at far end
-
- _smoothPath[0].x = _startX;
- _smoothPath[0].y = _startY;
- _smoothPath[0].dir = _startDir;
- _smoothPath[0].num = 0;
-
- lastDir = _startDir;
-
- // for each section of the route
-
- for (int p = 0; p < _routeLength; p++) {
- int32 dirS = _route[p].dirS;
- int32 dirD = _route[p].dirD;
- int32 nextDirS = _route[p + 1].dirS;
- int32 nextDirD = _route[p + 1].dirD;
-
- // Check directions into and out of a pair of nodes going in
- int32 dS = dirS - lastDir;
- if (dS < 0)
- dS = dS + NO_DIRECTIONS;
-
- int32 dD = dirD - lastDir;
- if (dD < 0)
- dD = dD + NO_DIRECTIONS;
-
- // coming out
- int32 dSS = dirS - nextDirS;
- if (dSS < 0)
- dSS = dSS + NO_DIRECTIONS;
-
- int32 dDD = dirD - nextDirD;
- if (dDD < 0)
- dDD = dDD + NO_DIRECTIONS;
-
- int32 dSD = dirS - nextDirD;
- if (dSD < 0)
- dSD = dSD + NO_DIRECTIONS;
-
- int32 dDS = dirD - nextDirS;
- if (dDS < 0)
- dDS = dDS + NO_DIRECTIONS;
-
- // Determine the amount of turning involved in each possible
- // path
-
- dS = turntable[dS];
- dD = turntable[dD];
- dSS = turntable[dSS];
- dDD = turntable[dDD];
- dSD = turntable[dSD];
- dDS = turntable[dDS];
-
- // get the best path out ie assume next section uses best
- // direction
-
- if (dSD < dSS)
- dSS = dSD;
-
- if (dDS < dDD)
- dDD = dDS;
-
- // Rate each option. Split routes look crap so weight against
- // them
-
- int32 SS = dS + dSS + 3;
- int32 SD = dS + dDD;
- int32 DS = dD + dSS;
- int32 DD = dD + dDD + 3;
-
- // set up turns as a sorted array of the turn values
-
- tempturns[0] = SS;
- turns[0] = 0;
- tempturns[1] = SD;
- turns[1] = 1;
- tempturns[2] = DS;
- turns[2] = 2;
- tempturns[3] = DD;
- turns[3] = 3;
-
- for (i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- if (tempturns[j] > tempturns[j + 1]) {
- SWAP(turns[j], turns[j + 1]);
- SWAP(tempturns[j], tempturns[j + 1]);
- }
- }
- }
-
- // best option matched in order of the priority we would like
- // to see on the screen but each option must be checked to see
- // if it can be walked
-
- int32 options = newCheck(1, _route[p].x, _route[p].y, _route[p + 1].x, _route[p + 1].y);
-
- assert(options);
-
- i = 0;
- steps = 0;
-
- do {
- int32 opt = 1 << turns[i];
- if (options & opt)
- steps = smoothCheck(turns[i], p, dirS, dirD);
- i++;
- } while (steps == 0 && i < 4);
-
- assert(steps);
-
- // route.X route.Y route.dir and bestTurns start at far end
- }
-
- // best turns will end heading as near as possible to target dir rest
- // is down to anim for now
-
- _smoothPath[steps].dir = 9;
- _smoothPath[steps].num = ROUTE_END_FLAG;
- return 1;
-}
-
-int32 Router::smoothCheck(int32 best, int32 p, int32 dirS, int32 dirD) {
- /*********************************************************************
- * Slip sliding away
- * This path checker checks to see if a walk that exactly follows the
- * path would be valid. This should be inherently true for atleast one
- * of the turn options.
- * No longer checks the data it only creates the smoothPath array JPS
- *********************************************************************/
-
- static int32 k;
- int32 dsx, dsy;
- int32 ddx, ddy;
- int32 ss0, ss1, ss2;
- int32 sd0, sd1, sd2;
-
- if (p == 0)
- k = 1;
-
- int32 x = _route[p].x;
- int32 y = _route[p].y;
- int32 x2 = _route[p + 1].x;
- int32 y2 = _route[p + 1].y;
- int32 ldx = x2 - x;
- int32 ldy = y2 - y;
- int32 dirX = 1;
- int32 dirY = 1;
-
- if (ldx < 0) {
- ldx = -ldx;
- dirX = -1;
- }
-
- if (ldy < 0) {
- ldy = -ldy;
- dirY = -1;
- }
-
- // set up sd0-ss2 to reflect possible movement in each direction
-
- if (dirS == 0 || dirS == 4) { // vert and diag
- ddx = ldx;
- ddy = (ldx * _diagonaly) / _diagonalx;
- dsy = ldy - ddy;
- ddx = ddx * dirX;
- ddy = ddy * dirY;
- dsy = dsy * dirY;
- dsx = 0;
-
- sd0 = (ddx + _modX[dirD] / 2) / _modX[dirD];
- ss0 = (dsy + _modY[dirS] / 2) / _modY[dirS];
- sd1 = sd0 / 2;
- ss1 = ss0 / 2;
- sd2 = sd0 - sd1;
- ss2 = ss0 - ss1;
- } else {
- ddy = ldy;
- ddx = (ldy * _diagonalx) / _diagonaly;
- dsx = ldx - ddx;
- ddy = ddy * dirY;
- ddx = ddx * dirX;
- dsx = dsx * dirX;
- dsy = 0;
-
- sd0 = (ddy + _modY[dirD] / 2) / _modY[dirD];
- ss0 = (dsx + _modX[dirS] / 2) / _modX[dirS];
- sd1 = sd0 / 2;
- ss1 = ss0 / 2;
- sd2 = sd0 - sd1;
- ss2 = ss0 - ss1;
- }
-
- switch (best) {
- case 0: // halfsquare, diagonal, halfsquare
- _smoothPath[k].x = x + dsx / 2;
- _smoothPath[k].y = y + dsy / 2;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss1;
- k++;
-
- _smoothPath[k].x = x + dsx / 2 + ddx;
- _smoothPath[k].y = y + dsy / 2 + ddy;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd0;
- k++;
-
- _smoothPath[k].x = x + dsx + ddx;
- _smoothPath[k].y = y + dsy + ddy;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss2;
- k++;
-
- break;
- case 1: // square, diagonal
- _smoothPath[k].x = x + dsx;
- _smoothPath[k].y = y + dsy;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss0;
- k++;
-
- _smoothPath[k].x = x2;
- _smoothPath[k].y = y2;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd0;
- k++;
-
- break;
- case 2: // diagonal square
- _smoothPath[k].x = x + ddx;
- _smoothPath[k].y = y + ddy;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd0;
- k++;
-
- _smoothPath[k].x = x2;
- _smoothPath[k].y = y2;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss0;
- k++;
-
- break;
- default: // halfdiagonal, square, halfdiagonal
- _smoothPath[k].x = x + ddx / 2;
- _smoothPath[k].y = y + ddy / 2;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd1;
- k++;
-
- _smoothPath[k].x = x + dsx + ddx / 2;
- _smoothPath[k].y = y + dsy + ddy / 2;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss0;
- k++;
-
- _smoothPath[k].x = x2;
- _smoothPath[k].y = y2;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd2;
- k++;
-
- break;
- }
-
- return k;
-}
-
-void Router::slidyPath() {
- /*********************************************************************
- * slidyPath creates a path based on part steps with no sliding to get
- * as near as possible to the target without any sliding this routine
- * is intended for use when just clicking about.
- *
- * produce a module list from the line data
- *********************************************************************/
-
- int32 smooth = 1;
- int32 slidy = 1;
-
- // strip out the short sections
-
- _modularPath[0].x = _smoothPath[0].x;
- _modularPath[0].y = _smoothPath[0].y;
- _modularPath[0].dir = _smoothPath[0].dir;
- _modularPath[0].num = 0;
-
- while (_smoothPath[smooth].num < ROUTE_END_FLAG) {
- int32 scale = _scaleA * _smoothPath[smooth].y + _scaleB;
- int32 deltaX = _smoothPath[smooth].x - _modularPath[slidy - 1].x;
- int32 deltaY = _smoothPath[smooth].y - _modularPath[slidy - 1].y;
- // quarter a step minimum
- int32 stepX = (scale * _modX[_smoothPath[smooth].dir]) >> 19;
- int32 stepY = (scale * _modY[_smoothPath[smooth].dir]) >> 19;
-
- if (ABS(deltaX) >= ABS(stepX) && ABS(deltaY) >= ABS(stepY)) {
- _modularPath[slidy].x = _smoothPath[smooth].x;
- _modularPath[slidy].y = _smoothPath[smooth].y;
- _modularPath[slidy].dir = _smoothPath[smooth].dir;
- _modularPath[slidy].num = 1;
- slidy++;
- }
- smooth++;
- }
-
- // in case the last bit had no steps
-
- if (slidy > 1) {
- _modularPath[slidy - 1].x = _smoothPath[smooth - 1].x;
- _modularPath[slidy - 1].y = _smoothPath[smooth - 1].y;
- }
-
- // set up the end of the walk
-
- _modularPath[slidy].x = _smoothPath[smooth - 1].x;
- _modularPath[slidy].y = _smoothPath[smooth - 1].y;
- _modularPath[slidy].dir = _targetDir;
- _modularPath[slidy].num = 0;
- slidy++;
-
- _modularPath[slidy].x = _smoothPath[smooth - 1].x;
- _modularPath[slidy].y = _smoothPath[smooth - 1].y;
- _modularPath[slidy].dir = 9;
- _modularPath[slidy].num = ROUTE_END_FLAG;
- slidy++;
-}
-
-// SLOW IN
-
-bool Router::addSlowInFrames(WalkData *walkAnim) {
- if (_walkData.usingSlowInFrames && _modularPath[1].num > 0) {
- for (int slowInFrameNo = 0; slowInFrameNo < _walkData.nSlowInFrames[_currentDir]; slowInFrameNo++) {
- walkAnim[_stepCount].frame = _firstSlowInFrame[_currentDir] + slowInFrameNo;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = _currentDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
- return true;
- }
-
- return false;
-}
-
-void Router::earlySlowOut(byte *ob_mega, byte *ob_walkdata) {
- int32 slowOutFrameNo;
- int32 walk_pc;
- WalkData *walkAnim;
-
- ObjectMega obMega(ob_mega);
-
- debug(5, "EARLY SLOW-OUT");
-
- loadWalkData(ob_walkdata);
-
- debug(5, "********************************");
- debug(5, "_framesPerStep = %d", _framesPerStep);
- debug(5, "_numberOfSlowOutFrames = %d", _numberOfSlowOutFrames);
- debug(5, "_firstWalkingTurnLeftFrame = %d", _firstWalkingTurnLeftFrame);
- debug(5, "_firstWalkingTurnRightFrame = %d", _firstWalkingTurnRightFrame);
- debug(5, "_firstSlowOutFrame = %d", _firstSlowOutFrame);
- debug(5, "********************************");
-
- walk_pc = obMega.getWalkPc();
-
- walkAnim = getRouteMem();
-
- // if this mega does actually have slow-out frames
- if (_walkData.usingSlowOutFrames) {
- // overwrite the next step (half a cycle) of the walk
- // (ie .step - 0..5)
-
- do {
- debug(5, "STEP NUMBER: walkAnim[%d].step = %d", walk_pc, walkAnim[walk_pc].step);
- debug(5, "ORIGINAL FRAME: walkAnim[%d].frame = %d", walk_pc, walkAnim[walk_pc].frame);
-
- // map from existing walk frame across to correct
- // frame number of slow-out - remember, there may be
- // more slow-out frames than walk-frames!
-
- if (walkAnim[walk_pc].frame >= _firstWalkingTurnRightFrame) {
- // if it's a walking turn-right, rather than a
- // normal step, then map it to a normal step
- // frame first
-
- walkAnim[walk_pc].frame -= _firstWalkingTurnRightFrame;
- debug(5, "MAPPED TO WALK: walkAnim[%d].frame = %d (walking turn-right frame --> walk frame)", walk_pc, walkAnim[walk_pc].frame);
- } else if (walkAnim[walk_pc].frame >= _firstWalkingTurnLeftFrame) {
- // if it's a walking turn-left, rather than a
- // normal step, then map it to a normal step
- // frame first
-
- walkAnim[walk_pc].frame -= _firstWalkingTurnLeftFrame;
- debug(5, "MAPPED TO WALK: walkAnim[%d].frame = %d (walking turn-left frame --> walk frame)", walk_pc, walkAnim[walk_pc].frame);
- }
-
- walkAnim[walk_pc].frame += _firstSlowOutFrame + ((walkAnim[walk_pc].frame / _framesPerStep) * (_numberOfSlowOutFrames - _framesPerStep));
- walkAnim[walk_pc].step = 0;
- debug(5, "SLOW-OUT FRAME: walkAnim[%d].frame = %d",walk_pc, walkAnim[walk_pc].frame);
- walk_pc++;
- } while (walkAnim[walk_pc].step > 0);
-
- // add stationary frame(s) (OPTIONAL)
-
- for (slowOutFrameNo = _framesPerStep; slowOutFrameNo < _numberOfSlowOutFrames; slowOutFrameNo++) {
- walkAnim[walk_pc].frame = walkAnim[walk_pc - 1].frame + 1;
- debug(5, "EXTRA FRAME: walkAnim[%d].frame = %d", walk_pc, walkAnim[walk_pc].frame);
- walkAnim[walk_pc].step = 0;
- walkAnim[walk_pc].dir = walkAnim[walk_pc - 1].dir;
- walkAnim[walk_pc].x = walkAnim[walk_pc - 1].x;
- walkAnim[walk_pc].y = walkAnim[walk_pc - 1].y;
- walk_pc++;
- }
- } else {
- // this mega doesn't have slow-out frames
- // stand in current direction
-
- walkAnim[walk_pc].frame = _firstStandFrame + walkAnim[walk_pc - 1].dir;
- walkAnim[walk_pc].step = 0;
- walkAnim[walk_pc].dir = walkAnim[walk_pc - 1].dir;
- walkAnim[walk_pc].x = walkAnim[walk_pc - 1].x;
- walkAnim[walk_pc].y = walkAnim[walk_pc - 1].y;
- walk_pc++;
- }
-
- // end of sequence
- walkAnim[walk_pc].frame = 512;
-
- // so that this doesn't happen again while 'george_walking' is still
- // '2'
- walkAnim[walk_pc].step = 99;
-}
-
-// SLOW OUT
-
-void Router::addSlowOutFrames(WalkData *walkAnim) {
- int32 slowOutFrameNo;
-
- // if the mega did actually walk, we overwrite the last step (half a
- // cycle) with slow-out frames + add any necessary stationary frames
-
- if (_walkData.usingSlowOutFrames && _lastCount >= _framesPerStep) {
- // place stop frames here
- // slowdown at the end of the last walk
-
- slowOutFrameNo = _lastCount - _framesPerStep;
-
- debug(5, "SLOW OUT: slowOutFrameNo(%d) = _lastCount(%d) - _framesPerStep(%d)", slowOutFrameNo, _lastCount, _framesPerStep);
-
- // overwrite the last step (half a cycle) of the walk
-
- do {
- // map from existing walk frame across to correct
- // frame number of slow-out - remember, there may be
- // more slow-out frames than walk-frames!
-
- walkAnim[slowOutFrameNo].frame += _firstSlowOutFrame + ((walkAnim[slowOutFrameNo].frame / _framesPerStep) * (_numberOfSlowOutFrames - _framesPerStep));
-
- // because no longer a normal walk-step
- walkAnim[slowOutFrameNo].step = 0;
-
- debug(5, "walkAnim[%d].frame = %d",slowOutFrameNo,walkAnim[slowOutFrameNo].frame);
- slowOutFrameNo++;
- } while (slowOutFrameNo < _lastCount);
-
- // add stationary frame(s) (OPTIONAL)
-
- for (slowOutFrameNo = _framesPerStep; slowOutFrameNo < _numberOfSlowOutFrames; slowOutFrameNo++) {
- walkAnim[_stepCount].frame = walkAnim[_stepCount - 1].frame + 1;
-
- debug(5, "EXTRA FRAMES: walkAnim[%d].frame = %d", _stepCount, walkAnim[_stepCount].frame);
-
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = walkAnim[_stepCount - 1].dir;
- walkAnim[_stepCount].x = walkAnim[_stepCount - 1].x;
- walkAnim[_stepCount].y = walkAnim[_stepCount - 1].y;
- _stepCount++;
- }
- }
-}
-
-void Router::slidyWalkAnimator(WalkData *walkAnim) {
- /*********************************************************************
- * Skidding every where HardWalk creates an animation that exactly
- * fits the smoothPath and uses foot slipping to fit whole steps into
- * the route
- *
- * Parameters: georgeg, mouseg
- * Returns: rout
- *
- * produce a module list from the line data
- *********************************************************************/
-
- static int32 left = 0;
- int32 p;
- int32 lastDir;
- int32 lastRealDir;
- int32 turnDir;
- int32 scale;
- int32 step;
- int32 module;
- int32 moduleEnd;
- int32 module16X;
- int32 module16Y;
- int32 stepX;
- int32 stepY;
- int32 errorX;
- int32 errorY;
- int32 lastErrorX;
- int32 lastErrorY;
- int32 frameCount;
- int32 frames;
-
- p = 0;
- lastDir = _modularPath[0].dir;
- _currentDir = _modularPath[1].dir;
-
- if (_currentDir == NO_DIRECTIONS)
- _currentDir = lastDir;
-
- _moduleX = _startX;
- _moduleY = _startY;
- module16X = _moduleX << 16;
- module16Y = _moduleY << 16;
- _stepCount = 0;
-
- // START THE WALK WITH THE FIRST STANDFRAME THIS MAY CAUSE A DELAY
- // BUT IT STOPS THE PLAYER MOVING FOR COLLISIONS ARE DETECTED
-
- debug(5, "SLIDY: STARTING THE WALK");
-
- module = _framesPerChar + lastDir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
-
- // TURN TO START THE WALK
-
- debug(5, "SLIDY: TURNING TO START THE WALK");
- // rotate if we need to
-
- if (lastDir != _currentDir) {
- // get the direction to turn
- turnDir = _currentDir - lastDir;
- if (turnDir < 0)
- turnDir += NO_DIRECTIONS;
-
- if (turnDir > 4)
- turnDir = -1;
- else if (turnDir > 0)
- turnDir = 1;
-
- // rotate to new walk direction
- // for george and nico put in a head turn at the start
-
- if (_walkData.usingStandingTurnFrames) {
- // new frames for turn frames 29oct95jps
- if (turnDir < 0)
- module = _firstStandingTurnLeftFrame + lastDir;
- else
- module = _firstStandingTurnRightFrame + lastDir;
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // rotate till were facing new dir then go back 45 degrees
- while (lastDir != _currentDir) {
- lastDir += turnDir;
-
- // new frames for turn frames 29oct95jps
- if (turnDir < 0) {
- if ( lastDir < 0)
- lastDir += NO_DIRECTIONS;
- module = _firstStandingTurnLeftFrame + lastDir;
- } else {
- if ( lastDir > 7)
- lastDir -= NO_DIRECTIONS;
- module = _firstStandingTurnRightFrame + lastDir;
- }
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // the back 45 degrees bit
- // step back one because new head turn for george takes us
- // past the new dir
- _stepCount--;
- }
-
- // his head is in the right direction
- lastRealDir = _currentDir;
-
- // SLIDY: THE SLOW IN
-
- addSlowInFrames(walkAnim);
-
- // THE WALK
-
- debug(5, "SLIDY: THE WALK");
-
- // start the walk on the left or right leg, depending on how the
- // slow-in frames were drawn
-
- // (0 = left; 1 = right)
-
- if (_walkData.leadingLeg[_currentDir] == 0) {
- // start the walk on the left leg (ie. at beginning of the
- // first step of the walk cycle)
- left = 0;
- } else {
- // start the walk on the right leg (ie. at beginning of the
- // second step of the walk cycle)
- left = _framesPerStep;
- }
-
- _lastCount = _stepCount;
-
- // this ensures that we don't put in turn frames for the start
- lastDir = 99;
-
- // this ensures that we don't put in turn frames for the start
- _currentDir = 99;
-
- do {
- assert(_stepCount < O_WALKANIM_SIZE);
- while (_modularPath[p].num == 0) {
- p++;
- if (_currentDir != 99)
- lastRealDir = _currentDir;
- lastDir = _currentDir;
- _lastCount = _stepCount;
- }
-
- // calculate average amount to lose in each step on the way
- // to the next node
-
- _currentDir = _modularPath[p].dir;
-
- if (_currentDir < NO_DIRECTIONS) {
- module = _currentDir * _framesPerStep * 2 + left;
-
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
-
- moduleEnd = module + _framesPerStep;
- step = 0;
- scale = (_scaleA * _moduleY + _scaleB);
-
- do {
- module16X += _walkData.dx[module] * scale;
- module16Y += _walkData.dy[module] * scale;
- _moduleX = module16X >> 16;
- _moduleY = module16Y >> 16;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = step; // normally 0,1,2,3,4,5,0,1,2,etc
- walkAnim[_stepCount].dir = _currentDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- step++;
- module++;
- } while (module < moduleEnd);
-
- stepX = _modX[_modularPath[p].dir];
- stepY = _modY[_modularPath[p].dir];
- errorX = _modularPath[p].x - _moduleX;
- errorX = errorX * stepX;
- errorY = _modularPath[p].y - _moduleY;
- errorY = errorY * stepY;
-
- if (errorX < 0 || errorY < 0) {
- _modularPath[p].num = 0; // the end of the path
-
- // okay those last steps took us past our
- // target but do we want to scoot or moonwalk
-
- frames = _stepCount - _lastCount;
- errorX = _modularPath[p].x - walkAnim[_stepCount - 1].x;
- errorY = _modularPath[p].y - walkAnim[_stepCount - 1].y;
-
- if (frames > _framesPerStep) {
- lastErrorX = _modularPath[p].x - walkAnim[_stepCount - 7].x;
- lastErrorY = _modularPath[p].y - walkAnim[_stepCount - 7].y;
-
- if (stepX == 0) {
- if (3 * ABS(lastErrorY) < ABS(errorY)) {
- // the last stop was
- // closest
- _stepCount -= _framesPerStep;
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
- }
- } else {
- if (3 * ABS(lastErrorX) < ABS(errorX)) {
- //the last stop was
- // closest
- _stepCount -= _framesPerStep;
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
- }
- }
- }
-
- errorX = _modularPath[p].x - walkAnim[_stepCount-1].x;
- errorY = _modularPath[p].y - walkAnim[_stepCount-1].y;
-
- // okay we've reached the end but we still
- // have an error
-
- if (errorX != 0) {
- frameCount = 0;
- frames = _stepCount - _lastCount;
-
- do {
- frameCount++;
- walkAnim[_lastCount + frameCount - 1].x += errorX * frameCount / frames;
- } while (frameCount < frames);
- }
-
- if (errorY != 0) {
- frameCount = 0;
- frames = _stepCount - _lastCount;
- do {
- frameCount++;
- walkAnim[_lastCount + frameCount - 1].y += errorY * frameCount / frames;
- } while (frameCount < frames);
- }
-
- // Now is the time to put in the turn frames
- // for the last turn
-
- if (frames < _framesPerStep) {
- // this ensures that we don't put in
- // turn frames for this walk or the
- // next
- _currentDir = 99;
- }
-
- if (_currentDir != 99)
- lastRealDir = _currentDir;
-
- // check each turn condition in turn
-
- // only for george
- if (lastDir != 99 && _currentDir != 99 && _walkData.usingWalkingTurnFrames) {
- // 1 and -7 going right -1 and 7 going
- // left
- lastDir = _currentDir - lastDir;
-
- if (lastDir == -1 || lastDir == 7 || lastDir == -2 || lastDir == 6) {
- // turn at the end of the last
- // walk
-
- _frame = _lastCount - _framesPerStep;
- do {
- // turning left
- walkAnim[_frame].frame += _firstWalkingTurnLeftFrame;
- _frame++;
- } while (_frame < _lastCount);
- } else if (lastDir == 1 || lastDir == -7 || lastDir == 2 || lastDir == -6) {
- // turn at the end of the
- // current walk
-
- _frame = _lastCount - _framesPerStep;
- do {
- // turning right
- walkAnim[_frame].frame += _firstWalkingTurnRightFrame;
- _frame++;
- } while (_frame < _lastCount);
- }
- lastDir = _currentDir;
- }
-
- // all turns checked
-
- _lastCount = _stepCount;
- _moduleX = walkAnim[_stepCount - 1].x;
- _moduleY = walkAnim[_stepCount - 1].y;
- module16X = _moduleX << 16;
- module16Y = _moduleY << 16;
- }
- }
- } while (_modularPath[p].dir < NO_DIRECTIONS);
-
-#ifdef SWORD2_DEBUG
- if (lastRealDir == 99)
- error("slidyWalkAnimatorlast direction error");
-#endif
-
- // THE SLOW OUT
- addSlowOutFrames(walkAnim);
-
- // TURNS TO END THE WALK ?
-
- // We've done the walk now put in any turns at the end
-
- if (_targetDir == 8) {
- // ANY direction -> stand in the last direction
-
- module = _firstStandFrame + lastRealDir;
- _targetDir = lastRealDir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- if (_targetDir == 9) {
- // 'stance' was non-zero
- if (_stepCount == 0) {
- module = _framesPerChar + lastRealDir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
- } else if (_targetDir != lastRealDir) {
- // rotate to target direction
- turnDir = _targetDir - lastRealDir;
- if ( turnDir < 0)
- turnDir += NO_DIRECTIONS;
-
- if (turnDir > 4)
- turnDir = -1;
- else if (turnDir > 0)
- turnDir = 1;
-
- // rotate to target direction
- // for george and nico put in a head turn at the start
-
- if (_walkData.usingStandingTurnFrames) {
- // new frames for turn frames 29oct95jps
- if (turnDir < 0)
- module = _firstStandingTurnLeftFrame + lastDir;
- else
- module = _firstStandingTurnRightFrame + lastDir;
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // rotate if we need to
-
- while (lastRealDir != _targetDir) {
- lastRealDir += turnDir;
-
- // new frames for turn frames 29oct95jps
- if (turnDir < 0) {
- if (lastRealDir < 0)
- lastRealDir += NO_DIRECTIONS;
- module = _firstStandingTurnLeftFrame + lastRealDir;
- } else {
- if (lastRealDir > 7)
- lastRealDir -= NO_DIRECTIONS;
- module = _firstStandingTurnRightFrame + lastRealDir;
- }
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- module = _firstStandFrame + lastRealDir;
- walkAnim[_stepCount - 1].frame = module;
- } else {
- // just stand at the end
- module = _firstStandFrame + lastRealDir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
-
- // write all the frames to "debug.txt"
- debug(5, "THE WALKDATA:");
-
- for (_frame = 0; _frame <= _stepCount; _frame++)
- debug(5, "walkAnim[%d].frame=%d", _frame, walkAnim[_frame].frame);
-
- debug(5, "routeFinder RouteSize is %d", _stepCount);
- return;
-}
-
-#ifndef FORCE_SLIDY
-
-// THE SOLID PATH ROUTINES
-
-int32 Router::solidPath() {
- /*********************************************************************
- * SolidPath creates a path based on whole steps with no sliding to
- * get as near as possible to the target without any sliding this
- * routine is currently unused, but is intended for use when just
- * clicking about.
- *
- * produce a module list from the line data
- *********************************************************************/
-
- int32 smooth;
- int32 solid;
- int32 scale;
- int32 stepX;
- int32 stepY;
- int32 deltaX;
- int32 deltaY;
-
- // strip out the short sections
-
- solid = 1;
- smooth = 1;
- _modularPath[0].x = _smoothPath[0].x;
- _modularPath[0].y = _smoothPath[0].y;
- _modularPath[0].dir = _smoothPath[0].dir;
- _modularPath[0].num = 0;
-
- do {
- scale = _scaleA * _smoothPath[smooth].y + _scaleB;
- deltaX = _smoothPath[smooth].x - _modularPath[solid - 1].x;
- deltaY = _smoothPath[smooth].y - _modularPath[solid - 1].y;
- stepX = _modX[_smoothPath[smooth].dir];
- stepY = _modY[_smoothPath[smooth].dir];
- stepX = stepX * scale;
- stepY = stepY * scale;
- stepX = stepX >> 16;
- stepY = stepY >> 16;
-
- if (ABS(deltaX) >= ABS(stepX) && ABS(deltaY) >= ABS(stepY)) {
- _modularPath[solid].x = _smoothPath[smooth].x;
- _modularPath[solid].y = _smoothPath[smooth].y;
- _modularPath[solid].dir = _smoothPath[smooth].dir;
- _modularPath[solid].num = 1;
- solid++;
- }
-
- smooth++;
- } while (_smoothPath[smooth].num < ROUTE_END_FLAG);
-
- // in case the last bit had no steps
-
- if (solid == 1) {
- // there were no paths so put in a dummy end
- solid = 2;
- _modularPath[1].dir = _smoothPath[0].dir;
- _modularPath[1].num = 0;
- }
-
- _modularPath[solid - 1].x = _smoothPath[smooth - 1].x;
- _modularPath[solid - 1].y = _smoothPath[smooth - 1].y;
-
- // set up the end of the walk
- _modularPath[solid].x = _smoothPath[smooth - 1].x;
- _modularPath[solid].y = _smoothPath[smooth - 1].y;
- _modularPath[solid].dir = 9;
- _modularPath[solid].num = ROUTE_END_FLAG;
-
- return 1;
-}
-
-int32 Router::solidWalkAnimator(WalkData *walkAnim) {
- /*********************************************************************
- * SolidWalk creates an animation based on whole steps with no sliding
- * to get as near as possible to the target without any sliding. This
- * routine is is intended for use when just clicking about.
- *
- * produce a module list from the line data
- *
- * returns 0 if solid route not found
- *********************************************************************/
-
- int32 left;
- int32 turnDir;
- int32 scale;
- int32 step;
- int32 errorX;
- int32 errorY;
- int32 moduleEnd;
- bool slowStart = false;
-
- // start at the beginning for a change
-
- int32 lastDir = _modularPath[0].dir;
- int32 module = _framesPerChar + lastDir;
-
- _currentDir = _modularPath[1].dir;
- _moduleX = _startX;
- _moduleY = _startY;
- _stepCount = 0;
-
- int32 module16X = _moduleX << 16;
- int32 module16Y = _moduleY << 16;
-
- // START THE WALK WITH THE FIRST STANDFRAME THIS MAY CAUSE A DELAY
- // BUT IT STOPS THE PLAYER MOVING FOR COLLISIONS ARE DETECTED
-
- debug(5, "SOLID: STARTING THE WALK");
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
-
- // TURN TO START THE WALK
-
- debug(5, "SOLID: TURNING TO START THE WALK");
-
- // rotate if we need to
-
- if (lastDir != _currentDir) {
- // get the direction to turn
- turnDir = _currentDir - lastDir;
- if (turnDir < 0)
- turnDir += NO_DIRECTIONS;
-
- if (turnDir > 4)
- turnDir = -1;
- else if (turnDir > 0)
- turnDir = 1;
-
- // rotate to new walk direction
- // for george and nico put in a head turn at the start
-
- if (_walkData.usingStandingTurnFrames) {
- // new frames for turn frames 29oct95jps
- if (turnDir < 0)
- module = _firstStandingTurnLeftFrame + lastDir;
- else
- module = _firstStandingTurnRightFrame + lastDir;
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // rotate till were facing new dir then go back 45 degrees
-
- while (lastDir != _currentDir) {
- lastDir += turnDir;
-
- // new frames for turn frames
- if (turnDir < 0) {
- if (lastDir < 0)
- lastDir += NO_DIRECTIONS;
- module = _firstStandingTurnLeftFrame + lastDir;
- } else {
- if (lastDir > 7)
- lastDir -= NO_DIRECTIONS;
- module = _firstStandingTurnRightFrame + lastDir;
- }
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // the back 45 degrees bit
- // step back one because new head turn for george takes us
- // past the new dir
-
- _stepCount--;
- }
-
- // THE SLOW IN
-
- slowStart = addSlowInFrames(walkAnim);
-
- // THE WALK
-
- debug(5, "SOLID: THE WALK");
-
- // start the walk on the left or right leg, depending on how the
- // slow-in frames were drawn
-
- // (0 = left; 1 = right)
- if (_walkData.leadingLeg[_currentDir] == 0) {
- // start the walk on the left leg (ie. at beginning of the
- // first step of the walk cycle)
- left = 0;
- } else {
- // start the walk on the right leg (ie. at beginning of the
- // second step of the walk cycle)
- left = _framesPerStep;
- }
-
- _lastCount = _stepCount;
-
- // this ensures that we don't put in turn frames for the start
- lastDir = 99;
-
- // this ensures that we don't put in turn frames for the start
- _currentDir = 99;
-
- int32 p = 1;
-
- do {
- while (_modularPath[p].num > 0) {
- _currentDir = _modularPath[p].dir;
- if (_currentDir < NO_DIRECTIONS) {
- module = _currentDir * _framesPerStep * 2 + left;
-
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
-
- moduleEnd = module + _framesPerStep;
- step = 0;
- scale = (_scaleA * _moduleY + _scaleB);
-
- do {
- module16X += _walkData.dx[module] * scale;
- module16Y += _walkData.dy[module] * scale;
- _moduleX = module16X >> 16;
- _moduleY = module16Y >> 16;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = step; // normally 0,1,2,3,4,5,0,1,2,etc
- walkAnim[_stepCount].dir = _currentDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- module++;
- step++;
- } while (module < moduleEnd);
-
- errorX = _modularPath[p].x - _moduleX;
- errorX = errorX * _modX[_modularPath[p].dir];
- errorY = _modularPath[p].y - _moduleY;
- errorY = errorY * _modY[_modularPath[p].dir];
-
- if (errorX < 0 || errorY < 0) {
- _modularPath[p].num = 0;
- _stepCount -= _framesPerStep;
-
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
-
- // Okay this is the end of a section
-
- _moduleX = walkAnim[_stepCount - 1].x;
- _moduleY = walkAnim[_stepCount - 1].y;
- module16X = _moduleX << 16;
- module16Y = _moduleY << 16;
- _modularPath[p].x = _moduleX;
- _modularPath[p].y = _moduleY;
-
- // Now is the time to put in the turn
- // frames for the last turn
-
- if (_stepCount - _lastCount < _framesPerStep) {
- // no step taken
-
- // clean up if a slow in but no
- // walk
-
- if (slowStart) {
- _stepCount -= _walkData.nSlowInFrames[_currentDir];
- _lastCount -= _walkData.nSlowInFrames[_currentDir];
- slowStart = false;
- }
-
- // this ensures that we don't
- // put in turn frames for this
- // walk or the next
-
- _currentDir = 99;
- }
-
- // check each turn condition in turn
- if (lastDir != 99 && _currentDir != 99 && _walkData.usingWalkingTurnFrames) {
- // only for george
- // 1 and -7 going right -1 and
- // 7 going left
-
- lastDir = _currentDir - lastDir;
-
- if (lastDir == -1 || lastDir == 7 || lastDir == -2 || lastDir == 6) {
- // turn at the end of
- // the last walk
-
- _frame = _lastCount - _framesPerStep;
-
- do {
- // turning left
- walkAnim[_frame].frame += _firstWalkingTurnLeftFrame;
- _frame++;
- } while (_frame < _lastCount);
- } else if (lastDir == 1 || lastDir == -7 || lastDir == 2 || lastDir == -6) {
- // turn at the end of
- // the current walk
-
- _frame = _lastCount - _framesPerStep;
- do {
- // turning right
- walkAnim[_frame].frame += _firstWalkingTurnRightFrame;
- _frame++;
- } while (_frame < _lastCount);
- }
- }
-
- // all turns checked
- _lastCount = _stepCount;
- }
- }
- }
- p++;
- lastDir = _currentDir;
-
- // can only be valid first time round
- slowStart = false;
- } while (_modularPath[p].dir < NO_DIRECTIONS);
-
- // THE SLOW OUT
-
- addSlowOutFrames(walkAnim);
-
- module = _framesPerChar + _modularPath[p - 1].dir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = _modularPath[p - 1].dir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
-
- debug(5, "THE WALKDATA:");
-
- for (_frame = 0; _frame <= _stepCount; _frame++)
- debug(5, "walkAnim[%d].frame=%d", _frame, walkAnim[_frame].frame);
-
- // NO END TURNS
-
- debug(5, "routeFinder RouteSize is %d", _stepCount);
- // now check the route
-
- int i = 0;
-
- do {
- if (!check(_modularPath[i].x, _modularPath[i].y, _modularPath[i + 1].x, _modularPath[i + 1].y))
- p = 0;
- i++;
- } while (i < p - 1);
-
- if (p != 0) {
- _targetDir = _modularPath[p - 1].dir;
- if (checkTarget(_moduleX, _moduleY) == 3) {
- // new target on a line
- p = 0;
- debug(5, "Solid walk target was on a line %d %d", _moduleX, _moduleY);
- }
- }
-
- return p;
-}
-#endif
-
-// THE SCAN ROUTINES
-
-bool Router::scan(int32 level) {
- /*********************************************************************
- * Called successively from routeFinder until no more changes take
- * place in the grid array, ie he best path has been found
- *
- * Scans through every point in the node array and checks if there is
- * a route between each point and if this route gives a new route.
- *
- * This routine could probably halve its processing time if it doubled
- * up on the checks after each route check
- *
- *********************************************************************/
-
- int32 x1, y1, x2, y2;
- int32 distance;
- bool changed = false;
-
- // For all the nodes that have new values and a distance less than
- // enddist, ie dont check for new routes from a point we checked
- // before or from a point that is already further away than the best
- // route so far.
-
- for (int i = 0; i < _nNodes; i++) {
- if (_node[i].dist < _node[_nNodes].dist && _node[i].level == level) {
- x1 = _node[i].x;
- y1 = _node[i].y;
-
- for (int j = _nNodes; j > 0; j--) {
- if (_node[j].dist > _node[i].dist) {
- x2 = _node[j].x;
- y2 = _node[j].y;
-
- if (ABS(x2 - x1) > 4.5 * ABS(y2 - y1))
- distance = (8 * ABS(x2 - x1) + 18 * ABS(y2 - y1)) / (54 * 8) + 1;
- else
- distance = (6 * ABS(x2 - x1) + 36 * ABS(y2 - y1)) / (36 * 14) + 1;
-
- if (distance + _node[i].dist < _node[_nNodes].dist && distance + _node[i].dist < _node[j].dist) {
- if (newCheck(0, x1, y1, x2, y2)) {
- _node[j].level = level + 1;
- _node[j].dist = distance + _node[i].dist;
- _node[j].prev = i;
- changed = true;
- }
- }
- }
- }
- }
- }
-
- return changed;
-}
-
-int32 Router::newCheck(int32 status, int32 x1, int32 y1, int32 x2, int32 y2) {
- /*********************************************************************
- * newCheck routine checks if the route between two points can be
- * achieved without crossing any of the bars in the Bars array.
- *
- * newCheck differs from check in that that 4 route options are
- * considered corresponding to actual walked routes.
- *
- * Note distance doesnt take account of shrinking ???
- *
- * Note Bars array must be properly calculated ie min max dx dy co
- *********************************************************************/
-
- int32 ldx;
- int32 ldy;
- int32 dlx;
- int32 dly;
- int32 dirX;
- int32 dirY;
- int32 step1;
- int32 step2;
- int32 step3;
- int32 steps;
- int32 options;
-
- steps = 0;
- options = 0;
- ldx = x2 - x1;
- ldy = y2 - y1;
- dirX = 1;
- dirY = 1;
-
- if (ldx < 0) {
- ldx = -ldx;
- dirX = -1;
- }
-
- if (ldy < 0) {
- ldy = -ldy;
- dirY = -1;
- }
-
- // make the route options
-
- if (_diagonaly * ldx > _diagonalx * ldy) {
- // dir = 1,2 or 2,3 or 5,6 or 6,7
-
- dly = ldy;
- dlx = (ldy * _diagonalx) / _diagonaly;
- ldx = ldx - dlx;
- dlx = dlx * dirX;
- dly = dly * dirY;
- ldx = ldx * dirX;
- ldy = 0;
-
- // options are square, diagonal a code 1 route
-
- step1 = check(x1, y1, x1 + ldx, y1);
- if (step1 != 0) {
- step2 = check(x1 + ldx, y1, x2, y2);
- if (step2 != 0) {
- steps = step1 + step2;
- options |= 2;
- }
- }
-
- // diagonal, square a code 2 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1 + dlx, y1 + dly);
- if (step1 != 0) {
- step2 = check(x1 + dlx, y2, x2, y2);
- if (step2 != 0) {
- steps = step1 + step2;
- options |= 4;
- }
- }
- }
-
- // halfsquare, diagonal, halfsquare a code 0 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1 + ldx / 2, y1);
- if (step1 != 0) {
- step2 = check(x1 + ldx / 2, y1, x1 + ldx / 2 + dlx, y2);
- if (step2 != 0) {
- step3 = check(x1 + ldx / 2 + dlx, y2, x2, y2);
- if (step3 != 0) {
- steps = step1 + step2 + step3;
- options |= 1;
- }
- }
- }
- }
-
- //halfdiagonal, square, halfdiagonal a code 3 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1 + dlx / 2, y1 + dly / 2);
- if (step1 != 0) {
- step2 = check(x1 + dlx / 2, y1 + dly / 2, x1 + ldx + dlx / 2, y1 + dly / 2);
- if (step2 != 0) {
- step3 = check(x1 + ldx + dlx / 2, y1 + dly / 2, x2, y2);
- if (step3 != 0) {
- steps = step1 + step2 + step3;
- options |= 8;
- }
- }
- }
- }
- } else {
- // dir = 7,0 or 0,1 or 3,4 or 4,5
-
- dlx = ldx;
- dly = (ldx * _diagonaly) / _diagonalx;
- ldy = ldy - dly;
- dlx = dlx * dirX;
- dly = dly * dirY;
- ldy = ldy * dirY;
- ldx = 0;
-
- // options are square, diagonal a code 1 route
-
- step1 = check(x1 ,y1, x1, y1 + ldy);
- if (step1 != 0) {
- step2 = check(x1, y1 + ldy, x2, y2);
- if (step2 != 0) {
- steps = step1 + step2;
- options |= 2;
- }
- }
-
- // diagonal, square a code 2 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x2, y1 + dly);
- if (step1 != 0) {
- step2 = check(x2, y1 + dly, x2, y2);
- if (step2 != 0) {
- steps = step1 + step2;
- options |= 4;
- }
- }
- }
-
- // halfsquare, diagonal, halfsquare a code 0 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1, y1 + ldy / 2);
- if (step1 != 0) {
- step2 = check(x1, y1 + ldy / 2, x2, y1 + ldy / 2 + dly);
- if (step2 != 0) {
- step3 = check(x2, y1 + ldy / 2 + dly, x2, y2);
- if (step3 != 0) {
- steps = step1 + step2 + step3;
- options |= 1;
- }
- }
- }
- }
-
- // halfdiagonal, square, halfdiagonal a code 3 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1 + dlx / 2, y1 + dly / 2);
- if (step1 != 0) {
- step2 = check(x1 + dlx / 2, y1 + dly / 2, x1 + dlx / 2, y1 + ldy + dly / 2);
- if (step2 != 0) {
- step3 = check(x1 + dlx / 2, y1 + ldy + dly / 2, x2, y2);
- if (step3 != 0) {
- steps = step1 + step2 + step3;
- options |= 8;
- }
- }
- }
- }
- }
-
- if (status == 0)
- status = steps;
- else
- status = options;
-
- return status;
-}
-
-// CHECK ROUTINES
-
-bool Router::check(int32 x1, int32 y1, int32 x2, int32 y2) {
- // call the fastest line check for the given line
- // returns true if line didn't cross any bars
-
- if (x1 == x2 && y1 == y2)
- return true;
-
- if (x1 == x2)
- return vertCheck(x1, y1, y2);
-
- if (y1 == y2)
- return horizCheck(x1, y1, x2);
-
- return lineCheck(x1, y1, x2, y2);
-}
-
-bool Router::lineCheck(int32 x1, int32 y1, int32 x2, int32 y2) {
- bool linesCrossed = true;
-
- int32 xmin = MIN(x1, x2);
- int32 xmax = MAX(x1, x2);
- int32 ymin = MIN(y1, y2);
- int32 ymax = MAX(y1, y2);
-
- // Line set to go one step in chosen direction so ignore if it hits
- // anything
-
- int32 dirx = x2 - x1;
- int32 diry = y2 - y1;
-
- int32 co = (y1 * dirx) - (x1 * diry); // new line equation
-
- for (int i = 0; i < _nBars && linesCrossed; i++) {
- // skip if not on module
- if (xmax >= _bars[i].xmin && xmin <= _bars[i].xmax && ymax >= _bars[i].ymin && ymin <= _bars[i].ymax) {
- // Okay, it's a valid line. Calculate an intercept. Wow
- // but all this arithmetic we must have loads of time
-
- // slope it he slope between the two lines
- int32 slope = (_bars[i].dx * diry) - (_bars[i].dy *dirx);
- // assuming parallel lines don't cross
- if (slope != 0) {
- // calculate x intercept and check its on both
- // lines
- int32 xc = ((_bars[i].co * dirx) - (co * _bars[i].dx)) / slope;
-
- // skip if not on module
- if (xc >= xmin - 1 && xc <= xmax + 1) {
- // skip if not on line
- if (xc >= _bars[i].xmin - 1 && xc <= _bars[i].xmax + 1) {
- int32 yc = ((_bars[i].co * diry) - (co * _bars[i].dy)) / slope;
-
- // skip if not on module
- if (yc >= ymin - 1 && yc <= ymax + 1) {
- // skip if not on line
- if (yc >= _bars[i].ymin - 1 && yc <= _bars[i].ymax + 1) {
- linesCrossed = false;
- }
- }
- }
- }
- }
- }
- }
-
- return linesCrossed;
-}
-
-bool Router::horizCheck(int32 x1, int32 y, int32 x2) {
- bool linesCrossed = true;
-
- int32 xmin = MIN(x1, x2);
- int32 xmax = MAX(x1, x2);
-
- // line set to go one step in chosen direction so ignore if it hits
- // anything
-
- for (int i = 0; i < _nBars && linesCrossed; i++) {
- // skip if not on module
- if (xmax >= _bars[i].xmin && xmin <= _bars[i].xmax && y >= _bars[i].ymin && y <= _bars[i].ymax) {
- // Okay, it's a valid line calculate an intercept. Wow
- // but all this arithmetic we must have loads of time
-
- if (_bars[i].dy == 0)
- linesCrossed = false;
- else {
- int32 ldy = y - _bars[i].y1;
- int32 xc = _bars[i].x1 + (_bars[i].dx * ldy) / _bars[i].dy;
- // skip if not on module
- if (xc >= xmin - 1 && xc <= xmax + 1)
- linesCrossed = false;
- }
- }
- }
-
- return linesCrossed;
-}
-
-bool Router::vertCheck(int32 x, int32 y1, int32 y2) {
- bool linesCrossed = true;
-
- int32 ymin = MIN(y1, y2);
- int32 ymax = MAX(y1, y2);
-
- // Line set to go one step in chosen direction so ignore if it hits
- // anything
-
- for (int i = 0; i < _nBars && linesCrossed; i++) {
- // skip if not on module
- if (x >= _bars[i].xmin && x <= _bars[i].xmax && ymax >= _bars[i].ymin && ymin <= _bars[i].ymax) {
- // Okay, it's a valid line calculate an intercept. Wow
- // but all this arithmetic we must have loads of time
-
- // both lines vertical and overlap in x and y so they
- // cross
-
- if (_bars[i].dx == 0)
- linesCrossed = false;
- else {
- int32 ldx = x - _bars[i].x1;
- int32 yc = _bars[i].y1 + (_bars[i].dy * ldx) / _bars[i].dx;
- // the intercept overlaps
- if (yc >= ymin - 1 && yc <= ymax + 1)
- linesCrossed = false;
- }
- }
- }
-
- return linesCrossed;
-}
-
-int32 Router::checkTarget(int32 x, int32 y) {
- int32 onLine = 0;
-
- int32 xmin = x - 1;
- int32 xmax = x + 1;
- int32 ymin = y - 1;
- int32 ymax = y + 1;
-
- // check if point +- 1 is on the line
- // so ignore if it hits anything
-
- for (int i = 0; i < _nBars && onLine == 0; i++) {
- // overlapping line
- if (xmax >= _bars[i].xmin && xmin <= _bars[i].xmax && ymax >= _bars[i].ymin && ymin <= _bars[i].ymax) {
- int32 xc, yc;
-
- // okay this line overlaps the target calculate
- // an y intercept for x
-
- // vertical line so we know it overlaps y
- if (_bars[i].dx == 0)
- yc = 0;
- else {
- int ldx = x - _bars[i].x1;
- yc = _bars[i].y1 + (_bars[i].dy * ldx) / _bars[i].dx;
- }
-
- // overlapping point for y
- if (yc >= ymin && yc <= ymax) {
- // target on a line so drop out
- onLine = 3;
- debug(5, "RouteFail due to target on a line %d %d", x, y);
- } else {
- // vertical line so we know it overlaps y
- if (_bars[i].dy == 0)
- xc = 0;
- else {
- int32 ldy = y - _bars[i].y1;
- xc = _bars[i].x1 + (_bars[i].dx * ldy) / _bars[i].dy;
- }
-
- // skip if not on module
- if (xc >= xmin && xc <= xmax) {
- // target on a line so drop out
- onLine = 3;
- debug(5, "RouteFail due to target on a line %d %d", x, y);
- }
- }
- }
- }
-
- return onLine;
-}
-
-// THE SETUP ROUTINES
-
-void Router::loadWalkData(byte *ob_walkdata) {
- uint16 firstFrameOfDirection;
- uint16 walkFrameNo;
- uint32 frameCounter = 0; // starts at frame 0 of mega set
- int i;
-
- _walkData.read(ob_walkdata);
-
- // 0 = not using slow out frames; non-zero = using that many frames
- // for each leading leg for each direction
-
- _numberOfSlowOutFrames = _walkData.usingSlowOutFrames;
-
- for (i = 0; i < NO_DIRECTIONS; i++) {
- firstFrameOfDirection = i * _walkData.nWalkFrames;
-
- _modX[i] = 0;
- _modY[i] = 0;
-
- for (walkFrameNo = firstFrameOfDirection; walkFrameNo < firstFrameOfDirection + _walkData.nWalkFrames / 2; walkFrameNo++) {
- // eg. _modX[0] is the sum of the x-step sizes for the
- // first half of the walk cycle for direction 0
- _modX[i] += _walkData.dx[walkFrameNo];
- _modY[i] += _walkData.dy[walkFrameNo];
- }
- }
-
- _diagonalx = _modX[3];
- _diagonaly = _modY[3];
-
- // interpret the walk data
-
- _framesPerStep = _walkData.nWalkFrames / 2;
- _framesPerChar = _walkData.nWalkFrames * NO_DIRECTIONS;
-
- // offset pointers added Oct 30 95 JPS
- // mega id references removed 16sep96 by JEL
-
- // WALK FRAMES
- // start on frame 0
-
- frameCounter += _framesPerChar;
-
- // STAND FRAMES
- // stand frames come after the walk frames
- // one stand frame for each direction
-
- _firstStandFrame = frameCounter;
- frameCounter += NO_DIRECTIONS;
-
- // STANDING TURN FRAMES - OPTIONAL!
- // standing turn-left frames come after the slow-out frames
- // one for each direction
- // standing turn-left frames come after the standing turn-right frames
- // one for each direction
-
- if (_walkData.usingStandingTurnFrames) {
- _firstStandingTurnLeftFrame = frameCounter;
- frameCounter += NO_DIRECTIONS;
-
- _firstStandingTurnRightFrame = frameCounter;
- frameCounter += NO_DIRECTIONS;
- } else {
- // refer instead to the normal stand frames
- _firstStandingTurnLeftFrame = _firstStandFrame;
- _firstStandingTurnRightFrame = _firstStandFrame;
- }
-
- // WALKING TURN FRAMES - OPTIONAL!
- // walking left-turn frames come after the stand frames
- // walking right-turn frames come after the walking left-turn frames
-
- if (_walkData.usingWalkingTurnFrames) {
- _firstWalkingTurnLeftFrame = frameCounter;
- frameCounter += _framesPerChar;
-
- _firstWalkingTurnRightFrame = frameCounter;
- frameCounter += _framesPerChar;
- } else {
- _firstWalkingTurnLeftFrame = 0;
- _firstWalkingTurnRightFrame = 0;
- }
-
- // SLOW-IN FRAMES - OPTIONAL!
- // slow-in frames come after the walking right-turn frames
-
- if (_walkData.usingSlowInFrames) {
- // Make note of frame number of first slow-in frame for each
- // direction. There may be a different number of slow-in
- // frames in each direction
-
- for (i = 0; i < NO_DIRECTIONS; i++) {
- _firstSlowInFrame[i] = frameCounter;
- frameCounter += _walkData.nSlowInFrames[i];
- }
- }
-
- // SLOW-OUT FRAMES - OPTIONAL!
- // slow-out frames come after the slow-in frames
-
- if (_walkData.usingSlowOutFrames)
- _firstSlowOutFrame = frameCounter;
-}
-
-// THE ROUTE EXTRACTOR
-
-void Router::extractRoute() {
- /*********************************************************************
- * extractRoute gets route from the node data after a full scan, route
- * is written with just the basic way points and direction options for
- * heading to the next point.
- *********************************************************************/
-
- int32 prev;
- int32 prevx;
- int32 prevy;
- int32 last;
- int32 point;
- int32 p;
- int32 dirx;
- int32 diry;
- int32 dir;
- int32 ldx;
- int32 ldy;
-
- // extract the route from the node data
-
- prev = _nNodes;
- last = prev;
- point = O_ROUTE_SIZE - 1;
- _route[point].x = _node[last].x;
- _route[point].y = _node[last].y;
-
- do {
- point--;
- prev = _node[last].prev;
- prevx = _node[prev].x;
- prevy = _node[prev].y;
- _route[point].x = prevx;
- _route[point].y = prevy;
- last = prev;
- } while (prev > 0);
-
- // now shuffle route down in the buffer
-
- _routeLength = 0;
-
- do {
- _route[_routeLength].x = _route[point].x;
- _route[_routeLength].y = _route[point].y;
- point++;
- _routeLength++;
- } while (point < O_ROUTE_SIZE);
-
- _routeLength--;
-
- // okay the route exists as a series point now put in some directions
-
- p = 0;
-
- do {
- ldx = _route[p + 1].x - _route[p].x;
- ldy = _route[p + 1].y - _route[p].y;
- dirx = 1;
- diry = 1;
-
- if (ldx < 0) {
- ldx = -ldx;
- dirx = -1;
- }
-
- if (ldy < 0) {
- ldy = -ldy;
- diry = -1;
- }
-
- if (_diagonaly * ldx > _diagonalx * ldy) {
- // dir = 1,2 or 2,3 or 5,6 or 6,7
-
- // 2 or 6
- dir = 4 - 2 * dirx;
- _route[p].dirS = dir;
-
- // 1, 3, 5 or 7
- dir = dir + diry * dirx;
- _route[p].dirD = dir;
- } else {
- // dir = 7,0 or 0,1 or 3,4 or 4,5
-
- // 0 or 4
- dir = 2 + 2 * diry;
- _route[p].dirS = dir;
-
- // 2 or 6
- dir = 4 - 2 * dirx;
-
- // 1, 3, 5 or 7
- dir = dir + diry * dirx;
- _route[p].dirD = dir;
- }
- p++;
- } while (p < _routeLength);
-
- // set the last dir to continue previous route unless specified
-
- if (_targetDir == 8) {
- // ANY direction
- _route[p].dirS = _route[p - 1].dirS;
- _route[p].dirD = _route[p - 1].dirD;
- } else {
- _route[p].dirS = _targetDir;
- _route[p].dirD = _targetDir;
- }
-
- return;
-}
-
-void Router::setUpWalkGrid(byte *ob_mega, int32 x, int32 y, int32 dir) {
- ObjectMega obMega(ob_mega);
-
- // get walk grid file + extra grid into 'bars' & 'node' arrays
- loadWalkGrid();
-
- // copy the mega structure into the local variables for use in all
- // subroutines
-
- _startX = obMega.getFeetX();
- _startY = obMega.getFeetY();
- _startDir = obMega.getCurDir();
- _targetX = x;
- _targetY = y;
- _targetDir = dir;
-
- _scaleA = obMega.getScaleA();
- _scaleB = obMega.getScaleB();
-
- // mega's current position goes into first node
-
- _node[0].x = _startX;
- _node[0].y = _startY;
- _node[0].level = 1;
- _node[0].prev = 0;
- _node[0].dist = 0;
-
- // reset other nodes
-
- for (int i = 1; i < _nNodes; i++) {
- _node[i].level = 0;
- _node[i].prev = 0;
- _node[i].dist = 9999;
- }
-
- // target position goes into final node
- _node[_nNodes].x = _targetX;
- _node[_nNodes].y = _targetY;
- _node[_nNodes].level = 0;
- _node[_nNodes].prev = 0;
- _node[_nNodes].dist = 9999;
-}
-
-void Router::plotWalkGrid() {
- int32 i;
-
- // get walk grid file + extra grid into 'bars' & 'node' arrays
- loadWalkGrid();
-
- // lines
-
- for (i = 0; i < _nBars; i++)
- _vm->_screen->drawLine(_bars[i].x1, _bars[i].y1, _bars[i].x2, _bars[i].y2, 254);
-
- // nodes
-
- // leave node 0 for start node
- for (i = 1; i < _nNodes; i++)
- plotCross(_node[i].x, _node[i].y, 184);
-}
-
-void Router::plotCross(int16 x, int16 y, uint8 colour) {
- _vm->_screen->drawLine(x - 1, y - 1, x + 1, y + 1, colour);
- _vm->_screen->drawLine(x + 1, y - 1, x - 1, y + 1, colour);
-}
-
-void Router::loadWalkGrid() {
- WalkGridHeader floorHeader;
- byte *fPolygrid;
- uint16 fPolygridLen;
-
- _nBars = 0; // reset counts
- _nNodes = 1; // leave node 0 for start-node
-
- // STATIC GRIDS (added/removed by object logics)
-
- // go through walkgrid list
- for (int i = 0; i < MAX_WALKGRIDS; i++) {
- if (_walkGridList[i]) {
- int j;
-
- // open walk grid file
- fPolygrid = _vm->_resman->openResource(_walkGridList[i]);
- fPolygridLen = _vm->_resman->fetchLen(_walkGridList[i]);
-
- Common::MemoryReadStream readS(fPolygrid, fPolygridLen);
-
- readS.seek(ResHeader::size());
-
- floorHeader.numBars = readS.readSint32LE();
- floorHeader.numNodes = readS.readSint32LE();
-
- // check that we're not going to exceed the max
- // allowed in the complete walkgrid arrays
-
- assert(_nBars + floorHeader.numBars < O_GRID_SIZE);
- assert(_nNodes + floorHeader.numNodes < O_GRID_SIZE);
-
- // lines
-
- for (j = 0; j < floorHeader.numBars; j++) {
- _bars[_nBars + j].x1 = readS.readSint16LE();
- _bars[_nBars + j].y1 = readS.readSint16LE();
- _bars[_nBars + j].x2 = readS.readSint16LE();
- _bars[_nBars + j].y2 = readS.readSint16LE();
- _bars[_nBars + j].xmin = readS.readSint16LE();
- _bars[_nBars + j].ymin = readS.readSint16LE();
- _bars[_nBars + j].xmax = readS.readSint16LE();
- _bars[_nBars + j].ymax = readS.readSint16LE();
- _bars[_nBars + j].dx = readS.readSint16LE();
- _bars[_nBars + j].dy = readS.readSint16LE();
- _bars[_nBars + j].co = readS.readSint32LE();
- }
-
- // nodes
-
- // leave node 0 for start node
- for (j = 0; j < floorHeader.numNodes; j++) {
- _node[_nNodes + j].x = readS.readSint16LE();
- _node[_nNodes + j].y = readS.readSint16LE();
- }
-
- // close walk grid file
- _vm->_resman->closeResource(_walkGridList[i]);
-
- // increment counts of total bars & nodes in whole
- // walkgrid
-
- _nBars += floorHeader.numBars;
- _nNodes += floorHeader.numNodes;
- }
- }
-}
-
-void Router::clearWalkGridList() {
- memset(_walkGridList, 0, sizeof(_walkGridList));
-}
-
-// called from fnAddWalkGrid
-
-void Router::addWalkGrid(int32 gridResource) {
- int i;
- // First, scan the list to see if this grid is already included
-
- for (i = 0; i < MAX_WALKGRIDS; i++) {
- if (_walkGridList[i] == gridResource)
- return;
- }
-
- // Scan the list for a free slot
-
- for (i = 0; i < MAX_WALKGRIDS; i++) {
- if (_walkGridList[i] == 0) {
- _walkGridList[i] = gridResource;
- return;
- }
- }
-
- error("_walkGridList[] full");
-}
-
-// called from fnRemoveWalkGrid
-
-void Router::removeWalkGrid(int32 gridResource) {
- for (int i = 0; i < MAX_WALKGRIDS; i++) {
- if (_walkGridList[i] == gridResource) {
- // If we've found it in the list, reset entry to zero.
- // Otherwise just ignore the request.
- _walkGridList[i] = 0;
- break;
- }
- }
-}
-
-} // End of namespace Sword2