////////////////////////////////////////////////////////////////////////////
//	Module 		: stalker_animation_manager.cpp
//	Created 	: 25.02.2003
//  Modified 	: 19.11.2004
//	Author		: Dmitriy Iassenev
//	Description : Stalker animation manager
////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "stalker_animation_manager.h"
#include "ai/stalker/ai_stalker.h"
#include "stalker_animation_data_storage.h"
#include "stalker_animation_data.h"
#include "stalker_movement_manager_smart_cover.h"

// TODO:
// stalker animation manager consists of 5 independent managers,
// they should be represented with the different classes:
//    * head
//    * torso
//    * legs
//    * globals
//    * script

CStalkerAnimationManager::CStalkerAnimationManager	(CAI_Stalker *object) :
	m_object					( object ),
	m_global					( object ),
	m_head						( object ),
	m_torso						( object ),
	m_legs						( object ),
	m_script					( object ),
	m_start_new_script_animation( false )
{
}

void CStalkerAnimationManager::reinit				()
{
	m_direction_start			= 0;
	m_current_direction			= eMovementDirectionForward;
	m_target_direction			= eMovementDirectionForward;

	m_change_direction_time		= 0;
	m_looking_back				= 0;

	m_no_move_actual			= false;
	
	m_script_animations.clear	();

	m_global.reset				();
	m_head.reset				();
	m_torso.reset				();
	m_legs.reset				();
	m_script.reset				();
	
	m_legs.step_dependence		(true);
	m_global.step_dependence	(true);
	m_script.step_dependence	(true);
	
	m_global.global_animation	(true);
	m_script.global_animation	(true);
	
	m_call_script_callback		= false;

	m_previous_speed			= 0.f;
	m_target_speed				= 0.f;
	m_last_non_zero_speed		= m_target_speed;

	m_special_danger_move		= false;
}

void CStalkerAnimationManager::reload				()
{
	m_visual					= object().Visual();

	m_crouch_state_config		= object().SpecificCharacter().crouch_type();
	VERIFY						((m_crouch_state_config == 0) || (m_crouch_state_config == 1) || (m_crouch_state_config == -1));
	m_crouch_state				= m_crouch_state_config;

	if (object().already_dead())
		return;

	m_skeleton_animated			= smart_cast<IKinematicsAnimated*>(m_visual);
	VERIFY						(m_skeleton_animated);

	m_data_storage				= stalker_animation_data_storage().object(m_skeleton_animated);
	VERIFY						(m_data_storage);

	if (!object().g_Alive())
		return;

#ifdef USE_HEAD_BONE_PART_FAKE
	VERIFY						(!m_data_storage->m_head_animations.A.empty());
	u16							bone_part = m_skeleton_animated->LL_GetMotionDef(m_data_storage->m_head_animations.A.front())->bone_or_part;
	VERIFY						(bone_part != BI_NONE);
	m_script_bone_part_mask		= CStalkerAnimationPair::all_bone_parts ^ (1 << bone_part);
#endif

	assign_bone_callbacks		();

#ifdef DEBUG
	global().set_dbg_info		(*object().cName(),"Global");
	head().set_dbg_info			(*object().cName(),"Head  ");
	torso().set_dbg_info		(*object().cName(),"Torso ");
	legs().set_dbg_info			(*object().cName(),"Legs  ");
	script().set_dbg_info		(*object().cName(),"Script");
#endif
};

void CStalkerAnimationManager::play_fx(float power_factor, int fx_index)
{
	VERIFY						(fx_index >= 0);
	VERIFY						(fx_index < (int)m_data_storage->m_part_animations.A[object().movement().body_state()].m_global.A[0].A.size());
#ifdef DEBUG
	if (psAI_Flags.is(aiAnimation)) {
		LPCSTR					name = m_skeleton_animated->LL_MotionDefName_dbg(m_data_storage->m_part_animations.A[object().movement().body_state()].m_global.A[0].A[fx_index]).first;
		Msg						("%6d [%s][%s][%s][%f]",Device.dwTimeGlobal,*object().cName(),"FX",name,power_factor);
	}
#endif
	m_skeleton_animated->PlayFX	(m_data_storage->m_part_animations.A[object().movement().body_state()].m_global.A[0].A[fx_index],power_factor);
}
