//===========================================================================//
// File:	Mech_Tool.cpp																	  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 09/09/98  JSE  Inital base class based off of Shadowrun/Adept
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "MW4Headers.hpp"

#include "Mech.hpp"
#include "MWTool.hpp"
#include "MaterialEffectHolder.hpp"








#define ScalarGreaterThanZero(attribname, modelname) \
		case attribname##AttributeID: \
		{ \
			if(!valid_data) \
			{ \
				Scalar value = 0.0f; \
				attribute_entry->SetValue(model, &value); \
				result = true; \
			} \
			if(model->##modelname < 0.0f ) \
			{ \
				_snprintf( \
					*error, \
					error_buffer, \
					"{[GameData]"#attribname"=%f}: value must be > 0!", \
					model->##modelname \
				);\
				result = false; \
			} \
			break; \
		}


#define Point3DGreaterThanZero(attribname, modelname) \
		case attribname##AttributeID: \
		{ \
			if(!valid_data) \
			{ \
				Point3D value = Point3D(0.0f,0.0f,0.0f); \
				attribute_entry->SetValue(model, &value); \
				result = true; \
			} \
			if(model->##modelname.x < 0.0f || model->##modelname.y < 0.0f || model->##modelname.z < 0.0f) \
			{ \
				_snprintf( \
					*error, \
					error_buffer, \
					"{[GameData]"#attribname"=%f,%f,%f}: value must be > 0!", \
					model->##modelname.x, \
					model->##modelname.y, \
					model->##modelname.z \
				);\
				result = false; \
			} \
			break; \
		}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Mech__CreateMessage::ConstructCreateMessage(Script *script)
{
	Check_Object(script);
	#if defined(_ARMOR)
		int stack_level = Tool::Instance->GetStackLevel();
	#endif

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

	Page *instance_page = script->instancePage;
	Check_Object(instance_page);
	NotationFile *instance_file = instance_page->GetNotationFile();
	Check_Object(instance_file);
	Check_Object(Tool::Instance);
	Tool::Instance->PushFilePath(instance_file);
	Check_Object(Resource::ParentFileDependencies);

	message->currentHeat = 0.0f;
	instance_page->GetEntry("CurrentHeat", &message->currentHeat);
	message->currentCoolant = 60.0f;
	instance_page->GetEntry("CurrentCoolant", &message->currentCoolant);
	message->maxCoolant = 60.0f;
	instance_page->GetEntry("MaxCoolant", &message->maxCoolant);

	message->m_doesHaveLightAmp = true;
	instance_page->GetEntry("DoesHaveLightAmp", &message->m_doesHaveLightAmp);

	message->m_armorBar = 0;
	instance_page->GetEntry("ArmorRating", &message->m_armorBar);
	message->m_powerBar = 0;
	instance_page->GetEntry("PowerRating", &message->m_powerBar);
	message->m_heatBar = 0;
	instance_page->GetEntry("HeatRating", &message->m_heatBar);
	message->m_speedBar = 0;
	instance_page->GetEntry("SpeedRating", &message->m_speedBar);

	Resource model_res;
	Entity::GetGameModelResourceFromDataListID(
		&model_res,
		message->dataListID
	);
	Verify(model_res.DoesResourceExist());
	Mech::GameModel *model =
		Cast_Pointer(Mech::GameModel*, model_res.GetPointer());
	Check_Object(model);

	message->m_mechID = model->mechID;

	Tool::Instance->PopFilePath();
	Verify(stack_level == Tool::Instance->GetStackLevel());
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Mech__GameModel::ConstructGameModel(Script *script)
{
	Check_Object(script);
	#if defined(_ARMOR)
		int stack_level = Tool::Instance->GetStackLevel();
	#endif

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

	//
	//------------------------------
	// Set up the model file pointer
	//------------------------------
	//
	NotationFile *model_file = script->modelFile;
	Check_Object(model_file);
	model->footFallEffectsTable = ResourceID::Null;
	Page *page = model_file->GetPage("GameData");
	Check_Object(page);
	NotationFile effects_file;
	if (page->GetEntry("FootEffectsFile", &effects_file))
	{
		FileDependencies *old_deps = Resource::ParentFileDependencies;
		FileDependencies effect_deps(*effects_file.GetFileDependencies());
		Resource::ParentFileDependencies = &effect_deps;
		model->footFallEffectsTable = CreateEffectTableResource(&effects_file, MaterialCount);
		Resource::ParentFileDependencies = old_deps;
		old_deps->AddDependencies(&effect_deps);
	}

	model->footStepsResource = ResourceID::Null;
	MString foot_resource_name = model_file->GetFileName();
	foot_resource_name += "{FootSteps}";
	Resource foot_step_resource(foot_resource_name);
	if(foot_step_resource.DoesResourceExist() && foot_step_resource.IsResourceUpToDate())
	{
		model->footStepsResource = foot_step_resource.GetResourceID();
	}
	else
	{
		DynamicMemoryStream foot_step_stream;
		const char *data;
		if(page->GetEntry("DefaultFootStepTexture", &data))
		{
			MString entry_string;
			entry_string = data;
		
			int material_num = -1;
			foot_step_stream << material_num;
			foot_step_stream << entry_string;
			bool is_default = true;
			foot_step_stream << is_default;

		}

		ChainOf<Note*> *foot_steps = page->MakeNoteChain("FootStepTexture");
		Check_Object(foot_steps);
		Page::NoteIterator foot_steps_list(foot_steps);
		Note *foot_step_entry;
		while ((foot_step_entry = foot_steps_list.ReadAndNext()) != NULL)
		{
			Check_Object(foot_step_entry);
			const char *foot_steps_data;
			foot_step_entry->GetEntry(&foot_steps_data);
			Check_Pointer(foot_steps_data);

			MString entry_string;
			MString texture_file_name;

			entry_string = foot_steps_data;
			texture_file_name = entry_string.GetNthToken(0, ",");

			MString material_name;
			material_name = entry_string.GetNthToken(1, ",");
			int material_num = MaterialTypeTextToAscii(material_name);
			
			foot_step_stream << material_num;
			foot_step_stream << texture_file_name;
			bool is_default = false;
			foot_step_stream << is_default;
		}
		if(foot_step_stream.GetBytesUsed() > 0)
		{
			foot_step_resource.Save(&foot_step_stream, Resource::ParentFileDependencies);
			model->footStepsResource = foot_step_resource.GetResourceID();
		}

		delete foot_steps;
	}
	
	model->m_craterID = -1;
	const char *crater_string;
	if(page->GetEntry("CraterName", &crater_string))
	{
		MString crater_mstring = crater_string;
		model->m_craterID = crater_mstring.GetHashValue();
	}

	model->heatManagerResource = ResourceID::Null;
	NotationFile heat_file;
	if(page->GetEntry("HeatManager", &heat_file))
	{
		const char *heat_file_name = heat_file.GetFileName();
		Check_Pointer(heat_file_name);

		Resource heat_resource(heat_file_name);
		if (heat_resource.DoesResourceExist() &&
				heat_resource.IsResourceUpToDate())
		{
			model->heatManagerResource = heat_resource.GetResourceID();
			if (!heat_resource.IsRegistered())
				heat_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
		}
		else
		{
			//
			//---------------------------------------
			// For each page, an entity will be built
			//---------------------------------------
			//
			FileDependencies heat_deps(*heat_file.GetFileDependencies());
			FileDependencies *parent = Resource::ParentFileDependencies;
			Resource::ParentFileDependencies = &heat_deps;
			Tool::Instance->PushFilePath(&heat_file);
			DynamicMemoryStream heat_stream;
			Page *page;
			page = heat_file.GetPage("HeatManager");
			Scalar movement_heat = 1.0f;
			int double_movement_heat = 50;
			Scalar double_movement_heat_percentage = 0.5f;
			page->GetEntry("MovementHeat", &movement_heat);
			Min_Clamp(movement_heat, 0.0f);
			heat_stream << movement_heat;

			page->GetEntry("DoubleMovementHeatAt", &double_movement_heat);
			Clamp(double_movement_heat, 0, 100);
			double_movement_heat_percentage = double_movement_heat / 100.0f;
			heat_stream << double_movement_heat_percentage;

			page->GetEntry("HeatEffectsSpeedAt", &double_movement_heat);
			Clamp(double_movement_heat, 0, 100);
			double_movement_heat_percentage = double_movement_heat / 100.0f;
			heat_stream << double_movement_heat_percentage;

			Scalar shut_time = 2.0f;
			page->GetEntry("ShutDownTime", &shut_time);
			heat_stream << shut_time;

			if (heat_stream.GetBytesUsed() > 0)
			{
				heat_resource.Save(&heat_stream, &heat_deps);
				if (!heat_resource.IsRegistered())
					parent->AddDependencies(&heat_deps);
				Check_Object(&heat_resource);
				model->heatManagerResource = heat_resource.GetResourceID();
			}
			else
				model->heatManagerResource = ResourceID::Null;
			Resource::ParentFileDependencies = parent;

			Tool::Instance->PopFilePath();
		}
	}
	Verify(stack_level == Tool::Instance->GetStackLevel());
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	Mech__GameModel::ReadAndVerify(
		Mech__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');

	//
	//----------------------------------------
	//Read in the values from the data entered
	//----------------------------------------
	//
	result =
		BaseClass::ReadAndVerify(
			model,
			attribute_entry,
			data,
			error,
			error_buffer
		);
	//
	//---------------------------
	//Verify all the model values
	//---------------------------
	//
	switch(attribute_entry->attributeID)
	{
		case TiltSpeedAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->tiltSpeed.angle < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TiltSpeed=%f}: value must be >= 0!",
					model->tiltSpeed.angle*Degrees_Per_Radian
				);
				result = false;
			}
			break;
		}
		case TiltDegreeAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->tiltDegree.angle < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TiltDegree=%f}: value must be >= 0!",
					model->tiltDegree.angle*Degrees_Per_Radian
				);
				result = false;
			}
			break;
		}
		case ScaleInternalTiltDegreeAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->scaleInternalTiltDegree < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]ScaleInternalTiltDegree=%f}: value must be >= 0!",
					model->scaleInternalTiltDegree
				);
				result = false;
			}
			break;
		}
		case FootReturnSecondsAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->footReturnSeconds < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]FootReturnSeconds=%f}: value must be >= 0!",
					model->footReturnSeconds
				);
				result = false;
			}
			break;
		}
		case FallAdjustmentSecondsAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->fallAdjustmentSeconds < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]FallAdjustmentSeconds=%f}: value must be >= 0!",
					model->fallAdjustmentSeconds
				);
				result = false;
			}
			break;
		}
		case GetUpAdjustmentSecondsAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->getUpAdjustmentSeconds < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]GetUpAdjustmentSeconds=%f}: value must be >= 0!",
					model->getUpAdjustmentSeconds
				);
				result = false;
			}
			break;
		}
		case FallAdjustmentDelaySecondsAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->fallAdjustmentDelaySeconds < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]FallAdjustmentDelaySeconds=%f}: value must be >= 0!",
					model->fallAdjustmentDelaySeconds
				);
				result = false;
			}
			break;
		}
		case GetUpAdjustmentDelaySecondsAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->getUpAdjustmentDelaySeconds < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]GetUpAdjustmentDelaySeconds=%f}: value must be >= 0!",
					model->getUpAdjustmentDelaySeconds
				);
				result = false;
			}
			break;
		}
		case PercentageOfTurnToStartTiltAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->percentageOfTurnToStartTilt < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]PercentageOfTurnToStartTilt=%f}: value must be >= 0!",
					model->percentageOfTurnToStartTilt
				);
				result = false;
			}
			break;
		}
		case PercentageOfSpeedToStartTiltAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->percentageOfSpeedToStartTilt < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]PercentageOfSpeedToStartTilt=%f}: value must be >= 0!",
					model->percentageOfSpeedToStartTilt
				);
				result = false;
			}
			break;
		}
		
		
		case DampenWorldJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->dampenWorldJoint < 0.0f || model->dampenWorldJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DampenWorldJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->dampenWorldJoint
				);
				result = false;
			}
			break;
		}
		case DampenRootJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->dampenRootJoint < 0.0f || model->dampenRootJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DampenRootJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->dampenRootJoint
				);
				result = false;
			}
			break;
		}
		case DampenTorsoJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->dampenTorsoJoint < 0.0f || model->dampenTorsoJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DampenTorsoJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->dampenTorsoJoint
				);
				result = false;
			}
			break;
		}
		case DampenHipJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->dampenHipJoint < 0.0f || model->dampenHipJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DampenHipJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->dampenHipJoint
				);
				result = false;
			}
			break;
		}
		case DampenTranslationJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->dampenTranslationJoint < 0.0f || model->dampenTranslationJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DampenTranslationJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->dampenTranslationJoint
				);
				result = false;
			}
			break;
		}
		
				case UndampenWorldJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->undampenWorldJoint < 0.0f || model->undampenWorldJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]UndampenWorldJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->undampenWorldJoint
				);
				result = false;
			}
			break;
		}
		case UndampenRootJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->undampenRootJoint < 0.0f || model->undampenRootJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]UndampenRootJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->undampenRootJoint
				);
				result = false;
			}
			break;
		}
		case UndampenTorsoJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->undampenTorsoJoint < 0.0f || model->undampenTorsoJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]UndampenTorsoJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->undampenTorsoJoint
				);
				result = false;
			}
			break;
		}
		case UndampenHipJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->undampenHipJoint < 0.0f || model->undampenHipJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]UndampenHipJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->undampenHipJoint
				);
				result = false;
			}
			break;
		}
		case UndampenTranslationJointAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->undampenTranslationJoint < 0.0f || model->undampenTranslationJoint > 1.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]UndampenTranslationJoint=%f}: value must be >= 0 && <= 1.0f!",
					model->undampenTranslationJoint
				);
				result = false;
			}
			break;
		}

		case TorsoScaleTakeHitAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->torsoScaleTakeHit < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]SorsoScaleTakeHit=%f}: value must be >= 0",
					model->torsoScaleTakeHit
				);
				result = false;
			}
			break;
		}

		case HipScaleTakeHitAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->hipScaleTakeHit < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]HipScaleTakeHit=%f}: value must be >= 0",
					model->hipScaleTakeHit
				);
				result = false;
			}
			break;
		}
		
		case RootScaleTakeHitAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->rootScaleTakeHit < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]RootScaleTakeHit=%f}: value must be >= 0",
					model->rootScaleTakeHit
				);
				result = false;
			}
			break;
		}
		
	
		case MinimumDamageForHitAnimationAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->minimumDamageForHitAnimation < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]MinimumDamageForHitAnimation=%f}: value must be >= 0!",
					model->minimumDamageForHitAnimation
				);
				result = false;
			}
			break;
		}
		case MinimumDamageForInternalHitAnimationAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->minimumDamageForInternalHitAnimation < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]MinimumDamageForInternalHitAnimation=%f}: value must be > 0!",
					model->minimumDamageForInternalHitAnimation
				);
				result = false;
			}
			break;
		}



		case TorsoHitSpringMotionLimitAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->torsoHitSpringMotionLimit <= 0.0f && model->torsoHitSpringMotionLimit > 180.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TorsoHitSpringMotionLimit=%f}: value must be > 0 && <= 180.0f!",
					model->torsoHitSpringMotionLimit
				);
				result = false;
			}
			else
			{
				model->torsoHitSpringMotionLimit = model->torsoHitSpringMotionLimit * Radians_Per_Degree;
			}
			break;
		}

		
		case TorsoHitSpringDecelerationAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->torsoHitSpringDeceleration < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TorsoHitSpringDeceleration=%f}: value must be > 0!",
					model->torsoHitSpringDeceleration
				);
				result = false;
			}
			else
			{
				model->torsoHitSpringDeceleration = model->torsoHitSpringDeceleration * Radians_Per_Degree;
			}
			break;
		}

		case TorsoHitSpringReturnSpeedAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->torsoHitSpringReturnSpeed < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TorsoHitSpringReturnSpeed=%f}: value must be > 0!",
					model->torsoHitSpringReturnSpeed
				);
				result = false;
			}
			else
			{
				model->torsoHitSpringReturnSpeed = model->torsoHitSpringReturnSpeed * Radians_Per_Degree;
			}
			break;
		}

		case TorsoHitSpringSpeedAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->torsoHitSpringSpeed < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TorsoHitSpringSpeed=%f}: value must be > 0!",
					model->torsoHitSpringSpeed
				);
				result = false;
			}
			else
			{
				model->torsoHitSpringSpeed = model->torsoHitSpringSpeed * Radians_Per_Degree;
			}
			break;
		}


		case HipHitSpringMotionLimitAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->hipHitSpringMotionLimit <= 0.0f && model->hipHitSpringMotionLimit > 180.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]HipHitSpringMotionLimit=%f}: value must be > 0 && <= 180.0f!",
					model->hipHitSpringMotionLimit
				);
				result = false;
			}
			else
			{
				model->hipHitSpringMotionLimit = model->hipHitSpringMotionLimit * Radians_Per_Degree;
			}
			break;
		}

		
		case HipHitSpringDecelerationAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->hipHitSpringDeceleration < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]HipHitSpringDeceleration=%f}: value must be > 0 ",
					model->hipHitSpringDeceleration
				);
				result = false;
			}
			else
			{
				model->hipHitSpringDeceleration = model->hipHitSpringDeceleration * Radians_Per_Degree;
			}
			break;
		}

		case HipHitSpringReturnSpeedAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->hipHitSpringReturnSpeed < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]HipHitSpringReturnSpeed=%f}: value must be > 0 !",
					model->hipHitSpringReturnSpeed
				);
				result = false;
			}
			else
			{
				model->hipHitSpringReturnSpeed = model->hipHitSpringReturnSpeed * Radians_Per_Degree;
			}
			break;
		}

		case HipHitSpringSpeedAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->hipHitSpringSpeed < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]HipHitSpringSpeed=%f}: value must be > 0 !",
					model->hipHitSpringSpeed
				);
				result = false;
			}
			else
			{
				model->hipHitSpringSpeed = model->hipHitSpringSpeed * Radians_Per_Degree;
			}
			break;
		}

		case RootHitSpringMotionLimitAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->rootHitSpringMotionLimit <= 0.0f && model->rootHitSpringMotionLimit > 180.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]RootHitSpringMotionLimit=%f}: value must be > 0 && <= 180.0f!",
					model->rootHitSpringMotionLimit
				);
				result = false;
			}
			else
			{
				model->rootHitSpringMotionLimit = model->rootHitSpringMotionLimit * Radians_Per_Degree;
			}
			break;
		}
		
		case RootHitSpringDecelerationAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->rootHitSpringDeceleration < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]RootHitSpringDeceleration=%f}: value must be > 0 ",
					model->rootHitSpringDeceleration
				);
				result = false;
			}
			else
			{
				model->rootHitSpringDeceleration = model->rootHitSpringDeceleration * Radians_Per_Degree;
			}
			break;
		}

		case RootHitSpringReturnSpeedAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->rootHitSpringReturnSpeed < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]RootHitSpringReturnSpeed=%f}: value must be > 0!",
					model->rootHitSpringReturnSpeed
				);
				result = false;
			}
			else
			{
				model->rootHitSpringReturnSpeed = model->rootHitSpringReturnSpeed * Radians_Per_Degree;
			}
			break;
		}

		case RootHitSpringSpeedAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->rootHitSpringSpeed < 0.0f )
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]RootHitSpringSpeed=%f}: value must be > 0!",
					model->rootHitSpringSpeed
				);
				result = false;
			}
			else
			{
				model->rootHitSpringSpeed = model->rootHitSpringSpeed * Radians_Per_Degree;
			}
			break;
		}



		ScalarGreaterThanZero(ExternalHitScaleBeamDamage, externalHitScaleBeamDamage)
		ScalarGreaterThanZero(ExternalHitScaleMissileDamage, externalHitScaleMissileDamage)
		ScalarGreaterThanZero(ExternalHitScaleProjectileDamage, externalHitScaleProjectileDamage)
		ScalarGreaterThanZero(ExternalHitScaleSplashDamage, externalHitScaleSplashDamage)
		ScalarGreaterThanZero(ExternalHitScaleHeatDamage, externalHitScaleHeatDamage)

		ScalarGreaterThanZero(InternalHitScaleBeamDamage, internalHitScaleBeamDamage)
		ScalarGreaterThanZero(InternalHitScaleMissileDamage, internalHitScaleMissileDamage)
		ScalarGreaterThanZero(InternalHitScaleProjectileDamage, internalHitScaleProjectileDamage)
		ScalarGreaterThanZero(InternalHitScaleSplashDamage, internalHitScaleSplashDamage)
		ScalarGreaterThanZero(InternalHitScaleHeatDamage, internalHitScaleHeatDamage)

		ScalarGreaterThanZero(InternalSpinHitScaleBeamDamage, internalSpinHitScaleBeamDamage)
		ScalarGreaterThanZero(InternalSpinHitScaleMissileDamage, internalSpinHitScaleMissileDamage)
		ScalarGreaterThanZero(InternalSpinHitScaleProjectileDamage, internalSpinHitScaleProjectileDamage)
		ScalarGreaterThanZero(InternalSpinHitScaleSplashDamage, internalSpinHitScaleSplashDamage)
		ScalarGreaterThanZero(InternalSpinHitScaleHeatDamage, internalSpinHitScaleHeatDamage)


		ScalarGreaterThanZero(SpinForceBeamDamage, spinForceBeamDamage)
		ScalarGreaterThanZero(SpinForceMissileDamage, spinForceMissileDamage)
		ScalarGreaterThanZero(SpinForceProjectileDamage, spinForceProjectileDamage)
		ScalarGreaterThanZero(SpinForceSplashDamage, spinForceSplashDamage)
		ScalarGreaterThanZero(SpinForceHeatDamage, spinForceHeatDamage)

		Point3DGreaterThanZero(EyeSpringMotionLimit, eyeSpringMotionLimit)
		Point3DGreaterThanZero(EyeSpringConstant, eyeSpringConstant)
		Point3DGreaterThanZero(EyeSpringDrag, eyeSpringDrag)
		Point3DGreaterThanZero(EyeSpringStopThreshold, eyeSpringStopThreshold)


		case DropJumpEffectAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
		case CradleAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
		case CradleDeathEffectAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
		case JumpJetEffectAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
		case InitialJumpJetEffectAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
		case LeftJumpJetSiteNameAttributeID:
		{
			if(!valid_data)
			{
				char *value;
				value = new char[MaxStringLength];
				Register_Pointer(value);
				Str_Copy(value, "", MaxStringLength);
				attribute_entry->SetValue(model, value);
				result = true;
				Unregister_Pointer(value);
				delete value;
				break;
			}
			break;
		}
		case RightJumpJetSiteNameAttributeID:
		{
			if(!valid_data)
			{
				char *value;
				value = new char[MaxStringLength];
				Register_Pointer(value);
				Str_Copy(value, "", MaxStringLength);
				attribute_entry->SetValue(model, value);
				result = true;
				Unregister_Pointer(value);
				delete value;
				break;
			}
			break;
		}
		case SearchLightResourceAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
		case MaxHeatAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 60.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->maxHeat <= 0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]MaxHeat=%f}: value must be >= 0!",
					model->maxHeat
				);
				result = false;
			}
			break;
		}
		case MechIDAttributeID:
		{
			if(!valid_data)
			{
				int value;
				value = -1;
				attribute_entry->SetValue(model, &value);
				return true;
			}	
			break;
		}
		case CanLoadJumpJetsAttributeID:
		{
			if(!valid_data)
			{
				bool value = true;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
			break;
		}
		case CanLoadECMAttributeID:
		{
			if(!valid_data)
			{
				bool value = true;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
			break;
		}
		case CanLoadBeagleAttributeID:
		{
			if(!valid_data)
			{
				bool value = true;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
			break;
		}
		case CanLoadLightAmpAttributeID:
		{
			if(!valid_data)
			{
				bool value = true;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
			break;
		}
		case CanLoadAMSAttributeID:
		{
			if(!valid_data)
			{
				bool value = true;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
			break;
		}
		case CanLoadLAMSAttributeID:
		{
			if(!valid_data)
			{
				bool value = true;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
			break;
		}
// MSL 5.02 SubSystems
//		case CanLoadEnhancedOpticsAttributeID:
//		{
//			if(!valid_data)
//			{
//				bool value = false;
//				attribute_entry->SetValue(model,&value);
//				result = true;
//			}
//			break;
//		}
		case CanLoadIFF_JammerAttributeID:
		{
			if(!valid_data)
			{
				bool value = false;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
			break;
		}
		case CanLoadAdvancedGyroAttributeID:
		{
			if(!valid_data)
			{
				bool value = false;
				attribute_entry->SetValue(model,&value);
				result = true;
			}
			break;
		}
		case AdvancedGyroTonnageAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 1.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->m_advancedGyroTonnage < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]AdvancedGyroTonnage=%f}: value must be >= 0 ",
					model->m_advancedGyroTonnage
				);
				result = false;
			}
			break;
		}
		case JumpJetTonnageAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 1.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->m_jumpJetTonnage < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]JumpJetTonnage=%f}: value must be >= 0 ",
					model->m_jumpJetTonnage
				);
				result = false;
			}
			break;
		}
		case TechTypeAttributeID:
		{
			if(!valid_data)
			{
				int value = 0;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->techType < 0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TechType=%f}: value must be >= 0!",
					model->techType
				);
				result = false;
			}
			break;
		}
		case CageDamageEffectAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
		case DamageNeededForCageEffectAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 1.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->maxHeat < 0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DamageNeedeForCageEffect=%f}: value must be > 0!",
					model->damageNeededForCageEffect
				);
				result = false;
			}
			break;
		}
		case MechRamEffectAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
// MSL 5.03 Glass
		case MechGlassRamEffectAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
		case WakeEffectResourceAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}

	}
	return result;
}