#include "MW4Headers.hpp"
#include "server\comline.hpp"
#include "adept\application.hpp"
#include "rail_move.hpp"
#include "move_rect.hpp"
#include "ai.hpp"

#pragma warning (push)
#include <vector>
#include <map>
#pragma warning (pop)

namespace MechWarrior4
{
	extern DWORD Path_Calcs_Count;
	extern DWORD GridPath_Calcs_Count;
	extern DWORD QuickPath_Calcs_Count;
	extern DWORD QuickRail_Calcs_Count;
}

namespace MW4AI
{
	extern __int64 tCalcPathTime;
	extern __int64 tQuickCheckTime;
	extern __int64 tCreatePathRequestsTime;
	extern __int64 tPathCalc1Time;
	extern __int64 tPathCalc2Time;
	extern __int64 tNodeToPathTime;
};

using namespace MW4AI;
using namespace MechWarrior4;

CRailPath::CRailPath (CRailGraph *graph,MoverAI *ai)
	: m_Start(-1,-1,-1)
	, m_End(-1,-1,-1)
{
	m_SubPathRequest = NULL;

	m_NearLastFrame = false;
	m_TenMeterAllowed = false;
	m_AI = ai;
	m_SubPath = NULL;
	m_Graph = graph;
	m_Strict = false;
	m_StartNode = NULL;
	m_EndNode = NULL;
	m_Calced = false;
	m_InNodePath = 0;
	m_Path.clear ();
	m_NodePath.clear ();
	m_InPath = m_Path.begin ();;
}
CRailPath::CRailPath (CRailGraph *graph,const Stuff::Point3D& start,const Stuff::Point3D& end,bool strict,MoverAI *ai,bool tenmeter)
	: m_Start(start)
	, m_End(end)
{
	m_NearLastFrame = false;
	m_TenMeterAllowed = tenmeter;
	m_AI = ai;
	m_SubPathRequest = NULL;
	m_SubPath = NULL;
	m_Graph = graph;
	m_Strict = strict;
	m_Graph->FindBestNode (m_Start,m_End,false,m_StartNode,m_EndNode);
	m_Calced = false;
	m_InNodePath = 0;
	m_Path.clear ();
	m_NodePath.clear ();
	m_InPath = m_Path.begin ();;
}

CRailPath::CRailPath (CRailGraph *graph,CRailNode *start,CRailNode *end,MoverAI *ai,bool tenmeter)
{
	m_NearLastFrame = false;
	m_TenMeterAllowed = tenmeter;
	m_AI = ai;
	m_SubPathRequest = NULL;
	m_SubPath = NULL;
	m_Graph = graph;
	m_StartNode = start;
	m_EndNode = end;
	m_Strict = true;
	m_Start = m_StartNode->Location ();
	m_End = m_EndNode->Location ();
	m_Calced = false;
	m_InNodePath = 0;
	m_Path.clear ();
	m_NodePath.clear ();
	m_InPath = m_Path.begin ();
//	m_GridRequests.clear ();
}

CRailPath::~CRailPath (void)
{
	m_NodePath.clear ();
	m_Path.clear ();
	
	delete m_SubPath;
	m_SubPath = NULL;
	delete m_SubPathRequest;
	m_SubPathRequest = NULL;
}

void CRailPath::UpdateSrcDest (CRailNode *src,CRailNode *dest)
{
	Verify (dest);
	m_StartNode = src;
	m_EndNode = dest;
	m_End = m_EndNode->Location ();
	m_Start = m_StartNode->Location ();
}

void CRailPath::UpdateSrcDest (const Stuff::Point3D& src,const Stuff::Point3D& dest)
{
	m_Start = src;
	m_End = dest;
	m_Graph->FindBestNode (m_Start,m_End,false,m_StartNode,m_EndNode);
}

void CRailPath::Save (MemoryStream *stream)
{

	stlport::vector<NodePathElement>::iterator iter1;
	stlport::vector<PathElement>::iterator iter2;

	*stream << m_TenMeterAllowed;
	*stream << m_Start;
	*stream << m_End;
	*stream << m_HeadPoint;
	*stream << m_UsageAllowed;
	*stream << m_Calced;
	*stream << m_Strict;
	if (m_StartNode)
	{
		*stream << true;
		*stream << m_StartNode->ID ();
	}
	else
		*stream << false;
	if (m_EndNode)
	{
		*stream << true;
		*stream << m_EndNode->ID ();
	}
	else
		*stream << false;
	*stream << m_InNodePath;
	*stream << ((int) m_State);
	*stream << m_NodePath.size ();
	*stream << m_Path.size ();
	int count;
	

	for (iter2 = m_Path.begin (),count = 0;(iter2 != m_Path.end ()) && (m_InPath != iter2);iter2++,count++);
	*stream << count;

	for (iter1 = m_NodePath.begin ();iter1 != m_NodePath.end ();iter1++)
	{
		iter1->Save (stream);
	}
	for (iter2 = m_Path.begin ();iter2 != m_Path.end ();iter2++)
	{
		iter2->Save (stream);
	}
}

void CRailPath::Load (MemoryStream *stream)
{
	bool flag;
	int temp;
	int size1,size2;

	*stream >> m_TenMeterAllowed;
	*stream >> m_Start;
	*stream >> m_End;
	*stream >> m_HeadPoint;
	*stream >> m_UsageAllowed;
	*stream >> m_Calced;
	*stream >> m_Strict;
	*stream >> flag;
	m_StartNode = NULL;
	if (flag)
	{
		int id;
		*stream >> id;
		m_StartNode = m_Graph->Node (id);
	}
	*stream >> flag;
	m_EndNode = NULL;
	if (flag)
	{
		int id;
		*stream >> id;
		m_EndNode = m_Graph->Node (id);
	}

	*stream >> m_InNodePath;
	*stream >> temp;
	m_State = (PATHSTATES) temp;
	*stream >> size1;
	*stream >> size2;
	int count,i;
	
	*stream >> count;

	m_NodePath.assign (size1,NodePathElement ());
	for (i=0;i<size1;i++)
	{
		m_NodePath[i].Load (stream);
	}
	m_Path.assign (size2,PathElement());
	for (i=0;i<size2;i++)
	{
		m_Path[i].Load (stream);
	}
	m_InPath = m_Path.begin ();
	m_InPath += count;
}

void CRailPath::PathElement::Save (MemoryStream *stream)
{
	*stream << loc;
	*stream << usage;
	*stream << onrail;
	*stream << linkid;
}
void CRailPath::PathElement::Load (MemoryStream *stream)
{
	*stream >> loc;
	*stream >> usage;
	*stream >> onrail;
	*stream >> linkid;
}
void CRailPath::NodePathElement::Save (MemoryStream *stream)
{
	*stream << usage;
	if (link)
	{
		*stream << true;
		*stream << link->ID ();
	}
	else
		*stream << false;
	if (destnode)
	{
		*stream << true;
		*stream << destnode->ID ();
	}
	else
		*stream << false;
}

void CRailPath::NodePathElement::Load (MemoryStream *stream)
{
	bool flag;
	int id;
	*stream >> usage;
	destnode = NULL;
	link = NULL;
	*stream >> flag;
	if (flag)
	{
		*stream >> id;
		link = g_MissionGraph->Link (id);
	}
	*stream >> flag;
	if (flag)
	{
		*stream >> id;
		destnode = g_MissionGraph->Node (id);
	}
}

float CRailPath::CostGuess (CRailNode *src)
{
	Stuff::Point3D start;
	Stuff::Point3D end;

	start = src->Location ();
	end = m_End;

	float t1,t2;

	t1 = end.x - start.x;
	t2 = end.z - start.z;

	t1 = t1<0 ? t1*-1.0f : t1;
	t2 = t2<0 ? t2*-1.0f : t2;

	return 0;
//	return t2 < t1 ? (t1+(t2/2.0f)) : (t2+(t1/2.0f));
}

void CRailPath::CalcOutVec (Stuff::Point3D& outvec)
{
	outvec = NextPoint ();
//	outvec = Stuff::Point3D (-1,-1,-1);
}


bool CRailPath::NewSubPath (const Stuff::Point3D& loc)
{
	if (m_InPath == m_Path.end ())
		return false;
	int mask=0;

	if (m_InPath->usage & JUMPFLAG)
	{
		Verify (!m_SubPathRequest);
		return true;
	}
	if (m_InPath->onrail)
	{
		Verify (!m_SubPathRequest);
		return true;
	}

	delete m_SubPath;
	m_SubPath = NULL;
	if (m_SubPathRequest)
	{
		m_SubPath = m_SubPathRequest->GridPath ();
		if (!m_SubPathRequest->Done ())
		{
			return true;
		}
		m_SubPathRequest->DetachGridPath ();
		delete m_SubPathRequest;
		m_SubPathRequest = NULL;
		if (!m_SubPath->Calced ())
		{
			if (m_InPath->linkid != -1)
				m_Graph->DeleteLink (m_InPath->linkid);
			delete m_SubPath;
			m_SubPath = NULL;
			m_Calced = false;
			return false;
		}
		if (m_SubPath->QuickValid ())
		{
			delete m_SubPath;
			m_SubPath = NULL;
		}
	}
	else
	{
		mask = ConvertUsagetoMovePass (m_InPath->usage);

		m_SubPathRequest = g_PathManager->AddRequest (gos_GetElapsedTime (),m_Graph,(unsigned short) mask,loc.x,loc.z,m_InPath->loc.x,m_InPath->loc.z,m_AI,m_TenMeterAllowed);
		return true;
#if 0
		gos_PushCurrentHeap (g_RailHeap);
		m_SubPath = new CGridPath (m_Graph,(unsigned short) mask,loc.x,loc.z,m_InPath->loc.x,m_InPath->loc.z,m_TenMeterAllowed);
		gos_PopCurrentHeap ();
		Verify (m_SubPath);
		m_SubPath->CalcPath();
#endif
	}
#if 0
	if (!m_SubPath->Calced ())
	{
		if (m_InPath->linkid != -1)
			m_Graph->DeleteLink (m_InPath->linkid);
		delete m_SubPath;
		m_SubPath = NULL;
		m_Calced = false;
		return false;
	}
	if (m_SubPath->QuickValid ())
	{
		delete m_SubPath;
		m_SubPath = NULL;
	}
#endif
	return true;
}

bool CRailPath::Next (const Stuff::Point3D& loc)
{
	if (m_SubPath)
	{
		if (m_SubPath->Next ())
		{
			return true;
		}
		delete m_SubPath;
		m_SubPath = NULL;
		if (m_InPath != m_Path.end ())
		{
			m_InPath++;
			return NewSubPath (loc);
		}
	}
	if (m_InPath != m_Path.end ())
	{
		m_InPath++;
		return NewSubPath (loc);
	}
	return false;
}

Stuff::Point3D CRailPath::CurrentPoint (void) const
{
	if (!m_Calced)
		return Stuff::Point3D (-1,-1,-1);
	if (m_State == RAIL_FINISH)
		return Stuff::Point3D (-1,-1,-1);

	if (m_InPath == m_Path.end () && (m_SubPath == NULL))
		return Stuff::Point3D (-1,-1,-1);

	if (m_SubPath)
		return m_SubPath->CurrentPoint ();
	else
		return m_InPath->loc;
}

bool CRailPath::PointBehind (const Stuff::Point3D& loc,const Stuff::Point3D& dest)
{
	Stuff::Point3D nextdest,destextra,nextdestextra;
	Scalar dist1,dist2,dot;

	nextdest = NextPoint ();
	if (nextdest == Point3D (-1,-1,-1))
		return false;

	int x,y,mask;
	x = (int) (loc.x/10);
	y = (int) (loc.z/10);
	mask = ConvertUsagetoMovePass (m_UsageAllowed&(~JUMPFLAG));
	if ((!m_Graph->MoveTo (x+1,y,0,mask)) || (!m_Graph->MoveTo (x-1,y,0,mask)) || (!m_Graph->MoveTo (x,y-1,0,mask)) || (!m_Graph->MoveTo (x,y+1,0,mask)))
	{
		return false;
	}

	destextra.Subtract (dest,loc);
	dist1 = destextra.GetLengthSquared ();
	nextdestextra.Subtract (nextdest,loc);
	dist2 = nextdestextra.GetLengthSquared ();
	if (dist2 < dist1)
		return true;

	dot = (nextdestextra.x*destextra.x) + (nextdestextra.z*destextra.z);
	dot /= (nextdestextra.GetLength () * destextra.GetLength ());

	if ((m_Graph->Passable (loc.x,loc.z) & BRIDGE_FLAG) && (dot <= 0.0f))
		return true;

	if ((dot <= 0.0f) && (dist1 < 400))
		return true;

	return false;
}

void CRailPath::PointList (stlport::vector<Point3D>& dest)
{
	dest.clear ();
	if (!m_Calced)
		return;
	if (m_InPath == m_Path.end () && (m_SubPath == NULL))
		return;
	gos_PushCurrentHeap (g_RailHeap);

	if (m_SubPath)
	{
		m_SubPath->PointList (dest);
	}
	stlport::vector<PathElement>::iterator iter;

	for (iter = m_InPath;iter != m_Path.end ();iter++)
	{
		dest.push_back (iter->loc);
	}
	gos_PopCurrentHeap ();
}

void CRailPath::Tick (const Stuff::Point3D& loc,Stuff::Time till,Stuff::Scalar speed,Stuff::Point3D& outvec,bool& jump,bool& prejump)
{
	m_HeadPoint = Stuff::Point3D (-1,-1,-1);

	Verify (m_Calced);
	jump = false;
	prejump = false;
	if (m_State == RAIL_FINISH)
		return;
	if (m_SubPathRequest)
	{
		if (m_SubPathRequest->Done ())
		{
			m_SubPath = m_SubPathRequest->DetachGridPath ();
			delete m_SubPathRequest;
			m_SubPathRequest = NULL;
			if (!m_SubPath->Calced ())
			{
				if (m_InPath->linkid != -1)
					m_Graph->DeleteLink (m_InPath->linkid);
				delete m_SubPath;
				m_SubPath = NULL;
				m_Calced = false;
				m_State = RAIL_FINISH;
				return;
			}
			if (m_SubPath->QuickValid ())
			{
				delete m_SubPath;
				m_SubPath = NULL;
			}
		}
		else
		{
			m_State = RAIL_MOVE_WAITING;
			return;
		}
	}
	m_State = RAIL_MOVE_ENDPOINT;
	CalcOutVec (outvec);

	Stuff::Point3D destloc,extra,fakeloc;
	Stuff::Scalar dist,move;

	destloc = CurrentPoint ();

	destloc.y = 0;
	fakeloc = loc;
	fakeloc.y = 0;
	extra.Subtract (destloc,fakeloc);
	dist = extra.GetLengthSquared ();

	if (speed < 0)
		move = (float) (speed * till * 6);		// use 6 frame buffer
	else
		move = (float) (speed * till * 6);		// use 6 frame buffer
	move *= move;

//	if ((dist<49.0) || (dist < move) || PointBehind (loc,destloc))
	if (m_NearLastFrame)
	{
		m_NearLastFrame = false;
		if (!Next (loc))
		{
			m_State = RAIL_FINISH;
			return;
		}
		if (!m_Calced)
			return;
		Tick (loc,till,speed,outvec,jump,prejump);
		return;
	}
#if 1
	if ((dist<16.0) || (dist < move) || PointBehind (loc,destloc))
	{
		m_NearLastFrame = true;
	}
#endif

	m_HeadPoint = CurrentPoint ();
	destloc = CurrentPoint ();

	destloc.y = 0;
	fakeloc = loc;
	fakeloc.y = 0;
	extra.Subtract (destloc,fakeloc);
	dist = extra.GetLengthSquared ();

	CalcOutVec (outvec);

	stlport::vector<PathElement>::iterator iter;
	iter = m_InPath;
	if (m_InPath != m_Path.end ())
		iter++;

	if (m_InPath->usage & JUMPFLAG)
		jump = true;
	else
		jump = false;
	if ((iter != m_Path.end ()) && (iter->usage & JUMPFLAG))
		prejump = true;

	bool flag = false;
	if ((!m_SubPath) && (iter == m_Path.end () && (m_State != RAIL_FINISH)))
		flag = true;
	if ((m_SubPath) && (iter == m_Path.end () && (m_State != RAIL_FINISH)))
	{
		if (m_SubPath->OneFromEnd ())
			flag = true;
	}
}

bool CRailGraph::PointOpen (Scalar x,Scalar y,int movepass)
{

	const int SIZEDELTA = 8;
	int delta[SIZEDELTA][2] = {
		{-1*BLOCK_GRID_RES,0*BLOCK_GRID_RES},
		{0*BLOCK_GRID_RES,-1*BLOCK_GRID_RES},
		{1*BLOCK_GRID_RES,0*BLOCK_GRID_RES},
		{0*BLOCK_GRID_RES,1*BLOCK_GRID_RES},
#if 1
		{-1*BLOCK_GRID_RES,-1*BLOCK_GRID_RES},
		{-1*BLOCK_GRID_RES,1*BLOCK_GRID_RES},
		{1*BLOCK_GRID_RES,-1*BLOCK_GRID_RES},
		{1*BLOCK_GRID_RES,1*BLOCK_GRID_RES}
#endif
	};
	int i;

	if (CheckCanPass (Passable (x,y),movepass))
		return false;
	for (i=0;i<SIZEDELTA;i++)
	{
		if (CheckCanPass (Passable (x+delta[i][0],y+delta[i][1]),movepass))
			return false;
	}
	return true;
}

Stuff::Point3D CRailGraph::PullPointElementMask (Stuff::Point3D& start,Stuff::Point3D& end,int movepass)
{
	end.y = 0;
	start.y = 0;
	if (!PointOpen (end.x,end.z , movepass))
	{
		Stuff::Point3D vec,tempvec,third;
		Stuff::Scalar len,curlen;

		third.Subtract (start,end);
		len = third.GetLengthSquared ();
		if (len < 5.0f)
			return Point3D (-1,-1,-1);
		vec.Normalize (third);
		curlen = 0;
		while ((curlen*curlen) < len)
		{
			curlen+=BLOCK_GRID_RES;
			third.Multiply (vec,curlen);
			tempvec.Add (third,end);
			if (PointOpen (tempvec.x,tempvec.z , movepass))
				return tempvec;
		}
		return Stuff::Point3D (-1,-1,-1);
	}
	else
		return end;

}

Stuff::Point3D CRailGraph::PullPointElement (Stuff::Point3D& start,Stuff::Point3D& end,int usage)
{
	int movepass;

	movepass = ConvertUsagetoMovePass (usage);
	return PullPointElementMask (start,end,movepass);
}

void CRailPath::DumpPath (void)
{
	stlport::vector<PathElement>::iterator iter;
	char text[100];
	
	iter = m_Path.begin ();
	while (iter != m_Path.end ())
	{
		sprintf (text,"Move Point %f,%f",iter->loc.x,iter->loc.z);
		COMSPEW (text);
		iter++;
	}
	COMSPEW ("");
}

void CRailPath::ReverseList (void)
{
	stlport::vector<NodePathElement>::iterator start,end;

//	COMSPEW ("reversing path list");
	start = m_NodePath.begin ();
	end = m_NodePath.end ();
	stlport::reverse (start,end);
}

void CRailPath::Reverify (int usage)
{
	return;
#if 0
	if (!m_QuickPath)
		return;
	
	unsigned short usa = (unsigned short) (m_UsageAllowed&(~JUMPFLAG));
	if (m_Graph->QuickCheck ((int) m_Start.x,(int) m_Start.z,(int) m_End.x,(int) m_End.z,(unsigned short) ConvertUsagetoMovePass (usa)))
		return;

	m_Calced = false;

	m_NodePath.clear ();
	m_Path.clear ();
	CalcPath (usage);
#endif
}

void CRailPath::CalcPath (int usage)
{
	PATH_LOGIC("Calc");
	TIME_FUNCTION(tCalcPathTime);

	Verify (m_Graph);
	int i;
	int type;
	my_heap<CRailNode *,true,railnodecmp> calc;
	CRailNode *temp;
	bool done;
	Scalar dist;
	Point3D extra;

	m_NearLastFrame = false;
	m_SubPathRequest = NULL;

	Set_Statistic(Path_Calcs_Count, Path_Calcs_Count+1);
//	usage &= ~JUMPFLAG;
	Verify (m_Graph->CountNodes ());
	Verify (m_Graph->CountLinks ());
	Verify (usage >0);
	m_UsageAllowed = usage & (~JUMPFLAG);

	AutoHeap local_heap (g_RailHeap);

	unsigned short usa = (unsigned short) (m_UsageAllowed&(~JUMPFLAG));

	extra = m_Graph->PullPointElement (m_Start,m_End,usa);
	if (extra == Point3D (-1,-1,-1))
	{
		m_Calced = false;
		return;
	}
	m_End = extra;

	m_QuickPath = false;
	if (m_Graph->QuickCheck ((int) m_Start.x,(int) m_Start.z,(int) m_End.x,(int) m_End.z,(unsigned short) ConvertUsagetoMovePass (usa)))
	{
		Set_Statistic(QuickRail_Calcs_Count, QuickRail_Calcs_Count+1);
		m_Calced = true;
		m_Path.push_back (PathElement (m_Start,usa,false,-1));
		m_Path.push_back (PathElement (m_End,usa,true,-1));
		m_InPath = m_Path.begin ();
		m_QuickPath = true;
		return;
	}

	if ((m_StartNode == NULL) || (m_EndNode == NULL))
	{
		m_Calced = false;
		m_State = RAIL_START_PATH;
		return;
	}

	m_Start.y = m_End.y = 0;
	extra.Subtract (m_Start,m_End);
	dist = extra.GetLengthSquared ();
	if ((m_StartNode == m_EndNode) || ((dist < (250.0f*250.0f)) && (!m_Graph->BridgeNear (m_Start,m_End))))
	{
		m_Calced = true;
		m_Path.push_back (PathElement (m_Start,usa,false,-1));

		Point3D temp;
		temp = m_Graph->PullPointElement (m_Start,m_End,usa);
		if (temp != Point3D (-1,-1,-1))
		{
			m_Path.push_back (PathElement (temp,usa,false,-1));
			m_InPath = m_Path.begin ();

			m_InPath++;

			gos_PushCurrentHeap (g_RailHeap);
			unsigned short mask = (unsigned short) ConvertUsagetoMovePass (m_InPath->usage);
			m_SubPath = new CGridPath (m_Graph,mask,m_Start.x,m_Start.z,m_End.x,m_End.z,m_TenMeterAllowed);
			gos_PopCurrentHeap ();
			Verify (m_SubPath);
			m_SubPath->DoCalcPath();
			if (m_SubPath->Calced ())
			{
				if (m_SubPath->QuickValid ())
				{
					delete m_SubPath;
					m_SubPath = NULL;
					m_Calced = true;
					m_Path.clear ();
					m_Path.push_back (PathElement (m_Start,usa,false,-1));
					m_Path.push_back (PathElement (m_End,usa,false,-1));
					m_InPath = m_Path.begin ();
					m_QuickPath = true;
					return;
				}
				return;
			}
			else if (m_StartNode == m_EndNode)
			{
				delete m_SubPath;
				m_SubPath = NULL;
				CreatePathRequests ();
				return;
			}
			else
			{
				m_Calced = false;
				delete m_SubPath;
				m_SubPath = NULL;
			}
#if 0
			if ((m_Calced) || (m_StartNode == m_EndNode))
			{
				Set_Statistic(QuickRail_Calcs_Count, QuickRail_Calcs_Count+1);
				m_QuickPath = true;
				return;
			}
#endif
		}
		else
			m_Calced = false;

		if (m_StartNode == m_EndNode)
		{
			m_QuickPath = true;
			m_State = RAIL_FINISH;
			m_Calced = true;
			m_Path.push_back (PathElement (m_End,usa,false,-1));
			m_InPath = m_Path.end ();
			return;
		}
	}

	m_Graph->ClearPathFlags ();

	m_StartNode->PathWeight (1,CostGuess (m_EndNode),usa);
	calc.Insert (m_StartNode);

	done = false;
	m_Calced = false;
	int count = 0;

	{
		PATH_LOGIC("RailPath phase 1");
		TIME_FUNCTION(tPathCalc1Time);
		{
			while (!done)
			{
				count++;
				if (count > (m_Graph->NumNodes ()*2))
				{
					break;
				}
				if (!calc.size ())
					break;
				temp = calc.ExtractMin ();
				if (temp == NULL)
					break;
				if (temp == m_EndNode)
				{
					done = true;
					break;
				}
				int size;
				float cost;

				cost = temp->PathWeight ();
				size = temp->NumLinks ();
				for (i=0;i<size;i++)
				{
					CRailNode *dest;
					CRailLink *curlink;
					float newcost;

					curlink = temp->Link (i);
					dest = curlink->OtherLocation (temp);
					newcost = curlink->LowestWeight (usage,type,temp);
					if (newcost == -1)
						continue;
					if (type == 0)
						continue;
					newcost += cost;
					if (dest->PathWeight (newcost,CostGuess (dest),type))
					{
						if (calc.Member (dest))
							calc.DecreaseKey (dest);
						else
							calc.Insert	(dest);
					}
				}
			}
		}

		if (!done)
			return;

		done = false;
		CRailNode *cur;
		int min;
		float mincost;

		cur = m_EndNode;

		min = NULL;
		count =0;

		{
			PATH_LOGIC("RailPath phase 2");
			TIME_FUNCTION(tPathCalc2Time);
			{
				while (!done)
				{
					count++;
					if (count > (m_Graph->NumNodes ()*2))
					{
						m_Calced = false;
						return;
					}
					min = 0;
					mincost = cur->Link (min)->OtherLocation (cur)->PathWeight ();
					if (cur->Link (min)->LowestWeight (usage,type,cur->Link (min)->OtherLocation (cur)) == -1.0f)
						mincost = 0;
					for (i=1;i<cur->NumLinks ();i++)
					{
						float t;

						t= cur->Link (i)->OtherLocation (cur)->PathWeight ();
						if (cur->Link (i)->LowestWeight (usage,type,cur->Link (i)->OtherLocation (cur)) == -1.0f)
							t = 0;
						if (((t < mincost) && (t != 0)) || (mincost == 0))
						{
							mincost = t;
							min = i;
						}
					}
					m_NodePath.push_back (NodePathElement (cur->Link (min),cur,cur->PathType ()));
					cur = cur->Link (min)->OtherLocation (cur);
					if (cur == m_StartNode)
					{
						int fred = 0;
						if (usage & LEGFLAG)
							fred = LEGFLAG;
						else if (usage & JUMPFLAG)
							fred = JUMPFLAG;
						else if (usage & TRACKFLAG)
							fred = TRACKFLAG;
						else if (usage & WHEELFLAG)
							fred = WHEELFLAG;
						else if (usage & FLYFLAG)
							fred = FLYFLAG;
						else if (usage & HOVERFLAG)
							fred = HOVERFLAG;
						else if (usage & HELIFLAG)
							fred = HELIFLAG;
						else if (usage & WATERFLAG)
							fred = WATERFLAG;
#if defined(LAB_ONLY)
						else
							PAUSE (("unknown movetype in calcpath"));
#endif

						m_NodePath.push_back (NodePathElement (NULL,cur,fred));
						ReverseList ();
						done = true;
						continue;
					}
				}
			}
		}

		m_Calced = true;
		m_State = RAIL_START_PATH;
		m_HeadPoint = Stuff::Point3D (-1,-1,-1);
		m_InNodePath = 0;
		ConvertNodeToPath ();
		if (m_Calced)
			CreatePathRequests ();
	}
}

void CRailPath::CreatePathRequests (void)
{
	TIME_FUNCTION(tCreatePathRequestsTime);

	if (m_Calced)
		NewSubPath (m_Start);
}


