#include "stdafx.h" #include "Durability.h" #include "SPlayerInfoMgr.h" #include "SGameSystem.h" #include "SkillBaseFile.h" #include "SInventoryMgr.h" #include "SItemDB.h" //#include "SGameMessageUI.h" #include "SStringDB.h" #include "sgame.h" #include "SGameManager.h" #include "SSummonSlotMgr.h" extern SGameSystem * g_pCurrentGameSystem; #define MSG(pMessage) g_pCurrentGameSystem->GetGame()->GetGameManager()->ProcMsgAtStatic(pMessage) namespace { const short g_nGauge = 12; // 게이지 개수. 11개인데 c_EquipSetNames의 순서에서 망토(cloak) 이 중간에 끼여있는 관계로 12개로 한다. }; void SRepairItemInfo::Set( ItemBaseEx_info * _pItemBase, SInventorySlot * pSlot ) { if( _pItemBase ) { if( pSlot->getMaxEtherealDurability() > 0) { maxEthereal = pSlot->getMaxEtherealDurability(); // 최대내구도. crrEthereal = pSlot->GetEtherealDurability(); // 현재내구도. if( crrEthereal == 0 ) percent = 0.0f; else if( crrEthereal > 0 ) { lossValue = maxEthereal - crrEthereal; // 손실 내구도값. percent = ( ( float )crrEthereal / ( float )maxEthereal ) * 100.0f; // 현재 내구도 %. } EtherealPerOne = (float)maxEthereal / 100.0f; // 1% 당 ethereal 량. } else Clear(); } else { Clear(); } } bool GetBiggerPercent( SRepairItemInfo & p1, SRepairItemInfo & p2 ) { return p1.percent > p2.percent; } bool GetsmallerPercent( SRepairItemInfo & p1, SRepairItemInfo & p2 ) { return p1.percent < p2.percent; } SDurability::SDurability(bool bChar) { bCharacter = bChar; } bool IsRepair( SInventorySlot * pSlot ) { if( pSlot == NULL ) return false; const ItemBaseEx_info * pItemBase = GetItemDB().GetItemData( pSlot->GetItemCode() ); if(pItemBase) { if( pSlot->getMaxEtherealDurability() > 0) // 상급아이템. { // 내구도가 소모된 아이템. int maxEthereal = pSlot->getMaxEtherealDurability(); int crrEthereal = pSlot->GetEtherealDurability(); if( crrEthereal < maxEthereal && crrEthereal > 0 ) { if( ( (float)maxEthereal / 10000.0f ) - ( (float)crrEthereal / 10000.0f ) >= 1.0f ) return true; } } } return false; } bool checkEthereal(SPlayerInfoMgr* pPlayerInfoMgr, int& nCurrentEthereal) { if( pPlayerInfoMgr == NULL ) return false; if( pPlayerInfoMgr->GetEtherealStoneDurability() <= 0 ) { MSG( &SIMSG_REQ_OPEN_MSGBOX( SIMSG_REQ_OPEN_MSGBOX::_MSGBOXID::MSGBOX_GENERAL, S( 7908 ), true ) ); return false; } nCurrentEthereal = pPlayerInfoMgr->GetEtherealStoneDurability(); // 현재 에테리얼충전량. if( nCurrentEthereal < 1 ) { MSG( &SIMSG_REQ_OPEN_MSGBOX( SIMSG_REQ_OPEN_MSGBOX::_MSGBOXID::MSGBOX_GENERAL, S( 733 ), true ) ); return false; } return true; } bool checkCharItems( SPlayerInfoMgr* pPlayerInfoMgr, SInventoryMgr* pInventoryMgr, std::vector< SRepairItemInfo >* pVector ) { if( pPlayerInfoMgr == NULL || pVector == NULL ) return false; int oldWearType = 0; int nSize = g_nGauge + 2; // 교체장비 추가. SInventorySlot* pSlot = NULL; for( int nWearType = 0; nWearType < nSize; ++nWearType ) { SRepairItemInfo aRepairInfo; if( nWearType >= g_nGauge ) // 교체무기. { oldWearType = nWearType; nWearType += ( ItemBase::ItemWearType::WEAR_SWAP_WEAPON - ItemBase::ItemWearType::WEAR_EAR - 1 ); } if (nWearType == 7) // 망토 제외. pSlot = pInventoryMgr->GetItemInfo( ItemBase::WEAR_SECOND_EAR ); else pSlot = pInventoryMgr->GetItemInfo( nWearType ); if( pSlot ) // 장비중. { if( IsRepair( pSlot ) ) // 수리해야 할 내구도가 소모된 아이템. { ItemBaseEx_info * pItemBase = const_cast< ItemBaseEx_info * >( GetItemDB().GetItemData( pSlot->GetItemCode() ) ); aRepairInfo.Set( pItemBase, pSlot ); pVector->push_back( aRepairInfo ); } } if( oldWearType > 0 ) nWearType = oldWearType; } /// 보스카드 체크 for (int beltIndex = 0; beltIndex < 6; ++beltIndex) { AR_HANDLE hItem = pInventoryMgr->GetBeltSlot(beltIndex); if( !hItem ) continue ; pSlot = pInventoryMgr->GetItemInfo(hItem); if( pSlot && GetItemDB().GetGroup(pSlot->GetItemCode()) == ItemBase::GROUP_BOSSCARD ) { if( IsRepair( pSlot ) ) { ItemBaseEx_info * pItemBase = const_cast< ItemBaseEx_info * >( GetItemDB().GetItemData( pSlot->GetItemCode() ) ); SRepairItemInfo aRepairInfo; aRepairInfo.Set( pItemBase, pSlot ); pVector->push_back( aRepairInfo ); } } } return true; } bool checkCreatureItems( SPlayerInfoMgr* pPlayerInfoMgr, SCreatureSlotMgr* pCreatureSlotMgr, SInventoryMgr* pInventoryMgr, std::vector< SRepairItemInfo >* pVector ) { if( pPlayerInfoMgr == NULL || pCreatureSlotMgr == NULL || pVector == NULL ) return false; float fRate = 0.0f; AR_HANDLE hCreture = pCreatureSlotMgr->GetSelectedCreature(); if( hCreture ) { int nCount = SCreatureSlotMgr::MAX_CREATURE_SLOT - 1; // 크리처 아이템 슬롯 5개 for( int i = 0; i < nCount; i++ ) { AR_HANDLE hItem = pCreatureSlotMgr->GetCreatureItem( hCreture, i ); if( hItem == NULL ) continue; SInventorySlot* pSlot = pInventoryMgr->GetItemInfo( hItem ); if( pSlot ) { if( IsRepair( pSlot ) ) { ItemBaseEx_info * pItemBase = const_cast< ItemBaseEx_info * >( GetItemDB().GetItemData( pSlot->GetItemCode() ) ); SRepairItemInfo aRepairInfo; aRepairInfo.Set( pItemBase, pSlot ); pVector->push_back( aRepairInfo ); } } } } return true; } float SDurability::calculate(SPlayerInfoMgr* pPlayerInfoMgr, SInventoryMgr* pInventoryMgr, SCreatureSlotMgr* pCreatureSlotMgr) { if( pPlayerInfoMgr == NULL || pInventoryMgr == NULL ) return 0.0f; int crrEthereal = 0; if( false == checkEthereal(pPlayerInfoMgr, crrEthereal) ) return 0.0f; crrEthereal *= 10000; m_arrRepairInfo.clear(); if( bCharacter ) { if( false == checkCharItems(pPlayerInfoMgr, pInventoryMgr, &m_arrRepairInfo) ) // 캐릭터 return 0.0f; } else { if( false == checkCreatureItems(pPlayerInfoMgr, pCreatureSlotMgr, pInventoryMgr, &m_arrRepairInfo) ) // 크리처 return 0.0f; } if( m_arrRepairInfo.empty() ) // 수리할 아이템이 없다. { MSG( &SIMSG_REQ_OPEN_MSGBOX( SIMSG_REQ_OPEN_MSGBOX::_MSGBOXID::MSGBOX_GENERAL, S( 732 ), true ) ); return 0.0f; } float sendPercent = 0.0f; // 서버에 전송할 충전 %. // 전체충전 가능검사. int needValue = 0; // 개별 충전필요량. int needTotalValue = 0; // 총 충전 필요량. int size = m_arrRepairInfo.size(); for( int i=0; i arrNeedEthereal; // 필요 에테리얼 량. float bigPercent = 0.0f; size = m_arrRepairInfo.size(); for( int i=0; i 0 ) { rest = crrEthereal;// - needTotalValue; int needValue = 0; // % 만큼 에테리얼을 채운다. //size = m_arrRepairInfo.size(); size = arrNeedEthereal.size(); for( int x=0; x 0 ) { rest -= needValue; // 나머지 에테리얼 감소. aInfo.crrEthereal += needValue; // 현재 % 다시 계산. aInfo.percent = (float)aInfo.crrEthereal / (float)aInfo.maxEthereal; } } // 오름차순 정렬. std::vector< SRepairItemInfo > arrRepairInfoSmall( m_arrRepairInfo.begin(), m_arrRepairInfo.end() ); sort( arrRepairInfoSmall.begin(), arrRepairInfoSmall.end(), GetsmallerPercent ); float smallPercent = arrRepairInfoSmall[ 0 ].percent; // 가장 작은 내구도 %. size = arrRepairInfoSmall.size(); bool bLoop = true; while( bLoop ) { for( int x=0; x