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

1140 lines
36 KiB
C++

#include "stdafx.h"
#include "KUITabControl.h"
#include "KUIControlButton.h"
#include "KUIControlStatic.h"
#include "KUIControlScroll.h"
#include "SGameManager.h"
//#include "SGameMessageUI.h"
#include "SUICreatureSkillWnd.h"
#include "SUIDisplayInfo.h"
#include "SUILazyTooltip.h"
#include "SSkillDB.h"
#include "SStringDB.h"
#include "SCreatureDB.h"
#include "SSummonSlotMgr.h"
#include "SSkillSlot.h"
#include "ErrorCode/ErrorCode.h"
#include "SUISysMsgDefine.h"
#include "SInventoryMgr.h"
#include "SLog.h"
namespace nsUICreatureSkillFundWnd
{
const int c_nDelta( 38 ); // 늘어나는 단위
const int c_nIconSelectDelta( 4 ); // 아이콘 선택 static 표시 위치 delta
const int c_nMAXLine( 7 );
const char* c_szTAB( "creature_skillfund_tab" );
const KColor g_enabledSkillIconColor( 0xffffffff );
const KColor g_disabledSkillIconColor( 0xff404040 );
enum
{ // 탭 타입
TAB_ACTIVE = 0,
TAB_PASSIVE,
};
};
using namespace rp;
using namespace nsUICreatureSkillFundWnd;
//-----------------------------------------------------------------------------------------------------------------
// 생성자
//-----------------------------------------------------------------------------------------------------------------
SUICreatureSkillFundWnd::SUICreatureSkillFundWnd( SGameManager* pGameManager, SUIDisplayInfo* pDisplayInfo )
: SUIWnd( pGameManager )
, m_pDisplayInfo( pDisplayInfo )
, m_nTabType( NULL )
, m_nGrade( NULL )
, m_nMaxLine( c_nMAXLine )
, m_nScrollPos( NULL )
{
}
//-----------------------------------------------------------------------------------------------------------------
// 파괴자
//-----------------------------------------------------------------------------------------------------------------
SUICreatureSkillFundWnd::~SUICreatureSkillFundWnd()
{
ClearSkillList();
}
//-----------------------------------------------------------------------------------------------------------------
// 컨트롤 초기화
//-----------------------------------------------------------------------------------------------------------------
bool SUICreatureSkillFundWnd::InitControls( KPoint kPos )
{
// 탭 만들기
KUISimpleTabControl* pTabControl = dynamicCast<KUISimpleTabControl*>(GetChild(c_szTAB));
if( pTabControl )
{
pTabControl->SetTabProperty( 0, false, 2 );
pTabControl->AddTabItem( S(6236)/*"<size:10>액티브"*/, S(6305)/*"액티브 스킬"*/ );
pTabControl->AddTabItem( S(6256)/*"<size:10>패시브"*/, S(6306)/*"패시브 스킬"*/ );
}
CreateControls();
return SUIWnd::InitControls(kPos);
}
//-----------------------------------------------------------------------------------------------------------------
// 데이터 초기화
//-----------------------------------------------------------------------------------------------------------------
bool SUICreatureSkillFundWnd::InitData( bool bReload )
{
if( bReload )
ClearSkillList();
m_nScrollPos = 0;
m_nTabType = 0;
m_nMaxLine = c_nMAXLine;
DisableAllSlot();
HideSelectBar();
return SUIWnd::InitData(bReload);
}
//-----------------------------------------------------------------------------------------------------------------
// 메시지 처리
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::PumpUpMessage( LPCSTR lpszControlID, DWORD nMessage, DWORD lparam, DWORD wparam )
{
switch(nMessage)
{
case KUI_MESSAGE::KBUTTON_CLICK:
{
m_pGameManager->StartSound( "ui_click_jlv01.wav" );
string str;
for( int i = 0; i < m_nMaxLine; i++ )
{
str = CStringUtil::StringFormat( "creature_skillfund_up%02d", i );
if( ::_stricmp( lpszControlID, str.c_str() ) == 0 )
{
ShowSelectBar(i, m_nGrade);
SkillUP(i, m_nGrade);
break;
}
}
}
break;
case KUI_MESSAGE::KICON_CLICK:
{
m_pGameManager->StartSound( "ui_button_click.wav" );
string str;
for( int i = 0; i < m_nMaxLine; i++ )
{
str = CStringUtil::StringFormat( "creature_skillfund_icon%02d", i );
if( ::_stricmp( lpszControlID, str.c_str() ) == 0 ) // 선택처리
{
ShowSelectBar(i, m_nGrade);
break;
}
}
}
break;
case KUI_MESSAGE::KSCROLL_SELECT: // 스크롤 선택
{
int nPos = (int)lparam;
nPos = max( nPos, 0 );
m_nScrollPos = nPos;
RefreshSkillSlot(m_nGrade, nPos);
}
break;
case KUI_MESSAGE::KTAB_SELECT: // 탭 변경
{
SelectTab();
InitScrollPosition();
m_pGameManager->PostMsgAtDynamic( new SIMSG_UI_CREATURE_FUND_TAB_UPDATE( m_nTabType, m_nGrade ) );
}
break;
}
SUIWnd::PumpUpMessage( lpszControlID, nMessage, lparam, wparam );
}
//-----------------------------------------------------------------------------------------------------------------
// 정적 메시지 처리
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::ProcMsgAtStatic( SGameMessage* pMsg )
{
switch(pMsg->nType)
{
case IMSG_UI_MOVE:
{
SIMSG_UI_MOVE* pMoveMsg = ( SIMSG_UI_MOVE* )pMsg;
MovePos( pMoveMsg->m_nX, pMoveMsg->m_nY-GetRect().GetHeight() );
pMsg->bUse = true;
}
break;
case IMSG_UI_SEND_DATA:
{
SIMSG_UI_SEND_DATA* msg = (SIMSG_UI_SEND_DATA*)pMsg;
if (msg->m_strString == "refresh")
{
if (IsShow())
UpdateSkillList(m_nTabType, m_nGrade);
}
pMsg->bUse = true;
}
break;
case IMSG_UI_CREATURE_FUND_TAB_UPDATE:
{
if( IsShow() )
{
SIMSG_UI_CREATURE_FUND_TAB_UPDATE* pSkillMsg = ( SIMSG_UI_CREATURE_FUND_TAB_UPDATE* )pMsg;
UpdateSkillList( pSkillMsg->m_nTabType, pSkillMsg->m_nGradeTab );
#ifdef _KUI_INVALIDATION
InvalidateWnd();
#endif
}
pMsg->bUse = true;
}
break;
case MSG_ADDED_SKILL_LIST:
case MSG_SKILL_LIST:
case MSG_LEVEL_UPDATE:
{
RefreshSkillInfo();
RefreshScrollbar( m_nGrade );
RefreshSkillSlot( m_nGrade, m_nScrollPos );
pMsg->bUse = true;
#ifdef _KUI_INVALIDATION
InvalidateWnd();
#endif
}
break;
case MSG_EXP_UPDATE:
{
RefreshSkillSlot( m_nGrade, m_nScrollPos );
pMsg->bUse = true;
#ifdef _KUI_INVALIDATION
InvalidateWnd();
#endif
}
break;
case MSG_PROPERTY:
{
SMSG_PROPERTY* pPropertyMsg = (SMSG_PROPERTY*)pMsg;
switch( pPropertyMsg->nPropertyType )
{
case SMSG_PROPERTY::PROPERTY_LEVEL:
case SMSG_PROPERTY::PROPERTY_EXP:
case SMSG_PROPERTY::PROPERTY_JP:
{
RefreshSkillInfo();
RefreshScrollbar( m_nGrade );
RefreshSkillSlot( m_nGrade, m_nScrollPos );
#ifdef _KUI_INVALIDATION
InvalidateWnd();
#endif
}
break;
}
pMsg->bUse = true;
}
break;
case MSG_RESULT:
{
SMSG_RESULT* pMsgResult = (SMSG_RESULT*)pMsg;
switch(pMsgResult->request_msg_id)
{
case TM_CS_JOB_LEVEL_UP:
{
if( pMsgResult->result == RESULT_SUCCESS )
{
RefreshSkillInfo();
RefreshScrollbar( m_nGrade );
RefreshSkillSlot( m_nGrade, m_nScrollPos );
#ifdef _KUI_INVALIDATION
InvalidateWnd();
#endif
}
}
break;
}
pMsg->bUse = true;
}
break;
}
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬투자윈도우
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::CreateControls()
{
RECT rc;
rc.left = 0; rc.top = c_nDelta; rc.right = 0; rc.bottom = c_nDelta;
KUIWnd* pIconCtr(NULL);
pIconCtr = GetChild( "creature_skillfund_icon00" );
if( pIconCtr )
pIconCtr->SetCorrectionRect( KRect( 0, 0, 130, 0 ) );
for( int i = 0; i < m_nMaxLine-1; i++ )
{
pIconCtr = CopyControl(
CStringUtil::StringFormat( "creature_skillfund_icon%02d" , i ).c_str(),
CStringUtil::StringFormat( "creature_skillfund_icon%02d" , i+1 ).c_str(),
rc );
CopyControl(
CStringUtil::StringFormat( "creature_skillfund_up%02d" , i ).c_str(),
CStringUtil::StringFormat( "creature_skillfund_up%02d" , i+1 ).c_str(),
rc );
CopyControl(
CStringUtil::StringFormat( "creature_skillfund_01info%02d" , i ).c_str(),
CStringUtil::StringFormat( "creature_skillfund_01info%02d" , i+1 ).c_str(),
rc );
CopyControl(
CStringUtil::StringFormat( "creature_skillfund_01info%02d_value", i ).c_str(),
CStringUtil::StringFormat( "creature_skillfund_01info%02d_value", i+1 ).c_str(),
rc );
CopyControl(
CStringUtil::StringFormat( "creature_skillfund_02info%02d" , i ).c_str(),
CStringUtil::StringFormat( "creature_skillfund_02info%02d" , i+1 ).c_str(),
rc );
CopyControl(
CStringUtil::StringFormat( "static_use_jp%02d" , i ).c_str(),
CStringUtil::StringFormat( "static_use_jp%02d" , i+1 ).c_str(),
rc );
CopyControl(
CStringUtil::StringFormat( "creature_skillfund_jp%02d" , i ).c_str(),
CStringUtil::StringFormat( "creature_skillfund_jp%02d" , i+1 ).c_str(),
rc );
CopyControl(
CStringUtil::StringFormat( "static_use_mp%02d" , i ).c_str(),
CStringUtil::StringFormat( "static_use_mp%02d" , i+1 ).c_str(),
rc );
CopyControl(
CStringUtil::StringFormat( "static_use_mp_value%02d" , i ).c_str(),
CStringUtil::StringFormat( "static_use_mp_value%02d" , i+1 ).c_str(),
rc );
if( pIconCtr )
pIconCtr->SetCorrectionRect( KRect( 0, 0, 130, 0 ) );
}
for( int i = 0; i < m_nMaxLine; i++ )
{
SetChildCaption( CStringUtil::StringFormat( "creature_skillfund_up%02d", i ).c_str(), GetStringDB().GetString( STRING_UP ) );
}
SetChildAsTop( "icon_select_over" );
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 리스트 얻기
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::GetSkillList( int nGrade, bool bPassive, vector<const SkillTreeEx>*& pSkillTreeList )
{
switch( nGrade )
{
case 0: !bPassive ? pSkillTreeList = &m_vActiveSkillTreeList_1 : pSkillTreeList = &m_vPassiveSkillTreeList_1; break;
case 1: !bPassive ? pSkillTreeList = &m_vActiveSkillTreeList_2 : pSkillTreeList = &m_vPassiveSkillTreeList_2; break;
case 2: !bPassive ? pSkillTreeList = &m_vActiveSkillTreeList_3 : pSkillTreeList = &m_vPassiveSkillTreeList_3; break;
}
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 리스트 갱신
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::UpdateSkillList( int nTabType, int nGrade )
{
m_nTabType = nTabType;
m_nScrollPos = 0;
m_nGrade = nGrade;
KUISimpleTabControl* pTab( dynamicCast<KUISimpleTabControl*>(GetChild(c_szTAB)) );
if( pTab )
pTab->SetSelectedItem( (DWORD)nTabType );
ClearSkillList();
RefreshSkillInfo();
RefreshScrollbar( nGrade );
RefreshSkillSlot( nGrade, m_nScrollPos );
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 리스트 비우기
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::ClearSkillList()
{
m_vActiveSkillTreeList.clear();
m_vActiveSkillTreeList_1.clear();
m_vActiveSkillTreeList_2.clear();
m_vActiveSkillTreeList_3.clear();
m_vPassiveSkillTreeList.clear();
m_vPassiveSkillTreeList_1.clear();
m_vPassiveSkillTreeList_2.clear();
m_vPassiveSkillTreeList_3.clear();
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 인가?
//-----------------------------------------------------------------------------------------------------------------
bool SUICreatureSkillFundWnd::IsSkill( int nIndex, int nGrade )
{
vector<const SkillTreeEx>* pSkillTreeList(NULL);
GetSkillList( nGrade, !IsActiveTab(), pSkillTreeList );
if( pSkillTreeList && nIndex >= 0 && nIndex < pSkillTreeList->size() )
return true;
return false;
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 정보 갱신
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::RefreshSkillInfo()
{
const SCreatureInfo* creatureInfo( m_CreatureSlotMgr.GetCreatureInfo( m_CreatureSlotMgr.GetSelectedCreature() ) );
if( creatureInfo == NULL )
return ;
// update tab by evolution count
UpdateTab( GetEvolution( *creatureInfo ) );
ClearSkillList();
// 진화 이전 크리쳐 ID 도 얻어 와서, 배우지 않은 스킬 모두를 표시 한다.
vector<int> creatureIDs;
GetCreatureDB().GetEvolveID( creatureInfo->GetID(), creatureIDs );
if( creatureIDs.empty() )
return ;
// 2010.05.18 크리쳐 슬롯 정보- prodongi
SInventorySlot* slot( m_InventoryMgr.GetItemInfo(m_CreatureSlotMgr.GetSelectedCreatureCard()) );
int enhance = (slot) ? slot->GetEnhance() : 0;
for( unsigned int grade = 0; grade < creatureIDs.size(); ++grade )
{
// 왜 여기서는 vector에 SkillTree를 보관하고 아래서는 주소값을 보관하는 것인가???
// SkillTreeData가 어차피 DB상에서 얻어오는 것이기 때문에 변화할 일은 없겠지만
// 서로 저장하는 방식이 다르다는 것이 옳은 것인가?? OTL
int creatureID = creatureIDs[ grade ];
const _SUMMON_INFO_FILE* pSummonDB = GetCreatureDB().GetCreatureData( creatureID );
if( pSummonDB == NULL )
continue;
for( int i = 0; i < _countof( pSummonDB->skill_tree_id ); ++i )
{
if( pSummonDB->skill_tree_id[i] == 0 )
continue;
const vector< SkillTreeEx >* creatureSkillTree = GetSkillTreeDB().GetSkillTreeData( pSummonDB->skill_tree_id[i] );
if( !creatureSkillTree )
continue;
vector< SkillTreeEx >::const_iterator it = creatureSkillTree->begin(),
itEnd = creatureSkillTree->end();
while( it != itEnd )
{
SkillTreeEx stSkillTree( (*it) );
// DB상에 들어있는 데이터는 크리처가 5렙단위로 특정 스킬을 몇렙까지
// 학습할 수 있는가의 데이터이다.
// ex) tree.jop_lv = 5 && tree.skill_id = 1 && tree.max_skill_lv 이라는 데이터가 있다면....
// 잡렙이 5이상이라면 1이라는 스킬을 max_skill_lv만큼 올릴 수 있다.
// tree.jop_lv = 10 && tree.skill_id = 1 && tree.max_skill_lv 이 또 정의 되있다면...
// 앞에서 잡렙 5렙일때의 조건은 무시해버려야한다 잡렙이 10일때의 max_skill_lv이
// 기준이 된다.
// 크리처가 기본형렙 50, 성장형 35렙이라면....
// 스킬트리를 돌면서 잡렙요구 35렙이하의 스킬트리정보를 리스트에 저장한다.
// 반복문을 돌다가 동일한 아이디의 스킬이 나온다면 무조건 max_skill_lv높은
// 스킬트리 정보를 저장한다.
// 여기서 저장해야 할 스킬트리 정보는 내가 학습가능한 스킬트리 정보이다.
// 아래 컨트롤들을 업데이트할때 스킬트리 정보를 뽑아서 배운 스킬이라면
// 현재 학습한 스킬렙+1을 학습 안한것은 1로 컨트롤에 업데이트한다.
if( stSkillTree.skill_tree_id != pSummonDB->skill_tree_id[i] )
{
it++;
continue;
}
int nSkillID = 0;
if( stSkillTree.bIsRandomSkill )
{
const SUMMON_RANDOM_SKILL_ID* const pRandomSkillIDList = GetSummonRandomSkillDB().GetRandomSkillIDList( stSkillTree.skill_group_id );
if( NULL == pRandomSkillIDList )
{
SDEBUGLOG( "[SUICreatureSkillFundWnd] 랜덤 스킬 ID 리스트 정보를 얻어 올 수 없습니다. - 그룹 ID [ %u ]", stSkillTree.skill_group_id );
assert( NULL );
continue;
}
bool bIsFind( false );
for( UINT nCount = 0; nCount < pRandomSkillIDList->vecSkillID.size(); nCount++ )
{
if( m_CreatureSkillSlotMgr.IsExistSkill( pRandomSkillIDList->vecSkillID[nCount], m_CreatureSlotMgr.GetSelectedCreature() ) )
{
int nChangedSkillID( pRandomSkillIDList->vecSkillID[nCount] );
stSkillTree.nChangedSkillID = nChangedSkillID;
nSkillID = nChangedSkillID;
bIsFind = true;
}
}
// 랜덤 스킬인데 스킬 리스트 중에 없다면, 아직 배우지 않은 스킬이다.
if( false == bIsFind )
nSkillID = stSkillTree.skill_id;
}
else
nSkillID = stSkillTree.skill_id;
if( NULL == nSkillID )
{
SDEBUGLOG( "[SUICreatureSkillFundWnd] 스킬 ID가 유효하지 않습니다. - 스킬트리 ID [ %d ]", stSkillTree.skill_tree_id );
assert( NULL );
it++;
continue;
}
SkillBaseEx* pSkillData( GetSkillDB().GetSkillData( nSkillID ) );
if( NULL == pSkillData )
{
SDEBUGLOG( "[SUICreatureSkillFundWnd] 스킬 데이터를 얻어 올 수 없습니다. - 스킬트리 ID [ %d ]", stSkillTree.skill_tree_id );
assert( NULL );
++it;
continue;
}
// 스킬을 배우기위한 크리처의 필요 잡렙을 충족하지 못하여 continue;
if( creatureInfo->GetEvolLevel( grade ) < stSkillTree.jop_lv )
{
++it;
continue;
}
// 이미 배운 스킬인데 배운 레벨이 더 높으니 continue;
if( !m_CreatureSkillSlotMgr.AbleLearnSkill( nSkillID,
stSkillTree.max_skill_lv,
m_CreatureSlotMgr.GetSelectedCreature() ) )
{
++it;
continue;
}
// 2010.05.18 강화 조건 검색 - prodongi
// AziaMafia Fix enhance Max stSkillTree.cenhance_max
//if (enhance < stSkillTree.cenhance_min || enhance > stSkillTree.cenhance_max)
if (enhance < stSkillTree.cenhance_min || enhance > 25)
{
++it;
continue;
}
vector<const SkillTreeEx>* activeList = 0;
vector<const SkillTreeEx>* passiveList = 0;
// ChangeSkill() : 이미 스킬이 등록되있는데
// 새로 등록하려는 트리정보가 스킬상승 레벨이 더 높다면 change
if( !pSkillData->IsPassive() )
{
GetSkillList( grade, false, activeList );
if( !ChangeSkill( stSkillTree, m_vActiveSkillTreeList ) )
{
m_vActiveSkillTreeList.push_back( stSkillTree );
}
if( activeList )
activeList->push_back( stSkillTree );
}
else
{
GetSkillList( grade, true, passiveList );
if( !ChangeSkill( stSkillTree, m_vPassiveSkillTreeList ) )
{
m_vPassiveSkillTreeList.push_back( stSkillTree );
}
if( passiveList )
passiveList->push_back( stSkillTree );
}
++it;
}
}
}
creatureIDs.clear();
RefreshSkillSlot( m_nGrade );
RefreshScrollbar( m_nGrade );
}
//-----------------------------------------------------------------------------------------------------------------
// 진화 단계 얻기
//-----------------------------------------------------------------------------------------------------------------
int SUICreatureSkillFundWnd::GetEvolution( const SCreatureInfo& creatureInfo )
{
int evolution( NULL ),
evolutionLv( NULL );
for( int i = 0; i < SCreatureInfo::MAX_CREATURE_EVOLUTION; ++i )
{
evolutionLv = creatureInfo.GetEvolLevel( i );
if( evolutionLv != -1 && evolutionLv )
++evolution;
else
break;
}
return evolution;
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 변경
//-----------------------------------------------------------------------------------------------------------------
bool SUICreatureSkillFundWnd::ChangeSkill( const SkillTreeEx& rTree, vector<const SkillTreeEx>& rcmpSkillList )
{
vector<const SkillTreeEx>::iterator It = rcmpSkillList.begin();
while( It != rcmpSkillList.end() )
{
const SkillTreeEx stSkillTree( (*It) );
if( stSkillTree.skill_id == rTree.skill_id )
{
if( stSkillTree.max_skill_lv > rTree.max_skill_lv )
{
rcmpSkillList.erase( It );
rcmpSkillList.push_back( stSkillTree );
}
return true;
}
++It;
}
return false;
}
//-----------------------------------------------------------------------------------------------------------------
// 트리 체크
//-----------------------------------------------------------------------------------------------------------------
bool SUICreatureSkillFundWnd::IsTreeCheck( const vector<SkillTreeEx>& vSkill_list, int nSkillID )
{
vector<SkillTreeEx>::const_iterator iter = vSkill_list.begin();
for( ; iter != vSkill_list.end(); ++iter )
{
if( (*iter).skill_id == nSkillID )
return true;
}
return false;
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 아이디 얻기
//-----------------------------------------------------------------------------------------------------------------
bool SUICreatureSkillFundWnd::GetSkillID( int& outId, int& outLv, int index, int grade )
{
vector<const SkillTreeEx>* pActiveSkillTreeList( NULL );
GetSkillList( grade, !IsActiveTab(), pActiveSkillTreeList );
if( !pActiveSkillTreeList )
return false;
if( index >= 0 && index < pActiveSkillTreeList->size() )
{
const SkillTreeEx stSkillTree( pActiveSkillTreeList->at( index ) );
if( true == stSkillTree.bIsRandomSkill && // 랜덤 스킬이고
NULL != stSkillTree.nChangedSkillID ) // 바뀐 스킬 아이디가 있다면 (랜덤으로 결정 된)
{
outId = stSkillTree.nChangedSkillID; // 바뀐 스킬 아이디
}
else
{
outId = stSkillTree.skill_id;
}
outLv = m_CreatureSkillSlotMgr.GetBaseSkillLevel( outId, m_CreatureSlotMgr.GetSelectedCreature() );
return true;
}
return false;
}
//-----------------------------------------------------------------------------------------------------------------
// 습득 가능 한 스킬 정보 얻기
//-----------------------------------------------------------------------------------------------------------------
bool SUICreatureSkillFundWnd::GetLearnableSkillIDnLv( int& outId, int& outoriginskilliD, int& outLearnableLv, int index, int grade )
{
vector<const SkillTreeEx>* pActiveSkillTreeList( NULL );
GetSkillList( grade, !IsActiveTab(), pActiveSkillTreeList );
if( !pActiveSkillTreeList )
return false;
if( index >= 0 && index < pActiveSkillTreeList->size() )
{
const SkillTreeEx stSkillTree( pActiveSkillTreeList->at( index ) );
// 기존 스킬이라면, 기존 대로 outId에 스킬 ID를 넣는다.
// 랜덤 스킬이라면, 기존의 결정되지 않은 스킬 ID (? 스킬 ID)를 outoriginskilliD에 넣어주고
// 랜덤 스킬로 인해 바뀐 Skill ID 를 outId에 넣는다.
if( true == stSkillTree.bIsRandomSkill && // 랜덤 스킬이고
NULL != stSkillTree.nChangedSkillID ) // 바뀐 스킬 아이디가 있다면 (랜덤으로 결정 된)
{
outId = stSkillTree.nChangedSkillID; // 바뀐 스킬 아이디
outoriginskilliD = stSkillTree.skill_id; // 바뀌기 전의 스킬 아이디
}
else
{
outId = stSkillTree.skill_id;
outoriginskilliD = 0;
}
outLearnableLv = m_CreatureSkillSlotMgr.GetBaseSkillLevel( outId, m_CreatureSlotMgr.GetSelectedCreature() ) + 1;
if( outLearnableLv > stSkillTree.max_skill_lv )
return false;
return m_CreatureSkillSlotMgr.AbleLearnSkill( outId, outLearnableLv, m_CreatureSlotMgr.GetSelectedCreature() );
}
return false;
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 슬롯 갱신
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::RefreshSkillSlot( int nGrade, int nRange )
{
HideSelectBar();
DisableAllSlot( false );
vector<const SkillTreeEx>* pActiveSkillTreeList( NULL );
GetSkillList( nGrade, !IsActiveTab(), pActiveSkillTreeList );
if( !pActiveSkillTreeList )
return;
int nStart = nRange;
int nActiveSize = pActiveSkillTreeList->size();
for( int index = 0; index < m_nMaxLine; index++, nStart++ )
{
if( nStart >= 0 && nStart < nActiveSize )
{
//gmpbigsun(20130708, #26906 ) : 이게 뭔가... 지역변수를 넘기고 자빠볐?..
//SkillTreeEx stSkillTree( pActiveSkillTreeList->at( nStart ) );
SkillTreeEx* pSkillTree = &pActiveSkillTreeList->at( nStart );
DisableSlot( index, true );
SetSkillData( pSkillTree, index, true );
}
}
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬
//-----------------------------------------------------------------------------------------------------------------
bool SUICreatureSkillFundWnd::IsPrecedentSkillSatisfied( const SkillTreeEx& tree )
{
bool bPrecedentSkillSatisfied = false;
for( int index = 0; index < 3; index++ )
{
if( tree.need_skill_id[ index ] == 0 )
bPrecedentSkillSatisfied = true;
else
{
if( m_CreatureSkillSlotMgr.GetBaseSkillLevel( tree.need_skill_id[ index ], m_CreatureSlotMgr.GetSelectedCreature() )
>= tree.need_skill_lv[ index ] )
{
bPrecedentSkillSatisfied = true;
}
else
{
bPrecedentSkillSatisfied = false;
break;
}
}
}
return bPrecedentSkillSatisfied;
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 데이터 설정
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::SetSkillData( const SkillTreeEx* pSkillTree, int nIndex, bool bShow )
{
if( pSkillTree == NULL )
return;
int nSkillID( NULL );
if( true == pSkillTree->bIsRandomSkill && // 랜덤 스킬이고
NULL != pSkillTree->nChangedSkillID ) // 바뀐 스킬 아이디가 있다면
{
nSkillID = pSkillTree->nChangedSkillID;
}
else
nSkillID = pSkillTree->skill_id;
if( NULL == nSkillID )
{
SDEBUGLOG( "[SUICreatureSkillFundWnd] 스킬 ID가 유효하지 않습니다. - 스킬트리 ID [ %d ]", pSkillTree->skill_tree_id );
assert( NULL );
return;
}
SkillBaseEx* skillData( GetSkillDB().GetSkillData( nSkillID ) );
if( skillData == NULL )
{
SDEBUGLOG( "[SUICreatureSkillFundWnd] 스킬 데이터를 얻어 올 수 없습니다. - 스킬트리 ID [ %d ]", pSkillTree->skill_tree_id );
assert( NULL );
return;
}
// 존재하지 않는 스킬이라면
// 필요스킬 1, 2, 3 이 이미 있고
// 필요스킬[0] 이 필요 없는 경우 는 무조건 저장
bool bPrecedentSkillSatisfied = false;
if( m_CreatureSkillSlotMgr.GetBaseSkillLevel( nSkillID, m_CreatureSlotMgr.GetSelectedCreature() ) >= ( pSkillTree->min_skill_lv - 1 ) &&
IsPrecedentSkillSatisfied( *pSkillTree ) ) // sonador 7.0.30 크리처 스킬 습득 프로세스 오류 수정
{
bPrecedentSkillSatisfied = true;
}
// 스킬 아이콘 =============
KUIControlIconStatic* pSkillIcon = dynamicCast<KUIControlIconStatic*>(GetChild(CStringUtil::StringFormat( "creature_skillfund_icon%02d", nIndex ).c_str() ));
if( pSkillIcon && bShow )
{
pSkillIcon->SetIcon( c_szDEF_SPR_NAME, skillData->icon_file_name );
if( bPrecedentSkillSatisfied )
{
pSkillIcon->SetIcon( c_szDEF_SPR_NAME, skillData->icon_file_name );
pSkillIcon->SetIconColor( g_enabledSkillIconColor );
}
else
{
pSkillIcon->SetIconColor( g_disabledSkillIconColor );
}
}
// 스킬 레벨 표시 =============
int nSkillLevel( NULL );
if( m_CreatureSkillSlotMgr.IsExistSkill( nSkillID, m_CreatureSlotMgr.GetSelectedCreature() ) )
{
// 스킬이 있는 경우 보유스킬레벨 + 1 과 max 중 큰것
nSkillLevel = max( m_CreatureSkillSlotMgr.GetBaseSkillLevel( nSkillID, m_CreatureSlotMgr.GetSelectedCreature() ) + 1, pSkillTree->min_skill_lv );
}
else
{
// 스킬이 없는 경우 min
nSkillLevel = pSkillTree->min_skill_lv;
}
if( pSkillIcon && bShow )
{
// sonador 1.2.5 Lazy Tooltip 구현 // sonador #2.1.2.4.3 팻 조작 UI 연동
pSkillIcon->SetLazyTooltip( new KLazyCreatureSkillFundTooltip(
*m_pDisplayInfo, pSkillTree, bPrecedentSkillSatisfied, IsActiveTab(), nSkillID, nSkillLevel, true ) );
}
// 필요 MP =============
SetChildCaption(
CStringUtil::StringFormat( "static_use_mp_value%02d", nIndex ).c_str(),
CStringUtil::StringFormat( "%s%d", S(6425), skillData->GetCostMP(nSkillLevel) ).c_str()
);
// 필요 JP =============
SetChildShow(
CStringUtil::StringFormat( "creature_skillfund_jp%02d", nIndex ).c_str(),
bPrecedentSkillSatisfied
);
SetChildCaption(
CStringUtil::StringFormat( "creature_skillfund_jp%02d", nIndex ).c_str(),
CStringUtil::StringFormat( "%s%d", S(6425), skillData->GetNeedJopPoint(nSkillLevel) ).c_str()
);
// 스킬 설명 ===========
if( bPrecedentSkillSatisfied )
{
SetChildCaption(
CStringUtil::StringFormat( "creature_skillfund_01info%02d_value", nIndex ).c_str(),
CStringUtil::StringFormat( "%s%d", S(6425), nSkillLevel ).c_str()
);
SetChildCaption(
CStringUtil::StringFormat( "creature_skillfund_02info%02d", nIndex ).c_str(),
GetStringDB().GetString( skillData->GetNameID() )
);
}
else
{
SetChildCaption(
CStringUtil::StringFormat( "creature_skillfund_01info%02d_value", nIndex ).c_str(),
CStringUtil::StringFormat( "%s%d", S(6425), nSkillLevel).c_str()
);
SetChildCaption(
CStringUtil::StringFormat( "creature_skillfund_02info%02d", nIndex ).c_str(),
CStringUtil::StringFormat(
"<#ff0000>%s",
GetStringDB().GetString( skillData->GetNameID() )
).c_str()
);
}
// 내 jp 가 필요 jp 보다 많으면 업버튼 활성화
KUIControlButton* pFundButton = dynamicCast<KUIControlButton*>(GetChild(CStringUtil::StringFormat( "creature_skillfund_up%02d", nIndex ).c_str() ));
if( pFundButton )
{
const SCreatureInfo* pInfo = m_CreatureSlotMgr.GetCreatureInfo(
m_CreatureSlotMgr.GetSelectedCreature() );
if( pInfo == NULL ) return;
if( pInfo->GetJP() >= skillData->GetNeedJopPoint( nSkillLevel ) && bPrecedentSkillSatisfied )
pFundButton->Enable();
else
pFundButton->Disable();
}
}
//-----------------------------------------------------------------------------------------------------------------
// 스킬 슬롯 비 활성화
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::DisableSlot( int nMode, bool bShow )
{
KUIControlIconStatic* pIcon = dynamicCast<KUIControlIconStatic*>(GetChild( CStringUtil::StringFormat( "creature_skillfund_icon%02d", nMode ).c_str() ));
if( pIcon )
{
pIcon->SetIcon( c_szDEF_SPR_NAME, "static_common_itemslot" );
pIcon->SetIconColor( g_enabledSkillIconColor );
pIcon->SetLazyTooltip();
pIcon->SetShow(true);
}
SetChildShow( CStringUtil::StringFormat( "creature_skillfund_up%02d" , nMode ).c_str(), bShow);
SetChildShow( CStringUtil::StringFormat( "creature_skillfund_01info%02d" , nMode ).c_str(), bShow);
SetChildShow( CStringUtil::StringFormat( "creature_skillfund_01info%02d_value", nMode ).c_str(), bShow);
SetChildShow( CStringUtil::StringFormat( "static_use_jp%02d" , nMode ).c_str(), bShow);
SetChildShow( CStringUtil::StringFormat( "creature_skillfund_02info%02d" , nMode ).c_str(), bShow);
SetChildShow( CStringUtil::StringFormat( "creature_skillfund_jp%02d" , nMode ).c_str(), bShow);
SetChildShow( CStringUtil::StringFormat( "static_use_mp%02d" , nMode ).c_str(), bShow);
SetChildShow( CStringUtil::StringFormat( "static_use_mp_value%02d" , nMode ).c_str(), bShow);
}
//-----------------------------------------------------------------------------------------------------------------
// 모든 스킬 슬롯 비 활성화
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::DisableAllSlot( bool bShow )
{
for( int index = 0; index < m_nMaxLine; index++ )
{
DisableSlot( index, bShow );
}
}
//-----------------------------------------------------------------------------------------------------------------
// 스크롤 바 갱신
//-----------------------------------------------------------------------------------------------------------------
void SUICreatureSkillFundWnd::RefreshScrollbar( int nGrade )
{
vector<const SkillTreeEx>* pActiveSkillTreeList( NULL );
GetSkillList( nGrade, !IsActiveTab(), pActiveSkillTreeList );
if( !pActiveSkillTreeList )
return;
int nCurCount( pActiveSkillTreeList->size() );
int nScrollRange( max(nCurCount - m_nMaxLine, 0) );
KUIControlVScroll* pScrollBar( dynamicCast<KUIControlVScroll*>(GetChild( "creature_skillfund_scroll" )) );
if( NULL != pScrollBar )
{
pScrollBar->SetMaxRange( DWORD(nScrollRange)+1 );
m_nScrollPos = pScrollBar->GetPosition();
}
}
/////////////////////////////////////////////
// 스킬투자 스킬업
/////////////////////////////////////////////
void SUICreatureSkillFundWnd::SkillUP( int nIndex, int nGrade )
{
if( !IsSkill(m_nScrollPos+nIndex, nGrade) ) return;
int nSkillID( -1 );
int nOriginSkillID( -1 );
int nSkillLv( -1 );
if( GetLearnableSkillIDnLv( nSkillID, nOriginSkillID, nSkillLv, m_nScrollPos + nIndex, nGrade ) )
{
SIMSG_UI_ACT_LEARN_SKILL msg;
msg.handle = m_CreatureSlotMgr.GetSelectedCreature();
msg.nSkillID = nSkillID;
msg.nOriginSkillID = nOriginSkillID;
msg.nSkillLv = nSkillLv;
m_pGameManager->ProcMsgAtStatic(&msg);
}
}
/////////////////////////////////////////////
// 스킬투자 선택바
/////////////////////////////////////////////
void SUICreatureSkillFundWnd::ShowSelectBar( int nIndex, int nGrade )
{
HideSelectBar();
if( IsSkill(m_nScrollPos+nIndex, nGrade) )
{
// 아이콘 선택 보이기
KUIWnd* pIcon = GetChild( CStringUtil::StringFormat( "creature_skillfund_icon%02d", nIndex ).c_str() );
if( pIcon )
{
KUIWnd* pSelect = GetChild( "static_select_over" );
KUIWnd* pBGWnd = GetChild( "static_select_over_back" );
KUIWnd* pIconOverWnd = GetChild( "icon_select_over" );
if( pSelect )
{
pSelect->MovePos( pIcon->GetRect().left-39, pIcon->GetRect().top-c_nIconSelectDelta );
pSelect->SetShow(true);
}
if( pBGWnd ) { pBGWnd->MovePos( pIcon->GetRect().left-39 , pIcon->GetRect().top-c_nIconSelectDelta ); pBGWnd->SetShow(true); }
if( pIconOverWnd ) { pIconOverWnd->MovePos( pIcon->GetRect().left, pIcon->GetRect().top ); pIconOverWnd->SetShow(true); }
}
}
}
void SUICreatureSkillFundWnd::HideSelectBar()
{
KUIWnd* pWnd = NULL;
// 아이콘 선택 감추기
pWnd = GetChild( "static_select_over" );
if( pWnd ) pWnd->SetShow(false);
pWnd = GetChild( "static_select_over_back" );
if( pWnd ) pWnd->SetShow(false);
pWnd = GetChild( "icon_select_over" );
if( pWnd ) pWnd->SetShow(false);
}
/////////////////////////////////////////////////////
// 탭
/////////////////////////////////////////////////////
bool SUICreatureSkillFundWnd::IsActiveTab() const
{
return ( m_nTabType == TAB_ACTIVE );
}
void SUICreatureSkillFundWnd::SelectTab()
{
KUISimpleTabControl* pTab = dynamicCast<KUISimpleTabControl*>(GetChild(c_szTAB));
if( pTab == NULL ) return;
m_nTabType = pTab->GetSelectedItem();
pTab = dynamicCast<KUISimpleTabControl*>(GetChild("creature_skillfund_tab2"));
if( pTab == NULL ) return;
m_nGrade = pTab->GetSelectedItem();
RefreshScrollbar( m_nGrade );
RefreshSkillSlot( m_nGrade, m_nScrollPos );
}
// { [sonador][7.3.10]스크롤 바 오류 수정
void SUICreatureSkillFundWnd::InitScrollPosition()
{
KUIControlVScroll* pScrollBar = dynamicCast<KUIControlVScroll*>(GetChild( "creature_skillfund_scroll" ));
if( NULL != pScrollBar )
{
pScrollBar->SetPosition( 0 );
m_nScrollPos = pScrollBar->GetPosition();
}
}
// }
void SUICreatureSkillFundWnd::OnNotifyUIWindowOpen( bool bOpen, bool bLimitWnd )
{
SUIWnd::OnNotifyUIWindowOpen(bOpen);
if( bOpen )
{
KUIWnd *pInfoWnd = m_pManager->FindWnd( "window_summon_skill" );
if( pInfoWnd ) MovePos( pInfoWnd->GetRect().right, pInfoWnd->GetRect().bottom - GetRect().GetHeight() );
RefreshSkillInfo();
RefreshScrollbar( m_nGrade );
RefreshSkillSlot( m_nGrade, m_nScrollPos );
}
}
void SUICreatureSkillFundWnd::UpdateTab( int nCnt )
{
KUISimpleTabControl* pTabControl = dynamicCast<KUISimpleTabControl*>(GetChild("creature_skillfund_tab2"));
if( pTabControl && 0 < nCnt && nCnt <= 3 )
{
pTabControl->RemoveTabAllItem();
KRect rt = pTabControl->GetRect();
rt.right = rt.left + ( 80 * (float)nCnt );
pTabControl->SetRect(rt);
pTabControl->SetTabProperty( 0, false, nCnt );
if( nCnt > 0 ) pTabControl->AddTabItem( S(35), S(35) );
if( nCnt > 1 ) pTabControl->AddTabItem( S(36), S(36) );
if( nCnt > 2 ) pTabControl->AddTabItem( S(37), S(37) );
pTabControl->SetSelectedItem( m_nGrade );
}
}