3336 lines
111 KiB
C++
3336 lines
111 KiB
C++
![]() |
#include "Frontend/Store/StoreMainScreen.h"
|
||
|
|
||
|
#include "frontend/hud_colour.h"
|
||
|
#include "frontend/PauseMenu.h"
|
||
|
#include "frontend/BusySpinner.h"
|
||
|
#include "Frontend/FrontendStatsMgr.h"
|
||
|
#include "frontend/HudTools.h"
|
||
|
#include "frontend/NewHud.h"
|
||
|
#include "frontend/Scaleform/ScaleFormMgr.h"
|
||
|
#include "Frontend/Store/StoreScreenMgr.h"
|
||
|
#include "Frontend/Store/StoreUIChannel.h"
|
||
|
#include "Frontend/Store/StoreTextureManager.h"
|
||
|
#include "FrontEnd/WarningScreen.h"
|
||
|
#include "game/Clock.h"
|
||
|
#include "Network/Cloud/Tunables.h"
|
||
|
#include "Network/Live/livemanager.h"
|
||
|
#include "Network/Live/NetworkTransactionTelemetry.h"
|
||
|
#include "Network/Live/NetworkTelemetry.h"
|
||
|
#include "Network/commerce/CommerceManager.h"
|
||
|
#include "Network/Stats//NetworkLeaderboardSessionMgr.h"
|
||
|
#include "Peds/rendering/PedHeadshotManager.h"
|
||
|
#include "SaveLoad/savegame_users_and_devices.h"
|
||
|
#include "scene/ExtraContent.h"
|
||
|
#include "stats/StatsInterface.h"
|
||
|
#include "system/controlMgr.h"
|
||
|
#include "system/pad.h"
|
||
|
#include "Stats/MoneyInterface.h"
|
||
|
#include "text/TextConversion.h"
|
||
|
|
||
|
#include "fwcommerce/CommerceUtil.h"
|
||
|
#include "fwcommerce/CommerceChannel.h"
|
||
|
#include "fwcommerce/CommerceConsumable.h"
|
||
|
#include "fwnet/netscgameconfigparser.h"
|
||
|
#include "rline/rlgamerinfo.h"
|
||
|
#include "rline/rlpresence.h"
|
||
|
#include "rline/scmembership/rlscmembership.h"
|
||
|
|
||
|
#if RSG_PC
|
||
|
#include "rline/rlpc.h"
|
||
|
#endif // RSG_PC
|
||
|
|
||
|
FRONTEND_STORE_OPTIMISATIONS()
|
||
|
|
||
|
PARAM(commerceAlwaysShowUpsell, "[commerce] For products with an upsell, always run the upsell flow");
|
||
|
|
||
|
#define STOREMENU_FILENAME "pause_menu_store_content"
|
||
|
#define BUTTONMENU_FILENAME "store_instructional_buttons"
|
||
|
const char* BLACKFADE_FILENAME = "STORE_BLACKOUT";
|
||
|
const char* BACKGROUNDMOVIE_FILENAME = "store_background";
|
||
|
|
||
|
const char* CONSUMABLE_AMOUNT_SUB_TAG = "[cash pack amount]";
|
||
|
const int CONSUMABLE_AMOUNT_STR_LEN = 32;
|
||
|
|
||
|
#if __XENON
|
||
|
const char* PRICE_STRING_SUFFIX = "";
|
||
|
#else
|
||
|
const char* PRICE_STRING_SUFFIX = "";
|
||
|
#endif
|
||
|
|
||
|
const s32 DEFAULT_TOP_CATAGORY = 0;
|
||
|
const s32 NUM_COLUMNS = 3;
|
||
|
|
||
|
const s32 CAT_COLUMN_INDEX = 0;
|
||
|
const s32 ITEM_COLUMN_INDEX = 1;
|
||
|
const s32 DETAIL_COLUMN_INDEX = 2;
|
||
|
const int MAX_NUM_ITEMS_IN_MIDDLE_COLUMN = 4;
|
||
|
|
||
|
const int MAX_REQUESTED_IMAGES = 6;
|
||
|
|
||
|
const int INVALID_COLUMN_INDEX = -1;
|
||
|
const int INVALID_ITEM_INDEX = -1;
|
||
|
|
||
|
const int RIGHT_STICK_DEADZONE = 64;
|
||
|
const int SIZE_OF_PRICE_BUFFER = 64;
|
||
|
const int STORE_FADE_TIME = 1000;
|
||
|
|
||
|
const int OFFLINE_FRAMES_TO_WAIT_FOR_SIGNOUT_MESSAGE = 12;
|
||
|
|
||
|
bool cStoreMainScreen::sm_bPlayerHasJustSignedOut = false;
|
||
|
|
||
|
static rlPresence::Delegate sPresenceDlgt;
|
||
|
|
||
|
cStoreMainScreen::cStoreMainScreen() :
|
||
|
m_LastSelectionTransition(NO_SELECTION_TRANSITION),
|
||
|
m_StoreMovieId(INVALID_MOVIE_ID),
|
||
|
m_ButtonMovieId(INVALID_MOVIE_ID),
|
||
|
m_StoreBgMovieId(INVALID_MOVIE_ID),
|
||
|
m_BlackFadeMovieId(INVALID_MOVIE_ID),
|
||
|
m_Initialised(false),
|
||
|
m_PendingListSetup(false),
|
||
|
m_ColumnReturnId(0),
|
||
|
m_ItemReturnId(0),
|
||
|
m_LastColumnIndex(CAT_COLUMN_INDEX),
|
||
|
m_LastItemIndex(INVALID_ITEM_INDEX),
|
||
|
m_LastCenterItemIndex(INVALID_ITEM_INDEX),
|
||
|
m_PendingSelection(false),
|
||
|
m_PendingHighlightChange(false),
|
||
|
m_PendingLongDescriptionItem(NULL),
|
||
|
m_PendingCheckoutProduct(NULL),
|
||
|
m_CurrentlySelectedCategory(INVALID_ITEM_INDEX),
|
||
|
m_WasInCheckout(false),
|
||
|
m_RefetchingPlatformData(false),
|
||
|
m_CurrentStartReturnId(0),
|
||
|
m_CurrentEndReturnId(0),
|
||
|
m_LastStartIndex(INVALID_ITEM_INDEX),
|
||
|
m_LastEndIndex(INVALID_ITEM_INDEX),
|
||
|
m_bLoadingAssets(false),
|
||
|
m_ConsumableProductCheckLevel(0),
|
||
|
mp_CurrentLeaderboardRead(NULL),
|
||
|
mp_PendingNumFriendsWhoOwnProduct(NULL),
|
||
|
m_CurrentNonCriticalWarningScreen(STORE_NON_CRIT_WARNING_NONE),
|
||
|
m_PendingNonCriticalWarningScreen(STORE_NON_CRIT_WARNING_NONE),
|
||
|
m_CurrentDCWarningScreen(STORE_WARNING_NONE),
|
||
|
m_FramesOffline(0),
|
||
|
m_InNoProductsMode(false),
|
||
|
m_PedHeadShotHandle(0),
|
||
|
m_PendingCash(0),
|
||
|
m_WasConsumableDataDirtyLastFrame(false),
|
||
|
m_StoreListsSetup(false),
|
||
|
m_QuickCheckout(false),
|
||
|
m_HasBeenInCheckout(false),
|
||
|
m_WasSignedOnlineOnEnter(false)
|
||
|
{
|
||
|
m_CurrentState = STATE_INVALID;
|
||
|
|
||
|
m_ProductIndexArray.Reset();
|
||
|
m_CategoryIndexArray.Reset();
|
||
|
|
||
|
m_RequestedImageIndices.Reset();
|
||
|
m_RequestedImageIndices.Reserve( MAX_REQUESTED_IMAGES );
|
||
|
|
||
|
m_LoadedImageIndices.Reset();
|
||
|
m_LoadedImageIndices.Reserve( MAX_REQUESTED_IMAGES );
|
||
|
|
||
|
m_NumFriendsWhoOwnProductMap.Reset();
|
||
|
|
||
|
sm_bPlayerHasJustSignedOut = false;
|
||
|
if (!sPresenceDlgt.IsBound())
|
||
|
{
|
||
|
sPresenceDlgt.Bind(cStoreMainScreen::OnPresenceEvent);
|
||
|
rlPresence::AddDelegate(&sPresenceDlgt);
|
||
|
}
|
||
|
|
||
|
#if RSG_NP
|
||
|
m_shouldCommerceLogoDisplay = false;
|
||
|
m_isCommerceLogoDisplaying = false;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
cStoreMainScreen::~cStoreMainScreen()
|
||
|
{
|
||
|
Shutdown();
|
||
|
|
||
|
if (sPresenceDlgt.IsBound())
|
||
|
sPresenceDlgt.Unbind();
|
||
|
|
||
|
rlPresence::RemoveDelegate(&sPresenceDlgt);
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::Init( int a_StoreMovieId, int a_ButtonMovieId )
|
||
|
{
|
||
|
m_StoreMovieId = a_StoreMovieId;
|
||
|
m_ButtonMovieId = a_ButtonMovieId;
|
||
|
|
||
|
InitInternal();
|
||
|
|
||
|
m_CurrentState = STATE_PENDING_INITIAL_DATA;
|
||
|
|
||
|
m_PurchaseCheckProductID.Reset();
|
||
|
m_WasConsumableDataDirtyLastFrame = false;
|
||
|
|
||
|
m_TimerSinceInputEnabled.Zero();
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::Init()
|
||
|
{
|
||
|
InitInternal();
|
||
|
|
||
|
RequestScaleformMovies();
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::InitInternal()
|
||
|
{
|
||
|
m_LastSelectionTransition = NO_SELECTION_TRANSITION;
|
||
|
|
||
|
m_Initialised = true;
|
||
|
|
||
|
m_ColumnReturnId = 0;
|
||
|
m_ItemReturnId = 0;
|
||
|
m_LastColumnIndex = CAT_COLUMN_INDEX;
|
||
|
m_LastItemIndex = INVALID_ITEM_INDEX;
|
||
|
m_LastCenterItemIndex = INVALID_ITEM_INDEX;
|
||
|
m_PendingSelection = false;
|
||
|
m_PendingHighlightChange = false;
|
||
|
m_PendingLongDescriptionItem = NULL;
|
||
|
m_PendingCheckoutProduct = NULL;
|
||
|
m_CurrentlySelectedCategory = INVALID_ITEM_INDEX;
|
||
|
m_WasInCheckout = false;
|
||
|
m_RefetchingPlatformData = false;
|
||
|
m_WasSignedOnlineOnEnter = CLiveManager::IsOnline();
|
||
|
|
||
|
m_ProductIndexArray.Reset();
|
||
|
m_CategoryIndexArray.Reset();
|
||
|
|
||
|
m_RequestedImageIndices.Reset();
|
||
|
m_RequestedImageIndices.Reserve( MAX_REQUESTED_IMAGES );
|
||
|
|
||
|
m_LoadedImageIndices.Reset();
|
||
|
m_LoadedImageIndices.Reserve( MAX_REQUESTED_IMAGES );
|
||
|
|
||
|
m_CurrentStartReturnId = 0;
|
||
|
m_CurrentEndReturnId = 0;
|
||
|
|
||
|
m_NumFriendsWhoOwnProductMap.Reset();
|
||
|
m_CurrentLeaderboardDataFetchProductId.Reset();
|
||
|
mp_PendingNumFriendsWhoOwnProduct = NULL;
|
||
|
|
||
|
m_CurrentDCWarningScreen = STORE_WARNING_NONE;
|
||
|
|
||
|
m_bLoadingAssets = false;
|
||
|
|
||
|
sm_bPlayerHasJustSignedOut = false;
|
||
|
|
||
|
m_ConsumableProductCheckId.Reset();
|
||
|
m_ConsumableProductCheckLevel = 0;
|
||
|
m_FramesOffline = 0;
|
||
|
m_InNoProductsMode = false;
|
||
|
|
||
|
m_CurrentNonCriticalWarningScreen = STORE_NON_CRIT_WARNING_NONE;
|
||
|
m_PendingNonCriticalWarningScreen = STORE_NON_CRIT_WARNING_NONE;
|
||
|
|
||
|
m_WasConsumableDataDirtyLastFrame = false;
|
||
|
m_PendingCash = 0;
|
||
|
m_StoreListsSetup = false;
|
||
|
m_QuickCheckout = false;
|
||
|
|
||
|
m_SubscriptionUpsellItemId.Clear();
|
||
|
m_SubscriptionUpsellTargetItemId.Clear();
|
||
|
m_PendingImageRequest = false;
|
||
|
|
||
|
InitialiseConsumablesLevel();
|
||
|
// if ( m_PedHeadShotHandle == 0 )
|
||
|
// {
|
||
|
// m_PedHeadShotHandle = (s32)PEDHEADSHOTMANAGER.RegisterPed(CGameWorld::FindLocalPlayer());
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::Shutdown()
|
||
|
{
|
||
|
#if RSG_NP
|
||
|
g_rlNp.GetCommonDialog().HideCommerceLogo();
|
||
|
m_shouldCommerceLogoDisplay = false;
|
||
|
m_isCommerceLogoDisplaying = false;
|
||
|
#endif
|
||
|
|
||
|
m_SubscriptionUpsellItemId.Clear();
|
||
|
m_SubscriptionUpsellTargetItemId.Clear();
|
||
|
m_PendingImageRequest = false;
|
||
|
|
||
|
// switch this off when we exit the store
|
||
|
MEMBERSHIP_ONLY(CLiveManager::SetSuppressMembershipForScript(false));
|
||
|
|
||
|
if ( m_StoreMovieId != INVALID_MOVIE_ID )
|
||
|
{
|
||
|
CScaleformMgr::RequestRemoveMovie(m_StoreMovieId);
|
||
|
m_StoreMovieId = INVALID_MOVIE_ID;
|
||
|
}
|
||
|
|
||
|
if ( m_ButtonMovieId != INVALID_MOVIE_ID )
|
||
|
{
|
||
|
CBusySpinner::UnregisterInstructionalButtonMovie(m_ButtonMovieId); // register this "instructional button" movie with the spinner system
|
||
|
CScaleformMgr::RequestRemoveMovie(m_ButtonMovieId);
|
||
|
m_ButtonMovieId = INVALID_MOVIE_ID;
|
||
|
}
|
||
|
|
||
|
if ( m_StoreBgMovieId != INVALID_MOVIE_ID )
|
||
|
{
|
||
|
CScaleformMgr::RequestRemoveMovie(m_StoreBgMovieId);
|
||
|
m_StoreBgMovieId = INVALID_MOVIE_ID;
|
||
|
}
|
||
|
|
||
|
if ( m_BlackFadeMovieId != INVALID_MOVIE_ID )
|
||
|
{
|
||
|
CScaleformMgr::RequestRemoveMovie(m_BlackFadeMovieId);
|
||
|
m_BlackFadeMovieId = INVALID_MOVIE_ID;
|
||
|
}
|
||
|
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
for ( s32 i = 0; i < m_LoadedImageIndices.GetCount(); i++ )
|
||
|
{
|
||
|
const cCommerceItemData *itemData = pCommerceUtil->GetItemData(m_LoadedImageIndices[i]);
|
||
|
|
||
|
if ( itemData && itemData->GetImagePaths().GetCount() > 0 )
|
||
|
{
|
||
|
const atString path(itemData->GetImagePaths()[0]);
|
||
|
cStoreScreenMgr::GetTextureManager()->ReleaseTexture( path );
|
||
|
}
|
||
|
}
|
||
|
m_LoadedImageIndices.Reset();
|
||
|
|
||
|
CLiveManager::GetCommerceMgr().SetAutoConsumePaused(false);
|
||
|
|
||
|
if (mp_CurrentLeaderboardRead != NULL)
|
||
|
{
|
||
|
CNetwork::GetLeaderboardMgr().GetLeaderboardReadMgr().ClearLeaderboardRead(mp_CurrentLeaderboardRead);
|
||
|
mp_CurrentLeaderboardRead = NULL;
|
||
|
m_CurrentLeaderboardDataFetchProductId.Reset();
|
||
|
}
|
||
|
|
||
|
if (m_PedHeadShotHandle != 0)
|
||
|
{
|
||
|
PEDHEADSHOTMANAGER.UnregisterPed(m_PedHeadShotHandle);
|
||
|
m_PedHeadShotHandle = 0;
|
||
|
}
|
||
|
|
||
|
mp_PendingNumFriendsWhoOwnProduct = NULL;
|
||
|
|
||
|
m_Initialised = false;
|
||
|
m_CurrentState = STATE_INVALID;
|
||
|
|
||
|
//Take this opportunity to kick off an data enumeration.
|
||
|
if (!CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataDirty())
|
||
|
{
|
||
|
CLiveManager::GetCommerceMgr().GetConsumableManager()->SetOwnershipDataDirty();
|
||
|
}
|
||
|
|
||
|
#if NET_ENABLE_MEMBERSHIP_FUNCTIONALITY
|
||
|
// refresh membership status - defaulted to false
|
||
|
if(Tunables::IsInstantiated() && Tunables::GetInstance().TryAccess(CD_GLOBAL_HASH, ATSTRINGHASH("NET_MEMBERSHIP_REFRESH_ON_STORE_SHUTDOWN", 0x8f865fd1), false))
|
||
|
{
|
||
|
storeUIDebugf1("Shutdown :: Requesting Membership Status");
|
||
|
rlScMembership::RequestMembershipStatus(NetworkInterface::GetLocalGamerIndex());
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//We should redisplay cash limit warnings at this point.
|
||
|
CLiveManager::GetCommerceMgr().ResetAutoConsumeMessage();
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateStoreLists()
|
||
|
{
|
||
|
if (!CLiveManager::GetCommerceMgr().HasValidData())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ClearImageRequests();
|
||
|
m_ProductIndexArray.Reset();
|
||
|
m_CategoryIndexArray.Reset();
|
||
|
|
||
|
m_StoreListsSetup = true;
|
||
|
|
||
|
if (m_InNoProductsMode)
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "MENU_STATE"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(1);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Clear up previous item column
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "REMOVE_COLUMN"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "ADD_COLUMN"))
|
||
|
{
|
||
|
//Plus one because this function seems to count the columns up from one. Charming.
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamString("contentImageList");
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_HEADER_COLOUR"))
|
||
|
{
|
||
|
CRGBA headerColour = CHudColour::GetRGBA(HUD_COLOUR_BLUE);
|
||
|
CScaleformMgr::AddParamInt(headerColour.GetRed());
|
||
|
CScaleformMgr::AddParamInt(headerColour.GetGreen());
|
||
|
CScaleformMgr::AddParamInt(headerColour.GetBlue());
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_COLUMN_TITLE"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_CATEGS"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_COLUMN_TITLE"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(1);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_CONTENT"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
#if __PPU
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SHOW_PLAYSTATION_LOGO"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamBool(true);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//Build the category list
|
||
|
const rage::cCommerceItemData* pTopLevelItemData = NULL;
|
||
|
pTopLevelItemData = pCommerceUtil->GetItemData( cStoreScreenMgr::GetBaseCategory(), cCommerceItemData::ITEM_TYPE_CATEGORY );
|
||
|
const cCommerceCategoryData* pTopLevelCategoryData = NULL;
|
||
|
if(pTopLevelItemData && pTopLevelItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_CATEGORY)
|
||
|
{
|
||
|
pTopLevelCategoryData = static_cast<const cCommerceCategoryData*>(pTopLevelItemData);
|
||
|
}
|
||
|
|
||
|
if (pTopLevelCategoryData==NULL)
|
||
|
{
|
||
|
//Handle the case where a top level category is not found for whatever reason
|
||
|
pTopLevelItemData = pCommerceUtil->GetItemData( "TOP_DEFAULT", cCommerceItemData::ITEM_TYPE_CATEGORY );
|
||
|
if(pTopLevelItemData && pTopLevelItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_CATEGORY)
|
||
|
{
|
||
|
pTopLevelCategoryData = static_cast<const cCommerceCategoryData*>(pTopLevelItemData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int numberOfCategories = 0;
|
||
|
|
||
|
bool customTopLevelCategory = false;
|
||
|
|
||
|
if(pTopLevelCategoryData)
|
||
|
{
|
||
|
for(int i= 0; i < pTopLevelCategoryData->GetNumProducts(); i++)
|
||
|
{
|
||
|
int itemIndex = pTopLevelCategoryData->GetItemIndex(i);
|
||
|
const cCommerceItemData* pCatItemData = pCommerceUtil->GetItemData(itemIndex);
|
||
|
|
||
|
if (pCatItemData)
|
||
|
{
|
||
|
//Check if we are a category or an item.
|
||
|
if (pCatItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_CATEGORY && (static_cast<const cCommerceCategoryData*>(pCatItemData))->GetNumProducts() > 0 )
|
||
|
{
|
||
|
m_CategoryIndexArray.PushAndGrow(itemIndex);
|
||
|
//Category, add to appropriate column
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
atString tempString = pCatItemData->GetName();
|
||
|
storeUIDebugf3("Setting the string name to %s",tempString.c_str());
|
||
|
CScaleformMgr::AddParamInt(CAT_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(numberOfCategories);
|
||
|
CScaleformMgr::AddParamString(tempString.c_str());
|
||
|
CScaleformMgr::EndMethod();
|
||
|
|
||
|
numberOfCategories++;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int initialCategoryIndex = INVALID_ITEM_INDEX;
|
||
|
int currentCatagory = m_CurrentlySelectedCategory;
|
||
|
|
||
|
if ( m_CurrentlySelectedCategory == INVALID_ITEM_INDEX )
|
||
|
{
|
||
|
//We are in the initial state of the store. Display the first category found.
|
||
|
if ( m_CategoryIndexArray.GetCount() == 0 )
|
||
|
{
|
||
|
//Check if we are looking at an over-ridden base category and see if that category is valid
|
||
|
if (pTopLevelCategoryData )
|
||
|
{
|
||
|
//Special case, a custom category with items but no sub category
|
||
|
|
||
|
//Category, add to appropriate column
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
atString tempString = pTopLevelCategoryData->GetName();
|
||
|
storeUIDebugf3("Setting the string name to %s",tempString.c_str());
|
||
|
CScaleformMgr::AddParamInt(CAT_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(numberOfCategories);
|
||
|
CScaleformMgr::AddParamString(tempString.c_str());
|
||
|
CScaleformMgr::EndMethod();
|
||
|
|
||
|
numberOfCategories++;
|
||
|
}
|
||
|
|
||
|
//Find the ID of this category
|
||
|
for (int i=0; i < pCommerceUtil->GetNumItems(); i++)
|
||
|
{
|
||
|
if ( pCommerceUtil->GetItemData(i)->GetId() == pTopLevelCategoryData->GetId() )
|
||
|
{
|
||
|
m_CategoryIndexArray.PushAndGrow(i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
customTopLevelCategory = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//No categories. Call function to setup no data notification here.
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
storeUIDebugf1("UpdateStoreLists :: InitialItemId: %s, SubscriptionUpsellItemId: %s, SubscriptionUpsellTargetItemId: %s",
|
||
|
cStoreScreenMgr::GetInitialItemID().c_str(),
|
||
|
m_SubscriptionUpsellItemId.c_str(),
|
||
|
m_SubscriptionUpsellTargetItemId.c_str());
|
||
|
|
||
|
// tracking whether we have an initial item or not
|
||
|
const cCommerceItemData* pInitialItemData = nullptr;
|
||
|
|
||
|
int validInitialCategoryIndex = INVALID_ITEM_INDEX;
|
||
|
if ( cStoreScreenMgr::GetInitialItemID().GetLength() > 0 )
|
||
|
{
|
||
|
pInitialItemData = pCommerceUtil->GetItemDataByItemId(cStoreScreenMgr::GetInitialItemID().c_str());
|
||
|
}
|
||
|
// if we have a target for post-upsell, use that
|
||
|
else if(m_SubscriptionUpsellTargetItemId.GetLength() > 0)
|
||
|
{
|
||
|
pInitialItemData = pCommerceUtil->GetItemDataByItemId(m_SubscriptionUpsellTargetItemId.c_str());
|
||
|
|
||
|
// our subscription changed, request new images
|
||
|
m_PendingImageRequest = true;
|
||
|
}
|
||
|
|
||
|
// tracking whether we have an initial item or not
|
||
|
if ( pInitialItemData )
|
||
|
{
|
||
|
//We found our initial item. Now check if there is a category that it is a member of in our category list
|
||
|
storeUIDebugf1("UpdateStoreLists :: Found InitialItem: %s", pInitialItemData->GetName().c_str());
|
||
|
|
||
|
for ( int iItemsCats = 0; iItemsCats < pInitialItemData->GetCategoryMemberships().GetCount(); iItemsCats++ )
|
||
|
{
|
||
|
for ( int iValidCats = 0; iValidCats < m_CategoryIndexArray.GetCount(); iValidCats++ )
|
||
|
{
|
||
|
if ( pInitialItemData->GetCategoryMemberships()[iItemsCats] == pCommerceUtil->GetItemData( m_CategoryIndexArray[iValidCats] )->GetId() )
|
||
|
{
|
||
|
//We have a found a category which
|
||
|
//a) the item belongs to
|
||
|
//b) is in our base category list
|
||
|
validInitialCategoryIndex = iValidCats;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (validInitialCategoryIndex == INVALID_ITEM_INDEX )
|
||
|
{
|
||
|
currentCatagory = m_CategoryIndexArray[0];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
currentCatagory = m_CategoryIndexArray[validInitialCategoryIndex];
|
||
|
initialCategoryIndex = validInitialCategoryIndex;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if ( m_CurrentlySelectedCategory < 0 || m_CurrentlySelectedCategory >= m_CategoryIndexArray.GetCount() )
|
||
|
{
|
||
|
commerceErrorf("We have hit the commerce list safety fall through with a category list size of %d and an index of %d", m_CategoryIndexArray.GetCount(), m_CurrentlySelectedCategory);
|
||
|
DoEmptyStoreCheck();
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//We have a valid slot.
|
||
|
storeUIAssert(m_CurrentlySelectedCategory >= 0 && m_CurrentlySelectedCategory < m_CategoryIndexArray.GetCount() );
|
||
|
|
||
|
currentCatagory = m_CategoryIndexArray[ m_CurrentlySelectedCategory ];
|
||
|
}
|
||
|
|
||
|
const cCommerceCategoryData* pCategoryData = NULL;
|
||
|
|
||
|
if (customTopLevelCategory)
|
||
|
{
|
||
|
pCategoryData = pTopLevelCategoryData;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Get the list of items in this category to display them.
|
||
|
const rage::cCommerceItemData* pItemData = NULL;
|
||
|
pItemData = pCommerceUtil->GetItemData( currentCatagory );
|
||
|
|
||
|
if(storeUIVerifyf( pItemData && pItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_CATEGORY, "pItem not retrieved") )
|
||
|
{
|
||
|
pCategoryData = static_cast<const cCommerceCategoryData*>(pItemData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
storeUIDebugf1("UpdateStoreLists :: Category data - NumItems: %d, Name: %s", pCategoryData->GetNumProducts(), pCategoryData->GetName().c_str());
|
||
|
|
||
|
//Clear the existing center data slot of items.
|
||
|
if ( CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT_EMPTY"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
//Clear the columns.
|
||
|
for (s32 iClearCols=1; iClearCols < NUM_COLUMNS; iClearCols++)
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT_EMPTY"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(iClearCols);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Clear the existing center data slot of items.
|
||
|
if ( CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "DISPLAY_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
int initialProductIndex = INVALID_ITEM_INDEX;
|
||
|
|
||
|
int numberOfItems = 0;
|
||
|
|
||
|
int numberOfProducts = 0;
|
||
|
if(pCategoryData)
|
||
|
{
|
||
|
numberOfItems = pCategoryData->GetNumProducts();
|
||
|
|
||
|
for(int i= 0; i < numberOfItems; i++)
|
||
|
{
|
||
|
int itemIndex = pCategoryData->GetItemIndex(i);
|
||
|
const cCommerceItemData* pCatItemData = pCommerceUtil->GetItemData(itemIndex);
|
||
|
|
||
|
if (pCatItemData)
|
||
|
{
|
||
|
//Check if we are a category or an item.
|
||
|
if (pCatItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_CATEGORY && (static_cast<const cCommerceCategoryData*>(pCatItemData))->GetNumProducts() > 0 )
|
||
|
{
|
||
|
m_CategoryIndexArray.PushAndGrow(itemIndex);
|
||
|
//Category, add to appropriate column
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
atString tempString = pCatItemData->GetName();
|
||
|
storeUIDebugf3("Setting the string name to %s",tempString.c_str());
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(numberOfCategories);
|
||
|
CScaleformMgr::AddParamString(tempString.c_str());
|
||
|
CScaleformMgr::EndMethod();
|
||
|
|
||
|
numberOfCategories++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pCatItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT)
|
||
|
{
|
||
|
const cCommerceProductData *pProductData = static_cast<const cCommerceProductData*>(pCatItemData);
|
||
|
|
||
|
const bool showProduct =
|
||
|
(pCommerceUtil->HasProductDetails(pProductData) || pCommerceUtil->ShouldAllowWithoutProduct(pProductData)) &&
|
||
|
!pCommerceUtil->ShouldHideProduct(pProductData);
|
||
|
|
||
|
storeUIDebugf1("UpdateStoreLists :: %s: %s - %s, HasProduct: %s, AllowWithoutProduct: %s, Hide: %s",
|
||
|
showProduct ? "Adding" : "Skipping",
|
||
|
pProductData ? pProductData->GetId().c_str() : "[InvalidProduct]",
|
||
|
pProductData ? pProductData->GetName().c_str() : "[InvalidProduct]",
|
||
|
pCommerceUtil->HasProductDetails(pProductData) ? "True" : "False",
|
||
|
pCommerceUtil->ShouldAllowWithoutProduct(pProductData) ? "True" : "False",
|
||
|
pCommerceUtil->ShouldHideProduct(pProductData) ? "True" : "False");
|
||
|
|
||
|
// exit if we can't show this product
|
||
|
if(!showProduct)
|
||
|
continue;
|
||
|
|
||
|
m_ProductIndexArray.PushAndGrow(itemIndex);
|
||
|
|
||
|
//Item, add to appropriate column
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(numberOfProducts);
|
||
|
|
||
|
//No string, so that the images start off as a spinner.
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
CScaleformMgr::EndMethod();
|
||
|
|
||
|
//Show the first product.
|
||
|
if ( numberOfProducts == 0 )
|
||
|
{
|
||
|
storeUIDebugf1("UpdateStoreLists :: Displaying First Item");
|
||
|
DisplayItemDetails( pProductData );
|
||
|
}
|
||
|
|
||
|
if (pProductData->GetId() == cStoreScreenMgr::GetInitialItemID() || pProductData->GetId() == m_SubscriptionUpsellTargetItemId)
|
||
|
{
|
||
|
storeUIDebugf1("UpdateStoreLists :: Displaying Initial Item (Index: %d, Product: %s)", numberOfProducts, pProductData->GetName().c_str());
|
||
|
|
||
|
initialProductIndex = numberOfProducts;
|
||
|
|
||
|
//Set the initial string to empty so this does not occur each time.
|
||
|
atString emptyString("");
|
||
|
cStoreScreenMgr::SetInitialItemID(emptyString);
|
||
|
|
||
|
//We want these details displayed on initial store entry
|
||
|
DisplayItemDetails( pProductData );
|
||
|
}
|
||
|
|
||
|
numberOfProducts++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( numberOfProducts == 0 )
|
||
|
{
|
||
|
//We have no products in this category, so clear the details column.
|
||
|
ClearItemDetails();
|
||
|
}
|
||
|
|
||
|
if ( initialCategoryIndex != INVALID_ITEM_INDEX )
|
||
|
{
|
||
|
//We have a non zero initial category set
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "HIGHLIGHT_ITEM"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(CAT_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(initialCategoryIndex);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
m_LastItemIndex = initialCategoryIndex;
|
||
|
}
|
||
|
|
||
|
if ( initialProductIndex != INVALID_ITEM_INDEX )
|
||
|
{
|
||
|
//We have found a requested initial product
|
||
|
m_LastColumnIndex = ITEM_COLUMN_INDEX;
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "HIGHLIGHT_ITEM"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(initialProductIndex);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
m_LastCenterItemIndex = initialProductIndex;
|
||
|
m_LastItemIndex = initialProductIndex;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "HIGHLIGHT_COLUMN"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(CAT_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
|
||
|
m_LastCenterItemIndex = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (s32 iCols=0; iCols < NUM_COLUMNS; iCols++)
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "DISPLAY_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(iCols);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "GET_CURRENT_START_INDEX"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
m_CurrentStartReturnId = CScaleformMgr::EndMethodReturnValue(m_CurrentStartReturnId);
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "GET_CURRENT_END_INDEX"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
m_CurrentEndReturnId = CScaleformMgr::EndMethodReturnValue(m_CurrentEndReturnId);
|
||
|
}
|
||
|
|
||
|
//Check for empty store
|
||
|
DoEmptyStoreCheck();
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::Update()
|
||
|
{
|
||
|
rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!m_Initialised)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#if RSG_NP
|
||
|
if (CWarningScreen::IsActive())
|
||
|
{
|
||
|
if (m_isCommerceLogoDisplaying)
|
||
|
{
|
||
|
g_rlNp.GetCommonDialog().HideCommerceLogo();
|
||
|
m_isCommerceLogoDisplaying = false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!m_isCommerceLogoDisplaying && m_shouldCommerceLogoDisplay)
|
||
|
{
|
||
|
m_isCommerceLogoDisplaying = g_rlNp.GetCommonDialog().ShowCommerceLogo(rlNpCommonDialog::COMMERCE_LOGO_POS_LEFT);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (!UpdateWarningScreen())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !UpdateNonCriticalWarningScreen() )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (m_PendingListSetup && !CLiveManager::GetCommerceMgr().GetCommerceUtil()->IsInErrorState() )
|
||
|
{
|
||
|
UpdateStoreLists();
|
||
|
m_PendingListSetup = false;
|
||
|
}
|
||
|
|
||
|
if (m_PendingLongDescriptionItem != NULL && pCommerceUtil->GetItemLongDescription(m_PendingLongDescriptionItem) != NULL)
|
||
|
{
|
||
|
DisplayItemDetails(m_PendingLongDescriptionItem);
|
||
|
m_PendingLongDescriptionItem = NULL;
|
||
|
}
|
||
|
|
||
|
switch( m_CurrentState )
|
||
|
{
|
||
|
case(STATE_INITIALISING):
|
||
|
UpdateInitialising();
|
||
|
break;
|
||
|
case(STATE_NEUTRAL):
|
||
|
UpdateInput();
|
||
|
break;
|
||
|
case(STATE_PENDING_INITIAL_DATA):
|
||
|
UpdatePendingInitialData();
|
||
|
break;
|
||
|
case(STATE_LOADING_ASSETS):
|
||
|
UpdateLoadingAssets();
|
||
|
break;
|
||
|
case(STATE_IN_CHECKOUT):
|
||
|
UpdateCheckout();
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( m_ColumnReturnId != 0 )
|
||
|
{
|
||
|
if (CScaleformMgr::IsReturnValueSet(m_ColumnReturnId))
|
||
|
{
|
||
|
m_LastColumnIndex = CScaleformMgr::GetReturnValueInt(m_ColumnReturnId);
|
||
|
m_ColumnReturnId = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_ItemReturnId != 0 )
|
||
|
{
|
||
|
if (CScaleformMgr::IsReturnValueSet(m_ItemReturnId))
|
||
|
{
|
||
|
m_LastItemIndex = CScaleformMgr::GetReturnValueInt(m_ItemReturnId);
|
||
|
|
||
|
if ( m_LastItemIndex < 0 )
|
||
|
{
|
||
|
commerceErrorf("m_LastItemIndex set to %d. Almost certainly bad.", m_LastItemIndex);
|
||
|
}
|
||
|
|
||
|
m_ItemReturnId = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool imageUpdateRequired = false;
|
||
|
|
||
|
if ( m_CurrentStartReturnId != 0 )
|
||
|
{
|
||
|
if (CScaleformMgr::IsReturnValueSet(m_CurrentStartReturnId))
|
||
|
{
|
||
|
m_LastStartIndex = CScaleformMgr::GetReturnValueInt(m_CurrentStartReturnId);
|
||
|
m_CurrentStartReturnId = 0;
|
||
|
|
||
|
if ( m_CurrentEndReturnId == 0 )
|
||
|
{
|
||
|
imageUpdateRequired = true;
|
||
|
}
|
||
|
|
||
|
// if (m_LastStartIndex < 0 || m_LastStartIndex > m_ProductIndexArray.GetCount() )
|
||
|
// {
|
||
|
// m_LastStartIndex = 0;
|
||
|
// }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_CurrentEndReturnId != 0 )
|
||
|
{
|
||
|
if (CScaleformMgr::IsReturnValueSet(m_CurrentEndReturnId))
|
||
|
{
|
||
|
m_LastEndIndex = CScaleformMgr::GetReturnValueInt(m_CurrentEndReturnId);
|
||
|
m_CurrentEndReturnId = 0;
|
||
|
|
||
|
if ( m_CurrentStartReturnId == 0 )
|
||
|
{
|
||
|
imageUpdateRequired = true;
|
||
|
}
|
||
|
|
||
|
// if (m_LastEndIndex < 0 || m_LastEndIndex > m_ProductIndexArray.GetCount() )
|
||
|
// {
|
||
|
// m_LastEndIndex = 0;
|
||
|
// }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//We have our new start and end IDs after a move, sort out the images
|
||
|
if (imageUpdateRequired || m_PendingImageRequest)
|
||
|
{
|
||
|
m_PendingImageRequest = false;
|
||
|
PopulateImageRequests();
|
||
|
}
|
||
|
|
||
|
UpdateImageRequests();
|
||
|
|
||
|
if ( pCommerceUtil->IsCategoryInfoPopulated() && m_CurrentState == STATE_NEUTRAL && CBusySpinner::IsOn() )
|
||
|
{
|
||
|
CBusySpinner::Off( SPINNER_SOURCE_STORE_LOADING );
|
||
|
}
|
||
|
|
||
|
if ( pCommerceUtil->IsContentInfoPopulated() && m_PendingHighlightChange && m_ItemReturnId == 0 && m_ColumnReturnId == 0 )
|
||
|
{
|
||
|
ProcessHighlightChange();
|
||
|
m_PendingHighlightChange = false;
|
||
|
UpdateContextHelp();
|
||
|
}
|
||
|
|
||
|
UpdateLeaderBoardDataFetch();
|
||
|
|
||
|
//If we were in the checkout we need to detect when that is no longer the case and correctly update the product states
|
||
|
if ( m_WasInCheckout && pCommerceUtil->IsInCheckout() == false && CLiveManager::IsOnline() && CLiveManager::IsOnlineRos()
|
||
|
&& pCommerceUtil->DidLastCheckoutSucceed() )
|
||
|
{
|
||
|
storeUIDebugf1("Update :: Now out of store");
|
||
|
//SEND AN UPDATE TO THE CONTENT SYSTEM TO RESCAN HERE
|
||
|
|
||
|
//Send the metric containing the completed checkout product here
|
||
|
const int TEMP_PRICE_STRING_LEN = 128;
|
||
|
char tempPriceString[TEMP_PRICE_STRING_LEN];
|
||
|
atString priceString;
|
||
|
if (m_PendingCheckoutProduct != nullptr && pCommerceUtil->GetProductPrice(m_PendingCheckoutProduct, tempPriceString, TEMP_PRICE_STRING_LEN) >= 0.0f)
|
||
|
{
|
||
|
CNetworkTelemetry::AppendMetric(MetricIngameStoreCheckoutComplete(tempPriceString, (m_PendingCheckoutProduct ? m_PendingCheckoutProduct->GetPlatformId().c_str() : "")));
|
||
|
}
|
||
|
|
||
|
|
||
|
// PS3 only xbox should process event for this
|
||
|
#if __PS3
|
||
|
EXTRACONTENT.OnContentDownloadCompleted();
|
||
|
#endif // __PS3
|
||
|
|
||
|
#if NET_ENABLE_MEMBERSHIP_FUNCTIONALITY
|
||
|
// refresh membership status - defaulted to true
|
||
|
if(Tunables::IsInstantiated() && Tunables::GetInstance().TryAccess(CD_GLOBAL_HASH, ATSTRINGHASH("NET_MEMBERSHIP_REFRESH_ON_PURCHASED_MEMBERSHIP", 0x2be302ce), true))
|
||
|
{
|
||
|
storeUIDebugf1("Update :: Requesting Membership Status");
|
||
|
rlScMembership::RequestMembershipStatus(NetworkInterface::GetLocalGamerIndex());
|
||
|
}
|
||
|
|
||
|
// Add relevant subscription Ids
|
||
|
if(rlScMembership::HasMembership(NetworkInterface::GetLocalGamerIndex()))
|
||
|
{
|
||
|
storeUIDebugf1("Update :: AddSubscriptionId: %s", rlScMembership::GetSubscriptionId());
|
||
|
CLiveManager::GetCommerceMgr().GetCommerceUtil()->AddSubscriptionId(rlScMembership::GetSubscriptionId());
|
||
|
}
|
||
|
|
||
|
// disable membership notifications for script
|
||
|
// don't reset the upsell item here - we need it to reinsert ourselves in the selection window
|
||
|
if(!m_SubscriptionUpsellItemId.empty())
|
||
|
{
|
||
|
storeUIDebugf1("Update :: Upsell Path, suppressing membership");
|
||
|
CLiveManager::SetSuppressMembershipForScript(true);
|
||
|
|
||
|
// we also want to show the welcome here
|
||
|
m_PendingNonCriticalWarningScreen = STORE_SUBSCRIPTION_WELCOME;
|
||
|
CLiveManager::SetHasShownMembershipWelcome();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
pCommerceUtil->DoDataRequest(false);
|
||
|
m_RefetchingPlatformData = true;
|
||
|
}
|
||
|
|
||
|
if ( m_RefetchingPlatformData == true && !pCommerceUtil->IsInDataFetchState() && pCommerceUtil->IsContentInfoPopulated() )
|
||
|
{
|
||
|
m_RefetchingPlatformData = false;
|
||
|
//ClearLoadedImages();
|
||
|
//m_PendingListSetup = true;
|
||
|
TriggerHighlightChange();
|
||
|
|
||
|
UpdateContextHelp();
|
||
|
|
||
|
//Check to see if a previously requested product is now owned, increment the money spent stat if so.
|
||
|
if ( m_PurchaseCheckProductID.GetLength() > 0 )
|
||
|
{
|
||
|
rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
if ( pCommerceUtil != NULL )
|
||
|
{
|
||
|
const cCommerceItemData *purchasedItem = pCommerceUtil->GetItemData(m_PurchaseCheckProductID);
|
||
|
|
||
|
if ( purchasedItem && purchasedItem->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT )
|
||
|
{
|
||
|
const cCommerceProductData *pProductData = static_cast<const cCommerceProductData*>(purchasedItem);
|
||
|
|
||
|
//Check to see if the item is now owned
|
||
|
if ( pProductData->IsConsumable() )
|
||
|
{
|
||
|
//Its a consumable. Store its inventory level
|
||
|
m_ConsumableProductCheckId = m_PurchaseCheckProductID;
|
||
|
m_ConsumableProductCheckLevel = CLiveManager::GetCommerceMgr().GetConsumableManager()->GetConsumableLevel(pProductData->GetConsumableId());
|
||
|
|
||
|
//then refetch data to compare.
|
||
|
CLiveManager::GetCommerceMgr().GetConsumableManager()->SetOwnershipDataDirty();
|
||
|
|
||
|
//Pause auto consume to avoid potential timing issues
|
||
|
CLiveManager::GetCommerceMgr().SetAutoConsumePaused(true);
|
||
|
|
||
|
}
|
||
|
else if ( pCommerceUtil->IsProductPurchased(pProductData) )
|
||
|
{
|
||
|
//Really not appropriate, due to currency differences
|
||
|
//AddProductsPriceToCashSpentStat(pProductData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StatsInterface::IncrementStat(STAT_MPPLY_STORE_CHECKOUTS_CANCELLED, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_PurchaseCheckProductID.Reset();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Probably a code entry. Rescan consumables in case it was a cash entry.
|
||
|
CLiveManager::GetCommerceMgr().GetConsumableManager()->SetOwnershipDataDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Do we have a pending consumables level check and valid consumables data since the last refresh?
|
||
|
if ( m_ConsumableProductCheckId.GetLength() > 0 && CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataPopulated() )
|
||
|
{
|
||
|
//Yes, compare the ownership level
|
||
|
rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
if ( pCommerceUtil != NULL )
|
||
|
{
|
||
|
const cCommerceItemData *purchasedItem = pCommerceUtil->GetItemData(m_ConsumableProductCheckId);
|
||
|
|
||
|
if ( purchasedItem && purchasedItem->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT )
|
||
|
{
|
||
|
const cCommerceProductData *pProductData = static_cast<const cCommerceProductData*>(purchasedItem);
|
||
|
|
||
|
if (CLiveManager::GetCommerceMgr().GetConsumableManager()->GetConsumableLevel(pProductData->GetConsumableId()) > m_ConsumableProductCheckLevel)
|
||
|
{
|
||
|
AddProductsPriceToCashSpentStat(pProductData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StatsInterface::IncrementStat(STAT_MPPLY_STORE_CHECKOUTS_CANCELLED, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_ConsumableProductCheckId.Reset();
|
||
|
}
|
||
|
|
||
|
if ( m_WasConsumableDataDirtyLastFrame && CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataPopulated() )
|
||
|
{
|
||
|
m_WasConsumableDataDirtyLastFrame = false;
|
||
|
UpdateChangeInConsumableLevelCheck();
|
||
|
UpdatePendingCash();
|
||
|
}
|
||
|
|
||
|
UpdateTopOfScreenTextInfo();
|
||
|
|
||
|
if ( CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataDirty() )
|
||
|
{
|
||
|
m_WasConsumableDataDirtyLastFrame = true;
|
||
|
}
|
||
|
|
||
|
if ( pCommerceUtil->IsContentInfoPopulated() && m_PendingSelection )
|
||
|
{
|
||
|
ProcessSelection();
|
||
|
m_PendingSelection = false;
|
||
|
UpdateContextHelp();
|
||
|
}
|
||
|
|
||
|
CBusySpinner::Update();
|
||
|
m_WasInCheckout = pCommerceUtil->IsInCheckout();
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::Render()
|
||
|
{
|
||
|
GRC_ALLOC_SCOPE_AUTO_PUSH_POP();
|
||
|
|
||
|
float fTimeStep = fwTimer::GetSystemTimeStep();
|
||
|
if (m_StoreBgMovieId >= 0)
|
||
|
{
|
||
|
CScaleformMgr::RenderMovie( m_StoreBgMovieId, fTimeStep, true );
|
||
|
}
|
||
|
|
||
|
if (m_CurrentState == STATE_LOADING_ASSETS ||
|
||
|
m_CurrentState == STATE_INITIALISING ||
|
||
|
m_CurrentState == STATE_PENDING_INITIAL_DATA)
|
||
|
{
|
||
|
CPauseMenu::RenderAnimatedSpinner(-1.0f, true, false); // fix for 1495684
|
||
|
}
|
||
|
|
||
|
if ( /*m_CurrentState == STATE_LOADING_ASSETS ||*/ m_CurrentState == STATE_PENDING_INITIAL_DATA && !cStoreScreenMgr::IsExitRequested() )
|
||
|
{
|
||
|
//char cHtmlFormattedBusyString[256];
|
||
|
//char* html = CTextConversion::TextToHtml(TheText.Get("STORE_LOADING"),cHtmlFormattedBusyString,sizeof(cHtmlFormattedBusyString));
|
||
|
//CBusySpinner::On( html, SPINNER_ICON_LOADING, SPINNER_SOURCE_STORE_LOADING );
|
||
|
//CPauseMenu::RenderAnimatedSpinner(-1.0f,true);
|
||
|
}
|
||
|
|
||
|
if (!m_Initialised)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#if RSG_PC
|
||
|
// hide instructional buttons if SCUI is showing ...hints are confusing
|
||
|
if (!g_rlPc.IsUiShowing())
|
||
|
#endif
|
||
|
{
|
||
|
if ( m_ButtonMovieId >= 0)
|
||
|
{
|
||
|
CScaleformMgr::RenderMovie( m_ButtonMovieId, fTimeStep, true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int buttonMovieIndex = CScaleformMgr::FindMovieByFilename(BUTTONMENU_FILENAME);
|
||
|
if ( buttonMovieIndex >= 0 )
|
||
|
{
|
||
|
CScaleformMgr::RenderMovie( buttonMovieIndex, fTimeStep, true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_StoreMovieId >= 0)
|
||
|
{
|
||
|
CScaleformMgr::RenderMovie( m_StoreMovieId, fTimeStep, true );
|
||
|
}
|
||
|
|
||
|
if (CNewHud::GetHudComponentMovieId(NEW_HUD_SAVING_GAME) >= 0)
|
||
|
{
|
||
|
CScaleformMgr::RenderMovie( CNewHud::GetHudComponentMovieId(NEW_HUD_SAVING_GAME), fTimeStep, true );
|
||
|
}
|
||
|
|
||
|
if ( m_BlackFadeMovieId >= 0 )
|
||
|
{
|
||
|
CScaleformMgr::RenderMovie( m_BlackFadeMovieId, fTimeStep, true );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateInitialising()
|
||
|
{
|
||
|
//They really, really should be if we are in here.
|
||
|
storeUIAssert(AreAllAssetsActive());
|
||
|
if (AreAllAssetsActive())
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "MENU_STATE"))
|
||
|
{
|
||
|
s32 menuStateParam = 1; //1 is the value we pass for the store screen.
|
||
|
CScaleformMgr::AddParamInt(menuStateParam);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_CONTENTIMAGE_SIZE"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt( static_cast<int>(pow(2.0f, cStoreScreenMgr::GetStoreItemNumPerColumnExp() ) ));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_SHOP_LOGO"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(cStoreScreenMgr::GetBranding());
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SHOW_SHOP_LOGO"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamBool( cStoreScreenMgr::GetBranding() != 0 );
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
UpdateTopOfScreenTextInfo();
|
||
|
|
||
|
// if (m_PedHeadShotHandle != 0 && CScaleformMgr::BeginMethod( m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_CHAR_IMG"))
|
||
|
// {
|
||
|
// const char* pedHeadShotTextureName = PEDHEADSHOTMANAGER.GetTextureName((s32)m_PedHeadShotHandle);
|
||
|
// CScaleformMgr::AddParamString( pedHeadShotTextureName, false);
|
||
|
// CScaleformMgr::AddParamString( pedHeadShotTextureName, false);
|
||
|
// bool
|
||
|
// CScaleformMgr::AddParamBool( pedHeadShotTextureName[0] != '\0'); // fixes 1212873
|
||
|
// CScaleformMgr::EndMethod();
|
||
|
// }
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
storeUIErrorf("Assets were not loaded upon reaching the store menu. Extreme badness alert.");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_CurrentState = STATE_NEUTRAL;
|
||
|
m_Initialised = true;
|
||
|
CLiveManager::GetCommerceMgr().OnEnterUIStore();
|
||
|
|
||
|
if ( !m_TimerSinceInputEnabled.IsStarted() )
|
||
|
{
|
||
|
m_TimerSinceInputEnabled.Start();
|
||
|
}
|
||
|
|
||
|
|
||
|
UpdateContextHelp();
|
||
|
|
||
|
//Take the loading spinner off screen
|
||
|
//CBusySpinner::Off( SPINNER_SOURCE_STORE_LOADING );
|
||
|
}
|
||
|
|
||
|
bool cStoreMainScreen::AreAllAssetsActive()
|
||
|
{
|
||
|
bool retVal = ( m_StoreMovieId != INVALID_MOVIE_ID && CScaleformMgr::IsMovieActive(m_StoreMovieId) &&
|
||
|
m_StoreBgMovieId != INVALID_MOVIE_ID && CScaleformMgr::IsMovieActive(m_StoreBgMovieId) &&
|
||
|
m_BlackFadeMovieId != INVALID_MOVIE_ID);
|
||
|
|
||
|
if ( m_ButtonMovieId != INVALID_MOVIE_ID && !CScaleformMgr::IsMovieActive(m_ButtonMovieId) )
|
||
|
{
|
||
|
retVal = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
return retVal;
|
||
|
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::CheckIncomingFunctions( atHashWithStringBank methodName, const GFxValue* /*args*/ )
|
||
|
{
|
||
|
if (!m_Initialised)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (methodName == ATSTRINGHASH("LOAD_PAUSE_MENU_STORE_CONTENT",0x879bc589))
|
||
|
{
|
||
|
storeUIDebugf3("Store Advert screen callback recieved by main menu.\n");
|
||
|
|
||
|
if (!DoQuickCheckout())
|
||
|
{
|
||
|
m_PendingListSetup = true;
|
||
|
|
||
|
#if RSG_NP
|
||
|
m_isCommerceLogoDisplaying = g_rlNp.GetCommonDialog().ShowCommerceLogo(rlNpCommonDialog::COMMERCE_LOGO_POS_LEFT);
|
||
|
m_shouldCommerceLogoDisplay = true;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( methodName == ATSTRINGHASH("FADE_TO_BLACK_COMPLETED",0x8d27a5a7) )
|
||
|
{
|
||
|
if ( m_CurrentState == STATE_STORE_FADE_TO_BLACK )
|
||
|
{
|
||
|
rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
if (m_PendingCheckoutProduct != NULL)
|
||
|
{
|
||
|
pCommerceUtil->CheckoutProduct(m_PendingCheckoutProduct);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pCommerceUtil->ProductCodeEntry();
|
||
|
}
|
||
|
|
||
|
m_HasBeenInCheckout = true;
|
||
|
m_CurrentState = STATE_IN_CHECKOUT;
|
||
|
|
||
|
// NOTE: good alternative position to HideCommerceLogo at end of fade, rather than start. 50/50 what looks nicer.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( methodName == ATSTRINGHASH("FADE_TO_TRANSPARENT_COMPLETED",0x351af647) )
|
||
|
{
|
||
|
if ( m_CurrentState == STATE_STORE_FADE_TO_TRANS )
|
||
|
{
|
||
|
m_CurrentState = STATE_NEUTRAL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateInput()
|
||
|
{
|
||
|
if (m_ColumnReturnId != 0 || m_ItemReturnId != 0) // fix for 1912443 - dont request multiple return value requests
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!AreAllAssetsActive())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (cStoreScreenMgr::IsExitRequested())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( m_InNoProductsMode || !m_StoreListsSetup )
|
||
|
{
|
||
|
//This input update allows the user access to exit and code entry.
|
||
|
UpdateNoContentInput();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool highlightChangeRequired = false;
|
||
|
bool currentSlotRangeCheckRequired = false;
|
||
|
|
||
|
int axisR = static_cast<s32>(CControlMgr::GetMainFrontendControl().GetFrontendRStickUpDown().GetNorm() * 128.0f);
|
||
|
|
||
|
if ( RIGHT_STICK_DEADZONE < Abs(axisR) )
|
||
|
{
|
||
|
if ( CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_ANALOG_STICK_INPUT") )
|
||
|
{
|
||
|
CScaleformMgr::AddParamBool(false);
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(axisR);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_CurrentStartReturnId == 0 && CPauseMenu::CheckInput(FRONTEND_INPUT_UP,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) )
|
||
|
{
|
||
|
if ( CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT") )
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(DPADUP);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( m_LastColumnIndex == ITEM_COLUMN_INDEX )
|
||
|
{
|
||
|
currentSlotRangeCheckRequired = true;
|
||
|
m_LastSelectionTransition = ITEM_TO_ITEM;
|
||
|
}
|
||
|
else if ( m_LastColumnIndex == CAT_COLUMN_INDEX )
|
||
|
{
|
||
|
m_LastSelectionTransition = CAT_TO_CAT;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
AssertMsg(false,"invalid column index");
|
||
|
}
|
||
|
|
||
|
highlightChangeRequired = true;
|
||
|
}
|
||
|
|
||
|
if ( m_CurrentStartReturnId == 0 && CPauseMenu::CheckInput(FRONTEND_INPUT_DOWN,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) )
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(DPADDOWN);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( m_LastColumnIndex == ITEM_COLUMN_INDEX )
|
||
|
{
|
||
|
if (m_LastItemIndex < m_ProductIndexArray.GetCount())
|
||
|
{
|
||
|
currentSlotRangeCheckRequired = true;
|
||
|
}
|
||
|
m_LastSelectionTransition = ITEM_TO_ITEM;
|
||
|
}
|
||
|
else if ( m_LastColumnIndex == CAT_COLUMN_INDEX )
|
||
|
{
|
||
|
m_LastSelectionTransition = CAT_TO_CAT;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
AssertMsg(false,"invalid column index");
|
||
|
}
|
||
|
|
||
|
highlightChangeRequired = true;
|
||
|
}
|
||
|
|
||
|
if ( CPauseMenu::CheckInput(FRONTEND_INPUT_BACK,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT_CIRCLE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
|
||
|
if ( m_LastColumnIndex == CAT_COLUMN_INDEX )
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
storeUIDebugf1("UpdateInput :: User requested exit");
|
||
|
|
||
|
cStoreScreenMgr::RequestExit();
|
||
|
CPauseMenu::PlaySound("BACK");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//We are on the item column.
|
||
|
if ( CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT") )
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(DPADLEFT);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
m_LastSelectionTransition = ITEM_TO_CAT;
|
||
|
|
||
|
highlightChangeRequired = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !m_InNoProductsMode && CPauseMenu::CheckInput(FRONTEND_INPUT_ACCEPT,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && !cStoreScreenMgr::IsExitRequested() )
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT_CROSS"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( m_LastColumnIndex == CAT_COLUMN_INDEX )
|
||
|
{
|
||
|
m_LastSelectionTransition = CAT_TO_ITEM;
|
||
|
|
||
|
//Set the selected item to be the top
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "HIGHLIGHT_ITEM"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
highlightChangeRequired = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//We are on an item
|
||
|
m_PendingSelection = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (CPauseMenu::CheckInput(FRONTEND_INPUT_Y,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && !cStoreScreenMgr::IsExitRequested() )
|
||
|
{
|
||
|
// rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
//
|
||
|
// if (pCommerceUtil)
|
||
|
// {
|
||
|
// pCommerceUtil->ProductCodeEntry();
|
||
|
// }
|
||
|
|
||
|
//Start the fade down
|
||
|
if (m_BlackFadeMovieId != INVALID_MOVIE_ID && CScaleformMgr::BeginMethod( m_BlackFadeMovieId, SF_BASE_CLASS_STORE, "FADE_TO_BLACK" ))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(STORE_FADE_TIME);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
m_PendingCheckoutProduct = NULL;
|
||
|
m_CurrentState = STATE_STORE_FADE_TO_BLACK;
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT_TRIANGLE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
CPauseMenu::PlaySound("SELECT");
|
||
|
|
||
|
#if RSG_NP
|
||
|
g_rlNp.GetCommonDialog().HideCommerceLogo();
|
||
|
m_shouldCommerceLogoDisplay = false;
|
||
|
m_isCommerceLogoDisplaying = false;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if (highlightChangeRequired)
|
||
|
{
|
||
|
TriggerHighlightChange();
|
||
|
}
|
||
|
|
||
|
if (currentSlotRangeCheckRequired)
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "GET_CURRENT_START_INDEX"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
|
||
|
m_CurrentStartReturnId = CScaleformMgr::EndMethodReturnValue(m_CurrentStartReturnId);
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "GET_CURRENT_END_INDEX"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
|
||
|
m_CurrentEndReturnId = CScaleformMgr::EndMethodReturnValue(m_CurrentEndReturnId);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateNoContentInput()
|
||
|
{
|
||
|
if ( CPauseMenu::CheckInput(FRONTEND_INPUT_BACK,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT_CIRCLE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
|
||
|
if ( m_LastColumnIndex == CAT_COLUMN_INDEX )
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
storeUIDebugf1("UpdateNoContentInput :: User requested exit");
|
||
|
|
||
|
cStoreScreenMgr::RequestExit();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (CPauseMenu::CheckInput(FRONTEND_INPUT_Y,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && !cStoreScreenMgr::IsExitRequested() )
|
||
|
{
|
||
|
//Start the fade down
|
||
|
if (m_BlackFadeMovieId != INVALID_MOVIE_ID && CScaleformMgr::BeginMethod( m_BlackFadeMovieId, SF_BASE_CLASS_STORE, "FADE_TO_BLACK" ))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(STORE_FADE_TIME);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
m_PendingCheckoutProduct = NULL;
|
||
|
m_CurrentState = STATE_STORE_FADE_TO_BLACK;
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT_TRIANGLE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
CPauseMenu::PlaySound("SELECT");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::ProcessSelection()
|
||
|
{
|
||
|
storeUIDebugf3("Selected column %d selection %d",m_LastColumnIndex,m_LastItemIndex);
|
||
|
|
||
|
rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( m_LastColumnIndex == DETAIL_COLUMN_INDEX || m_LastColumnIndex == ITEM_COLUMN_INDEX )
|
||
|
{
|
||
|
if ( m_LastCenterItemIndex == INVALID_ITEM_INDEX || m_LastCenterItemIndex >= m_ProductIndexArray.GetCount() )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
const cCommerceItemData* pItemData = pCommerceUtil->GetItemData(m_ProductIndexArray[ m_LastCenterItemIndex ]);
|
||
|
|
||
|
if ( pItemData != NULL && pItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT )
|
||
|
{
|
||
|
const cCommerceProductData *pProductData = static_cast<const cCommerceProductData*>(pItemData);
|
||
|
ProcessCheckoutSelected(pProductData);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//We are on the category column, so fire a dpad right message
|
||
|
if ( CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(DPADRIGHT);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
TriggerHighlightChange();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::ProcessHighlightChange()
|
||
|
{
|
||
|
storeUIDebugf3("ProcessHighlightChange :: Column: %d, Selection: %d", m_LastColumnIndex, m_LastItemIndex);
|
||
|
|
||
|
if ( m_LastColumnIndex == ITEM_COLUMN_INDEX )
|
||
|
{
|
||
|
//Store the item index for later
|
||
|
m_LastCenterItemIndex = m_LastItemIndex;
|
||
|
|
||
|
if ( m_LastItemIndex == INVALID_ITEM_INDEX || m_LastItemIndex >= m_ProductIndexArray.GetCount() )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const cCommerceItemData* pItemData = pCommerceUtil->GetItemData(m_ProductIndexArray[ m_LastItemIndex ]);
|
||
|
|
||
|
if ( pItemData != NULL && pItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT )
|
||
|
{
|
||
|
const cCommerceProductData *pProductData = static_cast<const cCommerceProductData*>(pItemData);
|
||
|
DisplayItemDetails( pProductData );
|
||
|
}
|
||
|
|
||
|
//Set slots with no loaded texture to display a blank.
|
||
|
for ( s32 iSlots = 0; iSlots < (Min(m_ProductIndexArray.GetCount(), MAX_NUM_ITEMS_IN_MIDDLE_COLUMN) ); iSlots++ )
|
||
|
{
|
||
|
int requestedSlotIndex = (m_LastStartIndex + iSlots) % m_ProductIndexArray.GetCount();
|
||
|
if ( m_LoadedImageIndices.Find( requestedSlotIndex ) == -1 )
|
||
|
{
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
if ( pCommerceUtil )
|
||
|
{
|
||
|
const cCommerceItemData *itemData = pCommerceUtil->GetItemData( m_ProductIndexArray[ requestedSlotIndex ] );
|
||
|
PopulateItemSlotWithData((m_LastStartIndex + iSlots) % m_ProductIndexArray.GetCount(), itemData, false);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_LastColumnIndex == CAT_COLUMN_INDEX)
|
||
|
{
|
||
|
if ( m_LastItemIndex == INVALID_ITEM_INDEX || m_LastItemIndex >= m_CategoryIndexArray.GetCount() || m_CategoryIndexArray.GetCount() == 1 )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_CurrentlySelectedCategory = m_LastItemIndex;
|
||
|
|
||
|
if ( m_LastSelectionTransition != ITEM_TO_CAT )
|
||
|
{
|
||
|
ClearLoadedImages();
|
||
|
|
||
|
m_PendingListSetup = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::DisplayItemDetails( const cCommerceProductData* pProductData )
|
||
|
{
|
||
|
rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
storeUIAssert( pProductData != NULL );
|
||
|
if ( pProductData == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT_EMPTY"))
|
||
|
{
|
||
|
//Plus one because this function seems to count the columns up from one. Charming.
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "ADD_COLUMN"))
|
||
|
{
|
||
|
//Plus one because this function seems to count the columns up from one. Charming.
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamString("DetailsList");
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_COLUMN_TITLE"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(2);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_DETAILS"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
char cashAmountString[CONSUMABLE_AMOUNT_STR_LEN];
|
||
|
cashAmountString[0] = 0;
|
||
|
|
||
|
if ( pProductData->IsConsumable() && MoneyInterface::GetCashPackValue(pProductData->GetConsumableId() ) != -1 )
|
||
|
{
|
||
|
CTextConversion::FormatIntForHumans(MoneyInterface::GetCashPackValue(pProductData->GetConsumableId()), cashAmountString, CONSUMABLE_AMOUNT_STR_LEN, "%s");
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
atString tempString = pProductData->GetName();
|
||
|
|
||
|
if ( pProductData->IsConsumable() && MoneyInterface::GetCashPackValue(pProductData->GetConsumableId() ) != -1 )
|
||
|
{
|
||
|
tempString.Replace(CONSUMABLE_AMOUNT_SUB_TAG, cashAmountString);
|
||
|
}
|
||
|
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamString(tempString.c_str());
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( pCommerceUtil->GetItemLongDescription(pProductData) != NULL )
|
||
|
{
|
||
|
atString longDescString(pCommerceUtil->GetItemLongDescription(pProductData));
|
||
|
|
||
|
if ( pProductData->IsConsumable() && MoneyInterface::GetCashPackValue(pProductData->GetConsumableId() ) != -1 )
|
||
|
{
|
||
|
longDescString.Replace(CONSUMABLE_AMOUNT_SUB_TAG, cashAmountString);
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(1);
|
||
|
CScaleformMgr::AddParamString(longDescString);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
//We have our long description.
|
||
|
m_PendingLongDescriptionItem = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_PendingLongDescriptionItem = pProductData;
|
||
|
}
|
||
|
|
||
|
if ( pProductData->GetEnumeratedFlag() )
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DESCRIPTION"))
|
||
|
{
|
||
|
const int TEMP_PRICE_STRING_LEN = 128;
|
||
|
char tempPriceString[TEMP_PRICE_STRING_LEN];
|
||
|
atString priceString;
|
||
|
if ( pCommerceUtil->GetProductPrice(pProductData,tempPriceString,TEMP_PRICE_STRING_LEN) != 0.0f)
|
||
|
{
|
||
|
priceString = tempPriceString;
|
||
|
priceString += PRICE_STRING_SUFFIX;
|
||
|
}
|
||
|
|
||
|
//char* string = TheText.Get("MKT_AIM_SPD");
|
||
|
|
||
|
char* statusString = NULL;
|
||
|
bool showPrice = true;
|
||
|
|
||
|
if ( pCommerceUtil->IsProductInstalled( pProductData ) )
|
||
|
{
|
||
|
statusString = TheText.Get("CMRC_INSTALLED");
|
||
|
showPrice = false;
|
||
|
}
|
||
|
else if ( pCommerceUtil->IsProductPurchased( pProductData ) && !pProductData->IsConsumable() )
|
||
|
{
|
||
|
statusString = TheText.Get("CMRC_PRCHSD");
|
||
|
showPrice = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
statusString = TheText.Get("CMRC_AVAIL");
|
||
|
}
|
||
|
|
||
|
if ( pProductData->IsConsumable() )
|
||
|
{
|
||
|
showPrice = true;
|
||
|
}
|
||
|
|
||
|
//Check if we have the data for how many of our friends own this product
|
||
|
const int *pNumFriendsWhoOwnProduct = m_NumFriendsWhoOwnProductMap.Access(pProductData->GetId() );
|
||
|
|
||
|
if ( pNumFriendsWhoOwnProduct == NULL )
|
||
|
{
|
||
|
//We dont have the data for this product. Set it as our next request.
|
||
|
mp_PendingNumFriendsWhoOwnProduct = pProductData;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Clear a pending request.
|
||
|
mp_PendingNumFriendsWhoOwnProduct = NULL;
|
||
|
}
|
||
|
|
||
|
if (showPrice)
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(2);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_PRICE"));
|
||
|
|
||
|
if ( priceString.GetLength() == 0 )
|
||
|
{
|
||
|
CScaleformMgr::AddParamString(TheText.Get("STORE_FREE_PRICE"));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CScaleformMgr::AddParamString(priceString.c_str());
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(2);
|
||
|
priceString.Clear();
|
||
|
CScaleformMgr::AddParamString(priceString.c_str());
|
||
|
CScaleformMgr::AddParamString(priceString.c_str());
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( pNumFriendsWhoOwnProduct )
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(*pNumFriendsWhoOwnProduct);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
}
|
||
|
|
||
|
CScaleformMgr::AddParamString(statusString);
|
||
|
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamBool(true);
|
||
|
CScaleformMgr::AddParamBool(pNumFriendsWhoOwnProduct != NULL);
|
||
|
CScaleformMgr::AddParamBool(true);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DESCRIPTION"))
|
||
|
{
|
||
|
//char* string = TheText.Get("MKT_AIM_SPD");
|
||
|
CScaleformMgr::AddParamInt(2);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_PRICE"));
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_AVAIL"));
|
||
|
CScaleformMgr::AddParamInt(15);
|
||
|
CScaleformMgr::AddParamBool(false);
|
||
|
CScaleformMgr::AddParamBool(false);
|
||
|
CScaleformMgr::AddParamBool(false);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Setup the status colour
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_STATUS_COLOURS"))
|
||
|
{
|
||
|
#if __XENON
|
||
|
CRGBA bgColour = CHudColour::GetRGBA(HUD_COLOUR_PLATFORM_GREEN);
|
||
|
CRGBA fgColour = CHudColour::GetRGBA(HUD_COLOUR_BLACK);
|
||
|
#else
|
||
|
CRGBA bgColour = CHudColour::GetRGBA(HUD_COLOUR_PLATFORM_BLUE);
|
||
|
CRGBA fgColour = CHudColour::GetRGBA(HUD_COLOUR_WHITE);
|
||
|
#endif
|
||
|
CScaleformMgr::AddParamInt(bgColour.GetRed());
|
||
|
CScaleformMgr::AddParamInt(bgColour.GetGreen());
|
||
|
CScaleformMgr::AddParamInt(bgColour.GetBlue());
|
||
|
|
||
|
CScaleformMgr::AddParamInt(fgColour.GetRed());
|
||
|
CScaleformMgr::AddParamInt(fgColour.GetGreen());
|
||
|
CScaleformMgr::AddParamInt(fgColour.GetBlue());
|
||
|
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "DISPLAY_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::ClearItemDetails( )
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "REMOVE_COLUMN"))
|
||
|
{
|
||
|
//Plus one because this function seems to count the columns up from one. Charming.
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "ADD_COLUMN"))
|
||
|
{
|
||
|
//Plus one because this function seems to count the columns up from one. Charming.
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamString("DetailsList");
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_COLUMN_TITLE"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(2);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_DETAILS"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(1);
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DESCRIPTION"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(2);
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
CScaleformMgr::AddParamInt(15);
|
||
|
CScaleformMgr::AddParamBool(false);
|
||
|
CScaleformMgr::AddParamBool(false);
|
||
|
CScaleformMgr::AddParamBool(false);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "DISPLAY_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(DETAIL_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateContextHelp()
|
||
|
{
|
||
|
//Because of the various paths into the store, we do not always own the instructional button movie.
|
||
|
int buttonMovieId = m_ButtonMovieId;
|
||
|
|
||
|
if ( buttonMovieId == INVALID_MOVIE_ID )
|
||
|
{
|
||
|
buttonMovieId = CScaleformMgr::FindMovieByFilename(BUTTONMENU_FILENAME);
|
||
|
}
|
||
|
|
||
|
//We couldn't get the movie ID from either source. Leave.
|
||
|
if ( buttonMovieId == INVALID_MOVIE_ID )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( buttonMovieId >= 0 )
|
||
|
{
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT_EMPTY"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_CLEAR_SPACE"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(200);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( m_InNoProductsMode || cStoreScreenMgr::GetCheckoutInitialItem())
|
||
|
{
|
||
|
//We don't want any additional buttons in this case.
|
||
|
}
|
||
|
else if ( m_LastColumnIndex == CAT_COLUMN_INDEX )
|
||
|
{
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(30);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_SELECT"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
else if ( m_LastCenterItemIndex != INVALID_ITEM_INDEX && m_LastCenterItemIndex < m_ProductIndexArray.GetCount() )
|
||
|
{
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssertf( pCommerceUtil, "Commerce utility was not initialised or present" );
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const cCommerceItemData* pItemData = pCommerceUtil->GetItemData(m_ProductIndexArray[ m_LastCenterItemIndex ]);
|
||
|
|
||
|
if ( pItemData != NULL && pItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT )
|
||
|
{
|
||
|
const cCommerceProductData *pProductData = static_cast<const cCommerceProductData*>(pItemData);
|
||
|
|
||
|
if ( pCommerceUtil->IsProductInstalled( pProductData ) )
|
||
|
{
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(30);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_DLOAD"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
else if ( pCommerceUtil->IsProductPurchased( pProductData ) && !pProductData->IsConsumable() )
|
||
|
{
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(30);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_DLOAD"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
else if ( pCommerceUtil->IsProductPurchasable( pProductData ) )
|
||
|
{
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(30);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_PURCHASE"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(1);
|
||
|
CScaleformMgr::AddParamInt(31);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_BACK"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
// Don't show the "Redeem Code"-button during a quick checkout
|
||
|
if ( !cStoreScreenMgr::GetCheckoutInitialItem()
|
||
|
&& CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT") )
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(2);
|
||
|
CScaleformMgr::AddParamInt(33);
|
||
|
CScaleformMgr::AddParamString(TheText.Get("CMRC_CODE"));
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "DRAW_INSTRUCTIONAL_BUTTONS"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_BACKGROUND_COLOUR"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(0);
|
||
|
CScaleformMgr::AddParamInt(80);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::PopulateImageRequests()
|
||
|
{
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int numRequiredImages = Min( MAX_NUM_ITEMS_IN_MIDDLE_COLUMN, m_ProductIndexArray.GetCount() );
|
||
|
|
||
|
//create an array of our currently required images
|
||
|
atArray<int> requiredImageArray;
|
||
|
|
||
|
for ( int iRequiredImageIt = 0; iRequiredImageIt < numRequiredImages; iRequiredImageIt++ )
|
||
|
{
|
||
|
int requiredImageIndex = (m_LastStartIndex + iRequiredImageIt ) % m_ProductIndexArray.GetCount();
|
||
|
requiredImageArray.PushAndGrow(requiredImageIndex);
|
||
|
}
|
||
|
|
||
|
//Check for unloads first.
|
||
|
bool deletionOccured = false;
|
||
|
do
|
||
|
{
|
||
|
deletionOccured = false;
|
||
|
for (s32 iLoadedImageIndices = 0; iLoadedImageIndices < m_LoadedImageIndices.GetCount(); iLoadedImageIndices++)
|
||
|
{
|
||
|
if ( requiredImageArray.Find(m_LoadedImageIndices[ iLoadedImageIndices ]) == -1 )
|
||
|
{
|
||
|
//We are outside the currently requested range, unload
|
||
|
const cCommerceItemData *itemData = pCommerceUtil->GetItemData(m_ProductIndexArray[ m_LoadedImageIndices[ iLoadedImageIndices ] ] );
|
||
|
|
||
|
if ( itemData && itemData->GetImagePaths().GetCount() > 0 )
|
||
|
{
|
||
|
const atString path(itemData->GetImagePaths()[0]);
|
||
|
//DO NOT CHECK IN!
|
||
|
cStoreScreenMgr::GetTextureManager()->ReleaseTexture( path );
|
||
|
PopulateItemSlotWithData(m_LoadedImageIndices[ iLoadedImageIndices ], itemData, false);
|
||
|
}
|
||
|
|
||
|
deletionOccured = true;
|
||
|
m_LoadedImageIndices.Delete( iLoadedImageIndices );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} while (deletionOccured);
|
||
|
|
||
|
|
||
|
//Now do the same check on the requested image array
|
||
|
do
|
||
|
{
|
||
|
deletionOccured = false;
|
||
|
for (s32 iRequestedImageIndices = 0; iRequestedImageIndices < m_RequestedImageIndices.GetCount(); iRequestedImageIndices++)
|
||
|
{
|
||
|
if ( requiredImageArray.Find(m_RequestedImageIndices[ iRequestedImageIndices ]) == -1 )
|
||
|
{
|
||
|
//We are outside the currently requested range, remove from requests
|
||
|
m_RequestedImageIndices.Delete( iRequestedImageIndices );
|
||
|
deletionOccured = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} while (deletionOccured);
|
||
|
|
||
|
for (int s = 0; s < requiredImageArray.GetCount() ; s++ )
|
||
|
{
|
||
|
|
||
|
bool found = false;
|
||
|
//Check if the image is already in our downloaded list
|
||
|
if ( m_LoadedImageIndices.Find(requiredImageArray[s]) != -1 )
|
||
|
{
|
||
|
found = true;
|
||
|
}
|
||
|
|
||
|
//Check if the image is already in our requested list
|
||
|
if ( m_RequestedImageIndices.Find(requiredImageArray[s]) != -1 )
|
||
|
{
|
||
|
found = true;
|
||
|
}
|
||
|
|
||
|
if (!found)
|
||
|
{
|
||
|
if ( m_RequestedImageIndices.GetCount() < m_RequestedImageIndices.GetCapacity() )
|
||
|
{
|
||
|
//See if the product has an image to request.
|
||
|
storeUIAssert( requiredImageArray[s] >= 0 && requiredImageArray[s] < m_ProductIndexArray.GetCount() );
|
||
|
const cCommerceItemData *itemData = pCommerceUtil->GetItemData( m_ProductIndexArray[ requiredImageArray[s] ] );
|
||
|
if ( itemData && itemData->GetImagePaths().GetCount() > 0 )
|
||
|
{
|
||
|
m_RequestedImageIndices.PushAndGrow(requiredImageArray[s]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (s32 i = 0; i < m_RequestedImageIndices.GetCount(); i++)
|
||
|
{
|
||
|
storeUIDebugf3("m_RequestedImageIndices[%d]: %d",i,m_RequestedImageIndices[i]);
|
||
|
}
|
||
|
storeUIDebugf3("Trying to add index %d",requiredImageArray[s]);
|
||
|
storeUIAssertf(false,"Too many requests to download images in main store screen");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateImageRequests()
|
||
|
{
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (int iRequestedImageIter = 0; iRequestedImageIter < m_RequestedImageIndices.GetCount(); iRequestedImageIter++)
|
||
|
{
|
||
|
int requestedImageIndex = m_RequestedImageIndices[iRequestedImageIter];
|
||
|
storeUIAssert( requestedImageIndex >= 0 && requestedImageIndex < m_ProductIndexArray.GetCount() );
|
||
|
const cCommerceItemData *itemData = pCommerceUtil->GetItemData( m_ProductIndexArray[ requestedImageIndex ] );
|
||
|
|
||
|
if ( itemData
|
||
|
&& itemData->GetImagePaths().GetCount() > 0
|
||
|
&& (m_LoadedImageIndices.Find( requestedImageIndex ) == -1)
|
||
|
&& cStoreScreenMgr::GetTextureManager()->RequestTexture( itemData->GetImagePaths()[0] ) )
|
||
|
{
|
||
|
storeUIDebugf3("Requested texture %s is now available from DL Tex man. This is slot %d", itemData->GetImagePaths()[0].c_str(), requestedImageIndex );
|
||
|
//We have our texture. Populate the slot.
|
||
|
PopulateItemSlotWithData( requestedImageIndex , itemData );
|
||
|
m_LoadedImageIndices.PushAndGrow(requestedImageIndex);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Pass to remove downloaded textures
|
||
|
for ( int iLoadedImageIter = 0; iLoadedImageIter < m_LoadedImageIndices.GetCount(); iLoadedImageIter++ )
|
||
|
{
|
||
|
int loadedImageIndex = m_LoadedImageIndices[ iLoadedImageIter ];
|
||
|
for (int iRequestedImageIter = 0; iRequestedImageIter < m_RequestedImageIndices.GetCount(); iRequestedImageIter++)
|
||
|
{
|
||
|
int requestedImageIndex = m_RequestedImageIndices[iRequestedImageIter];
|
||
|
if ( loadedImageIndex == requestedImageIndex )
|
||
|
{
|
||
|
storeUIDebugf3("Removing slot %d from the requested images array", requestedImageIndex );
|
||
|
//We have downloaded this slots image. Remove from the request list
|
||
|
m_RequestedImageIndices.Delete( iRequestedImageIter );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::PopulateItemSlotWithData( int a_Slot, const cCommerceItemData* a_ItemData, bool showImage )
|
||
|
{
|
||
|
storeUIAssert(a_ItemData);
|
||
|
if ( a_ItemData == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::AddParamInt(a_Slot);
|
||
|
|
||
|
if ( a_ItemData->GetImagePaths().GetCount() > 0 && showImage )
|
||
|
{
|
||
|
atString cloudStrippedPath = a_ItemData->GetImagePaths()[0];
|
||
|
cStoreTextureManager::ConvertPathToTextureName(cloudStrippedPath);
|
||
|
|
||
|
CScaleformMgr::AddParamString( cloudStrippedPath );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
}
|
||
|
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "DISPLAY_DATA_SLOT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(ITEM_COLUMN_INDEX);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::ClearLoadedImages()
|
||
|
{
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssert( pCommerceUtil );
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (s32 iLoadedImageIndices = 0; iLoadedImageIndices < m_LoadedImageIndices.GetCount(); iLoadedImageIndices++)
|
||
|
{
|
||
|
//We are outside the currently requested range, unload
|
||
|
const cCommerceItemData *itemData = pCommerceUtil->GetItemData(m_LoadedImageIndices[iLoadedImageIndices] );
|
||
|
|
||
|
if ( itemData && itemData->GetImagePaths().GetCount() > 0 )
|
||
|
{
|
||
|
const atString path(itemData->GetImagePaths()[0]);
|
||
|
cStoreScreenMgr::GetTextureManager()->ReleaseTexture( path );
|
||
|
}
|
||
|
}
|
||
|
m_LoadedImageIndices.Reset();
|
||
|
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::ClearImageRequests()
|
||
|
{
|
||
|
storeUIAssert( cStoreScreenMgr::GetTextureManager() );
|
||
|
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
if ( cStoreScreenMgr::GetTextureManager() == NULL || pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for ( int i = 0; i < m_RequestedImageIndices.GetCount(); i++ )
|
||
|
{
|
||
|
const cCommerceItemData *itemData = pCommerceUtil->GetItemData(m_ProductIndexArray[i]);
|
||
|
|
||
|
if ( itemData && itemData->GetImagePaths().GetCount() > 0 )
|
||
|
{
|
||
|
const atString path(itemData->GetImagePaths()[0]);
|
||
|
cStoreScreenMgr::GetTextureManager()->CancelRequest( path );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_RequestedImageIndices.Reset();
|
||
|
m_RequestedImageIndices.Reserve( MAX_REQUESTED_IMAGES );
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::TriggerHighlightChange()
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "GET_CURRENT_COLUMN"))
|
||
|
{
|
||
|
m_ColumnReturnId = CScaleformMgr::EndMethodReturnValue(m_ColumnReturnId);
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "GET_CURRENT_SELECTION"))
|
||
|
{
|
||
|
m_ItemReturnId = CScaleformMgr::EndMethodReturnValue(m_ItemReturnId);
|
||
|
}
|
||
|
|
||
|
m_PendingHighlightChange = true;
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdatePendingInitialData()
|
||
|
{
|
||
|
if ( CLiveManager::GetCommerceMgr().HasValidData() )
|
||
|
{
|
||
|
m_CurrentState = STATE_INITIALISING;
|
||
|
}
|
||
|
|
||
|
//Error checking should go here for failed commerce data
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::RequestScaleformMovies()
|
||
|
{
|
||
|
int buttonMovieId = CScaleformMgr::FindMovieByFilename(BUTTONMENU_FILENAME);
|
||
|
if ( buttonMovieId == -1 )
|
||
|
{
|
||
|
m_ButtonMovieId = CScaleformMgr::CreateMovie(BUTTONMENU_FILENAME, Vector2(0,0), Vector2(1.0f, 1.0f));
|
||
|
CBusySpinner::RegisterInstructionalButtonMovie(m_ButtonMovieId); // register this "instructional button" movie with the spinner system
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//The instructional movie is already loaded. Take this opportunity to empty it
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT_EMPTY"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if ( CScaleformMgr::BeginMethod(buttonMovieId, SF_BASE_CLASS_GENERIC, "CLEAR_ALL"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
m_StoreBgMovieId = CScaleformMgr::CreateMovie(BACKGROUNDMOVIE_FILENAME, Vector2(0,0), Vector2(1.0f, 1.0f));
|
||
|
|
||
|
|
||
|
m_BlackFadeMovieId = CScaleformMgr::CreateMovie(BLACKFADE_FILENAME, Vector2(0.0f, 0.0f), Vector2(1.0f, 1.0f));
|
||
|
|
||
|
Vector2 pos(cStoreScreenMgr::GetMovieXPos(), cStoreScreenMgr::GetMovieYPos());
|
||
|
Vector2 size(cStoreScreenMgr::GetMovieWidth(), cStoreScreenMgr::GetMovieHeight());
|
||
|
|
||
|
m_StoreMovieId = CScaleformMgr::CreateMovie(STOREMENU_FILENAME, pos, size); // this movie has seperate values for 4:3 and 16:9 as it wont fit inside safezone of 4:3
|
||
|
|
||
|
m_CurrentState = STATE_LOADING_ASSETS;
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateLoadingAssets()
|
||
|
{
|
||
|
if (AreAllAssetsActive())
|
||
|
{
|
||
|
//DISPLAY THE "LOADING DATA" dialog here
|
||
|
m_CurrentState = STATE_PENDING_INITIAL_DATA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::SetBgScrollSpeed( int speed )
|
||
|
{
|
||
|
if ( m_StoreMovieId != INVALID_MOVIE_ID )
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "ANIMATE_BACKGROUND"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(speed);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::OnMembershipGained()
|
||
|
{
|
||
|
storeUIDebugf1("OnMembershipGained :: Flagging List Refresh");
|
||
|
m_PendingListSetup = true;
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::AddProductsPriceToCashSpentStat( const cCommerceProductData* pProductData )
|
||
|
{
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
if (pCommerceUtil == NULL)
|
||
|
{
|
||
|
commerceAssertf(false, "AddProductsPriceToCashSpentStat :: Commerce util does not exist");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
char priceBuffer[SIZE_OF_PRICE_BUFFER];
|
||
|
float priceOfRequestedProduct = pCommerceUtil->GetProductPrice(pProductData,priceBuffer,SIZE_OF_PRICE_BUFFER);
|
||
|
StatsInterface::IncrementStat(STAT_MPPLY_STORE_MONEY_SPENT, priceOfRequestedProduct);
|
||
|
|
||
|
//THIS IS A VERY BAD NETWORK HEAVY FUNCTION! DO NOT CALL A LOT!!!!!
|
||
|
StatsInterface::TryMultiplayerSave( STAT_SAVETYPE_STORE );
|
||
|
}
|
||
|
|
||
|
bool cStoreMainScreen::UpdateWarningScreen()
|
||
|
{
|
||
|
if (m_WasInCheckout)
|
||
|
{
|
||
|
//Don't want to pull the rug out from under container functions.
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (cStoreScreenMgr::IsExitRequested())
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (sm_bPlayerHasJustSignedOut)
|
||
|
{
|
||
|
//We just leave for this now
|
||
|
if (m_StoreMovieId != INVALID_MOVIE_ID && CScaleformMgr::IsMovieActive(m_StoreMovieId) && CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
if (m_CurrentDCWarningScreen != STORE_WARNING_NONE)
|
||
|
CWarningScreen::Remove();
|
||
|
|
||
|
storeUIDebugf1("UpdateWarningScreen :: Requesting exit after sign out");
|
||
|
|
||
|
m_CurrentDCWarningScreen = STORE_WARNING_NONE;
|
||
|
cStoreScreenMgr::RequestExit();
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//Sign out messages don't come through immediately, so we need to delay the offline check briefly.
|
||
|
if (!CLiveManager::IsOnline() || !CLiveManager::IsOnlineRos() )
|
||
|
{
|
||
|
m_FramesOffline++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_FramesOffline = 0;
|
||
|
}
|
||
|
|
||
|
const rlGamerInfo* pGamerInfo = NetworkInterface::GetActiveGamerInfo();
|
||
|
if ( (m_FramesOffline > OFFLINE_FRAMES_TO_WAIT_FOR_SIGNOUT_MESSAGE)
|
||
|
|| CLiveManager::GetCommerceMgr().GetCommerceUtil()->IsInErrorState()
|
||
|
|| (pGamerInfo && pGamerInfo->IsOnline() && !rlGamerInfo::HasStorePrivileges(pGamerInfo->GetLocalIndex()))
|
||
|
|| m_CurrentDCWarningScreen != STORE_WARNING_NONE )
|
||
|
{
|
||
|
CBusySpinner::Off( SPINNER_SOURCE_STORE_LOADING );
|
||
|
|
||
|
if ( STORE_WARNING_NONE == m_CurrentDCWarningScreen )
|
||
|
{
|
||
|
//Since this is the first display, take this opportunity to show debug output identifying the cause.
|
||
|
storeUIDisplayf("Displaying store DC message. Cause: CLiveManager::IsOnlineRos() [%d] CLiveManager::IsOnline() [%d], CLiveManager::GetCommerceMgr().GetCommerceUtil()->IsInErrorState() [%d], rlGamerInfo::HasStorePrivileges(pGamerInfo->GetLocalIndex() [%d]",
|
||
|
CLiveManager::IsOnlineRos(), CLiveManager::IsOnline(), CLiveManager::GetCommerceMgr().GetCommerceUtil()->IsInErrorState(), rlGamerInfo::HasStorePrivileges(pGamerInfo->GetLocalIndex()) );
|
||
|
|
||
|
if ( CLiveManager::IsOnline() && pGamerInfo && !rlGamerInfo::HasStorePrivileges(pGamerInfo->GetLocalIndex()) )
|
||
|
{
|
||
|
m_CurrentDCWarningScreen = STORE_WARNING_AGE;
|
||
|
}
|
||
|
else if (!CLiveManager::IsOnline() && m_WasSignedOnlineOnEnter)
|
||
|
{
|
||
|
m_CurrentDCWarningScreen = STORE_WARNING_PLATFORM_LOST;
|
||
|
}
|
||
|
else if (!CLiveManager::IsOnline())
|
||
|
{
|
||
|
m_CurrentDCWarningScreen = STORE_WARNING_PLATFORM_OFFLINE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_CurrentDCWarningScreen = STORE_WARNING_ROS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
atHashWithStringBank message;
|
||
|
switch(m_CurrentDCWarningScreen)
|
||
|
{
|
||
|
case(STORE_WARNING_PLATFORM_OFFLINE):
|
||
|
message = "STORE_PLAT_OFFLINE";
|
||
|
break;
|
||
|
case(STORE_WARNING_PLATFORM_LOST):
|
||
|
message = "STORE_PLAT_LOS";
|
||
|
break;
|
||
|
case(STORE_WARNING_ROS):
|
||
|
message = "STORE_UNAVAIL_ROS";
|
||
|
break;
|
||
|
case(STORE_WARNING_AGE):
|
||
|
message = "HUD_AGERES";
|
||
|
break;
|
||
|
default:
|
||
|
message = "STORE_UNAVAIL";
|
||
|
}
|
||
|
|
||
|
CWarningScreen::SetMessage( WARNING_MESSAGE_STANDARD, message, FE_WARNING_OK);
|
||
|
|
||
|
if(CWarningScreen::CheckAllInput() == FE_WARNING_OK)
|
||
|
{
|
||
|
if (m_StoreMovieId != INVALID_MOVIE_ID && CScaleformMgr::IsMovieActive(m_StoreMovieId) && CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
storeUIDebugf1("UpdateWarningScreen :: Requesting exit after error");
|
||
|
|
||
|
m_CurrentDCWarningScreen = STORE_WARNING_NONE;
|
||
|
cStoreScreenMgr::RequestExit();
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// if we've received an invite, that's not confirmed and we are not suppressed by script
|
||
|
// static bool simulateInvite = false;
|
||
|
if ( ( CLiveManager::GetInviteMgr().HasPendingAcceptedInvite() && !CLiveManager::GetInviteMgr().HasConfirmedOrIsAutoConfirm() && !CLiveManager::GetInviteMgr().IsSuppressed())/* || simulateInvite */)
|
||
|
{
|
||
|
if (CBusySpinner::IsOn())
|
||
|
{
|
||
|
CBusySpinner::Off( SPINNER_SOURCE_STORE_LOADING );
|
||
|
}
|
||
|
|
||
|
CWarningScreen::SetMessage( WARNING_MESSAGE_STANDARD, CLiveManager::GetInviteMgr().GetConfirmText(), FE_WARNING_OK_CANCEL, false, -1, CLiveManager::GetInviteMgr().GetConfirmSubstring());
|
||
|
eWarningButtonFlags result = CWarningScreen::CheckAllInput();
|
||
|
|
||
|
if (result == FE_WARNING_OK)
|
||
|
{
|
||
|
if (m_StoreMovieId != INVALID_MOVIE_ID && CScaleformMgr::IsMovieActive(m_StoreMovieId) && CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
storeUIDebugf1("UpdateWarningScreen :: Requesting exit after invite");
|
||
|
|
||
|
cStoreScreenMgr::RequestExit();
|
||
|
|
||
|
//Since we have accepted an invite, we don't want to leave via the pause menu
|
||
|
cStoreScreenMgr::SetReturnToPauseMenu(false);
|
||
|
|
||
|
//Confirm invite
|
||
|
CLiveManager::GetInviteMgr().AutoConfirmInvite();
|
||
|
// simulateInvite = false;
|
||
|
}
|
||
|
else if (result == FE_WARNING_CANCEL)
|
||
|
{
|
||
|
CLiveManager::GetInviteMgr().CancelInvite();
|
||
|
// simulateInvite = false;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool cStoreMainScreen::UpdateNonCriticalWarningScreen()
|
||
|
{
|
||
|
if (cStoreScreenMgr::IsExitRequested())
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ( m_CurrentDCWarningScreen != STORE_WARNING_NONE )
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//Structured like this so that we can easily add new messages later.
|
||
|
if ( m_CurrentNonCriticalWarningScreen == STORE_NON_CRIT_WARNING_NONE )
|
||
|
{
|
||
|
switch(m_PendingNonCriticalWarningScreen)
|
||
|
{
|
||
|
case STORE_NON_CRIT_WARNING_NONE:
|
||
|
break;
|
||
|
|
||
|
case STORE_CANNOT_PURCHASE_CASH:
|
||
|
storeUIDisplayf("Setting m_CurrentNonCriticalWarningScreen to STORE_CANNOT_PURCHASE_CASH");
|
||
|
m_CurrentNonCriticalWarningScreen = STORE_CANNOT_PURCHASE_CASH;
|
||
|
m_PendingNonCriticalWarningScreen = STORE_NON_CRIT_WARNING_NONE;
|
||
|
break;
|
||
|
|
||
|
case STORE_SUBSCRIPTION_UPSELL:
|
||
|
storeUIDisplayf("Setting m_CurrentNonCriticalWarningScreen to STORE_SUBSCRIPTION_UPSELL");
|
||
|
m_CurrentNonCriticalWarningScreen = STORE_SUBSCRIPTION_UPSELL;
|
||
|
m_PendingNonCriticalWarningScreen = STORE_NON_CRIT_WARNING_NONE;
|
||
|
break;
|
||
|
|
||
|
case STORE_SUBSCRIPTION_WELCOME:
|
||
|
storeUIDisplayf("Setting m_CurrentNonCriticalWarningScreen to STORE_SUBSCRIPTION_WELCOME");
|
||
|
m_CurrentNonCriticalWarningScreen = STORE_SUBSCRIPTION_WELCOME;
|
||
|
m_PendingNonCriticalWarningScreen = STORE_NON_CRIT_WARNING_NONE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( m_CurrentNonCriticalWarningScreen != STORE_NON_CRIT_WARNING_NONE )
|
||
|
{
|
||
|
atHashWithStringBank header;
|
||
|
atHashWithStringBank message;
|
||
|
eWarningButtonFlags buttons = FE_WARNING_OK;
|
||
|
switch( m_CurrentNonCriticalWarningScreen )
|
||
|
{
|
||
|
case(STORE_CANNOT_PURCHASE_CASH):
|
||
|
header = 0u;
|
||
|
message = "STORE_CASH_PRODS_DISABLED";
|
||
|
break;
|
||
|
case(STORE_SUBSCRIPTION_UPSELL):
|
||
|
header = "STORE_PS_SUBSCRIBE";
|
||
|
message = "STORE_PS_UPSELL";
|
||
|
buttons = FE_WARNING_YES_NO;
|
||
|
break;
|
||
|
case(STORE_SUBSCRIPTION_WELCOME):
|
||
|
header = "ALERT_MEMBER_CONGRATS";
|
||
|
message = "ALERT_MEMBER_CONGRATS_MESSAGE";
|
||
|
break;
|
||
|
default:
|
||
|
storeUIAssertf(false,"Non implemented non critical message.");
|
||
|
}
|
||
|
|
||
|
CWarningScreen::SetMessageWithHeader( WARNING_MESSAGE_STANDARD, header, message, buttons);
|
||
|
|
||
|
const eWarningButtonFlags buttonPressed = CWarningScreen::CheckAllInput();
|
||
|
if(buttonPressed == FE_WARNING_OK || buttonPressed == FE_WARNING_YES)
|
||
|
{
|
||
|
switch (m_CurrentNonCriticalWarningScreen)
|
||
|
{
|
||
|
case(STORE_CANNOT_PURCHASE_CASH):
|
||
|
break;
|
||
|
case(STORE_SUBSCRIPTION_UPSELL):
|
||
|
if(storeUIVerifyf(!m_SubscriptionUpsellItemId.empty(), "Invalid Upsell Item!"))
|
||
|
{
|
||
|
cCommerceUtil* pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
const cCommerceItemData* pUpsellItem = pCommerceUtil->GetItemDataByItemId(m_SubscriptionUpsellItemId.c_str());
|
||
|
|
||
|
if(pUpsellItem && pUpsellItem->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT)
|
||
|
{
|
||
|
const cCommerceProductData* pUpsellProduct = static_cast<const cCommerceProductData*>(pUpsellItem);
|
||
|
|
||
|
// get upsells
|
||
|
const atArray<atString>& subscriptionUpsells = pUpsellProduct->GetSubscriptionUpsells();
|
||
|
const unsigned numUpsells = subscriptionUpsells.GetCount();
|
||
|
|
||
|
// need to find our subscription product
|
||
|
const unsigned numItems = pCommerceUtil->GetNumItems();
|
||
|
|
||
|
for(unsigned i = 0; i < numItems; i++)
|
||
|
{
|
||
|
const cCommerceItemData* pItemData = pCommerceUtil->GetItemData(i);
|
||
|
if(pItemData == nullptr)
|
||
|
continue;
|
||
|
|
||
|
if(pItemData->GetItemType() != cCommerceItemData::ITEM_TYPE_PRODUCT)
|
||
|
continue;
|
||
|
|
||
|
const cCommerceProductData* pOtherProductData = static_cast<const cCommerceProductData*>(pItemData);
|
||
|
if(!pOtherProductData->IsConsumable())
|
||
|
continue;
|
||
|
|
||
|
// check for our upsell in the list
|
||
|
for(int d = 0; d < numUpsells; d++)
|
||
|
{
|
||
|
if(subscriptionUpsells[d] == pOtherProductData->GetConsumableId())
|
||
|
{
|
||
|
// found our subscription upsell
|
||
|
storeUIDebugf1("ProcessCheckoutSelected :: SelectedProduct: %s, UpsellProduct: %s, SubscriptionId: %s",
|
||
|
pUpsellProduct->GetName().c_str(),
|
||
|
pOtherProductData->GetName().c_str(),
|
||
|
subscriptionUpsells[d].c_str());
|
||
|
|
||
|
// this starts a fade before the checkout begins
|
||
|
StartCheckout(pOtherProductData);
|
||
|
|
||
|
// suppress membership updates for script from here
|
||
|
MEMBERSHIP_ONLY(CLiveManager::SetSuppressMembershipForScript(true));
|
||
|
|
||
|
// found our product, bail
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case(STORE_SUBSCRIPTION_WELCOME):
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
m_CurrentNonCriticalWarningScreen = STORE_NON_CRIT_WARNING_NONE;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateLeaderBoardDataFetch()
|
||
|
{
|
||
|
//Do we have a fetch in progress? Is it done?
|
||
|
if ( mp_CurrentLeaderboardRead && mp_CurrentLeaderboardRead->Finished())
|
||
|
{
|
||
|
if ( mp_CurrentLeaderboardRead->Suceeded() )
|
||
|
{
|
||
|
//Get the total.
|
||
|
int friendsOwningThisProduct = 0;
|
||
|
for ( int s = 0; s < mp_CurrentLeaderboardRead->GetNumRows(); s++ )
|
||
|
{
|
||
|
if ( mp_CurrentLeaderboardRead->GetRow(s)->m_ColumnValues[0].Int64Val == 1 )
|
||
|
{
|
||
|
friendsOwningThisProduct++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int *existingTotal = m_NumFriendsWhoOwnProductMap.Access( m_CurrentLeaderboardDataFetchProductId );
|
||
|
|
||
|
if ( existingTotal )
|
||
|
{
|
||
|
*existingTotal = friendsOwningThisProduct;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_NumFriendsWhoOwnProductMap.Insert(m_CurrentLeaderboardDataFetchProductId,friendsOwningThisProduct);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Not sure what to do in this case.
|
||
|
}
|
||
|
|
||
|
//Clean up.
|
||
|
m_CurrentLeaderboardDataFetchProductId.Reset();
|
||
|
CNetwork::GetLeaderboardMgr().GetLeaderboardReadMgr().ClearLeaderboardRead(mp_CurrentLeaderboardRead);
|
||
|
mp_CurrentLeaderboardRead = NULL;
|
||
|
|
||
|
//Check if we have fulfilled the current request
|
||
|
if ( mp_PendingNumFriendsWhoOwnProduct )
|
||
|
{
|
||
|
const int *currentRequestFriendsOwned = m_NumFriendsWhoOwnProductMap.Access(mp_PendingNumFriendsWhoOwnProduct->GetId());
|
||
|
|
||
|
if ( currentRequestFriendsOwned )
|
||
|
{
|
||
|
DisplayItemDetails(mp_PendingNumFriendsWhoOwnProduct);
|
||
|
mp_PendingNumFriendsWhoOwnProduct = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//Are we not reading, and do we have an outstanding query?
|
||
|
if ( mp_CurrentLeaderboardRead == NULL && mp_PendingNumFriendsWhoOwnProduct != NULL && rlFriendsManager::GetTotalNumFriends(NetworkInterface::GetLocalGamerIndex()) > 0 )
|
||
|
{
|
||
|
const int COMMERCE_LEADERBOARD_ID = 927;
|
||
|
const Leaderboard* lbConf = GAME_CONFIG_PARSER.GetLeaderboard(COMMERCE_LEADERBOARD_ID);
|
||
|
if (lbConf == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//Build our group selector
|
||
|
rlLeaderboard2GroupSelector groupSelector;
|
||
|
groupSelector.m_NumGroups = 1;
|
||
|
strncpy(groupSelector.m_Group[0].m_Category,"ProductId",RL_LEADERBOARD2_CATEGORY_MAX_CHARS);
|
||
|
strncpy(groupSelector.m_Group[0].m_Id,mp_PendingNumFriendsWhoOwnProduct->GetId(),RL_LEADERBOARD2_GROUP_ID_MAX_CHARS);
|
||
|
|
||
|
//I am currently assuming these following two are empty params. Will consult.
|
||
|
rlLeaderboard2GroupSelector groupSelectors[MAX_LEADERBOARD_READ_GROUPS];
|
||
|
int numberOfGroups = 0;
|
||
|
|
||
|
const u32 LB_MAX_NUM_FRIENDS = 100;
|
||
|
|
||
|
CNetworkReadLeaderboards& readmgr = CNetwork::GetLeaderboardMgr().GetLeaderboardReadMgr();
|
||
|
|
||
|
//For testing
|
||
|
const bool includeMyself = false;
|
||
|
|
||
|
mp_CurrentLeaderboardRead = readmgr.ReadByFriends( COMMERCE_LEADERBOARD_ID, RL_LEADERBOARD2_TYPE_GROUP_MEMBER, groupSelector,
|
||
|
RL_INVALID_CLAN_ID, numberOfGroups, groupSelectors, includeMyself, 0, LB_MAX_NUM_FRIENDS);
|
||
|
|
||
|
if ( mp_CurrentLeaderboardRead == NULL )
|
||
|
{
|
||
|
mp_PendingNumFriendsWhoOwnProduct = NULL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//Fetch started correctly.
|
||
|
m_CurrentLeaderboardDataFetchProductId = mp_PendingNumFriendsWhoOwnProduct->GetId();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void cStoreMainScreen::OnPresenceEvent(const rlPresenceEvent* evt)
|
||
|
{
|
||
|
if (evt)
|
||
|
{
|
||
|
if (evt->GetId() == PRESENCE_EVENT_SIGNIN_STATUS_CHANGED)
|
||
|
{
|
||
|
const rlPresenceEventSigninStatusChanged* s = evt->m_SigninStatusChanged;
|
||
|
|
||
|
// check if this is a sign out event, only consider the currently active profile
|
||
|
if(s && ( s->SignedOut() || s->SignedOffline() ) && ( s->m_GamerInfo.GetLocalIndex() == CControlMgr::GetMainPlayerIndex() ) )
|
||
|
{
|
||
|
storeUIDisplayf("Main profile (%d) signed out", s->m_GamerInfo.GetLocalIndex());
|
||
|
sm_bPlayerHasJustSignedOut = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::DoEmptyStoreCheck()
|
||
|
{
|
||
|
const rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
storeUIAssert(pCommerceUtil);
|
||
|
|
||
|
if ( pCommerceUtil == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int numActiveProducts = 0;
|
||
|
//Loop through the categories
|
||
|
for ( int iCat = 0; iCat < m_CategoryIndexArray.GetCount(); iCat++ )
|
||
|
{
|
||
|
//GTA only supports one level of categories
|
||
|
const cCommerceItemData *pItemData = pCommerceUtil->GetItemData( m_CategoryIndexArray[iCat] );
|
||
|
if(pItemData && pItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_CATEGORY)
|
||
|
{
|
||
|
const cCommerceCategoryData *pCategoryData = static_cast<const cCommerceCategoryData*>(pItemData);
|
||
|
|
||
|
for (int iProds = 0; iProds < pCategoryData->GetNumProducts(); iProds++ )
|
||
|
{
|
||
|
int itemIndex = pCategoryData->GetItemIndex(iProds);
|
||
|
|
||
|
const cCommerceItemData *pCatItemToCheck = pCommerceUtil->GetItemData(itemIndex);
|
||
|
|
||
|
//Check if this is a product
|
||
|
if ( pCatItemToCheck->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT )
|
||
|
{
|
||
|
numActiveProducts++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
storeUIDebugf3("Found %d valid products", numActiveProducts);
|
||
|
|
||
|
if ( numActiveProducts == 0 )
|
||
|
{
|
||
|
m_InNoProductsMode = true;
|
||
|
DisplayNoProductsWarning();
|
||
|
UpdateContextHelp();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_InNoProductsMode = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::DisplayNoProductsWarning()
|
||
|
{
|
||
|
if ( m_StoreMovieId == SF_INVALID_MOVIE )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "DISPLAY_ERROR_MESSAGE"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamString("");
|
||
|
CScaleformMgr::AddParamString(TheText.Get("STORE_NO_CONTENT"));
|
||
|
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool cStoreMainScreen::DoQuickCheckout()
|
||
|
{
|
||
|
if (!cStoreScreenMgr::GetCheckoutInitialItem())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const rage::cCommerceItemData* pInitialItemData = nullptr;
|
||
|
rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
if (pCommerceUtil == nullptr || pCommerceUtil->IsInErrorState())
|
||
|
{
|
||
|
cStoreScreenMgr::SetCheckoutInitialItem(false);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const int num = pCommerceUtil->GetNumItems();
|
||
|
|
||
|
for (int i = 0; i < num; i++)
|
||
|
{
|
||
|
if (pCommerceUtil->GetItemData(i)->GetId() == cStoreScreenMgr::GetInitialItemID())
|
||
|
{
|
||
|
//we have found our initial product
|
||
|
pInitialItemData = pCommerceUtil->GetItemData(i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pInitialItemData != nullptr && pInitialItemData->GetItemType() == cCommerceItemData::ITEM_TYPE_PRODUCT)
|
||
|
{
|
||
|
const cCommerceProductData *pProductData = static_cast<const cCommerceProductData*>(pInitialItemData);
|
||
|
if (ProcessCheckoutSelected(pProductData))
|
||
|
{
|
||
|
storeUIDebugf1("DoQuickCheckout: ItemId: %s", cStoreScreenMgr::GetInitialItemID().c_str());
|
||
|
m_QuickCheckout = true;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
storeUIWarningf("DoQuickCheckout :: Skipped - %s not found", cStoreScreenMgr::GetInitialItemID().c_str());
|
||
|
cStoreScreenMgr::SetCheckoutInitialItem(false);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateCheckout()
|
||
|
{
|
||
|
rage::cCommerceUtil *pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
|
||
|
if (pCommerceUtil != nullptr && pCommerceUtil->IsInCheckout())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (m_QuickCheckout)
|
||
|
{
|
||
|
ExitQuickCheckout();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Start the fade down
|
||
|
if (CScaleformMgr::BeginMethod(m_BlackFadeMovieId, SF_BASE_CLASS_STORE, "FADE_TO_TRANSPARENT"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(STORE_FADE_TIME);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
m_CurrentState = STATE_STORE_FADE_TO_TRANS;
|
||
|
|
||
|
#if RSG_NP
|
||
|
m_isCommerceLogoDisplaying = g_rlNp.GetCommonDialog().ShowCommerceLogo(rlNpCommonDialog::COMMERCE_LOGO_POS_LEFT);
|
||
|
m_shouldCommerceLogoDisplay = true;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::ExitQuickCheckout()
|
||
|
{
|
||
|
if (cStoreScreenMgr::IsExitRequested())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
cStoreScreenMgr::SetCheckoutInitialItem(false);
|
||
|
m_QuickCheckout = false;
|
||
|
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
|
||
|
{
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
storeUIDebugf1("ExitQuickCheckout :: Requesting exit");
|
||
|
cStoreScreenMgr::RequestExit();
|
||
|
}
|
||
|
|
||
|
bool cStoreMainScreen::ProcessCheckoutSelected(const cCommerceProductData *pProductData)
|
||
|
{
|
||
|
// reset this here in all paths to be sure
|
||
|
m_SubscriptionUpsellItemId.Clear();
|
||
|
m_SubscriptionUpsellTargetItemId.Clear();
|
||
|
|
||
|
if(pProductData == nullptr)
|
||
|
return false;
|
||
|
|
||
|
cCommerceUtil* pCommerceUtil = CLiveManager::GetCommerceMgr().GetCommerceUtil();
|
||
|
if(pCommerceUtil == nullptr)
|
||
|
return false;
|
||
|
|
||
|
// check if we need to show an upsell instead of the actual product
|
||
|
// - true if we have any missing upsells tagged on the product
|
||
|
// - true if we have any upsells (fulfilled or not) and have -commerceAlwaysShowUpsell
|
||
|
const bool showSubscriptionUpsell = pCommerceUtil->HasMissingSubscriptionUpsells(pProductData)
|
||
|
NOTFINAL_ONLY(|| (pCommerceUtil->HasSubscriptionUpsell(pProductData) && PARAM_commerceAlwaysShowUpsell.Get()));
|
||
|
|
||
|
if(showSubscriptionUpsell)
|
||
|
{
|
||
|
// show a warning screen that an upsell is required for this product and offer an upsell option
|
||
|
// cache the product so that we can return to this in the menu once the purchase is complete
|
||
|
m_PendingNonCriticalWarningScreen = STORE_SUBSCRIPTION_UPSELL;
|
||
|
|
||
|
// store the upsell item
|
||
|
m_SubscriptionUpsellItemId = pProductData->GetId();
|
||
|
|
||
|
// an upsell product is a dummy entry for an existing product - get to the actual itemId by removing
|
||
|
// the upsell portion of the described itemId
|
||
|
int indexOfSplit = pProductData->GetId().IndexOf('_');
|
||
|
if(indexOfSplit > 0)
|
||
|
{
|
||
|
// step forward
|
||
|
m_SubscriptionUpsellTargetItemId = &pProductData->GetId().c_str()[++indexOfSplit];
|
||
|
}
|
||
|
|
||
|
#if RSG_OUTPUT
|
||
|
const cCommerceItemData* targetItemData = pCommerceUtil->GetItemDataByItemId(m_SubscriptionUpsellTargetItemId.c_str());
|
||
|
storeUIAssert(targetItemData != nullptr);
|
||
|
#endif
|
||
|
|
||
|
storeUIDebugf1("ProcessCheckoutSelected :: Showing upsell - Product: %s - %s, Target: %s - %s",
|
||
|
pProductData->GetName().c_str(),
|
||
|
pProductData->GetId().c_str(),
|
||
|
targetItemData ? targetItemData->GetName().c_str() : "Invalid",
|
||
|
targetItemData ? targetItemData->GetId().c_str() : "Invalid");
|
||
|
|
||
|
// indicate success
|
||
|
return true;
|
||
|
}
|
||
|
else if(pProductData->GetEnumeratedFlag())
|
||
|
{
|
||
|
storeUIDebugf1("ProcessCheckoutSelected :: Calling CheckoutProduct on item %s", pProductData->GetId().c_str());
|
||
|
|
||
|
//Check we are allowed to purchase cash.
|
||
|
if (pProductData->IsConsumable() &&
|
||
|
(CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataDirty() || !CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataPopulated()))
|
||
|
{
|
||
|
storeUIDisplayf("User is attempting to purchase another consumable before the value of the previous cosumable has been assessed.");
|
||
|
return false;
|
||
|
}
|
||
|
else if (pProductData->IsConsumable() && !IsUserAllowedToPurchaseCash(pProductData->GetConsumableId()))
|
||
|
{
|
||
|
storeUIDisplayf("Setting m_NeedToDisplayCashProductsDisabledMessage to true.");
|
||
|
m_PendingNonCriticalWarningScreen = STORE_CANNOT_PURCHASE_CASH;
|
||
|
return false;
|
||
|
}
|
||
|
else if (m_ConsumableProductCheckId.GetLength() > 0)
|
||
|
{
|
||
|
//We are waiting for info on a previously purchased cash product. Don't allow another cash purchase until we have updated.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!pCommerceUtil->IsProductPurchased(pProductData) || pProductData->IsConsumable())
|
||
|
{
|
||
|
m_PurchaseCheckProductID = pProductData->GetId();
|
||
|
CNetworkTelemetry::GetPurchaseMetricInformation().AddProductId(m_PurchaseCheckProductID);
|
||
|
}
|
||
|
|
||
|
// start the checkout process
|
||
|
StartCheckout(pProductData);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool cStoreMainScreen::StartCheckout(const cCommerceProductData* pProductData)
|
||
|
{
|
||
|
if(pProductData != nullptr)
|
||
|
{
|
||
|
storeUIDebugf1("StartCheckout :: ProductName: %s, ProductId: %s", pProductData->GetName().c_str(), pProductData->GetId().c_str());
|
||
|
|
||
|
m_PendingCheckoutProduct = pProductData;
|
||
|
|
||
|
//Start the fade down
|
||
|
if (CScaleformMgr::BeginMethod(m_BlackFadeMovieId, SF_BASE_CLASS_STORE, "FADE_TO_BLACK"))
|
||
|
{
|
||
|
CScaleformMgr::AddParamInt(STORE_FADE_TIME);
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
|
||
|
m_CurrentState = STATE_STORE_FADE_TO_BLACK;
|
||
|
|
||
|
#if RSG_NP
|
||
|
g_rlNp.GetCommonDialog().HideCommerceLogo();
|
||
|
m_shouldCommerceLogoDisplay = false;
|
||
|
m_isCommerceLogoDisplaying = false;
|
||
|
#endif
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool cStoreMainScreen::IsUserAllowedToPurchaseCash(const char* currentConsumableId)
|
||
|
{
|
||
|
if ( !cStoreScreenMgr::AreCashProductsAllowed() )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool currentConsumableHandled = false;
|
||
|
|
||
|
atString currentSelectedIDString(currentConsumableId);
|
||
|
|
||
|
if (currentConsumableId == NULL)
|
||
|
{
|
||
|
currentConsumableHandled = true;
|
||
|
}
|
||
|
|
||
|
MoneyInterface::CashProductBatches batchesPending;
|
||
|
if ( !CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataDirty() && CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataPopulated() )
|
||
|
{
|
||
|
const CCashProductsData::CCashProductsList& productsList = CashPackInfo::GetInstance().GetProductsList();
|
||
|
for (int i = 0; i < productsList.GetCount(); i++ )
|
||
|
{
|
||
|
atString packName;
|
||
|
|
||
|
if ( !productsList[i].GetSKUPackName(packName) )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int consumableLevel = CLiveManager::GetCommerceMgr().GetConsumableManager()->GetConsumableLevel( packName.c_str() );
|
||
|
if ( consumableLevel > 0 )
|
||
|
{
|
||
|
MoneyInterface::CashProductBatch batch;
|
||
|
batch.m_Quantity = consumableLevel;
|
||
|
|
||
|
//See if this is our currently selected ID, and if so bump the quantity by one and mark as handled.
|
||
|
if ( packName == currentSelectedIDString )
|
||
|
{
|
||
|
batch.m_Quantity++;
|
||
|
currentConsumableHandled = true;
|
||
|
}
|
||
|
|
||
|
batch.m_id.SetFromString(packName);
|
||
|
batchesPending.PushAndGrow(batch);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//We have no pending products, but still need space for the selected item
|
||
|
batchesPending.Reserve(1);
|
||
|
}
|
||
|
|
||
|
//If the currently selected consumable has not been added to the batches, we take care of that here.
|
||
|
if ( !currentConsumableHandled )
|
||
|
{
|
||
|
MoneyInterface::CashProductBatch batch;
|
||
|
batch.m_Quantity = 1;
|
||
|
batch.m_id.SetFromString(currentSelectedIDString);
|
||
|
currentConsumableHandled = true;
|
||
|
batchesPending.PushAndGrow(batch);
|
||
|
}
|
||
|
|
||
|
return MoneyInterface::CanBuyCashProducts( batchesPending );
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateTopOfScreenTextInfo()
|
||
|
{
|
||
|
int hour = CClock::GetHour();
|
||
|
int minute = CClock::GetMinute();
|
||
|
|
||
|
// get the date/time:
|
||
|
char const *asciiDayString = TheText.Get(CClock::GetDayOfWeekTextId());
|
||
|
|
||
|
char dateTimeString[64] = {"\0"};
|
||
|
|
||
|
formatf(dateTimeString, NELEM(dateTimeString), "%s %02d:%02d", asciiDayString, hour, minute);
|
||
|
|
||
|
char cashBuff[64];
|
||
|
CFrontendStatsMgr::FormatInt64ToCash(cStoreScreenMgr::GetWalletCashForDisplay(), cashBuff, NELEM(cashBuff));
|
||
|
//Cash
|
||
|
char CashString[128] = {0};
|
||
|
|
||
|
if (cStoreScreenMgr::WasOpenedFromNetworkGame() || NetworkInterface::IsGameInProgress())
|
||
|
{
|
||
|
char bankBuff[64];
|
||
|
CFrontendStatsMgr::FormatInt64ToCash(cStoreScreenMgr::GetBankCashForDisplay() + m_PendingCash, bankBuff, NELEM(bankBuff));
|
||
|
|
||
|
// build the string out of text from the text file & also the converted cash and bank cash
|
||
|
safecpy(CashString, TheText.Get("MENU_PLYR_BANK"), NELEM(CashString));
|
||
|
safecat(CashString, " ", NELEM(CashString));
|
||
|
safecat(CashString, (char*)bankBuff, NELEM(CashString));
|
||
|
safecat(CashString, " ", NELEM(CashString));
|
||
|
safecat(CashString, TheText.Get("MENU_PLYR_CASH"), NELEM(CashString));
|
||
|
safecat(CashString, " ", NELEM(CashString));
|
||
|
safecat(CashString, (char*)cashBuff, NELEM(CashString));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
safecpy(CashString, (char*)cashBuff, NELEM(CashString)); // just standard cash
|
||
|
}
|
||
|
|
||
|
|
||
|
if (CScaleformMgr::IsMovieActive(m_StoreMovieId))
|
||
|
{
|
||
|
if (CScaleformMgr::BeginMethod(m_StoreMovieId, SF_BASE_CLASS_STORE, ""))
|
||
|
{
|
||
|
CScaleformMgr::AddParamString( cStoreScreenMgr::GetPlayerNameToDisplay(), false);
|
||
|
CScaleformMgr::AddParamString( dateTimeString, false);
|
||
|
CScaleformMgr::AddParamString( CashString, false);
|
||
|
CScaleformMgr::AddParamBool( false );
|
||
|
CScaleformMgr::EndMethod();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::InitialiseConsumablesLevel()
|
||
|
{
|
||
|
const CCashProductsData::CCashProductsList& productsList = CashPackInfo::GetInstance().GetProductsList();
|
||
|
|
||
|
m_InitialConsumableLevels.Reset();
|
||
|
m_InitialConsumableLevels.Reserve(productsList.GetCount());
|
||
|
|
||
|
|
||
|
for ( int i=0; i < productsList.GetCount(); i++ )
|
||
|
{
|
||
|
atString packName;
|
||
|
|
||
|
if (!productsList[i].GetSKUPackName(packName))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int consumableLevel = 0;
|
||
|
|
||
|
if (CLiveManager::GetCommerceMgr().GetConsumableManager()->IsOwnershipDataPopulated())
|
||
|
{
|
||
|
consumableLevel = CLiveManager::GetCommerceMgr().GetConsumableManager()->GetConsumableLevel(packName);
|
||
|
}
|
||
|
|
||
|
m_InitialConsumableLevels.PushAndGrow(consumableLevel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdateChangeInConsumableLevelCheck()
|
||
|
{
|
||
|
const CCashProductsData::CCashProductsList& productsList = CashPackInfo::GetInstance().GetProductsList();
|
||
|
|
||
|
for ( int i=0; i < productsList.GetCount(); i++ )
|
||
|
{
|
||
|
atString packName;
|
||
|
|
||
|
if (!productsList[i].GetSKUPackName(packName))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int numberOfPackOwned = CLiveManager::GetCommerceMgr().GetConsumableManager()->GetConsumableLevel(packName);
|
||
|
|
||
|
//Take this opportunity to trigger telemetry based on level changes.
|
||
|
if ( m_InitialConsumableLevels[i] != numberOfPackOwned )
|
||
|
{
|
||
|
int newlyObtainedConsumableNum = numberOfPackOwned - m_InitialConsumableLevels[i];
|
||
|
if (newlyObtainedConsumableNum < 0)
|
||
|
newlyObtainedConsumableNum *= -1;
|
||
|
|
||
|
//DO EVENT: We just obtained newlyObtainedConsumableNum of autoConsumeArray[i] via the in game store.
|
||
|
//POSSIBLE FALSE POSITIVE CASE: Simultaneous web purchase or code redemption while in store. Differentiation on that level requires platform data.
|
||
|
|
||
|
int amount = static_cast<int>(productsList[i].m_Value * newlyObtainedConsumableNum);
|
||
|
float usdeAmount = productsList[i].m_USDE * newlyObtainedConsumableNum;
|
||
|
|
||
|
CNetworkTelemetry::AppendMetric(MetricInGamePurchaseVC(amount, usdeAmount));
|
||
|
|
||
|
//This line just here to avoid the warning as error.
|
||
|
(void)newlyObtainedConsumableNum;
|
||
|
|
||
|
//Now we set the initial level to the new level in case of multiple purchases in the same store session.
|
||
|
m_InitialConsumableLevels[i] = numberOfPackOwned;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void cStoreMainScreen::UpdatePendingCash()
|
||
|
{
|
||
|
const CCashProductsData::CCashProductsList& productsList = CashPackInfo::GetInstance().GetProductsList();
|
||
|
|
||
|
m_PendingCash = 0;
|
||
|
|
||
|
for ( int i=0; i < productsList.GetCount(); i++ )
|
||
|
{
|
||
|
atString packName;
|
||
|
|
||
|
if (!productsList[i].GetSKUPackName(packName))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int numberOfPackOwned = CLiveManager::GetCommerceMgr().GetConsumableManager()->GetConsumableLevel(packName);
|
||
|
int valueOfPack = MoneyInterface::GetCashPackValue(packName);
|
||
|
|
||
|
if ( valueOfPack != -1 )
|
||
|
{
|
||
|
m_PendingCash += ( numberOfPackOwned * valueOfPack );
|
||
|
}
|
||
|
}
|
||
|
}
|