#include "StdAfx.h" #include "DNUserSkill.h" #include "DNUserSession.h" #include "DNGameDataManager.h" #include "DNLogConnection.h" #include "DNMissionSystem.h" #include "DNDBConnectionManager.h" #include "DNDBConnection.h" extern TVillageConfig g_Config; CDNUserSkill::CDNUserSkill(CDNUserSession *pUserObj) : m_pUserSession(pUserObj) { m_pSkillData = m_pUserSession->GetSkillData( true ); for(DWORD i=0; iGetItem()->GetSkillPageCount(); for(int nSkillCount =0 ; nSkillCount < nOpendSkillPageCount; nSkillCount++) { for (int i = 0; i < SKILLMAX; i++){ if (m_pSkillData[nSkillCount].SkillList[i].nSkillID <= 0) continue; // µ¥ÀÌÅÍ¿¡ ¾ø´Â ½ºÅ³ ID°¡ DB ¿¡ ÀúÀåµÇ¾îÀÖ´Ù¸é ÀоîµéÀÌÁö ¾Ê´Â´Ù. const TSkillData* pSkillData = g_pDataManager->GetSkillData( m_pSkillData[nSkillCount].SkillList[i].nSkillID ); if( NULL == pSkillData ) continue; m_SkillList[nSkillCount][m_pSkillData[nSkillCount].SkillList[i].nSkillID] = m_pSkillData[nSkillCount].SkillList[i]; CDnSkillTreeSystem::S_POSSESSED_SKILL_INFO SkillInfo; SkillInfo.iSkillID = m_pSkillData[nSkillCount].SkillList[i].nSkillID; SkillInfo.iSkillLevel = m_pSkillData[nSkillCount].SkillList[i].cSkillLevel; SkillInfo.bCurrentLock = m_pSkillData[nSkillCount].SkillList[i].bLock; m_vlPossessedSkill[nSkillCount].push_back( SkillInfo ); if (m_pSkillData[nSkillCount].SkillList[i].nSkillID > 0){ for (int j = 0; j < m_pSkillData[nSkillCount].SkillList[i].cSkillLevel; j++){ nUseSkillPoint += g_pDataManager->GetNeedSkillPoint(m_pSkillData[nSkillCount].SkillList[i].nSkillID, j + 1); } } } // ¹®À彺ų üũ const TItem *pItem = m_pUserSession->GetItem()->GetGlyph( GLYPH_SPECIALSKILL ); if( pItem && pItem->nItemID ) { if( pItem->nItemID > 0 ) { TItemData *pItemData = g_pDataManager->GetItemData( pItem->nItemID ); if( pItemData && (pItemData->nSkillID > 0) ) { TSkillData *pSkillData = g_pDataManager->GetSkillData( pItemData->nSkillID ); TSkill Skill; Skill.nSkillID = pSkillData->nSkillID; Skill.cSkillLevel = 1; Skill.nCoolTime = 0; Skill.bLock = false; m_SkillList[nSkillCount][pItemData->nSkillID] = Skill; CDnSkillTreeSystem::S_POSSESSED_SKILL_INFO SkillInfo; SkillInfo.iSkillID = pItemData->nSkillID; SkillInfo.iSkillLevel = Skill.cSkillLevel; SkillInfo.bCurrentLock = Skill.bLock; m_vlPossessedSkill[nSkillCount].push_back( SkillInfo ); } } } } #ifdef PRE_ADD_SP_REVISION #ifdef _FINAL_BUILD // º¸À¯ ½ºÅ³ Æ÷ÀÎÆ® °ËÁõ. Ʋ¾îÁ® ÀÖ´õ¶óµµ º¸Á¤ ÈÄ Å¬¶ó¿¡°Ô µû·Î ÆÐŶÀº ¾Èº¸³½´Ù. // ¿©±â Áö³ª°£ ´ÙÀ½¿¡ Ŭ¶óÀÌ¾ðÆ®¿¡°Ô Á¤º¸°¡ º¸³»Áö±â ¶§¹®¿¡.. CheckAndRevisionSkillPoint( false ); #endif // #ifdef _FINAL_BUILD #endif // #ifdef PRE_ADD_SP_REVISION } void CDNUserSkill::SaveUserData(TUserData *pUserData) { if (m_SkillList[GetCurrentSkillPage()].empty()) return; memset(&(pUserData->Skill[DualSkill::Type::Primary].SkillList), 0, sizeof(TSkill) * SKILLMAX); TMapSkillList::iterator iter; int nCount = 0; for (iter = m_SkillList[GetCurrentSkillPage()].begin(); iter != m_SkillList[GetCurrentSkillPage()].end(); ++iter){ pUserData->Skill[DualSkill::Type::Primary].SkillList[nCount] = iter->second; pUserData->Skill[DualSkill::Type::Primary].SkillList[nCount].nCoolTime = 0; nCount++; } } // ½ºÅ³ Æ®¸®·Î ¹Ù²î¸é¼­ addskill ġƮ¿¡¼­¸¸ ¾²ÀÌ´Â ÇÔ¼öÀÔ´Ï´Ù.. void CDNUserSkill::AddSkill( int nSkillID, int iLevel/* = 0*/ ) { // 20080901 ·Î±×¼­¹ö ½ºÅ³Ãß°¡[ȹµæ] if ( nSkillID <= 0 ) { m_pUserSession->SendAddSkill(nSkillID, ERROR_SKILL_ACQUIREFAIL); return; } // ȹµæÇÑ ½ºÅ³ ¶Ç ȹµæÇÒ ¼ø ¾øÀ½. if( FindSkill( nSkillID ) ) { m_pUserSession->SendAddSkill(nSkillID, ERROR_SKILL_ACQUIREFAIL); return; } TSkill Skill; memset(&Skill, 0, sizeof(TSkill)); Skill.nSkillID = nSkillID; Skill.cSkillLevel = iLevel; //Skill.bLock = true; // ÃÖÃÊ¿¡ ½ºÅ³ ¾ò¾úÀ» ¶§´Â ¾ð¶ô »óÅÂ. (·¹º§ 0 »óÅÂ) Skill.bLock = false; m_SkillList[GetCurrentSkillPage()][nSkillID] = Skill; CDnSkillTreeSystem::S_POSSESSED_SKILL_INFO SkillInfo; SkillInfo.iSkillID = nSkillID; SkillInfo.iSkillLevel = Skill.cSkillLevel; SkillInfo.bCurrentLock = Skill.bLock; m_vlPossessedSkill[GetCurrentSkillPage()].push_back( SkillInfo ); if( m_pUserSession ) { m_pUserSession->GetDBConnection()->QueryAddSkill(m_pUserSession, nSkillID, Skill.cSkillLevel, 0, 0, DBDNWorldDef::SkillChangeCode::GainByAdmin); m_pUserSession->SendAddSkill(nSkillID, ERROR_NONE); m_pUserSession->GetEventSystem()->OnEvent( EventSystem::OnSkillAdd, 1, EventSystem::SkillID, nSkillID ); } } void CDNUserSkill::DelSkill(int nSkillID) { if (nSkillID <= 0){ m_pUserSession->SendDelSkill(nSkillID, ERROR_SKILL_DELETEFAIL); return; } if (m_SkillList[GetCurrentSkillPage()].empty()){ m_pUserSession->SendDelSkill(nSkillID, ERROR_SKILL_ISNOT_YOURS); return; } TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find(nSkillID); if (iter != m_SkillList[GetCurrentSkillPage()].end()){ m_SkillList[GetCurrentSkillPage()].erase(iter); vector::iterator iter = m_vlPossessedSkill[GetCurrentSkillPage()].begin(); for( iter; m_vlPossessedSkill[GetCurrentSkillPage()].end() != iter; ++iter ) { if( iter->iSkillID == nSkillID ) { m_vlPossessedSkill[GetCurrentSkillPage()].erase( iter ); break; } } m_pUserSession->SendDelSkill(nSkillID, ERROR_NONE); return; } if( m_pUserSession ) { m_pUserSession->GetDBConnection()->QueryDelSkill(m_pUserSession, nSkillID, DBDNWorldDef::SkillChangeCode::DelByAdmin, false, GetCurrentSkillPage() ); m_pUserSession->SendDelSkill(nSkillID, ERROR_SKILL_ISNOT_YOURS); } } #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) int CDNUserSkill::SkillLevelUp( int nSkillID, int nUsePoint ) #else void CDNUserSkill::SkillLevelUp( int nSkillID, int nUsePoint ) #endif { #ifdef PRE_ADD_SP_REVISION // #29463 À̽´ °ü·Ã ÇöÀç º¸À¯ ½ºÅ³ Æ÷ÀÎÆ®¿Í ½ºÅ³ ¼ÒÀ¯ ¸®½ºÆ®°¡ ´Ù¸¥ °æ¿ì¿£ ¿©±â¼­ º¸Á¤ÇØÁØ´Ù. #ifdef _FINAL_BUILD CheckAndRevisionSkillPoint(); #endif // #ifdef _FINAL_BUILD #endif // #ifdef PRE_ADD_SP_REVISION bool bReqSuccess = false; int nError = ERROR_NONE; bool bFinded = false; if (nSkillID <= 0) #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_GENERIC_UNKNOWNERROR;; #else return; #endif//#if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) if (m_SkillList[GetCurrentSkillPage()].empty()) #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_GENERIC_UNKNOWNERROR;; #else return; #endif//#if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find(nSkillID); if (iter != m_SkillList[GetCurrentSkillPage()].end()) bFinded = true; else { _ASSERT( "½ºÅ³ ¸®½ºÆ®¿¡¼­ ½ºÅ³À» ãÀ» ¼ö ¾ø½À´Ï´Ù." ); #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_GENERIC_UNKNOWNERROR;; #else return; #endif //#if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) } TSkill& SkillInfo = iter->second; DNTableFileFormat* pSkillLevelTable = GetDNTable( CDnTableDB::TSKILLLEVEL ); vector vlSkillLevelList; if( pSkillLevelTable->GetItemIDListFromField( "_SkillIndex", nSkillID, vlSkillLevelList ) == 0 ) { _ASSERT( "½ºÅ³ Å×ÀÌºí µ¥ÀÌÅÍ ¿À·ù" ); #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_GENERIC_UNKNOWNERROR;; #else return; #endif//#if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) } #if defined(PRE_FIX_NEXTSKILLINFO) int nLevelUpCount = 1; // ½ºÅ³·¹º§Àº ¹«Á¶°Ç 1¾¿ ¿Ã¸®°Ô µÇ¾îÀÖÀ½. SKILL_LEVEL_TABLE_IDS::iterator findIter; SKILL_LEVEL_INFO* pTableInfo = g_pDataManager->GetSkillLevelTableIDList(nSkillID, 0); int nNeedSkillPoint = 0; bool bValidPacket = false; if( NULL != pTableInfo ) { int nSkillLevel = SkillInfo.cSkillLevel + nLevelUpCount; findIter = pTableInfo->_SkillLevelTableIDs.find(nSkillLevel); int SkillLevelTableID = -1; if (findIter != pTableInfo->_SkillLevelTableIDs.end()) SkillLevelTableID = findIter->second; if( -1 != SkillLevelTableID ) { nNeedSkillPoint = pSkillLevelTable->GetFieldFromLablePtr( SkillLevelTableID, "_NeedSkillPoint" )->GetInteger(); #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) if( nNeedSkillPoint > 0 ) #else if( nNeedSkillPoint == nUsePoint ) #endif bValidPacket = true; } } if( false == bValidPacket ) { // ÆÐŶÀÇ µ¥ÀÌÅͰ¡ ¼­¹ö¿Í ´Ù¸£¹Ç·Î ¿¡·¯·Î ó¸®Çؼ­ µ¹·Áº¸³½´Ù. nError = ERROR_SKILL_LEVELUPFAIL_INVALID_SKILLPOINT; bFinded = false; } #else int iSkillLevelTableID = -1; for( int i = 0; i < (int)vlSkillLevelList.size(); ++i ) { int iNowLevel = pSkillLevelTable->GetFieldFromLablePtr( vlSkillLevelList.at(i), "_SkillLevel" )->GetInteger(); if( iNowLevel == SkillInfo.cSkillLevel ) { iSkillLevelTableID = vlSkillLevelList.at( i ); break; } } if( -1 == iSkillLevelTableID ) { _ASSERT( "½ºÅ³ Å×ÀÌºí µ¥ÀÌÅÍ ¿À·ù" ); return; } int nNeedSkillPoint = 0; int nLevelUpCount = 0; while( nUsePoint != nNeedSkillPoint ) { ++nLevelUpCount; nNeedSkillPoint += pSkillLevelTable->GetFieldFromLablePtr( iSkillLevelTableID+nLevelUpCount, "_NeedSkillPoint" )->GetInteger(); if( nUsePoint < nNeedSkillPoint ) { nError = ERROR_SKILL_LEVELUPFAIL_INVALID_SKILLPOINT; bFinded = false; break; } } #endif // PRE_FIX_NEXTSKILLINFO // ÇØ´ç ½ºÅ³À» °®°í ÀÖ´ÂÁö üũ // ½ºÅ³ ¾È °®°í ÀÖ´Â °æ¿ì¿£ Ãʱ⠵¥ÀÌÅͰ¡ ¹ºÁö ¹°¾îºÁ¼­ ¾Ë¾Æ³»ÀÚ. //bool bFinded = FindSkill( nSkillID ); if( bFinded ) { // º¸À¯ÇÑ ½ºÅ³ Æ÷ÀÎÆ®°¡ »ç¿ëÇÏ°Ú´Ù°í ³¯¾Æ¿Â Æ÷ÀÎÆ®º¸´Ù ÀÛÀ½ int iAvailSPByJob = GetAvailSkillPointByJob( nSkillID ); #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) if( nNeedSkillPoint <= iAvailSPByJob ) #else if( nNeedSkillPoint <= iAvailSPByJob && nUsePoint == nNeedSkillPoint ) #endif { int iLevelFrom = GetSkillLevel( nSkillID ); // ½ºÅ³ ·¹º§ Á¦ÇÑ Ã¼Å© TSkillData *pSkillData = g_pDataManager->GetSkillData(nSkillID); if (!pSkillData){ #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_SKILL_LEVELUPFAIL_ISNOT_YOURS;; #else m_pUserSession->SendSkillLevelUp( nSkillID, 0, ERROR_SKILL_LEVELUPFAIL_ISNOT_YOURS ); return; #endif//#if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) } int iNewLevel = iLevelFrom + nLevelUpCount; if( iNewLevel <= pSkillData->nMaxLevel ) { TSkillLevelData *pSkillLevel = g_pDataManager->GetSkillLevelData(nSkillID, iNewLevel); if (!pSkillLevel){ #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_SKILL_LEVELUPFAIL_ISNOT_YOURS; #else m_pUserSession->SendSkillLevelUp( nSkillID, 0, ERROR_SKILL_LEVELUPFAIL_ISNOT_YOURS ); return; #endif } if( pSkillLevel->cLevelLimit <= (int)m_pUserSession->GetLevel() ) { if( 0 < m_pUserSession->GetSkillPoint() ) { #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) SetSkillLevel( nSkillID, iNewLevel, DBDNWorldDef::SkillChangeCode::Use, false ); // ½ºÅ³Æ÷ÀÎÆ® ¾È¿¡¼­ Â÷°¨ #else SetSkillLevel( nSkillID, iNewLevel, DBDNWorldDef::SkillChangeCode::Use ); // ½ºÅ³Æ÷ÀÎÆ® ¾È¿¡¼­ Â÷°¨ #endif //#if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) bReqSuccess = true; } else { // ½ºÅ³ ·¹º§¾÷ Æ÷ÀÎÆ® ºÎÁ·ÇÔ. ERROR_SKILL_LEVELUPFAIL_INSUFFICIENCY_SKILLPOINT Ŭ¶ó·Î ¸®ÅÏ nError = ERROR_SKILL_LEVELUPFAIL_INSUFFICIENCY_SKILLPOINT; } } else { //TODO: ij¸¯ÅÍÀÇ ·¹º§ÀÌ ½ºÅ³ÀÇ Á¦ÇÑ ·¹º§ º¸´Ù ÀÛ½À´Ï´Ù.. nError = ERROR_SKILL_LEVELUPFAIL_INSUFFICIENCY_CHARACTERLEVEL; } } else { //TODO: ÃÖ´ë·Î Á¤ÇØÁ® ÀÖ´Â ½ºÅ³ ·¹º§ ÀÌ»óÀ» ¿Ã¸®·Á°í ÇÔ.. nError = ERROR_SKILL_LEVELUPFAIL_ALREADY_MAX; } } else { // TODO: ½ÇÁ¦ »ç¿ë ½ºÅ³Æ÷ÀÎÆ®º¸´Ù º¸À¯ Æ÷ÀÎÆ®º¸´Ù Àû°Å³ª Å×À̺íÀÇ µ¥ÀÌÅÍ¿Í ´Ù¸§. nError = ERROR_SKILL_LEVELUPFAIL_INVALID_SKILLPOINT; } } else { // ÇØ´ç ½ºÅ³ º¸À¯Çϰí ÀÖÁö ¾ÊÀ½. ERROR_SKILL_LEVELUPFAIL_ISNOT_YOURS Ŭ¶ó·Î ¸®ÅÏ nError = ERROR_SKILL_LEVELUPFAIL_ISNOT_YOURS; } #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return nError; #else if (!bReqSuccess) m_pUserSession->SendSkillLevelUp( nSkillID, 0, nError ); #endif } bool CDNUserSkill::FindSkill(int nSkillID) { if (nSkillID <= 0) return false; if (m_SkillList[GetCurrentSkillPage()].empty()) return false; TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find(nSkillID); if (iter != m_SkillList[GetCurrentSkillPage()].end()){ return true; } return false; } int CDNUserSkill::GetSkillLevel( int nSkillID ) { TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find( nSkillID ); if( iter != m_SkillList[GetCurrentSkillPage()].end() ) { return iter->second.cSkillLevel; } return -1; } void CDNUserSkill::SetSkillLevel( int nSkillID, int nLevel, int nLogCode, bool bSendSkillLevelUp /*= true*/ ) { TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find( nSkillID ); if( iter != m_SkillList[GetCurrentSkillPage()].end() ) { int nGap = nLevel - iter->second.cSkillLevel; iter->second.cSkillLevel = nLevel; ////////////////////////////////////////////////////////////////////////// // °ÔÀÓ¼­¹ö¿Í ¸¶Âù°¡Áö·Î ·¹º§ÀÌ ÇѲ¨¹ø¿¡ º¯ÇÏ´Â °æ¿ìµµ °¨¾È. // ÇöÀç 1·¹º§¾¿¸¸ ¿Ã¸®°Ô µÇ¾îÀÖÁö¸¸ °ÔÀÓ¼­¹ö¿Í µ¿ÀÏÇÏ°Ô ¸ÂÃçÁØ´Ù. int nNeedSkillPoint = 0; for( int i = 0; i < nGap; ++i ) nNeedSkillPoint += g_pDataManager->GetNeedSkillPoint(nSkillID, nLevel-i); ////////////////////////////////////////////////////////////////////////// if (nNeedSkillPoint > 0) m_pUserSession->ChangeSkillPoint(-nNeedSkillPoint, nSkillID, false, 0, GetCurrentSkillPage() ); m_pUserSession->GetDBConnection()->QueryModSkillLevel( m_pUserSession, nSkillID, nLevel, iter->second.nCoolTime, -nNeedSkillPoint, nLogCode); // dbÀúÀå: ½ºÅ³Æ÷ÀÎÆ®±îÁö °°ÀÌ ¾÷µ¥ÀÌÆ® if( bSendSkillLevelUp ) m_pUserSession->SendSkillLevelUp( nSkillID, nLevel, ERROR_NONE ); vector::iterator iter = m_vlPossessedSkill[GetCurrentSkillPage()].begin(); for( iter; m_vlPossessedSkill[GetCurrentSkillPage()].end() != iter; ++iter ) { if( iter->iSkillID == nSkillID ) { iter->iSkillLevel = nLevel; break; } } m_pUserSession->GetEventSystem()->OnEvent( EventSystem::OnSkillLevelUp, 2, EventSystem::SkillID, nSkillID, EventSystem::SkillLevel, nLevel ); } } // ½ºÅ³ ¾ð¶ô. ·¹º§ 0ÀÎ »óÅ·Πij¸¯ÅÍÀÇ º¸À¯ ½ºÅ³¿¡ Ãß°¡. void CDNUserSkill::UnLockSkill( int nSkillID ) { TSkill Skill; memset(&Skill, 0, sizeof(TSkill)); Skill.nSkillID = nSkillID; Skill.cSkillLevel = 0; Skill.bLock = false; // ¶ô º¯¼ö´Â ÇÊ¿ä ¾øÀ»µí;; m_SkillList[GetCurrentSkillPage()][nSkillID] = Skill; // µû·Î ÇÊ¿äÇÑ Á¤º¸¸¸ ¸ð¾Æ³õÀº º¤ÅÍ¿¡ Ãß°¡. CDnSkillTreeSystem::S_POSSESSED_SKILL_INFO SkillInfo; SkillInfo.iSkillID = nSkillID; SkillInfo.iSkillLevel = 0; SkillInfo.bCurrentLock = false; m_vlPossessedSkill[GetCurrentSkillPage()].push_back( SkillInfo ); m_pUserSession->SendUnlockSkill( nSkillID, ERROR_NONE ); m_pUserSession->GetDBConnection()->QueryAddSkill(m_pUserSession, nSkillID, SkillInfo.iSkillLevel, 0, DBDNWorldDef::SkillChangeCode::GainByBook, 0); // TODO: ½ºÅ³ ȹµæ °ü·Ã ¹Ì¼Ç ÂÊ ¹°¾îºÁ¼­ ó¸®. //m_pUserSession->GetEventSystem()->OnEvent( EventSystem::OnSkillAdd, 1, EventSystem::SkillID, nSkillID ); return; } // ¸¶À»¿¡¼­ ½ºÅ³ Æ®·¹ÀÌ³Ê NPC ·Î µ·À¸·Î ¾ð¶ô. ÇöÀç ȹµæ±îÁö ó¸®. #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) int CDNUserSkill::UnLockSkillByMoney( int nSkillID ) #else void CDNUserSkill::UnLockSkillByMoney( int nSkillID ) #endif { #ifdef PRE_ADD_SP_REVISION // #29463 À̽´ °ü·Ã ÇöÀç º¸À¯ ½ºÅ³ Æ÷ÀÎÆ®¿Í ½ºÅ³ ¼ÒÀ¯ ¸®½ºÆ®°¡ ´Ù¸¥ °æ¿ì¿£ ¿©±â¼­ º¸Á¤ÇØÁØ´Ù. #ifdef _FINAL_BUILD CheckAndRevisionSkillPoint(); #endif // #ifdef _FINAL_BUILD #endif // #ifdef PRE_ADD_SP_REVISION if (nSkillID <= 0){ #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_SKILL_ACQUIREFAIL; #else m_pUserSession->SendAcquireSkill( nSkillID, ERROR_SKILL_ACQUIREFAIL ); return; #endif //#if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) } // º¸À¯Çϰí ÀÖ´Â µ·À¸·Î µÇ´ÂÁö È®ÀÎ. TSkillData* pSkillData = g_pDataManager->GetSkillData( nSkillID ); if (!pSkillData){ #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_SKILL_ACQUIREFAIL; #else m_pUserSession->SendAcquireSkill( nSkillID, ERROR_SKILL_ACQUIREFAIL ); return; #endif } // °°ÀÌ ¸ø¹è¿ì°Ô ÇÑ ½ºÅ³Àº ¹è¿ï ¼ö ¾ø´Ù. if( IsExclusiveSkill( nSkillID, pSkillData->nExclusiveID ) ) { #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_SKILL_ACQUIRE_FAIL_EXCLUSIVE; #else m_pUserSession->SendAcquireSkill( nSkillID, ERROR_SKILL_ACQUIRE_FAIL_EXCLUSIVE ); return; #endif } // #36858 ±Û·Î¹ú ½ºÅ³·Î ¼­·Î ¿«¿© ÀÖ´Ù¸é ÇØ´ç ±×·ìÁß¿¡ Çϳª¸¸ ¹è¿öµµ ºÎ¸ð ½ºÅ³ Á¶°Ç¾øÀÌ ¹è¿ï ¼ö ÀÖ´Ù. bool bAlreadyGlobalSkillAcquired = false; if( HasSameGlobalIDSkill( pSkillData->nGlobalSkillGroup ) ) bAlreadyGlobalSkillAcquired = true; INT64 iNowMoney = m_pUserSession->GetCoin(); if( iNowMoney < pSkillData->nUnlockPrice ) { //m_pUserSession->SendUnlockSkill( nSkillID, ERROR_SKILL_UNLOCK_NOT_ENOUGH_MONEY ); // Ŭ¶ó¿¡¼­ ¸Þ½ÃÁö Çڵ鸵 º¸¿©ÁÖ´Â °ÍÀ» ÀüºÎ ȹµæ¿¡¼­ ó¸®ÇϹǷÎ.. #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_SKILL_UNLOCK_NOT_ENOUGH_MONEY; #else m_pUserSession->SendAcquireSkill( nSkillID, ERROR_SKILL_UNLOCK_NOT_ENOUGH_MONEY ); return; #endif } bool bAlreadyPossess = this->FindSkill( nSkillID ); if( bAlreadyPossess ) { #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_SKILL_UNLOCK_ALREADY_OPEN; #else m_pUserSession->SendAcquireSkill( nSkillID, ERROR_SKILL_UNLOCK_ALREADY_OPEN ); return; #endif } // ±×·¯¸é ȹµæ Á¶°ÇÀ» °Ë»çÇØ¼­ ȹµæÇÔ. int nRetCode = ERROR_NONE; CDnSkillTreeSystem* pSkillTreeSystem = g_pDataManager->GetSkillTreeSystem(); #ifdef PRE_ADD_ONLY_SKILLBOOK if( pSkillTreeSystem ) { bool bExistSkill = false; bool bNeedSkillBook = pSkillTreeSystem->IsNeedSkillBook( nSkillID, bExistSkill ); if( bExistSkill && bNeedSkillBook ) { return ERROR_SKILL_UNLOCK_FAIL; } } #endif // PRE_ADD_ONLY_SKILLBOOK CDnSkillTreeSystem::S_OUTPUT Output; CDnSkillTreeSystem::S_TRY_ACQUIRE TryAcquire( GetPossessedSkillInfo() ); TryAcquire.iCurrentCharLevel = m_pUserSession->GetLevel(); TryAcquire.iTryAcquireSkillID = nSkillID; // Á÷¾÷º°·Î Á¤ÇØÁ® ÀÖ´Â ¾µ ¼ö ÀÖ´Â SP ¸¦ ±âÁØÀ¸·Î ÇÑ´Ù. TryAcquire.iHasSkillPoint = GetAvailSkillPointByJob( nSkillID ); pSkillTreeSystem->TryAcquireSkill( TryAcquire, &Output ); bool bIgnoreParentSkillCondition = ( (CDnSkillTreeSystem::R_DONT_HAVE_PARENT_SKILL == Output.eResult) || (CDnSkillTreeSystem::R_LOCKED_PARENTSKILL == Output.eResult) || (CDnSkillTreeSystem::R_NOT_ENOUGH_PARENT_SKILL_LEVEL == Output.eResult) ) && true == bAlreadyGlobalSkillAcquired; if( CDnSkillTreeSystem::R_SUCCESS == Output.eResult || true == bIgnoreParentSkillCondition ) { // ½ºÅ³ ¸®½ºÆ®¿¡ ½ºÅ³ Ãß°¡. TSkill Skill; memset(&Skill, 0, sizeof(TSkill)); Skill.nSkillID = nSkillID; Skill.cSkillLevel = 0; Skill.bLock = false; // ¶ô º¯¼ö´Â ÇÊ¿ä ¾øÀ»µí;; m_SkillList[GetCurrentSkillPage()][nSkillID] = Skill; // µû·Î ÇÊ¿äÇÑ Á¤º¸¸¸ ¸ð¾Æ³õÀº º¤ÅÍ¿¡ Ãß°¡. CDnSkillTreeSystem::S_POSSESSED_SKILL_INFO SkillInfo; SkillInfo.iSkillID = nSkillID; SkillInfo.iSkillLevel = 0; SkillInfo.bCurrentLock = false; m_vlPossessedSkill[GetCurrentSkillPage()].push_back( SkillInfo ); // µ· Â÷°¨ m_pUserSession->DelCoin( pSkillData->nUnlockPrice, DBDNWorldDef::CoinChangeCode::DoNotDBSave, 0 ); // ¾ð¶ô ÆÐŶ Ŭ¶ó·Î º¸³¿. #if !defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) m_pUserSession->SendUnlockSkill( nSkillID, ERROR_NONE ); #endif // #if !defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) m_pUserSession->GetDBConnection()->QueryAddSkill(m_pUserSession, nSkillID, SkillInfo.iSkillLevel, 0, DBDNWorldDef::SkillChangeCode::GainByBuy, pSkillData->nUnlockPrice); // TODO: ½ºÅ³ ȹµæ °ü·Ã ¹Ì¼Ç ÂÊ ¹°¾îºÁ¼­ ó¸®. //m_pUserSession->GetEventSystem()->OnEvent( EventSystem::OnSkillAdd, 1, EventSystem::SkillID, nSkillID ); SetSkillLevel(nSkillID, 1, DBDNWorldDef::SkillChangeCode::Use, false); // ÇÔ¼ö¾È¿¡¼­ ½ºÅ³Æ÷ÀÎÆ® ¼öÁ¤ // ȹµæ ¼º°ø °á°ú¸¦ ÃÖÁ¾ Å뺸.CDnSkillTreeSystem::S_OUTPUT Output;CDnSkillTreeSystem::S_OUTPUT Output; #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_NONE; #else m_pUserSession->SendAcquireSkill( nSkillID, ERROR_NONE ); #endif } else { switch( Output.eResult ) { // ij¸¯ÅÍ ¿ä±¸·¹º§ÀÌ ¸ðÀÚ¶÷. case CDnSkillTreeSystem::R_NOT_ENOUGH_CHAR_LEVEL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_CHAR_LEVEL; break; // ¼±Çà(ºÎ¸ð) ½ºÅ³ÀÌ ¾øÀ½. case CDnSkillTreeSystem::R_DONT_HAVE_PARENT_SKILL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_DONT_HAVE_PARENT_SKILL; break; // ºÎ¸ð ½ºÅ³ÀÇ ·¹º§ÀÌ ÃæÁ·µÇÁö ¾ÊÀ½. case CDnSkillTreeSystem::R_NOT_ENOUGH_PARENT_SKILL_LEVEL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_PARENT_SKILL_LEVEL; break; // ½ºÅ³ Æ÷ÀÎÆ®°¡ ¸ðÀÚ¶ó¼­ ½ºÅ³À» ȹµæÇÒ ¼ö ¾øÀ½. case CDnSkillTreeSystem::R_NOT_ENOUGH_SKILLPOINT_TO_ACQUIRE: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_SKILLPOINT; break; default: nRetCode = ERROR_SKILL_UNLOCK_FAIL; break; } #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return nRetCode; #else m_pUserSession->SendAcquireSkill( nSkillID, nRetCode ); #endif } #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_NONE; #endif } bool CDNUserSkill::UseSkillBook( int nItemID ) { #ifdef PRE_ADD_SP_REVISION // #29463 À̽´ °ü·Ã ÇöÀç º¸À¯ ½ºÅ³ Æ÷ÀÎÆ®¿Í ½ºÅ³ ¼ÒÀ¯ ¸®½ºÆ®°¡ ´Ù¸¥ °æ¿ì¿£ ¿©±â¼­ º¸Á¤ÇØÁØ´Ù. #ifdef _FINAL_BUILD CheckAndRevisionSkillPoint(); #endif // #ifdef _FINAL_BUILD #endif // #ifdef PRE_ADD_SP_REVISION CDnSkillTreeSystem* pSkillTreeSystem = g_pDataManager->GetSkillTreeSystem(); // ½ºÅ³ºÏ »ç¿ë, Æ®·¹À̳ʿ¡°Ô µ· ÁöºÒ ½Ã¿¡ ½ºÅ³ ¾ð¶ô ¹× ȹµæ±îÁö Àϰý 󸮵ǵµ·Ï º¯°æµÊ. // SP °¡ ºÎÁ·Çϰųª ¼±Çà ½ºÅ³ ¾ø°Å³ª, ¼±Çà ½ºÅ³ÀÇ ·¹º§ÀÌ ³·°Å³ª, ij¸¯ÅÍÀÇ ·¹º§ÀÌ ³·Àº °æ¿ì ÀüºÎ Ã¼Å©ÇØ¼­ Åë°ú µÇ¾úÀ» °æ¿ì¿¡ // ½ºÅ³ ¾ð¶ô ¹× 1·¾À¸·Î Âï¾îÁØ´Ù. // ÀÌ¹Ì ¾ð¶ôÇÑ ½ºÅ³Àº ´Ù½Ã ¾ð¶ôÇÒ ¼ö ¾ø´Ù. // ¾ð¶ôµÈ »óÅÂÀÎ ·¹º§ 0ÀÏ ¶§µµ ½ºÅ³ ¼ÒÀ¯·Î ÇÒ °ÍÀÎÁö´Â °í¹ÎÇØº¸ÀÚ. int iSkillIDToUnLock = pSkillTreeSystem->FindSkillBySkillBook( nItemID ); if( 0 == iSkillIDToUnLock ) { g_Log.Log( LogType::_ERROR, L"[UseSkillBook Fail!!!] Can't find SkillID that using %d SkillBook Item ID\n", iSkillIDToUnLock ); _ASSERT( !"ÇØ´ç ½ºÅ³ºÏ ¾ÆÀÌÅÛ ID ·Î ¼³Á¤µÈ ½ºÅ³À» ãÀ» ¼ö ¾øÀ½." ); return false; } // °°ÀÌ ¸ø¹è¿ì°Ô ÇÑ ½ºÅ³Àº ¹è¿ï ¼ö ¾ø´Ù. const TSkillData* pSkillData = g_pDataManager->GetSkillData( iSkillIDToUnLock ); if( IsExclusiveSkill( iSkillIDToUnLock, pSkillData->nExclusiveID ) ) { m_pUserSession->SendAcquireSkill( iSkillIDToUnLock, ERROR_SKILL_ACQUIRE_FAIL_EXCLUSIVE ); return false; } // #36858 ±Û·Î¹ú ½ºÅ³·Î ¼­·Î ¿«¿© ÀÖ´Ù¸é ÇØ´ç ±×·ìÁß¿¡ Çϳª¸¸ ¹è¿öµµ ºÎ¸ð ½ºÅ³ Á¶°Ç¾øÀÌ ¹è¿ï ¼ö ÀÖ´Ù. bool bAlreadyGlobalSkillAcquired = false; if( HasSameGlobalIDSkill( pSkillData->nGlobalSkillGroup ) ) bAlreadyGlobalSkillAcquired = true; bool bSuccess = false; bool bAlreadyPossess = this->FindSkill( iSkillIDToUnLock ); int nRetCode = ERROR_NONE; int nResultSkillID = 0; if( false == bAlreadyPossess ) { CDnSkillTreeSystem::S_OUTPUT Output; CDnSkillTreeSystem::S_TRY_UNLOCK CurrentSkillInfo; CurrentSkillInfo.iTryUnlockSkillID = iSkillIDToUnLock; CurrentSkillInfo.iCurrentCharLevel = m_pUserSession->GetLevel(); CurrentSkillInfo.iSkillBookItemID = nItemID; // ½ºÅ³ÀÌ ¿ä±¸ÇÏ´Â Á÷¾÷ÀÌ È÷½ºÅ丮¿¡ ÀÖ´ÂÁö ÀûÀýÈ÷ ã¾Æ¼­ ó¸®. TSkillData* pSkillData = g_pDataManager->GetSkillData( iSkillIDToUnLock ); if (pSkillData == NULL) { g_Log.Log( LogType::_ERROR, L"[UseSkillBook - GetSkillData Fail!!!] Can't find %d SkillID\n", iSkillIDToUnLock ); return false; } CurrentSkillInfo.iJobID = -1; for( int i = 0; i < JOBMAX; ++i ) { BYTE cJob = m_pUserSession->GetStatusData()->cJobArray[ i ]; if( 0 < cJob ) { if( cJob == pSkillData->nNeedJobID ) { CurrentSkillInfo.iJobID = pSkillData->nNeedJobID; } } else break; } if( -1 != CurrentSkillInfo.iJobID ) { pSkillTreeSystem->TryUnLockSkill( CurrentSkillInfo, &Output ); // °á°ú¿¡ µû¶ó Ŭ¶óÀÌ¾ðÆ®¿¡ Å뺸. if( CDnSkillTreeSystem::R_SUCCESS == Output.eResult ) { // ¼º°ø. nResultSkillID = iSkillIDToUnLock; // ±×·¯¸é ȹµæ Á¶°ÇÀ» °Ë»ç. CDnSkillTreeSystem* pSkillTreeSystem = g_pDataManager->GetSkillTreeSystem(); CDnSkillTreeSystem::S_TRY_ACQUIRE TryAcquire( GetPossessedSkillInfo() ); TryAcquire.iCurrentCharLevel = m_pUserSession->GetLevel(); TryAcquire.iTryAcquireSkillID = nResultSkillID; // Á÷¾÷º°·Î Á¤ÇØÁ® ÀÖ´Â ¾µ ¼ö ÀÖ´Â SP ¸¦ ±âÁØÀ¸·Î ÇÑ´Ù. TryAcquire.iHasSkillPoint = GetAvailSkillPointByJob( nResultSkillID ); pSkillTreeSystem->TryAcquireSkill( TryAcquire, &Output ); #if defined(PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP) std::vector nNeedSPValues; pSkillTreeSystem->GetNeedSPValuesByJob(nResultSkillID, nNeedSPValues); std::vector jobHistory; GetJobHistory(m_pUserSession->GetStatusData()->cJobArray, jobHistory); bool bAvailableSPByJob = IsAvailableSPByJob(jobHistory, nNeedSPValues); if (bAvailableSPByJob == false) Output.eResult = CDnSkillTreeSystem::R_NOT_ENOUGH_SKILLPOINT_TO_ACQUIRE; #endif // PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP bool bIgnoreParentSkillCondition = ( (CDnSkillTreeSystem::R_DONT_HAVE_PARENT_SKILL == Output.eResult) || (CDnSkillTreeSystem::R_LOCKED_PARENTSKILL == Output.eResult) || (CDnSkillTreeSystem::R_NOT_ENOUGH_PARENT_SKILL_LEVEL == Output.eResult) ) && true == bAlreadyGlobalSkillAcquired; if( CDnSkillTreeSystem::R_SUCCESS == Output.eResult || true == bIgnoreParentSkillCondition ) { // Ŭ¶ó¿¡ Å뺸 ÈÄ À¯Àú°´Ã¼¿¡¼­ ½ºÅ³Á¤º¸ ²¨³»¼­ ·¹º§ 0À¸·Î ¼ÂÆÃ... ¹× ½ºÅ³ Ãß°¡. UnLockSkill( nResultSkillID ); // SendUnlockSkill() ³»ºÎ¿¡¼­ È£ÃâµÇ¾î ÆÐŶ ³ª°¨. bSuccess = true; SetSkillLevel( nResultSkillID, 1, DBDNWorldDef::SkillChangeCode::Use, false ); // ȹµæ ¼º°ø °á°ú¸¦ ÃÖÁ¾ Å뺸. m_pUserSession->SendAcquireSkill( nResultSkillID, ERROR_NONE ); } else { switch( Output.eResult ) { // ij¸¯ÅÍ ¿ä±¸·¹º§ÀÌ ¸ðÀÚ¶÷. case CDnSkillTreeSystem::R_NOT_ENOUGH_CHAR_LEVEL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_CHAR_LEVEL; break; // ¼±Çà(ºÎ¸ð) ½ºÅ³ÀÌ ¾øÀ½. case CDnSkillTreeSystem::R_DONT_HAVE_PARENT_SKILL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_DONT_HAVE_PARENT_SKILL; break; //// ºÎ¸ð ½ºÅ³ÀÌ ¶ôÀÌ µÇ¾îÀÖÀ½. //case CDnSkillTreeSystem::R_LOCKED_PARENTSKILL: // break; // ºÎ¸ð ½ºÅ³ÀÇ ·¹º§ÀÌ ÃæÁ·µÇÁö ¾ÊÀ½. case CDnSkillTreeSystem::R_NOT_ENOUGH_PARENT_SKILL_LEVEL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_PARENT_SKILL_LEVEL; break; // ½ºÅ³ Æ÷ÀÎÆ®°¡ ¸ðÀÚ¶ó¼­ ½ºÅ³À» ȹµæÇÒ ¼ö ¾øÀ½. case CDnSkillTreeSystem::R_NOT_ENOUGH_SKILLPOINT_TO_ACQUIRE: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_SKILLPOINT; break; } } } else { nRetCode = ERROR_SKILL_UNLOCK_FAIL; } } else { nRetCode = ERROR_SKILL_UNLOCK_MISMATCH_JOB; } } else { // ÀÌ¹Ì ¾ð¶ô ÇÑ »óÅÂÀÓ. nRetCode = ERROR_SKILL_UNLOCK_ALREADY_OPEN; } if( false == bSuccess ) { //m_pUserSession->SendUnlockSkill( nResultSkillID, nRetCode ); m_pUserSession->SendAcquireSkill( nResultSkillID, nRetCode ); } return bSuccess; } // ½ºÅ³ ȹµæ. (·¹º§ 0¿¡¼­ 1·Î ¹Ù²Þ) // ½ºÅ³ ¸®¼Â ÈÄ ´Ù½Ã ȹµæ½Ã ÀÌ°Ô È£ÃâµÈ´Ù. #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) int CDNUserSkill::AcquireSkill( int nSkillID ) #else void CDNUserSkill::AcquireSkill( int nSkillID ) #endif { #ifdef PRE_ADD_SP_REVISION // #29463 À̽´ °ü·Ã ÇöÀç º¸À¯ ½ºÅ³ Æ÷ÀÎÆ®¿Í ½ºÅ³ ¼ÒÀ¯ ¸®½ºÆ®°¡ ´Ù¸¥ °æ¿ì¿£ ¿©±â¼­ º¸Á¤ÇØÁØ´Ù. #ifdef _FINAL_BUILD CheckAndRevisionSkillPoint(); #endif // #ifdef _FINAL_BUILD #endif // #ifdef PRE_ADD_SP_REVISION TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find( nSkillID ); int nRetCode = ERROR_NONE; if( iter != m_SkillList[GetCurrentSkillPage()].end() ) { _ASSERT( false == iter->second.bLock ); _ASSERT( 0 == iter->second.cSkillLevel ); // ½ºÅ³ ¸®¼Â ÈÄ Àçȹµæ ÇÏ´Â °æ¿ì¿¡ »óÈ£ ¹èŸÀûÀÎ ½ºÅ³ÀÌ ÀÖ´ÂÁö üũ // °°ÀÌ ¸ø¹è¿ì°Ô ÇÑ ½ºÅ³Àº ¹è¿ï ¼ö ¾ø´Ù. TSkillData* pSkillData = g_pDataManager->GetSkillData( nSkillID ); if( m_pUserSession->GetSkill()->IsExclusiveSkill( nSkillID, pSkillData->nExclusiveID ) ) { // ±âº»ÀûÀ¸·Î´Â Ŭ¶ó¿¡¼­ ¸·±â ¶§¹®¿¡ ¼­¹ö·Î ÆÐŶÀ» º¸³½´Ù¸é ÇÙÀÌ´Ù. #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return ERROR_SKILL_ACQUIRE_FAIL_EXCLUSIVE; #else m_pUserSession->SendAcquireSkill( nSkillID, ERROR_SKILL_ACQUIRE_FAIL_EXCLUSIVE ); return; #endif // #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) } // #36858 ±Û·Î¹ú ½ºÅ³·Î ¼­·Î ¿«¿© ÀÖ´Ù¸é ÇØ´ç ±×·ìÁß¿¡ Çϳª¸¸ ¹è¿öµµ ºÎ¸ð ½ºÅ³ Á¶°Ç¾øÀÌ ¹è¿ï ¼ö ÀÖ´Ù. bool bAlreadyGlobalSkillAcquired = false; if( HasSameGlobalIDSkill( pSkillData->nGlobalSkillGroup ) ) bAlreadyGlobalSkillAcquired = true; CDnSkillTreeSystem* pSkillTreeSystem = g_pDataManager->GetSkillTreeSystem(); CDnSkillTreeSystem::S_TRY_ACQUIRE TryAcquire( GetPossessedSkillInfo() ); CDnSkillTreeSystem::S_OUTPUT Output; TryAcquire.iCurrentCharLevel = m_pUserSession->GetLevel(); TryAcquire.iTryAcquireSkillID = nSkillID; // Á÷¾÷º°·Î Á¤ÇØÁ® ÀÖ´Â ¾µ ¼ö ÀÖ´Â SP ¸¦ ±âÁØÀ¸·Î ÇÑ´Ù. TryAcquire.iHasSkillPoint = GetAvailSkillPointByJob( nSkillID ); // ½ºÅ³ÀÌ ¿ä±¸ÇÏ´Â Á÷¾÷ÀÌ È÷½ºÅ丮¿¡ ÀÖ´ÂÁö ÀûÀýÈ÷ ã¾Æ¼­ ó¸®. TryAcquire.iJobID = -1; if (pSkillData){ for( int i = 0; i < JOBMAX; ++i ) { BYTE cJob = m_pUserSession->GetStatusData()->cJobArray[ i ]; if( 0 < cJob ) { if( cJob == pSkillData->nNeedJobID ) { TryAcquire.iJobID = pSkillData->nNeedJobID; } } else break; } } if( -1 != TryAcquire.iJobID ) { pSkillTreeSystem->TryAcquireSkill( TryAcquire, &Output ); bool bIgnoreParentSkillCondition = ( (CDnSkillTreeSystem::R_DONT_HAVE_PARENT_SKILL == Output.eResult) || (CDnSkillTreeSystem::R_LOCKED_PARENTSKILL == Output.eResult) || (CDnSkillTreeSystem::R_NOT_ENOUGH_PARENT_SKILL_LEVEL == Output.eResult) ) && true == bAlreadyGlobalSkillAcquired; if( CDnSkillTreeSystem::R_SUCCESS == Output.eResult || true == bIgnoreParentSkillCondition ) { SetSkillLevel( nSkillID, 1, DBDNWorldDef::SkillChangeCode::Use, false ); // TODO: ½ºÅ³ ȹµæ °ü·Ã ¹Ì¼Ç ÂÊ ¹°¾îºÁ¼­ ó¸®. //m_pUserSession->GetEventSystem()->OnEvent( EventSystem::OnSkillAdd, 1, EventSystem::SkillID, nSkillID ); } else { switch( Output.eResult ) { // ij¸¯ÅÍ ¿ä±¸·¹º§ÀÌ ¸ðÀÚ¶÷. case CDnSkillTreeSystem::R_NOT_ENOUGH_CHAR_LEVEL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_CHAR_LEVEL; break; // ¼±Çà(ºÎ¸ð) ½ºÅ³ÀÌ ¾øÀ½. case CDnSkillTreeSystem::R_DONT_HAVE_PARENT_SKILL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_DONT_HAVE_PARENT_SKILL; break; //// ºÎ¸ð ½ºÅ³ÀÌ ¶ôÀÌ µÇ¾îÀÖÀ½. //case CDnSkillTreeSystem::R_LOCKED_PARENTSKILL: // break; // ºÎ¸ð ½ºÅ³ÀÇ ·¹º§ÀÌ ÃæÁ·µÇÁö ¾ÊÀ½. case CDnSkillTreeSystem::R_NOT_ENOUGH_PARENT_SKILL_LEVEL: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_PARENT_SKILL_LEVEL; break; // ½ºÅ³ Æ÷ÀÎÆ®°¡ ¸ðÀÚ¶ó¼­ ½ºÅ³À» ȹµæÇÒ ¼ö ¾øÀ½. case CDnSkillTreeSystem::R_NOT_ENOUGH_SKILLPOINT_TO_ACQUIRE: nRetCode = ERROR_SKILL_ACQUIRE_FAIL_NOT_ENOUGH_SKILLPOINT; break; } } } else nRetCode = ERROR_SKILL_ACQUIRE_FAIL_MISMATCH_JOB; } else { // ÇØ´ç ½ºÅ³ º¸À¯Çϰí ÀÖÁö ¾ÊÀ½. ERROR_SKILL_LEVELUPFAIL_ISNOT_YOURS Ŭ¶ó·Î ¸®ÅÏ nRetCode = ERROR_SKILL_ACQUIRE_FAIL_ISNOT_YOURS; } #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) return nRetCode; #else m_pUserSession->SendAcquireSkill( nSkillID, nRetCode ); #endif } // ġƮŰ Àü¿ë ½ºÅ³ ȹµæ ÇÔ¼ö.. void CDNUserSkill::CheatAcquireSkill( int nSkillID ) { TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find( nSkillID ); int nRetCode = ERROR_NONE; if( iter != m_SkillList[GetCurrentSkillPage()].end() ) { SetSkillLevel( nSkillID, 1, DBDNWorldDef::SkillChangeCode::ModSkillLevelByAdmin, false ); m_pUserSession->SendAcquireSkill( nSkillID, nRetCode ); } } #if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) void CDNUserSkill::ReservationSkillList(CSReservationSkillListReq* pUnlockSkillByMoneyReq) { if( pUnlockSkillByMoneyReq->nCount <= 0 ) return; SCReservationSkillListAck ReservationSkillAck; memset(&ReservationSkillAck, 0, sizeof(SCReservationSkillListAck)); for( int i=0; inCount; ++i) { memcpy(&ReservationSkillAck.tReservationSkillAck[i].tReservationSkill, &pUnlockSkillByMoneyReq->tReservationSkill[i], sizeof(TReservationSkillReq)); if(pUnlockSkillByMoneyReq->tReservationSkill[i].cType == ReservationSKillList::Type::UnLock) { ReservationSkillAck.tReservationSkillAck[i].nResult = UnLockSkillByMoney(pUnlockSkillByMoneyReq->tReservationSkill[i].nSkillID); } else if(pUnlockSkillByMoneyReq->tReservationSkill[i].cType == ReservationSKillList::Type::Acquire) { ReservationSkillAck.tReservationSkillAck[i].nResult = AcquireSkill(pUnlockSkillByMoneyReq->tReservationSkill[i].nSkillID); } else if(pUnlockSkillByMoneyReq->tReservationSkill[i].cType == ReservationSKillList::Type::LevelUp) { int nResult = ERROR_NONE; int nCurLevel = GetSkillLevel(pUnlockSkillByMoneyReq->tReservationSkill[i].nSkillID); if( nCurLevel >= pUnlockSkillByMoneyReq->tReservationSkill[i].nLevel) { nResult = ERROR_GENERIC_UNKNOWNERROR; } else { for( int j=nCurLevel;jtReservationSkill[i].nLevel;++j) { nResult = SkillLevelUp(pUnlockSkillByMoneyReq->tReservationSkill[i].nSkillID); if( nResult != ERROR_NONE) break; } } ReservationSkillAck.tReservationSkillAck[i].nResult = nResult; } else break; ++ReservationSkillAck.nCount; if(ReservationSkillAck.tReservationSkillAck[i].nResult != ERROR_NONE ) // µµÁß¿¡ 1°³¶óµµ ¿¡·¯³ª¸é ±×³É ¸¶¹«¸®.. break; } int nLen = sizeof(SCReservationSkillListAck) - sizeof(ReservationSkillAck.tReservationSkillAck) + (sizeof(TReservationSkillAck)*ReservationSkillAck.nCount); m_pUserSession->AddSendData(SC_SKILL, eSkill::SC_RESERVATION_SKILL_LIST_ACK, (char*)&ReservationSkillAck, nLen); } #endif //#if defined(PRE_ADD_SKILL_LEVELUP_RESERVATION) void CDNUserSkill::ResetSkill( int nSkillPage ) { // ÀüÁ÷½Ã¿¡ ¸ðµç ½ºÅ³ ÃʱâÈ­. // ³ª¸ÓÁø ij½ÃÅÛ °®°í ÇØ¾ßÇÔ. ResetAllSkill( nSkillPage ); m_pUserSession->GetDBConnection()->QueryResetSkill(m_pUserSession, nSkillPage); } void CDNUserSkill::WaitForUseSkillResetCashItemFromDBServer( vector& vlSkillIDsToReset ) { m_vlWaitingSkillIDsToReset = vlSkillIDsToReset; } void CDNUserSkill::OnResponseSkillResetCashItemFromDBServer( bool bSuccess ) { if( bSuccess ) { // ¹Þ¾Æ³õ¾Ò´ø ½ºÅ³ ¾ÆÀ̵ðµéÀ» ¸®¼Â. ½ºÅ³ Æ÷ÀÎÆ®´Â DB¿¡¼­ ¹ÞÀÚ¸¶ÀÚ Ã³¸®ÇØÁֹǷΠ¿©±â¼­ ½Å°æ ¾È½áµµ µÊ. int aiDefaultSkills[ DEFAULTSKILLMAX ] = { 0 }; g_pDataManager->GetCreateDefaultSkill( m_pUserSession->GetClassID(), aiDefaultSkills ); int nCount = 0; for( int i = 0; i != (int)m_vlWaitingSkillIDsToReset.size(); ++i ) { TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find( m_vlWaitingSkillIDsToReset.at(i) ); _ASSERT( m_SkillList[GetCurrentSkillPage()].end() != iter ); if( m_SkillList[GetCurrentSkillPage()].end() == iter ) continue; bool bDefaultSkill = false; for( int k = 0; k < DEFAULTSKILLMAX; ++k ) { if( aiDefaultSkills[ k ] == iter->second.nSkillID ) { bDefaultSkill = true; break; } } if( bDefaultSkill ) { iter->second.cSkillLevel = 1; } else iter->second.cSkillLevel = 0; for( UINT k = 0; k < m_vlPossessedSkill[GetCurrentSkillPage()].size(); ++k ) { if( iter->second.nSkillID == m_vlPossessedSkill[GetCurrentSkillPage()].at( k ).iSkillID ) m_vlPossessedSkill[GetCurrentSkillPage()].at( k ).iSkillLevel = iter->second.cSkillLevel; } nCount++; } } m_vlWaitingSkillIDsToReset.clear(); } void CDNUserSkill::GatherThisJobSkill( BYTE cJob, IN OUT vector& vlResult ) { // ÃßÈÄ ¼Óµµ¿¡ ¹®Á¦°¡ µÈ´Ù¸é µû·Î ¸®½ºÆ®¸¦ ±¸¼ºÇØ »ç¿ëÇϵµ·Ï ÇÑ´Ù. vector::iterator iter = m_vlPossessedSkill[GetCurrentSkillPage()].begin(); for ( iter; iter != m_vlPossessedSkill[GetCurrentSkillPage()].end(); ++iter ) { TSkillData* pSkillData = g_pDataManager->GetSkillData( iter->iSkillID ); if (!pSkillData) continue; if( pSkillData->nNeedJobID == cJob ) { // ȹµæ±îÁö ÇÑ »óÅ¿©¾ß ½ÇÁ¦ ½ºÅ³ º¸À¯ »óÅÂÀÓ. if( 0 < iter->iSkillLevel ) vlResult.push_back( iter->iSkillID ); } } } int CDNUserSkill::GetLevelUpSkillPoint( int nPrevLevel, int nCurLevel ) { if( nPrevLevel == nCurLevel ) return 0; int nSkillPoint = 0; for( int i=nPrevLevel+1; i<=nCurLevel; i++ ) { nSkillPoint += CPlayerLevelTable::GetInstance().GetValue( m_pUserSession->GetClassID(), i, CPlayerLevelTable::SkillPoint ); } return nSkillPoint; } bool CDNUserSkill::IsExclusiveSkill( int nSkillID, int nExclusiveID ) { if( 0 != nExclusiveID ) { TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].begin(); for(iter; iter != m_SkillList[GetCurrentSkillPage()].end(); ++iter) { const TSkill& ExistSkillData = iter->second; if( ExistSkillData.nSkillID <= 0 ) continue; if( nSkillID == ExistSkillData.nSkillID ) continue; // ·¹º§ 0 Â¥¸®·Î ¸®¼ÂµÈ °ÍÀº ¾òÀº °ÍÀÌ ¾Æ´Ï¹Ç·Î ºñ±³´ë»óÀÌ ¾Æ´Ô. if( 0 == ExistSkillData.cSkillLevel ) continue; const TSkillData* pSkillData = g_pDataManager->GetSkillData( ExistSkillData.nSkillID ); if( 0 != pSkillData->nExclusiveID ) { if( nExclusiveID == pSkillData->nExclusiveID ) return true; } } } return false; } int CDNUserSkill::GetUsedSPByJob( int nJobID ) { int iResult = 0; for( int i = 0; i < (int)m_vlPossessedSkill[GetCurrentSkillPage()].size(); ++i ) { int iSkillID = m_vlPossessedSkill[GetCurrentSkillPage()].at( i ).iSkillID; const TSkillData* pSkillData = g_pDataManager->GetSkillData( iSkillID ); // ÆÄÀ̳ΠºôµåÀ϶§¸¸ NULL üũ. Å×½ºÆ® ´Ü°è¿¡¼­´Â Á×µµ·Ï.. #if defined(_FINAL_BUILD) if( NULL == pSkillData ) continue; #endif // #if defined(_FINAL_BUILD) if( pSkillData->nNeedJobID == nJobID ) { int iLevel = m_vlPossessedSkill[GetCurrentSkillPage()].at( i ).iSkillLevel; int iSize = (int)pSkillData->vLevelDataList.size(); for( int k = 0; k < min(iLevel, iSize); ++k ) iResult += pSkillData->vLevelDataList.at( k ).nNeedSkillPoint; if (iLevel > iSize) g_Log.Log(LogType::_ERROR, L"GetUsedSPByJob - Wrong Skill Size(WORSETID:%d, CHARID:%d, iLevel:%d, iSize:%d)\r\n", m_pUserSession->GetWorldSetID(), m_pUserSession->GetCharacterDBID(), iLevel, iSize); } } return iResult; } int CDNUserSkill::GetAvailSkillPointByJob( int nSkillID ) { int iWholeSP = GetLevelUpSkillPoint( 1, m_pUserSession->GetLevel() ); float fAvailSPRatioByJob = m_pUserSession->GetAvailSkillPointRatioByJob( nSkillID ); const TSkillData* pSkillDataToLevelUp = g_pDataManager->GetSkillData( nSkillID ); int iUsedSPThisJob = 0; if (pSkillDataToLevelUp) iUsedSPThisJob = GetUsedSPByJob( pSkillDataToLevelUp->nNeedJobID ); // Àüü »ç¿ë°¡´É SP º¸´Ù Á÷¾÷ SP °¡ ³²Àº °ÍÀÌ ¸¹À¸¸é Àüü »ç¿ë°¡´É SP °¡ ÁøÂ¥ÀÌ¹Ç·Î ÇØ´ç Æ÷ÀÎÆ®·Î ¸®ÅÏ. int iAvailPoint = int(fAvailSPRatioByJob*iWholeSP)-iUsedSPThisJob; if( m_pUserSession->GetSkillPoint() < iAvailPoint ) iAvailPoint = m_pUserSession->GetSkillPoint(); return iAvailPoint; } void CDNUserSkill::OnAttachEquip( TItem *pItem ) { if( pItem->nItemID > 0 ) { TItemData *pItemData = g_pDataManager->GetItemData( pItem->nItemID ); if( pItemData && (pItemData->nSkillID > 0) ) { if( !FindSkill( pItemData->nSkillID ) ) { TSkill Skill; memset(&Skill, 0, sizeof(TSkill)); Skill.nSkillID = pItemData->nSkillID; Skill.cSkillLevel = 1; Skill.bLock = false; m_SkillList[GetCurrentSkillPage()][pItemData->nSkillID] = Skill; CDnSkillTreeSystem::S_POSSESSED_SKILL_INFO SkillInfo; SkillInfo.iSkillID = pItemData->nSkillID; SkillInfo.iSkillLevel = Skill.cSkillLevel; SkillInfo.bCurrentLock = Skill.bLock; m_vlPossessedSkill[GetCurrentSkillPage()].push_back( SkillInfo ); } } } } void CDNUserSkill::OnDetachEquip( TItem *pItem ) { if( pItem->nItemID > 0 ) { TItemData *pItemData = g_pDataManager->GetItemData( pItem->nItemID ); if( pItemData && (pItemData->nSkillID > 0) ) { TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].find( pItemData->nSkillID ); if (iter != m_SkillList[GetCurrentSkillPage()].end()){ m_SkillList[GetCurrentSkillPage()].erase(iter); vector::iterator iter = m_vlPossessedSkill[GetCurrentSkillPage()].begin(); for( iter; m_vlPossessedSkill[GetCurrentSkillPage()].end() != iter; ++iter ) { if( iter->iSkillID == pItemData->nSkillID ) { m_vlPossessedSkill[GetCurrentSkillPage()].erase( iter ); break; } } } } } } #ifdef PRE_ADD_SP_REVISION #ifdef _FINAL_BUILD void CDNUserSkill::CheckAndRevisionSkillPoint( bool bSendRevisionSPToClient/* = true*/ ) { if( NULL == m_pUserSession ) return; // #29463 À̽´ °ü·Ã ÇöÀç º¸À¯ ½ºÅ³ Æ÷ÀÎÆ®¿Í ½ºÅ³ ¼ÒÀ¯ ¸®½ºÆ®°¡ ´Ù¸¥ °æ¿ì¿£ ¿©±â¼­ º¸Á¤ÇØÁØ´Ù. int nUseSkillPoint = 0; int nWholeSP = GetLevelUpSkillPoint( 1, m_pUserSession->GetLevel() ); // µðÆúÆ® ½ºÅ³À» ¾ò¾î¿Í¼­ ÇöÀç µðÆúÆ® ½ºÅ³µé¸¸ ÀÖ°í 1·¾À̶ó¸é ½ºÅ³À» Çϳªµµ ÂïÀº °Ô ¾øÀ¸¹Ç·Î ¸®¼ÂÇÒ ¼ö ¾ø´Ù. int aiDefaultSkills[ DEFAULTSKILLMAX ] = { 0 }; g_pDataManager->GetCreateDefaultSkill( m_pUserSession->GetClassID(), aiDefaultSkills ); int iNumSkill = (int)m_vlPossessedSkill[GetCurrentSkillPage()].size(); for( int i = 0; i < iNumSkill; ++i ) { CDnSkillTreeSystem::S_POSSESSED_SKILL_INFO& PossessedSkill = m_vlPossessedSkill[GetCurrentSkillPage()].at( i ); // µðÆúÆ® ½ºÅ³ÀÌ°í ·¹º§ 1ÀÌ¸é ½ºÅ³ Æ÷ÀÎÆ® °è»ê¿¡¼­ »«´Ù. bool bDefaultSkill = false; bool bDefaultSkillOneLevel = false; for( int k = 0; k < DEFAULTSKILLMAX; ++k ) { if( aiDefaultSkills[ k ] == 0 ) break; if( PossessedSkill.iSkillID == aiDefaultSkills[ k ] ) { bDefaultSkill = true; if( 1 == PossessedSkill.iSkillLevel ) { bDefaultSkillOneLevel = true; } break; } } if( bDefaultSkill && bDefaultSkillOneLevel ) continue; for( int k = 0; k < PossessedSkill.iSkillLevel; ++k ) { // µðÆúÆ® ½ºÅ³Àº 1·¹º§ÀÇ ½ºÅ³ Æ÷ÀÎÆ®¸¦ °è»êÇÏÁö ¾Ê´Â´Ù. // Å×ÀÌºí¿¡ ÇÊ¿ä SP °¡ 0À¸·Î µÇ¾îÀÖÁö¸¸ ¸¸¿¡ Çϳª À߸ø ÀԷµǾúÀ» °æ¿ì¸¦ ´ëºñÇØ Äڵ忡¼­ ¸·´Â´Ù. if( bDefaultSkill && 0 == k ) continue; nUseSkillPoint += g_pDataManager->GetNeedSkillPoint(PossessedSkill.iSkillID, k + 1); } } int nLeftSkillPoint = nWholeSP - nUseSkillPoint; // ÇöÀç ÀúÀåµÇ¾îÀÖ´Â ½ºÅ³ Æ÷ÀÎÆ®¿Í °ªÀÌ ´Ù¸£´Ù¸é º¸Á¤Ã³¸®. int nNowSkillPoint = m_pUserSession->GetSkillPoint(); // ¸¸¾à ÃʰúÇØ¼­ ÀÌ¹Ì ½ºÅ³À» ÂïÀº »óŶó¸é ´ÙÀ½¿¡ ½ºÅ³¸®¼ÂÇÏ°í ½ºÅ³ ȹµæÇÒ¶§ º¸Á¤µÇµµ·Ï ±×³É ¿©±â¼± ³Ñ±ä´Ù. if( nLeftSkillPoint < 0 ) return; if( nNowSkillPoint != nLeftSkillPoint ) { m_pUserSession->SetSkillPoint( nLeftSkillPoint, GetCurrentSkillPage() ); #ifdef PRE_FIX_SP_REVISION_CHANGE_SP m_pUserSession->GetDBConnection()->QuerySetSkillPoint( m_pUserSession, nLeftSkillPoint, GetCurrentSkillPage() ); #else int nSkillPointDelta = nLeftSkillPoint - nNowSkillPoint; if( 0 < nSkillPointDelta ) { m_pUserSession->GetDBConnection()->QueryIncreaseSkillPoint( m_pUserSession, nSkillPointDelta, DBDNWorldDef::SkillPointCode::Repair, GetCurrentSkillPage() ); } else { // °¨¼Ò Äõ¸®¿¡µµ °¨¼ÒµÉ ½ºÅ³ Æ÷ÀÎÆ®¸¦ ¾ç¼ö·Î ³Ñ°ÜÁÖ¸é DB Ãø¿¡¼­ ÇØ´ç Æ÷ÀÎÆ® Â÷°¨. m_pUserSession->GetDBConnection()->QueryDecreaseSkillPoint( m_pUserSession, -nSkillPointDelta, GetCurrentSkillPage() ); } #endif // #ifdef PRE_FIX_SP_REVISION_CHANGE_SP // Ŭ¶óÀÌ¾ðÆ®¿¡°Ôµµ ½ºÅ³ Æ÷ÀÎÆ® ÆÐŶÀ» ¹Ð¾îÁØ´Ù. if( bSendRevisionSPToClient ) m_pUserSession->SendPushSkillPoint( nLeftSkillPoint ); } } #endif // #ifdef _FINAL_BUILD #endif // #ifdef PRE_ADD_SP_REVISION void CDNUserSkill::ResetAllSkill(int nSkillPage ) { // ±âº» ½ºÅ³À» Á¦¿ÜÇÏ°í ¸ðµç º¸À¯ ½ºÅ³À» 0À¸·Î ¸®¼Â. ¼Ò¸ðµÈ ½ºÅ³ Æ÷ÀÎÆ® º¹±¸½ÃÅ´. // ±âº» ½ºÅ³Àº 1·¾À¸·Î. int aiDefaultSkills[ DEFAULTSKILLMAX ] = { 0 }; g_pDataManager->GetCreateDefaultSkill( m_pUserSession->GetClassID(), aiDefaultSkills ); TMapSkillList::iterator iter; int nCount = 0; if( nSkillPage < DualSkill::Type::Primary || nSkillPage >= DualSkill::Type::MAX ) return; for (iter = m_SkillList[nSkillPage].begin(); iter != m_SkillList[nSkillPage].end(); ++iter) { bool bDefaultSkill = false; for( int i = 0; i < DEFAULTSKILLMAX; ++i ) { if( aiDefaultSkills[ i ] == iter->second.nSkillID ) { bDefaultSkill = true; break; } } if( bDefaultSkill ) { iter->second.cSkillLevel = 1; } else iter->second.cSkillLevel = 0; for( int i = 0; i < (int)m_vlPossessedSkill[nSkillPage].size(); ++i ) { if( iter->second.nSkillID == m_vlPossessedSkill[nSkillPage].at( i ).iSkillID ) m_vlPossessedSkill[nSkillPage].at( i ).iSkillLevel = iter->second.cSkillLevel; } nCount++; } } #ifdef PRE_ADD_CHANGEJOB_CASHITEM void CDNUserSkill::OnResponseChangeJobCode( USHORT wTotalSkillPoint ) { for(int nSkillPage = DualSkill::Type::Primary; nSkillPage < DualSkill::Type::MAX ; nSkillPage++ ) { ResetAllSkill( nSkillPage ); m_pUserSession->SetSkillPoint( wTotalSkillPoint, nSkillPage ); } } #endif // #ifdef PRE_ADD_CHANGEJOB_CASHITEM bool CDNUserSkill::HasSameGlobalIDSkill( int iGlobalSkillGroupID ) { bool bResult = false; if( 0 < iGlobalSkillGroupID ) { TMapSkillList::iterator iter = m_SkillList[GetCurrentSkillPage()].begin(); for(iter; iter != m_SkillList[GetCurrentSkillPage()].end(); ++iter) { const TSkillData* pExistSkillData = g_pDataManager->GetSkillData( iter->second.nSkillID ); if( pExistSkillData ) { if( pExistSkillData->nGlobalSkillGroup == iGlobalSkillGroupID ) { bResult = true; break; } } } } return bResult; } void CDNUserSkill::ApplyExpendedSkillPage( int nSkillPage ) { if( nSkillPage == GetCurrentSkillPage() || nSkillPage <= DualSkill::Type::Primary || nSkillPage >= DualSkill::Type::MAX) return; int aiDefaultSkills[ DEFAULTSKILLMAX ] = { 0 }; int addCount = 0; int nUseSkillPoint = 0; g_pDataManager->GetCreateDefaultSkill( m_pUserSession->GetClassID(), aiDefaultSkills ); for(int i=0; i 0 ) { m_pSkillData[nSkillPage].SkillList[addCount].cSkillLevel = 1; m_pSkillData[nSkillPage].SkillList[addCount].nSkillID = aiDefaultSkills[i]; m_pSkillData[nSkillPage].SkillList[addCount].nCoolTime = 0; addCount++; } } for (int i = 0; i < SKILLMAX; i++){ if (m_pSkillData[nSkillPage].SkillList[i].nSkillID <= 0) continue; // µ¥ÀÌÅÍ¿¡ ¾ø´Â ½ºÅ³ ID°¡ DB ¿¡ ÀúÀåµÇ¾îÀÖ´Ù¸é ÀоîµéÀÌÁö ¾Ê´Â´Ù. const TSkillData* pSkillData = g_pDataManager->GetSkillData( m_pSkillData[nSkillPage].SkillList[i].nSkillID ); if( NULL == pSkillData ) continue; m_SkillList[nSkillPage][m_pSkillData[nSkillPage].SkillList[i].nSkillID] = m_pSkillData[nSkillPage].SkillList[i]; CDnSkillTreeSystem::S_POSSESSED_SKILL_INFO SkillInfo; SkillInfo.iSkillID = m_pSkillData[nSkillPage].SkillList[i].nSkillID; SkillInfo.iSkillLevel = m_pSkillData[nSkillPage].SkillList[i].cSkillLevel; SkillInfo.bCurrentLock = m_pSkillData[nSkillPage].SkillList[i].bLock; m_vlPossessedSkill[nSkillPage].push_back( SkillInfo ); if (m_pSkillData[nSkillPage].SkillList[i].nSkillID > 0){ for (int j = 0; j < m_pSkillData[nSkillPage].SkillList[i].cSkillLevel; j++){ nUseSkillPoint += g_pDataManager->GetNeedSkillPoint(m_pSkillData[nSkillPage].SkillList[i].nSkillID, j + 1); } } } } int CDNUserSkill::GetCurrentSkillPage() { return m_pUserSession->GetSkillPage(); } #if defined(PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP) void CDNUserSkill::GetJobHistory(BYTE *cJobArray, vector& jobHistory) { for (int j = 0; j < JOBMAX; j++){ if (cJobArray[j] <= 0) continue; jobHistory.push_back((int)cJobArray[j]); } } bool CDNUserSkill::IsAvailableSPByJob(vector& jobHistory, vector& needSPValues) { bool isAvailableSPByJob = true; int nJobCount = (int)jobHistory.size(); int nJobID = -1; for (int i = 0; i < nJobCount; ++i) { if (IsAvailableSPByJob(jobHistory, needSPValues, i) == false) { isAvailableSPByJob = false; break; } } return isAvailableSPByJob; } bool CDNUserSkill::IsAvailableSPByJob(std::vector& jobHistory, vector& needSPValues, int nIndex) { bool isAvailableSPByJob = false; int nJobCount = (int)jobHistory.size(); int nNeedSPValue = 0; int nSPValueCount = (int)needSPValues.size(); if (nIndex >= 0 && nIndex < nSPValueCount) nNeedSPValue = needSPValues[nIndex]; //ÀüÁ÷ÀÌ µÇÁö ¾ÊÀº °æ¿ì?? if (nIndex >= nJobCount) { if (nNeedSPValue <= 0) return true; else return false; } int nJobID = -1; nJobID = jobHistory[nIndex]; int iUsedSkillPointInThisJob = GetUsedSPByJob( nJobID ); //ÇØ´ç JobID¿¡ »ç¿ëÇÑ SP°ªÀÌ È®ÀÎ¿ë °ªº¸´Ù Ä¿¾ß »ç¿ë °¡´É.. if (iUsedSkillPointInThisJob >= nNeedSPValue) isAvailableSPByJob = true; return isAvailableSPByJob; } #endif // PRE_ADD_SKILL_LEVELUP_LIMIT_BY_SP