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

641 lines
18 KiB
C++

#include "stdafx.h"
#include <mmo/ArType.h>
#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 <toolkit/nsl.h>
#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( "<size:14><left><vcenter>%s" ) , GetChild( ctrl_minutes ) ) );
mBoard.add( sui::MakeUpdatableWindow( "cur_points" , sui::SCaptionUpdator( "<size:12><hcenter><shadow><vcenter>%s /" ) , GetChild( ctrl_curpoints ) ) );
mBoard.add( sui::MakeUpdatableWindow( "obj_points" , sui::SCaptionUpdator( "<size:12><hcenter><shadow><vcenter><#ed1c24>%s" ) , GetChild( ctrl_objpoints ) ) );
mButton.add( sui::MakeUpdatableWindow( "leave.color" , sui::SEnableColorUpdator() , GetChild( ctrl_leaveRoom ) ) );
mButton.add( sui::MakeUpdatableWindow( "leave.caption" , sui::SCaptionUpdator( "<size:10><hcenter><vcenter>%s" ) , GetChild( ctrl_leaveRoom ) ) );
KUIControl* wnd = 0;
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_kill_1000 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_kill_0100 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_kill_0010 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_kill_0001 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_over_1000 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_over_0100 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_over_0010 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_over_0001 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_number" ); wnd->SetUsePos( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_boom_1000 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_big_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_boom_0100 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_big_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); }
wnd = dynamicCast<KUIControl*>(GetChild( ctrl_boom_0010 )); if( wnd ) { wnd->SetBack( wnd->GetSprName(), "font_kill_big_number" ); wnd->SetUsePos( true ); wnd->SetUseCustomSize( true ); }
wnd = dynamicCast<KUIControl*>(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<KUIControl*>(GetChild( ctrl_over_1000 ));
waterFallEnd = dynamicCast<KUIControl*>(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;
}
}