Files
2026-06-01 12:46:52 +02:00

557 lines
17 KiB
C++

#include "stdafx.h"
#include <toolkit/XStringUtil.h>
#include "SStringDB.h"
#include "SItemDB.h"
#include "SLog.h"
#include "SGameMessage.h"
#include "SGameManager.h"
//#include "SGameMessageUI.h"
#include "SInventoryMgr.h"
#include "SPlayerInfoMgr.h"
//#include "KUIControl.h"
#include "KUIControlStatic.h"
#include "KUIControlButton.h"
#include "SUIDurabilityWnd.h"
//#include "SUIUtil.h"
#include "SSummonSlotMgr.h"
//-----------------------------------------------------------------------------------------------------------------
// 이름 공간
//-----------------------------------------------------------------------------------------------------------------
namespace UIDurabilityWnd
{
const static short g_nGauge( 12 );
const char* g_arrGaugeAni[eDurabilityGauga_Max] = { "common_guage_titanium_line_lightgrey", // 내구도가 존재하지 않는 일반 아이템
"common_guage_titanium_line_red", // 1% ~ 32%
"common_guage_titanium_line_cyan", // 33% ~ 65%
"common_guage_titanium_line_yellowgreen", // 66% ~ 100%
"common_guage_titanium_line_Grey" }; // 내구도가 0%라서 수리가 필요한 아이템
const static short g_nGaugeCreature( 7 ); // 추가된 크리처 한마리당 슬롯 개수
const static int c_nMaxCreatureItem( 7 ); // 크리처 최대 아이템 개수
const static short g_nGaugeTotal( g_nGauge + (g_nGaugeCreature * 2) );
}
//-----------------------------------------------------------------------------------------------------------------
// 생성자
//-----------------------------------------------------------------------------------------------------------------
SUIDurabilityWnd::SUIDurabilityWnd( SGameManager * pGameManager )
: SUIWnd( pGameManager )
{
}
//-----------------------------------------------------------------------------------------------------------------
// 파괴자
//-----------------------------------------------------------------------------------------------------------------
SUIDurabilityWnd::~SUIDurabilityWnd()
{
Release();
}
//-----------------------------------------------------------------------------------------------------------------
// 해제
//-----------------------------------------------------------------------------------------------------------------
void SUIDurabilityWnd::Release()
{
m_arrGeneralItem.clear(); // 장비가 내구도가없는 일반아이템의경우 출력될 X 아이콘.
m_arrDrabilityGauge.clear(); // 내구도게이지.
m_vecUIMatchingInfo_Character.clear();
#ifdef DEF_METIN_CREATURE
m_arCreatureRepair0.clear();
m_arCreatureRepair1.clear();
#endif
}
//-----------------------------------------------------------------------------------------------------------------
// 컨트롤 초기화
//-----------------------------------------------------------------------------------------------------------------
bool SUIDurabilityWnd::InitControls( KPoint kPos )
{
return SUIWnd::InitControls( kPos );
}
//-----------------------------------------------------------------------------------------------------------------
// 윈도우 생성
//-----------------------------------------------------------------------------------------------------------------
SUIWnd* SUIDurabilityWnd::CreateWnd( const char* szFile, KUIWndManager* pWndManager, KPoint kPos, int nWindowID )
{
SUIWnd::CreateWnd( szFile, pWndManager, kPos, nWindowID );
CreateUIMatchingInfo_Character();
m_arrGeneralItem.resize( g_nGaugeTotal );
m_arrDrabilityGauge.resize( g_nGaugeTotal );
for( int i=g_nGauge; i<g_nGaugeTotal; ++i )
{
m_arrGeneralItem[i] = GetChild( CStringUtil::StringFormat( "mark_none_ex%02d", i+1 ).c_str() );
if( NULL == m_arrGeneralItem[i] )
{
SDEBUGLOG( "[UIDurabilityWnd] Can't Get UI Control - Name[%s]", CStringUtil::StringFormat( "mark_none_ex%02d", i+1 ).c_str() );
assert( m_arrGeneralItem[i] );
continue;
}
}
for( int i=g_nGauge; i<g_nGaugeTotal; ++i )
{
m_arrDrabilityGauge[i] = GetChild( CStringUtil::StringFormat( "gauge_repair_line_yellowgreen_%02d", i+1 ).c_str() );
if( m_arrDrabilityGauge[i] )
m_arrDrabilityGauge[i]->SetShow( false );
else
{
SDEBUGLOG( "[UIDurabilityWnd] Can't Get UI Control - Name[%s]", CStringUtil::StringFormat( "gauge_repair_line_yellowgreen_%02d", i+1 ).c_str() );
assert( m_arrDrabilityGauge[i] );
continue;
}
}
if( false == m_vecUIMatchingInfo_Character.empty() &&
m_vecUIMatchingInfo_Character[0].m_pGaugeBarControl )
{
m_fGaugeWidth = (float)m_vecUIMatchingInfo_Character[0].m_pGaugeBarControl->GetRect().GetWidth(); // 내구도 게이지 기본넓이.
}
#ifdef DEF_METIN_CREATURE
InitCreatureRepairUI();
#endif
return this;
}
//-----------------------------------------------------------------------------------------------------------------
// 메시지 처리
//-----------------------------------------------------------------------------------------------------------------
void SUIDurabilityWnd::PumpUpMessage( LPCSTR lpszControlID, DWORD nMessage, DWORD lparam, DWORD wparam )
{
switch( nMessage )
{
case KUI_MESSAGE::KGENWND_MOVE:
LimitMoveWnd();
break;
}
SUIWnd::PumpUpMessage( lpszControlID, nMessage, lparam, wparam );
}
//-----------------------------------------------------------------------------------------------------------------
// 윈도우 열릴 때
//-----------------------------------------------------------------------------------------------------------------
void SUIDurabilityWnd::OnNotifyUIWindowOpen( bool bOpen, bool bLimitWnd)
{
if( bOpen )
{
RefreshDurability();
}
}
//-----------------------------------------------------------------------------------------------------------------
// 캐릭터 내구도 UI와 장비의 매칭 정보 생성
//-----------------------------------------------------------------------------------------------------------------
void SUIDurabilityWnd::CreateUIMatchingInfo_Character()
{
m_vecUIMatchingInfo_Character.resize( g_nGauge );
for( WORD wDurabilityUIIndex = 0; wDurabilityUIIndex < g_nGauge; wDurabilityUIIndex++ )
{
UIMATCHINGINFO& stUIMatchingInfo = m_vecUIMatchingInfo_Character[wDurabilityUIIndex];
stUIMatchingInfo.m_nUIIndex = wDurabilityUIIndex;
stUIMatchingInfo.m_pGaugeBarControl = GetChild( CStringUtil::StringFormat( "gauge_repair_line_yellowgreen_%02d", wDurabilityUIIndex+1 ).c_str() );
if( NULL == stUIMatchingInfo.m_pGaugeBarControl )
{
SDEBUGLOG( "[UIDurabilityWnd] Can't Get UI Control - Name[%s]", CStringUtil::StringFormat( "gauge_repair_line_yellowgreen_%02d", wDurabilityUIIndex+1 ).c_str() );
assert( stUIMatchingInfo.m_pGaugeBarControl );
}
else
stUIMatchingInfo.m_pGaugeBarControl->SetShow( false );
stUIMatchingInfo.m_pBrokenIconControl = GetChild( CStringUtil::StringFormat( "mark_none_ex%02d", wDurabilityUIIndex+1 ).c_str() );
if( NULL == stUIMatchingInfo.m_pBrokenIconControl )
{
SDEBUGLOG( "[UIDurabilityWnd] Can't Get UI Control Pointer - Name[%s]", CStringUtil::StringFormat( "mark_none_ex%02d", wDurabilityUIIndex+1 ).c_str() );
assert( stUIMatchingInfo.m_pBrokenIconControl );
}
else
{
stUIMatchingInfo.m_pBrokenIconControl->SetAniName( "common_mark_titanium_repair_none" );
stUIMatchingInfo.m_pBrokenIconControl->SetShow( false );
}
stUIMatchingInfo.m_nWearType = GetWearTypeFromDurabilityUIIndex( wDurabilityUIIndex );
}
}
//-----------------------------------------------------------------------------------------------------------------
// 내구도 UI Index로 부터 장비 타입 얻기
// 추가 설명 : 하드 코딩 하기로 협약 된 부분입니다. 이해하세요...
//-----------------------------------------------------------------------------------------------------------------
UINT SUIDurabilityWnd::GetWearTypeFromDurabilityUIIndex( WORD wDurabilityUIIndex )
{
switch( wDurabilityUIIndex )
{
case 0:
return ItemBase::ItemWearType::WEAR_HELM;
case 1:
return ItemBase::ItemWearType::WEAR_ARMOR;
case 2:
return ItemBase::ItemWearType::WEAR_GLOVE;
case 3:
return ItemBase::ItemWearType::WEAR_BOOTS;
case 4:
return ItemBase::ItemWearType::WEAR_WEAPON;
case 5:
return ItemBase::ItemWearType::WEAR_SHIELD;
case 6:
return ItemBase::ItemWearType::WEAR_EAR;
case 7:
return ItemBase::ItemWearType::WEAR_SECOND_EAR;
case 8:
return ItemBase::ItemWearType::WEAR_RING;
case 9:
return ItemBase::ItemWearType::WEAR_SECOND_RING;
case 10:
return ItemBase::ItemWearType::WEAR_BELT;
case 11:
return ItemBase::ItemWearType::WEAR_ARMULET;
default:
{
SDEBUGLOG( "[UIDurabilityWnd] Invalide UI Index Number - UI Index [%d]", wDurabilityUIIndex );
}
return ItemBase::ItemWearType::WEAR_CANTWEAR;
}
return ItemBase::ItemWearType::WEAR_CANTWEAR;
}
void SUIDurabilityWnd::ProcMsgAtStatic(SGameMessage* pMsg)
{
switch (pMsg->nType)
{
case MSG_ITEM_WEAR_INFO:
case MSG_ITEM_INVEN:
RefreshDurability();
break;
case IMSG_UI_MOVE:
{
pMsg->bUse = true;
SIMSG_UI_MOVE* pMoveMsg = (SIMSG_UI_MOVE*)pMsg;
if (pMoveMsg->m_nX != this->GetRect().left || pMoveMsg->m_nY != this->GetRect().top)
MovePos(pMoveMsg->m_nX, pMoveMsg->m_nY);
}
break;
case IMSG_UI_SEND_DATA:
{
SIMSG_UI_SEND_DATA* pData = (SIMSG_UI_SEND_DATA*)pMsg;
if (pData->m_strString == "refresh_durability")
{
RefreshDurability();
}
}
break;
}
}
//-----------------------------------------------------------------------------------------------------------------
// 장비 타입으로 부터 매칭 정보 얻기
//-----------------------------------------------------------------------------------------------------------------
PUIMATCHINGINFO SUIDurabilityWnd::FindUIMatchingInfoFromWearType( const int nWearType )
{
if( m_vecUIMatchingInfo_Character.empty() )
return NULL;
for( UINT nCount = 0; nCount < m_vecUIMatchingInfo_Character.size(); nCount++ )
{
UIMATCHINGINFO stUIMatchingInfo = m_vecUIMatchingInfo_Character[nCount];
if( stUIMatchingInfo.m_nWearType == static_cast<UINT>( nWearType ) )
return &m_vecUIMatchingInfo_Character[nCount];
}
return NULL;
}
//-----------------------------------------------------------------------------------------------------------------
// 장비 타입으로 부터 내구도 정보 얻기
//-----------------------------------------------------------------------------------------------------------------
void SUIDurabilityWnd::GetDurabilityInfoFromWearType(const int nWearType, eWearItemStatus& eItemStatus, float& fDurabilityPercent)
{
SInventorySlot* pSlot( m_InventoryMgr.GetItemInfo( nWearType ) );
if( pSlot ) // 장비 있음
{
const ItemBaseEx_info* pItemBase( GetItemDB().GetItemData( pSlot->GetItemCode() ) );
if( NULL == pItemBase )
{
SDEBUGLOG( "[UIDurabilityWnd] Can't Get ItemInfo - ItemCode [ %n ]", pSlot->GetItemCode() );
assert( pItemBase );
eItemStatus = eWearItemStatus::eNone;
fDurabilityPercent = 0.0f;
}
else
{
if( pSlot->getMaxEtherealDurability() > 0 ) // 상급 아이템
{
float ethereal( pSlot->GetEtherealDurability() );
if( ethereal > 0.0f )
{
eItemStatus = eWearItemStatus::eHighClass;
fDurabilityPercent = (float)ethereal / (float)pSlot->getMaxEtherealDurability();
if( ( (float)pSlot->getMaxEtherealDurability() / 10000.0f ) - ( ethereal / 10000.0f ) < 1.0f )
fDurabilityPercent = 1.0f;
}
else
{
eItemStatus = eWearItemStatus::eBroken;
fDurabilityPercent = 0.0f;
}
}
else
{
eItemStatus = eWearItemStatus::eNormalClass; // 일반 아이템
fDurabilityPercent = 1.0f;
}
}
}
else // 장비 없음
{
eItemStatus = eWearItemStatus::eNone;
fDurabilityPercent = 0.0f;
}
return ;
}
//-----------------------------------------------------------------------------------------------------------------
// 내구도 갱신
//-----------------------------------------------------------------------------------------------------------------
void SUIDurabilityWnd::RefreshDurability()
{
for( UINT nCount = 0; nCount < m_vecUIMatchingInfo_Character.size(); nCount++ )
{
UIMATCHINGINFO stUIMatchingInfo = m_vecUIMatchingInfo_Character[nCount];
if( stUIMatchingInfo.m_pGaugeBarControl )
stUIMatchingInfo.m_pGaugeBarControl->SetShow( false );
if( stUIMatchingInfo.m_pBrokenIconControl )
{
stUIMatchingInfo.m_pBrokenIconControl->SetAniName( "common_mark_titanium_repair_none" );
stUIMatchingInfo.m_pBrokenIconControl->SetShow( false );
}
}
for( int nWearType = ItemBase::ItemWearType::WEAR_WEAPON; nWearType < ItemBase::ItemWearType::WEAR_FACE; ++nWearType )
{
if( nWearType == ItemBase::ItemWearType::WEAR_MANTLE ) // 망토는 제외
continue;
eDurabilityGaugaKind eGaugaKind( eDurabilityGauga_DontHave );
eWearItemStatus eItemStatus( eWearItemStatus::eNone );
float fDurabilityPercent( 0.0f );
// UI 매칭 정보 얻기
PUIMATCHINGINFO pUIMatchingInfo( FindUIMatchingInfoFromWearType( nWearType ) );
// 내구도 정도 얻기
GetDurabilityInfoFromWearType( nWearType, eItemStatus, fDurabilityPercent );
switch( eItemStatus )
{
case eWearItemStatus::eNone:
break;
case eWearItemStatus::eNormalClass:
{
eGaugaKind = eDurabilityGauga_DontHave;
if( pUIMatchingInfo && pUIMatchingInfo->m_pGaugeBarControl )
pUIMatchingInfo->m_pGaugeBarControl->SetShow( true );
}
break;
case eWearItemStatus::eHighClass:
{
if( fDurabilityPercent < 0.33f ) // red.
eGaugaKind = eDurabilityGauga_Danger;
else if( fDurabilityPercent < 0.66f ) // cyan.
eGaugaKind = eDurabilityGauga_Warning;
else // yellowgreen.
eGaugaKind = eDurabilityGauga_Normal;
if( pUIMatchingInfo && pUIMatchingInfo->m_pGaugeBarControl )
pUIMatchingInfo->m_pGaugeBarControl->SetShow( true );
}
break;
case eWearItemStatus::eBroken:
{
eGaugaKind = eDurabilityGauga_Broken;
if( pUIMatchingInfo && pUIMatchingInfo->m_pBrokenIconControl )
{
pUIMatchingInfo->m_pBrokenIconControl->SetAniName( "common_mark_titanium_repair_zero" );
pUIMatchingInfo->m_pBrokenIconControl->SetShow( true );
}
if( pUIMatchingInfo && pUIMatchingInfo->m_pGaugeBarControl )
pUIMatchingInfo->m_pGaugeBarControl->SetShow( true );
}
break;
default:
assert( NULL );
break;
}
if( pUIMatchingInfo && pUIMatchingInfo->m_pGaugeBarControl )
{
KRect rt( pUIMatchingInfo->m_pGaugeBarControl->GetRect() );
pUIMatchingInfo->m_pGaugeBarControl->SetAniName( g_arrGaugeAni[ eGaugaKind ] );
rt.right = rt.left + m_fGaugeWidth * fDurabilityPercent;
pUIMatchingInfo->m_pGaugeBarControl->Resize( rt );
}
}
for( int j = g_nGauge; j < g_nGaugeTotal; j++ )
{
m_arrDrabilityGauge[ j ]->SetShow(false);
}
int nCount = m_CreatureSlotMgr.GetCreatureItemCount( m_CreatureSlotMgr.GetSelectedCreature() );
nCount = max( nCount, c_nMaxCreatureItem );
// 크리처관련 내구도
int nSummonCount = 0;
int nStartID = g_nGauge;
for( int k = 0; k < SCreatureSlotMgr::MAX_CREATURE_SLOT; k++ )
{
if( nSummonCount >= SCreatureSlotMgr::MAX_SUMMON_SLOT )
break;
AR_HANDLE hCreture = m_CreatureSlotMgr.GetCreatureHandleByCardHandle( m_CreatureSlotMgr.GetEquipedCreatureCard(k) );
if( m_CreatureSlotMgr.IsExistSummonedCreature( hCreture ) == false )
continue ;
SInventorySlot* pSlot = m_InventoryMgr.GetItemInfo( m_CreatureSlotMgr.GetEquipedCreatureCard(k) );
if( pSlot )
{
refreshItemDurability( pSlot, m_arrDrabilityGauge[ nStartID ], m_fGaugeWidth );
}
for( int i = 0; i < c_nMaxCreatureItem - 2; i++ )
{
AR_HANDLE hItem = m_CreatureSlotMgr.GetCreatureItem( hCreture, i );
if( hItem == NULL )
continue;
SInventorySlot* pSlot = m_InventoryMgr.GetItemInfo( hItem );
if( pSlot )
{
// m_arrDrabilityGauge[ nStartID + i + 1 ] : 은 아이템 슬롯 전에 크리처 카드 슬롯이 있어서 인덱스 1 더해준다
refreshItemDurability( pSlot, m_arrDrabilityGauge[ nStartID + i + 1 ], m_fGaugeWidth );
}
}
nStartID += g_nGaugeCreature;
nSummonCount++;
}
}
#ifdef DEF_METIN_CREATURE
// UI가 그룹으로 묶여져 있지를 않다. 그룹으로 묶고 싶다 ㅠㅠ
void SUIDurabilityWnd::InitCreatureRepairUI()
{
for ( int i = c_nUICreatureRepair0; i < c_nUICreatureRepair0 + c_nRepairSlotSize; i++ )
{
KUIWnd* pWnd = GetChild( CStringUtil::StringFormat( "guage_base_%02d", i ).c_str() );
m_arCreatureRepair0.push_back(pWnd);
pWnd = GetChild( CStringUtil::StringFormat( "mark_%02d", i ).c_str() );
m_arCreatureRepair0.push_back(pWnd);
}
for ( int i = c_nUICreatureRepair1; i < c_nUICreatureRepair1 + c_nRepairSlotSize; i++ )
{
KUIWnd* pWnd = GetChild( CStringUtil::StringFormat( "guage_base_%02d", i ).c_str() );
m_arCreatureRepair1.push_back(pWnd);
pWnd = GetChild( CStringUtil::StringFormat( "mark_%02d", i ).c_str() );
m_arCreatureRepair1.push_back(pWnd);
}
}
void SUIDurabilityWnd::SetShowCreatureRepairUI(int nCreatureUI, bool bShow)
{
vector< KUIWnd*> *pCreatureUI = NULL;
switch(nCreatureUI)
{
case 0: pCreatureUI = &m_arCreatureRepair0; break;
case 1: pCreatureUI = &m_arCreatureRepair1; break;
default:
return;
}
for ( int i = 0; i < pCreatureUI->size(); i++ )
{
KUIWnd* pWnd = pCreatureUI->at(i);
pWnd->SetShow(bShow);
}
}
#endif