[Scummvm-cvs-logs] CVS: scummvm/sword2 anims.cpp,1.69,1.70 function.cpp,1.82,1.83 logic.h,1.44,1.45 router.h,1.20,1.21 speech.cpp,1.73,1.74 walker.cpp,1.46,1.47

Torbjörn Andersson eriktorbjorn at users.sourceforge.net
Tue May 3 02:00:55 CEST 2005


Update of /cvsroot/scummvm/scummvm/sword2
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31827

Modified Files:
	anims.cpp function.cpp logic.h router.h speech.cpp walker.cpp 
Log Message:
More cleanup/restructuring: Moved walk-related code from Logic to Router.
(I may have to think up some better name for that class later.)


Index: anims.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/anims.cpp,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -d -r1.69 -r1.70
--- anims.cpp	20 Feb 2005 15:38:47 -0000	1.69
+++ anims.cpp	3 May 2005 09:00:04 -0000	1.70
@@ -33,7 +33,6 @@
 #include "sword2/interpreter.h"
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
-#include "sword2/memory.h"
 #include "sword2/resman.h"
 #include "sword2/sound.h"
 #include "sword2/driver/animation.h"
@@ -45,8 +44,8 @@
 	//		1 pointer to object's graphic structure
 	//		2 resource id of animation file
 
- 	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
- 	ObjectGraphic *ob_graphic = (ObjectGraphic *) _vm->_memory->decodePtr(params[1]);
+ 	ObjectLogic *ob_logic = (ObjectLogic *) decodePtr(params[0]);
+ 	ObjectGraphic *ob_graphic = (ObjectGraphic *) decodePtr(params[1]);
 	byte *anim_file;
 	AnimHeader *anim_head;
  	int32 res = params[2];
@@ -166,11 +165,11 @@
 	// If this is the start of the anim, read the anim table to get the
 	// appropriate anim resource
 
- 	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
+ 	ObjectLogic *ob_logic = (ObjectLogic *) decodePtr(params[0]);
 
 	if (ob_logic->looping == 0) {
-	 	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
-		uint32 *anim_table = (uint32 *) _vm->_memory->decodePtr(params[3]);
+	 	ObjectMega *ob_mega = (ObjectMega *) decodePtr(params[2]);
+		uint32 *anim_table = (uint32 *) decodePtr(params[3]);
 
 		// appropriate anim resource is in 'table[direction]'
 		pars[2] = anim_table[ob_mega->current_dir];
@@ -180,14 +179,14 @@
 }
 
 void Logic::setSpriteStatus(uint32 sprite, uint32 type) {
-	ObjectGraphic *ob_graphic = (ObjectGraphic *) _vm->_memory->decodePtr(sprite);
+	ObjectGraphic *ob_graphic = (ObjectGraphic *) decodePtr(sprite);
 
 	// Remove the previous status, but don't affect the shading upper-word
 	ob_graphic->type = (ob_graphic->type & 0xffff0000) | type;
 }
 
 void Logic::setSpriteShading(uint32 sprite, uint32 type) {
-	ObjectGraphic *ob_graphic = (ObjectGraphic *) _vm->_memory->decodePtr(sprite);
+	ObjectGraphic *ob_graphic = (ObjectGraphic *) decodePtr(sprite);
 
 	// Remove the previous shading, but don't affect the status lower-word.
 	// Note that drivers may still shade mega frames automatically, even

Index: function.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/function.cpp,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -d -r1.82 -r1.83
--- function.cpp	2 May 2005 05:41:00 -0000	1.82
+++ function.cpp	3 May 2005 09:00:05 -0000	1.83
@@ -29,7 +29,6 @@
 #include "sword2/interpreter.h"
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
-#include "sword2/memory.h"
 #include "sword2/mouse.h"
 #include "sword2/resman.h"
 #include "sword2/router.h"
@@ -53,7 +52,7 @@
 	// 		1 pointer to ascii message
 
 	int32 key = params[0];
-	char *name = (char *) _vm->_memory->decodePtr(params[1]);
+	char *name = (char *) decodePtr(params[1]);
 
 	_vm->registerStartPoint(key, name);
 	return IR_CONT;
@@ -107,7 +106,7 @@
 	// params:	0 pointer to ObjectMouse or 0 for no write to mouse
 	//		  list
 
-	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+	ObjectMouse *ob_mouse = (ObjectMouse *) decodePtr(params[0]);
 
 	_vm->_mouse->registerMouse(ob_mouse, NULL);
 	return IR_CONT;
@@ -197,162 +196,12 @@
 	//		5 target y-coord
 	//		6 target direction (8 means end walk on ANY direction)
 
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
-	ObjectGraphic *ob_graph = (ObjectGraphic *) _vm->_memory->decodePtr(params[1]);
-	ObjectMega *ob_mega  = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
-
-	int16 target_x = (int16) params[4];
-	int16 target_y = (int16) params[5];
-	uint8 target_dir = (uint8) params[6];
-
-	ObjectWalkdata *ob_walkdata;
-
-	// If this is the start of the walk, calculate the route.
-
-	if (!ob_logic->looping) {
-		// If we're already there, don't even bother allocating
-		// memory and calling the router, just quit back & continue
-		// the script! This avoids an embarassing mega stand frame
-		// appearing for one cycle when we're already in position for
-		// an anim eg. repeatedly clicking on same object to repeat
-		// an anim - no mega frame will appear in between runs of the
-		// anim.
-		
-		if (ob_mega->feet_x == target_x && ob_mega->feet_y == target_y && ob_mega->current_dir == target_dir) {
-			_scriptVars[RESULT] = 0;
-			return IR_CONT;
-		}
-
-		assert(params[6] >= 0 && params[6] <= 8);
-
-		ob_walkdata = (ObjectWalkdata *) _vm->_memory->decodePtr(params[3]);
-
-		ob_mega->walk_pc = 0;
-
-		// Set up mem for _walkData in route_slots[] & set mega's
-		// 'route_slot_id' accordingly
-
-		_router->allocateRouteMem();
-
-		int32 route = _router->routeFinder(ob_mega, ob_walkdata, target_x, target_y, target_dir);
-
-		// 0 = can't make route to target
-		// 1 = created route
-		// 2 = zero route but may need to turn
-
-		if (route == 1 || route == 2) {
-			// so script fnWalk loop continues until end of
-			// walk-anim
-
-			ob_logic->looping = 1;
-
-			// need to animate the route now, so don't set result
-			// or return yet!
-
-			// started walk
-			ob_mega->currently_walking = 1;
-
-			// (see fnGetPlayerSaveData() in save_rest.cpp
-		} else {
-			_router->freeRouteMem();
-			_scriptVars[RESULT] = 1;
-			return IR_CONT;
-		}
-
-		// Walk is about to start, so set the mega's graphic resource
-		ob_graph->anim_resource = ob_mega->megaset_res;
-	} else if (_scriptVars[EXIT_FADING] && _vm->_screen->getFadeStatus() == RDFADE_BLACK) {
-		// Double clicked an exit so quit the walk when screen is black
-		// ok, thats it - back to script and change screen
-
-		ob_logic->looping = 0;
-		_router->freeRouteMem();
-
-		// Must clear in-case on the new screen there's a walk
-		// instruction (which would get cut short)
-		_scriptVars[EXIT_CLICK_ID] = 0;
-
-		// finished walk
-		ob_mega->currently_walking = 0;
-
-		// see fnGetPlayerSaveData() in save_rest.cpp
-
-		_scriptVars[RESULT] = 0;
-
-		// continue the script so that RESULT can be checked!
-		return IR_CONT;
-	}
-
-	// get pointer to walkanim & current frame position
-
-	WalkData *walkAnim = _router->getRouteMem();
-	int32 walk_pc = ob_mega->walk_pc;
-
-	// If stopping the walk early, overwrite the next step with a
-	// slow-out, then finish
-
-	if (checkEventWaiting()) {
-		if (walkAnim[walk_pc].step == 0 && walkAnim[walk_pc + 1].step == 1) {
-			// At the beginning of a step
-			ob_walkdata = (ObjectWalkdata *) _vm->_memory->decodePtr(params[3]);
-			_router->earlySlowOut(ob_mega, ob_walkdata);
-		}
-	}
-
-	// Get new frame of walk
-
-	ob_graph->anim_pc = walkAnim[walk_pc].frame;
-	ob_mega->current_dir = walkAnim[walk_pc].dir;
-	ob_mega->feet_x = walkAnim[walk_pc].x;
-	ob_mega->feet_y = walkAnim[walk_pc].y;
-
-	// Check if NEXT frame is in fact the end-marker of the walk sequence
-	// so we can return to script just as the final (stand) frame of the
-	// walk is set - so that if followed by an anim, the anim's first
-	// frame replaces the final stand-frame of the walk (see below)
-
-	// '512' is end-marker
-	if (walkAnim[walk_pc + 1].frame == 512) {
-		ob_logic->looping = 0;
-		_router->freeRouteMem();
-
-		// finished walk
-		ob_mega->currently_walking = 0;
-
-		// (see fnGetPlayerSaveData() in save_rest.cpp
-
-		// if George's walk has been interrupted to run a new action
-		// script for instance or Nico's walk has been interrupted by
-		// player clicking on her to talk
-
-		// There used to be code here for checking if two megas were
-		// colliding, but that code had been commented out, and it
-		// was only run if a function that always returned zero
-		// returned non-zero.
-
-		if (checkEventWaiting()) {
-			startEvent();
-			_scriptVars[RESULT] = 1;
-			return IR_TERMINATE;
-		} else {
-			_scriptVars[RESULT] = 0;
-
-			// CONTINUE the script so that RESULT can be checked!
-			// Also, if an anim command follows the fnWalk command,
-			// the 1st frame of the anim (which is always a stand
-			// frame itself) can replace the final stand frame of
-			// the walk, to hide the slight difference between the
-			// shrinking on the mega frames and the pre-shrunk anim
-			// start-frame.
-
-			return IR_CONT;
-		}
-	}
-
-	// Increment the walkanim frame number and come back next cycle
-
-	ob_mega->walk_pc++;
-	return IR_REPEAT;
+	return _router->doWalk(
+		(ObjectLogic *) decodePtr(params[0]),
+		(ObjectGraphic *) decodePtr(params[1]),
+		(ObjectMega *) decodePtr(params[2]),
+		(ObjectWalkdata *) decodePtr(params[3]),
+		params[4], params[5], params[6]);
 }
 
 /**
@@ -366,52 +215,16 @@
 	//		3 pointer to object's walkdata structure
 	//		4 anim resource id
 
-	int32 pars[7];
-
-	// Walkdata is needed for earlySlowOut if player clicks elsewhere
-	// during the walk.
-
-	pars[0] = params[0];
-	pars[1] = params[1];
-	pars[2] = params[2];
-	pars[3] = params[3];
-
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
-
-	// If this is the start of the walk, read anim file to get start coords
-
-	if (!ob_logic->looping) {
-		byte *anim_file = _vm->_resman->openResource(params[4]);
-		AnimHeader *anim_head = _vm->fetchAnimHeader( anim_file );
-
-		pars[4] = anim_head->feetStartX;
-		pars[5] = anim_head->feetStartY;
-		pars[6] = anim_head->feetStartDir;
-
-		_vm->_resman->closeResource(params[4]);
-
-		// If start coords not yet set in anim header, use the standby
-		// coords (which should be set beforehand in the script).
-
-		if (pars[4] == 0 && pars[5] == 0) {
-			byte buf[NAME_LEN];
-
-			pars[4] = _standbyX;
-			pars[5] = _standbyY;
-			pars[6] = _standbyDir;
-
-			debug(3, "WARNING: fnWalkToAnim(%s) used standby coords", _vm->fetchObjectName(params[4], buf));
-		}
-
-		assert(pars[6] >= 0 && pars[6] <= 7);
-	}
-
-	return fnWalk(pars);
+	return _router->walkToAnim(
+		(ObjectLogic *) decodePtr(params[0]),
+		(ObjectGraphic *) decodePtr(params[1]),
+		(ObjectMega *) decodePtr(params[2]),
+		(ObjectWalkdata *) decodePtr(params[3]),
+		params[4]);
 }
 
 /**
- * Turn mega to the specified direction. Just needs to call fnWalk() with
- * current feet coords, so router can produce anim of turn frames.
+ * Turn mega to the specified direction.
  */
 
 int32 Logic::fnTurn(int32 *params) {
@@ -421,29 +234,12 @@
 	//		3 pointer to object's walkdata structure
 	//		4 target direction
 
-	int32 pars[7];
-
-	pars[0] = params[0];
-	pars[1] = params[1];
-	pars[2] = params[2];
-	pars[3] = params[3];
-
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
-
-	// If this is the start of the turn, get the mega's current feet
-	// coords + the required direction
-
-	if (!ob_logic->looping) {
-		assert(params[4] >= 0 && params[4] <= 7);
-
-		ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
-
-		pars[4] = ob_mega->feet_x;
-		pars[5] = ob_mega->feet_y;
-		pars[6] = params[4];
-	}
-
-	return fnWalk(pars);
+	return _router->doFace(
+		(ObjectLogic *) decodePtr(params[0]),
+		(ObjectGraphic *) decodePtr(params[1]),
+		(ObjectMega *) decodePtr(params[2]),
+		(ObjectWalkdata *) decodePtr(params[3]),
+		params[4]);
 }
 
 /**
@@ -459,47 +255,28 @@
 	//		3 target y-coord
 	//		4 target direction
 
-	assert(params[4] >= 0 && params[4] <= 7);
-
-	ObjectGraphic *ob_graph = (ObjectGraphic *) _vm->_memory->decodePtr(params[0]);
-	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[1]);
-
-	// set up the stand frame & set the mega's new direction
-
-	ob_mega->feet_x = params[2];
-	ob_mega->feet_y = params[3];
-	ob_mega->current_dir = params[4];
-
-	// mega-set animation file
-	ob_graph->anim_resource	= ob_mega->megaset_res;
-
-	// dir + first stand frame (always frame 96)
-	ob_graph->anim_pc = params[4] + 96;
-
+	_router->standAt(
+		(ObjectGraphic *) decodePtr(params[0]),
+		(ObjectMega *) decodePtr(params[1]),
+		params[2], params[3], params[4]);
 	return IR_CONT;
 }
 
 /**
  * Stand mega into the specified direction at current feet coords.
- * Just needs to call fnStandAt() with current feet coords.
+ * Just needs to call standAt() with current feet coords.
  */
 
 int32 Logic::fnStand(int32 *params) {
 	// params:	0 pointer to object's graphic structure
 	//		1 pointer to object's mega structure
 	//		2 target direction
+	ObjectMega *ob_mega = (ObjectMega *) decodePtr(params[1]);
 
-	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[1]);
-
-	int32 pars[5];
-
-	pars[0] = params[0];
-	pars[1] = params[1];
-	pars[2] = ob_mega->feet_x;
-	pars[3] = ob_mega->feet_y;
-	pars[4] = params[2];
-
-	return fnStandAt(pars);
+	_router->standAt(
+		(ObjectGraphic *) decodePtr(params[0]),
+		ob_mega, ob_mega->feet_x, ob_mega->feet_y, params[2]);
+	return IR_CONT;
 }
 
 /**
@@ -511,35 +288,11 @@
 	//		1 pointer to object's mega structure
 	//		2 anim resource id
 
-	byte *anim_file = _vm->_resman->openResource(params[2]);
-	AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
-
-	int32 pars[5];
-
-	pars[0] = params[0];
-	pars[1] = params[1];
-
-	pars[2] = anim_head->feetEndX;
-	pars[3] = anim_head->feetEndY;
-	pars[4] = anim_head->feetEndDir;
-
-	// If start coords not available either use the standby coords (which
-	// should be set beforehand in the script)
-
-	if (pars[2] == 0 && pars[3] == 0) {
-		byte buf[NAME_LEN];
-
-		pars[2] = _standbyX;
-		pars[3] = _standbyY;
-		pars[4] = _standbyDir;
-
-		debug(3, "WARNING: fnStandAfterAnim(%s) used standby coords", _vm->fetchObjectName(params[2], buf));
-	}
-
-	assert(pars[4] >= 0 && pars[4] <= 7);
-
-	_vm->_resman->closeResource(params[2]);
-	return fnStandAt(pars);
+	_router->standAfterAnim(
+		(ObjectGraphic *) decodePtr(params[0]),
+		(ObjectMega *) decodePtr(params[1]),
+		params[2]);
+	return IR_CONT;
 }
 
 int32 Logic::fnPause(int32 *params) {
@@ -549,7 +302,7 @@
 	// NB. Pause-value of 0 causes script to continue, 1 causes a 1-cycle
 	// quit, 2 gives 2 cycles, etc.
 
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
+	ObjectLogic *ob_logic = (ObjectLogic *) decodePtr(params[0]);
 
 	if (ob_logic->looping == 0) {
 		ob_logic->looping = 1;
@@ -577,9 +330,8 @@
 
 int32 Logic::fnAddMenuObject(int32 *params) {
 	// params:	0 pointer to a MenuObject structure to copy down
-	MenuObject *menuObject = (MenuObject *) _vm->_memory->decodePtr(params[0]);
 
-	_vm->_mouse->addMenuObject(menuObject);
+	_vm->_mouse->addMenuObject((MenuObject *) decodePtr(params[0]));
 	return IR_CONT;
 }
 
@@ -628,7 +380,7 @@
 	AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
 
 	// set up anim resource in graphic object
-	ObjectGraphic *ob_graphic = (ObjectGraphic *) _vm->_memory->decodePtr(params[0]);
+	ObjectGraphic *ob_graphic = (ObjectGraphic *) decodePtr(params[0]);
 
 	ob_graphic->anim_resource = res;
 	ob_graphic->anim_pc = params[2] ? anim_head->noAnimFrames - 1 : 0;
@@ -643,7 +395,7 @@
 	//		1 minimum number of game-cycles to pause
 	//		2 maximum number of game-cycles to pause
 
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
+	ObjectLogic *ob_logic = (ObjectLogic *) decodePtr(params[0]);
 	int32 pars[2];
 
 	if (ob_logic->looping == 0) {
@@ -666,9 +418,9 @@
 	//		1 pointer to graphic structure
 	//		2 pointer to mega structure or NULL if not a mega
 
-	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
-	ObjectGraphic *ob_graph = (ObjectGraphic *) _vm->_memory->decodePtr(params[1]);
-	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
+	ObjectMouse *ob_mouse = (ObjectMouse *) decodePtr(params[0]);
+	ObjectGraphic *ob_graph = (ObjectGraphic *) decodePtr(params[1]);
+	ObjectMega *ob_mega = (ObjectMega *) decodePtr(params[2]);
 
 	_vm->_screen->registerFrame(ob_mouse, ob_graph, ob_mega);
 	return IR_CONT;
@@ -705,7 +457,7 @@
 
 	// params:	0 pointer to mega structure
 
-	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[0]);
+	ObjectMega *ob_mega = (ObjectMega *) decodePtr(params[0]);
 	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
 	screenInfo->player_feet_x = ob_mega->feet_x;
@@ -738,7 +490,7 @@
 int32 Logic::fnInitFloorMouse(int32 *params) {
 	// params:	0 pointer to object's mouse structure
 
- 	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+ 	ObjectMouse *ob_mouse = (ObjectMouse *) decodePtr(params[0]);
 	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
 	// floor is always lowest priority
@@ -762,14 +514,12 @@
 
 	// params: 	0 pointer to a mega structure
 
-	memcpy(&_engineMega, _vm->_memory->decodePtr(params[0]), sizeof(ObjectMega));
+	memcpy(&_engineMega, decodePtr(params[0]), sizeof(ObjectMega));
 	return IR_CONT;
 }
 
 /**
  * Turn mega to face point (x,y) on the floor
- * Just needs to call fnWalk() with current feet coords & direction computed
- * by whatTarget()
  */
 
 int32 Logic::fnFaceXY(int32 *params) {
@@ -780,27 +530,12 @@
 	//		4 target x-coord
 	//		5 target y-coord
 
-	int32 pars[7];
-
-	pars[0] = params[0];
-	pars[1] = params[1];
-	pars[2] = params[2];
-	pars[3] = params[3];
-
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
-
-	// If this is the start of the turn, get the mega's current feet
-	// coords + the required direction
-
-	if (!ob_logic->looping) {
-		ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
-	
-		pars[4] = ob_mega->feet_x;
-		pars[5] = ob_mega->feet_y;
-		pars[6] = whatTarget(ob_mega->feet_x, ob_mega->feet_y, params[4], params[5]);
-	}
-
-	return fnWalk(pars);
+	return _router->faceXY(
+		(ObjectLogic *) decodePtr(params[0]),
+		(ObjectGraphic *) decodePtr(params[1]),
+		(ObjectMega *) decodePtr(params[2]),
+		(ObjectWalkdata *) decodePtr(params[3]),
+		params[4], params[5]);
 }
 
 /**
@@ -894,7 +629,7 @@
 
 	_vm->_resman->closeResource(target);
 
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
+	ObjectLogic *ob_logic = (ObjectLogic *) decodePtr(params[0]);
 
 	if (_scriptVars[RESULT] == 1 && !_scriptVars[INS_COMMAND] && ob_logic->looping == 0) {
 		// The target is waiting, i.e. not busy, and there is no other
@@ -1001,65 +736,14 @@
 	//		2 pointer to object's mega structure
 	//		3 pointer to object's walkdata structure
 	//		4 id of target mega to face
-	//		5 distance
-
-	int32 pars[7];
-
-	pars[0] = params[0];
-	pars[1] = params[1];
-	pars[2] = params[2];
-	pars[3] = params[3];
-
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
-
-	// If this is the start of the walk, calculate the route.
-
-	if (!ob_logic->looping)	{
-		StandardHeader *head = (StandardHeader *) _vm->_resman->openResource(params[4]);
-
-		assert(head->fileType == GAME_OBJECT);
-
-		// Call the base script. This is the graphic/mouse service
-		// call, and will set _engineMega to the ObjectMega of mega we
-		// want to route to.
-
-		char *raw_script_ad = (char *) head;
-		uint32 null_pc = 3;
-
-		runScript(raw_script_ad, raw_script_ad, &null_pc);
-
-		_vm->_resman->closeResource(params[4]);
-
-		// Stand exactly beside the mega, ie. at same y-coord
-		pars[5] = _engineMega.feet_y;
-
-		ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
-
-		// Apply scale factor to walk distance. Ay+B gives 256 * scale
-		// ie. 256 * 256 * true_scale for even better accuracy, ie.
-		// scale = (Ay + B) / 256
-
-		int scale = (ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b) / 256;
-		int mega_separation = (params[5] * scale) / 256;
-
-		debug(4, "Target is at (%d, %d), separation %d", _engineMega.feet_x, _engineMega.feet_y, mega_separation);
-
-		if (_engineMega.feet_x < ob_mega->feet_x) {
-			// Target is left of us, so aim to stand to their
-			// right. Face down_left
-
-			pars[4] = _engineMega.feet_x + mega_separation;
-			pars[6] = 5;
-		} else {
-			// Ok, must be right of us so aim to stand to their
-			// left. Face down_right.
-
-			pars[4] = _engineMega.feet_x - mega_separation;
-			pars[6] = 3;
-		}
-	}
+	//		5 separation
 
-	return fnWalk(pars);
+	return _router->walkToTalkToMega(
+		(ObjectLogic *) decodePtr(params[0]),
+		(ObjectGraphic *) decodePtr(params[1]),
+		(ObjectMega *) decodePtr(params[2]),
+		(ObjectWalkdata *) decodePtr(params[3]),
+		params[4], params[5]);
 }
 
 int32 Logic::fnFadeDown(int32 *params) {
@@ -1111,8 +795,8 @@
 
 	// Set up the pointers which we know we'll always need
 
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[S_OB_LOGIC]);
-	ObjectGraphic *ob_graphic = (ObjectGraphic *) _vm->_memory->decodePtr(params[S_OB_GRAPHIC]);
+	ObjectLogic *ob_logic = (ObjectLogic *) decodePtr(params[S_OB_LOGIC]);
+	ObjectGraphic *ob_graphic = (ObjectGraphic *) decodePtr(params[S_OB_GRAPHIC]);
 
 	// FIRST TIME ONLY: create the text, load the wav, set up the anim,
 	// etc.
@@ -1229,8 +913,8 @@
 			// Use this direction table to derive the anim
 			// NB. ASSUMES WE HAVE A MEGA OBJECT!!
 
-			ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[S_OB_MEGA]);
-			int32 *anim_table = (int32 *) _vm->_memory->decodePtr(params[S_DIR_TABLE]);
+			ObjectMega *ob_mega = (ObjectMega *) decodePtr(params[S_OB_MEGA]);
+			int32 *anim_table = (int32 *) decodePtr(params[S_DIR_TABLE]);
 
 			_animId = anim_table[ob_mega->current_dir];
 		} else {
@@ -1504,7 +1188,7 @@
 	//		3 pointer to ob_mega
 	//		4 pointer to ob_walkdata
 
-	ObjectSpeech *ob_speech = (ObjectSpeech *) _vm->_memory->decodePtr(params[1]);
+	ObjectSpeech *ob_speech = (ObjectSpeech *) decodePtr(params[1]);
 
 	while (1) {
 		int32 pars[9];
@@ -1733,7 +1417,7 @@
 	// Where s is system scale, which itself is (256 * actual_scale) ie.
 	// s == 128 is half size
 
- 	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[0]);
+ 	ObjectMega *ob_mega = (ObjectMega *) decodePtr(params[0]);
 
 	ob_mega->scale_a = params[1];
 	ob_mega->scale_b = params[2];
@@ -1793,7 +1477,7 @@
 	StandardHeader *head = (StandardHeader *) _vm->_resman->openResource(params[1]);
 	assert(head->fileType == GAME_OBJECT);
 
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
+	ObjectLogic *ob_logic = (ObjectLogic *) decodePtr(params[0]);
 
 	if (!ob_logic->looping) {
 		// This is the first time, so set up the time-out.
@@ -1915,7 +1599,7 @@
 	// params:	0 pointer to object's mega structure
 	//		1 value to set it to
 
-	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[0]);
+	ObjectMega *ob_mega = (ObjectMega *) decodePtr(params[0]);
 
 	ob_mega->megaset_res = params[1];
 	return IR_CONT;
@@ -2041,12 +1725,7 @@
 	//		1 y-coord
 	//		2 direction (0..7)
 
-	assert(params[2] >= 0 && params[2] <= 7);
-
-	_standbyX = (int16) params[0];
-	_standbyY = (int16) params[1];
-	_standbyDir = (uint8) params[2];
-
+	_router->setStandbyCoords(params[0], params[1], params[2]);
 	return IR_CONT;
 }
 
@@ -2122,35 +1801,11 @@
 	//		1 pointer to object's mega structure
 	//		2 anim resource id
 
-	byte *anim_file = _vm->_resman->openResource(params[2]);
-	AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
-
-	int32 pars[5];
-
-	pars[0] = params[0];
-	pars[1] = params[1];
-
-	pars[2] = anim_head->feetStartX;
-	pars[3] = anim_head->feetStartY;
-	pars[4] = anim_head->feetStartDir;
-
-	// If start coords not available use the standby coords (which should
-	// be set beforehand in the script)
-
-	if (pars[2] == 0 && pars[3] == 0) {
-		byte buf[NAME_LEN];
-
-		pars[2] = _standbyX;
-		pars[3] = _standbyY;
-		pars[4] = _standbyDir;
-
-		debug(3, "WARNING: fnStandAtAnim(%s) used standby coords", _vm->fetchObjectName(params[2], buf));
-	}
-
-	assert(pars[4] >= 0 && pars[4] <= 7);
-
-	_vm->_resman->closeResource(params[2]);
-	return fnStandAt(pars);
+	_router->standAtAnim(
+		(ObjectGraphic *) decodePtr(params[0]),
+		(ObjectMega *) decodePtr(params[1]),
+		params[2]);
+	return IR_CONT;
 }
 
 #define SCROLL_MOUSE_WIDTH 20
@@ -2158,7 +1813,7 @@
 int32 Logic::fnSetScrollLeftMouse(int32 *params) {
 	// params:	0 pointer to object's mouse structure
 
- 	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+ 	ObjectMouse *ob_mouse = (ObjectMouse *) decodePtr(params[0]);
 	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
 	// Highest priority
@@ -2183,7 +1838,7 @@
 int32 Logic::fnSetScrollRightMouse(int32 *params) {
 	// params:	0 pointer to object's mouse structure
 
-	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+	ObjectMouse *ob_mouse = (ObjectMouse *) decodePtr(params[0]);
 	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
 	// Highest priority
@@ -2302,9 +1957,9 @@
 	//		1 pointer to object's graphic structure
 	//		2 pointer to object's mega structure
 
-	byte *logic_ptr = _vm->_memory->decodePtr(params[0]);
-	byte *graphic_ptr = _vm->_memory->decodePtr(params[1]);
-	byte *mega_ptr = _vm->_memory->decodePtr(params[2]);
+	byte *logic_ptr = decodePtr(params[0]);
+	byte *graphic_ptr = decodePtr(params[1]);
+	byte *mega_ptr = decodePtr(params[2]);
 
 	// Copy from savegame header to player object
 
@@ -2352,9 +2007,9 @@
 
 	// Copy from player object to savegame header
 
-	memcpy(&_vm->_saveGameHeader.logic, _vm->_memory->decodePtr(params[0]), sizeof(ObjectLogic));
-	memcpy(&_vm->_saveGameHeader.graphic, _vm->_memory->decodePtr(params[1]), sizeof(ObjectGraphic));
-	memcpy(&_vm->_saveGameHeader.mega, _vm->_memory->decodePtr(params[2]), sizeof(ObjectMega));
+	memcpy(&_vm->_saveGameHeader.logic, decodePtr(params[0]), sizeof(ObjectLogic));
+	memcpy(&_vm->_saveGameHeader.graphic, decodePtr(params[1]), sizeof(ObjectGraphic));
+	memcpy(&_vm->_saveGameHeader.mega, decodePtr(params[2]), sizeof(ObjectMega));
 
 	return IR_CONT;
 }
@@ -2426,7 +2081,7 @@
 	// params:	0 pointer to object's logic structure
 	//		1 number of game-cycles to pause
 
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
+	ObjectLogic *ob_logic = (ObjectLogic *) decodePtr(params[0]);
 
 	if (checkEventWaiting()) {
 		ob_logic->looping = 0;
@@ -2451,42 +2106,12 @@
 	//		3 pointer to object's walkdata structure
 	//		4 id of target mega to face
 
-	int32 pars[7];
-
-	pars[0] = params[0];
-	pars[1] = params[1];
-	pars[2] = params[2];
-	pars[3] = params[3];
-
-	ObjectLogic *ob_logic = (ObjectLogic *) _vm->_memory->decodePtr(params[0]);
-
-	// If this is the start of the walk, decide where to walk to.
-
-	if (!ob_logic->looping) {
-		StandardHeader *head = (StandardHeader *) _vm->_resman->openResource(params[4]);
-
-		assert(head->fileType == GAME_OBJECT);
-
-		// Call the base script. This is the graphic/mouse service
-		// call, and will set _engineMega to the ObjectMega of mega we
-		// want to turn to face.
-
-		char *raw_script_ad = (char *) head;
-		uint32 null_pc = 3;
-
-		runScript(raw_script_ad, raw_script_ad, &null_pc);
-
-		_vm->_resman->closeResource(params[4]);
-
-		ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
-
-		pars[3] = params[3];
-		pars[4] = ob_mega->feet_x;
-		pars[5] = ob_mega->feet_y;
-		pars[6] = whatTarget(ob_mega->feet_x, ob_mega->feet_y, _engineMega.feet_x, _engineMega.feet_y);
-	}
-
-	return fnWalk(pars);
+	return _router->faceMega(
+		(ObjectLogic *) decodePtr(params[0]),
+		(ObjectGraphic *) decodePtr(params[1]),
+		(ObjectMega *) decodePtr(params[2]),
+		(ObjectWalkdata *) decodePtr(params[3]),
+		params[4]);
 }
 
 int32 Logic::fnPlaySequence(int32 *params) {
@@ -2501,11 +2126,11 @@
 	// of computer games" - but at the very least we want to show the
 	// cutscene subtitles, so I removed them.
 
-	debug(5, "fnPlaySequence(\"%s\");", (const char *) _vm->_memory->decodePtr(params[0]));
+	debug(5, "fnPlaySequence(\"%s\");", (const char *) decodePtr(params[0]));
 
 	// add the appropriate file extension & play it
 
-	strcpy(filename, (const char *) _vm->_memory->decodePtr(params[0]));
+	strcpy(filename, (const char *) decodePtr(params[0]));
 
 	// Write to walkthrough file (zebug0.txt)
  	debug(5, "PLAYING SEQUENCE \"%s\"", filename);

Index: logic.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/logic.h,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- logic.h	24 Apr 2005 12:13:03 -0000	1.44
+++ logic.h	3 May 2005 09:00:05 -0000	1.45
@@ -23,6 +23,8 @@
 #ifndef _LOGIC
 #define _LOGIC
 
+#include "sword2/memory.h"
+
 namespace Sword2 {
 
 struct MovieTextObject;
@@ -51,6 +53,10 @@
 private:
 	Sword2Engine *_vm;
 
+	inline byte *decodePtr(int32 n) {
+		return _vm->_memory->decodePtr(n);
+	}
+
 	uint32 _objectKillList[OBJECT_KILL_LIST_SIZE];
 
 	// keeps note of no. of objects in the kill list
@@ -118,12 +124,6 @@
 	void formText(int32 *params);
 	bool wantSpeechForLine(uint32 wavId);
 
-	int16 _standbyX;	// see fnSetStandbyCoords()
-	int16 _standbyY;
-	int16 _standbyDir;
-
-	int whatTarget(int startX, int startY, int destX, int destY);
-
 	// Set by fnPassMega()
 	ObjectMega _engineMega;
 
@@ -133,6 +133,8 @@
 
 	EventUnit *getEventList() { return _eventList; }
 
+	ObjectMega *getEngineMega() { return &_engineMega; }
+
 	// Point to the global variable data
 	static uint32 *_scriptVars;
 

Index: router.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/router.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- router.h	2 May 2005 05:41:01 -0000	1.20
+++ router.h	3 May 2005 09:00:05 -0000	1.21
@@ -104,6 +104,10 @@
 private:
 	Sword2Engine *_vm;
 
+	int16 _standbyX;	// see fnSetStandbyCoords()
+	int16 _standbyY;
+	int16 _standbyDir;
+
 	// stores pointers to mem blocks containing routes created & used by
 	// megas (NULL if slot not in use)
 	WalkData *_routeSlots[TOTAL_ROUTE_SLOTS];
@@ -224,6 +228,24 @@
 		memset(_leadingLeg, 0, sizeof(_leadingLeg));
 	}
 
+	void setStandbyCoords(int16 x, int16 y, uint8 dir);
+	int whatTarget(int startX, int startY, int destX, int destY);
+
+	// Walking
+	int doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir);
+	int walkToAnim(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 animRes);
+	int walkToTalkToMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 megaId, uint32 separation);
+
+	// Turning
+	int doFace(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint8 target_dir);
+	int faceXY(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int16 target_x, int16 target_y);
+	int faceMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 megaId);
+
+	// Standing
+	void standAt(ObjectGraphic *ob_graph, ObjectMega *ob_mega, int32 x, int32 y, int32 dir);
+	void standAfterAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 animRes);
+	void standAtAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 animRes);
+
 	int32 routeFinder(ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int32 x, int32 y, int32 dir);
 
 	void earlySlowOut(ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata);

Index: speech.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/speech.cpp,v
retrieving revision 1.73
retrieving revision 1.74
diff -u -d -r1.73 -r1.74
--- speech.cpp	9 Apr 2005 13:07:59 -0000	1.73
+++ speech.cpp	3 May 2005 09:00:05 -0000	1.74
@@ -26,7 +26,6 @@
 #include "sword2/defs.h"
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
-#include "sword2/memory.h"
 #include "sword2/resman.h"
 
 namespace Sword2 {
@@ -88,7 +87,7 @@
 
 	if (cdt_entry->frameType & FRAME_OFFSET) {
 		// The frame has offsets, i.e. it's a scalable mega frame
-		ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[S_OB_MEGA]);
+		ObjectMega *ob_mega = (ObjectMega *) decodePtr(params[S_OB_MEGA]);
 
 		// Calculate scale at which to print the sprite, based on feet
 		// y-coord and scaling constants (NB. 'scale' is actually
@@ -159,7 +158,7 @@
 		return;
 	}
 
-	ObjectSpeech *ob_speech = (ObjectSpeech *) _vm->_memory->decodePtr(params[S_OB_SPEECH]);
+	ObjectSpeech *ob_speech = (ObjectSpeech *) decodePtr(params[S_OB_SPEECH]);
 
 	// Establish the max width allowed for this text sprite.
 	uint32 textWidth = ob_speech->width ? ob_speech->width : 400;

Index: walker.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/walker.cpp,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- walker.cpp	9 Apr 2005 13:08:00 -0000	1.46
+++ walker.cpp	3 May 2005 09:00:06 -0000	1.47
@@ -20,18 +20,26 @@
 
 // WALKER.CPP by James (14nov96)
 
-// Script functions for moving megas about the place & also for keeping tabs
-// on them
+// Functions for moving megas about the place & also for keeping tabs on them
 
 #include "common/stdafx.h"
 #include "sword2/sword2.h"
 #include "sword2/defs.h"
+#include "sword2/interpreter.h"
 #include "sword2/logic.h"
 #include "sword2/resman.h"
 #include "sword2/router.h"
 
 namespace Sword2 {
 
+void Router::setStandbyCoords(int16 x, int16 y, uint8 dir) {
+	assert(dir <= 7);
+
+	_standbyX = x;
+	_standbyY = y;
+	_standbyDir = dir;
+}
+
 /**
  * Work out direction from start to dest.
  */
@@ -40,7 +48,7 @@
 #define	diagonalx 36
 #define	diagonaly 8
 
-int Logic::whatTarget(int startX, int startY, int destX, int destY) {
+int Router::whatTarget(int startX, int startY, int destX, int destY) {
 	int deltaX = destX - startX;
 	int deltaY = destY - startY;
 
@@ -66,4 +74,366 @@
 	return (deltaY > 0) ? 5 : 7;
 }
 
+/**
+ * Walk meta to (x,y,dir). Set RESULT to 0 if it succeeded. Otherwise, set
+ * RESULT to 1. Return true if the mega has finished walking.
+ */
+
+int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir) {
+	// If this is the start of the walk, calculate the route.
+
+	if (!ob_logic->looping) {
+		// If we're already there, don't even bother allocating
+		// memory and calling the router, just quit back & continue
+		// the script! This avoids an embarassing mega stand frame
+		// appearing for one cycle when we're already in position for
+		// an anim eg. repeatedly clicking on same object to repeat
+		// an anim - no mega frame will appear in between runs of the
+		// anim.
+		
+		if (ob_mega->feet_x == target_x && ob_mega->feet_y == target_y && ob_mega->current_dir == target_dir) {
+			Logic::_scriptVars[RESULT] = 0;
+			return IR_CONT;
+		}
+
+		assert(target_dir <= 8);
+
+		ob_mega->walk_pc = 0;
+
+		// Set up mem for _walkData in route_slots[] & set mega's
+		// 'route_slot_id' accordingly
+		allocateRouteMem();
+
+		int32 route = routeFinder(ob_mega, ob_walkdata, target_x, target_y, target_dir);
+
+		// 0 = can't make route to target
+		// 1 = created route
+		// 2 = zero route but may need to turn
+
+		if (route != 1 && route != 2) {
+			freeRouteMem();
+			Logic::_scriptVars[RESULT] = 1;
+			return IR_CONT;
+		}
+
+		// Walk is about to start
+
+		ob_mega->currently_walking = 1;
+		ob_logic->looping = 1;
+		ob_graph->anim_resource = ob_mega->megaset_res;
+	} else if (Logic::_scriptVars[EXIT_FADING] && _vm->_screen->getFadeStatus() == RDFADE_BLACK) {
+		// Double clicked an exit, and the screen has faded down to
+		// black. Ok, that's it. Back to script and change screen.
+
+		// We have to clear te EXIT_CLICK_ID variable in case there's a
+		// walk instruction on the new screen, or it'd be cut short.
+
+		freeRouteMem();
+
+		ob_logic->looping = 0;
+		ob_mega->currently_walking = 0;
+		Logic::_scriptVars[EXIT_CLICK_ID] = 0;
+		Logic::_scriptVars[RESULT] = 0;
+
+		return IR_CONT;
+	}
+
+	// Get pointer to walkanim & current frame position
+
+	WalkData *walkAnim = getRouteMem();
+	int32 walk_pc = ob_mega->walk_pc;
+
+	// If stopping the walk early, overwrite the next step with a
+	// slow-out, then finish
+
+	if (_vm->_logic->checkEventWaiting() && walkAnim[walk_pc].step == 0 && walkAnim[walk_pc + 1].step == 1) {
+		// At the beginning of a step
+		earlySlowOut(ob_mega, ob_walkdata);
+	}
+
+	// Get new frame of walk
+
+	ob_graph->anim_pc = walkAnim[walk_pc].frame;
+	ob_mega->current_dir = walkAnim[walk_pc].dir;
+	ob_mega->feet_x = walkAnim[walk_pc].x;
+	ob_mega->feet_y = walkAnim[walk_pc].y;
+
+	// Is the NEXT frame is the end-marker (512) of the walk sequence?
+
+	if (walkAnim[walk_pc + 1].frame != 512) {
+		// No, it wasn't. Increment the walk-anim frame number and
+		// come back next cycle.
+		ob_mega->walk_pc++;
+		return IR_REPEAT;
+	}
+
+	// We have reached the end-marker, which means we can return to the
+	// script just as the final (stand) frame of the walk is set.
+
+	freeRouteMem();
+	ob_logic->looping = 0;
+	ob_mega->currently_walking = 0;
+
+	// If George's walk has been interrupted to run a new action script for
+	// instance or Nico's walk has been interrupted by player clicking on
+	// her to talk
+
+	// There used to be code here for checking if two megas were colliding,
+	// but it had been commented out, and it was only run if a function
+	// that always returned zero returned non-zero.
+
+	if (_vm->_logic->checkEventWaiting()) {
+		_vm->_logic->startEvent();
+		Logic::_scriptVars[RESULT] = 1;
+		return IR_TERMINATE;
+	}
+
+	Logic::_scriptVars[RESULT] = 0;
+
+	// CONTINUE the script so that RESULT can be checked! Also, if an anim
+	// command follows the fnWalk command, the 1st frame of the anim (which
+	// is always a stand frame itself) can replace the final stand frame of
+	// the walk, to hide the slight difference between the shrinking on the
+	// mega frames and the pre-shrunk anim start-frame.
+
+	return IR_CONT;
+}
+
+/**
+ * Walk mega to start position of anim
+ */
+
+int Router::walkToAnim(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 animRes) {
+	int16 target_x = 0;
+	int16 target_y = 0;
+	uint8 target_dir = 0;
+
+	// Walkdata is needed for earlySlowOut if player clicks elsewhere
+	// during the walk.
+
+	// If this is the start of the walk, read anim file to get start coords
+
+	if (!ob_logic->looping) {
+		byte *anim_file = _vm->_resman->openResource(animRes);
+		AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
+
+		target_x = anim_head->feetStartX;
+		target_y = anim_head->feetStartY;
+		target_dir = anim_head->feetStartDir;
+
+		_vm->_resman->closeResource(animRes);
+
+		// If start coords not yet set in anim header, use the standby
+		// coords (which should be set beforehand in the script).
+
+		if (target_x == 0 && target_y == 0) {
+			target_x = _standbyX;
+			target_y = _standbyY;
+			target_dir = _standbyDir;
+		}
+
+		assert(target_dir <= 7);
+	}
+
+	return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
+}
+
+/**
+ * Route to the left or right hand side of target id, if possible.
+ */
+
+int Router::walkToTalkToMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 megaId, uint32 separation) {
+	int16 target_x = 0;
+	int16 target_y = 0;
+	uint8 target_dir = 0;
+
+	// If this is the start of the walk, calculate the route.
+
+	if (!ob_logic->looping)	{
+		StandardHeader *head = (StandardHeader *) _vm->_resman->openResource(megaId);
+
+		assert(head->fileType == GAME_OBJECT);
+
+		// Call the base script. This is the graphic/mouse service
+		// call, and will set _engineMega to the ObjectMega of mega we
+		// want to route to.
+
+		char *raw_script_ad = (char *) head;
+		uint32 null_pc = 3;
+
+		_vm->_logic->runScript(raw_script_ad, raw_script_ad, &null_pc);
+		_vm->_resman->closeResource(megaId);
+
+		ObjectMega *targetMega = _vm->_logic->getEngineMega();
+
+		// Stand exactly beside the mega, ie. at same y-coord
+		target_y = targetMega->feet_y;
+
+		// Apply scale factor to walk distance. Ay+B gives 256 * scale
+		// ie. 256 * 256 * true_scale for even better accuracy, ie.
+		// scale = (Ay + B) / 256
+
+		int scale = (ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b) / 256;
+		int mega_separation = (separation * scale) / 256;
+
+		debug(4, "Target is at (%d, %d), separation %d", targetMega->feet_x, targetMega->feet_y, mega_separation);
+
+		if (targetMega->feet_x < ob_mega->feet_x) {
+			// Target is left of us, so aim to stand to their
+			// right. Face down_left
+
+			target_x = targetMega->feet_x + mega_separation;
+			target_dir = 5;
+		} else {
+			// Ok, must be right of us so aim to stand to their
+			// left. Face down_right.
+
+			target_x = targetMega->feet_x - mega_separation;
+			target_dir = 3;
+		}
+	}
+
+	return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
+}
+/**
+ * Turn mega to the specified direction. Just needs to call doWalk() with
+ * current feet coords, so router can produce anim of turn frames.
+ */
+
+int Router::doFace(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint8 target_dir) {
+	int16 target_x = 0;
+	int16 target_y = 0;
+
+	// If this is the start of the turn, get the mega's current feet
+	// coords + the required direction
+
+	if (!ob_logic->looping) {
+		assert(target_dir <= 7);
+
+		target_x = ob_mega->feet_x;
+		target_y = ob_mega->feet_y;
+	}
+
+	return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
+}
+
+/**
+ * Turn mega to face point (x,y) on the floor
+ */
+
+int Router::faceXY(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int16 target_x, int16 target_y) {
+	uint8 target_dir = 0;
+
+	// If this is the start of the turn, get the mega's current feet
+	// coords + the required direction
+
+	if (!ob_logic->looping) {
+		target_dir = whatTarget(ob_mega->feet_x, ob_mega->feet_y, target_x, target_y);
+	}
+
+	return doFace(ob_logic, ob_graph, ob_mega, ob_walkdata, target_dir);
+}
+
+/**
+ * Turn mega to face another mega.
+ */
+
+int Router::faceMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 megaId) {
+	uint8 target_dir = 0;
+
+	// If this is the start of the walk, decide where to walk to.
+
+	if (!ob_logic->looping) {
+		StandardHeader *head = (StandardHeader *) _vm->_resman->openResource(megaId);
+
+		assert(head->fileType == GAME_OBJECT);
+
+		// Call the base script. This is the graphic/mouse service
+		// call, and will set _engineMega to the ObjectMega of mega we
+		// want to turn to face.
+
+		char *raw_script_ad = (char *) head;
+		uint32 null_pc = 3;
+
+		_vm->_logic->runScript(raw_script_ad, raw_script_ad, &null_pc);
+		_vm->_resman->closeResource(megaId);
+
+		ObjectMega *targetMega = _vm->_logic->getEngineMega();
+
+		target_dir = whatTarget(ob_mega->feet_x, ob_mega->feet_y, targetMega->feet_x, targetMega->feet_y);
+	}
+
+	return doFace(ob_logic, ob_graph, ob_mega, ob_walkdata, target_dir);
+}
+
+/**
+ * Stand mega at (x,y,dir)
+ * Sets up the graphic object, but also needs to set the new 'current_dir' in
+ * the mega object, so the router knows in future
+ */
+
+void Router::standAt(ObjectGraphic *ob_graph, ObjectMega *ob_mega, int32 x, int32 y, int32 dir) {
+	assert(dir >= 0 && dir <= 7);
+
+	// Set up the stand frame & set the mega's new direction
+
+	ob_mega->feet_x = x;
+	ob_mega->feet_y = y;
+	ob_mega->current_dir = dir;
+
+	// Mega-set animation file
+	ob_graph->anim_resource	= ob_mega->megaset_res;
+
+	// Dir + first stand frame (always frame 96)
+	ob_graph->anim_pc = dir + 96;
+}
+
+/**
+ * stand mega at end position of anim
+ */
+
+void Router::standAfterAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 animRes) {
+	byte *anim_file = _vm->_resman->openResource(animRes);
+	AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
+
+	int32 x = anim_head->feetEndX;
+	int32 y = anim_head->feetEndY;
+	int32 dir = anim_head->feetEndDir;
+
+	_vm->_resman->closeResource(animRes);
+
+	// If start coords not available either use the standby coords (which
+	// should be set beforehand in the script)
+
+	if (x == 0 && y == 0) {
+		x = _standbyX;
+		y = _standbyY;
+		dir = _standbyDir;
+	}
+
+	standAt(ob_graph, ob_mega, x, y, dir);
+}
+
+void Router::standAtAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 animRes) {
+	byte *anim_file = _vm->_resman->openResource(animRes);
+	AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
+
+	int32 x = anim_head->feetStartX;
+	int32 y = anim_head->feetStartY;
+	int32 dir = anim_head->feetStartDir;
+
+	_vm->_resman->closeResource(animRes);
+
+	// If start coords not available use the standby coords (which should
+	// be set beforehand in the script)
+
+	if (x == 0 && y == 0) {
+		x = _standbyX;
+		y = _standbyY;
+		dir = _standbyDir;
+	}
+
+	standAt(ob_graph, ob_mega, x, y, dir);
+}
+
 } // End of namespace Sword2





More information about the Scummvm-git-logs mailing list