//--------------------------------------------------------------------------------------
// Copyright (C) 2008 http://shift.delblanco.es
//--------------------------------------------------------------------------------------
// SHIFT Videogame is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//--------------------------------------------------------------------------------------
// 3DObjElement.cpp
//--------------------------------------------------------------------------------------
#include "dxstdafx.h"
#include "3DObjElement.h"
#include "3DSoundMng.h"

//--------------------------------------------------------------------------------------
// Variables Globales
//--------------------------------------------------------------------------------------
extern C3DSoundMng      *g_3DSoundMng;     // Instancia externa para manejar sonidos 3D (3DSoundMng.cpp)

//--------------------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------------------
C3DObjElement::C3DObjElement()
{
    m_pType = 0;
	m_pSndAppear = NULL;
	m_pSndGet = NULL;
	m_pDelay = 0.0f;
}

//--------------------------------------------------------------------------------------
// Destructor
//--------------------------------------------------------------------------------------
C3DObjElement::~C3DObjElement()
{
	// Liberamos sonidos
    if(m_pSndAppear)	g_3DSoundMng->Destroy(m_pSndAppear);
    if(m_pSndGet)		g_3DSoundMng->Destroy(m_pSndGet);
}

//--------------------------------------------------------------------------------------
// Inicializa el elemento de la arena
//--------------------------------------------------------------------------------------
bool C3DObjElement::initialize(C3DObjArena *Arena, LPCWSTR ObjectPath, int Type)
{
    // Almacenamos el objeto asociado
    m_pArena = Arena;
	m_pType = Type;

    // Función de la clase padre
	// Cuidado, aquí si le indicamos como padre la arena, ya que el elemento será un objeto dependiente en la jerarquía
    if(!C3DObject::initialize(Arena, ObjectPath))
        return false;

    // Se usará una nueva instancia de CXMLIO
    CXMLIO *myXMLIO = new CXMLIO;
    if(!myXMLIO) return false;

    // Tomamos los elementos específicos del elemento
    if(myXMLIO->LoadFile(ObjectPath))
    {
        WCHAR value[MAX_STRING+1];

        // Sonidos adicionales del elemento (nodo 'sound')
        if(myXMLIO->MoveSubElement(L"sound"))
        {
            // Aparición (atributo 'appear')
            if(myXMLIO->GetAttribute(L"appear", value))
                m_pSndAppear = g_3DSoundMng->Create(value, this);
            // Captura (atributo 'get')
            if(myXMLIO->GetAttribute(L"get", value))
                m_pSndGet = g_3DSoundMng->Create(value, this);

            myXMLIO->MoveParent();
        }
    }

    // Liberamos el parseador de XML
    SAFE_DELETE(myXMLIO);

	// Cambiamos el estado del elemento
	m_pState = OBJELEMENT_FREE;

    return true;
}

//--------------------------------------------------------------------------------------
// Actualiza el elemento de la arena
//--------------------------------------------------------------------------------------
void C3DObjElement::update()
{
	// Si estamos en colisión
	if (m_pState == OBJELEMENT_COLLISION)
	{
		// Si no hemos llegado al límite
		if (m_pDelay < 1.0)
		{
			// Si es la primera vez, ajustamos los sistemas de partículas
			if (m_pDelay == 0.0f)
			{
				m_pParticles1->SetReleaseInterval(9999.0f);
				m_pParticles2->SetReleaseInterval(0.2f);
			}

			// Actualizamos los sistemas de partículas
			m_pParticles1->update();
			m_pParticles2->update();
		}

		// Si hemos llegado al límite, cambiamos el estado del elemento
		else m_pState = OBJELEMENT_FREE;

		// Acumulamos el tiempo desde la última actualización
		m_pDelay += DXUTGetElapsedTime();
	}

	// Función de la clase padre
    C3DObject::update();
}

//--------------------------------------------------------------------------------------
// Para activar el sonido de aparición del elemento
//--------------------------------------------------------------------------------------
void C3DObjElement::playAppear(bool loop, long volume, long frecuency)
{
	if(!m_pSndAppear) return;

	m_pSndAppear->Play(loop);
	if(volume)    m_pSndAppear->setVolume(volume);
	if(frecuency) m_pSndAppear->setFrecuency(frecuency);
}

//--------------------------------------------------------------------------------------
// Para activar el sonido de captura del elemento
//--------------------------------------------------------------------------------------
void C3DObjElement::playGet(bool loop, long volume, long frecuency)
{
	if(!m_pSndGet) return;

	m_pSndGet->Play(loop);
	if(volume)    m_pSndGet->setVolume(volume);
	if(frecuency) m_pSndGet->setFrecuency(frecuency);
}

//--------------------------------------------------------------------------------------
// Manejador de colisión básica
//--------------------------------------------------------------------------------------
bool C3DObjElement::onQuickCollision(C3DObject *object)
{
	// Sólo continuamos si la colisión es contra un vehículo
	if (!(object->getCollision()->getIsVehicle()))
		return false;

	// Desactivamos el elemento
	setEnabled(false);

	// Activamos el sonido de captura
	stopGet();
	playGet(false);

	// Cambiamos el estado del elemento
	m_pState = OBJELEMENT_PRECOLLISION;

	// Retornamos falso para que no se sigua comprobando la colisión
	return false;
}

//--------------------------------------------------------------------------------------
// Función para cambiar el estado de procesamiento del elemento, activado/desactivado
//--------------------------------------------------------------------------------------
void C3DObjElement::setEnabled(bool enabled)
{
	// Si estamos activando el elemento
	if (enabled)
	{
		// Salimos si el elemento está bloqueado
		if (m_pState != OBJELEMENT_FREE) return;

		// Ajustamos posición
		D3DXVECTOR3 v_aux;
		if (m_pType == OBJELEMENT_OBJECTIVE) m_pArena->getPosObjective(v_aux);
		else m_pArena->getPosElement(v_aux);
		v_aux.y = 2.0f;
		setPosition(v_aux);
		refreshTransformation();

		// Ajustamos los sistemas de partículas
		m_pParticles1->SetReleaseInterval(0.2f);
		m_pParticles1->SetPosition(v_aux);
		m_pParticles2->SetReleaseInterval(9999.0f);
		m_pParticles2->SetPosition(v_aux);

		// Activamos el sonido de aparición
		stopAppear();
		playAppear(false);

		// Reseteamos el temporizador y cambiamos el estado del elemento
		m_pDelay = 0.0f;
		m_pState = OBJELEMENT_LAUNCH;
	}

	// Función de la clase padre
    C3DObject::setEnabled(enabled);
}
