#include "StdAfx.h" #include ".\CrystallizeImplement.h" #include #include "StatisticsManager.h" #include "ExtraNPCManager.h" #include #include ".\ItemManager.h" #include ".\ChaoState.h" #include ".\Player.h" CrystallizeImplement::CrystallizeImplement( void ) { } CrystallizeImplement::~CrystallizeImplement( void ) { } VOID CrystallizeImplement::OnFailed( DWORD dwResult ) { MSG_CG_ITEM_CRYSTALIZE_NAK Message; Message.m_byErrorCode = (BYTE)dwResult; m_pPlayer->SendPacket( &Message, sizeof(Message) ); } VOID CrystallizeImplement::OnImplement( MSG_BASE* pRecvMessage ) { MSG_CG_ITEM_CRYSTALIZE_SYN* pRecvMsg = (MSG_CG_ITEM_CRYSTALIZE_SYN*)pRecvMessage; ItemManager* item_manager = m_pPlayer->GetItemManager(); SCSlotContainer* inventory = item_manager->GetItemSlotContainer(SI_INVENTORY); SCItemSlot& rTargetItem = (SCItemSlot &)inventory->GetSlot( pRecvMsg->m_TargetPos ); static CrystallizeImplement::sOutput Output; RC::eITEM_RESULT Result = Crystallize( rTargetItem, Output ); if( Result != RC::RC_ITEM_SUCCESS ) { OnFailed( Result ); return; } if( Output.TotalCount > 0 ) { MSG_CG_ITEM_CRYSTALIZE_SUCCESS_ACK Message; RC::eITEM_RESULT Result = item_manager->ObtainAllKindOfItem(Output.TotalCount, Output.ObtainCodeArray, Output.ObtainCountArray, &Message.m_ItemInfo); if( Result == RC::RC_ITEM_SUCCESS ) { // °áÁ¤È­ ¼º°ø ·Î±× GAMELOG->LogCrystalizeSuccess(m_pPlayer, rTargetItem, Output.TotalCount, Output.ObtainCodeArray, Output.ObtainCountArray); g_StatisticsManager.PlusStatisticType(eSTATISTIC_CRYSTALIZE_COUNT, 1); #ifdef _NA_007408_20140711_MODIFY_CRYSTALLIZE DeleteTargetItem(rTargetItem); #else inventory->DeleteSlot(pRecvMsg->m_TargetPos, NULL); #endif //_NA_007408_20140711_MODIFY_CRYSTALLIZE Message.m_Money = m_pPlayer->GetMoney(); m_pPlayer->SendPacket( &Message, Message.GetSize() ); } else { OnFailed( Result ); } } else { // °áÁ¤È­ ½ÇÆÐ ·Î±× GAMELOG->LogItem( ITEM_CRYSTALIZE_FAILED, m_pPlayer, &rTargetItem ); g_StatisticsManager.PlusStatisticType( eSTATISTIC_CRYSTALIZE_COUNT, 1 ); #ifdef _NA_007408_20140711_MODIFY_CRYSTALLIZE DeleteTargetItem(rTargetItem); #else inventory->DeleteSlot(pRecvMsg->m_TargetPos, NULL); #endif //_NA_007408_20140711_MODIFY_CRYSTALLIZE MSG_CG_ITEM_CRYSTALIZE_FAILED_ACK Message; Message.m_Money = m_pPlayer->GetMoney(); m_pPlayer->SendPacket( &Message, sizeof(Message) ); } } BOOL CrystallizeImplement::OnCheck( MSG_BASE* pRecvMsg, DWORD& OUT dwResult ) { MSG_CG_ITEM_CRYSTALIZE_SYN* pMessage = (MSG_CG_ITEM_CRYSTALIZE_SYN *)pRecvMsg; dwResult = RC::RC_ITEM_SUCCESS; ItemManager* item_manager = m_pPlayer->GetItemManager(); ASSERT(item_manager); if (item_manager == NULL) { dwResult = RC::RC_ITEM_FAILED; return FALSE; } SCSlotContainer* inventory = item_manager->GetItemSlotContainer(SI_INVENTORY); ASSERT(inventory); if (inventory == NULL) { dwResult = RC::RC_ITEM_FAILED; return FALSE; } if( !m_pPlayer->GetField() ) { dwResult = RC::RC_ITEM_UNABLE_FUNCTION_FOR_CUR_ZONE; return FALSE; } if( item_manager->IsRestrictFunction( eFUNCTIONALRESTRICT_CRYSTALIZE ) ) { dwResult = RC::RC_ITEM_UNUSABLE_FUNCTION; return FALSE; } #ifdef __NA_676_PK_SYSTEM_IMPROVEMENT if( !m_pPlayer->GetChaoState().CanUseFuction( CHAO_USE_CRYSTALIZE ) ) { dwResult = RC::RC_ITEM_UNABLE_FUNCTION_FOR_CHAOSTATE; return FALSE; } #else //__NA_676_PK_SYSTEM_IMPROVEMENT if( m_pPlayer->GetChaoState().IsChaoState() ) { dwResult = RC::RC_ITEM_UNABLE_FUNCTION_FOR_CHAOSTATE; return FALSE; } #endif //__NA_676_PK_SYSTEM_IMPROVEMENT if( m_pPlayer->GetBehave() == PLAYER_BEHAVE_UNEXPECTED_WAITING ) { dwResult = RC::RC_ITEM_INVALIDSTATEOFPLAYER; return FALSE; } if( !m_pPlayer->GetWarehouseInventoryProtector().INVENTORY().IsUsable() ) { dwResult = RC::RC_ITEM_INVENTORY_NEED_PASSWORD; return FALSE; } #ifdef _NA_007408_20140711_MODIFY_CRYSTALLIZE #else if( m_pPlayer->GetLevel() < LIMIT_LEVEL_CRYSTALIZE ) { dwResult = RC::RC_ITEM_UNABLE_FUNCTION_FOR_CURR_LEVEL; return FALSE; } #endif //_NA_007408_20140711_MODIFY_CRYSTALLIZE if( !item_manager->ValidState() ) { dwResult = RC::RC_ITEM_INVALIDSTATE; return FALSE; } if( !item_manager->ValidPos( SI_INVENTORY, pMessage->m_TargetPos ) ) { dwResult = RC::RC_ITEM_INVALIDPOS; return FALSE; } #ifdef _NA_007408_20140711_MODIFY_CRYSTALLIZE #else if( !g_ExtraNPCManager.IsLengthCanUseNPC( pMessage->m_NPCCode, m_pPlayer, eNPC_TYPE_ITEM_MIX ) ) { dwResult = RC::RC_ITEM_LENGTH_CANNOT_USE_NPC; return FALSE; } #endif //_NA_007408_20140711_MODIFY_CRYSTALLIZE return TRUE; } #ifdef _NA_007408_20140711_MODIFY_CRYSTALLIZE RC::eITEM_RESULT CrystallizeImplement::Crystallize( SCItemSlot& rTargetItem, CrystallizeImplement::sOutput& OUT Output ) { BYTE TotalCount = 0; SLOTCODE* ObtainCodeArray = Output.ObtainCodeArray; DURATYPE* ObtainCountArray = Output.ObtainCountArray; //Á¤·Ä¿ë STLX_MAP created_materials; // ¸ÕÀú, ¸¸µé¾îÁø Àç·áµéÀ» À̰÷¿¡ ´ã´Â´Ù. STLX_MAP::iterator miter; // Check Validity--------------------------------------------------------------------------- const BASE_ITEMINFO* const pItemInfo = rTargetItem.GetItemInfo(); FASSERT( pItemInfo ); if( !pItemInfo ) return RC::RC_ITEM_INVALID_VALUE; #ifdef _NA_008124_20150313_AWAKENING_SYSTEM SLOTCODE CrystallizeCode = ItemCrystalizeListParser::Instance()->GetCrystalizeCode( rTargetItem, rTargetItem.GetEnchant() ); #else SLOTCODE CrystallizeCode = ItemCrystalizeListParser::Instance()->GetCrystalizeCode( rTargetItem ); #endif // _NA_008124_20150313_AWAKENING_SYSTEM sITEM_CRYSTALIZE_LIST* pListInfo = ItemCrystalizeListParser::Instance()->GetCrystalizeListInfo( CrystallizeCode ); if( !pListInfo ) { SUNLOG( eCRITICAL_LOG, "CrystallizeImplement::Crystallize() Can't Find Crystallize List Information [Code : %d]", CrystallizeCode ); return RC::RC_ITEM_INVALID_VALUE; } if( pListInfo->m_ItemType != pItemInfo->m_wType ) return RC::RC_ITEM_INVALID_VALUE; if (rTargetItem.CanUseMixture(MIXTURE_CRYSTALIZE) == false) { return RC::RC_ITEM_NOT_MIXTURE; } //------------------------------------------------------------------------------------------ // Count Materials, »ý¼ºµÉ °áÁ¤Ã¼µéÀ» ¿ì¼± ±¸ÇÑ´Ù DWORD seed = 1; DWORD ObtainCount = 0; SLOTCODE material_code = 0; for( int count = 0 ; count < sITEM_CRYSTALIZE_LIST::MAX_MATERIALS ; ++count ) { material_code = pListInfo->m_pResult[count].m_MaterialCode; // °áÁ¤Ã¼ ȹµæ È®·ü seed = random( 1, 100 ); if( seed > pListInfo->m_pResult[count].m_ResultRatio ) continue; if( material_code == 0 ) continue; // »ý¼ºµÉ °áÁ¤Ã¼ °³¼ö °è»ê ObtainCount = pListInfo->m_pResult[count].m_MaterialCount; #ifdef _NA_008124_20150313_AWAKENING_SYSTEM SLOTCODE temp_crystallize_code = ItemCrystalizeListParser::Instance()->GetCrystalizeCode( rTargetItem, 0 ); sITEM_CRYSTALIZE_LIST* list_info = ItemCrystalizeListParser::Instance()->GetCrystalizeListInfo( temp_crystallize_code ); if( !list_info ) { continue; } ObtainCount += (list_info->m_pResult[count].m_MaterialCount * rTargetItem.GetAwakening()); #endif // _NA_008124_20150313_AWAKENING_SYSTEM // °áÁ¤Ã¼ÀÇ ±Ý¾×ÀÌ 0 ÀÌ ¾Æ´Ñ °æ¿ì ¾ÆÀÌÅÛÀÇ »óÁ¡ ±¸ÀÔ °¡°Ý/ MaterialMoney·Î Ãß°¡µÇ´Â °áÁ¤Ã¼ÀÇ °¹¼ö°¡ °áÁ¤µÈ´Ù. if( 0 != pListInfo->m_pResult[count].m_MaterialMoney ) { ObtainCount += (rTargetItem.GetPriceForBuy() / pListInfo->m_pResult[count].m_MaterialMoney); } miter = created_materials.find(material_code); if (miter == created_materials.end()) { created_materials[material_code] = ObtainCount; } else /* if (miter != created_materials.end())*/ { miter->second += ObtainCount; } } //created_materialsÀÇ Àç·áµéÀ» Àû´çÇÏ°Ô outputÀÇ ¹è¿­¿¡ ´ã¾ÆÁØ´Ù-------------------------------- for (miter = created_materials.begin(); miter != created_materials.end(); ++miter) { SLOTCODE material_code = miter->first; DWORD material_count = miter->second; // °áÁ¤Ã¼ÀÇ °¹¼ö°¡ 255°¡ ³ÑÀ» °æ¿ì ´ÙÀ½ ½½·ÔÀ¸·Î ³Ñ±ä´Ù. ÇÑ ½½·Ô´ç ÃÖ´ë 255°³ÀÇ µ¿ÀÏ ¾ÆÀÌÅÛ ¼ö¿ë °¡´É. // ¶ÇÇÑ ÃÖ´ë °¡Áú ¼ö ÀÖ´Â °áÁ¤Ã¼ÀÇ °¹¼ö¸¦ ÃÑ 2°³ÀÇ ½½·ÔÀ¸·Î Á¦ÇÑ ½ÃŲ´Ù. material_count = min( material_count, UCHAR_MAX*2 ); while( material_count > UCHAR_MAX ) { ObtainCodeArray[TotalCount] = material_code; ObtainCountArray[TotalCount] = UCHAR_MAX; material_count -= UCHAR_MAX; ++TotalCount; } if( material_count > 0 ) { ObtainCodeArray[TotalCount] = material_code; ObtainCountArray[TotalCount] = (BYTE)material_count; ++TotalCount; } } Output.TotalCount = TotalCount; ASSERT( TotalCount <= MAX_INVENTORY_SLOT_NUM ); if( TotalCount > MAX_INVENTORY_SLOT_NUM ) { SUNLOG( eCRITICAL_LOG, "CrystallizeImplement::Crystallize() Crystallize Overflow to Max Slot Count" ); return RC::RC_ITEM_FAILED; } return RC::RC_ITEM_SUCCESS; } VOID CrystallizeImplement::DeleteTargetItem( SCItemSlot& rTargetItem ) { ItemManager* item_manager = m_pPlayer->GetItemManager(); SCSlotContainer* inventory = item_manager->GetItemSlotContainer(SI_INVENTORY); MSG_CG_ITEM_LOSE_ACK delete_msg; delete_msg.m_ItemInfo.Clear(); DURATYPE item_count = delete_msg.m_ItemInfo.m_Count; delete_msg.m_ItemInfo.m_Slot[item_count].m_Num = rTargetItem.GetNum(); delete_msg.m_ItemInfo.m_Slot[item_count].m_Pos = rTargetItem.GetPos(); ++delete_msg.m_ItemInfo.m_Count; inventory->DeleteSlot(rTargetItem.GetPos(), NULL); m_pPlayer->SendPacket( &delete_msg, sizeof(delete_msg) ); } #else RC::eITEM_RESULT CrystallizeImplement::Crystallize( SCItemSlot& rTargetItem, CrystallizeImplement::sOutput& OUT Output ) { const BASE_ITEMINFO* const pItemInfo = rTargetItem.GetItemInfo(); FASSERT( pItemInfo ); if( !pItemInfo ) return RC::RC_ITEM_INVALID_VALUE; SLOTCODE CrystallizeCode = ItemCrystalizeListParser::Instance()->GetCrystalizeCode( rTargetItem ); sITEM_CRYSTALIZE_LIST* pListInfo = ItemCrystalizeListParser::Instance()->GetCrystalizeListInfo( CrystallizeCode ); if( !pListInfo ) { SUNLOG( eCRITICAL_LOG, "CrystallizeImplement::Crystallize() Can't Find Crystallize List Information [Code : %d]", CrystallizeCode ); return RC::RC_ITEM_INVALID_VALUE; } if( pListInfo->m_ItemType != pItemInfo->m_wType ) return RC::RC_ITEM_INVALID_VALUE; if (rTargetItem.CanUseMixture(MIXTURE_CRYSTALIZE) == false) { return RC::RC_ITEM_NOT_MIXTURE; } // ÀϹÝÀûÀÎ ¾ÆÀÌÅÛÀÎ °æ¿ì 1·¹º§ 0·©Å© EÀÎæƮÀÎ ¹«±â´Â ºÐÇØ ºÒ°¡´É if( pItemInfo->m_wSubType == eITEMSUBTYPE_GENERAL ) { if( pItemInfo->m_LV == 1 && rTargetItem.GetRank() == RANK_E && rTargetItem.GetEnchant() == 0 ) return RC::RC_ITEM_INVALID_VALUE; } // ±âº»ÀûÀ¸·Î pListInfo->m_ItemLevel = 0°ªÀ» °¡Áö¸ç, ¾Ç¼¼»ç¸®ÀÇ °æ¿ì 1, 2ÀÇ Level°ªÀ» °¡Áø´Ù. if( pListInfo->m_ItemLevel && ( pItemInfo->m_LV != pListInfo->m_ItemLevel ) ) return RC::RC_ITEM_INVALID_VALUE; if( pListInfo->m_EnchantLv != rTargetItem.GetEnchant() ) return RC::RC_ITEM_INVALID_VALUE; POSTYPE TotalCount = 0; DWORD seed = 1; int i = 0; MONEY ObtainCount = 0; SLOTCODE* ObtainCodeArray = Output.ObtainCodeArray; POSTYPE* ObtainCountArray = Output.ObtainCountArray; // 1Â÷ °áÁ¤Ã¼ ȹµæ È®·ü for( i = 0 ; i < sITEM_CRYSTALIZE_LIST::MAX_RESULT ; ++i ) { seed = random( 1, 100 ); if( seed > pListInfo->m_pResult[i].m_ResultRatio ) continue; if( pListInfo->m_pResult[i].m_MaterialCode == 0 ) continue; ObtainCount = pListInfo->m_pResult[i].m_MaterialCount; // °áÁ¤Ã¼ÀÇ ±Ý¾×ÀÌ 0 ÀÌ ¾Æ´Ñ °æ¿ì ¾ÆÀÌÅÛÀÇ »óÁ¡ ±¸ÀÔ °¡°Ý/ MaterialMoney·Î Ãß°¡µÇ´Â °áÁ¤Ã¼ÀÇ °¹¼ö°¡ °áÁ¤µÈ´Ù. if( 0 != pListInfo->m_pResult[i].m_MaterialMoney ) { ObtainCount += (rTargetItem.GetPriceForBuy() / pListInfo->m_pResult[i].m_MaterialMoney); } // °áÁ¤Ã¼ÀÇ °¹¼ö°¡ 255°¡ ³ÑÀ» °æ¿ì ´ÙÀ½ ½½·ÔÀ¸·Î ³Ñ±ä´Ù. ÇÑ ½½·Ô´ç ÃÖ´ë 255°³ÀÇ µ¿ÀÏ ¾ÆÀÌÅÛ ¼ö¿ë °¡´É. // ¶ÇÇÑ ÃÖ´ë °¡Áú ¼ö ÀÖ´Â °áÁ¤Ã¼ÀÇ °¹¼ö¸¦ ÃÑ 2°³ÀÇ ½½·ÔÀ¸·Î Á¦ÇÑ ½ÃŲ´Ù. ObtainCount = min( ObtainCount, UCHAR_MAX*2 ); while( ObtainCount > UCHAR_MAX ) { ObtainCodeArray[TotalCount] = pListInfo->m_pResult[i].m_MaterialCode; ObtainCountArray[TotalCount] = UCHAR_MAX; ObtainCount -= UCHAR_MAX; ++TotalCount; } if( ObtainCount > 0 ) { ObtainCodeArray[TotalCount] = pListInfo->m_pResult[i].m_MaterialCode; ObtainCountArray[TotalCount] = (POSTYPE)ObtainCount; ++TotalCount; } } // ·£´ý °áÁ¤Ã¼ ȹµæ È®·ü for( i = 0 ; i < sITEM_CRYSTALIZE_LIST::MAX_RANDOMRESULT ; ++i ) { seed = (DWORD)dRandom( 1, pListInfo->m_pRandomResult[i].m_RandomStandardRatio ); if( seed > pListInfo->m_pRandomResult[i].m_RandomRatio ) continue; if( pListInfo->m_pRandomResult[i].m_MaterialCode == 0 ) continue; // °áÁ¤Ã¼ÀÇ °¹¼ö°¡ 255°¡ ³ÑÀ» °æ¿ì ´ÙÀ½ ½½·ÔÀ¸·Î ³Ñ±ä´Ù. ÇÑ ½½·Ô´ç ÃÖ´ë 255°³ÀÇ µ¿ÀÏ ¾ÆÀÌÅÛ ¼ö¿ë °¡´É. // ¶ÇÇÑ ÃÖ´ë °¡Áú ¼ö ÀÖ´Â °áÁ¤Ã¼ÀÇ °¹¼ö¸¦ ÃÑ 1°³ÀÇ ½½·ÔÀ¸·Î Á¦ÇÑ ½ÃŲ´Ù. ObtainCount = min( pListInfo->m_pRandomResult[i].m_MaterialCount, UCHAR_MAX ); if( ObtainCount > 0 ) { ObtainCodeArray[TotalCount] = pListInfo->m_pRandomResult[i].m_MaterialCode; ObtainCountArray[TotalCount] = (POSTYPE)ObtainCount; ++TotalCount; } } Output.TotalCount = TotalCount; ASSERT( TotalCount <= MAX_INVENTORY_SLOT_NUM ); if( TotalCount > MAX_INVENTORY_SLOT_NUM ) { SUNLOG( eCRITICAL_LOG, "CrystallizeImplement::Crystallize() Crystallize Overflow to Max Slot Count" ); return RC::RC_ITEM_FAILED; } return RC::RC_ITEM_SUCCESS; } #endif //_NA_007408_20140711_MODIFY_CRYSTALLIZE