Files
2026-06-01 12:46:52 +02:00

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