433 lines
11 KiB
C++
433 lines
11 KiB
C++
#include "stdafx.h"
|
|
#include ".\sgameNpc.h"
|
|
|
|
#include "GameDefine.h"
|
|
#include "KSeqAvatarEx.h"
|
|
#include "KSeqModel.h"
|
|
|
|
#include "SNpcDB.h"
|
|
#include "SGameAniType.h"
|
|
#include "SAvatarProperty.h"
|
|
#include "SGameMessage.h"
|
|
#include "SGameViewPort.h"
|
|
|
|
#include "SAvatarStateMachine.h"
|
|
|
|
#include "SDebug_Util.h"
|
|
#include "SNpcResourceDB.h" /// 2011.06.14 - prodongi
|
|
|
|
const char * pNPC_QUEST_FILE[3][3] =
|
|
{
|
|
/// 2011.04.26 기존의 start, loop, end 모데링이 파일명만 다르고 똑같아서, 모델을 하나씩만 쓰도록 함,
|
|
/// 소스상에 정리가 필요한데, 추후에 하기로 함, - prodongi
|
|
/*
|
|
{"rcfx_questbegin01_start_lv01.nx3", "rcfx_questbegin01_loop_lv01.nx3", "rcfx_questbegin01_end_lv01.nx3"},
|
|
{"rcfx_questing01_start_lv01.nx3" , "rcfx_questing01_loop_lv01.nx3" , "rcfx_questing01_end_lv01.nx3" },
|
|
{"rcfx_questOK01_start_lv01.nx3" , "rcfx_questOK01_loop_lv01.nx3" , "rcfx_questOK01_end_lv01.nx3" },
|
|
*/
|
|
{"common_mark_npc_quest_start.nx3", "common_mark_npc_quest_start.nx3", "common_mark_npc_quest_start.nx3"},
|
|
{"common_mark_npc_quest_on.nx3" , "common_mark_npc_quest_on.nx3" , "common_mark_npc_quest_on.nx3" },
|
|
{"common_mark_npc_quest_end.nx3" , "common_mark_npc_quest_end.nx3" , "common_mark_npc_quest_end.nx3" },
|
|
};
|
|
|
|
const char * pNPC_QUEST_FLAG[3][3] =
|
|
{
|
|
{ "STARTABLE_start" , "STARTABLE_loop" , "STARTABLE_end" },
|
|
{ "IN_PROGRESS_start", "IN_PROGRESS_loop" , "IN_PROGRESS_end" },
|
|
{ "FINISHABLE_start" , "FINISHABLE_loop" , "FINISHABLE_end" },
|
|
};
|
|
|
|
bool SGameNpc::s_bForceRender = true;
|
|
|
|
SGameNpc::SGameNpc( ENC_INT nNpcID ) : SGamePlayer( nNpcID )
|
|
{
|
|
m_pStateVM = new SNpcStateMachine; //상태 머신
|
|
m_pStateVM->SetReceiver( this );
|
|
|
|
m_nNPCID = nNpcID;
|
|
|
|
m_pQuestFinish = NULL;
|
|
m_pQuestIng = NULL;
|
|
m_pQuestStart = NULL;
|
|
|
|
m_vFixedView = K3DVector( 0.f, 0.f, 0.f );
|
|
m_vOldTargetPos = K3DVector( 0.f, 0.f, 0.f );
|
|
|
|
m_bUseRot = false;
|
|
m_fTargetRoll = 1.f;
|
|
m_fPresentRoll = 1.f;
|
|
|
|
m_hTargetHandle = 0;
|
|
m_seqMark = NULL; /// 2011.06.14 - prodongi
|
|
|
|
Init();
|
|
}
|
|
|
|
SGameNpc::~SGameNpc()
|
|
{
|
|
SAFE_DELETE( m_pQuestFinish );
|
|
SAFE_DELETE( m_pQuestIng );
|
|
SAFE_DELETE( m_pQuestStart );
|
|
SAFE_DELETE(m_seqMark); /// 2011.06.14 - prodongi
|
|
}
|
|
|
|
void SGameNpc::SetNpcTargetHandle( AR_HANDLE hTarget )
|
|
{
|
|
m_hTargetHandle = hTarget;
|
|
if( m_hTargetHandle == 0 )
|
|
{
|
|
m_vOldTargetPos = K3DVector( 0.f, 0.f, 0.f );
|
|
K3DVector vPos = *GetPosition();
|
|
vPos += m_vFixedView * 5.0f;
|
|
SetViewVector( vPos );
|
|
}
|
|
}
|
|
|
|
void SGameNpc::SetViewVectorAngle( float fAngle )
|
|
{
|
|
K3DVector vCur = GetCurPosWithChangeDir();
|
|
|
|
//방향 설정
|
|
K3DMatrix mat, matRot, matTrans;
|
|
K3DMatrixIdentity(matRot);
|
|
K3DMatrixIdentity(matTrans);
|
|
|
|
//무작위 회전
|
|
/* float fRandom = (float)rand() / (float)RAND_MAX;
|
|
fAngle = ((fRandom * (float)fabs(360.0f-1.0f))+1.0f);*/
|
|
|
|
//북쪽이 기준이다
|
|
K3DMatrixRotationZ( matRot, (fAngle+270.f) * ( (D3DX_PI * 2.f) / 360.f ) );
|
|
GetHeight( vCur.x, vCur.y, vCur.z,m_wCurTile );
|
|
K3DMatrixTranslation( matTrans, vCur.x, vCur.y, vCur.z );
|
|
|
|
K3DMatrixMultiply( mat, matTrans, matRot );
|
|
|
|
SetTransform(mat);
|
|
|
|
//북쪽이 기준
|
|
K3DVectorTransform( m_vFixedView, K3DVector( 0.f, -1.f, 0.f ), matRot );
|
|
|
|
K3DVector vPos = *GetPosition();
|
|
vPos += m_vFixedView * 5.0f;
|
|
m_fTargetRoll = m_fPresentRoll = atan2( vPos.y-GetPosition()->y, vPos.x-GetPosition()->x );
|
|
}
|
|
|
|
void SGameNpc::SetViewVector( const K3DVector &tpos )
|
|
{
|
|
m_fTargetRoll = atan2( tpos.y-GetPosition()->y, tpos.x-GetPosition()->x );
|
|
m_dwPrevTime = m_dwTime;
|
|
m_bUseRot = true;
|
|
}
|
|
|
|
void SGameNpc::SetStatus( unsigned status )
|
|
{
|
|
SGameAvatarEx::SetStatus( status );
|
|
|
|
CheckStatus( GetStatus() );
|
|
}
|
|
|
|
void SGameNpc::CheckStatus( unsigned status )
|
|
{
|
|
for( int i(0); 3>i; i++ )
|
|
m_bQuestFlag[i] = false;
|
|
|
|
if( status & TS_ENTER::NPCInfo::FLAG_HAS_STARTABLE_QUEST )
|
|
{
|
|
// _oprint( "NPC flag - Quest Start\n" );
|
|
if( m_pQuestStart ) m_pQuestStart->PlayAnimation( m_dwTime, pNPC_QUEST_FLAG[0][0] );
|
|
m_bQuestFlag[0] = true;
|
|
}
|
|
|
|
if( status & TS_ENTER::NPCInfo::FLAG_HAS_IN_PROGRESS_QUEST )
|
|
{
|
|
// _oprint( "NPC flag - Quest In Progress\n" );
|
|
if( m_pQuestIng ) m_pQuestIng->PlayAnimation( m_dwTime, pNPC_QUEST_FLAG[1][0] );
|
|
m_bQuestFlag[1] = true;
|
|
}
|
|
|
|
if( status & TS_ENTER::NPCInfo::FLAG_HAS_FINISHABLE_QUEST )
|
|
{
|
|
// _oprint( "NPC flag - Quest Finishable\n" );
|
|
if( m_pQuestFinish ) m_pQuestFinish->PlayAnimation( m_dwTime, pNPC_QUEST_FLAG[2][0] );
|
|
m_bQuestFlag[2] = true;
|
|
}
|
|
}
|
|
|
|
void SGameNpc::OnNetInput( struct SGameMessage * pMsg )
|
|
{
|
|
//퀘스트 상태 처리 해줘야 함.
|
|
switch( pMsg->nType )
|
|
{
|
|
case MSG_ENTER :
|
|
{
|
|
SMSG_ENTER * pEnterMsg = static_cast<SMSG_ENTER*>(pMsg);
|
|
SMSG_ENTER::NPCInfo * pNpcInfo = (SMSG_ENTER::NPCInfo *)(pEnterMsg+1);
|
|
|
|
CheckStatus( pNpcInfo->status );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SGameNpc::Init()
|
|
{
|
|
K3DMatrixIdentity( m_LocalMat );
|
|
|
|
for( int i(0); 3>i; i++ )
|
|
{
|
|
m_bQuestFlag[i] = false;
|
|
}
|
|
|
|
/// 2011.06.14 - prodongi
|
|
initMark();
|
|
}
|
|
|
|
/// 2011.06.14 - prodongi
|
|
void SGameNpc::initMark()
|
|
{
|
|
NpcResourceBase * pNpcResourceInfo = GetNpcResourceDB().GetNpcInfo(m_nNPCID);
|
|
if (!pNpcResourceInfo)
|
|
return ;
|
|
int type = pNpcResourceInfo->type;
|
|
if (2 > type || 6 < type)
|
|
return ;
|
|
|
|
char const* filename;
|
|
switch (type)
|
|
{
|
|
case 2: filename = "common_mark_npc_teleport.nx3"; break;
|
|
case 3: filename = "common_mark_npc_mount.nx3"; break;
|
|
case 4: filename = "common_mark_npc_exchange.nx3"; break;
|
|
case 5: filename = "common_mark_npc_warehouse.nx3"; break; /// 2011.08.03 - prodongi
|
|
case 6: filename = "common_mark_npc_auction.nx3"; break;
|
|
}
|
|
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
|
|
m_seqMark = new KSeqModel;
|
|
m_seqMark->AddAnimation("default", filename, KNX3Manager::SEQTYPE_ALL, &loadpack );
|
|
}
|
|
|
|
void SGameNpc::CheckAniState( class KSeqModel * pModel, const char * pCheckAniName, const char * pPlayAniName )
|
|
{
|
|
if( !pModel->IsPlaying() && _stricmp( pModel->GetCurrentAnimationName(), pCheckAniName ) == 0 )
|
|
{
|
|
pModel->PlayAnimation( m_dwTime, pPlayAniName, SEQTYPE_LOOP );
|
|
}
|
|
}
|
|
|
|
void SGameNpc::CheckTargetHandle()
|
|
{
|
|
if( m_hTargetHandle != 0)
|
|
{
|
|
SGameAvatarEx* pTarget = (SGameAvatarEx*)GetGameObject( m_hTargetHandle );
|
|
if( pTarget )
|
|
{
|
|
const K3DVector* vPosition = pTarget->GetPosition();
|
|
if( vPosition->x != m_vOldTargetPos.x || vPosition->y != m_vOldTargetPos.y )
|
|
{
|
|
m_vOldTargetPos = *vPosition;
|
|
SetViewVector( m_vOldTargetPos );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SGameNpc::Process( DWORD time, unsigned long uProcessBitVector )
|
|
{
|
|
m_LocalMat = *GetTransform();
|
|
/// 2011.04.26 위치 조정 - prodongi
|
|
//m_LocalMat._43 += 20.f;
|
|
m_LocalMat._43 += 29.f;
|
|
|
|
if( m_bQuestFlag[0] )
|
|
{
|
|
if( !m_pQuestStart )
|
|
{
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
|
|
m_pQuestStart = new KSeqModel;
|
|
for( int i(0); 3>i; i++ )
|
|
{
|
|
if( m_pQuestStart ) m_pQuestStart->AddAnimation( pNPC_QUEST_FLAG[0][i], pNPC_QUEST_FILE[0][i], KNX3Manager::SEQTYPE_ALL, &loadpack );
|
|
}
|
|
|
|
if( m_pQuestStart ) m_pQuestStart->PlayAnimation( m_dwTime, pNPC_QUEST_FLAG[0][0] );
|
|
}
|
|
|
|
m_pQuestStart->Process( time );
|
|
CheckAniState( m_pQuestStart, pNPC_QUEST_FLAG[0][0], pNPC_QUEST_FLAG[0][1] );
|
|
}
|
|
|
|
if( m_bQuestFlag[1] )
|
|
{
|
|
if( !m_pQuestIng )
|
|
{
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
|
|
m_pQuestIng = new KSeqModel;
|
|
for( int i(0); 3>i; i++ )
|
|
{
|
|
if( m_pQuestIng ) m_pQuestIng->AddAnimation( pNPC_QUEST_FLAG[1][i], pNPC_QUEST_FILE[1][i], KNX3Manager::SEQTYPE_ALL, &loadpack );
|
|
}
|
|
if( m_pQuestIng ) m_pQuestIng->PlayAnimation( m_dwTime, pNPC_QUEST_FLAG[1][0] );
|
|
}
|
|
|
|
m_pQuestIng ->Process( time );
|
|
CheckAniState( m_pQuestIng, pNPC_QUEST_FLAG[1][0], pNPC_QUEST_FLAG[1][1] );
|
|
}
|
|
|
|
if( m_bQuestFlag[2] )
|
|
{
|
|
if( !m_pQuestFinish )
|
|
{
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
|
|
m_pQuestFinish = new KSeqModel;
|
|
for( int i(0); 3>i; i++ )
|
|
{
|
|
if( m_pQuestFinish ) m_pQuestFinish->AddAnimation( pNPC_QUEST_FLAG[2][i], pNPC_QUEST_FILE[2][i], KNX3Manager::SEQTYPE_ALL, &loadpack );
|
|
}
|
|
if( m_pQuestFinish ) m_pQuestFinish->PlayAnimation( m_dwTime, pNPC_QUEST_FLAG[2][0] );
|
|
}
|
|
|
|
m_pQuestFinish->Process( time );
|
|
CheckAniState( m_pQuestFinish, pNPC_QUEST_FLAG[2][0], pNPC_QUEST_FLAG[2][1] );
|
|
}
|
|
|
|
// NPC Rotation when Activation
|
|
if (ENV().GetInt("npc_player_rotation", 0) != 0)
|
|
{
|
|
CheckTargetHandle();
|
|
}
|
|
|
|
|
|
//Load 검사?
|
|
if( !m_bIsActivated || !m_bIsInit ) return false;
|
|
|
|
/// 2011.06.14 - prodongi
|
|
procMark(time);
|
|
|
|
float roll, prevroll;
|
|
roll = fmod(m_fTargetRoll, 3.1415926f*2);
|
|
prevroll = fmod(m_fPresentRoll, 3.1415926f*2);
|
|
|
|
const float unitval = 3.1415926f/12*(time - m_dwPrevTime)/66.f;
|
|
|
|
if(fabs(roll - prevroll) > fabs(roll - prevroll - 3.1415926f*2))
|
|
prevroll += 3.1415926f*2;
|
|
else if(fabs(roll - prevroll) > fabs(roll - prevroll + 3.1415926f*2))
|
|
prevroll -= 3.1415926f*2;
|
|
|
|
float minval = min(fabs(roll - prevroll), min(fabs(roll - prevroll + 3.1415926f*2), fabs(roll - prevroll - 3.1415926f*2)));
|
|
|
|
if((roll > prevroll) && (minval > unitval))
|
|
m_fPresentRoll += unitval;
|
|
else if(roll > prevroll)
|
|
m_fPresentRoll = m_fTargetRoll;
|
|
|
|
if((roll < prevroll) && (minval > unitval))
|
|
m_fPresentRoll -= unitval;
|
|
else if(roll < prevroll)
|
|
m_fPresentRoll = m_fTargetRoll;
|
|
|
|
if( m_bUseRot )
|
|
{
|
|
K3DMatrix zRollMat;
|
|
K3DMatrixIdentity( zRollMat );
|
|
K3DMatrixRotationZ( zRollMat, m_fPresentRoll + 3.1415926f/2 );
|
|
m_vView = K3DVector( 0.f, 1.f, 0.f );
|
|
K3DVectorTransform( m_vView, m_vView, zRollMat );
|
|
|
|
zRollMat._41 = GetTransform()->_41;
|
|
zRollMat._42 = GetTransform()->_42;
|
|
zRollMat._43 = GetTransform()->_43;
|
|
|
|
SetTransform( zRollMat );
|
|
|
|
if( m_fPresentRoll == m_fTargetRoll )
|
|
m_bUseRot = false;
|
|
}
|
|
|
|
if( m_bUseRot )
|
|
{
|
|
K3DMatrix zRollMat;
|
|
K3DMatrixIdentity( zRollMat );
|
|
|
|
K3DMatrixRotationZ( zRollMat, m_fPresentRoll + 3.1415926f/2 );
|
|
m_vView = K3DVector( 0.0f, 1.0f, 0.0f );
|
|
K3DVectorTransform( m_vView, m_vView, zRollMat );
|
|
|
|
zRollMat._41 = GetTransform()->_41;
|
|
zRollMat._42 = GetTransform()->_42;
|
|
zRollMat._43 = GetTransform()->_43;
|
|
|
|
SetTransform( zRollMat );
|
|
|
|
if( m_fPresentRoll == m_fTargetRoll )
|
|
m_bUseRot = false;
|
|
}
|
|
|
|
return SGameAvatarEx::Process( time, uProcessBitVector );
|
|
}
|
|
|
|
bool SGameNpc::Render( unsigned long uRenderBitVector, class KViewportObject** ppViewportList, int nViewportCount)
|
|
{
|
|
if( GetForceRender() == false ) return false;
|
|
|
|
for(int i = 0; i < nViewportCount; ++i)
|
|
{
|
|
if(ppViewportList[i]->GetAttributes() & KViewportObject::VIEWPORT_GAME)
|
|
{
|
|
if( m_pQuestStart && m_bQuestFlag[0] ) { m_pQuestStart ->SetTransform( m_LocalMat ); m_pQuestStart ->Render( ppViewportList[i] ); }
|
|
if( m_pQuestIng && m_bQuestFlag[1] ) { m_pQuestIng ->SetTransform( m_LocalMat ); m_pQuestIng ->Render( ppViewportList[i] ); }
|
|
if( m_pQuestFinish && m_bQuestFlag[2] ) { m_pQuestFinish->SetTransform( m_LocalMat ); m_pQuestFinish->Render( ppViewportList[i] ); }
|
|
/// 2011.06.14 - prodongi
|
|
renderMark(ppViewportList[i]);
|
|
}
|
|
}
|
|
|
|
return SGameAvatarEx::Render( uRenderBitVector, ppViewportList, nViewportCount );
|
|
}
|
|
|
|
/// 2011.06.14 - prodongi
|
|
void SGameNpc::procMark(DWORD time)
|
|
{
|
|
if (!m_seqMark) return ;
|
|
if( m_pQuestStart && m_bQuestFlag[0] ) return ;
|
|
if( m_pQuestIng && m_bQuestFlag[1] ) return ;
|
|
if( m_pQuestFinish && m_bQuestFlag[2] ) return ;
|
|
|
|
if (!m_seqMark->IsPlaying())
|
|
{
|
|
m_seqMark->PlayAnimation(m_dwTime, "default", KSeqModel::SEQTYPE_LOOP);
|
|
}
|
|
m_seqMark->Process(time);
|
|
}
|
|
|
|
void SGameNpc::renderMark(KViewportObject* viewportList)
|
|
{
|
|
if (!m_seqMark) return ;
|
|
if( m_pQuestStart && m_bQuestFlag[0] ) return ;
|
|
if( m_pQuestIng && m_bQuestFlag[1] ) return ;
|
|
if( m_pQuestFinish && m_bQuestFlag[2] ) return ;
|
|
|
|
m_seqMark->SetTransform(m_LocalMat);
|
|
m_seqMark->Render(viewportList);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|