diff options
author | PikalaxALT <pikalaxalt@gmail.com> | 2018-03-31 14:37:24 -0400 |
---|---|---|
committer | PikalaxALT <pikalaxalt@gmail.com> | 2018-03-31 14:37:24 -0400 |
commit | 0015d6fe2c6a53c5f757599122ae9fd1a156a69f (patch) | |
tree | 81b7269c767da1ad4a5a9ac01e58ead5e92f0983 /src/field/shop.c | |
parent | 46bc01f0dd1a3435b3c6ce71e1be0d19b7aaa5bd (diff) | |
parent | 59f81c5f2a25ec77baf4a30c3da9ccb7675d1562 (diff) |
Merge branch 'master' into contest_link_80C2020
Diffstat (limited to 'src/field/shop.c')
-rw-r--r-- | src/field/shop.c | 1240 |
1 files changed, 0 insertions, 1240 deletions
diff --git a/src/field/shop.c b/src/field/shop.c deleted file mode 100644 index e087628da..000000000 --- a/src/field/shop.c +++ /dev/null @@ -1,1240 +0,0 @@ -#include "global.h" -#include "shop.h" -#include "decompress.h" -#include "field_fadetransition.h" -#include "field_weather.h" -#include "item_menu.h" -#include "main.h" -#include "menu.h" -#include "menu_helpers.h" -#include "money.h" -#include "palette.h" -#include "script.h" -#include "sound.h" -#include "sprite.h" -#include "strings.h" -#include "task.h" -#include "tv.h" -#include "scanline_effect.h" -#include "field_map_obj.h" -#include "field_player_avatar.h" -#include "fieldmap.h" -#include "item.h" -#include "decoration.h" -#include "constants/items.h" -#include "constants/songs.h" -#include "overworld.h" -#include "decoration_inventory.h" -#include "field_camera.h" -#include "ewram.h" - -extern bool8 SellMenu_QuantityRoller(u8, u8); - -extern u8 gBuyMenuFrame_Gfx[]; -extern u16 gBuyMenuFrame_Tilemap[]; -extern u16 gMenuMoneyPal[16]; - -static void Shop_DisplayPriceInList(int firstItemId, int lastItemId, bool32 hasControlCode); -static void Shop_PrintItemDescText(void); -static void Task_ReturnToBuyMenu(u8); -static void Task_ExitBuyMenu(u8); -static void Task_ExitBuyMenuDoFade(u8); -static void Task_UpdatePurchaseHistory(u8); -static void Task_HandleShopMenuBuy(u8 taskId); -static void Task_HandleShopMenuSell(u8 taskId); -static void Task_HandleShopMenuQuit(u8 taskId); -static void Task_DoItemPurchase(u8 taskId); -static void Task_CancelItemPurchase(u8 taskId); -static void Task_DoBuySellMenu(u8); -static void Shop_FadeAndRunBuySellCallback(u8); -static void BuyMenuDrawGraphics(void); -static void sub_80B3240(void); -static void DrawFirstMartScrollIndicators(void); -static void Shop_DrawViewport(void); -static void Shop_InitMenus(int, int); -static void Shop_PrintItemDesc(void); -static void Shop_DoCursorAction(u8); -static void Shop_LoadViewportObjects(void); -static void Shop_AnimViewportObjects(void); - -// iwram -static struct MartInfo gMartInfo; - -// ewram -EWRAM_DATA u32 gMartTotalCost = 0; -EWRAM_DATA s16 gMartViewportObjects[16][4] = {0}; -EWRAM_DATA struct ItemSlot gMartPurchaseHistory[3] = {0}; -EWRAM_DATA u8 gMartPurchaseHistoryId = 0; - -EWRAM_DATA u8 gUnknown_02038731 = 0; // This really should be in fldeff_escalator, but being in a new file aligns the ewram, which doesnt match the ROM. - -// rodata -static const struct MenuAction2 sBuySellQuitMenuActions[] = -{ - { MartText_Buy, Task_HandleShopMenuBuy }, - { MartText_Sell, Task_HandleShopMenuSell }, - { MartText_Quit2, Task_HandleShopMenuQuit }, -}; - -static const u8 gMartBuySellOptionList[] = {SHOP_BUY, SHOP_SELL, SHOP_EXIT}; -static const u8 gMartBuyNoSellOptionList[] = {SHOP_BUY, SHOP_EXIT}; - -static const u16 gUnusedMartArray[] = {0x2, 0x3, 0x4, 0xD, 0x121, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0x0, 0x0}; - -static const struct YesNoFuncTable sShopPurchaseYesNoFuncs[] = -{ - Task_DoItemPurchase, - Task_CancelItemPurchase -}; - -static u8 CreateShopMenu(u8 martType) -{ - ScriptContext2_Enable(); - gMartInfo.martType = martType; - gMartInfo.cursor = 0; - - if (martType == MART_TYPE_0) - { - gMartInfo.numChoices = 2; - Menu_DrawStdWindowFrame(0, 0, 10, 7); - Menu_PrintItemsReordered(1, 1, 3, sBuySellQuitMenuActions, gMartBuySellOptionList); - } - else - { - gMartInfo.numChoices = 1; - Menu_DrawStdWindowFrame(0, 0, 10, 5); - Menu_PrintItemsReordered(1, 1, 2, sBuySellQuitMenuActions, gMartBuyNoSellOptionList); - } - InitMenu(0, 1, 1, gMartInfo.numChoices + 1, 0, 9); // add 1 for cancel - - return CreateTask(Task_DoBuySellMenu, 8); -} - -static void SetShopMenuCallback(void *callbackPtr) -{ - gMartInfo.callback = callbackPtr; -} - -static void SetShopItemsForSale(u16 *items) -{ - u16 i = 0; - - gMartInfo.itemList = items; - gMartInfo.itemCount = 0; - - while (gMartInfo.itemList[i]) - { - gMartInfo.itemCount++; - i++; - } -} - -static void Task_DoBuySellMenu(u8 taskId) -{ - const u8 taskIdConst = taskId; // why is a local const needed to match? - - if (gMain.newAndRepeatedKeys & DPAD_UP) - { - if (gMartInfo.cursor) // can move cursor up? - { - PlaySE(SE_SELECT); - gMartInfo.cursor = Menu_MoveCursor(-1); - } - } - else if (gMain.newAndRepeatedKeys & DPAD_DOWN) - { - if (gMartInfo.cursor != gMartInfo.numChoices) // can move cursor down? - { - PlaySE(SE_SELECT); - gMartInfo.cursor = Menu_MoveCursor(1); - } - } - else if (gMain.newKeys & A_BUTTON) - { - PlaySE(SE_SELECT); - if (gMartInfo.martType == MART_TYPE_0) - { - sBuySellQuitMenuActions[gMartBuySellOptionList[gMartInfo.cursor]].func(taskIdConst); - } - else - { - sBuySellQuitMenuActions[gMartBuyNoSellOptionList[gMartInfo.cursor]].func(taskIdConst); - } - } - else if (gMain.newKeys & B_BUTTON) - { - PlaySE(SE_SELECT); - Task_HandleShopMenuQuit(taskIdConst); - } -} - -static void Task_HandleShopMenuBuy(u8 taskId) -{ - gTasks[taskId].data[8] = (u32)BuyMenuDrawGraphics >> 16; - gTasks[taskId].data[9] = (u32)BuyMenuDrawGraphics; - gTasks[taskId].func = Shop_FadeAndRunBuySellCallback; - FadeScreen(1, 0); -} - -static void Task_HandleShopMenuSell(u8 taskId) -{ - gTasks[taskId].data[8] = (u32)ItemMenu_LoadSellMenu >> 16; - gTasks[taskId].data[9] = (u32)ItemMenu_LoadSellMenu; - gTasks[taskId].func = Shop_FadeAndRunBuySellCallback; - FadeScreen(1, 0); -} - -static void Task_HandleShopMenuQuit(u8 taskId) -{ - Menu_DestroyCursor(); - Menu_EraseWindowRect(0, 0, 11, 8); - sub_80BE3BC(); - ScriptContext2_Disable(); - DestroyTask(taskId); - - if (gMartInfo.callback) - gMartInfo.callback(); // run the callback if it exists. -} - -static void Shop_FadeAndRunBuySellCallback(u8 taskId) -{ - if (!gPaletteFade.active) - { - SetMainCallback2((void *)((u16)gTasks[taskId].data[8] << 16 | (u16)gTasks[taskId].data[9])); - DestroyTask(taskId); - } -} - -static void ReturnToShopMenuAfterExitingSellMenu(u8 taskId) -{ - CreateShopMenu(gMartInfo.martType); - DestroyTask(taskId); -} - -static void Task_ReturnToMartMenu(u8 taskId) -{ - if (IsWeatherNotFadingIn() == 1) - { - if (gMartInfo.martType == MART_TYPE_2) - DisplayItemMessageOnField(taskId, gOtherText_CanIHelpYou, ReturnToShopMenuAfterExitingSellMenu, 0); - else - DisplayItemMessageOnField(taskId, gOtherText_AnythingElse, ReturnToShopMenuAfterExitingSellMenu, 0); - } -} - -void Shop_FadeReturnToMartMenu(void) -{ - pal_fill_black(); - CreateTask(Task_ReturnToMartMenu, 0x8); -} - -void Shop_RunExitSellMenuTask(u8 taskId) -{ - Task_ReturnToMartMenu(taskId); -} - -// unused -void Shop_LoadExitSellMenuTask(u8 taskId) -{ - gTasks[taskId].func = Task_ReturnToMartMenu; -} - -static void MainCB2(void) -{ - AnimateSprites(); - BuildOamBuffer(); - RunTasks(); - UpdatePaletteFade(); -} - -static void VBlankCB(void) -{ - LoadOam(); - ProcessSpriteCopyRequests(); - TransferPlttBuffer(); - DmaCopy16Defvars(3, gBGTilemapBuffers[1], (void *)(VRAM + 0xE800), 0x800); - DmaCopy16Defvars(3, gBGTilemapBuffers[2], (void *)(VRAM + 0xE000), 0x800); - DmaCopy16Defvars(3, gBGTilemapBuffers[3], (void *)(VRAM + 0xF000), 0x800); -} - -static void BuyMenuDrawGraphics(void) -{ - ClearVideoCallbacks(); - ScanlineEffect_Stop(); - REG_BG1HOFS = 0; - REG_BG1VOFS = 0; - REG_BG2HOFS = 0; - REG_BG2VOFS = 0; - REG_BG3HOFS = 0; - REG_BG3VOFS = 0; - gPaletteFade.bufferTransferDisabled = 1; - - /* - THEORY: This seemingly useless loop is required in order to match this - function without hacks. The reason is because it alters the 0 optimization - of a later assignment into using 2 different 0s instead of the same register. - It is speculated that at some point Game Freak insert an artificial - breakpoint here in order to look at the contents of OAM before it is cleared, - possibly because a programmer made a mistake in shop.c which corrupted its - contents. There may have been a macro here which at one point idled on the - while(1) but was changed to 0 for release due to a define somewhere. A - while(0) also matches, but it is more correct to use do {} while(0) as it - was a fix to prevent compiler warnings on older compilers. - */ - do {} while(0); - - DmaFill32Defvars(3, 0, (void*)OAM, OAM_SIZE); - LZDecompressVram(gBuyMenuFrame_Gfx, (void*)(VRAM + 0x7C00)); - LZDecompressWram(gBuyMenuFrame_Tilemap, ewram18000_2); - LoadCompressedPalette(gMenuMoneyPal, 0xC0, sizeof(gMenuMoneyPal)); - FreeAllSpritePalettes(); - ResetPaletteFade(); - ResetSpriteData(); - ResetTasks(); - Text_LoadWindowTemplate(&gWindowTemplate_81E6DFC); - InitMenuWindow(&gWindowTemplate_81E6DFC); - Shop_DrawViewport(); - gMartInfo.cursor = 0; - gMartInfo.choicesAbove = 0; - Menu_EraseWindowRect(0, 0, 0x20, 0x20); - OpenMoneyWindow(gSaveBlock1.money, 0, 0); - Shop_InitMenus(0, 7); - Shop_PrintItemDesc(); - DrawFirstMartScrollIndicators(); - CreateTask(Shop_DoCursorAction, 0x8); - sub_80B3240(); - BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); - gPaletteFade.bufferTransferDisabled = 0; - SetVBlankCallback(VBlankCB); - SetMainCallback2(MainCB2); -} - -static void sub_80B3240(void) -{ - u16 colors[2] = {RGB(14, 15, 16), RGB_WHITE}; - - LoadPalette(&colors[1], 0xD1, sizeof colors[1]); - LoadPalette(&colors[0], 0xD8, sizeof colors[0]); -} - -static void DrawFirstMartScrollIndicators(void) -{ - ClearVerticalScrollIndicatorPalettes(); - - if (gMartInfo.itemCount > 7) - { - CreateVerticalScrollIndicators(TOP_ARROW, 172, 12); - CreateVerticalScrollIndicators(BOTTOM_ARROW, 172, 148); - SetVerticalScrollIndicators(TOP_ARROW, INVISIBLE); - } -} - -static void Shop_TryDrawVerticalScrollIndicators(void) -{ - if (gMartInfo.choicesAbove == 0) - SetVerticalScrollIndicators(TOP_ARROW, INVISIBLE); - else - SetVerticalScrollIndicators(TOP_ARROW, VISIBLE); - - if (gMartInfo.choicesAbove + 7 >= gMartInfo.itemCount) - SetVerticalScrollIndicators(BOTTOM_ARROW, INVISIBLE); - else - SetVerticalScrollIndicators(BOTTOM_ARROW, VISIBLE); -} - -// what is the point of this function? the tiles always get overwritten by BuyMenuDrawTextboxBG. -static void BuyMenuDrawTextboxBG_Old(u16 *array, s16 offset1, s16 offset2) -{ - array[offset1 + offset2] = 0xC3E1; - array[offset1 + offset2 + 1] = 0xC3E1; -} - -static void BuyMenuDrawMapMetatileLayer(u16 *array, s16 offset1, s16 offset2, u16 *array2) -{ - // This function draws a whole 2x2 metatile. - array[offset1 + offset2] = array2[0]; // top left - array[offset1 + offset2 + 1] = array2[1]; // top right - array[offset1 + offset2 + 32] = array2[2]; // bottom left - array[offset1 + offset2 + 33] = array2[3]; // bottom right -} - -static void BuyMenuDrawMapMetatile(int var1, int var2, u16 *var3, s32 var4) -{ - u8 tempVar4 = var4; - s16 offset1 = var1 * 2; - s16 offset2 = (var2 * 0x40) + 0x40; - - switch (tempVar4) - { - case 0: // _080B335C - BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[2], offset1, offset2, var3); - BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[1], offset1, offset2, var3 + 4); - break; - case 1: // _080B3364 - BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[3], offset1, offset2, var3); - BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[2], offset1, offset2, var3 + 4); - break; - case 2: // _080B3398 - BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[3], offset1, offset2, var3); - BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[1], offset1, offset2, var3 + 4); - break; - } -} - -// used to draw the border tiles around the viewport. -static void BuyMenuDrawMapPartialMetatile(s16 var1, int var2, u16 *var3) -{ - s16 offset1 = var1 * 2; - s16 offset2 = (var2 * 0x40) + 0x40; - - BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[3], offset1, offset2, var3); - BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[2], offset1, offset2, var3 + 4); -} - -static void Shop_DrawViewportTiles(void) -{ - s16 facingX; - s16 facingY; - s16 x; - s16 y; - - GetXYCoordsOneStepInFrontOfPlayer(&facingX, &facingY); - facingX -= 3; - facingY -= 3; - - for (y = 0; y < 6; y++) - { - for (x = 0; x < 7; x++) - { - u16 metatileId = MapGridGetMetatileIdAt(facingX + x, facingY + y); - - if (y != 5 && x != 6) - { - s32 r3 = MapGridGetMetatileLayerTypeAt(facingX + x, facingY + y); - - if (metatileId < 512) - BuyMenuDrawMapMetatile(x, y, (u16 *)gMapHeader.mapData->primaryTileset->metatiles + metatileId * 8, r3); - else - BuyMenuDrawMapMetatile(x, y, (u16 *)gMapHeader.mapData->secondaryTileset->metatiles + (metatileId - 512) * 8, r3); - } - else - { - if (metatileId < 512) - BuyMenuDrawMapPartialMetatile(x, y, (u16 *)gMapHeader.mapData->primaryTileset->metatiles + metatileId * 8); - else - BuyMenuDrawMapPartialMetatile(x, y, (u16 *)gMapHeader.mapData->secondaryTileset->metatiles + (metatileId - 512) * 8); - } - - if (y == 0 && x != 0 && x != 6) - BuyMenuDrawTextboxBG_Old(gBGTilemapBuffers[1], x * 2, 64); - } - } -} - -static void Shop_DrawViewport(void) -{ - ClearBGTilemapBuffers(); - Shop_LoadViewportObjects(); - Shop_AnimViewportObjects(); - Shop_DrawViewportTiles(); -} - -static void Shop_LoadViewportObjects(void) -{ - s16 facingX; - s16 facingY; - u8 playerHeight; - u8 y; - u8 x; - u8 r8 = 0; - - GetXYCoordsOneStepInFrontOfPlayer(&facingX, &facingY); - playerHeight = PlayerGetZCoord(); - for (y = 0; y < 16; y++) - gMartViewportObjects[y][MAP_OBJ_ID] = 16; - for (y = 0; y < 5; y++) - { - for (x = 0; x < 7; x++) - { - u8 mapObjId = GetFieldObjectIdByXYZ(facingX - 3 + x, facingY - 2 + y, playerHeight); - - if (mapObjId != 16) - { - gMartViewportObjects[r8][MAP_OBJ_ID] = mapObjId; - gMartViewportObjects[r8][X_COORD] = x; - gMartViewportObjects[r8][Y_COORD] = y; - if (gMapObjects[mapObjId].mapobj_unk_18 == 1) - gMartViewportObjects[r8][ANIM_NUM] = 0; - if (gMapObjects[mapObjId].mapobj_unk_18 == 2) - gMartViewportObjects[r8][ANIM_NUM] = 1; - if (gMapObjects[mapObjId].mapobj_unk_18 == 3) - gMartViewportObjects[r8][ANIM_NUM] = 2; - if (gMapObjects[mapObjId].mapobj_unk_18 == 4) - gMartViewportObjects[r8][ANIM_NUM] = 3; - r8++; - } - } - } -} - -static void Shop_AnimViewportObjects(void) -{ - u8 i; - - for (i = 0; i < 16; i++) // max objects? - { - if (gMartViewportObjects[i][MAP_OBJ_ID] == 16) - continue; - - StartSpriteAnim(&gSprites[AddPseudoFieldObject( - gMapObjects[gMartViewportObjects[i][MAP_OBJ_ID]].graphicsId, - SpriteCallbackDummy, - (u16)gMartViewportObjects[i][X_COORD] * 16 + 8, - (u16)gMartViewportObjects[i][Y_COORD] * 16 + 32, - 2)], - gMartViewportObjects[i][ANIM_NUM]); - } -} - -static void BuyMenuDrawTextboxBG(void) -{ - s16 i; - - for (i = 0; i < 0x400; i++) - { - if (ewram18000[i] != 0) - gBGTilemapBuffers[1][i] = ewram18000[i] + 0xC3E0; - } -} - -static void Shop_InitMenus(int firstItemId, int lastItemId) -{ - BuyMenuDrawTextboxBG(); - Shop_DisplayPriceInList(firstItemId, lastItemId, 0); - InitMenu(0, 0xE, 0x2, 0x8, gMartInfo.cursor, 0xF); -} - -// after printing the item quantity and price, restore the textbox tiles before the Yes/No prompt. -static void BuyMenuDrawTextboxBG_Restore(void) -{ - u16 i, j; - - for (i = 0; i < 8; i++) - for (j = 0; j < 14; j++) - gBGTilemapBuffers[1][32 * (i + 12) + j] = ewram18300[32 * i + j] + 0xC3E0; -} - -static void Shop_PrintItemDesc(void) -{ - Shop_PrintItemDescText(); -} - -#define tItemCount data[1] - -static void Shop_DisplayPriceInCheckoutWindow(u8 taskId) -{ - u16 itemListIndex = gMartInfo.choicesAbove + gMartInfo.cursor; - u16 itemId = gMartInfo.itemList[itemListIndex]; - u32 price = (ItemId_GetPrice(itemId) >> GetPriceReduction(1)); - - PrintMoneyAmount(gTasks[taskId].tItemCount * price, 6, 6, 11); - gStringVar1[0] = EXT_CTRL_CODE_BEGIN; - gStringVar1[1] = 0x14; - gStringVar1[2] = 0x6; - ConvertIntToDecimalStringN(&gStringVar1[3], gTasks[taskId].tItemCount, 1, 2); - Menu_PrintText(gOtherText_xString1, 1, 11); - sub_80A3FA0(gBGTilemapBuffers[1], 1, 11, 12, 2, 0xC3E1); -} - -static void Shop_DisplayNormalPriceInList(u16 itemId, u8 var2, bool32 hasControlCode) -{ - u8 *stringPtr = gStringVar1; - - if (hasControlCode != FALSE) - { - stringPtr[0] = EXT_CTRL_CODE_BEGIN; - stringPtr[1] = 0x1; - stringPtr[2] = 0x2; - stringPtr += 3; - } - - CopyItemName(itemId, stringPtr); - - sub_8072A18(&gStringVar1[0], 0x70, var2 << 3, 0x58, 0x1); - stringPtr = gStringVar1; - - if (hasControlCode != FALSE) - stringPtr = &gStringVar1[3]; - - GetMoneyAmountText(stringPtr, (ItemId_GetPrice(itemId) >> GetPriceReduction(1)), 0x4); - Menu_PrintTextPixelCoords(&gStringVar1[0], 0xCA, var2 << 3, 1); -} - -static void Shop_DisplayDecorationPriceInList(u16 itemId, u8 var2, bool32 hasControlCode) -{ - u8 *stringPtr = gStringVar1; - - if (hasControlCode != FALSE) - { - stringPtr[0] = EXT_CTRL_CODE_BEGIN; - stringPtr[1] = 0x1; - stringPtr[2] = 0x2; - stringPtr += 3; - } - - StringCopy(stringPtr, gDecorations[itemId].name); - sub_8072A18(&gStringVar1[0], 0x70, var2 << 3, 0x58, 0x1); - stringPtr = gStringVar1; - - if (hasControlCode != FALSE) - stringPtr = &gStringVar1[3]; - - // some names are the maximum string length for a shop item. Because there is no room for - // a 6 character price (including the currency), a sprite is instead used for anything that - // is the maximum decoration price in order to fit it on screen. - if (gDecorations[itemId].price == 10000) - { - Draw10000Sprite(0x19, var2, hasControlCode); - } - else - { - GetMoneyAmountText(stringPtr, gDecorations[itemId].price, 0x4); - Menu_PrintTextPixelCoords(&gStringVar1[0], 0xCA, var2 << 3, 0x1); - } -} - -static void Shop_DisplayPriceInList(int firstItemId, int lastItemId, bool32 hasControlCode) -{ - u8 i; - - for (i = firstItemId; i <= lastItemId && gMartInfo.choicesAbove + i < gMartInfo.itemCount; i++) - { - if (gMartInfo.martType == MART_TYPE_0) - Shop_DisplayNormalPriceInList(gMartInfo.itemList[gMartInfo.choicesAbove + i], (i << 1) + 2, hasControlCode); - else - Shop_DisplayDecorationPriceInList(gMartInfo.itemList[gMartInfo.choicesAbove + i], (i << 1) + 2, hasControlCode); - } - - if (i != 8 && gMartInfo.choicesAbove + i == gMartInfo.itemCount) - { - Menu_BlankWindowRect(0xE, (i << 1) + 2, 0x1C, (i << 1) + 3); - Menu_PrintText(gOtherText_CancelNoTerminator, 0xE, (i << 1) + 2); - } -} - -static void Shop_PrintItemDescText(void) -{ - if (gMartInfo.choicesAbove + gMartInfo.cursor != gMartInfo.itemCount) - { - if (gMartInfo.martType == MART_TYPE_0) - { - sub_8072AB0(ItemId_GetDescription(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]), - 0x4, 0x68, 0x68, 0x30, 0); - } - else - sub_8072AB0(gDecorations[gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]].description, - 0x4, 0x68, 0x68, 0x30, 0); - } - else - { - sub_8072AB0(gOtherText_QuitShopping, 0x4, 0x68, 0x68, 0x30, 0); - } -} - -static void Shop_DoPremierBallCheck(u8 taskId) -{ - if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) - { - Shop_DisplayPriceInList(gMartInfo.cursor, gMartInfo.cursor, 0); - PlaySE(SE_SELECT); - - if (gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor] == ITEM_POKE_BALL && gTasks[taskId].tItemCount >= 10 && AddBagItem(ITEM_PREMIER_BALL, 1) == TRUE) - DisplayItemMessageOnField(taskId, gOtherText_FreePremierBall, Task_ReturnToBuyMenu, 0xC3E1); - else - Task_ReturnToBuyMenu(taskId); - } -} - -static void Shop_DoItemTransaction(u8 taskId) -{ - IncrementGameStat(GAME_STAT_SHOPPED); - RemoveMoney(&gSaveBlock1.money, gMartTotalCost); - PlaySE(SE_REGI); - UpdateMoneyWindow(gSaveBlock1.money, 0, 0); - gTasks[taskId].func = Shop_DoPremierBallCheck; -} - -static void Shop_DoPricePrintAndReturnToBuyMenu(u8 taskId) -{ - Shop_DisplayPriceInList(gMartInfo.cursor, gMartInfo.cursor, 0); - Task_ReturnToBuyMenu(taskId); -} - -static void Task_DoItemPurchase(u8 taskId) -{ - Menu_EraseWindowRect(0x7, 0x8, 0xD, 0xD); - sub_80A3FA0(gBGTilemapBuffers[1], 8, 9, 4, 4, 0); - BuyMenuDrawTextboxBG_Restore(); - Shop_DrawViewportTiles(); - - if (IsEnoughMoney(gSaveBlock1.money, gMartTotalCost)) - { - if (gMartInfo.martType == MART_TYPE_0) - { - if (AddBagItem(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor], gTasks[taskId].tItemCount)) - { - DisplayItemMessageOnField(taskId, gOtherText_HereYouGo, Shop_DoItemTransaction, 0xC3E1); - Task_UpdatePurchaseHistory(taskId); - } - else - DisplayItemMessageOnField(taskId, gOtherText_NoRoomFor, Shop_DoPricePrintAndReturnToBuyMenu, 0xC3E1); - } - else // a normal mart is only type 0, so types 1 and 2 are decoration marts. - { - if (IsThereStorageSpaceForDecoration(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor])) - { - if (gMartInfo.martType == MART_TYPE_1) - DisplayItemMessageOnField(taskId, gOtherText_HereYouGo2, Shop_DoItemTransaction, 0xC3E1); - else - DisplayItemMessageOnField(taskId, gOtherText_HereYouGo3, Shop_DoItemTransaction, 0xC3E1); - } - else - { - StringExpandPlaceholders(gStringVar4, gOtherText_SpaceForIsFull); - DisplayItemMessageOnField(taskId, gStringVar4, Shop_DoPricePrintAndReturnToBuyMenu, 0xC3E1); - } - } - } - else - DisplayItemMessageOnField(taskId, gOtherText_NotEnoughMoney, Shop_DoPricePrintAndReturnToBuyMenu, 0xC3E1); -} - -static void Shop_DoYesNoPurchase(u8 taskId) -{ - DisplayYesNoMenu(7, 8, 1); - sub_80A3FA0(gBGTilemapBuffers[1], 8, 9, 4, 4, 0xC3E1); - DoYesNoFuncWithChoice(taskId, sShopPurchaseYesNoFuncs); -} - -static void Task_CancelItemPurchase(u8 taskId) -{ - Shop_DisplayPriceInList(gMartInfo.cursor, gMartInfo.cursor, 0); - Menu_EraseWindowRect(0x7, 0x8, 0xD, 0xD); - sub_80A3FA0(gBGTilemapBuffers[1], 0x8, 0x9, 0x4, 0x4, 0); - Task_ReturnToBuyMenu(taskId); -} - -static void Shop_PrintPrice(u8 taskId) -{ - if (SellMenu_QuantityRoller(taskId, gMartInfo.curItemCount) == TRUE) - Shop_DisplayPriceInCheckoutWindow(taskId); - - if (gMain.newKeys & A_BUTTON) - { - gMartTotalCost = (ItemId_GetPrice(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]) >> GetPriceReduction(1)) * gTasks[taskId].tItemCount; // set total cost of your purchase. - Menu_EraseWindowRect(0, 0xA, 0xD, 0xD); - sub_80A3FA0(gBGTilemapBuffers[1], 0x1, 0xB, 0xC, 0x2, 0); - BuyMenuDrawTextboxBG_Restore(); - Shop_DrawViewportTiles(); - CopyItemName(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor], gStringVar1); - ConvertIntToDecimalStringN(gStringVar2, gTasks[taskId].tItemCount, 0, 0x2); - ConvertIntToDecimalStringN(gStringVar3, gMartTotalCost, 0, 0x8); - StringExpandPlaceholders(gStringVar4, gOtherText_ThatWillBe); - DisplayItemMessageOnField(taskId, gStringVar4, Shop_DoYesNoPurchase, 0xC3E1); - } - else if (gMain.newKeys & B_BUTTON) - { - Shop_DisplayPriceInList(gMartInfo.cursor, gMartInfo.cursor, 0); - Task_ReturnToBuyMenu(taskId); - } -} - -// set the item count in the mart info to the maximum allowed by the player's budget. -static void Shop_UpdateCurItemCountToMax(u8 taskId) -{ - u16 var; - - gTasks[taskId].tItemCount = 1; - Menu_DrawStdWindowFrame(0, 0xA, 0xD, 0xD); - Shop_DisplayPriceInCheckoutWindow(taskId); - - var = gSaveBlock1.money / (ItemId_GetPrice(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]) >> GetPriceReduction(1)); - if (var > 99) - gMartInfo.curItemCount = 99; - else - gMartInfo.curItemCount = var; - - gTasks[taskId].func = Shop_PrintPrice; -} - -#ifdef NONMATCHING -static void Shop_MoveItemListUp(void) -{ - u16 *r1; - u16 *r2; - register u8 *r10 asm("r10"); - s32 i; - s32 j; - struct Window *r8 = &gMenuWindow; - - r1 = r8->tilemap; - r1 += 0x1EF; - r2 = r1; - r2 += 64; - r10 = r8->tileData; - - for (i = 0; i < 14; i++) - { - for (j = 0; j < 15; j++) - { - if ((r1[j] & 0x3FF) <= r8->tileDataStartOffset + 1) - r2[j] = r8->tileDataStartOffset + 1; - else - r2[j] = r1[j] + 0x3C; - } - - r1 -= 32; - r2 -= 32; - } - - { - u8 *r1 = r10 + 0x3A20; - u8 *r2 = r1 + 0x780; - for (i = 0; i < 14; i++) - { - DmaCopy16(3, r1, r2, 0x1E0); - r2 -= 0x3C0; - r1 -= 0x3C0; - } - } -} -#else -__attribute__((naked)) -static void Shop_MoveItemListUp(void) -{ - asm(".syntax unified\n\ - push {r4-r7,lr}\n\ - mov r7, r10\n\ - mov r6, r9\n\ - mov r5, r8\n\ - push {r5-r7}\n\ - sub sp, 0x4\n\ - ldr r0, _080B4020 @ =gMenuWindow\n\ - mov r8, r0\n\ - ldr r1, [r0, 0x28]\n\ - ldr r3, _080B4024 @ =0x000003de\n\ - adds r1, r3\n\ - adds r2, r1, 0\n\ - adds r2, 0x80\n\ - ldr r7, [r0, 0x24]\n\ - mov r10, r7\n\ - ldr r0, _080B4028 @ =0x000003ff\n\ - mov r9, r0\n\ - movs r6, 0xD\n\ -_080B3FAC:\n\ - adds r3, r2, 0\n\ - subs r3, 0x40\n\ - str r3, [sp]\n\ - movs r7, 0x40\n\ - negs r7, r7\n\ - adds r7, r1\n\ - mov r12, r7\n\ - adds r3, r2, 0\n\ - adds r4, r1, 0\n\ - movs r5, 0xE\n\ -_080B3FC0:\n\ - ldrh r2, [r4]\n\ - mov r1, r9\n\ - ands r1, r2\n\ - mov r7, r8\n\ - ldrh r0, [r7, 0x1A]\n\ - adds r0, 0x1\n\ - cmp r1, r0\n\ - ble _080B3FD4\n\ - adds r0, r2, 0\n\ - adds r0, 0x3C\n\ -_080B3FD4:\n\ - strh r0, [r3]\n\ - adds r3, 0x2\n\ - adds r4, 0x2\n\ - subs r5, 0x1\n\ - cmp r5, 0\n\ - bge _080B3FC0\n\ - ldr r2, [sp]\n\ - mov r1, r12\n\ - subs r6, 0x1\n\ - cmp r6, 0\n\ - bge _080B3FAC\n\ - ldr r1, _080B402C @ =0x00003a20\n\ - add r1, r10\n\ - movs r0, 0xF0\n\ - lsls r0, 3\n\ - adds r2, r1, r0\n\ - ldr r3, _080B4030 @ =0x040000d4\n\ - ldr r5, _080B4034 @ =0x800000f0\n\ - ldr r4, _080B4038 @ =0xfffffc40\n\ - movs r6, 0xD\n\ -_080B3FFC:\n\ - str r1, [r3]\n\ - str r2, [r3, 0x4]\n\ - str r5, [r3, 0x8]\n\ - ldr r0, [r3, 0x8]\n\ - adds r2, r4\n\ - adds r1, r4\n\ - subs r6, 0x1\n\ - cmp r6, 0\n\ - bge _080B3FFC\n\ - add sp, 0x4\n\ - pop {r3-r5}\n\ - mov r8, r3\n\ - mov r9, r4\n\ - mov r10, r5\n\ - pop {r4-r7}\n\ - pop {r0}\n\ - bx r0\n\ - .align 2, 0\n\ -_080B4020: .4byte gMenuWindow\n\ -_080B4024: .4byte 0x000003de\n\ -_080B4028: .4byte 0x000003ff\n\ -_080B402C: .4byte 0x00003a20\n\ -_080B4030: .4byte 0x040000d4\n\ -_080B4034: .4byte 0x800000f0\n\ -_080B4038: .4byte 0xfffffc40\n\ - .syntax divided"); -} -#endif - -#ifdef NONMATCHING -static void Shop_MoveItemListDown(void) -{ - u16 *r1; - u16 *r2; - u8 *r10; - s32 i; - s32 j; - struct Window *r8 = &gMenuWindow; - - r1 = r8->tilemap; - r1 += 0x4F; - r2 = r1; - r2 += 64; - r10 = r8->tileData; - - for (i = 0; i < 14; i++) - { - for (j = 0; j < 15; j++) - { - if ((r1[j] & 0x3FF) <= r8->tileDataStartOffset + 1) - r2[j] = r8->tileDataStartOffset + 1; - else - r2[j] = r1[j] + 0x3C; - } - - r1 += 32; - r2 += 32; - } - - { - register u8 *r1 asm("r1") = r10 + 0x960; - register u8 *r2 asm("r2") = r1; - - r1 += 0x780; - for (i = 0; i < 14; i++) - { - DmaCopy16(3, r1, r2, 0x1E0); - r1 += 0x3C0; - r2 += 0x3C0; - } - } -} -#else -__attribute__((naked)) -static void Shop_MoveItemListDown(void) -{ - asm(".syntax unified\n\ - push {r4-r7,lr}\n\ - mov r7, r10\n\ - mov r6, r9\n\ - mov r5, r8\n\ - push {r5-r7}\n\ - sub sp, 0x4\n\ - ldr r0, _080B40D8 @ =gMenuWindow\n\ - mov r8, r0\n\ - ldr r2, [r0, 0x28]\n\ - adds r1, r2, 0\n\ - adds r1, 0x9E\n\ - adds r2, r1, 0\n\ - adds r1, 0x80\n\ - ldr r3, [r0, 0x24]\n\ - mov r10, r3\n\ - ldr r7, _080B40DC @ =0x000003ff\n\ - mov r9, r7\n\ - movs r6, 0xD\n\ -_080B4060:\n\ - adds r0, r2, 0\n\ - adds r0, 0x40\n\ - str r0, [sp]\n\ - movs r3, 0x40\n\ - adds r3, r1\n\ - mov r12, r3\n\ - adds r3, r2, 0\n\ - adds r4, r1, 0\n\ - movs r5, 0xE\n\ -_080B4072:\n\ - ldrh r2, [r4]\n\ - mov r1, r9\n\ - ands r1, r2\n\ - mov r7, r8\n\ - ldrh r0, [r7, 0x1A]\n\ - adds r0, 0x1\n\ - cmp r1, r0\n\ - ble _080B4086\n\ - adds r0, r2, 0\n\ - subs r0, 0x3C\n\ -_080B4086:\n\ - strh r0, [r3]\n\ - adds r3, 0x2\n\ - adds r4, 0x2\n\ - subs r5, 0x1\n\ - cmp r5, 0\n\ - bge _080B4072\n\ - ldr r2, [sp]\n\ - mov r1, r12\n\ - subs r6, 0x1\n\ - cmp r6, 0\n\ - bge _080B4060\n\ - movs r1, 0x96\n\ - lsls r1, 4\n\ - add r1, r10\n\ - adds r2, r1, 0\n\ - movs r0, 0xF0\n\ - lsls r0, 3\n\ - adds r1, r0\n\ - ldr r3, _080B40E0 @ =0x040000d4\n\ - ldr r5, _080B40E4 @ =0x800000f0\n\ - movs r4, 0xF0\n\ - lsls r4, 2\n\ - movs r6, 0xD\n\ -_080B40B4:\n\ - str r1, [r3]\n\ - str r2, [r3, 0x4]\n\ - str r5, [r3, 0x8]\n\ - ldr r0, [r3, 0x8]\n\ - adds r2, r4\n\ - adds r1, r4\n\ - subs r6, 0x1\n\ - cmp r6, 0\n\ - bge _080B40B4\n\ - add sp, 0x4\n\ - pop {r3-r5}\n\ - mov r8, r3\n\ - mov r9, r4\n\ - mov r10, r5\n\ - pop {r4-r7}\n\ - pop {r0}\n\ - bx r0\n\ - .align 2, 0\n\ -_080B40D8: .4byte gMenuWindow\n\ -_080B40DC: .4byte 0x000003ff\n\ -_080B40E0: .4byte 0x040000d4\n\ -_080B40E4: .4byte 0x800000f0\n\ - .syntax divided"); -} -#endif - -static void Shop_DoCursorAction(u8 taskId) -{ - if (!gPaletteFade.active) - { - if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP) // only up can be pressed - { - if (gMartInfo.cursor == 0) - { - if (gMartInfo.choicesAbove == 0) // if there are no choices above, dont bother - return; - - PlaySE(SE_SELECT); - gMartInfo.choicesAbove--; // since cursor is at the top and there are choices above the top, scroll the menu up by updating choicesAbove. - Shop_MoveItemListUp(); - Shop_DisplayPriceInList(0, 0, 0); - Shop_PrintItemDescText(); - Shop_TryDrawVerticalScrollIndicators(); - } - else // if the cursor is not 0, choicesAbove cannot be updated yet since the cursor is at the top of the menu, so update cursor. - { - PlaySE(SE_SELECT); - gMartInfo.cursor = Menu_MoveCursor(-1); // move cursor up - Shop_PrintItemDescText(); - } - } - else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN) // only down can be pressed - { - if (gMartInfo.cursor == 7) // are you at the bottom of the menu? - { - if (gMartInfo.choicesAbove + gMartInfo.cursor == gMartInfo.itemCount) // are you at cancel? - return; - - PlaySE(SE_SELECT); - gMartInfo.choicesAbove++; - Shop_MoveItemListDown(); - Shop_DisplayPriceInList(7, 7, 0); - Shop_PrintItemDescText(); - Shop_TryDrawVerticalScrollIndicators(); - } - else if (gMartInfo.cursor != gMartInfo.itemCount) - { - PlaySE(SE_SELECT); - gMartInfo.cursor = Menu_MoveCursor(1); - Shop_PrintItemDescText(); - } - } - else if (gMain.newKeys & A_BUTTON) - { - PlaySE(SE_SELECT); - - if (gMartInfo.choicesAbove + gMartInfo.cursor != gMartInfo.itemCount) // did you not hit CANCEL? - { - PauseVerticalScrollIndicator(TOP_ARROW); - PauseVerticalScrollIndicator(BOTTOM_ARROW); - SetVerticalScrollIndicators(BOTTOM_ARROW, INVISIBLE); - Shop_DisplayPriceInList(gMartInfo.cursor, gMartInfo.cursor, 1); - Menu_DestroyCursor(); - Menu_EraseWindowRect(0, 0xC, 0xD, 0x13); - - if (gMartInfo.martType == MART_TYPE_0) - { - gMartTotalCost = (ItemId_GetPrice(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]) >> GetPriceReduction(1)); // set 1x price - if (!IsEnoughMoney(gSaveBlock1.money, gMartTotalCost)) - { - DisplayItemMessageOnField(taskId, gOtherText_NotEnoughMoney, Shop_DoPricePrintAndReturnToBuyMenu, 0xC3E1); // tail merge - } - else // _080B42BA - { - CopyItemName(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor], gStringVar1); - StringExpandPlaceholders(gStringVar4, gOtherText_HowManyYouWant); - DisplayItemMessageOnField(taskId, gStringVar4, Shop_UpdateCurItemCountToMax, 0xC3E1); - } - } - else // _080B428C - { - gMartTotalCost = gDecorations[gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]].price; - - if (!IsEnoughMoney(gSaveBlock1.money, gMartTotalCost)) - { - DisplayItemMessageOnField(taskId, gOtherText_NotEnoughMoney, Shop_DoPricePrintAndReturnToBuyMenu, 0xC3E1); // tail merge - } - else - { - StringCopy(gStringVar1, gDecorations[gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]].name); - ConvertIntToDecimalStringN(gStringVar2, gMartTotalCost, 0, 0x8); - - if (gMartInfo.martType == MART_TYPE_1) - { - StringExpandPlaceholders(gStringVar4, gOtherText_ThatWillBe2); - } - else - { - StringExpandPlaceholders(gStringVar4, gOtherText_ThatWillBe3); - } - DisplayItemMessageOnField(taskId, gStringVar4, Shop_DoYesNoPurchase, 0xC3E1); - } - } - } - else - Task_ExitBuyMenu(taskId); - } - else if (gMain.newKeys & B_BUTTON) // go back to buy/sell/exit menu - { - PlaySE(SE_SELECT); - Task_ExitBuyMenu(taskId); - } - } -} - -static void Task_ReturnToBuyMenu(u8 taskId) -{ - Menu_EraseWindowRect(0, 0xE, 0x1D, 0x13); - Menu_EraseWindowRect(0, 0xA, 0xD, 0xD); - sub_80A3FA0(gBGTilemapBuffers[1], 0x1, 0xB, 0xC, 0x2, 0); - Shop_DrawViewportTiles(); - Shop_InitMenus(6, 7); - Shop_PrintItemDesc(); - StartVerticalScrollIndicators(TOP_ARROW); - StartVerticalScrollIndicators(BOTTOM_ARROW); - Shop_TryDrawVerticalScrollIndicators(); - gTasks[taskId].func = Shop_DoCursorAction; -} - -static void Task_ExitBuyMenu(u8 taskId) -{ - gFieldCallback = Shop_FadeReturnToMartMenu; - BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); - gTasks[taskId].func = Task_ExitBuyMenuDoFade; -} - -static void Task_ExitBuyMenuDoFade(u8 taskId) -{ - if (!gPaletteFade.active) - { - CloseMoneyWindow(0, 0); - BuyMenuFreeMemory(); - SetMainCallback2(c2_exit_to_overworld_2_switch); - DestroyTask(taskId); - } -} - -// Task_UpdatePurchaseHistory -static void Task_UpdatePurchaseHistory(u8 taskId) -{ - u16 i; - - for (i = 0; i < 3; i++) - { - if (gMartPurchaseHistory[i].itemId == gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor] - && gMartPurchaseHistory[i].quantity != 0) - { - if (gMartPurchaseHistory[i].quantity + gTasks[taskId].tItemCount > 255) - gMartPurchaseHistory[i].quantity = 255; - else - gMartPurchaseHistory[i].quantity += gTasks[taskId].tItemCount; - return; - } - } - - if (gMartPurchaseHistoryId < 3) - { - gMartPurchaseHistory[gMartPurchaseHistoryId].itemId = gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]; - gMartPurchaseHistory[gMartPurchaseHistoryId].quantity = gTasks[taskId].tItemCount; - gMartPurchaseHistoryId++; - } -} - -#undef tItemCount - -static void ClearItemPurchases(void) -{ - gMartPurchaseHistoryId = 0; - ClearItemSlots(gMartPurchaseHistory, 3); -} - -void Shop_CreatePokemartMenu(u16 *itemList) -{ - CreateShopMenu(MART_TYPE_0); - SetShopItemsForSale(itemList); - ClearItemPurchases(); - SetShopMenuCallback(EnableBothScriptContexts); -} - -void Shop_CreateDecorationShop1Menu(u16 *itemList) -{ - CreateShopMenu(MART_TYPE_1); - SetShopItemsForSale(itemList); - SetShopMenuCallback(EnableBothScriptContexts); -} - -void Shop_CreateDecorationShop2Menu(u16 *itemList) -{ - CreateShopMenu(MART_TYPE_2); - SetShopItemsForSale(itemList); - SetShopMenuCallback(EnableBothScriptContexts); -} |