DragonNest/GameCommon/DnPartialPlayProcessor.cpp
2024-12-20 16:56:44 +08:00

347 lines
No EOL
22 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "DnActor.h"
#include "DnPartialPlayProcessor.h"
#include "DnStateBlow.h"
#if defined( PRE_FIX_71333 )
#include "DnMonsterActor.h"
#endif
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
CDnPartialPlayProcessor::CDnPartialPlayProcessor()
: m_fMoveSpeed( 0.0f )
, m_iTime( 0 )
, m_iNowActionState( 0 )
, m_fStartActionLength( 0.0f )
, m_fLoopActionLength( 0.0f )
, m_fElapsedTime( 0.0f )
, m_fLoopActionElapsedTime( 0.0f )
, m_bPlayEnd( false )
#ifdef PRE_FIX_71333
, m_bLoopActionEnd( false )
#endif // PRE_FIX_71333
#ifdef PRE_FIX_68898
, m_isSkipEndAction( false )
#endif // PRE_FIX_68898
{
m_iType = PARTIAL_PLAY_ANI;
m_fTimeLength = 0.0f;
}
CDnPartialPlayProcessor::CDnPartialPlayProcessor( DnActorHandle hActor,
const char* pStartActionName, const char* pLoopActionName,
const char* pEndActionName,
int iTime, float fMoveSpeed ) : IDnSkillProcessor( hActor ),
m_strStartActionName( pStartActionName ),
m_strLoopActionName( pLoopActionName ),
m_strEndActionName( pEndActionName ),
m_iTime( iTime ),
m_fMoveSpeed( fMoveSpeed ),
//m_bStartedLastAction( false ),
m_iNowActionState( -1 ),
m_fLoopActionLength( 0.0f ),
m_fElapsedTime( 0.0f ),
m_fStartActionLength( 0.0f ),
m_fLoopActionElapsedTime( 0.0f ),
m_bPlayEnd( false )
#if defined(PRE_FIX_68898)
, m_isSkipEndAction(false)
#endif // PRE_FIX_68898
#if defined( PRE_FIX_71333 )
,m_bLoopActionEnd(false)
#endif
{
m_iType = PARTIAL_PLAY_ANI;
}
CDnPartialPlayProcessor::~CDnPartialPlayProcessor(void)
{
}
void CDnPartialPlayProcessor::_UpdatePlayTime( void )
{
CEtActionBase::ActionElementStruct* pStartActionInfo = m_hHasActor->GetElement( m_strStartActionName.c_str() );
CEtActionBase::ActionElementStruct* pEndActionInfo = m_hHasActor->GetElement( m_strEndActionName.c_str() );
if( pStartActionInfo && pEndActionInfo )
{
// StartAction 은 현재 프레임에 맞춰서 끝까지 진행해야한다.
float fFPS = m_hHasActor->CDnActionBase::GetFPS();
m_fStartActionLength = (float)pStartActionInfo->dwLength / fFPS;
m_fLoopActionLength = (float)m_iTime / 1000.0f;
m_fTimeLength = m_fStartActionLength + m_fLoopActionLength + (float)pEndActionInfo->dwLength / fFPS;
}
else
{
// Note 한기: CBT 2차때 pStartActionInfo 를 찾지 못해 뻗은 케이스가 있어서 그런 상황에선 스킬을 아예 종료시킨다.
// 일반적인 상황은 아니고 캐릭터가 유령이 되면 액션 셋이 바뀌기 때문에 액션을 못찾게 되는데,,
// 남의 캐릭터가 스킬 썼다고 패킷이 왔을 당시 이미 남의 캐릭이 죽어 유령 상태인
// 경우(부활하지 못했을 수도. 아님 죽은 후 2초 정도 후에 스킬 쓴 패킷이 오거나.)가 되겠다.
m_iNowActionState = END_ACTION;
m_hHasActor->ReserveFinishSkill( m_hHasActor->GetProcessSkill() );
}
}
void CDnPartialPlayProcessor::CopyFrom( IDnSkillProcessor* pProcessor )
{
if( NULL == pProcessor )
return;
if( GetType() != pProcessor->GetType() )
return;
CDnPartialPlayProcessor* pSource = static_cast<CDnPartialPlayProcessor*>( pProcessor );
m_strStartActionName = pSource->m_strStartActionName;
m_strLoopActionName = pSource->m_strLoopActionName;
m_strEndActionName = pSource->m_strEndActionName;
m_fMoveSpeed = pSource->m_fMoveSpeed;
m_iTime = pSource->m_iTime;
#if defined(PRE_FIX_68898)
m_isSkipEndAction = pSource->m_isSkipEndAction;
#endif // PRE_FIX_68898
#if defined(PRE_FIX_71333 )
if( m_hParentSkill && (m_hParentSkill->GetClassID() == 33175 || m_hParentSkill->GetClassID() == 33176) )
{
g_Log.Log(LogType::_PROFESSORK_SKILL, L"[CDnPartialPlayProcessor::CopyFrom -> Skill Probelm] SkillID:%d CurrentAction:%S Source->m_iTiem:%d\r\n", m_hParentSkill->GetClassID(), m_hHasActor->GetCurrentAction(), pSource->m_iTime);
}
if( pSource->m_iTime - m_iTime > 6000 )
{
g_Log.Log(LogType::_PROFESSORK_SKILL, L"[CDnPartialPlayProcessor::CopyFrom -> Time Problem] SkillID:%d CurrentAction:%S Source->m_iTiem:%d\r\n", m_hParentSkill->GetClassID(), m_hHasActor->GetCurrentAction(), pSource->m_iTime);
}
#endif
}
void CDnPartialPlayProcessor::OnBegin( LOCAL_TIME LocalTime, float fDelta, DnSkillHandle hParentSkill )
{
if( m_hHasActor )
{
m_iNowActionState = START_ACTION;
m_fElapsedTime = 0.0f;
m_fStartActionLength = 0.0f;
m_fLoopActionLength = 0.0f;
m_fLoopActionElapsedTime = 0.0f;
m_bPlayEnd = false;
m_hHasActor->SetMovable( false );
m_hHasActor->SetActionQueue( m_strStartActionName.c_str() );
_UpdatePlayTime();
#if defined(PRE_FIX_68898)
m_isSkipEndAction = false;
#endif // PRE_FIX_68898
#if defined( PRE_FIX_71333 )
m_bLoopActionEnd = false;
#endif
}
}
void CDnPartialPlayProcessor::Process( LOCAL_TIME LocalTime, float fDelta )
{
if( !m_hHasActor )
return;
if( m_bPlayEnd )
return;
// 시작과 끝 액션은 끝까지 해야하므로 프레임 변경에 의한 지속시간을 누적으로 처리해야한다.
if( m_iNowActionState == START_ACTION ||
m_iNowActionState == END_ACTION )
{
float fFPS = m_hHasActor->CDnActionBase::GetFPS();
m_fElapsedTime += fDelta * (fFPS/60.0f);
}
else
{
m_fElapsedTime += fDelta;
}
_UpdatePlayTime();
// 시작 액션이 끝나면 루핑 액션으로 넘어감
switch( m_iNowActionState )
{
case START_ACTION:
if( m_fElapsedTime >= m_fStartActionLength )
m_iNowActionState = LOOP_ACTION;
break;
// 루핑 액션인 경우 Z 축으로 이동 시키고 끝나는 시점 찝어냄
case LOOP_ACTION:
//m_fLoopActionLength -= fDelta;
//m_fLoopActionElapsedTime += fDelta * (fFPS/60.0f);
m_fLoopActionElapsedTime += fDelta; // 루프 액션은 기존대로 frame 변경에 대한 영향을 받지 않도록 처리. #
// #24949
if( 0 == m_hHasActor->GetCantXZMoveSEReferenceCount() )
{
m_hHasActor->MoveZ( m_fMoveSpeed * fDelta );
}
//if( m_fLoopActionLength <= 0.0f )
if( m_fLoopActionLength < m_fLoopActionElapsedTime )
{
//m_fLoopActionLength = 0.0f;
if( false == m_hHasActor->IsDie() )
{
m_hHasActor->SetMovable( false );
#if defined(PRE_FIX_68898)
#if defined( PRE_FIX_71333 )
if(m_isSkipEndAction == false)
{
m_bLoopActionEnd = m_hHasActor->SetActionQueue( m_strEndActionName.c_str() );
#if defined( _GAMESERVER )
if( !m_bLoopActionEnd )
{
if( m_hHasActor->IsMonsterActor() )
{
CDnMonsterActor* pMonster = (CDnMonsterActor *)m_hHasActor.GetPointer();
if( pMonster->GetGrade() >= CDnMonsterState::Boss )
g_Log.Log(LogType::_PROFESSORK_SKILL, L"[CDnPartialPlayProcessor::Process] Loop Action SetActionQueue Fail MonsterID:%d StartActionName:%S EndActionName:%S CurrentAction:%S \r\n", pMonster->GetMonsterClassID(), m_strStartActionName.c_str(), m_strEndActionName.c_str(), m_hHasActor->GetCurrentAction());
}
}
#endif // #if defined( _GAMESERVER )
}
else
{
m_bLoopActionEnd = true;
#if defined( _GAMESERVER )
if( m_hHasActor->IsMonsterActor() )
{
CDnMonsterActor* pMonster = (CDnMonsterActor *)m_hHasActor.GetPointer();
g_Log.Log(LogType::_PROFESSORK_SKILL, L"[CDnPartialPlayProcessor::Process] m_isSkipEndAction Error MonsterID:%d StartActionName:%S EndActionName:%S CurrentAction:%S \r\n",pMonster->GetMonsterClassID(), m_strStartActionName.c_str(), m_strEndActionName.c_str(), m_hHasActor->GetCurrentAction());
}
#endif // #if defined( _GAMESERVER )
}
#else // #if defined( PRE_FIX_71333 )
if (m_isSkipEndAction == false)
m_hHasActor->SetActionQueue( m_strEndActionName.c_str() );
#endif // #if defined( PRE_FIX_71333 )
#else // #if defined(PRE_FIX_68898)
m_hHasActor->SetActionQueue( m_strEndActionName.c_str() );
#endif // PRE_FIX_68898
m_iNowActionState = END_ACTION;
}
}
break;
case END_ACTION:
// 종료 액션 진행 중...
if( m_fTimeLength < m_fElapsedTime )
{
m_bPlayEnd = true;
m_fTimeLength = 0.0;
}
break;
}
// 공격이 끊겼을 경우엔 중단시킨다.
// 스탠드 액션 변경 상태효과가 있으면 loop 중에 중지 되지 않는다.
if( false == m_hHasActor->GetStateBlow()->IsApplied( STATE_BLOW::BLOW_121 ) )
{
if( false == m_hHasActor->IsAttack() )
{
m_bPlayEnd = true;
m_fTimeLength = 0.0f;
}
}
}
void CDnPartialPlayProcessor::OnEnd( LOCAL_TIME LocalTime, float fDelta )
{
// 중간에 끊기는 경우 라스트 액션 그냥 재생해 줌.
if( END_ACTION != m_iNowActionState )
{
if( m_hHasActor && !m_hHasActor->IsDie() )
{
// 행동 불가일 때는 공격, 스킬사용 못함
// 따라서 여기서 임시로 해제 했다가 다시 걸어주도록 하자.
bool bCantAction = false;
if( (m_hHasActor->GetStateEffect() & CDnActorState::Cant_AttackAction) == CDnActorState::Cant_AttackAction )
{
bCantAction = true;
m_hHasActor->SetStateEffect( m_hHasActor->GetStateEffect() & ~CDnActorState::Cant_AttackAction );
}
// 맞았을 때는 그냥 히트 액션 실행
if( false == m_hHasActor->IsHit() )
{
m_hHasActor->SetMovable( false );
#if defined(PRE_FIX_68898)
#if defined( PRE_FIX_71333 )
if (m_isSkipEndAction == false)
{
m_bLoopActionEnd = m_hHasActor->SetActionQueue( m_strEndActionName.c_str() );
if( !m_bLoopActionEnd )
{
// 루프 액션이 끝나고 엔드액션을 넣을때 어떤 이유로든 실패가 되면 루프가 안끝나게 되므로 강제로 엔드액션을 실행시킴
m_hHasActor->SetAction( m_strEndActionName.c_str(), 0, 3 );
}
#if defined( _GAMESERVER )
if( !m_bLoopActionEnd )
{
if( m_hHasActor->IsMonsterActor() )
{
CDnMonsterActor* pMonster = (CDnMonsterActor *)m_hHasActor.GetPointer();
if( pMonster->GetGrade() >= CDnMonsterState::Boss )
g_Log.Log(LogType::_PROFESSORK_SKILL, L"[CDnPartialPlayProcessor::OnEnd] End Action SetActionQueue Fail MonsterID:%d StartActionName:%S EndActionName:%S CurrentAction:%S \r\n", pMonster->GetMonsterClassID(), m_strStartActionName.c_str(), m_strEndActionName.c_str(), m_hHasActor->GetCurrentAction());
}
}
#endif // #if defined( _GAMESERVER )
}
#if defined( _GAMESERVER )
else
{
if( m_hHasActor->IsMonsterActor() )
{
CDnMonsterActor* pMonster = (CDnMonsterActor *)m_hHasActor.GetPointer();
g_Log.Log(LogType::_PROFESSORK_SKILL, L"[CDnPartialPlayProcessor::Process] m_isSkipEndAction Error MonsterID:%d StartActionName:%S EndActionName:%S CurrentAction:%S \r\n",pMonster->GetMonsterClassID(), m_strStartActionName.c_str(), m_strEndActionName.c_str(), m_hHasActor->GetCurrentAction());
}
}
#endif // #if defined( _GAMESERVER )
#else
if (m_isSkipEndAction == false)
m_hHasActor->SetActionQueue( m_strEndActionName.c_str() );
m_isSkipEndAction = false;
#endif
#else
m_hHasActor->SetActionQueue( m_strEndActionName.c_str() );
#endif // PRE_FIX_68898
}
if( bCantAction )
{
m_hHasActor->SetStateEffect( m_hHasActor->GetStateEffect() | CDnActorState::Cant_AttackAction );
}
}
}
#if defined( PRE_FIX_71333 )
if( END_ACTION == m_iNowActionState )
{
if( !m_bLoopActionEnd )
{
// 루프 액션이 끝나고 엔드액션을 넣을때 어떤 이유로든 실패가 되면 루프가 안끝나게 되므로 강제로 엔드액션을 실행시킴
m_hHasActor->SetAction( m_strEndActionName.c_str(), 0, 3 );
}
}
m_bLoopActionEnd = false;
#endif
}