Files
Leviathan/Client/Game/game/Interface/SUITargetStateWnd.cpp
T
2026-06-01 12:46:52 +02:00

627 lines
18 KiB
C++

#include "stdafx.h"
#include "KUIWndManager.h"
#include "KUIControlStatic.h"
#include "KUIControlClockBox.h"
#include "SGameManager.h"
//#include "SGameMessageUI.h"
#include "SUITargetStateWnd.h"
#include "SUIDisplayInfo.h"
#include "STenacityDB.h"
#include "SkillBaseFile.h"
#include "SGameOption.h"
#include "SPlayerInfoMgr.h"
#include "KUIControlQuickEffect.h"
#include "SGameAvatarEx.h"
#include "KUIWnd.h"
#include "SGame.h"
#include "SSummonSlotMgr.h"
#include "./Target/SUITargetWnd_Player.h"
#include "./Target/SUITargetWnd_Creature.h"
namespace
{
enum SHOW_TYPE
{
SHOW_SHORT = 0,
SHOW_MIDDLE,
SHOW_LONG,
};
const int c_nMaxStateIcon = 36;
const int c_nMaxNum = 36;
const int c_nIconHeight = 20; /// 2011.01.19 - prodongi
const int REITERATION_OFFSET = 5; /// 2011.03.30 오버렙 아이콘의 상태 아이콘에 대한 옵셋값 - prodongi
const int MAX_REITERATION_LEVEL = 99; /// 2011.04.01 - prodongi
};
bool SUITargetStateWnd::InitControls( KPoint kPos )
{
CreateItemIcon(); // 아이콘 생성
KRect rReiteration; /// 2011.03.30 - prodongi
KUIWnd* pWnd = NULL;
// state 재사용 시간 컨트롤
for( int i = 1; i <= c_nMaxStateIcon; i++ )
{
KUIWnd* pIcon = GetChild( CStringUtil::StringFormat("state_effect_h_icon%02d", i).c_str() );
if( pIcon )
{
pWnd = m_pManager->CreateControl( KUIWND_CREATE_ARG( "clockbox", CStringUtil::StringFormat("state_effect_h_clock%02d", i).c_str(), " ", pIcon->GetRect(), 0, KFLAG_NO_GET_MESSAGE, this, "", c_szDEF_SPR_NAME, m_pManager, 0, "", KANCHOR_LEFT | KANCHOR_TOP ) );
if( pWnd ) ((KUIControlClockBox*)pWnd)->SetColor( c_ColorClockControl );
/// 2011.03.30 중첩 아이콘 생성 - prodongi
rReiteration.left = pIcon->GetRect().left + REITERATION_OFFSET;
rReiteration.top = pIcon->GetRect().top + REITERATION_OFFSET;
rReiteration.right = pIcon->GetRect().right;
rReiteration.bottom = pIcon->GetRect().bottom;
pWnd = m_pManager->CreateControl( KUIWND_CREATE_ARG( "static", CStringUtil::StringFormat("state_effect_h_reiteration%02d", i).c_str(), " ", rReiteration, 0, KFLAG_GET_PASS_MESSAGE, this, "", c_szDEF_SPR_NAME, m_pManager, 0, "", KANCHOR_LEFT | KANCHOR_TOP ) );
if (pWnd)
{
pWnd->SetShow(false);
}
}
}
return SUIWnd::InitControls(kPos);
}
bool SUITargetStateWnd::InitData( bool bReload )
{
m_nShowType = -1;
m_nCurNegativePos = 0;
DisableSlot( 0, c_nMaxNum, false );
return SUIWnd::InitData(bReload);
}
void SUITargetStateWnd::PumpUpMessage( LPCSTR lpszControlID, DWORD nMessage, DWORD lparam, DWORD wparam )
{
switch(nMessage)
{
case KUI_MESSAGE::KBUTTON_CLICK:
break;
case KUI_MESSAGE::KGENWND_MOVE: // 윈도우 이동
break;
}
SUIWnd::PumpUpMessage( lpszControlID, nMessage, lparam, wparam );
}
void SUITargetStateWnd::ProcMsgAtStatic( SGameMessage* pMsg )
{
switch(pMsg->nType)
{
case MSG_STATE:
{
pMsg->bUse = true;
}
break;
case IMSG_UI_STATE_UPDATE:
{
if( IsSetTarget() )
{
CheckState();
if( !IsShow() && IsSlot() )
m_pGameManager->PostMsgAtDynamic( new SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_STATE, true ) );
if( IsShow() && !IsSlot() )
m_pGameManager->PostMsgAtDynamic( new SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_STATE, false ) );
}
pMsg->bUse = true;
}
break;
case IMSG_UI_TARGET_INFO:
{
SIMSG_UI_TARGET_INFO* pTargetMsg = ( SIMSG_UI_TARGET_INFO* )pMsg;
if( pTargetMsg->handle )
{
CalcOpenPosition( pTargetMsg->nObjType );
m_pTarget = NULL; //타겟이 바뀔경우 이곳을 들어오니 m_pTarget을 NULL로 초기화하는 것
IsSetTarget();
//갱신
if( IsSlot() ) //-N4- 갱신후 슬롯의 데이터 유무에 따라 구분
{
RefreshAllStateInfo();
m_pGameManager->PostMsgAtDynamic( new SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_STATE, true ) );
}
else m_pGameManager->PostMsgAtDynamic( new SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_STATE, false ) );
}
else
{
// 리스트 초기화 하고 닫는다
CloseWnd();
}
pMsg->bUse = true;
}
break;
case IMSG_UI_STATE_LIST_UPDATE:
{
UpdateStateData(pMsg);
pMsg->bUse = true;
}
break;
}
}
void SUITargetStateWnd::CalcOpenPosition( int nObjType )
{
if( NULL == m_pGameManager )
return ;
if( TS_ENTER::GAME_PLAYER == nObjType )
{
SUITargetWnd_Player* pTargetWnd_Player( dynamicCast<SUITargetWnd_Player*>( m_pGameManager->GetSUI(SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_PLAYER) ) );
if( pTargetWnd_Player )
{
KRect rtTargetPlayer( pTargetWnd_Player->GetRect() );
KRect rtTargetState( GetRect() );
int nOffset( ( rtTargetPlayer.GetWidth() - rtTargetState.GetWidth() ) / 2 );
MovePos( rtTargetPlayer.left + nOffset, rtTargetPlayer.bottom );
}
return ;
}
if( TS_ENTER::GAME_SUMMON == nObjType ||
TS_ENTER::GAME_MOB == nObjType ||
TS_ENTER::GAME_PET == nObjType )
{
SUITargetWnd_Creature* pTargetWnd_Creature( dynamicCast<SUITargetWnd_Creature*>( m_pGameManager->GetSUI(SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_CREATURE) ) );
if( pTargetWnd_Creature )
{
KRect rtTargetCreature( pTargetWnd_Creature->GetRect() );
KRect rtTargetState( GetRect() );
int nOffset( ( rtTargetCreature.GetWidth() - rtTargetState.GetWidth() ) / 2 );
MovePos( rtTargetCreature.left + nOffset, rtTargetCreature.bottom );
}
return ;
}
}
void SUITargetStateWnd::OnNotifyUIWindowOpen( bool bOpen, bool bLimitWnd )
{
SUIWnd::OnNotifyUIWindowOpen( bOpen, bLimitWnd );
if( bOpen )
{
IsSetTarget();
RefreshAllStateInfo();
}
else
{
m_pTarget = NULL;
}
}
// =========================================
// 윈도우
// =========================================
void SUITargetStateWnd::CreateItemIcon()
{
KUIControlIconStatic* pIcon = dynamicCast<KUIControlIconStatic*>(GetChild( "state_effect_h_icon01" ));
if( pIcon == NULL ) return;
KRect rt = pIcon->GetRect();
KRect EffectRT = rt;
EffectRT.right = EffectRT.left + c_nIconHeight;
EffectRT.bottom = EffectRT.top + c_nIconHeight;
int nLeft, nTop = 0;
nLeft = rt.left; nTop = rt.top;
rt.left += c_nIconHeight;
KUIWnd* pWnd = NULL;
for( int i = 2; i <= c_nMaxNum; i++ )
{
rt.right = rt.left + c_nIconHeight;
rt.bottom = rt.top + c_nIconHeight;
pWnd = m_pManager->CreateControl( KUIWND_CREATE_ARG( "iconstatic", CStringUtil::StringFormat( "state_effect_h_icon%02d", i ).c_str(), " ", rt, 0, 0, this, "static_job_unknownicon", c_szDEF_SPR_NAME, m_pManager, 0, "tooltip", KANCHOR_LEFT | KANCHOR_TOP ) );
if( i%12 == 0 )
{
rt.left = nLeft;
rt.top = nTop + c_nIconHeight;
nTop = rt.top;
}
else
rt.left += c_nIconHeight;
}
/*pWnd = m_pManager->CreateControl( KUIWND_CREATE_ARG( "quick_effect", "icon_effect", " ", EffectRT, 0, KFLAG_NO_GET_MESSAGE, this, "", c_szDEF_SPR_NAME, m_pManager, 0, "", KANCHOR_LEFT | KANCHOR_TOP ) );
if( pWnd )
{
KUIControlQuickEffect* pSlotEffect( ((KUIControlQuickEffect*)pWnd) );
pSlotEffect->ToggleOn(true);
pSlotEffect->SetShow(false);
pSlotEffect->SetAniTargetSize( EffectRT.GetWidth()*2.5, EffectRT.GetHeight()*2.5 );
pSlotEffect->MovePos( EffectRT.left-17, EffectRT.top-17 );
SetChildAsTop( "icon_effect" );
}*/
}
// =========================================
// 스테이트 리스트
// =========================================
bool SUITargetStateWnd::IsCashState( int nCode )
{
for( int i(0); i<c_nMaxCashState; ++i )
{
if( c_nCashStateId[i] == nCode )
return true;
}
return false;
}
// =========================================
// 스테이트 슬롯
// =========================================
void SUITargetStateWnd::CloseWnd()
{
m_pTarget = NULL;
m_pGameManager->PostMsgAtDynamic( new SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_STATE, false ) );
}
bool SUITargetStateWnd::IsSlot()
{
if( !m_pTarget ) return false;
// sonador 7.0.20 Mantis 0002775: [버프] 라펠즈PC방이나 시크루트 버프를 받은 아바타 타겟 시 제대로 보이지 않음
return ( !m_pTarget->GetCashStateList().empty() || !m_pTarget->GetPositiveStateList().empty() || !m_pTarget->GetNegativeStateList().empty() );
}
bool SUITargetStateWnd::IsSetTarget()
{
if( !m_pTarget )
{
SGame* pGame = m_pGameManager->GetActiveGame();
if( !pGame || pGame->GetGameType() != GAME_TYPE_WORLD )
return false;
AR_HANDLE handle = m_PlayerInfoMgr.GetTarget();
m_pTarget = (SGameAvatarEx*)(pGame->GetGameObject(handle));
if( !m_pTarget )
return false;
}
return true;
}
void SUITargetStateWnd::RefreshAllStateInfo()
{
if( !IsSetTarget() ) return;
vec_state_slot& PositiveList = m_pTarget->GetPositiveStateList();
vec_state_slot& NegativeList = m_pTarget->GetNegativeStateList();
int nPositiveCount = static_cast<int>(PositiveList.size());
int nNegativeCount = static_cast<int>(NegativeList.size());
if( nPositiveCount>24 ) nPositiveCount = 24;
//이로운 지속효과를 세팅
for( int i(0); i<nPositiveCount; i++ )
{
SetStateData( i, PositiveList[i], false );
}
//이로운 지속효과 라인에서 나머지 부분을 NULL로 쎄팅
int nPositiveEndIndex(0);
if( nPositiveCount )
{
//((nPositiveCount-1)/10+1) * 10
//-> 1~10 = 10 / 11~20 = 20 으로 NULL로 쎄팅해야할 마지막 부분을 구하는 식
nPositiveEndIndex = ((nPositiveCount-1)/12+1) * 12;
for( int i(nPositiveCount); i<nPositiveEndIndex; i++ )
{
SetStateData( i, NULL, false );
}
}
//해로운 지속효과 쎄팅
for( int index(nPositiveEndIndex), nNegative(0); index<c_nMaxNum; ++index, ++nNegative )
{
if( nNegative<nNegativeCount )
SetStateData( index, NegativeList[nNegative], false );
else SetStateData( index, NULL, false );
}
}
int SUITargetStateWnd::GetStateCodeForIndex( int nIndex )
{
if( !IsSetTarget() ) return -1;
vec_state_slot& PositiveList = m_pTarget->GetPositiveStateList();
vec_state_slot& NegativeList = m_pTarget->GetNegativeStateList();
int nPositiveCount = static_cast<int>(PositiveList.size());
int nNegativeCount = static_cast<int>(NegativeList.size());
int nMaxCnt( nPositiveCount );
if( nMaxCnt > nIndex )
{
int nPositiveIndex( nIndex );
if( 0 <= nPositiveIndex && nPositiveIndex < nPositiveCount && PositiveList[ nPositiveIndex ] )
return PositiveList[ nPositiveIndex ]->GetStateCode();
}
else
{
int nStartIndex = (int)( (nMaxCnt+11) / 12 ) * 12;
int nNegativeIndex = nIndex - nStartIndex;
if( 0 <= nNegativeIndex && nNegativeIndex < nNegativeCount && nNegativeCount < c_nMaxStateIcon-1 )
{
if( NegativeList[ nNegativeIndex ] )
return NegativeList[ nNegativeIndex ]->GetStateCode();
}
}
return -1;
}
void SUITargetStateWnd::SetStateData( int Index, SStateSlot* pInfo, bool bCash, bool bOnlyTime/*=false*/ )
{
if( Index < 0 ) return;
KUIControlIconStatic* pIcon(NULL);
KUIControlClockBox* pClock(NULL);
/// 2011.03.30 - prodongi
KUIControlStatic* ctrlReIteration = NULL;
pIcon = dynamicCast<KUIControlIconStatic*>(GetChild( CStringUtil::StringFormat("state_effect_h_icon%02d", Index+1).c_str() ));
pClock = dynamicCast<KUIControlClockBox*>(GetChild( CStringUtil::StringFormat("state_effect_h_clock%02d", Index+1).c_str() ));
/// 2011.03.30 - prodongi
ctrlReIteration = dynamicCast<KUIControlStatic*>(GetChild( CStringUtil::StringFormat("state_effect_h_reiteration%02d", Index+1).c_str() ));
if( pIcon )
{
if( bCash ) pIcon->SetAbleReSizeRes(false);
if( pInfo )
{
pIcon->SetShow(true);
if(!bOnlyTime) pIcon->SetIcon( c_szDEF_SPR_NAME, GetTenacityDB().GetIconName(pInfo->GetStateCode()) );
pIcon->SetTooltip( m_pDisplayInfo->GetStateToolTipText(pInfo->GetStateCode(), pInfo->GetEndTime(), pInfo->GetStateLevel(), pInfo->GetStateValue(), pInfo->IsToggleSkill()).c_str() );
}
else pIcon->SetShow(false);
}
if( pClock ) //토글형 스킬은 쿨타임 생략
{
if( pInfo && !pInfo->IsToggleSkill() )
{
pClock->SetShow(true);
pClock->SetMaxTime( pInfo->GetMaxTime() );
pClock->SetCurTime( pInfo->GetRemainTime() );
pClock->Begin( true );
}
else pClock->SetShow(false);
}
/// 2011.03.30 - prodongi
if (ctrlReIteration)
{
setReiterationCount(pInfo, ctrlReIteration);
}
}
void SUITargetStateWnd::CheckState()
{
if( !IsSetTarget() ) return;
vec_state_slot& CashStateList = m_pTarget->GetCashStateList();
vec_state_slot& PositiveList = m_pTarget->GetPositiveStateList();
vec_state_slot& NegativeList = m_pTarget->GetNegativeStateList();
CheckStateList( 0, CashStateList, false, true );
CheckStateList( 0, PositiveList, false, false );
CheckStateList( 0, NegativeList, true, false );
}
int SUITargetStateWnd::CheckStateList( int nIndex, std::vector<SStateSlot*>& rStateList, bool bharmful, bool bCash )
{
nIndex = GetUpdateStateIndex(nIndex, bharmful, bCash);
if( nIndex < 0 ) return -1;
if( rStateList.size() > 0 )
{
iterator_state_slot it = rStateList.begin();
while( it != rStateList.end() )
{
SStateSlot* pInfo = (*it);
KUIControlIconStatic* pIcon = dynamicCast<KUIControlIconStatic*>(GetChild( CStringUtil::StringFormat("state_effect_h_icon%02d", nIndex+1).c_str() ));
if( pIcon ) pIcon->SetTooltip( m_pDisplayInfo->GetStateToolTipText(pInfo->GetStateCode(), pInfo->GetEndTime(), pInfo->GetStateLevel(), pInfo->GetStateValue(), pInfo->IsToggleSkill()).c_str() );
nIndex++;
it++;
}
}
return nIndex;
}
void SUITargetStateWnd::UpdateStateData( SGameMessage* pMsg )
{
SIMSG_UI_STATE_LIST_UPDATE* pStateMsg = (SIMSG_UI_STATE_LIST_UPDATE*)pMsg;
int Index(-1);
switch( pStateMsg->nUpdateType )
{
case SIMSG_UI_STATE_LIST_UPDATE::STATE_CHANGE:
{
Index = GetUpdateStateIndex(pStateMsg->nIndex, pStateMsg->bharmful, false);
if( Index != -1 )
SetStateData(Index, pStateMsg->pState, false);
}
break;
case SIMSG_UI_STATE_LIST_UPDATE::STATE_ADD:
case SIMSG_UI_STATE_LIST_UPDATE::STATE_ADD_CASH:
case SIMSG_UI_STATE_LIST_UPDATE::STATE_CHANGE_CASH:
case SIMSG_UI_STATE_LIST_UPDATE::STATE_DELETE:
case SIMSG_UI_STATE_LIST_UPDATE::STATE_DELETE_CASH:
case SIMSG_UI_STATE_LIST_UPDATE::STATE_REFRESH:
{
RefreshAllStateInfo();
}
break;
}
if( !IsShow() && IsSlot() )
m_pGameManager->PostMsgAtDynamic( new SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_STATE, true ) );
if( IsShow() && !IsSlot() )
m_pGameManager->PostMsgAtDynamic( new SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TARGET_STATE, false ) );
}
int SUITargetStateWnd::GetUpdateStateIndex( int Index, bool bHarmhul, bool bCash )
{
if( Index < 0 ) return -1;
if( !IsSetTarget() ) return -1;
vec_state_slot& CashStateList = m_pTarget->GetCashStateList();
vec_state_slot& PositiveList = m_pTarget->GetPositiveStateList();
vec_state_slot& NegativeList = m_pTarget->GetNegativeStateList();
int nCrrIndex(0);
if(bHarmhul)
{
int nSize( CashStateList.size() + PositiveList.size() );
if( nSize>0 )
{
if( nSize<=12 ) nCrrIndex = 12;
else nCrrIndex = 24;
nCrrIndex += Index;
if( nCrrIndex<36 )
return nCrrIndex;
}
else if( Index<24 )
{
return Index;
}
}
else
{
if( !bCash ) Index += CashStateList.size();
if( Index<24 ) return Index;
}
return -1;
}
void SUITargetStateWnd::DisableSlot( int nIndex, int nEnd, bool bShow )
{
KUIControlIconStatic* pIcon = NULL;
KUIControlClockBox* pClock = NULL;
/// 2011.03.30 - prodongi
KUIControlStatic* ctrlReIteration;
for( int i = nIndex; i < nEnd; i++ )
{
pIcon = dynamicCast<KUIControlIconStatic*>(GetChild( CStringUtil::StringFormat("state_effect_h_icon%02d", i+1).c_str() ));
if( pIcon )
{
pIcon->SetShow(bShow);
pIcon->SetIcon(0);
pIcon->SetTooltip();
}
pClock = dynamicCast<KUIControlClockBox*>(GetChild( CStringUtil::StringFormat("state_effect_h_clock%02d", i+1).c_str() ));
if( pClock )
{
pClock->SetShow(bShow);
pClock->SetCurTime(0);
pClock->SetMaxTime(0);
pClock->Begin();
}
/// 2011.03.30 - prodongi
ctrlReIteration = dynamicCast<KUIControlStatic*>(GetChild( CStringUtil::StringFormat("state_effect_h_reiteration%02d", i+1).c_str() ));
if( ctrlReIteration )
{
ctrlReIteration->SetShow(bShow);
}
}
}
DWORD SUITargetStateWnd::OnMouseMessage(DWORD dwMessage, int x, int y)
{
if( dwMessage == KLBUTTON_DBLCLK )
{
AR_HANDLE handle(NULL);
KUIWnd* pIcon(NULL);
for( int i(0); i<c_nMaxStateIcon; ++i )
{
pIcon = GetChild( CStringUtil::StringFormat("state_effect_h_icon%02d", i+1).c_str() );
if( pIcon->IsShow() && pIcon->IsInRect(x, y) )
{
int nCode = GetStateCodeForIndex(i);
if( IsAbleRemove( nCode ) )
{
handle = GetOwnerHandle_TargetSummonCreatureForOnlyLocalPlayer();
if( handle )
m_pGameManager->ProcMsgAtStatic( &SIMSG_REQUEST_REMOVE_STATE( handle, nCode ) );
}
break;
}
}
}
return SUIWnd::OnMouseMessage( dwMessage, x, y );
}
bool SUITargetStateWnd::IsAbleRemove( int nID )
{
if( nID )
{
StateInfoEx* s_data = GetTenacityDB().GetTenacityData(nID);
if( s_data && s_data->state_time_type & 1<<5 )
return true;
}
return false;
}
AR_HANDLE SUITargetStateWnd::GetOwnerHandle_TargetSummonCreatureForOnlyLocalPlayer()
{
if( IsSetTarget() )
{
AR_HANDLE hTarget = m_pTarget->GetArID();
if( hTarget &&
( m_CreatureSlotMgr.IsExistSummonedCreature(hTarget) ||
m_PlayerInfoMgr.IsLocalPlayer(hTarget) ) )
{
return hTarget;
}
}
return NULL;
}
/// 2011.03.30 - prodongi
void SUITargetStateWnd::setReiterationCount(SStateSlot const* state, KUIControlStatic* control)
{
if (!state)
{
control->SetShow(false);
return ;
}
StateInfoEx const* info = GetTenacityDB().GetTenacityData(state->GetStateCode());
if (info && 0 < info->reiteration_count)
{
int level = min(state->GetStateLevel(), MAX_REITERATION_LEVEL);
control->SetShow(true);
control->SetCaption(CStringUtil::StringFormat("<font:font_01><out><#ffffff><size:8><vcenter><right>%d", level).c_str());
}
else
{
control->SetShow(false);
}
}