#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(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); }