diff options
Diffstat (limited to 'src/mystery_gift.c')
-rwxr-xr-x[-rw-r--r--] | src/mystery_gift.c | 1966 |
1 files changed, 478 insertions, 1488 deletions
diff --git a/src/mystery_gift.c b/src/mystery_gift.c index 6ae6a9534..1df6533d9 100644..100755 --- a/src/mystery_gift.c +++ b/src/mystery_gift.c @@ -1,1672 +1,662 @@ #include "global.h" +#include "util.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.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 "mevent.h" -#include "mevent_801BAAC.h" -#include "save.h" -#include "link.h" -#include "mevent_client.h" #include "event_data.h" -#include "link_rfu.h" -#include "mevent_news.h" -#include "mevent_server.h" -#include "constants/cable_club.h" +#include "easy_chat.h" +#include "script.h" +#include "battle_tower.h" +#include "wonder_news.h" +#include "string_util.h" +#include "new_game.h" +#include "mystery_gift.h" +#include "constants/mystery_gift.h" -void bgid_upload_textbox_1(u8 bgId); -void task_add_00_mystery_gift(void); -void task00_mystery_gift(u8 taskId); +static EWRAM_DATA bool32 sStatsEnabled = FALSE; -EWRAM_DATA u8 sDownArrowCounterAndYCoordIdx[8] = {}; -EWRAM_DATA bool8 gGiftIsFromEReader = FALSE; +static void ClearSavedWonderNewsMetadata(void); +static void ClearSavedWonderNews(void); +static void ClearSavedWonderCard(void); +static bool32 ValidateWonderNews(const struct WonderNews *); +static bool32 ValidateWonderCard(const struct WonderCard *); +static void ClearSavedWonderCardMetadata(void); +static void ClearSavedTrainerIds(void); +static void IncrementCardStatForNewTrainer(u32, u32, u32 *, int); -static const u16 gUnkTextboxBorderPal[] = INCBIN_U16("graphics/interface/unk_textbox_border.gbapal"); -static const u32 gUnkTextboxBorderGfx[] = INCBIN_U32("graphics/interface/unk_textbox_border.4bpp.lz"); +#define CALC_CRC(data) CalcCRC16WithTable((void *)&(data), sizeof(data)) -struct MysteryGiftTaskData +void ClearMysteryGift(void) { - u16 curPromptWindowId; - u16 unk2; - u16 unk4; - u16 unk6; - u8 state; - u8 textState; - u8 unkA; - u8 unkB; - u8 IsCardOrNews; - u8 source; - u8 prevPromptWindowId; - u8 * buffer; -}; - -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 = 0x00, - .tilemapLeft = 0x00, - .tilemapTop = 0x00, - .width = 0x1e, - .height = 0x02, - .paletteNum = 0x0c, - .baseBlock = 0x0013 - }, { - .bg = 0x00, - .tilemapLeft = 0x01, - .tilemapTop = 0x0f, - .width = 0x1c, - .height = 0x04, - .paletteNum = 0x0c, - .baseBlock = 0x004f - }, { - .bg = 0x00, - .tilemapLeft = 0x00, - .tilemapTop = 0x0f, - .width = 0x1e, - .height = 0x05, - .paletteNum = 0x0d, - .baseBlock = 0x004f - }, { - 0xFF - } -}; - -static const struct WindowTemplate sWindowTemplate_PromptYesOrNo_Width28 = { - .bg = 0x00, - .tilemapLeft = 0x01, - .tilemapTop = 0x0f, - .width = 0x1c, - .height = 0x04, - .paletteNum = 0x0c, - .baseBlock = 0x00e5 -}; - -static const struct WindowTemplate sWindowTemplate_PromptYesOrNo_Width20 = { - .bg = 0x00, - .tilemapLeft = 0x01, - .tilemapTop = 0x0f, - .width = 0x14, - .height = 0x04, - .paletteNum = 0x0c, - .baseBlock = 0x00e5 -}; - -static const struct WindowTemplate sMysteryGiftMenuWindowTemplate = { - .bg = 0x00, - .tilemapLeft = 0x01, - .tilemapTop = 0x0f, - .width = 0x13, - .height = 0x04, - .paletteNum = 0x0c, - .baseBlock = 0x00e5 -}; - -static const struct WindowTemplate sWindowTemplate_ThreeOptions = { - .bg = 0x00, - .tilemapLeft = 0x08, - .tilemapTop = 0x06, - .width = 0x0e, - .height = 0x06, - .paletteNum = 0x0c, - .baseBlock = 0x0155 -}; - -static const struct WindowTemplate sWindowTemplate_YesNoBox = { - .bg = 0x00, - .tilemapLeft = 0x17, - .tilemapTop = 0x0f, - .width = 0x06, - .height = 0x04, - .paletteNum = 0x0c, - .baseBlock = 0x0155 -}; - -static const struct WindowTemplate sWindowTemplate_7by8 = { - .bg = 0x00, - .tilemapLeft = 0x16, - .tilemapTop = 0x0b, - .width = 0x07, - .height = 0x08, - .paletteNum = 0x0c, - .baseBlock = 0x0155 -}; - -static const struct WindowTemplate sWindowTemplate_7by6 = { - .bg = 0x00, - .tilemapLeft = 0x16, - .tilemapTop = 0x0d, - .width = 0x07, - .height = 0x06, - .paletteNum = 0x0c, - .baseBlock = 0x0155 -}; + CpuFill32(0, &gSaveBlock1Ptr->mysteryGift, sizeof(gSaveBlock1Ptr->mysteryGift)); + ClearSavedWonderNewsMetadata(); // Clear is redundant, InitSavedWonderNews would be sufficient + InitQuestionnaireWords(); +} -static const struct WindowTemplate sWindowTemplate_7by4 = { - .bg = 0x00, - .tilemapLeft = 0x16, - .tilemapTop = 0x0f, - .width = 0x07, - .height = 0x04, - .paletteNum = 0x0c, - .baseBlock = 0x0155 -}; +struct WonderNews *GetSavedWonderNews(void) +{ + return &gSaveBlock1Ptr->mysteryGift.news; +} -static const struct ListMenuItem sListMenuItems_CardsOrNews[] = { - { gText_WonderCards, 0 }, - { gText_WonderNews, 1 }, - { gText_Exit3, -2 } -}; +struct WonderCard *GetSavedWonderCard(void) +{ + return &gSaveBlock1Ptr->mysteryGift.card; +} -static const struct ListMenuItem sListMenuItems_WirelessOrFriend[] = { - { gText_WirelessCommunication, 0 }, - { gText_Friend2, 1 }, - { gText_Cancel2, -2 } -}; +struct WonderCardMetadata *GetSavedWonderCardMetadata(void) +{ + return &gSaveBlock1Ptr->mysteryGift.cardMetadata; +} -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 -}; +struct WonderNewsMetadata *GetSavedWonderNewsMetadata(void) +{ + return &gSaveBlock1Ptr->mysteryGift.newsMetadata; +} -static const struct ListMenuItem sListMenuItems_ReceiveSendToss[] = { - { gText_Receive, 0 }, - { gText_Send, 1 }, - { gText_Toss, 2 }, - { gText_Cancel2, -2 } -}; +u16 *GetQuestionnaireWordsPtr(void) +{ + return gSaveBlock1Ptr->mysteryGift.questionnaireWords; +} -static const struct ListMenuItem sListMenuItems_ReceiveToss[] = { - { gText_Receive, 0 }, - { gText_Toss, 2 }, - { gText_Cancel2, -2 } -}; +// Equivalent to ClearSavedWonderCardAndRelated, but nothing else to clear +void ClearSavedWonderNewsAndRelated(void) +{ + ClearSavedWonderNews(); +} -static const struct ListMenuItem sListMenuItems_ReceiveSend[] = { - { gText_Receive, 0 }, - { gText_Send, 1 }, - { gText_Cancel2, -2 } -}; +bool32 SaveWonderNews(const struct WonderNews *news) +{ + if (!ValidateWonderNews(news)) + return FALSE; -static const struct ListMenuItem sListMenuItems_Receive[] = { - { gText_Receive, 0 }, - { gText_Cancel2, -2 } -}; + ClearSavedWonderNews(); + gSaveBlock1Ptr->mysteryGift.news = *news; + gSaveBlock1Ptr->mysteryGift.newsCrc = CALC_CRC(gSaveBlock1Ptr->mysteryGift.news); + return TRUE; +} -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 -}; +bool32 ValidateSavedWonderNews(void) +{ + if (CALC_CRC(gSaveBlock1Ptr->mysteryGift.news) != gSaveBlock1Ptr->mysteryGift.newsCrc) + return FALSE; + if (!ValidateWonderNews(&gSaveBlock1Ptr->mysteryGift.news)) + return FALSE; -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 -}; + return TRUE; +} -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 bool32 ValidateWonderNews(const struct WonderNews *news) +{ + if (news->id == 0) + return FALSE; -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 -}; + return TRUE; +} -static const u8 *const Unref_082F0710[] = { - gText_VarietyOfEventsImportedWireless, - gText_WonderCardsInPossession, - gText_ReadNewsThatArrived, - gText_ReturnToTitle -}; +bool32 IsSendingSavedWonderNewsAllowed(void) +{ + const struct WonderNews *news = &gSaveBlock1Ptr->mysteryGift.news; + if (news->sendType == SEND_TYPE_DISALLOWED) + return FALSE; -ALIGNED(2) const u8 sMG_Ereader_TextColor_1[] = { 0, 1, 2 }; -ALIGNED(2) const u8 sMG_Ereader_TextColor_1_Copy[] = { 0, 1, 2 }; -ALIGNED(2) const u8 sMG_Ereader_TextColor_2[] = { 1, 2, 3 }; + return TRUE; +} -void vblankcb_mystery_gift_e_reader_run(void) +static void ClearSavedWonderNews(void) { - ProcessSpriteCopyRequests(); - LoadOam(); - TransferPlttBuffer(); + CpuFill32(0, GetSavedWonderNews(), sizeof(gSaveBlock1Ptr->mysteryGift.news)); + gSaveBlock1Ptr->mysteryGift.newsCrc = 0; } -void c2_mystery_gift_e_reader_run(void) +static void ClearSavedWonderNewsMetadata(void) { - RunTasks(); - RunTextPrinters(); - AnimateSprites(); - BuildOamBuffer(); + CpuFill32(0, GetSavedWonderNewsMetadata(), sizeof(gSaveBlock1Ptr->mysteryGift.newsMetadata)); + InitSavedWonderNews(); } -bool32 HandleMysteryGiftOrEReaderSetup(s32 mg_or_ereader) +bool32 IsWonderNewsSameAsSaved(const u8 *news) { - switch (gMain.state) + const u8 *savedNews = (const u8 *)&gSaveBlock1Ptr->mysteryGift.news; + u32 i; + if (!ValidateSavedWonderNews()) + return FALSE; + + for (i = 0; i < sizeof(gSaveBlock1Ptr->mysteryGift.news); i++) { - 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)); - - bgid_upload_textbox_1(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(gUnkTextboxBorderPal, 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(mg_or_ereader, 0); - 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_mystery_gift_e_reader_run); - EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); - return TRUE; + if (savedNews[i] != news[i]) + return FALSE; } - return FALSE; + return TRUE; } -void c2_mystery_gift(void) +void ClearSavedWonderCardAndRelated(void) { - if (HandleMysteryGiftOrEReaderSetup(0)) - { - SetMainCallback2(c2_mystery_gift_e_reader_run); - gGiftIsFromEReader = FALSE; - task_add_00_mystery_gift(); - } - RunTasks(); + ClearSavedWonderCard(); + ClearSavedWonderCardMetadata(); + ClearSavedTrainerIds(); + ClearRamScript(); + ClearMysteryGiftFlags(); + ClearMysteryGiftVars(); + ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer); } -void c2_ereader(void) +bool32 SaveWonderCard(const struct WonderCard *card) { - if (HandleMysteryGiftOrEReaderSetup(1)) - { - SetMainCallback2(c2_mystery_gift_e_reader_run); - gGiftIsFromEReader = TRUE; - task_add_00_ereader(); - } -} + struct WonderCardMetadata *metadata; + if (!ValidateWonderCard(card)) + return FALSE; -void MainCB_FreeAllBuffersAndReturnToInitTitleScreen(void) -{ - gGiftIsFromEReader = FALSE; - FreeAllWindowBuffers(); - Free(GetBgTilemapBuffer(0)); - Free(GetBgTilemapBuffer(1)); - Free(GetBgTilemapBuffer(2)); - Free(GetBgTilemapBuffer(3)); - SetMainCallback2(CB2_InitTitleScreen); + ClearSavedWonderCardAndRelated(); + memcpy(&gSaveBlock1Ptr->mysteryGift.card, card, sizeof(struct WonderCard)); + gSaveBlock1Ptr->mysteryGift.cardCrc = CALC_CRC(gSaveBlock1Ptr->mysteryGift.card); + metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata; + metadata->iconSpecies = (&gSaveBlock1Ptr->mysteryGift.card)->iconSpecies; + return TRUE; } -void PrintMysteryGiftOrEReaderTopMenu(bool8 mg_or_ereader, bool32 usePickOkCancel) +bool32 ValidateSavedWonderCard(void) { - const u8 * header; - const u8 * options; - FillWindowPixelBuffer(0, 0); - if (mg_or_ereader == 0) - { - header = gText_MysteryGift; - options = !usePickOkCancel ? gText_PickOKExit : gText_PickOKCancel; - } - else - { - header = gJPText_MysteryGift; - options = gJPText_DecideStop; - } + if (gSaveBlock1Ptr->mysteryGift.cardCrc != CALC_CRC(gSaveBlock1Ptr->mysteryGift.card)) + return FALSE; + if (!ValidateWonderCard(&gSaveBlock1Ptr->mysteryGift.card)) + return FALSE; + if (!ValidateSavedRamScript()) + return FALSE; - AddTextPrinterParameterized4(0, 1, 4, 1, 0, 0, sMG_Ereader_TextColor_1, -1, header); - AddTextPrinterParameterized4(0, 0, GetStringRightAlignXOffset(0, options, 0xDE), 1, 0, 0, sMG_Ereader_TextColor_1, -1, options); - CopyWindowToVram(0, 2); - PutWindowTilemap(0); + return TRUE; } -void MG_DrawTextBorder(u8 windowId) +static bool32 ValidateWonderCard(const struct WonderCard *card) { - DrawTextBorderOuter(windowId, 0x01, 0xF); + if (card->flagId == 0) + return FALSE; + if (card->type >= CARD_TYPE_COUNT) + return FALSE; + if (!(card->sendType == SEND_TYPE_DISALLOWED + || card->sendType == SEND_TYPE_ALLOWED + || card->sendType == SEND_TYPE_ALLOWED_ALWAYS)) + return FALSE; + if (card->bgType >= NUM_WONDER_BGS) + return FALSE; + if (card->maxStamps > MAX_STAMP_CARD_STAMPS) + return FALSE; + + return TRUE; } -void MG_DrawCheckerboardPattern(u32 bg) +bool32 IsSendingSavedWonderCardAllowed(void) { - s32 i = 0, j; + const struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card; + if (card->sendType == SEND_TYPE_DISALLOWED) + return FALSE; - FillBgTilemapBufferRect(bg, 0x003, 0, 0, 32, 2, 0x11); + return TRUE; +} - 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 ClearSavedWonderCard(void) +{ + CpuFill32(0, &gSaveBlock1Ptr->mysteryGift.card, sizeof(gSaveBlock1Ptr->mysteryGift.card)); + gSaveBlock1Ptr->mysteryGift.cardCrc = 0; } -void ClearScreenInBg0(bool32 ignoreTopTwoRows) +static void ClearSavedWonderCardMetadata(void) { - 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); + CpuFill32(0, GetSavedWonderCardMetadata(), sizeof(gSaveBlock1Ptr->mysteryGift.cardMetadata)); + gSaveBlock1Ptr->mysteryGift.cardMetadataCrc = 0; } -void AddTextPrinterToWindow1(const u8 *str) +u16 GetWonderCardFlagID(void) { - 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); + if (ValidateSavedWonderCard()) + return gSaveBlock1Ptr->mysteryGift.card.flagId; + + return 0; } -static void ClearTextWindow(void) +void DisableWonderCardSending(struct WonderCard *card) { - rbox_fill_rectangle(1); - ClearWindowTilemap(1); - CopyWindowToVram(1, 1); + if (card->sendType == SEND_TYPE_ALLOWED) + card->sendType = SEND_TYPE_DISALLOWED; } -bool32 MG_PrintTextOnWindow1AndWaitButton(u8 *textState, const u8 *str) +static bool32 IsWonderCardFlagIDInValidRange(u16 flagId) { - switch (*textState) - { - case 0: - AddTextPrinterToWindow1(str); - (*textState)++; - break; - case 1: - DrawDownArrow(1, 0xD0, 0x14, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]); - if (({JOY_NEW(A_BUTTON | B_BUTTON);})) - (*textState)++; - break; - case 2: - DrawDownArrow(1, 0xD0, 0x14, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]); - *textState = 0; - ClearTextWindow(); + if (flagId >= WONDER_CARD_FLAG_OFFSET && flagId < WONDER_CARD_FLAG_OFFSET + NUM_WONDER_CARD_FLAGS) return TRUE; - case 0xFF: - *textState = 2; - return FALSE; - } + return FALSE; } -static void HideDownArrow(void) +static const u16 sReceivedGiftFlags[] = +{ + FLAG_RECEIVED_AURORA_TICKET, + FLAG_RECEIVED_MYSTIC_TICKET, + FLAG_RECEIVED_OLD_SEA_MAP, + FLAG_WONDER_CARD_UNUSED_1, + FLAG_WONDER_CARD_UNUSED_2, + FLAG_WONDER_CARD_UNUSED_3, + FLAG_WONDER_CARD_UNUSED_4, + FLAG_WONDER_CARD_UNUSED_5, + FLAG_WONDER_CARD_UNUSED_6, + FLAG_WONDER_CARD_UNUSED_7, + FLAG_WONDER_CARD_UNUSED_8, + FLAG_WONDER_CARD_UNUSED_9, + FLAG_WONDER_CARD_UNUSED_10, + FLAG_WONDER_CARD_UNUSED_11, + FLAG_WONDER_CARD_UNUSED_12, + FLAG_WONDER_CARD_UNUSED_13, + FLAG_WONDER_CARD_UNUSED_14, + FLAG_WONDER_CARD_UNUSED_15, + FLAG_WONDER_CARD_UNUSED_16, + FLAG_WONDER_CARD_UNUSED_17, +}; + +bool32 IsSavedWonderCardGiftNotReceived(void) { - DrawDownArrow(1, 0xD0, 0x14, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]); + u16 value = GetWonderCardFlagID(); + if (!IsWonderCardFlagIDInValidRange(value)) + return FALSE; + + // If flag is set, player has received gift from this card + if (FlagGet(sReceivedGiftFlags[value - WONDER_CARD_FLAG_OFFSET]) == TRUE) + return FALSE; + + return TRUE; } -static void ShowDownArrow(void) +static int GetNumStampsInMetadata(const struct WonderCardMetadata *data, int size) { - DrawDownArrow(1, 0xD0, 0x14, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]); + int numStamps = 0; + int i; + for (i = 0; i < size; i++) + { + if (data->stampData[STAMP_ID][i] && data->stampData[STAMP_SPECIES][i] != SPECIES_NONE) + numStamps++; + } + + return numStamps; } -bool32 unref_HideDownArrowAndWaitButton(u8 * textState) +static bool32 IsStampInMetadata(const struct WonderCardMetadata *metadata, const u16 *stamp, int maxStamps) { - switch (*textState) + int i; + for (i = 0; i < maxStamps; i++) { - case 0: - HideDownArrow(); - if (JOY_NEW(A_BUTTON | B_BUTTON)) - (*textState)++; - break; - case 1: - ShowDownArrow(); - *textState = 0; - return TRUE; + if (metadata->stampData[STAMP_ID][i] == stamp[STAMP_ID]) + return TRUE; + if (metadata->stampData[STAMP_SPECIES][i] == stamp[STAMP_SPECIES]) + return TRUE; } + return FALSE; } -static bool32 PrintStringAndWait2Seconds(u8 * counter, const u8 * str) +static bool32 ValidateStamp(const u16 *stamp) { - if (*counter == 0) - AddTextPrinterToWindow1(str); - - if (++(*counter) > 120) - { - *counter = 0; - ClearTextWindow(); - return TRUE; - } - else - { + if (stamp[STAMP_ID] == 0) return FALSE; - } + if (stamp[STAMP_SPECIES] == SPECIES_NONE) + return FALSE; + if (stamp[STAMP_SPECIES] >= NUM_SPECIES) + return FALSE; + return TRUE; } -static u32 MysteryGift_HandleThreeOptionMenu(u8 * unused0, u16 * unused1, u8 whichMenu) +static int GetNumStampsInSavedCard(void) { - struct ListMenuTemplate listMenuTemplate = sListMenuTemplate_ThreeOptions; - struct WindowTemplate windowTemplate = sWindowTemplate_ThreeOptions; - s32 width; - s32 response; + struct WonderCard *card; + if (!ValidateSavedWonderCard()) + return 0; - 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; + card = &gSaveBlock1Ptr->mysteryGift.card; + if (card->type != CARD_TYPE_STAMP) + return 0; - response = DoMysteryGiftListMenu(&windowTemplate, &listMenuTemplate, 1, 0x00A, 0xE0); - if (response != -1) - { - ClearWindowTilemap(2); - CopyWindowToVram(2, 1); - } - return response; + return GetNumStampsInMetadata(&gSaveBlock1Ptr->mysteryGift.cardMetadata, card->maxStamps); } -s8 mevent_message_print_and_prompt_yes_no(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str) +bool32 MysteryGift_TrySaveStamp(const u16 *stamp) { - struct WindowTemplate windowTemplate; - s8 input; + struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card; + int maxStamps = card->maxStamps; + int i; + if (!ValidateStamp(stamp)) + return FALSE; + + if (IsStampInMetadata(&gSaveBlock1Ptr->mysteryGift.cardMetadata, stamp, maxStamps)) + return FALSE; - switch (*textState) + for (i = 0; i < maxStamps; i++) { - case 0: - StringExpandPlaceholders(gStringVar4, str); - if (yesNoBoxPlacement == 0) - *windowId = AddWindow(&sWindowTemplate_PromptYesOrNo_Width28); - else - *windowId = AddWindow(&sWindowTemplate_PromptYesOrNo_Width20); - 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 (yesNoBoxPlacement == 0) - windowTemplate.tilemapTop = 9; - else - windowTemplate.tilemapTop = 15; - CreateYesNoMenu(&windowTemplate, 10, 14, 0); - (*textState)++; - break; - case 2: - input = Menu_ProcessInputNoWrapClearOnChoose(); - if (input == MENU_B_PRESSED || input == 0 || input == 1) + if (gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_ID][i] == 0 + && gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_SPECIES][i] == SPECIES_NONE) { - *textState = 0; - rbox_fill_rectangle(*windowId); - ClearWindowTilemap(*windowId); - CopyWindowToVram(*windowId, 1); - RemoveWindow(*windowId); - return input; + gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_ID][i] = stamp[STAMP_ID]; + gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_SPECIES][i] = stamp[STAMP_SPECIES]; + return TRUE; } - break; - case (u8)MENU_B_PRESSED: - *textState = 0; - rbox_fill_rectangle(*windowId); - ClearWindowTilemap(*windowId); - CopyWindowToVram(*windowId, 1); - RemoveWindow(*windowId); - return MENU_B_PRESSED; } - return MENU_NOTHING_CHOSEN; + return FALSE; } -static s32 HandleMysteryGiftListMenu(u8 * textState, u16 * windowId, bool32 cannotToss, bool32 cannotSend) +#define GAME_DATA_VALID_VAR 0x101 +#define GAME_DATA_VALID_GIFT_TYPE_1 (1 << 2) +#define GAME_DATA_VALID_GIFT_TYPE_2 (1 << 9) + +void MysteryGift_LoadLinkGameData(struct MysteryGiftLinkGameData *data, bool32 isWonderNews) { - struct WindowTemplate windowTemplate; - s32 input; + int i; + CpuFill32(0, data, sizeof(*data)); + data->validationVar = GAME_DATA_VALID_VAR; + data->validationFlag1 = 1; + data->validationFlag2 = 1; - switch (*textState) + if (isWonderNews) { - case 0: - if (cannotToss == 0) - { - StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithCards); - } - else - { - StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithNews); - } - *windowId = AddWindow(&sMysteryGiftMenuWindowTemplate); - 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 == 0) - { - input = DoMysteryGiftListMenu(&sWindowTemplate_7by6, &sListMenu_ReceiveToss, 1, 0x00A, 0xE0); - } - else - { - input = DoMysteryGiftListMenu(&sWindowTemplate_7by4, &sListMenu_Receive, 1, 0x00A, 0xE0); - } - } - else - { - if (cannotToss == 0) - { - input = DoMysteryGiftListMenu(&sWindowTemplate_7by8, &sListMenu_ReceiveSendToss, 1, 0x00A, 0xE0); - } - else - { - input = DoMysteryGiftListMenu(&sWindowTemplate_7by6, &sListMenu_ReceiveSend, 1, 0x00A, 0xE0); - } - } - if (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 -2; + // Despite setting these for News, they are + // only ever checked for Cards + data->validationGiftType1 = GAME_DATA_VALID_GIFT_TYPE_1 | 1; + data->validationGiftType2 = GAME_DATA_VALID_GIFT_TYPE_2 | 1; + } + else // Wonder Card + { + data->validationGiftType1 = GAME_DATA_VALID_GIFT_TYPE_1; + data->validationGiftType2 = GAME_DATA_VALID_GIFT_TYPE_2; } - return -1; -} - -static bool32 ValidateCardOrNews(bool32 cardOrNews) -{ - if (cardOrNews == 0) + if (ValidateSavedWonderCard()) { - return ValidateReceivedWonderCard(); + data->flagId = GetSavedWonderCard()->flagId; + data->cardMetadata = *GetSavedWonderCardMetadata(); + data->maxStamps = GetSavedWonderCard()->maxStamps; } else { - return ValidateReceivedWonderNews(); + data->flagId = 0; } + + for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++) + data->questionnaireWords[i] = gSaveBlock1Ptr->mysteryGift.questionnaireWords[i]; + + CopyTrainerId(data->playerTrainerId, gSaveBlock2Ptr->playerTrainerId); + StringCopy(data->playerName, gSaveBlock2Ptr->playerName); + for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++) + data->easyChatProfile[i] = gSaveBlock1Ptr->easyChatProfile[i]; + + memcpy(data->romHeaderGameCode, RomHeaderGameCode, GAME_CODE_LENGTH); + data->romHeaderSoftwareVersion = RomHeaderSoftwareVersion; } -static bool32 HandleLoadWonderCardOrNews(u8 * state, bool32 cardOrNews) +bool32 MysteryGift_ValidateLinkGameData(const struct MysteryGiftLinkGameData *data, bool32 isWonderNews) { - switch (*state) + if (data->validationVar != GAME_DATA_VALID_VAR) + return FALSE; + + if (!(data->validationFlag1 & 1)) + return FALSE; + + if (!(data->validationFlag2 & 1)) + return FALSE; + + if (!isWonderNews) { - case 0: - if (cardOrNews == 0) - { - InitWonderCardResources(GetSavedWonderCard(), sav1_get_mevent_buffer_2()); - } - else - { - InitWonderNewsResources(GetSavedWonderNews()); - } - (*state)++; - break; - case 1: - if (cardOrNews == 0) - { - if (!FadeToWonderCardMenu()) - { - return FALSE; - } - } - else - { - if (!FadeToWonderNewsMenu()) - { - return FALSE; - } - } - *state = 0; - return TRUE; + if (!(data->validationGiftType1 & GAME_DATA_VALID_GIFT_TYPE_1)) + return FALSE; + + if (!(data->validationGiftType2 & (GAME_DATA_VALID_GIFT_TYPE_2 | 0x180))) + return FALSE; } - return FALSE; + return TRUE; } -static bool32 DestroyNewsOrCard(bool32 cardOrNews) +u32 MysteryGift_CompareCardFlags(const u16 *flagId, const struct MysteryGiftLinkGameData *data, const void *unused) { - if (cardOrNews == 0) - { - DestroyWonderCard(); - } - else - { - DestroyWonderNews(); - } - return TRUE; + // Has a Wonder Card already? + if (data->flagId == 0) + return HAS_NO_CARD; + + // Has this Wonder Card already? + if (*flagId == data->flagId) + return HAS_SAME_CARD; + + // Player has a different Wonder Card + return HAS_DIFF_CARD; } -static bool32 TearDownCardOrNews_ReturnToTopMenu(bool32 cardOrNews, bool32 arg1) +// This is referenced by the Mystery Gift server, but the instruction it's referenced in is never used, +// so the return values here are never checked by anything. +u32 MysteryGift_CheckStamps(const u16 *stamp, const struct MysteryGiftLinkGameData *data, const void *unused) { - if (cardOrNews == 0) - { - if (FadeOutFromWonderCard(arg1) != 0) - { - DestroyWonderCardResources(); - return TRUE; - } - else - { - return FALSE; - } - } - else + int stampsMissing = data->maxStamps - GetNumStampsInMetadata(&data->cardMetadata, data->maxStamps); + + // Has full stamp card? + if (stampsMissing == 0) + return 1; + + // Already has stamp? + if (IsStampInMetadata(&data->cardMetadata, stamp, data->maxStamps)) + return 3; + + // Only 1 empty stamp left? + if (stampsMissing == 1) + return 4; + + // This is a new stamp + return 2; +} + +bool32 MysteryGift_DoesQuestionnaireMatch(const struct MysteryGiftLinkGameData *data, const u16 *words) +{ + int i; + for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++) { - if (FadeOutFromWonderNews(arg1) != 0) - { - DestroyWonderNewsResources(); - return TRUE; - } - else - { + if (data->questionnaireWords[i] != words[i]) return FALSE; - } } + + return TRUE; } -static s32 mevent_message_prompt_discard(u8 * textState, u16 * windowId, bool32 cardOrNews) +static int GetNumStampsInLinkData(const struct MysteryGiftLinkGameData *data) { - if (cardOrNews == 0) - { - return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_IfThrowAwayCardEventWontHappen); - } - else - { - return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_OkayToDiscardNews); - } + return GetNumStampsInMetadata(&data->cardMetadata, data->maxStamps); } -static bool32 mevent_message_was_thrown_away(u8 * textState, bool32 cardOrNews) +u16 MysteryGift_GetCardStatFromLinkData(const struct MysteryGiftLinkGameData *data, u32 stat) { - if (cardOrNews == 0) - { - return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderCardThrownAway); - } - else + switch (stat) { - return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderNewsThrownAway); + case CARD_STAT_BATTLES_WON: + return data->cardMetadata.battlesWon; + case CARD_STAT_BATTLES_LOST: + return data->cardMetadata.battlesLost; + case CARD_STAT_NUM_TRADES: + return data->cardMetadata.numTrades; + case CARD_STAT_NUM_STAMPS: + return GetNumStampsInLinkData(data); + case CARD_STAT_MAX_STAMPS: + return data->maxStamps; + default: + AGB_ASSERT(0); + return 0; } } -static bool32 mevent_save_game(u8 * state) +static void IncrementCardStat(u32 statType) { - switch (*state) + struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card; + if (card->type == CARD_TYPE_LINK_STAT) { - 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);})) + u16 *stat = NULL; + switch (statType) { - (*state)++; + case CARD_STAT_BATTLES_WON: + stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.battlesWon; + break; + case CARD_STAT_BATTLES_LOST: + stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.battlesLost; + break; + case CARD_STAT_NUM_TRADES: + stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.numTrades; + break; + case CARD_STAT_NUM_STAMPS: // Unused + case CARD_STAT_MAX_STAMPS: // Unused + break; } - break; - case 4: - *state = 0; - ClearTextWindow(); - return TRUE; - } - - return FALSE; -} - -static const u8 * mevent_message(u32 * a0, u8 a1, u8 cardOrNews, u32 msgId) -{ - const u8 * msg = NULL; - *a0 = 0; - switch (msgId) - { - case 0: - *a0 = 0; - msg = gText_NothingSentOver; - break; - case 1: - *a0 = 0; - msg = gText_RecordUploadedViaWireless; - break; - case 2: - *a0 = 1; - msg = cardOrNews == 0 ? gText_WonderCardReceived : gText_WonderCardReceivedFrom; - break; - case 3: - *a0 = 1; - msg = cardOrNews == 0 ? gText_WonderNewsReceived : gText_WonderNewsReceivedFrom; - break; - case 4: - *a0 = 1; - msg = gText_NewStampReceived; - break; - case 5: - *a0 = 0; - msg = gText_AlreadyHadCard; - break; - case 6: - *a0 = 0; - msg = gText_AlreadyHadStamp; - break; - case 7: - *a0 = 0; - msg = gText_AlreadyHadNews; - break; - case 8: - *a0 = 0; - msg = gText_NoMoreRoomForStamps; - break; - case 9: - *a0 = 0; - msg = gText_CommunicationCanceled; - break; - case 10: - *a0 = 0; - msg = a1 == 0 ? gText_CantAcceptCardFromTrainer : gText_CantAcceptNewsFromTrainer; - break; - case 11: - *a0 = 0; - msg = gText_CommunicationError; - break; - case 12: - *a0 = 1; - msg = gText_NewTrainerReceived; - break; - case 13: - *a0 = 1; - break; - case 14: - *a0 = 0; - break; + if (stat == NULL) + AGB_ASSERT(0); + else if (++(*stat) > MAX_WONDER_CARD_STAT) + *stat = MAX_WONDER_CARD_STAT; } - - return msg; } -static bool32 PrintMGSuccessMessage(u8 * state, const u8 * arg1, u16 * arg2) +u16 MysteryGift_GetCardStat(u32 stat) { - switch (*state) + switch (stat) { - case 0: - if (arg1 != NULL) + case CARD_STAT_BATTLES_WON: + { + struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card; + if (card->type == CARD_TYPE_LINK_STAT) { - AddTextPrinterToWindow1(arg1); + struct WonderCardMetadata *metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata; + return metadata->battlesWon; } - PlayFanfare(MUS_OBTAIN_ITEM); - *arg2 = 0; - (*state)++; break; - case 1: - if (++(*arg2) > 0xF0) + } + case CARD_STAT_BATTLES_LOST: + { + struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card; + if (card->type == CARD_TYPE_LINK_STAT) { - (*state)++; + struct WonderCardMetadata *metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata; + return metadata->battlesLost; } break; - case 2: - if (IsFanfareTaskInactive()) + } + case CARD_STAT_NUM_TRADES: + { + struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card; + if (card->type == CARD_TYPE_LINK_STAT) { - *state = 0; - ClearTextWindow(); - return TRUE; + struct WonderCardMetadata *metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata; + return metadata->numTrades; } break; } - return FALSE; -} - -static const u8 * mevent_message_stamp_card_etc_send_status(u32 * a0, u8 unused, u32 msgId) -{ - const u8 * result = gText_CommunicationError; - *a0 = 0; - switch (msgId) + case CARD_STAT_NUM_STAMPS: { - case 0: - result = gText_NothingSentOver; - break; - case 1: - result = gText_RecordUploadedViaWireless; - break; - case 2: - result = gText_WonderCardSentTo; - *a0 = 1; - break; - case 3: - result = gText_WonderNewsSentTo; - *a0 = 1; - break; - case 4: - result = gText_StampSentTo; - break; - case 5: - result = gText_OtherTrainerHasCard; - break; - case 6: - result = gText_OtherTrainerHasStamp; - break; - case 7: - result = gText_OtherTrainerHasNews; - break; - case 8: - result = gText_NoMoreRoomForStamps; - break; - case 9: - result = gText_OtherTrainerCanceled; - break; - case 10: - result = gText_CantSendGiftToTrainer; - break; - case 11: - result = gText_CommunicationError; - break; - case 12: - result = gText_GiftSentTo; - break; - case 13: - result = gText_GiftSentTo; - break; - case 14: - result = gText_CantSendGiftToTrainer; + struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card; + if (card->type == CARD_TYPE_STAMP) + return GetNumStampsInSavedCard(); break; } - return result; -} - -static bool32 PrintMGSendStatus(u8 * state, u16 * arg1, u8 arg2, u32 msgId) -{ - u32 flag; - const u8 * str = mevent_message_stamp_card_etc_send_status(&flag, arg2, msgId); - if (flag) + case CARD_STAT_MAX_STAMPS: { - return PrintMGSuccessMessage(state, str, arg1); + struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card; + if (card->type == CARD_TYPE_STAMP) + return card->maxStamps; + break; } - else - { - return MG_PrintTextOnWindow1AndWaitButton(state, str); } + + AGB_ASSERT(0); + return 0; } -void task_add_00_mystery_gift(void) +void MysteryGift_DisableStats(void) { - u8 taskId = CreateTask(task00_mystery_gift, 0); - struct MysteryGiftTaskData * data = (void *)gTasks[taskId].data; - data->state = 0; - data->textState = 0; - data->unkA = 0; - data->unkB = 0; - data->IsCardOrNews = 0; - data->source = 0; - data->curPromptWindowId = 0; - data->unk2 = 0; - data->unk4 = 0; - data->unk6 = 0; - data->prevPromptWindowId = 0; - data->buffer = AllocZeroed(0x40); + sStatsEnabled = FALSE; } -void task00_mystery_gift(u8 taskId) +bool32 MysteryGift_TryEnableStatsByFlagId(u16 flagId) { - struct MysteryGiftTaskData *data = (void *)gTasks[taskId].data; - u32 sp0, flag; - const u8 *r1; + sStatsEnabled = FALSE; + if (flagId == 0) + return FALSE; + + if (!ValidateSavedWonderCard()) + return FALSE; + + if (gSaveBlock1Ptr->mysteryGift.card.flagId != flagId) + return FALSE; - switch (data->state) + sStatsEnabled = TRUE; + return TRUE; +} + +void MysteryGift_TryIncrementStat(u32 stat, u32 trainerId) +{ + if (sStatsEnabled) { - case 0: - data->state = 1; - break; - case 1: - switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->curPromptWindowId, FALSE)) + switch (stat) { - case 0: - data->IsCardOrNews = 0; - if (ValidateReceivedWonderCard() == TRUE) - { - data->state = 18; - } - else - { - data->state = 2; - } - break; - case 1: - data->IsCardOrNews = 1; - if (ValidateReceivedWonderNews() == TRUE) - { - data->state = 18; - } - else - { - data->state = 2; - } - break; - case -2u: - data->state = 37; + case CARD_STAT_NUM_TRADES: + IncrementCardStatForNewTrainer(CARD_STAT_NUM_TRADES, + trainerId, + gSaveBlock1Ptr->mysteryGift.trainerIds[1], + ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[1])); break; - } - break; - case 2: - { - if (data->IsCardOrNews == 0) - { - if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveCardNewOneInput)) - { - data->state = 3; - PrintMysteryGiftOrEReaderTopMenu(0, 1); - } - } - else - { - if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveNewsNewOneInput)) - { - data->state = 3; - PrintMysteryGiftOrEReaderTopMenu(0, 1); - } - } - break; - } - case 3: - if (data->IsCardOrNews == 0) - { - AddTextPrinterToWindow1(gText_WhereShouldCardBeAccessed); - } - else - { - AddTextPrinterToWindow1(gText_WhereShouldNewsBeAccessed); - } - data->state = 4; - break; - case 4: - switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->curPromptWindowId, TRUE)) - { - case 0: - ClearTextWindow(); - data->state = 5; - data->source = 0; + case CARD_STAT_BATTLES_WON: + IncrementCardStatForNewTrainer(CARD_STAT_BATTLES_WON, + trainerId, + gSaveBlock1Ptr->mysteryGift.trainerIds[0], + ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[0])); break; - case 1: - ClearTextWindow(); - data->state = 5; - data->source = 1; + case CARD_STAT_BATTLES_LOST: + IncrementCardStatForNewTrainer(CARD_STAT_BATTLES_LOST, + trainerId, + gSaveBlock1Ptr->mysteryGift.trainerIds[0], + ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[0])); break; - case -2u: - ClearTextWindow(); - if (ValidateCardOrNews(data->IsCardOrNews)) - { - data->state = 18; - } - else - { - data->state = 0; - PrintMysteryGiftOrEReaderTopMenu(0, 0); - } + default: + AGB_ASSERT(0); break; } - break; - case 5: - *gStringVar1 = EOS; - *gStringVar2 = EOS; - *gStringVar3 = EOS; + } +} - switch (data->IsCardOrNews) - { - case 0: - if (data->source == 1) - { - MEvent_CreateTask_CardOrNewsWithFriend(ACTIVITY_WONDER_CARD); - } - else if (data->source == 0) - { - MEvent_CreateTask_CardOrNewsOverWireless(ACTIVITY_WONDER_CARD); - } - break; - case 1: - if (data->source == 1) - { - MEvent_CreateTask_CardOrNewsWithFriend(ACTIVITY_WONDER_NEWS); - } - else if (data->source == 0) - { - MEvent_CreateTask_CardOrNewsOverWireless(ACTIVITY_WONDER_NEWS); - } - break; - } - data->state = 6; - break; - case 6: - if (gReceivedRemoteLinkPlayers != 0) - { - ClearScreenInBg0(TRUE); - data->state = 7; - mevent_client_do_init(data->IsCardOrNews); - } - else if (gSpecialVar_Result == LINKUP_FAILED) - { - ClearScreenInBg0(TRUE); - data->state = 3; - } - break; - case 7: - AddTextPrinterToWindow1(gText_Communicating); - data->state = 8; - break; - case 8: - switch (mevent_client_do_exec(&data->curPromptWindowId)) - { - case 6: - Rfu_SetCloseLinkCallback(); - data->prevPromptWindowId = data->curPromptWindowId; - data->state = 13; - break; - case 5: - memcpy(data->buffer, mevent_client_get_buffer(), 0x40); - mevent_client_inc_flag(); - break; - case 3: - data->state = 10; - break; - case 2: - data->state = 9; - break; - case 4: - data->state = 11; - StringCopy(gStringVar1, gLinkPlayers[0].name); - break; - } - break; - case 9: - flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, mevent_client_get_buffer()); - switch (flag) - { - case 0: - mevent_client_set_param(0); - mevent_client_inc_flag(); - data->state = 7; - break; - case 1: - mevent_client_set_param(1); - mevent_client_inc_flag(); - data->state = 7; - break; - case -1u: - mevent_client_set_param(1); - mevent_client_inc_flag(); - data->state = 7; - break; - } - break; - case 10: - if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, mevent_client_get_buffer())) - { - mevent_client_inc_flag(); - data->state = 7; - } - break; - case 11: - flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_ThrowAwayWonderCard); - switch (flag) - { - case 0: - if (CheckReceivedGiftFromWonderCard() == TRUE) - { - data->state = 12; - } - else - { - mevent_client_set_param(0); - mevent_client_inc_flag(); - data->state = 7; - } - break; - case 1: - mevent_client_set_param(1); - mevent_client_inc_flag(); - data->state = 7; - break; - case -1u: - mevent_client_set_param(1); - mevent_client_inc_flag(); - data->state = 7; - break; - } - break; - case 12: - flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_HaventReceivedCardsGift); - switch (flag) - { - case 0: - mevent_client_set_param(0); - mevent_client_inc_flag(); - data->state = 7; - break; - case 1: - mevent_client_set_param(1); - mevent_client_inc_flag(); - data->state = 7; - break; - case -1u: - mevent_client_set_param(1); - mevent_client_inc_flag(); - data->state = 7; - break; - } - break; - case 13: - if (gReceivedRemoteLinkPlayers == 0) - { - DestroyWirelessStatusIndicatorSprite(); - data->state = 14; - } - break; - case 14: - if (PrintStringAndWait2Seconds(&data->textState, gText_CommunicationCompleted)) - { - if (data->source == 1) - { - StringCopy(gStringVar1, gLinkPlayers[0].name); - } - data->state = 15; - } - break; - case 15: - r1 = mevent_message(&sp0, data->IsCardOrNews, data->source, data->prevPromptWindowId); - if (r1 == NULL) - { - r1 = data->buffer; - } - if (sp0) - { - flag = PrintMGSuccessMessage(&data->textState, r1, &data->curPromptWindowId); - } - else - { - flag = MG_PrintTextOnWindow1AndWaitButton(&data->textState, r1); - } - if (flag) - { - if (data->prevPromptWindowId == 3) - { - if (data->source == 1) - { - GenerateRandomNews(1); - } - else - { - GenerateRandomNews(2); - } - } - if (!sp0) - { - data->state = 0; - PrintMysteryGiftOrEReaderTopMenu(0, 0); - } - else - { - data->state = 17; - } - } - break; - case 16: - if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError)) - { - data->state = 0; - PrintMysteryGiftOrEReaderTopMenu(0, 0); - } - break; - case 17: - if (mevent_save_game(&data->textState)) - { - data->state = 18; - } - break; - case 18: - if (HandleLoadWonderCardOrNews(&data->textState, data->IsCardOrNews)) - { - data->state = 20; - } - break; - case 20: - if (data->IsCardOrNews == 0) - { - if (({JOY_NEW(A_BUTTON);})) - { - data->state = 21; - } - if (({JOY_NEW(B_BUTTON);})) - { - data->state = 27; - } - } - else - { - switch (MENews_GetInput(gMain.newKeys)) - { - case 0: - MENews_RemoveScrollIndicatorArrowPair(); - data->state = 21; - break; - case 1: - data->state = 27; - break; - } - } - break; - case 21: +static void ClearSavedTrainerIds(void) +{ + CpuFill32(0, gSaveBlock1Ptr->mysteryGift.trainerIds, sizeof(gSaveBlock1Ptr->mysteryGift.trainerIds)); +} + +// Returns TRUE if it's a new trainer id, FALSE if an existing one. +// In either case the given trainerId is saved in element 0 +static bool32 RecordTrainerId(u32 trainerId, u32 *trainerIds, int size) +{ + int i, j; + + for (i = 0; i < size; i++) { - u32 result; - if (data->IsCardOrNews == 0) - { - if (WonderCard_Test_Unk_08_6()) - { - result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, FALSE); - } - else - { - result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, TRUE); - } - } - else - { - if (WonderNews_Test_Unk_02()) - { - result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, FALSE); - } - else - { - result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, TRUE); - } - } - switch (result) - { - case 0: - data->state = 28; - break; - case 1: - data->state = 29; + if (trainerIds[i] == trainerId) break; - case 2: - data->state = 22; - break; - case -2u: - if (data->IsCardOrNews == 1) - { - MENews_AddScrollIndicatorArrowPair(); - } - data->state = 20; - break; - } - break; } - case 22: - switch (mevent_message_prompt_discard(&data->textState, &data->curPromptWindowId, data->IsCardOrNews)) - { - case 0: - if (data->IsCardOrNews == 0 && CheckReceivedGiftFromWonderCard() == TRUE) - { - data->state = 23; - } - else - { - data->state = 24; - } - break; - case 1: - data->state = 21; - break; - case -1: - data->state = 21; - break; - } - break; - case 23: - switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, TRUE, gText_HaventReceivedGiftOkayToDiscard)) - { - case 0: - data->state = 24; - break; - case 1: - data->state = 21; - break; - case -1u: - data->state = 21; - break; - } - break; - case 24: - if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1)) - { - DestroyNewsOrCard(data->IsCardOrNews); - data->state = 25; - } - break; - case 25: - if (mevent_save_game(&data->textState)) - { - data->state = 26; - } - break; - case 26: - if (mevent_message_was_thrown_away(&data->textState, data->IsCardOrNews)) - { - data->state = 0; - PrintMysteryGiftOrEReaderTopMenu(0, 0); - } - break; - case 27: - if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 0)) - { - data->state = 0; - } - break; - case 28: - if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1)) - { - data->state = 3; - } - break; - case 29: - if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1)) - { - switch (data->IsCardOrNews) - { - case 0: - MEvent_CreateTask_Leader(ACTIVITY_WONDER_CARD); - break; - case 1: - MEvent_CreateTask_Leader(ACTIVITY_WONDER_NEWS); - break; - } - data->source = 1; - data->state = 30; - } - break; - case 30: - if (gReceivedRemoteLinkPlayers != 0) - { - ClearScreenInBg0(1); - data->state = 31; - } - else if (gSpecialVar_Result == LINKUP_FAILED) - { - ClearScreenInBg0(1); - data->state = 18; - } - break; - case 31: - *gStringVar1 = EOS; - *gStringVar2 = EOS; - *gStringVar3 = EOS; - if (data->IsCardOrNews == 0) - { - AddTextPrinterToWindow1(gText_SendingWonderCard); - mevent_srv_new_wcard(); - } - else - { - AddTextPrinterToWindow1(gText_SendingWonderNews); - mevent_srv_init_wnews(); - } - data->state = 32; - break; - case 32: - if (mevent_srv_common_do_exec(&data->curPromptWindowId) == 3) - { - data->prevPromptWindowId = data->curPromptWindowId; - data->state = 33; - } - break; - case 33: - Rfu_SetCloseLinkCallback(); - StringCopy(gStringVar1, gLinkPlayers[1].name); - data->state = 34; - break; - case 34: - if (gReceivedRemoteLinkPlayers == 0) - { - DestroyWirelessStatusIndicatorSprite(); - data->state = 35; - } - break; - case 35: - if (PrintMGSendStatus(&data->textState, &data->curPromptWindowId, data->source, data->prevPromptWindowId)) - { - if (data->source == 1 && data->prevPromptWindowId == 3) - { - GenerateRandomNews(3); - data->state = 17; - } - else - { - data->state = 0; - PrintMysteryGiftOrEReaderTopMenu(0, 0); - } - } - break; - case 36: - if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError)) - { - data->state = 0; - PrintMysteryGiftOrEReaderTopMenu(0, 0); - } - break; - case 37: - CloseLink(); - Free(data->buffer); - DestroyTask(taskId); - SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen); - break; + if (i == size) + { + // New trainer, shift array and insert new id at front + for (j = size - 1; j > 0; j--) + trainerIds[j] = trainerIds[j - 1]; + + trainerIds[0] = trainerId; + return TRUE; } -} + else + { + // Existing trainer, shift back to old slot and move id to front + for (j = i; j > 0; j--) + trainerIds[j] = trainerIds[j - 1]; -u16 GetMysteryGiftBaseBlock(void) -{ - return 0x1A9; + trainerIds[0] = trainerId; + return FALSE; + } } -void bgid_upload_textbox_1(u8 bgId) +static void IncrementCardStatForNewTrainer(u32 stat, u32 trainerId, u32 *trainerIds, int size) { - DecompressAndLoadBgGfxUsingHeap(bgId, gUnkTextboxBorderGfx, 0x100, 0, 0); + if (RecordTrainerId(trainerId, trainerIds, size)) + IncrementCardStat(stat); } |