#include "AdeptHeaders.hpp"

#include "EntityManager.hpp"
#include "RendererManager.hpp"
#include "Application.hpp"
#include "Tool.hpp"
#include <ElementRenderer\GroupElement.hpp>
#include <ElementRenderer\StateChange.hpp>

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Entity__CreateMessage::ConstructCreateMessage(Script *script)
{
	Check_Object(script);

	//
	//--------------
	// Set up stream
	//--------------
	//
	MemoryStream *message_stream = script->messageStream;
	Check_Object(message_stream);
	message_stream->AllocateBytes(sizeof(Entity__CreateMessage));
	Replicator__CreateMessage::ConstructCreateMessage(script);
	Entity__CreateMessage *message =
		Cast_Pointer(
			Entity__CreateMessage*,
			message_stream->GetPointer()
		);
	message->messageLength = sizeof(*message);

	//
	//---------------------------------------------------------------
	// Point at the notation file and make other files relative to it
	//---------------------------------------------------------------
	//
	Page *page = script->instancePage;
	Check_Object(page);
	Check_Object(Tool::Instance);
	Tool::Instance->PushFilePath(page->GetNotationFile());

	//
	//---------------
	// Read the flags
	//---------------
	//
	bool flag = false;
	page->GetEntry("TileBound", &flag);
	if (flag)
		message->replicatorFlags |= Entity::TileBoundFlag;

	//
	//-------------
	//Get Alignment
	//-------------
	//
	const char *alignment_text;
	int alignment_value = Entity::DefaultAlignment;
	if(page->GetEntry("Alignment", &alignment_text))
		alignment_value = Entity::AlignmentTextToAscii(alignment_text);

	message->alignment = alignment_value;

	//
	//----------------------------------------------------
	// Find out the GameModel we need to build and open it
	//----------------------------------------------------
	//
	Entity::ClassData *class_data;
	{
		const char* model_name;
		page->GetEntry("Model", &model_name, true);
		Resource resource;
		class_data = Tool::Instance->ConstructDataList(&resource, model_name);
		Check_Object(&resource);
		Verify(resource.DoesResourceExist());
		message->dataListID = resource.GetResourceID();
	}

	//
	//-------------------------------------------------------------------------
	// If this entity is a collider, make sure that it has a solid volume entry
	// in the game model
	//-------------------------------------------------------------------------
	//
	if ((message->replicatorFlags&Entity::AlwaysCollidesMask) != Entity::NeverCollidesMask)
	{
		Resource model_res;
		Entity::GetGameModelResourceFromDataListID(
			&model_res,
			message->dataListID
		);
		Verify(model_res.DoesResourceExist());
		Entity::GameModel *game_model =
			Cast_Pointer(Entity::GameModel*, model_res.GetPointer());
		Check_Object(game_model);
		if (game_model->obbStreamResourceID == ResourceID::Null)
			message->replicatorFlags &= ~Entity::AlwaysCollidesMask;
	}

	//
	//-------------------------------
	// Deal with the initial position
	//-------------------------------
	//
	Point3D translation = Point3D::Identity;
	page->GetEntry("Translation", &translation);
	YawPitchRoll rotation = YawPitchRoll::Identity;
	page->GetEntry("Rotation", &rotation);
	message->localToParent.BuildTranslation(translation);
	message->localToParent.BuildRotation(rotation);

	//
	//-------------------------
	// Save the execution state
	//-------------------------
	//
	Entity::ExecutionStateEngine::FactoryRequest::Script state_script;
	Check_Object(class_data);
	Verify(class_data->IsDerivedFrom(Entity::DefaultData));
	state_script.engineClass = class_data->executionStateClass;
	Check_Object(state_script.engineClass);
	state_script.instancePage = page;
	state_script.stateEngineName = "ExecutionState";
	message->executionState.ConstructFactoryRequest(&state_script);
	Tool::Instance->PopFilePath();

	//
	//----------------------------------
	// Set the initial age of the entity
	//----------------------------------
	//
	message->initialAge = 0.0f;
	page->GetEntry("Age", &message->initialAge);

	//
	//-------------------------
	//Save the instance name id
	//-------------------------
	//

	message->nameID = NameTable::NullObjectID;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Entity::SaveInstanceText(Page *page)
{
	Check_Object(this);
	Check_Object(page);

	//
	//--------------------
	// Save the Model Name
	//--------------------
	//
	Check_Object(&gameModelResource);
	page->SetEntry("Model", (const char *)GetModelName());
	//
	//-------------------------
	// Save the Execution State
	//-------------------------
	//
	if(executionState)
	{
		int execution_state = executionState->GetState();
		MString execution_state_text;
		switch(execution_state)
		{
		case ExecutionStateEngine::NeverExecuteState:
			{
				execution_state_text = "NeverExecuteState";
				break;
			}
		case ExecutionStateEngine::ExecuteOnceState:
			{
				execution_state_text = "ExecuteOnceState";
				break;
			}
		case ExecutionStateEngine::AlwaysExecuteState:
			{
				execution_state_text = "AlwaysExecuteState";
				break;
			}
		default:
			{
#if defined(_ARMOR)
				if(*instanceName)
				{
					PAUSE(("Execution State for %s has not been defined", (const char *)instanceName));
				}
#endif
				
				execution_state_text = "NeverExecuteState";
				break;
			}
		}
		page->SetEntry("ExecutionState", execution_state_text);
	}
	else
	{
		page->SetEntry("ExecutionState", "NeverExecuteState");
	
	}
	//
	//--------------------------
	// Save all the Entity Flags
	//--------------------------
	//
	page->SetEntry("TileBound", IsTileBound());
			
	//
	//---------------------------------------------------
	// Save the Translation and Rotation in String format
	//---------------------------------------------------
	//
	Point3D local_translation(GetLocalToParent());
	page->SetEntry("Translation", local_translation);
	YawPitchRoll rotation_value(GetLocalToParent());
	page->SetEntry("Rotation", rotation_value);

	const char *alignment_text;
	alignment_text = Entity::AlignmentAsciiToText(alignment);
	page->SetEntry("Alignment", alignment_text);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Entity__GameModel::ConstructGameModel(Script *script)
{
	Check_Object(script);

	//
	//--------------
	// Set up stream
	//--------------
	//
	MemoryStream *model_stream = script->modelStream;
	Check_Object(model_stream);
	model_stream->AllocateBytes(sizeof(Entity__GameModel));
	Entity__GameModel *model =
		Cast_Pointer(Entity__GameModel*, model_stream->GetPointer());

	//
	//--------------------
	// Set up the class ID
	//--------------------
	//
	Entity::ClassData *class_data = script->modelClassData;
	Check_Object(class_data);
	model->classID = class_data->GetClassID();
	NotationFile *model_file = script->modelFile;
	Check_Object(model_file);
	Page *page = model_file->GetPage("GameData");
	Check_Object(page);
	
	//
	//-------------------------------------------
	// Read the element in from the notation file
	//-------------------------------------------
	//
	gos_PushCurrentHeap(ElementRenderer::GroupElement::s_Heap);
	ElementRenderer::Element *element = new ElementRenderer::GroupElement();
	Check_Object(element);
	unsigned
		state=element->GetElementState(),
		delta;
	OBB
		bounds;
	ElementRenderer::Element::ReadStateFromPage(
		page,
		*MString::s_Empty,
		&state,
		&delta,
		&bounds
	);
	ElementRenderer::StateChange *states =
		new ElementRenderer::StateChange(page, *MString::s_Empty);
	Check_Object(states);

	//
	//-------------------------------
	// Write the data out to a stream
	//-------------------------------
	//
	DynamicMemoryStream element_stream;
	state &= ~ElementRenderer::Element::CullMask;
	state |=
		ElementRenderer::Element::RootMode
		 | ElementRenderer::Element::MatrixDirtyFlag;
	element_stream << state << bounds;
	states->Save(&element_stream);
	Check_Object(states);
	delete states;
	gos_PopCurrentHeap();

	//
	//-----------------------------------------
	// Save the element stream in the resources
	//-----------------------------------------
	//
	MString element_name = model_file->GetFileName();
	element_name += "{Element}";
	Resource element_resource(element_name);
	element_resource.Save(&element_stream, Resource::ParentFileDependencies);
	Verify(element_resource.DoesResourceExist());
	model->elementResourceID = element_resource.GetResourceID();

	//
	//-----------------------------------------
	// Clear out the collision OBB resource IDs
	//-----------------------------------------
	//
	model->obbStreamResourceID = ResourceID::Null;
	if (class_data->obbFactory != NULL)
		(*class_data->obbFactory)(script);
	Check_Object(element);
	delete element;

	//
	//-------------------------------------------
	// Spin Through all the game model attributes
	//-------------------------------------------
	//
	ModelAttributeEntry *attribute_entry;
	TableIteratorOf<ModelAttributeEntry *, Entity__GameModel::AttributeID> iterator(
		&class_data->gameModelAttributeTable.attributesByID);
	int num_attributes = iterator.GetSize();
	int i;
	for(i=Entity__GameModel::AnyAttributeID + 1;i<num_attributes;i++)
	{
		attribute_entry = 
			class_data->gameModelAttributeTable.GetAttributeEntry(i);
		Check_Object(attribute_entry);
		const char *data = "";
		page->GetEntry(attribute_entry->attributeName, &data);
		char *error_message;
		error_message = new char[128];
		strcpy(error_message, "");
		Check_Pointer(error_message);
		if(!(*class_data->modelVerifier)(model, attribute_entry, data, &error_message, 128))
		{
			STOP(("%s Game Model Error : %s", model_file->GetFileName(), error_message));
		}
		Check_Pointer(error_message);
		delete [] error_message;
	}

	//
	//------------------------
	// Set the collision flags
	//------------------------
	//
	model->defaultFlags = 0;
	if(model->collider)
		model->defaultFlags |= Entity::ColliderFlag;
	if(model->canBeWalkedOn)
		model->defaultFlags |= Entity::CanBeWalkedOnFlag|Entity::CanBeShotFlag;
	if(model->canBeShot)
		model->defaultFlags |= Entity::CanBeShotFlag;
	if(model->waterSurface)
		model->defaultFlags |= Entity::WaterSurfaceFlag;
	if(model->OBBCollides)
		model->defaultFlags |= Entity::OBBCollidesFlag;
	if (model->defaultFlags == Entity::OBBCollidesFlag)
		model->defaultFlags = 0;

	const char *walk_thru_string;
	if(page->GetEntry("WalkThruFlag", &walk_thru_string))
	{
		model->defaultFlags |= WalkThruTextToAscii(walk_thru_string);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Entity__GameModel::ConstructOBBStream(Script *script)
{
	Check_Object(script);

	//
	//--------------
	// Set up stream
	//--------------
	//
	MemoryStream *model_stream = script->modelStream;
	Check_Object(model_stream);
	Entity__GameModel *model =
		Cast_Pointer(Entity__GameModel*, model_stream->GetPointer());

	//
	//------------------------------
	// See if there is an OBB stream
	//------------------------------
	//
	NotationFile *model_file = script->modelFile;
	Check_Object(model_file);
	Page *page = model_file->GetPage("GameData");
	Check_Object(page);
	const char* obb_stream_name;
	if (!page->GetEntry("SolidOBB", &obb_stream_name))
		return;

	//
	//--------------------------------------------------------
	// There is, so now we have to stuff it into the resources
	//--------------------------------------------------------
	//
	Check_Pointer(obb_stream_name);
	FileStream obb_stream(obb_stream_name);
	const char* file_name = obb_stream.GetFileName();
	Resource res(file_name);
	if (!res.DoesResourceExist() || !res.IsResourceUpToDate())
	{
		FileDependencies obb_dependencies;
		obb_dependencies.AddDependency(&obb_stream);
		res.Save(&obb_stream, &obb_dependencies);
		if (!res.IsRegistered())
			Resource::ParentFileDependencies->AddDependencies(&obb_dependencies);
	}
	else if (!res.IsRegistered())
		res.AddFileDependenciesTo(Resource::ParentFileDependencies);
	model->obbStreamResourceID = res.GetResourceID();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	Entity__GameModel::ReadAndVerify(
		Entity__GameModel *model, 
		ModelAttributeEntry *attribute_entry, 
		const char *data,
		char **error,
		int error_buffer
	)
{
	Check_Object(attribute_entry);
	bool result = false;
	bool valid_data = (*data != '\0');

	//
	//----------------------------------------
	//This is the Genric Type read in Section.
	//----------------------------------------
	//

	if(valid_data)
	{
		switch(attribute_entry->attributeType)
		{
		case ScalarClassID:
			{
				Scalar value = AtoF(data);
				attribute_entry->SetValue(model, &value);
				result = true;
				break;
			}
		case Vector3DClassID:
			{
				Vector3D value;
				int entries = sscanf(
					data,
					"%f %f %f",
					&value.x,
					&value.y,
					&value.z
				);
				if(entries != 3)
				{
					_snprintf(
						*error,
						error_buffer,
						"{[GameData]%s=%s}Bad Vector Value",
						(char *)attribute_entry->attributeName,
						data
					);
					return false;
				}
				attribute_entry->SetValue(model, &value);
				result = true;
				break;
			}
		case IntClassID:
			{
				int value = atoi(data);
				attribute_entry->SetValue(model, &value);
				result = true;
				break;
			}
		case BoolClassID:
			{
				bool value = (!_stricmp(data, "true") || !_stricmp(data, "yes") || atoi(data) != 0);
				attribute_entry->SetValue(model, &value);
				result = true;
				break;
			}
		case RadianClassID:
			{
				Radian value = AtoF(data);
				value = value * Stuff::Radians_Per_Degree;
				attribute_entry->SetValue(model, &value);
				result = true;
				break;
			}
		case Point3DClassID:
			{
				Point3D value;
				int entries;
				entries = sscanf(
					data,
					"%f %f %f",
					&value.x,
					&value.y,
					&value.z
				);
				if(entries != 3)
				{
					_snprintf(
						*error,
						error_buffer,
						"{[GameData]%s=%s}Bad Point Value",
						(char *)attribute_entry->attributeName,
						data
					);
					return false;
				}
				attribute_entry->SetValue(model, &value);
				result = true;
				break;
			}	
		case RGBAColorClassID:
			{
				RGBAColor value;
				int entries;
				entries = sscanf(
					data,
					"%f %f %f %f",
					&value.red,
					&value.green,
					&value.blue,
					&value.alpha
				);
				if (entries == 3)
				{
					value.alpha = 1.0f;
				}
				if (entries < 3)
				{
					_snprintf(
						*error,
						error_buffer,
						"{[GameData]%s=%s}Bad RGBAColor Value",
						(char *)attribute_entry->attributeName,
						data
					);
					return false;
				}
				attribute_entry->SetValue(model, &value);
				result = true;
				break;
			}	
		case UnitQuaternionClassID:
			{
				//Read in a quaternion as a YawpitchRoll angle
				UnitQuaternion value;
				YawPitchRoll yaw_pitch_roll;
				int entries;
				entries = sscanf(
					data,
					"%f %f %f",
					&yaw_pitch_roll.yaw.angle,
					&yaw_pitch_roll.pitch.angle,
					&yaw_pitch_roll.roll.angle
				);
				if(entries != 3)
				{
					_snprintf(
						*error,
						error_buffer,
						"{[GameData]%s=%s}Bad Angle Value",
						(char *)attribute_entry->attributeName,
						data
					);
					return false;
				}
				yaw_pitch_roll.yaw *= Radians_Per_Degree;
				yaw_pitch_roll.pitch *= Radians_Per_Degree;
				yaw_pitch_roll.roll *= Radians_Per_Degree;
				value = yaw_pitch_roll;
				value.Normalize();
				attribute_entry->SetValue(model, &value);
				result = true;
				break;
			}
		case CharClassID:
			{
				char *value;
				value = new char[MaxStringLength];
				Check_Pointer(value);
				Str_Copy(value, data, MaxStringLength);
				attribute_entry->SetValue(model, value);
				result = true;
				Check_Pointer(value);
				delete value;
				break;
			}
		case ResourceIDClassID:
			{
				const char* resource_name = (const char *)data;
				const char* resource_extension = strrchr(resource_name, '.');

				// resource_extension == NULL is a valid value.

				if(resource_extension && !_stricmp(resource_extension, ".data"))
				{
					//
					//------------------------------------------------
					//If we are a .data file then Create us as a model
					//------------------------------------------------
					//
					Resource model_resource;
					Tool::Instance->ConstructDataList(&model_resource, resource_name);
					Check_Object(&model_resource);
					Verify(model_resource.DoesResourceExist());
					attribute_entry->SetValue(model, (void *)&model_resource.GetResourceID());
					result = true;
				}
				else if(resource_extension && !_stricmp(resource_extension, ".instance"))
				{
					NotationFile instance_file(resource_name);
					Resource instance_resource;
					ReplicatorID base_id = ReplicatorID::Null;
					Check_Object(Tool::Instance);
					Tool::Instance->ConstructCreateMessage(
						&instance_resource,
						&instance_file,
						&base_id
					);
					Verify(instance_resource.DoesResourceExist());
					attribute_entry->SetValue(model, (void *)&instance_resource.GetResourceID());
					result = true;
				}
				else
				{
					ResourceID default_id = ResourceID::Null;
					attribute_entry->SetValue(model, (void *)&default_id);
					result = true;
				}
				break;
			}
		}
	}
	switch(attribute_entry->attributeID)
	{
	case ColliderAttributeID:
		{
			if(!valid_data)
			{
				bool value = false;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
		}
		break;
	case CanBeShotAttributeID:
		{
			if(!valid_data)
			{
				bool value = false;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
		}
		break;
	case CanBeWalkedOnAttributeID:
		{
			if(!valid_data)
			{
				bool value = false;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
		}
		break;
	case WaterSurfaceAttributeID:
		{
			if(!valid_data)
			{
				bool value = false;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
		}
		break;
	case OBBCollidesAttributeID:
		{
			if(!valid_data)
			{
				bool value = true;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
		}
		break;
	}

	return result;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Entity__GameModel::WriteToText(
		Entity__GameModel *model,
		ModelAttributeEntry *attribute_entry,
		char **text_string
	)
{
	Check_Object(attribute_entry);
	Check_Pointer(model);

	switch(attribute_entry->attributeType)
	{
	case ScalarClassID:
		{
			Scalar value;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			sprintf(
				*text_string,
				"%.2f",
				value
			);
			break;
		}
	case RadianClassID:
		{
			Radian value;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			value = value * Stuff::Degrees_Per_Radian;
			sprintf(
				*text_string,
				"%.2f",
				value.angle
			);
			break;
		}
	case IntClassID:
		{
			int value;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			sprintf(
				*text_string,
				"%d",
				value
			);
			break;
		}
	case Vector3DClassID:
		{
			Vector3D value;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			sprintf(
				*text_string,
				"%.2f %.2f %.2f",
				value.x,
				value.y,
				value.z
			);
			break;
		}
	case BoolClassID:
		{
			bool value;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			if(value)
			{
				strcpy(*text_string, "yes");
			}
			else
			{
				strcpy(*text_string, "no");
			}
			break;
		}
	case Point3DClassID:
		{
			Point3D value;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			sprintf(
				*text_string,
				"%.2f %.2f %.2f",
				value.x,
				value.y,
				value.z
			);
			break;
		}
	case RGBAColorClassID:
		{
			RGBAColor value;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			sprintf(
				*text_string,
				"%.2f %.2f %.2f %.2f",
				value.red,
				value.green,
				value.blue,
				value.alpha
			);
			break;
		}
	case UnitQuaternionClassID:
		{
			UnitQuaternion value;
			YawPitchRoll yaw_pitch_roll;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			yaw_pitch_roll = value;
			sprintf(
				*text_string,
				"%.2f %.2f %.2f",
				yaw_pitch_roll.yaw,
				yaw_pitch_roll.pitch,
				yaw_pitch_roll.roll
			);
			break;
		}
		case ResourceIDClassID:
		{
			ResourceID value;
			attribute_entry->GetValue((Entity__GameModel *)model, &value);
			char path[256],*p;
			if(value != ResourceID::Null)
			{
				Resource resource(value);
				strcpy(path,resource.GetName());

				p = strrchr(path,'{');
				if (p) p = 0;
				p = strrchr(path,'.');
				if (!stricmp(p,".data"))
				{
					sprintf(*text_string,"Content\\%s",path);
				}

			}
			else
			{				
				strcpy(path, "NULL");
				sprintf(*text_string,"%s",path);
			}
	
			break;
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Entity__GameModel::SaveGameModel(
		Entity__GameModel *model,
		Stuff::NotationFile *data_file
	)
{
	Check_Object(model);
	Check_Object(data_file);

	//
	//---------------------------------------------------------------
	//First we need to spin through our attributes and write them out
	//---------------------------------------------------------------
	//
	ModelAttributeEntry *attribute_entry;
	Entity__ClassData *class_data;
	class_data = (Entity__ClassData *)Entity::FindClassData(model->classID);
	TableIteratorOf<ModelAttributeEntry *, Entity__GameModel::AttributeID> iterator(
		&class_data->gameModelAttributeTable.attributesByID);
	int num_attributes = iterator.GetSize();
	int i;


	Page *page = data_file->SetPage("GameData");
	Check_Object(page);
	
	page->SetEntry("Class",class_data->GetClassName());

	//This is temp for right now...eventually we will need a text write function in element
	if(model->elementResourceID != ResourceID::Null)
	{
		Resource element_resource(model->elementResourceID);
		Verify(element_resource.DoesResourceExist());
	
		//We need to yank out the cull mode from this stream
		unsigned element_state;
		element_resource >> element_state;

		if (element_state & ElementRenderer::Element::BoundsLockedFlag)
		{
			page->SetEntry("Cull", "NeverCull");
		}
	}

	for(i=Entity__GameModel::AnyAttributeID + 1;i<num_attributes;i++)
	{
		attribute_entry = 
			class_data->gameModelAttributeTable.GetAttributeEntry(i);

		Check_Object(attribute_entry);

		char* data = new char [Entity__GameModel::MaxStringLength];
		Register_Pointer(data);

		class_data->modelWriteToText(model, attribute_entry, &data);

		page->SetEntry(attribute_entry->attributeName,data);

		Unregister_Pointer(data);
		delete [] data;
	}
	
	int flags = model->defaultFlags;
	if(flags & Entity::HeavyCanWalkThruType)
		page->SetEntry("WalkThruFlag", "HeavyCanWalkThru");
	else if(flags & Entity::MediumCanWalkThruType)
		page->SetEntry("WalkThruFlag", "MediumCanWalkThru");
	else if(flags & Entity::AnythingCanWalkThruType)
		page->SetEntry("WalkThruFlag", "AnythingCanWalkThru");
	//
	//--------------------------------------------------------
	//Now we need to save out the specific non attribute stuff
	//--------------------------------------------------------
	//
#if 0
	if(obbStreamResourceID != ResourceID::Null)
	{
		Resource obb_resource(obbStreamResourceID);
		Verify(obb_resource.DoesResourceExist());
		data_file->SetEntry("GameData", 
#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
const char *
	Entity::AlignmentAsciiToText(int alignment)
{
	switch(alignment)
	{
	case Player:
		return "Player";
	case Enemy:
		return "Enemy";
	case Team1:
		return "Team1";
	case Team2:
		return "Team2";
	case Team3:
		return "Team3";
	case Team4:
		return "Team4";
	}
	return "Default";
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	Entity::AlignmentTextToAscii(const char *alignment)
{
	if(!_stricmp(alignment, "Player"))
		return Player;
	else if(!_stricmp(alignment, "Enemy"))
		return Enemy;
	else if(!_stricmp(alignment, "Team1"))
		return Team1;
	else if(!_stricmp(alignment, "Team2"))
		return Team2;
	else if(!_stricmp(alignment, "Team3"))
		return Team3;
	else if(!_stricmp(alignment, "Team4"))
		return Team4;

	return DefaultAlignment;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Entity__GameModel::GetEffectResourceID(ResourceID *return_id, const ResourceID& effect_stream, BYTE index)
{
	ResourceID *effect_array;
	Resource effect_resource(effect_stream);
	Verify(effect_resource.DoesResourceExist());

	BYTE material_count;
	effect_resource >> material_count;
	if (material_count <= index)
	{
		*return_id = ResourceID::Null;
		return;
	}
	effect_array = Cast_Pointer(ResourceID *, effect_resource.GetPointer());
	*return_id = effect_array[index];

	#if defined(_ARMOR)
		if(*return_id != ResourceID::Null)
		{
			Resource verify_resource(*return_id);
			Verify(verify_resource.DoesResourceExist());
		}
	#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	Entity__GameModel::WalkThruTextToAscii(const char *string)
{
	if(!_stricmp(string, "NothingCanWalkThru"))
		return Entity::NothingCanWalkThruType;
	else if(!_stricmp(string, "HeavyCanWalkThru"))
		return Entity::HeavyCanWalkThruType;
	else if(!_stricmp(string, "MediumCanWalkThru"))
		return Entity::MediumCanWalkThruType;
	else if(!_stricmp(string, "AnythingCanWalkThru"))
		return Entity::AnythingCanWalkThruType;
	else
		STOP(("Walk Thru Type: %s is not valid", string));
	return 0;
}

