#include "Stdafx.h" #include "SecondarySkillRepositoryServer.h" #include "SecondarySkillEventHandlerServer.h" #include "SecondarySkill.h" #include "DNUserSession.h" #include "ManufactureSkill.h" #include "SecondarySkillFactory.h" #include "SecondarySkillRecipe.h" #include "DNGameDataManager.h" #if defined( PRE_ADD_SECONDARY_SKILL ) CSecondarySkillRepositoryServer::CSecondarySkillRepositoryServer( CDNUserSession* pSession ) :m_pSession(pSession),m_bManufacturing(false) { m_pEventHandler = new CSecondarySkillEventHandlerServer( pSession ); } void CSecondarySkillRepositoryServer::SendList() { SecondarySkill::SCList TxPacket; memset( &TxPacket, 0, sizeof(TxPacket) ); _ASSERT( m_mSecondarySkill.size() <= _countof(TxPacket.SkillList) ); if( m_mSecondarySkill.size() > _countof(TxPacket.SkillList) ) return; for( std::map::iterator itor=m_mSecondarySkill.begin() ; itor!=m_mSecondarySkill.end() ; ++itor ) { CSecondarySkill* pSkill = (*itor).second; TxPacket.SkillList[TxPacket.cCount].iSkillID = pSkill->GetSkillID(); TxPacket.SkillList[TxPacket.cCount].iExp = pSkill->GetExp(); TxPacket.SkillList[TxPacket.cCount].Grade = pSkill->GetGrade(); TxPacket.SkillList[TxPacket.cCount].iLevel = pSkill->GetLevel(); ++TxPacket.cCount; } int iSize = sizeof(TxPacket)-sizeof(TxPacket.SkillList)+(TxPacket.cCount*sizeof(TxPacket.SkillList[0])); m_pSession->AddSendData( SC_SECONDARYSKILL, eSecondarySkill::SC_LIST, reinterpret_cast(&TxPacket), iSize ); #if defined( _WORK ) for( int i=0 ; iSendDebugChat( wszBuf ); } #endif // #if defined( _WORK ) _SendRecipeList(); } void CSecondarySkillRepositoryServer::_SendRecipeList() { for( std::map::iterator itor=m_mSecondarySkill.begin() ; itor!=m_mSecondarySkill.end() ; ++itor ) { CSecondarySkill* pSkill = (*itor).second; if( pSkill->GetType() != SecondarySkill::Type::ManufactureSkill ) continue; CManufactureSkill* pManufactureSkill = static_cast(pSkill); if( pManufactureSkill->GetRecipeCount() <= 0 ) continue; std::vector vList; pManufactureSkill->CopyList( vList ); // Send Recipe SecondarySkill::SCRecipeList TxPacket; memset( &TxPacket, 0, sizeof(TxPacket) ); TxPacket.cCount = static_cast(vList.size()); for( UINT i=0 ; iGetSkillID(); TxPacket.RecipeList[i].iItemID = vList[i]->GetItemID(); TxPacket.RecipeList[i].biItemSerial = vList[i]->GetItemSerial(); TxPacket.RecipeList[i].nExp = vList[i]->GetExp(); #if defined( _WORK ) WCHAR wszBuf[MAX_PATH]; wsprintf( wszBuf, L"[º¸Á¶½ºÅ³] SC_RECIPE_LIST SkillID:%d ItemID:%d ItemSerial:%I64d Exp:%d", TxPacket.RecipeList[i].iSkillID, TxPacket.RecipeList[i].iItemID, TxPacket.RecipeList[i].biItemSerial, TxPacket.RecipeList[i].nExp ); m_pSession->SendDebugChat( wszBuf ); #endif // #if defined( _WORK ) } int iSize = sizeof(TxPacket)-sizeof(TxPacket.RecipeList)+(TxPacket.cCount*sizeof(TxPacket.RecipeList[0])); m_pSession->AddSendData( SC_SECONDARYSKILL, eSecondarySkill::SC_RECIPE_LIST, reinterpret_cast(&TxPacket), iSize ); } } // ERROR_NONE : OK // ±×¿Ü : ¿¡·¯°ª int CSecondarySkillRepositoryServer::CanCreate( CSecondarySkill* pCreateSkill ) { int iMaxCount = 0; switch( pCreateSkill->GetType() ) { case SecondarySkill::Type::ManufactureSkill: { iMaxCount = SecondarySkill::Max::LearnManufactureSkill; break; } case SecondarySkill::Type::ProductionSkill: { iMaxCount = SecondarySkill::Max::LearnProductionSkill; break; } case SecondarySkill::Type::CommonSkill: { iMaxCount = SecondarySkill::Max::LearnCommonSkill; break; } } // Áߺ¹ ¹× ÃÖ´ë ¼ö °Ë»ç if( Get( pCreateSkill->GetSkillID() ) || GetCount( pCreateSkill->GetType() ) >= iMaxCount ) return ERROR_GENERIC_INVALIDREQUEST; return ERROR_NONE; } // ERROR_NONE : OK // ±×¿Ü : ¿¡·¯°ª int CSecondarySkillRepositoryServer::CanAddRecipe( CSecondarySkill* pSkill, CSecondarySkillRecipe* pRecipe ) { // Á¦ÀÛ ½ºÅ³ °Ë»ç if( pSkill->GetType() != SecondarySkill::Type::ManufactureSkill ) return ERROR_GENERIC_INVALIDREQUEST; // ÃÖ´ë Recipe °³¼ö °Ë»ç CManufactureSkill* pManufactureSkill = static_cast(pSkill); if( pManufactureSkill->GetRecipeCount() >= pManufactureSkill->GetMaxRecipeCount() ) return ERROR_SECONDARYSKILL_ADDRECIPE_MAX; // ½ºÅ³ID °Ë»ç if( pSkill->GetSkillID() != pRecipe->GetSkillID() ) return ERROR_GENERIC_INVALIDREQUEST; // Grade °Ë»ç if( pSkill->GetGrade() < pRecipe->GetRequiredGrade() ) return ERROR_GENERIC_INVALIDREQUEST; // ·¹º§°Ë»ç if( pSkill->GetGrade() == pRecipe->GetRequiredGrade() ) { if( pSkill->GetLevel() < pRecipe->GetRequiredSkillLevel() ) return ERROR_GENERIC_INVALIDREQUEST; } return ERROR_NONE; } // ERROR_NONE : OK À϶§ CSecondarySkillRecipe Æ÷ÀÎÅÍ ÂüÁ¶°ªÀ¸·Î ¹Ýȯ // ±×¿Ü : ¿¡·¯°ª int CSecondarySkillRepositoryServer::CanDeleteRecipe( CSecondarySkill* pSkill, int iItemID, CSecondarySkillRecipe*& pRecipe ) { // Type °Ë»ç if( pSkill->GetType() != SecondarySkill::Type::ManufactureSkill ) return ERROR_GENERIC_INVALIDREQUEST; // ·¹½ÃÇÇ ¾ò±â CManufactureSkill* pManufactureSkill = static_cast(pSkill); pRecipe = pManufactureSkill->GetRecipe( iItemID ); if( pRecipe == NULL ) return ERROR_GENERIC_INVALIDREQUEST; return ERROR_NONE; } // ERROR_NONE : OK À϶§ CSecondarySkillRecipe Æ÷ÀÎÅÍ ÂüÁ¶°ªÀ¸·Î ¹Ýȯ // ±×¿Ü : ¿¡·¯°ª int CSecondarySkillRepositoryServer::CanExtractRecipe( CSecondarySkill* pSkill, int iItemID, CSecondarySkillRecipe*& pRecipe ) { // Type °Ë»ç if( pSkill->GetType() != SecondarySkill::Type::ManufactureSkill ) return ERROR_GENERIC_INVALIDREQUEST; // ·¹½ÃÇÇ ¾ò±â CManufactureSkill* pManufactureSkill = static_cast(pSkill); pRecipe = pManufactureSkill->GetRecipe( iItemID ); if( pRecipe == NULL ) return ERROR_GENERIC_INVALIDREQUEST; // 100% Full»óÅÂÀÎÁö °Ë»ç if( pRecipe->GetMaxExp() <= 0 ) return ERROR_GENERIC_INVALIDREQUEST; if( pRecipe->GetExp() != pRecipe->GetMaxExp() ) return ERROR_GENERIC_INVALIDREQUEST; return ERROR_NONE; } // ERROR_NONE : OK À϶§ CSecondarySkillRecipe Æ÷ÀÎÅÍ ÂüÁ¶°ªÀ¸·Î ¹Ýȯ // ±×¿Ü : ¿¡·¯°ª int CSecondarySkillRepositoryServer::CanManufacture( CSecondarySkill* pSkill, bool bIsStart, int iItemID, CSecondarySkillRecipe*& pRecipe ) { // Type °Ë»ç if( pSkill->GetType() != SecondarySkill::Type::ManufactureSkill ) return ERROR_GENERIC_INVALIDREQUEST; // ·¹½ÃÇÇ ¾ò±â CManufactureSkill* pManufactureSkill = static_cast(pSkill); pRecipe = pManufactureSkill->GetRecipe( iItemID ); if( pRecipe == NULL ) return ERROR_GENERIC_INVALIDREQUEST; TSecondarySkillRecipeTableData* pRecipeData = g_pDataManager->GetSecondarySkillRecipeTableData( pRecipe->GetItemID() ); if( pRecipeData == NULL ) return ERROR_GENERIC_INVALIDREQUEST; // µµ±¸ÅÛ °Ë»ç for( int i=0 ; i<_countof(pRecipeData->iToolItemID) ; ++i ) { if( pRecipeData->iToolItemID[i] <= 0 ) continue; if( m_pSession->GetItem()->GetInventoryItemCount( pRecipeData->iToolItemID[i] ) <= 0 ) return ERROR_GENERIC_INVALIDREQUEST; } // Àç·áÅÛ °Ë»ç for( int i=0 ; i<_countof(pRecipeData->iMaterialItemCount) ; ++i ) { if( pRecipeData->iMaterialItemID[i] <= 0 ) continue; if( m_pSession->GetItem()->GetInventoryItemCount( pRecipeData->iMaterialItemID[i] ) < pRecipeData->iMaterialItemCount[i] ) return ERROR_GENERIC_INVALIDREQUEST; } // Àκ¥Å丮 ºó ÀÚ¸® °Ë»ç int iCreateItemID = pRecipeData->GetManufactureItemID( pRecipe->GetExp(), pRecipe->GetMaxExp() ); TItemData* pItemData = g_pDataManager->GetItemData( iCreateItemID ); if( pItemData == NULL ) { _ASSERT(0); return ERROR_GENERIC_INVALIDREQUEST; } if( pItemData->nType != ITEMTYPE_INSTANT ) { if( m_pSession->GetItem()->FindBlankInventorySlotCount() <= 0 ) return ERROR_GENERIC_INVALIDREQUEST; } else { // ºô¸®Áö¼­¹ö´Â ITEMTYPE_INSTANT Á¦ÀÛÀÌ ºÒ°¡´ÉÇÑ´Ù. #if defined( _VILLAGESERVER ) return ERROR_SECONDARYSKILL_MANUFACTURE_DONTALLOWMAP; #endif // #if defined( _VILLAGESERVER ) } if( bIsStart == true ) { // °á°úÅÛ °Ë»ç int iResultItemID = pRecipeData->GetManufactureItemID( pRecipe->GetExp(), pRecipe->GetMaxExp() ); TItemData* pResultItemData = g_pDataManager->GetItemData( iResultItemID ); if( pResultItemData == NULL ) { _ASSERT(0); return ERROR_GENERIC_INVALIDREQUEST; } if( !g_pDataManager->IsUseItemAllowMapTypeCheck( iResultItemID, m_pSession->GetMapIndex() ) ) return ERROR_SECONDARYSKILL_MANUFACTURE_DONTALLOWMAP; // ÇöÀç Á¦ÀÛÁßÀÎ ½ºÅ³ÀÌ ÀÖ´ÂÁö °Ë»ç if( GetManufacturingSkill() ) return ERROR_GENERIC_INVALIDREQUEST; // ÀÌ¹Ì Á¦ÀÛÁßÀÎÁö °Ë»ç if( pManufactureSkill->bIsManufacturing() == true ) return ERROR_GENERIC_INVALIDREQUEST; } else { // Á¦ÀÛÁßÀÎÁö °Ë»ç if( pManufactureSkill->bIsManufacturing() == false ) return ERROR_GENERIC_INVALIDREQUEST; // Á¦À۽𣠰˻ç if( timeGetTime()-pManufactureSkill->GetManufactureTick() + 900 < static_cast(pRecipeData->iMaxTime) ) return ERROR_GENERIC_INVALIDREQUEST; } return ERROR_NONE; } // ERROR_NONE : OK À϶§ CManufactureSkill Æ÷ÀÎÅÍ ÂüÁ¶°ªÀ¸·Î ¹Ýȯ // ±×¿Ü : ¿¡·¯°ª int CSecondarySkillRepositoryServer::CanCancelManufacture( CManufactureSkill*& pManufacturingSkill ) { #if defined( _GAMESERVER ) // °ÔÀÓ¼­¹ö´Â È£Ãâ ºóµµ¼ö°¡ ³ô¾Æ Flag ·Î ¸ÕÀú °Ë»çÇÑ´Ù. if( bIsManufacturing() == false ) return ERROR_GENERIC_INVALIDREQUEST; #endif // #if defined( _GAMESERVER ) // ÇöÀç Á¦ÀÛÁßÀÎ ½ºÅ³ °Ë»ç pManufacturingSkill = static_cast(GetManufacturingSkill()); if( pManufacturingSkill == NULL ) return ERROR_GENERIC_INVALIDREQUEST; return ERROR_NONE; } // Ŭ¶óÀÌ¾ðÆ®¿¡ ¹ÞÀº ·¹½ÃÇÇ Ãß°¡ int CSecondarySkillRepositoryServer::AddRecipe( SecondarySkill::CSAddRecipe* pPacket ) { CSecondarySkill* pSkill = Get( pPacket->iSkillID ); if( pSkill == NULL ) return ERROR_SECONDARYSKILL_ADDRECIPE_FAILED; const TItem* pItem = NULL; switch( pPacket->cInvenType ) { case ITEMPOSITION_INVEN: { pItem = m_pSession->GetItem()->GetInventory(pPacket->cInvenIndex); if( pItem == NULL ) return ERROR_SECONDARYSKILL_ADDRECIPE_FAILED; if( pItem->nSerial != pPacket->biInvenSerial) return ERROR_SECONDARYSKILL_ADDRECIPE_FAILED; break; } case ITEMPOSITION_CASHINVEN: { pItem = m_pSession->GetItem()->GetCashInventory( pPacket->biInvenSerial ); if( pItem == NULL ) return ERROR_SECONDARYSKILL_ADDRECIPE_FAILED; break; } default: { return ERROR_SECONDARYSKILL_ADDRECIPE_FAILED; } } // ¾ÆÀÌÅÛ Å¸ÀÔ °Ë»ç TItemData* pItemData = g_pDataManager->GetItemData( pItem->nItemID ); if( pItemData == NULL ) return ERROR_SECONDARYSKILL_ADDRECIPE_FAILED; if( pItemData->nType != ITEMTYPE_SECONDARYSKILL_RECIPE ) return ERROR_SECONDARYSKILL_ADDRECIPE_FAILED; // ·¹½ÃÇÇ »ý¼º int iRet = ERROR_SECONDARYSKILL_ADDRECIPE_FAILED; CSecondarySkillRecipe* pRecipe = NULL; do { pRecipe = CSecondarySkillFactory::CreateRecipe( pPacket->iSkillID, pItem->nItemID, pPacket->biInvenSerial, pItem->wDur ); if( pRecipe == NULL || pRecipe->IsValid() == false ) break; iRet = CanAddRecipe( pSkill, pRecipe ); if( iRet != ERROR_NONE ) break; // ¾ÆÀÌÅÛ Á¦°Å bool bDeleteRet = false; if( pPacket->cInvenType == ITEMPOSITION_INVEN ) bDeleteRet = m_pSession->GetItem()->DeleteInventoryBySlot( pPacket->cInvenIndex, 1, pPacket->biInvenSerial, 0 ); else bDeleteRet = m_pSession->GetItem()->DeleteCashInventoryBySerial( pPacket->biInvenSerial, 1, false ); _ASSERT( bDeleteRet ); // ·¹½ÃÇÇ Ãß°¡ CManufactureSkill* pManufactureSkill = static_cast(pSkill); iRet = pManufactureSkill->AddRecipe( pRecipe ); if( iRet != ERROR_NONE ) break; // EventHandler È£Ãâ m_pEventHandler->OnAddRecipe( pRecipe, pItemData->IsCash ); return ERROR_NONE; }while( false ); SAFE_DELETE( pRecipe ); return iRet; } // DB¿¡¼­ ¹ÞÀº ·¹½ÃÇÇ Ãß°¡ bool CSecondarySkillRepositoryServer::AddRecipe( TSecondarySkillRecipe* pRecipeData ) { CSecondarySkill* pSkill = Get( pRecipeData->iSkillID ); if( pSkill == NULL ) return false; CSecondarySkillRecipe* pRecipe = CSecondarySkillFactory::CreateRecipe( pRecipeData->iSkillID, pRecipeData->iItemID, pRecipeData->biItemSerial, pRecipeData->nExp ); do { if( pRecipe == NULL || pRecipe->IsValid() == false ) break; #if defined( _FINAL_BUILD ) if( pSkill->GetType() != SecondarySkill::Type::ManufactureSkill ) break; #else // °³¹ß¹öÁ¯¿¡¼­¸¸ ÇØ´ç ¿¡·¯¿¡ ´ëÇÑ ¿¡·¯ ó¸®ÇÏ°í ±âº»ÀûÀ¸·Î DB¿¡¼­ ¹ÞÀº µ¥ÀÌÅÍ´Â ½Å·ÚÇÑ´Ù. if( CanAddRecipe( pSkill, pRecipe ) != ERROR_NONE ) { _ASSERT(0); break; } #endif // #if defined( _FINAL_BUILD ) CManufactureSkill* pManufactureSkill = static_cast(pSkill); if( pManufactureSkill->AddRecipe( pRecipe ) != ERROR_NONE ) break; return true; }while( false ); SAFE_DELETE( pRecipe ); return false; } // Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ¹ÞÀº ·¹½ÃÇÇ Á¦°Å bool CSecondarySkillRepositoryServer::DeleteRecipe( SecondarySkill::CSDeleteRecipe* pPacket ) { CSecondarySkill* pSkill = Get( pPacket->iSkillID ); if( pSkill == NULL ) return false; CSecondarySkillRecipe* pRecipe = NULL; if( CanDeleteRecipe( pSkill, pPacket->iItemID, pRecipe ) != ERROR_NONE ) return false; CManufactureSkill* pManufactureSkill = static_cast(pSkill); if( pManufactureSkill->DeleteRecipe( pRecipe ) == false ) return false; bool bRet = m_pEventHandler->OnDeleteRecipe( pRecipe ); _ASSERT( bRet ); SAFE_DELETE( pRecipe ); return true; } // Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ¹ÞÀº ·¹½ÃÇÇ ÃßÃâ bool CSecondarySkillRepositoryServer::ExtractRecipe( SecondarySkill::CSExtractRecipe* pPacket ) { CSecondarySkill* pSkill = Get( pPacket->iSkillID ); if( pSkill == NULL ) return false; CSecondarySkillRecipe* pRecipe = NULL; if( CanExtractRecipe( pSkill, pPacket->iItemID, pRecipe ) != ERROR_NONE ) return false; CManufactureSkill* pManufactureSkill = static_cast(pSkill); // ¾ÆÀÌÅÛ ¿©ºÐ °ø°£ üũ TItemData* pItemData = g_pDataManager->GetItemData( pRecipe->GetItemID() ); if( pItemData == NULL ) return false; // ·¹½ÃÇÇ Á¦°Å if( pManufactureSkill->DeleteRecipe( pRecipe ) == false ) return false; // ij½Ã¾ÆÀÌÅÛÀº ½½·Ô Á¦ÇÑÀÌ ¾ø´Ù. int iEmptyInvenIndex = -1; if( pItemData->IsCash != true) { iEmptyInvenIndex = m_pSession->GetItem()->FindBlankInventorySlot(); if( iEmptyInvenIndex < 0 ) return false; TItem ExtractItem; if( CDNUserItem::MakeItemStruct( pRecipe->GetItemID(), ExtractItem ) == false ) return false; ExtractItem.nSerial = pRecipe->GetItemSerial(); ExtractItem.wDur = pRecipe->GetExp(); if( m_pSession->GetItem()->CreateInvenWholeItemByIndex( iEmptyInvenIndex, ExtractItem ) != ERROR_NONE ) return false; } else { TItem ExtractItem; if( m_pSession->GetItem()->MakeCashItemStruct( 0, pRecipe->GetItemID(), ExtractItem ) == false ) return false; ExtractItem.nSerial = pRecipe->GetItemSerial(); ExtractItem.wDur = pRecipe->GetExp(); if( m_pSession->GetItem()->CreateCashInvenWholeItem( ExtractItem ) != ERROR_NONE ) return false; } bool bRet = m_pEventHandler->OnExtractRecipe( pRecipe, pItemData->IsCash ); _ASSERT( bRet ); SAFE_DELETE( pRecipe ); return true; } int CSecondarySkillRepositoryServer::DoManufacture( SecondarySkill::CSManufacture* pPacket ) { CSecondarySkill* pSkill = Get( pPacket->iSkillID ); if( pSkill == NULL ) return ERROR_SECONDARYSKILL_MANUFACTURE_FAILED; CSecondarySkillRecipe* pRecipe = NULL; int iRet = CanManufacture( pSkill, pPacket->bIsStart, pPacket->iItemID, pRecipe ); if( iRet != ERROR_NONE ) return iRet; bool bRet = m_pEventHandler->OnManufacture( pSkill, pRecipe, pPacket->bIsStart ); _ASSERT( bRet ); return ERROR_NONE; } bool CSecondarySkillRepositoryServer::CancelManufacture( bool bSend/*=true*/ ) { CManufactureSkill* pManufacturingSkill = NULL; if( CanCancelManufacture( pManufacturingSkill ) != ERROR_NONE ) { _ASSERT( bIsManufacturing() == false ); return false; } _ASSERT( bIsManufacturing() ); _ASSERT( pManufacturingSkill ); m_pEventHandler->OnCancelManufacture( pManufacturingSkill, bSend ); return true; } // ÇöÀç Á¦ÀÛÁßÀÎ ½ºÅ³ Æ÷ÀÎÅÍ ¾ò±â CSecondarySkill* CSecondarySkillRepositoryServer::GetManufacturingSkill() { for( std::map::iterator itor=m_mSecondarySkill.begin() ; itor!=m_mSecondarySkill.end() ; ++itor ) { CSecondarySkill* pSkill = (*itor).second; if( pSkill->GetType() != SecondarySkill::Type::ManufactureSkill ) continue; CManufactureSkill* pManufactureSkill = static_cast(pSkill); if( pManufactureSkill->bIsManufacturing() ) return pSkill; } return NULL; } #endif // #if defined( PRE_ADD_SECONDARY_SKILL )