#include "stdafx.h" #include "SInventoryMgr.h" //#include //#include #include "SGame.h" #include "SChatType.h" #include "SGameMessage.h" //#include "SGameMessageUI.h" #include "SkillBaseFile.h" #include "SItemDB.h" #include "SStringDB.h" #include "SUIDefine.h" #include "SGameInput.h" #include "SSummonSlotMgr.h" #include "SUISysMsgDefine.h" #include "SDebug_Util.h" #include #include "SUIUtil.h" // AziaMafia ++ #include "SCommandSystem.h" #include "SGameSystem.h" extern SGameSystem* g_pCurrentGameSystem; //IsInstanceUnstackable : 중복불가능한가? ( 비정적데이터를 이용하여 ) bool IsInstanceUnstackable( SInventorySlot* pSlot ) { static SInventoryMgr* pInvenMgr = NULL; if( pInvenMgr == NULL ) pInvenMgr = static_cast(GameUIMgrInstance.GetUIMgr( SGameUIInstance::INVENTORY_MGR )); return pSlot->GetXFlag().IsOn( ItemInstance::ITEM_FLAG_SUMMON ) || ( pInvenMgr && pInvenMgr->IsEquipCard( pSlot->GetHandle() ) ); } bool IsInstanceUnstackable( const XFlag& rFlag ) { return rFlag.IsOn( ItemInstance::ITEM_FLAG_SUMMON ); } bool IsInstanceUnstackable( const int nFlag ) { XFlag xFlag; xFlag.CopyFrom( &nFlag); return IsInstanceUnstackable( xFlag ); } const char* GetMaterialSound( int nMaterial ) { switch( nMaterial ) { case 0: return "ui_wear_skin01.wav"; break;//피부 case 1: return "ui_wear_leather01.wav"; break;//가죽 case 2: return "ui_wear_wood01.wav"; break;//나무 case 3: return "ui_wear_steel01.wav"; break;//금속 case 4: return "ui_wear_feather01.wav"; break;//깃털 case 5: return "ui_wear_stone01.wav"; break;//돌 case 6: return "ui_wear_bone01.wav"; break;//뼈 case 7: return "ui_wear_acc01.wav"; break;//악세서리 case 8: return "ui_wear_cube01.wav"; break;//큐브 case 9: return "ui_wear_paper01.wav"; break;//종이 case 10: return "ui_wear_shackle01.wav"; break;//쇠사슬 case 11: return "ui_wear_water01.wav"; break;//물 case 12: return "ui_wear_cloth01.wav"; break;//옷감류 case 13: return "ui_wear_powder01.wav"; break;//가루류 default : return "ui_icon_drag.wav"; // case 99: //기타 } return "ui_icon_drag.wav"; } ////////////////////////////////////////////////////////////////////////// // shop slot SShopSlot::SShopSlot() { m_nItemCode = 0; m_nIconID = 0; m_nPrice = money_t( 0 ); m_nHuntaHolicPoint = money_t( 0 ); // #2.1.2.11.1 m_hNpc = NULL; } SShopSlot::~SShopSlot() { } void SShopSlot::SetItemCode( int nItemCode ) { m_nItemCode = nItemCode; m_nIconID = GetItemDB().GetIconID(nItemCode); } ////////////////////////////////////////////////////////////////////////// //Invetory Slot SInventorySlot::SInventorySlot() : m_bIsAppendedDecomposeWnd( false ) { m_nGetItemCount = count_t( 0 ); m_bIsExistence = false; m_nIconID = 0; ::memset( &m_ItemInfo, 0, sizeof(m_ItemInfo) ); m_nLastDurabilityCheckPercent = 0; m_nLastDurabilityValue = 0; m_bShowDecoration = true; // 꾸미기아이템 보임. } SInventorySlot::~SInventorySlot() { } void SInventorySlot::SetItem( TS_ITEM_INFO* pItemInfo ) { ::memcpy( &m_ItemInfo, pItemInfo, sizeof(m_ItemInfo) ); } // { [sonador][3.1.2] 경매장 구현 const unsigned int SInventorySlot::GetMaxEndurance( TS_ITEM_BASE_INFO* item ) { const ItemBaseEx_info* pItemBaseInfo( GetItemDB().GetItemData( item->Code ) ); if( NULL == pItemBaseInfo ) return NULL; if( NULL == item->socket ) return NULL; int nJewelID( NULL ); unsigned int dwMaxEndurance( NULL ); const ItemBaseEx_info* pJewelInfo( NULL ); const int nJewelSlotCount( pItemBaseInfo->socket + item->random_option.GetAddJewelSocketCount() ); for( int i( 0 ); i < nJewelSlotCount; ++i ) { nJewelID = item->socket[i]; if( nJewelID ) { pJewelInfo = GetItemDB().GetItemData( nJewelID ); if( pJewelInfo ) dwMaxEndurance += pJewelInfo->nEndurance; } } return dwMaxEndurance; } const int SInventorySlot::GetCrrEndurancePer( TS_ITEM_BASE_INFO* item, unsigned int& rEndurance ) { const ItemBaseEx_info* pItemBaseInfo( GetItemDB( ).GetItemData( item->Code ) ); if( NULL == pItemBaseInfo ) return SInventorySlot::NONEITEM; if( NULL == item->socket ) return SInventorySlot::SOKETNULL; int nJewelID( 0 ); unsigned int dwMaxEndurance( GetMaxEndurance( item ) ); if( dwMaxEndurance ) { unsigned int dwEndurance = ( item->endurance + 99999 ) / 100000; dwMaxEndurance = dwMaxEndurance / 100000; if( dwMaxEndurance == 0 ) rEndurance = 0; else rEndurance = dwEndurance * 100 / dwMaxEndurance; if( rEndurance == 0 && dwEndurance != 0 ) rEndurance = 1; return SInventorySlot::ENDURANCE_SUCCESS; } return SInventorySlot::NONESOKET; } const unsigned int SInventorySlot::GetMaxEndurance() { return GetMaxEndurance( &m_ItemInfo ); } const int SInventorySlot::GetCrrEndurancePer( unsigned int& rEndurance ) { return GetCrrEndurancePer( &m_ItemInfo, rEndurance ); } // 2010.07.14 - prodongi int SInventorySlot::getMaxEtherealDurability() const { float pEnhanceDurability[30] = { 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 10.f, 10.f, 10.f, 10.f }; ItemBaseEx_info const* itemBaseInfo = GetItemDB( ).GetItemData(m_ItemInfo.Code); if (!itemBaseInfo) return 0; if (itemBaseInfo->nType == ItemBase::TYPE_ARMOR && GetEnhance() > 0 && GetEnhance() <= 29) return itemBaseInfo->nEthereal_durability * pEnhanceDurability[ GetEnhance() - 1 ]; return itemBaseInfo->nEthereal_durability; } // 2010.07.14 - prodongi bool SInventorySlot::isExhausted() const { if (isExhaustedSummonCard(m_ItemInfo.Code, GetEnhance(), GetEtherealDurability())) return true; return ((0 < getMaxEtherealDurability()) && (0 == GetEtherealDurability())); } bool SInventorySlot::IsAwakeningItem() { for ( int i = 0; i < ItemBase::MAX_AWAKENING_OPTION; i++ ) { if ( m_ItemInfo.awakenoption.nData[i] != 0 ) return true; } return false; } void SInventorySlot::SetUpdateCount( count_t nNewCount, bool bDestroy /*= false*/ ) { if( !bDestroy ) m_nGetItemCount = GetItemCount() > 0 ? (nNewCount - GetItemCount()) : nNewCount; else m_nGetItemCount = nNewCount; } //----------------------------------------------------------------------------------------------------------------- // 보석 장착 슬롯 개수 얻기 // 설명 : 기본 ItemResourceDB에 설정된 슬롯 개수 + 랜덤 옵션으로 생성 된 슬롯 개수 //----------------------------------------------------------------------------------------------------------------- const int SInventorySlot::GetJewelSlotCount() { int nJewelSlotCount( NULL ); int nte = m_ItemInfo.Code; const ItemBaseEx_info* pItemBaseInfo( GetItemDB().GetItemData( GetItemCode() ) ); if( NULL == pItemBaseInfo ) return nJewelSlotCount; nJewelSlotCount += pItemBaseInfo->socket; TS_ITEM_BASE_INFO::RANDOM_OPTION* const pRandomOption( GetRandomOption() ); if( NULL == pRandomOption ) return nJewelSlotCount; nJewelSlotCount += pRandomOption->GetAddJewelSocketCount(); return nJewelSlotCount; } ////////////////////////////////////////////////////////////////////////// //Invetory SInventoryMgr::SInventoryMgr() : SGameUIMgr() // 2011.03.29 - servantes , m_pUpdateItemInfo( NULL ) { Clear(); m_pUpdateItemInfo = new SInventorySlot; } SInventoryMgr::~SInventoryMgr() { Clear(); } void SInventoryMgr::Clear() { ItemSet(SET_INDEX_01); for( unsigned int a(0); ItemBase::MAX_ITEM_WEAR>a; a++ ) { m_itemCode[a] = 0; m_itemHandle[a] = 0; } m_dwTime = 0; m_dwCheckLendingTime = 0; m_nCheckCount = 0; for( int i(0); TS_SC_ITEM_COOL_TIME::MAX_ITEM_COOLTIME_GROUP>i; i++ ) { m_dwCur_time[i] = 0; m_dwCool_time[i] = 0; m_dwRemain_time[i] = 0; } m_hCashDragItem = 0; for( int i(0); c_BeltSlotCnt>i; i++ ) handle_BeltSlot[i] = 0; m_vLendingItem.clear(); SAFE_DELETE_VECTOR( m_vInventory ); SAFE_DELETE_VECTOR( m_vecShopList ); m_vCashItemList.clear(); m_vEquipCareList.clear(); SAFE_DELETE( m_pUpdateItemInfo ); m_rqItemState = RQ_ITEM_STATE::RQ_ITEM_STATE_NONE; // 아이템 요청 상태. } void SInventoryMgr::ResetInfo() { Clear(); if( m_pUpdateItemInfo == NULL ) m_pUpdateItemInfo = new SInventorySlot; } AR_HANDLE SInventoryMgr::GetItemHandle( int nIndex ) { if( m_vInventory.empty() ) return NO_HANDLE; if( (int)m_vInventory.size() <= nIndex ) return NO_HANDLE; return m_vInventory[nIndex]->GetHandle(); } AR_HANDLE SInventoryMgr::GetItemHandleForCode( int nItemCode ) { int nSize = (int)m_vInventory.size(); for( int i(0); iGetItemCode() == nItemCode ) return m_vInventory[i]->GetHandle(); } return 0; } //Update Item Info void SInventoryMgr::UpdateWear( struct SMSG_ITEM_WEAR* pMsg ) { for( int i=0; ItemBase::MAX_ITEM_SPARE_WEAR>i; i++ ) { m_itemCode[i] = pMsg->nItemCode[i]; } } void SInventoryMgr::UpdateWearInfo( struct SMSG_ITEM_WEAR_INFO* pMsg, bool bCreature ) { AR_HANDLE handle = 0; for( unsigned int i(0); m_vInventory.size()>i; i++ ) { if( m_vInventory[i]->GetHandle() == pMsg->item_handle ) { //변경된 아이템의 위치 갱신 m_vInventory[i]->SetPosition( pMsg->wear_position ); m_vInventory[i]->SetWearHandle(NULL); if( bCreature ) { m_vInventory[i]->SetWearHandle(pMsg->target_handle); break; } if( pMsg->wear_position != -1 ) { //기존에 있던 넘의 핸들을 얻는다. handle = m_itemHandle[pMsg->wear_position]; m_itemHandle[pMsg->wear_position] = pMsg->item_handle; } else { for( unsigned int a(0); ItemBase::MAX_ITEM_WEAR>a; a++ ) { if( m_itemHandle[a] == pMsg->item_handle ) m_itemHandle[a] = 0; } } break; } } //기존에 들어 있던것의 위치를 없앤다. if( !handle ) return; for( unsigned int i(0); m_vInventory.size()>i; i++ ) { if( m_vInventory[i]->GetHandle() == handle ) { m_vInventory[i]->SetPosition( -1 ); break; } } } //Item Use void SInventoryMgr::Rq_UseItem( int nRace, AR_HANDLE item_handle, AR_HANDLE target_handle, AR_HANDLE item_target_handle, const char* lpText/*=NULL*/ ) { if( m_vInventory.empty() ) return; for( unsigned int i(0); m_vInventory.size()>i; i++ ) { if( m_vInventory[i]->GetHandle() == item_handle ) { const ItemBaseEx_info * pItemBase = GetItemDB().GetItemData( m_vInventory[i]->GetItemCode() ); //사용 가능 한가? if( ItemBase::TYPE_USEABLE == pItemBase->nType ) { short nCoolTimeGroup = GetItemDB().GetCoolTimeGroup( m_vInventory[i]->GetItemCode() ); if( GetItemMaxCoolTime( (nCoolTimeGroup-1) ) < GetItemCurCoolTime( (nCoolTimeGroup-1) ) ) { if( nCoolTimeGroup == 1 || //레드 포션 nCoolTimeGroup == 2 || //오렌지 포션 nCoolTimeGroup == 3 || //블루 포션 nCoolTimeGroup == 4 || //신속의 포션 nCoolTimeGroup == 5 || //바람의 포션 nCoolTimeGroup == 6 ) //스펠 포션 { //포션류만 소리 재생. if( m_pGame ) m_pGame->StartSound( "ui_click_potion01.wav" ); } } /* TS_CS_USE_ITEM use_msg; //타겟에 사용 할 수 있는가? if( pItemBase->Flag.IsOn(ItemBase::FLAG_TARGET_USE) ) { //타겟을 얻음, 타겟에게 사용 use_msg.item_handle = item_handle; use_msg.target_handle = target_handle; } else { //자신한테만 사용한다. use_msg.item_handle = item_handle; use_msg.target_handle = 0; } SetUpdateItemInfo( m_vInventory[i] ); SendMsg( &use_msg );*/ if( pItemBase->CheckFlag(ItemBase::FLAG_TARGET_USE) ) { //타겟을 얻음, 타겟에게 사용 AR_UNIT nRange = pItemBase->nThrowRange * GameRule::DEFAULT_UNIT_SIZE; /* SInputUseItem inupt( target_handle, item_handle, nRange, pItemBase->fOptVar1[0] ); if( m_pGame ) m_pGame->AddGameInput( &inupt );*/ SIMSG_UI_ACT_USEITEM msg; msg.m_hItemUseTargetHandle = item_target_handle; msg.m_hTargetHandle = target_handle; msg.m_hItemHandle = item_handle; msg.m_fUseRange = nRange; msg.m_nSkillID = pItemBase->dOptVar1[0]; msg.m_bNeedTarget = true; if( lpText ) msg.m_strParameter = lpText; ProcMsgAtStatic( &msg ); } else { //자신한테만 사용한다. /* SInputUseItem inupt( 0, item_handle, 0, 0 ); if( m_pGame ) m_pGame->AddGameInput( &inupt );*/ bool bIsPosition = false; if( pItemBase->nType == ItemBase::TYPE_USEABLE && ((int)pItemBase->dOptVar1[0]) == 0 ) { bIsPosition = true; } // 2012. 8. 8 - marine 추가 성능 아이디가 1(hp), 2(mp)인 경우에는 이동을 유지하도록 수정 if( pItemBase->nType == ItemBase::TYPE_USEABLE && (((int)pItemBase->nOptType[0]) == 1 || ((int)pItemBase->nOptType[0]) == 2 ) ) { bIsPosition = true; } SIMSG_UI_ACT_USEITEM msg; msg.m_hItemUseTargetHandle = item_target_handle; msg.m_hTargetHandle = 0; msg.m_hItemHandle = item_handle; msg.m_fUseRange = 0; msg.m_nSkillID = 0; msg.m_bIsPosition = bIsPosition; if( lpText ) msg.m_strParameter = lpText; ProcMsgAtStatic( &msg ); } SetUpdateItemInfo( m_vInventory[i] ); } else { bool bUseItem(false); if( ItemBase::TYPE_USE == pItemBase->nType ) //장착시 사용인 아이템의 경우 { /* for( int i(0); ItemBase::MAX_ITEM_WEAR>i; i++ ) { if( m_itemHandle[i] == item_handle ) //장착되있다면 { bUseItem = true; break; } } if( ItemBase::GROUP_RIDING == pItemBase->nGroup || ItemBase::GROUP_CASH_ITEM == pItemBase->nGroup ) bUseItem = true;*/ // if( bUseItem ) { SIMSG_UI_ACT_USEITEM msg; //사용 msg.m_hItemUseTargetHandle = item_target_handle; msg.m_hTargetHandle = target_handle; msg.m_hItemHandle = item_handle; msg.m_fUseRange = 0; msg.m_nSkillID = pItemBase->dOptVar1[0]; msg.m_bNeedTarget = false; ProcMsgAtStatic( &msg ); return; } } if( m_vInventory[i]->GetItem() == NULL ) { assert( 0 && "Item Data Error!!!" ); continue; } //너무 빨리 장비를 장착하려고하지는 않는가? 2009.07.31 sfreer { static AR_TIME lastpuTime = 0; AR_TIME time = GetSafeTickCount(); if (time < lastpuTime + 200) //200 tick 안에 wearInfo 들어 오면 무시 { SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_PUT_ITEM_TOOFAST ) ); return; } lastpuTime = time; } //장착 레벨이 되는가? int nItemCode = m_vInventory[i]->GetItemCode(); ItemBase::ItemWearType wearType = GetItemDB().GetWearType( m_vInventory[i]->GetItemCode() ); if( wearType == ItemBase::WEAR_CANTWEAR && nItemCode != 804000 ) { //아무 것도 안 해... return; //사용 } else { int nPosition = GetItemDB().GetWearType( m_vInventory[i]->GetItemCode() ); BOOL bPut = FALSE; unsigned int a = 0; // 장착여부 검사. 장착되어 있다면 탈착. bintitle. 2010.11.15. bPut = TRUE; for( ; ItemBase::MAX_ITEM_WEAR>a; a++ ) { if( m_itemHandle[a] == item_handle ) { //탈착 bPut = FALSE; break; } } // 장착되지 않았다면 양손 여부 검사. bintitle. 2010.11.15. if( bPut ) { //장착 할수 있는 종족 인가? bool bRace = GetItemDB().IsWearablebyRace( nItemCode, nRace ); if( !bRace ) { SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_PUT_ITEM_FAIL ) ); _oprint( "Cannot equip due to wrong race... ItemCode: %d, Race: %d\n", nItemCode,nRace ); return; //사용 불가 } // From ZONE source; dual crossbows if (pItemBase->nClass == ItemBase::CLASS_ONEHAND_SWORD || pItemBase->nClass == ItemBase::CLASS_DAGGER || pItemBase->nClass == ItemBase::CLASS_ONEHAND_AXE || <<<<<<< HEAD pItemBase->nClass == ItemBase::CLASS_CROSSBOW) //Double Crossbow { CheckWeapon(pItemBase, item_handle, ItemBase::WEAR_WEAPON, ItemBase::WEAR_SHIELD, a, nPosition, bPut); } else if( pItemBase->nClass == ItemBase::CLASS_DECO_ONEHAND_SWORD || pItemBase->nClass == ItemBase::CLASS_DECO_DAGGER || pItemBase->nClass == ItemBase::CLASS_DECO_ONEHAND_AXE || pItemBase->nClass == ItemBase::CLASS_DECO_CROSSBOW) //Double Crossbow ======= pItemBase->nClass == ItemBase::CLASS_CROSSBOW) { CheckWeapon(pItemBase, item_handle, ItemBase::WEAR_WEAPON, ItemBase::WEAR_SHIELD, a, nPosition, bPut); } else if (pItemBase->nClass == ItemBase::CLASS_DECO_ONEHAND_SWORD || pItemBase->nClass == ItemBase::CLASS_DECO_DAGGER || pItemBase->nClass == ItemBase::CLASS_DECO_ONEHAND_AXE || pItemBase->nClass == ItemBase::CLASS_DECO_CROSSBOW) >>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05 { CheckWeapon(pItemBase, item_handle, ItemBase::WEAR_DECO_WEAPON, ItemBase::WEAR_DECO_SHIELD, a, nPosition, bPut); } //양손 장착 가능 무기인가 검사 //if( pItemBase->nClass == ItemBase::CLASS_ONEHAND_SWORD || // pItemBase->nClass == ItemBase::CLASS_DAGGER || // pItemBase->nClass == ItemBase::CLASS_ONEHAND_AXE || // // // AziaMafia Double Crossbow // pItemBase->nClass == ItemBase::CLASS_CROSSBOW) //{ // CheckWeapon(pItemBase, item_handle, ItemBase::WEAR_WEAPON, ItemBase::WEAR_SHIELD, a, nPosition, bPut); //} //else if( pItemBase->nClass == ItemBase::CLASS_DECO_ONEHAND_SWORD || // pItemBase->nClass == ItemBase::CLASS_DECO_DAGGER || // pItemBase->nClass == ItemBase::CLASS_DECO_ONEHAND_AXE || // // // AziaMafia Double Crossbow // pItemBase->nClass == ItemBase::CLASS_DECO_CROSSBOW) //{ // CheckWeapon(pItemBase, item_handle, ItemBase::WEAR_DECO_WEAPON, ItemBase::WEAR_DECO_SHIELD, a, nPosition, bPut); //} //else //{ // //Loop 도는 것은 나중에 고치자~ // //이미 장착 되어 있나 판별 // bPut = TRUE; // for( ; ItemBase::MAX_ITEM_WEAR>a; a++ ) // { // if( m_itemHandle[a] == item_handle ) // { // //탈착 // bPut = FALSE; // break; // } // } //} } // bintitle. 2010.11.15. // ( target_handle == 0 가능 ); if( bPut ) { { //에테리얼 내구도 체크 SInventorySlot* pSlot = m_vInventory[i]; const ItemBaseEx_info * pItem = GetItemDB().GetItemData( pSlot->GetItemCode() ); if(pItem->nEthereal_durability > 0) { if( pSlot->GetEtherealDurability() == 0) { SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_PUT_BROKEN_ITEM ) ); _oprint( "Ethereal durability is 0. ItemCode: %d\n", nItemCode); return; //사용 불가 } } } if( m_pGame ) { m_pGame->StartSound( GetMaterialSound( GetItemDB().GetMaterial( m_vInventory[i]->GetItemCode() ) ) ); m_pGame->Rq_PutOnOffItem( target_handle, item_handle, nPosition); } //장착 /* TS_CS_PUTON_ITEM msg; msg.item_handle = item_handle; msg.target_handle = target_handle; msg.position = nPosition; assert( msg.position != 255 && "Data Error~ 장착 Position 이상~" ); SendMsg( &msg );*/ return; //사용 } else//탈착 시키자 { if( m_pGame ) m_pGame->Rq_PutOnOffItem( target_handle, 0, a ); /* TS_CS_PUTOFF_ITEM msg; msg.position = a;//실제 장착위치//GetItemDB().GetWearType( m_vInventory[i]->GetItemCode() ); msg.target_handle = target_handle; SendMsg( &msg );*/ return; //사용 } } } } } } void SInventoryMgr::CheckWeapon( const ItemBaseEx_info* pItemBase, int item_handle, ItemBase::ItemWearType MainWearType, ItemBase::ItemWearType SubWearType, unsigned int& a, int& nPosition, BOOL& bPut ) { if( m_itemHandle[MainWearType] == 0) { a = MainWearType; nPosition = MainWearType; bPut = TRUE; } //Sub(Shield)슬롯이 비어있다면 이곳에 장착 하자 else if( m_itemHandle[SubWearType] == 0 ) { //Main(Weapon)슬롯 무기와 같지 않아야 한다 if( m_itemHandle[MainWearType] != item_handle ) { <<<<<<< HEAD //Main(Weapon)슬롯이 한손검이나 데거 혹은 치장무기가 장착돼있어야 한다 ItemBase::ItemClass clss = GetItemDB().GetClassID( m_itemCode[MainWearType] ); if( clss == ItemBase::CLASS_ONEHAND_SWORD || clss == ItemBase::CLASS_DAGGER || clss == ItemBase::CLASS_ONEHAND_AXE || clss == ItemBase::CLASS_DECO_ONEHAND_SWORD || clss == ItemBase::CLASS_DECO_DAGGER || clss == ItemBase::CLASS_DECO_ONEHAND_AXE || clss == ItemBase::CLASS_CROSSBOW || clss == ItemBase::CLASS_DECO_CROSSBOW) //Double Crossbow ======= // From ZONE source; dual crossbows ItemBase::ItemClass clss = GetItemDB().GetClassID(m_itemCode[MainWearType]); if (clss == ItemBase::CLASS_ONEHAND_SWORD || clss == ItemBase::CLASS_DAGGER || clss == ItemBase::CLASS_ONEHAND_AXE || clss == ItemBase::CLASS_DECO_ONEHAND_SWORD || clss == ItemBase::CLASS_DECO_DAGGER || clss == ItemBase::CLASS_DECO_ONEHAND_AXE || clss == ItemBase::CLASS_CROSSBOW || clss == ItemBase::CLASS_DECO_CROSSBOW) >>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05 { if (clss == pItemBase->nClass) nPosition = SubWearType; } //Main(Weapon)슬롯이 한손검이나 데거 혹은 치장무기가 장착돼있어야 한다 //ItemBase::ItemClass clss = GetItemDB().GetClassID( m_itemCode[MainWearType] ); //if( clss == ItemBase::CLASS_ONEHAND_SWORD || clss == ItemBase::CLASS_DAGGER || clss == ItemBase::CLASS_ONEHAND_AXE || // clss == ItemBase::CLASS_DECO_ONEHAND_SWORD || clss == ItemBase::CLASS_DECO_DAGGER // || clss == ItemBase::CLASS_DECO_ONEHAND_AXE // // AziaMafia Double Crossbow // || clss == ItemBase::CLASS_CROSSBOW // || clss == ItemBase::CLASS_DECO_CROSSBOW ) //{ // //장착될 아이템과 Main(Weapon)에 장착된 아이템이 같은 클래스여야 한다 // if( clss == pItemBase->nClass ) // nPosition = SubWearType; //} bPut = TRUE; } else a = MainWearType; } else //양손모두 장착돼 있다면 { //Main(Weapon)슬롯과 같다면 탈착 시킨다 if( m_itemHandle[MainWearType] == item_handle ) a = MainWearType; //Sub(Shield)슬롯과 같다면 탈착 시킨다 else if( m_itemHandle[SubWearType] == item_handle ) a = SubWearType; else//새로운 아이템 이면 { nPosition = MainWearType; bPut = TRUE; } } } void SInventoryMgr::AddEquipCard( AR_HANDLE target_handle, AR_HANDLE hItem ) { for( unsigned int i(0); m_vEquipCareList.size()>i; i++ ) { if( m_vEquipCareList[i].item_handle == hItem ) return; } EQUIP_CARD equip_card; equip_card.item_handle = hItem; equip_card.target_handle = target_handle; m_vEquipCareList.push_back( equip_card ); } void SInventoryMgr::DelEquipCard( AR_HANDLE target_handle, AR_HANDLE hItem ) { for( unsigned int i(0); m_vEquipCareList.size()>i; i++ ) { if( m_vEquipCareList[i].item_handle == hItem ) { m_vEquipCareList.erase( m_vEquipCareList.begin()+i ); return; } } } bool SInventoryMgr::IsEquipCard( AR_HANDLE hItem ) const /// 2010.12.29 const 추가 { for( unsigned int i(0); m_vEquipCareList.size()>i; i++ ) { if( m_vEquipCareList[i].item_handle == hItem ) { return true; } } return false; } void SInventoryMgr::SetBeltSlotCard( struct SMSG_BELT_SLOT_INFO* pMsg ) { for( int i(0); c_BeltSlotCnt>i; i++ ) handle_BeltSlot[i] = pMsg->handle[i]; } bool SInventoryMgr::IsBeltSlotCard( AR_HANDLE hItem ) const /// 2010.12.29 const 추가 - prodongi { for( int i(0); c_BeltSlotCnt>i; i++ ) { if( handle_BeltSlot[i] == hItem ) return true; } return false; } // 아이템의 장착여부 반환. bool SInventoryMgr::IsEquip( AR_HANDLE handle ) { for( int i=0; ii; i++ ) { if( handle_BeltSlot[i] == hItem ) return i; } return -1; } int SInventoryMgr::GetEmptyBeltSlotIndex() { for( int i(0); c_BeltSlotCnt>i; i++ ) { if( handle_BeltSlot[i] == 0 ) return i; } return -1; } AR_HANDLE SInventoryMgr::GetBeltSlot( int nIndex ) { if( nIndex >= 0 && nIndex < c_BeltSlotCnt ) return handle_BeltSlot[nIndex]; return 0; } // 2010.08.17 - prodongi //void SInventoryMgr::Rq_BeltCardPut( bool bPutOn, AR_HANDLE hItem ) void SInventoryMgr::Rq_BeltCardPut( bool bPutOn, AR_HANDLE hItem, int putSlot ) { if( bPutOn ) { TS_CS_PUTON_CARD msg; // 2010.08.17 - prodongi //msg.position = GetEmptyBeltSlotIndex(); msg.position = putSlot; msg.item_handle = hItem; SendMsg( &msg ); } else { // 탈착 TS_CS_PUTOFF_CARD msg; msg.position = GetBeltSlotIndex( hItem ); SendMsg( &msg ); } } // creture item void SInventoryMgr::Rq_CreatureUseItem( AR_HANDLE item_handle, AR_HANDLE target_handle ) { if( m_vInventory.empty() ) return; for( unsigned int i(0); m_vInventory.size()>i; i++ ) { if( m_vInventory[i]->GetHandle() == item_handle ) { SInventorySlot* pItem = m_vInventory[i]; if( pItem->GetPosition() == ItemBase::WEAR_NONE ) { //장착 TS_CS_PUTON_ITEM msg; msg.item_handle = item_handle; msg.target_handle = target_handle; //msg.position = ItemBase::MAX_ITEM_WEAR; // 서버에서의 max 값을 날린다.. 크리처는 특정 장착 위치가 없다 // 서버에서의 max 값을 날린다.. 크리처는 특정 장착 위치가 없다. // 2010.10.05. bintitle. 아바타에 SWAP 장비가 추가되어 MAX가 28 개로 늘었다. 하지만 크리쳐는 서버에서 MAX 24 만 인정하므로 24로 변경. msg.position = ItemBase::MAX_ITEM_SPARE_WEAR; assert( msg.position != 255 && "Data Error~ 장착 Position 이상~" ); SendMsg( &msg ); return; //사용 } else { // 탈착 TS_CS_PUTOFF_ITEM msg; msg.position = pItem->GetPosition()%1000; msg.target_handle = target_handle; SendMsg( &msg ); return; //사용 } } } } void SInventoryMgr::SetItemCoolTime( int nIndex, DWORD dwCoolTime ) { if( nIndex >= 0 && nIndex < TS_SC_ITEM_COOL_TIME::MAX_ITEM_COOLTIME_GROUP ) { if( m_dwRemain_time[nIndex] == 0 ) { m_dwRemain_time[nIndex] = dwCoolTime; m_dwCool_time[nIndex] = dwCoolTime; m_dwCur_time[nIndex] = m_dwTime; } } } int SInventoryMgr::GetItemCurCoolTime( int nIndex ) { if( nIndex >= 0 && nIndex < TS_SC_ITEM_COOL_TIME::MAX_ITEM_COOLTIME_GROUP ) return m_dwTime - m_dwCur_time[nIndex]; return 0; } int SInventoryMgr::GetItemMaxCoolTime( int nIndex ) { if( nIndex >= 0 && nIndex < TS_SC_ITEM_COOL_TIME::MAX_ITEM_COOLTIME_GROUP ) return m_dwCool_time[nIndex]; return 0; } void SInventoryMgr::Process( DWORD time ) { m_dwTime = time; //아이템 그룹 쿨 타임 처리 for( int i(0); TS_SC_ITEM_COOL_TIME::MAX_ITEM_COOLTIME_GROUP>i; i++ ) { if( (m_dwRemain_time[i] > 0) && (m_dwTime - m_dwCur_time[i]) >= (DWORD)m_dwRemain_time[i] ) { m_dwRemain_time[i] = 0; } } //대여 시간 처리 if( m_dwCheckLendingTime == 0 ) { m_dwCheckLendingTime = m_dwTime; } else { if( (m_dwTime - m_dwCheckLendingTime) >= CHECK_LENDING_TIME ) { //대여 아이템 갱신 m_dwCheckLendingTime = m_dwTime; ++m_nCheckCount; for( unsigned int i(0); m_vLendingItem.size()>i; i++ ) { SInventorySlot * pInvenSlot = m_vLendingItem[i]; if( pInvenSlot->GetItem()->remain_time > 0 ) --pInvenSlot->GetItem()->remain_time; } for ( unsigned int i(0); m_vInventory.size()>i; i++ ) { if (( m_vInventory[i]->GetItem()->elemental_effect_type != 0 ) && ( m_vInventory[i]->GetItem()->elemental_effect_remain_time > 0 )) --m_vInventory[i]->GetItem()->elemental_effect_remain_time; } if( m_nCheckCount >= 60 ) { m_nCheckCount = 0; ProcMsgAtStatic( &(SIMSG_UI_STATE_UPDATE(SIMSG_TOGGLE_UIWINDOW::UIWINDOW_INVENTORY)) ); } } } } int SInventoryMgr::GetLendingItemTime( AR_HANDLE item_handle ) { for( unsigned int i(0); m_vLendingItem.size()>i; i++ ) { SInventorySlot * pInvenSlot = m_vLendingItem[i]; if( pInvenSlot->GetHandle() == item_handle ) { return pInvenSlot->GetItem()->remain_time; } } return 0; } void SInventoryMgr::_addLendingItem( SInventorySlot* pItemSlot ) { if( pItemSlot->GetItem()->remain_time > 0 ) { m_vLendingItem.push_back( pItemSlot ); } } void SInventoryMgr::ClearCashItem() { m_vCashItemList.clear(); } void SInventoryMgr::UpdateCashItem( TS_SC_COMMERCIAL_STORAGE_LIST::CommercialItemInfo* pCashItemInfo ) { for( unsigned int i(0); m_vCashItemList.size()>i; i++ ) { TS_SC_COMMERCIAL_STORAGE_LIST::CommercialItemInfo* pItemInfo = &m_vCashItemList[i]; if( pItemInfo->commercial_item_uid == pCashItemInfo->commercial_item_uid ) { //기존것 갱신 pItemInfo->count = pCashItemInfo->count; return; } } //새로 추가 TS_SC_COMMERCIAL_STORAGE_LIST::CommercialItemInfo newItem; newItem.commercial_item_uid = pCashItemInfo->commercial_item_uid; newItem.code = pCashItemInfo->code; newItem.count = pCashItemInfo->count; m_vCashItemList.push_back( newItem ); } //내구도 관련 메시지 체크 하여 출력하는 함수 void SInventoryMgr::CheckDurabilityMsg(SInventorySlot* pSlot) { /*if( pSlot->m_nLastDurabilityValue < pSlot->GetEtherealDurability()) pSlot->m_nLastDurabilityCheckPercent = 0;*/ const ItemBaseEx_info * pItem = GetItemDB().GetItemData( pSlot->GetItemCode() ); int CheckPercent = 0; if(pItem && pSlot->m_nLastDurabilityValue > pSlot->GetEtherealDurability()) { if(pSlot->getMaxEtherealDurability() > 0 && pItem->nClass != 451) { if( pSlot->GetEtherealDurability() == 0) { if(pSlot->m_nLastDurabilityCheckPercent == 0 || pSlot->m_nLastDurabilityCheckPercent != 1 ) CheckPercent = 1; } else if( pSlot->GetEtherealDurability() <= pSlot->getMaxEtherealDurability()*0.2 ) { if(pSlot->m_nLastDurabilityCheckPercent == 0 || pSlot->m_nLastDurabilityCheckPercent != 20 ) CheckPercent = 20; } else if( pSlot->GetEtherealDurability() <= pSlot->getMaxEtherealDurability()*0.4 ) { if(pSlot->m_nLastDurabilityCheckPercent == 0 || pSlot->m_nLastDurabilityCheckPercent != 40) CheckPercent = 40; } else if( pSlot->GetEtherealDurability() <= pSlot->getMaxEtherealDurability()*0.6 ) { if(pSlot->m_nLastDurabilityCheckPercent == 0 || pSlot->m_nLastDurabilityCheckPercent != 60) CheckPercent = 60; } else if( pSlot->GetEtherealDurability() <= pSlot->getMaxEtherealDurability()*0.8 ) { if(pSlot->m_nLastDurabilityCheckPercent == 0 || pSlot->m_nLastDurabilityCheckPercent != 80) CheckPercent = 80; } if(CheckPercent > 0) { pSlot->m_nLastDurabilityCheckPercent = CheckPercent; std::string basemsg; if(CheckPercent==1) basemsg = S(7907); else if(CheckPercent==20) basemsg = S(7906); else basemsg = S(7905); XStringUtil::Replace( basemsg, "#@item_name@#", GetStringDB().GetString( pItem->nNameId ) ); //CStringUtil::StringFormat( "%s(%d%%)", basemsg.c_str(), basemsg ); m_pGame->AddChatMessage( basemsg.c_str() ); } } } pSlot->m_nLastDurabilityValue = pSlot->GetEtherealDurability(); } //Item 추가 int SInventoryMgr::AddItem( TS_ITEM_INFO * pItemInfo ) { if( pItemInfo == NULL ) return 1; //기존것 갱신 for( unsigned int i(0); m_vInventory.size()>i; i++ ) { if( m_vInventory[i]->GetHandle() == pItemInfo->handle ) { /// 2010.12.08 아이템의 영혼력이 바꼈을 때, 오토 메세지 수정 - prodongi if( m_vInventory[i]->GetEndurance() != 0 && pItemInfo->endurance == 0 ) SendGameInterfaceMsg( &SIMSG_UI_EMPTY_SOULPWER_MSG(pItemInfo->handle, true) ); else SendGameInterfaceMsg( &SIMSG_UI_EMPTY_SOULPWER_MSG(pItemInfo->handle, false) ); m_vInventory[i]->SetUpdateCount( count_t( pItemInfo->count ) ); m_vInventory[i]->SetItem( pItemInfo ); CheckDurabilityMsg( m_vInventory[i] ); return (int)m_vInventory.size(); } } //새것 추가 SInventorySlot * pInvenSlot = new SInventorySlot; pInvenSlot->SetUpdateCount( count_t( pItemInfo->count ) ); pInvenSlot->SetItem( pItemInfo ); //순서 있음 m_vInventory.push_back( pInvenSlot ); CheckDurabilityMsg( pInvenSlot ); //대여 시간이 있는 것들만 추가됨. _addLendingItem( pInvenSlot ); if( pInvenSlot->IsEquipItem() && !pInvenSlot->IsStorageItem() && !pInvenSlot->IsSummonEquip() ) { if( pItemInfo->wear_position < ItemBase::MAX_ITEM_WEAR && pItemInfo->wear_position > -1 ) { m_itemCode[pItemInfo->wear_position] = pItemInfo->Code; m_itemHandle[pItemInfo->wear_position] = pItemInfo->handle; } } SetUpdateItemInfo( pInvenSlot ); /// 2010.12.08 영혼력이 0 이면 오토 메세지 출력 - prodongi if (0 == pItemInfo->endurance) { unsigned int nEndurancePer; int nResult = pInvenSlot->GetCrrEndurancePer(nEndurancePer); if( nResult == SInventorySlot::ENDURANCE_SUCCESS ) { if (0 == nEndurancePer && IsEndurance(nEndurancePer)) { SendGameInterfaceMsg( &SIMSG_UI_EMPTY_SOULPWER_MSG(pItemInfo->handle, true) ); } } } return (int)m_vInventory.size(); } //Item 삭제 int SInventoryMgr::DropItem( AR_HANDLE item_handle ) { if( m_vInventory.empty() ) return 0; /*for( unsigned int i(0); m_vInventory.size()>i; i++ ) { if( m_vInventory[i]->GetHandle() == item_handle ) { delete m_vInventory[i]; m_vInventory.erase( m_vInventory.begin()+i ); return 1; } }*/ std::vector::iterator it = m_vInventory.begin(); while( it != m_vInventory.end() ) { SInventorySlot* pSlot = (*it); if( pSlot && pSlot->GetHandle() == item_handle ) { SetUpdateItemInfo( pSlot ); _delLendingItem( pSlot ); delete pSlot; _onEraseItem( m_vInventory.erase(it) ); return 1; } it++; } SetUpdateItemInfo( NULL ); return 0; } void SInventoryMgr::_delLendingItem( SInventorySlot* pItemSlot ) { std::vector::iterator it = m_vLendingItem.begin(); while( it != m_vLendingItem.end() ) { SInventorySlot* pSlot = (*it); if( pSlot && pSlot->GetHandle() == pItemSlot->GetHandle() ) { m_vLendingItem.erase(it); return; } ++it; } } //Item 제거. int SInventoryMgr::DestroyItem( AR_HANDLE item_handle ) { // 아이템 파괴상태 일 경우 함수종료. if( m_vInventory.empty() || m_rqItemState == RQ_ITEM_STATE::RQ_ITEM_STATE_ERASE ) return 0; // 상태 초기화. if( m_rqItemState == RQ_ITEM_STATE::RQ_ITEM_STATE_DROP ) m_rqItemState = RQ_ITEM_STATE::RQ_ITEM_STATE_NONE; /*for( unsigned int i(0); m_vInventory.size()>i; i++ ) { if( m_vInventory[i]->GetHandle() == item_handle ) { delete m_vInventory[i]; m_vInventory.erase( m_vInventory.begin()+i ); return 1; } }*/ std::vector::iterator it = m_vInventory.begin(); while( it != m_vInventory.end() ) { SInventorySlot* pSlot = (*it); if( pSlot && pSlot->GetHandle() == item_handle ) { /// 2010.12.08 영혼력 충전 오토메세지 삭제 - prodongi if (0 == pSlot->GetEndurance()) { SendGameInterfaceMsg( &SIMSG_UI_EMPTY_SOULPWER_MSG(item_handle, false) ); } //모두 다 버린다. 버릴 갯수 설정 pSlot->SetUpdateCount( pSlot->GetItemCount(), true ); SetUpdateItemInfo( pSlot ); _delLendingItem( pSlot ); delete pSlot; _onEraseItem( m_vInventory.erase(it) ); return 1; } it++; } SetUpdateItemInfo( NULL ); return 0; } void SInventoryMgr::_onEraseItem( std::vector::iterator it ) { for( ; it != m_vInventory.end() ; ++it ) { ((*it)->GetItem())->index--; } } // 아이템파괴. int SInventoryMgr::EraseItem( AR_HANDLE handle, __int64 count ) { // 상태 초기화. if( m_rqItemState == RQ_ITEM_STATE::RQ_ITEM_STATE_ERASE ) m_rqItemState = RQ_ITEM_STATE::RQ_ITEM_STATE_NONE; // 0 이면 파괴 실패. if( handle == 0 ) return 0; SInventorySlot * pSlot; int size = m_vInventory.size(); for( std::vector::iterator it=m_vInventory.begin(); it!=m_vInventory.end(); ++it ) { pSlot = (*it); if( pSlot && pSlot->GetHandle() == handle ) // GetItemCode() == itemCode ) { SendDestroyMsg(count, pSlot->GetItemCode() ); return 1; } } //SetUpdateItemInfo( NULL ); //// 0 이면 파괴 실패. //if( itemCode == 0 ) // return 0; //SInventorySlot * pSlot; //int size = m_vInventory.size(); //for( std::vector::iterator it=m_vInventory.begin(); it!=m_vInventory.end(); ++it ) //{ // pSlot = (*it); // if( pSlot && pSlot->GetItemCode() == itemCode ) // { // if( pSlot->GetItemCount().getAmount() == 0 ) // 0개이하면 제거. // { // _delLendingItem( pSlot ); // delete pSlot; // m_vInventory.erase( it ); // return 1; // } // } //} return 0; } void SInventoryMgr::SendDestroyMsg(int count, int itemCode) { // 시스템메세지 출력. SMSG_CHATTING msg; msg.nChatType = CHAT_SYSTEM; msg.szSender = ""; char strCount[10]={0,}; ::itoa( count, strCount, 10 ); msg.strText = SStringDB::ParseString( 730, "#@item_name@#", GetStringDB( ).GetString( GetItemDB().GetTextID( itemCode ) ), "#@item_num@#", strCount ); //msg.strText = CStringUtil::StringFormat( "[%s - %d개] 파괴 되었습니다.", GetStringDB( ).GetString( GetItemDB().GetTextID( pSlot->GetItemCode() ) ), count ); this->m_pGame->ProcMsgAtStatic( &msg ); } int SInventoryMgr::UpdateItemCount( AR_HANDLE item_handle, count_t nItemCount, bool fromDestory /* = false */ ) { if( m_vInventory.empty() ) return 0; SInventorySlot * pSlot; for( unsigned int i(0); m_vInventory.size()>i; i++ ) { pSlot = m_vInventory[i]; if( pSlot->GetHandle() == item_handle ) { count_t beforeCount = pSlot->GetItemCount(); pSlot->SetUpdateCount( nItemCount ); pSlot->SetItemCount( nItemCount ); SetUpdateItemInfo( pSlot ); // 0개면 제거. if( pSlot->GetItemCount().getAmount() < 1 ) { std::vector::iterator it = find( m_vInventory.begin(), m_vInventory.end(), pSlot ); if( it != m_vInventory.end() ) { // 2012. 7. 20 - marine 완전히 파괴된 경우이므로 이전에 업데이트 하기 전의 count를 쓴다. // EraseItem()에서도 메세지를 넣지만 여기서 삭제되면 핸들이 사라지기때문에 삭제되기전에 메시지를 날린다. if(fromDestory) SendDestroyMsg( beforeCount.getAmount(), pSlot->GetItemCode() ); _delLendingItem( pSlot ); delete pSlot; _onEraseItem( m_vInventory.erase(it) ); return 1; } } return 1; } } SetUpdateItemInfo( NULL ); return 0; } SInventorySlot* SInventoryMgr::GetItemInfo( AR_HANDLE hItem ) { if( hItem == NULL ) return NULL; if( m_vInventory.empty() ) return NULL; for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetHandle() == hItem ) return m_vInventory[i]; } return NULL; } SInventorySlot* SInventoryMgr::GetItemInfo( int nWearPos ) { if( nWearPos == -1 ) return NULL; if( m_vInventory.empty() ) return NULL; for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->IsPlayerEquipItem(nWearPos) ) return m_vInventory[i]; } return NULL; } SInventorySlot* SInventoryMgr::GetItemInfo( ItemInstance::ItemUID itemUID ) { if( m_vInventory.empty() ) return NULL; for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetUID() == itemUID ) return m_vInventory[i]; } return NULL; } void SInventoryMgr::GetItemInfo( std::vector& rItemList, ItemBase::ItemCode code, int level, int enhance ) { if( m_vInventory.empty() ) return; for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { bool bPush(true); if( m_vInventory[i]->GetItemCode() == code ) { if( level && m_vInventory[i]->GetLevel() != level ) bPush = false; if( enhance && m_vInventory[i]->GetEnhance() != enhance ) bPush = false; if( bPush ) rItemList.push_back(m_vInventory[i]); } } } SInventorySlot* SInventoryMgr::GetCodeItemInfo( ItemBase::ItemCode code ) { if( m_vInventory.empty() ) return NULL; for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetItemCode() == code ) { return m_vInventory[i]; } } return NULL; } SInventorySlot* SInventoryMgr::GetComparableEquipItemInfo( SInventorySlot* pItem, bool second_equip ) { if( pItem->IsEquipItem() == false ) { return GetComparableEquipItemInfo( pItem->GetItemCode(), second_equip ); } return NULL; } SInventorySlot* SInventoryMgr::GetComparableEquipItemInfo( ItemBase::ItemCode code, bool second_equip ) { SInventorySlot* pEquipItem = NULL; int wear_pos = GetItemDB().GetWearType( code ); if( wear_pos >= 0 ) { // 벨트 슬롯은 비교하지 않는다.(너무 많다.) if( wear_pos == ItemBase::ItemWearType::WEAR_BELT_SLOT ) { return NULL; } // 반지 혹은 무기 if( wear_pos == ItemBase::ItemWearType::WEAR_RING || wear_pos == ItemBase::ItemWearType::WEAR_WEAPON || wear_pos == ItemBase::ItemWearType::WEAR_TWOHAND ) { if( second_equip ) { if( wear_pos == ItemBase::ItemWearType::WEAR_RING ) { // 두번째 반지 wear_pos = ItemBase::ItemWearType::WEAR_RING + 1; } else { // 이도류의 경우만. 방패는 제외한다. wear_pos = ItemBase::ItemWearType::WEAR_SHIELD; pEquipItem = GetItemInfo( wear_pos ); if( pEquipItem != NULL ) { if( GetItemDB().GetWearType( pEquipItem->GetItemCode() ) == ItemBase::ItemWearType::WEAR_WEAPON ) { return pEquipItem; } } return NULL; } } } else { // 반지가 아닌데 두번째 장비를 요구하면 리턴 if( second_equip ) { return NULL; } } pEquipItem = GetItemInfo( wear_pos ); if( pEquipItem == NULL ) { // 무기라면(투핸드 원핸드 비교) if( wear_pos == ItemBase::ItemWearType::WEAR_WEAPON ) { pEquipItem = GetItemInfo( ItemBase::ItemWearType::WEAR_TWOHAND ); } else if( wear_pos == ItemBase::ItemWearType::WEAR_TWOHAND ) { pEquipItem = GetItemInfo( ItemBase::ItemWearType::WEAR_WEAPON ); } } } return pEquipItem; } SInventorySlot* SInventoryMgr::GetItemInfoCreatureUID( int nUID ) { if( m_vInventory.empty() ) return NULL; for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetItem()->socket[0] == nUID ) return m_vInventory[i]; } return NULL; } bool SInventoryMgr::GetInvenDataList2( int nCategory, std::vector< SInventorySlot*>& vecInvenList ) { //gmpbigsun( 20130904 ) : nCategory에 따라 Type Value를 재설정하고 아이템DB값의 bitset포함여부로 판단한다. vecInvenList.clear(); int nNewValue = 0; switch( nCategory ) { case UI_ITEM_ALL: nNewValue = UI_ITEM_NEW_ALL; break; case UI_ITEM_EQUIP: nNewValue = UI_ITEM_NEW_1; break; case UI_ITEM_USE: nNewValue = UI_ITEM_NEW_2; break; case UI_ITEM_CARD: nNewValue = UI_ITEM_NEW_3; break; case UI_ITEM_CREATURE: nNewValue = UI_ITEM_NEW_4; break; case UI_ITEM_EXPEND: nNewValue = UI_ITEM_NEW_5; break; case UI_ITEM_ETC: nNewValue = UI_ITEM_NEW_6; break; case UI_ITEM_QUEST: nNewValue = UI_ITEM_NEW_7; break; case UI_ITEM_CRU: nNewValue = UI_ITEM_NEW_8; break; case UI_ITEM_COLLECTION: nNewValue = UI_ITEM_NEW_9; break; case UI_ITEM_CARD2: nNewValue = UI_ITEM_NEW_10; break; default: nNewValue = 0; break; } //TODO: //nNewVlaue 와 DB의 bitset &(and)결과에 의해 결과 리스트를 뽑음. int nMaxSize = static_cast(m_vInventory.size()); for( int i = 0; i < nMaxSize; ++i ) { SInventorySlot* pSlot = m_vInventory[i]; if( !pSlot ) continue; //oops //창고아이템 pass if( pSlot->IsStorageItem() ) continue; const ItemBaseEx_info* pItem = GetItemDB().GetItemData( pSlot->GetItemCode() ); if( !pItem ) continue; //oops if( nNewValue == UI_ITEM_ALL ) { //AziaMafia All item inventaire /* if ( !( pItem->nCategory_Bitset & UI_ITEM_NEW_3 ) && !( pItem->nCategory_Bitset & UI_ITEM_NEW_4 ) ) { vecInvenList.push_back( pSlot ); } */ //add item into all if ((!(pItem->nCategory_Bitset & UI_ITEM_NEW_7) && !(pItem->nCategory_Bitset & UI_ITEM_NEW_4) && !(pItem->nCategory_Bitset & UI_ITEM_NEW_3)) || pSlot->GetItemCode() == 800001 //800001 Unit Card ) { vecInvenList.push_back(pSlot); } } //Category Creature else if (UI_ITEM_NEW_4 == nNewValue && (pSlot->GetXFlag().IsOn(ItemInstance::ITEM_FLAG_CARD) || pSlot->GetItemCode() == 800000 // Chalk of Restoration || pSlot->GetItemCode() == 710001 // Soul Catalyst || pSlot->GetItemCode() == 710004)) // Advanced Soul Catalyst vecInvenList.push_back(pSlot); // else if( UI_ITEM_NEW_7 == nNewValue && pItem->CheckFlag( ItemBase::ITEM_FLAG::FLAG_QUEST ) ) // vecInvenList.push_back( pSlot ); // else if( UI_ITEM_NEW_8 == nNewValue && pItem->CheckFlag( ItemBase::ITEM_FLAG::FLAG_CASHITEM ) ) // vecInvenList.push_back( pSlot ); else if (UI_ITEM_NEW_10 == nNewValue ) { SGameAvatarEx* pOwner = g_pCurrentGameSystem->GetLocalPlayer(); if (pOwner && (ItemBase::GROUP_SKILLCARD == pItem->nGroup || pSlot->GetItemCode() == 700401 // Cube de Compétence || pSlot->GetItemCode() == 700402 // Ancien Cube de Compétence )) if (isWearableSkillCardItem(pItem, g_pCurrentGameSystem->GetSkillSlotMgr() ) == true ) vecInvenList.push_back(pSlot); } else { if( pItem->nCategory_Bitset & nNewValue ) vecInvenList.push_back( pSlot ); } } return true; } /// 2010.11.24 - prodongi void SInventoryMgr::GetInvenDataList( int nCategory, std::vector& vecInvenList, SCreatureSlotMgr const& creatureSlotMgr, bool bExceptEquipItem, bool bExceptDontBuyItem ) //void SInventoryMgr::GetInvenDataList( int nCategory, std::vector& vecInvenList, bool bExceptEquipItem, bool bExceptDontBuyItem ) { vecInvenList.clear(); int nUseType = (-1); switch( nCategory ) { case UI_ITEM_ALL: nUseType = (-1); break; case UI_ITEM_EQUIP: nUseType = ItemBase::TYPE_ARMOR; break; case UI_ITEM_CARD: nUseType = ItemBase::TYPE_CARD; break; case UI_ITEM_EXPEND: nUseType = ItemBase::TYPE_USEABLE; break; case UI_ITEM_ETC: nUseType = ItemBase::TYPE_ETC; break; case UI_ITEM_USE: nUseType = ItemBase::TYPE_USE; break; case UI_ITEM_QUEST: nUseType = 9999; break; //퀘스트는 플래그 case UI_ITEM_CREATURE: nUseType = ItemBase::TYPE_CREATURE; break; //servantes 2010.11.24 크리처 버튼 안 눌러지는 버그 수정 case UI_ITEM_CRU: nUseType = -2; break; default: break; } if(nUseType == ItemBase::TYPE_CREATURE) //크리처 //servantes 2010.11.24 크리처 버튼 안 눌러지는 버그 수정 { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { SInventorySlot* pSlot = m_vInventory[i]; int nGruop = GetItemDB().GetGroup(pSlot->GetItemCode()); //그룹 bool bCARD = pSlot->GetXFlag().IsOn( ItemInstance::ITEM_FLAG_CARD ); //크리처 장비 카드 여부 if( nGruop == ItemBase::GROUP_SUMMONCARD || //크리처 카드 bCARD ) //크리처 장비 카드 { /// 2010.12.29 - prodongi //vecInvenList.push_back( pSlot ); const ItemBaseEx_info * item = GetItemDB().GetItemData( pSlot->GetItemCode() ); if (enableSellItem(bExceptEquipItem, bExceptDontBuyItem, pSlot, creatureSlotMgr, item)) { vecInvenList.push_back( pSlot ); } } } } else if(nUseType == ItemBase::TYPE_CARD) //카드 //servantes 2010.11.24 { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { SInventorySlot* pSlot = m_vInventory[i]; int nGruop = GetItemDB().GetGroup(pSlot->GetItemCode()); //그룹 if( nGruop == ItemBase::GROUP_SKILLCARD || //스킬 카드 nGruop == ItemBase::GROUP_ITEMCARD || //아이템 카드 nGruop == ItemBase::GROUP_SPELLCARD || //스펠 카드 nGruop == ItemBase::GROUP_SUMMONCARD ) //크리처 카드 { /// 2010.12.29 - prodongi //vecInvenList.push_back( pSlot ); const ItemBaseEx_info * item = GetItemDB().GetItemData( pSlot->GetItemCode() ); if (enableSellItem(bExceptEquipItem, bExceptDontBuyItem, pSlot, creatureSlotMgr, item)) { vecInvenList.push_back( pSlot ); } } } } else if( nUseType != 9999 ) { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->IsStorageItem() ) continue; const ItemBaseEx_info * pItem = GetItemDB().GetItemData( m_vInventory[i]->GetItemCode() ); bool bInsert = false; if( pItem->nType == nUseType ) { bInsert = true; if( nUseType == ItemBase::TYPE_ARMOR ) { //장비 얻을때, 카드화 아이템 제외 if( m_vInventory[i]->GetXFlag().IsOn( ItemInstance::ITEM_FLAG_CARD ) ) bInsert = false; } } else { if( nUseType == ItemBase::TYPE_CARD ) { //카드 얻을때, 카드화 아이템 포함 if( m_vInventory[i]->GetXFlag().IsOn( ItemInstance::ITEM_FLAG_CARD ) ) bInsert = true; } else { // 실제적인 기타 ( 각 탭에 매칭되는 타입 이외의 아이템들 ) if( nUseType == -2 ) { if( pItem->nType != ItemBase::TYPE_ARMOR && pItem->nType != ItemBase::TYPE_USEABLE && pItem->nType != ItemBase::TYPE_ETC && pItem->nType != ItemBase::TYPE_CREATURE && pItem->nType != ItemBase::TYPE_CARD ) bInsert = true; } } } // if usetype == -1 : 모든 리스트, else : 특정 탭에 해당하는 아이템만, 퀘스트 아이템 제외, 상점 매각 불가 제외 //if (nUseType == -1 || bInsert && !pItem->CheckFlag(ItemBase::ITEM_FLAG::FLAG_QUEST)) if( nUseType == -1 || bInsert && !pItem->CheckFlag( ItemBase::ITEM_FLAG::FLAG_QUEST ) ) { /// 2010.12.29 - prodongi /* // if except equipitem : 비장착된 아이템만 장착된 카드도 제외, else : 창고 아이템만 제외 if( (bExceptEquipItem && (!m_vInventory[i]->IsEquipItem() && !IsEquipCard(m_vInventory[i]->GetHandle())) ) || (!bExceptEquipItem && !m_vInventory[i]->IsStorageItem() ) ) { if( bExceptDontBuyItem ) { //상점, 매각 불가 아이템은 스킵 if( pItem->CheckFlag( ItemBase::ITEM_FLAG::FLAG_CANT_SELL ) ) continue; } /// 2010.11.15 - prodongi if (bExceptEquipItem) { if (IsBeltSlotCard(m_vInventory[i]->GetHandle())) continue; /// 2010.11.24 편성된 크리처 카드 인지 검사 - prodongi if (creatureSlotMgr.IsExistCreatureCard(m_vInventory[i]->GetHandle())) continue; } vecInvenList.push_back( m_vInventory[i] ); } */ if (enableSellItem(bExceptEquipItem, bExceptDontBuyItem, m_vInventory[i], creatureSlotMgr, pItem)) { vecInvenList.push_back( m_vInventory[i] ); } } } } else { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->IsStorageItem() ) continue; const ItemBaseEx_info * pItem = GetItemDB().GetItemData( m_vInventory[i]->GetItemCode() ); if( pItem->CheckFlag( ItemBase::ITEM_FLAG::FLAG_QUEST ) ) { if( (bExceptEquipItem && !m_vInventory[i]->IsEquipItem()) || (!bExceptEquipItem && !m_vInventory[i]->IsStorageItem() ) ) vecInvenList.push_back(m_vInventory[i]); } } } } ////////////////////////////////////////////////////////////////////////// // shop list void SInventoryMgr::AddShopItem( SMSG_MARKET* pMsg ) { SAFE_DELETE_VECTOR( m_vecShopList ); SMSG_MARKET::ItemInfo* pItemInfo = pMsg->pItemInfo; for( int i = 0; i < pMsg->item_count; i++ ) { SShopSlot* pSlot = new SShopSlot; pSlot->SetNpcHandle( pMsg->npc_handle ); pSlot->SetItemCode( pItemInfo->code ); pSlot->SetPrice( money_t( pItemInfo->price ) ); pSlot->SetHuntaHolicPoint( money_t( pItemInfo->huntaholic_point ) ); // #2.1.2.11.1 pSlot->SetArenaPoint(money_t(pItemInfo->arena_point)); pSlot->SetRank( GetItemDB().GetItemRank( pItemInfo->code ) ); m_vecShopList.push_back(pSlot); pItemInfo++; } } void SInventoryMgr::GetShopDataList( int nCategory, std::vector& vecShopList ) { vecShopList.clear(); int nUseType = (-1); switch( nCategory ) { case UI_ITEM_ALL: nUseType = (-1); break; case UI_ITEM_EQUIP: nUseType = ItemBase::TYPE_ARMOR; break; case UI_ITEM_CARD: nUseType = ItemBase::TYPE_CARD; break; case UI_ITEM_EXPEND: nUseType = ItemBase::TYPE_USEABLE; break; case UI_ITEM_ETC: nUseType = ItemBase::TYPE_ETC; break; case UI_ITEM_USE: nUseType = ItemBase::TYPE_USE; break; case UI_ITEM_QUEST: nUseType = 9999; break; //퀘스트는 플래그로 처리 case UI_ITEM_CRU: nUseType = -2; break; } if( nUseType != 9999 ) { std::vector::iterator it = m_vecShopList.begin(); while( it != m_vecShopList.end() ) { SShopSlot* pSlot = (*it); const ItemBaseEx_info * pItem = GetItemDB().GetItemData( pSlot->GetItemCode() ); if( nUseType == -1 || GetItemDB().GetUseType(pSlot->GetItemCode()) == nUseType && !pItem->CheckFlag( ItemBase::ITEM_FLAG::FLAG_QUEST ) ) vecShopList.push_back(pSlot); else { if( nUseType == -2 && GetItemDB().GetUseType( pSlot->GetItemCode() ) != nUseType && !pItem->CheckFlag( ItemBase::ITEM_FLAG::FLAG_QUEST ) ) vecShopList.push_back( pSlot ); } it++; } } else { std::vector::iterator it = m_vecShopList.begin(); while( it != m_vecShopList.end() ) { SShopSlot* pSlot = (*it); const ItemBaseEx_info * pItem = GetItemDB().GetItemData( pSlot->GetItemCode() ); if( pItem->CheckFlag( ItemBase::ITEM_FLAG::FLAG_QUEST ) ) vecShopList.push_back(pSlot); it++; } } } SShopSlot* SInventoryMgr::GetShopItem( int nItemCode ) { std::vector::iterator it = m_vecShopList.begin(); while( it != m_vecShopList.end() ) { SShopSlot* pSlot = (*it); if( pSlot->GetItemCode() == nItemCode ) return pSlot; it++; } return NULL; } void SInventoryMgr::SetUpdateItemInfo( SInventorySlot* pSlot ) { if( pSlot ) { *m_pUpdateItemInfo = *pSlot; m_pUpdateItemInfo->SetExistence( true ); } else { m_pUpdateItemInfo->SetExistence( false ); } } SInventorySlot* SInventoryMgr::GetUpdateItemInfo( AR_HANDLE handle ) { if( m_pUpdateItemInfo->GetHandle() == handle ) { if( m_pUpdateItemInfo->IsExistence() ) return m_pUpdateItemInfo; else return NULL; } return NULL; } bool SInventoryMgr::IsExistItem( int nItemCode ) { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetItemCode() == nItemCode ) return true; } return false; } bool SInventoryMgr::IsExistItem( AR_HANDLE hItem ) { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetHandle() == hItem ) return true; } return false; } bool SInventoryMgr::IsExistItem( AR_HANDLE hItem, count_t nItemCount ) { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetHandle() == hItem && m_vInventory[i]->GetItemCount() >= nItemCount ) return true; } return false; } bool SInventoryMgr::IsExistInvenItem( int nItemCode ) { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetItemCode() == nItemCode && !m_vInventory[i]->IsStorageItem() ) { return true; } } return false; } bool SInventoryMgr::IsAwakeningItem(SInventorySlot* pSlot) { return pSlot->IsAwakeningItem(); } AR_HANDLE SInventoryMgr::GetFirstFindItem( int nItemCode ) { for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->GetItemCode() == nItemCode ) return m_vInventory[i]->GetHandle(); } return 0; } count_t SInventoryMgr::GetItemCount( int nItemCode ) { int nSize = (int)m_vInventory.size(); for( int i = 0; i < nSize; ++i ) { if( m_vInventory[i]->GetItemCode() == nItemCode ) return m_vInventory[i]->GetItemCount(); } return count_t( 0 ); } void SInventoryMgr::GetEquipItemList( std::vector& vecInvenList ) { vecInvenList.clear(); for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->IsEquipItem() && !m_vInventory[i]->IsStorageItem() && !m_vInventory[i]->IsSummonEquip() ) vecInvenList.push_back(m_vInventory[i]); } } // 2010.07.22 - prodongi void SInventoryMgr::getCreatureEquipItemList( std::vector& vecInvenList, AR_HANDLE creatureHandle ) { vecInvenList.clear(); for( int i = 0; i < static_cast(m_vInventory.size()); i++ ) { if( m_vInventory[i]->IsEquipItem() && !m_vInventory[i]->IsStorageItem() && m_vInventory[i]->IsSummonEquip() ) { if (m_vInventory[i]->GetWearHandle() == creatureHandle) vecInvenList.push_back(m_vInventory[i]); } } } void SInventoryMgr::SortItemList() { struct TItemLess { //두인자가 같을 경우 무조건 false가 나오도록 해야한다. 흠 false가 바꾸는 것인데... bool operator () ( SInventorySlot* a, SInventorySlot* b ) { if( !a || !b ) return true; TS_ITEM_INFO* pInfo_1 = a->GetItem(); TS_ITEM_INFO* pInfo_2 = b->GetItem(); if( !pInfo_1 || !pInfo_2 ) return true; return pInfo_1->index < pInfo_2->index; } } pred; std::sort( m_vInventory.begin(), m_vInventory.end(), pred ); } /// 2010.12.29 - prodongi bool SInventoryMgr::enableSellItem(bool exceptEquipItem, bool exceptDontBuyItem, SInventorySlot const* slot, SCreatureSlotMgr const& creatureSlotMgr, ItemBaseEx_info const* item) const { // if except equipitem : 비장착된 아이템만 장착된 카드도 제외, else : 창고 아이템만 제외 if( (exceptEquipItem && (!slot->IsEquipItem() && !IsEquipCard(slot->GetHandle())) ) || (!exceptEquipItem && !slot->IsStorageItem() ) ) { if( exceptDontBuyItem ) { //상점, 매각 불가 아이템은 스킵 if( item && item->CheckFlag( ItemBase::ITEM_FLAG::FLAG_CANT_SELL ) ) return false; } /// 2010.11.15 - prodongi if (exceptEquipItem) { if (IsBeltSlotCard(slot->GetHandle())) return false; /// 2010.11.24 편성된 크리처 카드 인지 검사 - prodongi if (creatureSlotMgr.IsExistCreatureCard(slot->GetHandle())) return false; } return true; } return false; }