Trainer Class Based Poké Balls - pret/pokeemerald GitHub Wiki

Credit to Buffel Saft for posting this in the Simple Modifications Pokecommunity Thread.

This tutorial will implement different trainer classes sending out their Pokemon in different Poke Balls, just like in Gen 7.

First, this will require a new struct to be made in include/battle_main.h:

struct TrainerBall
{
    u8 classId;
    u8 Ball; // make this a u16 if needed
};

Now that we have the struct, we need to pair all the trainer classes to a Poke Ball type. Add this table to src/battle_main.c:

const struct TrainerBall gTrainerBallTable[] = {
    {TRAINER_CLASS_HIKER, ITEM_POKE_BALL},
    {TRAINER_CLASS_TEAM_AQUA, ITEM_NET_BALL},
    {TRAINER_CLASS_PKMN_BREEDER, ITEM_LUXURY_BALL},
    {TRAINER_CLASS_COOLTRAINER, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_BIRD_KEEPER, ITEM_NEST_BALL},
    {TRAINER_CLASS_COLLECTOR, ITEM_REPEAT_BALL},
    {TRAINER_CLASS_SWIMMER_M, ITEM_DIVE_BALL},
    {TRAINER_CLASS_TEAM_MAGMA, ITEM_POKE_BALL},
    {TRAINER_CLASS_EXPERT, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_AQUA_ADMIN, ITEM_GREAT_BALL},
    {TRAINER_CLASS_BLACK_BELT, ITEM_POKE_BALL},
    {TRAINER_CLASS_AQUA_LEADER, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_HEX_MANIAC, ITEM_POKE_BALL},
    {TRAINER_CLASS_AROMA_LADY, ITEM_NET_BALL},
    {TRAINER_CLASS_RUIN_MANIAC, ITEM_POKE_BALL},
    {TRAINER_CLASS_INTERVIEWER, ITEM_TIMER_BALL},
    {TRAINER_CLASS_TUBER_F, ITEM_NET_BALL},
    {TRAINER_CLASS_TUBER_M, ITEM_NET_BALL},
    {TRAINER_CLASS_LADY, ITEM_LUXURY_BALL},
    {TRAINER_CLASS_BEAUTY, ITEM_LUXURY_BALL},
    {TRAINER_CLASS_RICH_BOY, ITEM_LUXURY_BALL},
    {TRAINER_CLASS_POKEMANIAC, ITEM_REPEAT_BALL},
    {TRAINER_CLASS_GUITARIST, ITEM_TIMER_BALL},
    {TRAINER_CLASS_KINDLER, ITEM_POKE_BALL},
    {TRAINER_CLASS_CAMPER, ITEM_NEST_BALL},
    {TRAINER_CLASS_PICNICKER, ITEM_NEST_BALL},
    {TRAINER_CLASS_BUG_MANIAC, ITEM_NET_BALL},
    {TRAINER_CLASS_PSYCHIC, ITEM_POKE_BALL},
    {TRAINER_CLASS_GENTLEMAN, ITEM_LUXURY_BALL},
    {TRAINER_CLASS_ELITE_FOUR, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_LEADER, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_SCHOOL_KID, ITEM_POKE_BALL},
    {TRAINER_CLASS_SR_AND_JR, ITEM_POKE_BALL},
    {TRAINER_CLASS_WINSTRATE, ITEM_GREAT_BALL},
    {TRAINER_CLASS_POKEFAN, ITEM_POKE_BALL},
    {TRAINER_CLASS_YOUNGSTER, ITEM_POKE_BALL},
    {TRAINER_CLASS_CHAMPION, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_FISHERMAN, ITEM_DIVE_BALL},
    {TRAINER_CLASS_TRIATHLETE, ITEM_TIMER_BALL},
    {TRAINER_CLASS_DRAGON_TAMER, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_NINJA_BOY, ITEM_POKE_BALL},
    {TRAINER_CLASS_BATTLE_GIRL, ITEM_POKE_BALL},
    {TRAINER_CLASS_PARASOL_LADY, ITEM_NET_BALL},
    {TRAINER_CLASS_SWIMMER_F, ITEM_DIVE_BALL},
    {TRAINER_CLASS_TWINS, ITEM_REPEAT_BALL},
    {TRAINER_CLASS_SAILOR, ITEM_DIVE_BALL},
    {TRAINER_CLASS_COOLTRAINER_2, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_MAGMA_ADMIN, ITEM_GREAT_BALL},
    {TRAINER_CLASS_RIVAL, ITEM_PREMIER_BALL},
    {TRAINER_CLASS_BUG_CATCHER, ITEM_NET_BALL},
    {TRAINER_CLASS_PKMN_RANGER, ITEM_NEST_BALL},
    {TRAINER_CLASS_MAGMA_LEADER, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_LASS, ITEM_POKE_BALL},
    {TRAINER_CLASS_YOUNG_COUPLE, ITEM_REPEAT_BALL},
    {TRAINER_CLASS_OLD_COUPLE, ITEM_REPEAT_BALL},
    {TRAINER_CLASS_SIS_AND_BRO, ITEM_REPEAT_BALL},
    {TRAINER_CLASS_SALON_MAIDEN, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_DOME_ACE, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_PALACE_MAVEN , ITEM_ULTRA_BALL},
    {TRAINER_CLASS_ARENA_TYCOON, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_FACTORY_HEAD, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_PIKE_QUEEN, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_PYRAMID_KING, ITEM_ULTRA_BALL},
    {TRAINER_CLASS_RS_PROTAG, ITEM_MASTER_BALL},
    {0xFF, ITEM_POKE_BALL},
};

You are free to customize this table to your liking. It contains every trainer class and Poke Ball found in Pokemon Emerald, except for PKMN_TRAINER_1 AND PKMN_TRAINER_2 since they go unused.

Finally, we need to have the trainers use the Poke Balls we defined earlier. In the CreateNPCTrainerParty function of src/battle_main.c, add the following:

                 for (j = 0; j < MAX_MON_MOVES; j++)
                 {
                     SetMonData(&party[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]);
                     SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp);
                 }
                 break;
             }
             }
+            for (j = 0; gTrainerBallTable[j].classId != 0xFF; j++)
+            {
+                if (gTrainerBallTable[j].classId == gTrainers[trainerNum].trainerClass)
+                    break;
+            }
+            SetMonData(&party[i], MON_DATA_POKEBALL, &gTrainerBallTable[j].Ball);
         }
 
         gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;
     }
 
     return gTrainers[trainerNum].partySize;
 }

And that's it!