#include "rpl4.h"
#pragma hdrstop

#include "rpl4vid.h"
#include "..\rp\chute.h"
#include "..\munga\door.h"
#include "..\munga\doorfram.h"
#include "..\munga_l4\l4vidrnd.h"
#include "..\munga\mission.h"
#include "..\rp\rpplayer.h"
#include "..\rp\weapsys.h"
#include "..\munga\notation.h"
#include "..\munga\namelist.h"
#include "..\rp\vtv.h"
#include "..\munga\app.h"

// RB 1/14/07
//#include <dpl\dpl.h>
//#include <dpl\dplutils.h>
//#include <dpl\dpl_vpx.h>

extern Entity
	*Entity_Being_Created;		// !!! temp, till callback handlers become a class
// HACK, this code makes sure the left and right engine geometry is loaded
// one time and re-used.  A more generic solution using the connection
// manager will be created once we are sure it is safe to apply this
// optimization to all cases.
d3d_OBJECT
	*left_engine,
	*right_engine;
//
//#############################################################################
// Constructor for the video renderer
//#############################################################################
//
RPL4VideoRenderer::RPL4VideoRenderer(
	HWND hWnd,
	unsigned int screenWidth,
	unsigned int screenHeight,
	bool fullscreen,
	InterestType interest_type,
	InterestDepth depth_calibration
) : DPLRenderer(hWnd, screenWidth, screenHeight, fullscreen, interest_type, depth_calibration)
{
//STUBBED: DPL RB 1/14/07
	vtvCount			=	0;
	vtvsExpected   =	999;
////
//// Preload a couple of things for DPL
////
//	dpl_LoadObject ( "chg", dpl_load_normal );
//	dpl_LoadObject ( "rivet", dpl_load_normal );
//	dpl_LoadObject ( "lsaber", dpl_load_normal );
//	dpl_LoadObject ( "bst", dpl_load_normal );
//	dpl_LoadObject ( "tsphere", dpl_load_normal );
}

//
//#############################################################################
// Destructor for the video renderer
//#############################################################################
//
RPL4VideoRenderer::~RPL4VideoRenderer()
{
}
#if 0
void
	RPL4VideoRenderer::MakeJointedMoverRenderables(
		Entity			*entity
		ViewFrom			view_type
)
{
	bool inDeathZone
	dpl_ISECT_MODE
		intersect_mode;
	uint32
		intersect_mask;
	char
		my_filename[40];
	dpl_LOAD_MODE
		cache_mode;

	JointedMover
		*jointed_mover;

	Verify(entity->IsDerivedFrom(JointedMover::GetClassDerivations());
	jointed_mover = Cast_Object(
		JointedMover*,
		entity
	);

	cache_mode = dpl_load_nocache;
	//
	//~~~~~~~~~~~~~~~~~~~~~~~
	// Outside or Inside View
	//~~~~~~~~~~~~~~~~~~~~~~~
	//
	if (type == inside_entity)
	{
		inDepthZone = true;
		//buildInZone		=	dplDeathZone;
		intersect_mode =  dpl_isect_mode_obj;
		intersect_mask  =  NULL;
		skl_type = EntitySegment::SkeletonType_A;
	}
   else
	{
		inDepthZone = true;
		//buildInZone		=	dplDeathZone;
		intersect_mode =  dpl_isect_mode_geometry;
		intersect_mask  =  INTERSECT_ALL;
		skl_type = EntitySegment::SkeletonType_N;
	}
   //
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Create the root renderable and tie it to the entity
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
   RootRenderable	*this_root =
		new RootRenderable(
			entity,							// Entity to attach the renderable to
			RootRenderable::Dynamic,	// How/when to execute the renderable
			NULL,								// object to hang on the DCS, may be a list later <NULL>
			false,					// DPL Zone this stuff will live in (for culling)
			intersect_mode,				// type of intersections to do on this object
			intersect_mask);				// intersection mask for the object
	Register_Object(this_root);
   if(eyeRelative && (entity == GetLinkedEntity()))
	{
		dpl_DCS* aDCS=this_root->GetDCS();
		Check_Pointer(aDCS);
		Check_Pointer(dplTestEyeDCS);
		dpl_AddDCSToDCS( aDCS, dplTestEyeDCS );
	}
   //
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// create an array for the parent DCS' sizeof(segmentTable)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	dpl_DCS **dcs_array = new (dpl_DCS(*[jointed_mover->segmentCount]));
	Register_Pointer(dcs_array);

	//
	//~~~~~~~~~~~~~~~~~~~~~~~~
	// Get The Joint Subsystem
	//~~~~~~~~~~~~~~~~~~~~~~~~
	//
	CString *object_file_name;
	JointSubsystem* joint_subsystem = jointed_mover->GetJointSubsystem();
	Check(joint_subsystem);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Get the Segment table for this jointed Mover
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	EntitySegment::SegmentTableIterator segment_iterator(jointed_mover->segmentTable);
	EntitySegment *current_segment;
   while ((current_segment = segment_iterator.ReadAndNext()) != NULL)
	{
		Check(current_segment);
		//
		//~~~~~~~~~~~~~~~~~~~~~~
		// Get the offset matrix
		//~~~~~~~~~~~~~~~~~~~~~~
		//
		LinearMatrix offset_matrix;
		offset_matrix = current_segment->GetBaseOffset();

		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Get the parent DCS of the DCS we will be creating
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		dpl_DCS *parent_DCS;
		if(!current_segment->GetParent())
		{
			parent_DCS = this_root->GetDCS();
		}
		else
		{
			int parent_index;
			parent_index = current_segment->GetParentIndex();
			Verify(
				(parent_index >= 0) &&
				(parent_index < jointed_mover->segmentCount)
			);
			parent_DCS = dcs_array[parent_index];
		}
		Check_Pointer(parent_DCS);
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// See if this segment is a Site
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		if(current_segment->IsSiteSegment())
		{
			//
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			// If this is an eye site build the eye renderable
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			//
			if(type == insideEntity &&
				strcmp(current_segment->GetName(), "siteeyepoint") == 0)
			{
				EulerAngles* eyepoint_rotation =
					(EulerAngles*)entity->GetAttributePointer("EyepointRotation");
				#if 0 //DEBUG_LEVEL > 0
				DPLEyeRenderable* this_eye      =
				#endif
					mCamera =
					new DPLEyeRenderable(
						entity,
						false,
						offset_matrix,
						parent_DCS,
						dplMainView,
						eyepoint_rotation
					);
				Register_Object(this_eye);
			}
			continue;
		}
      //
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Get the dpl object and load it
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		object_file_name = current_segment->GetVideoObjectName(skl_type);
		if(object_file_name)
		{
			Dump(*object_file_name);
			//cout<<"normal object "<<*object_file_name<<"\n";
			strcpy(my_filename,*object_file_name);
			*(my_filename + (strlen(my_filename) - 4)) = '\0';
			this_object =   dpl_LoadObject ( my_filename,cache_mode );
		}
		else
		{
			this_object = NULL;
		}
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Get the segment index
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		int this_segment_index;
		this_segment_index = current_segment->GetIndex();
		Verify(
			(this_segment_index >= 0) &&
			(this_segment_index < jointed_mover->segmentCount)
		);
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// If this segment has a joint Get it
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		int joint_index;
		joint_index = current_segment->GetJointIndex();
		Joint::JointType joint_type;
		Joint *this_joint = NULL;
		if(joint_index == -1)
		{
			joint_type = Joint::StaticJointType;
		}
		else
		{
			Verify(joint_index < joint_subsystem->GetJointCount());
			this_joint = joint_subsystem->GetJoint(joint_index);
			Check(this_joint);
			joint_type = this_joint->GetJointType();
		}
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Make the appropriate renderable
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		switch(joint_type)
		{
			case Joint::HingeXJointType:
			case Joint::HingeYJointType:
			case Joint::HingeZJointType:
			{
				HingeRenderable *this_child =
					new HingeRenderable(
						entity,							// Entity to attach the renderable to
						HingeRenderable::Dynamic,	// How/when to execute the renderable
						this_object,					// object to hang on the DCS, may be a list later <NULL>
						false,					// DPL Zone this stuff will live in (for culling)
						intersect_mode,				// type of intersections to do on this object
						intersect_mask,				// intersection mask for the object
						parent_DCS,						// the parent DCS we will be offsetting from
						&offset_matrix,				// offset matrix to be applied prior to joint DCS
						this_joint->GetHingePtr());	// Hinge attribute we will use to control the joint
				Register_Object(this_child);
				dcs_array[this_segment_index] = this_child->GetDCS();
				}
				break;
			}
			case Joint::BallJointType:
			{
				BallJointRenderable *this_child =
					new BallJointRenderable(
						entity,									// Entity to attach the renderable to
						BallJointRenderable::Dynamic,		// How/when to execute the renderable
						this_object,							// object to hang on the DCS, may be a list later <NULL>
						false,							// DPL Zone this stuff will live in (for culling)
						intersect_mode,						// type of intersections to do on this object
						intersect_mask,						// intersection mask for the object
						parent_DCS,								// the parent DCS we will be offsetting from
						&offset_matrix,						// offset matrix to be applied prior to joint DCS
						this_joint->GetEulerAnglesPtr());// Euler angles to control rotation of the ball joint
				Register_Object(this_child);
				dcs_array[this_segment_index] = this_child->GetDCS();
				break;
			}
			case Joint::BallTranslationJointType:
			{
				BallTranslateJointRenderable *this_child =
					new BallTranslateJointRenderable(
						entity,							// Entity to attach the renderable to
						BallTranslateJointRenderable::Dynamic,		// How/when to execute the renderable
						this_object,					// object to hang on the DCS, may be a list later <NULL>
						false,					// DPL Zone this stuff will live in (for culling)
						intersect_mode,				// type of intersections to do on this object
						intersect_mask,				// intersection mask for the object
						parent_DCS,						// the parent DCS we will be offsetting from
						&offset_matrix,				// offset matrix to be applied prior to joint DCS
						this_joint->GetEulerAnglesPtr(),	 // Euler angles to control rotation of the ball joint
						this_joint->GetTranslationPtr()		// offset for the translation part of the joint
					);
				Register_Object(this_child);
				dcs_array[this_segment_index] = this_child->GetDCS();
				break;
			}
			case Joint::StaticJointType:
			default:
			{
				DPLStaticChildRenderable *this_child =
					new DPLStaticChildRenderable(
						entity,
						false,
						this_object,
						intersect_mode,
						intersect_mask,
						offset_matrix,
						parent_DCS
						);
				Register_Object(this_child);
				dcs_array[this_segment_index] = this_child->GetDCS();
				break;
			}
		}
	}
   //
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Cycle through the VTV's subsystems and create the site renderables
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	for(int ii=0;ii<entity->GetSubsystemCount();++ii)
	{
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Controls Mapper is not propagated across
		// the network so we must ignore it here for replicants
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		if (ii == VTV::ControlsMapperSubsystem)
		{
			continue;
		}
		Subsystem *current_subsystem = entity->GetSubsystem(ii);
		Check(current_subsystem);
		int site_index = current_subsystem->GetSegmentIndex();
		if (site_index != -1)
		{
			EntitySegment *site_segment = entity->GetSegment(site_index);
			Check(site_segment);
			//
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			// Get the parentDCS for this site
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			//
			dpl_DCS *parent_DCS;
			if(!site_segment->GetParent())
			{
				parent_DCS = this_root->GetDCS();
			}
			else
			{
				int parent_index;
				parent_index = site_segment->GetParentIndex();
				Verify(
					(parent_index >= 0) &&
					(parent_index < jointed_mover->segmentCount)
				);
				parent_DCS = dcs_array[parent_index];
			}
			Check_Pointer(parent_DCS);

			//
			//~~~~~~~~~~~~~~~~~~~~
			// Get the base offset
			//~~~~~~~~~~~~~~~~~~~~
			//
			LinearMatrix	base_offset = site_segment->GetBaseOffset();
			switch(current_subsystem->GetClassID())
			{
				class LaserDrillClassID:
					this_object =	dpl_LoadObject ( "lsaber", dpl_load_normal );
					Check_Pointer(this_object);
					Vector3D* laser_scale =
						(Vector3D*)current_subsystem->GetAttributePointer("LaserScale");
					Logical* laser_on =
						(Logical*)current_subsystem->GetAttributePointer("LaserOn");
					DPLScaleRenderable *this_scaler =
						new DPLScaleRenderable(
						entity,
						buildInZone,
						this_object,
						dpl_isect_mode,
						NULL,
						base_offset,
						parent_DCS,
						laser_scale,
						laser_on
					);
					Register_Object(this_scaler);
				break;
			}
		}
	}
   Unregister_Pointer(dcs_array);
	delete[] dcs_array;

	Check_Fpu();
}
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// RPL4VideoRenderer::RecurseSKLFile This routine is called recursively to
// to descend the hiearchy of a notation file and create all the renderables
// needed to get an object visible.
//
void
	RPL4VideoRenderer::RecurseSKLFile(
		Entity			*entity,
		HierarchicalDrawComponent	*parent,
		NotationFile	*mech_skeleton,
		const char		*page_name,
		int				recursion_depth,
		ViewFrom			type,
		int				*joint_counter,
		dpl_LOAD_MODE	cache_mode
	)
{
//STUBBED: DPL RB 1/14/07
	NameList
		*joint_pages,
		*site_pages;

	NameList::Entry
		*entry;

	const char
		*site_page_name,
		*next_joint_page_name;		// The next joint name (argument to a recursive call)

	const char
		*object_file_name,
		*my_joint_type;

	char
		*gun_name,
		*gun_attribute_name,
		my_filename[40];

	int
		gun_site;



#ifdef NOISY_RENDERER
	int
		i;							// loop counter
#endif

	Point3D
		translation(0,0,0);

	EulerAngles
		rotation(0,0,0);

	HierarchicalDrawComponent
		*next_parent;

	d3d_OBJECT *this_object = NULL;

	dpl_ISECT_MODE
		intersect_mode;
	uint32
		intersect_mask;
	bool inDeathZone;
	//
	// get the intersect mode hooked up properly
	//
	if(type == insideEntity)
	{
		inDeathZone = true;
		//buildInZone		=	dplDeathZone;
//		intersect_mode =	dpl_isect_mode_obj;
		intersect_mask	=  NULL;
	}
	else
	{
		inDeathZone = false;
		//buildInZone		=	dplMainZone;
//		intersect_mode =	dpl_isect_mode_geometry;
		intersect_mask	=  INTERSECT_ALL;
	}
	//
	// indent by the recursion depth and print out the current page name
	//
#ifdef NOISY_RENDERER
	Tell(recursion_depth);
	for (i = 0; i < recursion_depth; i++)
		Tell("..");
	Tell(page_name << "\n");
#endif
	//
	// suck the brains out of this page to create the renderable from
	//
	mech_skeleton->GetEntry(page_name,	"tranx"	,&translation.x);
	mech_skeleton->GetEntry(page_name,	"trany"	,&translation.y);
	mech_skeleton->GetEntry(page_name,	"tranz"	,&translation.z);
	mech_skeleton->GetEntry(page_name,	"pitch"	,&rotation.pitch.angle);
	mech_skeleton->GetEntry(page_name,	"yaw"		,&rotation.yaw.angle);
	mech_skeleton->GetEntry(page_name,	"roll"	,&rotation.roll.angle);

	if(mech_skeleton->GetEntry(page_name,	"Object"	,&object_file_name))
	{
		strcpy(my_filename,object_file_name);
		*(my_filename + (strlen(my_filename) - 4)) = '\0';
#ifdef NOISY_RENDERER
		Tell(recursion_depth);
		for (i = 0; i < recursion_depth; i++)
			Tell("..");
		Tell("BGF file: " << my_filename << "\n");
#endif
//		// HACK, this code makes sure the left and right engine geometry is loaded
//		// one time and re-used.  A more generic solution using the connection
//		// manager will be created once we are sure it is safe to apply this
//		// optimization to all cases.
//		if(	(strcmp("vra",my_filename) == 0) ||
//				(strcmp("vrc",my_filename) == 0) ||
//				(strcmp("vrn",my_filename) == 0)	||
//				(strcmp("vrt",my_filename) == 0))
//		{
//			if(right_engine == 0)
//			{
//				char *file = new char[strlen(my_filename) + 5];
//				strcpy_s(file,strlen(my_filename)+5,my_filename);
//				strcat_s(file,strlen(my_filename)+5,".bgf");
//				this_object		=	d3d_OBJECT::LoadObject ( GetDevice(), file );
//				right_engine	=	this_object;
////				cout<<"Load right engine\n";
//			}
//			else
//			{
//				this_object		=	right_engine;
////				cout<<"re-use right engine\n";
//			}
//		}
//		else if(	(strcmp("vla",my_filename) == 0) ||
//					(strcmp("vlc",my_filename) == 0) ||
//					(strcmp("vln",my_filename) == 0)	||
//					(strcmp("vlt",my_filename) == 0))
//		{
//			if(left_engine == 0)
//			{
//				char *file = new char[strlen(my_filename) + 5];
//				strcpy_s(file,strlen(my_filename)+5,my_filename);
//				strcat_s(file,strlen(my_filename)+5,".bgf");
//				this_object		=	d3d_OBJECT::LoadObject ( GetDevice(), file );
//				left_engine		=	this_object;
////				cout<<"Load left engine\n";
//			}
//			else
//			{
//				this_object		=	left_engine;
////            cout<<"re-use left engine\n";
//			}
//		}
//		else
		{
			char *file = new char[strlen(my_filename) + 5];
			strcpy_s(file,strlen(my_filename)+5,my_filename);
			strcat_s(file,strlen(my_filename)+5,".bgf");
			this_object		=	d3d_OBJECT::LoadObject ( GetDevice(), file );
		}
	}
	else
	{
		this_object = NULL;
	}
	//
	// dump out the data for me to look at
	//
#ifdef NOISY_RENDERER
	Tell(recursion_depth);
	for (i = 0; i < recursion_depth; i++)
		Tell("..");
	Dump(translation);
	Tell(recursion_depth);
	for (i = 0; i < recursion_depth; i++)
		Tell("..");
	Dump(rotation);
#endif
	//
	// Construct the renderable to display this part of the thing
	//
	LinearMatrix  Offset_Matrix;
	Offset_Matrix = translation;
	Offset_Matrix = rotation;
	my_joint_type = "none";
	mech_skeleton->GetEntry(page_name,	"Type"	,&my_joint_type);
	if(recursion_depth>1)
		(*joint_counter)++;
	if(strncmp(my_joint_type,"hinge",5) == 0)
	{
		Tell("Hinge Joint " << (*joint_counter) << "\n");

		VTV *vtv = (VTV*) entity;
		JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
		Verify(
			(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
			Joint::HingeXJointType) ||
			(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
			Joint::HingeYJointType) ||
			(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
			Joint::HingeZJointType)
		);
		const Hinge *hinge_joint =
			&joint_subsystem->GetJoint(*joint_counter)->GetHinge();
		HingeRenderable *this_child =
			new HingeRenderable(
				entity,							// Entity to attach the renderable to
				HingeRenderable::Dynamic,	// How/when to execute the renderable
				this_object,					// object to hang on the DCS, may be a list later <NULL>
				inDeathZone,					// DPL Zone this stuff will live in (for culling)
				intersect_mode,				// type of intersections to do on this object
				intersect_mask,				// intersection mask for the object
				parent,						// the parent DCS we will be offsetting from
				&Offset_Matrix, 				// offset matrix to be applied prior to joint DCS
				hinge_joint);					// Hinge attribute we will use to control the joint
		Register_Object(this_child);
		next_parent	=  this_child;
	}
	else if(strcmp(my_joint_type,"ball") == 0)
	{
		Tell("Ball Joint " << (*joint_counter) << "\n");
		VTV *vtv = (VTV*) entity;
		JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
		const EulerAngles *euler_angles =
			&joint_subsystem->GetJoint(*joint_counter)->GetEulerAngles();
		Verify(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
			Joint::BallJointType);
		BallJointRenderable *this_child =
			new BallJointRenderable(
				entity,									// Entity to attach the renderable to
				BallJointRenderable::Dynamic,		// How/when to execute the renderable
				this_object,							// object to hang on the DCS, may be a list later <NULL>
				false,							// DPL Zone this stuff will live in (for culling)
				intersect_mode,						// type of intersections to do on this object
				intersect_mask,						// intersection mask for the object
				parent,								// the parent DCS we will be offsetting from
				&Offset_Matrix,						// offset matrix to be applied prior to joint DCS
				euler_angles);							// Euler angles to control rotation of the ball joint
		Register_Object(this_child);
		next_parent	=  this_child;
	}
	else if(strcmp(my_joint_type,"balltranslate") == 0)
	{
		Tell("Ball Translation Joint " << (*joint_counter) << "\n");
		VTV *vtv = (VTV*) entity;
		JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
		const EulerAngles *euler_angles =
			&joint_subsystem->GetJoint(*joint_counter)->GetEulerAngles();
		const Point3D	*point_3D =
			&joint_subsystem->GetJoint(*joint_counter)->GetTranslation();

		Verify(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
			Joint::BallTranslationJointType);
		BallTranslateJointRenderable *this_child =
			new BallTranslateJointRenderable(
				entity,							// Entity to attach the renderable to
				BallTranslateJointRenderable::Dynamic,		// How/when to execute the renderable
				this_object,					// object to hang on the DCS, may be a list later <NULL>
				false,					// DPL Zone this stuff will live in (for culling)
				intersect_mode,				// type of intersections to do on this object
				intersect_mask,				// intersection mask for the object
				parent,						// the parent DCS we will be offsetting from
				&Offset_Matrix,				// offset matrix to be applied prior to joint DCS
				euler_angles,					// Euler angles to control rotation of the ball joint
				point_3D);						// offset for the translation part of the joint
		Register_Object(this_child);
		next_parent	=  this_child;
	}
	else
	{
	// Tell("Static Joint" << (*joint_counter) << "\n");
	DPLStaticChildRenderable *this_child =
		new DPLStaticChildRenderable(
			entity,
			inDeathZone,
			this_object,
			intersect_mode,
			intersect_mask,
			Offset_Matrix,
			parent
			);
	Register_Object(this_child);
	next_parent	=  this_child;
	}
	//
	// Get a the list of joint pages from the current page
	//
	if(type == insideEntity)
	{
//		dpl_SetDCSNearField ( next_parent_dcs, True );
//      dpl_FlushDCS(next_parent_dcs);
	}
	joint_pages = mech_skeleton->MakeEntryList(page_name,"joint");
	Register_Object(joint_pages);
	recursion_depth++;
	//
	// Recursively process all the joint pages on the current page
	//
	for(	entry = joint_pages->GetFirstEntry();
			entry;
			entry = entry->GetNextEntry())
	{
		// Get the name of the next joint page
		next_joint_page_name = (char *)entry->dataReference;
		// Process the next page recursively through this routine
		RecurseSKLFile(
			entity,
			next_parent,
			mech_skeleton,
			next_joint_page_name,
			recursion_depth,
			type,
			joint_counter,
			cache_mode);
	}
	//
	// now check the list of sites for stuff to hook up
	//
	site_pages = mech_skeleton->MakeEntryList(page_name,"site");
	Register_Object(site_pages);
	//
	// process all the site pages on the current page
	//
	for(	entry = site_pages->GetFirstEntry();
			entry;
			entry = entry->GetNextEntry())
	{
		// Get the name of the next joint page
		site_page_name = (char *)entry->dataReference;
		//
		// Setup a eyepoint site, connect it to a rotation attribute so we can move it
		// arround.
		//
		if(type == insideEntity &&
			strcmp(site_page_name, "siteeyepoint") == 0)
		{
			mech_skeleton->GetEntry(site_page_name,	"tranx"	,&translation.x);
			mech_skeleton->GetEntry(site_page_name,	"trany"	,&translation.y);
			mech_skeleton->GetEntry(site_page_name,	"tranz"	,&translation.z);
			mech_skeleton->GetEntry(site_page_name,	"pitch"	,&rotation.pitch.angle);
			mech_skeleton->GetEntry(site_page_name,	"yaw"		,&rotation.yaw.angle);
			mech_skeleton->GetEntry(site_page_name,	"roll"	,&rotation.roll.angle);
#ifdef NOISY_RENDERER
			Tell(recursion_depth);
			for (i = 0; i < recursion_depth; i++)
				Tell("..");
			Tell(site_page_name << "\n");
			Tell(recursion_depth);
			for (i = 0; i < recursion_depth; i++)
				Tell("..");
			Dump(translation);
			Tell(recursion_depth);
			for (i = 0; i < recursion_depth; i++)
				Tell("..");
			Dump(rotation);
#endif
			EulerAngles* eyepoint_rotation = (EulerAngles*)entity->GetAttributePointer("EyepointRotation");
			Offset_Matrix = translation;
			Offset_Matrix = rotation;
			#if 0 //DEBUG_LEVEL > 0
			DPLEyeRenderable* this_eye	=
         #endif
				mCamera =
				new DPLEyeRenderable(
					entity,
//					buildInZone,
					Offset_Matrix,
					next_parent,
					eyepoint_rotation
				);
			Register_Object(this_eye);
		}
		//
		// Setup a gunport site, this works for all the sites
		// this is kind of funky but will be replaced as the VID file goes on line.
		// !!! Hack
		//
		gun_site					=	False;
		gun_name					=	"";
		gun_attribute_name	=	"";
		if(strcmp(site_page_name,"sitefrontrightport") == 0)
		{
			gun_site					=	True;
			gun_name					=	"LaserGun1";
			gun_attribute_name	=	"FrontLaserOn";
		}
		else if(strcmp(site_page_name,"sitefrontleftport") == 0)
		{
			gun_site					=	True;
			gun_name					=	"LaserGun2";
			gun_attribute_name	=	"FrontLaserOn";
		}
		else if(strcmp(site_page_name,"sitefrontcenterport") == 0)
		{
			gun_site					=	True;
			gun_name					=	"LaserGun";
			gun_attribute_name	=	"FrontLaserOn";
		}
		else if(strcmp(site_page_name,"sitebackrightport") == 0)
		{
			gun_site					=	True;
			gun_name					=	"LaserGun1";
			gun_attribute_name	=	"RearLaserOn";
		}
		else if(strcmp(site_page_name,"sitebackleftport") == 0)
		{
			gun_site					=	True;
			gun_name					=	"LaserGun2";
			gun_attribute_name	=	"RearLaserOn";
		}
		else if(strcmp(site_page_name,"sitebackcenterport") == 0)
		{
			gun_site					=	True;
			gun_name					=	"LaserGun";
			gun_attribute_name	=	"RearLaserOn";
		}
		if(gun_site)
		{
			LaserGun* laser_subsystem=
				(LaserGun*)entity->FindSubsystem(gun_name);
			if(laser_subsystem)
			{
				mech_skeleton->GetEntry(site_page_name,	"tranx"	,&translation.x);
				mech_skeleton->GetEntry(site_page_name,	"trany"	,&translation.y);
				mech_skeleton->GetEntry(site_page_name,	"tranz"	,&translation.z);
				mech_skeleton->GetEntry(site_page_name,	"pitch"	,&rotation.pitch.angle);
				mech_skeleton->GetEntry(site_page_name,	"yaw"		,&rotation.yaw.angle);
				mech_skeleton->GetEntry(site_page_name,	"roll"	,&rotation.roll.angle);
				Vector3D* laser_scale =
					(Vector3D*)laser_subsystem->GetAttributePointer("LaserScale");
				Logical* laser_on =
					(Logical*)laser_subsystem->GetAttributePointer(gun_attribute_name);
				this_object =	d3d_OBJECT::LoadObject ( GetDevice(), "lsaber.bgf" );

				if( laser_subsystem && laser_scale && laser_on && this_object)
				{
					Tell("Hooked "<<gun_name<<" to site "<<site_page_name<<"\n");
					Check(laser_scale);
					Check_Pointer(laser_on);
					Offset_Matrix.BuildIdentity();
					Offset_Matrix = translation;
					Offset_Matrix = rotation;
					#if DEBUG_LEVEL > 0
					DPLScaleRenderable *this_scaler =
               #endif
						new DPLScaleRenderable(
						entity,
						inDeathZone,
						this_object,
						intersect_mode,
						intersect_mask,
						Offset_Matrix,
						next_parent,
						laser_scale,
						laser_on);
					Register_Object(this_scaler);
				}
			}
		}
		//
		// Setup a chute site, get the position and attributes to control it and bind
		// them all up for use.
		//
		if(strcmp(site_page_name, "sitechute") == 0)
		{
			mech_skeleton->GetEntry(site_page_name,	"tranx"	,&translation.x);
			mech_skeleton->GetEntry(site_page_name,	"trany"	,&translation.y);
			mech_skeleton->GetEntry(site_page_name,	"tranz"	,&translation.z);
			Chute* chute_subsystem=
				(Chute*)entity->FindSubsystem("Chute");
			if (chute_subsystem)
			{
				Check(chute_subsystem);
				Quaternion*	chute_rotation =
					(Quaternion*)chute_subsystem->GetAttributePointer("ChuteDirection");
				Vector3D* chute_scale =
					(Vector3D*)chute_subsystem->GetAttributePointer("ScaleFactor");
				Logical* chute_open =
					(Logical*)chute_subsystem->GetAttributePointer("ChuteOn");
				this_object =	d3d_OBJECT::LoadObject ( GetDevice(), "cht.bgf" );
				if(chute_rotation && chute_scale && chute_open && this_object)
				{
					Check(chute_rotation);
					Check(chute_scale);
					Check_Pointer(chute_open);
					Check_Pointer(this_object);
					Offset_Matrix.BuildIdentity();
					Offset_Matrix = translation;
					#if DEBUG_LEVEL > 0
					DPLScaleQuatRenderable *this_scaler =
               #endif
						new DPLScaleQuatRenderable(
							entity,
							inDeathZone,
							this_object,
							intersect_mode,
							intersect_mask,
							Offset_Matrix,
							next_parent,
							chute_rotation,
							chute_scale,
							chute_open);
					Register_Object(this_scaler);
				}
				else
				{
					if(!chute_rotation)
						DEBUG_STREAM<<"ChuteSite couldn't find ChuteDirection attribute\n" << std::flush;
					if(!chute_scale)
						DEBUG_STREAM<<"ChuteSite couldn't find ChuteScale attribute\n" << std::flush;
					if(!chute_open)
						DEBUG_STREAM<<"ChuteSite couldn't find ChuteOn attribute\n" << std::flush;
					if(!this_object)
						DEBUG_STREAM<<"ChuteSite couldn't find chute DPL object\n" << std::flush;
				}
			}
		}
		//
		// Setup a booster site, get the site position and the attribute(s) that will
		// control the booster.  Setup origin matrix and renderables to control the
		// appearance of the booster.
		//
		if(strcmp(site_page_name, "sitebooster") == 0)
		{
#ifdef NOISY_RENDERER
			Tell(recursion_depth);
			for (i = 0; i < recursion_depth; i++)
				Tell("..");
			Tell(site_page_name << "\n");
			Tell(recursion_depth);
			for (i = 0; i < recursion_depth; i++)
				Tell("..");
			Dump(translation);
#endif
			mech_skeleton->GetEntry(site_page_name,	"tranx"	,&translation.x);
			mech_skeleton->GetEntry(site_page_name,	"trany"	,&translation.y);
			mech_skeleton->GetEntry(site_page_name,	"tranz"	,&translation.z);
			Vector3D* booster_scale =
				(Vector3D*)entity->GetAttributePointer("BoosterScale");
			Logical* booster_on =
				(Logical*)entity->GetAttributePointer("BoosterOn");
			this_object =	d3d_OBJECT::LoadObject ( GetDevice(), "bst.bgf" );
			if( booster_scale && booster_on && this_object)
			{
				Check(booster_scale);
				Check_Pointer(booster_on);
				Offset_Matrix.BuildIdentity();
				Offset_Matrix = translation;
				#if DEBUG_LEVEL > 0
				DPLScaleRenderable*		this_scaler =
            #endif
					/*new DPLScaleRenderable(
					entity,
					inDeathZone,
					this_object,
					intersect_mode,
					intersect_mask,
					Offset_Matrix,
					next_parent,
					booster_scale,
					booster_on);*/
			}
			else
			{
				if(!booster_scale)
					DEBUG_STREAM<<"BoosterSite couldn't find BoosterScale attribute\n" << std::flush;
				if(!booster_on)
					DEBUG_STREAM<<"BoosterSite couldn't find BoosterOn attribute\n" << std::flush;
				if(!this_object)
					DEBUG_STREAM<<"BoosterSite couldn't find booster DPL object\n" << std::flush;
			}
			Scalar*	booster_smoke_density	=
				(Scalar*)entity->GetAttributePointer("BoosterSmokeDensity");
			if( booster_smoke_density )
			{
				translation.z +=3.0;
			#if 1
				#if DEBUG_LEVEL > 0
				DPLRepeatSFXRenderable*		this_effect	=
				#endif
					new DPLRepeatSFXRenderable(
						entity,
						inDeathZone,
						translation,
						next_parent,			// offset is relative to this
						0,								// type code for the effect
						booster_smoke_density);
				Register_Object(this_effect);
			#else
				DPLPSFXRenderable*		this_effect	=
					new DPLPSFXRenderable(
						entity,								// Entity to attach the renderable to
						DPLPSFXRenderable::Dynamic,	// How/when to execute the renderable
						booster_on,							// address containing the trigger
						myPSFXDescriptons[4],			// Pointer to the psfx description in memory
						next_parent_dcs,					// DCS the effect is relative to (may be NULL)
						&translation);						// Offset (or world coordinants if DCS is NULL)
				Register_Object(this_effect);
			#endif
			}
			else
			{
				if(!booster_smoke_density)
					DEBUG_STREAM<<"BoosterSite couldn't find BoosterSmokeDensity attribute\n" << std::flush;
			}
		}
	}
//
// Unregister the namelist objects we created in this subroutine
//
	Check(joint_pages);
	Unregister_Object(joint_pages);
	delete joint_pages;
	Check(site_pages);
	Unregister_Object(site_pages);
   delete site_pages;
}


//
//#############################################################################
// This starts the process for of reading in a .skl file for a vtv.
//#############################################################################
//
HierarchicalDrawComponent*
	RPL4VideoRenderer::ReadSKLFile(
		Entity					*entity,				// The entity we are dealing with
		ResourceDescription	*model_resource,	// Pointer to the video resource
		ViewFrom					type,					// type of reference to create
		char						skeleton_type)		// TEMPORARY!!!! to handle color substitutions
{
//STUBBED: DPL RB 1/14/07
	//dpl_ZONE
	//	*buildInZone;
	bool inDeathZone;
	int
		joint_counter;
	char
		*skl_filename,
		TempFileName[256];
	NotationFile
		*object_skeleton;
	dpl_ISECT_MODE
		intersect_mode;
	uint32
		intersect_mask;
	// test code for load size reduction
	left_engine		= 0;
	right_engine	= 0;
	//
	// Currently, the name of the .skl file to read in is in the video resource
	// After reading in the .skl file we die if the page count was zero,
	// indicating an empty file.
	//
	strcpy(TempFileName,"video\\");
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// HACK to test video resource format changes
	skl_filename = (char *)model_resource->resourceAddress;
	skl_filename += sizeof(int);
	strcat(TempFileName, skl_filename);
	//strcat(TempFileName, ".skl");
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
	// !!! Temporary hack to get proper vtv skl file to load
	TempFileName[8]	=	skeleton_type;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	#ifdef NOISY_RENDERER
	Tell("RPL4VID.cpp loading .skl file "<<TempFileName<<"\n");
	#endif
	object_skeleton = new NotationFile(TempFileName);
	if(object_skeleton->PageCount() == 0)
	{
		DEBUG_STREAM << "RPL4VID.cpp couldn't load .skl file "<<TempFileName<<"\n" << std::flush;
		delete object_skeleton;
		return	NULL;
	}
	//
	// Register the notation file and check it
	//
	Register_Object(object_skeleton);
	Check(object_skeleton);

	//
	// Create the root renderable and tie it to the entity
	//
	if(type == insideEntity)
	{
		inDeathZone = true;
		//buildInZone		=	dplDeathZone;
//		intersect_mode =	dpl_isect_mode_obj;
		intersect_mask	=  NULL;
	}
	else
	{
		inDeathZone = false;
		//buildInZone		=	dplMainZone;
//		intersect_mode =	dpl_isect_mode_geometry;
		intersect_mask	=  INTERSECT_ALL;
	}

	RootRenderable	*this_root =
		new RootRenderable(
			entity,								// Entity to attach the renderable to
			RootRenderable::Dynamic,		// How/when to execute the renderable
			NULL,									// object to hang on the DCS, may be a list later <NULL>
			inDeathZone,						// DPL Zone this stuff will live in (for culling)
			intersect_mode,					// type of intersections to do on this object
			intersect_mask);					// intersection mask for the object
	Register_Object(this_root);

	if(eyeRelative && entity == GetLinkedEntity())
	{
		dpl_DCS* aDCS=this_root->GetDCS();
		Check_Pointer(aDCS);
		Check_Pointer(dplTestEyeDCS);
//		dpl_AddDCSToDCS( aDCS, dplTestEyeDCS );
	}

	//
	// Process all the interesting notation file pages
	//
	Check(object_skeleton);
	joint_counter	=	-1;
	LinearMatrix	starting_matrix(True);
	dpl_LOAD_MODE dpl_load_nocache;
	RecurseSKLFile(
		entity,
		this_root,
		object_skeleton,
		"ROOT",
		1,
		type,
		&joint_counter,
		dpl_load_nocache);
	//
	// Close the notation file
	//
	Unregister_Object(object_skeleton);
	delete object_skeleton;
	return this_root;
}

//
//#############################################################################
// This is the routine that will eventually process the script to create all
// the renderables necessary to get an object on the screen.  For the moment it
// is just executing a hardwired script.
//#############################################################################
//
void
	RPL4VideoRenderer::MakeEntityRenderables(
				Entity					*entity,				// The entity we are dealing with
				ResourceDescription	*model_resource,	// Pointer to the video resource
				ViewFrom					view_type)			// Type of reference (inside/outside...etc.)

{
#define	MAX_DOS_FILENAME 15
	HierarchicalDrawComponent
		*root;
	//
	// Make sure the callback system knows what entity is being created
	// !!!! This global will be replaced later.
	//
	Entity_Being_Created = entity;
	//
	//	Examine the class id of the entity and call the appropriate creation script.
	// If we don't recognize the entity ID here we fall through to the inhereted
	// level and let it take care of it.
	//
	switch(entity->GetClassID())
	{
		case	VTVClassID:
		{
			vtvCount++;
			Tell("-------Creating VTV #"<<vtvCount<<"-------\n");
			//
			// Call routine to setup material substitution
			//
			char geo_sub = SetupMaterialSubstitutionList(entity,view_type);
			//
			// Go on with VTV creation
			//
			root	=	ReadSKLFile(entity,model_resource,view_type,geo_sub);
			if(view_type == insideEntity)
			{
				//
				// Script for renderables needed for inside view of the vehicle
				//
				vehicleReticle =	(Reticle *)entity->GetAttributePointer("TargetReticle");
				if(vehicleReticle)
				{
					Tell("RPL4VideoRenderer::vehicleReticle should be hooked up\n");
					mReticle = new ReticleRenderable(
						entity,						// Entity to attach the renderable to
						ReticleRenderable::Dynamic,	// How/when to execute the renderable
						&vehicleReticle,			// Pointer to the reticle structure in the entity
						dplMainView);				// the view associated with our eye
					
					Register_Object(this_reticle);
				}
				else
				{
					Tell("RPL4VideoRenderer::vehicleReticle NOT hooked up\n");
				}
				StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
				if(simulation_state)
				{
					Tell("RPL4VideoRenderer::translocate effect hooked up\n");
					#if DEBUG_LEVEL > 0
					POVTranslocateRenderable* translocate =
					#endif
						new POVTranslocateRenderable(
							entity,										// Entity to attach the renderable to
							POVTranslocateRenderable::Watcher,	// How/when to execute the renderable
							true,								// DPL zone the world is in
							dplDeathZone,								// DPL zone the player's VTV and death effect are in
							root,			   					// the parent DCS we will be offsetting from
							simulation_state,							// State dial we use to control the translocation
							VTV::BurningState);						//	State that controls start/end of the effect
					Register_Object(translocate);
				}
				else
				{
					Tell("RPL4VideoRenderer::translocate effect NOT hooked up\n");
				}
			}
			else
			{
				//
				// Script for renderables needed for outside view of the vehicle
				//
				Point3D	my_offset_point(0.0, 0.0, 0.0);
				StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
				if(simulation_state)
				{
					Tell("RPL4VideoRenderer::death effect hooked up\n");
#if 1
					#if DEBUG_LEVEL > 0
					DPLSFXRenderable*	my_death_effect =
               #endif
						new DPLSFXRenderable(
							entity,					// Entity to attach the effect to
							false,			// DPL zone everything will be in
							my_offset_point,		// Point offset from the parent DCS
							root,				// Parent DCS (can be NULL for world)
							simulation_state,		// Trigger effect when this attribute changes
							VTV::BurningState,	// Trigger effect when in this state
							6,							// Type of effect to trigger
							0.1);						// Effect repeat speed.
#else
					#if DEBUG_LEVEL > 0
					DPLPSFXStateRenderable* my_death_effect =
               #endif
						new DPLPSFXStateRenderable(
							entity,									// Entity to attach the renderable to
							DPLPSFXStateRenderable::Watcher,	// How/when to execute the renderable
							simulation_state,						// Trigger effect when this state changes
							VTV::BurningState,					// The state to edge trigger on
							myPSFXDescriptons[2],				// name of file with the PFX description in it
							root_DCS,								// DCS the effect is relative to (may be NULL)
							&my_offset_point);						// Offset (or world coordinants if DCS is NULL)
#endif
					Register_Object(my_death_effect);
				}
				else
				{
					Tell("RPL4VideoRenderer::death effect NOT hooked up\n");
				}
				StateIndicator* collision_state = (StateIndicator *)entity->GetAttributePointer("CollisionState");
				if(simulation_state)
				{
					Tell("RPL4VideoRenderer::collision effects hooked up\n");
					#if DEBUG_LEVEL > 0
					DPLSFXRenderable*	initial_collision_effect =
					#endif
						new DPLSFXRenderable(
							entity,						// Entity to attach the effect to
							false,				// DPL zone everything will be in
							my_offset_point,			// Point offset from the parent DCS
							root,					// Parent DCS (can be NULL for world)
							collision_state,			// Trigger effect when this attribute changes
							VTV::InitialHitState,	// Trigger effect when in this state
							1,								// Type of effect to trigger
							0.1);							// Effect repeat speed.
					Register_Object(initial_collision_effect);
					#if DEBUG_LEVEL > 0
					DPLSFXRenderable*	scrape_collision_effect =
					#endif
						new DPLSFXRenderable(
							entity,					// Entity to attach the effect to
							false,			// DPL zone everything will be in
							my_offset_point,		// Point offset from the parent DCS
							root,				// Parent DCS (can be NULL for world)
							collision_state,		// Trigger effect when this attribute changes
							VTV::SlideState,		// Trigger effect when in this state
							1,							// Type of effect to trigger
							0.1);						// Effect repeat speed.
					Register_Object(scrape_collision_effect);
				}
				else
				{
					Tell("RPL4VideoRenderer::collision effects NOT hooked up\n");
				}
			}
			//
			// Teardown the vtv materal substitution namelists and disconnect DPL substitution handler
			//
			TearDownMaterialSubstitutionList();
#if 0
			//
			// Check for all players loaded
			//
			if((vtvCount			>=	vtvsExpected)	&&
				(GetRendererStatus()	==	LoadingRendererStatus))
			{
				Tell("Renderer Status set to running in RPL4VideoRenderer::MakeEntityRenderables\n");
				SetRendererStatusToRunning();
			}
#endif
			break;
		}
		//
		// This constructs the renderables needed for the player class
		//
		case  CrusherClassID:
		case  BlockerClassID:
		case  RunnerClassID:
		case  PlayerClassID:
		case	RPPlayerClassID:
		{
			//
			// We need to construct the translocate effect but only if this is a
			// player on another computer.  We check this by asking if this is
			// a replicant instance.
			//
			StateIndicator* player_simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
			if(entity->GetInstance() == Player::ReplicantInstance)
			{
				//
				// Setup the translocation effect for third party view
				//
				Point3D* drop_zone_position = (Point3D *)entity->GetAttributePointer("DropZoneLocation");
				if(player_simulation_state && drop_zone_position)
				{
					Tell("third party translocate effect is hooked up\n");
					#if DEBUG_LEVEL > 0
					TranslocationRenderable	*my_translocate=
					#endif
						new TranslocationRenderable(
						entity,										// Entity to attach the renderable to
						TranslocationRenderable::Watcher,	// How/when to execute the renderable
						false,								// DPL zone everything will be in
						player_simulation_state,				// Trigger effects off of this state dial
						drop_zone_position,						// Attribute that holds where the new drop will be
						RPPlayer::DropZoneAcquiredState);	// State that indicates drop zone is valid (starts effect)
					Register_Object(my_translocate);
				}
				else
				{
					Tell("third party translocate effect NOT hooked up\n");
				}
			}
			else
			{
				if(player_simulation_state)
				{
					Tell("Start/end effect hooked up\n");
					#if DEBUG_LEVEL > 0
					POVStartEndRenderable*	start_end	=
               #endif
						new POVStartEndRenderable(
							entity,										// Entity to attach the renderable to
							POVStartEndRenderable::Watcher,		// How/when to execute the renderable
							true,								// DPL zone the world is in
							dplDeathZone,								// DPL zone the player's VTV and death effect are in
							dplMainView,								// The view containing our eye
							player_simulation_state,				// State dial we use to control the translocation
							fogRed,                					// Fog color
							fogGreen,
							fogBlue,
							fogNear,										// The near fog plane
							fogFar,										// The far fog plane
							RPPlayer::MissionStartingState,		// State that signals start of mission
							RPPlayer::MissionEndingState);		// State that signals end of mission
					Register_Object(start_end);
				}
				else
				{
					Tell("Start/end effect NOT hooked up\n");
				}
			}
			break;
		}
		//
		// At the RP level we have no default method for creating objects so we call the
		// next level down (l4) and let it have a try at creating the renderables.
		//
		default:
		{
			DPLRenderer::MakeEntityRenderables(
				entity,				// The entity we are dealing with
				model_resource,	// video resource for this entity
				view_type);			// type of reference to create !!! should be enum
			break;
		}
	}
	//
	// Make sure the callback system knows what entity is being created
	// !!!! This global will be replaced later.
	//
	Entity_Being_Created = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LoadMissionImplementation  For the moment it doesn't do much, just determines
// how many players we should be expecting and sets a variable in the renderer
// about it.
//
void
	RPL4VideoRenderer::LoadMissionImplementation(Mission* mission)
{
	Tell("RPL4VideoRenderer::LoadMissionImplementation has been called\n");
	//
	// First call our inhereted method to make sure the division card is initialized right
	//
	DPLRenderer::LoadMissionImplementation(mission);
#if 0
//
// This is a !!! HACK to figure out in advance how many VTV's to expect so we can
// setup the game state properly.
//
	Mission::HostAddressIterator mission_iterator(mission);
	vtvsExpected = mission_iterator.GetSize();
	//
	// Check for all players loaded
	//
	if((vtvCount			>=	vtvsExpected)	&&
		(GetRendererStatus()	==	LoadingRendererStatus))
	{
		Tell("Renderer Status set to running in RPL4VideoRenderer::LoadMissionImplementation\n");
		SetRendererStatusToRunning();
	}
#endif
}
//
//#############################################################################
// SetupMaterialSubstitutionList   This routine sets up the material substitution
// prior to loading a vehicle.
//#############################################################################
//
char
	RPL4VideoRenderer::SetupMaterialSubstitutionList(
		Entity*	entity,
		ViewFrom	view_type) 	// The entity we will be substituting for.
{
	//STUBBED: DPL RB 1/14/07
	extern NameList
		*materialSubstitutionList;
	static const char
		* const color_parameter = "%color%",
		* const badge_parameter = "%badge%";
	static int
		color_parm_len = strlen(color_parameter),
		badge_parm_len = strlen(badge_parameter);
	NotationFile
		*veh_tbl;		// vehicle table from resource file
	NameList::Entry
		*entry;		// used to loop through namelists
	const char
		*egg_color,	// color name in egg file (from entity)
		*egg_badge,	// badge name in egg file (from entity)
		*veh_color,	// color code from vehicle table
		*veh_badge;	// badge code from vehicle table
	const char
		*source,		// tracks progress in source string
		*pc;			// jumps ahead of source pointer
	char
		*destination,	// tracks progress in destination string
		buffer[80];	// holds result while being constructed
	int
		len;			// misc. length
	char
		*vehicleTableResource;
	long
		vehicleTableResourceLength;
	char geometry_substitution = 'n';

	Verify(materialSubstitutionList == NULL);
	//
	// Get the vehicle table out of resources.
	//
	ResourceDescription *res =
		application->GetResourceFile()->FindResourceDescription(
			"vehicletable",
			ResourceDescription::VehicleTableResourceType
		);

	if (!res)
	{
		 return(geometry_substitution);
	}
	Check(res);
	res->Lock();

	vehicleTableResource = (char *)res->resourceAddress;
	vehicleTableResourceLength = (long)res->resourceSize;

	char
		*vehicle_table = new char[vehicleTableResourceLength];
	Register_Pointer(vehicle_table);
	memcpy(vehicle_table, vehicleTableResource, vehicleTableResourceLength);

	veh_tbl = new NotationFile;
	Register_Object(veh_tbl);
	veh_tbl->ReadText(vehicle_table, vehicleTableResourceLength);

	Unregister_Pointer(vehicle_table);
	delete vehicle_table;

	res->Unlock();

	//
	// Fetch the color and badge pointers out of the entity and into our local stuff
	//
	egg_color	=	((VTV *)entity)->vehicleColor;
	egg_badge	=	((VTV *)entity)->vehicleBadge;
	Check_Pointer(egg_color);
	Check_Pointer(egg_badge);
	if (!veh_tbl->GetEntry("color", egg_color, &veh_color))
	{
		veh_color = NULL;
	}

	if (!veh_tbl->GetEntry("badge", egg_badge, &veh_badge))
	{
		veh_badge = NULL;
	}
	else
	{
		if(view_type == insideEntity)
		{
			geometry_substitution = *(veh_badge + strlen(veh_badge) - 2);		//ourself
		}
		else
		{
			geometry_substitution = *(veh_badge + strlen(veh_badge) - 1);		//someone else
		}
	}
	//--------------------------------------------------
	// get generic substitution list from vehicle table
	//--------------------------------------------------
	materialSubstitutionList = veh_tbl->MakeEntryList("substitute");
	Register_Object(materialSubstitutionList);
	//-------------------------------------------------------------
	// fill in % place holders with specifics for vtv being loaded
	//-------------------------------------------------------------
	entry = materialSubstitutionList->GetFirstEntry();
	while (entry)
	{
		source = entry->GetChar();
		*(destination = buffer) = '\0';
		while ((pc = strchr(source, '%')) != NULL)
		{
			if ((len = pc-source) != 0)
			{
				strncpy(destination, source, len);
				source = pc;
				destination += len;
			}
			if (!strncmp(pc, color_parameter, color_parm_len))
			{
				if (veh_color)
				{
					Str_Copy(
						destination,
						veh_color,
						sizeof(buffer)-(destination-buffer)
					);
					destination += strlen(veh_color);
				}
				source += color_parm_len;
			}
			else if (!strncmp(pc, badge_parameter, badge_parm_len))
			{
				if (veh_badge)
				{
					const char
						*qc = veh_badge;

					while (isgraph(*qc))
					{
						++qc;
					}
					if ((len = qc - veh_badge) != 0)
					{
						strncpy(destination, veh_badge, len);
						destination += len;
					}
				}
				source += badge_parm_len;
			}
			else
			{
				//-------------------------------------
				// % was not from recognized parameter
				//-------------------------------------
				*destination++ = *source++;
			}
		}
		if (*source)
		{
			Str_Copy(
				destination,
				source,
				sizeof(buffer)-(destination-buffer)
			);
		}
		else
		{
			*destination = '\0';
		}

		//---------------------------------------
		// make copy of result and store in list
		//---------------------------------------
		destination = new char[strlen(buffer)+1];
		Register_Pointer(destination);
		strcpy(destination, buffer);

		entry->dataReference = (void *)destination;

		entry = entry->GetNextEntry();
	}
	Unregister_Object(veh_tbl);
	delete veh_tbl;
	//dpl_SetMaterialNameCallback(substituteMaterial);
	return geometry_substitution;
}
//
//#############################################################################
// TearDownMaterialSubstitutionList   This routine destroys and disconnects the
// material substitution stuff after a vehicle has been loaded.
//#############################################################################
//
void
	RPL4VideoRenderer::TearDownMaterialSubstitutionList()
{
	//STUBBED: DPL RB 1/14/07
	NameList::Entry
		*entry;
	char
		*p;

	extern NameList
		*materialSubstitutionList;

	if (materialSubstitutionList)
	{
		entry = materialSubstitutionList->GetFirstEntry();
		while (entry)
		{
			if ((p = entry->GetChar()) != NULL)
			{
				Unregister_Pointer(p);
				delete p;
				entry->dataReference = NULL;
			}
			entry = entry->GetNextEntry();
		}
		Unregister_Object(materialSubstitutionList);
		delete materialSubstitutionList;
		materialSubstitutionList = NULL;
	}
	//dpl_SetMaterialNameCallback(NULL);
}
//===========================================================================//
