void CControlAnimationBase::ValidateAnimation()
{
    SAnimItem *item_it = m_anim_storage[cur_anim_info().motion];

    bool is_moving_anim		= !fis_zero(item_it->velocity.velocity.linear);
    bool is_moving_on_path	= m_object->control().path_builder().is_moving_on_path();

    if (is_moving_on_path && is_moving_anim) {
        m_object->dir().use_path_direction(cur_anim_info().motion == eAnimDragCorpse);
        return;
    }

    if (!is_moving_on_path && is_moving_anim) {
        cur_anim_info().motion				= eAnimStandIdle;
        m_object->move().stop				();
        return;
    }

    if (is_moving_on_path && !is_moving_anim) {
        m_object->move().stop				();
        return;
    }

    if (!m_object->control().direction().is_turning() && ((cur_anim_info().motion == eAnimStandTurnLeft) || (cur_anim_info().motion == eAnimStandTurnRight))) {
        cur_anim_info().motion		= eAnimStandIdle;
        return;
    }
}
void CControlAnimationBase::CheckReplacedAnim()
{
	for (REPLACED_ANIM_IT it=m_tReplacedAnims.begin(); m_tReplacedAnims.end()!=it ;++it) 
		if ((cur_anim_info().get_motion() == it->cur_anim) && (*(it->flag) == true)) { 
			cur_anim_info().set_motion (it->new_anim);
			return;
		}
}
void CControlAnimationBase::FX_Play(EHitSide side, float amount)
{
    if (fx_time_last_play + FX_CAN_PLAY_MIN_INTERVAL > m_object->m_dwCurrentTime) return;

    SAnimItem *anim_it = m_anim_storage[cur_anim_info().motion];
    VERIFY(anim_it);

    clamp(amount,0.f,1.f);

    shared_str	*p_str = 0;
    switch (side) {
    case eSideFront:
        p_str = &anim_it->fxs.front;
        break;
    case eSideBack:
        p_str = &anim_it->fxs.back;
        break;
    case eSideLeft:
        p_str = &anim_it->fxs.left;
        break;
    case eSideRight:
        p_str = &anim_it->fxs.right;
        break;
    }

    if (p_str && p_str->size()) smart_cast<CKinematicsAnimated*>(m_object->Visual())->PlayFX(*(*p_str), amount);

    fx_time_last_play = m_object->m_dwCurrentTime;
}
bool CControlAnimationBase::IsStandCurAnim()
{
	SAnimItem *item_it = m_anim_storage[cur_anim_info().get_motion()];
	VERIFY2(item_it, make_string("animation not found in m_anim_storage!"));;

	if (fis_zero(item_it->velocity.velocity.linear)) return true;
	return false;
}
bool CControlAnimationBase::IsStandCurAnim()
{
    SAnimItem *item_it = m_anim_storage[cur_anim_info().motion];
    VERIFY(item_it);

    if (fis_zero(item_it->velocity.velocity.linear)) return true;
    return false;
}
bool CControlAnimationBase::IsTurningCurAnim()
{
    SAnimItem *item_it = m_anim_storage[cur_anim_info().motion];
    VERIFY(item_it);

    if (!fis_zero(item_it->velocity.velocity.angular_real)) return true;
    return false;
}
void CControlAnimationBase::select_animation(bool anim_end)
{
    // start new animation
    SControlAnimationData		*ctrl_data = (SControlAnimationData*)m_man->data(this, ControlCom::eControlAnimation);
    if (!ctrl_data) return;

    if (m_state_attack && !anim_end) return;

    if (cur_anim_info().motion == eAnimAttack) m_state_attack = true;
    else m_state_attack = false;


    // перекрыть все определения и установть анимацию
    m_object->ForceFinalAnimation();

    // получить элемент SAnimItem, соответствующий текущей анимации
    SAnimItem *anim_it = m_anim_storage[cur_anim_info().motion];
    VERIFY(anim_it);

    // определить необходимый индекс
    int index;
    if (-1 != anim_it->spec_id) index = anim_it->spec_id;
    else {
        VERIFY(anim_it->count != 0);
        index = ::Random.randI(anim_it->count);
    }

    // установить анимацию
    string128	s1,s2;
    MotionID	cur_anim		= smart_cast<CKinematicsAnimated*>(m_object->Visual())->ID_Cycle_Safe(strconcat(sizeof(s2),s2,*anim_it->target_name,itoa(index,s1,10)));

    // Setup Com
    ctrl_data->global.motion	= cur_anim;
    ctrl_data->global.actual	= false;
    ctrl_data->set_speed		(m_cur_anim.speed._get_target());

    // Заполнить текущую анимацию
    string64	st,tmp;
    strconcat	(sizeof(st),st,*anim_it->target_name,itoa(index,tmp,10));
    //	sprintf_s		(st, "%s%d", *anim_it->second.target_name, index);
    m_cur_anim.name				= st;
    m_cur_anim.index			= u8(index);
    m_cur_anim.time_started		= Device.dwTimeGlobal;
    m_cur_anim.speed._set_current	(1.f);
    m_cur_anim.speed._set_target	(-1.f);
}
void CControlAnimationBase::reinit()
{
	inherited::reinit		();

	m_tAction				= ACT_STAND_IDLE;
	spec_params				= 0;

	fx_time_last_play		= 0;

	accel_init				();

	aa_time_last_attack		= 0;

	// обновить количество анимаций
	m_anim_motion_map.clear	();
	UpdateAnimCount			();

	// инициализация информации о текущей анимации
	m_cur_anim.set_motion			(eAnimStandIdle);
	m_cur_anim.index			= 0;
	m_cur_anim.time_started		= 0;
	m_cur_anim.speed._set_current	(-1.f);
	m_cur_anim.speed._set_target	(-1.f);
	m_cur_anim.blend			= 0;
	m_cur_anim.speed_change_vel	= 1.f;

	prev_motion					= cur_anim_info().get_motion(); 

	m_prev_character_velocity	= 0.01f;

	spec_anim					= eAnimUndefined;

	// test
	m_man->capture				(this, ControlCom::eControlAnimation);
	m_man->subscribe			(this, ControlCom::eventAnimationSignal);

	AA_reload					(pSettings->r_string(*(m_object->cNameSect()), "attack_params"));

	braking_mode				= false;

	m_state_attack				= false;
	m_override_animation		= eAnimUndefined;
	m_override_animation_index	= (u32)-1;
}
void   CControlAnimationBase::SetCurAnim (EMotionAnim a)
{
	cur_anim_info().set_motion(a);
}