#include "stdafx.h" #include #include "SUIDefine.h" #include "SGameManager.h" #include "SGameSystem.h" //#include "SGameMessageUI.h" #include "SNetMessage.h" #include "SGameMessage.h" #include "ErrorCode/ErrorCode.h" #include "KUIWndManager.h" #include "KUIControlStatic.h" #include "KUIControlButton.h" #include "SStringDB.h" #include "SHuntaHolicResourceDB.h" #include "TemplateUtil.h" #include "SHuntaHolicSystem.h" #include "SGameSystem.h" #include "SUIHuntaHolicScoreBoardWnd.h" #include #include "SDebug_Util.h" extern SGameSystem* g_pCurrentGameSystem; #define HUNTAHOLICSYSTEM g_pCurrentGameSystem->GetContentsMgr().acquire< SHuntaHolicSystem >( "huntaholic" ) namespace hhi = huntaholic_interface; namespace { const char* ctrl_minutes = "static_msg03"; const char* ctrl_curpoints = "static_msg05"; const char* ctrl_objpoints = "static_msg06"; const char* ctrl_kill_1000 = "static_number_01"; const char* ctrl_kill_0100 = "static_number_02"; const char* ctrl_kill_0010 = "static_number_03"; const char* ctrl_kill_0001 = "static_number_04"; const char* ctrl_over_1000 = "static_number_01_up"; const char* ctrl_over_0100 = "static_number_02_up"; const char* ctrl_over_0010 = "static_number_03_up"; const char* ctrl_over_0001 = "static_number_04_up"; const char* ctrl_boom_1000 = "static_big_number_01"; const char* ctrl_boom_0100 = "static_big_number_02"; const char* ctrl_boom_0010 = "static_big_number_03"; const char* ctrl_boom_0001 = "static_big_number_04"; //#ifdef _E7_P2_UI_NUMPAD_ // servantes 2010.10.13, 나가기 버튼인데 왜 이름이 enter 인가??(ui팀에 문의 요망,,) // const char* ctrl_leaveRoom = "button_enter"; //#else const char* ctrl_leaveRoom = "bearload_end"; //#endif enum KILLCOUNT_FX { WATERFALL = 0, EXPLOSION }; const int KILLCOUNT_FX_PLAYTIME[ 2 ] = { 100, 400 }; struct FxVisibility { FxVisibility( float _vis ) : vis( _vis ) {} void operator () ( sui::kui_updatable_window*& wndProp ) { KUIWnd* wnd = wndProp->get_window(); if( !wnd ) return; wnd->ChangeAlpha( vis ); } float vis; }; struct FxHeight { FxHeight( int _height ) : height( _height ) {} void operator () ( sui::kui_updatable_window*& wndProp ) { KUIWnd* wnd = wndProp->get_window(); if( !wnd ) return; wnd->MovePos( wnd->GetRect().left, height ); } int height; }; _CID( onEndWaterFallFx ); class FxWaterFall { public: FxWaterFall( KObject* callback ) : mCallBack( callback ) , mObj( 0 ) , mStart( 0 ) , mEnd( 0 ) , mStartTime( 0 ) , mDuration( 0 ) , mPlaying( false ) { } void process( DWORD time ) { if( !mPlaying || !mObj ) return; if( mStartTime == 0 ) mStartTime = time; float t = (float)( time - mStartTime ) / mDuration; int x = (int)( t * ( mEnd - mStart ) ) + mStart; if( x >= mEnd ) { mCallBack->Perform( id_onEndWaterFallFx ); x = mEnd; t = 0.f; mPlaying = false; } std::for_each( (*mObj).begin(), (*mObj).end(), FxHeight( x ) ); std::for_each( (*mObj).begin(), (*mObj).end(), FxVisibility( t ) ); } void play( sui::kui_updatable_window_array* obj, DWORD duration, int start, int end ) { mPlaying = true; mStartTime = 0; mObj = obj; mDuration = duration; mStart = start; mEnd = end; } bool isPlaying() const { return mPlaying; } private: bool mPlaying; KObject* mCallBack; sui::kui_updatable_window_array* mObj; int mStart; int mEnd; DWORD mDuration; DWORD mStartTime; }; class FxExplosion { public: FxExplosion() : mObj( 0 ) , mSrc( 0 ) , mPlaying( false ) , mStartTime( 0 ) , mDuration( 0 ) , mScaleGoal( 1.f ) { } void process( DWORD time ) { if( !mPlaying || !mObj || !mSrc || ( mObj->size() != mSrc->size() ) ) return; if( mStartTime == 0 ) mStartTime = time; float t = (float)( time - mStartTime ) / mDuration; float scale = 0.f; // ----------------------------------------------------- // s = ( g - 1 ) t ^ ( 1 / p ) // ln( s / ( g - 1 ) ) = ln( t ) / p // ln( s ) = ln( t ) / p + ln( g - 1 ) // s = e ^ ( ln( t ) / p + ln( g - 1 ) ) // ----------------------------------------------------- // s : scale ( 0 <= s < g - 1 ) // g : goal scale ( 1 <= g ) // t : progress time ( 0 <= t < 1 ) // p : slope ( == 4 ) // e : exponential // ----------------------------------------------------- if( t >= 1.f ) { mPlaying = false; } if( t > 0.f ) { t = ::min( t, 1.f ); scale = ::exp( ( ::log( t ) / 4 ) + ::log( mScaleGoal - 1 ) ); //_oprint( "* debug explosion fx: t = %f, scale = %f\n", t, scale ); } for( int i = 0; i < mSrc->size(); ++i ) { KUIWnd* wnd = (*mSrc)[ i ].get_window(); if( wnd ) { const KRect& src = wnd->GetRect(); KRect scaled( ( src.left - mScaleCenter.x ) * scale + src.left, ( src.top - mScaleCenter.y ) * scale + src.top, ( src.right - mScaleCenter.x ) * scale + src.right, ( src.bottom - mScaleCenter.y ) * scale + src.bottom ); KUIWnd* obj = (*mObj)[ i ].get_window(); if( obj ) obj->Resize( scaled ); } } std::for_each( (*mObj).begin(), (*mObj).end(), FxVisibility( 1.f - t ) ); } void play( sui::kui_updatable_window_array* obj , sui::kui_updatable_window_array* src , DWORD duration , const KPoint& scaleCenter , float scaleGoal ) { mPlaying = true; mStartTime = 0; mObj = obj; mSrc = src; mDuration = duration; mScaleCenter = scaleCenter; mScaleGoal = scaleGoal; } bool isPlaying() const { return mPlaying; } private: bool mPlaying; sui::kui_updatable_window_array* mObj; sui::kui_updatable_window_array* mSrc; DWORD mDuration; DWORD mStartTime; KPoint mScaleCenter; float mScaleGoal; }; } SUIHuntaHolicScoreBoardWnd::SUIHuntaHolicScoreBoardWnd( SGameManager* pGameManager ) : SUIWnd( pGameManager ) , mWaterFallFx( 0 ) , mExplosionFx( 0 ) , mMode( MODE_NORMAL ) { } SUIHuntaHolicScoreBoardWnd::~SUIHuntaHolicScoreBoardWnd() { cleanUp(); } void SUIHuntaHolicScoreBoardWnd::Process( DWORD time ) { if( mWaterFallFx && mWaterFallFx->isPlaying() ) mWaterFallFx->process( time ); if( mExplosionFx && mExplosionFx->isPlaying() ) mExplosionFx->process( time ); // #define __TEST_HUNTAHOLICSYSTEM #if defined( __TEST_HUNTAHOLICSYSTEM ) setMode( MODE_COMPLETE ); #endif if( mMode == MODE_COMPLETE ) { static DWORD tick = 0; static bool twinkle = false; if( time - tick > 500 ) { tick = time; twinkle = !twinkle; if( twinkle ) { mButton[ "leave.color" ].set_data( "<#0072bc>" ); mButton[ "leave.caption" ].set_data( S( 6672 ) ); } else { mButton[ "leave.color" ].set_data( "<#242424>" ); mButton[ "leave.caption" ].set_data( S( 6672 ) ); } mButton[ "leave.color" ].update(); mButton[ "leave.caption" ].update(); } } SUIWnd::Process( time ); } bool SUIHuntaHolicScoreBoardWnd::InitControls( KPoint pos ) { cleanUp(); mBoard.add( sui::MakeUpdatableWindow( "time_limit" , sui::SCaptionUpdator( "%s" ) , GetChild( ctrl_minutes ) ) ); mBoard.add( sui::MakeUpdatableWindow( "cur_points" , sui::SCaptionUpdator( "%s /" ) , GetChild( ctrl_curpoints ) ) ); mBoard.add( sui::MakeUpdatableWindow( "obj_points" , sui::SCaptionUpdator( "<#ed1c24>%s" ) , GetChild( ctrl_objpoints ) ) ); mButton.add( sui::MakeUpdatableWindow( "leave.color" , sui::SEnableColorUpdator() , GetChild( ctrl_leaveRoom ) ) ); mButton.add( sui::MakeUpdatableWindow( "leave.caption" , sui::SCaptionUpdator( "%s" ) , GetChild( ctrl_leaveRoom ) ) ); KUIControl* wnd = 0; wnd = dynamicCast(GetChild( ctrl_kill_1000 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); } wnd = dynamicCast(GetChild( ctrl_kill_0100 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); } wnd = dynamicCast(GetChild( ctrl_kill_0010 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); } wnd = dynamicCast(GetChild( ctrl_kill_0001 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); } wnd = dynamicCast(GetChild( ctrl_over_1000 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); } wnd = dynamicCast(GetChild( ctrl_over_0100 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); } wnd = dynamicCast(GetChild( ctrl_over_0010 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); } wnd = dynamicCast(GetChild( ctrl_over_0001 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); } wnd = dynamicCast(GetChild( ctrl_boom_1000 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_big_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); } wnd = dynamicCast(GetChild( ctrl_boom_0100 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_big_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); } wnd = dynamicCast(GetChild( ctrl_boom_0010 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_big_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); } wnd = dynamicCast(GetChild( ctrl_boom_0001 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_big_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); } mKillCount.add( sui::MakeUpdatableWindow( "num_1000", sui::SAniFrameIndexUpdator(), GetChild( ctrl_kill_1000 ) ) ); mKillCount.add( sui::MakeUpdatableWindow( "num_0100", sui::SAniFrameIndexUpdator(), GetChild( ctrl_kill_0100 ) ) ); mKillCount.add( sui::MakeUpdatableWindow( "num_0010", sui::SAniFrameIndexUpdator(), GetChild( ctrl_kill_0010 ) ) ); mKillCount.add( sui::MakeUpdatableWindow( "num_0001", sui::SAniFrameIndexUpdator(), GetChild( ctrl_kill_0001 ) ) ); mOverCount.add( sui::MakeUpdatableWindow( "num_1000", sui::SAniFrameIndexUpdator(), GetChild( ctrl_over_1000 ) ) ); mOverCount.add( sui::MakeUpdatableWindow( "num_0100", sui::SAniFrameIndexUpdator(), GetChild( ctrl_over_0100 ) ) ); mOverCount.add( sui::MakeUpdatableWindow( "num_0010", sui::SAniFrameIndexUpdator(), GetChild( ctrl_over_0010 ) ) ); mOverCount.add( sui::MakeUpdatableWindow( "num_0001", sui::SAniFrameIndexUpdator(), GetChild( ctrl_over_0001 ) ) ); mBoomCount.add( sui::MakeUpdatableWindow( "num_1000", sui::SAniFrameIndexUpdator(), GetChild( ctrl_boom_1000 ) ) ); mBoomCount.add( sui::MakeUpdatableWindow( "num_0100", sui::SAniFrameIndexUpdator(), GetChild( ctrl_boom_0100 ) ) ); mBoomCount.add( sui::MakeUpdatableWindow( "num_0010", sui::SAniFrameIndexUpdator(), GetChild( ctrl_boom_0010 ) ) ); mBoomCount.add( sui::MakeUpdatableWindow( "num_0001", sui::SAniFrameIndexUpdator(), GetChild( ctrl_boom_0001 ) ) ); KUIControl *waterFallBegin, *waterFallEnd; waterFallBegin = dynamicCast(GetChild( ctrl_over_1000 )); waterFallEnd = dynamicCast(GetChild( ctrl_kill_1000 )); if( waterFallBegin && waterFallEnd ) { mWaterFallFx = new FxWaterFall( this ); } mExplosionFx = new FxExplosion(); return SUIWnd::InitControls( pos ); } bool SUIHuntaHolicScoreBoardWnd::InitData( bool reload ) { setMode( MODE_NORMAL ); return SUIWnd::InitData( reload ); } void* SUIHuntaHolicScoreBoardWnd::Perform( KID id, KArg& msg ) { if( id == hhi::id_updateTimeLimit ) { hhi::updateTimeLimit* real = static_cast< hhi::updateTimeLimit* >( &msg ); unsigned int timeLimit = HUNTAHOLICSYSTEM->getArTimeLimitByMinutes(); char buffer[ 32 ]; ::sprintf_s( buffer, "%s%u", real->maskColor, timeLimit ); mBoard[ "time_limit" ].set_data( buffer ); mBoard[ "time_limit" ].update(); } else if( id == hhi::id_updateScore ) { hhi::updateScore* real = static_cast< hhi::updateScore* >( &msg ); const HuntaHolicResource& db = GetHuntaHolicResourceDB().Find( HUNTAHOLICSYSTEM->getLobby().huntaholic_id ); char buffer[ 32 ]; ::sprintf_s( buffer, "%s%d", real->maskColor, HUNTAHOLICSYSTEM->getMyScore().score ); mBoard[ "obj_points" ].set_data( db.objective_point ); mBoard[ "cur_points" ].set_data( buffer ); mBoard[ "obj_points" ].update(); mBoard[ "cur_points" ].update(); } else if( id == hhi::id_updateKillCount ) { updateCount( mKillCount, HUNTAHOLICSYSTEM->getMyScore().kill_count ); } else if( id == hhi::id_updateKillCountByWaterFallFx ) { updateCount( mOverCount, HUNTAHOLICSYSTEM->getMyScore().kill_count ); if( mWaterFallFx && mOverCount[ "num_1000" ].get_window() && mKillCount[ "num_1000" ].get_window() ) mWaterFallFx->play( &mOverCount, KILLCOUNT_FX_PLAYTIME[ KILLCOUNT_FX::WATERFALL ], mKillCount[ "num_1000" ].get_window()->GetRect().top - 14, mKillCount[ "num_1000" ].get_window()->GetRect().top ); } else if( id == hhi::id_updateKillCountByExplosionFx ) { updateCount( mBoomCount, HUNTAHOLICSYSTEM->getMyScore().kill_count ); updateCount( mKillCount, HUNTAHOLICSYSTEM->getMyScore().kill_count ); if( mExplosionFx ) mExplosionFx->play( &mBoomCount, &mKillCount, KILLCOUNT_FX_PLAYTIME[ KILLCOUNT_FX::EXPLOSION ], getScaleCenter(), 1.8f ); } else if( id == id_onEndWaterFallFx ) { updateCount( mKillCount, HUNTAHOLICSYSTEM->getMyScore().kill_count ); } else if( id == hhi::id_setScoreBoardNormalMode ) { setMode( MODE_NORMAL ); } else if( id == hhi::id_setScoreBoardCompleteMode ) { setMode( MODE_COMPLETE ); } return SUIWnd::Perform( id, msg ); } void SUIHuntaHolicScoreBoardWnd::PumpUpMessage( LPCTSTR controlID, DWORD msg, DWORD lparam, DWORD wparam ) { switch( msg ) { case KUI_MESSAGE::KBUTTON_CLICK: { if( !::stricmp( controlID, ctrl_leaveRoom ) ) { if( HUNTAHOLICSYSTEM->isHunting() ) { if( HUNTAHOLICSYSTEM->isObjCompleted() ) m_pGameManager->PostMsgAtDynamic( new SIMSG_REQ_OPEN_MSGBOX( SIMSG_REQ_OPEN_MSGBOX::MSGBOX_HUNTAHOLIC_SCOREBOARD, S( 6671 ), "huntaholic_scoreboard" ) ); else m_pGameManager->PostMsgAtDynamic( new SIMSG_REQ_OPEN_MSGBOX( SIMSG_REQ_OPEN_MSGBOX::MSGBOX_HUNTAHOLIC_SCOREBOARD, S( 6670 ), "huntaholic_scoreboard" ) ); } } } break; } SUIWnd::PumpUpMessage( controlID, msg, lparam, wparam ); } void SUIHuntaHolicScoreBoardWnd::ProcMsgAtStatic( SGameMessage* msg ) { switch( msg->nType ) { case IMSG_UI_SEND_DATA: { SIMSG_UI_SEND_DATA *data = dynamicCast< SIMSG_UI_SEND_DATA* >( msg ); if( data->m_strString == "huntaholic_scoreboard" ) { HUNTAHOLICSYSTEM->reqLeaveInstance(); } } break; } } void SUIHuntaHolicScoreBoardWnd::OnNotifyUIWindowOpen( bool open, bool limitWnd ) { if( open ) { updateCount( mKillCount, 0 ); updateCount( mOverCount, 0 ); updateCount( mBoomCount, 0 ); std::for_each( mOverCount.begin(), mOverCount.end(), FxVisibility( 0.f ) ); std::for_each( mBoomCount.begin(), mBoomCount.end(), FxVisibility( 0.f ) ); } } DWORD SUIHuntaHolicScoreBoardWnd::OnMouseMessage( DWORD msg, int x, int y ) { DWORD ret = SUIWnd::OnMouseMessage( msg, x, y ); if( KMR_NO_GET & ret ) return ret; // do something ... #if defined( _TEST_HUNTAHOLICSYSTEM ) static int countTest = 0; switch( countTest ) { case 0: updateCount( mOverCount, 1345 ); if( mWaterFallFx && mOverCount[ "num_1000" ].get_window() && mKillCount[ "num_1000" ].get_window() ) mWaterFallFx->play( &mOverCount, KILLCOUNT_FX_PLAYTIME[ KILLCOUNT_FX::WATERFALL ], mKillCount[ "num_1000" ].get_window()->GetRect().top - 14, mKillCount[ "num_1000" ].get_window()->GetRect().top ); break; case 1: updateCount( mBoomCount, 1346 ); updateCount( mKillCount, 1346 ); if( mExplosionFx ) mExplosionFx->play( &mBoomCount, &mKillCount, KILLCOUNT_FX_PLAYTIME[ KILLCOUNT_FX::EXPLOSION ], getScaleCenter(), 1.8f ); break; } countTest++; if( countTest > 1 ) countTest = 0; #endif return ret; } void SUIHuntaHolicScoreBoardWnd::cleanUp() { mBoard.clear(); mButton.clear(); mKillCount.clear(); mOverCount.clear(); mBoomCount.clear(); rp::safe_delete( mWaterFallFx ); rp::safe_delete( mExplosionFx ); } void SUIHuntaHolicScoreBoardWnd::updateMinutes( int minutes ) { char buffer[ 32 ]; ::sprintf_s( buffer, "%d", minutes ); mBoard[ "time_limit" ].set_data( buffer ); mBoard[ "time_limit" ].update(); } void SUIHuntaHolicScoreBoardWnd::updateCount( sui::kui_updatable_window_array& obj, int count ) { count = ::min( 9999, ::max( 0, count ) ); char idBuffer[ 32 ]; int quotient( 0 ), remainder( count ); bool enableZero = false; for( int i = 0; i < 4; ++i ) { int divider = ::pow( 10.f ,( 4 - 1 ) - i ); quotient = remainder / divider; remainder = remainder - ( quotient * divider ); if( enableZero == false && ( quotient != 0 || i == 3 ) ) // 이제부터 나오는 0은 유효 자리수에 포함된 것 enableZero = true; if( enableZero == false && quotient == 0 ) { // 유효 자리수를 넘어가는 0을 안보이게 처리 quotient = -1; } ::sprintf( idBuffer, "num_%.4d", divider ); obj[ idBuffer ].set_data( quotient ); obj[ idBuffer ].update(); } } KPoint SUIHuntaHolicScoreBoardWnd::getScaleCenter() { KPoint scaledCenter( 0, 0 ); bool first = true; for( int i = 0; i < mKillCount.size(); ++i ) { int number; mKillCount[ i ].get_data( number ); KUIWnd* wnd = mKillCount[ i ].get_window(); if( !wnd || number == -1 ) continue; int wndCenterX = wnd->GetRect().left + wnd->GetRect().GetWidth() / 2; int wndCenterY = wnd->GetRect().top + wnd->GetRect().GetHeight() / 2; if( first ) { scaledCenter.x = wndCenterX; scaledCenter.y = wndCenterY; first = false; } else { scaledCenter.x = ( scaledCenter.x + wndCenterX ) / 2; scaledCenter.y = ( scaledCenter.y + wndCenterY ) / 2; } } return scaledCenter; } void SUIHuntaHolicScoreBoardWnd::setMode( MODE mode ) { mMode = mode; switch( mMode ) { case MODE_NORMAL: { mButton[ "leave.color" ].set_data( "<#242424>" ); mButton[ "leave.caption" ].set_data( S( 6669 ) ); mButton[ "leave.color" ].update(); mButton[ "leave.caption" ].update(); } break; case MODE_COMPLETE: { } break; } }