diff --git a/config/373307D9/symbols.txt b/config/373307D9/symbols.txt index 7c2324847..0a1ef8a18 100644 --- a/config/373307D9/symbols.txt +++ b/config/373307D9/symbols.txt @@ -168933,7 +168933,7 @@ except_data_82919D68 = .text:0x82919D60; // type:object size:0x8 scope:global __unwind$193683 = .text:0x82919E28; // type:function size:0x20 scope:global ?HasAward@AccomplishmentGroup@@QBA_NXZ = .text:0x82919E48; // type:function size:0x38 scope:global ??0AccomplishmentGroup@@QAA@PAVDataArray@@H@Z = .text:0x82919E80; // type:function size:0x60 scope:global -?GetName@AccomplishmentGroup@@QBA?AVSymbol@@XZ = .text:0x82919EE0; // type:function size:0xC scope:global +merged_GetSym0x4 = .text:0x82919EE0; // type:function size:0xC scope:global merged_82919EF0 = .text:0x82919EF0; // type:function size:0xC scope:global ?GetDanceCrazeSong@CampaignEra@@QBA?AVSymbol@@XZ = .text:0x82919F00; // type:function size:0xC scope:global ?deallocate@?$StlNodeAlloc@PAVCampaignEraSongEntry@@@stlpmtx_std@@QBAXPAPAVCampaignEraSongEntry@@I@Z = .text:0x82919F10; // type:function size:0x80 scope:global diff --git a/src/lazer/meta_ham/AccomplishmentManager.cpp b/src/lazer/meta_ham/AccomplishmentManager.cpp index c0604b02b..9eec0d925 100644 --- a/src/lazer/meta_ham/AccomplishmentManager.cpp +++ b/src/lazer/meta_ham/AccomplishmentManager.cpp @@ -226,6 +226,7 @@ void AccomplishmentManager::ConfigureAccomplishmentCategoryData(DataArray *cfg) if (HasAccomplishmentCategory(name)) { MILO_NOTIFY("%s accomplishment category already exists, skipping", name.Str()); delete pAccomplishmentCategory; + continue; } else { Symbol group = pAccomplishmentCategory->GetGroup(); if (!HasAccomplishmentGroup(group)) { @@ -235,6 +236,7 @@ void AccomplishmentManager::ConfigureAccomplishmentCategoryData(DataArray *cfg) group.Str() ); delete pAccomplishmentCategory; + continue; } else { mAccomplishmentCategories[name] = pAccomplishmentCategory; if (pAccomplishmentCategory->HasAward()) { @@ -276,6 +278,7 @@ void AccomplishmentManager::ConfigureAccomplishmentData(DataArray *cfg) { if (HasAccomplishment(name)) { MILO_NOTIFY("%s accomplishment already exists, skipping", name.Str()); delete pAccomplishment; + continue; } else { Symbol cat = pAccomplishment->GetCategory(); if (!HasAccomplishmentCategory(cat)) { @@ -285,6 +288,7 @@ void AccomplishmentManager::ConfigureAccomplishmentData(DataArray *cfg) { cat.Str() ); delete pAccomplishment; + continue; } else { mAccomplishments[name] = pAccomplishment; if (pAccomplishment->HasAward()) { @@ -892,13 +896,18 @@ void AccomplishmentManager::UpdateMiscellaneousSongDataForUser( } HardCoreStatus AccomplishmentManager::GetIconHardCoreStatus(int x) const { - int i; - for (i = 0; i < 4; i++) { - if (x < mIconThresholds[i]) { - return (HardCoreStatus)i; + HardCoreStatus result = (HardCoreStatus)0; + int i = 0; + const int *thresholds = mIconThresholds; + while (i < 4) { + if (x < *thresholds) { + return result; } + result = (HardCoreStatus)i; + i++; + thresholds++; } - return (HardCoreStatus)3; + return result; } bool AccomplishmentManager::HasCompletedAccomplishment(HamUser *user, Symbol s) const { diff --git a/src/lazer/meta_ham/HamStorePanel.cpp b/src/lazer/meta_ham/HamStorePanel.cpp index 2d4daaf1b..a5d6aea28 100644 --- a/src/lazer/meta_ham/HamStorePanel.cpp +++ b/src/lazer/meta_ham/HamStorePanel.cpp @@ -1,12 +1,15 @@ #include "meta_ham/HamStorePanel.h" #include "HamStoreOffer.h" +#include "macros.h" #include "meta/SongMgr.h" #include "meta/StoreEnumeration.h" #include "meta/StoreOffer.h" #include "meta/StorePanel.h" +#include "meta/StorePurchaser.h" #include "meta_ham/HamProfile.h" #include "meta_ham/HamStoreFilterProvider.h" #include "meta_ham/HamStoreProvider.h" +#include "meta_ham/HamUI.h" #include "meta_ham/ProfileMgr.h" #include "meta_ham/UIEventMgr.h" #include "net_ham/HamStoreCartJobs.h" @@ -21,22 +24,41 @@ #include "os/PlatformMgr.h" #include "os/System.h" #include "os/User.h" +#include "stl/_vector.h" +#include "ui/UI.h" #include "utl/Loader.h" #include "utl/MakeString.h" +#include "utl/NetCacheMgr.h" +#include "utl/NetLoader.h" #include "utl/Std.h" #include "utl/Symbol.h" HamStorePanel::HamStorePanel() - : unka0(), unka4(), mOfferProvider(), unkb8(), unkc0(false), unk128(), unk154(false), - unk155(true), unk156(false), unk157(false), unk158(false), unk159(false), unk184(), - mXboxPurchaser() { - for (int i = 7; i != 0; i--) { + : unka0(), mMetadata(), mOfferProvider(), unkb8(), unkc0(false), unk128(), + unk154(false), unk155(true), unk156(false), unk157(false), unk158(false), + unk159(false), unk184(-1), mXboxPurchaser() { + for (int i = 0; i < 7; i++) { unk138[i] = 0; } - DataArray *sysConfig = SystemConfig("store"); - DataArray *specialOfferArray = sysConfig->FindArray("special_offers", false); + DataArray *specialOfferArray = + SystemConfig("store")->FindArray("special_offers", false); if (specialOfferArray) { + int numOffers = specialOfferArray->Size() - 1; + HamSpecialOffer tempOffer; + unk16c.resize(numOffers, tempOffer); + unk178.resize(numOffers, 0); + + for (int i = 0; i < numOffers; i++) { + DataArray *offerArray = specialOfferArray->Array(i + 1); + HamSpecialOffer &offer = unk16c[i]; + offer.unk4 = offerArray->Sym(0); + offer.unk14 = false; + offer.unk8 = StorePurchaseable::OfferStringToID(offerArray->Str(1)); + unk178[i] = offer.unk8; + offer.unk10 = offerArray->ForceSym(2); + } } + TheContentMgr.RegisterCallback(this, false); } @@ -246,7 +268,201 @@ void HamStorePanel::CreateCartUIs() { static Symbol description("description"); static Symbol art("art"); static Symbol store_filter_song_import_offers("store_filter_song_import_offers"); - // something + unkac.insert(unkac.begin(), 1, new HamStoreFilter(store_filter_shopping_cart)); + unkac.push_back(new HamStoreFilter(store_filter_song_import_offers)); +} + +bool HamStorePanel::IsSpecialOfferOwned(Symbol offer) const { + FOREACH (it, unk16c) { + if ((*it).unk4 == offer) { + return (*it).unk14; + } + } + Symbol s = offer; // bruh + MILO_NOTIFY("Unknown offer %s", s); + return false; +} + +void HamStorePanel::ResetCancelTimer() { + unkc0 = false; + unkc4.Restart(); +} + +bool HamStorePanel::ContentTitleDiscovered(unsigned int ui, Symbol s) { + static Symbol dc2_gond("dc2_gond"); + if (ui == 0x373307d2) { + FOREACH (it, unk16c) { + if (it->unk4 == dc2_gond) { + it->unk10 = s; + break; + } + } + return false; + } + return true; +} + +void HamStorePanel::ContentMounted(char const *c1, char const *c2) { + FOREACH (it, unk16c) { + if (it->unk10 == c1) { + Symbol s = it->unk4; + MILO_LOG("Store: special offer %s on local drive.\n", s); + it->unk14 = true; + return; + } + } +} + +bool HamStorePanel::ContentDiscovered(Symbol s) { + FOREACH (it, unk16c) { + if (it->unk10 == s) { + return false; + } + } + return true; +} + +bool HamStorePanel::BuySpecialOffer(Symbol offer) { + if (mXboxPurchaser) { + MILO_FAIL("There is a purchase in progress."); + } + FOREACH (it, unk16c) { + if ((*it).unk4 == offer) { + Profile *profile = StoreProfile(); + if (profile) { + mXboxPurchaser = + new XboxPurchaser(profile->GetPadNum(), it->unk8, 0, 0, unk8c, 0); + mXboxPurchaser->Initiate(); + } + return true; + } + } + Symbol s = offer; + MILO_NOTIFY("Unknown offer %s", s); + return false; +} + +void HamStorePanel::Poll() { + StorePanel::Poll(); + if (!unkc0 && unkc4.SplitMs() > 5000.0f) { + unkc0 = true; + if (TheHamUI.FocusPanel() == this) { + TheHamUI.GetHelpBarPanel()->SyncToPanel(this); + } + } + if (!mLoadOk) { + return; + } + if (!TheNetCacheMgr->IsReady()) { + return; + } + if (unk94 != 2) { + return; + } + if (unka0) { + unka0->PollLoading(); + if (unka0->IsLoaded()) { + mMetadata = unka0->GetUnk4(); + MILO_ASSERT(mMetadata, 0xfe); + mMetadata->AddRef(); + static Symbol motd("motd"); + mMetadata->FindData(motd, unkb8, false); + DataArray *filterArray = mMetadata->FindArray("filters", true); + DeleteAll(unkac); + for (int i = 1; i < filterArray->Size(); i++) { + unkac.push_back(new HamStoreFilter(filterArray->Array(i))); + } + DataArray *offerArray = mMetadata->FindArray("offers", true); + PopulateOffers(offerArray, false); + CreateCartUIs(); + unk154 = true; + } else { + if (!unka0->HasFailed()) { + goto tag; + } + MILO_NOTIFY("Request for %s failed.", GetIndexFile()); + ExitError((StoreError)3); + } + RELEASE(unka0); + } else { + if (mMetadata == 0) { + String indexFile = GetIndexFile(); + unka0 = new DataNetLoader(indexFile); + } else if (unk154 && (unk157 || !unk155)) { + unk154 = false; + unk70 = true; + } + } +tag: + if (unk156 && unk128 != 0) { + if (unkf8.SplitMs() >= unk128) { + RelockCart(); + } + } + if (mXboxPurchaser) { + mXboxPurchaser->Poll(); + if (!mXboxPurchaser->IsPurchasing()) { + bool purchaseMade = false; + bool needsEnum = false; + if (mXboxPurchaser->IsSuccess()) { + purchaseMade = mXboxPurchaser->PurchaseMade(); + needsEnum = mXboxPurchaser->NeedsEnum(); + if (purchaseMade && needsEnum) { + RefreshSpecialOfferStatus(); + } + } + + static Message special_finished("special_finished", 0, 0); + special_finished[0] = purchaseMade; + special_finished[1] = needsEnum; + HandleType(special_finished); + TheUI->Handle(special_finished, false); + RELEASE(mXboxPurchaser); + } + } +} + +void HamStorePanel::Unload() { + RELEASE(unka0); + RELEASE(mOfferProvider); + if (mMetadata) { + mMetadata->Release(); + mMetadata = nullptr; + } + DeleteAll(unkac); + unkc4.Stop(); + unkc0 = false; + unkf8.Stop(); + unk128 = 0; + unk155 = true; + unk154 = false; + unk157 = false; + unk158 = false; + unk159 = false; + if (unk156) { + UnlockCart(); + } + StorePanel::Unload(); +} + +void HamStorePanel::FinishSpecialOfferEnum(std::vector const &vec, bool b) { + unk184 = -1; + if (!b) { + MILO_LOG("Store: failed to enum our special offers.\n"); + } else { + for (int i = 0; i < unk16c.size(); i++) { + if (!unk16c[i].unk14) { + unk16c[i].unk14 = vec[i]; + } + + if (unk16c[i].unk14) { + MILO_LOG("Store: special offer %s is owned\n", unk16c[i].unk4); + } + } + } + static Message refresh_complete("refresh_complete", 0); + refresh_complete[0] = b; + TheUI->Handle(refresh_complete, false); } BEGIN_HANDLERS(HamStorePanel) @@ -257,14 +473,14 @@ BEGIN_HANDLERS(HamStorePanel) ) HANDLE_EXPR(offer_provider, (Hmx::Object *)mOfferProvider) HANDLE_EXPR(filter_provider, (Hmx::Object *)mOfferProvider->GetFilterProvider()) - HANDLE_ACTION(reset_cancel_timer, (unkc0 = false, unkc4.Restart())) + HANDLE_ACTION(reset_cancel_timer, ResetCancelTimer()) HANDLE_EXPR(allow_cancel, unkc0) HANDLE_EXPR(is_cart_enabled, unk155) HANDLE_ACTION(disable_cart, DisableCart()) HANDLE_ACTION(get_cart, GetCart()) HANDLE_ACTION(add_offer_to_cart, AddOfferToCart(_msg->Obj(2))) HANDLE_ACTION(remove_offer_from_cart, RemoveOfferFromCart(_msg->Obj(2))) - HANDLE_ACTION(cart_checkout, MultipleItemsCheckout(mOfferProvider->GetCartOffers())) + HANDLE_ACTION(cart_checkout, MultipleItemsCheckout(mOfferProvider->GetOffersInCart())) HANDLE_ACTION(lock_cart, LockCart()) HANDLE_ACTION(unlock_cart, UnlockCart()) HANDLE_EXPR(is_curr_filter_cart, IsCurrFilterCart(_msg->Int(2))) @@ -272,7 +488,7 @@ BEGIN_HANDLERS(HamStorePanel) HANDLE_EXPR(is_cart_full, mOfferProvider->NumOffersInCart() == 6) HANDLE_ACTION(empty_cart, EmptyCart()) HANDLE_ACTION(set_filter_to_cart, SetFilterToCart()) - HANDLE_ACTION(set_filter_to_songs, SetFilterToSongs()) + HANDLE_EXPR(set_filter_to_songs, SetFilterToSongs()) HANDLE_ACTION(refresh_special_offers, RefreshSpecialOfferStatus()) HANDLE_EXPR(check_owned, IsSpecialOfferOwned(_msg->ForceSym(2))) HANDLE_EXPR(buy_special, BuySpecialOffer(_msg->ForceSym(2))) diff --git a/src/lazer/meta_ham/HamStorePanel.h b/src/lazer/meta_ham/HamStorePanel.h index 68b9e16f2..f97caab2d 100644 --- a/src/lazer/meta_ham/HamStorePanel.h +++ b/src/lazer/meta_ham/HamStorePanel.h @@ -15,10 +15,19 @@ #include "os/User.h" #include "stl/_vector.h" #include "types.h" +#include "utl/NetLoader.h" #include "utl/Str.h" #include "utl/Symbol.h" #include +struct HamSpecialOffer { +public: + Symbol unk4; + unsigned long long unk8; + Symbol unk10; + bool unk14; +}; + class HamStorePanel : public StorePanel, public ContentMgr::Callback { public: // Hmx::Object @@ -39,7 +48,7 @@ class HamStorePanel : public StorePanel, public ContentMgr::Callback { virtual StoreOffer *MakeNewOffer(DataArray *); virtual StoreOffer *FindOffer(Symbol) const; virtual bool EnumerateSubsetOfOfferIDs() const { return 0; } - virtual void GetOfferIDsToEnumerate(std::vector &, bool) const; + virtual void GetOfferIDsToEnumerate(std::vector &, bool) const; // ContentMgr::Callback virtual bool ContentDiscovered(Symbol); @@ -77,10 +86,11 @@ class HamStorePanel : public StorePanel, public ContentMgr::Callback { void AddDLCToCart(int); void CreateCartUIs(); void ReadCartData(); + void ResetCancelTimer(); DataNode OnMsg(RCJobCompleteMsg const &); - int unka0; - int unka4; + DataNetLoader *unka0; + DataArray *mMetadata; // 0xa4 HamStoreProvider *mOfferProvider; // 0xa8 std::vector unkac; String unkb8; @@ -98,7 +108,7 @@ class HamStorePanel : public StorePanel, public ContentMgr::Callback { bool unk159; std::list unk15c; std::list unk164; - std::vector unk16c; + std::vector unk16c; std::vector unk178; int unk184; XboxPurchaser *mXboxPurchaser; // 0x188 diff --git a/src/lazer/meta_ham/HamStoreProvider.cpp b/src/lazer/meta_ham/HamStoreProvider.cpp index c92b95ee2..66ea415c0 100644 --- a/src/lazer/meta_ham/HamStoreProvider.cpp +++ b/src/lazer/meta_ham/HamStoreProvider.cpp @@ -76,9 +76,7 @@ Symbol HamStoreProvider::DataSymbol(int idx) const { return (*mFilteredOffers)[idx]->StoreOfferData()->Sym(0); } -void HamStoreProvider::Text( - int, int data, UIListLabel *slot, UILabel *label -) const { +void HamStoreProvider::Text(int, int data, UIListLabel *slot, UILabel *label) const { MILO_ASSERT_RANGE(data, 0, mFilteredOffers->size(), 0x118); StoreOffer *offer = (*mFilteredOffers)[data]; if (!offer) { @@ -114,7 +112,8 @@ void HamStoreProvider::Text( } } else if (slot->Matches("cost")) { String temp; - if (!ShowBrowserPurchased(offer) && !offer->InLibrary() && offer->IsAvailable()) { + if (!ShowBrowserPurchased(offer) && !offer->InLibrary() + && offer->IsAvailable()) { static_cast(label)->SetStoreOfferCost(offer); } return; @@ -221,6 +220,8 @@ void HamStoreProvider::ApplySort() { } } +std::list *HamStoreProvider::GetOffersInCart() { return &unkb0; } + BEGIN_HANDLERS(HamStoreProvider) HANDLE_ACTION(refresh, Refresh()) HANDLE_EXPR(get_offer, OnGetOffer(_msg->Int(2))) diff --git a/src/lazer/meta_ham/HamStoreProvider.h b/src/lazer/meta_ham/HamStoreProvider.h index 70cc4188d..76ff6daf0 100644 --- a/src/lazer/meta_ham/HamStoreProvider.h +++ b/src/lazer/meta_ham/HamStoreProvider.h @@ -48,11 +48,11 @@ class HamStoreProvider : public UIListProvider, public Hmx::Object { void SetFilter(HamStoreFilter const *); void OnNextSort(); void Refresh(); + std::list *GetOffersInCart(); bool AllowSortToggle() { return mSorts.size() > 1; } PackSongListProvider GetPackProvider() { return unk78; } HamStoreFilterProvider *GetFilterProvider() { return unk74; } - std::list *GetCartOffers() { return &unkb0; } protected: std::vector *unk30; diff --git a/src/system/meta/StoreOffer.h b/src/system/meta/StoreOffer.h index 0bf766c5e..a992f5e5e 100644 --- a/src/system/meta/StoreOffer.h +++ b/src/system/meta/StoreOffer.h @@ -16,10 +16,11 @@ class StorePurchaseable : public Hmx::Object { char const *CostStr() const; bool IsAvailable() { return isAvailable; } bool IsPurchased() { return isPurchased; } + unsigned long long SongID() const { return songID; } bool isAvailable; // 0x2c bool isPurchased; // 0x2d - u64 songID; // 0x30 + unsigned long long songID; // 0x30 int cost; // 0x38 }; diff --git a/src/system/meta/StorePanel.h b/src/system/meta/StorePanel.h index 2f2c27f5d..1e64bd212 100644 --- a/src/system/meta/StorePanel.h +++ b/src/system/meta/StorePanel.h @@ -27,9 +27,18 @@ class StorePanel : public UIPanel { virtual void Enter(); virtual void Exit(); virtual bool Exiting() const; + virtual bool Unloading() const; // virtual void Poll(); virtual bool IsLoaded() const; virtual void Unload(); + virtual bool IsSongInLibrary(int const &) const = 0; + virtual void ExitStore(StoreError) const = 0; + virtual Profile *StoreProfile() const = 0; + virtual StoreOffer *MakeNewOffer(DataArray *) = 0; + virtual StoreOffer *FindOffer(Symbol) const = 0; + virtual bool EnumerateSubsetOfOfferIDs() const { return 0; }; + virtual void + GetOfferIDsToEnumerate(std::vector &, bool) const = 0; virtual void LoadArt(char const *, UIPanel *); StorePanel(); @@ -67,6 +76,7 @@ class StorePanel : public UIPanel { virtual void FinishEnum(std::list const &, bool); virtual StoreError UpdateOffers(std::list const &, bool); virtual void UpdateFromEnumProduct(StorePurchaseable *, EnumProduct const *); + virtual void StoreUserProfileSwappedToUser(LocalUser *) = 0; void StartReEnum(); DataNode OnMsg(SigninChangedMsg const &); diff --git a/src/system/meta/StorePurchaser.h b/src/system/meta/StorePurchaser.h index 2e97cd324..58a10d58a 100644 --- a/src/system/meta/StorePurchaser.h +++ b/src/system/meta/StorePurchaser.h @@ -26,14 +26,16 @@ class StorePurchaser { class XboxPurchaser : public StorePurchaser, public Hmx::Object { public: // Hmx::Object - ~XboxPurchaser(); + virtual ~XboxPurchaser(); virtual DataNode Handle(DataArray *, bool); // StorePurchaser - virtual void Initiate(); - virtual bool IsPurchasing() const; - virtual bool IsSuccess() const; - virtual bool PurchaseMade() const; + virtual void Initiate(); // 0x4 + virtual bool IsPurchasing() const; // 0x8 + virtual bool IsSuccess() const; // 0xc + virtual bool PurchaseMade() const; // 0x10 + virtual bool NeedsEnum() const { return true; }; // 0x14 + virtual void Poll() {}; // 0x18 XboxPurchaser( int, diff --git a/src/system/utl/NetLoader.h b/src/system/utl/NetLoader.h index 5be1ddf0c..269cee61d 100644 --- a/src/system/utl/NetLoader.h +++ b/src/system/utl/NetLoader.h @@ -64,6 +64,8 @@ class DataNetLoader { bool HasFailed(); void PollLoading(); + DataArray *GetUnk4() const { return unk4; } + private: NetLoader *unk0; // 0x0 DataArray *unk4; // 0x4