
#include "../idlib/precompiled.h"
#pragma hdrstop

#include "Game_local.h"

#define RECORDRATE		300 //record every X ms


#define RECORD_LAUNCHAIM	1
#define RECORD_UNSPAWN		2
#define RECORD_SPAWN		3

const idEventDef EV_recordclear( "recordclear", "d" );
const idEventDef EV_recordstart( "recordstart", "dd" );
const idEventDef EV_recordstop( "recordstop" );
const idEventDef EV_recordplay( "recordplay", "d" );
const idEventDef EV_geteventcount( "geteventcount", "d", 'd' );
const idEventDef EV_getlasteventtimestamp( "getlasteventtimestamp", "d", 'd' );
const idEventDef EV_setrecordstarttime( "setrecordstarttime" );
const idEventDef EV_moveplayertoghost( "moveplayertoghost", "d" );
const idEventDef EV_setcomplete( "setcomplete", "dd" );
const idEventDef EV_getcomplete( "getcomplete", "d", 'd' );
const idEventDef EV_recordspawn( "recordspawn", "sdvf" );
const idEventDef EV_recordunspawn( "recordunspawn", "d" );
const idEventDef EV_recordlaunchaim( "recordlaunchaim", "dvf" );

const idEventDef EV_reset( "worldreset" );

CLASS_DECLARATION( idEntity, idWorldManager )
	EVENT( EV_recordstart,			idWorldManager::Event_recordstart)
	EVENT( EV_recordstop,			idWorldManager::Event_recordstop)
	EVENT( EV_recordplay,			idWorldManager::Event_recordplay)
	EVENT( EV_reset,				idWorldManager::Event_reset)
	EVENT( EV_geteventcount,		idWorldManager::Event_geteventcount)
	EVENT( EV_getlasteventtimestamp, idWorldManager::Event_getlasteventtimestamp)
	EVENT( EV_setrecordstarttime,	idWorldManager::Event_setrecordstarttime)
	EVENT( EV_moveplayertoghost,	idWorldManager::Event_moveplayertoghost)
	EVENT( EV_recordclear,			idWorldManager::Event_recordclear)
	EVENT( EV_recordspawn,			idWorldManager::RecordSpawn)
	EVENT( EV_recordunspawn,		idWorldManager::RecordUnspawn)
	EVENT( EV_recordlaunchaim,		idWorldManager::RecordLaunchAim)

	EVENT( EV_setcomplete,			idWorldManager::Event_setcomplete)
	EVENT( EV_getcomplete,			idWorldManager::Event_getcomplete)
END_CLASS

void idWorldManager::Save( idSaveGame *savefile ) const
{
	savefile->WriteInt(index);
	savefile->WriteInt(state);
	savefile->WriteInt(recordStarttime);
	savefile->WriteInt(nextRecordtime);
	savefile->WriteVec3(lastPosition);
	savefile->WriteFloat(lastAngle);

	//RECORDS.
	for (int i = 0; i < 3; i++)
	{
		savefile->WriteObject(records[i].ghost);
		savefile->WriteInt(records[i].index);
		savefile->WriteBool(records[i].playing);
		savefile->WriteBool(records[i].completed);

		int totalEvents = records[i].events.Num();
		savefile->WriteInt(totalEvents); //how many events.

		for (int k = 0; k < totalEvents; k++)
		{
			savefile->WriteInt(records[i].events[k].timestamp);
			savefile->WriteVec3(records[i].events[k].position);
			savefile->WriteFloat(records[i].events[k].yaw);
			savefile->WriteString(records[i].events[k].deckcommand.c_str());
			savefile->WriteString(records[i].events[k].frobcommand.c_str());
			savefile->WriteString(records[i].events[k].spawncommand.c_str());
			savefile->WriteBool(records[i].events[k].done);
			savefile->WriteInt(records[i].events[k].entID);
			savefile->WriteInt(records[i].events[k].recordtype);
		}
	}


	//RECORDLINES
	for (int i = 0; i < 3; i++)
	{
		int totalLines = recordlines[i].lines.Num();
		savefile->WriteInt(totalLines);

		for (int k = 0; k < totalLines; k++)
		{
			savefile->WriteVec3(recordlines[i].lines[k].position1);
			savefile->WriteVec3(recordlines[i].lines[k].position2);
		}
	}
}

void idWorldManager::Restore( idRestoreGame *savefile )
{
	savefile->ReadInt(index);
	savefile->ReadInt(state);
	savefile->ReadInt(recordStarttime);
	savefile->ReadInt(nextRecordtime);
	savefile->ReadVec3(lastPosition);
	savefile->ReadFloat(lastAngle);

	//RECORDS.
	for (int i = 0; i < 3; i++)
	{
		savefile->ReadObject(reinterpret_cast<idClass *&>( records[i].ghost ) );
		savefile->ReadInt(records[i].index);
		savefile->ReadBool(records[i].playing);
		savefile->ReadBool(records[i].completed);

		int totalEvents;
		savefile->ReadInt(totalEvents);

		for (int k = 0; k < totalEvents; k++)
		{
			record_t newEvent;

			savefile->ReadInt(newEvent.timestamp);
			savefile->ReadVec3(newEvent.position);
			savefile->ReadFloat(newEvent.yaw);
			savefile->ReadString(newEvent.deckcommand);
			savefile->ReadString(newEvent.frobcommand);
			savefile->ReadString(newEvent.spawncommand);
			savefile->ReadBool(newEvent.done);
			savefile->ReadInt(newEvent.entID);
			savefile->ReadInt(newEvent.recordtype);

			records[i].events.Append(newEvent);
		}
	}


	//RECORDLINES	
	for (int i = 0; i < 3; i++)
	{
		recordlines[i].lines.Clear();

		int totalLines;
		savefile->ReadInt(totalLines);

		for (int k = 0; k < totalLines; k++)
		{
			recordline_t newLine;

			savefile->ReadVec3(newLine.position1);
			savefile->ReadVec3(newLine.position2);

			recordlines[i].lines.Append(newLine);
		}
	}
}

void idWorldManager::Spawn( void )
{
	int i;
	for (i = 0; i < 3; i++)
	{
		idDict args;

		records[i].index = 0;
		records[i].playing = false;
		records[i].completed = false;
		
		args.Clear();
		args.Set( "model", "models/monster_npc/tris.ase" );
		args.SetInt( "solid", 0 );
		args.Set("skin", "skins/npc/ghost2");
		records[i].ghost = ( idMover * )gameLocal.SpawnEntityType( idMover::Type, &args );
		records[i].ghost->Hide();

		recordlines[i].lines.Clear();
	}

	lastPosition = vec3_zero;
	lastAngle = 0;
	nextRecordtime = 0;
	recordStarttime = 0;
	index = 0;
	state = OFF;
	BecomeActive( TH_THINK );
}



void idWorldManager::Event_getcomplete(int idx)
{
	idThread::ReturnInt(records[idx].completed);
}

void idWorldManager::Event_setcomplete(int idx, bool value)
{
	records[idx].completed = value;
}

void idWorldManager::Event_moveplayertoghost(int idx)
{
	//common->Printf("ghost %f %f %f\n", records[idx].ghost->GetPhysics()->GetOrigin().x, records[idx].ghost->GetPhysics()->GetOrigin().y, records[idx].ghost->GetPhysics()->GetOrigin().z);
	gameLocal.GetLocalPlayer()->SetOrigin( records[idx].ghost->GetPhysics()->GetOrigin() + idVec3(0,0,0) );
}

void idWorldManager::Event_recordclear(int idx)
{
	if (idx < 0)
	{
		return;
	}

	//erase all events.
	records[idx].events.Clear();
}

void idWorldManager::Event_setrecordstarttime()
{
	recordStarttime = gameLocal.time;
}

void idWorldManager::Event_getlasteventtimestamp(int idx)
{
	int indexOfLastEvent = records[idx].events.Num();

	if (indexOfLastEvent <= 0)
	{
		idThread::ReturnInt(0);
		return;
	}

	int time = records[idx].events[indexOfLastEvent - 1].timestamp;

	time += gameLocal.time;

	idThread::ReturnFloat(time / 1000.0f);
}

void idWorldManager::Event_geteventcount(int idx)
{	
	idThread::ReturnInt(	records[idx].events.Num() );
}

void idWorldManager::Event_reset(void)
{
	int i;

	for ( i = 0; i < gameLocal.num_entities; i++ )
	{
		if ( !gameLocal.entities[ i ] )
			continue;

		if (gameLocal.entities[i]->IsType(idMoveableItem::Type))
		{
			gameLocal.entities[i]->GetPhysics()->PutToRest();

			gameLocal.entities[i]->SetOrigin(static_cast<idMoveableItem *>( gameLocal.entities[i] )->originalPosition);
			gameLocal.entities[i]->SetAxis(static_cast<idMoveableItem *>( gameLocal.entities[i] )->originalAngle);


			if (static_cast<idMoveableItem *>( gameLocal.entities[i] )->frozen == 2)
			{
				static_cast<idMoveableItem *>( gameLocal.entities[i] )->frozen = 1;
			}
		}
		else if (gameLocal.entities[i]->IsType(idLever::Type))
		{
			static_cast<idLever *>( gameLocal.entities[i] )->Reset();
		}
		else if (gameLocal.entities[i]->IsType(idMoveable::Type))
		{
			gameLocal.entities[i]->GetPhysics()->PutToRest();

			gameLocal.entities[i]->SetOrigin(static_cast<idMoveable *>( gameLocal.entities[i] )->originalPosition);
			gameLocal.entities[i]->SetAxis(static_cast<idMoveable *>( gameLocal.entities[i] )->originalAngle);				

			gameLocal.entities[i]->GetPhysics()->PutToRest();
		}
		else if (gameLocal.entities[i]->IsType(idMover::Type))
		{
			//gameLocal.entities[i]->GetPhysics()->PutToRest();
			if (gameLocal.entities[i]->spawnArgs.GetInt("resetmover", "0") <= 0)
			{
				continue;
			}

			static_cast<idMover *>( gameLocal.entities[i] )->Event_StopMoving();
			static_cast<idMover *>( gameLocal.entities[i] )->Event_StopRotating();


			if ( gameLocal.entities[i]->GetBindMaster() == NULL )
			{
				gameLocal.entities[i]->SetOrigin( static_cast<idMover *>(gameLocal.entities[i] )->originalPosition );
			}
			else
			{
				if (gameLocal.entities[i]->GetBindMaster()->IsType(idMover::Type))
				{
					idVec3 masterPos = GetLocalCoordinates( static_cast<idMover *>(gameLocal.entities[i]->GetBindMaster())->originalPosition );
					gameLocal.entities[i]->SetOrigin(  static_cast<idMover *>(gameLocal.entities[i] )->originalPosition - masterPos);
				}
				else
				{
					idVec3 orgPos = GetLocalCoordinates( static_cast<idMover *>(gameLocal.entities[i])->originalPosition );
					gameLocal.entities[i]->SetOrigin(  orgPos );
				}
			}


			gameLocal.entities[i]->SetAxis(static_cast<idMover *>( gameLocal.entities[i] )->originalAngle);				
		}
		else if (gameLocal.entities[i]->IsType(idTrembler::Type))
		{
			static_cast<idTrembler *>( gameLocal.entities[i] )->Reset();
		}
	}

	//popcorn reset.

	gameLocal.GetLocalPlayer()->popcornPosition = vec3_zero;
}

void idWorldManager::Event_recordstart( int idx, int continuation )
{
	lastPosition = gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin();

	if (!continuation)
	{
		recordStarttime = gameLocal.time;

		//reset the record lines.
		if (idx >= 0)
		{
			recordlines[idx].lines.Clear();
		}
	}

	this->index = idx;

	if (idx >= 0)
	{
		state = RECORDING;
		records[index].ghost->Hide();

		if (!continuation)
		{
			records[index].events.Clear();
		}
	}


	//worldmanager_moveable

	int i;
	for ( i = 0; i < gameLocal.num_entities; i++ )
	{
		if ( !gameLocal.entities[ i ] )
			continue;

		if (!gameLocal.entities[i]->IsType(idWorldManager_Moveable::Type))
			continue;

		int role = gameLocal.entities[i]->spawnArgs.GetInt("role", "-1");

		if (role != index)
			continue;

		static_cast<idWorldManager_Moveable *>( gameLocal.entities[i])->Event_startrecord( continuation );
	}
	
}

void idWorldManager::Event_recordstop( void )
{
	int i;

	state = OFF;

	this->index = 0;

	for ( i = 0; i < gameLocal.num_entities; i++ )
	{
		if ( !gameLocal.entities[ i ] )
			continue;

		if (!gameLocal.entities[i]->IsType(idWorldManager_Moveable::Type))
			continue;

		static_cast<idWorldManager_Moveable *>( gameLocal.entities[i])->Event_stop();
	}
}

void idWorldManager::Event_recordplay( int idx )
{
	int i;

	if (records[idx].events.Num() <= 0)
	{
		return;
	}


	records[idx].index = 0;
	records[idx].playing = true;
	records[idx].ghost->Show();
	records[idx].ghost->SetSkin(declManager->FindSkin(  this->spawnArgs.GetString(va("skin%d", idx), "skins/npc/ghost2")  ));

	//flag every event as NOT DONE.
	for (i = 0; i < records[idx].events.Num(); i++)
	{
		records[idx].events[i].done = false;
	}


	//the colored line that the operative poops out.
	if (index == -1)
	{
		recordline_t newLine;
		newLine.position1 = records[idx].events[0].position;
		newLine.position2 = records[idx].events[0].position;
		recordlines[idx].lines.Append(newLine);
	}


	for ( i = 0; i < gameLocal.num_entities; i++ )
	{
		if ( !gameLocal.entities[ i ] )
			continue;

		if (!gameLocal.entities[i]->IsType(idWorldManager_Moveable::Type))
			continue;

		int role = gameLocal.entities[i]->spawnArgs.GetInt("role", "-1");

		if (role == index)
			continue;

		static_cast<idWorldManager_Moveable *>( gameLocal.entities[i])->Event_startplay();
	}
}

void idWorldManager::RecordDeck( const char *deckString )
{
	if (state == OFF)
	{
		return;
	}

	record_t newEvent;
	newEvent.timestamp = gameLocal.time - recordStarttime;
	newEvent.deckcommand = deckString;
	
	records[index].events.Append( newEvent );
}

void idWorldManager::RecordFrob( const char *entName )
{
	if (state == OFF)
	{
		return;
	}

	record_t newEvent;
	newEvent.timestamp = gameLocal.time - recordStarttime;
	newEvent.frobcommand = entName;
	
	records[index].events.Append( newEvent );
}

void idWorldManager::RecordUnspawn( int id )
{
	if (state == OFF)
	{
		return;
	}

	record_t newEvent;
	newEvent.recordtype = RECORD_UNSPAWN;
	newEvent.timestamp = gameLocal.time - recordStarttime;
	newEvent.entID = id;
	
	records[index].events.Append( newEvent );
}

void idWorldManager::RecordSpawn( const char *defName, int id, const idVec3 &pos, float yaw )
{
	if (state == OFF)
	{
		return;
	}

	record_t newEvent;
	newEvent.recordtype = RECORD_SPAWN;
	newEvent.timestamp = gameLocal.time - recordStarttime;
	newEvent.spawncommand = defName;
	newEvent.position = pos;
	newEvent.yaw = yaw;
	newEvent.entID = id;
	
	records[index].events.Append( newEvent );

	if (developer.GetBool())
	{
		common->Printf("worldmanager: recording entity spawn ID %d     defname %s  \n", id, defName);
	}
}

void idWorldManager::RecordLaunchAim( int id, const idVec3 &dir, float force )
{
	if (state == OFF)
	{
		return;
	}
	
	if (id < 0)
		return;

	record_t newEvent;
	newEvent.timestamp = gameLocal.time - recordStarttime;
	newEvent.recordtype = RECORD_LAUNCHAIM;
	newEvent.entID = id;		//id #
	newEvent.position = dir;	//direction.
	newEvent.yaw = force;		//force.
	
	records[index].events.Append( newEvent );


	if (developer.GetBool())
	{
		common->Printf("worldmanager: recording launcher aim ID %d  \n", id);
	}
}

void idWorldManager::UpdatePlay( int idx )
{
	int currentIndex = records[idx].index;

	if (currentIndex > records[idx].events.Num() - 1)
	{
		return;
	}

	if (records[idx].events[currentIndex].timestamp < gameLocal.time - recordStarttime)
	{
		if (!records[idx].events[currentIndex].frobcommand.IsEmpty() && !records[idx].events[currentIndex].done)
		{
			//FROB EVENT.
			idEntity *frobEnt;
			frobEnt = gameLocal.FindEntity( records[idx].events[currentIndex].frobcommand );
			if (frobEnt)
			{

				if (frobEnt->IsType(idTrigger_Multi::Type))
				{
					static_cast<idTrigger_Multi *>( frobEnt )->TriggerAction(NULL);
				}
				else
				{
					gameLocal.GetLocalPlayer()->DoFrob(frobEnt);
					//common->Printf("frobbing! %d\n", gameLocal.time);
				}
			}
			else
			{
				gameLocal.Warning("WorldManager couldn't find frob ent: %s\n", gameLocal.FindEntity( records[idx].events[currentIndex].frobcommand.c_str()));
			}

			records[idx].events[currentIndex].done = true;
		}
		else if (records[idx].events[currentIndex].recordtype == RECORD_LAUNCHAIM && !records[idx].events[currentIndex].done)
		{
			//event: change launcher aim.
			
			//find the launcher with this id.
			int i;
			int targetEnt = -1;

			for ( i = 0; i < gameLocal.num_entities; i++ )
			{
				if ( !gameLocal.entities[ i ] )
					continue;

				int kk = records[idx].events[currentIndex].entID;

				if (gameLocal.entities[i]->spawnArgs.GetInt("id") != records[idx].events[currentIndex].entID)
				{
					continue;
				}

				targetEnt = i;
				break;
			}

			if (developer.GetBool())
			{
				common->Printf("worldmanager: aiming launcher entity ID %d  \n", records[idx].events[currentIndex].entID);
			}

			if (targetEnt >= 0)
			{
				//legacy.
				gameLocal.entities[targetEnt]->spawnArgs.SetVector("new_launchdir", records[idx].events[currentIndex].position);
				gameLocal.entities[targetEnt]->spawnArgs.SetInt("new_force", records[idx].events[currentIndex].yaw);
				gameLocal.entities[targetEnt]->spawnArgs.SetInt("new_update", 1);

				static_cast<idLauncher *>( gameLocal.entities[i] )->SetLaunchDir(records[idx].events[currentIndex].position, records[idx].events[currentIndex].yaw);
			}

			records[idx].events[currentIndex].done = true;
		}
		else if (!records[idx].events[currentIndex].deckcommand.IsEmpty() && !records[idx].events[currentIndex].done)
		{
			//DECK EVENT.
			gameLocal.RunDeckCommand(records[idx].events[currentIndex].deckcommand.c_str());

			records[idx].events[currentIndex].done = true;
		}
		else if (records[idx].events[currentIndex].recordtype == RECORD_UNSPAWN && !records[idx].events[currentIndex].done)
		{
			//UNSPAWN EVENT.
			//find the ent with this id.
			int i;
			int targetEnt = -1;

			for ( i = 0; i < gameLocal.num_entities; i++ )
			{
				if ( !gameLocal.entities[ i ] )
					continue;

				int kk = records[idx].events[currentIndex].entID;

				if (gameLocal.entities[i]->spawnArgs.GetInt("id") != records[idx].events[currentIndex].entID)
				{
					continue;
				}

				targetEnt = i;
				break;
			}

			if (targetEnt >= 0)
			{
				gameLocal.entities[targetEnt]->PostEventMS( &EV_Remove, 0 );
				//gameLocal.entities[targetEnt]->Event_CallFunction("onPick");
			}

			records[idx].events[currentIndex].done = true;
		}
		else if (records[idx].events[currentIndex].recordtype == RECORD_SPAWN && !records[idx].events[currentIndex].done)
		{
			
			//SPAWN EVENT.

			idEntity	*ent;
			idDict		args;
			idAngles	ang;

			int id = gameLocal.time - recordStarttime;

			if (developer.GetBool())
			{
				common->Printf("worldmanager: spawning entity ID %d  classname %s \n", records[idx].events[currentIndex].entID,
					records[idx].events[currentIndex].spawncommand.c_str());
			}

			args.Set( "classname", records[idx].events[currentIndex].spawncommand );
			args.SetVector( "origin", records[idx].events[currentIndex].position );
			args.SetInt( "id", records[idx].events[currentIndex].entID);
			bool bSpawn = gameLocal.SpawnEntityDef( args, &ent );

			if (ent)
			{
				ent->spawnArgs.SetInt("id", records[idx].events[currentIndex].entID);  //BC 7-21-2016 was crashing here.
			
				ang.pitch = 0;
				ang.yaw = records[idx].events[currentIndex].yaw;
				ang.roll = 0;
				ent->SetAngles( ang );
			}

			if (developer.GetBool())
			{
				common->Printf("worldmanager: spawning success:%d\n",  bSpawn);
				
			}

			records[idx].events[currentIndex].done = true;
		}
		else
		{
			//MOVE EVENT.
			float moveTime = (float)RECORDRATE / 1000;
		
			records[idx].ghost->Event_SetMoveTime(moveTime);
			records[idx].ghost->Event_MoveToPos(records[idx].events[currentIndex].position);
			
			idAngles newAng = idAngles(0, records[idx].events[currentIndex].yaw, 0);
			records[idx].ghost->SetAxis(newAng.ToMat3());

			if (index == -1)
			{
				int lastLineIndex = recordlines[idx].lines.Num() - 1;
				recordline_t newLine;
				newLine.position1 = recordlines[idx].lines[lastLineIndex].position2;
				newLine.position2 = records[idx].events[currentIndex].position;

				recordlines[idx].lines.Append(newLine);
			}

			records[idx].events[currentIndex].done = true;
		}

		
		records[idx].index++;
	}
}

void idWorldManager::UpdateRecord( void )
{
	if (state == OFF)
	{
		return;
	}

	if (gameLocal.time < nextRecordtime)
	{
		return;
	}

	nextRecordtime = gameLocal.time + RECORDRATE;

	idVec3 currentPosition = gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin();
	int currentAngle = (int)gameLocal.GetLocalPlayer()->viewAngles.yaw;	

	if ((int)lastPosition.x == (int)currentPosition.x && (int)lastPosition.y == (int)currentPosition.y && (int)lastPosition.z == (int)currentPosition.z && (int)lastAngle == (int)currentAngle)
	{
		return;
	}

	lastPosition = currentPosition;
	lastAngle = gameLocal.GetLocalPlayer()->viewAngles.yaw;	
	
	record_t newEvent;
	newEvent.timestamp = gameLocal.time - recordStarttime;
	newEvent.position = currentPosition;
	newEvent.yaw = currentAngle;
	newEvent.deckcommand = NULL;
	newEvent.frobcommand = NULL;
	
	records[index].events.Append( newEvent );
}

void idWorldManager::Think( void )
{
	int i;
	UpdateRecord();

	for (i = 0; i < 3; i++)
	{
		idVec4 markerColor;
		idVec3 markerPos;
		int markerRadius = 24;

		if (records[i].playing)
		{
			UpdatePlay(i);
		}
		else
		{
			continue;
		}

		if (state == OFF && index != -1 /*caser*/)
		{
			continue;
		}

		if (this->index == i)
		{
			continue;
		}

		if (!records[i].ghost->IsHidden())
		{
			if ((int)(gameLocal.time * 0.004) % 3 == 0)
			{
				markerRadius = 12;
			}

			switch (i)
			{
				case 0:		markerColor = idVec4(.25, .75, 1, 1); break; //blue.
				case 1:		markerColor = idVec4(.74, .9, .26, 1); break;  //green.
				default:	markerColor = idVec4(1, .6, 0, 1); break; //orange.
			}

			//blue .25, .75, 1
			//yellow 1, .8, 0, 1
			//red .9, .25, .25

			markerPos = records[i].ghost->GetPhysics()->GetOrigin() + idVec3(0,0,85);
			gameRenderWorld->DebugLine( markerColor, markerPos + idVec3(0,0,-markerRadius), markerPos + idVec3(0,0,markerRadius) );
			gameRenderWorld->DebugLine( markerColor, markerPos + idVec3(0,-markerRadius,0), markerPos + idVec3(0,markerRadius,0) );
			gameRenderWorld->DebugLine( markerColor, markerPos + idVec3(-markerRadius,0,0), markerPos + idVec3(markerRadius,0,0) );

			if (index == -1)
			{
				//draw lines.
				int k;

				if (recordlines[i].lines.Num() >= 3)
				{
					for (k = 0; k < recordlines[i].lines.Num() - 1; k++)
					{
						if (k > 2) //BC hack. The initial lines are garbage data. So, just skip them.
						{
							gameRenderWorld->DebugLine( markerColor, 
								recordlines[i].lines[k].position1, recordlines[i].lines[k].position2 );
						}
					}


					//This is the dangly bit that connects the last recordline position to the character model's feet.
					if (records[i].index < recordlines[i].lines.Num() && i > 1)
					{
						gameRenderWorld->DebugLine( markerColor, 
							recordlines[i].lines[records[i].index].position1,
							records[i].ghost->GetPhysics()->GetOrigin() );
					}
				}
			}
		}
	}
}




