/*********************************************************************//**
*	Znicitelny objekt.
*	Realizuje entitu, kterou lze znicit a pote se zni stanou ulomky,
*	ktere ovlada system ulomku.
*	
*	author: Michal Jirous
*	date: 23.04.2009
*	file: func_breakable.cpp
**********************************************************************/

#include "ent_func_breakable.h"

using namespace modelLib;
//#include "attack_info.h"
FuncBreakable::FuncBreakable()
{
	m_sClassName = "func_breakable";
	m_bDestroyed = false;
	m_iHealth = 2000;
	m_iMaterial = MATERIAL_CONCRETE;
	m_iProperties = ENT_PARM_COLLIDING | ENT_PARM_RENDER |  ENT_PARM_RUNNABLE |  ENT_PARM_SHOOTABLE;
	m_iGibsType = GIBS_CONCRETE;
}


#include "general_sounds.h"
void FuncBreakable::onAttack( const AttackInfo &attackInfo )
{
	if( m_bDestroyed )
		return;
	m_iHealth -= attackInfo.m_iDamage;
	
	

	if( m_iHealth <= 0 )
	{
		if( attackInfo.face )
			((Face*)(attackInfo.face))->getLightColor( (float*)&m_GibsColor );
		else
			m_GibsColor = Color(1,1,1);
		destroy();
		
	}
	else
		generalSounds.playHurtSound( m_iMaterial, m_Sound );
}



void FuncBreakable::passStoredEvent( BackTimeData &backData )
{
	CBaseFunction::passStoredEvent( backData );
	if( backData.type == EVENT_DEATH )
	{
		if( !m_bDestroyed )
			destroy();
	}
}

void FuncBreakable::goBackInTime()
{
	CBaseFunction::goBackInTime();

	for( std::list<BackTimeData>::reverse_iterator riter = m_BackTimeData.rbegin(); riter != m_BackTimeData.rend(); ++riter )
	{
		if( (*riter).type == EVENT_BORDER )	//na border bych tu nemel narazit
			return;

		if( (*riter).type == EVENT_DEATH )
		{
			m_bDestroyed = false;
		}
	}
}

bool FuncBreakable::renderCullTest( RenderData &renderData )
{
	if( !m_bDestroyed )
		return CBaseFunction::renderCullTest( renderData );
	return false;
}

#include "game.h"
void FuncBreakable::setParameters( parameters_t &parametersMap )
{
	CBaseFunction::setParameters( parametersMap );

	std::string value = getParameterValue( parametersMap, "health" );
	if( !value.empty() )
		m_iStore_Health = atoi( value.c_str() );

	value = getParameterValue( parametersMap, "material" );
	if( !value.empty() )
		m_iMaterial = atoi( value.c_str() );

	value = getParameterValue( parametersMap, "gibs" );
	if( !value.empty() )
		m_iGibsType = atoi( value.c_str() );
	

	m_iHealth = m_iStore_Health;
	m_Sound.setPosition( origin.x, origin.y, origin.z );
	m_Sound.setSourceRelative( AL_FALSE );
}

void FuncBreakable::onTarget( int target_type )
{
	if( !m_bDestroyed )
		destroy();
}

void FuncBreakable::render( RenderData &renderData )
{
	if( !m_bDestroyed )
		CBaseFunction::render( renderData );

}

void FuncBreakable::restart()
{
	m_bDestroyed = false;
	m_iHealth = m_iStore_Health;
	for( std::list<Gib_elem>::iterator iter = m_Gibs.begin(); iter != m_Gibs.end(); ++iter )
		(*iter).restart();
}

bool FuncBreakable::collisionDetection( CollisionData &collData )
{
	if( !m_bDestroyed )
		return CBaseFunction::collisionDetection( collData );
	return false;
}
bool FuncBreakable::rayTrace( RayTraceData &rayData )
{
	if( !m_bDestroyed )
		return CBaseFunction::rayTrace( rayData );
	return false;
}

void FuncBreakable::destroy()
{
	generalSounds.playDestroySound( m_iMaterial, m_Sound );
	m_bDestroyed = true;

	m_BackTimeData.push_front( BackTimeData() );
	m_BackTimeData.front().event_time = game.getGameTime();
	m_BackTimeData.front().type = EVENT_DEATH;


	for( std::list<Gib_elem>::iterator iter = m_Gibs.begin(); iter != m_Gibs.end(); ++iter )
	{
		(*iter).m_Color = m_GibsColor;
		gibsSystem.addGib( &(*iter) );
	}

}



#include "level_loader.h"
void FuncBreakable::compile()
{
	CBaseFunction::compile();


	if( m_iGibsType >= GIBS_COUNT )
		return;

	BoundingBox &box = levelLoader.m_LevelData.models[ m_SolidModel ].bounds;
	
	const int x_size = (int)(box.m_fBounds[MAX_X] - box.m_fBounds[MIN_X]);
	const int y_size = (int)(box.m_fBounds[MAX_Y] - box.m_fBounds[MIN_Y]);
	const int z_size = (int)(box.m_fBounds[MAX_Z] - box.m_fBounds[MIN_Z]);

	const int VOLUME = x_size * y_size * z_size;
	const int NUM_GIBS = (const int)((float)VOLUME * GIBS_PER_QUADRIC_PIXEL);

	m_Gibs.resize( NUM_GIBS );

	for( std::list<Gib_elem>::iterator iter = m_Gibs.begin(); iter != m_Gibs.end(); ++iter )
	{
		Point position;
		position.x = box.m_fBounds[MIN_X] + rand() % x_size;
		position.y = box.m_fBounds[MIN_Y] + rand() % y_size;
		position.z = box.m_fBounds[MIN_Z] + rand() % z_size;
		
		Vector velocity;
		velocity.x = ((float)(rand() % 1000) / 1000.0f) - 0.5f;
		velocity.y = ((float)(rand() % 1000) / 1000.0f) - 0.5f;
		velocity.z = ((float)(rand() % 1000) / 1000.0f) - 0.5f;
		
		velocity = velocity * 5.0f;

		HLModelElement *pModel = modelLib::modelLibrary.applyHalfLifeMDL( "Gibs/" + gibsModels[m_iGibsType] );
		if( pModel )
		{
			int numModels = HLMDL(pModel)->getGroupPartsCount( 0 );
			HLMDL(pModel)->setGroupAndPart( 0, rand() % numModels );

			(*iter).create( pModel, position, velocity );
		}
		//
	
	
	}

}
	
void FuncBreakable::decompile()
{
	CBaseFunction::decompile();
}
