#include "StdAfx.h" #include "DnSkillTreeSystem.h" #include "DnTableDB.h" #if defined(_VILLAGESERVER) || defined(_GAMESERVER) #include "DNGameDataManager.h" #else #include "DNTableFile.h" #endif #include "DnCommonUtil.h" #ifdef _DEBUG #define new new(_NORMAL_BLOCK,__FILE__,__LINE__) #endif CDnSkillTreeSystem::CDnSkillTreeSystem(void) { } CDnSkillTreeSystem::~CDnSkillTreeSystem(void) { SAFE_DELETE_PVEC( m_vlpJobSkillTreeList ); } bool CDnSkillTreeSystem::InitializeTable( void ) { bool bResult = true; // ½ºÅ³ Å×À̺í·ÎºÎÅÍ ÇÊ¿ä Á÷¾÷ Á¤º¸/ ¶ô/¾ð¶ô Á¤º¸ ¹× ÇÊ¿äÇÑ ½ºÅ³ºÏ ItemID ¸¦ ¾ò¾î¿È. DNTableFileFormat* pSkillTable = GetDNTable( CDnTableDB::TSKILL ); DNTableFileFormat* pSkillLevelTable = GetDNTable( CDnTableDB::TSKILLLEVEL ); DNTableFileFormat* pSkillTreeTable = GetDNTable( CDnTableDB::TSKILLTREE ); int iNumSkill = pSkillTable->GetItemCount(); for( int iIndex = 0; iIndex < iNumSkill; ++iIndex ) { int iSkillID = pSkillTable->GetItemID( iIndex ); // Æ®¸®Å×ÀÌºí¿¡¼­ ¿¬°üµÈ Å×À̺í ID ¾ò¾î¿È. vector vlSkillTreeTableItemID; pSkillTreeTable->GetItemIDListFromField( "_SkillTableID", iSkillID, vlSkillTreeTableItemID ); if( (int)vlSkillTreeTableItemID.empty() ) continue; _ASSERT( (int)vlSkillTreeTableItemID.size() == 1 ); int iTreeTableID = vlSkillTreeTableItemID.front(); // ½ºÅ³ ÃÖÃÊ È¹µæ½Ã ÇÊ¿äÇÑ SP ´Â ½ºÅ³ ·¹º§Å×ÀÌºí¿¡ ÀÖ´Â ÇÊ¿ä SP 1·¾Â¥¸®¿¡¼­ ¾ò¾î¿Â´Ù. vector vlSkillLevelList; // pve ±âÁØÀ¸·Î ó¸®ÇÏ¸é µÈ´Ù. pSkillLevelTable->GetItemIDListFromField( "_SkillIndex", iSkillID, vlSkillLevelList ); // pve, pvp ´ë»óÀÎÁö È®ÀÎÇÏ¿© °É·¯³¿. vector::iterator iterLevelList = vlSkillLevelList.begin(); for( iterLevelList; iterLevelList != vlSkillLevelList.end(); ) { int iSkillLevelTableID = *iterLevelList; int iApplyType = pSkillLevelTable->GetFieldFromLablePtr( iSkillLevelTableID, "_ApplyType" )->GetInteger(); if( iApplyType != 0 ) iterLevelList = vlSkillLevelList.erase( iterLevelList ); else ++iterLevelList; } _ASSERT( false == vlSkillLevelList.empty() ); // if (vlSkillLevelList.empty() == true) continue; int iSkillLevelTableID = vlSkillLevelList.front(); int iNeedJobID = pSkillTable->GetFieldFromLablePtr( iSkillID, "_NeedJob" )->GetInteger(); map::iterator iter = m_mapSkillTreeByJobID.find( iNeedJobID ); if( m_mapSkillTreeByJobID.end() == iter ) { S_SKILLTREE_INFO* pNewTree = new S_SKILLTREE_INFO; pNewTree->iJobID = iNeedJobID; m_mapSkillTreeByJobID.insert( make_pair(iNeedJobID, pNewTree) ); m_vlpJobSkillTreeList.push_back( pNewTree ); pNewTree->vlNodeRenderInfo.assign( MAX_SKILL_SLOT_COUNT, S_NODE_RENDER_INFO() ); } S_SKILLTREE_INFO* pTree = m_mapSkillTreeByJobID[ iNeedJobID ]; S_NODE_INFO* pNodeInfo = new S_NODE_INFO; pNodeInfo->iSkillID = iSkillID; pNodeInfo->iJobID = iNeedJobID; pNodeInfo->iNeedSkillPointToAcquire = pSkillLevelTable->GetFieldFromLablePtr( iSkillLevelTableID, "_NeedSkillPoint" )->GetInteger(); pNodeInfo->iTreeSlotIndex = pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, "_TreeSlotIndex" )->GetInteger(); pNodeInfo->bDefaultLocked = (pSkillTable->GetFieldFromLablePtr( iSkillID, "_Lock" )->GetInteger() == 1) ? true : false; #if defined( PRE_ADD_PRESET_SKILLTREE ) char szLabel[256] = {0,}; for( int itr = 0; itr < E_ADVICE_SKILL_LEVEL_COUNT; ++itr ) { sprintf_s( szLabel, _countof(szLabel), "_AdviceSkillLevel%d", itr + 1 ); int nAdviceSkillLevel = pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, szLabel )->GetInteger(); pNodeInfo->vecAdviceSkillLevel.push_back( nAdviceSkillLevel ); } #endif // #if defined( PRE_ADD_PRESET_SKILLTREE ) #if defined( PRE_ADD_ONLY_SKILLBOOK ) pNodeInfo->bNeedSkillBook = (pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, "_NeedSkillBook" )->GetInteger() == 1) ? true : false; #endif // #if defined( PRE_ADD_ONLY_SKILLBOOK ) // ȹµæÁ¶°Ç Á¤º¸ char caLabel[ 32 ]; pNodeInfo->UnLockCondition.iUnlockSkillBookItemID = pSkillTable->GetFieldFromLablePtr( iSkillID, "_UnlockSkillBookItemID" )->GetInteger(); pNodeInfo->AcquireCondition.iNeedLevel = pSkillLevelTable->GetFieldFromLablePtr( iSkillLevelTableID, "_LevelLimit" )->GetInteger(); for( int i = 0; i < MAX_PARENT_SKILL_COUNT; ++i ) { // Á¤ÀǵÇÁö ¾ÊÀº °ªÀº 0 ÀÏ ¼öµµ ÀÖ´Ù. sprintf_s( caLabel, "_NeedParentSkillLevel%d", i + 1 ); int iNeedLevel = pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, caLabel )->GetInteger(); if( 0 != iNeedLevel ) pNodeInfo->AcquireCondition.vlParentSkillNeedLevel.push_back( iNeedLevel ); } // ÃÖ´ë ½½·Ô Å©±â°¡ ³Ñ¾î°¬À½. ÇÁ·Î±×·¥À» Á¾·á½ÃŰ´Â °Í À̿ܿ¡´Â ´äÀÌ ¾ø´Ù! _ASSERT( pNodeInfo->iTreeSlotIndex < (int)pTree->vlNodeRenderInfo.size() ); pTree->vlNodeRenderInfo.at( pNodeInfo->iTreeSlotIndex ) = S_NODE_RENDER_INFO( iSkillID, pNodeInfo->iTreeSlotIndex, iNeedJobID, &pNodeInfo->UnLockCondition, &pNodeInfo->AcquireCondition ); pNodeInfo->pNodeRenderInfo = &(pTree->vlNodeRenderInfo[pNodeInfo->iTreeSlotIndex]); pTree->vlpNodeList.push_back( pNodeInfo ); pTree->mapNodeBySkillID.insert( make_pair(iSkillID, pNodeInfo) ); m_mapNodeListBySkillBookID.insert( make_pair(pNodeInfo->UnLockCondition.iUnlockSkillBookItemID, pNodeInfo) ); } // ºÎ¸ðÀÚ½Ä ±¸¼º Á¤º¸ ¹× Æ®¸® ±¸¼º¿¡ ´ëÇÑ µ¥ÀÌÅ͸¦ ±¸¼ºÇÑ´Ù. _MakeupParentSkillLinks( pSkillTreeTable, pSkillTable ); return bResult; } #if defined(_VILLAGESERVER) || defined(_GAMESERVER) bool CDnSkillTreeSystem::InitializeTableUsingDataManager( CDNGameDataManager* pDataManager ) { bool bResult = true; // ½ºÅ³ Å×À̺í·ÎºÎÅÍ ÇÊ¿ä Á÷¾÷ Á¤º¸/ ¶ô/¾ð¶ô Á¤º¸ ¹× ÇÊ¿äÇÑ ½ºÅ³ºÏ ItemID ¸¦ ¾ò¾î¿È. #ifdef _WORK DNTableFileFormat* pSkillTable; if (pDataManager->GetLoaded()) pSkillTable = CDnTableDB::GetInstance().ReLoadSox( CDnTableDB::TSKILL ); else pSkillTable = GetDNTable( CDnTableDB::TSKILL ); #else DNTableFileFormat* pSkillTable = GetDNTable( CDnTableDB::TSKILL ); #endif int iNumSkill = pSkillTable->GetItemCount(); for( int iIndex = 0; iIndex < iNumSkill; ++iIndex ) { int iSkillID = pSkillTable->GetItemID( iIndex ); // Æ®¸®Å×ÀÌºí¿¡¼­ ¿¬°üµÈ Å×À̺í ID ¾ò¾î¿È. TSkillTreeData* pSkillTreeData = pDataManager->GetSkillTreeData( iSkillID ); if( NULL == pSkillTreeData ) continue; // ½ºÅ³ ÃÖÃÊ È¹µæ½Ã ÇÊ¿äÇÑ SP ´Â ½ºÅ³ ·¹º§Å×ÀÌºí¿¡ ÀÖ´Â ÇÊ¿ä SP 1·¾Â¥¸®¿¡¼­ ¾ò¾î¿Â´Ù. const TSkillData* pSkillData = pDataManager->GetSkillData( iSkillID ); int iNeedJobID = pSkillData->nNeedJobID; map::iterator iter = m_mapSkillTreeByJobID.find( iNeedJobID ); if( m_mapSkillTreeByJobID.end() == iter ) { S_SKILLTREE_INFO* pNewTree = new S_SKILLTREE_INFO; pNewTree->iJobID = iNeedJobID; m_mapSkillTreeByJobID.insert( make_pair(iNeedJobID, pNewTree) ); m_vlpJobSkillTreeList.push_back( pNewTree ); pNewTree->vlNodeRenderInfo.assign( MAX_SKILL_SLOT_COUNT, S_NODE_RENDER_INFO() ); } S_SKILLTREE_INFO* pTree = m_mapSkillTreeByJobID[ iNeedJobID ]; S_NODE_INFO* pNodeInfo = new S_NODE_INFO; pNodeInfo->iSkillID = iSkillID; pNodeInfo->iJobID = iNeedJobID; // ½ºÅ³ ·¹º§ µ¥ÀÌÅͰ¡ ÇØ´ç ½ºÅ³ id ·Î Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì ·Î±× ³²±â°í ³Ñ±è. if( pSkillData->vLevelDataList.empty() ) { g_Log.Log( LogType::_ERROR, L"[CSkillTreeSystem::InitializeTableUsingDataManager] Not Exist SkillLevelTable Data!! SkillID: %d \r\n", iSkillID ); SAFE_DELETE( pNodeInfo ); continue; } pNodeInfo->iNeedSkillPointToAcquire = pSkillData->vLevelDataList.front().nNeedSkillPoint; pNodeInfo->iTreeSlotIndex = pSkillTreeData->nTreeSlotIndex; pNodeInfo->bDefaultLocked = pSkillData->bDefaultLocked; #if defined( PRE_ADD_ONLY_SKILLBOOK ) pNodeInfo->bNeedSkillBook = pSkillTreeData->bNeedSkillBook; #endif // #if defined( PRE_ADD_ONLY_SKILLBOOK ) // ȹµæÁ¶°Ç Á¤º¸ pNodeInfo->UnLockCondition.iUnlockSkillBookItemID = pSkillData->nUnlockSkillBookItemID; pNodeInfo->AcquireCondition.iNeedLevel = pSkillData->vLevelDataList.front().cLevelLimit; for( int i = 0; i < MAX_PARENT_SKILL_COUNT; ++i ) { // Á¤ÀǵÇÁö ¾ÊÀº °ªÀº 0 ÀÏ ¼öµµ ÀÖÀ½ int iNeedLevel = pSkillTreeData->nNeedParentSkillLevel[ i ]; if( 0 != iNeedLevel ) pNodeInfo->AcquireCondition.vlParentSkillNeedLevel.push_back( iNeedLevel ); } // ÃÖ´ë ½½·Ô Å©±â°¡ ³Ñ¾î°¬À½. ÇÁ·Î±×·¥À» Á¾·á½ÃŰ´Â °Í À̿ܿ¡´Â ´äÀÌ ¾ø´Ù! _ASSERT( pNodeInfo->iTreeSlotIndex < (int)pTree->vlNodeRenderInfo.size() ); pTree->vlNodeRenderInfo.at( pNodeInfo->iTreeSlotIndex ) = S_NODE_RENDER_INFO( iSkillID, pNodeInfo->iTreeSlotIndex, iNeedJobID, &pNodeInfo->UnLockCondition, &pNodeInfo->AcquireCondition ); pNodeInfo->pNodeRenderInfo = &(pTree->vlNodeRenderInfo[pNodeInfo->iTreeSlotIndex]); pTree->vlpNodeList.push_back( pNodeInfo ); pTree->mapNodeBySkillID.insert( make_pair(iSkillID, pNodeInfo) ); m_mapNodeListBySkillBookID.insert( make_pair(pNodeInfo->UnLockCondition.iUnlockSkillBookItemID, pNodeInfo) ); } // ºÎ¸ðÀÚ½Ä ±¸¼º Á¤º¸ ¹× Æ®¸® ±¸¼º¿¡ ´ëÇÑ µ¥ÀÌÅ͸¦ ±¸¼ºÇÑ´Ù. int iNumTreeNode = pDataManager->GetNumSkillTreeData(); for( int iIndex = 0; iIndex < iNumTreeNode; ++iIndex ) { const TSkillTreeData* pSkillTreeData = pDataManager->GetSkillTreeDataByIndex( iIndex ); //const TSkillData* pSkillData = pDataManager->GetSkillData( pSkillTreeData->nSkillID ); //int iJobID = pSkillData->nNeedJobID; S_NODE_INFO* pNodeInfo = _FindNode( pSkillTreeData->nSkillID ); if( NULL == pNodeInfo ) { OutputDebug( "[%d] ½ºÅ³ Æ®¸® Å×ÀÌºí¿£ ÀÖÀ¸³ª ½ºÅ³ Å×ÀÌºí¿¡ ¾ø´Â ½ºÅ³ ID\n", pSkillTreeData->nSkillID ); _ASSERT( !"½ºÅ³ Æ®¸® Å×ÀÌºí¿£ ÀÖÀ¸³ª ½ºÅ³ Å×ÀÌºí¿¡ ¾ø´Â ½ºÅ³ ID" ); } else { #if defined(PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP) pNodeInfo->pNodeRenderInfo->vlNeedJobSP.push_back(pSkillTreeData->nNeedBasicSP); pNodeInfo->pNodeRenderInfo->vlNeedJobSP.push_back(pSkillTreeData->nNeedFirstSP); pNodeInfo->pNodeRenderInfo->vlNeedJobSP.push_back(pSkillTreeData->nNeedSecondSP); #endif // PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP } // ºÎ¸ð ½ºÅ³ ã¾Æ¼­ ÀÚ±â ÀÚ½ÅÀ» µî·Ï½ÃŲ´Ù. for( int i = 0; i < MAX_PARENT_SKILL_COUNT; ++i ) { int iParentSkillID = pSkillTreeData->nParentSkillID[ i ]; if( 0 != iParentSkillID ) { S_NODE_INFO* pParentNodeInfo = _FindNode( iParentSkillID ); if( NULL == pParentNodeInfo ) { OutputDebug( "[%d ÀÇ ºÎ¸ð·Î ¼³Á¤µÈ %d] ½ºÅ³ Æ®¸® Å×ÀÌºí¿£ ÀÖÀ¸³ª ½ºÅ³ Å×ÀÌºí¿¡ ¾ø´Â ½ºÅ³ ID\n", pSkillTreeData->nSkillID, iParentSkillID ); _ASSERT( !"½ºÅ³ Æ®¸® Å×ÀÌºí¿£ ÀÖÀ¸³ª ½ºÅ³ Å×ÀÌºí¿¡ ¾ø´Â ½ºÅ³ ID" ); } if( pNodeInfo ) pNodeInfo->vlpParentNodeInfo.push_back( pParentNodeInfo ); if( pParentNodeInfo ) pParentNodeInfo->vlpChildNodeInfo.push_back( pNodeInfo ); } } } return bResult; } #endif CDnSkillTreeSystem::S_NODE_INFO* CDnSkillTreeSystem::_FindNode( int iSkillID ) { S_NODE_INFO* pNodeInfo = NULL; vector::iterator iter = m_vlpJobSkillTreeList.begin(); for( iter; iter != m_vlpJobSkillTreeList.end(); ++iter ) { map& mapNodeBySkillID = (*iter)->mapNodeBySkillID; map::iterator iterNode = mapNodeBySkillID.find( iSkillID ); if( mapNodeBySkillID.end() != iterNode ) { pNodeInfo = iterNode->second; } } return pNodeInfo; } #ifdef PRE_ADD_ONLY_SKILLBOOK bool CDnSkillTreeSystem::IsNeedSkillBook( int iSkillID, bool& bExistSkill ) { S_NODE_INFO* pNodeInfo = NULL; vector::iterator iter = m_vlpJobSkillTreeList.begin(); for( iter; iter != m_vlpJobSkillTreeList.end(); ++iter ) { map& mapNodeBySkillID = (*iter)->mapNodeBySkillID; map::iterator iterNode = mapNodeBySkillID.find( iSkillID ); if( mapNodeBySkillID.end() != iterNode ) { pNodeInfo = iterNode->second; } } if( pNodeInfo ) { bExistSkill = true; return pNodeInfo->bNeedSkillBook; } bExistSkill = false; return false; } #endif // PRE_ADD_ONLY_SKILLBOOK void CDnSkillTreeSystem::_MakeupParentSkillLinks( DNTableFileFormat* pSkillTreeTable, DNTableFileFormat* pSkillTable ) { // ºÎ¸ð/ÀÚ½Ä ½ºÅ³ ³ëµå Á¤º¸¸¦ À̾îÁØ´Ù. int iNumTreeNode = pSkillTreeTable->GetItemCount(); for( int iIndex = 0; iIndex < iNumTreeNode; ++iIndex ) { int iTreeTableID = pSkillTreeTable->GetItemID( iIndex ); int iSkillID = pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, "_SkillTableID" )->GetInteger(); if( 0 == iSkillID ) continue; int iJobID = pSkillTable->GetFieldFromLablePtr( iSkillID, "_NeedJob" )->GetInteger(); S_NODE_INFO* pNodeInfo = _FindNode( iSkillID ); _ASSERT( pNodeInfo && "½ºÅ³ Æ®¸® Å×ÀÌºí¿£ ¾ø´Â ½ºÅ³ ID" ); if( pNodeInfo ) { // ºÎ¸ð ½ºÅ³ ã¾Æ¼­ ÀÚ±â ÀÚ½ÅÀ» µî·Ï½ÃŲ´Ù. char caLabel[ 32 ]; for( int i = 0; i < MAX_PARENT_SKILL_COUNT; ++i ) { sprintf_s( caLabel, "_ParentSkillID%d", i + 1 ); int iParentSkillID = pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, caLabel )->GetInteger(); if( 0 != iParentSkillID ) { S_NODE_INFO* pParentNodeInfo = _FindNode( iParentSkillID ); if (pParentNodeInfo == NULL) continue; pNodeInfo->vlpParentNodeInfo.push_back( pParentNodeInfo ); pNodeInfo->pNodeRenderInfo->vlParentSkillJobIDs.push_back( pParentNodeInfo->iJobID ); pNodeInfo->pNodeRenderInfo->vlParentSkillIDs.push_back( pParentNodeInfo->iSkillID ); _ASSERT( pNodeInfo->iSkillID == pNodeInfo->pNodeRenderInfo->iSkillID && "½ºÅ³ Å×ÀÌºí¿¡¼­ °°Àº Á÷¾÷±ºÀÇ ½ºÅ³ ½½·ÔÀÌ Áߺ¹µÇ¾úÀ» °¡´É¼ºÀÌ ÀÖ½À´Ï´Ù." ); if( pNodeInfo->iSkillID != pNodeInfo->pNodeRenderInfo->iSkillID ) { OutputDebug( "[SkillID: %d] ½ºÅ³ Å×ÀÌºí¿¡¼­ °°Àº Á÷¾÷±ºÀÇ ½ºÅ³ ½½·Ô(%d)ÀÌ Áߺ¹µÇ¾úÀ» °¡´É¼ºÀÌ ÀÖ½À´Ï´Ù.\n", pNodeInfo->iSkillID, pNodeInfo->pNodeRenderInfo->iSlotIndex ); } // °°Àº Á÷¾÷ Æ®¸® ¾È¿¡¼­ÀÇ ÀÚ½Ä ½½·Ô À妽º. if( pNodeInfo->iJobID == pParentNodeInfo->iJobID ) pParentNodeInfo->pNodeRenderInfo->vlChildSlotIndexInJob.push_back( pNodeInfo->iTreeSlotIndex ); pParentNodeInfo->vlpChildNodeInfo.push_back( pNodeInfo ); } } #if defined(PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP) int nLimitSPValue = pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, "_NeedBasicSP1" )->GetInteger(); pNodeInfo->pNodeRenderInfo->vlNeedJobSP.push_back(nLimitSPValue); nLimitSPValue = pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, "_NeedFirstSP1" )->GetInteger(); pNodeInfo->pNodeRenderInfo->vlNeedJobSP.push_back(nLimitSPValue); nLimitSPValue = pSkillTreeTable->GetFieldFromLablePtr( iTreeTableID, "_NeedSecondSP1" )->GetInteger(); pNodeInfo->pNodeRenderInfo->vlNeedJobSP.push_back(nLimitSPValue); #endif // PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP } } } void CDnSkillTreeSystem::TryUnLockSkill( const S_TRY_UNLOCK& PresentInfo, S_OUTPUT* pResult ) { const S_NODE_INFO* pSkillNodeInfo = _FindNode( PresentInfo.iTryUnlockSkillID ); // ÁÖ¾îÁø ½ºÅ³ Á¤º¸¿¡ ÇØ´çÇÏ´Â ½ºÅ³ ³ëµå°¡ Á¸ÀçÇϴ°¡. if( NULL == pSkillNodeInfo ) { pResult->eResult = R_ERROR; pResult->eErrorCode = E_CANT_FIND_SKILLNODE; return; } //// Á÷¾÷ÀÌ ÀÏÄ¡Çϴ°¡. È÷½ºÅ丮 µÚÁ®¼­ ÇÏÀ§ Á÷¾÷ÀÌ¸é °¡´ÉÇÏ´Ù. //if( pSkillNodeInfo->iJobID != PresentInfo.iJobID ) //{ // pResult->eResult = R_ERROR; // pResult->eErrorCode = E_MISMATCH_JOB; //} //½ºÅ³ºÏ ´õÀÌ»ó »ç¿ëÇÏÁö ¾ÊÀ½? #if defined(PRE_FIX_51727) #else // ½ºÅ³ºÏÀÌ ¸Â´ÂÁö. if( PresentInfo.iSkillBookItemID != pSkillNodeInfo->UnLockCondition.iUnlockSkillBookItemID ) { pResult->eResult = R_INVALID_SKILLBOOK_ITEMID; return; } #endif // PRE_FIX_51727 #if defined(_CLIENT) && defined( PRE_ADD_ONLY_SKILLBOOK ) if( true == pSkillNodeInfo->bNeedSkillBook ) { pResult->eResult = R_ONLY_SKILL_BOOK; return; } #endif // #if defined( PRE_ADD_ONLY_SKILLBOOK ) pResult->eResult = R_SUCCESS; } void CDnSkillTreeSystem::TryAcquireSkill( const S_TRY_ACQUIRE& TryAcquire, S_OUTPUT* pResult ) { // ÀÌ¹Ì ¹è¿î ½ºÅ³ÀÎÁö, Á÷¾÷ÀÌ ÀÏÄ¡ÇÏ´ÂÁö, Çʿ䷹º§ÀÌ ÃæÁ·µÇ´ÂÁö. const S_NODE_INFO* pSkillNodeInfo = _FindNode( TryAcquire.iTryAcquireSkillID ); // ¼±Çà(ºÎ¸ð)½ºÅ³ ȹµæ »óÅÂ. // ÁÖ¾îÁø ½ºÅ³ Á¤º¸¿¡ ÇØ´çÇÏ´Â ½ºÅ³ ³ëµå°¡ Á¸ÀçÇϴ°¡. if( NULL == pSkillNodeInfo ) { pResult->eResult = R_ERROR; pResult->eErrorCode = E_CANT_FIND_SKILLNODE; return; } // ¼±Çà ½ºÅ³ÀÌ Á¸ÀçÇÑ´Ù¸é ȹµæÇÑ »óÅÂÀΰ¡. // SkillInfo ±¸Á¶Ã¼¿¡ ¸Â´Â ÇÔ¼ö °´Ã¼. struct FindSkill : unary_function { int m_iSkillIDToFind; FindSkill( int iSkillID ) : m_iSkillIDToFind( iSkillID ) {}; bool operator () ( const S_POSSESSED_SKILL_INFO& SkillInfo ) { return SkillInfo.iSkillID == m_iSkillIDToFind; } }; //// Á÷¾÷ÀÌ ÀÏÄ¡Çϴ°¡. È÷½ºÅ丮 µÚÁ®¼­ ÇÏÀ§ Á÷¾÷ÀÌ¸é °¡´ÉÇÏ´Ù. //if( pSkillNodeInfo->iJobID != TryAcquire.iJobID ) //{ // pResult->eResult = R_ERROR; // pResult->eErrorCode = E_MISMATCH_JOB; //} // ÇÊ¿ä ·¹º§ÀÌ ÃæÁ·µÇ´ÂÁö... ±Ùµ¥ ¾ð¶ôÇÒ ¶§´Â ·¹º§ üũ ¾ÈÇÏ´Â °ÇÁö ¹°¾îºÁ¾ß°Ú±º. if( TryAcquire.iCurrentCharLevel < pSkillNodeInfo->AcquireCondition.iNeedLevel ) { pResult->eResult = R_NOT_ENOUGH_CHAR_LEVEL; return; } // º¸À¯ÇÑ ½ºÅ³ Æ÷ÀÎÆ®°¡ ¿ä±¸ Æ÷ÀÎÆ®º¸´Ù ¸¹ÀºÁö üũ. if( TryAcquire.iHasSkillPoint < pSkillNodeInfo->iNeedSkillPointToAcquire ) { pResult->eResult = R_NOT_ENOUGH_SKILLPOINT_TO_ACQUIRE; return; } // ºÎ¸ð ½ºÅ³ÀÌ ÃæÁ·µÇ´ÂÁö. ºÎ¸ð½ºÅ³ ·¹º§±îÁö ÃæÁ·µÇ¾î¾ß ÇÔ. if( false == pSkillNodeInfo->vlpParentNodeInfo.empty() ) { size_t NumParentSkill = pSkillNodeInfo->vlpParentNodeInfo.size(); for( size_t i = 0; i < NumParentSkill; ++i ) { const S_NODE_INFO* pParentNodeInfo = pSkillNodeInfo->vlpParentNodeInfo.at( i ); vector::const_iterator iter = find_if( TryAcquire.vlPossessedSkillInfo.begin(), TryAcquire.vlPossessedSkillInfo.end(), FindSkill(pParentNodeInfo->iSkillID) ); if( TryAcquire.vlPossessedSkillInfo.end() == iter ) { pResult->eResult = R_DONT_HAVE_PARENT_SKILL; return; } // ºÎ¸ð ½ºÅ³ÀÌ ¾ð¶ô »óÅÂÀ̾î¾ß ÇÔ. if( true == iter->bCurrentLock ) { pResult->eResult = R_LOCKED_PARENTSKILL; return; } // ºÎ¸ð ½ºÅ³ÀÇ ·¹º§À» Á¶°Ç ÀÌ»ó ¿Ã·ÁÁÖ¾î¾ß ÇÔ. int iParentSkillNeedLevel = pSkillNodeInfo->AcquireCondition.vlParentSkillNeedLevel.at( i ); if( iter->iSkillLevel < iParentSkillNeedLevel ) { pResult->eResult = R_NOT_ENOUGH_PARENT_SKILL_LEVEL; return; } } } pResult->eResult = R_SUCCESS; } int CDnSkillTreeSystem::GetNodeCount( int iJobID ) const { int iResult = 0; map::const_iterator iter = m_mapSkillTreeByJobID.find( iJobID ); if( m_mapSkillTreeByJobID.end() != iter ) iResult = (int)iter->second->vlpNodeList.size(); return iResult; } int CDnSkillTreeSystem::GetSlotCount( int iJobID ) const { int iResult = 0; map::const_iterator iter = m_mapSkillTreeByJobID.find( iJobID ); if( m_mapSkillTreeByJobID.end() != iter ) { // ¿ÞÂÊ¿¡¼­ ¿À¸¥ÂÊÀ¸·Î ½½·Ô À妽º°¡ ´Ã¾î³ª¹Ç·Î °¡Àå ³¡¿¡ ÀÖ´Â ½½·ÔÀ妽º°¡ °¡Àå Å©´Ù. //iResult = (int)iter->second->vlNodeRenderInfo.back().iSlotIndex + 1; iResult = MAX_SKILL_SLOT_COUNT; } return iResult; } void CDnSkillTreeSystem::GetNodeRenderInfo( int iSlotIndex, int iJobID, /*OUT*/S_NODE_RENDER_INFO* pNodeRenderInfo ) const { _ASSERT( pNodeRenderInfo ); if( NULL == pNodeRenderInfo ) return; map::const_iterator iter = m_mapSkillTreeByJobID.find( iJobID ); if( m_mapSkillTreeByJobID.end() != iter ) { const S_SKILLTREE_INFO* pSkillTree = iter->second; if( NULL == pSkillTree ) return; _ASSERT( iSlotIndex < (int)pSkillTree->vlNodeRenderInfo.size() ); if( iSlotIndex < (int)pSkillTree->vlNodeRenderInfo.size() ) *pNodeRenderInfo = pSkillTree->vlNodeRenderInfo.at( iSlotIndex ); } } int CDnSkillTreeSystem::FindSkillBySkillBook( int iSkillBookItemID ) { int iResult = 0; map::iterator iter = m_mapNodeListBySkillBookID.find( iSkillBookItemID ); if( m_mapNodeListBySkillBookID.end() != iter ) { iResult = iter->second->iSkillID; } return iResult; } #ifdef PRE_ADD_LEVELUP_GUIDE void CDnSkillTreeSystem::GetLevelUpSkillInfo(std::vector& newSkillIdList, int newLevel, int jobId) { std::map::const_iterator iter = m_mapSkillTreeByJobID.find(jobId); if (m_mapSkillTreeByJobID.end() != iter) { const S_SKILLTREE_INFO* pInfo = (*iter).second; if (pInfo) { const std::vector& nodeInfoList = pInfo->vlpNodeList; std::vector::const_iterator nodeInfoIter = nodeInfoList.begin(); for (; nodeInfoIter != nodeInfoList.end(); ++nodeInfoIter) { const S_NODE_INFO* pNodeInfo = (*nodeInfoIter); if (pNodeInfo && (pNodeInfo->AcquireCondition.iNeedLevel == newLevel)) newSkillIdList.push_back(pNodeInfo->iSkillID); } } } } void CDnSkillTreeSystem::GetLevelUpSkillInfo(std::vector& newSkillIdList, int newLevel, const std::vector& jobHistoryVec) { std::vector::const_iterator& iter = jobHistoryVec.begin(); for (; iter != jobHistoryVec.end(); ++iter) { const int& jobId = *iter; if (CommonUtil::IsValidCharacterJobId(jobId) == false) continue; GetLevelUpSkillInfo(newSkillIdList, newLevel, jobId); } } #endif #if defined(PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP) void CDnSkillTreeSystem::GetNeedSPValuesByJob(int nSkillID, std::vector& nNeedSPValues) { CDnSkillTreeSystem::S_NODE_INFO* pInfo = _FindNode(nSkillID); if (pInfo && pInfo->pNodeRenderInfo) nNeedSPValues = pInfo->pNodeRenderInfo->vlNeedJobSP; } #endif // PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP int CDnSkillTreeSystem::IsParentSkill( const int nParentSkillID, const int nChildSkillID ) { S_NODE_INFO * pData = _FindNode( nChildSkillID ); if( NULL == pData ) return 0; for( DWORD itr = 0; itr < pData->vlpParentNodeInfo.size(); ++itr ) { if( nParentSkillID == pData->vlpParentNodeInfo[itr]->iSkillID ) return pData->AcquireCondition.vlParentSkillNeedLevel[itr]; } return 0; } void CDnSkillTreeSystem::GetParentSkillData( const int nChildSkillID, std::vector< std::pair > & vecParentSkillData ) { S_NODE_INFO * pData = _FindNode( nChildSkillID ); if( NULL == pData ) return; for( DWORD itr = 0; itr < pData->vlpParentNodeInfo.size(); ++itr ) vecParentSkillData.push_back( std::make_pair( pData->vlpParentNodeInfo[itr]->iSkillID, pData->AcquireCondition.vlParentSkillNeedLevel[itr] ) ); } #if defined( PRE_ADD_PRESET_SKILLTREE ) void CDnSkillTreeSystem::GetAdviceSkillTree( const int nAdviceSkill_Index, const std::vector & vecJobList, std::vector< std::pair > & vecData ) { if( E_ADVICE_SKILL_LEVEL_COUNT <= nAdviceSkill_Index ) return; vecData.clear(); for( DWORD itr = 0; itr < vecJobList.size(); ++itr ) { if( NULL == m_mapSkillTreeByJobID[ vecJobList[itr] ] ) continue; std::vector & vecNodeList = m_mapSkillTreeByJobID[ vecJobList[itr] ]->vlpNodeList; std::vector::iterator Itor = vecNodeList.begin(); for( ; Itor != vecNodeList.end(); ++Itor ) { BYTE cAdviceSkillLevel = (*Itor)->vecAdviceSkillLevel[ nAdviceSkill_Index ]; if( 0 != cAdviceSkillLevel ) vecData.push_back( std::make_pair( (*Itor)->iSkillID, cAdviceSkillLevel ) ); } } } #endif // #if defined( PRE_ADD_PRESET_SKILLTREE )