//=============================================================================
// The navigation point serializer
// Native branch class only, rename this file if compiled in normal mode
// Loads the defined array of NavPoint structs and proceeds to creating
// the new Navigation Points as well as starting the link processing
//
// For testing purposes, do not modify or redistribute
// Have suggestions? Contact me.
// caco_fff@hotmail.com - Higor at UT99.org
//=============================================================================
class Botz_PathLoader expands Actor
	native;

struct NavPoint
{
	var() byte PathClass;
	var() vector PLoc;
	var() rotator PRot;
	var() float MaxDist;
	var() byte OtherFlags; //byte 0 is OneWayIncoming, byte 1 is OneWayOutgoing
};

struct PrunedComp
{
	var() NavigationPoint A, B; //Struct is defined differently in c++ and will crash upon visualization
	//The point of using it like this is to gain ability to read the array from the properties window
};

var NavPoint CurNav;
var const array<NavPoint> NavArray;
var const array<PrunedComp> Pruned;
var MasterGasterFer MasterG;
var class<Botz_NavigBase> NBaseList[255];

function SaveNodes( pawn Sender)
{
	local Botz_NavigBase WP;
	local bool bSave;
	local string PathName;

	ClearArray();

	//Double pass save, to ensure proper connections
	ForEach AllActors (class'Botz_NavigBase', WP)
		if ( !WP.bPushSave && PathToNav(WP) )
		{
			AddCurToArray();
			bSave = true;
		}
		
	ForEach AllActors (class'Botz_NavigBase', WP)
		if ( WP.bPushSave && PathToNav(WP) )
		{
			AddCurToArray();
			bSave = true;
		}

	if ( bSave )
	{
		PathName = string(self);
		PathName = "Botz//" $ Left(PathName, InStr(PathName,".") ) $ "_botz";
		if ( !SaveArray( PathName) )
		{
			Sender.ClientMessage("Failed to save to file "$PathName);
			return;
		}
		Sender.ClientMessage("File saved to "$PathName);
	}
	else
		Sender.ClientMessage("No custom path nodes saved");
}

function LoadNodes()
{
	local int i;
	local Botz_PathLoader aNew;
	local string PathName;
	local Botz_NavigBase aNavig;

	ClearArray();
	ClearPrunes();
	InitPruned();
	PathName = string(self);
	PathName = "Botz//" $ Left(PathName, InStr(PathName,".") ) $ "_botz";
	if ( !ReadArray( PathName) )
	{
		Log("BOTZ > Map doesn't contain additional navigation points");
		return;
	}
	While ( ArrayToCur(i++) )
		PathFromNav();

	ForEach AllActors (class'Botz_Navigbase', aNavig)
	{
		if ( aNavig.MyLoader == self ) //Prevents autopathing from special nodes
			aNavig.PathCandidates(); //Path after everything's been created
	}

//	ClearPrunes(); DO NOT CLEAR, DEBUG
}

function bool PathToNav( Botz_NavigBase Cur)
{
	CurNav.PathClass = ClassIdentifier( Cur.Class);
	if ( CurNav.PathClass == 255 )
		return false;
	CurNav.PLoc = Cur.Location;
	CurNav.PRot = Cur.Rotation;
	CurNav.OtherFlags = 0;
	if ( Cur.bOneWayInc )
		CurNav.OtherFlags = 1;
	if ( Cur.bOneWayOut )
		CurNav.OtherFlags += 2;
	CurNav.MaxDist = Cur.MaxDistance;
	return true;
}

function PathFromNav()
{
	local class<Botz_NavigBase> newClass;
	local Botz_NavigBase newPath;
	
	newClass = IdentifyClass( CurNav.PathClass);
	if ( newClass == none )
	{
		Log("BOTZ > Unknown path identifier: "$CurNav.PathClass );
		return;
	}
	newPath = Spawn( newClass,,,CurNav.PLoc, CurNav.PRot); //Answer my call!
	newPath.bOneWayInc = (CurNav.OtherFlags & 1) > 0;
	newPath.bOneWayOut = (CurNav.OtherFlags & 2) > 0;
	newPath.MaxDistance = CurNav.MaxDist;

	if ( Botz_NavigRemover(newPath) != none )
	{
		Botz_NavigRemover(newPath).RemovePaths();
		return;
	}

	newPath.MyLoader = self;
	newPath.LockActor( true); //Put in NavigationPointList and prevent deletion
}



static function byte ClassIdentifier( class<Botz_NavigBase> aClass)
{
	switch (aClass)
	{
		case class'Botz_NavigBase':
			return 0;
		case class'Botz_NavigNode':
			return 1;
		case class'Botz_JumpNode':
			return 2;
		case class'Botz_SimpleTDest':
			return 3;
		case class'Botz_NavigDoor':
			return 4;
		case class'Botz_LiftCenter':
			return 5;
		case class'Botz_LiftExit':
			return 6;
		case class'Botz_NavigDoorSpecial':
			return 7;
		case class'Botz_DodgeStart':
			return 8;
		case class'Botz_DodgeEnd':
			return 9;
		case class'Botz_NavigAirBase':
			return 10;
		case class'Botz_NavigRemover':
			return 11;
		case class'Botz_DirectLink':
			return 12;
		case class'Botz_DirectTDest':
			return 13;
		case class'Botz_LiftJumpExit':
			return 14;
		case class'Botz_DirectPistonTrans':
			return 15;
	}
	return 255;
}

static function class<Botz_NavigBase> IdentifyClass( byte cId)
{
	return default.NBaseList[cId];
	switch (cId)
	{
		case 0:
			return class'Botz_NavigBase';
		case 1:
			return class'Botz_NavigNode';
		case 2:
			return class'Botz_JumpNode';
		case 3:
			return class'Botz_SimpleTDest';
		case 4:
			return class'Botz_NavigDoor';
		case 5:
			return class'Botz_LiftCenter';
		case 6:
			return class'Botz_LiftExit';
		case 7:
			return class'Botz_NavigDoorSpecial';
		case 8:
			return class'Botz_DodgeStart';
		case 9:
			return class'Botz_DodgeEnd';
		case 10:
			return class'Botz_NavigAirBase';
		case 11:
			return class'Botz_NavigRemover';
		case 12:
			return class'Botz_DirectLink';
		case 13:
			return class'Botz_DirectTDest';
		case 14:
			return class'Botz_LiftJumpExit';
	}
	return none;
}



native final function ClearArray();
native final function AddCurToArray();
native final function bool ArrayToCur( int index);
native final function bool SaveArray( string FileName);
native final function bool ReadArray( string FileName);
native final function InitPruned(); //Inits preset pruned paths
native final function AddPrune(NavigationPoint A, NavigationPoint B);
native final function bool IsPruned( NavigationPoint A, NavigationPoint B);
native final function ClearPrunes();


defaultproperties
{
	bHidden=True
	NBaseList(0)=class'Botz_NavigBase'
	NBaseList(1)=class'Botz_NavigNode'
	NBaseList(2)=class'Botz_JumpNode'
	NBaseList(3)=class'Botz_SimpleTDest'
	NBaseList(4)=class'Botz_NavigDoor'
	NBaseList(5)=class'Botz_LiftCenter'
	NBaseList(6)=class'Botz_LiftExit'
	NBaseList(7)=class'Botz_NavigDoorSpecial'
	NBaseList(8)=class'Botz_DodgeStart'
	NBaseList(9)=class'Botz_DodgeEnd'
	NBaseList(10)=class'Botz_NavigAirBase'
	NBaseList(11)=class'Botz_NavigRemover'
	NBaseList(12)=class'Botz_DirectLink'
	NBaseList(13)=class'Botz_DirectTDest'
	NBaseList(14)=class'Botz_LiftJumpExit'
	NBaseList(15)=class'Botz_DirectPistonTrans'
}