Skip large gaps in Pokédex - Pawkkie/Team-Aquas-Asset-Repo GitHub Wiki

By te_on.

If you catch a Pokémon with a high dex number, there's a good chance you'll need to scroll a long ways in the Pokédex before reaching its entry.

dex_large_gap_example

With a few code changes, you can eliminate that giant gap to look like this:

dex_skipped_gap_example

Click here if you just want to see a diff of the changes. Or you can download the patch file here.

Customization

SKIP_TRESHOLD (default 4)

By default, skips will only trigger when there are more than 4 unseen Pokémon between two seen Pokémon. You can change this behavior by changing the value of SKIP_THRESHOLD. The larger the value, the bigger the gap needs to be to trigger a skip.

Vanilla Pokédex

For the regular Emerald Pokédex, you will be modifying src/pokedex.c.

     WIN_VU_METER,
 };
 
+static const u8 sText_TripleBullet[] = _("···");
+
 // For scrolling search parameter
 #define MAX_SEARCH_PARAM_ON_SCREEN   6
 #define MAX_SEARCH_PARAM_CURSOR_POS  (MAX_SEARCH_PARAM_ON_SCREEN - 1)

 #define MAX_MONS_ON_SCREEN 4

 #define LIST_SCROLL_STEP         16
 
+#define SKIP_THRESHOLD           4 // Number of Pokémon to check are unseen before triggering a skip
+#define SHOW_TRIPLE_BULLET       0xFFFE // Used to indicate sText_TripleBullet should be displayed (0xFFFE is an invalid dex number)
+
 #define POKEBALL_ROTATION_TOP    64
 #define POKEBALL_ROTATION_BOTTOM (POKEBALL_ROTATION_TOP - 16)
 static void CreatePokedexList(u8 dexMode, u8 order)
 {
    u32 vars[3]; //I have no idea why three regular variables are stored in an array, but whatever.
 #define temp_dexCount   vars[0]
 #define temp_isHoennDex vars[1]
 #define temp_dexNum     vars[2]
-    s32 i;
+    s32 i, j;
+    u16 monSeen;
 
     sPokedexView->pokemonListCount = 0;
...
     case ORDER_NUMERICAL:
         if (temp_isHoennDex)
         {
-            for (i = 0; i < temp_dexCount; i++)
+            s16 r5;
+            for (i = 0, r5 = 0; i < temp_dexCount; i++)
             {
                 temp_dexNum = HoennToNationalOrder(i + 1);
-                sPokedexView->pokedexList[i].dexNum = temp_dexNum;
-                sPokedexView->pokedexList[i].seen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
-                sPokedexView->pokedexList[i].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
-                if (sPokedexView->pokedexList[i].seen)
-                    sPokedexView->pokemonListCount = i + 1;
+                monSeen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
+                if (!monSeen && i < temp_dexCount - 1 - SKIP_THRESHOLD)
+                {
+                    // Check if the next SKIP_THRESHOLD entries are also unseen
+                    for (j = 1; j <= SKIP_THRESHOLD; j++)
+                    {
+                        if (GetSetPokedexFlag(HoennToNationalOrder(i + j), FLAG_GET_SEEN))
+                            break;
+                    }
+                    if (j == SKIP_THRESHOLD + 1)
+                    {
+                        // Loop until the next seen entry
+                        do
+                        {
+                            i++;
+                            monSeen = GetSetPokedexFlag(HoennToNationalOrder(i + 1), FLAG_GET_SEEN);
+                        } while (!monSeen && i < temp_dexCount - 1);
+                        
+                        temp_dexNum = HoennToNationalOrder(i + 1);
+                        sPokedexView->pokedexList[r5].dexNum = 0;
+                        sPokedexView->pokedexList[r5].seen = FALSE;
+                        sPokedexView->pokedexList[r5].owned = FALSE;
+                        r5++;
+                    }
+                }
+                sPokedexView->pokedexList[r5].dexNum = temp_dexNum;
+                sPokedexView->pokedexList[r5].seen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
+                sPokedexView->pokedexList[r5].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
+                if (sPokedexView->pokedexList[r5].seen)
+                    sPokedexView->pokemonListCount = r5 + 1;
+                r5++;
             }
         }
         else
         {
             s16 r5, r10;
             for (i = 0, r5 = 0, r10 = 0; i < temp_dexCount; i++)
             {
                 temp_dexNum = i + 1;
-                if (GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN))
+                monSeen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
+                if (monSeen)
                     r10 = 1;
                 if (r10)
                 {
+                    if (!monSeen && i < temp_dexCount - 1 - SKIP_THRESHOLD)
+                    {
+                        // Check if the next SKIP_THRESHOLD entries are also unseen
+                        for (j = 1; j <= SKIP_THRESHOLD; j++)
+                        {
+                            if (GetSetPokedexFlag(i + j + 1, FLAG_GET_SEEN))
+                                break;
+                        }
+                        if (j == SKIP_THRESHOLD + 1)
+                        {
+                            // Loop until the next seen entry
+                            while (i < temp_dexCount - 1 && !GetSetPokedexFlag(i + 1, FLAG_GET_SEEN))
+                            {
+                                i++;
+                            }
+                            
+                            temp_dexNum = i + 1;
+                            sPokedexView->pokedexList[r5].dexNum = 0;
+                            sPokedexView->pokedexList[r5].seen = FALSE;
+                            sPokedexView->pokedexList[r5].owned = FALSE;
+                            r5++;
+                        }
+                    }
                     sPokedexView->pokedexList[r5].dexNum = temp_dexNum;
                     sPokedexView->pokedexList[r5].seen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
                     sPokedexView->pokedexList[r5].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
 static void CreateMonListEntry(u8 position, u16 b, u16 ignored)
 {
...
     case 0: // Initial
     default:
...
                 ClearMonListEntry(17, i * 2, ignored);
                 if (sPokedexView->pokedexList[entryNum].seen)
                 {
-                    CreateMonDexNum(entryNum, 0x12, i * 2, ignored);
+                    CreateMonDexNum(entryNum, 0x12, i * 2, FALSE);
                     CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, 0x11, i * 2, ignored);
                     CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, 0x16, i * 2);
                 }
                 else
                 {
-                    CreateMonDexNum(entryNum, 0x12, i * 2, ignored);
+                    CreateMonDexNum(entryNum, 0x12, i * 2, sPokedexView->pokedexList[entryNum].dexNum == 0);
                     CreateCaughtBall(FALSE, 0x11, i * 2, ignored);
-                    CreateMonName(0, 0x16, i * 2);
+                    CreateMonName(sPokedexView->pokedexList[entryNum].dexNum == 0 ? SHOW_TRIPLE_BULLET : 0, 0x16, i * 2);
                 }
             }
             entryNum++;
...
     case 1: // Up
...
             ClearMonListEntry(17, sPokedexView->listVOffset * 2, ignored);
             if (sPokedexView->pokedexList[entryNum].seen)
             {
-                CreateMonDexNum(entryNum, 18, sPokedexView->listVOffset * 2, ignored);
+                CreateMonDexNum(entryNum, 18, sPokedexView->listVOffset * 2, FALSE);
                 CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, 0x11, sPokedexView->listVOffset * 2, ignored);
                 CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, 0x16, sPokedexView->listVOffset * 2);
             }
             else
             {
-                CreateMonDexNum(entryNum, 18, sPokedexView->listVOffset * 2, ignored);
+                CreateMonDexNum(entryNum, 18, sPokedexView->listVOffset * 2, sPokedexView->pokedexList[entryNum].dexNum == 0);
                 CreateCaughtBall(FALSE, 17, sPokedexView->listVOffset * 2, ignored);
-                CreateMonName(0, 0x16, sPokedexView->listVOffset * 2);
+                CreateMonName(sPokedexView->pokedexList[entryNum].dexNum == 0 ? SHOW_TRIPLE_BULLET : 0, 0x16, sPokedexView->listVOffset * 2);
             }
         }
         break;
...
     case 2: // Down
...
             ClearMonListEntry(17, vOffset * 2, ignored);
             if (sPokedexView->pokedexList[entryNum].seen)
             {
-                CreateMonDexNum(entryNum, 18, vOffset * 2, ignored);
+                CreateMonDexNum(entryNum, 18, vOffset * 2, FALSE);
                 CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, 0x11, vOffset * 2, ignored);
                 CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, 0x16, vOffset * 2);
             }
             else
             {
-                CreateMonDexNum(entryNum, 18, vOffset * 2, ignored);
+                CreateMonDexNum(entryNum, 18, vOffset * 2, sPokedexView->pokedexList[entryNum].dexNum == 0);
                 CreateCaughtBall(FALSE, 0x11, vOffset * 2, ignored);
-                CreateMonName(0, 0x16, vOffset * 2);
+                CreateMonName(sPokedexView->pokedexList[entryNum].dexNum == 0 ? SHOW_TRIPLE_BULLET : 0, 0x16, vOffset * 2);
             }
         }
         break;
     }
     CopyWindowToVram(0, COPYWIN_GFX);
 }
-static void CreateMonDexNum(u16 entryNum, u8 left, u8 top, u16 unused)
+static void CreateMonDexNum(u16 entryNum, u8 left, u8 top, u16 skip)
 {
     u8 text[7];
     u16 dexNum, offset = 2;

     dexNum = sPokedexView->pokedexList[entryNum].dexNum;
     if (sPokedexView->dexMode == DEX_MODE_HOENN)
         dexNum = NationalToHoennOrder(dexNum);
-    memcpy(text, sText_No0000, ARRAY_COUNT(sText_No0000));
-    if (NATIONAL_DEX_COUNT > 999 && sPokedexView->dexMode != DEX_MODE_HOENN)
+    if (skip)
     {
-        text[2] = CHAR_0 + dexNum / 1000;
-        offset++;
+        text[0] = EOS;
+    }
+    else
+    {
+        memcpy(text, sText_No0000, ARRAY_COUNT(sText_No0000));
+        if (NATIONAL_DEX_COUNT > 999 && sPokedexView->dexMode != DEX_MODE_HOENN)
+        {
+            text[2] = CHAR_0 + dexNum / 1000;
+            offset++;
+        }
+        text[offset++] = CHAR_0 + (dexNum % 1000) / 100;
+        text[offset++] = CHAR_0 + ((dexNum % 1000) % 100) / 10;
+        text[offset++] = CHAR_0 + ((dexNum % 1000) % 100) % 10;
+        text[offset++] = EOS;
     }
-    text[offset++] = CHAR_0 + (dexNum % 1000) / 100;
-    text[offset++] = CHAR_0 + ((dexNum % 1000) % 100) / 10;
-    text[offset++] = CHAR_0 + ((dexNum % 1000) % 100) % 10;
-    text[offset++] = EOS;
     PrintMonDexNum(0, FONT_NARROW, text, left, top);
 }
 static u8 CreateMonName(u16 num, u8 left, u8 top)
 {
     const u8 *str;
 
-    num = NationalPokedexNumToSpecies(num);
-    if (num)
-        str = GetSpeciesName(num);
+    if (num == SHOW_TRIPLE_BULLET)
+    {
+        str = sText_TripleBullet;
+    }
     else
-        str = sText_TenDashes;
+    {
+        num = NationalPokedexNumToSpecies(num);
+        if (num)
+            str = GetSpeciesName(num);
+        else
+            str = sText_TenDashes;
+    }
     PrintMonName(0, FONT_NARROW, str, left, top);
     return StringLength(str);
 }

HGSS Pokédex

For the HGSS Pokédex, you will be modifying src/pokedex_plus_hgss.c. Changes are very similar to those in src/pokedex.c.

 static const u8 sText_No0000[] = _("0000");
 static const u8 sCaughtBall_Gfx[] = INCBIN_U8("graphics/pokedex/caught_ball.4bpp");
 static const u8 sText_TenDashes[] = _("----------");
+static const u8 sText_TripleBullet[] = _("   ···");
 ALIGNED(4) static const u8 sExpandedPlaceholder_PokedexDescription[] = _("");
 static const u16 sSizeScreenSilhouette_Pal[] = INCBIN_U16("graphics/pokedex/size_silhouette.gbapal");
 #define LIST_SCROLL_STEP         16
 
+#define SKIP_THRESHOLD           4 // Number of Pokémon to check are unseen before triggering a skip
+#define SHOW_TRIPLE_BULLET       0xFFFE // Used to indicate sText_TripleBullet should be displayed (0xFFFE is an invalid dex number)
+
 #define POKEBALL_ROTATION_TOP    64
 #define POKEBALL_ROTATION_BOTTOM (POKEBALL_ROTATION_TOP - 16)
 static void CreatePokedexList(u8 dexMode, u8 order)
 {
     u32 vars[3]; //I have no idea why three regular variables are stored in an array, but whatever.
 #define temp_dexCount   vars[0]
 #define temp_isHoennDex vars[1]
 #define temp_dexNum     vars[2]
-    s16 i;
+    s16 i, j;
+    u16 monSeen;
 
     sPokedexView->pokemonListCount = 0;
...
     case ORDER_NUMERICAL:
         if (temp_isHoennDex)
         {
-            for (i = 0; i < temp_dexCount; i++)
+            s16 r5;
+            for (i = 0, r5 = 0; i < temp_dexCount; i++)
             {
                 temp_dexNum = HoennToNationalOrder(i + 1);
-                sPokedexView->pokedexList[i].dexNum = temp_dexNum;
-                sPokedexView->pokedexList[i].seen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
-                sPokedexView->pokedexList[i].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
-                if (sPokedexView->pokedexList[i].seen)
-                    sPokedexView->pokemonListCount = i + 1;
+                monSeen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
+                if (!monSeen && i < temp_dexCount - 1 - SKIP_THRESHOLD)
+                {
+                    // Check if the next SKIP_THRESHOLD entries are also unseen
+                    for (j = 1; j <= SKIP_THRESHOLD; j++)
+                    {
+                        if (GetSetPokedexFlag(HoennToNationalOrder(i + j), FLAG_GET_SEEN))
+                            break;
+                    }
+                    if (j == SKIP_THRESHOLD + 1)
+                    {
+                        // Loop until the next seen entry
+                        do
+                        {
+                            i++;
+                            monSeen = GetSetPokedexFlag(HoennToNationalOrder(i + 1), FLAG_GET_SEEN);
+                        } while (!monSeen && i < temp_dexCount - 1);
+                        
+                        temp_dexNum = HoennToNationalOrder(i + 1);
+                        sPokedexView->pokedexList[r5].dexNum = 0;
+                        sPokedexView->pokedexList[r5].seen = FALSE;
+                        sPokedexView->pokedexList[r5].owned = FALSE;
+                        r5++;
+                    }
+                }
+                sPokedexView->pokedexList[r5].dexNum = temp_dexNum;
+                sPokedexView->pokedexList[r5].seen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
+                sPokedexView->pokedexList[r5].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
+                if (sPokedexView->pokedexList[r5].seen)
+                    sPokedexView->pokemonListCount = r5 + 1;
+                r5++;
             }
         }
         else
         {
             s16 r5, r10;
             for (i = 0, r5 = 0, r10 = 0; i < temp_dexCount; i++)
             {
                 temp_dexNum = i + 1;
-                if (GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN))
+                monSeen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
+                if (monSeen)
                     r10 = 1;
                 if (r10)
                 {
+                    if (!monSeen && i < temp_dexCount - 1 - SKIP_THRESHOLD)
+                    {
+                        // Check if the next SKIP_THRESHOLD entries are also unseen
+                        for (j = 1; j <= SKIP_THRESHOLD; j++)
+                        {
+                            if (GetSetPokedexFlag(i + j + 1, FLAG_GET_SEEN))
+                                break;
+                        }
+                        if (j == SKIP_THRESHOLD + 1)
+                        {
+                            // Loop until the next seen entry
+                            while (i < temp_dexCount - 1 && !GetSetPokedexFlag(i + 1, FLAG_GET_SEEN))
+                            {
+                                i++;
+                            }
+                            
+                            temp_dexNum = i + 1;
+                            sPokedexView->pokedexList[r5].dexNum = 0;
+                            sPokedexView->pokedexList[r5].seen = FALSE;
+                            sPokedexView->pokedexList[r5].owned = FALSE;
+                            r5++;
+                        }
+                    }
                     sPokedexView->pokedexList[r5].dexNum = temp_dexNum;
                     sPokedexView->pokedexList[r5].seen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
                     sPokedexView->pokedexList[r5].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
 static void CreateMonListEntry(u8 position, u16 b, u16 ignored)
 {
...
     case 0: // Initial
     default:
...
                 ClearMonListEntry(MON_LIST_X, i * 2, ignored);
                 if (sPokedexView->pokedexList[entryNum].seen)
                 {
-                    CreateMonDexNum(entryNum, MON_LIST_X+1, i * 2, ignored);
+                    CreateMonDexNum(entryNum, MON_LIST_X+1, i * 2, FALSE);
                     CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, MON_LIST_X, i * 2, ignored);
                     CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, MON_LIST_X + 5, i * 2);
                 }
                 else
                 {
-                    CreateMonDexNum(entryNum, MON_LIST_X+1, i * 2, ignored);
+                    CreateMonDexNum(entryNum, MON_LIST_X+1, i * 2, sPokedexView->pokedexList[entryNum].dexNum == 0);
                     CreateCaughtBall(FALSE, MON_LIST_X, i * 2, ignored);
-                    CreateMonName(0, MON_LIST_X + 5, i * 2);
+                    CreateMonName(sPokedexView->pokedexList[entryNum].dexNum == 0 ? SHOW_TRIPLE_BULLET : 0, MON_LIST_X + 5, i * 2);
                 }
             }
             entryNum++;
         }
         break;
     case 1: // Up
...
             ClearMonListEntry(MON_LIST_X, sPokedexView->listVOffset * 2, ignored);
             if (sPokedexView->pokedexList[entryNum].seen)
             {
-                CreateMonDexNum(entryNum, MON_LIST_X+1, sPokedexView->listVOffset * 2, ignored);
+                CreateMonDexNum(entryNum, MON_LIST_X+1, sPokedexView->listVOffset * 2, FALSE);
                 CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, MON_LIST_X, sPokedexView->listVOffset * 2, ignored);
                 CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, MON_LIST_X + 5, sPokedexView->listVOffset * 2);
             }
             else
             {
-                CreateMonDexNum(entryNum, MON_LIST_X+1, sPokedexView->listVOffset * 2, ignored);
+                CreateMonDexNum(entryNum, MON_LIST_X+1, sPokedexView->listVOffset * 2, sPokedexView->pokedexList[entryNum].dexNum == 0);
                 CreateCaughtBall(FALSE, MON_LIST_X, sPokedexView->listVOffset * 2, ignored);
-                CreateMonName(0, MON_LIST_X + 5, sPokedexView->listVOffset * 2);
+                CreateMonName(sPokedexView->pokedexList[entryNum].dexNum == 0 ? SHOW_TRIPLE_BULLET : 0, MON_LIST_X + 5, sPokedexView->listVOffset * 2);
             }
         }
         break;
     case 2: // Down
             ClearMonListEntry(MON_LIST_X, vOffset * 2, ignored);
             if (sPokedexView->pokedexList[entryNum].seen)
             {
-                CreateMonDexNum(entryNum, MON_LIST_X+1, vOffset * 2, ignored);
+                CreateMonDexNum(entryNum, MON_LIST_X+1, vOffset * 2, FALSE);
                 CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, MON_LIST_X, vOffset * 2, ignored);
                 CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, MON_LIST_X + 5, vOffset * 2);
             }
             else
             {
-                CreateMonDexNum(entryNum, MON_LIST_X+1, vOffset * 2, ignored);
+                CreateMonDexNum(entryNum, MON_LIST_X+1, vOffset * 2, sPokedexView->pokedexList[entryNum].dexNum == 0);
                 CreateCaughtBall(FALSE, MON_LIST_X, vOffset * 2, ignored);
-                CreateMonName(0, MON_LIST_X + 5, vOffset * 2);
+                CreateMonName(sPokedexView->pokedexList[entryNum].dexNum == 0 ? SHOW_TRIPLE_BULLET : 0, MON_LIST_X + 5, vOffset * 2);
             }
         }
         break;
-static void CreateMonDexNum(u16 entryNum, u8 left, u8 top, u16 unused)
+static void CreateMonDexNum(u16 entryNum, u8 left, u8 top, u16 skip)
 {
     u8 text[5];
     u16 dexNum, offset = 0;

     dexNum = sPokedexView->pokedexList[entryNum].dexNum;
     if (sPokedexView->dexMode == DEX_MODE_HOENN)
         dexNum = NationalToHoennOrder(dexNum);
     memcpy(text, sText_No0000, ARRAY_COUNT(sText_No0000));
-    if (NATIONAL_DEX_COUNT > 999 && sPokedexView->dexMode != DEX_MODE_HOENN)
+    if (skip)
+    {
+        text[offset++] = EOS;
+    }
+    else
     {
-        text[0] = CHAR_0 + dexNum / 1000;
-        offset++;
+        if (NATIONAL_DEX_COUNT > 999 && sPokedexView->dexMode != DEX_MODE_HOENN)
+        {
+            text[0] = CHAR_0 + dexNum / 1000;
+            offset++;
+        }
+        text[offset++] = CHAR_0 + (dexNum % 1000) / 100;
+        text[offset++] = CHAR_0 + ((dexNum % 1000) % 100) / 10;
+        text[offset++] = CHAR_0 + ((dexNum % 1000) % 100) % 10;
+        text[offset++] = EOS;
     }
-    text[offset++] = CHAR_0 + (dexNum % 1000) / 100;
-    text[offset++] = CHAR_0 + ((dexNum % 1000) % 100) / 10;
-    text[offset++] = CHAR_0 + ((dexNum % 1000) % 100) % 10;
-    text[offset++] = EOS;
     PrintMonDexNumAndName(0, FONT_NARROW, text, left, top);
 }
 static u8 CreateMonName(u16 num, u8 left, u8 top)
 {
     const u8 *str;
-
-    num = NationalPokedexNumToSpecies(num);
-    if (num)
-        str = GetSpeciesName(num);
+    if (num == SHOW_TRIPLE_BULLET)
+    {
+        str = sText_TripleBullet;
+    }
     else
-        str = sText_TenDashes;
+    {
+        num = NationalPokedexNumToSpecies(num);
+        if (num)
+            str = GetSpeciesName(num);
+        else
+            str = sText_TenDashes;
+    }
     PrintMonDexNumAndName_2(0, FONT_NARROW, str, left, top);
     return StringLength(str);
 }