summaryrefslogtreecommitdiff
path: root/src/mystery_gift_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mystery_gift_menu.c')
-rw-r--r--src/mystery_gift_menu.c1618
1 files changed, 1618 insertions, 0 deletions
diff --git a/src/mystery_gift_menu.c b/src/mystery_gift_menu.c
new file mode 100644
index 000000000..e1236adfd
--- /dev/null
+++ b/src/mystery_gift_menu.c
@@ -0,0 +1,1618 @@
+#include "global.h"
+#include "main.h"
+#include "text.h"
+#include "task.h"
+#include "malloc.h"
+#include "gpu_regs.h"
+#include "scanline_effect.h"
+#include "text_window.h"
+#include "bg.h"
+#include "window.h"
+#include "strings.h"
+#include "text_window.h"
+#include "menu.h"
+#include "palette.h"
+#include "constants/songs.h"
+#include "sound.h"
+#include "mystery_gift_menu.h"
+#include "union_room.h"
+#include "title_screen.h"
+#include "ereader_screen.h"
+#include "international_string_util.h"
+#include "list_menu.h"
+#include "string_util.h"
+#include "mystery_gift.h"
+#include "mystery_gift_view.h"
+#include "save.h"
+#include "link.h"
+#include "mystery_gift_client.h"
+#include "mystery_gift_server.h"
+#include "event_data.h"
+#include "link_rfu.h"
+#include "wonder_news.h"
+#include "constants/cable_club.h"
+
+#define LIST_MENU_TILE_NUM 10
+#define LIST_MENU_PAL_NUM 224
+
+static void LoadMysteryGiftTextboxBorder(u8 bgId);
+static void CreateMysteryGiftTask(void);
+static void Task_MysteryGift(u8 taskId);
+
+EWRAM_DATA static u8 sDownArrowCounterAndYCoordIdx[8] = {};
+EWRAM_DATA bool8 gGiftIsFromEReader = FALSE;
+
+static const u16 sTextboxBorder_Pal[] = INCBIN_U16("graphics/interface/mystery_gift_textbox_border.gbapal");
+static const u32 sTextboxBorder_Gfx[] = INCBIN_U32("graphics/interface/mystery_gift_textbox_border.4bpp.lz");
+
+struct MysteryGiftTaskData
+{
+ u16 var; // Multipurpose
+ u16 unused1;
+ u16 unused2;
+ u16 unused3;
+ u8 state;
+ u8 textState;
+ u8 unused4;
+ u8 unused5;
+ bool8 isWonderNews;
+ bool8 sourceIsFriend;
+ u8 msgId;
+ u8 * clientMsg;
+};
+
+static const struct BgTemplate sBGTemplates[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 15,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 14,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x000
+ }, {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 13,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000
+ }, {
+ .bg = 3,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 12,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000
+ }
+};
+
+static const struct WindowTemplate sMainWindows[] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 0,
+ .tilemapTop = 0,
+ .width = 30,
+ .height = 2,
+ .paletteNum = 12,
+ .baseBlock = 0x0013
+ }, {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 28,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x004f
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0,
+ .tilemapTop = 15,
+ .width = 30,
+ .height = 5,
+ .paletteNum = 13,
+ .baseBlock = 0x004f
+ },
+ DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate sWindowTemplate_YesNoMsg_Wide = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 28,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x00e5
+};
+
+static const struct WindowTemplate sWindowTemplate_YesNoMsg = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 20,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x00e5
+};
+
+static const struct WindowTemplate sWindowTemplate_GiftSelect = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 19,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x00e5
+};
+
+static const struct WindowTemplate sWindowTemplate_ThreeOptions = {
+ .bg = 0,
+ .tilemapLeft = 8,
+ .tilemapTop = 6,
+ .width = 14,
+ .height = 6,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct WindowTemplate sWindowTemplate_YesNoBox = {
+ .bg = 0,
+ .tilemapLeft = 23,
+ .tilemapTop = 15,
+ .width = 6,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct WindowTemplate sWindowTemplate_GiftSelect_3Options = {
+ .bg = 0,
+ .tilemapLeft = 22,
+ .tilemapTop = 11,
+ .width = 7,
+ .height = 8,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct WindowTemplate sWindowTemplate_GiftSelect_2Options = {
+ .bg = 0,
+ .tilemapLeft = 22,
+ .tilemapTop = 13,
+ .width = 7,
+ .height = 6,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct WindowTemplate sWindowTemplate_GiftSelect_1Option = {
+ .bg = 0,
+ .tilemapLeft = 22,
+ .tilemapTop = 15,
+ .width = 7,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct ListMenuItem sListMenuItems_CardsOrNews[] = {
+ { gText_WonderCards, 0 },
+ { gText_WonderNews, 1 },
+ { gText_Exit3, LIST_CANCEL }
+};
+
+static const struct ListMenuItem sListMenuItems_WirelessOrFriend[] = {
+ { gText_WirelessCommunication, 0 },
+ { gText_Friend2, 1 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuTemplate sListMenuTemplate_ThreeOptions = {
+ .items = NULL,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const struct ListMenuItem sListMenuItems_ReceiveSendToss[] = {
+ { gText_Receive, 0 },
+ { gText_Send, 1 },
+ { gText_Toss, 2 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuItem sListMenuItems_ReceiveToss[] = {
+ { gText_Receive, 0 },
+ { gText_Toss, 2 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuItem sListMenuItems_ReceiveSend[] = {
+ { gText_Receive, 0 },
+ { gText_Send, 1 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuItem sListMenuItems_Receive[] = {
+ { gText_Receive, 0 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuTemplate sListMenu_ReceiveSendToss = {
+ .items = sListMenuItems_ReceiveSendToss,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 4,
+ .maxShowed = 4,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const struct ListMenuTemplate sListMenu_ReceiveToss = {
+ .items = sListMenuItems_ReceiveToss,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const struct ListMenuTemplate sListMenu_ReceiveSend = {
+ .items = sListMenuItems_ReceiveSend,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const struct ListMenuTemplate sListMenu_Receive = {
+ .items = sListMenuItems_Receive,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 2,
+ .maxShowed = 2,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const u8 *const Unref_082F0710[] = {
+ gText_VarietyOfEventsImportedWireless,
+ gText_WonderCardsInPossession,
+ gText_ReadNewsThatArrived,
+ gText_ReturnToTitle
+};
+
+ALIGNED(2) static const u8 sTextColors_TopMenu[] = { TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY };
+ALIGNED(2) static const u8 sTextColors_TopMenu_Copy[] = { TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY };
+ALIGNED(2) static const u8 sMG_Ereader_TextColor_2[] = { TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY };
+
+static void VBlankCB_MysteryGiftEReader(void)
+{
+ ProcessSpriteCopyRequests();
+ LoadOam();
+ TransferPlttBuffer();
+}
+
+void CB2_MysteryGiftEReader(void)
+{
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+}
+
+static bool32 HandleMysteryGiftOrEReaderSetup(s32 isEReader)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ ResetPaletteFade();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ ScanlineEffect_Stop();
+ ResetBgsAndClearDma3BusyFlags(0);
+
+ InitBgsFromTemplates(0, sBGTemplates, ARRAY_COUNT(sBGTemplates));
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgX(3, 0, 0);
+ ChangeBgY(3, 0, 0);
+
+ SetBgTilemapBuffer(3, Alloc(BG_SCREEN_SIZE));
+ SetBgTilemapBuffer(2, Alloc(BG_SCREEN_SIZE));
+ SetBgTilemapBuffer(1, Alloc(BG_SCREEN_SIZE));
+ SetBgTilemapBuffer(0, Alloc(BG_SCREEN_SIZE));
+
+ LoadMysteryGiftTextboxBorder(3);
+ InitWindows(sMainWindows);
+ DeactivateAllTextPrinters();
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ gMain.state++;
+ break;
+ case 1:
+ LoadPalette(sTextboxBorder_Pal, 0, 0x20);
+ LoadPalette(GetTextWindowPalette(2), 0xd0, 0x20);
+ Menu_LoadStdPalAt(0xC0);
+ LoadUserWindowBorderGfx(0, 0xA, 0xE0);
+ LoadUserWindowBorderGfx_(0, 0x1, 0xF0);
+ FillBgTilemapBufferRect(0, 0x000, 0, 0, 32, 32, 0x11);
+ FillBgTilemapBufferRect(1, 0x000, 0, 0, 32, 32, 0x11);
+ FillBgTilemapBufferRect(2, 0x000, 0, 0, 32, 32, 0x11);
+ MG_DrawCheckerboardPattern(3);
+ PrintMysteryGiftOrEReaderTopMenu(isEReader, FALSE);
+ gMain.state++;
+ break;
+ case 2:
+ CopyBgTilemapBufferToVram(3);
+ CopyBgTilemapBufferToVram(2);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(0);
+ gMain.state++;
+ break;
+ case 3:
+ ShowBg(0);
+ ShowBg(3);
+ PlayBGM(MUS_RG_MYSTERY_GIFT);
+ SetVBlankCallback(VBlankCB_MysteryGiftEReader);
+ EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CB2_InitMysteryGift(void)
+{
+ if (HandleMysteryGiftOrEReaderSetup(FALSE))
+ {
+ SetMainCallback2(CB2_MysteryGiftEReader);
+ gGiftIsFromEReader = FALSE;
+ CreateMysteryGiftTask();
+ }
+ RunTasks();
+}
+
+void CB2_InitEReader(void)
+{
+ if (HandleMysteryGiftOrEReaderSetup(TRUE))
+ {
+ SetMainCallback2(CB2_MysteryGiftEReader);
+ gGiftIsFromEReader = TRUE;
+ CreateEReaderTask();
+ }
+}
+
+void MainCB_FreeAllBuffersAndReturnToInitTitleScreen(void)
+{
+ gGiftIsFromEReader = FALSE;
+ FreeAllWindowBuffers();
+ Free(GetBgTilemapBuffer(0));
+ Free(GetBgTilemapBuffer(1));
+ Free(GetBgTilemapBuffer(2));
+ Free(GetBgTilemapBuffer(3));
+ SetMainCallback2(CB2_InitTitleScreen);
+}
+
+void PrintMysteryGiftOrEReaderTopMenu(bool8 isEReader, bool32 useCancel)
+{
+ const u8 * header;
+ const u8 * options;
+ FillWindowPixelBuffer(0, 0);
+ if (!isEReader)
+ {
+ header = gText_MysteryGift;
+ options = !useCancel ? gText_PickOKExit : gText_PickOKCancel;
+ }
+ else
+ {
+ header = gJPText_MysteryGift;
+ options = gJPText_DecideStop;
+ }
+
+ AddTextPrinterParameterized4(0, 1, 4, 1, 0, 0, sTextColors_TopMenu, TEXT_SPEED_FF, header);
+ AddTextPrinterParameterized4(0, 0, GetStringRightAlignXOffset(0, options, 0xDE), 1, 0, 0, sTextColors_TopMenu, TEXT_SPEED_FF, options);
+ CopyWindowToVram(0, 2);
+ PutWindowTilemap(0);
+}
+
+void MG_DrawTextBorder(u8 windowId)
+{
+ DrawTextBorderOuter(windowId, 0x01, 0xF);
+}
+
+void MG_DrawCheckerboardPattern(u32 bg)
+{
+ s32 i = 0, j;
+
+ FillBgTilemapBufferRect(bg, 0x003, 0, 0, 32, 2, 0x11);
+
+ for (i = 0; i < 18; i++)
+ {
+ for (j = 0; j < 32; j++)
+ {
+ if ((i & 1) != (j & 1))
+ FillBgTilemapBufferRect(bg, 1, j, i + 2, 1, 1, 0x11);
+ else
+ FillBgTilemapBufferRect(bg, 2, j, i + 2, 1, 1, 0x11);
+ }
+ }
+}
+
+static void ClearScreenInBg0(bool32 ignoreTopTwoRows)
+{
+ switch (ignoreTopTwoRows)
+ {
+ case 0:
+ FillBgTilemapBufferRect(0, 0, 0, 0, 32, 32, 0x11);
+ break;
+ case 1:
+ FillBgTilemapBufferRect(0, 0, 0, 2, 32, 30, 0x11);
+ break;
+ }
+ CopyBgTilemapBufferToVram(0);
+}
+
+void AddTextPrinterToWindow1(const u8 *str)
+{
+ StringExpandPlaceholders(gStringVar4, str);
+ FillWindowPixelBuffer(1, 0x11);
+ AddTextPrinterParameterized4(1, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(1, 0x001, 0xF);
+ PutWindowTilemap(1);
+ CopyWindowToVram(1, 3);
+}
+
+static void ClearTextWindow(void)
+{
+ rbox_fill_rectangle(1);
+ ClearWindowTilemap(1);
+ CopyWindowToVram(1, 1);
+}
+
+#define DOWN_ARROW_X 208
+#define DOWN_ARROW_Y 20
+
+bool32 PrintMysteryGiftMenuMessage(u8 *textState, const u8 *str)
+{
+ switch (*textState)
+ {
+ case 0:
+ AddTextPrinterToWindow1(str);
+ (*textState)++;
+ break;
+ case 1:
+ DrawDownArrow(1, DOWN_ARROW_X, DOWN_ARROW_Y, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ if (({JOY_NEW(A_BUTTON | B_BUTTON);}))
+ (*textState)++;
+ break;
+ case 2:
+ DrawDownArrow(1, DOWN_ARROW_X, DOWN_ARROW_Y, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ *textState = 0;
+ ClearTextWindow();
+ return TRUE;
+ case 0xFF:
+ *textState = 2;
+ return FALSE;
+ }
+ return FALSE;
+}
+
+static void HideDownArrow(void)
+{
+ DrawDownArrow(1, DOWN_ARROW_X, DOWN_ARROW_Y, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+}
+
+static void ShowDownArrow(void)
+{
+ DrawDownArrow(1, DOWN_ARROW_X, DOWN_ARROW_Y, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+}
+
+// Unused
+static bool32 HideDownArrowAndWaitButton(u8 * textState)
+{
+ switch (*textState)
+ {
+ case 0:
+ HideDownArrow();
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ (*textState)++;
+ break;
+ case 1:
+ ShowDownArrow();
+ *textState = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool32 PrintStringAndWait2Seconds(u8 * counter, const u8 * str)
+{
+ if (*counter == 0)
+ AddTextPrinterToWindow1(str);
+
+ if (++(*counter) > 120)
+ {
+ *counter = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static u32 MysteryGift_HandleThreeOptionMenu(u8 * unused0, u16 * unused1, u8 whichMenu)
+{
+ struct ListMenuTemplate listMenuTemplate = sListMenuTemplate_ThreeOptions;
+ struct WindowTemplate windowTemplate = sWindowTemplate_ThreeOptions;
+ s32 width;
+ s32 response;
+
+ if (whichMenu == 0)
+ listMenuTemplate.items = sListMenuItems_CardsOrNews;
+ else
+ listMenuTemplate.items = sListMenuItems_WirelessOrFriend;
+
+ width = Intl_GetListMenuWidth(&listMenuTemplate);
+ if (width & 1)
+ width++;
+
+ windowTemplate.width = width;
+ if (width < 30)
+ windowTemplate.tilemapLeft = (30 - width) / 2;
+ else
+ windowTemplate.tilemapLeft = 0;
+
+ response = DoMysteryGiftListMenu(&windowTemplate, &listMenuTemplate, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ if (response != LIST_NOTHING_CHOSEN)
+ {
+ ClearWindowTilemap(2);
+ CopyWindowToVram(2, 1);
+ }
+ return response;
+}
+
+s8 DoMysteryGiftYesNo(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str)
+{
+ struct WindowTemplate windowTemplate;
+ s8 input;
+
+ switch (*textState)
+ {
+ case 0:
+ // Print question message
+ StringExpandPlaceholders(gStringVar4, str);
+ if (yesNoBoxPlacement == 0)
+ *windowId = AddWindow(&sWindowTemplate_YesNoMsg_Wide);
+ else
+ *windowId = AddWindow(&sWindowTemplate_YesNoMsg);
+ FillWindowPixelBuffer(*windowId, 0x11);
+ AddTextPrinterParameterized4(*windowId, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(*windowId, 0x001, 0x0F);
+ CopyWindowToVram(*windowId, 2);
+ PutWindowTilemap(*windowId);
+ (*textState)++;
+ break;
+ case 1:
+ // Create Yes/No
+ windowTemplate = sWindowTemplate_YesNoBox;
+ if (yesNoBoxPlacement == 0)
+ windowTemplate.tilemapTop = 9;
+ else
+ windowTemplate.tilemapTop = 15;
+ CreateYesNoMenu(&windowTemplate, 10, 14, 0);
+ (*textState)++;
+ break;
+ case 2:
+ // Handle Yes/No input
+ input = Menu_ProcessInputNoWrapClearOnChoose();
+ if (input == MENU_B_PRESSED || input == 0 || input == 1)
+ {
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return input;
+ }
+ break;
+ case 0xFF:
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return MENU_B_PRESSED;
+ }
+
+ return MENU_NOTHING_CHOSEN;
+}
+
+// Handle the "Receive/Send/Toss" menu that appears when selecting Wonder Card/News
+static s32 HandleGiftSelectMenu(u8 * textState, u16 * windowId, bool32 cannotToss, bool32 cannotSend)
+{
+ struct WindowTemplate windowTemplate;
+ s32 input;
+
+ switch (*textState)
+ {
+ case 0:
+ // Print menu message
+ if (!cannotToss)
+ StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithCards);
+ else
+ StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithNews);
+ *windowId = AddWindow(&sWindowTemplate_GiftSelect);
+ FillWindowPixelBuffer(*windowId, 0x11);
+ AddTextPrinterParameterized4(*windowId, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(*windowId, 0x001, 0x0F);
+ CopyWindowToVram(*windowId, 2);
+ PutWindowTilemap(*windowId);
+ (*textState)++;
+ break;
+ case 1:
+ windowTemplate = sWindowTemplate_YesNoBox;
+ if (cannotSend)
+ {
+ if (!cannotToss)
+ input = DoMysteryGiftListMenu(&sWindowTemplate_GiftSelect_2Options, &sListMenu_ReceiveToss, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ else
+ input = DoMysteryGiftListMenu(&sWindowTemplate_GiftSelect_1Option, &sListMenu_Receive, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ }
+ else
+ {
+ if (!cannotToss)
+ input = DoMysteryGiftListMenu(&sWindowTemplate_GiftSelect_3Options, &sListMenu_ReceiveSendToss, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ else
+ input = DoMysteryGiftListMenu(&sWindowTemplate_GiftSelect_2Options, &sListMenu_ReceiveSend, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ }
+ if (input != LIST_NOTHING_CHOSEN)
+ {
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return input;
+ }
+ break;
+ case 0xFF:
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return LIST_CANCEL;
+ }
+
+ return LIST_NOTHING_CHOSEN;
+}
+
+static bool32 ValidateCardOrNews(bool32 isWonderNews)
+{
+ if (!isWonderNews)
+ return ValidateSavedWonderCard();
+ else
+ return ValidateSavedWonderNews();
+}
+
+static bool32 HandleLoadWonderCardOrNews(u8 * state, bool32 isWonderNews)
+{
+ switch (*state)
+ {
+ case 0:
+ if (!isWonderNews)
+ WonderCard_Init(GetSavedWonderCard(), GetSavedWonderCardMetadata());
+ else
+ WonderNews_Init(GetSavedWonderNews());
+ (*state)++;
+ break;
+ case 1:
+ if (!isWonderNews)
+ {
+ if (!WonderCard_Enter())
+ return FALSE;
+ }
+ else
+ {
+ if (!WonderNews_Enter())
+ return FALSE;
+ }
+ *state = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static bool32 ClearSavedNewsOrCard(bool32 isWonderNews)
+{
+ if (!isWonderNews)
+ ClearSavedWonderCardAndRelated();
+ else
+ ClearSavedWonderNewsAndRelated();
+ return TRUE;
+}
+
+static bool32 ExitWonderCardOrNews(bool32 isWonderNews, bool32 useCancel)
+{
+ if (!isWonderNews)
+ {
+ if (WonderCard_Exit(useCancel))
+ {
+ WonderCard_Destroy();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (WonderNews_Exit(useCancel))
+ {
+ WonderNews_Destroy();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+static s32 AskDiscardGift(u8 * textState, u16 * windowId, bool32 isWonderNews)
+{
+ if (!isWonderNews)
+ return DoMysteryGiftYesNo(textState, windowId, TRUE, gText_IfThrowAwayCardEventWontHappen);
+ else
+ return DoMysteryGiftYesNo(textState, windowId, TRUE, gText_OkayToDiscardNews);
+}
+
+static bool32 PrintThrownAway(u8 * textState, bool32 isWonderNews)
+{
+ if (!isWonderNews)
+ return PrintMysteryGiftMenuMessage(textState, gText_WonderCardThrownAway);
+ else
+ return PrintMysteryGiftMenuMessage(textState, gText_WonderNewsThrownAway);
+}
+
+static bool32 SaveOnMysteryGiftMenu(u8 * state)
+{
+ switch (*state)
+ {
+ case 0:
+ AddTextPrinterToWindow1(gText_DataWillBeSaved);
+ (*state)++;
+ break;
+ case 1:
+ TrySavingData(SAVE_NORMAL);
+ (*state)++;
+ break;
+ case 2:
+ AddTextPrinterToWindow1(gText_SaveCompletedPressA);
+ (*state)++;
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ (*state)++;
+ break;
+ case 4:
+ *state = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static const u8 * GetClientResultMessage(bool32 * successMsg, bool8 isWonderNews, bool8 sourceIsFriend, u32 msgId)
+{
+ const u8 * msg = NULL;
+ *successMsg = FALSE;
+
+ switch (msgId)
+ {
+ case CLI_MSG_NOTHING_SENT:
+ *successMsg = FALSE;
+ msg = gText_NothingSentOver;
+ break;
+ case CLI_MSG_RECORD_UPLOADED:
+ *successMsg = FALSE;
+ msg = gText_RecordUploadedViaWireless;
+ break;
+ case CLI_MSG_CARD_RECEIVED:
+ *successMsg = TRUE;
+ msg = !sourceIsFriend ? gText_WonderCardReceived : gText_WonderCardReceivedFrom;
+ break;
+ case CLI_MSG_NEWS_RECEIVED:
+ *successMsg = TRUE;
+ msg = !sourceIsFriend ? gText_WonderNewsReceived : gText_WonderNewsReceivedFrom;
+ break;
+ case CLI_MSG_STAMP_RECEIVED:
+ *successMsg = TRUE;
+ msg = gText_NewStampReceived;
+ break;
+ case CLI_MSG_HAD_CARD:
+ *successMsg = FALSE;
+ msg = gText_AlreadyHadCard;
+ break;
+ case CLI_MSG_HAD_STAMP:
+ *successMsg = FALSE;
+ msg = gText_AlreadyHadStamp;
+ break;
+ case CLI_MSG_HAD_NEWS:
+ *successMsg = FALSE;
+ msg = gText_AlreadyHadNews;
+ break;
+ case CLI_MSG_NO_ROOM_STAMPS:
+ *successMsg = FALSE;
+ msg = gText_NoMoreRoomForStamps;
+ break;
+ case CLI_MSG_COMM_CANCELED:
+ *successMsg = FALSE;
+ msg = gText_CommunicationCanceled;
+ break;
+ case CLI_MSG_CANT_ACCEPT:
+ *successMsg = FALSE;
+ msg = !isWonderNews ? gText_CantAcceptCardFromTrainer : gText_CantAcceptNewsFromTrainer;
+ break;
+ case CLI_MSG_COMM_ERROR:
+ *successMsg = FALSE;
+ msg = gText_CommunicationError;
+ break;
+ case CLI_MSG_TRAINER_RECEIVED:
+ *successMsg = TRUE;
+ msg = gText_NewTrainerReceived;
+ break;
+ case CLI_MSG_BUFFER_SUCCESS:
+ *successMsg = TRUE;
+ // msg is NULL, use buffer
+ break;
+ case CLI_MSG_BUFFER_FAILURE:
+ *successMsg = FALSE;
+ // msg is NULL, use buffer
+ break;
+ }
+
+ return msg;
+}
+
+static bool32 PrintSuccessMessage(u8 * state, const u8 * msg, u16 * timer)
+{
+ switch (*state)
+ {
+ case 0:
+ if (msg != NULL)
+ AddTextPrinterToWindow1(msg);
+ PlayFanfare(MUS_OBTAIN_ITEM);
+ *timer = 0;
+ (*state)++;
+ break;
+ case 1:
+ if (++(*timer) > 240)
+ (*state)++;
+ break;
+ case 2:
+ if (IsFanfareTaskInactive())
+ {
+ *state = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static const u8 * GetServerResultMessage(bool32 * wonderSuccess, bool8 sourceIsFriend, u32 msgId)
+{
+ const u8 * result = gText_CommunicationError;
+ *wonderSuccess = FALSE;
+ switch (msgId)
+ {
+ case SVR_MSG_NOTHING_SENT:
+ result = gText_NothingSentOver;
+ break;
+ case SVR_MSG_RECORD_UPLOADED:
+ result = gText_RecordUploadedViaWireless;
+ break;
+ case SVR_MSG_CARD_SENT:
+ result = gText_WonderCardSentTo;
+ *wonderSuccess = TRUE;
+ break;
+ case SVR_MSG_NEWS_SENT:
+ result = gText_WonderNewsSentTo;
+ *wonderSuccess = TRUE;
+ break;
+ case SVR_MSG_STAMP_SENT:
+ result = gText_StampSentTo;
+ break;
+ case SVR_MSG_HAS_CARD:
+ result = gText_OtherTrainerHasCard;
+ break;
+ case SVR_MSG_HAS_STAMP:
+ result = gText_OtherTrainerHasStamp;
+ break;
+ case SVR_MSG_HAS_NEWS:
+ result = gText_OtherTrainerHasNews;
+ break;
+ case SVR_MSG_NO_ROOM_STAMPS:
+ result = gText_NoMoreRoomForStamps;
+ break;
+ case SVR_MSG_CLIENT_CANCELED:
+ result = gText_OtherTrainerCanceled;
+ break;
+ case SVR_MSG_CANT_SEND_GIFT_1:
+ result = gText_CantSendGiftToTrainer;
+ break;
+ case SVR_MSG_COMM_ERROR:
+ result = gText_CommunicationError;
+ break;
+ case SVR_MSG_GIFT_SENT_1:
+ result = gText_GiftSentTo;
+ break;
+ case SVR_MSG_GIFT_SENT_2:
+ result = gText_GiftSentTo;
+ break;
+ case SVR_MSG_CANT_SEND_GIFT_2:
+ result = gText_CantSendGiftToTrainer;
+ break;
+ }
+ return result;
+}
+
+static bool32 PrintServerResultMessage(u8 * state, u16 * timer, bool8 sourceIsFriend, u32 msgId)
+{
+ bool32 wonderSuccess;
+ const u8 * str = GetServerResultMessage(&wonderSuccess, sourceIsFriend, msgId);
+ if (wonderSuccess)
+ return PrintSuccessMessage(state, str, timer);
+ else
+ return PrintMysteryGiftMenuMessage(state, str);
+}
+
+// States for Task_MysteryGift.
+// CLIENT states are for when the player is receiving a gift, and use mystery_gift_client.c link functions.
+// SERVER states are for when the player is sending a gift, and use mystery_gift_server.c link functions.
+// Other states handle the general Mystery Gift menu usage.
+enum {
+ MG_STATE_TO_MAIN_MENU,
+ MG_STATE_MAIN_MENU,
+ MG_STATE_DONT_HAVE_ANY,
+ MG_STATE_SOURCE_PROMPT,
+ MG_STATE_SOURCE_PROMPT_INPUT,
+ MG_STATE_CLIENT_LINK_START,
+ MG_STATE_CLIENT_LINK_WAIT,
+ MG_STATE_CLIENT_COMMUNICATING,
+ MG_STATE_CLIENT_LINK,
+ MG_STATE_CLIENT_YES_NO,
+ MG_STATE_CLIENT_MESSAGE,
+ MG_STATE_CLIENT_ASK_TOSS,
+ MG_STATE_CLIENT_ASK_TOSS_UNRECEIVED,
+ MG_STATE_CLIENT_LINK_END,
+ MG_STATE_CLIENT_COMM_COMPLETED,
+ MG_STATE_CLIENT_RESULT_MSG,
+ MG_STATE_CLIENT_ERROR,
+ MG_STATE_SAVE_LOAD_GIFT,
+ MG_STATE_LOAD_GIFT,
+ MG_STATE_UNUSED,
+ MG_STATE_HANDLE_GIFT_INPUT,
+ MG_STATE_HANDLE_GIFT_SELECT,
+ MG_STATE_ASK_TOSS,
+ MG_STATE_ASK_TOSS_UNRECEIVED,
+ MG_STATE_TOSS,
+ MG_STATE_TOSS_SAVE,
+ MG_STATE_TOSSED,
+ MG_STATE_GIFT_INPUT_EXIT,
+ MG_STATE_RECEIVE,
+ MG_STATE_SEND,
+ MG_STATE_SERVER_LINK_WAIT,
+ MG_STATE_SERVER_LINK_START,
+ MG_STATE_SERVER_LINK,
+ MG_STATE_SERVER_LINK_END,
+ MG_STATE_SERVER_LINK_END_WAIT,
+ MG_STATE_SERVER_RESULT_MSG,
+ MG_STATE_SERVER_ERROR,
+ MG_STATE_EXIT,
+};
+
+static void CreateMysteryGiftTask(void)
+{
+ u8 taskId = CreateTask(Task_MysteryGift, 0);
+ struct MysteryGiftTaskData * data = (void *)gTasks[taskId].data;
+ data->state = MG_STATE_TO_MAIN_MENU;
+ data->textState = 0;
+ data->unused4 = 0;
+ data->unused5 = 0;
+ data->isWonderNews = 0;
+ data->sourceIsFriend = 0;
+ data->var = 0;
+ data->unused1 = 0;
+ data->unused2 = 0;
+ data->unused3 = 0;
+ data->msgId = 0;
+ data->clientMsg = AllocZeroed(CLIENT_MAX_MSG_SIZE);
+}
+
+static void Task_MysteryGift(u8 taskId)
+{
+ struct MysteryGiftTaskData *data = (void *)gTasks[taskId].data;
+ u32 successMsg, input;
+ const u8 *msg;
+
+ switch (data->state)
+ {
+ case MG_STATE_TO_MAIN_MENU:
+ data->state = MG_STATE_MAIN_MENU;
+ break;
+ case MG_STATE_MAIN_MENU:
+ // Main Mystery Gift menu, player can select Wonder Cards or News (or exit)
+ switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->var, FALSE))
+ {
+ case 0: // "Wonder Cards"
+ data->isWonderNews = FALSE;
+ if (ValidateSavedWonderCard() == TRUE)
+ data->state = MG_STATE_LOAD_GIFT;
+ else
+ data->state = MG_STATE_DONT_HAVE_ANY;
+ break;
+ case 1: // "Wonder News"
+ data->isWonderNews = TRUE;
+ if (ValidateSavedWonderNews() == TRUE)
+ data->state = MG_STATE_LOAD_GIFT;
+ else
+ data->state = MG_STATE_DONT_HAVE_ANY;
+ break;
+ case LIST_CANCEL:
+ data->state = MG_STATE_EXIT;
+ break;
+ }
+ break;
+ case MG_STATE_DONT_HAVE_ANY:
+ {
+ // Player doesn't have any Wonder Card/News
+ // Start prompt to ask where to read one from
+ if (!data->isWonderNews)
+ {
+ if (PrintMysteryGiftMenuMessage(&data->textState, gText_DontHaveCardNewOneInput))
+ {
+ data->state = MG_STATE_SOURCE_PROMPT;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, TRUE);
+ }
+ }
+ else
+ {
+ if (PrintMysteryGiftMenuMessage(&data->textState, gText_DontHaveNewsNewOneInput))
+ {
+ data->state = MG_STATE_SOURCE_PROMPT;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, TRUE);
+ }
+ }
+ break;
+ }
+ case MG_STATE_SOURCE_PROMPT:
+ if (!data->isWonderNews)
+ AddTextPrinterToWindow1(gText_WhereShouldCardBeAccessed);
+ else
+ AddTextPrinterToWindow1(gText_WhereShouldNewsBeAccessed);
+ data->state = MG_STATE_SOURCE_PROMPT_INPUT;
+ break;
+ case MG_STATE_SOURCE_PROMPT_INPUT:
+ // Choose where to access the Wonder Card/News from
+ switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->var, TRUE))
+ {
+ case 0: // "Wireless Communication"
+ ClearTextWindow();
+ data->state = MG_STATE_CLIENT_LINK_START;
+ data->sourceIsFriend = FALSE;
+ break;
+ case 1: // "Friend"
+ ClearTextWindow();
+ data->state = MG_STATE_CLIENT_LINK_START;
+ data->sourceIsFriend = TRUE;
+ break;
+ case LIST_CANCEL:
+ ClearTextWindow();
+ if (ValidateCardOrNews(data->isWonderNews))
+ {
+ data->state = MG_STATE_LOAD_GIFT;
+ }
+ else
+ {
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_LINK_START:
+ *gStringVar1 = EOS;
+ *gStringVar2 = EOS;
+ *gStringVar3 = EOS;
+
+ switch (data->isWonderNews)
+ {
+ case FALSE:
+ if (data->sourceIsFriend == TRUE)
+ CreateTask_LinkMysteryGiftWithFriend(ACTIVITY_WONDER_CARD);
+ else if (data->sourceIsFriend == FALSE)
+ CreateTask_LinkMysteryGiftOverWireless(ACTIVITY_WONDER_CARD);
+ break;
+ case TRUE:
+ if (data->sourceIsFriend == TRUE)
+ CreateTask_LinkMysteryGiftWithFriend(ACTIVITY_WONDER_NEWS);
+ else if (data->sourceIsFriend == FALSE)
+ CreateTask_LinkMysteryGiftOverWireless(ACTIVITY_WONDER_NEWS);
+ break;
+ }
+ data->state = MG_STATE_CLIENT_LINK_WAIT;
+ break;
+ case MG_STATE_CLIENT_LINK_WAIT:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ MysteryGiftClient_Create(data->isWonderNews);
+ }
+ else if (gSpecialVar_Result == LINKUP_FAILED)
+ {
+ // Link failed, return to link start menu
+ ClearScreenInBg0(TRUE);
+ data->state = MG_STATE_SOURCE_PROMPT;
+ }
+ break;
+ case MG_STATE_CLIENT_COMMUNICATING:
+ AddTextPrinterToWindow1(gText_Communicating);
+ data->state = MG_STATE_CLIENT_LINK;
+ break;
+ case MG_STATE_CLIENT_LINK:
+ switch (MysteryGiftClient_Run(&data->var))
+ {
+ case CLI_RET_END:
+ Rfu_SetCloseLinkCallback();
+ data->msgId = data->var;
+ data->state = MG_STATE_CLIENT_LINK_END;
+ break;
+ case CLI_RET_COPY_MSG:
+ memcpy(data->clientMsg, MysteryGiftClient_GetMsg(), 0x40);
+ MysteryGiftClient_AdvanceState();
+ break;
+ case CLI_RET_PRINT_MSG:
+ data->state = MG_STATE_CLIENT_MESSAGE;
+ break;
+ case CLI_RET_YES_NO:
+ data->state = MG_STATE_CLIENT_YES_NO;
+ break;
+ case CLI_RET_ASK_TOSS:
+ data->state = MG_STATE_CLIENT_ASK_TOSS;
+ StringCopy(gStringVar1, gLinkPlayers[0].name);
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_YES_NO:
+ input = DoMysteryGiftYesNo(&data->textState, &data->var, FALSE, MysteryGiftClient_GetMsg());
+ switch (input)
+ {
+ case 0: // Yes
+ MysteryGiftClient_SetParam(FALSE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ MysteryGiftClient_SetParam(TRUE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_MESSAGE:
+ if (PrintMysteryGiftMenuMessage(&data->textState, MysteryGiftClient_GetMsg()))
+ {
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ }
+ break;
+ case MG_STATE_CLIENT_ASK_TOSS:
+ // Player is receiving a new Wonder Card/News but needs to toss an existing one to make room.
+ // Ask for confirmation.
+ input = DoMysteryGiftYesNo(&data->textState, &data->var, FALSE, gText_ThrowAwayWonderCard);
+ switch (input)
+ {
+ case 0: // Yes
+ if (IsSavedWonderCardGiftNotReceived() == TRUE)
+ {
+ data->state = MG_STATE_CLIENT_ASK_TOSS_UNRECEIVED;
+ }
+ else
+ {
+ MysteryGiftClient_SetParam(FALSE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ }
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ MysteryGiftClient_SetParam(TRUE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_ASK_TOSS_UNRECEIVED:
+ // Player has selected to toss a Wonder Card that they haven't received the gift for.
+ // Ask for confirmation again.
+ input = DoMysteryGiftYesNo(&data->textState, &data->var, FALSE, gText_HaventReceivedCardsGift);
+ switch (input)
+ {
+ case 0: // Yes
+ MysteryGiftClient_SetParam(FALSE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ MysteryGiftClient_SetParam(TRUE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_LINK_END:
+ if (gReceivedRemoteLinkPlayers == 0)
+ {
+ DestroyWirelessStatusIndicatorSprite();
+ data->state = MG_STATE_CLIENT_COMM_COMPLETED;
+ }
+ break;
+ case MG_STATE_CLIENT_COMM_COMPLETED:
+ if (PrintStringAndWait2Seconds(&data->textState, gText_CommunicationCompleted))
+ {
+ if (data->sourceIsFriend == TRUE)
+ StringCopy(gStringVar1, gLinkPlayers[0].name);
+ data->state = MG_STATE_CLIENT_RESULT_MSG;
+ }
+ break;
+ case MG_STATE_CLIENT_RESULT_MSG:
+ msg = GetClientResultMessage(&successMsg, data->isWonderNews, data->sourceIsFriend, data->msgId);
+ if (msg == NULL)
+ msg = data->clientMsg;
+ if (successMsg)
+ input = PrintSuccessMessage(&data->textState, msg, &data->var);
+ else
+ input = PrintMysteryGiftMenuMessage(&data->textState, msg);
+ // input var re-used, here it is TRUE if the message is finished
+ if (input)
+ {
+ if (data->msgId == CLI_MSG_NEWS_RECEIVED)
+ {
+ if (data->sourceIsFriend == TRUE)
+ GenerateRandomWonderNews(WONDER_NEWS_RECV_FRIEND);
+ else
+ GenerateRandomWonderNews(WONDER_NEWS_RECV_WIRELESS);
+ }
+ if (!successMsg)
+ {
+ // Did not receive card/news, return to main menu
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ else
+ {
+ data->state = MG_STATE_SAVE_LOAD_GIFT;
+ }
+ }
+ break;
+ case MG_STATE_SAVE_LOAD_GIFT:
+ if (SaveOnMysteryGiftMenu(&data->textState))
+ data->state = MG_STATE_LOAD_GIFT;
+ break;
+ case MG_STATE_LOAD_GIFT:
+ if (HandleLoadWonderCardOrNews(&data->textState, data->isWonderNews))
+ data->state = MG_STATE_HANDLE_GIFT_INPUT;
+ break;
+ case MG_STATE_HANDLE_GIFT_INPUT:
+ if (!data->isWonderNews)
+ {
+ // Handle Wonder Card input
+ if (JOY_NEW(A_BUTTON))
+ data->state = MG_STATE_HANDLE_GIFT_SELECT;
+ if (JOY_NEW(B_BUTTON))
+ data->state = MG_STATE_GIFT_INPUT_EXIT;
+ }
+ else
+ {
+ switch (WonderNews_GetInput(gMain.newKeys))
+ {
+ case NEWS_INPUT_A:
+ WonderNews_RemoveScrollIndicatorArrowPair();
+ data->state = MG_STATE_HANDLE_GIFT_SELECT;
+ break;
+ case NEWS_INPUT_B:
+ data->state = MG_STATE_GIFT_INPUT_EXIT;
+ break;
+ }
+ }
+ break;
+ case MG_STATE_HANDLE_GIFT_SELECT:
+ {
+ // A Wonder Card/News has been selected, handle its menu
+ u32 result;
+ if (!data->isWonderNews)
+ {
+ if (IsSendingSavedWonderCardAllowed())
+ result = HandleGiftSelectMenu(&data->textState, &data->var, data->isWonderNews, FALSE);
+ else
+ result = HandleGiftSelectMenu(&data->textState, &data->var, data->isWonderNews, TRUE);
+ }
+ else
+ {
+ if (IsSendingSavedWonderNewsAllowed())
+ result = HandleGiftSelectMenu(&data->textState, &data->var, data->isWonderNews, FALSE);
+ else
+ result = HandleGiftSelectMenu(&data->textState, &data->var, data->isWonderNews, TRUE);
+ }
+ switch (result)
+ {
+ case 0: // Receive
+ data->state = MG_STATE_RECEIVE;
+ break;
+ case 1: // Send
+ data->state = MG_STATE_SEND;
+ break;
+ case 2: // Toss
+ data->state = MG_STATE_ASK_TOSS;
+ break;
+ case LIST_CANCEL:
+ if (data->isWonderNews == TRUE)
+ WonderNews_AddScrollIndicatorArrowPair();
+ data->state = MG_STATE_HANDLE_GIFT_INPUT;
+ break;
+ }
+ break;
+ }
+ case MG_STATE_ASK_TOSS:
+ // Player is attempting to discard a saved Wonder Card/News
+ switch (AskDiscardGift(&data->textState, &data->var, data->isWonderNews))
+ {
+ case 0: // Yes
+ if (!data->isWonderNews && IsSavedWonderCardGiftNotReceived() == TRUE)
+ data->state = MG_STATE_ASK_TOSS_UNRECEIVED;
+ else
+ data->state = MG_STATE_TOSS;
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ data->state = MG_STATE_HANDLE_GIFT_SELECT;
+ break;
+ }
+ break;
+ case MG_STATE_ASK_TOSS_UNRECEIVED:
+ // Player has selected to toss a Wonder Card that they haven't received the gift for.
+ // Ask for confirmation again.
+ switch ((u32)DoMysteryGiftYesNo(&data->textState, &data->var, TRUE, gText_HaventReceivedGiftOkayToDiscard))
+ {
+ case 0: // Yes
+ data->state = MG_STATE_TOSS;
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ data->state = MG_STATE_HANDLE_GIFT_SELECT;
+ break;
+ }
+ break;
+ case MG_STATE_TOSS:
+ if (ExitWonderCardOrNews(data->isWonderNews, TRUE))
+ {
+ ClearSavedNewsOrCard(data->isWonderNews);
+ data->state = MG_STATE_TOSS_SAVE;
+ }
+ break;
+ case MG_STATE_TOSS_SAVE:
+ if (SaveOnMysteryGiftMenu(&data->textState))
+ data->state = MG_STATE_TOSSED;
+ break;
+ case MG_STATE_TOSSED:
+ if (PrintThrownAway(&data->textState, data->isWonderNews))
+ {
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ break;
+ case MG_STATE_GIFT_INPUT_EXIT:
+ if (ExitWonderCardOrNews(data->isWonderNews, FALSE))
+ data->state = MG_STATE_TO_MAIN_MENU;
+ break;
+ case MG_STATE_RECEIVE:
+ if (ExitWonderCardOrNews(data->isWonderNews, TRUE))
+ data->state = MG_STATE_SOURCE_PROMPT;
+ break;
+ case MG_STATE_SEND:
+ if (ExitWonderCardOrNews(data->isWonderNews, TRUE))
+ {
+ switch (data->isWonderNews)
+ {
+ case FALSE:
+ CreateTask_SendMysteryGift(ACTIVITY_WONDER_CARD);
+ break;
+ case TRUE:
+ CreateTask_SendMysteryGift(ACTIVITY_WONDER_NEWS);
+ break;
+ }
+ data->sourceIsFriend = TRUE;
+ data->state = MG_STATE_SERVER_LINK_WAIT;
+ }
+ break;
+ case MG_STATE_SERVER_LINK_WAIT:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = MG_STATE_SERVER_LINK_START;
+ }
+ else if (gSpecialVar_Result == LINKUP_FAILED)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = MG_STATE_LOAD_GIFT;
+ }
+ break;
+ case MG_STATE_SERVER_LINK_START:
+ *gStringVar1 = EOS;
+ *gStringVar2 = EOS;
+ *gStringVar3 = EOS;
+
+ if (!data->isWonderNews)
+ {
+ AddTextPrinterToWindow1(gText_SendingWonderCard);
+ MysterGiftServer_CreateForCard();
+ }
+ else
+ {
+ AddTextPrinterToWindow1(gText_SendingWonderNews);
+ MysterGiftServer_CreateForNews();
+ }
+ data->state = MG_STATE_SERVER_LINK;
+ break;
+ case MG_STATE_SERVER_LINK:
+ if (MysterGiftServer_Run(&data->var) == SVR_RET_END)
+ {
+ data->msgId = data->var;
+ data->state = MG_STATE_SERVER_LINK_END;
+ }
+ break;
+ case MG_STATE_SERVER_LINK_END:
+ Rfu_SetCloseLinkCallback();
+ StringCopy(gStringVar1, gLinkPlayers[1].name);
+ data->state = MG_STATE_SERVER_LINK_END_WAIT;
+ break;
+ case MG_STATE_SERVER_LINK_END_WAIT:
+ if (gReceivedRemoteLinkPlayers == 0)
+ {
+ DestroyWirelessStatusIndicatorSprite();
+ data->state = MG_STATE_SERVER_RESULT_MSG;
+ }
+ break;
+ case MG_STATE_SERVER_RESULT_MSG:
+ if (PrintServerResultMessage(&data->textState, &data->var, data->sourceIsFriend, data->msgId))
+ {
+ if (data->sourceIsFriend == TRUE && data->msgId == SVR_MSG_NEWS_SENT)
+ {
+ GenerateRandomWonderNews(WONDER_NEWS_SENT);
+ data->state = MG_STATE_SAVE_LOAD_GIFT;
+ }
+ else
+ {
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ }
+ break;
+ case MG_STATE_CLIENT_ERROR:
+ case MG_STATE_SERVER_ERROR:
+ if (PrintMysteryGiftMenuMessage(&data->textState, gText_CommunicationError))
+ {
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ break;
+ case MG_STATE_EXIT:
+ CloseLink();
+ Free(data->clientMsg);
+ DestroyTask(taskId);
+ SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
+ break;
+ }
+}
+
+u16 GetMysteryGiftBaseBlock(void)
+{
+ return 0x1A9;
+}
+
+static void LoadMysteryGiftTextboxBorder(u8 bgId)
+{
+ DecompressAndLoadBgGfxUsingHeap(bgId, sTextboxBorder_Gfx, 0x100, 0, 0);
+}