diff --git a/graphics/party_menu/bg.bin b/graphics/party_menu/bg.bin index d6ff1114d116..4b7f4aa72c03 100644 Binary files a/graphics/party_menu/bg.bin and b/graphics/party_menu/bg.bin differ diff --git a/graphics/party_menu/bg.png b/graphics/party_menu/bg.png index 15ff74304dd3..ec4d51d70932 100644 Binary files a/graphics/party_menu/bg.png and b/graphics/party_menu/bg.png differ diff --git a/graphics/party_menu/bg_ditto.bin b/graphics/party_menu/bg_ditto.bin new file mode 100644 index 000000000000..7a1fce1faf03 Binary files /dev/null and b/graphics/party_menu/bg_ditto.bin differ diff --git a/include/constants/party_menu.h b/include/constants/party_menu.h index 3a7ad372ffa8..1a1459302f1d 100644 --- a/include/constants/party_menu.h +++ b/include/constants/party_menu.h @@ -17,7 +17,8 @@ #define PARTY_LAYOUT_DOUBLE 1 #define PARTY_LAYOUT_MULTI 2 #define PARTY_LAYOUT_MULTI_SHOWCASE 3 // The layout during the screen that appears just before a multi battle -#define PARTY_LAYOUT_COUNT 4 +#define PARTY_LAYOUT_DITTO 4 +#define PARTY_LAYOUT_COUNT 5 #define KEEP_PARTY_LAYOUT 0xFF #define PARTY_MENU_TYPE_FIELD 0 diff --git a/include/graphics.h b/include/graphics.h index 010e1c8acb80..d3cc240d2424 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -1811,6 +1811,8 @@ extern const u32 gPartyMenuBg_Tilemap[]; extern const u16 gPartyMenuBg_Pal[]; extern const u16 gPartyMenuBg_Pal_Shiny[]; +extern const u32 gPartyMenuBg_DittoTilemap[]; + // berry pics extern const u32 gBerryPic_Cheri[]; extern const u32 gBerryPic_Chesto[]; diff --git a/src/data/party_menu.h b/src/data/party_menu.h index d639c7755825..efcc247081a1 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -59,6 +59,20 @@ static const struct PartyMenuBoxInfoRects sPartyBoxInfoRects[] = }, 77, 4, 64, 16 // Description text }, + [PARTY_BOX_DITTO_STATS] = + { + BlitBitmapToPartyWindow_LeftColumn, + { + //The below are the x, y, width, and height for each of the following info + 4, 2, 40, 13, // Nickname + 4, 22, 32, 8, // Level + 30, 2, 8, 8, // Gender + 25, 22, 24, 8, // HP + 40, 22, 24, 8, // Max HP + 14, 18, 48, 3 // HP bar + }, + 12, 34, 64, 16 // Description text (e.g. NO USE) + }, }; @@ -103,6 +117,15 @@ static const u8 sPartyMenuSpriteCoords[PARTY_LAYOUT_COUNT][PARTY_SIZE][4 * 2] = {104, 106, 106, 116, 136, 115, 102, 113}, {104, 130, 106, 140, 136, 139, 102, 137}, }, + [PARTY_LAYOUT_DITTO] = + { + { 16, 40, 20, 50, 50, 52, 16, 34}, + {104, 18, 108, 28, 136, 27, 102, 25}, + {104, 42, 108, 52, 136, 51, 102, 49}, + {104, 66, 108, 76, 136, 75, 102, 73}, + {104, 90, 108, 100, 136, 99, 102, 97}, + { 16, 80, 76, 99, 20, 110, 16, 74}, + } }; // Used only when both Cancel and Confirm are present @@ -174,13 +197,13 @@ static const struct WindowTemplate sDittoPartyMenuWindowTemplate[] = .paletteNum = 7, .baseBlock = 0x14B, }, - { // Party mon 6 // UNUSED + { // Party mon 6 - Used for Ditto stats .bg = 0, - .tilemapLeft = 12, - .tilemapTop = 13, - .width = 18, - .height = 3, - .paletteNum = 8, + .tilemapLeft = 1, + .tilemapTop = 10, + .width = 10, + .height = 6, + .paletteNum = 3, .baseBlock = 0x181, }, [WIN_MSG] = { @@ -645,14 +668,14 @@ static const struct WindowTemplate sLevelUpStatsWindowTemplate = .baseBlock = 0x2E9, }; -static const struct WindowTemplate sUnusedWindowTemplate1 = +static const struct WindowTemplate sDittoStatsWindowTemplate = { - .bg = 2, - .tilemapLeft = 2, - .tilemapTop = 15, - .width = 27, + .bg = 3, + .tilemapLeft = 1, + .tilemapTop = 11, + .width = 8, .height = 4, - .paletteNum = 14, + .paletteNum = 15, .baseBlock = 0x1DF, }; diff --git a/src/graphics.c b/src/graphics.c index 254109edb139..60f018f04ec4 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1677,6 +1677,8 @@ const u16 gPartyMenuBg_Pal[] = INCBIN_U16("graphics/party_menu/bg.gbapal"); const u16 gPartyMenuBg_Pal_Shiny[] = INCBIN_U16("graphics/party_menu/bg_shiny.gbapal"); const u32 gPartyMenuBg_Tilemap[] = INCBIN_U32("graphics/party_menu/bg.bin.lz"); +const u32 gPartyMenuBg_DittoTilemap[] = INCBIN_U32("graphics/party_menu/bg_ditto.bin.lz"); + const u32 gPartyMenuPokeball_Gfx[] = INCBIN_U32("graphics/party_menu/pokeball.4bpp.lz"); const u32 gPartyMenuPokeballSmall_Gfx[] = INCBIN_U32("graphics/party_menu/pokeball_small.4bpp.lz"); //unused const u16 gPartyMenuPokeball_Pal[] = INCBIN_U16("graphics/party_menu/pokeball.gbapal"); diff --git a/src/party_menu.c b/src/party_menu.c index 3b71e4d0a74d..466e7305a944 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -157,6 +157,7 @@ enum { enum { PARTY_BOX_LEFT_COLUMN, PARTY_BOX_RIGHT_COLUMN, + PARTY_BOX_DITTO_STATS, }; enum { @@ -303,6 +304,7 @@ static void DisplayPartyPokemonDataForWirelessMinigame(u8); static void DisplayPartyPokemonDataForBattlePyramidHeldItem(u8); static bool8 DisplayPartyPokemonDataForMoveTutorOrEvolutionItem(u8); static void DisplayPartyPokemonData(u8); +static void DisplayDittoPokemonData(u8); static void DisplayPartyPokemonNickname(struct Pokemon *, struct PartyMenuBox *, u8); static void DisplayPartyPokemonLevelCheck(struct Pokemon *, struct PartyMenuBox *, u8); static void DisplayPartyPokemonGenderNidoranCheck(struct Pokemon *, struct PartyMenuBox *, u8); @@ -928,7 +930,10 @@ static bool8 AllocPartyMenuBgGfx(void) case 1: if (!IsDma3ManagerBusyWithBgCopy()) { - LZDecompressWram(gPartyMenuBg_Tilemap, sPartyBgTilemapBuffer); + if (PlayerIsDitto()) + LZDecompressWram(gPartyMenuBg_DittoTilemap, sPartyBgTilemapBuffer); + else + LZDecompressWram(gPartyMenuBg_Tilemap, sPartyBgTilemapBuffer); sPartyMenuInternal->data[0]++; } break; @@ -985,18 +990,17 @@ static void FreePartyPointers(void) static void InitPartyMenuBoxes(u8 layout) { - u8 partySize = PlayerIsDitto() ? DITTO_PARTY : PARTY_SIZE; - - sPartyMenuBoxes = Alloc(sizeof(struct PartyMenuBox[partySize])); + sPartyMenuBoxes = Alloc(sizeof(struct PartyMenuBox[PARTY_SIZE])); LoadPartyMenuBoxes(layout); } static void LoadPartyMenuBoxes(u8 layout) { u32 i; - u8 partySize = PlayerIsDitto() ? DITTO_PARTY : PARTY_SIZE; + if (PlayerIsDitto()) + layout = PARTY_LAYOUT_DITTO; - for (i = 0; i < partySize; i++) + for (i = 0; i < PARTY_SIZE; i++) { sPartyMenuBoxes[i].infoRects = &sPartyBoxInfoRects[PARTY_BOX_RIGHT_COLUMN]; sPartyMenuBoxes[i].spriteCoords = sPartyMenuSpriteCoords[layout][i]; @@ -1009,7 +1013,9 @@ static void LoadPartyMenuBoxes(u8 layout) // The first party mon goes in the left column sPartyMenuBoxes[0].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN]; - if (layout == PARTY_LAYOUT_MULTI_SHOWCASE) + if (PlayerIsDitto()) + sPartyMenuBoxes[5].infoRects = &sPartyBoxInfoRects[PARTY_BOX_DITTO_STATS]; + else if (layout == PARTY_LAYOUT_MULTI_SHOWCASE) sPartyMenuBoxes[3].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN]; else if (layout != PARTY_LAYOUT_SINGLE) sPartyMenuBoxes[1].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN]; @@ -1036,6 +1042,10 @@ static void RenderPartyMenuBox(u8 slot) LoadDittoPalette(DITTO_PALSLOT, DITTO_PALETTE_NORMAL); CopyWindowToVram(sPartyMenuBoxes[0].windowId, COPYWIN_GFX); } + else if (PlayerIsDitto() && slot == 5) + { + DisplayDittoPokemonData(slot); + } else if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) == SPECIES_NONE) { DrawEmptySlot(sPartyMenuBoxes[slot].windowId); @@ -1088,6 +1098,16 @@ static void DisplayPartyPokemonData(u8 slot) } } +static void DisplayDittoPokemonData(u8 slot) +{ + DisplayPartyPokemonNickname(&gPlayerParty[0], &sPartyMenuBoxes[slot], 0); + DisplayPartyPokemonLevelCheck(&gPlayerParty[0], &sPartyMenuBoxes[slot], 0); + DisplayPartyPokemonGenderNidoranCheck(&gPlayerParty[0], &sPartyMenuBoxes[slot], 0); + DisplayPartyPokemonHPCheck(&gPlayerParty[0], &sPartyMenuBoxes[slot], 0); + DisplayPartyPokemonMaxHPCheck(&gPlayerParty[0], &sPartyMenuBoxes[slot], 0); + DisplayPartyPokemonHPBarCheck(&gPlayerParty[0], &sPartyMenuBoxes[slot]); +} + static void DisplayPartyPokemonDescriptionData(u8 slot, u8 stringID) { if (PlayerIsDitto() && slot == 0) @@ -1283,7 +1303,8 @@ static void CreatePartyMonSprites(u8 slot) } else if (PlayerIsDitto() && slot == 0) { - return; // Replace with any sprites we want to Animate onto Ditto + CreatePartyMonHeldItemSprite(&gPlayerParty[0], &sPartyMenuBoxes[5]); + CreatePartyMonStatusSprite(&gPlayerParty[0], &sPartyMenuBoxes[5]); } else if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) != SPECIES_NONE) { @@ -2130,16 +2151,21 @@ static void BufferBagFullCantTakeItemMessage(u16 itemUnused) #define tHPToAdd data[3] #define tPartyId data[4] #define tStartHP data[5] +#define tPartySlot data[6] static void Task_PartyMenuModifyHP(u8 taskId) { s16 *data = gTasks[taskId].data; + bool8 drawHpIcon = 1; + + if (PlayerIsDitto() && tPartyId == 0) + drawHpIcon = 3; tHP += tHPIncrement; tHPToAdd--; SetMonData(&gPlayerParty[tPartyId], MON_DATA_HP, &tHP); - DisplayPartyPokemonHPCheck(&gPlayerParty[tPartyId], &sPartyMenuBoxes[tPartyId], 1); - DisplayPartyPokemonHPBarCheck(&gPlayerParty[tPartyId], &sPartyMenuBoxes[tPartyId]); + DisplayPartyPokemonHPCheck(&gPlayerParty[tPartyId], &sPartyMenuBoxes[tPartySlot], drawHpIcon); + DisplayPartyPokemonHPBarCheck(&gPlayerParty[tPartyId], &sPartyMenuBoxes[tPartySlot]); if (tHPToAdd == 0 || tHP == 0 || tHP == tMaxHP) { // If HP was recovered, buffer the amount recovered @@ -2161,6 +2187,11 @@ void PartyMenuModifyHP(u8 taskId, u8 slot, s8 hpIncrement, s16 hpDifference, Tas tHPToAdd = hpDifference; tPartyId = slot; tStartHP = tHP; + tPartySlot = slot; + + if (PlayerIsDitto() && tPartyId == 0) + tPartySlot = 5; + SetTaskFuncWithFollowupFunc(taskId, Task_PartyMenuModifyHP, task); } @@ -2341,13 +2372,13 @@ u8 CanTeachMove(struct Pokemon *mon, u16 move) static void InitPartyMenuWindows(u8 layout) { + if (PlayerIsDitto()) + layout = PARTY_LAYOUT_DITTO; + switch (layout) { case PARTY_LAYOUT_SINGLE: - if (PlayerIsDitto()) - InitWindows(sDittoPartyMenuWindowTemplate); - else - InitWindows(sSinglePartyMenuWindowTemplate); + InitWindows(sSinglePartyMenuWindowTemplate); break; case PARTY_LAYOUT_DOUBLE: InitWindows(sDoublePartyMenuWindowTemplate); @@ -2355,6 +2386,9 @@ static void InitPartyMenuWindows(u8 layout) case PARTY_LAYOUT_MULTI: InitWindows(sMultiPartyMenuWindowTemplate); break; + case PARTY_LAYOUT_DITTO: + InitWindows(sDittoPartyMenuWindowTemplate); + break; default: // PARTY_LAYOUT_MULTI_SHOWCASE InitWindows(sShowcaseMultiPartyMenuWindowTemplate); break; @@ -2670,7 +2704,9 @@ static void DisplayPartyPokemonHPCheck(struct Pokemon *mon, struct PartyMenuBox { if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE) { - if (c != 0) + if (c == 3) + FillWindowPixelRect(menuBox->windowId, PIXEL_FILL(0), 20, 25, 15, 8); + else if (c != 0) menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[12] >> 3, (menuBox->infoRects->dimensions[13] >> 3) + 1, menuBox->infoRects->dimensions[14] >> 3, menuBox->infoRects->dimensions[15] >> 3, FALSE); if (c != 2) DisplayPartyPokemonHP(GetMonData(mon, MON_DATA_HP), GetMonData(mon, MON_DATA_MAX_HP), menuBox); @@ -4889,7 +4925,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task) PlaySE(SE_GLASS_FLUTE); } SetPartyMonAilmentGfx(mon, &sPartyMenuBoxes[gPartyMenu.slotId]); - if (gSprites[sPartyMenuBoxes[gPartyMenu.slotId].statusSpriteId].invisible) + if (gSprites[sPartyMenuBoxes[gPartyMenu.slotId].statusSpriteId].invisible && (!PlayerIsDitto() && gPartyMenu.slotId == 0)) DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[gPartyMenu.slotId], 1); if (canHeal == TRUE) {