/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/walker.cpp,v 1.4 2003/07/28 11:21:25 khalek Exp $
 */

//--------------------------------------------------------------------------------------
// WALKER.CPP by James (14nov96)

// script functions for moving megas about the place & also for keeping tabs on them

// FN_walk()				// walk to (x,y,dir)
// FN_walk_to_anim()		// walk to start position of anim
// FN_turn()				// turn to (dir)
// FN_stand_at()			// stand at (x,y,dir)
// FN_stand()				// stand facing (dir)
// FN_stand_after_anim()	// stand at end position of anim
// FN_face_id()				// turn to face object (id)
// FN_face_xy()				// turn to face point (x,y)
// FN_is_facing()			// is mega (id) facing us?
// FN_get_pos()				// get details of another mega's position

//--------------------------------------------------------------------------------------

#include "stdafx.h"
//#include "src\driver96.h"
#include "console.h"
#include "defs.h"
#include "events.h"
#include "function.h"
#include "interpreter.h"
#include "logic.h"	// for FN_add_to_kill_list
#include "object.h"
#include "protocol.h"
#include "router.h"
#include "sync.h"

//--------------------------------------------------------------------------------------

int16	standby_x;			// see FN_set_standby_coords
int16	standby_y;
uint8	standby_dir;

//--------------------------------------------------------------------------------------
/*
uint8 Check_walk_anim_ok( Object_mega *ob_mega, Object_walkdata *ob_walkdata );
//--------------------------------------------------------------------------------------
// NEW CODE TO VERIFY THAT THE WALK-ANIM CONTAINS NO INVALID FRAMES!
// (James 15sep97)
uint8 Check_walk_anim_ok( Object_mega *ob_mega, Object_walkdata *ob_walkdata )
{
	int32		walk_pc=0;
	_walkData	*walkAnim;
	uint8		*anim_file;
	_animHeader	*anim_head;
	uint32		lastValidFrameNo;
	uint8		ok=1;


	anim_file = res_man.Res_open(ob_mega->megaset_res);	// open mega-set file
	anim_head = FetchAnimHeader( anim_file );			// set up pointer to the animation header
 	lastValidFrameNo = anim_head->noAnimFrames-1;		// get last valid frame number
	res_man.Res_close(ob_mega->megaset_res);			// close file

   	walkAnim = LockRouteMem();	// lock the _walkData array

	while (ok && (walkAnim[walk_pc].frame != 512))	// '512' id end-marker
	{
		if (walkAnim[walk_pc].frame > lastValidFrameNo)	// if frame exceeds the allowed range
			ok=0;

		walk_pc++;
	}

	FloatRouteMem();	// allow _walkData array to float about memory again

	return(ok);
}
*/
//--------------------------------------------------------------------------------------
// walk mega to (x,y,dir)

int32 FN_walk(int32 *params)	// James (14nov96)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 target x-coord
	//			5 target y-coord
	//			6 target direction

	Object_logic	*ob_logic;
	Object_graphic	*ob_graph;
	Object_mega		*ob_mega;
	Object_walkdata	*ob_walkdata;
	int16			target_x;
	int16			target_y;
	uint8			target_dir;
	int8			route;
	int32			walk_pc;
	_walkData		*walkAnim;

	//----------------------------------------------------------------------------------------
	// get the parameters

	ob_logic	= (Object_logic *)params[0];
	ob_graph	= (Object_graphic *)params[1];
	ob_mega		= (Object_mega *)params[2];

	target_x	= (int16) params[4];
	target_y	= (int16) params[5];
	target_dir	= (uint8) params[6];

	//----------------------------------------------------------------------------------------
	// if this is the start of the walk, calculate route

	if (ob_logic->looping==0)
	{
		//---------------------------
		// 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))
		{
			RESULT = 0;				// 0 means ok - finished walk
			return(IR_CONT);			// may as well continue the script
		}

		//---------------------------
		if ((params[6] < 0) || (params[6] > 8))	// invalid direction (NB. '8' means end walk on ANY direction)
			Con_fatal_error("Invalid direction (%d) in FN_walk (%s line %u)",params[6],__FILE__,__LINE__);
		//---------------------------

		ob_walkdata	= (Object_walkdata *)params[3];

		ob_mega->walk_pc=0;			//always

		AllocateRouteMem();	// set up mem for _walkData in route_slots[] & set mega's 'route_slot_id' accordingly
		route = (int8) RouteFinder(ob_mega, ob_walkdata, target_x, target_y, target_dir);

		/*
		if (id == PLAYER)
		{
			nExtraBars = 0;
			nExtraNodes = 0;
			if	((route == 1) || (route == 2))
			{
				megaOnGrid = 0;	// if we have just checked a grid with the mega on the grid take the mega off
				reRouteGeorge = 0;
			}
		}
		*/

		if	((route == 1) || (route == 2))	// 1=created route	2=zero route but may need to turn
		{
			//-------------------------------------------
			ob_logic->looping	= 1;		// so script FN_walk loop continues until end of walk-anim
											// need to animate the route now, so don't set result or return yet!

			ob_mega->currently_walking=1;	// started walk(James23jun97)
											// (see FN_get_player_savedata() in save_rest.cpp
			//-------------------------------------------
		}
		else							// 0=can't make route to target
		{
			FreeRouteMem();		// free up the walkdata mem block
			RESULT = 1;					// 1 means error, no walk created
			return(IR_CONT);			// may as well continue the script
		}

		// ok, walk is about to start, so set the mega's graphic resource
		ob_graph->anim_resource = ob_mega->megaset_res;
	}
	//----------------------------------------------------------------------------------------
	// double clicked an exit so quit the walk when screen is black

 	else if ((EXIT_FADING) && (GetFadeStatus()==RDFADE_BLACK))
	{
//		ok, thats it - back to script and change screen

		ob_logic->looping=0;	// so script loop stops
		FreeRouteMem();			// free up the walkdata mem block

		EXIT_CLICK_ID=0;		// must clear in-case on the new screen there's a walk instruction (which would get cut short)
//		EXIT_FADING=0;	// this will be reset when we change screens, so we can use it in script to check if a 2nd-click came along


		ob_mega->currently_walking=0;	// finished walk (James23jun97)
										// (see FN_get_player_savedata() in save_rest.cpp

		ob_mega->colliding=0;

		RESULT = 0;				// 0 means ok
		return(IR_CONT);		// continue the script so that RESULT can be checked!
	}
	//----------------------------------------------------------------------------------------
	// get pointer to walkanim & current frame position

	walkAnim	= LockRouteMem();	// lock the _walkData array
	walk_pc		= ob_mega->walk_pc;

	//----------------------------------------------------------------------------------------
	// if stopping the walk early, overwrite the next step with a slow-out, then finish

	if (Check_event_waiting())
	{
		if ((walkAnim[walk_pc].step == 0) && (walkAnim[walk_pc+1].step == 1))	// at the beginning of a step
		{
			ob_walkdata	= (Object_walkdata *)params[3];
			EarlySlowOut(ob_mega,ob_walkdata);
		}
	}
/*
	else if (CheckForCollision())
	{
		if ((walkAnim[walk_pc].step == 0) && (walkAnim[walk_pc+1].step == 1))	// at the beginning of a step
		{
			ob_walkdata	= (Object_walkdata *)params[3];
			EarlySlowOut(ob_mega,ob_walkdata);

			ob_mega->colliding=1;
		}
	}
*/
	//------------------------------------------------------------------
	// 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)

	if (walkAnim[walk_pc+1].frame==512)	// '512' is end-marker
	{
		ob_logic->looping=0;	// so script loop stops
		FreeRouteMem();	// free up the walkdata mem block

		ob_mega->currently_walking=0;	// finished walk(James23jun97)
										// (see FN_get_player_savedata() in save_rest.cpp
/*
		if (ID==CUR_PLAYER_ID)
		{
			george_walking = 0;

			if (megaOnGrid == 2)
				megaOnGrid = 0;
		}
*/

		if (Check_event_waiting())	// 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
			ob_mega->colliding=0;	// Don't care about collision now we've got an event
			Start_event();
			RESULT = 1;				// 1 means didn't finish walk
			return(IR_TERMINATE);
		}
		else if (ob_mega->colliding)	// If we almost collided with another mega,
		{								// then we want to re-route from scratch.
			ob_mega->colliding=0;		// reset the flag now we've acknowledged the collision
			return(IR_REPEAT);			// Stop the script, but repeat this call next cycle
		}
		else
		{
			RESULT = 0;				// 0 means ok - finished walk
			return(IR_CONT);		// CONTINUE the script so that RESULT can be checked!
									// Also, if an anim command follows the FN_walk 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.
		}
	}
	//----------------------------------------------------------------------------------------
	// increment the walkanim frame number, float the walkanim & come back next cycle

	ob_mega->walk_pc++;

	FloatRouteMem();	// allow _walkData array to float about memory again
	return(IR_REPEAT);	// stop the script, but repeat this call next cycle

	//------------------------------------------------------------------
}
//--------------------------------------------------------------------------------------
// walk mega to start position of anim

int32 FN_walk_to_anim(int32 *params)	// James (14nov96)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 anim resource id

	Object_logic	*ob_logic;
	uint8			*anim_file;
	_animHeader		*anim_head;
	int32			pars[7];

	//----------------------------------------------------------------------------------------
	// if this is the start of the walk, read anim file to get start coords

	ob_logic = (Object_logic *)params[0];

	if (ob_logic->looping==0)
	{
		anim_file = res_man.Res_open(params[4]);		// open anim file
		anim_head = FetchAnimHeader( anim_file );		// point to animation header

		pars[4] = anim_head->feetStartX;				// target_x
		pars[5] = anim_head->feetStartY;				// target_y
		pars[6] = anim_head->feetStartDir;				// target_dir

		res_man.Res_close(params[4]);					// close anim file

		//------------------------------------------
		if ((pars[4]==0)&&(pars[5]==0))					// if start coords not yet set in anim header
		{
			pars[4] = standby_x;						// use the standby coords
			pars[5] = standby_y;						// (which should be set beforehand in the script)
			pars[6] = standby_dir;

			Zdebug("WARNING: FN_walk_to_anim(%s) used standby coords", FetchObjectName(params[4]));
		}

		if ((pars[6] < 0) || (pars[6] > 7))				// check for invalid direction
			Con_fatal_error("Invalid direction (%d) in FN_walk_to_anim (%s line %u)", pars[6],__FILE__,__LINE__);

		//------------------------------------------
	}
	//----------------------------------------------------------------------------------------
	// set up the rest of the parameters for FN_walk()

	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];	// walkdata - needed for EarlySlowOut if player clicks elsewhere during the walk

	//-------------------------------------------------------------------------------------------------------

	return FN_walk(pars);	// call FN_walk() with target coords set to anim start position
}

//--------------------------------------------------------------------------------------
// turn mega to <direction>
// just needs to call FN_walk() with current feet coords, so router can produce anim of turn frames

int32 FN_turn(int32 *params)	// James (15nov96)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 target direction

	Object_logic	*ob_logic;
	Object_mega		*ob_mega;
	int32			pars[7];

	// if this is the start of the turn, get the mega's current feet coords + the required direction

	ob_logic = (Object_logic *)params[0];

	if (ob_logic->looping==0)
	{
	 	//--------------------------------------------
		if ((params[4] < 0) || (params[4] > 7))	// invalid direction
			Con_fatal_error("Invalid direction (%d) in FN_turn (%s line %u)",params[4],__FILE__,__LINE__);
		//--------------------------------------------

	 	ob_mega = (Object_mega *)params[2];
	
		pars[4] = ob_mega->feet_x;
		pars[5] = ob_mega->feet_y;
		pars[6] = params[4];	// DIRECTION to turn to
	}

	//----------------------------------------------------------------------------------------
	// set up the rest of the parameters for FN_walk()

	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];

	//----------------------------------------------------------------------------------------

	return FN_walk(pars);	// call FN_walk() with target coords set to feet coords
}
//--------------------------------------------------------------------------------------
// 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

int32 FN_stand_at(int32 *params)	// James
{
	// params:	0 pointer to object's graphic structure
	//			1 pointer to object's mega structure
	//			2 target x-coord
	//			3 target y-coord
	//			4 target direction

	Object_mega		*ob_mega;
	Object_graphic	*ob_graph;

	//----------------------------------------------------------------------------------------
	// check for invalid direction

	if ((params[4] < 0) || (params[4] > 7))	// invalid direction
		Con_fatal_error("Invalid direction (%d) in FN_stand_at (%s line %u)",params[4],__FILE__,__LINE__);

	//----------------------------------------------------------------------------------------
	// set up pointers to the graphic & mega structure

	ob_graph	= (Object_graphic *)params[0];
	ob_mega		= (Object_mega *)params[1];

	//----------------------------------------------------------------------------------------
	// set up the stand frame & set the mega's new direction

	ob_graph->anim_resource	= ob_mega->megaset_res;	// mega-set animation file
	ob_mega->feet_x			= params[2];			// x
	ob_mega->feet_y			= params[3];			// y
	ob_graph->anim_pc		= params[4]+96;			// dir + first stand frame (always frame 96)
	ob_mega->current_dir	= params[4];			// dir

 	//----------------------------------------------------------------------------------------

	return(IR_CONT);	// continue the script
}

//--------------------------------------------------------------------------------------
// stand mega in <direction> at current feet coords
// just needs to call FN_stand_at() with current feet coords

int32 FN_stand(int32 *params)	// James (15nov96)
{
	// params:	0 pointer to object's graphic structure
	//			1 pointer to object's mega structure
	//			2 target direction

	Object_mega *ob_mega = (Object_mega *)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];	// DIRECTION to stand in

	return FN_stand_at(pars);	// call FN_stand_at() with target coords set to feet coords
}
//--------------------------------------------------------------------------------------
// stand mega at end position of anim

int32 FN_stand_after_anim(int32 *params)	// James (14nov96)
{
	// params:	0 pointer to object's graphic structure
	//			1 pointer to object's mega structure
	//			2 anim resource id

	uint8 *anim_file;
	_animHeader *anim_head;
	int32 pars[5];

	//----------------------------------------------------------------------------------------
	// open the anim file & set up a pointer to the animation header

	anim_file = res_man.Res_open(params[2]);	// open anim file
	anim_head = FetchAnimHeader( anim_file );

	//----------------------------------------------------------------------------------------
	// set up the parameter list for FN_walk_to()

	pars[0] = params[0];
	pars[1] = params[1];

	pars[2] = anim_head->feetEndX;					// x
	pars[3] = anim_head->feetEndY;					// y
	pars[4] = anim_head->feetEndDir;				// dir

	//----------------------------------------------------------------------------------------

	if ((pars[2]==0)&&(pars[3]==0))					// if start coords not available either
	{
		pars[2] = standby_x;						// use the standby coords
		pars[3] = standby_y;						// (which should be set beforehand in the script)
		pars[4] = standby_dir;

		Zdebug("WARNING: FN_stand_after_anim(%s) used standby coords", FetchObjectName(params[2]));
	}

	if ((pars[4] < 0) || (pars[4] > 7))				// check for invalid direction
		Con_fatal_error("Invalid direction (%d) in FN_stand_after_anim (%s line %u)", pars[4],__FILE__,__LINE__);

	//----------------------------------------------------------------------------------------
	// close the anim file

	res_man.Res_close(params[2]);		// close anim file

	//----------------------------------------------------------------------------------------

	return FN_stand_at(pars);			// call FN_stand_at() with target coords set to anim end position
}

//--------------------------------------------------------------------------------------
// stand mega at start position of anim

int32 FN_stand_at_anim(int32 *params)	// James (07feb97)
{
	// params:	0 pointer to object's graphic structure
	//			1 pointer to object's mega structure
	//			2 anim resource id

	uint8 *anim_file;
	_animHeader *anim_head;
	int32 pars[5];

	//----------------------------------------------------------------------------------------
	// open the anim file & set up a pointer to the animation header

	anim_file = res_man.Res_open(params[2]);	// open anim file
	anim_head = FetchAnimHeader( anim_file );

	//----------------------------------------------------------------------------------------
	// set up the parameter list for FN_walk_to()

	pars[0] = params[0];
	pars[1] = params[1];

	pars[2] = anim_head->feetStartX;				// x
	pars[3] = anim_head->feetStartY;				// y
	pars[4] = anim_head->feetStartDir;				// dir

	if ((pars[2]==0)&&(pars[3]==0))					// if start coords not available
	{
		pars[2] = standby_x;						// use the standby coords
		pars[3] = standby_y;						// (which should be set beforehand in the script)
		pars[4] = standby_dir;

		Zdebug("WARNING: FN_stand_at_anim(%s) used standby coords", FetchObjectName(params[2]));
	}

	if ((pars[4] < 0) || (pars[4] > 7))				// check for invalid direction
		Con_fatal_error("Invalid direction (%d) in FN_stand_after_anim (%s line %u)", pars[4],__FILE__,__LINE__);

	//-------------------------------------------------------------------------------------------------------
	// close the anim file

	res_man.Res_close(params[2]);		// close anim file

	//-------------------------------------------------------------------------------------------------------

	return FN_stand_at(pars);			// call FN_stand_at() with target coords set to anim end position
}

//--------------------------------------------------------------------------------------
// Code to workout direction from start to dest

#define	diagonalx 36	// used in what_target not valid for all megas	jps 17mar95
#define	diagonaly 8


int What_target(int startX,	int	startY, int	destX, int	destY)		//S2.1(20Jul95JPS)
{
	int tar_dir;
//setting up
	int deltaX = destX-startX;
	int deltaY = destY-startY;
	int signX = (deltaX > 0);
	int signY = (deltaY > 0);
	int	slope;

	if ( (abs(deltaY) * diagonalx ) < (abs(deltaX) * diagonaly / 2))
	{
		slope = 0;// its flat
	}
	else if ( (abs(deltaY) * diagonalx / 2) > (abs(deltaX) * diagonaly ) )
	{
		slope = 2;// its vertical
	}
	else
	{
		slope = 1;// its diagonal
	}

	if (slope == 0) //flat
	{
		if (signX == 1)	// going right
		{
			tar_dir = 2;
		}
		else
		{
			tar_dir = 6;
		}
	}
	else if (slope == 2) //vertical
	{
		if (signY == 1)	// going down
		{
			tar_dir = 4;
		}
		else
		{
			tar_dir = 0;
		}
	}
	else if (signX == 1) //right diagonal
	{
		if (signY == 1)	// going down
		{
			tar_dir = 3;
		}
		else
		{
			tar_dir = 1;
		}
	}
 	else //left diagonal
	{
		if (signY == 1)	// going down
		{
			tar_dir = 5;
		}
		else
		{
			tar_dir = 7;
		}
	}
	return tar_dir;
}

//--------------------------------------------------------------------------------------
// turn mega to face point (x,y) on the floor
// just needs to call FN_walk() with current feet coords & direction computed by What_target()

int32 FN_face_xy(int32 *params)	// James (29nov96)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 target x-coord
	//			5 target y-coord

	Object_logic	*ob_logic;
	Object_mega		*ob_mega;
 	int32			pars[7];

	//----------------------------------------------------------------------------------------
	// if this is the start of the turn, get the mega's current feet coords + the required direction

	ob_logic = (Object_logic *)params[0];

	if (ob_logic->looping==0)
	{
	 	ob_mega = (Object_mega *)params[2];
	
		pars[4] = ob_mega->feet_x;
		pars[5] = ob_mega->feet_y;
		pars[6] = What_target( ob_mega->feet_x, ob_mega->feet_y, params[4], params[5] );	// set target direction
	}

	//----------------------------------------------------------------------------------------
	// set up the rest of the parameters for FN_walk()

	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];

	//----------------------------------------------------------------------------------------

	return FN_walk(pars);	// call FN_walk() with target coords set to feet coords
}
//--------------------------------------------------------------------------------------
int32	FN_face_mega(int32	*params) 	//S2.1(3mar95jps)	Tony29Nov96
{
//params	0 pointer to object's logic structure
//			1 pointer to object's graphic structure
//			2 pointer to object's mega structure
//			3 pointer to object's walkdata structure

//			4 id of target mega to face

	uint32	null_pc=3;	//get ob_mega
	char	*raw_script_ad;
	int32	pars[7];
	Object_logic	*ob_logic;
	Object_mega		*ob_mega;
	_standardHeader	*head;


	ob_mega = (Object_mega *)params[2];
	ob_logic = (Object_logic *)params[0];


	if (ob_logic->looping==0)
	{

//		get targets info
		head = (_standardHeader*) res_man.Res_open(params[4]);
		if	(head->fileType!=GAME_OBJECT)
			Con_fatal_error("FN_face_mega %d not an object", params[4]);

		raw_script_ad = (char *)head;	// (head+1) + sizeof(_object_hub);	//get to raw script data

		RunScript( raw_script_ad, raw_script_ad, &null_pc );	//call the base script - this is the graphic/mouse service call
		res_man.Res_close(params[4]);

//		engine_mega is now the Object_mega of mega we want to turn to face

		pars[3] = params[3];
		pars[4] = ob_mega->feet_x;
		pars[5] = ob_mega->feet_y;
		pars[6] = What_target( ob_mega->feet_x, ob_mega->feet_y, engine_mega.feet_x, engine_mega.feet_y );
	}



	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];

	return FN_walk(pars);	// call FN_walk() with target coords set to feet coords

}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//	FN_walk		(here for reference instead of splitting a window)

	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 target x-coord
	//			5 target y-coord
	//			6 target direction
//------------------------------------------------------------------------------------
int32	FN_walk_to_talk_to_mega(int32	*params)	//Tony2Dec96
{
//we route to left or right hand side of target id if possible
//target is a shrinking mega

	Object_mega		*ob_mega;
	Object_logic	*ob_logic;

	uint32	null_pc=3;	//4th script - get mega
	char	*raw_script_ad;
	int32	pars[7];
	int	scale;
	int	mega_seperation=params[5];
	_standardHeader	*head;


//params	0 pointer to object's logic structure
//			1 pointer to object's graphic structure
//			2 pointer to object's mega structure
//			3 pointer to object's walkdata structure

//			4 id of target mega to face
//			5 distance


	ob_logic = (Object_logic*) params[0];
	ob_mega = (Object_mega*) params[2];

	pars[0] = params[0];	// standard stuff
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];			// walkdata



	if	(!ob_logic->looping)	//not been here before so decide where to walk-to
	{
//		first request the targets info
		head = (_standardHeader*) res_man.Res_open(params[4]);
		if	(head->fileType!=GAME_OBJECT)
			Con_fatal_error("FN_walk_to_talk_to_mega %d not an object", params[4]);

		raw_script_ad = (char *)head;	// (head+1) + sizeof(_object_hub);	//get to raw script data
		RunScript( raw_script_ad, raw_script_ad, &null_pc );	//call the base script - this is the graphic/mouse service call
		res_man.Res_close(params[4]);

//		engine_mega is now the Object_mega of mega we want to route to


		pars[5] = engine_mega.feet_y;	// stand exactly beside the mega, ie. at same y-coord


//		apply scale factor to walk distance
		scale = (ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b)/256;	// Ay+B gives 256*scale ie. 256*256*true_scale for even better accuracy, ie. scale = (Ay+B)/256

		mega_seperation= (mega_seperation*scale)/256;

//		Zdebug("seperation %d", mega_seperation);
//		Zdebug(" target x %d, y %d", engine_mega.feet_x, engine_mega.feet_y);

		if	(engine_mega.feet_x < ob_mega->feet_x)	// target is left of us
		{
			pars[4] = engine_mega.feet_x+mega_seperation;	// so aim to stand to their right
			pars[6] = 5;	// face down_left
		}
		else										// ok, must be right of us
		{
			pars[4] = engine_mega.feet_x-mega_seperation;	// so aim to stand to their left
			pars[6] = 3;	// face down_right
		}
	}

  	//first cycle builds the route - thereafter merely follows it

	return FN_walk(pars);	//call FN_walk() with target coords set to feet coords
							//RESULT will be 1 when it finishes or 0 if it failed to build route
}
//------------------------------------------------------------------------------------
int32 FN_set_walkgrid(int32 *params)	// (6dec96 JEL)
{
	Con_fatal_error("FN_set_walkgrid no longer valid");
	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
// add this walkgrid resource to the list of those used for routing in this location
// - note this is ignored in the resource is already in the list

int32 FN_add_walkgrid(int32 *params)	// (03mar97 JEL)
{
	// params	0 id of walkgrid resource

	// all objects that add walkgrids must be restarted whenever we reneter a location

	if (ID != 8)	// DON'T EVER KILL GEORGE!
		FN_add_to_kill_list(params);// need to call this in case it wasn't called in script! ('params' just used as dummy param)

	AddWalkGrid(params[0]);

	res_man.Res_open(params[0]);	// Touch the grid, getting it into memory.
	res_man.Res_close(params[0]);

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
// remove this walkgrid resource from the list of those used for routing in this location
// - note that this is ignored if the resource isn't actually in the list

int32 FN_remove_walkgrid(int32 *params)	// (03mar97 JEL)
{
	// params	0 id of walkgrid resource

	RemoveWalkGrid(params[0]);

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_register_walkgrid(int32 *params)
{
	Con_fatal_error("FN_register_walkgrid no longer valid");
	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_set_scaling(int32 *params)	// (6dec96 JEL)
{
	// params	0 pointer to object's mega structure
	//				1 scale constant A
	//				2 scale constant B

	// 256*s = A*y + B

	// where s is system scale, which itself is (256 * actual_scale) ie. s==128 is half size

 	Object_mega *ob_mega = (Object_mega *) params[0];

	ob_mega->scale_a = params[1];
	ob_mega->scale_b = params[2];

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_set_standby_coords(int32 *params)	// (10dec97 JEL)
{
	// set the standby walk coords to be used by FN_walk_to_anim & FN_stand_after_anim
	// when the anim header's start/end coords are zero

	// useful during development; can stay in final game anyway

	// params	0 x-coord
	//			1 y-coord
	//			2 direction (0..7)

	//----------------------------------------------------------------------------------------
	// check for invalid direction

	if ((params[2] < 0) || (params[2] > 7))	// invalid direction
		Con_fatal_error("Invalid direction (%d) in FN_set_standby_coords (%s line %u)",params[2],__FILE__,__LINE__);

	//----------------------------------------------------------------------------------------

	standby_x	= (int16) params[0];
	standby_y	= (int16) params[1];
	standby_dir	= (uint8) params[2];

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
