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

#include "MW4Headers.hpp"

#include "Weapon.hpp"
#include "MWTool.hpp"
#include "MWDamageObject.hpp"

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

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

	//
	//---------------------------
	// Point at the notation file
	//---------------------------
	//
	Page *page = script->instancePage;
	Check_Object(page);
	Check_Object(Tool::Instance);

	const char *site_name;
	page->GetEntry("Site", &site_name, true);
	Check_Pointer(site_name);
	Str_Copy(message->siteName, _strlwr((char*)site_name), sizeof(message->siteName));

	const char *eject_site;
	MString eject_site_name = " ";
	if(page->GetEntry("EjectSite", &eject_site))
		eject_site_name = eject_site;
//	else
//		eject_site_name = site_name;
	Str_Copy(message->ejectSiteName, _strlwr((char*)eject_site_name), sizeof(message->ejectSiteName));

	int ammo_count;
	if(page->GetEntry("AmmoCount", &ammo_count))
	{
		message->ammoCount = ammo_count;
	}
	else
	{
		message->ammoCount = -1;
	}

	message->initialAmmoCount = message->ammoCount;

	message->groupIndex = Weapon::DefaultWeaponGroupFlags;
	ChainOf<Note*> *weapon_group = page->MakeNoteChain("GroupIndex");
	Check_Object(weapon_group);
	Page::NoteIterator weapon_group_list(weapon_group);
	Note *weapon_name_entry;
	while ((weapon_name_entry = weapon_group_list.ReadAndNext()) != NULL)
	{
		const char * weapon_group_num;
		weapon_name_entry->GetEntry(&weapon_group_num);
		int index = atoi(weapon_group_num);
		switch(index)
		{
		case 1:
			message->groupIndex |= Weapon::WeaponGroup1Flag;
			break;
		case 2:
			message->groupIndex |= Weapon::WeaponGroup2Flag;
			break;
		case 3:
			message->groupIndex |= Weapon::WeaponGroup3Flag;
			break;
		case 4:
			message->groupIndex |= Weapon::WeaponGroup4Flag;
			break;
		case 5:
			message->groupIndex |= Weapon::WeaponGroup5Flag;
			break;
		case 6:
			message->groupIndex |= Weapon::WeaponGroup6Flag;
			break;
		}
	}
	delete weapon_group;

// MSL 5.04 Rear Firing Weapons				
	int weapon_facing = 0;
	if(page->GetEntry("WeaponFacing", &weapon_facing))
	{
		message->m_weaponFacing = weapon_facing;
	}
	else
	{
		message->m_weaponFacing = 0;
	}

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Weapon::SaveInstanceText(Page *instance_page)
{
	Check_Object(this);

	Subsystem::SaveInstanceText(instance_page);

	instance_page->SetEntry("Site", (const char *)siteName);
//	notation_file->SetEntry(instance_name, "GroupIndex", groupIndex);
	if(IsInWeaponGroup1())
		instance_page->AppendEntry("GroupIndex", "1");
	if(IsInWeaponGroup2())
		instance_page->AppendEntry("GroupIndex", "2");
	if(IsInWeaponGroup3())
		instance_page->AppendEntry("GroupIndex", "3");
	if(IsInWeaponGroup4())
		instance_page->AppendEntry("GroupIndex", "4");
	if(IsInWeaponGroup5())
		instance_page->AppendEntry("GroupIndex", "5");
	if(IsInWeaponGroup6())
		instance_page->AppendEntry("GroupIndex", "6");

	int ammo_count = DECRYPT(encryptedAmmoCount);
	instance_page->SetEntry("AmmoCount", ammo_count);

}

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

	//
	//--------------
	// Set up stream
	//--------------
	//
	MemoryStream *model_stream = script->modelStream;
	Check_Object(model_stream);
	model_stream->AllocateBytes(sizeof(Weapon__GameModel));
	Subsystem__GameModel::ConstructGameModel(script);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	Weapon__GameModel::ReadAndVerify(
		Weapon__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 = 
		Subsystem__GameModel::ReadAndVerify(
			model, 
			attribute_entry, 
			data,
			error,
			error_buffer
		);
	//
	//---------------------------
	//Verify all the model values
	//---------------------------
	//
	switch(attribute_entry->attributeID)
	{
	case MuzzleFlashResourceAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
	case EjectEffectResourceAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}
	case NumFireAttributeID:
		{
			if(!valid_data)
			{
				int value = 1;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if (model->numFire <= 0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]NumFire=%d}: value must be > 0!",
					model->numFire
				);
				result = false;
			}
			break;
		}
	case HudEffectAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if (model->m_HudEffect < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]HudEffect=%d}: value must be > 0.0f!",
					model->m_HudEffect
				);
				result = false;
			}
			break;
		}
	case HeatAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			else
			{
				Scalar value = (Scalar)atof(data);
				value /= 2;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			break;
		}
	case HeatSpreadTimeAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 3.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->heatSpreadTime < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]HeatSpreadTime=%f}: value must be > 0!",
					model->heatSpreadTime
				);
				result = false;
			}
			break;
		}
	case MaxAmmoAttributeID:
		{
			if(!valid_data)
			{
				int value = 0;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->maxAmmoCount < 0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]MaxAmmo=%f}: value must be >= 0!",
					model->maxAmmoCount
				);
				result = false;
			}
			break;
		}
	case AmmoPerShotAttributeID:
		{
			if(!valid_data)
			{
				int value = 1;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->ammoPerShot <= 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]AmmoPerShot=%f}: value must be > 0!",
					model->ammoPerShot
				);
				result = false;
			}
			break;
		}
	case HeatToDealAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->heatToDeal < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]HeatToDeal=%f}: value must be >= 0!",
					model->heatToDeal
				);
				result = false;
			}
			break;
		}
		case SplashRadiusAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->splashRadius < 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]SplashRadius=%f}: value must be >= 0!",
					model->splashRadius
				);
				result = false;
			}
			break;
		}



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

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

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

			break;
		}
	case DamageAmountAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if (model->damageAmount < 0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DamageAmount=%f}: value must be >= 0!",
					model->damageAmount
				);
				result = false;
			}
			break;
		}
	case MaxDistanceAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 300.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if (model->maxDistance <= 0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]MaxDistance=%f}: value must be > 0!",
					model->maxDistance
				);
				result = false;
			}
			break;
		}
// MSL 5.03 Min Distance
//	case MinDistanceAttributeID:
//		{
//			if(!valid_data)
//			{
//				Scalar value = 0.0f;
//				attribute_entry->SetValue(model, &value);
//				result = true;
//			}
//			if (model->minDistance < 0)
//			{
//				_snprintf(
//					*error,
//					error_buffer,
//					"{[GameData]MinDistance=%f}: value must be >= 0!",
//					model->minDistance
//				);
//				result = false;
//			}
//			break;
//		}
	case ReloadTimeAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 1.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if (model->reloadTime < 0.0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]ReloadTime=%f}: value must be > 0!",
					model->reloadTime
				);
				result = false;
			}

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