* Expanded the amount of max items per stack from 99 to 999 * Set Battle Pyramid Bag stack limit back to 99 This commit exists for archival purposes. People who may want to set the limit of item stacks in the Battle Pyramid's bag to 999 can refer to its code diff. * Reintroduced the Battle Pyramid changes through a MAX_PYRAMID_BAG_ITEM_CAPACITY constant * Gave 3 digit support to the Battle Pyramid's bag * Rewrote the comment for MAX_PYRAMID_BAG_ITEM_CAPACITY * Made DebugAction_Give_Item_SelectQuantity use MAX_ITEM_DIGITS * Ditched BERRY_CAPACITY_DIGITS and BAG_ITEM_CAPACITY_DIGITS * Removed MAX_BERRY_CAPACITY No point in keeping it if we're making all item stacks cap at 999. * Applied review corrections * Removed pointless local var in DebugAction_Give_Item_SelectQuantity * Defined a MAX_PYRAMID_ITEM_DIGITS * Cleaned up some of the functions in which MAX_ITEM_DIGITS is used Summary: -Removed pointless local variables in CheckBagHasSpace, AddBagItem, PrintItemQuantity and PrintItemSoldAmount. -Removed pointless brackets in an if statement of CheckBagHasSpace. -Initialized the pocket local variable of CheckBagHasSpace from the get go to save a few lines too. --------- Co-authored-by: Eduardo Quezada D'Ottone <eduardo602002@gmail.com>
1283 lines
39 KiB
C
1283 lines
39 KiB
C
#include "global.h"
|
|
#include "bg.h"
|
|
#include "data.h"
|
|
#include "decompress.h"
|
|
#include "decoration.h"
|
|
#include "decoration_inventory.h"
|
|
#include "event_object_movement.h"
|
|
#include "field_player_avatar.h"
|
|
#include "field_screen_effect.h"
|
|
#include "field_weather.h"
|
|
#include "fieldmap.h"
|
|
#include "gpu_regs.h"
|
|
#include "graphics.h"
|
|
#include "international_string_util.h"
|
|
#include "item.h"
|
|
#include "item_icon.h"
|
|
#include "item_menu.h"
|
|
#include "list_menu.h"
|
|
#include "main.h"
|
|
#include "malloc.h"
|
|
#include "menu.h"
|
|
#include "menu_helpers.h"
|
|
#include "money.h"
|
|
#include "overworld.h"
|
|
#include "palette.h"
|
|
#include "party_menu.h"
|
|
#include "scanline_effect.h"
|
|
#include "script.h"
|
|
#include "shop.h"
|
|
#include "sound.h"
|
|
#include "sprite.h"
|
|
#include "string_util.h"
|
|
#include "strings.h"
|
|
#include "text_window.h"
|
|
#include "tv.h"
|
|
#include "constants/decorations.h"
|
|
#include "constants/items.h"
|
|
#include "constants/metatile_behaviors.h"
|
|
#include "constants/rgb.h"
|
|
#include "constants/songs.h"
|
|
|
|
#define TAG_SCROLL_ARROW 2100
|
|
#define TAG_ITEM_ICON_BASE 2110
|
|
|
|
#define MAX_ITEMS_SHOWN 8
|
|
|
|
enum {
|
|
WIN_BUY_SELL_QUIT,
|
|
WIN_BUY_QUIT,
|
|
};
|
|
|
|
enum {
|
|
WIN_MONEY,
|
|
WIN_ITEM_LIST,
|
|
WIN_ITEM_DESCRIPTION,
|
|
WIN_QUANTITY_IN_BAG,
|
|
WIN_QUANTITY_PRICE,
|
|
WIN_MESSAGE,
|
|
};
|
|
|
|
enum {
|
|
COLORID_NORMAL, // Item descriptions, quantity in bag, and quantity/price
|
|
COLORID_ITEM_LIST, // The text in the item list, and the cursor normally
|
|
COLORID_GRAY_CURSOR, // When the cursor has selected an item to purchase
|
|
};
|
|
|
|
enum {
|
|
MART_TYPE_NORMAL,
|
|
MART_TYPE_DECOR,
|
|
MART_TYPE_DECOR2,
|
|
};
|
|
|
|
// shop view window NPC info enum
|
|
enum
|
|
{
|
|
OBJ_EVENT_ID,
|
|
X_COORD,
|
|
Y_COORD,
|
|
ANIM_NUM,
|
|
LAYER_TYPE
|
|
};
|
|
|
|
struct MartInfo
|
|
{
|
|
void (*callback)(void);
|
|
const struct MenuAction *menuActions;
|
|
const u16 *itemList;
|
|
u16 itemCount;
|
|
u8 windowId;
|
|
u8 martType;
|
|
};
|
|
|
|
struct ShopData
|
|
{
|
|
u16 tilemapBuffers[4][0x400];
|
|
u32 totalCost;
|
|
u16 itemsShowed;
|
|
u16 selectedRow;
|
|
u16 scrollOffset;
|
|
u16 maxQuantity;
|
|
u8 scrollIndicatorsTaskId;
|
|
u8 iconSlot;
|
|
u8 itemSpriteIds[2];
|
|
s16 viewportObjects[OBJECT_EVENTS_COUNT][5];
|
|
};
|
|
|
|
static EWRAM_DATA struct MartInfo sMartInfo = {0};
|
|
static EWRAM_DATA struct ShopData *sShopData = NULL;
|
|
static EWRAM_DATA struct ListMenuItem *sListMenuItems = NULL;
|
|
static EWRAM_DATA u8 (*sItemNames)[ITEM_NAME_LENGTH + 2] = {0};
|
|
static EWRAM_DATA u8 sPurchaseHistoryId = 0;
|
|
EWRAM_DATA struct ItemSlot gMartPurchaseHistory[SMARTSHOPPER_NUM_ITEMS] = {0};
|
|
|
|
static void Task_ShopMenu(u8 taskId);
|
|
static void Task_HandleShopMenuQuit(u8 taskId);
|
|
static void CB2_InitBuyMenu(void);
|
|
static void Task_GoToBuyOrSellMenu(u8 taskId);
|
|
static void MapPostLoadHook_ReturnToShopMenu(void);
|
|
static void Task_ReturnToShopMenu(u8 taskId);
|
|
static void ShowShopMenuAfterExitingBuyOrSellMenu(u8 taskId);
|
|
static void BuyMenuDrawGraphics(void);
|
|
static void BuyMenuAddScrollIndicatorArrows(void);
|
|
static void Task_BuyMenu(u8 taskId);
|
|
static void BuyMenuBuildListMenuTemplate(void);
|
|
static void BuyMenuInitBgs(void);
|
|
static void BuyMenuInitWindows(void);
|
|
static void BuyMenuDecompressBgGraphics(void);
|
|
static void BuyMenuSetListEntry(struct ListMenuItem *, u16, u8 *);
|
|
static void BuyMenuAddItemIcon(u16, u8);
|
|
static void BuyMenuRemoveItemIcon(u16, u8);
|
|
static void BuyMenuPrint(u8 windowId, const u8 *text, u8 x, u8 y, s8 speed, u8 colorSet);
|
|
static void BuyMenuDrawMapGraphics(void);
|
|
static void BuyMenuCopyMenuBgToBg1TilemapBuffer(void);
|
|
static void BuyMenuCollectObjectEventData(void);
|
|
static void BuyMenuDrawObjectEvents(void);
|
|
static void BuyMenuDrawMapBg(void);
|
|
static bool8 BuyMenuCheckForOverlapWithMenuBg(int, int);
|
|
static void BuyMenuDrawMapMetatile(s16, s16, const u16 *, u8);
|
|
static void BuyMenuDrawMapMetatileLayer(u16 *dest, s16 offset1, s16 offset2, const u16 *src);
|
|
static bool8 BuyMenuCheckIfObjectEventOverlapsMenuBg(s16 *);
|
|
static void ExitBuyMenu(u8 taskId);
|
|
static void Task_ExitBuyMenu(u8 taskId);
|
|
static void BuyMenuTryMakePurchase(u8 taskId);
|
|
static void BuyMenuReturnToItemList(u8 taskId);
|
|
static void Task_BuyHowManyDialogueInit(u8 taskId);
|
|
static void BuyMenuConfirmPurchase(u8 taskId);
|
|
static void BuyMenuPrintItemQuantityAndPrice(u8 taskId);
|
|
static void Task_BuyHowManyDialogueHandleInput(u8 taskId);
|
|
static void BuyMenuSubtractMoney(u8 taskId);
|
|
static void RecordItemPurchase(u8 taskId);
|
|
static void Task_ReturnToItemListAfterItemPurchase(u8 taskId);
|
|
static void Task_ReturnToItemListAfterDecorationPurchase(u8 taskId);
|
|
static void Task_HandleShopMenuBuy(u8 taskId);
|
|
static void Task_HandleShopMenuSell(u8 taskId);
|
|
static void BuyMenuPrintItemDescriptionAndShowItemIcon(s32 item, bool8 onInit, struct ListMenu *list);
|
|
static void BuyMenuPrintPriceInList(u8 windowId, u32 itemId, u8 y);
|
|
|
|
static const struct YesNoFuncTable sShopPurchaseYesNoFuncs =
|
|
{
|
|
BuyMenuTryMakePurchase,
|
|
BuyMenuReturnToItemList
|
|
};
|
|
|
|
static const struct MenuAction sShopMenuActions_BuySellQuit[] =
|
|
{
|
|
{ gText_ShopBuy, {.void_u8=Task_HandleShopMenuBuy} },
|
|
{ gText_ShopSell, {.void_u8=Task_HandleShopMenuSell} },
|
|
{ gText_ShopQuit, {.void_u8=Task_HandleShopMenuQuit} }
|
|
};
|
|
|
|
static const struct MenuAction sShopMenuActions_BuyQuit[] =
|
|
{
|
|
{ gText_ShopBuy, {.void_u8=Task_HandleShopMenuBuy} },
|
|
{ gText_ShopQuit, {.void_u8=Task_HandleShopMenuQuit} }
|
|
};
|
|
|
|
static const struct WindowTemplate sShopMenuWindowTemplates[] =
|
|
{
|
|
[WIN_BUY_SELL_QUIT] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 2,
|
|
.tilemapTop = 1,
|
|
.width = 9,
|
|
.height = 6,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x0008,
|
|
},
|
|
// Separate shop menu window for decorations, which can't be sold
|
|
[WIN_BUY_QUIT] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 2,
|
|
.tilemapTop = 1,
|
|
.width = 9,
|
|
.height = 4,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x0008,
|
|
}
|
|
};
|
|
|
|
static const struct ListMenuTemplate sShopBuyMenuListTemplate =
|
|
{
|
|
.items = NULL,
|
|
.moveCursorFunc = BuyMenuPrintItemDescriptionAndShowItemIcon,
|
|
.itemPrintFunc = BuyMenuPrintPriceInList,
|
|
.totalItems = 0,
|
|
.maxShowed = 0,
|
|
.windowId = WIN_ITEM_LIST,
|
|
.header_X = 0,
|
|
.item_X = 8,
|
|
.cursor_X = 0,
|
|
.upText_Y = 1,
|
|
.cursorPal = 2,
|
|
.fillValue = 0,
|
|
.cursorShadowPal = 3,
|
|
.lettersSpacing = 0,
|
|
.itemVerticalPadding = 0,
|
|
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
|
|
.fontId = FONT_NARROW,
|
|
.cursorKind = CURSOR_BLACK_ARROW
|
|
};
|
|
|
|
static const struct BgTemplate sShopBuyMenuBgTemplates[] =
|
|
{
|
|
{
|
|
.bg = 0,
|
|
.charBaseIndex = 2,
|
|
.mapBaseIndex = 31,
|
|
.screenSize = 0,
|
|
.paletteMode = 0,
|
|
.priority = 0,
|
|
.baseTile = 0
|
|
},
|
|
{
|
|
.bg = 1,
|
|
.charBaseIndex = 0,
|
|
.mapBaseIndex = 30,
|
|
.screenSize = 0,
|
|
.paletteMode = 0,
|
|
.priority = 1,
|
|
.baseTile = 0
|
|
},
|
|
{
|
|
.bg = 2,
|
|
.charBaseIndex = 0,
|
|
.mapBaseIndex = 29,
|
|
.screenSize = 0,
|
|
.paletteMode = 0,
|
|
.priority = 2,
|
|
.baseTile = 0
|
|
},
|
|
{
|
|
.bg = 3,
|
|
.charBaseIndex = 0,
|
|
.mapBaseIndex = 28,
|
|
.screenSize = 0,
|
|
.paletteMode = 0,
|
|
.priority = 3,
|
|
.baseTile = 0
|
|
}
|
|
};
|
|
|
|
static const struct WindowTemplate sShopBuyMenuWindowTemplates[] =
|
|
{
|
|
[WIN_MONEY] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 1,
|
|
.tilemapTop = 1,
|
|
.width = 10,
|
|
.height = 2,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x001E,
|
|
},
|
|
[WIN_ITEM_LIST] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 14,
|
|
.tilemapTop = 2,
|
|
.width = 15,
|
|
.height = 16,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x0032,
|
|
},
|
|
[WIN_ITEM_DESCRIPTION] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 0,
|
|
.tilemapTop = 13,
|
|
.width = 14,
|
|
.height = 6,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x0122,
|
|
},
|
|
[WIN_QUANTITY_IN_BAG] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 1,
|
|
.tilemapTop = 11,
|
|
.width = 12,
|
|
.height = 2,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x0176,
|
|
},
|
|
[WIN_QUANTITY_PRICE] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 18,
|
|
.tilemapTop = 11,
|
|
.width = 10,
|
|
.height = 2,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x018E,
|
|
},
|
|
[WIN_MESSAGE] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 2,
|
|
.tilemapTop = 15,
|
|
.width = 27,
|
|
.height = 4,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x01A2,
|
|
},
|
|
DUMMY_WIN_TEMPLATE
|
|
};
|
|
|
|
static const struct WindowTemplate sShopBuyMenuYesNoWindowTemplates =
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 21,
|
|
.tilemapTop = 9,
|
|
.width = 5,
|
|
.height = 4,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x020E,
|
|
};
|
|
|
|
static const u8 sShopBuyMenuTextColors[][3] =
|
|
{
|
|
[COLORID_NORMAL] = {1, 2, 3},
|
|
[COLORID_ITEM_LIST] = {0, 2, 3},
|
|
[COLORID_GRAY_CURSOR] = {0, 3, 2},
|
|
};
|
|
|
|
static u8 CreateShopMenu(u8 martType)
|
|
{
|
|
int numMenuItems;
|
|
|
|
LockPlayerFieldControls();
|
|
sMartInfo.martType = martType;
|
|
|
|
if (martType == MART_TYPE_NORMAL)
|
|
{
|
|
struct WindowTemplate winTemplate = sShopMenuWindowTemplates[WIN_BUY_SELL_QUIT];
|
|
winTemplate.width = GetMaxWidthInMenuTable(sShopMenuActions_BuySellQuit, ARRAY_COUNT(sShopMenuActions_BuySellQuit));
|
|
sMartInfo.windowId = AddWindow(&winTemplate);
|
|
sMartInfo.menuActions = sShopMenuActions_BuySellQuit;
|
|
numMenuItems = ARRAY_COUNT(sShopMenuActions_BuySellQuit);
|
|
}
|
|
else
|
|
{
|
|
struct WindowTemplate winTemplate = sShopMenuWindowTemplates[WIN_BUY_QUIT];
|
|
winTemplate.width = GetMaxWidthInMenuTable(sShopMenuActions_BuyQuit, ARRAY_COUNT(sShopMenuActions_BuyQuit));
|
|
sMartInfo.windowId = AddWindow(&winTemplate);
|
|
sMartInfo.menuActions = sShopMenuActions_BuyQuit;
|
|
numMenuItems = ARRAY_COUNT(sShopMenuActions_BuyQuit);
|
|
}
|
|
|
|
SetStandardWindowBorderStyle(sMartInfo.windowId, FALSE);
|
|
PrintMenuTable(sMartInfo.windowId, numMenuItems, sMartInfo.menuActions);
|
|
InitMenuInUpperLeftCornerNormal(sMartInfo.windowId, numMenuItems, 0);
|
|
PutWindowTilemap(sMartInfo.windowId);
|
|
CopyWindowToVram(sMartInfo.windowId, COPYWIN_MAP);
|
|
|
|
return CreateTask(Task_ShopMenu, 8);
|
|
}
|
|
|
|
static void SetShopMenuCallback(void (* callback)(void))
|
|
{
|
|
sMartInfo.callback = callback;
|
|
}
|
|
|
|
static void SetShopItemsForSale(const u16 *items)
|
|
{
|
|
u16 i = 0;
|
|
|
|
sMartInfo.itemList = items;
|
|
sMartInfo.itemCount = 0;
|
|
|
|
// Read items until ITEM_NONE / DECOR_NONE is reached
|
|
while (sMartInfo.itemList[i])
|
|
{
|
|
sMartInfo.itemCount++;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
static void Task_ShopMenu(u8 taskId)
|
|
{
|
|
s8 inputCode = Menu_ProcessInputNoWrap();
|
|
switch (inputCode)
|
|
{
|
|
case MENU_NOTHING_CHOSEN:
|
|
break;
|
|
case MENU_B_PRESSED:
|
|
PlaySE(SE_SELECT);
|
|
Task_HandleShopMenuQuit(taskId);
|
|
break;
|
|
default:
|
|
sMartInfo.menuActions[inputCode].func.void_u8(taskId);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#define tItemCount data[1]
|
|
#define tItemId data[5]
|
|
#define tListTaskId data[7]
|
|
#define tCallbackHi data[8]
|
|
#define tCallbackLo data[9]
|
|
|
|
static void Task_HandleShopMenuBuy(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
tCallbackHi = (u32)CB2_InitBuyMenu >> 16;
|
|
tCallbackLo = (u32)CB2_InitBuyMenu;
|
|
gTasks[taskId].func = Task_GoToBuyOrSellMenu;
|
|
FadeScreen(FADE_TO_BLACK, 0);
|
|
}
|
|
|
|
static void Task_HandleShopMenuSell(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
tCallbackHi = (u32)CB2_GoToSellMenu >> 16;
|
|
tCallbackLo = (u32)CB2_GoToSellMenu;
|
|
gTasks[taskId].func = Task_GoToBuyOrSellMenu;
|
|
FadeScreen(FADE_TO_BLACK, 0);
|
|
}
|
|
|
|
void CB2_ExitSellMenu(void)
|
|
{
|
|
gFieldCallback = MapPostLoadHook_ReturnToShopMenu;
|
|
SetMainCallback2(CB2_ReturnToField);
|
|
}
|
|
|
|
static void Task_HandleShopMenuQuit(u8 taskId)
|
|
{
|
|
ClearStdWindowAndFrameToTransparent(sMartInfo.windowId, 2); // Incorrect use, making it not copy it to vram.
|
|
RemoveWindow(sMartInfo.windowId);
|
|
TryPutSmartShopperOnAir();
|
|
UnlockPlayerFieldControls();
|
|
DestroyTask(taskId);
|
|
|
|
if (sMartInfo.callback)
|
|
sMartInfo.callback();
|
|
}
|
|
|
|
static void Task_GoToBuyOrSellMenu(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
if (!gPaletteFade.active)
|
|
{
|
|
DestroyTask(taskId);
|
|
SetMainCallback2((void *)((u16)tCallbackHi << 16 | (u16)tCallbackLo));
|
|
}
|
|
}
|
|
|
|
static void MapPostLoadHook_ReturnToShopMenu(void)
|
|
{
|
|
FadeInFromBlack();
|
|
CreateTask(Task_ReturnToShopMenu, 8);
|
|
}
|
|
|
|
static void Task_ReturnToShopMenu(u8 taskId)
|
|
{
|
|
if (IsWeatherNotFadingIn() == TRUE)
|
|
{
|
|
if (sMartInfo.martType == MART_TYPE_DECOR2)
|
|
DisplayItemMessageOnField(taskId, gText_CanIHelpWithAnythingElse, ShowShopMenuAfterExitingBuyOrSellMenu);
|
|
else
|
|
DisplayItemMessageOnField(taskId, gText_AnythingElseICanHelp, ShowShopMenuAfterExitingBuyOrSellMenu);
|
|
}
|
|
}
|
|
|
|
static void ShowShopMenuAfterExitingBuyOrSellMenu(u8 taskId)
|
|
{
|
|
CreateShopMenu(sMartInfo.martType);
|
|
DestroyTask(taskId);
|
|
}
|
|
|
|
static void CB2_BuyMenu(void)
|
|
{
|
|
RunTasks();
|
|
AnimateSprites();
|
|
BuildOamBuffer();
|
|
DoScheduledBgTilemapCopiesToVram();
|
|
UpdatePaletteFade();
|
|
}
|
|
|
|
static void VBlankCB_BuyMenu(void)
|
|
{
|
|
LoadOam();
|
|
ProcessSpriteCopyRequests();
|
|
TransferPlttBuffer();
|
|
}
|
|
|
|
static void CB2_InitBuyMenu(void)
|
|
{
|
|
u8 taskId;
|
|
|
|
switch (gMain.state)
|
|
{
|
|
case 0:
|
|
SetVBlankHBlankCallbacksToNull();
|
|
CpuFastFill(0, (void *)OAM, OAM_SIZE);
|
|
ScanlineEffect_Stop();
|
|
ResetTempTileDataBuffers();
|
|
FreeAllSpritePalettes();
|
|
ResetPaletteFade();
|
|
ResetSpriteData();
|
|
ResetTasks();
|
|
ClearScheduledBgCopiesToVram();
|
|
sShopData = AllocZeroed(sizeof(struct ShopData));
|
|
sShopData->scrollIndicatorsTaskId = TASK_NONE;
|
|
sShopData->itemSpriteIds[0] = SPRITE_NONE;
|
|
sShopData->itemSpriteIds[1] = SPRITE_NONE;
|
|
BuyMenuBuildListMenuTemplate();
|
|
BuyMenuInitBgs();
|
|
FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x20, 0x20);
|
|
FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 0x20, 0x20);
|
|
FillBgTilemapBufferRect_Palette0(2, 0, 0, 0, 0x20, 0x20);
|
|
FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 0x20, 0x20);
|
|
BuyMenuInitWindows();
|
|
BuyMenuDecompressBgGraphics();
|
|
gMain.state++;
|
|
break;
|
|
case 1:
|
|
if (!FreeTempTileDataBuffersIfPossible())
|
|
gMain.state++;
|
|
break;
|
|
default:
|
|
BuyMenuDrawGraphics();
|
|
BuyMenuAddScrollIndicatorArrows();
|
|
taskId = CreateTask(Task_BuyMenu, 8);
|
|
gTasks[taskId].tListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, 0, 0);
|
|
BlendPalettes(PALETTES_ALL, 16, RGB_BLACK);
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
|
SetVBlankCallback(VBlankCB_BuyMenu);
|
|
SetMainCallback2(CB2_BuyMenu);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void BuyMenuFreeMemory(void)
|
|
{
|
|
Free(sShopData);
|
|
Free(sListMenuItems);
|
|
Free(sItemNames);
|
|
FreeAllWindowBuffers();
|
|
}
|
|
|
|
static void BuyMenuBuildListMenuTemplate(void)
|
|
{
|
|
u16 i;
|
|
|
|
sListMenuItems = Alloc((sMartInfo.itemCount + 1) * sizeof(*sListMenuItems));
|
|
sItemNames = Alloc((sMartInfo.itemCount + 1) * sizeof(*sItemNames));
|
|
for (i = 0; i < sMartInfo.itemCount; i++)
|
|
BuyMenuSetListEntry(&sListMenuItems[i], sMartInfo.itemList[i], sItemNames[i]);
|
|
|
|
StringCopy(sItemNames[i], gText_Cancel2);
|
|
sListMenuItems[i].name = sItemNames[i];
|
|
sListMenuItems[i].id = LIST_CANCEL;
|
|
|
|
gMultiuseListMenuTemplate = sShopBuyMenuListTemplate;
|
|
gMultiuseListMenuTemplate.items = sListMenuItems;
|
|
gMultiuseListMenuTemplate.totalItems = sMartInfo.itemCount + 1;
|
|
if (gMultiuseListMenuTemplate.totalItems > MAX_ITEMS_SHOWN)
|
|
gMultiuseListMenuTemplate.maxShowed = MAX_ITEMS_SHOWN;
|
|
else
|
|
gMultiuseListMenuTemplate.maxShowed = gMultiuseListMenuTemplate.totalItems;
|
|
|
|
sShopData->itemsShowed = gMultiuseListMenuTemplate.maxShowed;
|
|
}
|
|
|
|
static void BuyMenuSetListEntry(struct ListMenuItem *menuItem, u16 item, u8 *name)
|
|
{
|
|
if (sMartInfo.martType == MART_TYPE_NORMAL)
|
|
CopyItemName(item, name);
|
|
else
|
|
StringCopy(name, gDecorations[item].name);
|
|
|
|
menuItem->name = name;
|
|
menuItem->id = item;
|
|
}
|
|
|
|
static void BuyMenuPrintItemDescriptionAndShowItemIcon(s32 item, bool8 onInit, struct ListMenu *list)
|
|
{
|
|
const u8 *description;
|
|
if (onInit != TRUE)
|
|
PlaySE(SE_SELECT);
|
|
|
|
if (item != LIST_CANCEL)
|
|
BuyMenuAddItemIcon(item, sShopData->iconSlot);
|
|
else
|
|
BuyMenuAddItemIcon(ITEM_LIST_END, sShopData->iconSlot);
|
|
|
|
BuyMenuRemoveItemIcon(item, sShopData->iconSlot ^ 1);
|
|
sShopData->iconSlot ^= 1;
|
|
if (item != LIST_CANCEL)
|
|
{
|
|
if (sMartInfo.martType == MART_TYPE_NORMAL)
|
|
description = ItemId_GetDescription(item);
|
|
else
|
|
description = gDecorations[item].description;
|
|
}
|
|
else
|
|
{
|
|
description = gText_QuitShopping;
|
|
}
|
|
|
|
FillWindowPixelBuffer(WIN_ITEM_DESCRIPTION, PIXEL_FILL(0));
|
|
BuyMenuPrint(WIN_ITEM_DESCRIPTION, description, 3, 1, 0, COLORID_NORMAL);
|
|
}
|
|
|
|
static void BuyMenuPrintPriceInList(u8 windowId, u32 itemId, u8 y)
|
|
{
|
|
u8 x;
|
|
|
|
if (itemId != LIST_CANCEL)
|
|
{
|
|
if (sMartInfo.martType == MART_TYPE_NORMAL)
|
|
{
|
|
ConvertIntToDecimalStringN(
|
|
gStringVar1,
|
|
ItemId_GetPrice(itemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT),
|
|
STR_CONV_MODE_LEFT_ALIGN,
|
|
5);
|
|
}
|
|
else
|
|
{
|
|
ConvertIntToDecimalStringN(
|
|
gStringVar1,
|
|
gDecorations[itemId].price,
|
|
STR_CONV_MODE_LEFT_ALIGN,
|
|
5);
|
|
}
|
|
|
|
if (ItemId_GetImportance(itemId) && (CheckBagHasItem(itemId, 1) || CheckPCHasItem(itemId, 1)))
|
|
StringCopy(gStringVar4, gText_SoldOut);
|
|
else
|
|
StringExpandPlaceholders(gStringVar4, gText_PokedollarVar1);
|
|
x = GetStringRightAlignXOffset(FONT_NARROW, gStringVar4, 120);
|
|
AddTextPrinterParameterized4(windowId, FONT_NARROW, x, y, 0, 0, sShopBuyMenuTextColors[COLORID_ITEM_LIST], TEXT_SKIP_DRAW, gStringVar4);
|
|
}
|
|
}
|
|
|
|
static void BuyMenuAddScrollIndicatorArrows(void)
|
|
{
|
|
if (sShopData->scrollIndicatorsTaskId == TASK_NONE && sMartInfo.itemCount + 1 > MAX_ITEMS_SHOWN)
|
|
{
|
|
sShopData->scrollIndicatorsTaskId = AddScrollIndicatorArrowPairParameterized(
|
|
SCROLL_ARROW_UP,
|
|
172,
|
|
12,
|
|
148,
|
|
sMartInfo.itemCount - (MAX_ITEMS_SHOWN - 1),
|
|
TAG_SCROLL_ARROW,
|
|
TAG_SCROLL_ARROW,
|
|
&sShopData->scrollOffset);
|
|
}
|
|
}
|
|
|
|
static void BuyMenuRemoveScrollIndicatorArrows(void)
|
|
{
|
|
if (sShopData->scrollIndicatorsTaskId != TASK_NONE)
|
|
{
|
|
RemoveScrollIndicatorArrowPair(sShopData->scrollIndicatorsTaskId);
|
|
sShopData->scrollIndicatorsTaskId = TASK_NONE;
|
|
}
|
|
}
|
|
|
|
static void BuyMenuPrintCursor(u8 scrollIndicatorsTaskId, u8 colorSet)
|
|
{
|
|
u8 y = ListMenuGetYCoordForPrintingArrowCursor(scrollIndicatorsTaskId);
|
|
BuyMenuPrint(WIN_ITEM_LIST, gText_SelectorArrow2, 0, y, 0, colorSet);
|
|
}
|
|
|
|
static void BuyMenuAddItemIcon(u16 item, u8 iconSlot)
|
|
{
|
|
u8 spriteId;
|
|
u8 *spriteIdPtr = &sShopData->itemSpriteIds[iconSlot];
|
|
if (*spriteIdPtr != SPRITE_NONE)
|
|
return;
|
|
|
|
if (sMartInfo.martType == MART_TYPE_NORMAL || item == ITEM_LIST_END)
|
|
{
|
|
spriteId = AddItemIconSprite(iconSlot + TAG_ITEM_ICON_BASE, iconSlot + TAG_ITEM_ICON_BASE, item);
|
|
if (spriteId != MAX_SPRITES)
|
|
{
|
|
*spriteIdPtr = spriteId;
|
|
gSprites[spriteId].x2 = 24;
|
|
gSprites[spriteId].y2 = 88;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
spriteId = AddDecorationIconObject(item, 20, 84, 1, iconSlot + TAG_ITEM_ICON_BASE, iconSlot + TAG_ITEM_ICON_BASE);
|
|
if (spriteId != MAX_SPRITES)
|
|
*spriteIdPtr = spriteId;
|
|
}
|
|
}
|
|
|
|
static void BuyMenuRemoveItemIcon(u16 item, u8 iconSlot)
|
|
{
|
|
u8 *spriteIdPtr = &sShopData->itemSpriteIds[iconSlot];
|
|
if (*spriteIdPtr == SPRITE_NONE)
|
|
return;
|
|
|
|
FreeSpriteTilesByTag(iconSlot + TAG_ITEM_ICON_BASE);
|
|
FreeSpritePaletteByTag(iconSlot + TAG_ITEM_ICON_BASE);
|
|
DestroySprite(&gSprites[*spriteIdPtr]);
|
|
*spriteIdPtr = SPRITE_NONE;
|
|
}
|
|
|
|
static void BuyMenuInitBgs(void)
|
|
{
|
|
ResetBgsAndClearDma3BusyFlags(0);
|
|
InitBgsFromTemplates(0, sShopBuyMenuBgTemplates, ARRAY_COUNT(sShopBuyMenuBgTemplates));
|
|
SetBgTilemapBuffer(1, sShopData->tilemapBuffers[1]);
|
|
SetBgTilemapBuffer(2, sShopData->tilemapBuffers[3]);
|
|
SetBgTilemapBuffer(3, sShopData->tilemapBuffers[2]);
|
|
SetGpuReg(REG_OFFSET_BG0HOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG0VOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG1HOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG1VOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG2HOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG2VOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG3HOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG3VOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
|
|
ShowBg(0);
|
|
ShowBg(1);
|
|
ShowBg(2);
|
|
ShowBg(3);
|
|
}
|
|
|
|
static void BuyMenuDecompressBgGraphics(void)
|
|
{
|
|
DecompressAndCopyTileDataToVram(1, gShopMenu_Gfx, 0x3A0, 0x3E3, 0);
|
|
LZDecompressWram(gShopMenu_Tilemap, sShopData->tilemapBuffers[0]);
|
|
LoadCompressedPalette(gShopMenu_Pal, BG_PLTT_ID(12), PLTT_SIZE_4BPP);
|
|
}
|
|
|
|
static void BuyMenuInitWindows(void)
|
|
{
|
|
InitWindows(sShopBuyMenuWindowTemplates);
|
|
DeactivateAllTextPrinters();
|
|
LoadUserWindowBorderGfx(WIN_MONEY, 1, BG_PLTT_ID(13));
|
|
LoadMessageBoxGfx(WIN_MONEY, 0xA, BG_PLTT_ID(14));
|
|
PutWindowTilemap(WIN_MONEY);
|
|
PutWindowTilemap(WIN_ITEM_LIST);
|
|
PutWindowTilemap(WIN_ITEM_DESCRIPTION);
|
|
}
|
|
|
|
static void BuyMenuPrint(u8 windowId, const u8 *text, u8 x, u8 y, s8 speed, u8 colorSet)
|
|
{
|
|
AddTextPrinterParameterized4(windowId, FONT_NORMAL, x, y, 0, 0, sShopBuyMenuTextColors[colorSet], speed, text);
|
|
}
|
|
|
|
static void BuyMenuDisplayMessage(u8 taskId, const u8 *text, TaskFunc callback)
|
|
{
|
|
DisplayMessageAndContinueTask(taskId, WIN_MESSAGE, 10, 14, FONT_NORMAL, GetPlayerTextSpeedDelay(), text, callback);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
}
|
|
|
|
static void BuyMenuDrawGraphics(void)
|
|
{
|
|
BuyMenuDrawMapGraphics();
|
|
BuyMenuCopyMenuBgToBg1TilemapBuffer();
|
|
AddMoneyLabelObject(19, 11);
|
|
PrintMoneyAmountInMoneyBoxWithBorder(WIN_MONEY, 1, 13, GetMoney(&gSaveBlock1Ptr->money));
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
ScheduleBgCopyTilemapToVram(2);
|
|
ScheduleBgCopyTilemapToVram(3);
|
|
}
|
|
|
|
static void BuyMenuDrawMapGraphics(void)
|
|
{
|
|
BuyMenuCollectObjectEventData();
|
|
BuyMenuDrawObjectEvents();
|
|
BuyMenuDrawMapBg();
|
|
}
|
|
|
|
static void BuyMenuDrawMapBg(void)
|
|
{
|
|
s16 i, j;
|
|
s16 x, y;
|
|
const struct MapLayout *mapLayout;
|
|
u16 metatile;
|
|
u8 metatileLayerType;
|
|
|
|
mapLayout = gMapHeader.mapLayout;
|
|
GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
|
|
x -= 4;
|
|
y -= 4;
|
|
|
|
for (j = 0; j < 10; j++)
|
|
{
|
|
for (i = 0; i < 15; i++)
|
|
{
|
|
metatile = MapGridGetMetatileIdAt(x + i, y + j);
|
|
if (BuyMenuCheckForOverlapWithMenuBg(i, j) == TRUE)
|
|
metatileLayerType = MapGridGetMetatileLayerTypeAt(x + i, y + j);
|
|
else
|
|
metatileLayerType = METATILE_LAYER_TYPE_COVERED;
|
|
|
|
if (metatile < NUM_METATILES_IN_PRIMARY)
|
|
BuyMenuDrawMapMetatile(i, j, mapLayout->primaryTileset->metatiles + metatile * NUM_TILES_PER_METATILE, metatileLayerType);
|
|
else
|
|
BuyMenuDrawMapMetatile(i, j, mapLayout->secondaryTileset->metatiles + ((metatile - NUM_METATILES_IN_PRIMARY) * NUM_TILES_PER_METATILE), metatileLayerType);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void BuyMenuDrawMapMetatile(s16 x, s16 y, const u16 *src, u8 metatileLayerType)
|
|
{
|
|
u16 offset1 = x * 2;
|
|
u16 offset2 = y * 64;
|
|
|
|
switch (metatileLayerType)
|
|
{
|
|
case METATILE_LAYER_TYPE_NORMAL:
|
|
BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[3], offset1, offset2, src);
|
|
BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[1], offset1, offset2, src + 4);
|
|
break;
|
|
case METATILE_LAYER_TYPE_COVERED:
|
|
BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[2], offset1, offset2, src);
|
|
BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[3], offset1, offset2, src + 4);
|
|
break;
|
|
case METATILE_LAYER_TYPE_SPLIT:
|
|
BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[2], offset1, offset2, src);
|
|
BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[1], offset1, offset2, src + 4);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void BuyMenuDrawMapMetatileLayer(u16 *dest, s16 offset1, s16 offset2, const u16 *src)
|
|
{
|
|
// This function draws a whole 2x2 metatile.
|
|
dest[offset1 + offset2] = src[0]; // top left
|
|
dest[offset1 + offset2 + 1] = src[1]; // top right
|
|
dest[offset1 + offset2 + 32] = src[2]; // bottom left
|
|
dest[offset1 + offset2 + 33] = src[3]; // bottom right
|
|
}
|
|
|
|
static void BuyMenuCollectObjectEventData(void)
|
|
{
|
|
s16 facingX;
|
|
s16 facingY;
|
|
u8 y;
|
|
u8 x;
|
|
u8 numObjects = 0;
|
|
|
|
GetXYCoordsOneStepInFrontOfPlayer(&facingX, &facingY);
|
|
|
|
for (y = 0; y < OBJECT_EVENTS_COUNT; y++)
|
|
sShopData->viewportObjects[y][OBJ_EVENT_ID] = OBJECT_EVENTS_COUNT;
|
|
|
|
for (y = 0; y < 5; y++)
|
|
{
|
|
for (x = 0; x < 7; x++)
|
|
{
|
|
u8 objEventId = GetObjectEventIdByXY(facingX - 4 + x, facingY - 2 + y);
|
|
|
|
if (objEventId != OBJECT_EVENTS_COUNT)
|
|
{
|
|
sShopData->viewportObjects[numObjects][OBJ_EVENT_ID] = objEventId;
|
|
sShopData->viewportObjects[numObjects][X_COORD] = x;
|
|
sShopData->viewportObjects[numObjects][Y_COORD] = y;
|
|
sShopData->viewportObjects[numObjects][LAYER_TYPE] = MapGridGetMetatileLayerTypeAt(facingX - 4 + x, facingY - 2 + y);
|
|
|
|
switch (gObjectEvents[objEventId].facingDirection)
|
|
{
|
|
case DIR_SOUTH:
|
|
sShopData->viewportObjects[numObjects][ANIM_NUM] = ANIM_STD_FACE_SOUTH;
|
|
break;
|
|
case DIR_NORTH:
|
|
sShopData->viewportObjects[numObjects][ANIM_NUM] = ANIM_STD_FACE_NORTH;
|
|
break;
|
|
case DIR_WEST:
|
|
sShopData->viewportObjects[numObjects][ANIM_NUM] = ANIM_STD_FACE_WEST;
|
|
break;
|
|
case DIR_EAST:
|
|
default:
|
|
sShopData->viewportObjects[numObjects][ANIM_NUM] = ANIM_STD_FACE_EAST;
|
|
break;
|
|
}
|
|
numObjects++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void BuyMenuDrawObjectEvents(void)
|
|
{
|
|
u8 i;
|
|
u8 spriteId;
|
|
const struct ObjectEventGraphicsInfo *graphicsInfo;
|
|
|
|
for (i = 0; i < OBJECT_EVENTS_COUNT; i++)
|
|
{
|
|
if (sShopData->viewportObjects[i][OBJ_EVENT_ID] == OBJECT_EVENTS_COUNT)
|
|
continue;
|
|
|
|
graphicsInfo = GetObjectEventGraphicsInfo(gObjectEvents[sShopData->viewportObjects[i][OBJ_EVENT_ID]].graphicsId);
|
|
|
|
spriteId = CreateObjectGraphicsSprite(
|
|
gObjectEvents[sShopData->viewportObjects[i][OBJ_EVENT_ID]].graphicsId,
|
|
SpriteCallbackDummy,
|
|
(u16)sShopData->viewportObjects[i][X_COORD] * 16 + 8,
|
|
(u16)sShopData->viewportObjects[i][Y_COORD] * 16 + 48 - graphicsInfo->height / 2,
|
|
2);
|
|
|
|
if (BuyMenuCheckIfObjectEventOverlapsMenuBg(sShopData->viewportObjects[i]) == TRUE)
|
|
{
|
|
gSprites[spriteId].subspriteTableNum = 4;
|
|
gSprites[spriteId].subspriteMode = SUBSPRITES_ON;
|
|
}
|
|
|
|
StartSpriteAnim(&gSprites[spriteId], sShopData->viewportObjects[i][ANIM_NUM]);
|
|
}
|
|
}
|
|
|
|
static bool8 BuyMenuCheckIfObjectEventOverlapsMenuBg(s16 *object)
|
|
{
|
|
if (!BuyMenuCheckForOverlapWithMenuBg(object[X_COORD], object[Y_COORD] + 2) && object[LAYER_TYPE] != METATILE_LAYER_TYPE_COVERED)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
static void BuyMenuCopyMenuBgToBg1TilemapBuffer(void)
|
|
{
|
|
s16 i;
|
|
u16 *dest = sShopData->tilemapBuffers[1];
|
|
const u16 *src = sShopData->tilemapBuffers[0];
|
|
|
|
for (i = 0; i < 1024; i++)
|
|
{
|
|
if (src[i] != 0)
|
|
dest[i] = src[i] + 0xC3E3;
|
|
}
|
|
}
|
|
|
|
static bool8 BuyMenuCheckForOverlapWithMenuBg(int x, int y)
|
|
{
|
|
const u16 *metatile = sShopData->tilemapBuffers[0];
|
|
int offset1 = x * 2;
|
|
int offset2 = y * 64;
|
|
|
|
if (metatile[offset2 + offset1] == 0 &&
|
|
metatile[offset2 + offset1 + 32] == 0 &&
|
|
metatile[offset2 + offset1 + 1] == 0 &&
|
|
metatile[offset2 + offset1 + 33] == 0)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void Task_BuyMenu(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
if (!gPaletteFade.active)
|
|
{
|
|
s32 itemId = ListMenu_ProcessInput(tListTaskId);
|
|
ListMenuGetScrollAndRow(tListTaskId, &sShopData->scrollOffset, &sShopData->selectedRow);
|
|
|
|
switch (itemId)
|
|
{
|
|
case LIST_NOTHING_CHOSEN:
|
|
break;
|
|
case LIST_CANCEL:
|
|
PlaySE(SE_SELECT);
|
|
ExitBuyMenu(taskId);
|
|
break;
|
|
default:
|
|
PlaySE(SE_SELECT);
|
|
tItemId = itemId;
|
|
ClearWindowTilemap(WIN_ITEM_DESCRIPTION);
|
|
BuyMenuRemoveScrollIndicatorArrows();
|
|
BuyMenuPrintCursor(tListTaskId, COLORID_GRAY_CURSOR);
|
|
|
|
if (sMartInfo.martType == MART_TYPE_NORMAL)
|
|
sShopData->totalCost = (ItemId_GetPrice(itemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT));
|
|
else
|
|
sShopData->totalCost = gDecorations[itemId].price;
|
|
|
|
if (ItemId_GetImportance(itemId) && (CheckBagHasItem(itemId, 1) || CheckPCHasItem(itemId, 1)))
|
|
BuyMenuDisplayMessage(taskId, gText_ThatItemIsSoldOut, BuyMenuReturnToItemList);
|
|
else if (!IsEnoughMoney(&gSaveBlock1Ptr->money, sShopData->totalCost))
|
|
{
|
|
BuyMenuDisplayMessage(taskId, gText_YouDontHaveMoney, BuyMenuReturnToItemList);
|
|
}
|
|
else
|
|
{
|
|
if (sMartInfo.martType == MART_TYPE_NORMAL)
|
|
{
|
|
CopyItemName(itemId, gStringVar1);
|
|
if (ItemId_GetImportance(itemId))
|
|
{
|
|
ConvertIntToDecimalStringN(gStringVar2, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6);
|
|
StringExpandPlaceholders(gStringVar4, gText_YouWantedVar1ThatllBeVar2);
|
|
tItemCount = 1;
|
|
sShopData->totalCost = (ItemId_GetPrice(tItemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT)) * tItemCount;
|
|
BuyMenuDisplayMessage(taskId, gStringVar4, BuyMenuConfirmPurchase);
|
|
}
|
|
else if (ItemId_GetPocket(itemId) == POCKET_TM_HM)
|
|
{
|
|
StringCopy(gStringVar2, gMoveNames[ItemIdToBattleMoveId(itemId)]);
|
|
BuyMenuDisplayMessage(taskId, gText_Var1CertainlyHowMany2, Task_BuyHowManyDialogueInit);
|
|
}
|
|
else
|
|
{
|
|
BuyMenuDisplayMessage(taskId, gText_Var1CertainlyHowMany, Task_BuyHowManyDialogueInit);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StringCopy(gStringVar1, gDecorations[itemId].name);
|
|
ConvertIntToDecimalStringN(gStringVar2, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6);
|
|
|
|
if (sMartInfo.martType == MART_TYPE_DECOR)
|
|
StringExpandPlaceholders(gStringVar4, gText_Var1IsItThatllBeVar2);
|
|
else // MART_TYPE_DECOR2
|
|
StringExpandPlaceholders(gStringVar4, gText_YouWantedVar1ThatllBeVar2);
|
|
|
|
BuyMenuDisplayMessage(taskId, gStringVar4, BuyMenuConfirmPurchase);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void Task_BuyHowManyDialogueInit(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
u16 quantityInBag = CountTotalItemQuantityInBag(tItemId);
|
|
u16 maxQuantity;
|
|
|
|
DrawStdFrameWithCustomTileAndPalette(WIN_QUANTITY_IN_BAG, FALSE, 1, 13);
|
|
ConvertIntToDecimalStringN(gStringVar1, quantityInBag, STR_CONV_MODE_RIGHT_ALIGN, MAX_ITEM_DIGITS + 1);
|
|
StringExpandPlaceholders(gStringVar4, gText_InBagVar1);
|
|
BuyMenuPrint(WIN_QUANTITY_IN_BAG, gStringVar4, 0, 1, 0, COLORID_NORMAL);
|
|
tItemCount = 1;
|
|
DrawStdFrameWithCustomTileAndPalette(WIN_QUANTITY_PRICE, FALSE, 1, 13);
|
|
BuyMenuPrintItemQuantityAndPrice(taskId);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
|
|
maxQuantity = GetMoney(&gSaveBlock1Ptr->money) / sShopData->totalCost;
|
|
|
|
if (maxQuantity > MAX_BAG_ITEM_CAPACITY)
|
|
sShopData->maxQuantity = MAX_BAG_ITEM_CAPACITY;
|
|
else
|
|
sShopData->maxQuantity = maxQuantity;
|
|
|
|
gTasks[taskId].func = Task_BuyHowManyDialogueHandleInput;
|
|
}
|
|
|
|
static void Task_BuyHowManyDialogueHandleInput(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
if (AdjustQuantityAccordingToDPadInput(&tItemCount, sShopData->maxQuantity) == TRUE)
|
|
{
|
|
sShopData->totalCost = (ItemId_GetPrice(tItemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT)) * tItemCount;
|
|
BuyMenuPrintItemQuantityAndPrice(taskId);
|
|
}
|
|
else
|
|
{
|
|
if (JOY_NEW(A_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
ClearStdWindowAndFrameToTransparent(WIN_QUANTITY_PRICE, FALSE);
|
|
ClearStdWindowAndFrameToTransparent(WIN_QUANTITY_IN_BAG, FALSE);
|
|
ClearWindowTilemap(WIN_QUANTITY_PRICE);
|
|
ClearWindowTilemap(WIN_QUANTITY_IN_BAG);
|
|
PutWindowTilemap(WIN_ITEM_LIST);
|
|
CopyItemName(tItemId, gStringVar1);
|
|
ConvertIntToDecimalStringN(gStringVar2, tItemCount, STR_CONV_MODE_LEFT_ALIGN, MAX_ITEM_DIGITS);
|
|
ConvertIntToDecimalStringN(gStringVar3, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6);
|
|
BuyMenuDisplayMessage(taskId, gText_Var1AndYouWantedVar2, BuyMenuConfirmPurchase);
|
|
}
|
|
else if (JOY_NEW(B_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
ClearStdWindowAndFrameToTransparent(WIN_QUANTITY_PRICE, FALSE);
|
|
ClearStdWindowAndFrameToTransparent(WIN_QUANTITY_IN_BAG, FALSE);
|
|
ClearWindowTilemap(WIN_QUANTITY_PRICE);
|
|
ClearWindowTilemap(WIN_QUANTITY_IN_BAG);
|
|
BuyMenuReturnToItemList(taskId);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void BuyMenuConfirmPurchase(u8 taskId)
|
|
{
|
|
CreateYesNoMenuWithCallbacks(taskId, &sShopBuyMenuYesNoWindowTemplates, 1, 0, 0, 1, 13, &sShopPurchaseYesNoFuncs);
|
|
}
|
|
|
|
static void BuyMenuTryMakePurchase(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
PutWindowTilemap(WIN_ITEM_LIST);
|
|
|
|
if (sMartInfo.martType == MART_TYPE_NORMAL)
|
|
{
|
|
if (AddBagItem(tItemId, tItemCount) == TRUE)
|
|
{
|
|
RecordItemPurchase(taskId);
|
|
BuyMenuDisplayMessage(taskId, gText_HereYouGoThankYou, BuyMenuSubtractMoney);
|
|
}
|
|
else
|
|
{
|
|
BuyMenuDisplayMessage(taskId, gText_NoMoreRoomForThis, BuyMenuReturnToItemList);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (DecorationAdd(tItemId))
|
|
{
|
|
if (sMartInfo.martType == MART_TYPE_DECOR)
|
|
BuyMenuDisplayMessage(taskId, gText_ThankYouIllSendItHome, BuyMenuSubtractMoney);
|
|
else // MART_TYPE_DECOR2
|
|
BuyMenuDisplayMessage(taskId, gText_ThanksIllSendItHome, BuyMenuSubtractMoney);
|
|
}
|
|
else
|
|
{
|
|
BuyMenuDisplayMessage(taskId, gText_SpaceForVar1Full, BuyMenuReturnToItemList);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void BuyMenuSubtractMoney(u8 taskId)
|
|
{
|
|
IncrementGameStat(GAME_STAT_SHOPPED);
|
|
RemoveMoney(&gSaveBlock1Ptr->money, sShopData->totalCost);
|
|
PlaySE(SE_SHOP);
|
|
PrintMoneyAmountInMoneyBox(WIN_MONEY, GetMoney(&gSaveBlock1Ptr->money), 0);
|
|
|
|
if (sMartInfo.martType == MART_TYPE_NORMAL)
|
|
gTasks[taskId].func = Task_ReturnToItemListAfterItemPurchase;
|
|
else
|
|
gTasks[taskId].func = Task_ReturnToItemListAfterDecorationPurchase;
|
|
}
|
|
|
|
static void Task_ReturnToItemListAfterItemPurchase(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
if (JOY_NEW(A_BUTTON | B_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
|
|
// Purchasing 10+ Poke Balls gets the player a Premier Ball
|
|
if (tItemId == ITEM_POKE_BALL && tItemCount >= 10 && AddBagItem(ITEM_PREMIER_BALL, 1) == TRUE)
|
|
BuyMenuDisplayMessage(taskId, gText_ThrowInPremierBall, BuyMenuReturnToItemList);
|
|
else
|
|
BuyMenuReturnToItemList(taskId);
|
|
}
|
|
}
|
|
|
|
static void Task_ReturnToItemListAfterDecorationPurchase(u8 taskId)
|
|
{
|
|
if (JOY_NEW(A_BUTTON | B_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
BuyMenuReturnToItemList(taskId);
|
|
}
|
|
}
|
|
|
|
static void BuyMenuReturnToItemList(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE);
|
|
RedrawListMenu(tListTaskId);
|
|
BuyMenuPrintCursor(tListTaskId, COLORID_ITEM_LIST);
|
|
PutWindowTilemap(WIN_ITEM_LIST);
|
|
PutWindowTilemap(WIN_ITEM_DESCRIPTION);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
BuyMenuAddScrollIndicatorArrows();
|
|
gTasks[taskId].func = Task_BuyMenu;
|
|
}
|
|
|
|
static void BuyMenuPrintItemQuantityAndPrice(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
FillWindowPixelBuffer(WIN_QUANTITY_PRICE, PIXEL_FILL(1));
|
|
PrintMoneyAmount(WIN_QUANTITY_PRICE, 38, 1, sShopData->totalCost, TEXT_SKIP_DRAW);
|
|
ConvertIntToDecimalStringN(gStringVar1, tItemCount, STR_CONV_MODE_LEADING_ZEROS, MAX_ITEM_DIGITS);
|
|
StringExpandPlaceholders(gStringVar4, gText_xVar1);
|
|
BuyMenuPrint(WIN_QUANTITY_PRICE, gStringVar4, 0, 1, 0, COLORID_NORMAL);
|
|
}
|
|
|
|
static void ExitBuyMenu(u8 taskId)
|
|
{
|
|
gFieldCallback = MapPostLoadHook_ReturnToShopMenu;
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
|
gTasks[taskId].func = Task_ExitBuyMenu;
|
|
}
|
|
|
|
static void Task_ExitBuyMenu(u8 taskId)
|
|
{
|
|
if (!gPaletteFade.active)
|
|
{
|
|
RemoveMoneyLabelObject();
|
|
BuyMenuFreeMemory();
|
|
SetMainCallback2(CB2_ReturnToField);
|
|
DestroyTask(taskId);
|
|
}
|
|
}
|
|
|
|
static void ClearItemPurchases(void)
|
|
{
|
|
sPurchaseHistoryId = 0;
|
|
memset(gMartPurchaseHistory, 0, sizeof(gMartPurchaseHistory));
|
|
}
|
|
|
|
static void RecordItemPurchase(u8 taskId)
|
|
{
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
u16 i;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gMartPurchaseHistory); i++)
|
|
{
|
|
if (gMartPurchaseHistory[i].itemId == tItemId && gMartPurchaseHistory[i].quantity != 0)
|
|
{
|
|
if (gMartPurchaseHistory[i].quantity + tItemCount > 255)
|
|
gMartPurchaseHistory[i].quantity = 255;
|
|
else
|
|
gMartPurchaseHistory[i].quantity += tItemCount;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (sPurchaseHistoryId < ARRAY_COUNT(gMartPurchaseHistory))
|
|
{
|
|
gMartPurchaseHistory[sPurchaseHistoryId].itemId = tItemId;
|
|
gMartPurchaseHistory[sPurchaseHistoryId].quantity = tItemCount;
|
|
sPurchaseHistoryId++;
|
|
}
|
|
}
|
|
|
|
#undef tItemCount
|
|
#undef tItemId
|
|
#undef tListTaskId
|
|
#undef tCallbackHi
|
|
#undef tCallbackLo
|
|
|
|
void CreatePokemartMenu(const u16 *itemsForSale)
|
|
{
|
|
CreateShopMenu(MART_TYPE_NORMAL);
|
|
SetShopItemsForSale(itemsForSale);
|
|
ClearItemPurchases();
|
|
SetShopMenuCallback(ScriptContext_Enable);
|
|
}
|
|
|
|
void CreateDecorationShop1Menu(const u16 *itemsForSale)
|
|
{
|
|
CreateShopMenu(MART_TYPE_DECOR);
|
|
SetShopItemsForSale(itemsForSale);
|
|
SetShopMenuCallback(ScriptContext_Enable);
|
|
}
|
|
|
|
void CreateDecorationShop2Menu(const u16 *itemsForSale)
|
|
{
|
|
CreateShopMenu(MART_TYPE_DECOR2);
|
|
SetShopItemsForSale(itemsForSale);
|
|
SetShopMenuCallback(ScriptContext_Enable);
|
|
}
|