1013 lines
31 KiB
C++
1013 lines
31 KiB
C++
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
|
|
#if defined( INCLUDE_SCALEFORM )
|
|
|
|
#include <time.h>
|
|
|
|
#include "basepanel.h"
|
|
#include "medalstatsdialog_scaleform.h"
|
|
#include "../engine/filesystem_engine.h"
|
|
|
|
#include "vgui/IInput.h"
|
|
#include "vgui/ILocalize.h"
|
|
#include "vgui/ISurface.h"
|
|
#include "vgui/ISystem.h"
|
|
#include "vgui/IVGui.h"
|
|
#include "fmtstr.h"
|
|
#include "iachievementmgr.h"
|
|
#include "achievementmgr.h"
|
|
#include "cs_achievementdefs.h"
|
|
#include "achievements_cs.h"
|
|
#include "cs_player_rank_mgr.h"
|
|
#include "cs_player_rank_shared.h"
|
|
|
|
#include "gameui_util.h"
|
|
|
|
#ifdef _X360
|
|
#include "xbox/xbox_launch.h"
|
|
#endif
|
|
#include "keyvalues.h"
|
|
#include "engineinterface.h"
|
|
#include "modinfo.h"
|
|
#include "gameui_interface.h"
|
|
|
|
#include "tier1/utlbuffer.h"
|
|
#include "filesystem.h"
|
|
|
|
#include "cs_gamestats_shared.h"
|
|
#include "cs_client_gamestats.h"
|
|
|
|
using namespace vgui;
|
|
|
|
// for SRC
|
|
#include <vstdlib/random.h>
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
#define MAX_ACHIEVEMENT_STRLEN 1024
|
|
#define MAX_STATS_STRLEN 128
|
|
|
|
// Maximum number of recent achievements to track
|
|
// -- This number should be the same as the maximum number of slots in the UI panel for recently unlocked
|
|
#define MAX_RECENT_ACHIEVEMENT_SLOTS 40
|
|
|
|
extern CAchievementMgr g_AchievementMgrCS;
|
|
|
|
#if !defined( _GAMECONSOLE )
|
|
void RequestEloBracket( volatile int32 *pOutBracket, int32 game_mode, int32 input_device );
|
|
#endif
|
|
|
|
CCreateMedalStatsDialogScaleform* CCreateMedalStatsDialogScaleform::m_pInstance = NULL;
|
|
|
|
SFUI_BEGIN_GAME_API_DEF
|
|
SFUI_DECL_METHOD( OnOk ),
|
|
SFUI_DECL_METHOD( UpdateCurrentAchievement ),
|
|
SFUI_DECL_METHOD( GetAchievementStatus ),
|
|
SFUI_DECL_METHOD( GetRecentAchievementCount ),
|
|
SFUI_DECL_METHOD( GetRecentAchievementName ),
|
|
SFUI_DECL_METHOD( GetRankForCurrentCatagory ),
|
|
SFUI_DECL_METHOD( GetAchievedInCategory ),
|
|
SFUI_DECL_METHOD( GetMaxAwardsForCatagory ),
|
|
SFUI_DECL_METHOD( GetMinAwardNeededForRank ),
|
|
SFUI_END_GAME_API_DEF( CCreateMedalStatsDialogScaleform, MedalStatsScreen )
|
|
;
|
|
|
|
|
|
ConVar player_last_medalstats_panel( "player_last_medalstats_panel", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE | FCVAR_SS, "Last opened panel in the Medals & Stats screen" );
|
|
ConVar player_last_medalstats_category( "player_last_medalstats_category", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE | FCVAR_SS, "Last selected category on the Medals panel in the Medals & Stats screen" );
|
|
ConVar player_medalstats_recent_range( "player_medalstats_recent_range", "432000", FCVAR_RELEASE, "Window (in seconds of recent achievements to show" );
|
|
ConVar player_medalstats_most_recent_time( "player_medalstats_most_recent_time", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE | FCVAR_SS, "Timestamp of most recently earned achievement displayed on Medals & Stats screen" );
|
|
|
|
void CCreateMedalStatsDialogScaleform::LoadDialog( eDialogType type )
|
|
{
|
|
if ( !m_pInstance )
|
|
{
|
|
m_pInstance = new CCreateMedalStatsDialogScaleform( type );
|
|
SFUI_REQUEST_ELEMENT( SF_FULL_SCREEN_SLOT, g_pScaleformUI, CCreateMedalStatsDialogScaleform, m_pInstance, MedalStatsScreen );
|
|
}
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::UnloadDialog( void )
|
|
{
|
|
if ( m_pInstance )
|
|
{
|
|
m_pInstance->RemoveFlashElement();
|
|
}
|
|
}
|
|
|
|
CCreateMedalStatsDialogScaleform::CCreateMedalStatsDialogScaleform( eDialogType type ) :
|
|
m_MedalNameHandle(NULL),
|
|
m_MedalUnlockHandle(NULL),
|
|
m_MedalDescHandle(NULL),
|
|
m_LastMatchTeamStats(NULL),
|
|
m_LastMatchFaveWeaponName(NULL),
|
|
m_LastMatchFaveWeaponStats(NULL),
|
|
m_LastMatchPerfStats(NULL),
|
|
m_LastMatchMiscStats(NULL),
|
|
m_OverallPlayerName(NULL),
|
|
m_OverallMVPsText(NULL),
|
|
m_OverallPlayerStats(NULL),
|
|
m_OverallFaveWeaponName(NULL),
|
|
m_OverallFaveWeaponStats(NULL),
|
|
m_OverallFaveMapStats(NULL),
|
|
m_type( type ),
|
|
m_mostRecentAchievementTime(0)
|
|
{
|
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( GET_ACTIVE_SPLITSCREEN_SLOT() );
|
|
m_iPlayerSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
|
|
|
|
#if !defined( _GAMECONSOLE )
|
|
m_nEloBracket = -1;
|
|
#if 0 // Disabling elo bracket display in the menu.
|
|
// Right now our elo values arn't meaningful so for 1.20 we're disabling the display.
|
|
// This is done in scaleform, but i'm also disabling it here because we still have this unsolved ecoroutine
|
|
// crash on OSX that will be triggered by the yielding gc message...
|
|
RequestEloBracket( &m_nEloBracket, ELOGameType::CLASSIC_COMPETITIVE, INPUT_DEVICE_KEYBOARD_MOUSE );
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::OnOk( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
CCreateMedalStatsDialogScaleform::UnloadDialog();
|
|
}
|
|
|
|
CEG_NOINLINE void CCreateMedalStatsDialogScaleform::UpdateCurrentAchievement( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
if ( FlashAPIIsValid() )
|
|
{
|
|
const char *achievementName = pui->Params_GetArgAsString( obj, 0 );
|
|
|
|
CCSBaseAchievement* pAchievement = NULL;
|
|
|
|
// if we passed in an empty string, clear all of the achievement fields
|
|
bool bClearFields = ( achievementName[0] == 0 );
|
|
|
|
if ( !bClearFields )
|
|
{
|
|
pAchievement = dynamic_cast<CCSBaseAchievement*>(g_AchievementMgrCS.GetAchievementByName( achievementName, m_iPlayerSlot ));
|
|
}
|
|
|
|
UpdateMedalProgress( pAchievement );
|
|
|
|
bool bShouldHide = ( pAchievement && pAchievement->ShouldHideUntilAchieved() && !pAchievement->IsAchieved() );
|
|
|
|
CEG_ENCRYPT_FUNCTION( CCreateMedalStatsDialogScaleform_UpdateCurrentAchievement );
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
if ( m_MedalNameHandle )
|
|
{
|
|
if ( !pAchievement )
|
|
{
|
|
// Report an error if the achievement is not found, not properly setup, etc.
|
|
m_pScaleformUI->Value_SetText( m_MedalNameHandle, bClearFields ? "" : "#SFUI_MedalsInfo_Invalid" );
|
|
}
|
|
else if ( bShouldHide )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_MedalNameHandle, "#SFUI_MedalsInfo_LockedName" );
|
|
}
|
|
else
|
|
{
|
|
const wchar_t * pName = ACHIEVEMENT_LOCALIZED_NAME( pAchievement );
|
|
if ( pName )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_MedalNameHandle, pName );
|
|
}
|
|
else
|
|
{
|
|
// Missing our localization string!
|
|
m_pScaleformUI->Value_SetText( m_MedalNameHandle, "#SFUI_MedalsInfo_Invalid" );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( m_MedalUnlockHandle )
|
|
{
|
|
if ( !pAchievement )
|
|
{
|
|
// Report an error if the achievement is not found, not properly setup, etc.
|
|
m_pScaleformUI->Value_SetText( m_MedalUnlockHandle, bClearFields ? "" : "#SFUI_MedalsInfo_Invalid" );
|
|
}
|
|
else if ( bShouldHide )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_MedalUnlockHandle, "" );
|
|
}
|
|
else
|
|
{
|
|
wchar_t achDate[MAX_ACHIEVEMENT_STRLEN];
|
|
V_wcsncpy( achDate, L"", sizeof(achDate) );
|
|
|
|
if ( pAchievement->IsAchieved() )
|
|
{
|
|
int year, month, day, hour, minute, second;
|
|
if ( pAchievement->GetAwardTime(year, month, day, hour, minute, second) )
|
|
{
|
|
V_swprintf_safe( achDate, PRI_WS_FOR_WS L" : %4d-%02d-%02d", g_pVGuiLocalize->Find( "#SFUI_MedalsInfo_Unlocked" ), year, month, day );
|
|
}
|
|
else
|
|
{
|
|
// we don't have an unlock time from our info, so just report it is unlocked
|
|
V_wcsncpy( achDate, L"#SFUI_MedalsInfo_Unlocked", sizeof(achDate) );
|
|
}
|
|
}
|
|
|
|
m_pScaleformUI->Value_SetText( m_MedalUnlockHandle, achDate );
|
|
}
|
|
}
|
|
|
|
if ( m_MedalDescHandle )
|
|
{
|
|
if ( !pAchievement )
|
|
{
|
|
// Report an error if the achievement is not found, not properly setup, etc.
|
|
m_pScaleformUI->Value_SetText( m_MedalDescHandle, bClearFields ? "" : "#SFUI_MedalsInfo_Invalid" );
|
|
}
|
|
else if ( bShouldHide )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_MedalDescHandle, "#SFUI_MedalsInfo_LockedDesc" );
|
|
}
|
|
else
|
|
{
|
|
const wchar_t * pDesc = ACHIEVEMENT_LOCALIZED_DESC( pAchievement );
|
|
if ( pDesc )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_MedalDescHandle, pDesc );
|
|
}
|
|
else
|
|
{
|
|
// Missing our localization string!
|
|
m_pScaleformUI->Value_SetText( m_MedalDescHandle, "#SFUI_MedalsInfo_Invalid" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::GetAchievementStatus( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
const char *achievementName = pui->Params_GetArgAsString( obj, 0 );
|
|
CCSBaseAchievement* pAchievement = dynamic_cast<CCSBaseAchievement*>(g_AchievementMgrCS.GetAchievementByName( achievementName, m_iPlayerSlot ));
|
|
|
|
eAchievementStatus Result = eAchievement_Locked;
|
|
|
|
if ( pAchievement )
|
|
{
|
|
if ( pAchievement->IsAchieved() )
|
|
{
|
|
// Determine if it's recently achieved, or just unlocked
|
|
if ( pAchievement->GetUnlockTime() > (uint)(player_medalstats_most_recent_time.GetInt()) )
|
|
Result = eAchievement_RecentUnlock;
|
|
else
|
|
Result = eAchievement_Unlocked;
|
|
}
|
|
else if ( pAchievement->ShouldHideUntilAchieved() )
|
|
{
|
|
Result = eAchievement_Secret;
|
|
}
|
|
}
|
|
|
|
m_pScaleformUI->Params_SetResult( obj, Result );
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::FlashLoaded( void )
|
|
{
|
|
if ( FlashAPIIsValid() )
|
|
{
|
|
LockInputToSlot( m_iPlayerSlot );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "InitDialogData", NULL, 0 );
|
|
}
|
|
}
|
|
|
|
static void GetTextBoxForElement( IScaleformUI *pScaleformUI, SFVALUE root, const char *elementName, const char *textElementName, SFVALUE &sfv )
|
|
{
|
|
SFVALUE TempHandle = pScaleformUI->Value_GetMember( root, elementName );
|
|
|
|
if ( TempHandle )
|
|
{
|
|
sfv = pScaleformUI->Value_GetMember( TempHandle, textElementName );
|
|
pScaleformUI->ReleaseValue( TempHandle );
|
|
}
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::FlashReady( void )
|
|
{
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
SFVALUE PanelHandle = m_pScaleformUI->Value_GetMember( m_FlashAPI, "Panel" );
|
|
|
|
if ( PanelHandle )
|
|
{
|
|
SFVALUE AnimatedPanelHandle = m_pScaleformUI->Value_GetMember( PanelHandle, "Panel" );
|
|
|
|
if ( AnimatedPanelHandle )
|
|
{
|
|
// Medals panel members
|
|
SFVALUE MedalPanel = m_pScaleformUI->Value_GetMember( AnimatedPanelHandle, "Medals" );
|
|
|
|
if ( MedalPanel )
|
|
{
|
|
SFVALUE AnimatedMedalPanel = m_pScaleformUI->Value_GetMember( MedalPanel, "Medals" );
|
|
|
|
if ( AnimatedMedalPanel )
|
|
{
|
|
SFVALUE TextPanel = m_pScaleformUI->Value_GetMember( AnimatedMedalPanel, "Text" );
|
|
|
|
if ( TextPanel )
|
|
{
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "MedalName", "MedalName", m_MedalNameHandle );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "MedalUnlockDate", "MedalUnlockDate", m_MedalUnlockHandle );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "MedalDesc", "MedalDesc", m_MedalDescHandle );
|
|
|
|
|
|
m_pScaleformUI->ReleaseValue( TextPanel );
|
|
}
|
|
|
|
m_pScaleformUI->ReleaseValue( AnimatedMedalPanel );
|
|
}
|
|
|
|
m_pScaleformUI->ReleaseValue( MedalPanel );
|
|
}
|
|
|
|
|
|
// Last match panel members
|
|
SFVALUE LastMatchPanel = m_pScaleformUI->Value_GetMember( AnimatedPanelHandle, "LastMatch" );
|
|
|
|
if ( LastMatchPanel )
|
|
{
|
|
SFVALUE AnimatedLastMatchPanel = m_pScaleformUI->Value_GetMember( LastMatchPanel, "LastMatch" );
|
|
|
|
if ( AnimatedLastMatchPanel )
|
|
{
|
|
SFVALUE TextPanel = m_pScaleformUI->Value_GetMember( AnimatedLastMatchPanel, "Text" );
|
|
|
|
if ( TextPanel )
|
|
{
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "TeamData", "TeamData", m_LastMatchTeamStats );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "FavoriteWeaponName", "FavoriteWeaponName", m_LastMatchFaveWeaponName );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "WeaponData", "WeaponData", m_LastMatchFaveWeaponStats );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "PerformanceData", "PerformanceData", m_LastMatchPerfStats );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "MiscData", "MiscData", m_LastMatchMiscStats );
|
|
|
|
m_pScaleformUI->ReleaseValue( TextPanel );
|
|
}
|
|
|
|
m_pScaleformUI->ReleaseValue( AnimatedLastMatchPanel );
|
|
}
|
|
|
|
m_pScaleformUI->ReleaseValue( LastMatchPanel );
|
|
}
|
|
|
|
|
|
// Overall stats panel members
|
|
SFVALUE OverallPanel = m_pScaleformUI->Value_GetMember( AnimatedPanelHandle, "OverAll" );
|
|
|
|
if ( OverallPanel )
|
|
{
|
|
SFVALUE AnimatedOverallPanel = m_pScaleformUI->Value_GetMember( OverallPanel, "OverAll" );
|
|
|
|
if ( AnimatedOverallPanel )
|
|
{
|
|
SFVALUE TextPanel = m_pScaleformUI->Value_GetMember( AnimatedOverallPanel, "Text" );
|
|
|
|
if ( TextPanel )
|
|
{
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "PlayerName", "PlayerName", m_OverallPlayerName );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "Stars", "Stars", m_OverallMVPsText );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "PlayerData", "PlayerData", m_OverallPlayerStats );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "WeaponName", "WeaponName", m_OverallFaveWeaponName );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "WeaponData", "WeaponData", m_OverallFaveWeaponStats );
|
|
GetTextBoxForElement( m_pScaleformUI, TextPanel, "MapDescription", "MapDescription", m_OverallFaveMapStats );
|
|
|
|
m_pScaleformUI->ReleaseValue( TextPanel );
|
|
}
|
|
|
|
m_pScaleformUI->ReleaseValue( AnimatedOverallPanel );
|
|
}
|
|
|
|
m_pScaleformUI->ReleaseValue( OverallPanel );
|
|
}
|
|
|
|
m_pScaleformUI->ReleaseValue( AnimatedPanelHandle );
|
|
}
|
|
|
|
m_pScaleformUI->ReleaseValue( PanelHandle );
|
|
}
|
|
|
|
PopulateLastMatchStats();
|
|
|
|
PopulateOverallStats();
|
|
|
|
GenerateRecentAchievements();
|
|
|
|
Show();
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::UpdateMedalProgress( CCSBaseAchievement *pAchievement )
|
|
{
|
|
if ( FlashAPIIsValid() )
|
|
{
|
|
bool bShowProgress = ( pAchievement && pAchievement->GetGoal() > 1 );
|
|
|
|
// if this achievement gets saved with game and we're not in a level and have not achieved it, then we do not have any state
|
|
// for this achievement, don't show progress
|
|
if ( bShowProgress && ( pAchievement->GetFlags() & ACH_SAVE_WITH_GAME ) && !GameUI().IsInLevel() && !pAchievement->IsAchieved() )
|
|
{
|
|
bShowProgress = false;
|
|
}
|
|
|
|
int iCount = -1;
|
|
int iGoal = -1;
|
|
|
|
if ( bShowProgress )
|
|
{
|
|
iCount = pAchievement->GetCount();
|
|
iGoal = pAchievement->GetGoal();
|
|
// Once an achievement is achieved, we can't rely on the count to be accurate any longer - force the count to the max
|
|
if ( iCount > iGoal || pAchievement->IsAchieved() )
|
|
{
|
|
iCount = iGoal;
|
|
}
|
|
}
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
WITH_SFVALUEARRAY( data, 2 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( data, 0, iCount );
|
|
m_pScaleformUI->ValueArray_SetElement( data, 1, iGoal);
|
|
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "setMedalsProgress", data, 2 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CCreateMedalStatsDialogScaleform::PreUnloadFlash( void )
|
|
{
|
|
UnlockInput();
|
|
|
|
// save off the time of the most recent achievement so we can highlight new ones on a future invoke
|
|
player_medalstats_most_recent_time.SetValue((int)m_mostRecentAchievementTime);
|
|
|
|
SafeReleaseSFVALUE( m_MedalNameHandle );
|
|
SafeReleaseSFVALUE( m_MedalUnlockHandle );
|
|
SafeReleaseSFVALUE( m_MedalDescHandle );
|
|
|
|
SafeReleaseSFVALUE( m_LastMatchTeamStats );
|
|
SafeReleaseSFVALUE( m_LastMatchFaveWeaponName );
|
|
SafeReleaseSFVALUE( m_LastMatchFaveWeaponStats );
|
|
SafeReleaseSFVALUE( m_LastMatchPerfStats );
|
|
SafeReleaseSFVALUE( m_LastMatchMiscStats );
|
|
|
|
SafeReleaseSFVALUE( m_OverallPlayerName );
|
|
SafeReleaseSFVALUE( m_OverallMVPsText );
|
|
SafeReleaseSFVALUE( m_OverallPlayerStats );
|
|
SafeReleaseSFVALUE( m_OverallFaveWeaponName );
|
|
SafeReleaseSFVALUE( m_OverallFaveWeaponStats );
|
|
SafeReleaseSFVALUE( m_OverallFaveMapStats );
|
|
|
|
return true;
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::PostUnloadFlash( void )
|
|
{
|
|
if ( GameUI().IsInLevel() )
|
|
{
|
|
BasePanel()->RestorePauseMenu();
|
|
}
|
|
else
|
|
{
|
|
BasePanel()->RestoreMainMenuScreen();
|
|
}
|
|
|
|
m_recentAchievements.Purge();
|
|
|
|
m_pInstance = NULL;
|
|
delete this;
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::Show( void )
|
|
{
|
|
if ( FlashAPIIsValid() )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
WITH_SFVALUEARRAY( args, 1 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, m_type );
|
|
ScaleformUI()->Value_InvokeWithoutReturn( m_FlashAPI, "showPanel", args, 1 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::Hide( void )
|
|
{
|
|
if ( FlashAPIIsValid() )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
ScaleformUI()->Value_InvokeWithoutReturn( m_FlashAPI, "hidePanel", 0, NULL );
|
|
}
|
|
}
|
|
}
|
|
|
|
static int AchievementDateSortPredicate( CCSBaseAchievement* const* pLeft, CCSBaseAchievement* const* pRight )
|
|
{
|
|
if (!pLeft || !pRight || !(*pLeft) || ! (*pRight))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if ((*pLeft)->GetSortKey() < (*pRight)->GetSortKey())
|
|
{
|
|
return 1;
|
|
}
|
|
else if ((*pLeft)->GetSortKey() > (*pRight)->GetSortKey())
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::GenerateRecentAchievements( void )
|
|
{
|
|
// "Recent" achievements are defined as all earned achievments with an "age" less than that value
|
|
// specified by player_medalstats_recent_range convar.
|
|
|
|
int iCount = g_AchievementMgrCS.GetAchievementCount();
|
|
m_recentAchievements.RemoveAll();
|
|
m_recentAchievements.EnsureCapacity(iCount);
|
|
|
|
time_t ltime;
|
|
time( <ime );
|
|
uint now = (uint)ltime;
|
|
|
|
for ( int i = 0; i < iCount; ++i )
|
|
{
|
|
CCSBaseAchievement* pAchievement = (CCSBaseAchievement*)g_AchievementMgrCS.GetAchievementByIndex( i, m_iPlayerSlot );
|
|
if ( pAchievement && pAchievement->IsAchieved() )
|
|
{
|
|
uint unlockTime = pAchievement->GetUnlockTime();
|
|
|
|
// figure out which was earned most recently for highlighting new ones
|
|
if ( unlockTime > m_mostRecentAchievementTime )
|
|
m_mostRecentAchievementTime = unlockTime;
|
|
|
|
int age = now - unlockTime;
|
|
if ( age < player_medalstats_recent_range.GetInt() )
|
|
{
|
|
m_recentAchievements.AddToTail(pAchievement);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_recentAchievements.Sort( AchievementDateSortPredicate );
|
|
int unlockCount = m_recentAchievements.Count();
|
|
|
|
// Cap our list to the X most recent achievements only (should coincide with the number of slots to show on the screen)
|
|
if ( unlockCount > MAX_RECENT_ACHIEVEMENT_SLOTS )
|
|
{
|
|
m_recentAchievements.RemoveMultipleFromTail( unlockCount - MAX_RECENT_ACHIEVEMENT_SLOTS );
|
|
}
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::GetRecentAchievementCount( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
m_pScaleformUI->Params_SetResult( obj, m_recentAchievements.Count() );
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::GetRecentAchievementName( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
int achievementIdx = (int) pui->Params_GetArgAsNumber( obj, 0 );
|
|
|
|
if ( achievementIdx < m_recentAchievements.Count() )
|
|
{
|
|
CCSBaseAchievement* pAch = m_recentAchievements[ achievementIdx ];
|
|
|
|
if ( pAch )
|
|
{
|
|
m_pScaleformUI->Params_SetResult( obj, pAch->GetName() );
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Fall through to here, reset the achievement name
|
|
m_pScaleformUI->Params_SetResult( obj, L"" );
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::GetRankForCurrentCatagory( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
// this list is different, unfortunately. In this list, 0 is "recently earned"
|
|
int nCurCatagory = (int) pui->Params_GetArgAsNumber( obj, 0 );
|
|
// catagory 5 is the recently unlocked catagory, hide the progress
|
|
if ( nCurCatagory >= MEDAL_CATEGORY_COUNT || nCurCatagory < MEDAL_CATEGORY_START )
|
|
return;
|
|
|
|
int nCurRank = g_PlayerRankManager.CalculateRankForCategory( (MedalCategory_t)nCurCatagory );
|
|
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
m_pScaleformUI->Params_SetResult( obj, nCurRank );
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::GetMaxAwardsForCatagory( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
// this list is different, unfortunately. In this list, 0 is "recently earned"
|
|
int nCurCatagory = (int) pui->Params_GetArgAsNumber( obj, 0 );
|
|
// catagory 5 is the recently unlocked catagory, hide the progress
|
|
if ( nCurCatagory >= MEDAL_CATEGORY_COUNT || nCurCatagory < MEDAL_CATEGORY_START )
|
|
return;
|
|
|
|
int nAwards = g_PlayerRankManager.GetTotalMedalsInCategory( (MedalCategory_t)nCurCatagory );
|
|
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
m_pScaleformUI->Params_SetResult( obj, nAwards );
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::GetAchievedInCategory( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
// this list is different, unfortunately. In this list, 0 is "recently earned"
|
|
int nCurCatagory = (int) pui->Params_GetArgAsNumber( obj, 0 );
|
|
// catagory 5 is the recently unlocked catagory, hide the progress
|
|
if ( nCurCatagory >= MEDAL_CATEGORY_COUNT || nCurCatagory < MEDAL_CATEGORY_START )
|
|
return;
|
|
|
|
int nCurAwards = g_PlayerRankManager.CountAchievedInCategory( (MedalCategory_t)nCurCatagory );
|
|
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
m_pScaleformUI->Params_SetResult( obj, nCurAwards );
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::GetMinAwardNeededForRank( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
// this list is different, unfortunately. In this list, 0 is "recently earned"
|
|
int nCurCatagory = (int) pui->Params_GetArgAsNumber( obj, 0 );
|
|
// catagory 5 is the recently unlocked catagory, hide the progress
|
|
if ( nCurCatagory >= MEDAL_CATEGORY_COUNT || nCurCatagory < MEDAL_CATEGORY_START )
|
|
return;
|
|
|
|
int nRank = (int) pui->Params_GetArgAsNumber( obj, 1 );
|
|
if ( nRank >= MEDAL_RANK_COUNT || nRank < MEDAL_RANK_NONE )
|
|
return;
|
|
|
|
int nCurAwards = g_PlayerRankManager.GetMinMedalsForRank( (MedalCategory_t)nCurCatagory, (MedalRank_t)nRank );
|
|
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
m_pScaleformUI->Params_SetResult( obj, nCurAwards );
|
|
}
|
|
|
|
static int GetStatValue( int desiredStat, const StatsCollection_t& statsCollection )
|
|
{
|
|
|
|
Assert(desiredStat >= 0 && desiredStat < CSSTAT_MAX);
|
|
if ( desiredStat >= 0 && desiredStat < CSSTAT_MAX)
|
|
{
|
|
return statsCollection[desiredStat];
|
|
}
|
|
else
|
|
{
|
|
return CSSTAT_UNDEFINED;
|
|
}
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::PopulateLastMatchStats()
|
|
{
|
|
int userSlot = STEAM_PLAYER_SLOT;
|
|
|
|
#if defined ( _X360 )
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
userSlot = m_iPlayerSlot;
|
|
#endif
|
|
|
|
// We actually want to query the LASTMATCH stats from the lifetime collection, where they're written at the end of each match
|
|
const StatsCollection_t& personalMatchStats = g_CSClientGameStats.GetLifetimeStats( userSlot );
|
|
|
|
wchar_t teamStats[MAX_STATS_STRLEN];
|
|
{
|
|
int roundWonTValue = GetStatValue( CSSTAT_LASTMATCH_T_ROUNDS_WON, personalMatchStats );
|
|
int roundWonCTValue = GetStatValue( CSSTAT_LASTMATCH_CT_ROUNDS_WON, personalMatchStats );
|
|
int roundWonValue = GetStatValue( CSSTAT_LASTMATCH_ROUNDS_WON, personalMatchStats );
|
|
int maxPlayersValue = GetStatValue( CSSTAT_LASTMATCH_MAX_PLAYERS, personalMatchStats );
|
|
|
|
V_snwprintf( teamStats, ARRAYSIZE(teamStats), L"%d\n%d\n%d\n%d", roundWonTValue, roundWonCTValue, roundWonValue, maxPlayersValue );
|
|
}
|
|
|
|
const char *weaponName = "#SFUI_LastMatch_NoFaveWeapon";
|
|
const char *shortWeaponName = "weapon_none";
|
|
|
|
wchar_t weaponStats[MAX_STATS_STRLEN];
|
|
{
|
|
CSWeaponID faveWeaponID = static_cast<CSWeaponID>( GetStatValue( CSSTAT_LASTMATCH_FAVWEAPON_ID, personalMatchStats ) );
|
|
|
|
shortWeaponName = WeaponIdAsString( faveWeaponID );
|
|
|
|
const CCSWeaponInfo *pInfo = GetWeaponInfo( faveWeaponID );
|
|
if ( pInfo )
|
|
{
|
|
weaponName = pInfo->szPrintName;
|
|
}
|
|
|
|
int faveWeaponHits = GetStatValue( CSSTAT_LASTMATCH_FAVWEAPON_HITS, personalMatchStats );
|
|
int faveWeaponKills = GetStatValue( CSSTAT_LASTMATCH_FAVWEAPON_KILLS, personalMatchStats );
|
|
|
|
float accuracy = 0.0f;
|
|
int faveWeaponShots = GetStatValue( CSSTAT_LASTMATCH_FAVWEAPON_SHOTS, personalMatchStats );
|
|
|
|
if (faveWeaponShots != 0)
|
|
{
|
|
accuracy = ((float)faveWeaponHits / (float)faveWeaponShots) * 100.0f;
|
|
}
|
|
|
|
V_snwprintf( weaponStats, ARRAYSIZE( weaponStats ), L"%d\n%d\n%3.2f", faveWeaponHits, faveWeaponKills, accuracy );
|
|
}
|
|
|
|
wchar_t perfStats[MAX_STATS_STRLEN];
|
|
wchar_t miscStats[MAX_STATS_STRLEN];
|
|
{
|
|
int stars = GetStatValue( CSSTAT_LASTMATCH_MVPS, personalMatchStats );
|
|
int kills = GetStatValue( CSSTAT_LASTMATCH_KILLS, personalMatchStats );
|
|
int deaths = GetStatValue( CSSTAT_LASTMATCH_DEATHS, personalMatchStats );
|
|
int roundsPlayed = GetStatValue( CSTAT_LASTMATCH_ROUNDS_PLAYED, personalMatchStats );
|
|
int contribScore = GetStatValue( CSSTAT_LASTMATCH_CONTRIBUTION_SCORE, personalMatchStats );
|
|
|
|
float killDeathRatio = 0.f;
|
|
if (deaths > 0)
|
|
{
|
|
killDeathRatio = (float)kills / (float)deaths;
|
|
}
|
|
|
|
float contribPerRound = contribScore;
|
|
if ( roundsPlayed > 0 )
|
|
{
|
|
contribPerRound = (float)contribScore / (float)roundsPlayed;
|
|
}
|
|
|
|
V_snwprintf( perfStats, ARRAYSIZE( perfStats ), L"%d\n%d\n%d\n%.3f\n%3.1f", stars, kills, deaths, killDeathRatio, contribPerRound );
|
|
|
|
int damage = GetStatValue( CSSTAT_LASTMATCH_DAMAGE, personalMatchStats );
|
|
int dominations = GetStatValue( CSSTAT_LASTMATCH_DOMINATIONS, personalMatchStats );
|
|
int revenges = GetStatValue( CSSTAT_LASTMATCH_REVENGES, personalMatchStats );
|
|
int moneySpent = GetStatValue( CSSTAT_LASTMATCH_MONEYSPENT, personalMatchStats );
|
|
|
|
float costPerKill = 0.f;
|
|
if (kills > 0)
|
|
{
|
|
costPerKill = (float)moneySpent / (float)kills;
|
|
}
|
|
|
|
V_snwprintf( miscStats, ARRAYSIZE( miscStats ), L"%d\n%.3f\n%d\n%d", damage, costPerKill, dominations, revenges );
|
|
}
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
// Update the favorite weapon icon
|
|
{
|
|
WITH_SFVALUEARRAY( data, 1 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( data, 0, shortWeaponName );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "setLastMatchFavoriteWeapon", data, 1 );
|
|
}
|
|
}
|
|
|
|
if ( m_LastMatchTeamStats )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_LastMatchTeamStats, teamStats );
|
|
}
|
|
|
|
if ( m_LastMatchFaveWeaponName )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_LastMatchFaveWeaponName, weaponName );
|
|
}
|
|
|
|
if ( m_LastMatchFaveWeaponStats )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_LastMatchFaveWeaponStats, weaponStats );
|
|
}
|
|
|
|
if ( m_LastMatchPerfStats )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_LastMatchPerfStats, perfStats );
|
|
}
|
|
|
|
if ( m_LastMatchMiscStats )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_LastMatchMiscStats, miscStats );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCreateMedalStatsDialogScaleform::PopulateOverallStats()
|
|
{
|
|
int userSlot = STEAM_PLAYER_SLOT;
|
|
|
|
const char *playerName = "Player";
|
|
{
|
|
SF_FORCE_SPLITSCREEN_PLAYER_GUARD( m_iPlayerSlot );
|
|
IPlayerLocal *pProfile = g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->GetLocalPlayer( XBX_GetUserId( m_iPlayerSlot ) );
|
|
if ( pProfile )
|
|
{
|
|
playerName = pProfile->GetName();
|
|
}
|
|
userSlot = m_iPlayerSlot;
|
|
}
|
|
|
|
const StatsCollection_t& lifetimeStats = g_CSClientGameStats.GetLifetimeStats( userSlot );
|
|
|
|
wchar_t starsText[MAX_STATS_STRLEN];
|
|
{
|
|
int numMVPs = GetStatValue( CSSTAT_MVPS, lifetimeStats );
|
|
V_snwprintf( starsText, ARRAYSIZE( starsText ), g_pVGuiLocalize->Find("#SFUI_Overall_Stars"), numMVPs );
|
|
}
|
|
|
|
wchar_t playerStats[MAX_STATS_STRLEN];
|
|
{
|
|
int roundsPlayed = GetStatValue( CSSTAT_ROUNDS_PLAYED, lifetimeStats );
|
|
int roundsWon = GetStatValue( CSSTAT_ROUNDS_WON, lifetimeStats );
|
|
int shotsFired = GetStatValue( CSSTAT_SHOTS_FIRED, lifetimeStats );
|
|
int shotsHit = GetStatValue( CSSTAT_SHOTS_HIT, lifetimeStats );
|
|
int numKills = GetStatValue( CSSTAT_KILLS, lifetimeStats );
|
|
int numDeaths = GetStatValue( CSSTAT_DEATHS, lifetimeStats );
|
|
|
|
float winPct = 0.f;
|
|
if ( roundsPlayed > 0 )
|
|
{
|
|
winPct = (float)roundsWon / (float)roundsPlayed * 100.0f;
|
|
}
|
|
|
|
float hitRatio = 0.f;
|
|
if ( shotsFired > 0 )
|
|
{
|
|
hitRatio = (float)shotsHit / (float)shotsFired;
|
|
}
|
|
|
|
float killDeathRatio = 0.f;
|
|
if ( numDeaths > 0 )
|
|
{
|
|
killDeathRatio = (float)numKills / (float)numDeaths;
|
|
}
|
|
|
|
V_snwprintf( playerStats, ARRAYSIZE( playerStats ), L"%d\n%d\n%3.2f\n%d\n%d\n%3.2f\n\n%d\n%d\n%.3f", roundsPlayed, roundsWon, winPct,
|
|
shotsFired, shotsHit, hitRatio, numKills, numDeaths, killDeathRatio );
|
|
}
|
|
|
|
const char *shortMapName = "map_none";
|
|
const wchar_t* wszFaveMapName;
|
|
wchar_t mapStats[MAX_STATS_STRLEN];
|
|
|
|
{
|
|
wszFaveMapName = g_pVGuiLocalize->Find("#SFUI_Overall_NoFavorite");
|
|
|
|
// determine which map we've played the most
|
|
const MapName_MapStatId* pFavoriteMapStat = NULL;
|
|
int numRounds = 0;
|
|
for (int i = 0; MapName_StatId_Table[i].statWinsId != CSSTAT_UNDEFINED; ++i)
|
|
{
|
|
const MapName_MapStatId& mapStatId = MapName_StatId_Table[i];
|
|
PlayerStatData_t stat = g_CSClientGameStats.GetStatById( mapStatId.statRoundsId, userSlot );
|
|
if (stat.iStatValue > numRounds)
|
|
{
|
|
pFavoriteMapStat = &mapStatId;
|
|
numRounds = stat.iStatValue;
|
|
}
|
|
}
|
|
|
|
numRounds = 0;
|
|
int numWins = 0;
|
|
float winPct = 0.f;
|
|
|
|
// use the values from our favorite map
|
|
if ( pFavoriteMapStat )
|
|
{
|
|
shortMapName = pFavoriteMapStat->szMapName;
|
|
wszFaveMapName = CSGameRules()->GetFriendlyMapName(shortMapName);
|
|
|
|
numWins = g_CSClientGameStats.GetStatById( pFavoriteMapStat->statWinsId, userSlot ).iStatValue;
|
|
numRounds = g_CSClientGameStats.GetStatById( pFavoriteMapStat->statRoundsId, userSlot ).iStatValue;
|
|
|
|
if (numRounds > 0)
|
|
{
|
|
winPct = ((float)numWins / (float)numRounds) * 100.0f;
|
|
}
|
|
}
|
|
|
|
V_snwprintf( mapStats, ARRAYSIZE( mapStats ), g_pVGuiLocalize->Find("#SFUI_Overall_MapStats"), wszFaveMapName, numRounds, numWins, winPct );
|
|
}
|
|
|
|
const char *shortWeaponName = "weapon_none";
|
|
const char *weaponName = "#SFUI_Overall_NoFavorite";
|
|
|
|
wchar_t faveWeaponStats[MAX_STATS_STRLEN];
|
|
{
|
|
const WeaponName_StatId* pFavoriteWeaponStatEntry = NULL;
|
|
|
|
// Find the weapon stat with the most kills
|
|
int numKills = 0;
|
|
for (int i = 0; WeaponName_StatId_Table[i].killStatId != CSSTAT_UNDEFINED; ++i)
|
|
{
|
|
// ignore weapons with no hit counts (knife and grenade)
|
|
if (WeaponName_StatId_Table[i].hitStatId == CSSTAT_UNDEFINED )
|
|
continue;
|
|
|
|
const WeaponName_StatId& weaponStatEntry = WeaponName_StatId_Table[i];
|
|
PlayerStatData_t stat = g_CSClientGameStats.GetStatById( weaponStatEntry.killStatId, userSlot );
|
|
if (stat.iStatValue > numKills)
|
|
{
|
|
pFavoriteWeaponStatEntry = &weaponStatEntry;
|
|
numKills = stat.iStatValue;
|
|
}
|
|
}
|
|
|
|
int hits = 0;
|
|
int shots = 0;
|
|
int kills = 0;
|
|
float killsPerShot = 0.f;
|
|
|
|
if (pFavoriteWeaponStatEntry)
|
|
{
|
|
CSWeaponID faveWeaponID = static_cast<CSWeaponID>( pFavoriteWeaponStatEntry->weaponId );
|
|
|
|
shortWeaponName = WeaponIdAsString( faveWeaponID );
|
|
const CCSWeaponInfo *pInfo = GetWeaponInfo( faveWeaponID );
|
|
if ( pInfo )
|
|
{
|
|
weaponName = pInfo->szPrintName;
|
|
}
|
|
|
|
hits = g_CSClientGameStats.GetStatById( pFavoriteWeaponStatEntry->hitStatId, userSlot ).iStatValue;
|
|
shots = g_CSClientGameStats.GetStatById( pFavoriteWeaponStatEntry->shotStatId, userSlot ).iStatValue;
|
|
kills = g_CSClientGameStats.GetStatById( pFavoriteWeaponStatEntry->killStatId, userSlot ).iStatValue;
|
|
|
|
// Do we want accuracy, or kills/shot?
|
|
if (shots > 0)
|
|
{
|
|
killsPerShot = (float)kills / (float)shots;
|
|
}
|
|
}
|
|
|
|
V_snwprintf( faveWeaponStats, ARRAYSIZE( faveWeaponStats ), L"%d\n%d\n%d\n%.3f", shots, hits, kills, killsPerShot );
|
|
}
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
// Update the favorite weapon & map icon
|
|
{
|
|
WITH_SFVALUEARRAY( data, 2 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( data, 0, shortWeaponName );
|
|
m_pScaleformUI->ValueArray_SetElement( data, 1, shortMapName );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "setOverallFavoriteWeaponAndMap", data, 2 );
|
|
}
|
|
}
|
|
|
|
if ( m_OverallPlayerName )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_OverallPlayerName, playerName );
|
|
}
|
|
|
|
if ( m_OverallMVPsText )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_OverallMVPsText, starsText );
|
|
}
|
|
|
|
if ( m_OverallPlayerStats )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_OverallPlayerStats, playerStats );
|
|
}
|
|
|
|
if ( m_OverallFaveWeaponName )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_OverallFaveWeaponName, weaponName );
|
|
}
|
|
|
|
if ( m_OverallFaveWeaponStats )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_OverallFaveWeaponStats, faveWeaponStats );
|
|
}
|
|
|
|
if ( m_OverallFaveMapStats )
|
|
{
|
|
m_pScaleformUI->Value_SetText( m_OverallFaveMapStats, mapStats );
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|