mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-04-25 16:43:53 +00:00
1336 lines
53 KiB
C++
1336 lines
53 KiB
C++
#include "../../Minecraft.World/Platform/stdafx.h"
|
|
#include <xuiresource.h>
|
|
#include <xuiapp.h>
|
|
#include "XUI_Leaderboards.h"
|
|
#include "../../Minecraft.World/Blocks/Tile.h"
|
|
#include "../../Minecraft.World/Items/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: {
|
|
int 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 =
|
|
std::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 = std::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);
|
|
}
|
|
}
|