Advertisement
Guest User

Untitled

a guest
Nov 20th, 2024
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 40.83 KB | None | 0 0
  1. #include "global.h"
  2. #include "bg.h"
  3. #include "data.h"
  4. #include "decompress.h"
  5. #include "decoration.h"
  6. #include "decoration_inventory.h"
  7. #include "event_object_movement.h"
  8. #include "field_player_avatar.h"
  9. #include "field_screen_effect.h"
  10. #include "field_weather.h"
  11. #include "fieldmap.h"
  12. #include "gpu_regs.h"
  13. #include "graphics.h"
  14. #include "international_string_util.h"
  15. #include "item.h"
  16. #include "item_icon.h"
  17. #include "item_menu.h"
  18. #include "list_menu.h"
  19. #include "main.h"
  20. #include "malloc.h"
  21. #include "menu.h"
  22. #include "menu_helpers.h"
  23. #include "money.h"
  24. #include "overworld.h"
  25. #include "palette.h"
  26. #include "party_menu.h"
  27. #include "scanline_effect.h"
  28. #include "script.h"
  29. #include "shop.h"
  30. #include "sound.h"
  31. #include "sprite.h"
  32. #include "string_util.h"
  33. #include "strings.h"
  34. #include "text_window.h"
  35. #include "tv.h"
  36. #include "constants/decorations.h"
  37. #include "constants/items.h"
  38. #include "constants/metatile_behaviors.h"
  39. #include "constants/rgb.h"
  40. #include "constants/songs.h"
  41.  
  42. #define TAG_SCROLL_ARROW   2100
  43. #define TAG_ITEM_ICON_BASE 2110
  44.  
  45. #define MAX_ITEMS_SHOWN 8
  46.  
  47. enum {
  48.     WIN_BUY_SELL_QUIT,
  49.     WIN_BUY_QUIT,
  50. };
  51.  
  52. enum {
  53.     WIN_MONEY,
  54.     WIN_ITEM_LIST,
  55.     WIN_ITEM_DESCRIPTION,
  56.     WIN_QUANTITY_IN_BAG,
  57.     WIN_QUANTITY_PRICE,
  58.     WIN_MESSAGE,
  59. };
  60.  
  61. enum {
  62.     COLORID_NORMAL,      // Item descriptions, quantity in bag, and quantity/price
  63.     COLORID_ITEM_LIST,   // The text in the item list, and the cursor normally
  64.     COLORID_GRAY_CURSOR, // When the cursor has selected an item to purchase
  65. };
  66.  
  67. enum {
  68.     MART_TYPE_NORMAL,
  69.     MART_TYPE_DECOR,
  70.     MART_TYPE_DECOR2,
  71.     MART_TYPE_VARIABLE,
  72. };
  73.  
  74. // shop view window NPC info enum
  75. enum
  76. {
  77.     OBJ_EVENT_ID,
  78.     X_COORD,
  79.     Y_COORD,
  80.     ANIM_NUM,
  81.     LAYER_TYPE
  82. };
  83.  
  84. struct MartInfo
  85. {
  86.     void (*callback)(void);
  87.     const struct MenuAction *menuActions;
  88.     const u16 *itemList;
  89.     u16 itemCount;
  90.     u8 windowId;
  91.     u8 martType;
  92. };
  93.  
  94. struct ShopData
  95. {
  96.     u16 tilemapBuffers[4][0x400];
  97.     u32 totalCost;
  98.     u16 itemsShowed;
  99.     u16 selectedRow;
  100.     u16 scrollOffset;
  101.     u8 maxQuantity;
  102.     u8 scrollIndicatorsTaskId;
  103.     u8 iconSlot;
  104.     u8 itemSpriteIds[2];
  105.     s16 viewportObjects[OBJECT_EVENTS_COUNT][5];
  106. };
  107.  
  108. static EWRAM_DATA struct MartInfo sMartInfo = {0};
  109. static EWRAM_DATA struct ShopData *sShopData = NULL;
  110. static EWRAM_DATA struct ListMenuItem *sListMenuItems = NULL;
  111. static EWRAM_DATA u8 (*sItemNames)[ITEM_NAME_LENGTH + 2] = {0};
  112. static EWRAM_DATA u8 sPurchaseHistoryId = 0;
  113. EWRAM_DATA struct ItemSlot gMartPurchaseHistory[SMARTSHOPPER_NUM_ITEMS] = {0};
  114.  
  115. static void Task_ShopMenu(u8 taskId);
  116. static void Task_HandleShopMenuQuit(u8 taskId);
  117. static void CB2_InitBuyMenu(void);
  118. static void Task_GoToBuyOrSellMenu(u8 taskId);
  119. static void MapPostLoadHook_ReturnToShopMenu(void);
  120. static void Task_ReturnToShopMenu(u8 taskId);
  121. static void ShowShopMenuAfterExitingBuyOrSellMenu(u8 taskId);
  122. static void BuyMenuDrawGraphics(void);
  123. static void BuyMenuAddScrollIndicatorArrows(void);
  124. static void Task_BuyMenu(u8 taskId);
  125. static void BuyMenuBuildListMenuTemplate(void);
  126. static void BuyMenuInitBgs(void);
  127. static void BuyMenuInitWindows(void);
  128. static void BuyMenuDecompressBgGraphics(void);
  129. static void BuyMenuSetListEntry(struct ListMenuItem *, u16, u8 *);
  130. static void BuyMenuAddItemIcon(u16, u8);
  131. static void BuyMenuRemoveItemIcon(u16, u8);
  132. static void BuyMenuPrint(u8 windowId, const u8 *text, u8 x, u8 y, s8 speed, u8 colorSet);
  133. static void BuyMenuDrawMapGraphics(void);
  134. static void BuyMenuCopyMenuBgToBg1TilemapBuffer(void);
  135. static void BuyMenuCollectObjectEventData(void);
  136. static void BuyMenuDrawObjectEvents(void);
  137. static void BuyMenuDrawMapBg(void);
  138. static bool8 BuyMenuCheckForOverlapWithMenuBg(int, int);
  139. static void BuyMenuDrawMapMetatile(s16, s16, const u16 *, u8);
  140. static void BuyMenuDrawMapMetatileLayer(u16 *dest, s16 offset1, s16 offset2, const u16 *src);
  141. static bool8 BuyMenuCheckIfObjectEventOverlapsMenuBg(s16 *);
  142. static void ExitBuyMenu(u8 taskId);
  143. static void Task_ExitBuyMenu(u8 taskId);
  144. static void BuyMenuTryMakePurchase(u8 taskId);
  145. static void BuyMenuReturnToItemList(u8 taskId);
  146. static void Task_BuyHowManyDialogueInit(u8 taskId);
  147. static void BuyMenuConfirmPurchase(u8 taskId);
  148. static void BuyMenuPrintItemQuantityAndPrice(u8 taskId);
  149. static void Task_BuyHowManyDialogueHandleInput(u8 taskId);
  150. static void BuyMenuSubtractMoney(u8 taskId);
  151. static void RecordItemPurchase(u8 taskId);
  152. static void Task_ReturnToItemListAfterItemPurchase(u8 taskId);
  153. static void Task_ReturnToItemListAfterDecorationPurchase(u8 taskId);
  154. static void Task_HandleShopMenuBuy(u8 taskId);
  155. static void Task_HandleShopMenuSell(u8 taskId);
  156. static void BuyMenuPrintItemDescriptionAndShowItemIcon(s32 item, bool8 onInit, struct ListMenu *list);
  157. static void BuyMenuPrintPriceInList(u8 windowId, u32 itemId, u8 y);
  158.  
  159. static const struct YesNoFuncTable sShopPurchaseYesNoFuncs =
  160. {
  161.     BuyMenuTryMakePurchase,
  162.     BuyMenuReturnToItemList
  163. };
  164.  
  165. static const struct MenuAction sShopMenuActions_BuySellQuit[] =
  166. {
  167.     { gText_ShopBuy, {.void_u8=Task_HandleShopMenuBuy} },
  168.     { gText_ShopSell, {.void_u8=Task_HandleShopMenuSell} },
  169.     { gText_ShopQuit, {.void_u8=Task_HandleShopMenuQuit} }
  170. };
  171.  
  172. static const struct MenuAction sShopMenuActions_BuyQuit[] =
  173. {
  174.     { gText_ShopBuy, {.void_u8=Task_HandleShopMenuBuy} },
  175.     { gText_ShopQuit, {.void_u8=Task_HandleShopMenuQuit} }
  176. };
  177.  
  178. static const struct WindowTemplate sShopMenuWindowTemplates[] =
  179. {
  180.     [WIN_BUY_SELL_QUIT] = {
  181.         .bg = 0,
  182.         .tilemapLeft = 2,
  183.         .tilemapTop = 1,
  184.         .width = 9,
  185.         .height = 6,
  186.         .paletteNum = 15,
  187.         .baseBlock = 0x0008,
  188.     },
  189.     // Separate shop menu window for decorations, which can't be sold
  190.     [WIN_BUY_QUIT] = {
  191.         .bg = 0,
  192.         .tilemapLeft = 2,
  193.         .tilemapTop = 1,
  194.         .width = 9,
  195.         .height = 4,
  196.         .paletteNum = 15,
  197.         .baseBlock = 0x0008,
  198.     }
  199. };
  200.  
  201. static const struct ListMenuTemplate sShopBuyMenuListTemplate =
  202. {
  203.     .items = NULL,
  204.     .moveCursorFunc = BuyMenuPrintItemDescriptionAndShowItemIcon,
  205.     .itemPrintFunc = BuyMenuPrintPriceInList,
  206.     .totalItems = 0,
  207.     .maxShowed = 0,
  208.     .windowId = WIN_ITEM_LIST,
  209.     .header_X = 0,
  210.     .item_X = 8,
  211.     .cursor_X = 0,
  212.     .upText_Y = 1,
  213.     .cursorPal = 2,
  214.     .fillValue = 0,
  215.     .cursorShadowPal = 3,
  216.     .lettersSpacing = 0,
  217.     .itemVerticalPadding = 0,
  218.     .scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
  219.     .fontId = FONT_NARROW,
  220.     .cursorKind = CURSOR_BLACK_ARROW
  221. };
  222.  
  223. static const struct BgTemplate sShopBuyMenuBgTemplates[] =
  224. {
  225.     {
  226.         .bg = 0,
  227.         .charBaseIndex = 2,
  228.         .mapBaseIndex = 31,
  229.         .screenSize = 0,
  230.         .paletteMode = 0,
  231.         .priority = 0,
  232.         .baseTile = 0
  233.     },
  234.     {
  235.         .bg = 1,
  236.         .charBaseIndex = 0,
  237.         .mapBaseIndex = 30,
  238.         .screenSize = 0,
  239.         .paletteMode = 0,
  240.         .priority = 1,
  241.         .baseTile = 0
  242.     },
  243.     {
  244.         .bg = 2,
  245.         .charBaseIndex = 0,
  246.         .mapBaseIndex = 29,
  247.         .screenSize = 0,
  248.         .paletteMode = 0,
  249.         .priority = 2,
  250.         .baseTile = 0
  251.     },
  252.     {
  253.         .bg = 3,
  254.         .charBaseIndex = 0,
  255.         .mapBaseIndex = 28,
  256.         .screenSize = 0,
  257.         .paletteMode = 0,
  258.         .priority = 3,
  259.         .baseTile = 0
  260.     }
  261. };
  262.  
  263. static const struct WindowTemplate sShopBuyMenuWindowTemplates[] =
  264. {
  265.     [WIN_MONEY] = {
  266.         .bg = 0,
  267.         .tilemapLeft = 1,
  268.         .tilemapTop = 1,
  269.         .width = 10,
  270.         .height = 2,
  271.         .paletteNum = 15,
  272.         .baseBlock = 0x001E,
  273.     },
  274.     [WIN_ITEM_LIST] = {
  275.         .bg = 0,
  276.         .tilemapLeft = 14,
  277.         .tilemapTop = 2,
  278.         .width = 15,
  279.         .height = 16,
  280.         .paletteNum = 15,
  281.         .baseBlock = 0x0032,
  282.     },
  283.     [WIN_ITEM_DESCRIPTION] = {
  284.         .bg = 0,
  285.         .tilemapLeft = 0,
  286.         .tilemapTop = 13,
  287.         .width = 14,
  288.         .height = 6,
  289.         .paletteNum = 15,
  290.         .baseBlock = 0x0122,
  291.     },
  292.     [WIN_QUANTITY_IN_BAG] = {
  293.         .bg = 0,
  294.         .tilemapLeft = 1,
  295.         .tilemapTop = 11,
  296.         .width = 12,
  297.         .height = 2,
  298.         .paletteNum = 15,
  299.         .baseBlock = 0x0176,
  300.     },
  301.     [WIN_QUANTITY_PRICE] = {
  302.         .bg = 0,
  303.         .tilemapLeft = 18,
  304.         .tilemapTop = 11,
  305.         .width = 10,
  306.         .height = 2,
  307.         .paletteNum = 15,
  308.         .baseBlock = 0x018E,
  309.     },
  310.     [WIN_MESSAGE] = {
  311.         .bg = 0,
  312.         .tilemapLeft = 2,
  313.         .tilemapTop = 15,
  314.         .width = 27,
  315.         .height = 4,
  316.         .paletteNum = 15,
  317.         .baseBlock = 0x01A2,
  318.     },
  319.     DUMMY_WIN_TEMPLATE
  320. };
  321.  
  322. static const struct WindowTemplate sShopBuyMenuYesNoWindowTemplates =
  323. {
  324.     .bg = 0,
  325.     .tilemapLeft = 21,
  326.     .tilemapTop = 9,
  327.     .width = 5,
  328.     .height = 4,
  329.     .paletteNum = 15,
  330.     .baseBlock = 0x020E,
  331. };
  332.  
  333. static const u8 sShopBuyMenuTextColors[][3] =
  334. {
  335.     [COLORID_NORMAL]      = {1, 2, 3},
  336.     [COLORID_ITEM_LIST]   = {0, 2, 3},
  337.     [COLORID_GRAY_CURSOR] = {0, 3, 2},
  338. };
  339.  
  340. static u8 CreateShopMenu(u8 martType)
  341. {
  342.     int numMenuItems;
  343.  
  344.     LockPlayerFieldControls();
  345.     sMartInfo.martType = martType;
  346.  
  347.     if (martType == MART_TYPE_NORMAL || martType == MART_TYPE_VARIABLE)
  348.     {
  349.         struct WindowTemplate winTemplate = sShopMenuWindowTemplates[WIN_BUY_SELL_QUIT];
  350.         winTemplate.width = GetMaxWidthInMenuTable(sShopMenuActions_BuySellQuit, ARRAY_COUNT(sShopMenuActions_BuySellQuit));
  351.         sMartInfo.windowId = AddWindow(&winTemplate);
  352.         sMartInfo.menuActions = sShopMenuActions_BuySellQuit;
  353.         numMenuItems = ARRAY_COUNT(sShopMenuActions_BuySellQuit);
  354.     }
  355.     else
  356.     {
  357.         struct WindowTemplate winTemplate = sShopMenuWindowTemplates[WIN_BUY_QUIT];
  358.         winTemplate.width = GetMaxWidthInMenuTable(sShopMenuActions_BuyQuit, ARRAY_COUNT(sShopMenuActions_BuyQuit));
  359.         sMartInfo.windowId = AddWindow(&winTemplate);
  360.         sMartInfo.menuActions = sShopMenuActions_BuyQuit;
  361.         numMenuItems = ARRAY_COUNT(sShopMenuActions_BuyQuit);
  362.     }
  363.  
  364.     SetStandardWindowBorderStyle(sMartInfo.windowId, FALSE);
  365.     PrintMenuTable(sMartInfo.windowId, numMenuItems, sMartInfo.menuActions);
  366.     InitMenuInUpperLeftCornerNormal(sMartInfo.windowId, numMenuItems, 0);
  367.     PutWindowTilemap(sMartInfo.windowId);
  368.     CopyWindowToVram(sMartInfo.windowId, COPYWIN_MAP);
  369.  
  370.     return CreateTask(Task_ShopMenu, 8);
  371. }
  372.  
  373. static void SetShopMenuCallback(void (* callback)(void))
  374. {
  375.     sMartInfo.callback = callback;
  376. }
  377.  
  378. static void SetShopItemsForSale(const u16 *items)
  379. {
  380.     u16 i = 0;
  381.  
  382.     sMartInfo.itemList = items;
  383.     sMartInfo.itemCount = 0;
  384.  
  385.     // Read items until ITEM_NONE / DECOR_NONE is reached
  386.     while (items[i])
  387.     {
  388.         sMartInfo.itemCount++;
  389.         i += (sMartInfo.martType == MART_TYPE_VARIABLE) ? 2 : 1;
  390.     }
  391. }
  392.  
  393. static u32 SearchItemListForPrice(u32 itemId)
  394. {
  395.     u16 i;
  396.  
  397.     for(i = 0; i < sMartInfo.itemCount; i+=2)
  398.     {
  399.         if(sMartInfo.itemList[i] == itemId)
  400.         {
  401.             return sMartInfo.itemList[i+1];
  402.         }
  403.     }
  404.  
  405.     return 0;
  406. }
  407.  
  408. static void Task_ShopMenu(u8 taskId)
  409. {
  410.     s8 inputCode = Menu_ProcessInputNoWrap();
  411.     switch (inputCode)
  412.     {
  413.     case MENU_NOTHING_CHOSEN:
  414.         break;
  415.     case MENU_B_PRESSED:
  416.         PlaySE(SE_SELECT);
  417.         Task_HandleShopMenuQuit(taskId);
  418.         break;
  419.     default:
  420.         sMartInfo.menuActions[inputCode].func.void_u8(taskId);
  421.         break;
  422.     }
  423. }
  424.  
  425. #define tItemCount  data[1]
  426. #define tItemId     data[5]
  427. #define tListTaskId data[7]
  428. #define tCallbackHi data[8]
  429. #define tCallbackLo data[9]
  430.  
  431. static void Task_HandleShopMenuBuy(u8 taskId)
  432. {
  433.     s16 *data = gTasks[taskId].data;
  434.     tCallbackHi = (u32)CB2_InitBuyMenu >> 16;
  435.     tCallbackLo = (u32)CB2_InitBuyMenu;
  436.     gTasks[taskId].func = Task_GoToBuyOrSellMenu;
  437.     FadeScreen(FADE_TO_BLACK, 0);
  438. }
  439.  
  440. static void Task_HandleShopMenuSell(u8 taskId)
  441. {
  442.     s16 *data = gTasks[taskId].data;
  443.     tCallbackHi = (u32)CB2_GoToSellMenu >> 16;
  444.     tCallbackLo = (u32)CB2_GoToSellMenu;
  445.     gTasks[taskId].func = Task_GoToBuyOrSellMenu;
  446.     FadeScreen(FADE_TO_BLACK, 0);
  447. }
  448.  
  449. void CB2_ExitSellMenu(void)
  450. {
  451.     gFieldCallback = MapPostLoadHook_ReturnToShopMenu;
  452.     SetMainCallback2(CB2_ReturnToField);
  453. }
  454.  
  455. static void Task_HandleShopMenuQuit(u8 taskId)
  456. {
  457.     ClearStdWindowAndFrameToTransparent(sMartInfo.windowId, 2); // Incorrect use, making it not copy it to vram.
  458.     RemoveWindow(sMartInfo.windowId);
  459.     TryPutSmartShopperOnAir();
  460.     UnlockPlayerFieldControls();
  461.     DestroyTask(taskId);
  462.  
  463.     if (sMartInfo.callback)
  464.         sMartInfo.callback();
  465. }
  466.  
  467. static void Task_GoToBuyOrSellMenu(u8 taskId)
  468. {
  469.     s16 *data = gTasks[taskId].data;
  470.     if (!gPaletteFade.active)
  471.     {
  472.         DestroyTask(taskId);
  473.         SetMainCallback2((void *)((u16)tCallbackHi << 16 | (u16)tCallbackLo));
  474.     }
  475. }
  476.  
  477. static void MapPostLoadHook_ReturnToShopMenu(void)
  478. {
  479.     FadeInFromBlack();
  480.     CreateTask(Task_ReturnToShopMenu, 8);
  481. }
  482.  
  483. static void Task_ReturnToShopMenu(u8 taskId)
  484. {
  485.     if (IsWeatherNotFadingIn() == TRUE)
  486.     {
  487.         if (sMartInfo.martType == MART_TYPE_DECOR2)
  488.             DisplayItemMessageOnField(taskId, gText_CanIHelpWithAnythingElse, ShowShopMenuAfterExitingBuyOrSellMenu);
  489.         else
  490.             DisplayItemMessageOnField(taskId, gText_AnythingElseICanHelp, ShowShopMenuAfterExitingBuyOrSellMenu);
  491.     }
  492. }
  493.  
  494. static void ShowShopMenuAfterExitingBuyOrSellMenu(u8 taskId)
  495. {
  496.     CreateShopMenu(sMartInfo.martType);
  497.     DestroyTask(taskId);
  498. }
  499.  
  500. static void CB2_BuyMenu(void)
  501. {
  502.     RunTasks();
  503.     AnimateSprites();
  504.     BuildOamBuffer();
  505.     DoScheduledBgTilemapCopiesToVram();
  506.     UpdatePaletteFade();
  507. }
  508.  
  509. static void VBlankCB_BuyMenu(void)
  510. {
  511.     LoadOam();
  512.     ProcessSpriteCopyRequests();
  513.     TransferPlttBuffer();
  514. }
  515.  
  516. static void CB2_InitBuyMenu(void)
  517. {
  518.     u8 taskId;
  519.  
  520.     switch (gMain.state)
  521.     {
  522.     case 0:
  523.         SetVBlankHBlankCallbacksToNull();
  524.         CpuFastFill(0, (void *)OAM, OAM_SIZE);
  525.         ScanlineEffect_Stop();
  526.         ResetTempTileDataBuffers();
  527.         FreeAllSpritePalettes();
  528.         ResetPaletteFade();
  529.         ResetSpriteData();
  530.         ResetTasks();
  531.         ClearScheduledBgCopiesToVram();
  532.         sShopData = AllocZeroed(sizeof(struct ShopData));
  533.         sShopData->scrollIndicatorsTaskId = TASK_NONE;
  534.         sShopData->itemSpriteIds[0] = SPRITE_NONE;
  535.         sShopData->itemSpriteIds[1] = SPRITE_NONE;
  536.         InitShopItemsForSale();
  537.         BuyMenuBuildListMenuTemplate();
  538.         BuyMenuInitBgs();
  539.         FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x20, 0x20);
  540.         FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 0x20, 0x20);
  541.         FillBgTilemapBufferRect_Palette0(2, 0, 0, 0, 0x20, 0x20);
  542.         FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 0x20, 0x20);
  543.         BuyMenuInitWindows();
  544.         BuyMenuDecompressBgGraphics();
  545.         gMain.state++;
  546.         break;
  547.     case 1:
  548.         if (!FreeTempTileDataBuffersIfPossible())
  549.             gMain.state++;
  550.         break;
  551.     default:
  552.         BuyMenuDrawGraphics();
  553.         BuyMenuAddScrollIndicatorArrows();
  554.         taskId = CreateTask(Task_BuyMenu, 8);
  555.         gTasks[taskId].tListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, 0, 0);
  556.         BlendPalettes(PALETTES_ALL, 16, RGB_BLACK);
  557.         BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
  558.         SetVBlankCallback(VBlankCB_BuyMenu);
  559.         SetMainCallback2(CB2_BuyMenu);
  560.         break;
  561.     }
  562. }
  563.  
  564. static void BuyMenuFreeMemory(void)
  565. {
  566.     Free(sShopData);
  567.     Free(sListMenuItems);
  568.     Free(sItemNames);
  569.     FreeAllWindowBuffers();
  570. }
  571.  
  572. static void BuyMenuBuildListMenuTemplate(void)
  573. {
  574.     u16 i;
  575.  
  576.     sListMenuItems = Alloc((sMartInfo.itemCount + 1) * sizeof(*sListMenuItems));
  577.     sItemNames = Alloc((sMartInfo.itemCount + 1) * sizeof(*sItemNames));
  578.     for (i = 0; i < sMartInfo.itemCount; i++)
  579.     {
  580.         if (sMartInfo.martType == MART_TYPE_VARIABLE)
  581.             BuyMenuSetListEntry(&sListMenuItems[i], (sMartInfo.itemList)[i*2], sItemNames[i]);
  582.         else
  583.             BuyMenuSetListEntry(&sListMenuItems[i], (sMartInfo.itemList)[i], sItemNames[i]);
  584.     }
  585.  
  586.     StringCopy(sItemNames[i], gText_Cancel2);
  587.     sListMenuItems[i].name = sItemNames[i];
  588.     sListMenuItems[i].id = LIST_CANCEL;
  589.  
  590.     gMultiuseListMenuTemplate = sShopBuyMenuListTemplate;
  591.     gMultiuseListMenuTemplate.items = sListMenuItems;
  592.     gMultiuseListMenuTemplate.totalItems = sMartInfo.itemCount + 1;
  593.     if (gMultiuseListMenuTemplate.totalItems > MAX_ITEMS_SHOWN)
  594.         gMultiuseListMenuTemplate.maxShowed = MAX_ITEMS_SHOWN;
  595.     else
  596.         gMultiuseListMenuTemplate.maxShowed = gMultiuseListMenuTemplate.totalItems;
  597.  
  598.     sShopData->itemsShowed = gMultiuseListMenuTemplate.maxShowed;
  599. }
  600.  
  601. static void BuyMenuSetListEntry(struct ListMenuItem *menuItem, u16 item, u8 *name)
  602. {
  603.     if (sMartInfo.martType == MART_TYPE_NORMAL || sMartInfo.martType == MART_TYPE_VARIABLE)
  604.         CopyItemName(item, name);
  605.     else
  606.         StringCopy(name, gDecorations[item].name);
  607.  
  608.     menuItem->name = name;
  609.     menuItem->id = item;
  610. }
  611.  
  612. static void BuyMenuPrintItemDescriptionAndShowItemIcon(s32 item, bool8 onInit, struct ListMenu *list)
  613. {
  614.     const u8 *description;
  615.     if (onInit != TRUE)
  616.         PlaySE(SE_SELECT);
  617.  
  618.     if (item != LIST_CANCEL)
  619.         BuyMenuAddItemIcon(item, sShopData->iconSlot);
  620.     else
  621.         BuyMenuAddItemIcon(ITEM_LIST_END, sShopData->iconSlot);
  622.  
  623.     BuyMenuRemoveItemIcon(item, sShopData->iconSlot ^ 1);
  624.     sShopData->iconSlot ^= 1;
  625.     if (item != LIST_CANCEL)
  626.     {
  627.         if (sMartInfo.martType == MART_TYPE_NORMAL || sMartInfo.martType == MART_TYPE_VARIABLE)
  628.             description = ItemId_GetDescription(item);
  629.         else
  630.             description = gDecorations[item].description;
  631.     }
  632.     else
  633.     {
  634.         description = gText_QuitShopping;
  635.     }
  636.  
  637.     FillWindowPixelBuffer(WIN_ITEM_DESCRIPTION, PIXEL_FILL(0));
  638.     BuyMenuPrint(WIN_ITEM_DESCRIPTION, description, 3, 1, 0, COLORID_NORMAL);
  639. }
  640.  
  641. static void BuyMenuPrintPriceInList(u8 windowId, u32 itemId, u8 y)
  642. {
  643.     u8 x;
  644.  
  645.     if (itemId != LIST_CANCEL)
  646.     {
  647.         if (sMartInfo.martType == MART_TYPE_NORMAL)
  648.         {
  649.             ConvertIntToDecimalStringN(
  650.                 gStringVar1,
  651.                 ItemId_GetPrice(itemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT),
  652.                 STR_CONV_MODE_LEFT_ALIGN,
  653.                 5);
  654.         }
  655.         else if(sMartInfo.martType == MART_TYPE_VARIABLE)
  656.         {
  657.             ConvertIntToDecimalStringN(
  658.                 gStringVar1,
  659.                 SearchItemListForPrice(itemId),
  660.                 STR_CONV_MODE_LEFT_ALIGN,
  661.                 5);
  662.         }
  663.         else
  664.         {
  665.             ConvertIntToDecimalStringN(
  666.                 gStringVar1,
  667.                 gDecorations[itemId].price,
  668.                 STR_CONV_MODE_LEFT_ALIGN,
  669.                 5);
  670.         }
  671.  
  672.         StringExpandPlaceholders(gStringVar4, gText_PokedollarVar1);
  673.         x = GetStringRightAlignXOffset(FONT_NARROW, gStringVar4, 120);
  674.         AddTextPrinterParameterized4(windowId, FONT_NARROW, x, y, 0, 0, sShopBuyMenuTextColors[COLORID_ITEM_LIST], TEXT_SKIP_DRAW, gStringVar4);
  675.     }
  676. }
  677.  
  678. static void BuyMenuAddScrollIndicatorArrows(void)
  679. {
  680.     if (sShopData->scrollIndicatorsTaskId == TASK_NONE && sMartInfo.itemCount + 1 > MAX_ITEMS_SHOWN)
  681.     {
  682.         sShopData->scrollIndicatorsTaskId = AddScrollIndicatorArrowPairParameterized(
  683.             SCROLL_ARROW_UP,
  684.             172,
  685.             12,
  686.             148,
  687.             sMartInfo.itemCount - (MAX_ITEMS_SHOWN - 1),
  688.             TAG_SCROLL_ARROW,
  689.             TAG_SCROLL_ARROW,
  690.             &sShopData->scrollOffset);
  691.     }
  692. }
  693.  
  694. static void BuyMenuRemoveScrollIndicatorArrows(void)
  695. {
  696.     if (sShopData->scrollIndicatorsTaskId != TASK_NONE)
  697.     {
  698.         RemoveScrollIndicatorArrowPair(sShopData->scrollIndicatorsTaskId);
  699.         sShopData->scrollIndicatorsTaskId = TASK_NONE;
  700.     }
  701. }
  702.  
  703. static void BuyMenuPrintCursor(u8 scrollIndicatorsTaskId, u8 colorSet)
  704. {
  705.     u8 y = ListMenuGetYCoordForPrintingArrowCursor(scrollIndicatorsTaskId);
  706.     BuyMenuPrint(WIN_ITEM_LIST, gText_SelectorArrow2, 0, y, 0, colorSet);
  707. }
  708.  
  709. static void BuyMenuAddItemIcon(u16 item, u8 iconSlot)
  710. {
  711.     u8 spriteId;
  712.     u8 *spriteIdPtr = &sShopData->itemSpriteIds[iconSlot];
  713.     if (*spriteIdPtr != SPRITE_NONE)
  714.         return;
  715.  
  716.     if (sMartInfo.martType == MART_TYPE_NORMAL || sMartInfo.martType == MART_TYPE_VARIABLE || item == ITEM_LIST_END)
  717.     {
  718.         spriteId = AddItemIconSprite(iconSlot + TAG_ITEM_ICON_BASE, iconSlot + TAG_ITEM_ICON_BASE, item);
  719.         if (spriteId != MAX_SPRITES)
  720.         {
  721.             *spriteIdPtr = spriteId;
  722.             gSprites[spriteId].x2 = 24;
  723.             gSprites[spriteId].y2 = 88;
  724.         }
  725.     }
  726.     else
  727.     {
  728.         spriteId = AddDecorationIconObject(item, 20, 84, 1, iconSlot + TAG_ITEM_ICON_BASE, iconSlot + TAG_ITEM_ICON_BASE);
  729.         if (spriteId != MAX_SPRITES)
  730.             *spriteIdPtr = spriteId;
  731.     }
  732. }
  733.  
  734. static void BuyMenuRemoveItemIcon(u16 item, u8 iconSlot)
  735. {
  736.     u8 *spriteIdPtr = &sShopData->itemSpriteIds[iconSlot];
  737.     if (*spriteIdPtr == SPRITE_NONE)
  738.         return;
  739.  
  740.     FreeSpriteTilesByTag(iconSlot + TAG_ITEM_ICON_BASE);
  741.     FreeSpritePaletteByTag(iconSlot + TAG_ITEM_ICON_BASE);
  742.     DestroySprite(&gSprites[*spriteIdPtr]);
  743.     *spriteIdPtr = SPRITE_NONE;
  744. }
  745.  
  746. static void BuyMenuInitBgs(void)
  747. {
  748.     ResetBgsAndClearDma3BusyFlags(0);
  749.     InitBgsFromTemplates(0, sShopBuyMenuBgTemplates, ARRAY_COUNT(sShopBuyMenuBgTemplates));
  750.     SetBgTilemapBuffer(1, sShopData->tilemapBuffers[1]);
  751.     SetBgTilemapBuffer(2, sShopData->tilemapBuffers[3]);
  752.     SetBgTilemapBuffer(3, sShopData->tilemapBuffers[2]);
  753.     SetGpuReg(REG_OFFSET_BG0HOFS, 0);
  754.     SetGpuReg(REG_OFFSET_BG0VOFS, 0);
  755.     SetGpuReg(REG_OFFSET_BG1HOFS, 0);
  756.     SetGpuReg(REG_OFFSET_BG1VOFS, 0);
  757.     SetGpuReg(REG_OFFSET_BG2HOFS, 0);
  758.     SetGpuReg(REG_OFFSET_BG2VOFS, 0);
  759.     SetGpuReg(REG_OFFSET_BG3HOFS, 0);
  760.     SetGpuReg(REG_OFFSET_BG3VOFS, 0);
  761.     SetGpuReg(REG_OFFSET_BLDCNT, 0);
  762.     SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
  763.     ShowBg(0);
  764.     ShowBg(1);
  765.     ShowBg(2);
  766.     ShowBg(3);
  767. }
  768.  
  769. static void BuyMenuDecompressBgGraphics(void)
  770. {
  771.     DecompressAndCopyTileDataToVram(1, gShopMenu_Gfx, 0x3A0, 0x3E3, 0);
  772.     LZDecompressWram(gShopMenu_Tilemap, sShopData->tilemapBuffers[0]);
  773.     LoadCompressedPalette(gShopMenu_Pal, BG_PLTT_ID(12), PLTT_SIZE_4BPP);
  774. }
  775.  
  776. static void BuyMenuInitWindows(void)
  777. {
  778.     InitWindows(sShopBuyMenuWindowTemplates);
  779.     DeactivateAllTextPrinters();
  780.     LoadUserWindowBorderGfx(WIN_MONEY, 1, BG_PLTT_ID(13));
  781.     LoadMessageBoxGfx(WIN_MONEY, 0xA, BG_PLTT_ID(14));
  782.     PutWindowTilemap(WIN_MONEY);
  783.     PutWindowTilemap(WIN_ITEM_LIST);
  784.     PutWindowTilemap(WIN_ITEM_DESCRIPTION);
  785. }
  786.  
  787. static void BuyMenuPrint(u8 windowId, const u8 *text, u8 x, u8 y, s8 speed, u8 colorSet)
  788. {
  789.     AddTextPrinterParameterized4(windowId, FONT_NORMAL, x, y, 0, 0, sShopBuyMenuTextColors[colorSet], speed, text);
  790. }
  791.  
  792. static void BuyMenuDisplayMessage(u8 taskId, const u8 *text, TaskFunc callback)
  793. {
  794.     DisplayMessageAndContinueTask(taskId, WIN_MESSAGE, 10, 14, FONT_NORMAL, GetPlayerTextSpeedDelay(), text, callback);
  795.     ScheduleBgCopyTilemapToVram(0);
  796. }
  797.  
  798. static void BuyMenuDrawGraphics(void)
  799. {
  800.     BuyMenuDrawMapGraphics();
  801.     BuyMenuCopyMenuBgToBg1TilemapBuffer();
  802.     AddMoneyLabelObject(19, 11);
  803.     PrintMoneyAmountInMoneyBoxWithBorder(WIN_MONEY, 1, 13, GetMoney(&gSaveBlock1Ptr->money));
  804.     ScheduleBgCopyTilemapToVram(0);
  805.     ScheduleBgCopyTilemapToVram(1);
  806.     ScheduleBgCopyTilemapToVram(2);
  807.     ScheduleBgCopyTilemapToVram(3);
  808. }
  809.  
  810. static void BuyMenuDrawMapGraphics(void)
  811. {
  812.     BuyMenuCollectObjectEventData();
  813.     BuyMenuDrawObjectEvents();
  814.     BuyMenuDrawMapBg();
  815. }
  816.  
  817. static void BuyMenuDrawMapBg(void)
  818. {
  819.     s16 i, j;
  820.     s16 x, y;
  821.     const struct MapLayout *mapLayout;
  822.     u16 metatile;
  823.     u8 metatileLayerType;
  824.  
  825.     mapLayout = gMapHeader.mapLayout;
  826.     GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
  827.     x -= 4;
  828.     y -= 4;
  829.  
  830.     for (j = 0; j < 10; j++)
  831.     {
  832.         for (i = 0; i < 15; i++)
  833.         {
  834.             metatile = MapGridGetMetatileIdAt(x + i, y + j);
  835.             if (BuyMenuCheckForOverlapWithMenuBg(i, j) == TRUE)
  836.                 metatileLayerType = MapGridGetMetatileLayerTypeAt(x + i, y + j);
  837.             else
  838.                 metatileLayerType = METATILE_LAYER_TYPE_COVERED;
  839.  
  840.             if (metatile < NUM_METATILES_IN_PRIMARY)
  841.                 BuyMenuDrawMapMetatile(i, j, mapLayout->primaryTileset->metatiles + metatile * NUM_TILES_PER_METATILE, metatileLayerType);
  842.             else
  843.                 BuyMenuDrawMapMetatile(i, j, mapLayout->secondaryTileset->metatiles + ((metatile - NUM_METATILES_IN_PRIMARY) * NUM_TILES_PER_METATILE), metatileLayerType);
  844.         }
  845.     }
  846. }
  847.  
  848. static void BuyMenuDrawMapMetatile(s16 x, s16 y, const u16 *src, u8 metatileLayerType)
  849. {
  850.     u16 offset1 = x * 2;
  851.     u16 offset2 = y * 64;
  852.  
  853.     switch (metatileLayerType)
  854.     {
  855.     case METATILE_LAYER_TYPE_NORMAL:
  856.         BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[3], offset1, offset2, src);
  857.         BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[1], offset1, offset2, src + 4);
  858.         break;
  859.     case METATILE_LAYER_TYPE_COVERED:
  860.         BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[2], offset1, offset2, src);
  861.         BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[3], offset1, offset2, src + 4);
  862.         break;
  863.     case METATILE_LAYER_TYPE_SPLIT:
  864.         BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[2], offset1, offset2, src);
  865.         BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[1], offset1, offset2, src + 4);
  866.         break;
  867.     }
  868. }
  869.  
  870. static void BuyMenuDrawMapMetatileLayer(u16 *dest, s16 offset1, s16 offset2, const u16 *src)
  871. {
  872.     // This function draws a whole 2x2 metatile.
  873.     dest[offset1 + offset2] = src[0]; // top left
  874.     dest[offset1 + offset2 + 1] = src[1]; // top right
  875.     dest[offset1 + offset2 + 32] = src[2]; // bottom left
  876.     dest[offset1 + offset2 + 33] = src[3]; // bottom right
  877. }
  878.  
  879. static void BuyMenuCollectObjectEventData(void)
  880. {
  881.     s16 facingX;
  882.     s16 facingY;
  883.     u8 y;
  884.     u8 x;
  885.     u8 numObjects = 0;
  886.  
  887.     GetXYCoordsOneStepInFrontOfPlayer(&facingX, &facingY);
  888.  
  889.     for (y = 0; y < OBJECT_EVENTS_COUNT; y++)
  890.         sShopData->viewportObjects[y][OBJ_EVENT_ID] = OBJECT_EVENTS_COUNT;
  891.  
  892.     for (y = 0; y < 5; y++)
  893.     {
  894.         for (x = 0; x < 7; x++)
  895.         {
  896.             u8 objEventId = GetObjectEventIdByXY(facingX - 4 + x, facingY - 2 + y);
  897.  
  898.             if (objEventId != OBJECT_EVENTS_COUNT)
  899.             {
  900.                 sShopData->viewportObjects[numObjects][OBJ_EVENT_ID] = objEventId;
  901.                 sShopData->viewportObjects[numObjects][X_COORD] = x;
  902.                 sShopData->viewportObjects[numObjects][Y_COORD] = y;
  903.                 sShopData->viewportObjects[numObjects][LAYER_TYPE] = MapGridGetMetatileLayerTypeAt(facingX - 4 + x, facingY - 2 + y);
  904.  
  905.                 switch (gObjectEvents[objEventId].facingDirection)
  906.                 {
  907.                 case DIR_SOUTH:
  908.                     sShopData->viewportObjects[numObjects][ANIM_NUM] = ANIM_STD_FACE_SOUTH;
  909.                     break;
  910.                 case DIR_NORTH:
  911.                     sShopData->viewportObjects[numObjects][ANIM_NUM] = ANIM_STD_FACE_NORTH;
  912.                     break;
  913.                 case DIR_WEST:
  914.                     sShopData->viewportObjects[numObjects][ANIM_NUM] = ANIM_STD_FACE_WEST;
  915.                     break;
  916.                 case DIR_EAST:
  917.                 default:
  918.                     sShopData->viewportObjects[numObjects][ANIM_NUM] = ANIM_STD_FACE_EAST;
  919.                     break;
  920.                 }
  921.                 numObjects++;
  922.             }
  923.         }
  924.     }
  925. }
  926.  
  927. static void BuyMenuDrawObjectEvents(void)
  928. {
  929.     u8 i;
  930.     u8 spriteId;
  931.     const struct ObjectEventGraphicsInfo *graphicsInfo;
  932.  
  933.     for (i = 0; i < OBJECT_EVENTS_COUNT; i++)
  934.     {
  935.         if (sShopData->viewportObjects[i][OBJ_EVENT_ID] == OBJECT_EVENTS_COUNT)
  936.             continue;
  937.  
  938.         graphicsInfo = GetObjectEventGraphicsInfo(gObjectEvents[sShopData->viewportObjects[i][OBJ_EVENT_ID]].graphicsId);
  939.  
  940.         spriteId = CreateObjectGraphicsSprite(
  941.             gObjectEvents[sShopData->viewportObjects[i][OBJ_EVENT_ID]].graphicsId,
  942.             SpriteCallbackDummy,
  943.             (u16)sShopData->viewportObjects[i][X_COORD] * 16 + 8,
  944.             (u16)sShopData->viewportObjects[i][Y_COORD] * 16 + 48 - graphicsInfo->height / 2,
  945.             2);
  946.  
  947.         if (BuyMenuCheckIfObjectEventOverlapsMenuBg(sShopData->viewportObjects[i]) == TRUE)
  948.         {
  949.             gSprites[spriteId].subspriteTableNum = 4;
  950.             gSprites[spriteId].subspriteMode = SUBSPRITES_ON;
  951.         }
  952.  
  953.         StartSpriteAnim(&gSprites[spriteId], sShopData->viewportObjects[i][ANIM_NUM]);
  954.     }
  955. }
  956.  
  957. static bool8 BuyMenuCheckIfObjectEventOverlapsMenuBg(s16 *object)
  958. {
  959.     if (!BuyMenuCheckForOverlapWithMenuBg(object[X_COORD], object[Y_COORD] + 2) && object[LAYER_TYPE] != METATILE_LAYER_TYPE_COVERED)
  960.         return TRUE;
  961.     else
  962.         return FALSE;
  963. }
  964.  
  965. static void BuyMenuCopyMenuBgToBg1TilemapBuffer(void)
  966. {
  967.     s16 i;
  968.     u16 *dest = sShopData->tilemapBuffers[1];
  969.     const u16 *src = sShopData->tilemapBuffers[0];
  970.  
  971.     for (i = 0; i < 1024; i++)
  972.     {
  973.         if (src[i] != 0)
  974.             dest[i] = src[i] + 0xC3E3;
  975.     }
  976. }
  977.  
  978. static bool8 BuyMenuCheckForOverlapWithMenuBg(int x, int y)
  979. {
  980.     const u16 *metatile = sShopData->tilemapBuffers[0];
  981.     int offset1 = x * 2;
  982.     int offset2 = y * 64;
  983.  
  984.     if (metatile[offset2 + offset1] == 0 &&
  985.         metatile[offset2 + offset1 + 32] == 0 &&
  986.         metatile[offset2 + offset1 + 1] == 0 &&
  987.         metatile[offset2 + offset1 + 33] == 0)
  988.         return TRUE;
  989.  
  990.     return FALSE;
  991. }
  992.  
  993. static void Task_BuyMenu(u8 taskId)
  994. {
  995.     s16 *data = gTasks[taskId].data;
  996.  
  997.     if (!gPaletteFade.active)
  998.     {
  999.         s32 itemId = ListMenu_ProcessInput(tListTaskId);
  1000.         ListMenuGetScrollAndRow(tListTaskId, &sShopData->scrollOffset, &sShopData->selectedRow);
  1001.  
  1002.         switch (itemId)
  1003.         {
  1004.         case LIST_NOTHING_CHOSEN:
  1005.             break;
  1006.         case LIST_CANCEL:
  1007.             PlaySE(SE_SELECT);
  1008.             ExitBuyMenu(taskId);
  1009.             break;
  1010.         default:
  1011.             PlaySE(SE_SELECT);
  1012.             tItemId = itemId;
  1013.             ClearWindowTilemap(WIN_ITEM_DESCRIPTION);
  1014.             BuyMenuRemoveScrollIndicatorArrows();
  1015.             BuyMenuPrintCursor(tListTaskId, COLORID_GRAY_CURSOR);
  1016.  
  1017.             if (sMartInfo.martType == MART_TYPE_VARIABLE)
  1018.                 sShopData->totalCost = SearchItemListForPrice(itemId);
  1019.             else if(sMartInfo.martType == MART_TYPE_NORMAL)
  1020.                 sShopData->totalCost = (ItemId_GetPrice(itemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT));
  1021.             else
  1022.                 sShopData->totalCost = gDecorations[itemId].price;
  1023.  
  1024.             if (!IsEnoughMoney(&gSaveBlock1Ptr->money, sShopData->totalCost))
  1025.             {
  1026.                 BuyMenuDisplayMessage(taskId, gText_YouDontHaveMoney, BuyMenuReturnToItemList);
  1027.             }
  1028.             else if (ItemId_GetPocket(itemId) == POCKET_TM_HM && CheckBagHasItem(itemId, 1))
  1029.             {
  1030.                 BuyMenuDisplayMessage(taskId, gText_YouAlreadyHaveThis, BuyMenuReturnToItemList);
  1031.             }
  1032.             else
  1033.             {
  1034.                 if ((sMartInfo.martType == MART_TYPE_NORMAL) || (sMartInfo.martType == MART_TYPE_VARIABLE))
  1035.                 {
  1036.                     CopyItemName(itemId, gStringVar1);
  1037.                     if (ItemId_GetPocket(itemId) == POCKET_TM_HM)
  1038.                     {
  1039.                         StringCopy(gStringVar2, gMoveNames[ItemIdToBattleMoveId(itemId)]);
  1040.                         BuyMenuDisplayMessage(taskId, gText_Var1CertainlyHowMany2, Task_BuyHowManyDialogueInit);
  1041.                     }
  1042.                     else
  1043.                     {
  1044.                         BuyMenuDisplayMessage(taskId, gText_Var1CertainlyHowMany, Task_BuyHowManyDialogueInit);
  1045.                     }
  1046.                 }
  1047.                 else
  1048.                 {
  1049.                     StringCopy(gStringVar1, gDecorations[itemId].name);
  1050.                     ConvertIntToDecimalStringN(gStringVar2, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6);
  1051.  
  1052.                     if (sMartInfo.martType == MART_TYPE_DECOR)
  1053.                         StringExpandPlaceholders(gStringVar4, gText_Var1IsItThatllBeVar2);
  1054.                     else // MART_TYPE_DECOR2
  1055.                         StringExpandPlaceholders(gStringVar4, gText_YouWantedVar1ThatllBeVar2);
  1056.  
  1057.                     BuyMenuDisplayMessage(taskId, gStringVar4, BuyMenuConfirmPurchase);
  1058.                 }
  1059.             }
  1060.             break;
  1061.         }
  1062.     }
  1063. }
  1064.  
  1065. static void Task_BuyHowManyDialogueInit(u8 taskId)
  1066. {
  1067.     s16 *data = gTasks[taskId].data;
  1068.  
  1069.     u16 quantityInBag = CountTotalItemQuantityInBag(tItemId);
  1070.     u16 maxQuantity;
  1071.  
  1072.     DrawStdFrameWithCustomTileAndPalette(WIN_QUANTITY_IN_BAG, FALSE, 1, 13);
  1073.     ConvertIntToDecimalStringN(gStringVar1, quantityInBag, STR_CONV_MODE_RIGHT_ALIGN, MAX_ITEM_DIGITS + 1);
  1074.     StringExpandPlaceholders(gStringVar4, gText_InBagVar1);
  1075.     BuyMenuPrint(WIN_QUANTITY_IN_BAG, gStringVar4, 0, 1, 0, COLORID_NORMAL);
  1076.     tItemCount = 1;
  1077.     DrawStdFrameWithCustomTileAndPalette(WIN_QUANTITY_PRICE, FALSE, 1, 13);
  1078.     BuyMenuPrintItemQuantityAndPrice(taskId);
  1079.     ScheduleBgCopyTilemapToVram(0);
  1080.  
  1081.     maxQuantity = GetMoney(&gSaveBlock1Ptr->money) / sShopData->totalCost;
  1082.  
  1083.     if (maxQuantity > MAX_BAG_ITEM_CAPACITY)
  1084.         sShopData->maxQuantity = MAX_BAG_ITEM_CAPACITY;
  1085.     else
  1086.         sShopData->maxQuantity = maxQuantity;
  1087.  
  1088.     gTasks[taskId].func = Task_BuyHowManyDialogueHandleInput;
  1089. }
  1090.  
  1091. static void Task_BuyHowManyDialogueHandleInput(u8 taskId)
  1092. {
  1093.     s16 *data = gTasks[taskId].data;
  1094.  
  1095.     if (AdjustQuantityAccordingToDPadInput(&tItemCount, sShopData->maxQuantity) == TRUE)
  1096.     {
  1097.         if(sMartInfo.martType == MART_TYPE_VARIABLE)
  1098.             sShopData->totalCost = SearchItemListForPrice(tItemId) * tItemCount;
  1099.         else
  1100.             sShopData->totalCost = (ItemId_GetPrice(tItemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT)) * tItemCount;
  1101.         BuyMenuPrintItemQuantityAndPrice(taskId);
  1102.     }
  1103.     else
  1104.     {
  1105.         if (JOY_NEW(A_BUTTON))
  1106.         {
  1107.             PlaySE(SE_SELECT);
  1108.             ClearStdWindowAndFrameToTransparent(WIN_QUANTITY_PRICE, FALSE);
  1109.             ClearStdWindowAndFrameToTransparent(WIN_QUANTITY_IN_BAG, FALSE);
  1110.             ClearWindowTilemap(WIN_QUANTITY_PRICE);
  1111.             ClearWindowTilemap(WIN_QUANTITY_IN_BAG);
  1112.             PutWindowTilemap(WIN_ITEM_LIST);
  1113.             CopyItemName(tItemId, gStringVar1);
  1114.             ConvertIntToDecimalStringN(gStringVar2, tItemCount, STR_CONV_MODE_LEFT_ALIGN, BAG_ITEM_CAPACITY_DIGITS);
  1115.             ConvertIntToDecimalStringN(gStringVar3, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6);
  1116.             BuyMenuDisplayMessage(taskId, gText_Var1AndYouWantedVar2, BuyMenuConfirmPurchase);
  1117.         }
  1118.         else if (JOY_NEW(B_BUTTON))
  1119.         {
  1120.             PlaySE(SE_SELECT);
  1121.             ClearStdWindowAndFrameToTransparent(WIN_QUANTITY_PRICE, FALSE);
  1122.             ClearStdWindowAndFrameToTransparent(WIN_QUANTITY_IN_BAG, FALSE);
  1123.             ClearWindowTilemap(WIN_QUANTITY_PRICE);
  1124.             ClearWindowTilemap(WIN_QUANTITY_IN_BAG);
  1125.             BuyMenuReturnToItemList(taskId);
  1126.         }
  1127.     }
  1128. }
  1129.  
  1130. static void BuyMenuConfirmPurchase(u8 taskId)
  1131. {
  1132.     CreateYesNoMenuWithCallbacks(taskId, &sShopBuyMenuYesNoWindowTemplates, 1, 0, 0, 1, 13, &sShopPurchaseYesNoFuncs);
  1133. }
  1134.  
  1135. static void BuyMenuTryMakePurchase(u8 taskId)
  1136. {
  1137.     s16 *data = gTasks[taskId].data;
  1138.  
  1139.     PutWindowTilemap(WIN_ITEM_LIST);
  1140.  
  1141.     if (sMartInfo.martType == MART_TYPE_NORMAL || sMartInfo.martType == MART_TYPE_VARIABLE)
  1142.     {
  1143.         if (AddBagItem(tItemId, tItemCount) == TRUE)
  1144.         {
  1145.             BuyMenuDisplayMessage(taskId, gText_HereYouGoThankYou, BuyMenuSubtractMoney);
  1146.             RecordItemPurchase(taskId);
  1147.         }
  1148.         else
  1149.         {
  1150.             BuyMenuDisplayMessage(taskId, gText_NoMoreRoomForThis, BuyMenuReturnToItemList);
  1151.         }
  1152.     }
  1153.     else
  1154.     {
  1155.         if (DecorationAdd(tItemId))
  1156.         {
  1157.             if (sMartInfo.martType == MART_TYPE_DECOR)
  1158.                 BuyMenuDisplayMessage(taskId, gText_ThankYouIllSendItHome, BuyMenuSubtractMoney);
  1159.             else // MART_TYPE_DECOR2
  1160.                 BuyMenuDisplayMessage(taskId, gText_ThanksIllSendItHome, BuyMenuSubtractMoney);
  1161.         }
  1162.         else
  1163.         {
  1164.             BuyMenuDisplayMessage(taskId, gText_SpaceForVar1Full, BuyMenuReturnToItemList);
  1165.         }
  1166.     }
  1167. }
  1168.  
  1169. static void BuyMenuSubtractMoney(u8 taskId)
  1170. {
  1171.     IncrementGameStat(GAME_STAT_SHOPPED);
  1172.     RemoveMoney(&gSaveBlock1Ptr->money, sShopData->totalCost);
  1173.     PlaySE(SE_SHOP);
  1174.     PrintMoneyAmountInMoneyBox(WIN_MONEY, GetMoney(&gSaveBlock1Ptr->money), 0);
  1175.  
  1176.     if (sMartInfo.martType == MART_TYPE_NORMAL || sMartInfo.martType == MART_TYPE_VARIABLE)
  1177.         gTasks[taskId].func = Task_ReturnToItemListAfterItemPurchase;
  1178.     else
  1179.         gTasks[taskId].func = Task_ReturnToItemListAfterDecorationPurchase;
  1180. }
  1181.  
  1182. static void Task_ReturnToItemListAfterItemPurchase(u8 taskId)
  1183. {
  1184.     s16 *data = gTasks[taskId].data;
  1185.  
  1186.     if (JOY_NEW(A_BUTTON | B_BUTTON))
  1187.     {
  1188.         PlaySE(SE_SELECT);
  1189.  
  1190.         // Purchasing 10+ Poke Balls gets the player a Premier Ball
  1191.         if (tItemId == ITEM_POKE_BALL && tItemCount >= 10 && AddBagItem(ITEM_PREMIER_BALL, 1) == TRUE)
  1192.             BuyMenuDisplayMessage(taskId, gText_ThrowInPremierBall, BuyMenuReturnToItemList);
  1193.         else
  1194.             BuyMenuReturnToItemList(taskId);
  1195.     }
  1196. }
  1197.  
  1198. static void Task_ReturnToItemListAfterDecorationPurchase(u8 taskId)
  1199. {
  1200.     if (JOY_NEW(A_BUTTON | B_BUTTON))
  1201.     {
  1202.         PlaySE(SE_SELECT);
  1203.         BuyMenuReturnToItemList(taskId);
  1204.     }
  1205. }
  1206.  
  1207. static void BuyMenuReturnToItemList(u8 taskId)
  1208. {
  1209.     s16 *data = gTasks[taskId].data;
  1210.  
  1211.     ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE);
  1212.     BuyMenuPrintCursor(tListTaskId, COLORID_ITEM_LIST);
  1213.     PutWindowTilemap(WIN_ITEM_LIST);
  1214.     PutWindowTilemap(WIN_ITEM_DESCRIPTION);
  1215.     ScheduleBgCopyTilemapToVram(0);
  1216.     BuyMenuAddScrollIndicatorArrows();
  1217.     gTasks[taskId].func = Task_BuyMenu;
  1218. }
  1219.  
  1220. static void BuyMenuPrintItemQuantityAndPrice(u8 taskId)
  1221. {
  1222.     s16 *data = gTasks[taskId].data;
  1223.  
  1224.     FillWindowPixelBuffer(WIN_QUANTITY_PRICE, PIXEL_FILL(1));
  1225.     PrintMoneyAmount(WIN_QUANTITY_PRICE, 38, 1, sShopData->totalCost, TEXT_SKIP_DRAW);
  1226.     ConvertIntToDecimalStringN(gStringVar1, tItemCount, STR_CONV_MODE_LEADING_ZEROS, BAG_ITEM_CAPACITY_DIGITS);
  1227.     StringExpandPlaceholders(gStringVar4, gText_xVar1);
  1228.     BuyMenuPrint(WIN_QUANTITY_PRICE, gStringVar4, 0, 1, 0, COLORID_NORMAL);
  1229. }
  1230.  
  1231. static void ExitBuyMenu(u8 taskId)
  1232. {
  1233.     gFieldCallback = MapPostLoadHook_ReturnToShopMenu;
  1234.     BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
  1235.     gTasks[taskId].func = Task_ExitBuyMenu;
  1236. }
  1237.  
  1238. static void Task_ExitBuyMenu(u8 taskId)
  1239. {
  1240.     if (!gPaletteFade.active)
  1241.     {
  1242.         RemoveMoneyLabelObject();
  1243.         BuyMenuFreeMemory();
  1244.         SetMainCallback2(CB2_ReturnToField);
  1245.         DestroyTask(taskId);
  1246.     }
  1247. }
  1248.  
  1249. static void ClearItemPurchases(void)
  1250. {
  1251.     sPurchaseHistoryId = 0;
  1252.     memset(gMartPurchaseHistory, 0, sizeof(gMartPurchaseHistory));
  1253. }
  1254.  
  1255. static void RecordItemPurchase(u8 taskId)
  1256. {
  1257.     s16 *data = gTasks[taskId].data;
  1258.  
  1259.     u16 i;
  1260.  
  1261.     for (i = 0; i < ARRAY_COUNT(gMartPurchaseHistory); i++)
  1262.     {
  1263.         if (gMartPurchaseHistory[i].itemId == tItemId && gMartPurchaseHistory[i].quantity != 0)
  1264.         {
  1265.             if (gMartPurchaseHistory[i].quantity + tItemCount > 255)
  1266.                 gMartPurchaseHistory[i].quantity = 255;
  1267.             else
  1268.                 gMartPurchaseHistory[i].quantity += tItemCount;
  1269.             return;
  1270.         }
  1271.     }
  1272.  
  1273.     if (sPurchaseHistoryId < ARRAY_COUNT(gMartPurchaseHistory))
  1274.     {
  1275.         gMartPurchaseHistory[sPurchaseHistoryId].itemId = tItemId;
  1276.         gMartPurchaseHistory[sPurchaseHistoryId].quantity = tItemCount;
  1277.         sPurchaseHistoryId++;
  1278.     }
  1279. }
  1280.  
  1281. #undef tItemCount
  1282. #undef tItemId
  1283. #undef tListTaskId
  1284. #undef tCallbackHi
  1285. #undef tCallbackLo
  1286.  
  1287. void CreatePokemartMenu(const u16 *itemsForSale)
  1288. {
  1289.     CreateShopMenu(MART_TYPE_NORMAL);
  1290.     SetShopItemsForSale(itemsForSale);
  1291.     ClearItemPurchases();
  1292.     SetShopMenuCallback(ScriptContext_Enable);
  1293. }
  1294.  
  1295. void CreateVariablePokemartMenu(const u16 *itemsForSale)
  1296. {
  1297.     CreateShopMenu(MART_TYPE_VARIABLE);
  1298.     SetShopItemsForSale(itemsForSale);
  1299.     ClearItemPurchases();
  1300.     SetShopMenuCallback(ScriptContext_Enable);
  1301. }
  1302.  
  1303. void CreateDecorationShop1Menu(const u16 *itemsForSale)
  1304. {
  1305.     CreateShopMenu(MART_TYPE_DECOR);
  1306.     SetShopItemsForSale(itemsForSale);
  1307.     SetShopMenuCallback(ScriptContext_Enable);
  1308. }
  1309.  
  1310. void CreateDecorationShop2Menu(const u16 *itemsForSale)
  1311. {
  1312.     CreateShopMenu(MART_TYPE_DECOR2);
  1313.     SetShopItemsForSale(itemsForSale);
  1314.     SetShopMenuCallback(ScriptContext_Enable);
  1315. }
  1316.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement