533 lines
11 KiB
C++
533 lines
11 KiB
C++
//------------------------------------------------------------------------------
|
|
// LottNPC.cpp
|
|
// (C) 2009 Webzen Sunstudio
|
|
//------------------------------------------------------------------------------
|
|
#include "SunClientPrecompiledHeader.h"
|
|
|
|
|
|
#include "LottoNPC.h"
|
|
#include "NPC.h"
|
|
#include "uiLottoMan/uiLottoMan.h"
|
|
#include "ResourceManager.h"
|
|
#include "objectmanager.h"
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
LottoNPC::LottoNPC( void )
|
|
:m_bNumberAni(FALSE),
|
|
m_bLottoActive(TRUE),
|
|
m_iOldNumber(0)
|
|
{
|
|
SetObjectType(LOTTO_NPC_OBJECT);
|
|
|
|
memset(&m_ResInfo,NULL,sizeof(m_ResInfo));
|
|
memset(&m_ppRenderPart,NULL,sizeof(m_ppRenderPart));
|
|
memset(&m_ppNumberUnit,NULL,sizeof(m_ppNumberUnit));
|
|
memset(&m_arBonPosition,-1,sizeof(m_arBonPosition));
|
|
memset(&m_arCurNumber,-1,sizeof(m_arCurNumber));
|
|
memset(&m_arOldNumber,-1,sizeof(m_arOldNumber));
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
LottoNPC::~LottoNPC( void )
|
|
{
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
BOOL LottoNPC::Create( DWORD dwObjectKey, DWORD dwID)
|
|
{
|
|
BOOL bRet = NPC::Create(dwObjectKey,dwID);
|
|
|
|
//step1:숫자오브젝트 리소스코드(숫자판+숫자유닛)
|
|
m_ResInfo.m_rNumberCode = ENGINE_RESOURCE_ID_OFFSET + 5045;
|
|
m_ResInfo.m_rBaseCode = ENGINE_RESOURCE_ID_OFFSET + 5044;
|
|
|
|
//step2:위에 리소스코드를 로드
|
|
LoadNumberObject();
|
|
|
|
//step3:숫자판때기에 그려주기위에 판때기의 숫자본위치 추출
|
|
ExtractBoneIndex();
|
|
|
|
//step4:디폴트로 숫자초기화
|
|
RefreshNumber();
|
|
|
|
//step5:서버에서는 갱신시에만 숫자정보를보내기때문에 맵입장 npc초기화시 클라에서 정보 요청해준다.
|
|
uiLottoMan* pLottoMan = GET_DIALOG_MANAGER(uiLottoMan, UIMAN_LOTTO_MAN);
|
|
|
|
if(pLottoMan)
|
|
{
|
|
pLottoMan->SEND_LOTTO_INFO_SYN(false);
|
|
}
|
|
|
|
//step6:로또매니저에 로또오브젝트키를등록한(로또정보갱신(숫자)는 매니저를통해 이뤄진다)
|
|
uiLottoMan* pLoginMan = GET_DIALOG_MANAGER(uiLottoMan, UIMAN_LOTTO_MAN);
|
|
if(pLoginMan)
|
|
{
|
|
pLoginMan->RegisterLottoKey(this->GetObjectKey());
|
|
}
|
|
|
|
SetShadowDraw(TRUE);
|
|
if(m_pBasePart)
|
|
{
|
|
m_pBasePart->EnableShadowCast(TRUE);
|
|
m_pBasePart->EnableShadowReceive(TRUE);
|
|
}
|
|
|
|
InitMeshHeight();
|
|
|
|
return bRet;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 리소스해제
|
|
*/
|
|
void LottoNPC::Destroy( void )
|
|
{
|
|
FreeNumberObject();
|
|
|
|
NPC::Destroy();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** 리소스로드
|
|
*/
|
|
void LottoNPC::LoadNumberObject()
|
|
{
|
|
//step1:베이스 파츠(숫자판때기)
|
|
m_pBasePart = ResourceManager::Instance()->AllocResourceUnitDraw(m_ResInfo.m_rBaseCode);
|
|
|
|
int i=0;
|
|
|
|
//step2:wzu(유닛파일로드)
|
|
for( i = 0 ; i < NUM_MAX_UNIT ; ++i )
|
|
{
|
|
m_ppNumberUnit[i] = ResourceManager::Instance()->AllocResourceUnit(m_ResInfo.m_rNumberCode+i);
|
|
assert(m_ppNumberUnit[i] && "리소스가 없습니다.");
|
|
}
|
|
|
|
//step3:유닛을 그려줄 UnitDraw로드
|
|
for( i = 0;i<MAX_BONE_POS;++i)
|
|
{
|
|
m_ppRenderPart[i] = (CWzUnitDraw *)Func_ContactWzd( CW_NEW_WZUNITDRAW, 0);
|
|
|
|
assert(m_ppRenderPart[i]);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 숫자판때기+숫자리소스해제
|
|
*/
|
|
void LottoNPC::FreeNumberObject()
|
|
{
|
|
//step1:베이스 파츠(숫자판때기)
|
|
if(m_pBasePart)
|
|
{
|
|
ResourceManager::Instance()->FreeResourceUnitDraw(m_pBasePart);
|
|
}
|
|
|
|
//step2:wzu(유닛파일로드)
|
|
int i=0;
|
|
|
|
for( ; i < NUM_MAX_UNIT ; ++i )
|
|
{
|
|
ResourceManager::Instance()->FreeResourceUnit(m_ResInfo.m_rNumberCode+i);
|
|
m_ppNumberUnit[i]= NULL;
|
|
}
|
|
|
|
//step3:유닛을 그려줄 UnitDraw로드
|
|
for( i = 0 ; i < MAX_BONE_POS ; ++i )
|
|
{
|
|
if(m_ppRenderPart[i])
|
|
{
|
|
g_pSunRenderer->DestroyResourceForWzUnitDraw(m_ppRenderPart[i]);
|
|
|
|
Func_ContactWzd( CW_DELETE_WZUNITDRAW, m_ppRenderPart[i] );
|
|
|
|
m_ppRenderPart[i] =NULL;
|
|
}
|
|
}
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 로또 활성.비활성
|
|
*/
|
|
void LottoNPC::SetLottoActive(BOOL bActive)
|
|
{
|
|
if(bActive==m_bLottoActive)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_bLottoActive = bActive;
|
|
|
|
uiLottoMan* pLottoMan= GET_DIALOG_MANAGER(uiLottoMan, UIMAN_LOTTO_MAN);
|
|
|
|
if(!pLottoMan)
|
|
{
|
|
return;
|
|
}
|
|
//비활성(정산):추첨채팅메시지와함께 숫자판이 숫자가 계속바뀐다
|
|
if(m_bLottoActive)
|
|
{
|
|
m_iOldNumber=-1;
|
|
SetDrawNumber(pLottoMan->GetLottoInfo()->m_i64TotalAccum);
|
|
}
|
|
else
|
|
{
|
|
//5286 %d회 로또 추첨이 시작되었습니다.
|
|
TCHAR szTemp[INTERFACE_STRING_LENGTH];
|
|
TCHAR szMessage[INTERFACE_STRING_LENGTH];
|
|
g_InterfaceManager.GetInterfaceString(5286, szTemp);
|
|
Snprintf(szMessage, INTERFACE_STRING_LENGTH, szTemp,pLottoMan->GetLottoInfo()->m_wLottoDrawNum);
|
|
AddChatMessage(szMessage);
|
|
|
|
for(int a=0;a<MAX_BONE_POS;++a)
|
|
{
|
|
m_arOldNumber[a]=a%9;
|
|
}
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** NPC셋팅정보
|
|
*/
|
|
void LottoNPC::SetExtraInfo( EXTRA_NPCINFO * pExtraInfo)
|
|
{
|
|
NPC::SetExtraInfo(pExtraInfo);
|
|
|
|
if(m_pBasePart)
|
|
{
|
|
m_pBasePart->SetPosition(pExtraInfo->m_fNPCPos[0],pExtraInfo->m_fNPCPos[1],pExtraInfo->m_fNPCPos[2]);
|
|
}
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 업데이트
|
|
*/
|
|
BOOL LottoNPC::Process( DWORD dwTick )
|
|
{
|
|
//기본 숫자판그리기
|
|
if(!m_pBasePart)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
g_pSunRenderer->ProgressUnitFrame( m_pBasePart,0.0f);
|
|
g_pSunRenderer->AnimateUnit(m_pBasePart);
|
|
|
|
//숫자판위의 숫자들
|
|
for( int i = 0 ; i < MAX_BONE_POS ; ++i )
|
|
{
|
|
if(!m_ppRenderPart[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
g_pSunRenderer->ProgressUnitFrame(m_ppRenderPart[i],0.0f);
|
|
|
|
if(m_arBonPosition[i]==-1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
WzMatrix *pBoneMatrix = m_pBasePart->GetTransformBuffer();
|
|
|
|
//본위치 숫자를 부친다
|
|
if(pBoneMatrix)
|
|
{
|
|
g_pSunRenderer->AnimateUnit(m_ppRenderPart[i],0,&pBoneMatrix[m_arBonPosition[i]]);
|
|
}
|
|
}
|
|
|
|
|
|
SetBillBoard();
|
|
|
|
BOOL bRet = Character::Process(dwTick);
|
|
|
|
//비활성상태일경우(정산중)
|
|
if(!m_bLottoActive)
|
|
{
|
|
SetChatDisplayTime(1000);
|
|
AnimationNumberChaos(dwTick);
|
|
RefreshNumber();
|
|
}
|
|
else
|
|
{
|
|
//숫자애니메이션
|
|
if(m_bNumberAni)
|
|
{
|
|
AnimationNumber(dwTick);
|
|
RefreshNumber();
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 랜더링
|
|
*/
|
|
BOOL LottoNPC::Render()
|
|
{
|
|
//숫자판
|
|
if(!m_pBasePart)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
g_pSunRenderer->RenderUnit( m_pBasePart);
|
|
|
|
//숫자들
|
|
for( int i = 0 ; i < MAX_BONE_POS ; ++i )
|
|
{
|
|
if(!m_ppRenderPart[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
g_pSunRenderer->RenderUnit( m_ppRenderPart[i] );
|
|
}
|
|
|
|
return NPC::Render();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** 본인덱스추출(각자릿수 숫자위치)
|
|
*/
|
|
void LottoNPC::ExtractBoneIndex()
|
|
{
|
|
if(!m_pBasePart)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CWzUnit* pUnit = m_pBasePart->GetWzUnit();
|
|
|
|
//유닛없으면 리턴
|
|
if(!pUnit)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TCHAR szNumber[30];
|
|
|
|
for(int i=0;i<MAX_BONE_POS;++i)
|
|
{
|
|
//arg1: 10의자리 arg2:1의자리
|
|
Sprintf (szNumber, _T("NO%d%d"), i/10,i%10);
|
|
WzBoneInfo *pInfo = pUnit->GetBoneInfo(StrToWzID(szNumber));
|
|
m_arBonPosition[i] = (pInfo ? (pInfo->m_iNode):(-1));
|
|
}
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 숫자애니메이션(숫자가 또로록올라가는 효과)
|
|
*/
|
|
void LottoNPC::AnimationNumber(DWORD dwTick)
|
|
{
|
|
static DWORD dwUpdateTick = 0;
|
|
|
|
//일정간격마다 갱신한다.
|
|
dwUpdateTick+=dwTick;
|
|
if(dwUpdateTick < 50)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwUpdateTick = 0;
|
|
|
|
int nFindTopIndex = -1;
|
|
|
|
//최상위숫자를 찾는다.
|
|
int i=0;
|
|
for(;i<MAX_BONE_POS;++i)
|
|
{
|
|
//숫자 낮으면 즉각적용
|
|
if(m_arCurNumber[i] == -1)
|
|
{
|
|
m_arOldNumber[i] = m_arCurNumber[i];
|
|
}
|
|
else
|
|
{
|
|
//높은숫자 밑으로는 죄다 올린다.
|
|
if( nFindTopIndex == -1 && m_arCurNumber[i]!=m_arOldNumber[i])
|
|
{
|
|
nFindTopIndex = i;
|
|
|
|
if(++m_arOldNumber[i]>9)
|
|
{
|
|
m_arOldNumber[i] = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//마지막으르 제외한 나머지는 ++시켜준다.
|
|
for( i=nFindTopIndex+1;i<MAX_BONE_POS;++i)
|
|
{
|
|
if(++m_arOldNumber[i]>9)
|
|
{
|
|
m_arOldNumber[i] = 0;
|
|
}
|
|
}
|
|
|
|
//더이상 애니할게 없다면 애니종료
|
|
if(nFindTopIndex==-1)
|
|
{
|
|
memcpy(&m_arOldNumber,&m_arCurNumber,sizeof(m_arCurNumber));
|
|
m_bNumberAni = FALSE;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 숫자애니메이션(규칙없이 모든자릿수가 계속돈다)
|
|
*/
|
|
void LottoNPC::AnimationNumberChaos(DWORD dwTick)
|
|
{
|
|
static DWORD dwUpdateTickChaos = 0;
|
|
|
|
//일정간격마다 갱신한다.
|
|
dwUpdateTickChaos+=dwTick;
|
|
if(dwUpdateTickChaos < 100)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwUpdateTickChaos = 0;
|
|
for(int i=0;i<MAX_BONE_POS;++i)
|
|
{
|
|
if(++m_arOldNumber[i]>9)
|
|
{
|
|
m_arOldNumber[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 숫자를 문자로 변환해 각자릿수를 분리해 배열에 담는다
|
|
*/
|
|
void LottoNPC::SetparateNumber(INT64 Number)
|
|
{
|
|
//바뀌지않았다면 리턴!
|
|
if(m_iOldNumber==Number && Number!=0)
|
|
{
|
|
m_bNumberAni = FALSE;
|
|
return;
|
|
}
|
|
|
|
m_iOldNumber = Number;
|
|
|
|
TCHAR szNumber[100]={0};
|
|
_i64toa(Number,szNumber,10);
|
|
|
|
int iLen = strlen(szNumber);
|
|
util::_tstring str(szNumber);
|
|
|
|
memset(m_arCurNumber,-1,sizeof(m_arCurNumber));
|
|
|
|
//자연스럽게 올라가는 애니를 위해
|
|
if(Number!=0)
|
|
{
|
|
for(int a=0;a<MAX_BONE_POS;++a)
|
|
{
|
|
m_arOldNumber[a]=a%9;
|
|
}
|
|
}
|
|
|
|
int nInsertPos=0;
|
|
int nCnt=0;
|
|
|
|
for(int i=0;i<iLen;++i)
|
|
{
|
|
//끝자리숫자 추출
|
|
util::_tstring tempStr = str.substr((iLen-1)-i,1);
|
|
int nNeedNum = atoi(tempStr.c_str());
|
|
|
|
int nNumPos = (MAX_BONE_POS-1)-i;
|
|
|
|
//15자리이상은 취급안한다.
|
|
if(nNumPos<0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
m_arCurNumber[nNumPos] = nNeedNum;
|
|
}
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 숫자를 셋팅한다( NPC::SetDrawNumber에의해 호출)
|
|
*/
|
|
void LottoNPC::SetDrawNumber(INT64 Number)
|
|
{
|
|
//활성화상태에서만 받겠다
|
|
if(m_bLottoActive)
|
|
{
|
|
m_bNumberAni = TRUE;
|
|
SetparateNumber(Number);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** UnitDraw의 물고있는 Unit를 교체해준다(숫자교체)
|
|
*/
|
|
void LottoNPC::RefreshNumber()
|
|
{
|
|
for( int i = 0;i<MAX_BONE_POS;++i)
|
|
{
|
|
if(!m_ppRenderPart[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(m_arOldNumber[i]== -1 || m_arOldNumber[i]>(NUM_MAX_UNIT-2) )
|
|
{
|
|
m_ppRenderPart[i]->SetWzUnit(m_ppNumberUnit[0],FALSE);
|
|
}
|
|
else
|
|
{
|
|
m_ppRenderPart[i]->SetWzUnit(m_ppNumberUnit[m_arOldNumber[i]+1],FALSE);
|
|
}
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** 숫자판 빌보드
|
|
*/
|
|
void LottoNPC::SetBillBoard()
|
|
{
|
|
static WzVector vOldAxisCam;
|
|
|
|
//카메라 행렬얻기
|
|
WzMatrix wmViewMat;
|
|
g_pSunRenderer->GetViewMatrix(&wmViewMat);
|
|
|
|
//X축에대한 빌보딩
|
|
WzVector vAxisOrg,vAxisCam;
|
|
|
|
//카메라 메트릭스의 Right(x축)성분 추출
|
|
SetVector(&vAxisCam,wmViewMat._11, wmViewMat._21,wmViewMat._31);
|
|
|
|
//값이 바뀌었을대만 한다.
|
|
if(vAxisCam==vOldAxisCam)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SetVector(&vAxisOrg,1.0f,0.0f,0.0f);
|
|
|
|
//회전축얻기
|
|
WzVector vRotAxis;
|
|
VectorCrossProduct( &vRotAxis, &vAxisOrg, &vAxisCam);
|
|
VectorNormalize( &vRotAxis, &vRotAxis);
|
|
|
|
//최종회전메트릭스얻기
|
|
WzMatrix wmFinalRot;
|
|
MatrixRotation(&wmFinalRot, &vRotAxis, acosf( VectorDotProduct( &vAxisOrg, &vAxisCam)));
|
|
m_pBasePart->SetRotationByMatrix(&wmFinalRot);
|
|
|
|
vOldAxisCam = vAxisCam;
|
|
}
|
|
|
|
|
|
|