323 lines
8.5 KiB
C++
323 lines
8.5 KiB
C++
#include "stdafx.h"
|
|
#include "SNpcResourceDB.h"
|
|
|
|
#include <Windows.h>
|
|
#include "KTypes.h"
|
|
#include <kfile/KStream.h>
|
|
#include <kfile/KFileManager.h>
|
|
#include <toolkit/XStringUtil.h>
|
|
#include "SkillBaseFile.h"
|
|
#include "ContentStruct.h"
|
|
#include "SStringDB.h"
|
|
|
|
#include "ItemBase.h"
|
|
|
|
#include "SDebug_Util.h"
|
|
|
|
extern HWND g_hWnd;
|
|
|
|
static std::vector< NpcEventPeriodResourceBase > s_vNpcEventPeriodInfo;
|
|
|
|
SNpcResourceDB* SNpcResourceDB::m_pThis = NULL;
|
|
SNpcResourceDB & GetNpcResourceDB()
|
|
{
|
|
if( NULL == SNpcResourceDB::m_pThis )
|
|
SNpcResourceDB::m_pThis = new SNpcResourceDB;
|
|
|
|
return *SNpcResourceDB::m_pThis;
|
|
// static SNpcResourceDB NpcResourceDB;
|
|
// return NpcResourceDB;
|
|
}
|
|
|
|
SNpcResourceDB::SNpcResourceDB() : m_hashNpcResource( 1 ), m_hashNpcEventPeriodResource( 1 )
|
|
{
|
|
Init();
|
|
}
|
|
|
|
SNpcResourceDB::~SNpcResourceDB()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
void SNpcResourceDB::Init()
|
|
{
|
|
Load();
|
|
}
|
|
|
|
void SNpcResourceDB::Load()
|
|
{
|
|
// NPC Resource를 로딩할 때 국가별 이벤트 NPC 제어를 같이 하기 위해 EventPeriodResource도 로딩한다.
|
|
KStream * pRess = KFileManager::Instance().CreateStreamFromResource( "db_NPCEventPeriodResource.rdb" );
|
|
if( !pRess )
|
|
return;
|
|
|
|
KStream * pRes = KFileManager::Instance().CreateStreamFromResource( "db_NPCResource.rdb" );
|
|
if( !pRes )
|
|
{
|
|
KFileManager::Instance().DeleteStream( pRess );
|
|
return;
|
|
}
|
|
|
|
GAME_DB db_hdrs, db_hdr;
|
|
|
|
pRess->Read( &db_hdrs, sizeof(db_hdrs) );
|
|
pRes->Read( &db_hdr, sizeof(db_hdr) );
|
|
|
|
#ifdef _DEV_RDB_
|
|
|
|
// RDB 와 Header의 사이즈 비교.
|
|
int fileSize = pRes->Size() - ( STR_DATE_BUFFER + sizeof( int ) );
|
|
int headerSize = sizeof(NpcResourceBase) * db_hdr.nCount;
|
|
if( fileSize != headerSize )
|
|
{
|
|
char str[512] = { NULL, };
|
|
sprintf( str, "*** RDB Error !!! ***\n\n생성날짜%s\n파일:%s\n파일사이즈:%d\n헤더사이즈:%d\n ",
|
|
db_hdr.szDate,
|
|
__FILE__,
|
|
fileSize,
|
|
headerSize
|
|
);
|
|
|
|
::MessageBox( g_hWnd, str, "Error", MB_OK );
|
|
|
|
if( ::MessageBox( g_hWnd, "RDB와 클라이언트가 맞지않습니다. 강제종료하시겠습니까?", "Error", MB_YESNO ) == IDYES )
|
|
{
|
|
exit( 1 );
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
for( int i(0); db_hdrs.nCount>i; i++ )
|
|
{
|
|
NpcEventPeriodResourceBase *pResource = new NpcEventPeriodResourceBase;
|
|
|
|
pRess->Read( pResource, sizeof( NpcEventPeriodResourceBase ) );
|
|
if( !( pResource->local_flag & GameRule::GetCurrentLocalBitSet() ) )
|
|
{
|
|
delete pResource;
|
|
continue;
|
|
}
|
|
|
|
NpcEventPeriodResourceBase *pFindNpc = NULL;
|
|
|
|
if( m_hashNpcEventPeriodResource.lookup( pResource->id, pFindNpc ) == false )
|
|
{
|
|
m_hashNpcEventPeriodResource.add( pResource->id, pResource );
|
|
}
|
|
else
|
|
{
|
|
_oprint( "!!!!Data Error NpcEventPeriodResource Code 가 중복되었습니다.!!!! \n" );
|
|
assert(0); //기획팀에 알려 주세여. 바로 수정 해야 합니다.
|
|
|
|
delete pResource;
|
|
}
|
|
}
|
|
|
|
for( int i(0); db_hdr.nCount>i; i++ )
|
|
{
|
|
NpcResourceClient * pItem = new NpcResourceClient;
|
|
memset( pItem, 0, sizeof(NpcResourceBase) );
|
|
|
|
pRes->Read( pItem, sizeof(NpcResourceBase) );
|
|
|
|
// 끝난 기간 Npc면 로딩조차 안할거임. 또한 hashNpcEventPeriodResource에 로컬 플래그가 만족되면 NpcResource의 로컬 플래그는 무시.
|
|
bool bNoUseLocalFlag = false;
|
|
NpcEventPeriodResourceBase *pFindNpc = NULL;
|
|
if( m_hashNpcEventPeriodResource.lookup( pItem->id, pFindNpc ) == true )
|
|
{
|
|
time_t nowtime;
|
|
time(&nowtime);
|
|
/*if( pFindNpc->end_of_period < nowtime )
|
|
{
|
|
if( m_hashNpcEventPeriodResource.erase( pItem->id ) )
|
|
delete pFindNpc;
|
|
|
|
delete pItem;
|
|
continue;
|
|
}*/ // 클라에서 시간 체크 제거
|
|
bNoUseLocalFlag = true;
|
|
}
|
|
|
|
// NPC 제외 국가 플래그에 의한 필터링, 단 EventPeriodResource에 ID가 있다면 필터링 안 함
|
|
if( ( pItem->local_flag & GameRule::GetCurrentLocalBitSet() ) && !bNoUseLocalFlag )
|
|
{
|
|
delete pItem;
|
|
continue;
|
|
}
|
|
|
|
pItem->real_uid = pItem->id;
|
|
|
|
pItem->id = XFastRandom();
|
|
|
|
NpcResourceClient* pFindItem = NULL;
|
|
|
|
// _oprint( "SNpcResourceDB : NPC ID : %d\n", pItem->id );
|
|
|
|
if( m_hashNpcResource.lookup( pItem->real_uid, pFindItem ) == false )
|
|
{
|
|
m_hashNpcResource.add( pItem->real_uid, pItem );
|
|
}
|
|
else
|
|
{
|
|
_oprint( "Data Error: NpcResource Code is duplicated: %i\n", (int)pItem->id ); // Fraun adjusting logs
|
|
assert(0); // Please inform the planning team. It needs to be fixed immediately.
|
|
|
|
delete pItem;
|
|
}
|
|
}
|
|
|
|
KFileManager::Instance().DeleteStream( pRes );
|
|
KFileManager::Instance().DeleteStream( pRess );
|
|
}
|
|
|
|
void SNpcResourceDB::Destroy()
|
|
{
|
|
NpcResourceClient* pItem = NULL;
|
|
bool res = false;
|
|
res = m_hashNpcResource.get_first_value( pItem );
|
|
while ( res )
|
|
{
|
|
if ( pItem != NULL )
|
|
{
|
|
delete pItem;
|
|
}
|
|
res = m_hashNpcResource.get_next_value( pItem );
|
|
}
|
|
m_hashNpcResource.clear();
|
|
|
|
NpcEventPeriodResourceBase* pRes = NULL;
|
|
res = false;
|
|
res = m_hashNpcEventPeriodResource.get_first_value( pRes );
|
|
while ( res )
|
|
{
|
|
if ( pRes != NULL )
|
|
{
|
|
delete pRes;
|
|
}
|
|
res = m_hashNpcEventPeriodResource.get_next_value( pRes );
|
|
}
|
|
m_hashNpcEventPeriodResource.clear();
|
|
}
|
|
|
|
|
|
void SNpcResourceDB::EnumNPC( std::vector< NPCRenderInfo > * pList )
|
|
{
|
|
NpcResourceClient* pNPCInfo = NULL;
|
|
bool res;
|
|
res = m_hashNpcResource.get_first_value( pNPCInfo );
|
|
while ( res )
|
|
{
|
|
std::string strNPCName = GetStringDB().GetString( pNPCInfo->text_id );
|
|
strNPCName += " ";
|
|
strNPCName += GetStringDB().GetString( pNPCInfo->name_text_id );
|
|
|
|
bool bIsPeriodic = false;
|
|
int nBeginPeriod = 0, nEndPeriod = 0;
|
|
NpcEventPeriodResourceBase *pFindNPCPeriod = NULL;
|
|
if( m_hashNpcEventPeriodResource.lookup( pNPCInfo->real_uid, pFindNPCPeriod ) )
|
|
{
|
|
bIsPeriodic = true;
|
|
nBeginPeriod = pFindNPCPeriod->begin_of_period;
|
|
nEndPeriod = pFindNPCPeriod->end_of_period;
|
|
}
|
|
|
|
// 나중에 뚫린다면...이녀석 때문일까....ㅠ.ㅠ 고칠 엄두가 안난다....ㅠㅠ by P.Lotos
|
|
pList->push_back( SNpcResourceDB::NPCRenderInfo( pNPCInfo->real_uid, strNPCName.c_str(), pNPCInfo->x, pNPCInfo->y, bIsPeriodic, nBeginPeriod, nEndPeriod, pNPCInfo->type ) );
|
|
|
|
res = m_hashNpcResource.get_next_value( pNPCInfo );
|
|
}
|
|
}
|
|
|
|
|
|
vector<NPCIDENTITYFORDEV> SNpcResourceDB::GetNpcIdentityList( string strFindNpcName )
|
|
{
|
|
vector<NPCIDENTITYFORDEV> vecNpcIdentity;
|
|
|
|
#ifdef _DEV
|
|
KHash< struct NpcResourceClient*, hashPr_mod_ENC_INT>::node* _node = NULL;
|
|
|
|
bool bResult = m_hashNpcResource.get_first_node( _node );
|
|
while ( bResult )
|
|
{
|
|
NpcResourceClient* pNpc( _node->value );
|
|
|
|
if( pNpc )
|
|
{
|
|
string strNpcName( S( pNpc->name_text_id ) );
|
|
|
|
size_t found = strNpcName.find( strFindNpcName );
|
|
|
|
if (found != string::npos)
|
|
{
|
|
NPCIDENTITYFORDEV stNpcIdentityForDev;
|
|
|
|
stNpcIdentityForDev.m_uNpcID = pNpc->real_uid.value();
|
|
stNpcIdentityForDev.m_strNpcName = strNpcName;
|
|
|
|
vecNpcIdentity.push_back( stNpcIdentityForDev );
|
|
}
|
|
}
|
|
|
|
bResult = m_hashNpcResource.get_next_node( _node );
|
|
}
|
|
#endif
|
|
|
|
return vecNpcIdentity;
|
|
}
|
|
|
|
int SNpcResourceDB::GetNpcItemCode( int nWearType, NpcResourceBase* pNpcResource )
|
|
{
|
|
if( pNpcResource == NULL )
|
|
{
|
|
// if( !m_hashNpcResource.lookup( nWearType, pNpcResource ) )
|
|
// {
|
|
return 0;
|
|
// }
|
|
}
|
|
|
|
/* WEAR_WEAPON = 0, // 오른손전용 (방패라던가)
|
|
WEAR_SHIELD = 1, // 왼손전용
|
|
WEAR_ARMOR = 2, // 갑옷
|
|
WEAR_HELM = 3, // 투구
|
|
WEAR_GLOVE = 4, // 장갑
|
|
WEAR_BOOTS = 5, // 부츠
|
|
WEAR_BELT = 6, // 벨트
|
|
WEAR_MANTLE = 7, // 망토
|
|
WEAR_ARMULET = 8, // 목걸이
|
|
WEAR_RING = 9, // 반지
|
|
// 10 은 반지 두번째 슬롯을 위해 예약
|
|
WEAR_EAR = 11, // 귀걸이
|
|
WEAR_EYE = 12, // 눈
|
|
WEAR_DECO_HAIR = 13, // 입
|
|
|
|
WEAR_EAR_EYE = 90, // 귀+눈
|
|
WEAR_EAR_MOUTH = 91, // 귀+입
|
|
WEAR_EYE_MOUTH = 92, // 눈+입
|
|
WEAR_EYE_EAR_MOUTH = 93, // 눈+귀+입
|
|
WEAR_TWOFINGER_RING = 94, // 반지 두칸 소모
|
|
WEAR_TWOHAND = 99, // 투핸드
|
|
|
|
WEAR_SKILL = 100, // 스킬*/
|
|
|
|
switch( nWearType )
|
|
{
|
|
case ItemBase::WEAR_WEAPON: return pNpcResource->weapon_item_id;
|
|
case ItemBase::WEAR_SHIELD: return pNpcResource->shield_item_id;
|
|
case ItemBase::WEAR_ARMOR: return pNpcResource->body_id;
|
|
//의상? 이건 뭐지
|
|
//case ItemBase:: return pNpcResource->clothes_item_id;
|
|
case ItemBase::WEAR_HELM: return pNpcResource->helm_item_id;
|
|
case ItemBase::WEAR_GLOVE: return pNpcResource->gloves_item_id;
|
|
case ItemBase::WEAR_BOOTS: return pNpcResource->boots_item_id;
|
|
case ItemBase::WEAR_BELT: return pNpcResource->belt_item_id;
|
|
case ItemBase::WEAR_MANTLE: return pNpcResource->mantle_item_id;
|
|
case ItemBase::WEAR_ARMULET: return pNpcResource->necklace_item_id;
|
|
case ItemBase::WEAR_EAR: return pNpcResource->earring_item_id;
|
|
case ItemBase::WEAR_RING: return pNpcResource->ring1_item_id;
|
|
//링2
|
|
case 10: return pNpcResource->ring2_item_id;
|
|
}
|
|
|
|
return 0;
|
|
} |