/** 
 * \file Dwarf.cpp
 * \brief CDwarf class member functions implementation. CDwarf holds model's position and facing.
 * 
 * \author Petar Bajic, MPE (C) All Rights Reserved, Homepage: www.mystic-peanut.com
 * \date January, 16 2007.
 */

#include "Dwarf.h"
#include "Sheep.h"


#pragma warning( disable : 4996 ) // disable deprecated warning 
#include <strsafe.h>
#pragma warning( default : 4996 )

/**
 * \brief Standard constructor.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
CDwarf::CDwarf()
{
	m_Model = NULL;
	m_SnatchingSound = NULL;
	m_DyingSound1 = NULL;
	m_DyingSound2 = NULL;
	m_Position = D3DXVECTOR3(0.0f,0.0f,-500.0f);
	m_Facing = 0.0f;
	m_WalkCenter = true;
	m_CarryingSheep = false;
	m_Slowed = false;
	m_Alive = false;
	m_Scared = false;
	m_Hit = false;
	m_HitFly = false;
	m_HitTime = 0.0f;
	m_HitAngle = 0.0f;
	m_PickAnimTime = 0.0f;
	m_bPickAnim = false;
	m_HitFall = D3DX_PI/2;
	m_TargetSheep = NULL;
}

/**
 * \brief Extended constructor. Takes preloaded skinned model to avoid multiple loading for many dwarfs.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
CDwarf::CDwarf(CXFileEntity* model)
{
	if (model != NULL)
	{
		m_Model = new CXFileEntity();
		//Clone Animation Controler
		HRESULT hr = model->m_animController->CloneAnimationController(
			model->m_animController->GetMaxNumAnimationOutputs(),
			model->m_animController->GetMaxNumAnimationSets(),
			model->m_animController->GetMaxNumTracks(),
			model->m_animController->GetMaxNumEvents(),
			&(m_Model->m_animController));
		m_Model->m_currentTime = 0;

		//Other parameters we just copy
		m_Model->m_boneMatrices = model->m_boneMatrices;
		m_Model->m_currentAnimationSet = model->m_currentAnimationSet;
		m_Model->m_currentTrack = model->m_currentTrack;
		m_Model->m_firstMesh = model->m_firstMesh;
		m_Model->m_frameRoot = model->m_frameRoot;
		m_Model->m_maxBones = model->m_maxBones;
		m_Model->m_numAnimationSets = model->m_numAnimationSets;
		m_Model->m_speedAdjust = model->m_speedAdjust;
		m_Model->m_sphereCentre = model->m_sphereCentre;
		m_Model->m_sphereRadius = model->m_sphereRadius;

	}
	else
	{
			m_Model = NULL;
	}

	m_SnatchingSound = NULL;
	m_DyingSound1 = NULL;
	m_DyingSound2 = NULL;

	m_Position = D3DXVECTOR3(0.0f,0.0f,-500.0f);
	m_Facing = 0.0f;
	
	m_WalkCenter = true;
	m_CarryingSheep = false;
	m_Slowed = false;
	m_Alive = false;
	m_Scared = false;
	m_Hit = false;
	m_HitTime = 0.0f;
	m_HitAngle = 0.0f;
	m_HitFall = D3DX_PI/2;
	m_PickAnimTime = 0.0f;
	m_bPickAnim = false;
	m_TargetSheep = NULL;
}

/**
 * \brief Standard destructor.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
CDwarf::~CDwarf()
{
	if(m_Model != NULL)
		delete m_Model;
}

/**
 * \brief Init function loads skinned model (CXFileEntity) and dwarf specific sounds.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
bool CDwarf::Init(HWND hWnd, LPDIRECT3DDEVICE9 pd3dDevice, IDirectSound8* pDS)
{
	m_Model = new CXFileEntity(); // Create our entity class
	// Load an x file to start with
	WCHAR strFullPath[MAX_PATH];
	GetCurrentDirectory(MAX_PATH,strFullPath);
	StringCchCat(strFullPath, 255, L"//Media//Models//dwarf.x");
	HRESULT hr = m_Model->LoadXFile(pd3dDevice,strFullPath);
	if (FAILED(hr))
	{
		MessageBox(hWnd,L"Could not load Media/Models/dwarf.x file",L"Error",MB_OK);
		return false;
	}
	m_Model->SetAnimationSet(0);//walk

	//Init Sounds
	m_SnatchingSound = new CSound();
	if (!m_SnatchingSound->Init(pDS, L"Media/Sounds/dwarf_gotcha.wav"))
	{
		MessageBox(hWnd,L"Could not load Media/Sounds/dwarf_gotcha.wav file",L"Error",MB_OK);
		return false;
	}
	m_DyingSound1 = new CSound();
	if (!m_DyingSound1->Init(pDS, L"Media/Sounds/dwarf_die_01.wav"))
	{
		MessageBox(hWnd,L"Could not load Media/Sounds/dwarf_die_01.wav file",L"Error",MB_OK);
		return false;
	}
	m_DyingSound2 = new CSound();
	if (!m_DyingSound2->Init(pDS, L"Media/Sounds/dwarf_die_02.wav"))
	{
		MessageBox(hWnd,L"Could not load Media/Sounds/dwarf_die_02.wav file",L"Error",MB_OK);
		return false;
	}

	return true;
}

/**
 * \brief Create sounds for dwarf instance.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
bool CDwarf::InitSounds(HWND hWnd, IDirectSound8* pDS)
{
	//Init Sounds
	m_SnatchingSound = new CSound();
	if (!m_SnatchingSound->Init(pDS, L"Media/Sounds/dwarf_gotcha.wav"))
	{
		MessageBox(hWnd,L"Could not load Media/Sounds/dwarf_gotcha.wav file",L"Error",MB_OK);
		return false;
	}
	m_DyingSound1 = new CSound();
	if (!m_DyingSound1->Init(pDS, L"Media/Sounds/dwarf_die_01.wav"))
	{
		MessageBox(hWnd,L"Could not load Media/Sounds/dwarf_die_01.wav file",L"Error",MB_OK);
		return false;
	}
	m_DyingSound2 = new CSound();
	if (!m_DyingSound2->Init(pDS, L"Media/Sounds/dwarf_die_02.wav"))
	{
		MessageBox(hWnd,L"Could not load Media/Sounds/dwarf_die_02.wav file",L"Error",MB_OK);
		return false;
	}
}

/**
 * \brief Move animated model.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::OnFrameMove(LPDIRECT3DDEVICE9 pd3dDevice, float fElapsedTime, D3DXMATRIXA16* matWorld)
{
	if (m_bPickAnim)
	{
		m_PickAnimTime += fElapsedTime;
		if (m_PickAnimTime > 0.6f)
		{
			m_bPickAnim = false;
			m_PickAnimTime = 0.0f;
			m_Model->SetAnimationSet(0);//Walk Anim
		}
	}

	if(m_Alive)
		m_Model->OnFrameMove(pd3dDevice, fElapsedTime, matWorld);
}

/**
 * \brief Render skinned model.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::OnRender(LPDIRECT3DDEVICE9 pd3dDevice)
{
	if (m_Alive)
		m_Model->Render(pd3dDevice);
}

/**
 * \brief Restart dwarf (position, facing, etc..)
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::Restart()
{
	m_Position = D3DXVECTOR3(0.0f,0.0f,0.0f);
	m_Facing = 0.0f;
}

/**
 * \brief Dwarf goes into picking animation.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::StartPickAnim()
{
	m_Model->SetAnimationSet(1);//Pick Anim
	m_bPickAnim = true;
}

/**
 * \brief Snatch sheep changes dwarf animation, direction of moving, and attaches sheep to this dwarf.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::SnatchSheep()
{
	m_WalkCenter = false;
	m_Facing += D3DX_PI;  //Turns and walks the oposite direction
	m_TargetSheep->m_BeingCarriedAway = true;
	m_TargetSheep->m_Model->SetAnimationSet(0);
	m_TargetSheep->m_Facing = m_Facing - D3DX_PI/2;
	m_CarryingSheep = true;
	m_PickAnimTime = 0.0f;
	m_bPickAnim = false;
	m_Model->SetAnimationSet(2);//Carrying Animation
	//Play Sound
	m_SnatchingSound->Stop();
	m_SnatchingSound->Reset();
	m_SnatchingSound->Play();
}

/**
 * \brief Places dwarf on the field and directs him toward closest sheep.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::GetInTheGame()
{
	m_Alive = true;
	m_CarryingSheep = false;
	m_Model->SetAnimationSet(0);//walk
	m_bPickAnim = false;
	m_PickAnimTime = 0.0f;
	//Dwarsf should appear from all four sides of the world
	//Random side is picked, then random coordinate position on that side.
	int rand_side = 0;
	int rand_position = 0;
	rand_side = (rand() % 4);// rand(0 to 3);
	rand_position = (rand() % 100) - 50;// from -50 to 50;

	if (rand_side == 1)
	{
		m_Position.x = -50.0f;
		m_Position.z = (float)rand_position;
	}
	else if (rand_side == 2)
	{
		m_Position.z = 50.0f;
		m_Position.x = (float)rand_position;
	}
	else if (rand_side == 3)
	{
		m_Position.x = 50.0f;
		m_Position.z = (float)rand_position;
	}
	else if (rand_side == 0)
	{
		m_Position.z = -50.0f;
		m_Position.x = (float)rand_position;
	}
	m_Position.y = 0.0f;
}

/**
 * \brief Dwarf dies and dissapears. Reset his attribute for new appearance.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::DieOut()
{
	m_Alive = false;
	m_CarryingSheep = false;
	m_Slowed = false;
	m_Scared = false;
	m_TargetSheep = NULL;	
	m_Position = D3DXVECTOR3(0.0f,0.0f,-500.0f);
	m_Facing = 0.0f;
	m_Hit = false;
	m_HitFly = false;
	m_HitTime = 0.0f;
	m_WalkCenter = true;
}

/**
 * \brief While OnFrameMove animates dwarf in place, 
 * this function moves him arround depending on his condition.
 * If dwarf is hit, he flies and dies.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::Move(float chunk, double fTime)
{
	float bit = chunk;

	//dont move the deadios
	if (m_Alive)
	{
		if (m_Hit)
		{
			bit = bit * 5;
		}
		else if (m_Slowed)
		{
			bit = bit/2;
		}

		if (m_Hit)
		{
			m_Position.z -= bit * cos(m_HitAngle);
			m_Position.x -= bit * sin(m_HitAngle);

			if (m_HitFly)
			{
				m_Position.y += bit*3;
			}
		}
		else
		{
			m_Position.z += bit * cos(m_Facing);
			m_Position.x += bit * sin(m_Facing);
			//Move the sheep with dwarf
			if (m_CarryingSheep && (m_TargetSheep != NULL))
			{
				//place sheep on the dwarf left shoulder 
				m_TargetSheep->m_Position = m_Position;
				m_TargetSheep->m_Position.z += 1.1f * sin(m_Facing);
				m_TargetSheep->m_Position.x -= 1.1f * cos(m_Facing);
				m_TargetSheep->m_Position.y = 4.3f + (float)(0.18*sin(fTime*23));
			}
		}
	}
}

/**
 * \brief Play sound of dying dwarf when he flies up in the air.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::PlaySoundRikoshetDying()
{
	m_DyingSound1->Stop();
	m_DyingSound1->Reset();
	m_DyingSound1->Play();
}

/**
 * \brief Play sound of dying dwarf when he drops down to the ground bouncing.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CDwarf::PlaySoundBouncingDying()
{
	m_DyingSound2->Stop();
	m_DyingSound2->Reset();
	m_DyingSound2->Play();
}