1203 lines
41 KiB
C++
1203 lines
41 KiB
C++
#include "stdafx.h"
|
|
#include <xuiresource.h>
|
|
#include <xuiapp.h>
|
|
#include "XUI_Leaderboards.h"
|
|
#include "..\..\..\Minecraft.World\Tile.h"
|
|
#include "..\..\..\Minecraft.World\Item.h"
|
|
#include "XUI_Ctrl_CraftIngredientSlot.h"
|
|
#include "XUI_XZP_Icons.h"
|
|
|
|
LPCWSTR CScene_Leaderboards::m_TitleIconNameA[7]=
|
|
{
|
|
L"XuiHSlot1",
|
|
L"XuiHSlot2",
|
|
L"XuiHSlot3",
|
|
L"XuiHSlot4",
|
|
L"XuiHSlot5",
|
|
L"XuiHSlot6",
|
|
L"XuiHSlot7",
|
|
};
|
|
|
|
LPCWSTR CScene_Leaderboards::m_TextColumnNameA[7]=
|
|
{
|
|
L"text_Column1",
|
|
L"text_Column2",
|
|
L"text_Column3",
|
|
L"text_Column4",
|
|
L"text_Column5",
|
|
L"text_Column6",
|
|
L"text_Column7",
|
|
};
|
|
|
|
|
|
// if the value is greater than 511, it's an xzp icon that needs displayed, rather than the game icon
|
|
const int CScene_Leaderboards::TitleIcons[CScene_Leaderboards::NUM_LEADERBOARDS][7] =
|
|
{
|
|
{ XZP_ICON_WALKED, XZP_ICON_FALLEN, Item::minecart_Id, Item::boat_Id, NULL },
|
|
{ Tile::dirt_Id, Tile::stoneBrick_Id, Tile::sand_Id, Tile::rock_Id, Tile::gravel_Id, Tile::clay_Id, Tile::obsidian_Id },
|
|
{ Item::egg_Id, Item::wheat_Id, Tile::mushroom1_Id, Tile::reeds_Id, Item::milk_Id, Tile::pumpkin_Id, NULL },
|
|
{ XZP_ICON_ZOMBIE, XZP_ICON_SKELETON, XZP_ICON_CREEPER, XZP_ICON_SPIDER, XZP_ICON_SPIDERJOCKEY, XZP_ICON_ZOMBIEPIGMAN, XZP_ICON_SLIME },
|
|
};
|
|
|
|
const int CScene_Leaderboards::LEADERBOARD_HEADERS[CScene_Leaderboards::NUM_LEADERBOARDS][4] = {
|
|
{ SPASTRING_LB_TRAVELLING_PEACEFUL_NAME, SPASTRING_LB_TRAVELLING_EASY_NAME, SPASTRING_LB_TRAVELLING_NORMAL_NAME, SPASTRING_LB_TRAVELLING_HARD_NAME },
|
|
{ SPASTRING_LB_MINING_BLOCKS_PEACEFUL_NAME, SPASTRING_LB_MINING_BLOCKS_EASY_NAME, SPASTRING_LB_MINING_BLOCKS_NORMAL_NAME, SPASTRING_LB_MINING_BLOCKS_HARD_NAME },
|
|
{ SPASTRING_LB_FARMING_PEACEFUL_NAME, SPASTRING_LB_FARMING_EASY_NAME, SPASTRING_LB_FARMING_NORMAL_NAME, SPASTRING_LB_FARMING_HARD_NAME },
|
|
{ NULL, SPASTRING_LB_KILLS_EASY_NAME, SPASTRING_LB_KILLS_NORMAL_NAME, SPASTRING_LB_KILLS_HARD_NAME },
|
|
};
|
|
|
|
const CScene_Leaderboards::LeaderboardDescriptor CScene_Leaderboards::LEADERBOARD_DESCRIPTORS[CScene_Leaderboards::NUM_LEADERBOARDS][4] = {
|
|
{
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_TRAVELLING_PEACEFUL, 4, STATS_COLUMN_TRAVELLING_PEACEFUL_WALKED, STATS_COLUMN_TRAVELLING_PEACEFUL_FALLEN, STATS_COLUMN_TRAVELLING_PEACEFUL_MINECART, STATS_COLUMN_TRAVELLING_PEACEFUL_BOAT, NULL, NULL, NULL,NULL),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_TRAVELLING_EASY, 4, STATS_COLUMN_TRAVELLING_EASY_WALKED, STATS_COLUMN_TRAVELLING_EASY_FALLEN, STATS_COLUMN_TRAVELLING_EASY_MINECART, STATS_COLUMN_TRAVELLING_EASY_BOAT, NULL, NULL, NULL,NULL),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_TRAVELLING_NORMAL, 4, STATS_COLUMN_TRAVELLING_NORMAL_WALKED, STATS_COLUMN_TRAVELLING_NORMAL_FALLEN, STATS_COLUMN_TRAVELLING_NORMAL_MINECART, STATS_COLUMN_TRAVELLING_NORMAL_BOAT, NULL, NULL, NULL,NULL),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_TRAVELLING_HARD, 4, STATS_COLUMN_TRAVELLING_HARD_WALKED, STATS_COLUMN_TRAVELLING_HARD_FALLEN, STATS_COLUMN_TRAVELLING_HARD_MINECART, STATS_COLUMN_TRAVELLING_HARD_BOAT, NULL, NULL, NULL,NULL),
|
|
},
|
|
{
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_MINING_BLOCKS_PEACEFUL, 7, STATS_COLUMN_MINING_BLOCKS_PEACEFUL_DIRT, STATS_COLUMN_MINING_BLOCKS_PEACEFUL_STONE, STATS_COLUMN_MINING_BLOCKS_PEACEFUL_SAND, STATS_COLUMN_MINING_BLOCKS_PEACEFUL_COBBLESTONE, STATS_COLUMN_MINING_BLOCKS_PEACEFUL_GRAVEL, STATS_COLUMN_MINING_BLOCKS_PEACEFUL_CLAY, STATS_COLUMN_MINING_BLOCKS_PEACEFUL_OBSIDIAN,NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_MINING_BLOCKS_EASY, 7, STATS_COLUMN_MINING_BLOCKS_EASY_DIRT, STATS_COLUMN_MINING_BLOCKS_EASY_STONE, STATS_COLUMN_MINING_BLOCKS_EASY_SAND, STATS_COLUMN_MINING_BLOCKS_EASY_COBBLESTONE, STATS_COLUMN_MINING_BLOCKS_EASY_GRAVEL, STATS_COLUMN_MINING_BLOCKS_EASY_CLAY, STATS_COLUMN_MINING_BLOCKS_EASY_OBSIDIAN,NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_MINING_BLOCKS_NORMAL, 7, STATS_COLUMN_MINING_BLOCKS_NORMAL_DIRT, STATS_COLUMN_MINING_BLOCKS_NORMAL_STONE, STATS_COLUMN_MINING_BLOCKS_NORMAL_SAND, STATS_COLUMN_MINING_BLOCKS_NORMAL_COBBLESTONE, STATS_COLUMN_MINING_BLOCKS_NORMAL_GRAVEL, STATS_COLUMN_MINING_BLOCKS_NORMAL_CLAY, STATS_COLUMN_MINING_BLOCKS_NORMAL_OBSIDIAN,NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_MINING_BLOCKS_HARD, 7, STATS_COLUMN_MINING_BLOCKS_HARD_DIRT, STATS_COLUMN_MINING_BLOCKS_HARD_STONE, STATS_COLUMN_MINING_BLOCKS_HARD_SAND, STATS_COLUMN_MINING_BLOCKS_HARD_COBBLESTONE, STATS_COLUMN_MINING_BLOCKS_HARD_GRAVEL, STATS_COLUMN_MINING_BLOCKS_HARD_CLAY, STATS_COLUMN_MINING_BLOCKS_HARD_OBSIDIAN,NULL ),
|
|
},
|
|
{
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_FARMING_PEACEFUL, 6, STATS_COLUMN_FARMING_PEACEFUL_EGGS, STATS_COLUMN_FARMING_PEACEFUL_WHEAT, STATS_COLUMN_FARMING_PEACEFUL_MUSHROOMS, STATS_COLUMN_FARMING_PEACEFUL_SUGARCANE, STATS_COLUMN_FARMING_PEACEFUL_MILK, STATS_COLUMN_FARMING_PEACEFUL_PUMPKINS, NULL,NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_FARMING_EASY, 6, STATS_COLUMN_FARMING_EASY_EGGS, STATS_COLUMN_FARMING_PEACEFUL_WHEAT, STATS_COLUMN_FARMING_EASY_MUSHROOMS, STATS_COLUMN_FARMING_EASY_SUGARCANE, STATS_COLUMN_FARMING_EASY_MILK, STATS_COLUMN_FARMING_EASY_PUMPKINS, NULL,NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_FARMING_NORMAL, 6, STATS_COLUMN_FARMING_NORMAL_EGGS, STATS_COLUMN_FARMING_NORMAL_WHEAT, STATS_COLUMN_FARMING_NORMAL_MUSHROOMS, STATS_COLUMN_FARMING_NORMAL_SUGARCANE, STATS_COLUMN_FARMING_NORMAL_MILK, STATS_COLUMN_FARMING_NORMAL_PUMPKINS, NULL,NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_FARMING_HARD, 6, STATS_COLUMN_FARMING_HARD_EGGS, STATS_COLUMN_FARMING_HARD_WHEAT, STATS_COLUMN_FARMING_HARD_MUSHROOMS, STATS_COLUMN_FARMING_HARD_SUGARCANE, STATS_COLUMN_FARMING_HARD_MILK, STATS_COLUMN_FARMING_HARD_PUMPKINS, NULL,NULL ),
|
|
},
|
|
{
|
|
CScene_Leaderboards::LeaderboardDescriptor( NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_KILLS_EASY, 7, STATS_COLUMN_KILLS_EASY_ZOMBIES, STATS_COLUMN_KILLS_EASY_SKELETONS, STATS_COLUMN_KILLS_EASY_CREEPERS, STATS_COLUMN_KILLS_EASY_SPIDERS, STATS_COLUMN_KILLS_EASY_SPIDERJOCKEYS, STATS_COLUMN_KILLS_EASY_ZOMBIEPIGMEN, STATS_COLUMN_KILLS_EASY_SLIME,NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_KILLS_NORMAL, 7, STATS_COLUMN_KILLS_NORMAL_ZOMBIES, STATS_COLUMN_KILLS_NORMAL_SKELETONS, STATS_COLUMN_KILLS_NORMAL_CREEPERS, STATS_COLUMN_KILLS_NORMAL_SPIDERS, STATS_COLUMN_KILLS_NORMAL_SPIDERJOCKEYS, STATS_COLUMN_KILLS_NORMAL_ZOMBIEPIGMEN, STATS_COLUMN_KILLS_NORMAL_SLIME,NULL ),
|
|
CScene_Leaderboards::LeaderboardDescriptor( STATS_VIEW_KILLS_HARD, 7, STATS_COLUMN_KILLS_HARD_ZOMBIES, STATS_COLUMN_KILLS_HARD_SKELETONS, STATS_COLUMN_KILLS_HARD_CREEPERS, STATS_COLUMN_KILLS_HARD_SPIDERS, STATS_COLUMN_KILLS_HARD_SPIDERJOCKEYS, STATS_COLUMN_KILLS_HARD_ZOMBIEPIGMEN, STATS_COLUMN_KILLS_HARD_SLIME,NULL ),
|
|
},
|
|
};
|
|
|
|
HRESULT CScene_Leaderboards::OnInit(XUIMessageInit *pInitData, BOOL &bHandled)
|
|
{
|
|
m_iPad = *(int *)pInitData->pvInitData;
|
|
MapChildControls();
|
|
m_bReady=false;
|
|
|
|
// if we're not in the game, we need to use basescene 0
|
|
if(Minecraft::GetInstance()->level==NULL)
|
|
{
|
|
m_iPad=DEFAULT_XUI_MENU_USER;
|
|
}
|
|
|
|
m_bPopulatedOnce = false;
|
|
|
|
ui.SetTooltips(m_iPad,-1, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGE_FILTER, -1);
|
|
CXuiSceneBase::ShowLogo( m_iPad, FALSE );
|
|
|
|
m_friends = NULL;
|
|
m_numFriends = 0;
|
|
m_filteredFriends = NULL;
|
|
m_numFilteredFriends = 0;
|
|
|
|
m_newTop = m_newSel = -1;
|
|
|
|
m_isProcessingStatsRead = false;
|
|
|
|
// Alert the app the we want to be informed of ethernet connections
|
|
app.SetLiveLinkRequired( true );
|
|
|
|
LeaderboardManager::Instance()->OpenSession();
|
|
|
|
//GetFriends();
|
|
|
|
m_currentLeaderboard = 0;
|
|
m_currentDifficulty = 2;
|
|
SetLeaderboardHeader();
|
|
|
|
m_currentFilter = LeaderboardManager::eFM_Friends;
|
|
wchar_t filterBuffer[40];
|
|
swprintf(filterBuffer, 40, L"%ls%ls", app.GetString(IDS_LEADERBOARD_FILTER), app.GetString(IDS_LEADERBOARD_FILTER_FRIENDS));
|
|
m_textFilter.SetText(filterBuffer);
|
|
|
|
wchar_t entriesBuffer[40];
|
|
swprintf(entriesBuffer, 40, L"%ls%i", app.GetString(IDS_LEADERBOARD_ENTRIES), 0);
|
|
m_textEntries.SetText(entriesBuffer);
|
|
|
|
ReadStats(-1);
|
|
|
|
// title icons
|
|
for(int i=0;i<7;i++)
|
|
{
|
|
m_pHTitleIconSlots[i]=NULL;
|
|
m_fTitleIconXPositions[i]=0.0f;
|
|
m_fTextXPositions[i]=0.0f;
|
|
m_hTextEntryA[i]=NULL;
|
|
}
|
|
|
|
|
|
bHandled = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void CScene_Leaderboards::Reposition(int iNumber)
|
|
{
|
|
float fIconSize; // including gap
|
|
float fNewIconIncrement;
|
|
D3DXVECTOR3 vPos;
|
|
|
|
fIconSize=(m_fTitleIconXPositions[6]-m_fTitleIconXPositions[0])/6.0f;
|
|
fNewIconIncrement=(fIconSize*7.0f)/(float)iNumber;
|
|
|
|
// reposition the title icons based on the number there are
|
|
for(int i=0;i<iNumber;i++)
|
|
{
|
|
m_pHTitleIconSlots[i]->GetPosition(&vPos);
|
|
vPos.x=m_fTitleIconXPositions[0]+(((float)i)*fNewIconIncrement)+(fNewIconIncrement-fIconSize)/2.0f;
|
|
m_pHTitleIconSlots[i]->SetPosition(&vPos);
|
|
}
|
|
}
|
|
|
|
void CScene_Leaderboards::RepositionText(int iNumber)
|
|
{
|
|
float fTextSize; // including gap
|
|
float fNewTextIncrement;
|
|
D3DXVECTOR3 vPos;
|
|
|
|
fTextSize=(m_fTextXPositions[6]-m_fTextXPositions[0])/6.0f;
|
|
fNewTextIncrement=(fTextSize*7.0f)/(float)iNumber;
|
|
|
|
// reposition the title icons based on the number there are
|
|
for(int i=0;i<iNumber;i++)
|
|
{
|
|
// and reposition the text
|
|
XuiElementGetPosition(m_hTextEntryA[i],&vPos);
|
|
vPos.x=m_fTextXPositions[0]+(((float)i)*fNewTextIncrement);
|
|
XuiElementSetPosition(m_hTextEntryA[i],&vPos);
|
|
// and change the size
|
|
float fWidth,fHeight;
|
|
XuiElementGetBounds(m_hTextEntryA[i],&fWidth,&fHeight);
|
|
XuiElementSetBounds(m_hTextEntryA[i],fNewTextIncrement,fHeight);
|
|
}
|
|
}
|
|
|
|
HRESULT CScene_Leaderboards::OnDestroy()
|
|
{
|
|
LeaderboardManager::Instance()->CancelOperation();
|
|
LeaderboardManager::Instance()->CloseSession();
|
|
|
|
// Alert the app the we no longer want to be informed of ethernet connections
|
|
app.SetLiveLinkRequired( false );
|
|
|
|
while( m_isProcessingStatsRead )
|
|
{
|
|
Sleep( 10 );
|
|
}
|
|
|
|
if( m_friends != NULL )
|
|
delete [] m_friends;
|
|
|
|
if( m_filteredFriends != NULL )
|
|
delete [] m_filteredFriends;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CScene_Leaderboards::OnNotifySetFocus(HXUIOBJ hObjSource, XUINotifyFocus *pNotifyFocusData, BOOL& bHandled)
|
|
{
|
|
UpdateTooltips();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CScene_Leaderboards::OnNotifySelChanged(HXUIOBJ hObjSource, XUINotifySelChanged *pNotifySelChangedData, BOOL& bHandled)
|
|
{
|
|
|
|
if(m_bReady && pNotifySelChangedData->iOldItem!=-1)
|
|
{
|
|
CXuiSceneBase::PlayUISFX(eSFX_Focus);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CScene_Leaderboards::UpdateTooltips()
|
|
{
|
|
int iTooltipFriendRequest=-1;
|
|
int iTooltipGamerCardOrProfile=-1;
|
|
if( m_leaderboard.m_currentEntryCount > 0 )
|
|
{
|
|
unsigned int selection = (unsigned int)m_listGamers.GetCurSel();
|
|
|
|
// if the selected user is me, don't show Send Friend Request, and show the gamer profile, not the gamer card
|
|
|
|
// Check that the index is actually within range of the data we've got before accessing the m_leaderboard.m_entries array
|
|
int idx = selection - (m_leaderboard.m_entryStartIndex-1);
|
|
if( ( idx < 0 ) || ( idx >= NUM_ENTRIES ) )
|
|
{
|
|
return;
|
|
}
|
|
if(m_leaderboard.m_entries[idx].m_bPlayer)
|
|
{
|
|
iTooltipGamerCardOrProfile=IDS_TOOLTIPS_VIEW_GAMERPROFILE;
|
|
}
|
|
else
|
|
{
|
|
iTooltipGamerCardOrProfile=IDS_TOOLTIPS_VIEW_GAMERCARD;
|
|
// if we're on the friends filter, then don't show the Send Friend Request
|
|
bool bIsFriend = m_currentFilter == LeaderboardManager::eFM_Friends;
|
|
|
|
if(!bIsFriend)
|
|
{
|
|
// check the entry we're on
|
|
if( m_leaderboard.m_currentEntryCount > 0 )
|
|
{
|
|
if( selection >= m_leaderboard.m_entryStartIndex-1 &&
|
|
selection < (m_leaderboard.m_entryStartIndex+m_leaderboard.m_currentEntryCount-1) )
|
|
{
|
|
if( (m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1)].m_bFriend==false) && (m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1)].m_bRequestedFriend==false))
|
|
{
|
|
iTooltipFriendRequest=IDS_TOOLTIPS_SEND_FRIEND_REQUEST;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 4J-PB - no room on the screen for the LT/RT prompt
|
|
/*
|
|
if(m_leaderboard.m_currentEntryCount>11)
|
|
{
|
|
ui.SetTooltips(m_iPad, iTooltipFriendRequest, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGE_FILTER, iTooltipGamerCardOrProfile, IDS_TOOLTIPS_PAGEUP, IDS_TOOLTIPS_PAGEDOWN);
|
|
}
|
|
else*/
|
|
{
|
|
ui.SetTooltips(m_iPad, iTooltipFriendRequest, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGE_FILTER, iTooltipGamerCardOrProfile);
|
|
}
|
|
}
|
|
|
|
HRESULT CScene_Leaderboards::OnKeyDown(XUIMessageInput* pInputData, BOOL& bHandled)
|
|
{
|
|
ui.AnimateKeyPress(pInputData->UserIndex, pInputData->dwKeyCode);
|
|
|
|
switch(pInputData->dwKeyCode)
|
|
{
|
|
case VK_PAD_RSHOULDER:
|
|
case VK_PAD_LSHOULDER:
|
|
{
|
|
//Do nothing if a stats read is currently in progress, otherwise the system complains about to many read requests
|
|
if(m_bPopulatedOnce && LeaderboardManager::Instance()->isIdle() )
|
|
{
|
|
if( pInputData->dwKeyCode == VK_PAD_RSHOULDER )
|
|
{
|
|
++m_currentDifficulty;
|
|
if( m_currentDifficulty == 4 )
|
|
m_currentDifficulty = 0;
|
|
|
|
if( m_currentLeaderboard == LEADERBOARD_KILLS_POSITION && m_currentDifficulty == 0 )
|
|
m_currentDifficulty = 1;
|
|
}
|
|
else
|
|
{
|
|
if( m_currentDifficulty == 0 )
|
|
m_currentDifficulty = 4;
|
|
--m_currentDifficulty;
|
|
|
|
if( m_currentLeaderboard == LEADERBOARD_KILLS_POSITION && m_currentDifficulty == 0 )
|
|
m_currentDifficulty = 3;
|
|
}
|
|
|
|
SetLeaderboardHeader();
|
|
ClearLeaderboardTitlebar();
|
|
|
|
ReadStats(-1);
|
|
CXuiSceneBase::PlayUISFX(eSFX_Press);
|
|
}
|
|
|
|
bHandled = TRUE;
|
|
}
|
|
break;
|
|
case VK_PAD_LTHUMB_RIGHT:
|
|
case VK_PAD_LTHUMB_LEFT:
|
|
case VK_PAD_DPAD_LEFT:
|
|
case VK_PAD_DPAD_RIGHT:
|
|
{
|
|
//Do nothing if a stats read is currently in progress, otherwise the system complains about to many read requests
|
|
if ( m_bPopulatedOnce && LeaderboardManager::Instance()->isIdle() )
|
|
{
|
|
m_bReady=false;
|
|
if(( pInputData->dwKeyCode == VK_PAD_LTHUMB_RIGHT ) ||(pInputData->dwKeyCode == VK_PAD_DPAD_RIGHT))
|
|
{
|
|
++m_currentLeaderboard;
|
|
if( m_currentLeaderboard == NUM_LEADERBOARDS )
|
|
m_currentLeaderboard = 0;
|
|
}
|
|
else
|
|
{
|
|
if( m_currentLeaderboard == 0 )
|
|
m_currentLeaderboard = NUM_LEADERBOARDS;
|
|
--m_currentLeaderboard;
|
|
}
|
|
|
|
if( m_currentLeaderboard == LEADERBOARD_KILLS_POSITION && m_currentDifficulty == 0 )
|
|
m_currentDifficulty = 1;
|
|
|
|
SetLeaderboardHeader();
|
|
ClearLeaderboardTitlebar();
|
|
|
|
|
|
ReadStats(-1);
|
|
CXuiSceneBase::PlayUISFX(eSFX_Press);
|
|
}
|
|
bHandled = TRUE;
|
|
}
|
|
break;
|
|
case VK_PAD_LTRIGGER:
|
|
case VK_PAD_RTRIGGER:
|
|
{
|
|
//Do nothing if a stats read is currently in progress, otherwise the system complains about to many read requests
|
|
if( m_bPopulatedOnce && LeaderboardManager::Instance()->isIdle() )
|
|
{
|
|
if( m_leaderboard.m_totalEntryCount <= 10 )
|
|
break;
|
|
|
|
if( pInputData->dwKeyCode == VK_PAD_LTRIGGER )
|
|
{
|
|
m_newTop = m_listGamers.GetTopItem() - 10;
|
|
if( m_newTop < 0 )
|
|
m_newTop = 0;
|
|
|
|
m_newSel = m_newTop;
|
|
}
|
|
else
|
|
{
|
|
m_newTop = m_listGamers.GetTopItem() + 10;
|
|
if( m_newTop+10 > (int)m_leaderboard.m_totalEntryCount )
|
|
{
|
|
m_newTop = m_leaderboard.m_totalEntryCount - 10;
|
|
if( m_newTop < 0 )
|
|
m_newTop = 0;
|
|
}
|
|
|
|
m_newSel = m_newTop;
|
|
}
|
|
//CXuiSceneBase::PlayUISFX(eSFX_Press);
|
|
}
|
|
bHandled = TRUE;
|
|
}
|
|
break;
|
|
case VK_PAD_X:
|
|
{
|
|
//Do nothing if a stats read is currently in progress, otherwise the system complains about to many read requests
|
|
if( m_bPopulatedOnce && LeaderboardManager::Instance()->isIdle() )
|
|
{
|
|
switch( m_currentFilter )
|
|
{
|
|
case LeaderboardManager::eFM_Friends:
|
|
{
|
|
m_currentFilter = LeaderboardManager::eFM_MyScore;
|
|
wchar_t filterBuffer[40];
|
|
swprintf_s(filterBuffer, 40, L"%ls%ls", app.GetString(IDS_LEADERBOARD_FILTER), app.GetString(IDS_LEADERBOARD_FILTER_MYSCORE));
|
|
m_textFilter.SetText(filterBuffer);
|
|
}
|
|
break;
|
|
case LeaderboardManager::eFM_MyScore:
|
|
{
|
|
m_currentFilter = LeaderboardManager::eFM_TopRank;
|
|
wchar_t filterBuffer[40];
|
|
swprintf_s(filterBuffer, 40, L"%ls%ls", app.GetString(IDS_LEADERBOARD_FILTER), app.GetString(IDS_LEADERBOARD_FILTER_OVERALL));
|
|
m_textFilter.SetText(filterBuffer);
|
|
}
|
|
break;
|
|
case LeaderboardManager::eFM_TopRank:
|
|
{
|
|
m_currentFilter = LeaderboardManager::eFM_Friends;
|
|
wchar_t filterBuffer[40];
|
|
swprintf_s(filterBuffer, 40, L"%ls%ls", app.GetString(IDS_LEADERBOARD_FILTER), app.GetString(IDS_LEADERBOARD_FILTER_FRIENDS));
|
|
m_textFilter.SetText(filterBuffer);
|
|
}
|
|
break;
|
|
}
|
|
|
|
ReadStats(-1);
|
|
CXuiSceneBase::PlayUISFX(eSFX_Press);
|
|
}
|
|
bHandled = TRUE;
|
|
}
|
|
break;
|
|
case VK_PAD_Y:
|
|
{
|
|
//Show gamercard
|
|
if( m_leaderboard.m_currentEntryCount > 0 )
|
|
{
|
|
unsigned int selection = (unsigned int)m_listGamers.GetCurSel();
|
|
if( selection >= m_leaderboard.m_entryStartIndex-1 &&
|
|
selection < (m_leaderboard.m_entryStartIndex+m_leaderboard.m_currentEntryCount-1) )
|
|
{
|
|
PlayerUID xuid = m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1)].m_xuid;
|
|
if( xuid != INVALID_XUID )
|
|
{
|
|
XShowGamerCardUI(ProfileManager.GetLockedProfile(), xuid);
|
|
CXuiSceneBase::PlayUISFX(eSFX_Press);
|
|
}
|
|
}
|
|
}
|
|
bHandled = TRUE;
|
|
}
|
|
break;
|
|
case VK_PAD_A:
|
|
{
|
|
//Send friend request if the filter mode is not friend, and they're not a friend or a pending friend
|
|
if( m_currentFilter != LeaderboardManager::eFM_Friends )
|
|
{
|
|
if( m_leaderboard.m_currentEntryCount > 0 )
|
|
{
|
|
unsigned int selection = (unsigned int)m_listGamers.GetCurSel();
|
|
if( selection >= m_leaderboard.m_entryStartIndex-1 &&
|
|
selection < (m_leaderboard.m_entryStartIndex+m_leaderboard.m_currentEntryCount-1) )
|
|
{
|
|
//If not the player and neither currently a friend or requested to be a friend
|
|
if( !m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1) ].m_bPlayer &&
|
|
!m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1) ].m_bFriend &&
|
|
!m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1) ].m_bRequestedFriend )
|
|
{
|
|
PlayerUID xuid = m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1) ].m_xuid;
|
|
if( xuid != INVALID_XUID )
|
|
{
|
|
XShowFriendRequestUI(ProfileManager.GetLockedProfile(), xuid);
|
|
CXuiSceneBase::PlayUISFX(eSFX_Press);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bHandled = TRUE;
|
|
}
|
|
break;
|
|
case VK_PAD_B:
|
|
case VK_ESCAPE:
|
|
{
|
|
BYTE userIndex = pInputData->UserIndex;
|
|
if( !app.IsPauseMenuDisplayed(userIndex) )
|
|
{
|
|
// If we are not from a pause menu, then we are from the main menu
|
|
userIndex = XUSER_INDEX_ANY;
|
|
}
|
|
|
|
app.NavigateBack(userIndex);
|
|
bHandled = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
// DELETING //
|
|
#if 0
|
|
void CScene_Leaderboards::GetFriends()
|
|
{
|
|
DWORD resultsSize;
|
|
HANDLE hEnumerator;
|
|
DWORD ret;
|
|
|
|
m_numFriends = 0;
|
|
|
|
//First, get a list of (up to 100) friends (this is the maximum that the enumerator currently supports)
|
|
ret = XFriendsCreateEnumerator( ProfileManager.GetLockedProfile(), 0, 100, &resultsSize, &hEnumerator);
|
|
if( ret != ERROR_SUCCESS )
|
|
return;
|
|
|
|
m_friends = (XONLINE_FRIEND*) new BYTE[ resultsSize ];
|
|
DWORD numFriends;
|
|
|
|
ret = XEnumerate(
|
|
hEnumerator,
|
|
m_friends,
|
|
resultsSize,
|
|
&numFriends,
|
|
NULL );
|
|
|
|
if( ret != ERROR_SUCCESS )
|
|
numFriends = 0;
|
|
|
|
m_numFriends = numFriends;
|
|
|
|
m_filteredFriends = new PlayerUID[m_numFriends+1];
|
|
|
|
m_numFilteredFriends = 0;
|
|
for( unsigned int friendIndex=0 ; friendIndex<numFriends ; ++friendIndex )
|
|
{
|
|
if( ( m_friends[friendIndex].dwFriendState & ( XONLINE_FRIENDSTATE_FLAG_SENTREQUEST | XONLINE_FRIENDSTATE_FLAG_RECEIVEDREQUEST ) ) == 0 )
|
|
{
|
|
m_filteredFriends[m_numFilteredFriends++] = m_friends[friendIndex].xuid;
|
|
}
|
|
}
|
|
m_filteredFriends[m_numFilteredFriends++] = LeaderboardManager::Instance()->GetMyXUID();
|
|
}
|
|
#endif
|
|
|
|
void CScene_Leaderboards::ReadStats(int startIndex)
|
|
{
|
|
//If startIndex == -1, then use default values
|
|
if( startIndex == -1 )
|
|
{
|
|
m_newEntryIndex = 1;
|
|
m_newReadSize = READ_SIZE;
|
|
|
|
m_leaderboard.m_totalEntryCount = 0;
|
|
m_leaderboard.m_currentEntryCount = 0;
|
|
|
|
m_listGamers.DeleteItems(0, m_listGamers.GetItemCount());
|
|
}
|
|
else
|
|
{
|
|
m_newEntryIndex = (unsigned int)startIndex;
|
|
m_newReadSize = min((int)READ_SIZE, (int)m_leaderboard.m_totalEntryCount-(startIndex-1));
|
|
}
|
|
|
|
//Setup the spec structure for the read request
|
|
/* XUSER_STATS_SPEC* spec = new XUSER_STATS_SPEC[1]; // 4j-jev, moved into xboxLeaderboardManager
|
|
spec[0].dwViewId = LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_viewId;
|
|
spec[0].dwNumColumnIds = LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_columnCount;
|
|
for( unsigned int i=0 ; i<spec[0].dwNumColumnIds ; ++i )
|
|
spec[0].rgwColumnIds[i] = LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_columnIds[i]; */
|
|
|
|
/*//This call takes ownership of spec and will free it when done
|
|
LeaderboardManager::Instance()->ReadStats(
|
|
m_newEntryIndex,
|
|
m_newReadSize,
|
|
1,
|
|
spec,
|
|
(startIndex == -1) ? m_currentFilter : LeaderboardManager::eFM_TopRank,
|
|
CScene_Leaderboards::OnStatsReadComplete,
|
|
reinterpret_cast<void*>(this),
|
|
m_numFilteredFriends,
|
|
m_filteredFriends);*/
|
|
|
|
switch (startIndex == -1 ? m_currentFilter : LeaderboardManager::eFM_TopRank)
|
|
{
|
|
case LeaderboardManager::eFM_TopRank:
|
|
LeaderboardManager::Instance()->ReadStats_TopRank( this,
|
|
m_currentDifficulty, (LeaderboardManager::EStatsType) m_currentLeaderboard,
|
|
m_newEntryIndex, m_newReadSize
|
|
);
|
|
break;
|
|
case LeaderboardManager::eFM_MyScore:
|
|
LeaderboardManager::Instance()->ReadStats_MyScore( this,
|
|
m_currentDifficulty, (LeaderboardManager::EStatsType) m_currentLeaderboard,
|
|
INVALID_XUID/*ignored*/,
|
|
m_newReadSize
|
|
);
|
|
break;
|
|
case LeaderboardManager::eFM_Friends:
|
|
LeaderboardManager::Instance()->ReadStats_Friends( this,
|
|
m_currentDifficulty, (LeaderboardManager::EStatsType) m_currentLeaderboard,
|
|
INVALID_XUID /*ignored*/,
|
|
0 /*ignored*/, 0 /*ignored*/
|
|
);
|
|
break;
|
|
}
|
|
|
|
//Show the loading message
|
|
m_textInfo.SetText(app.GetString(IDS_LEADERBOARD_LOADING));
|
|
m_textInfo.SetShow(true);
|
|
}
|
|
|
|
bool CScene_Leaderboards::OnStatsReadComplete(bool success, int numResults, LeaderboardManager::ViewOut results)
|
|
{
|
|
//CScene_Leaderboards* scene = reinterpret_cast<CScene_Leaderboards*>(userdata);
|
|
|
|
m_isProcessingStatsRead = true;
|
|
|
|
//bool noResults = LeaderboardManager::Instance()->GetStatsState() != XboxLeaderboardManager::eStatsState_Ready;
|
|
bool ret;
|
|
|
|
if (success)
|
|
{
|
|
m_numStats = numResults;
|
|
m_stats = results;
|
|
ret = RetrieveStats();
|
|
}
|
|
else ret = true;
|
|
|
|
//else LeaderboardManager::Instance()->SetStatsRetrieved(false);
|
|
|
|
PopulateLeaderboard(!success);
|
|
|
|
m_isProcessingStatsRead = false;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
bool CScene_Leaderboards::RetrieveStats()
|
|
{
|
|
|
|
if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards)))
|
|
{
|
|
m_leaderboard.m_totalEntryCount = NUM_ENTRIES;
|
|
m_leaderboard.m_currentEntryCount = NUM_ENTRIES;
|
|
m_leaderboard.m_entryStartIndex = 1;
|
|
m_leaderboard.m_numColumns = LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_columnCount;
|
|
|
|
//For each entry in the leaderboard
|
|
for( unsigned int entryIndex=0 ; entryIndex<m_leaderboard.m_currentEntryCount ; entryIndex++ )
|
|
{
|
|
m_leaderboard.m_entries[entryIndex].m_xuid = INVALID_XUID;
|
|
|
|
m_leaderboard.m_entries[entryIndex].m_rank = entryIndex+1;
|
|
swprintf(m_leaderboard.m_entries[entryIndex].m_wcRank, 12, L"12345678");//(int)m_leaderboard.m_entries[entryIndex].m_rank);
|
|
|
|
swprintf(m_leaderboard.m_entries[entryIndex].m_gamerTag, 17, L"WWWWWWWWWWWWWWWW");
|
|
|
|
//m_leaderboard.m_entries[entryIndex].m_locale = (entryIndex % 37) + 1;
|
|
|
|
bool isDistanceLeaderboard = LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_viewId == STATS_VIEW_TRAVELLING_PEACEFUL || LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_viewId == STATS_VIEW_TRAVELLING_EASY || LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_viewId == STATS_VIEW_TRAVELLING_NORMAL || LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_viewId == STATS_VIEW_TRAVELLING_HARD;
|
|
|
|
for( unsigned int i=0 ; i<m_leaderboard.m_numColumns ; i++ )
|
|
{
|
|
if( !isDistanceLeaderboard )
|
|
{
|
|
m_leaderboard.m_entries[entryIndex].m_columns[i] = USHRT_MAX;
|
|
swprintf(m_leaderboard.m_entries[entryIndex].m_wcColumns[i], 12, L"%u", m_leaderboard.m_entries[entryIndex].m_columns[i]);
|
|
}
|
|
else
|
|
{
|
|
m_leaderboard.m_entries[entryIndex].m_columns[i] = UINT_MAX;
|
|
swprintf(m_leaderboard.m_entries[entryIndex].m_wcColumns[i], 12, L"%.1fkm", ((float)m_leaderboard.m_entries[entryIndex].m_columns[i])/100.f/1000.f);
|
|
}
|
|
}
|
|
|
|
m_leaderboard.m_entries[entryIndex].m_bPlayer = (entryIndex == 0);
|
|
m_leaderboard.m_entries[entryIndex].m_bOnline = (entryIndex != 0);
|
|
m_leaderboard.m_entries[entryIndex].m_bFriend = (entryIndex != 0);
|
|
m_leaderboard.m_entries[entryIndex].m_bRequestedFriend = false;
|
|
}
|
|
|
|
//LeaderboardManager::Instance()->SetStatsRetrieved(true);
|
|
|
|
return true;
|
|
}
|
|
|
|
//assert( LeaderboardManager::Instance()->GetStats() != NULL );
|
|
//PXUSER_STATS_READ_RESULTS stats = LeaderboardManager::Instance()->GetStats();
|
|
//if( m_currentFilter == LeaderboardManager::eFM_Friends ) LeaderboardManager::Instance()->SortFriendStats();
|
|
|
|
bool isDistanceLeaderboard = m_stats->pViews[0].dwViewId == STATS_VIEW_TRAVELLING_PEACEFUL || m_stats->pViews[0].dwViewId == STATS_VIEW_TRAVELLING_EASY || m_stats->pViews[0].dwViewId == STATS_VIEW_TRAVELLING_NORMAL || m_stats->pViews[0].dwViewId == STATS_VIEW_TRAVELLING_HARD;
|
|
|
|
//First read
|
|
if( m_leaderboard.m_totalEntryCount == 0 )
|
|
{
|
|
m_leaderboard.m_totalEntryCount = (m_currentFilter == LeaderboardManager::eFM_Friends) ? m_stats->pViews[0].dwNumRows : m_stats->pViews[0].dwTotalViewRows;
|
|
m_leaderboard.m_currentEntryCount = m_stats->pViews[0].dwNumRows;
|
|
|
|
if( m_leaderboard.m_totalEntryCount == 0 || m_leaderboard.m_currentEntryCount == 0 )
|
|
{
|
|
//LeaderboardManager::Instance()->SetStatsRetrieved(false);
|
|
return false;
|
|
}
|
|
|
|
m_leaderboard.m_numColumns = m_stats->pViews[0].pRows[0].dwNumColumns;
|
|
|
|
m_leaderboard.m_entryStartIndex = (m_currentFilter == LeaderboardManager::eFM_Friends) ? 1 : m_stats->pViews[0].pRows[0].dwRank;
|
|
|
|
for( unsigned int entryIndex=0 ; entryIndex<m_leaderboard.m_currentEntryCount ; ++entryIndex )
|
|
CopyLeaderboardEntry(&(m_stats->pViews[0].pRows[entryIndex]), &(m_leaderboard.m_entries[entryIndex]), isDistanceLeaderboard);
|
|
|
|
//If the filter mode is "My Score" then centre the list around the entries and select the player's score
|
|
if( m_currentFilter == LeaderboardManager::eFM_MyScore )
|
|
{
|
|
//Centre the leaderboard list on the entries
|
|
m_newTop = m_leaderboard.m_entryStartIndex-1;
|
|
|
|
//Select the player entry
|
|
for( unsigned int i=m_leaderboard.m_entryStartIndex ; i<m_leaderboard.m_entryStartIndex+m_leaderboard.m_currentEntryCount ; ++i )
|
|
if( m_leaderboard.m_entries[i-m_leaderboard.m_entryStartIndex].m_bPlayer )
|
|
{
|
|
m_newSel = i-1; // this might be off the screen!
|
|
// and reposition the top one
|
|
if(m_newSel-m_newTop>9)
|
|
{
|
|
m_newTop=m_newSel-9;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//Additional read
|
|
else
|
|
{
|
|
unsigned int insertPosition = 0;
|
|
|
|
//If the first new entry is at a smaller index than the current first entry
|
|
if( m_newEntryIndex < m_leaderboard.m_entryStartIndex )
|
|
{
|
|
if( (m_leaderboard.m_entryStartIndex-1) < m_newReadSize )
|
|
m_newReadSize = m_leaderboard.m_entryStartIndex-1;
|
|
|
|
//Move current entries forward
|
|
memmove((void*)(m_leaderboard.m_entries+m_newReadSize), (void*)m_leaderboard.m_entries, sizeof(LeaderboardEntry)*(NUM_ENTRIES-m_newReadSize));
|
|
|
|
//Set the (now smaller) entry start index
|
|
m_leaderboard.m_entryStartIndex = m_newEntryIndex;
|
|
|
|
//We will be inserting the new entries at the start of the array
|
|
insertPosition = 0;
|
|
|
|
//Entry count is either max possible entries or current entry count + read size, whichever is smaller
|
|
m_leaderboard.m_currentEntryCount = min((int)NUM_ENTRIES, (int)(m_leaderboard.m_currentEntryCount+m_newReadSize));
|
|
}
|
|
//If the last new entry is at a greater position than the last possible entry
|
|
else if( m_newEntryIndex+m_newReadSize-1 >= m_leaderboard.m_entryStartIndex+NUM_ENTRIES )
|
|
{
|
|
//Calculate the overlap (this is by how much new entries would overhang the end of the array)
|
|
int overlap = (((m_newEntryIndex-1)+m_newReadSize-1) - (m_leaderboard.m_entryStartIndex-1)) - NUM_ENTRIES + 1;
|
|
|
|
//Move current entries backwards
|
|
memmove((void*)m_leaderboard.m_entries, (void*)(m_leaderboard.m_entries+overlap), sizeof(LeaderboardEntry)*(NUM_ENTRIES-overlap));
|
|
|
|
//Set the (now larger) start index
|
|
m_leaderboard.m_entryStartIndex += overlap;
|
|
|
|
//We will be inserting the new entries at the end of the array
|
|
insertPosition = NUM_ENTRIES - m_newReadSize;
|
|
|
|
//Entry count is max possible entries
|
|
m_leaderboard.m_currentEntryCount = NUM_ENTRIES;
|
|
}
|
|
//Otherwise we're inserting at the end of the array and there is plenty of room
|
|
else
|
|
{
|
|
insertPosition = m_leaderboard.m_currentEntryCount;
|
|
m_leaderboard.m_currentEntryCount += m_newReadSize;
|
|
}
|
|
|
|
//For each entry in the leaderboard
|
|
for( unsigned int entryIndex=0 ; entryIndex<m_newReadSize ; ++entryIndex )
|
|
{
|
|
CopyLeaderboardEntry(&(m_stats->pViews[0].pRows[entryIndex]), &(m_leaderboard.m_entries[insertPosition]), isDistanceLeaderboard);
|
|
insertPosition++;
|
|
}
|
|
}
|
|
|
|
//LeaderboardManager::Instance()->SetStatsRetrieved(true);
|
|
return true;
|
|
}
|
|
|
|
HRESULT CScene_Leaderboards::OnGetItemCountAll(XUIMessageGetItemCount *pGetItemCountData, BOOL& bHandled)
|
|
{
|
|
pGetItemCountData->cItems = m_leaderboard.m_totalEntryCount;
|
|
|
|
//if(LeaderboardManager::Instance()->GetStatsRead())
|
|
//{
|
|
// m_bReady=true;
|
|
//}
|
|
bHandled = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CScene_Leaderboards::OnGetSourceDataText(XUIMessageGetSourceText *pGetSourceTextData,BOOL& bHandled)
|
|
{
|
|
if( pGetSourceTextData->bItemData )
|
|
{
|
|
if( m_newTop != -1 && m_newSel != -1 )
|
|
{
|
|
HRESULT ret = m_listGamers.SetTopItem(m_newTop);
|
|
assert( ret == S_OK );
|
|
|
|
ret = m_listGamers.SetCurSel(m_newSel);
|
|
assert( ret == S_OK );
|
|
|
|
// update the tooltips
|
|
|
|
m_newTop = m_newSel = -1;
|
|
|
|
bHandled = true;
|
|
return S_OK;
|
|
}
|
|
|
|
unsigned int item = pGetSourceTextData->iItem;
|
|
|
|
if( m_leaderboard.m_totalEntryCount > 0 && (item+1) < m_leaderboard.m_entryStartIndex )
|
|
{
|
|
if( LeaderboardManager::Instance()->isIdle() )
|
|
{
|
|
int readIndex = m_leaderboard.m_entryStartIndex - READ_SIZE;
|
|
if( readIndex <= 0 )
|
|
readIndex = 1;
|
|
assert( readIndex >= 1 && readIndex <= (int)m_leaderboard.m_totalEntryCount );
|
|
ReadStats(readIndex);
|
|
}
|
|
}
|
|
else if( m_leaderboard.m_totalEntryCount > 0 && (item+1) >= (m_leaderboard.m_entryStartIndex+m_leaderboard.m_currentEntryCount) )
|
|
{
|
|
if( LeaderboardManager::Instance()->isIdle() )
|
|
{
|
|
int readIndex = m_leaderboard.m_entryStartIndex + m_leaderboard.m_currentEntryCount;
|
|
assert( readIndex >= 1 && readIndex <= (int)m_leaderboard.m_totalEntryCount );
|
|
ReadStats(readIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned int index = item - (m_leaderboard.m_entryStartIndex-1);
|
|
if( 0 == pGetSourceTextData->iData )
|
|
{
|
|
pGetSourceTextData->szText = m_leaderboard.m_entries[index].m_wcRank;
|
|
bHandled = TRUE;
|
|
}
|
|
else if( 1 == pGetSourceTextData->iData )
|
|
{
|
|
pGetSourceTextData->szText = m_leaderboard.m_entries[index].m_gamerTag;
|
|
bHandled = TRUE;
|
|
}
|
|
else if( pGetSourceTextData->iData >= 3 && pGetSourceTextData->iData <= 9 )
|
|
{
|
|
if( m_leaderboard.m_numColumns <= (unsigned int)(pGetSourceTextData->iData-3) )
|
|
pGetSourceTextData->szText = L"";
|
|
else
|
|
pGetSourceTextData->szText = m_leaderboard.m_entries[index].m_wcColumns[pGetSourceTextData->iData-3];
|
|
bHandled = TRUE;
|
|
}
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CScene_Leaderboards::OnGetSourceDataImage(XUIMessageGetSourceImage* pGetImage, BOOL& bHandled)
|
|
{
|
|
if( (pGetImage->iData == 2) && (pGetImage->bItemData) )
|
|
{
|
|
if( m_newTop != -1 && m_newSel != -1 )
|
|
{
|
|
//Do nothing, alignment handled in OnGetSourceDataText
|
|
|
|
bHandled = true;
|
|
return S_OK;
|
|
}
|
|
|
|
unsigned int item = pGetImage->iItem;
|
|
if( m_leaderboard.m_totalEntryCount > 0 && (item+1) < m_leaderboard.m_entryStartIndex )
|
|
{
|
|
//Do nothing, reading handled in OnGetSourceDataText
|
|
}
|
|
else if( m_leaderboard.m_totalEntryCount > 0 && (item+1) >= (m_leaderboard.m_entryStartIndex+m_leaderboard.m_currentEntryCount) )
|
|
{
|
|
//Do nothing, reading handled in OnGetSourceDataText
|
|
}
|
|
// 4J-PB - we're not allowed to show flags any more
|
|
// else
|
|
// {
|
|
// unsigned int index = item - (m_leaderboard.m_entryStartIndex-1);
|
|
// if( m_leaderboard.m_entries[index].m_locale > 0 && m_leaderboard.m_entries[index].m_locale <= XC_LOCALE_RUSSIAN_FEDERATION )
|
|
// pGetImage->szPath = FLAG_ICON_PATHS[ m_leaderboard.m_entries[index].m_locale-1 ];
|
|
// bHandled = TRUE;
|
|
// }
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CScene_Leaderboards::PopulateLeaderboard(bool noResults)
|
|
{
|
|
HRESULT hr;
|
|
HXUIOBJ visual=NULL;
|
|
HXUIOBJ hTemp=NULL;
|
|
hr=XuiControlGetVisual(m_listGamers.m_hObj,&visual);
|
|
|
|
if(m_pHTitleIconSlots[0]==NULL)
|
|
{
|
|
VOID *pObj;
|
|
HXUIOBJ button;
|
|
D3DXVECTOR3 vPos;
|
|
|
|
for(int i=0;i<7;i++)
|
|
{
|
|
// retrieve the visual for the title icon
|
|
hr=XuiElementGetChildById(visual,m_TitleIconNameA[i],&button);
|
|
|
|
XuiObjectFromHandle( button, &pObj );
|
|
m_pHTitleIconSlots[i] = (CXuiCtrlCraftIngredientSlot *)pObj;
|
|
|
|
// store the default position, since we'll be repositioning these depending on how many are valid for each board
|
|
m_pHTitleIconSlots[i]->GetPosition(&vPos);
|
|
m_fTitleIconXPositions[i]= vPos.x;
|
|
}
|
|
}
|
|
|
|
int iValidSlots=SetLeaderboardTitleIcons();
|
|
|
|
if( !noResults && m_leaderboard.m_totalEntryCount > 0 )
|
|
{
|
|
hr=XuiElementGetChildById(visual,L"XuiLabel_Gamertag",&hTemp);
|
|
if(hTemp)
|
|
{
|
|
XuiControlSetText(hTemp,app.GetString( IDS_LEADERBOARD_GAMERTAG ));
|
|
XuiElementSetShow(hTemp, TRUE);
|
|
}
|
|
hr=XuiElementGetChildById(visual,L"XuiLabel_Rank",&hTemp);
|
|
if(hTemp)
|
|
{
|
|
XuiControlSetText(hTemp,app.GetString( IDS_LEADERBOARD_RANK ));
|
|
XuiElementSetShow(hTemp, TRUE);
|
|
}
|
|
|
|
//Update entries display
|
|
wchar_t entriesBuffer[40];
|
|
if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards)))
|
|
{
|
|
swprintf(entriesBuffer, 40, L"%ls12345678", app.GetString(IDS_LEADERBOARD_ENTRIES));
|
|
}
|
|
else
|
|
{
|
|
swprintf(entriesBuffer, 40, L"%ls%i", app.GetString(IDS_LEADERBOARD_ENTRIES), m_leaderboard.m_totalEntryCount);
|
|
}
|
|
|
|
m_textEntries.SetText(entriesBuffer);
|
|
|
|
//Hide the loading message
|
|
m_textInfo.SetShow(false);
|
|
|
|
//Add space for new entries
|
|
m_listGamers.InsertItems(0, m_leaderboard.m_totalEntryCount);
|
|
|
|
// 4J Stu - Fix for leaderboards taking forever to update. Was looping over m_totalEntryCount which is ~2mil in
|
|
// some leaderboards in production atm.
|
|
// Changed to loop over the range of cached values, although even that is probably overkill.
|
|
// Really only the newly updated rows need changed, but this shouldn't cause any performance issues
|
|
for(DWORD i = m_leaderboard.m_entryStartIndex - 1; i < (m_leaderboard.m_entryStartIndex - 1) + m_leaderboard.m_currentEntryCount; ++i)
|
|
{
|
|
HXUIOBJ visual=NULL;
|
|
HXUIOBJ button;
|
|
D3DXVECTOR3 vPos;
|
|
// 4J-PB - fix for #13768 - Leaderboards: Player scores appear misaligned when viewed under the "My Score" leaderboard filter
|
|
HXUIOBJ hTop=m_listGamers.GetItemControl(i-(m_leaderboard.m_entryStartIndex - 1));
|
|
HRESULT hr=XuiControlGetVisual(hTop,&visual);
|
|
|
|
for(int j=0;j<7;j++)
|
|
{
|
|
hr=XuiElementGetChildById(visual,m_TextColumnNameA[j],&button);
|
|
m_hTextEntryA[j]=button;
|
|
|
|
XuiElementGetPosition(button,&vPos);
|
|
m_fTextXPositions[j]=vPos.x;
|
|
}
|
|
RepositionText(iValidSlots);
|
|
}
|
|
|
|
// hide empty icon boxes
|
|
for(int i = (LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_columnCount);i<7;i++)
|
|
{
|
|
m_pHTitleIconSlots[i]->SetShow(FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr=XuiElementGetChildById(visual,L"XuiLabel_Gamertag",&hTemp);
|
|
if(hTemp)
|
|
{
|
|
XuiElementSetShow(hTemp, FALSE);
|
|
}
|
|
hr=XuiElementGetChildById(visual,L"XuiLabel_Rank",&hTemp);
|
|
if(hTemp)
|
|
{
|
|
XuiElementSetShow(hTemp, FALSE);
|
|
}
|
|
|
|
//Update entries display (to zero)
|
|
wchar_t entriesBuffer[40];
|
|
swprintf(entriesBuffer, 40, L"%ls0", app.GetString(IDS_LEADERBOARD_ENTRIES));
|
|
m_textEntries.SetText(entriesBuffer);
|
|
|
|
//Show the no results message
|
|
m_textInfo.SetText(app.GetString(IDS_LEADERBOARD_NORESULTS));
|
|
m_textInfo.SetShow(true);
|
|
|
|
// hide the icons
|
|
for(int i=0;i<7;i++)
|
|
{
|
|
m_pHTitleIconSlots[i]->SetShow(FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
m_bPopulatedOnce = true;
|
|
}
|
|
|
|
void CScene_Leaderboards::CopyLeaderboardEntry(PXUSER_STATS_ROW statsRow, LeaderboardEntry* leaderboardEntry, bool isDistanceLeaderboard)
|
|
{
|
|
leaderboardEntry->m_xuid = statsRow->xuid;
|
|
|
|
//Copy the rank
|
|
leaderboardEntry->m_rank = statsRow->dwRank;
|
|
DWORD displayRank = leaderboardEntry->m_rank;
|
|
if(displayRank > 9999999) displayRank = 9999999;
|
|
swprintf_s(leaderboardEntry->m_wcRank, 12, L"%u", displayRank);
|
|
|
|
//strcpy(statsRow->szGamertag,"WWWWWWWWWWWWWWWW");
|
|
|
|
//Convert the gamertag from char to wchar_t
|
|
MultiByteToWideChar(
|
|
CP_UTF8,
|
|
0,
|
|
statsRow->szGamertag,
|
|
strlen(statsRow->szGamertag),
|
|
leaderboardEntry->m_gamerTag,
|
|
XUSER_NAME_SIZE );
|
|
//Null terminate the gamertag
|
|
leaderboardEntry->m_gamerTag[strlen(statsRow->szGamertag)] = L'\0';
|
|
|
|
//Copy the locale
|
|
//leaderboardEntry->m_locale = statsRow->pColumns[0].Value.nData;
|
|
|
|
//Copy the other columns
|
|
for( unsigned int i=0 ; i<statsRow->dwNumColumns ; i++ )
|
|
{
|
|
leaderboardEntry->m_columns[i] = statsRow->pColumns[i].Value.nData;
|
|
if( !isDistanceLeaderboard )
|
|
{
|
|
DWORD displayValue = leaderboardEntry->m_columns[i];
|
|
if(displayValue > 99999) displayValue = 99999;
|
|
swprintf_s(leaderboardEntry->m_wcColumns[i], 12, L"%u",displayValue);
|
|
#ifdef _DEBUG
|
|
app.DebugPrintf("Value - %d\n",leaderboardEntry->m_columns[i]);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// check how many digits we have
|
|
int iDigitC=0;
|
|
unsigned int uiVal=leaderboardEntry->m_columns[i];
|
|
// uiVal=0xFFFFFFFF;
|
|
// leaderboardEntry->m_columns[i-1]=uiVal;
|
|
|
|
while(uiVal!=0)
|
|
{
|
|
uiVal/=10;
|
|
iDigitC++;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
app.DebugPrintf("Value - %d\n",leaderboardEntry->m_columns[i]);
|
|
#endif
|
|
if(iDigitC<4)
|
|
{
|
|
// m
|
|
swprintf_s(leaderboardEntry->m_wcColumns[i], 12, L"%um", leaderboardEntry->m_columns[i]);
|
|
#ifdef _DEBUG
|
|
app.DebugPrintf("Display - %um\n", leaderboardEntry->m_columns[i]);
|
|
#endif
|
|
}
|
|
else if(iDigitC<8)
|
|
{
|
|
// km with a .X
|
|
swprintf_s(leaderboardEntry->m_wcColumns[i], 12, L"%.1fkm", ((float)leaderboardEntry->m_columns[i])/1000.f);
|
|
#ifdef _DEBUG
|
|
app.DebugPrintf("Display - %.1fkm\n", ((float)leaderboardEntry->m_columns[i])/1000.f);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// bigger than that, so no decimal point
|
|
swprintf_s(leaderboardEntry->m_wcColumns[i], 12, L"%.0fkm", ((float)leaderboardEntry->m_columns[i])/1000.f);
|
|
#ifdef _DEBUG
|
|
app.DebugPrintf("Display - %.0fkm\n", ((float)leaderboardEntry->m_columns[i])/1000.f);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
//Is the player
|
|
if( statsRow->xuid == ((XboxLeaderboardManager*)LeaderboardManager::Instance())->GetMyXUID() )
|
|
{
|
|
leaderboardEntry->m_bPlayer = true;
|
|
leaderboardEntry->m_bOnline = false;
|
|
leaderboardEntry->m_bFriend = false;
|
|
leaderboardEntry->m_bRequestedFriend = false;
|
|
}
|
|
else
|
|
{
|
|
leaderboardEntry->m_bPlayer = false;
|
|
leaderboardEntry->m_bOnline = false;
|
|
leaderboardEntry->m_bFriend = false;
|
|
leaderboardEntry->m_bRequestedFriend = false;
|
|
|
|
//Check for friend status
|
|
for( unsigned int friendIndex=0 ; friendIndex<m_numFriends ; ++friendIndex )
|
|
{
|
|
if( m_friends[friendIndex].xuid == statsRow->xuid )
|
|
{
|
|
if( ( m_friends[friendIndex].dwFriendState & ( XONLINE_FRIENDSTATE_FLAG_SENTREQUEST | XONLINE_FRIENDSTATE_FLAG_RECEIVEDREQUEST ) ) == 0 )
|
|
{
|
|
//Is friend, might be online
|
|
leaderboardEntry->m_bFriend = true;
|
|
leaderboardEntry->m_bOnline = ( m_friends[friendIndex].dwFriendState & XONLINE_FRIENDSTATE_FLAG_ONLINE );
|
|
leaderboardEntry->m_bRequestedFriend = false;
|
|
}
|
|
else
|
|
{
|
|
//Friend request sent but not accepted yet
|
|
leaderboardEntry->m_bOnline = false;
|
|
leaderboardEntry->m_bFriend = false;
|
|
leaderboardEntry->m_bRequestedFriend = true;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CScene_Leaderboards::SetLeaderboardHeader()
|
|
{
|
|
WCHAR buffer[40];
|
|
DWORD bufferLength = 40;
|
|
|
|
DWORD ret = XResourceGetString(LEADERBOARD_HEADERS[m_currentLeaderboard][m_currentDifficulty], buffer, &bufferLength, NULL);
|
|
|
|
if( ret == ERROR_SUCCESS )
|
|
m_textLeaderboard.SetText(buffer);
|
|
}
|
|
|
|
int CScene_Leaderboards::SetLeaderboardTitleIcons()
|
|
{
|
|
int iValidIcons=0;
|
|
|
|
for(int i=0;i<7;i++)
|
|
{
|
|
if(TitleIcons[m_currentLeaderboard][i]==0)
|
|
{
|
|
m_pHTitleIconSlots[i]->SetShow(FALSE);
|
|
}
|
|
else
|
|
{
|
|
iValidIcons++;
|
|
m_pHTitleIconSlots[i]->SetIcon(DEFAULT_XUI_MENU_USER,TitleIcons[m_currentLeaderboard][i],0,1,10,31,false,FALSE);
|
|
}
|
|
}
|
|
|
|
Reposition(iValidIcons);
|
|
|
|
return iValidIcons;
|
|
}
|
|
void CScene_Leaderboards::ClearLeaderboardTitlebar()
|
|
{
|
|
for(int i=0;i<7;i++)
|
|
{
|
|
m_pHTitleIconSlots[i]->SetShow(FALSE);
|
|
}
|
|
|
|
HXUIOBJ visual=NULL;
|
|
HXUIOBJ hTemp=NULL;
|
|
HRESULT hr;
|
|
hr=XuiControlGetVisual(m_listGamers.m_hObj,&visual);
|
|
|
|
hr=XuiElementGetChildById(visual,L"XuiLabel_Gamertag",&hTemp);
|
|
if(hTemp)
|
|
{
|
|
XuiElementSetShow(hTemp, FALSE);
|
|
}
|
|
hr=XuiElementGetChildById(visual,L"XuiLabel_Rank",&hTemp);
|
|
if(hTemp)
|
|
{
|
|
XuiElementSetShow(hTemp, FALSE);
|
|
}
|
|
}
|