#include "stdafx.h" #include "SNpcResourceDB.h" #include #include "KTypes.h" #include #include #include #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 SNpcResourceDB::GetNpcIdentityList( string strFindNpcName ) { vector 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; }