#include "global.h" #include "gflib.h" #include "scanline_effect.h" #include "task.h" #include "link.h" #include "overworld.h" #include "menu.h" #include "event_data.h" #include "easy_chat.h" #include "money.h" #include "strings.h" #include "trainer_card.h" #include "pokedex.h" #include "pokemon_icon.h" #include "graphics.h" #include "help_system.h" #include "trainer_pokemon_sprites.h" #include "new_menu_helpers.h" #include "constants/songs.h" #include "constants/game_stat.h" #include "constants/trainers.h" // Trainer Card Strings enum { TRAINER_CARD_STRING_NAME = 0, TRAINER_CARD_STRING_HOF_TIME, TRAINER_CARD_STRING_LINK_RECORD, TRAINER_CARD_STRING_WIN_LOSS, TRAINER_CARD_STRING_LINK_WINS, TRAINER_CARD_STRING_LINK_LOSSES, TRAINER_CARD_STRING_TRADES, TRAINER_CARD_STRING_TRADE_COUNT, TRAINER_CARD_STRING_BERRY_CRUSH, TRAINER_CARD_STRING_BERRY_CRUSH_COUNT, TRAINER_CARD_STRING_UNION_ROOM, TRAINER_CARD_STRING_UNION_ROOM_NUM, TRAINER_CARD_STRING_COUNT, }; struct TrainerCardData { u8 mainState; u8 printState; u8 gfxLoadState; u8 bgPalLoadState; u8 flipDrawState; bool8 isLink; u8 timeColonBlinkTimer; bool8 timeColonInvisible; bool8 onBack; bool8 allowDMACopy; bool8 hasPokedex; bool8 hasHofResult; bool8 hasLinkResults; bool8 hasBattleTowerWins; bool8 var_E; bool8 var_F; bool8 hasTrades; bool8 hasBadge[NUM_BADGES]; u8 easyChatProfile[TRAINER_CARD_PROFILE_LENGTH][13]; u8 strings[TRAINER_CARD_STRING_COUNT][70]; u8 var_395; u16 monIconPals[16 * PARTY_SIZE]; s8 flipBlendY; u8 cardType; void (*callback2)(void); struct TrainerCard trainerCard; u16 frontTilemap[600]; u16 backTilemap[600]; u16 bgTilemap[600]; u8 badgeTiles[0x80 * NUM_BADGES]; u16 stickerTiles[0x100]; u16 cardTiles[0x1180]; u16 cardTilemapBuffer[0x1000]; u16 bgTilemapBuffer[0x1000]; u16 cardTop; bool8 timeColonNeedDraw; u8 language; }; /* size = 0x7BD0 */ // RAM EWRAM_DATA struct TrainerCard gTrainerCards[4] = {0}; EWRAM_DATA static struct TrainerCardData *sTrainerCardDataPtr = NULL; // Function Declaration static void VBlankCB_TrainerCard(void); static void HBlankCB_TrainerCard(void); static void CB2_TrainerCard(void); static void CloseTrainerCard(u8 taskId); static void Task_TrainerCard(u8 taskId); static bool8 LoadCardGfx(void); static void CB2_InitTrainerCard(void); static u32 GetCappedGameStat(u8 statId, u32 maxValue); static u8 GetTrainerStarCount(struct TrainerCard *trainerCard); static void SetPlayerCardData(struct TrainerCard *trainerCard, u8 cardType); static void SetDataFromTrainerCard(void); static void HandleGpuRegs(void); static void UpdateCardFlipRegs(u16 cardTop); static void ResetGpuRegs(void); static void TrainerCardNull(void); static void sub_8089C5C(void); static void sub_8089C80(void); static void sub_8089CA4(void); static void InitBgsAndWindows(void); static void SetTrainerCardCB2(void); static void SetUpTrainerCardTask(void); static bool8 PrintAllOnCardFront(void); static bool8 PrintAllOnCardBack(void); static void BufferTextForCardBack(void); static void PrintNameOnCardFront(void); static void PrintIdOnCard(void); static void PrintMoneyOnCard(void); static u16 GetCaughtMonsCount(void); static void PrintPokedexOnCard(void); static void PrintTimeOnCard(void); static void PrintProfilePhraseOnCard(void); static void BufferNameForCardBack(void); static void PrintNameOnCardBack(void); static void BufferHofDebutTime(void); static void PrintHofDebutTimeOnCard(void); static void BufferLinkBattleResults(void); static void PrintLinkBattleResultsOnCard(void); static void BufferNumTrades(void); static void PrintTradesStringOnCard(void); static void BufferBerryCrushPoints(void); static void PrintBerryCrushStringOnCard(void); static void BufferUnionRoomStats(void); static void PrintUnionStringOnCard(void); static void PrintPokemonIconsOnCard(void); static void LoadMonIconGfx(void); static void PrintStickersOnCard(void); static void LoadStickerGfx(void); static void DrawTrainerCardWindow(u8 windowId); static bool8 SetTrainerCardBgsAndPals(void); static void DrawCardScreenBackground(const u16* ptr); static void DrawCardFrontOrBack(const u16* ptr); static void DrawStarsAndBadgesOnCard(void); static void DrawCardBackStats(void); static void BlinkTimeColon(void); static void FlipTrainerCard(void); static bool8 IsCardFlipTaskActive(void); static void Task_DoCardFlipTask(u8 taskId); static bool8 Task_BeginCardFlip(struct Task* task); static bool8 Task_AnimateCardFlipDown(struct Task* task); static bool8 Task_DrawFlippedCardSide(struct Task* task); static bool8 Task_SetCardFlipped(struct Task* task); static bool8 Task_AnimateCardFlipUp(struct Task* task); static bool8 Task_EndCardFlip(struct Task *task); static void InitTrainerCardData(void); static u8 GetCardType(void); static void CreateTrainerCardTrainerPic(void); // Data static const u32 sTrainerCardStickers_Gfx[] = INCBIN_U32("graphics/trainer_card/stickers.4bpp.lz"); static const u32 sHoennTrainerCardFront_Tilemap[] = INCBIN_U32("graphics/trainer_card/front_hoenn.bin"); static const u32 sKantoTrainerCardFront_Tilemap[] = INCBIN_U32("graphics/trainer_card/front.bin"); static const u32 sHoennTrainerCardBack_Tilemap[] = INCBIN_U32("graphics/trainer_card/back_hoenn.bin"); static const u32 sKantoTrainerCardBack_Tilemap[] = INCBIN_U32("graphics/trainer_card/back.bin"); static const u32 sHoennTrainerCardFrontLink_Tilemap[] = INCBIN_U32("graphics/trainer_card/front_hoenn_link.bin"); static const u32 sKantoTrainerCardFrontLink_Tilemap[] = INCBIN_U32("graphics/trainer_card/front_link.bin"); static const u32 sHoennTrainerCardBg_Tilemap[] = INCBIN_U32("graphics/trainer_card/bg_hoenn.bin"); static const u32 sKantoTrainerCardBg_Tilemap[] = INCBIN_U32("graphics/trainer_card/bg.bin"); static const u16 sHoennTrainerCard1Stars_Pals[] = INCBIN_U16("graphics/trainer_card/em_1stars_pals.gbapal"); static const u16 sKantoTrainerCard1Stars_Pals[] = INCBIN_U16("graphics/trainer_card/fr_1stars_pals.gbapal"); static const u16 sHoennTrainerCard2Stars_Pals[] = INCBIN_U16("graphics/trainer_card/em_2stars_pals.gbapal"); static const u16 sKantoTrainerCard2Stars_Pals[] = INCBIN_U16("graphics/trainer_card/fr_2stars_pals.gbapal"); static const u16 sHoennTrainerCard3Stars_Pals[] = INCBIN_U16("graphics/trainer_card/em_3stars_pals.gbapal"); static const u16 sKantoTrainerCard3Stars_Pals[] = INCBIN_U16("graphics/trainer_card/fr_3stars_pals.gbapal"); static const u16 sHoennTrainerCard4Stars_Pals[] = INCBIN_U16("graphics/trainer_card/em_4stars_pals.gbapal"); static const u16 sKantoTrainerCard4Stars_Pals[] = INCBIN_U16("graphics/trainer_card/fr_4stars_pals.gbapal"); static const u16 sHoennTrainerCardFemaleBackground_Pal[] = INCBIN_U16("graphics/trainer_card/em_female_bg.gbapal"); static const u16 sKantoTrainerCardFemaleBackground_Pal[] = INCBIN_U16("graphics/trainer_card/fr_female_bg.gbapal"); static const u16 sHoennTrainerCardBadges_Pal[] = INCBIN_U16("graphics/trainer_card/em_badges.gbapal"); static const u16 sKantoTrainerCardBadges_Pal[] = INCBIN_U16("graphics/trainer_card/fr_badges.gbapal"); static const u16 sTrainerCardGold_Pal[] = INCBIN_U16("graphics/trainer_card/gold.gbapal"); static const u16 sTrainerCardStickerPal1[] = INCBIN_U16("graphics/trainer_card/sticker1.gbapal"); static const u16 sTrainerCardStickerPal2[] = INCBIN_U16("graphics/trainer_card/sticker2.gbapal"); static const u16 sTrainerCardStickerPal3[] = INCBIN_U16("graphics/trainer_card/sticker3.gbapal"); static const u16 sTrainerCardStickerPal4[] = INCBIN_U16("graphics/trainer_card/sticker4.gbapal"); static const u32 sHoennTrainerCardBadges_Gfx[] = INCBIN_U32("graphics/trainer_card/em_badges.4bpp.lz"); static const u32 sKantoTrainerCardBadges_Gfx[] = INCBIN_U32("graphics/trainer_card/badges.4bpp.lz"); static const struct BgTemplate sTrainerCardBgTemplates[4] = { { .bg = 0, .charBaseIndex = 0, .mapBaseIndex = 27, .screenSize = 2, .paletteMode = 0, .priority = 2, .baseTile = 0 }, { .bg = 1, .charBaseIndex = 2, .mapBaseIndex = 29, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0 }, { .bg = 2, .charBaseIndex = 0, .mapBaseIndex = 30, .screenSize = 0, .paletteMode = 0, .priority = 3, .baseTile = 0 }, { .bg = 3, .charBaseIndex = 0, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 1, .baseTile = 192 } }; static const struct WindowTemplate sTrainerCardWindowTemplates[4] = { { .bg = 1, .tilemapLeft = 2, .tilemapTop = 15, .width = 26, .height = 4, .paletteNum = 15, .baseBlock = 0x241 }, { .bg = 1, .tilemapLeft = 1, .tilemapTop = 1, .width = 27, .height = 18, .paletteNum = 15, .baseBlock = 0x1 }, { .bg = 3, .tilemapLeft = 19, .tilemapTop = 5, .width = 9, .height = 10, .paletteNum = 8, .baseBlock = 0x150 }, DUMMY_WIN_TEMPLATE }; static const u16 *const sHoennTrainerCardStarPals[] = { gHoennTrainerCard_Pal, sHoennTrainerCard1Stars_Pals, sHoennTrainerCard2Stars_Pals, sHoennTrainerCard3Stars_Pals, sHoennTrainerCard4Stars_Pals }; static const u16 *const sKantoTrainerCardStarPals[] = { gKantoTrainerCard_Pal, sKantoTrainerCard1Stars_Pals, sKantoTrainerCard2Stars_Pals, sKantoTrainerCard3Stars_Pals, sKantoTrainerCard4Stars_Pals }; static const u8 sTrainerCardTextColors[] = {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY}; static const u8 sTrainerCardStatColors[] = {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}; static const u8 sTimeColonInvisibleTextColors[] = {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_TRANSPARENT, TEXT_COLOR_TRANSPARENT}; static const u8 sTrainerCardFontIds[] = {0, 2, 0}; static const u8 sTrainerPicOffsets[2][GENDER_COUNT][2] = { // Kanto { [MALE] = {13, 4}, [FEMALE] = {13, 4} }, // Hoenn { [MALE] = {1, 0}, [FEMALE] = {1, 0} } }; static const u8 sTrainerPicFacilityClasses[][2] = { [CARD_TYPE_FRLG] = { [MALE] = FACILITY_CLASS_RED, [FEMALE] = FACILITY_CLASS_LEAF }, [CARD_TYPE_RSE] = { [MALE] = FACILITY_CLASS_BRENDAN, [FEMALE] = FACILITY_CLASS_MAY }, }; static const u8 sLinkTrainerPicFacilityClasses[GENDER_COUNT][NUM_LINK_TRAINER_CARD_CLASSES] = { [MALE] = { FACILITY_CLASS_COOLTRAINER_M, FACILITY_CLASS_BLACK_BELT, FACILITY_CLASS_CAMPER, FACILITY_CLASS_YOUNGSTER, FACILITY_CLASS_PSYCHIC_M, FACILITY_CLASS_BUG_CATCHER, FACILITY_CLASS_TAMER, FACILITY_CLASS_JUGGLER }, [FEMALE] = { FACILITY_CLASS_COOLTRAINER_F, FACILITY_CLASS_CHANNELER, FACILITY_CLASS_PICNICKER, FACILITY_CLASS_LASS, FACILITY_CLASS_RS_PSYCHIC_F, FACILITY_CLASS_BATTLE_GIRL, FACILITY_CLASS_RS_PKMN_BREEDER_F, FACILITY_CLASS_BEAUTY } }; static bool8 (*const sTrainerCardFlipTasks[])(struct Task *) = { Task_BeginCardFlip, Task_AnimateCardFlipDown, Task_DrawFlippedCardSide, Task_SetCardFlipped, Task_AnimateCardFlipUp, Task_EndCardFlip }; static const u8 sTrainerCardFrontNameXPositions[] = {0x14, 0x10}; static const u8 sTrainerCardFrontNameYPositions[] = {0x1D, 0x21}; static const u8 sTrainerCardIdXPositions[] = {0x8E, 0x80}; static const u8 sTrainerCardIdYPositions[] = {0xA, 0x9}; static const u8 *const sTimeColonTextColors[] = {sTrainerCardTextColors, sTimeColonInvisibleTextColors}; static const u8 sTrainerCardTimeHoursXPositions[] = {0x65, 0x55}; static const u8 sTrainerCardTimeHoursYPositions[] = {0x77, 0x67}; static const u8 sTrainerCardTimeMinutesXPositions[] = {0x7C, 0x6C}; static const u8 sTrainerCardTimeMinutesYPositions[] = {0x58, 0x59}; static const u8 sTrainerCardProfilePhraseXPositions[] = {0x73, 0x69}; static const u8 sTrainerCardProfilePhraseYPositions[] = {0x82, 0x78}; static const u8 sTrainerCardBackNameXPositions[] = {0x8A, 0xD8}; static const u8 sTrainerCardBackNameYPositions[] = {0xB, 0xA}; static const u8 sTrainerCardHofDebutXPositions[] = {0xA, 0x10, 0x0, 0x0}; static const u8 *const sLinkTrainerCardRecordStrings[] = {gText_LinkBattles, gText_LinkCableBattles}; static const u8 sPokemonIconPalSlots[] = {5, 6, 7, 8, 9, 10}; static const u8 sPokemonIconXOffsets[] = {0, 4, 8, 12, 16, 20}; static const u8 sStickerPalSlots[] = {11, 12, 13, 14}; static const u8 sStarYOffsets[] = {7, 6, 0, 0}; static const struct TrainerCard sLinkPlayerTrainerCardTemplate1 = { .rse = { .gender = MALE, .stars = 4, .hasPokedex = TRUE, .caughtAllHoenn = TRUE, .hasAllPaintings = TRUE, .hofDebutHours = 999, .hofDebutMinutes = 59, .hofDebutSeconds = 59, .caughtMonsCount = 200, .trainerId = 0x6072, .playTimeHours = 999, .playTimeMinutes = 59, .linkBattleWins = 5535, .linkBattleLosses = 5535, .battleTowerWins = 5535, .battleTowerStraightWins = 5535, .contestsWithFriends = 55555, .pokeblocksWithFriends = 44444, .pokemonTrades = 33333, .money = 999999, .easyChatProfile = {0, 0, 0, 0}, .playerName = _("あかみ どりお") }, .version = VERSION_FIRE_RED, .hasAllFrontierSymbols = FALSE, .berryCrushPoints = 5555, .unionRoomNum = 8500, .berriesPicked = 5456, .jumpsInRow = 6300, .shouldDrawStickers = TRUE, .hasAllMons = TRUE, .monIconTint = MON_ICON_TINT_PINK, .facilityClass = 0, .stickers = {1, 2, 3}, .monSpecies = {SPECIES_CHARIZARD, SPECIES_DIGLETT, SPECIES_NIDORINA, SPECIES_FEAROW, SPECIES_PARAS, SPECIES_SLOWBRO} }; static const struct TrainerCard sLinkPlayerTrainerCardTemplate2 = { .rse = { .gender = FEMALE, .stars = 2, .hasPokedex = TRUE, .caughtAllHoenn = TRUE, .hasAllPaintings = TRUE, .hofDebutHours = 999, .hofDebutMinutes = 59, .hofDebutSeconds = 59, .caughtMonsCount = 200, .trainerId = 0x6072, .playTimeHours = 999, .playTimeMinutes = 59, .linkBattleWins = 5535, .linkBattleLosses = 5535, .battleTowerWins = 65535, .battleTowerStraightWins = 65535, .contestsWithFriends = 55555, .pokeblocksWithFriends = 44444, .pokemonTrades = 33333, .money = 999999, .easyChatProfile = {0, 0, 0, 0}, .playerName = _("るびさふぁこ!") }, .version = 0, .hasAllFrontierSymbols = FALSE, .berryCrushPoints = 555, .unionRoomNum = 500, .berriesPicked = 456, .jumpsInRow = 300, .shouldDrawStickers = TRUE, .hasAllMons = TRUE, .monIconTint = MON_ICON_TINT_PINK, .facilityClass = 0, .stickers = {1, 2, 3}, .monSpecies = {SPECIES_CHARIZARD, SPECIES_DIGLETT, SPECIES_NIDORINA, SPECIES_FEAROW, SPECIES_PARAS, SPECIES_SLOWBRO} }; // Functions static void VBlankCB_TrainerCard(void) { LoadOam(); ProcessSpriteCopyRequests(); TransferPlttBuffer(); BlinkTimeColon(); if (sTrainerCardDataPtr->allowDMACopy) DmaCopy16(3, &gScanlineEffectRegBuffers[0], &gScanlineEffectRegBuffers[1], 0x140); } static void HBlankCB_TrainerCard(void) { u16 backup; u16 bgVOffset; backup = REG_IME; REG_IME = 0; bgVOffset = gScanlineEffectRegBuffers[1][REG_VCOUNT & 0xFF]; REG_BG0VOFS = bgVOffset; REG_IME = backup; } static void CB2_TrainerCard(void) { RunTasks(); AnimateSprites(); BuildOamBuffer(); UpdatePaletteFade(); } static void CloseTrainerCard(u8 taskId) { SetMainCallback2(sTrainerCardDataPtr->callback2); FreeAllWindowBuffers(); FREE_AND_SET_NULL(sTrainerCardDataPtr); DestroyTask(taskId); } // States for Task_TrainerCard. Skips the initial states, which are done once in order #define STATE_HANDLE_INPUT_FRONT 10 #define STATE_HANDLE_INPUT_BACK 11 #define STATE_WAIT_FLIP_TO_BACK 12 #define STATE_WAIT_FLIP_TO_FRONT 13 #define STATE_CLOSE_CARD 14 #define STATE_WAIT_LINK_PARTNER 15 #define STATE_CLOSE_CARD_LINK 16 static void Task_TrainerCard(u8 taskId) { switch (sTrainerCardDataPtr->mainState) { // Draw card initially case 0: if (!IsDma3ManagerBusyWithBgCopy()) { FillWindowPixelBuffer(1, PIXEL_FILL(0)); sTrainerCardDataPtr->mainState++; } break; case 1: if (PrintAllOnCardFront()) sTrainerCardDataPtr->mainState++; break; case 2: DrawTrainerCardWindow(1); sTrainerCardDataPtr->mainState++; break; case 3: FillWindowPixelBuffer(2, PIXEL_FILL(0)); CreateTrainerCardTrainerPic(); DrawTrainerCardWindow(2); sTrainerCardDataPtr->mainState++; break; case 4: DrawCardScreenBackground(sTrainerCardDataPtr->bgTilemap); sTrainerCardDataPtr->mainState++; break; case 5: DrawCardFrontOrBack(sTrainerCardDataPtr->frontTilemap); sTrainerCardDataPtr->mainState++; break; case 6: DrawStarsAndBadgesOnCard(); sTrainerCardDataPtr->mainState++; break; // Fade in case 7: if (gWirelessCommType == 1 && gReceivedRemoteLinkPlayers == TRUE) { LoadWirelessStatusIndicatorSpriteGfx(); CreateWirelessStatusIndicatorSprite(230, 150); } BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); SetVBlankCallback(VBlankCB_TrainerCard); sTrainerCardDataPtr->mainState++; break; case 8: if (!UpdatePaletteFade() && !IsDma3ManagerBusyWithBgCopy()) { PlaySE(SE_CARD_OPEN); sTrainerCardDataPtr->mainState = STATE_HANDLE_INPUT_FRONT; } break; case 9: if (!IsSEPlaying()) sTrainerCardDataPtr->mainState++; break; case STATE_HANDLE_INPUT_FRONT: // Blink the : in play time if (!gReceivedRemoteLinkPlayers && sTrainerCardDataPtr->timeColonNeedDraw) { PrintTimeOnCard(); DrawTrainerCardWindow(1); sTrainerCardDataPtr->timeColonNeedDraw = FALSE; } if (JOY_NEW(A_BUTTON)) { SetHelpContext(HELPCONTEXT_TRAINER_CARD_BACK); FlipTrainerCard(); PlaySE(SE_CARD_FLIP); sTrainerCardDataPtr->mainState = STATE_WAIT_FLIP_TO_BACK; } else if (JOY_NEW(B_BUTTON)) { if (gReceivedRemoteLinkPlayers && sTrainerCardDataPtr->isLink && InUnionRoom() == TRUE) { sTrainerCardDataPtr->mainState = STATE_WAIT_LINK_PARTNER; } else { BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); sTrainerCardDataPtr->mainState = STATE_CLOSE_CARD; } } break; case STATE_WAIT_FLIP_TO_BACK: if (IsCardFlipTaskActive() && Overworld_LinkRecvQueueLengthMoreThan2() != TRUE) { PlaySE(SE_CARD_OPEN); sTrainerCardDataPtr->mainState = STATE_HANDLE_INPUT_BACK; } break; case STATE_HANDLE_INPUT_BACK: if (JOY_NEW(B_BUTTON)) { if (gReceivedRemoteLinkPlayers && sTrainerCardDataPtr->isLink && InUnionRoom() == TRUE) { sTrainerCardDataPtr->mainState = STATE_WAIT_LINK_PARTNER; } else if (gReceivedRemoteLinkPlayers) { BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); sTrainerCardDataPtr->mainState = STATE_CLOSE_CARD; } else { SetHelpContext(HELPCONTEXT_TRAINER_CARD_FRONT); FlipTrainerCard(); sTrainerCardDataPtr->mainState = STATE_WAIT_FLIP_TO_FRONT; PlaySE(SE_CARD_FLIP); } } else if (JOY_NEW(A_BUTTON)) { if (gReceivedRemoteLinkPlayers && sTrainerCardDataPtr->isLink && InUnionRoom() == TRUE) { sTrainerCardDataPtr->mainState = STATE_WAIT_LINK_PARTNER; } else { BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); sTrainerCardDataPtr->mainState = STATE_CLOSE_CARD; } } break; case STATE_WAIT_LINK_PARTNER: SetCloseLinkCallback(); DrawDialogueFrame(0, 1); AddTextPrinterParameterized(0, 2, gText_WaitingTrainerFinishReading, 0, 1, TEXT_SPEED_FF, 0); CopyWindowToVram(0, COPYWIN_BOTH); sTrainerCardDataPtr->mainState = STATE_CLOSE_CARD_LINK; break; case STATE_CLOSE_CARD_LINK: if (!gReceivedRemoteLinkPlayers) { BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); sTrainerCardDataPtr->mainState = STATE_CLOSE_CARD; } break; case STATE_CLOSE_CARD: if (!UpdatePaletteFade()) CloseTrainerCard(taskId); break; case STATE_WAIT_FLIP_TO_FRONT: if (IsCardFlipTaskActive() && Overworld_LinkRecvQueueLengthMoreThan2() != TRUE) { sTrainerCardDataPtr->mainState = STATE_HANDLE_INPUT_FRONT; PlaySE(SE_CARD_OPEN); } break; } } static bool8 LoadCardGfx(void) { switch (sTrainerCardDataPtr->gfxLoadState) { case 0: if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE) LZ77UnCompWram(sHoennTrainerCardBg_Tilemap, sTrainerCardDataPtr->bgTilemap); else LZ77UnCompWram(sKantoTrainerCardBg_Tilemap, sTrainerCardDataPtr->bgTilemap); break; case 1: if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE) LZ77UnCompWram(sHoennTrainerCardBack_Tilemap, sTrainerCardDataPtr->backTilemap); else LZ77UnCompWram(sKantoTrainerCardBack_Tilemap, sTrainerCardDataPtr->backTilemap); break; case 2: if (!sTrainerCardDataPtr->isLink) { if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE) LZ77UnCompWram(sHoennTrainerCardFront_Tilemap, sTrainerCardDataPtr->frontTilemap); else LZ77UnCompWram(sKantoTrainerCardFront_Tilemap, sTrainerCardDataPtr->frontTilemap); } else { if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE) LZ77UnCompWram(sHoennTrainerCardFrontLink_Tilemap, sTrainerCardDataPtr->frontTilemap); else LZ77UnCompWram(sKantoTrainerCardFrontLink_Tilemap, sTrainerCardDataPtr->frontTilemap); } break; case 3: // ? Doesnt check for RSE, sHoennTrainerCardBadges_Gfx goes unused LZ77UnCompWram(sKantoTrainerCardBadges_Gfx, sTrainerCardDataPtr->badgeTiles); break; case 4: if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE) LZ77UnCompWram(gHoennTrainerCard_Gfx, &sTrainerCardDataPtr->cardTiles); else LZ77UnCompWram(gKantoTrainerCard_Gfx, &sTrainerCardDataPtr->cardTiles); break; case 5: if (sTrainerCardDataPtr->cardType == CARD_TYPE_FRLG) LZ77UnCompWram(sTrainerCardStickers_Gfx, sTrainerCardDataPtr->stickerTiles); break; default: sTrainerCardDataPtr->gfxLoadState = 0; return TRUE; } sTrainerCardDataPtr->gfxLoadState++; return FALSE; } static void CB2_InitTrainerCard(void) { switch (gMain.state) { case 0: ResetGpuRegs(); SetUpTrainerCardTask(); gMain.state++; break; case 1: TrainerCardNull(); gMain.state++; break; case 2: sub_8089C5C(); gMain.state++; break; case 3: sub_8089C80(); gMain.state++; // fallthrough case 4: sub_8089CA4(); gMain.state++; break; case 5: InitBgsAndWindows(); gMain.state++; break; case 6: LoadStdWindowFrameGfx(); gMain.state++; break; case 7: LoadMonIconGfx(); gMain.state++; break; case 8: if (LoadCardGfx() == TRUE) gMain.state++; break; case 9: LoadStickerGfx(); gMain.state++; break; case 10: HandleGpuRegs(); gMain.state++; break; case 11: BufferTextForCardBack(); gMain.state++; break; case 12: if (SetTrainerCardBgsAndPals() == TRUE) gMain.state++; break; case 13: gMain.state++; break; default: SetTrainerCardCB2(); break; } } static u32 GetCappedGameStat(u8 statId, u32 maxValue) { u32 statValue = GetGameStat(statId); return min(maxValue, statValue); } static u8 GetTrainerStarCount(struct TrainerCard *trainerCard) { u8 stars = 0; if (trainerCard->rse.hofDebutHours != 0 || trainerCard->rse.hofDebutMinutes != 0 || trainerCard->rse.hofDebutSeconds != 0) stars++; if (trainerCard->rse.caughtAllHoenn) stars++; if (trainerCard->rse.battleTowerStraightWins > 49) stars++; if (trainerCard->rse.hasAllPaintings) stars++; return stars; } static void SetPlayerCardData(struct TrainerCard *trainerCard, u8 cardType) { u32 playTime; u8 i; trainerCard->rse.gender = gSaveBlock2Ptr->playerGender; trainerCard->rse.playTimeHours = gSaveBlock2Ptr->playTimeHours; trainerCard->rse.playTimeMinutes = gSaveBlock2Ptr->playTimeMinutes; playTime = GetGameStat(GAME_STAT_FIRST_HOF_PLAY_TIME); if (!GetGameStat(GAME_STAT_ENTERED_HOF)) playTime = 0; trainerCard->rse.hofDebutHours = playTime >> 16; trainerCard->rse.hofDebutMinutes = (playTime >> 8) & 0xFF; trainerCard->rse.hofDebutSeconds = playTime & 0xFF; if ((playTime >> 16) > 999) { trainerCard->rse.hofDebutHours = 999; trainerCard->rse.hofDebutMinutes = 59; trainerCard->rse.hofDebutSeconds = 59; } trainerCard->rse.hasPokedex = FlagGet(FLAG_SYS_POKEDEX_GET); trainerCard->rse.caughtAllHoenn = HasAllHoennMons(); trainerCard->rse.caughtMonsCount = GetCaughtMonsCount(); trainerCard->rse.trainerId = (gSaveBlock2Ptr->playerTrainerId[1] << 8) | gSaveBlock2Ptr->playerTrainerId[0]; trainerCard->rse.linkBattleWins = GetCappedGameStat(GAME_STAT_LINK_BATTLE_WINS, 9999); trainerCard->rse.linkBattleLosses = GetCappedGameStat(GAME_STAT_LINK_BATTLE_LOSSES, 9999); trainerCard->rse.pokemonTrades = GetCappedGameStat(GAME_STAT_POKEMON_TRADES, 0xFFFF); trainerCard->rse.battleTowerWins = 0; trainerCard->rse.battleTowerStraightWins = 0; trainerCard->rse.contestsWithFriends = 0; trainerCard->rse.pokeblocksWithFriends = 0; trainerCard->rse.hasAllPaintings = FALSE; trainerCard->rse.money = GetMoney(&gSaveBlock1Ptr->money); for (i = 0; i < TRAINER_CARD_PROFILE_LENGTH; i++) trainerCard->rse.easyChatProfile[i] = gSaveBlock1Ptr->easyChatProfile[i]; StringCopy(trainerCard->rse.playerName, gSaveBlock2Ptr->playerName); if (cardType == CARD_TYPE_FRLG) { trainerCard->rse.stars = GetTrainerStarCount(trainerCard); } else if (cardType == CARD_TYPE_RSE) { trainerCard->rse.stars = 0; if (trainerCard->rse.hofDebutHours != 0 || (trainerCard->rse.hofDebutMinutes != 0 || trainerCard->rse.hofDebutSeconds != 0)) trainerCard->rse.stars = cardType; if (HasAllKantoMons()) trainerCard->rse.stars++; if (HasAllMons()) trainerCard->rse.stars++; } } void TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard *trainerCard) { u8 id = 0; trainerCard->version = GAME_VERSION; SetPlayerCardData(trainerCard, CARD_TYPE_RSE); if (GetCardType() != CARD_TYPE_FRLG) return; trainerCard->rse.stars = id; if (trainerCard->rse.hofDebutHours != 0 || trainerCard->rse.hofDebutMinutes != 0 || trainerCard->rse.hofDebutSeconds != 0) trainerCard->rse.stars = 1; trainerCard->rse.caughtAllHoenn = HasAllKantoMons(); trainerCard->hasAllMons = HasAllMons(); trainerCard->berriesPicked = gSaveBlock2Ptr->berryPick.berriesPicked; trainerCard->jumpsInRow = gSaveBlock2Ptr->pokeJump.jumpsInRow; trainerCard->berryCrushPoints = GetCappedGameStat(GAME_STAT_BERRY_CRUSH_POINTS, 0xFFFF); trainerCard->unionRoomNum = GetCappedGameStat(GAME_STAT_NUM_UNION_ROOM_BATTLES, 0xFFFF); trainerCard->shouldDrawStickers = TRUE; if (trainerCard->rse.caughtAllHoenn) trainerCard->rse.stars++; if (trainerCard->hasAllMons) trainerCard->rse.stars++; if (trainerCard->berriesPicked >= 200 && trainerCard->jumpsInRow >= 200) trainerCard->rse.stars++; id = ((u16)trainerCard->rse.trainerId) % NUM_LINK_TRAINER_CARD_CLASSES; if (trainerCard->rse.gender == FEMALE) trainerCard->facilityClass = sLinkTrainerPicFacilityClasses[FEMALE][id]; else trainerCard->facilityClass = sLinkTrainerPicFacilityClasses[MALE][id]; trainerCard->stickers[0] = VarGet(VAR_HOF_BRAG_STATE); trainerCard->stickers[1] = VarGet(VAR_EGG_BRAG_STATE); trainerCard->stickers[2] = VarGet(VAR_LINK_WIN_BRAG_STATE); trainerCard->monIconTint = VarGet(VAR_TRAINER_CARD_MON_ICON_TINT_IDX); trainerCard->monSpecies[0] = MailSpeciesToIconSpecies(VarGet(VAR_TRAINER_CARD_MON_ICON_1)); trainerCard->monSpecies[1] = MailSpeciesToIconSpecies(VarGet(VAR_TRAINER_CARD_MON_ICON_2)); trainerCard->monSpecies[2] = MailSpeciesToIconSpecies(VarGet(VAR_TRAINER_CARD_MON_ICON_3)); trainerCard->monSpecies[3] = MailSpeciesToIconSpecies(VarGet(VAR_TRAINER_CARD_MON_ICON_4)); trainerCard->monSpecies[4] = MailSpeciesToIconSpecies(VarGet(VAR_TRAINER_CARD_MON_ICON_5)); trainerCard->monSpecies[5] = MailSpeciesToIconSpecies(VarGet(VAR_TRAINER_CARD_MON_ICON_6)); } static void SetDataFromTrainerCard(void) { u32 badgeFlag; u8 i; sTrainerCardDataPtr->hasPokedex = FALSE; sTrainerCardDataPtr->hasHofResult = FALSE; sTrainerCardDataPtr->hasLinkResults = FALSE; sTrainerCardDataPtr->hasBattleTowerWins = FALSE; sTrainerCardDataPtr->var_E = FALSE; sTrainerCardDataPtr->var_F = FALSE; sTrainerCardDataPtr->hasTrades = FALSE; memset(sTrainerCardDataPtr->hasBadge, FALSE, sizeof(sTrainerCardDataPtr->hasBadge)); if (sTrainerCardDataPtr->trainerCard.rse.hasPokedex) sTrainerCardDataPtr->hasPokedex++; if (sTrainerCardDataPtr->trainerCard.rse.hofDebutHours != 0 || sTrainerCardDataPtr->trainerCard.rse.hofDebutMinutes != 0 || sTrainerCardDataPtr->trainerCard.rse.hofDebutSeconds != 0) sTrainerCardDataPtr->hasHofResult++; if (sTrainerCardDataPtr->trainerCard.rse.linkBattleWins != 0 || sTrainerCardDataPtr->trainerCard.rse.linkBattleLosses != 0) sTrainerCardDataPtr->hasLinkResults++; if (sTrainerCardDataPtr->trainerCard.rse.pokemonTrades != 0) sTrainerCardDataPtr->hasTrades++; for (i = 0, badgeFlag = FLAG_BADGE01_GET; badgeFlag <= FLAG_BADGE08_GET; badgeFlag++, i++) { if (FlagGet(badgeFlag)) sTrainerCardDataPtr->hasBadge[i]++; } } static void HandleGpuRegs(void) { ShowBg(0); ShowBg(1); ShowBg(2); ShowBg(3); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP | DISPCNT_BG_ALL_ON); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_DARKEN); SetGpuReg(REG_OFFSET_BLDY, 0); SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ); SetGpuReg(REG_OFFSET_WIN0V, WININ_WIN0_CLR | WIN_RANGE(0, 0x80)); SetGpuReg(REG_OFFSET_WIN0H, WININ_WIN0_CLR | WININ_WIN0_OBJ | WIN_RANGE(0, 0xC0)); if (gReceivedRemoteLinkPlayers) EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); else EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK); } // Part of animating card flip static void UpdateCardFlipRegs(u16 cardTop) { s8 blendY = (cardTop + 40) / 10; if (blendY <= 4) blendY = 0; sTrainerCardDataPtr->flipBlendY = blendY; SetGpuReg(REG_OFFSET_BLDY, sTrainerCardDataPtr->flipBlendY); SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(sTrainerCardDataPtr->cardTop, 160 - sTrainerCardDataPtr->cardTop)); } static void ResetGpuRegs(void) { SetVBlankCallback(NULL); SetHBlankCallback(NULL); SetGpuReg(REG_OFFSET_DISPCNT, 0); } static void TrainerCardNull(void) { } static void sub_8089C5C(void) { DmaClear32(3, (void *)OAM, OAM_SIZE); } static void sub_8089C80(void) { DmaClear16(3, (void *)PLTT, PLTT_SIZE); } static void sub_8089CA4(void) { SetGpuReg(REG_OFFSET_BG0CNT, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG1CNT, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG2CNT, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG3CNT, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG0HOFS, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG0VOFS, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG1HOFS, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG1VOFS, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG2HOFS, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG2VOFS, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG3HOFS, DISPCNT_MODE_0); SetGpuReg(REG_OFFSET_BG3VOFS, DISPCNT_MODE_0); } static void InitBgsAndWindows(void) { ResetSpriteData(); ResetPaletteFade(); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sTrainerCardBgTemplates, NELEMS(sTrainerCardBgTemplates)); 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); InitWindows(sTrainerCardWindowTemplates); DeactivateAllTextPrinters(); } static void SetTrainerCardCB2(void) { SetMainCallback2(CB2_TrainerCard); SetHelpContext(HELPCONTEXT_TRAINER_CARD_FRONT); } static void SetUpTrainerCardTask(void) { ResetTasks(); ScanlineEffect_Stop(); CreateTask(Task_TrainerCard, 0); InitTrainerCardData(); SetDataFromTrainerCard(); } static bool8 PrintAllOnCardFront(void) { switch (sTrainerCardDataPtr->printState) { case 0: PrintNameOnCardFront(); break; case 1: PrintIdOnCard(); break; case 2: PrintMoneyOnCard(); break; case 3: PrintPokedexOnCard(); break; case 4: PrintTimeOnCard(); break; case 5: PrintProfilePhraseOnCard(); break; default: sTrainerCardDataPtr->printState = 0; return TRUE; } sTrainerCardDataPtr->printState++; return FALSE; } static bool8 PrintAllOnCardBack(void) { switch (sTrainerCardDataPtr->printState) { case 0: PrintNameOnCardBack(); break; case 1: PrintHofDebutTimeOnCard(); break; case 2: PrintLinkBattleResultsOnCard(); break; case 3: PrintTradesStringOnCard(); break; case 4: PrintBerryCrushStringOnCard(); break; case 5: PrintUnionStringOnCard(); break; case 6: PrintPokemonIconsOnCard(); break; case 7: PrintStickersOnCard(); break; default: sTrainerCardDataPtr->printState = 0; return TRUE; } sTrainerCardDataPtr->printState++; return FALSE; } static void BufferTextForCardBack(void) { BufferNameForCardBack(); BufferHofDebutTime(); BufferLinkBattleResults(); BufferNumTrades(); BufferBerryCrushPoints(); BufferUnionRoomStats(); } static void PrintNameOnCardFront(void) { u8 buffer[2][32]; u8* txtPtr; txtPtr = StringCopy(buffer[0], gText_TrainerCardName); txtPtr = buffer[1]; StringCopy(txtPtr, sTrainerCardDataPtr->trainerCard.rse.playerName); ConvertInternationalString(txtPtr, sTrainerCardDataPtr->language); StringAppend(buffer[0], txtPtr); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardFrontNameXPositions[sTrainerCardDataPtr->cardType], sTrainerCardFrontNameYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, buffer[0]); } static void PrintIdOnCard(void) { u8 buffer[32]; u8* txtPtr; txtPtr = StringCopy(buffer, gText_TrainerCardIDNo); ConvertIntToDecimalStringN(txtPtr, sTrainerCardDataPtr->trainerCard.rse.trainerId, STR_CONV_MODE_LEADING_ZEROS, 5); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardIdXPositions[sTrainerCardDataPtr->cardType], sTrainerCardIdYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, buffer); } static void PrintMoneyOnCard(void) { u8 buffer[10]; u8* txtPtr; u8 x; txtPtr = StringCopy(buffer, gText_TrainerCardYen); ConvertIntToDecimalStringN(txtPtr, sTrainerCardDataPtr->trainerCard.rse.money, STR_CONV_MODE_LEFT_ALIGN, 6); if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE) { x = -122 - 6 * StringLength(buffer); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 20, 56, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardMoney); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], x, 56, sTrainerCardTextColors, TEXT_SPEED_FF, buffer); } else { x = 118 - 6 * StringLength(buffer); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 16, 57, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardMoney); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], x, 57, sTrainerCardTextColors, TEXT_SPEED_FF, buffer); } } static u16 GetCaughtMonsCount(void) { if (IsNationalPokedexEnabled()) return GetNationalPokedexCount(FLAG_GET_CAUGHT); else return GetKantoPokedexCount(FLAG_GET_CAUGHT); } static void PrintPokedexOnCard(void) { u8 buffer[10]; u8 x; if (FlagGet(FLAG_SYS_POKEDEX_GET)) { ConvertIntToDecimalStringN(buffer, sTrainerCardDataPtr->trainerCard.rse.caughtMonsCount, 0, 3); if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE) { x = -120 - 6 * StringLength(buffer); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 20, 72, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardPokedex); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], x, 72, sTrainerCardTextColors, TEXT_SPEED_FF, buffer); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 138, 72, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardNull); } else { x = 120 - 6 * StringLength(buffer); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 16, 73, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardPokedex); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], x, 73, sTrainerCardTextColors, TEXT_SPEED_FF, buffer); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 138, 73, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardNull); } } } static void PrintTimeOnCard(void) { u16 hours; u16 minutes; u8 buffer[6]; hours = gSaveBlock2Ptr->playTimeHours; minutes = gSaveBlock2Ptr->playTimeMinutes; if (sTrainerCardDataPtr->isLink) { hours = sTrainerCardDataPtr->trainerCard.rse.playTimeHours; minutes = sTrainerCardDataPtr->trainerCard.rse.playTimeMinutes; } if (hours > 999) hours = 999; if (minutes > 59) minutes = 59; FillWindowPixelRect(1, PIXEL_FILL(0), sTrainerCardTimeHoursXPositions[sTrainerCardDataPtr->cardType], sTrainerCardTimeMinutesYPositions[sTrainerCardDataPtr->cardType], 50, 12); if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE) AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 20, 88, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardTime); else AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 16, 89, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardTime); ConvertIntToDecimalStringN(buffer, hours, STR_CONV_MODE_RIGHT_ALIGN, 3); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardTimeHoursXPositions[sTrainerCardDataPtr->cardType], sTrainerCardTimeMinutesYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, buffer); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardTimeHoursYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTimeMinutesYPositions[sTrainerCardDataPtr->cardType], sTimeColonTextColors[sTrainerCardDataPtr->timeColonInvisible], TEXT_SPEED_FF, gText_Colon2); ConvertIntToDecimalStringN(buffer, minutes, STR_CONV_MODE_LEADING_ZEROS, 2); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardTimeMinutesXPositions[sTrainerCardDataPtr->cardType], sTrainerCardTimeMinutesYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, buffer); } static void PrintProfilePhraseOnCard(void) { if (sTrainerCardDataPtr->isLink) { AddTextPrinterParameterized3(1, 2, 10, sTrainerCardProfilePhraseXPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->easyChatProfile[0]); AddTextPrinterParameterized3(1, 2, GetStringWidth(2, sTrainerCardDataPtr->easyChatProfile[0], 0) + 16, sTrainerCardProfilePhraseXPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->easyChatProfile[1]); AddTextPrinterParameterized3(1, 2, 10, sTrainerCardProfilePhraseYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->easyChatProfile[2]); AddTextPrinterParameterized3(1, 2, GetStringWidth(2, sTrainerCardDataPtr->easyChatProfile[2], 0) + 16, sTrainerCardProfilePhraseYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->easyChatProfile[3]); } } static void BufferNameForCardBack(void) { StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_NAME], sTrainerCardDataPtr->trainerCard.rse.playerName); ConvertInternationalString(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_NAME], sTrainerCardDataPtr->language); if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE) { StringAppend(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_NAME], gText_Var1sTrainerCard); } } static void PrintNameOnCardBack(void) { u8 x; if (sTrainerCardDataPtr->cardType == CARD_TYPE_FRLG) { AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardBackNameXPositions[sTrainerCardDataPtr->cardType], sTrainerCardBackNameYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_NAME]); } else { x = sTrainerCardBackNameXPositions[sTrainerCardDataPtr->cardType] - GetStringWidth(sTrainerCardFontIds[1], sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_NAME], GetFontAttribute(sTrainerCardFontIds[1], FONTATTR_LETTER_SPACING)); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], x, sTrainerCardBackNameYPositions[sTrainerCardDataPtr->cardType], sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_NAME]); } } static void BufferHofDebutTime(void) { u8 buffer[10]; u8* txtPtr; if (sTrainerCardDataPtr->hasHofResult) { ConvertIntToDecimalStringN(buffer, sTrainerCardDataPtr->trainerCard.rse.hofDebutHours, STR_CONV_MODE_RIGHT_ALIGN, 3); txtPtr = StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_HOF_TIME], buffer); StringAppendN(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_HOF_TIME], gText_Colon2, 2); ConvertIntToDecimalStringN(buffer, sTrainerCardDataPtr->trainerCard.rse.hofDebutMinutes, STR_CONV_MODE_LEADING_ZEROS, 2); StringAppendN(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_HOF_TIME], buffer, 3); StringAppendN(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_HOF_TIME], gText_Colon2, 2); ConvertIntToDecimalStringN(buffer, sTrainerCardDataPtr->trainerCard.rse.hofDebutSeconds, STR_CONV_MODE_LEADING_ZEROS, 2); StringAppendN(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_HOF_TIME], buffer, 3); } } static void PrintHofDebutTimeOnCard(void) { if (sTrainerCardDataPtr->hasHofResult) { AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardHofDebutXPositions[sTrainerCardDataPtr->cardType], 35, sTrainerCardTextColors, TEXT_SPEED_FF, gText_HallOfFameDebut); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 164, 35, sTrainerCardStatColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_HOF_TIME]); } } static void BufferLinkBattleResults(void) { u8 buffer[30]; if (sTrainerCardDataPtr->hasLinkResults) { StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_LINK_RECORD], sLinkTrainerCardRecordStrings[sTrainerCardDataPtr->cardType]); StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_WIN_LOSS], gText_WinLossRatio); ConvertIntToDecimalStringN(buffer, sTrainerCardDataPtr->trainerCard.rse.linkBattleWins, STR_CONV_MODE_RIGHT_ALIGN, 4); StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_LINK_WINS], buffer); ConvertIntToDecimalStringN(buffer, sTrainerCardDataPtr->trainerCard.rse.linkBattleLosses, STR_CONV_MODE_RIGHT_ALIGN, 4); StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_LINK_LOSSES], buffer); } } static void PrintLinkBattleResultsOnCard(void) { if (sTrainerCardDataPtr->hasLinkResults) { AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardHofDebutXPositions[sTrainerCardDataPtr->cardType], 51, sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_LINK_RECORD]); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 130, 51, sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_WIN_LOSS]); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 144, 51, sTrainerCardStatColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_LINK_WINS]); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 192, 51, sTrainerCardStatColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_LINK_LOSSES]); } } static void BufferNumTrades(void) { if (sTrainerCardDataPtr->hasTrades) { StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_TRADES], gText_PokemonTrades); ConvertIntToDecimalStringN(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_TRADE_COUNT], sTrainerCardDataPtr->trainerCard.rse.pokemonTrades, STR_CONV_MODE_RIGHT_ALIGN, 5); } } static void PrintTradesStringOnCard(void) { if (sTrainerCardDataPtr->hasTrades) { AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardHofDebutXPositions[sTrainerCardDataPtr->cardType], 67, sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_TRADES]); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 186, 67, sTrainerCardStatColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_TRADE_COUNT]); } } static void BufferBerryCrushPoints(void) { if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE) { StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_BERRY_CRUSH], gText_BerryCrushes); ConvertIntToDecimalStringN(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_BERRY_CRUSH_COUNT], sTrainerCardDataPtr->trainerCard.berryCrushPoints, STR_CONV_MODE_RIGHT_ALIGN, 5); } } static void PrintBerryCrushStringOnCard(void) { if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE && sTrainerCardDataPtr->trainerCard.berryCrushPoints) { AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardHofDebutXPositions[sTrainerCardDataPtr->cardType], 99, sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_BERRY_CRUSH]); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 186, 99, sTrainerCardStatColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_BERRY_CRUSH_COUNT]); } } static void BufferUnionRoomStats(void) { if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE) { StringCopy(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_UNION_ROOM], gText_UnionRoomTradesBattles); ConvertIntToDecimalStringN(sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_UNION_ROOM_NUM], sTrainerCardDataPtr->trainerCard.unionRoomNum, STR_CONV_MODE_RIGHT_ALIGN, 5); } } static void PrintUnionStringOnCard(void) { if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE && sTrainerCardDataPtr->trainerCard.unionRoomNum) { AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], sTrainerCardHofDebutXPositions[sTrainerCardDataPtr->cardType], 83, sTrainerCardTextColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_UNION_ROOM]); AddTextPrinterParameterized3(1, sTrainerCardFontIds[1], 186, 83, sTrainerCardStatColors, TEXT_SPEED_FF, sTrainerCardDataPtr->strings[TRAINER_CARD_STRING_UNION_ROOM_NUM]); } } static void PrintPokemonIconsOnCard(void) { u8 i; u8 paletteSlots[PARTY_SIZE]; u8 xOffsets[PARTY_SIZE]; memcpy(paletteSlots, sPokemonIconPalSlots, sizeof(sPokemonIconPalSlots)); memcpy(xOffsets, sPokemonIconXOffsets, sizeof(sPokemonIconXOffsets)); if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE) { for (i = 0; i < PARTY_SIZE; i++) { if (sTrainerCardDataPtr->trainerCard.monSpecies[i]) { u8 monSpecies = GetMonIconPaletteIndexFromSpecies(sTrainerCardDataPtr->trainerCard.monSpecies[i]); WriteSequenceToBgTilemapBuffer(3, 16 * i + 224, xOffsets[i] + 3, 15, 4, 4, paletteSlots[monSpecies], 1); } } } } static void LoadMonIconGfx(void) { u8 i; CpuCopy16(gMonIconPalettes, sTrainerCardDataPtr->monIconPals, 2 * NELEMS(sTrainerCardDataPtr->monIconPals)); switch (sTrainerCardDataPtr->trainerCard.monIconTint) { case MON_ICON_TINT_NORMAL: break; case MON_ICON_TINT_BLACK: TintPalette_CustomTone(sTrainerCardDataPtr->monIconPals, 96, 0, 0, 0); break; case MON_ICON_TINT_PINK: TintPalette_CustomTone(sTrainerCardDataPtr->monIconPals, 96, 500, 330, 310); break; case MON_ICON_TINT_SEPIA: TintPalette_SepiaTone(sTrainerCardDataPtr->monIconPals, 96); break; } LoadPalette(sTrainerCardDataPtr->monIconPals, 80, 192); for (i = 0; i < PARTY_SIZE; i++) { LoadBgTiles(3, GetMonIconTiles(sTrainerCardDataPtr->trainerCard.monSpecies[i], 0), 512, 16 * i + 32); } } static void PrintStickersOnCard(void) { u8 i; u8 palSlots[4]; memcpy(palSlots, sStickerPalSlots, sizeof(sStickerPalSlots)); if (sTrainerCardDataPtr->cardType == CARD_TYPE_FRLG && sTrainerCardDataPtr->trainerCard.shouldDrawStickers == TRUE) { for (i = 0; i < TRAINER_CARD_STICKER_TYPES; i++) { u8 sticker = sTrainerCardDataPtr->trainerCard.stickers[i]; if (sTrainerCardDataPtr->trainerCard.stickers[i]) WriteSequenceToBgTilemapBuffer(3, i * 4 + 320, i * 3 + 2, 2, 2, 2, palSlots[sticker - 1], 1); } } } static void LoadStickerGfx(void) { LoadPalette(sTrainerCardStickerPal1, 176, 32); LoadPalette(sTrainerCardStickerPal2, 192, 32); LoadPalette(sTrainerCardStickerPal3, 208, 32); LoadPalette(sTrainerCardStickerPal4, 224, 32); LoadBgTiles(3, sTrainerCardDataPtr->stickerTiles, 1024, 128); } static void DrawTrainerCardWindow(u8 windowId) { PutWindowTilemap(windowId); CopyWindowToVram(windowId, COPYWIN_BOTH); } static bool8 SetTrainerCardBgsAndPals(void) { switch (sTrainerCardDataPtr->bgPalLoadState) { case 0: LoadBgTiles(3, sTrainerCardDataPtr->badgeTiles, NELEMS(sTrainerCardDataPtr->badgeTiles), 0); break; case 1: LoadBgTiles(0, sTrainerCardDataPtr->cardTiles, 0x1800, 0); break; case 2: if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE) LoadPalette(sHoennTrainerCardStarPals[sTrainerCardDataPtr->trainerCard.rse.stars], 0, 96); else LoadPalette(sKantoTrainerCardStarPals[sTrainerCardDataPtr->trainerCard.rse.stars], 0, 96); break; case 3: if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE) LoadPalette(sHoennTrainerCardBadges_Pal, 48, 32); else LoadPalette(sKantoTrainerCardBadges_Pal, 48, 32); break; case 4: if (sTrainerCardDataPtr->cardType == CARD_TYPE_RSE && sTrainerCardDataPtr->trainerCard.rse.gender != MALE) LoadPalette(sHoennTrainerCardFemaleBackground_Pal, 16, 32); else if (sTrainerCardDataPtr->trainerCard.rse.gender != MALE) LoadPalette(sKantoTrainerCardFemaleBackground_Pal, 16, 32); break; case 5: LoadPalette(sTrainerCardGold_Pal, 64, 32); break; case 6: SetBgTilemapBuffer(0, sTrainerCardDataPtr->cardTilemapBuffer); SetBgTilemapBuffer(2, sTrainerCardDataPtr->bgTilemapBuffer); break; default: FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32); FillBgTilemapBufferRect_Palette0(2, 0, 0, 0, 32, 32); FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 32, 32); return TRUE; } sTrainerCardDataPtr->bgPalLoadState++; return FALSE; } static void DrawCardScreenBackground(const u16* ptr) { s16 i, j; u16 *dst = sTrainerCardDataPtr->bgTilemapBuffer; for (i = 0; i < 20; i++) { for (j = 0; j < 32; j++) { if (j < 30) dst[32 * i + j] = ptr[30 * i + j]; else dst[32 * i + j] = ptr[0]; } } CopyBgTilemapBufferToVram(2); } static void DrawCardFrontOrBack(const u16* ptr) { s16 i, j; u16 *dst = sTrainerCardDataPtr->cardTilemapBuffer; for (i = 0; i < 20; i++) { for (j = 0; j < 32; j++) { if (j < 30) dst[32 * i + j] = ptr[30 * i + j]; else dst[32 * i + j] = ptr[0]; } } CopyBgTilemapBufferToVram(0); } static void DrawStarsAndBadgesOnCard(void) { s16 i, x; u16 tileNum = 192; u8 palNum = 3; FillBgTilemapBufferRect(3, 143, 15, sStarYOffsets[sTrainerCardDataPtr->cardType], sTrainerCardDataPtr->trainerCard.rse.stars, 1, 4); if (!sTrainerCardDataPtr->isLink) { x = 4; for (i = 0; i < NUM_BADGES; i++, tileNum += 2, x += 3) { if (sTrainerCardDataPtr->hasBadge[i]) { FillBgTilemapBufferRect(3, tileNum, x, 16, 1, 1, palNum); FillBgTilemapBufferRect(3, tileNum + 1, x + 1, 16, 1, 1, palNum); FillBgTilemapBufferRect(3, tileNum + 16, x, 17, 1, 1, palNum); FillBgTilemapBufferRect(3, tileNum + 17, x + 1, 17, 1, 1, palNum); } } } CopyBgTilemapBufferToVram(3); } static void DrawCardBackStats(void) { if (sTrainerCardDataPtr->cardType != CARD_TYPE_RSE) { if (sTrainerCardDataPtr->hasTrades) { FillBgTilemapBufferRect(3, 141, 26, 9, 1, 1, 1); FillBgTilemapBufferRect(3, 157, 26, 10, 1, 1, 1); } if (sTrainerCardDataPtr->trainerCard.berryCrushPoints) { FillBgTilemapBufferRect(3, 141, 21, 13, 1, 1, 1); FillBgTilemapBufferRect(3, 157, 21, 14, 1, 1, 1); } if (sTrainerCardDataPtr->trainerCard.unionRoomNum) { FillBgTilemapBufferRect(3, 141, 27, 11, 1, 1, 1); FillBgTilemapBufferRect(3, 157, 27, 12, 1, 1, 1); } } else { if (sTrainerCardDataPtr->hasTrades) { FillBgTilemapBufferRect(3, 141, 26, 9, 1, 1, 0); FillBgTilemapBufferRect(3, 157, 26, 10, 1, 1, 0); } } CopyBgTilemapBufferToVram(3); } static void BlinkTimeColon(void) { if (++sTrainerCardDataPtr->timeColonBlinkTimer > 60) { sTrainerCardDataPtr->timeColonBlinkTimer = 0; sTrainerCardDataPtr->timeColonInvisible ^= 1; sTrainerCardDataPtr->timeColonNeedDraw = TRUE; } } u8 GetTrainerCardStars(u8 cardId) { return gTrainerCards[cardId].rse.stars; } #define tFlipState data[0] static void FlipTrainerCard(void) { u8 taskId = CreateTask(Task_DoCardFlipTask, 0); Task_DoCardFlipTask(taskId); SetHBlankCallback(HBlankCB_TrainerCard); } static bool8 IsCardFlipTaskActive(void) { if (FindTaskIdByFunc(Task_DoCardFlipTask) == 0xFF) return TRUE; else return FALSE; } static void Task_DoCardFlipTask(u8 taskId) { while(sTrainerCardFlipTasks[gTasks[taskId].tFlipState](&gTasks[taskId])) ; } static bool8 Task_BeginCardFlip(struct Task* task) { u32 i; HideBg(1); HideBg(3); ScanlineEffect_Stop(); ScanlineEffect_Clear(); for (i = 0; i < 160; i++) gScanlineEffectRegBuffers[1][i] = 0; task->tFlipState++; return FALSE; } static bool8 Task_AnimateCardFlipDown(struct Task* task) { u32 r4, r5, r10, r7, r6, var_24, r9, var; s16 i; sTrainerCardDataPtr->allowDMACopy = FALSE; if (task->data[1] >= 77) task->data[1] = 77; else task->data[1] += 7; sTrainerCardDataPtr->cardTop = task->data[1]; UpdateCardFlipRegs(task->data[1]); r7 = task->data[1]; r9 = 160 - r7; r4 = r9 - r7; r6 = -r7 << 16; r5 = 0xA00000 / r4; r5 += 0xFFFF0000; var_24 = r6; var_24 += r5 * r4; r10 = r5 / r4; r5 *= 2; for (i = 0; i < r7; i++) { gScanlineEffectRegBuffers[0][i] = -i; } for (; i < (s16)r9; i++) { var = r6 >> 16; r6 += r5; r5 -= r10; gScanlineEffectRegBuffers[0][i] = var; } var = var_24 >> 16; for (; i < 160; i++) { gScanlineEffectRegBuffers[0][i] = var; } sTrainerCardDataPtr->allowDMACopy = TRUE; if (task->data[1] >= 77) task->tFlipState++; return FALSE; } static bool8 Task_DrawFlippedCardSide(struct Task* task) { sTrainerCardDataPtr->allowDMACopy = FALSE; if (Overworld_LinkRecvQueueLengthMoreThan2() == TRUE) return FALSE; do { switch (sTrainerCardDataPtr->flipDrawState) { case 0: FillWindowPixelBuffer(1, PIXEL_FILL(0)); FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 32, 32); break; case 1: if (!sTrainerCardDataPtr->onBack) { if (!PrintAllOnCardBack()) return FALSE; } else { if (!PrintAllOnCardFront()) return FALSE; } break; case 2: if (!sTrainerCardDataPtr->onBack) DrawCardFrontOrBack(sTrainerCardDataPtr->backTilemap); else DrawTrainerCardWindow(1); break; case 3: if (!sTrainerCardDataPtr->onBack) DrawCardBackStats(); else FillWindowPixelBuffer(2, PIXEL_FILL(0)); break; case 4: if (sTrainerCardDataPtr->onBack) CreateTrainerCardTrainerPic(); break; default: task->tFlipState++; sTrainerCardDataPtr->allowDMACopy = TRUE; sTrainerCardDataPtr->flipDrawState = 0; return FALSE; } sTrainerCardDataPtr->flipDrawState++; } while (!gReceivedRemoteLinkPlayers); return FALSE; } static bool8 Task_SetCardFlipped(struct Task* task) { sTrainerCardDataPtr->allowDMACopy = FALSE; // If on back of card, draw front of card because its being flipped if (sTrainerCardDataPtr->onBack) { DrawTrainerCardWindow(2); DrawCardScreenBackground(sTrainerCardDataPtr->bgTilemap); DrawCardFrontOrBack(sTrainerCardDataPtr->frontTilemap); DrawStarsAndBadgesOnCard(); } DrawTrainerCardWindow(1); sTrainerCardDataPtr->onBack ^= 1; task->tFlipState++; sTrainerCardDataPtr->allowDMACopy = TRUE; PlaySE(SE_CARD_FLIPPING); return FALSE; } static bool8 Task_AnimateCardFlipUp(struct Task* task) { u32 r4, r5, r10, r7, r6, var_24, r9, var; s16 i; sTrainerCardDataPtr->allowDMACopy = FALSE; if (task->data[1] <= 5) task->data[1] = 0; else task->data[1] -= 5; sTrainerCardDataPtr->cardTop = task->data[1]; UpdateCardFlipRegs(task->data[1]); r7 = task->data[1]; r9 = 160 - r7; r4 = r9 - r7; r6 = -r7 << 16; r5 = 0xA00000 / r4; r5 += 0xFFFF0000; var_24 = r6; var_24 += r5 * r4; r10 = r5 / r4; r5 /= 2; for (i = 0; i < r7; i++) { gScanlineEffectRegBuffers[0][i] = -i; } for (; i < (s16)(r9); i++) { var = r6 >> 16; r6 += r5; r5 += r10; gScanlineEffectRegBuffers[0][i] = var; } var = var_24 >> 16; for (; i < 160; i++) { gScanlineEffectRegBuffers[0][i] = var; } sTrainerCardDataPtr->allowDMACopy = TRUE; if (task->data[1] <= 0) task->tFlipState++; return FALSE; } static bool8 Task_EndCardFlip(struct Task *task) { ShowBg(1); ShowBg(3); SetHBlankCallback(NULL); DestroyTask(FindTaskIdByFunc(Task_DoCardFlipTask)); return FALSE; } void ShowPlayerTrainerCard(void (*callback)(void)) { sTrainerCardDataPtr = AllocZeroed(sizeof(*sTrainerCardDataPtr)); sTrainerCardDataPtr->callback2 = callback; if (InUnionRoom() == TRUE) sTrainerCardDataPtr->isLink = TRUE; else sTrainerCardDataPtr->isLink = FALSE; sTrainerCardDataPtr->language = GAME_LANGUAGE; TrainerCard_GenerateCardForLinkPlayer(&sTrainerCardDataPtr->trainerCard); SetMainCallback2(CB2_InitTrainerCard); } void ShowTrainerCardInLink(u8 cardId, void (*callback)(void)) { sTrainerCardDataPtr = AllocZeroed(sizeof(*sTrainerCardDataPtr)); sTrainerCardDataPtr->callback2 = callback; sTrainerCardDataPtr->isLink = TRUE; sTrainerCardDataPtr->trainerCard = gTrainerCards[cardId]; sTrainerCardDataPtr->language = gLinkPlayers[cardId].language; SetMainCallback2(CB2_InitTrainerCard); } static void InitTrainerCardData(void) { u8 i; sTrainerCardDataPtr->mainState = 0; sTrainerCardDataPtr->timeColonBlinkTimer = gSaveBlock2Ptr->playTimeVBlanks; sTrainerCardDataPtr->timeColonInvisible = FALSE; sTrainerCardDataPtr->onBack = FALSE; sTrainerCardDataPtr->flipBlendY = 0; if (GetCardType() == CARD_TYPE_RSE) sTrainerCardDataPtr->cardType = CARD_TYPE_RSE; else sTrainerCardDataPtr->cardType = CARD_TYPE_FRLG; for (i = 0; i < TRAINER_CARD_PROFILE_LENGTH; i++) CopyEasyChatWord(sTrainerCardDataPtr->easyChatProfile[i], sTrainerCardDataPtr->trainerCard.rse.easyChatProfile[i]); } static u8 GetCardType(void) { if (sTrainerCardDataPtr == NULL) { if (gGameVersion == VERSION_FIRE_RED || gGameVersion == VERSION_LEAF_GREEN) return CARD_TYPE_FRLG; else return CARD_TYPE_RSE; } else { if (sTrainerCardDataPtr->trainerCard.version == VERSION_FIRE_RED || sTrainerCardDataPtr->trainerCard.version == VERSION_LEAF_GREEN) return CARD_TYPE_FRLG; else return CARD_TYPE_RSE; } } static void CreateTrainerCardTrainerPic(void) { u8 facilityClass = sTrainerPicFacilityClasses[sTrainerCardDataPtr->cardType][sTrainerCardDataPtr->trainerCard.rse.gender]; if (InUnionRoom() == TRUE && gReceivedRemoteLinkPlayers == 1) { facilityClass = sTrainerCardDataPtr->trainerCard.facilityClass; CreateTrainerCardTrainerPicSprite(FacilityClassToPicIndex(facilityClass), TRUE, sTrainerPicOffsets[sTrainerCardDataPtr->cardType][sTrainerCardDataPtr->trainerCard.rse.gender][0], sTrainerPicOffsets[sTrainerCardDataPtr->cardType][sTrainerCardDataPtr->trainerCard.rse.gender][1], 8, 2); } else { if (sTrainerCardDataPtr->cardType != CARD_TYPE_FRLG) { CreateTrainerCardTrainerPicSprite(FacilityClassToPicIndex(facilityClass), TRUE, sTrainerPicOffsets[sTrainerCardDataPtr->cardType][sTrainerCardDataPtr->trainerCard.rse.gender][0], sTrainerPicOffsets[sTrainerCardDataPtr->cardType][sTrainerCardDataPtr->trainerCard.rse.gender][1], 8, 2); } else { CreateTrainerCardTrainerPicSprite(PlayerGenderToFrontTrainerPicId_Debug(sTrainerCardDataPtr->trainerCard.rse.gender, TRUE), TRUE, sTrainerPicOffsets[sTrainerCardDataPtr->cardType][sTrainerCardDataPtr->trainerCard.rse.gender][0], sTrainerPicOffsets[sTrainerCardDataPtr->cardType][sTrainerCardDataPtr->trainerCard.rse.gender][1], 8, 2); } } } // Unused static void Unref_InitTrainerCard(void (*callback)(void)) { ShowPlayerTrainerCard(callback); SetMainCallback2(CB2_InitTrainerCard); } // Unused static void Unref_InitTrainerCardLink(void (*callback)(void)) { memcpy(gTrainerCards, &sLinkPlayerTrainerCardTemplate1, sizeof(sLinkPlayerTrainerCardTemplate1)); ShowTrainerCardInLink(CARD_TYPE_FRLG, callback); SetMainCallback2(CB2_InitTrainerCard); } // Unused static void Unref_InitTrainerCardLink2(void (*callback)(void)) { memcpy(gTrainerCards, &sLinkPlayerTrainerCardTemplate2, sizeof(sLinkPlayerTrainerCardTemplate2)); ShowTrainerCardInLink(CARD_TYPE_FRLG, callback); SetMainCallback2(CB2_InitTrainerCard); }