pokeemerald/src/trainer_card.c

1896 lines
56 KiB
C
Raw Normal View History

2019-01-09 03:51:19 +01:00
#include "global.h"
#include "scanline_effect.h"
#include "palette.h"
#include "task.h"
#include "main.h"
#include "window.h"
#include "malloc.h"
2019-01-09 03:51:19 +01:00
#include "link.h"
#include "bg.h"
#include "sound.h"
#include "frontier_pass.h"
2019-01-09 03:51:19 +01:00
#include "overworld.h"
#include "menu.h"
#include "text.h"
2019-01-19 18:14:59 +01:00
#include "event_data.h"
2019-01-20 18:24:35 +01:00
#include "easy_chat.h"
2019-01-19 18:14:59 +01:00
#include "money.h"
2019-01-20 18:24:35 +01:00
#include "strings.h"
2019-01-19 18:14:59 +01:00
#include "string_util.h"
#include "trainer_card.h"
#include "gpu_regs.h"
#include "international_string_util.h"
#include "pokedex.h"
2019-03-02 09:18:08 +01:00
#include "pokemon_icon.h"
2019-01-19 18:14:59 +01:00
#include "graphics.h"
#include "pokemon_icon.h"
2019-01-20 18:24:35 +01:00
#include "trainer_pokemon_sprites.h"
#include "contest_util.h"
2019-01-20 18:24:35 +01:00
#include "constants/songs.h"
#include "constants/game_stat.h"
#include "constants/battle_frontier.h"
2019-04-04 23:05:46 +02:00
#include "constants/rgb.h"
2020-02-07 18:48:47 +01:00
#include "constants/trainers.h"
2019-01-19 18:14:59 +01:00
2019-01-20 18:24:35 +01:00
struct TrainerCardData
2019-01-19 23:04:33 +01:00
{
2020-02-07 18:48:47 +01:00
u8 mainState;
2019-01-20 18:24:35 +01:00
u8 printState;
u8 gfxLoadState;
u8 bgPalLoadState;
2020-02-07 18:48:47 +01:00
u8 flipDrawState;
2019-01-20 18:24:35 +01:00
bool8 isLink;
2020-02-07 18:48:47 +01:00
u8 timeColonBlinkTimer;
bool8 timeColonInvisible;
bool8 onBack;
2019-01-20 18:24:35 +01:00
bool8 allowDMACopy;
bool8 hasPokedex;
bool8 hasHofResult;
bool8 hasLinkResults;
bool8 hasBattleTowerWins;
2020-02-07 18:48:47 +01:00
bool8 unused_E;
bool8 unused_F;
2019-01-20 18:24:35 +01:00
bool8 hasTrades;
2020-02-07 18:48:47 +01:00
u8 badgeCount[NUM_BADGES];
u8 easyChatProfile[TRAINER_CARD_PROFILE_LENGTH][13];
u8 textPlayersCard[70];
u8 textHofTime[70];
u8 textLinkBattleType[140];
u8 textLinkBattleWins[70];
u8 textLinkBattleLosses[140];
u8 textNumTrades[140];
u8 textBerryCrushPts[140];
u8 textUnionRoomStats[70];
u8 textNumLinkPokeblocks[70];
u8 textNumLinkContests[70];
u8 textBattleFacilityStat[70];
u16 monIconPal[16 * PARTY_SIZE];
s8 flipBlendY;
bool8 timeColonNeedDraw;
2019-01-20 18:24:35 +01:00
u8 cardType;
bool8 isHoenn;
2020-02-07 18:48:47 +01:00
u16 blendColor;
2019-01-09 03:51:19 +01:00
void (*callback2)(void);
2019-01-20 18:24:35 +01:00
struct TrainerCard trainerCard;
2020-02-07 18:48:47 +01:00
u16 frontTilemap[600];
u16 backTilemap[600];
u16 bgTilemap[600];
u8 badgeTiles[0x80 * NUM_BADGES];
u8 stickerTiles[0x200];
u8 cardTiles[0x2300];
u16 cardTilemapBuffer[0x1000];
u16 bgTilemapBuffer[0x1000];
2021-03-22 00:54:23 +01:00
u16 cardTop;
2019-01-20 18:24:35 +01:00
u8 language;
};
// EWRAM
2019-02-02 12:44:00 +01:00
EWRAM_DATA struct TrainerCard gTrainerCards[4] = {0};
2019-01-20 18:24:35 +01:00
EWRAM_DATA static struct TrainerCardData *sData = NULL;
//this file's functions
static void VblankCb_TrainerCard(void);
static void HblankCb_TrainerCard(void);
2020-02-07 18:48:47 +01:00
static void BlinkTimeColon(void);
2019-01-20 18:24:35 +01:00
static void CB2_TrainerCard(void);
static void CloseTrainerCard(u8 task);
2020-02-07 18:48:47 +01:00
static bool8 PrintAllOnCardFront(void);
static void DrawTrainerCardWindow(u8);
static void CreateTrainerCardTrainerPic(void);
static void DrawCardScreenBackground(u16*);
static void DrawCardFrontOrBack(u16*);
static void DrawStarsAndBadgesOnCard(void);
2019-01-20 18:24:35 +01:00
static void PrintTimeOnCard(void);
2020-02-07 18:48:47 +01:00
static void FlipTrainerCard(void);
static bool8 IsCardFlipTaskActive(void);
2019-01-20 18:24:35 +01:00
static bool8 LoadCardGfx(void);
static void CB2_InitTrainerCard(void);
static u32 GetCappedGameStat(u8 statId, u32 maxValue);
static bool8 HasAllFrontierSymbols(void);
static u8 GetRubyTrainerStars(struct TrainerCard*);
static u16 GetCaughtMonsCount(void);
static void SetPlayerCardData(struct TrainerCard*, u8);
static void TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard*);
2019-01-20 18:24:35 +01:00
static u8 VersionToCardType(u8);
static void SetDataFromTrainerCard(void);
2021-03-22 00:54:23 +01:00
static void InitGpuRegs(void);
2019-01-20 18:24:35 +01:00
static void ResetGpuRegs(void);
static void InitBgsAndWindows(void);
static void SetTrainerCardCb2(void);
2020-02-07 18:48:47 +01:00
static void SetUpTrainerCardTask(void);
static void InitTrainerCardData(void);
2019-01-20 18:24:35 +01:00
static u8 GetSetCardType(void);
2020-02-07 18:48:47 +01:00
static void PrintNameOnCardFront(void);
2019-01-20 18:24:35 +01:00
static void PrintIdOnCard(void);
static void PrintMoneyOnCard(void);
static void PrintPokedexOnCard(void);
static void PrintProfilePhraseOnCard(void);
2020-02-07 18:48:47 +01:00
static bool8 PrintAllOnCardBack(void);
static void PrintNameOnCardBack(void);
static void PrintHofDebutTimeOnCard(void);
static void PrintLinkBattleResultsOnCard(void);
2019-01-20 18:24:35 +01:00
static void PrintTradesStringOnCard(void);
static void PrintBerryCrushStringOnCard(void);
static void PrintPokeblockStringOnCard(void);
static void PrintUnionStringOnCard(void);
static void PrintContestStringOnCard(void);
2020-02-07 18:48:47 +01:00
static void PrintPokemonIconsOnCard(void);
2019-01-20 18:24:35 +01:00
static void PrintBattleFacilityStringOnCard(void);
2020-02-07 18:48:47 +01:00
static void PrintStickersOnCard(void);
static void BufferTextsVarsForCardPage2(void);
static void BufferNameForCardBack(void);
static void BufferHofDebutTime(void);
static void BufferLinkBattleResults(void);
static void BufferNumTrades(void);
static void BufferBerryCrushPoints(void);
static void BufferUnionRoomStats(void);
static void BufferLinkPokeblocksNum(void);
static void BufferLinkContestNum(void);
static void BufferBattleFacilityStats(void);
static void PrintStatOnBackOfCard(u8 top, const u8* str1, u8* str2, const u8* color);
static void LoadStickerGfx(void);
2019-01-20 18:24:35 +01:00
static u8 SetCardBgsAndPals(void);
2020-02-07 18:48:47 +01:00
static void DrawCardBackStats(void);
static void Task_DoCardFlipTask(u8);
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);
2021-03-22 00:54:23 +01:00
static void UpdateCardFlipRegs(u16);
2020-02-07 18:48:47 +01:00
static void LoadMonIconGfx(void);
2019-01-20 18:24:35 +01:00
2021-03-22 00:54:23 +01:00
static const u32 sTrainerCardStickers_Gfx[] = INCBIN_U32("graphics/trainer_card/stickers_fr.4bpp.lz");
static const u16 sUnused_Pal[] = INCBIN_U16("graphics/trainer_card/unused.gbapal");
static const u16 sHoennTrainerCard1Star_Pal[] = INCBIN_U16("graphics/trainer_card/one_star.gbapal");
static const u16 sKantoTrainerCard1Star_Pal[] = INCBIN_U16("graphics/trainer_card/one_star_fr.gbapal");
static const u16 sHoennTrainerCard2Star_Pal[] = INCBIN_U16("graphics/trainer_card/two_stars.gbapal");
static const u16 sKantoTrainerCard2Star_Pal[] = INCBIN_U16("graphics/trainer_card/two_stars_fr.gbapal");
static const u16 sHoennTrainerCard3Star_Pal[] = INCBIN_U16("graphics/trainer_card/three_stars.gbapal");
static const u16 sKantoTrainerCard3Star_Pal[] = INCBIN_U16("graphics/trainer_card/three_stars_fr.gbapal");
static const u16 sHoennTrainerCard4Star_Pal[] = INCBIN_U16("graphics/trainer_card/four_stars.gbapal");
static const u16 sKantoTrainerCard4Star_Pal[] = INCBIN_U16("graphics/trainer_card/four_stars_fr.gbapal");
2020-02-07 18:48:47 +01:00
static const u16 sHoennTrainerCardFemaleBg_Pal[] = INCBIN_U16("graphics/trainer_card/female_bg.gbapal");
static const u16 sKantoTrainerCardFemaleBg_Pal[] = INCBIN_U16("graphics/trainer_card/female_bg_fr.gbapal");
2021-03-22 00:54:23 +01:00
static const u16 sHoennTrainerCardBadges_Pal[] = INCBIN_U16("graphics/trainer_card/badges.gbapal");
static const u16 sKantoTrainerCardBadges_Pal[] = INCBIN_U16("graphics/trainer_card/badges_fr.gbapal");
static const u16 sTrainerCardGold_Pal[] = INCBIN_U16("graphics/trainer_card/gold.gbapal");
static const u16 sTrainerCardSticker1_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr1.gbapal");
static const u16 sTrainerCardSticker2_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr2.gbapal");
static const u16 sTrainerCardSticker3_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr3.gbapal");
static const u16 sTrainerCardSticker4_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr4.gbapal");
static const u32 sHoennTrainerCardBadges_Gfx[] = INCBIN_U32("graphics/trainer_card/badges.4bpp.lz");
static const u32 sKantoTrainerCardBadges_Gfx[] = INCBIN_U32("graphics/trainer_card/badges_fr.4bpp.lz");
2020-02-07 18:48:47 +01:00
static const struct BgTemplate sTrainerCardBgTemplates[4] =
2019-01-20 18:24:35 +01:00
{
{
.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
},
};
2020-02-07 18:48:47 +01:00
static const struct WindowTemplate sTrainerCardWindowTemplates[] =
2019-01-20 18:24:35 +01:00
{
{
.bg = 1,
.tilemapLeft = 2,
.tilemapTop = 15,
.width = 27,
.height = 4,
.paletteNum = 15,
.baseBlock = 0x253,
},
{
.bg = 1,
.tilemapLeft = 1,
.tilemapTop = 1,
.width = 28,
.height = 18,
.paletteNum = 15,
.baseBlock = 0x1,
},
{
.bg = 3,
.tilemapLeft = 19,
.tilemapTop = 5,
.width = 9,
.height = 10,
.paletteNum = 8,
.baseBlock = 0x150,
},
DUMMY_WIN_TEMPLATE
};
2020-02-07 18:48:47 +01:00
static const u16 *const sHoennTrainerCardStarPals[] =
2019-01-20 18:24:35 +01:00
{
2020-02-07 18:48:47 +01:00
gHoennTrainerCard0Star_Pal,
sHoennTrainerCard1Star_Pal,
sHoennTrainerCard2Star_Pal,
sHoennTrainerCard3Star_Pal,
sHoennTrainerCard4Star_Pal,
2019-01-20 18:24:35 +01:00
};
2020-02-07 18:48:47 +01:00
static const u16 *const sKantoTrainerCardStarPals[] =
2019-01-20 18:24:35 +01:00
{
2020-02-07 18:48:47 +01:00
gKantoTrainerCard0Star_Pal,
sKantoTrainerCard1Star_Pal,
sKantoTrainerCard2Star_Pal,
sKantoTrainerCard3Star_Pal,
sKantoTrainerCard4Star_Pal,
2019-01-20 18:24:35 +01:00
};
2021-04-10 04:39:34 +02:00
static const u8 sTrainerCardTextColors[] = {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY};
2019-12-10 19:48:20 +01:00
static const u8 sTrainerCardStatColors[] = {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED};
2020-02-07 18:48:47 +01:00
static const u8 sTimeColonInvisibleTextColors[6] = {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_TRANSPARENT, TEXT_COLOR_TRANSPARENT};
2019-01-20 18:24:35 +01:00
2020-02-07 18:48:47 +01:00
static const u8 sTrainerPicOffset[2][GENDER_COUNT][2] =
2019-01-20 18:24:35 +01:00
{
2020-02-07 18:48:47 +01:00
// Kanto
{
[MALE] = {13, 4},
[FEMALE] = {13, 4}
},
// Hoenn
{
[MALE] = {1, 0},
[FEMALE] = {1, 0}
},
2019-01-20 18:24:35 +01:00
};
2020-02-07 18:48:47 +01:00
static const u8 sTrainerPicFacilityClass[][GENDER_COUNT] =
{
[CARD_TYPE_FRLG] =
{
[MALE] = FACILITY_CLASS_RED,
[FEMALE] = FACILITY_CLASS_LEAF
},
[CARD_TYPE_RS] =
{
[MALE] = FACILITY_CLASS_RS_BRENDAN,
[FEMALE] = FACILITY_CLASS_RS_MAY
},
[CARD_TYPE_EMERALD] =
{
[MALE] = FACILITY_CLASS_BRENDAN,
[FEMALE] = FACILITY_CLASS_MAY
}
};
2019-01-20 18:24:35 +01:00
2020-02-07 18:48:47 +01:00
static bool8 (*const sTrainerCardFlipTasks[])(struct Task *) =
2019-01-20 18:24:35 +01:00
{
2020-02-07 18:48:47 +01:00
Task_BeginCardFlip,
Task_AnimateCardFlipDown,
Task_DrawFlippedCardSide,
Task_SetCardFlipped,
Task_AnimateCardFlipUp,
Task_EndCardFlip,
2019-01-20 18:24:35 +01:00
};
static void VblankCb_TrainerCard(void)
2019-01-09 03:51:19 +01:00
{
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
2020-02-07 18:48:47 +01:00
BlinkTimeColon();
2019-01-20 18:24:35 +01:00
if (sData->allowDMACopy)
2019-01-09 03:51:19 +01:00
DmaCopy16(3, &gScanlineEffectRegBuffers[0], &gScanlineEffectRegBuffers[1], 0x140);
}
2019-01-20 18:24:35 +01:00
static void HblankCb_TrainerCard(void)
2019-01-09 03:51:19 +01:00
{
u16 backup;
u16 bgVOffset;
2019-01-19 23:04:33 +01:00
2019-01-09 03:51:19 +01:00
backup = REG_IME;
REG_IME = 0;
bgVOffset = gScanlineEffectRegBuffers[1][REG_VCOUNT & 0xFF];
REG_BG0VOFS = bgVOffset;
REG_IME = backup;
}
2019-01-20 18:24:35 +01:00
static void CB2_TrainerCard(void)
2019-01-09 03:51:19 +01:00
{
RunTasks();
2019-01-19 18:14:59 +01:00
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
2019-01-09 03:51:19 +01:00
}
2019-01-20 18:24:35 +01:00
static void CloseTrainerCard(u8 taskId)
2019-01-09 03:51:19 +01:00
{
2019-01-20 18:24:35 +01:00
SetMainCallback2(sData->callback2);
2019-01-09 03:51:19 +01:00
FreeAllWindowBuffers();
2019-01-20 18:24:35 +01:00
FREE_AND_SET_NULL(sData);
2019-01-09 03:51:19 +01:00
DestroyTask(taskId);
2019-01-19 23:04:33 +01:00
}
2019-01-09 03:51:19 +01:00
2020-02-07 18:48:47 +01:00
// 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)
2019-01-09 03:51:19 +01:00
{
2020-02-07 18:48:47 +01:00
switch (sData->mainState)
2019-01-09 03:51:19 +01:00
{
2020-02-07 18:48:47 +01:00
// Draw card initially
2019-01-19 23:04:33 +01:00
case 0:
if (!IsDma3ManagerBusyWithBgCopy())
2019-01-09 03:51:19 +01:00
{
FillWindowPixelBuffer(1, PIXEL_FILL(0));
2020-02-07 18:48:47 +01:00
sData->mainState++;
2019-01-09 03:51:19 +01:00
}
break;
case 1:
2020-02-07 18:48:47 +01:00
if (PrintAllOnCardFront())
sData->mainState++;
2019-01-09 03:51:19 +01:00
break;
case 2:
2020-02-07 18:48:47 +01:00
DrawTrainerCardWindow(1);
sData->mainState++;
2019-01-09 03:51:19 +01:00
break;
case 3:
FillWindowPixelBuffer(2, PIXEL_FILL(0));
2020-02-07 18:48:47 +01:00
CreateTrainerCardTrainerPic();
DrawTrainerCardWindow(2);
sData->mainState++;
2019-01-09 03:51:19 +01:00
break;
case 4:
2020-02-07 18:48:47 +01:00
DrawCardScreenBackground(sData->bgTilemap);
sData->mainState++;
2019-01-09 03:51:19 +01:00
break;
case 5:
2020-02-07 18:48:47 +01:00
DrawCardFrontOrBack(sData->frontTilemap);
sData->mainState++;
2019-01-09 03:51:19 +01:00
break;
case 6:
2020-02-07 18:48:47 +01:00
DrawStarsAndBadgesOnCard();
sData->mainState++;
2019-01-09 03:51:19 +01:00
break;
2020-02-07 18:48:47 +01:00
// Fade in
2019-01-09 03:51:19 +01:00
case 7:
2019-01-19 23:04:33 +01:00
if (gWirelessCommType == 1 && gReceivedRemoteLinkPlayers == TRUE)
2019-01-09 03:51:19 +01:00
{
2019-04-04 23:05:46 +02:00
LoadWirelessStatusIndicatorSpriteGfx();
2019-01-09 03:51:19 +01:00
CreateWirelessStatusIndicatorSprite(230, 150);
}
2021-02-24 17:01:02 +01:00
BlendPalettes(PALETTES_ALL, 16, sData->blendColor);
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, sData->blendColor);
2019-01-20 18:24:35 +01:00
SetVBlankCallback(VblankCb_TrainerCard);
2020-02-07 18:48:47 +01:00
sData->mainState++;
2019-01-09 03:51:19 +01:00
break;
case 8:
2019-01-19 23:04:33 +01:00
if (!UpdatePaletteFade() && !IsDma3ManagerBusyWithBgCopy())
2019-01-09 03:51:19 +01:00
{
2020-08-21 00:02:00 +02:00
PlaySE(SE_RG_CARD_OPEN);
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_HANDLE_INPUT_FRONT;
2019-01-09 03:51:19 +01:00
}
break;
case 9:
2019-01-19 23:04:33 +01:00
if (!IsSEPlaying())
2020-02-07 18:48:47 +01:00
sData->mainState++;
2019-01-09 03:51:19 +01:00
break;
2020-02-07 18:48:47 +01:00
case STATE_HANDLE_INPUT_FRONT:
// Blink the : in play time
if (!gReceivedRemoteLinkPlayers && sData->timeColonNeedDraw)
2019-01-09 03:51:19 +01:00
{
2019-01-19 23:04:33 +01:00
PrintTimeOnCard();
2020-02-07 18:48:47 +01:00
DrawTrainerCardWindow(1);
sData->timeColonNeedDraw = FALSE;
2019-01-19 23:04:33 +01:00
}
2020-09-05 03:11:55 +02:00
if (JOY_NEW(A_BUTTON))
2019-01-09 03:51:19 +01:00
{
2020-02-07 18:48:47 +01:00
FlipTrainerCard();
2020-08-21 00:02:00 +02:00
PlaySE(SE_RG_CARD_FLIP);
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_WAIT_FLIP_TO_BACK;
2019-01-09 03:51:19 +01:00
}
2020-09-05 03:11:55 +02:00
else if (JOY_NEW(B_BUTTON))
2019-01-09 03:51:19 +01:00
{
2019-01-20 18:24:35 +01:00
if (gReceivedRemoteLinkPlayers && sData->isLink && InUnionRoom() == TRUE)
2019-01-19 23:04:33 +01:00
{
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_WAIT_LINK_PARTNER;
2019-01-19 23:04:33 +01:00
}
2019-01-09 03:51:19 +01:00
else
{
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, sData->blendColor);
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_CLOSE_CARD;
2019-01-09 03:51:19 +01:00
}
2019-01-19 23:04:33 +01:00
}
2019-01-09 03:51:19 +01:00
break;
2020-02-07 18:48:47 +01:00
case STATE_WAIT_FLIP_TO_BACK:
2021-03-19 01:35:39 +01:00
if (IsCardFlipTaskActive() && Overworld_LinkRecvQueueLengthMoreThan2() != TRUE)
2019-01-09 03:51:19 +01:00
{
2020-08-21 00:02:00 +02:00
PlaySE(SE_RG_CARD_OPEN);
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_HANDLE_INPUT_BACK;
2019-01-19 23:04:33 +01:00
}
break;
2020-02-07 18:48:47 +01:00
case STATE_HANDLE_INPUT_BACK:
2020-09-05 03:11:55 +02:00
if (JOY_NEW(B_BUTTON))
2019-01-09 03:51:19 +01:00
{
2019-01-20 18:24:35 +01:00
if (gReceivedRemoteLinkPlayers && sData->isLink && InUnionRoom() == TRUE)
2019-01-19 23:04:33 +01:00
{
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_WAIT_LINK_PARTNER;
2019-01-19 23:04:33 +01:00
}
else if (gReceivedRemoteLinkPlayers)
2019-01-09 03:51:19 +01:00
{
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, sData->blendColor);
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_CLOSE_CARD;
2019-01-09 03:51:19 +01:00
}
else
{
2020-02-07 18:48:47 +01:00
FlipTrainerCard();
sData->mainState = STATE_WAIT_FLIP_TO_FRONT;
2020-08-21 00:02:00 +02:00
PlaySE(SE_RG_CARD_FLIP);
2019-01-09 03:51:19 +01:00
}
2019-01-19 23:04:33 +01:00
}
2020-09-05 03:11:55 +02:00
else if (JOY_NEW(A_BUTTON))
2019-01-09 03:51:19 +01:00
{
2019-01-20 18:24:35 +01:00
if (gReceivedRemoteLinkPlayers && sData->isLink && InUnionRoom() == TRUE)
2019-01-19 23:04:33 +01:00
{
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_WAIT_LINK_PARTNER;
2019-01-19 23:04:33 +01:00
}
2019-01-09 03:51:19 +01:00
else
{
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, sData->blendColor);
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_CLOSE_CARD;
2019-01-09 03:51:19 +01:00
}
}
2019-01-19 23:04:33 +01:00
break;
2020-02-07 18:48:47 +01:00
case STATE_WAIT_LINK_PARTNER:
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
DrawDialogueFrame(0, 1);
2019-01-09 03:51:19 +01:00
AddTextPrinterParameterized(0, 1, gText_WaitingTrainerFinishReading, 0, 1, 255, 0);
CopyWindowToVram(0, 3);
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_CLOSE_CARD_LINK;
2019-01-09 03:51:19 +01:00
break;
2020-02-07 18:48:47 +01:00
case STATE_CLOSE_CARD_LINK:
2019-01-19 23:04:33 +01:00
if (!gReceivedRemoteLinkPlayers)
2019-01-09 03:51:19 +01:00
{
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, sData->blendColor);
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_CLOSE_CARD;
2019-01-09 03:51:19 +01:00
}
break;
2020-02-07 18:48:47 +01:00
case STATE_CLOSE_CARD:
2019-01-19 23:04:33 +01:00
if (!UpdatePaletteFade())
2019-01-20 18:24:35 +01:00
CloseTrainerCard(taskId);
2019-01-09 03:51:19 +01:00
break;
2020-02-07 18:48:47 +01:00
case STATE_WAIT_FLIP_TO_FRONT:
2021-03-19 01:35:39 +01:00
if (IsCardFlipTaskActive() && Overworld_LinkRecvQueueLengthMoreThan2() != TRUE)
2019-01-09 03:51:19 +01:00
{
2020-02-07 18:48:47 +01:00
sData->mainState = STATE_HANDLE_INPUT_FRONT;
2020-08-21 00:02:00 +02:00
PlaySE(SE_RG_CARD_OPEN);
2019-01-09 03:51:19 +01:00
}
2019-01-19 23:04:33 +01:00
break;
2019-01-09 03:51:19 +01:00
}
}
2019-01-20 18:24:35 +01:00
static bool8 LoadCardGfx(void)
2019-01-09 03:51:19 +01:00
{
2019-01-20 18:24:35 +01:00
switch (sData->gfxLoadState)
2019-01-09 03:51:19 +01:00
{
case 0:
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG)
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gHoennTrainerCardBg_Tilemap, sData->bgTilemap);
2019-01-09 03:51:19 +01:00
else
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gKantoTrainerCardBg_Tilemap, sData->bgTilemap);
2019-01-09 03:51:19 +01:00
break;
case 1:
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG)
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gHoennTrainerCardBack_Tilemap, sData->backTilemap);
2019-01-09 03:51:19 +01:00
else
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gKantoTrainerCardBack_Tilemap, sData->backTilemap);
2019-01-09 03:51:19 +01:00
break;
case 2:
2019-01-20 18:24:35 +01:00
if (!sData->isLink)
2019-01-09 03:51:19 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG)
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gHoennTrainerCardFront_Tilemap, sData->frontTilemap);
2019-01-09 03:51:19 +01:00
else
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gKantoTrainerCardFront_Tilemap, sData->frontTilemap);
2019-01-09 03:51:19 +01:00
}
else
{
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG)
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gHoennTrainerCardFrontLink_Tilemap, sData->frontTilemap);
2019-01-09 03:51:19 +01:00
else
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gKantoTrainerCardFrontLink_Tilemap, sData->frontTilemap);
2019-01-09 03:51:19 +01:00
}
break;
case 3:
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG)
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(sHoennTrainerCardBadges_Gfx, sData->badgeTiles);
2019-01-09 03:51:19 +01:00
else
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(sKantoTrainerCardBadges_Gfx, sData->badgeTiles);
2019-01-09 03:51:19 +01:00
break;
case 4:
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG)
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gHoennTrainerCard_Gfx, sData->cardTiles);
2019-01-09 03:51:19 +01:00
else
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(gKantoTrainerCard_Gfx, sData->cardTiles);
2019-01-09 03:51:19 +01:00
break;
case 5:
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG)
2020-02-07 18:48:47 +01:00
LZ77UnCompWram(sTrainerCardStickers_Gfx, sData->stickerTiles);
2019-01-09 03:51:19 +01:00
break;
default:
2019-01-20 18:24:35 +01:00
sData->gfxLoadState = 0;
2019-01-19 18:14:59 +01:00
return TRUE;
2019-01-09 03:51:19 +01:00
}
2019-01-20 18:24:35 +01:00
sData->gfxLoadState++;
2019-01-19 18:14:59 +01:00
return FALSE;
}
2019-01-20 18:24:35 +01:00
static void CB2_InitTrainerCard(void)
2019-01-19 23:04:33 +01:00
{
switch (gMain.state)
{
case 0:
2019-01-20 18:24:35 +01:00
ResetGpuRegs();
2020-02-07 18:48:47 +01:00
SetUpTrainerCardTask();
2019-01-19 23:04:33 +01:00
gMain.state++;
break;
case 1:
DmaClear32(3, (void *)OAM, OAM_SIZE);
gMain.state++;
break;
case 2:
2020-02-07 18:48:47 +01:00
if (!sData->blendColor)
2019-01-19 23:04:33 +01:00
DmaClear16(3, (void *)PLTT, PLTT_SIZE);
gMain.state++;
break;
case 3:
ResetSpriteData();
FreeAllSpritePalettes();
ResetPaletteFade();
gMain.state++;
case 4:
2019-01-20 18:24:35 +01:00
InitBgsAndWindows();
2019-01-19 23:04:33 +01:00
gMain.state++;
break;
case 5:
2020-02-07 18:48:47 +01:00
LoadMonIconGfx();
2019-01-19 23:04:33 +01:00
gMain.state++;
break;
case 6:
2019-01-20 18:24:35 +01:00
if (LoadCardGfx() == TRUE)
2019-01-19 23:04:33 +01:00
gMain.state++;
break;
case 7:
2020-02-07 18:48:47 +01:00
LoadStickerGfx();
2019-01-19 23:04:33 +01:00
gMain.state++;
break;
case 8:
2021-03-22 00:54:23 +01:00
InitGpuRegs();
2019-01-19 23:04:33 +01:00
gMain.state++;
break;
case 9:
2020-02-07 18:48:47 +01:00
BufferTextsVarsForCardPage2();
2019-01-19 23:04:33 +01:00
gMain.state++;
break;
case 10:
2019-01-20 18:24:35 +01:00
if (SetCardBgsAndPals() == TRUE)
2019-01-19 23:04:33 +01:00
gMain.state++;
break;
default:
2019-01-20 18:24:35 +01:00
SetTrainerCardCb2();
2019-01-19 23:04:33 +01:00
break;
}
}
2019-01-20 18:24:35 +01:00
static u32 GetCappedGameStat(u8 statId, u32 maxValue)
2019-01-19 23:04:33 +01:00
{
u32 statValue = GetGameStat(statId);
return min(maxValue, statValue);
}
2019-01-20 18:24:35 +01:00
static bool8 HasAllFrontierSymbols(void)
2019-01-19 18:14:59 +01:00
{
u8 i;
2019-01-19 23:04:33 +01:00
for (i = 0; i < NUM_FRONTIER_FACILITIES; i++)
2019-01-19 18:14:59 +01:00
{
2019-01-19 23:04:33 +01:00
if (!FlagGet(FLAG_SYS_TOWER_SILVER + 2 * i) || !FlagGet(FLAG_SYS_TOWER_GOLD + 2 * i))
2019-01-19 18:14:59 +01:00
return FALSE;
}
2019-01-19 23:04:33 +01:00
return TRUE;
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
u32 CountPlayerTrainerStars(void)
2019-01-19 18:14:59 +01:00
{
2019-01-19 23:04:33 +01:00
u8 stars = 0;
if (GetGameStat(GAME_STAT_ENTERED_HOF))
stars++;
if (HasAllHoennMons())
stars++;
if (CountPlayerContestPaintings() > 4)
stars++;
if (HasAllFrontierSymbols())
stars++;
return stars;
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static u8 GetRubyTrainerStars(struct TrainerCard *trainerCard)
2019-01-19 18:14:59 +01:00
{
2019-01-19 23:04:33 +01:00
u8 stars = 0;
2019-01-19 18:14:59 +01:00
2019-01-19 23:04:33 +01:00
if (trainerCard->hofDebutHours || trainerCard->hofDebutMinutes || trainerCard->hofDebutSeconds)
stars++;
if (trainerCard->caughtAllHoenn)
stars++;
2019-01-20 18:24:35 +01:00
if (trainerCard->battleTowerStraightWins > 49)
2019-01-19 23:04:33 +01:00
stars++;
if (trainerCard->hasAllPaintings)
stars++;
return stars;
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void SetPlayerCardData(struct TrainerCard *trainerCard, u8 cardType)
2019-01-19 18:14:59 +01:00
{
u32 playTime;
u8 i;
trainerCard->gender = gSaveBlock2Ptr->playerGender;
trainerCard->playTimeHours = gSaveBlock2Ptr->playTimeHours;
trainerCard->playTimeMinutes = gSaveBlock2Ptr->playTimeMinutes;
playTime = GetGameStat(GAME_STAT_FIRST_HOF_PLAY_TIME);
2019-01-19 23:04:33 +01:00
if (!GetGameStat(GAME_STAT_ENTERED_HOF))
2019-01-19 18:14:59 +01:00
playTime = 0;
2019-01-19 23:04:33 +01:00
trainerCard->hofDebutHours = playTime >> 16;
trainerCard->hofDebutMinutes = (playTime >> 8) & 0xFF;
trainerCard->hofDebutSeconds = playTime & 0xFF;
if ((playTime >> 16) > 999)
2019-01-19 18:14:59 +01:00
{
2019-01-19 23:04:33 +01:00
trainerCard->hofDebutHours = 999;
trainerCard->hofDebutMinutes = 59;
trainerCard->hofDebutSeconds = 59;
2019-01-19 18:14:59 +01:00
}
2019-01-19 23:04:33 +01:00
2019-01-19 18:14:59 +01:00
trainerCard->hasPokedex = FlagGet(FLAG_SYS_POKEDEX_GET);
2019-01-19 23:04:33 +01:00
trainerCard->caughtAllHoenn = HasAllHoennMons();
trainerCard->caughtMonsCount = GetCaughtMonsCount();
2019-01-19 18:14:59 +01:00
trainerCard->trainerId = (gSaveBlock2Ptr->playerTrainerId[1] << 8) | gSaveBlock2Ptr->playerTrainerId[0];
2019-01-19 23:04:33 +01:00
trainerCard->linkBattleWins = GetCappedGameStat(GAME_STAT_LINK_BATTLE_WINS, 9999);
trainerCard->linkBattleLosses = GetCappedGameStat(GAME_STAT_LINK_BATTLE_LOSSES, 9999);
trainerCard->pokemonTrades = GetCappedGameStat(GAME_STAT_POKEMON_TRADES, 0xFFFF);
2019-01-19 18:14:59 +01:00
trainerCard->money = GetMoney(&gSaveBlock1Ptr->money);
2020-02-07 18:48:47 +01:00
for (i = 0; i < TRAINER_CARD_PROFILE_LENGTH; i++)
trainerCard->easyChatProfile[i] = gSaveBlock1Ptr->easyChatProfile[i];
2019-01-19 23:04:33 +01:00
2019-01-19 18:14:59 +01:00
StringCopy(trainerCard->playerName, gSaveBlock2Ptr->playerName);
2019-01-19 23:04:33 +01:00
2019-01-20 18:24:35 +01:00
switch (cardType)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
case CARD_TYPE_EMERALD:
2019-01-19 18:14:59 +01:00
trainerCard->battleTowerWins = 0;
2019-01-20 18:24:35 +01:00
trainerCard->battleTowerStraightWins = 0;
2019-01-22 21:56:57 +01:00
// Seems like GF got CARD_TYPE_FRLG and CARD_TYPE_RS wrong.
case CARD_TYPE_FRLG:
2019-01-19 23:04:33 +01:00
trainerCard->contestsWithFriends = GetCappedGameStat(GAME_STAT_WON_LINK_CONTEST, 999);
trainerCard->pokeblocksWithFriends = GetCappedGameStat(GAME_STAT_POKEBLOCKS_WITH_FRIENDS, 0xFFFF);
if (CountPlayerContestPaintings() > 4)
trainerCard->hasAllPaintings = TRUE;
2019-01-20 18:24:35 +01:00
trainerCard->stars = GetRubyTrainerStars(trainerCard);
2019-01-19 18:14:59 +01:00
break;
2019-01-22 21:56:57 +01:00
case CARD_TYPE_RS:
2019-01-19 18:14:59 +01:00
trainerCard->battleTowerWins = 0;
2019-01-20 18:24:35 +01:00
trainerCard->battleTowerStraightWins = 0;
2019-01-19 18:14:59 +01:00
trainerCard->contestsWithFriends = 0;
trainerCard->pokeblocksWithFriends = 0;
2019-01-19 23:04:33 +01:00
trainerCard->hasAllPaintings = 0;
2019-01-19 18:14:59 +01:00
trainerCard->stars = 0;
2019-01-19 23:04:33 +01:00
break;
2019-01-19 18:14:59 +01:00
}
}
static void TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard *trainerCard)
2019-01-19 18:14:59 +01:00
{
memset(trainerCard, 0, sizeof(struct TrainerCard));
2019-01-22 21:56:57 +01:00
trainerCard->version = GAME_VERSION;
2019-01-20 18:24:35 +01:00
SetPlayerCardData(trainerCard, CARD_TYPE_EMERALD);
trainerCard->hasAllSymbols = HasAllFrontierSymbols();
2019-11-24 22:58:40 +01:00
trainerCard->frontierBP = gSaveBlock2Ptr->frontier.cardBattlePoints;
2019-01-20 18:24:35 +01:00
if (trainerCard->hasAllSymbols)
2019-01-19 18:14:59 +01:00
trainerCard->stars++;
2019-01-19 23:04:33 +01:00
if (trainerCard->gender == FEMALE)
2020-02-07 18:48:47 +01:00
trainerCard->facilityClass = gLinkPlayerFacilityClasses[(trainerCard->trainerId % NUM_FEMALE_LINK_FACILITY_CLASSES) + NUM_MALE_LINK_FACILITY_CLASSES];
2019-01-19 18:14:59 +01:00
else
2020-02-07 18:48:47 +01:00
trainerCard->facilityClass = gLinkPlayerFacilityClasses[trainerCard->trainerId % NUM_MALE_LINK_FACILITY_CLASSES];
2019-01-19 18:14:59 +01:00
}
2019-01-19 23:04:33 +01:00
2019-01-19 18:14:59 +01:00
void TrainerCard_GenerateCardForPlayer(struct TrainerCard *trainerCard)
{
memset(trainerCard, 0, 0x60);
2019-01-22 21:56:57 +01:00
trainerCard->version = GAME_VERSION;
2019-01-20 18:24:35 +01:00
SetPlayerCardData(trainerCard, CARD_TYPE_EMERALD);
2020-02-07 18:48:47 +01:00
trainerCard->hasAllFrontierSymbols = HasAllFrontierSymbols();
2019-11-24 22:58:40 +01:00
*((u16*)&trainerCard->berryCrushPoints) = gSaveBlock2Ptr->frontier.cardBattlePoints;
2020-02-07 18:48:47 +01:00
if (trainerCard->hasAllFrontierSymbols)
2019-01-19 18:14:59 +01:00
trainerCard->stars++;
2019-01-19 23:04:33 +01:00
if (trainerCard->gender == FEMALE)
2020-02-07 18:48:47 +01:00
trainerCard->facilityClass = gLinkPlayerFacilityClasses[(trainerCard->trainerId % NUM_FEMALE_LINK_FACILITY_CLASSES) + NUM_MALE_LINK_FACILITY_CLASSES];
2019-01-19 18:14:59 +01:00
else
2020-02-07 18:48:47 +01:00
trainerCard->facilityClass = gLinkPlayerFacilityClasses[trainerCard->trainerId % NUM_MALE_LINK_FACILITY_CLASSES];
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
void CopyTrainerCardData(struct TrainerCard *dst, u16 *src, u8 gameVersion)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
memset(dst, 0, sizeof(struct TrainerCard));
dst->version = gameVersion;
2019-01-19 23:04:33 +01:00
2019-01-20 18:24:35 +01:00
switch (VersionToCardType(gameVersion))
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
case CARD_TYPE_FRLG:
2019-01-20 18:24:35 +01:00
memcpy(dst, src, 0x60);
2019-01-19 18:14:59 +01:00
break;
2019-01-22 21:56:57 +01:00
case CARD_TYPE_RS:
2019-01-20 18:24:35 +01:00
memcpy(dst, src, 0x38);
2019-01-19 18:14:59 +01:00
break;
2019-01-20 18:24:35 +01:00
case CARD_TYPE_EMERALD:
memcpy(dst, src, 0x60);
2019-01-22 21:56:57 +01:00
dst->berryCrushPoints = 0;
2019-01-20 18:24:35 +01:00
dst->hasAllSymbols = src[29];
dst->frontierBP = src[30];
2019-01-19 23:04:33 +01:00
break;
2019-01-19 18:14:59 +01:00
}
}
2019-01-20 18:24:35 +01:00
static void SetDataFromTrainerCard(void)
2019-01-19 18:14:59 +01:00
{
u8 i;
u32 badgeFlag;
2019-01-19 23:04:33 +01:00
2019-01-20 18:24:35 +01:00
sData->hasPokedex = FALSE;
sData->hasHofResult = FALSE;
sData->hasLinkResults = FALSE;
sData->hasBattleTowerWins = FALSE;
2020-02-07 18:48:47 +01:00
sData->unused_E = FALSE;
sData->unused_F = FALSE;
2019-01-20 18:24:35 +01:00
sData->hasTrades = FALSE;
memset(sData->badgeCount, 0, sizeof(sData->badgeCount));
if (sData->trainerCard.hasPokedex)
sData->hasPokedex++;
if (sData->trainerCard.hofDebutHours
|| sData->trainerCard.hofDebutMinutes
|| sData->trainerCard.hofDebutSeconds)
sData->hasHofResult++;
if (sData->trainerCard.linkBattleWins || sData->trainerCard.linkBattleLosses)
sData->hasLinkResults++;
if (sData->trainerCard.pokemonTrades)
sData->hasTrades++;
if (sData->trainerCard.battleTowerWins || sData->trainerCard.battleTowerStraightWins)
sData->hasBattleTowerWins++;
2020-02-07 18:48:47 +01:00
for (i = 0, badgeFlag = FLAG_BADGE01_GET; badgeFlag < FLAG_BADGE01_GET + NUM_BADGES; badgeFlag++, i++)
2019-01-19 18:14:59 +01:00
{
2019-01-19 23:04:33 +01:00
if (FlagGet(badgeFlag))
2019-01-20 18:24:35 +01:00
sData->badgeCount[i]++;
2019-01-19 18:14:59 +01:00
}
}
2021-03-22 00:54:23 +01:00
static void InitGpuRegs(void)
2019-01-19 18:14:59 +01:00
{
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
ShowBg(0);
ShowBg(1);
ShowBg(2);
ShowBg(3);
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);
2021-03-22 00:54:23 +01:00
SetGpuReg(REG_OFFSET_WIN0V, DISPLAY_HEIGHT);
SetGpuReg(REG_OFFSET_WIN0H, DISPLAY_WIDTH);
2019-01-19 23:04:33 +01:00
if (gReceivedRemoteLinkPlayers)
2019-01-19 18:14:59 +01:00
EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
else
EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK);
}
2021-03-22 00:54:23 +01:00
static void UpdateCardFlipRegs(u16 cardTop)
2019-01-19 18:14:59 +01:00
{
2021-03-22 00:54:23 +01:00
s8 blendY = (cardTop + 40) / 10;
2019-01-19 23:04:33 +01:00
2021-03-22 00:54:23 +01:00
if (blendY <= 4)
blendY = 0;
sData->flipBlendY = blendY;
2020-02-07 18:48:47 +01:00
SetGpuReg(REG_OFFSET_BLDY, sData->flipBlendY);
2021-03-22 00:54:23 +01:00
SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(sData->cardTop, DISPLAY_HEIGHT - sData->cardTop));
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void ResetGpuRegs(void)
2019-01-19 18:14:59 +01:00
{
SetVBlankCallback(NULL);
SetHBlankCallback(NULL);
SetGpuReg(REG_OFFSET_DISPCNT, 0);
SetGpuReg(REG_OFFSET_BG0CNT, 0);
SetGpuReg(REG_OFFSET_BG1CNT, 0);
SetGpuReg(REG_OFFSET_BG2CNT, 0);
SetGpuReg(REG_OFFSET_BG3CNT, 0);
}
2019-01-20 18:24:35 +01:00
static void InitBgsAndWindows(void)
2019-01-19 18:14:59 +01:00
{
ResetBgsAndClearDma3BusyFlags(0);
2020-02-07 18:48:47 +01:00
InitBgsFromTemplates(0, sTrainerCardBgTemplates, ARRAY_COUNT(sTrainerCardBgTemplates));
2019-01-19 18:14:59 +01:00
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);
2020-02-07 18:48:47 +01:00
InitWindows(sTrainerCardWindowTemplates);
2019-01-19 18:14:59 +01:00
DeactivateAllTextPrinters();
2020-02-07 18:48:47 +01:00
LoadMessageBoxAndBorderGfx();
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void SetTrainerCardCb2(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
SetMainCallback2(CB2_TrainerCard);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void SetUpTrainerCardTask(void)
2019-01-19 18:14:59 +01:00
{
ResetTasks();
ScanlineEffect_Stop();
2020-02-07 18:48:47 +01:00
CreateTask(Task_TrainerCard, 0);
InitTrainerCardData();
2019-01-20 18:24:35 +01:00
SetDataFromTrainerCard();
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static bool8 PrintAllOnCardFront(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
switch (sData->printState)
2019-01-19 18:14:59 +01:00
{
case 0:
2020-02-07 18:48:47 +01:00
PrintNameOnCardFront();
2019-01-19 18:14:59 +01:00
break;
case 1:
2019-01-19 23:04:33 +01:00
PrintIdOnCard();
2019-01-19 18:14:59 +01:00
break;
case 2:
2019-01-19 23:04:33 +01:00
PrintMoneyOnCard();
2019-01-19 18:14:59 +01:00
break;
case 3:
2019-01-19 23:04:33 +01:00
PrintPokedexOnCard();
2019-01-19 18:14:59 +01:00
break;
case 4:
2019-01-19 23:04:33 +01:00
PrintTimeOnCard();
2019-01-19 18:14:59 +01:00
break;
case 5:
2019-01-19 23:04:33 +01:00
PrintProfilePhraseOnCard();
2019-01-19 18:14:59 +01:00
break;
default:
2019-01-20 18:24:35 +01:00
sData->printState = 0;
2019-01-19 18:14:59 +01:00
return TRUE;
}
2019-01-20 18:24:35 +01:00
sData->printState++;
2019-01-19 18:14:59 +01:00
return FALSE;
}
2020-02-07 18:48:47 +01:00
static bool8 PrintAllOnCardBack(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
switch (sData->printState)
2019-01-19 18:14:59 +01:00
{
case 0:
2020-02-07 18:48:47 +01:00
PrintNameOnCardBack();
2019-01-19 18:14:59 +01:00
break;
case 1:
2020-02-07 18:48:47 +01:00
PrintHofDebutTimeOnCard();
2019-01-19 18:14:59 +01:00
break;
case 2:
2020-02-07 18:48:47 +01:00
PrintLinkBattleResultsOnCard();
2019-01-19 18:14:59 +01:00
break;
case 3:
2019-01-19 23:04:33 +01:00
PrintTradesStringOnCard();
2019-01-19 18:14:59 +01:00
break;
case 4:
2019-01-19 23:04:33 +01:00
PrintBerryCrushStringOnCard();
PrintPokeblockStringOnCard();
2019-01-19 18:14:59 +01:00
break;
case 5:
2019-01-19 23:04:33 +01:00
PrintUnionStringOnCard();
PrintContestStringOnCard();
2019-01-19 18:14:59 +01:00
break;
case 6:
2020-02-07 18:48:47 +01:00
PrintPokemonIconsOnCard();
2019-01-19 23:04:33 +01:00
PrintBattleFacilityStringOnCard();
2019-01-19 18:14:59 +01:00
break;
case 7:
2020-02-07 18:48:47 +01:00
PrintStickersOnCard();
2019-01-19 18:14:59 +01:00
break;
default:
2019-01-20 18:24:35 +01:00
sData->printState = 0;
2019-01-19 18:14:59 +01:00
return TRUE;
}
2019-01-20 18:24:35 +01:00
sData->printState++;
2019-01-19 18:14:59 +01:00
return FALSE;
}
2020-02-07 18:48:47 +01:00
static void BufferTextsVarsForCardPage2(void)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
BufferNameForCardBack();
BufferHofDebutTime();
BufferLinkBattleResults();
BufferNumTrades();
BufferBerryCrushPoints();
BufferUnionRoomStats();
BufferLinkPokeblocksNum();
BufferLinkContestNum();
BufferBattleFacilityStats();
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void PrintNameOnCardFront(void)
2019-01-19 18:14:59 +01:00
{
u8 buffer[32];
u8* txtPtr;
txtPtr = StringCopy(buffer, gText_TrainerCardName);
2019-01-20 18:24:35 +01:00
StringCopy(txtPtr, sData->trainerCard.playerName);
ConvertInternationalString(txtPtr, sData->language);
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG)
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, 20, 28, sTrainerCardTextColors, TEXT_SPEED_FF, buffer);
2019-01-19 18:14:59 +01:00
else
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, 16, 33, sTrainerCardTextColors, TEXT_SPEED_FF, buffer);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void PrintIdOnCard(void)
2019-01-19 18:14:59 +01:00
{
u8 buffer[32];
u8* txtPtr;
s32 xPos;
u32 top;
txtPtr = StringCopy(buffer, gText_TrainerCardIDNo);
2019-01-20 18:24:35 +01:00
ConvertIntToDecimalStringN(txtPtr, sData->trainerCard.trainerId, STR_CONV_MODE_LEADING_ZEROS, 5);
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG)
2019-01-19 18:14:59 +01:00
{
2019-01-19 23:04:33 +01:00
xPos = GetStringCenterAlignXOffset(1, buffer, 80) + 132;
2019-01-19 18:14:59 +01:00
top = 9;
}
else
{
xPos = GetStringCenterAlignXOffset(1, buffer, 96) + 120;
top = 9;
}
2019-01-19 23:04:33 +01:00
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, xPos, top, sTrainerCardTextColors, TEXT_SPEED_FF, buffer);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void PrintMoneyOnCard(void)
2019-01-19 18:14:59 +01:00
{
s32 xOffset;
u8 top;
2019-01-19 23:04:33 +01:00
2019-01-20 18:24:35 +01:00
if (!sData->isHoenn)
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, 20, 56, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardMoney);
2019-01-19 18:14:59 +01:00
else
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, 16, 57, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardMoney);
2019-01-19 23:04:33 +01:00
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, sData->trainerCard.money, STR_CONV_MODE_LEFT_ALIGN, 6);
2019-01-19 18:14:59 +01:00
StringExpandPlaceholders(gStringVar4, gText_PokedollarVar1);
2019-01-20 18:24:35 +01:00
if (!sData->isHoenn)
2019-01-19 18:14:59 +01:00
{
xOffset = GetStringRightAlignXOffset(1, gStringVar4, 144);
top = 56;
}
else
{
xOffset = GetStringRightAlignXOffset(1, gStringVar4, 128);
top = 57;
2019-01-19 23:04:33 +01:00
}
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, xOffset, top, sTrainerCardTextColors, TEXT_SPEED_FF, gStringVar4);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static u16 GetCaughtMonsCount(void)
2019-01-19 18:14:59 +01:00
{
2019-01-19 23:04:33 +01:00
if (IsNationalPokedexEnabled())
2019-01-19 18:14:59 +01:00
return GetNationalPokedexCount(FLAG_GET_CAUGHT);
2019-01-19 23:04:33 +01:00
else
return GetHoennPokedexCount(FLAG_GET_CAUGHT);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void PrintPokedexOnCard(void)
2019-01-19 18:14:59 +01:00
{
s32 xOffset;
u8 top;
2019-01-19 23:04:33 +01:00
if (FlagGet(FLAG_SYS_POKEDEX_GET))
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (!sData->isHoenn)
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, 20, 72, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardPokedex);
2019-01-19 18:14:59 +01:00
else
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, 16, 73, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardPokedex);
2019-09-30 21:43:44 +02:00
StringCopy(ConvertIntToDecimalStringN(gStringVar4, sData->trainerCard.caughtMonsCount, STR_CONV_MODE_LEFT_ALIGN, 3), gText_EmptyString6);
2019-01-20 18:24:35 +01:00
if (!sData->isHoenn)
2019-01-19 18:14:59 +01:00
{
xOffset = GetStringRightAlignXOffset(1, gStringVar4, 144);
top = 72;
}
else
{
xOffset = GetStringRightAlignXOffset(1, gStringVar4, 128);
top = 73;
2019-01-19 23:04:33 +01:00
}
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, xOffset, top, sTrainerCardTextColors, TEXT_SPEED_FF, gStringVar4);
2019-01-19 18:14:59 +01:00
}
}
2020-02-07 18:48:47 +01:00
static const u8 *const sTimeColonTextColors[] = {sTrainerCardTextColors, sTimeColonInvisibleTextColors};
2019-01-20 18:24:35 +01:00
static void PrintTimeOnCard(void)
2019-01-19 18:14:59 +01:00
{
u16 hours;
u16 minutes;
s32 width;
2020-02-07 18:48:47 +01:00
u32 x, y, totalWidth;
2019-01-19 23:04:33 +01:00
2019-01-20 18:24:35 +01:00
if (!sData->isHoenn)
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, 20, 88, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardTime);
2019-01-19 18:14:59 +01:00
else
2019-12-10 19:48:20 +01:00
AddTextPrinterParameterized3(1, 1, 16, 89, sTrainerCardTextColors, TEXT_SPEED_FF, gText_TrainerCardTime);
2019-01-19 23:04:33 +01:00
2019-01-20 18:24:35 +01:00
if (sData->isLink)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
hours = sData->trainerCard.playTimeHours;
minutes = sData->trainerCard.playTimeMinutes;
2019-01-19 18:14:59 +01:00
}
else
{
hours = gSaveBlock2Ptr->playTimeHours;
minutes = gSaveBlock2Ptr->playTimeMinutes;
}
2019-01-19 23:04:33 +01:00
if (hours > 999)
2019-01-19 18:14:59 +01:00
hours = 999;
2019-01-19 23:04:33 +01:00
if (minutes > 59)
2019-01-19 18:14:59 +01:00
minutes = 59;
width = GetStringWidth(1, gText_Colon2, 0);
2019-01-19 23:04:33 +01:00
2019-01-20 18:24:35 +01:00
if (!sData->isHoenn)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
x = 144;
y = 88;
2019-01-19 23:04:33 +01:00
}
2019-01-19 18:14:59 +01:00
else
{
2020-02-07 18:48:47 +01:00
x = 128;
y = 89;
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
totalWidth = width + 30;
x -= totalWidth;
2019-01-19 23:04:33 +01:00
2020-02-07 18:48:47 +01:00
FillWindowPixelRect(1, PIXEL_FILL(0), x, y, totalWidth, 15);
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar4, hours, STR_CONV_MODE_RIGHT_ALIGN, 3);
2020-02-07 18:48:47 +01:00
AddTextPrinterParameterized3(1, 1, x, y, sTrainerCardTextColors, TEXT_SPEED_FF, gStringVar4);
x += 18;
AddTextPrinterParameterized3(1, 1, x, y, sTimeColonTextColors[sData->timeColonInvisible], TEXT_SPEED_FF, gText_Colon2);
x += width;
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar4, minutes, STR_CONV_MODE_LEADING_ZEROS, 2);
2020-02-07 18:48:47 +01:00
AddTextPrinterParameterized3(1, 1, x, y, sTrainerCardTextColors, TEXT_SPEED_FF, gStringVar4);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void PrintProfilePhraseOnCard(void)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
static const u8 yOffsetsLine1[] = {113, 104};
static const u8 yOffsetsLine2[] = {129, 120};
2019-01-20 18:24:35 +01:00
if (sData->isLink)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
AddTextPrinterParameterized3(1, 1, 8, yOffsetsLine1[sData->isHoenn], sTrainerCardTextColors, TEXT_SPEED_FF, sData->easyChatProfile[0]);
AddTextPrinterParameterized3(1, 1, GetStringWidth(1, sData->easyChatProfile[0], 0) + 14, yOffsetsLine1[sData->isHoenn], sTrainerCardTextColors, TEXT_SPEED_FF, sData->easyChatProfile[1]);
AddTextPrinterParameterized3(1, 1, 8, yOffsetsLine2[sData->isHoenn], sTrainerCardTextColors, TEXT_SPEED_FF, sData->easyChatProfile[2]);
AddTextPrinterParameterized3(1, 1, GetStringWidth(1, sData->easyChatProfile[2], 0) + 14, yOffsetsLine2[sData->isHoenn], sTrainerCardTextColors, TEXT_SPEED_FF, sData->easyChatProfile[3]);
2019-01-19 18:14:59 +01:00
}
}
2020-02-07 18:48:47 +01:00
static void BufferNameForCardBack(void)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
StringCopy(sData->textPlayersCard, sData->trainerCard.playerName);
ConvertInternationalString(sData->textPlayersCard, sData->language);
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
StringCopy(gStringVar1, sData->textPlayersCard);
StringExpandPlaceholders(sData->textPlayersCard, gText_Var1sTrainerCard);
2019-01-19 18:14:59 +01:00
}
}
2020-02-07 18:48:47 +01:00
static void PrintNameOnCardBack(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (!sData->isHoenn)
2020-02-07 18:48:47 +01:00
AddTextPrinterParameterized3(1, 1, 136, 9, sTrainerCardTextColors, TEXT_SPEED_FF, sData->textPlayersCard);
2019-01-19 18:14:59 +01:00
else
2020-02-07 18:48:47 +01:00
AddTextPrinterParameterized3(1, 1, GetStringRightAlignXOffset(1, sData->textPlayersCard, 216), 9, sTrainerCardTextColors, TEXT_SPEED_FF, sData->textPlayersCard);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static const u8 sText_HofTime[] = _("{STR_VAR_1}:{STR_VAR_2}:{STR_VAR_3}");
2019-01-20 18:24:35 +01:00
2020-02-07 18:48:47 +01:00
static void BufferHofDebutTime(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->hasHofResult)
2019-01-19 18:14:59 +01:00
{
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, sData->trainerCard.hofDebutHours, STR_CONV_MODE_RIGHT_ALIGN, 3);
ConvertIntToDecimalStringN(gStringVar2, sData->trainerCard.hofDebutMinutes, STR_CONV_MODE_LEADING_ZEROS, 2);
ConvertIntToDecimalStringN(gStringVar3, sData->trainerCard.hofDebutSeconds, STR_CONV_MODE_LEADING_ZEROS, 2);
2020-02-07 18:48:47 +01:00
StringExpandPlaceholders(sData->textHofTime, sText_HofTime);
2019-01-19 18:14:59 +01:00
}
}
2020-02-07 18:48:47 +01:00
static void PrintStatOnBackOfCard(u8 top, const u8* statName, u8* stat, const u8* color)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
static const u8 xOffsets[] = {8, 16};
static const u8 widths[] = {216, 216};
AddTextPrinterParameterized3(1, 1, xOffsets[sData->isHoenn], top * 16 + 33, sTrainerCardTextColors, TEXT_SPEED_FF, statName);
AddTextPrinterParameterized3(1, 1, GetStringRightAlignXOffset(1, stat, widths[sData->isHoenn]), top * 16 + 33, color, TEXT_SPEED_FF, stat);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void PrintHofDebutTimeOnCard(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->hasHofResult)
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(0, gText_HallOfFameDebut, sData->textHofTime, sTrainerCardStatColors);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static const u8 *const sLinkBattleTexts[] =
{
[CARD_TYPE_FRLG] = gText_LinkBattles,
[CARD_TYPE_RS] = gText_LinkCableBattles,
[CARD_TYPE_EMERALD] = gText_LinkBattles
};
2019-01-20 18:24:35 +01:00
2020-02-07 18:48:47 +01:00
static void BufferLinkBattleResults(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->hasLinkResults)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
StringCopy(sData->textLinkBattleType, sLinkBattleTexts[sData->cardType]);
ConvertIntToDecimalStringN(sData->textLinkBattleWins, sData->trainerCard.linkBattleWins, STR_CONV_MODE_LEFT_ALIGN, 4);
ConvertIntToDecimalStringN(sData->textLinkBattleLosses, sData->trainerCard.linkBattleLosses, STR_CONV_MODE_LEFT_ALIGN, 4);
2019-01-19 18:14:59 +01:00
}
}
2020-02-07 18:48:47 +01:00
static void PrintLinkBattleResultsOnCard(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->hasLinkResults)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
StringCopy(gStringVar1, sData->textLinkBattleWins);
StringCopy(gStringVar2, sData->textLinkBattleLosses);
2019-01-19 18:14:59 +01:00
StringExpandPlaceholders(gStringVar4, gText_WinsLosses);
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(1, sData->textLinkBattleType, gStringVar4, sTrainerCardTextColors);
2019-01-19 18:14:59 +01:00
}
}
2020-02-07 18:48:47 +01:00
static void BufferNumTrades(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->hasTrades)
2020-02-07 18:48:47 +01:00
ConvertIntToDecimalStringN(sData->textNumTrades, sData->trainerCard.pokemonTrades, STR_CONV_MODE_RIGHT_ALIGN, 5);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void PrintTradesStringOnCard(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->hasTrades)
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(2, gText_PokemonTrades, sData->textNumTrades, sTrainerCardStatColors);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void BufferBerryCrushPoints(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.berryCrushPoints)
2020-02-07 18:48:47 +01:00
ConvertIntToDecimalStringN(sData->textBerryCrushPts, sData->trainerCard.berryCrushPoints, STR_CONV_MODE_RIGHT_ALIGN, 5);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void PrintBerryCrushStringOnCard(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.berryCrushPoints)
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(4, gText_BerryCrush, sData->textBerryCrushPts, sTrainerCardStatColors);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void BufferUnionRoomStats(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.unionRoomNum)
2020-02-07 18:48:47 +01:00
ConvertIntToDecimalStringN(sData->textUnionRoomStats, sData->trainerCard.unionRoomNum, STR_CONV_MODE_RIGHT_ALIGN, 5);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void PrintUnionStringOnCard(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.unionRoomNum)
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(3, gText_UnionTradesAndBattles, sData->textUnionRoomStats, sTrainerCardStatColors);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void BufferLinkPokeblocksNum(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG && sData->trainerCard.pokeblocksWithFriends)
2019-01-19 18:14:59 +01:00
{
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, sData->trainerCard.pokeblocksWithFriends, STR_CONV_MODE_RIGHT_ALIGN, 5);
2020-02-07 18:48:47 +01:00
StringExpandPlaceholders(sData->textNumLinkPokeblocks, gText_NumPokeblocks);
2019-01-19 18:14:59 +01:00
}
}
2019-01-20 18:24:35 +01:00
static void PrintPokeblockStringOnCard(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG && sData->trainerCard.pokeblocksWithFriends)
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(3, gText_PokeblocksWithFriends, sData->textNumLinkPokeblocks, sTrainerCardStatColors);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void BufferLinkContestNum(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG && sData->trainerCard.contestsWithFriends)
2020-02-07 18:48:47 +01:00
ConvertIntToDecimalStringN(sData->textNumLinkContests, sData->trainerCard.contestsWithFriends, STR_CONV_MODE_RIGHT_ALIGN, 5);
2019-01-19 18:14:59 +01:00
}
2019-01-20 18:24:35 +01:00
static void PrintContestStringOnCard(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG && sData->trainerCard.contestsWithFriends)
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(4, gText_WonContestsWFriends, sData->textNumLinkContests, sTrainerCardStatColors);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void BufferBattleFacilityStats(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
switch (sData->cardType)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
case CARD_TYPE_RS:
2019-01-20 18:24:35 +01:00
if (sData->hasBattleTowerWins)
2019-01-19 18:14:59 +01:00
{
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, sData->trainerCard.battleTowerWins, STR_CONV_MODE_RIGHT_ALIGN, 4);
ConvertIntToDecimalStringN(gStringVar2, sData->trainerCard.battleTowerStraightWins, STR_CONV_MODE_RIGHT_ALIGN, 4);
2020-02-07 18:48:47 +01:00
StringExpandPlaceholders(sData->textBattleFacilityStat, gText_WinsStraight);
2019-01-19 18:14:59 +01:00
}
break;
2019-01-20 18:24:35 +01:00
case CARD_TYPE_EMERALD:
if (sData->trainerCard.frontierBP)
2019-01-19 18:14:59 +01:00
{
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, sData->trainerCard.frontierBP, STR_CONV_MODE_RIGHT_ALIGN, 5);
2020-02-07 18:48:47 +01:00
StringExpandPlaceholders(sData->textBattleFacilityStat, gText_NumBP);
2019-01-19 18:14:59 +01:00
}
2019-01-19 23:04:33 +01:00
break;
2019-01-22 21:56:57 +01:00
case CARD_TYPE_FRLG:
2019-01-19 23:04:33 +01:00
break;
2019-01-19 18:14:59 +01:00
}
}
2019-01-20 18:24:35 +01:00
static void PrintBattleFacilityStringOnCard(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
switch (sData->cardType)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
case CARD_TYPE_RS:
2019-01-20 18:24:35 +01:00
if (sData->hasBattleTowerWins)
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(5, gText_BattleTower, sData->textBattleFacilityStat, sTrainerCardTextColors);
2019-01-19 18:14:59 +01:00
break;
2019-01-20 18:24:35 +01:00
case CARD_TYPE_EMERALD:
if (sData->trainerCard.frontierBP)
2020-02-07 18:48:47 +01:00
PrintStatOnBackOfCard(5, gText_BattlePtsWon, sData->textBattleFacilityStat, sTrainerCardStatColors);
2019-01-19 23:04:33 +01:00
break;
2019-01-22 21:56:57 +01:00
case CARD_TYPE_FRLG:
2019-01-19 23:04:33 +01:00
break;
}
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void PrintPokemonIconsOnCard(void)
2019-01-19 18:14:59 +01:00
{
u8 i;
2020-02-07 18:48:47 +01:00
u8 paletteSlots[PARTY_SIZE] = {5, 6, 7, 8, 9, 10};
u8 xOffsets[PARTY_SIZE] = {0, 4, 8, 12, 16, 20};
2019-01-19 23:04:33 +01:00
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
for (i = 0; i < PARTY_SIZE; i++)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->trainerCard.monSpecies[i])
2019-01-19 18:14:59 +01:00
{
u8 monSpecies = GetMonIconPaletteIndexFromSpecies(sData->trainerCard.monSpecies[i]);
2020-02-07 18:48:47 +01:00
WriteSequenceToBgTilemapBuffer(3, 16 * i + 224, xOffsets[i] + 3, 15, 4, 4, paletteSlots[monSpecies], 1);
2019-01-19 18:14:59 +01:00
}
}
2019-01-19 23:04:33 +01:00
}
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void LoadMonIconGfx(void)
2019-01-19 18:14:59 +01:00
{
u8 i;
2019-01-19 23:04:33 +01:00
2020-02-07 18:48:47 +01:00
CpuSet(gMonIconPalettes, sData->monIconPal, 0x60);
switch (sData->trainerCard.monIconTint)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
case MON_ICON_TINT_NORMAL:
2019-01-19 23:04:33 +01:00
break;
2020-02-07 18:48:47 +01:00
case MON_ICON_TINT_BLACK:
TintPalette_CustomTone(sData->monIconPal, 96, 0, 0, 0);
2019-01-19 18:14:59 +01:00
break;
2020-02-07 18:48:47 +01:00
case MON_ICON_TINT_PINK:
TintPalette_CustomTone(sData->monIconPal, 96, 500, 330, 310);
2019-01-19 18:14:59 +01:00
break;
2020-02-07 18:48:47 +01:00
case MON_ICON_TINT_SEPIA:
TintPalette_SepiaTone(sData->monIconPal, 96);
2019-01-19 23:04:33 +01:00
break;
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
LoadPalette(sData->monIconPal, 80, 192);
2019-01-19 23:04:33 +01:00
2020-02-07 18:48:47 +01:00
for (i = 0; i < PARTY_SIZE; i++)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->trainerCard.monSpecies[i])
LoadBgTiles(3, GetMonIconTiles(sData->trainerCard.monSpecies[i], 0), 512, 16 * i + 32);
2019-01-19 23:04:33 +01:00
}
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void PrintStickersOnCard(void)
2019-01-19 18:14:59 +01:00
{
u8 i;
2020-02-07 18:48:47 +01:00
u8 paletteSlots[4] = {11, 12, 13, 14};
2019-01-20 18:24:35 +01:00
2020-02-07 18:48:47 +01:00
if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.shouldDrawStickers == TRUE)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
for (i = 0; i < TRAINER_CARD_STICKER_TYPES; i++)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
u8 sticker = sData->trainerCard.stickers[i];
if (sData->trainerCard.stickers[i])
WriteSequenceToBgTilemapBuffer(3, i * 4 + 320, i * 3 + 2, 2, 2, 2, paletteSlots[sticker - 1], 1);
2019-01-19 18:14:59 +01:00
}
}
}
2020-02-07 18:48:47 +01:00
static void LoadStickerGfx(void)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
LoadPalette(sTrainerCardSticker1_Pal, 176, 32);
LoadPalette(sTrainerCardSticker2_Pal, 192, 32);
LoadPalette(sTrainerCardSticker3_Pal, 208, 32);
LoadPalette(sTrainerCardSticker4_Pal, 224, 32);
LoadBgTiles(3, sData->stickerTiles, 1024, 128);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void DrawTrainerCardWindow(u8 windowId)
2019-01-19 18:14:59 +01:00
{
PutWindowTilemap(windowId);
CopyWindowToVram(windowId, 3);
}
2019-01-20 18:24:35 +01:00
static u8 SetCardBgsAndPals(void)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
switch (sData->bgPalLoadState)
2019-01-19 18:14:59 +01:00
{
case 0:
2020-02-07 18:48:47 +01:00
LoadBgTiles(3, sData->badgeTiles, ARRAY_COUNT(sData->badgeTiles), 0);
2019-01-19 18:14:59 +01:00
break;
case 1:
2020-02-07 18:48:47 +01:00
LoadBgTiles(0, sData->cardTiles, 0x1800, 0);
2019-01-19 18:14:59 +01:00
break;
case 2:
2019-01-22 21:56:57 +01:00
if (sData->cardType != CARD_TYPE_FRLG)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
LoadPalette(sHoennTrainerCardStarPals[sData->trainerCard.stars], 0, 96);
LoadPalette(sHoennTrainerCardBadges_Pal, 48, 32);
if (sData->trainerCard.gender != MALE)
LoadPalette(sHoennTrainerCardFemaleBg_Pal, 16, 32);
2019-01-19 18:14:59 +01:00
}
else
{
2020-02-07 18:48:47 +01:00
LoadPalette(sKantoTrainerCardStarPals[sData->trainerCard.stars], 0, 96);
LoadPalette(sKantoTrainerCardBadges_Pal, 48, 32);
if (sData->trainerCard.gender != MALE)
LoadPalette(sKantoTrainerCardFemaleBg_Pal, 16, 32);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
LoadPalette(sTrainerCardGold_Pal, 64, 32);
2019-01-19 18:14:59 +01:00
break;
case 3:
2020-02-07 18:48:47 +01:00
SetBgTilemapBuffer(0, sData->cardTilemapBuffer);
SetBgTilemapBuffer(2, sData->bgTilemapBuffer);
2019-01-19 18:14:59 +01:00
break;
case 4:
FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32);
FillBgTilemapBufferRect_Palette0(2, 0, 0, 0, 32, 32);
FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 32, 32);
default:
return 1;
}
2019-01-20 18:24:35 +01:00
sData->bgPalLoadState++;
2019-01-09 03:51:19 +01:00
return 0;
}
2020-02-07 18:48:47 +01:00
static void DrawCardScreenBackground(u16 *ptr)
2019-01-19 23:04:33 +01:00
{
s16 i, j;
2020-02-07 18:48:47 +01:00
u16 *dst = sData->bgTilemapBuffer;
2019-01-19 23:04:33 +01:00
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);
}
2020-02-07 18:48:47 +01:00
static void DrawCardFrontOrBack(u16* ptr)
2019-01-19 23:04:33 +01:00
{
s16 i, j;
2020-02-07 18:48:47 +01:00
u16 *dst = sData->cardTilemapBuffer;
2019-01-19 23:04:33 +01:00
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);
}
2020-02-07 18:48:47 +01:00
static void DrawStarsAndBadgesOnCard(void)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
static const u8 yOffsets[] = {7, 7};
2019-01-19 23:04:33 +01:00
s16 i, x;
u16 tileNum = 192;
u8 palNum = 3;
2020-02-07 18:48:47 +01:00
FillBgTilemapBufferRect(3, 143, 15, yOffsets[sData->isHoenn], sData->trainerCard.stars, 1, 4);
2019-01-20 18:24:35 +01:00
if (!sData->isLink)
2019-01-19 23:04:33 +01:00
{
x = 4;
2020-02-07 18:48:47 +01:00
for (i = 0; i < NUM_BADGES; i++, tileNum += 2, x += 3)
2019-01-19 23:04:33 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->badgeCount[i])
2019-01-19 23:04:33 +01:00
{
FillBgTilemapBufferRect(3, tileNum, x, 15, 1, 1, palNum);
FillBgTilemapBufferRect(3, tileNum + 1, x + 1, 15, 1, 1, palNum);
FillBgTilemapBufferRect(3, tileNum + 16, x, 16, 1, 1, palNum);
FillBgTilemapBufferRect(3, tileNum + 17, x + 1, 16, 1, 1, palNum);
}
}
}
CopyBgTilemapBufferToVram(3);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void DrawCardBackStats(void)
2019-01-19 18:14:59 +01:00
{
2019-01-22 21:56:57 +01:00
if (sData->cardType == CARD_TYPE_FRLG)
2019-01-19 18:14:59 +01:00
{
2019-01-20 18:24:35 +01:00
if (sData->hasTrades)
2019-01-19 18:14:59 +01:00
{
FillBgTilemapBufferRect(3, 141, 27, 9, 1, 1, 1);
FillBgTilemapBufferRect(3, 157, 27, 10, 1, 1, 1);
}
2019-01-22 21:56:57 +01:00
if (sData->trainerCard.berryCrushPoints)
2019-01-19 18:14:59 +01:00
{
FillBgTilemapBufferRect(3, 141, 21, 13, 1, 1, 1);
FillBgTilemapBufferRect(3, 157, 21, 14, 1, 1, 1);
}
2019-01-20 18:24:35 +01:00
if (sData->trainerCard.unionRoomNum)
2019-01-19 18:14:59 +01:00
{
FillBgTilemapBufferRect(3, 141, 27, 11, 1, 1, 1);
FillBgTilemapBufferRect(3, 157, 27, 12, 1, 1, 1);
}
}
else
{
2019-01-20 18:24:35 +01:00
if (sData->hasTrades)
2019-01-19 18:14:59 +01:00
{
FillBgTilemapBufferRect(3, 141, 27, 9, 1, 1, 0);
FillBgTilemapBufferRect(3, 157, 27, 10, 1, 1, 0);
}
2019-01-20 18:24:35 +01:00
if (sData->trainerCard.contestsWithFriends)
2019-01-19 18:14:59 +01:00
{
FillBgTilemapBufferRect(3, 141, 27, 13, 1, 1, 0);
FillBgTilemapBufferRect(3, 157, 27, 14, 1, 1, 0);
}
2019-01-20 18:24:35 +01:00
if (sData->hasBattleTowerWins)
2019-01-19 18:14:59 +01:00
{
FillBgTilemapBufferRect(3, 141, 17, 15, 1, 1, 0);
FillBgTilemapBufferRect(3, 157, 17, 16, 1, 1, 0);
FillBgTilemapBufferRect(3, 140, 27, 15, 1, 1, 0);
FillBgTilemapBufferRect(3, 156, 27, 16, 1, 1, 0);
}
}
CopyBgTilemapBufferToVram(3);
}
2020-02-07 18:48:47 +01:00
static void BlinkTimeColon(void)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
if (++sData->timeColonBlinkTimer > 60)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
sData->timeColonBlinkTimer = 0;
sData->timeColonInvisible ^= 1;
sData->timeColonNeedDraw = TRUE;
2019-01-19 18:14:59 +01:00
}
}
u8 GetTrainerCardStars(u8 cardId)
2019-01-19 18:14:59 +01:00
{
struct TrainerCard* trainerCards = gTrainerCards;
return trainerCards[cardId].stars;
}
2020-02-07 18:48:47 +01:00
#define tFlipState data[0]
2021-03-22 00:54:23 +01:00
#define tCardTop data[1]
2020-02-07 18:48:47 +01:00
static void FlipTrainerCard(void)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
u8 taskId = CreateTask(Task_DoCardFlipTask, 0);
Task_DoCardFlipTask(taskId);
2019-01-20 18:24:35 +01:00
SetHBlankCallback(HblankCb_TrainerCard);
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static bool8 IsCardFlipTaskActive(void)
2019-01-19 18:14:59 +01:00
{
2021-02-20 05:22:26 +01:00
if (FindTaskIdByFunc(Task_DoCardFlipTask) == TASK_NONE)
2019-01-19 18:14:59 +01:00
return TRUE;
2019-01-19 23:04:33 +01:00
else
return FALSE;
2019-01-19 18:14:59 +01:00
}
2020-02-07 18:48:47 +01:00
static void Task_DoCardFlipTask(u8 taskId)
2019-01-19 18:14:59 +01:00
{
2020-02-07 18:48:47 +01:00
while(sTrainerCardFlipTasks[gTasks[taskId].tFlipState](&gTasks[taskId]))
2019-01-19 18:14:59 +01:00
;
}
2020-02-07 18:48:47 +01:00
static bool8 Task_BeginCardFlip(struct Task* task)
2019-01-19 18:14:59 +01:00
{
u32 i;
2019-01-19 23:04:33 +01:00
2019-01-19 18:14:59 +01:00
HideBg(1);
HideBg(3);
ScanlineEffect_Stop();
ScanlineEffect_Clear();
2021-03-22 00:54:23 +01:00
for (i = 0; i < DISPLAY_HEIGHT; i++)
2019-01-19 18:14:59 +01:00
gScanlineEffectRegBuffers[1][i] = 0;
2020-02-07 18:48:47 +01:00
task->tFlipState++;
2019-01-19 18:14:59 +01:00
return FALSE;
}
2019-01-20 18:24:35 +01:00
2021-03-22 00:54:23 +01:00
// Note: Cannot be DISPLAY_HEIGHT / 2, or cardHeight will be 0
#define CARD_FLIP_Y ((DISPLAY_HEIGHT / 2) - 3)
2020-02-07 18:48:47 +01:00
static bool8 Task_AnimateCardFlipDown(struct Task* task)
2019-01-20 18:24:35 +01:00
{
2021-03-22 00:54:23 +01:00
u32 cardHeight, r5, r10, cardTop, r6, var_24, cardBottom, var;
2019-01-20 18:24:35 +01:00
s16 i;
sData->allowDMACopy = FALSE;
2021-03-22 00:54:23 +01:00
if (task->tCardTop >= CARD_FLIP_Y)
task->tCardTop = CARD_FLIP_Y;
2019-01-20 18:24:35 +01:00
else
2021-03-22 00:54:23 +01:00
task->tCardTop += 7;
sData->cardTop = task->tCardTop;
UpdateCardFlipRegs(task->tCardTop);
cardTop = task->tCardTop;
cardBottom = DISPLAY_HEIGHT - cardTop;
cardHeight = cardBottom - cardTop;
r6 = -cardTop << 16;
r5 = (DISPLAY_HEIGHT << 16) / cardHeight;
r5 -= 1 << 16;
2019-01-20 18:24:35 +01:00
var_24 = r6;
2021-03-22 00:54:23 +01:00
var_24 += r5 * cardHeight;
r10 = r5 / cardHeight;
2019-01-20 18:24:35 +01:00
r5 *= 2;
2021-03-22 00:54:23 +01:00
for (i = 0; i < cardTop; i++)
2019-01-20 18:24:35 +01:00
gScanlineEffectRegBuffers[0][i] = -i;
2021-03-22 00:54:23 +01:00
for (; i < (s16)cardBottom; i++)
2019-01-20 18:24:35 +01:00
{
var = r6 >> 16;
r6 += r5;
r5 -= r10;
gScanlineEffectRegBuffers[0][i] = var;
}
var = var_24 >> 16;
2021-03-22 00:54:23 +01:00
for (; i < DISPLAY_HEIGHT; i++)
2019-01-20 18:24:35 +01:00
gScanlineEffectRegBuffers[0][i] = var;
sData->allowDMACopy = TRUE;
2021-03-22 00:54:23 +01:00
if (task->tCardTop >= CARD_FLIP_Y)
2020-02-07 18:48:47 +01:00
task->tFlipState++;
2019-01-20 18:24:35 +01:00
return FALSE;
}
2020-02-07 18:48:47 +01:00
static bool8 Task_DrawFlippedCardSide(struct Task* task)
2019-01-20 18:24:35 +01:00
{
sData->allowDMACopy = FALSE;
2021-03-19 01:35:39 +01:00
if (Overworld_LinkRecvQueueLengthMoreThan2() == TRUE)
2019-01-20 18:24:35 +01:00
return FALSE;
do
{
2020-02-07 18:48:47 +01:00
switch (sData->flipDrawState)
2019-01-20 18:24:35 +01:00
{
case 0:
FillWindowPixelBuffer(1, PIXEL_FILL(0));
2019-01-20 18:24:35 +01:00
FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 0x20, 0x20);
break;
case 1:
2020-02-07 18:48:47 +01:00
if (!sData->onBack)
2019-01-20 18:24:35 +01:00
{
2020-02-07 18:48:47 +01:00
if (!PrintAllOnCardBack())
2019-01-20 18:24:35 +01:00
return FALSE;
}
else
{
2020-02-07 18:48:47 +01:00
if (!PrintAllOnCardFront())
2019-01-20 18:24:35 +01:00
return FALSE;
}
break;
case 2:
2020-02-07 18:48:47 +01:00
if (!sData->onBack)
DrawCardFrontOrBack(sData->backTilemap);
2019-01-20 18:24:35 +01:00
else
2020-02-07 18:48:47 +01:00
DrawTrainerCardWindow(1);
2019-01-20 18:24:35 +01:00
break;
case 3:
2020-02-07 18:48:47 +01:00
if (!sData->onBack)
DrawCardBackStats();
2019-01-20 18:24:35 +01:00
else
FillWindowPixelBuffer(2, PIXEL_FILL(0));
2019-01-20 18:24:35 +01:00
break;
case 4:
2020-02-07 18:48:47 +01:00
if (sData->onBack)
CreateTrainerCardTrainerPic();
2019-01-20 18:24:35 +01:00
break;
default:
2020-02-07 18:48:47 +01:00
task->tFlipState++;
2019-01-20 18:24:35 +01:00
sData->allowDMACopy = TRUE;
2020-02-07 18:48:47 +01:00
sData->flipDrawState = 0;
2019-01-20 18:24:35 +01:00
return FALSE;
}
2020-02-07 18:48:47 +01:00
sData->flipDrawState++;
2019-01-20 18:24:35 +01:00
} while (gReceivedRemoteLinkPlayers == 0);
return FALSE;
}
2020-02-07 18:48:47 +01:00
static bool8 Task_SetCardFlipped(struct Task* task)
2019-01-20 18:24:35 +01:00
{
sData->allowDMACopy = FALSE;
2020-02-07 18:48:47 +01:00
// If on back of card, draw front of card because its being flipped
if (sData->onBack)
2019-01-20 18:24:35 +01:00
{
2020-02-07 18:48:47 +01:00
DrawTrainerCardWindow(2);
DrawCardScreenBackground(sData->bgTilemap);
DrawCardFrontOrBack(sData->frontTilemap);
DrawStarsAndBadgesOnCard();
2019-01-20 18:24:35 +01:00
}
2020-02-07 18:48:47 +01:00
DrawTrainerCardWindow(1);
sData->onBack ^= 1;
task->tFlipState++;
2019-01-20 18:24:35 +01:00
sData->allowDMACopy = TRUE;
2020-08-21 00:02:00 +02:00
PlaySE(SE_RG_CARD_FLIPPING);
2019-01-20 18:24:35 +01:00
return FALSE;
}
2020-02-07 18:48:47 +01:00
static bool8 Task_AnimateCardFlipUp(struct Task* task)
2019-01-20 18:24:35 +01:00
{
2021-03-22 00:54:23 +01:00
u32 cardHeight, r5, r10, cardTop, r6, var_24, cardBottom, var;
2019-01-20 18:24:35 +01:00
s16 i;
sData->allowDMACopy = FALSE;
2021-03-22 00:54:23 +01:00
if (task->tCardTop <= 5)
task->tCardTop = 0;
2019-01-20 18:24:35 +01:00
else
2021-03-22 00:54:23 +01:00
task->tCardTop -= 5;
sData->cardTop = task->tCardTop;
UpdateCardFlipRegs(task->tCardTop);
cardTop = task->tCardTop;
cardBottom = DISPLAY_HEIGHT - cardTop;
cardHeight = cardBottom - cardTop;
r6 = -cardTop << 16;
r5 = (DISPLAY_HEIGHT << 16) / cardHeight;
r5 -= 1 << 16;
2019-01-20 18:24:35 +01:00
var_24 = r6;
2021-03-22 00:54:23 +01:00
var_24 += r5 * cardHeight;
r10 = r5 / cardHeight;
2019-01-20 18:24:35 +01:00
r5 /= 2;
2021-03-22 00:54:23 +01:00
for (i = 0; i < cardTop; i++)
2019-01-20 18:24:35 +01:00
gScanlineEffectRegBuffers[0][i] = -i;
2021-03-22 00:54:23 +01:00
for (; i < (s16)cardBottom; i++)
2019-01-20 18:24:35 +01:00
{
var = r6 >> 16;
r6 += r5;
r5 += r10;
gScanlineEffectRegBuffers[0][i] = var;
}
var = var_24 >> 16;
2021-03-22 00:54:23 +01:00
for (; i < DISPLAY_HEIGHT; i++)
2019-01-20 18:24:35 +01:00
gScanlineEffectRegBuffers[0][i] = var;
sData->allowDMACopy = TRUE;
2021-03-22 00:54:23 +01:00
if (task->tCardTop <= 0)
2020-02-07 18:48:47 +01:00
task->tFlipState++;
2019-01-20 18:24:35 +01:00
return FALSE;
}
2020-02-07 18:48:47 +01:00
static bool8 Task_EndCardFlip(struct Task *task)
2019-01-20 18:24:35 +01:00
{
ShowBg(1);
ShowBg(3);
SetHBlankCallback(NULL);
2020-02-07 18:48:47 +01:00
DestroyTask(FindTaskIdByFunc(Task_DoCardFlipTask));
2019-01-20 18:24:35 +01:00
return FALSE;
}
void ShowPlayerTrainerCard(void (*callback)(void))
{
sData = AllocZeroed(sizeof(*sData));
sData->callback2 = callback;
if (callback == CB2_ReshowFrontierPass)
2020-02-07 18:48:47 +01:00
sData->blendColor = RGB_WHITE;
2019-01-20 18:24:35 +01:00
else
2020-02-07 18:48:47 +01:00
sData->blendColor = RGB_BLACK;
2019-01-20 18:24:35 +01:00
if (InUnionRoom() == TRUE)
sData->isLink = TRUE;
else
sData->isLink = FALSE;
2019-01-22 21:56:57 +01:00
sData->language = GAME_LANGUAGE;
TrainerCard_GenerateCardForLinkPlayer(&sData->trainerCard);
2019-01-20 18:24:35 +01:00
SetMainCallback2(CB2_InitTrainerCard);
}
void ShowTrainerCardInLink(u8 cardId, void (*callback)(void))
{
sData = AllocZeroed(sizeof(*sData));
sData->callback2 = callback;
sData->isLink = TRUE;
sData->trainerCard = gTrainerCards[cardId];
sData->language = gLinkPlayers[cardId].language;
SetMainCallback2(CB2_InitTrainerCard);
}
2020-02-07 18:48:47 +01:00
static void InitTrainerCardData(void)
2019-01-20 18:24:35 +01:00
{
u8 i;
2020-02-07 18:48:47 +01:00
sData->mainState = 0;
sData->timeColonBlinkTimer = gSaveBlock2Ptr->playTimeVBlanks;
sData->timeColonInvisible = FALSE;
sData->onBack = FALSE;
sData->flipBlendY = 0;
2019-01-20 18:24:35 +01:00
sData->cardType = GetSetCardType();
2020-02-07 18:48:47 +01:00
for (i = 0; i < TRAINER_CARD_PROFILE_LENGTH; i++)
CopyEasyChatWord(sData->easyChatProfile[i], sData->trainerCard.easyChatProfile[i]);
2019-01-20 18:24:35 +01:00
}
static u8 GetSetCardType(void)
{
if (sData == NULL)
{
if (gGameVersion == VERSION_FIRE_RED || gGameVersion == VERSION_LEAF_GREEN)
2019-01-22 21:56:57 +01:00
return CARD_TYPE_FRLG;
2019-01-20 18:24:35 +01:00
else if (gGameVersion == VERSION_EMERALD)
return CARD_TYPE_EMERALD;
else
2019-01-22 21:56:57 +01:00
return CARD_TYPE_RS;
2019-01-20 18:24:35 +01:00
}
else
{
if (sData->trainerCard.version == VERSION_FIRE_RED || sData->trainerCard.version == VERSION_LEAF_GREEN)
{
sData->isHoenn = FALSE;
2019-01-22 21:56:57 +01:00
return CARD_TYPE_FRLG;
2019-01-20 18:24:35 +01:00
}
else if (sData->trainerCard.version == VERSION_EMERALD)
{
sData->isHoenn = TRUE;
return CARD_TYPE_EMERALD;
}
else
{
sData->isHoenn = TRUE;
2019-01-22 21:56:57 +01:00
return CARD_TYPE_RS;
2019-01-20 18:24:35 +01:00
}
}
}
static u8 VersionToCardType(u8 version)
{
if (version == VERSION_FIRE_RED || version == VERSION_LEAF_GREEN)
2019-01-22 21:56:57 +01:00
return CARD_TYPE_FRLG;
2019-01-20 18:24:35 +01:00
else if (version == VERSION_EMERALD)
return CARD_TYPE_EMERALD;
else
2019-01-22 21:56:57 +01:00
return CARD_TYPE_RS;
2019-01-20 18:24:35 +01:00
}
2020-02-07 18:48:47 +01:00
static void CreateTrainerCardTrainerPic(void)
2019-01-20 18:24:35 +01:00
{
if (InUnionRoom() == TRUE && gReceivedRemoteLinkPlayers == 1)
{
2020-02-07 18:48:47 +01:00
CreateTrainerCardTrainerPicSprite(FacilityClassToPicIndex(sData->trainerCard.facilityClass),
2019-01-20 18:24:35 +01:00
TRUE,
2020-02-07 18:48:47 +01:00
sTrainerPicOffset[sData->isHoenn][sData->trainerCard.gender][0],
sTrainerPicOffset[sData->isHoenn][sData->trainerCard.gender][1],
2019-01-20 18:24:35 +01:00
8,
2);
}
else
{
2020-02-07 18:48:47 +01:00
CreateTrainerCardTrainerPicSprite(FacilityClassToPicIndex(sTrainerPicFacilityClass[sData->cardType][sData->trainerCard.gender]),
2019-01-20 18:24:35 +01:00
TRUE,
2020-02-07 18:48:47 +01:00
sTrainerPicOffset[sData->isHoenn][sData->trainerCard.gender][0],
sTrainerPicOffset[sData->isHoenn][sData->trainerCard.gender][1],
2019-01-20 18:24:35 +01:00
8,
2);
}
}