Util: Implement ClothUtil (#841)

This commit is contained in:
Narr the Reg 2026-01-15 12:36:22 -06:00 committed by GitHub
parent dad8e66852
commit 843c05ac78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 351 additions and 61 deletions

View file

@ -152972,39 +152972,39 @@ Util/ClothUtil.o:
- offset: 0x54c2bc
size: 128
label: _ZN2rs21buyItemInShopItemListEPKN2al18IUseSceneObjHolderEi
status: NotDecompiled
status: Matching
- offset: 0x54c33c
size: 128
label: _ZN2rs23isBuyItemInShopItemListEPKN2al18IUseSceneObjHolderEi
status: NotDecompiled
status: Matching
- offset: 0x54c3bc
size: 64
label: _ZN2rs7buyItemEPKN2al18IUseSceneObjHolderEPKN8ShopItem8ItemInfoE
status: NotDecompiled
status: Matching
- offset: 0x54c3fc
size: 52
label: _ZN2rs10buyItemAllEPKN2al18IUseSceneObjHolderE
status: NotDecompiled
status: Matching
- offset: 0x54c430
size: 104
label: _ZN2rs9isBuyItemE22GameDataHolderAccessorPKN8ShopItem8ItemInfoE
status: NotDecompiled
status: Matching
- offset: 0x54c498
size: 12
label: _ZN2rs11isHaveClothE22GameDataHolderAccessorPKc
status: NotDecompiled
status: Matching
- offset: 0x54c4a4
size: 12
label: _ZN2rs9isHaveCapE22GameDataHolderAccessorPKc
status: NotDecompiled
status: Matching
- offset: 0x54c4b0
size: 12
label: _ZN2rs13isHaveStickerE22GameDataHolderAccessorPKc
status: NotDecompiled
status: Matching
- offset: 0x54c4bc
size: 12
label: _ZN2rs10isHaveGiftE22GameDataHolderAccessorPKc
status: NotDecompiled
status: Matching
- offset: 0x54c4c8
size: 8
label: _ZN2rs12getClothListE22GameDataHolderAccessor
@ -153012,23 +153012,23 @@ Util/ClothUtil.o:
- offset: 0x54c4d0
size: 8
label: _ZN2rs16getClothListSizeE22GameDataHolderAccessor
status: NotDecompiled
status: Matching
- offset: 0x54c4d8
size: 48
label: _ZN2rs11isHaveClothE22GameDataHolderAccessori
status: NotDecompiled
status: Matching
- offset: 0x54c508
size: 44
label: _ZN2rs19isHaveClothByFileIdE22GameDataHolderAccessorPKci
status: NotDecompiled
status: Matching
- offset: 0x54c534
size: 8
label: _ZN2rs16calcHaveClothNumE22GameDataHolderAccessor
status: NotDecompiled
status: Matching
- offset: 0x54c53c
size: 228
label: _ZN2rs8buyClothEPKN2al18IUseSceneObjHolderEPKc
status: NotDecompiled
status: Matching
- offset: 0x54c620
size: 8
label: _ZN2rs10getCapListE22GameDataHolderAccessor
@ -153036,43 +153036,43 @@ Util/ClothUtil.o:
- offset: 0x54c628
size: 8
label: _ZN2rs14getCapListSizeE22GameDataHolderAccessor
status: NotDecompiled
status: Matching
- offset: 0x54c630
size: 48
label: _ZN2rs9isHaveCapE22GameDataHolderAccessori
status: NotDecompiled
status: Matching
- offset: 0x54c660
size: 44
label: _ZN2rs17isHaveCapByFileIdE22GameDataHolderAccessorPKci
status: NotDecompiled
status: Matching
- offset: 0x54c68c
size: 312
label: _ZN2rs18isCompleteClothCapEPKN2al18IUseSceneObjHolderE
status: NotDecompiled
status: Matching
- offset: 0x54c7c4
size: 184
label: _ZN2rs15isCompleteClothEPKN2al18IUseSceneObjHolderE
status: NotDecompiled
status: Matching
- offset: 0x54c87c
size: 184
label: _ZN2rs13isCompleteCapEPKN2al18IUseSceneObjHolderE
status: NotDecompiled
status: Matching
- offset: 0x54c934
size: 204
label: _ZN2rs15isCompleteClothEPKN2al18IUseSceneObjHolderEi
status: NotDecompiled
status: Matching
- offset: 0x54ca00
size: 204
label: _ZN2rs13isCompleteCapEPKN2al18IUseSceneObjHolderEi
status: NotDecompiled
status: Matching
- offset: 0x54cacc
size: 8
label: _ZN2rs14calcHaveCapNumE22GameDataHolderAccessor
status: NotDecompiled
status: Matching
- offset: 0x54cad4
size: 228
label: _ZN2rs6buyCapEPKN2al18IUseSceneObjHolderEPKc
status: NotDecompiled
status: Matching
- offset: 0x54cbb8
size: 8
label: _ZN2rs11getGiftListE22GameDataHolderAccessor
@ -153080,19 +153080,19 @@ Util/ClothUtil.o:
- offset: 0x54cbc0
size: 8
label: _ZN2rs15getGiftListSizeE22GameDataHolderAccessor
status: NotDecompiled
status: Matching
- offset: 0x54cbc8
size: 48
label: _ZN2rs10isHaveGiftE22GameDataHolderAccessori
status: NotDecompiled
status: Matching
- offset: 0x54cbf8
size: 8
label: _ZN2rs15calcHaveGiftNumE22GameDataHolderAccessor
status: NotDecompiled
status: Matching
- offset: 0x54cc00
size: 48
label: _ZN2rs17checkCompleteGiftE22GameDataHolderAccessori
status: NotDecompiled
status: Matching
- offset: 0x54cc30
size: 8
label: _ZN2rs14getStickerListE22GameDataHolderAccessor
@ -153100,55 +153100,55 @@ Util/ClothUtil.o:
- offset: 0x54cc38
size: 8
label: _ZN2rs18getStickerListSizeE22GameDataHolderAccessor
status: NotDecompiled
status: Matching
- offset: 0x54cc40
size: 48
label: _ZN2rs13isHaveStickerE22GameDataHolderAccessori
status: NotDecompiled
status: Matching
- offset: 0x54cc70
size: 8
label: _ZN2rs18calcHaveStickerNumE22GameDataHolderAccessor
status: NotDecompiled
status: Matching
- offset: 0x54cc78
size: 48
label: _ZN2rs20checkCompleteStickerE22GameDataHolderAccessori
status: NotDecompiled
status: Matching
- offset: 0x54cca8
size: 12
label: _ZN2rs18getTestClothesNameEv
status: NotDecompiled
status: Matching
- offset: 0x54ccb4
size: 12
label: _ZN2rs14getTestCapNameEv
status: NotDecompiled
status: Matching
- offset: 0x54ccc0
size: 12
label: _ZN2rs15getTestGiftNameEv
status: NotDecompiled
status: Matching
- offset: 0x54cccc
size: 12
label: _ZN2rs18getTestStickerNameEv
status: NotDecompiled
status: Matching
- offset: 0x54ccd8
size: 12
label: _ZN2rs15getTestItemNameEv
status: NotDecompiled
status: Matching
- offset: 0x54cce4
size: 12
label: _ZN2rs16getTestShineNameEv
status: NotDecompiled
status: Matching
- offset: 0x54ccf0
size: 36
label: _ZN2rs13getMsTextNameERKN8ShopItem8ItemTypeE
status: NotDecompiled
status: Matching
- offset: 0x54cd14
size: 44
label: _ZN2rs14getDisplayNameEPKN2al17IUseMessageSystemERKN8ShopItem8ItemInfoE
status: NotDecompiled
status: Matching
- offset: 0x54cd40
size: 20
label: _ZN2rs10isTypeWearEPKN8ShopItem12ShopItemInfoE
status: NotDecompiled
status: Matching
Util/ColliderDisk.o:
'.text':
- offset: 0x54cd54

View file

@ -1,23 +1,59 @@
#pragma once
#include <basis/seadTypes.h>
#include <container/seadBuffer.h>
namespace ShopItem {
enum class ItemType : u32 { Cloth, Cap, Gift, Sticker, UseItem, Moon };
struct ShopItemInfo {
s32 characterId;
s32 numberingId;
enum class ItemType : s32 {
Invalid = -1,
Cloth,
Cap,
Gift,
Sticker,
UseItem,
Moon,
};
enum class CoinType : s32 {
Invalid = -1,
Coin,
Collect,
};
struct ShopAmiiboInfo {
s32 characterId = -1;
s32 numberingId = -1;
};
static_assert(sizeof(ShopAmiiboInfo) == 0x8);
struct ItemInfo {
s32 index;
ItemInfo() { name[0] = '\0'; }
s32 index = -1;
char name[0x80];
ItemType type;
u32 itemCount;
ShopItemInfo* shopItemInfo;
bool isAOC;
ItemType type = ItemType::Invalid;
sead::Buffer<ShopAmiiboInfo> amiiboInfoList;
bool isAOC = false;
};
static_assert(sizeof(ItemInfo) == 0xa0);
struct ShopItemInfo {
ShopItemInfo() {
storeName[0] = '\0';
clearWorld[0] = '\0';
}
ItemInfo info = {};
s32 price = -1;
CoinType coinType = CoinType::Invalid;
char storeName[0x80];
char clearWorld[0x80];
s32 moonNum = -1;
};
static_assert(sizeof(ShopItemInfo) == 0x1b0);
} // namespace ShopItem

View file

@ -466,6 +466,14 @@ public:
void disableCapMessageLifeOneKidsMode() { mIsEnableCapMessageLifeOneKidsMode = false; }
sead::FixedSafeString<64>* getCapName() { return mCapNamePtr; }
sead::FixedSafeString<64>* getClothName() { return mClothNamePtr; }
sead::FixedSafeString<64>* getStickerName() { return mStickerNamePtr; }
sead::FixedSafeString<64>* getGiftName() { return mGiftNamePtr; }
private:
char _000[0x18];
FixedHeapArray<s32, sNumWorlds> mShopShineNum;
@ -526,7 +534,10 @@ private:
char _6d8[0x8];
HintPhotoData* mHintPhotoData;
s64 mPlayTimeTotal;
char _6f0[0x20];
sead::FixedSafeString<64>* mCapNamePtr;
sead::FixedSafeString<64>* mClothNamePtr;
sead::FixedSafeString<64>* mStickerNamePtr;
sead::FixedSafeString<64>* mGiftNamePtr;
sead::FixedSafeString<64> mCurrentCostumeName;
sead::FixedSafeString<64> mCurrentCapName;
bool mIsCostumeRandom;

View file

@ -382,7 +382,7 @@ void setCostumeRandomMode(al::IUseSceneObjHolder* holder);
void setCapRandomMode(al::IUseSceneObjHolder* holder);
void resetCostumeRandomMode(al::IUseSceneObjHolder* holder);
void resetCapRandomMode(al::IUseSceneObjHolder* holder);
const sead::PtrArray<ShopItem::ItemInfo>& getShopItemInfoList(GameDataHolderAccessor accessor);
const sead::PtrArray<ShopItem::ShopItemInfo>& getShopItemInfoList(GameDataHolderAccessor accessor);
bool isExistHackObjInfo(GameDataHolderAccessor accessor, const char* hackName);
const HackObjInfo& getHackObjInfo(GameDataHolderAccessor accessor, const char* hackName);
void addHackDictionary(GameDataHolderWriter writer, const char* hackName);

View file

@ -176,7 +176,7 @@ public:
bool isBossAttackedHomeNext(s32 worldId) const;
void playScenarioStartCamera(s32 questNo);
bool isPlayAlreadyScenarioStartCamera(s32 questNo) const;
const sead::PtrArray<ShopItem::ItemInfo>& getShopItemInfoList() const;
const sead::PtrArray<ShopItem::ShopItemInfo>& getShopItemInfoList() const;
bool checkNeedTreasureMessageStage(const char* stageName) const;
bool tryFindLinkDestStageInfo(const char** destStageName, const char** destLabel,
const char* srcStageName, const char* srcLabel) const;
@ -254,8 +254,8 @@ private:
TemporaryScenarioCameraHolder* mTemporaryScenarioCameraHolder;
bool* mIsPlayAlreadyScenarioStartCamera;
sead::PtrArray<StageLockInfo> mStageLockList;
sead::PtrArray<ShopItem::ItemInfo> mShopItemList;
sead::PtrArray<ShopItem::ItemInfo> mShopItemListE3;
sead::PtrArray<ShopItem::ShopItemInfo> mShopItemList;
sead::PtrArray<ShopItem::ShopItemInfo> mShopItemListE3;
sead::PtrArray<ShopItem::ItemInfo> mItemCloth;
sead::PtrArray<ShopItem::ItemInfo> mItemCap;
sead::PtrArray<ShopItem::ItemInfo> mItemGift;

View file

@ -1,19 +1,262 @@
#include "Util/ClothUtil.h"
#include "Library/Base/StringUtil.h"
#include "Library/Message/MessageHolder.h"
#include "Layout/ShopLayoutInfo.h"
#include "System/GameDataFile.h"
#include "System/GameDataFunction.h"
#include "System/GameDataHolder.h"
const sead::PtrArray<ShopItem::ItemInfo>& rs::getClothList(GameDataHolderAccessor accessor) {
namespace rs {
void buyItemInShopItemList(const al::IUseSceneObjHolder* user, s32 itemIdx) {
const sead::PtrArray<ShopItem::ShopItemInfo>& itemList =
GameDataFunction::getShopItemInfoList(user);
GameDataHolderAccessor(user)->getGameDataFile()->buyItem(&itemList[itemIdx]->info, true);
}
bool isBuyItemInShopItemList(const al::IUseSceneObjHolder* user, s32 itemIdx) {
const sead::PtrArray<ShopItem::ShopItemInfo>& itemList =
GameDataFunction::getShopItemInfoList(user);
return GameDataHolderAccessor(user)->getGameDataFile()->isBuyItem(&itemList[itemIdx]->info);
}
void buyItem(const al::IUseSceneObjHolder* user, const ShopItem::ItemInfo* itemInfo) {
GameDataHolderAccessor(user)->getGameDataFile()->buyItem(itemInfo, true);
}
void buyItemAll(const al::IUseSceneObjHolder* user) {
GameDataHolderAccessor(user)->getGameDataFile()->buyItemAll();
}
bool isBuyItem(GameDataHolderAccessor accessor, const ShopItem::ItemInfo* itemInfo) {
switch (itemInfo->type) {
case ShopItem::ItemType::Cloth:
return isHaveCloth(accessor, itemInfo->name);
case ShopItem::ItemType::Cap:
return isHaveCap(accessor, itemInfo->name);
case ShopItem::ItemType::Gift:
return isHaveGift(accessor, itemInfo->name);
case ShopItem::ItemType::Sticker:
return isHaveSticker(accessor, itemInfo->name);
default:
return false;
}
}
bool isHaveCloth(GameDataHolderAccessor accessor, const char* name) {
return accessor->getGameDataFile()->isBuyItem(name,
accessor->getGameDataFile()->getClothName());
}
bool isHaveCap(GameDataHolderAccessor accessor, const char* name) {
return accessor->getGameDataFile()->isBuyItem(name, accessor->getGameDataFile()->getCapName());
}
bool isHaveSticker(GameDataHolderAccessor accessor, const char* name) {
return accessor->getGameDataFile()->isBuyItem(name,
accessor->getGameDataFile()->getStickerName());
}
bool isHaveGift(GameDataHolderAccessor accessor, const char* name) {
return accessor->getGameDataFile()->isBuyItem(name, accessor->getGameDataFile()->getGiftName());
}
const sead::PtrArray<ShopItem::ItemInfo>& getClothList(GameDataHolderAccessor accessor) {
return accessor->getClothList();
}
const sead::PtrArray<ShopItem::ItemInfo>& rs::getCapList(GameDataHolderAccessor accessor) {
s32 getClothListSize(GameDataHolderAccessor accessor) {
return getClothList(accessor).size();
}
bool isHaveCloth(GameDataHolderAccessor accessor, s32 clothIdx) {
return accessor->getGameDataFile()->isBuyItem(getClothList(accessor)[clothIdx]->name,
accessor->getGameDataFile()->getClothName());
}
bool isHaveClothByFileId(GameDataHolderAccessor accessor, const char* clothName, s32 fileId) {
GameDataFile* gameDataFile = accessor->getGameDataFile(fileId);
return gameDataFile->isBuyItem(clothName, gameDataFile->getClothName());
}
s32 calcHaveClothNum(GameDataHolderAccessor accessor) {
return accessor->getGameDataFile()->calcHaveClothNum();
}
void buyCloth(const al::IUseSceneObjHolder* user, const char* clothName) {
const sead::PtrArray<ShopItem::ItemInfo>& list = getClothList(user);
for (s32 i = 0; i < list.size(); i++) {
if (al::isEqualString(clothName, list[i]->name)) {
buyItem(user, list[i]);
return;
}
}
}
const sead::PtrArray<ShopItem::ItemInfo>& getCapList(GameDataHolderAccessor accessor) {
return accessor->getCapList();
}
const sead::PtrArray<ShopItem::ItemInfo>& rs::getGiftList(GameDataHolderAccessor accessor) {
s32 getCapListSize(GameDataHolderAccessor accessor) {
return getCapList(accessor).size();
}
bool isHaveCap(GameDataHolderAccessor accessor, s32 capIdx) {
return accessor->getGameDataFile()->isBuyItem(getCapList(accessor)[capIdx]->name,
accessor->getGameDataFile()->getCapName());
}
bool isHaveCapByFileId(GameDataHolderAccessor accessor, const char* capName, s32 fileId) {
GameDataFile* gameDataFile = accessor->getGameDataFile(fileId);
return gameDataFile->isBuyItem(capName, gameDataFile->getCapName());
}
bool isCompleteClothCap(const al::IUseSceneObjHolder* user) {
return isCompleteCloth(user) && isCompleteCap(user);
}
bool isCompleteCloth(const al::IUseSceneObjHolder* user) {
const sead::PtrArray<ShopItem::ItemInfo>& list = getClothList(user);
for (s32 i = 0; i < list.size(); i++)
if (!list[i]->isAOC && !isHaveCloth(user, list[i]->name))
return false;
return true;
}
bool isCompleteCap(const al::IUseSceneObjHolder* user) {
const sead::PtrArray<ShopItem::ItemInfo>& list = getCapList(user);
for (s32 i = 0; i < list.size(); i++)
if (!list[i]->isAOC && !isHaveCap(user, list[i]->name))
return false;
return true;
}
bool isCompleteCloth(const al::IUseSceneObjHolder* user, s32 fileId) {
const sead::PtrArray<ShopItem::ItemInfo>& list = getClothList(user);
for (s32 i = 0; i < list.size(); i++)
if (!list[i]->isAOC && !isHaveClothByFileId(user, list[i]->name, fileId))
return false;
return true;
}
bool isCompleteCap(const al::IUseSceneObjHolder* user, s32 fileId) {
const sead::PtrArray<ShopItem::ItemInfo>& list = getCapList(user);
for (s32 i = 0; i < list.size(); i++)
if (!list[i]->isAOC && !isHaveCapByFileId(user, list[i]->name, fileId))
return false;
return true;
}
s32 calcHaveCapNum(GameDataHolderAccessor accessor) {
return accessor->getGameDataFile()->calcHaveCapNum();
}
void buyCap(const al::IUseSceneObjHolder* user, const char* capName) {
const sead::PtrArray<ShopItem::ItemInfo>& list = getCapList(user);
for (s32 i = 0; i < list.size(); i++) {
if (al::isEqualString(capName, list[i]->name)) {
buyItem(user, list[i]);
return;
}
}
}
const sead::PtrArray<ShopItem::ItemInfo>& getGiftList(GameDataHolderAccessor accessor) {
return accessor->getGiftList();
}
const sead::PtrArray<ShopItem::ItemInfo>& rs::getStickerList(GameDataHolderAccessor accessor) {
s32 getGiftListSize(GameDataHolderAccessor accessor) {
return getGiftList(accessor).size();
}
bool isHaveGift(GameDataHolderAccessor accessor, s32 giftIdx) {
return accessor->getGameDataFile()->isBuyItem(getGiftList(accessor)[giftIdx]->name,
accessor->getGameDataFile()->getGiftName());
}
s32 calcHaveGiftNum(GameDataHolderAccessor accessor) {
return accessor->getGameDataFile()->calcHaveGiftNum();
}
bool checkCompleteGift(GameDataHolderAccessor accessor, s32 fileId) {
return accessor->getGameDataFile(fileId)->calcHaveGiftNum() == getGiftListSize(accessor);
}
const sead::PtrArray<ShopItem::ItemInfo>& getStickerList(GameDataHolderAccessor accessor) {
return accessor->getStickerList();
}
s32 getStickerListSize(GameDataHolderAccessor accessor) {
return getStickerList(accessor).size();
}
bool isHaveSticker(GameDataHolderAccessor accessor, s32 stickerIdx) {
return accessor->getGameDataFile()->isBuyItem(getStickerList(accessor)[stickerIdx]->name,
accessor->getGameDataFile()->getStickerName());
}
s32 calcHaveStickerNum(GameDataHolderAccessor accessor) {
return accessor->getGameDataFile()->calcHaveStickerNum();
}
bool checkCompleteSticker(GameDataHolderAccessor accessor, s32 fileId) {
return accessor->getGameDataFile(fileId)->calcHaveStickerNum() == getStickerListSize(accessor);
}
const char* getTestClothesName() {
return "Mario";
}
const char* getTestCapName() {
return "MarioCap";
}
const char* getTestGiftName() {
return "GiftDharma";
}
const char* getTestStickerName() {
return "TestSticker";
}
const char* getTestItemName() {
return "TestItem";
}
const char* getTestShineName() {
return "MoonTutorial";
}
const char* getMsTextName(const ShopItem::ItemType& itemType) {
switch (itemType) {
case ShopItem::ItemType::Cloth:
return "ItemCloth";
case ShopItem::ItemType::Cap:
return "ItemCap";
case ShopItem::ItemType::Gift:
return "ItemGift";
case ShopItem::ItemType::Sticker:
return "ItemSticker";
case ShopItem::ItemType::UseItem:
return "ItemUseItem";
case ShopItem::ItemType::Moon:
return "ItemMoon";
default:
return nullptr;
}
}
const char16* getDisplayName(const al::IUseMessageSystem* user,
const ShopItem::ItemInfo& itemInfo) {
return al::getSystemMessageString(user, getMsTextName(itemInfo.type), itemInfo.name);
}
bool isTypeWear(const ShopItem::ShopItemInfo* itemInfo) {
return itemInfo->info.type == ShopItem::ItemType::Cloth ||
itemInfo->info.type == ShopItem::ItemType::Cap;
}
} // namespace rs

View file

@ -12,7 +12,7 @@ class IUseMessageSystem;
namespace ShopItem {
struct ItemInfo;
enum class ItemType : u32;
enum class ItemType : s32;
struct ShopItemInfo;
} // namespace ShopItem