Repository navigation
Add New Pokeballs From Sinnoh
This code adds the balls from Sinnoh, Unova and Alola:
ITEM_HEAL_BALL, ITEM_DUSK_BALL, ITEM_QUICK_BALL, ITEM_PARK_BALL, ITEM_CHERISH_BALL, ITEM_DREAM_BALL and ITEM_BEAST_BALL
Credits:
All of this code comes from emerald-expansion, HnS / heart n soul, pokeemerald-worped, crystal dust, and emerald++
Ball effects:
Heal Ball - heals the pokemon on being added to party or sent to box; x1 ball multiplier at all times.
Dusk Ball - between 8pm and 3am or in a map classed as a cave/underground, ball has x3.5 multiplier; otherwise x1 ball multiplier.
Quick Ball - on 1st turn only has x4 ball multiplier; otherwise x1 ball multiplier.
Park Ball - will only catch a pokemon when the Map Type = MAP_TYPE_UNKNOWN, otherwise will NOT catch; x1 ball multiplier at all times. (intended to be used in a "Pal Park"-type area or another Safari Zone and not be available anywhere else).
Cherish Ball - will NOT catch any pokemon no matter what, ever. (intended to be used as a ball for gift pokemon in a "mystery gift"-type pokemon and not be available anywhere else. change ballMultiplier = 0; to any number greater than 0 to make it able to catch pokemon).
Dream Ball - if the wild pokemon is asleep, ball has x5 ball catch multiplier; otherwise x1 ball multiplier.
Beast Ball - if the ultra beasts are added to your decomp, then ball has x5 ball multiplier with a x0.1 multiplier for non-Ultra Beast pokemon. if the ultra beasts are NOT in your decomp, the ball will instead work on Johto Beasts and multiply their catch rate by 30 with a x1.5 ball multiplier, or a x0.1 multiplier for all non-Johto Beast pokemon.
How to change ball multipliers:
change ballMultiplier to any 2 or 3 digit number (up to a maximum 255)
eg: ballMultiplier = 75; will give a 7.5x ball catch multiplier
How To Use:
pull from this branch, or add manually using the guide below.
git remote add tenaya15 https://github.com/tenaya15/tenaya15emerald.git
git pull tenaya15 sinnoh_balls
first download this zip file sinnoh_balls.zip
Extract the graphics folder to your decomp/hack root folder
near the top of filein function gBattlescriptsForBallThrow::
add after .4byte BattleScript_BallThrow @ ITEM_PREMIER_BALL
.4byte BattleScript_BallThrow @ ITEM_HEAL_BALL
.4byte BattleScript_BallThrow @ ITEM_DUSK_BALL
.4byte BattleScript_BallThrow @ ITEM_QUICK_BALL
.4byte BattleScript_BallThrow @ ITEM_PARK_BALL
.4byte BattleScript_BallThrow @ ITEM_CHERISH_BALL
.4byte BattleScript_BallThrow @ ITEM_DREAM_BALL
.4byte BattleScript_BallThrow @ ITEM_BEAST_BALL
there are two versions of changes for this file depending if you have an up-to-date pret decomp or not. Only use one of the options for this file.
Option 1: IF YOU HAVE LATEST VERSION THAT USES enum
add to the enum section at the top of the file after ITEM_PREMIER_BALL:
ITEM_HEAL_BALL,
ITEM_DUSK_BALL,
ITEM_QUICK_BALL,
ITEM_PARK_BALL,
ITEM_CHERISH_BALL,
ITEM_DREAM_BALL,
ITEM_BEAST_BALL,
then delete the following lines from inside the same section:
ITEM_034,
ITEM_035,
ITEM_036,
ITEM_037,
ITEM_038,
ITEM_039,
ITEM_03A,
__
then change #define LAST_BALL ITEM_PREMIER_BALL near the end of the file to:
#define LAST_BALL ITEM_BEAST_BALL
__
Option 2: IF YOUR VERSION STILL USES #define FOR ITEMS
we are replacing 7 unused items so this will require moving some items down
NOTE: If you have already added new items to your hack, you will need to manually adjust the below numbers to take into consideration these new items
delete lines
#define ITEM_034 52
#define ITEM_035 53
#define ITEM_036 54
#define ITEM_037 55
#define ITEM_038 56
#define ITEM_039 57
#define ITEM_03A 58
add the following after #define ITEM_PREMIER_BALL 12
#define ITEM_HEAL_BALL 13
#define ITEM_DUSK_BALL 14
#define ITEM_QUICK_BALL 15
#define ITEM_PARK_BALL 16
#define ITEM_CHERISH_BALL 17
#define ITEM_DREAM_BALL 18
#define ITEM_BEAST_BALL 19
// Note: If moving ball IDs around, updating FIRST_BALL/LAST_BALL is not sufficient
// Several places expect the ball IDs to be first and contiguous (e.g. gBattlescriptsForBallThrow and MON_DATA_POKEBALL)
// If adding new balls, it's easiest to insert them after the last ball and increment the below IDs (and removing ITEM_034 for example)
#define FIRST_BALL ITEM_MASTER_BALL
#define LAST_BALL ITEM_BEAST_BALL
// Pokémon Items
#define ITEM_POTION 20
#define ITEM_ANTIDOTE 21
#define ITEM_BURN_HEAL 22
#define ITEM_ICE_HEAL 23
#define ITEM_AWAKENING 24
#define ITEM_PARALYZE_HEAL 25
#define ITEM_FULL_RESTORE 26
#define ITEM_MAX_POTION 27
#define ITEM_HYPER_POTION 28
#define ITEM_SUPER_POTION 29
#define ITEM_FULL_HEAL 30
#define ITEM_REVIVE 31
#define ITEM_MAX_REVIVE 32
#define ITEM_FRESH_WATER 33
#define ITEM_SODA_POP 34
#define ITEM_LEMONADE 35
#define ITEM_MOOMOO_MILK 36
#define ITEM_ENERGY_POWDER 37
#define ITEM_ENERGY_ROOT 38
#define ITEM_HEAL_POWDER 39
#define ITEM_REVIVAL_HERB 40
#define ITEM_ETHER 41
#define ITEM_MAX_ETHER 42
#define ITEM_ELIXIR 43
#define ITEM_MAX_ELIXIR 44
#define ITEM_LAVA_COOKIE 45
#define ITEM_BLUE_FLUTE 46
#define ITEM_YELLOW_FLUTE 47
#define ITEM_RED_FLUTE 48
#define ITEM_BLACK_FLUTE 49
#define ITEM_WHITE_FLUTE 50
#define ITEM_BERRY_JUICE 51
#define ITEM_SACRED_ASH 52
#define ITEM_SHOAL_SALT 53
#define ITEM_SHOAL_SHELL 54
#define ITEM_RED_SHARD 55
#define ITEM_BLUE_SHARD 56
#define ITEM_YELLOW_SHARD 57
#define ITEM_GREEN_SHARD 58
add to the end of file, before #endif //GUARD_GRAPHICS_H
// new balls in battle
extern const u32 gBallGfx_Heal[];
extern const u32 gBallPal_Heal[];
extern const u32 gBallGfx_Dusk[];
extern const u32 gBallPal_Dusk[];
extern const u32 gBallGfx_Quick[];
extern const u32 gBallPal_Quick[];
extern const u32 gBallGfx_Park[];
extern const u32 gBallPal_Park[];
extern const u32 gBallGfx_Cherish[];
extern const u32 gBallPal_Cherish[];
extern const u32 gBallGfx_Dream[];
extern const u32 gBallPal_Dream[];
extern const u32 gBallGfx_Beast[];
extern const u32 gBallPal_Beast[];
//new ball items
extern const u32 gItemIcon_HealBall[];
extern const u32 gItemIconPalette_HealBall[];
extern const u32 gItemIcon_DuskBall[];
extern const u32 gItemIconPalette_DuskBall[];
extern const u32 gItemIcon_QuickBall[];
extern const u32 gItemIconPalette_QuickBall[];
extern const u32 gItemIcon_ParkBall[];
extern const u32 gItemIconPalette_ParkBall[];
extern const u32 gItemIcon_CherishBall[];
extern const u32 gItemIconPalette_CherishBall[];
extern const u32 gItemIcon_DreamBall[];
extern const u32 gItemIconPalette_DreamBall[];
extern const u32 gItemIcon_BeastBall[];
extern const u32 gItemIconPalette_BeastBall[];
add to the first enum section, after line BALL_PREMIER, and before line POKEBALL_COUNT
BALL_HEAL,
BALL_DUSK,
BALL_QUICK,
BALL_PARK,
BALL_CHERISH,
BALL_DREAM,
BALL_BEAST,
IMPORTANT NOTE: there are two versions to this step depending if you have an up-to-date pokeemerald decomp that uses INCGFX or an older one that still uses INCBIN.
IF YOU HAVE AN UP-TO-DATE VERSION THAT USES INCGFX
add to the end of the file:
// new pokeballs
const u32 gItemIcon_HealBall[] = INCGFX_U32("graphics/items/icons/heal_ball.png", ".4bpp.lz");
const u32 gItemIconPalette_HealBall[] = INCGFX_U32("graphics/items/icon_palettes/heal_ball.pal", ".gbapal.lz");
const u32 gItemIcon_DuskBall[] = INCGFX_U32("graphics/items/icons/dusk_ball.png", ".4bpp.lz");
const u32 gItemIconPalette_DuskBall[] = INCGFX_U32("graphics/items/icon_palettes/dusk_ball.pal", ".gbapal.lz");
const u32 gItemIcon_QuickBall[] = INCGFX_U32("graphics/items/icons/quick_ball.png", ".4bpp.lz");
const u32 gItemIconPalette_QuickBall[] = INCGFX_U32("graphics/items/icon_palettes/quick_ball.pal", ".gbapal.lz");
const u32 gItemIcon_ParkBall[] = INCGFX_U32("graphics/items/icons/park_ball.png", ".4bpp.lz");
const u32 gItemIconPalette_ParkBall[] = INCGFX_U32("graphics/items/icon_palettes/park_ball.pal", ".gbapal.lz");
const u32 gItemIcon_CherishBall[] = INCGFX_U32("graphics/items/icons/cherish_ball.png", ".4bpp.lz");
const u32 gItemIconPalette_CherishBall[] = INCGFX_U32("graphics/items/icon_palettes/cherish_ball.pal", ".gbapal.lz");
const u32 gItemIcon_DreamBall[] = INCGFX_U32("graphics/items/icons/dream_ball.png", ".4bpp.lz");
const u32 gItemIconPalette_DreamBall[] = INCGFX_U32("graphics/items/icon_palettes/dream_ball.pal", ".gbapal.lz");
const u32 gItemIcon_BeastBall[] = INCGFX_U32("graphics/items/icons/beast_ball.png", ".4bpp.lz");
const u32 gItemIconPalette_BeastBall[] = INCGFX_U32("graphics/items/icon_palettes/beast_ball.pal", ".gbapal.lz");
OR
IF YOU HAVE AN OLDER VERSION THAT STILL USES INCBIN
add to the end of the file:
const u32 gItemIcon_HealBall[] = INCBIN_U32("graphics/items/icons/heal_ball.4bpp.lz");
const u32 gItemIconPalette_HealBall[] = INCBIN_U32("graphics/items/icon_palettes/heal_ball.gbapal.lz");
const u32 gItemIcon_DuskBall[] = INCBIN_U32("graphics/items/icons/dusk_ball.4bpp.lz");
const u32 gItemIconPalette_DuskBall[] = INCBIN_U32("graphics/items/icon_palettes/dusk_ball.gbapal.lz");
const u32 gItemIcon_QuickBall[] = INCBIN_U32("graphics/items/icons/quick_ball.4bpp.lz");
const u32 gItemIconPalette_QuickBall[] = INCBIN_U32("graphics/items/icon_palettes/quick_ball.gbapal.lz");
const u32 gItemIcon_ParkBall[] = INCBIN_U32("graphics/items/icons/park_ball.4bpp.lz");
const u32 gItemIconPalette_ParkBall[] = INCBIN_U32("graphics/items/icon_palettes/park_ball.gbapal.lz");
const u32 gItemIcon_CherishBall[] = INCBIN_U32("graphics/items/icons/cherish_ball.4bpp.lz");
const u32 gItemIconPalette_CherishBall[] = INCBIN_U32("graphics/items/icon_palettes/cherish_ball.gbapal.lz");
const u32 gItemIcon_DreamBall[] = INCBIN_U32("graphics/items/icons/dream_ball.4bpp.lz");
const u32 gItemIconPalette_DreamBall[] = INCBIN_U32("graphics/items/icon_palettes/dream_ball.gbapal.lz");
const u32 gItemIcon_BeastBall[] = INCBIN_U32("graphics/items/icons/beast_ball.4bpp.lz");
const u32 gItemIconPalette_BeastBall[] = INCBIN_U32("graphics/items/icon_palettes/beast_ball.gbapal.lz");
IMPORTANT NOTE: there are two versions to this step depending if you have an up-to-date pokeemerald decomp that uses INCGFX or an older one that still uses INCBIN.
IF YOU HAVE AN UP-TO-DATE VERSION THAT USES INCGFX
add to the end of file:
//new pokeballs
const u32 gBallGfx_Heal[] = INCGFX_U32("graphics/balls/heal.png", ".4bpp.lz");
const u32 gBallPal_Heal[] = INCGFX_U32("graphics/balls/heal.png", ".gbapal.lz");
const u32 gBallGfx_Dusk[] = INCGFX_U32("graphics/balls/dusk.png", ".4bpp.lz");
const u32 gBallPal_Dusk[] = INCGFX_U32("graphics/balls/dusk.png", ".gbapal.lz");
const u32 gBallGfx_Quick[] = INCGFX_U32("graphics/balls/quick.png", ".4bpp.lz");
const u32 gBallPal_Quick[] = INCGFX_U32("graphics/balls/quick.png", ".gbapal.lz");
const u32 gBallGfx_Park[] = INCGFX_U32("graphics/balls/park.png", ".4bpp.lz");
const u32 gBallPal_Park[] = INCGFX_U32("graphics/balls/park.png", ".gbapal.lz");
const u32 gBallGfx_Cherish[] = INCGFX_U32("graphics/balls/cherish.png", ".4bpp.lz");
const u32 gBallPal_Cherish[] = INCGFX_U32("graphics/balls/cherish.png", ".gbapal.lz");
const u32 gBallGfx_Dream[] = INCGFX_U32("graphics/balls/dream.png", ".4bpp.lz");
const u32 gBallPal_Dream[] = INCGFX_U32("graphics/balls/dream.png", ".gbapal.lz");
const u32 gBallGfx_Beast[] = INCGFX_U32("graphics/balls/beast.png", ".4bpp.lz");
const u32 gBallPal_Beast[] = INCGFX_U32("graphics/balls/beast.png", ".gbapal.lz");
OR
IF YOU HAVE AN OLDER VERSION THAT STILL USES INCBIN
add to the end of the file:
const u32 gBallGfx_Heal[] = INCBIN_U32("graphics/balls/heal.4bpp.lz");
const u32 gBallPal_Heal[] = INCBIN_U32("graphics/balls/heal.gbapal.lz");
const u32 gBallGfx_Dusk[] = INCBIN_U32("graphics/balls/dusk.4bpp.lz");
const u32 gBallPal_Dusk[] = INCBIN_U32("graphics/balls/dusk.gbapal.lz");
const u32 gBallGfx_Quick[] = INCBIN_U32("graphics/balls/quick.4bpp.lz");
const u32 gBallPal_Quick[] = INCBIN_U32("graphics/balls/quick.gbapal.lz");
const u32 gBallGfx_Park[] = INCBIN_U32("graphics/balls/park.4bpp.lz");
const u32 gBallPal_Park[] = INCBIN_U32("graphics/balls/park.gbapal.lz");
const u32 gBallGfx_Cherish[] = INCBIN_U32("graphics/balls/cherish.4bpp.lz");
const u32 gBallPal_Cherish[] = INCBIN_U32("graphics/balls/cherish.gbapal.lz");
const u32 gBallGfx_Dream[] = INCBIN_U32("graphics/balls/dream.4bpp.lz");
const u32 gBallPal_Dream[] = INCBIN_U32("graphics/balls/dream.gbapal.lz");
const u32 gBallGfx_Beast[] = INCBIN_U32("graphics/balls/beast.4bpp.lz");
const u32 gBallPal_Beast[] = INCBIN_U32("graphics/balls/beast.gbapal.lz");
add to the end of the file:
// new pokeballs
static const u8 sHealBallDesc[] = _(
"A remedial ball\n"
"that restores\n"
"caught Pokémon.");
static const u8 sDuskBallDesc[] = _(
"A ball that works\n"
"better at night\n"
"or in dark places.");
static const u8 sQuickBallDesc[] = _(
"A ball that works\n"
"better at the\n"
"start of a battle.");
static const u8 sParkBallDesc[] = _(
"A special ball\n"
"used only in\n"
"the Pal Park.");
static const u8 sCherishBallDesc[] = _(
"A rare ball crafted\n"
"to commemorate a\n"
"special occasion.");
static const u8 sDreamBallDesc[] = _(
"A ball that works\n"
"better on Pokémon\n"
"that are asleep");
static const u8 sBeastBallDesc[] = _(
"A special ball\n"
"designed to catch\n"
"Ultra Beasts.");
NOTE: if you have already added new items to your hack, you may already have deleted some of the lines below
add after [ITEM_PREMIER_BALL] = {gItemIcon_PremierBall, gItemIconPalette_LuxuryBall},
// new pokeballs
[ITEM_HEAL_BALL] = {gItemIcon_HealBall, gItemIconPalette_HealBall},
[ITEM_DUSK_BALL] = {gItemIcon_DuskBall, gItemIconPalette_DuskBall},
[ITEM_QUICK_BALL] = {gItemIcon_QuickBall, gItemIconPalette_QuickBall},
[ITEM_PARK_BALL] = {gItemIcon_ParkBall, gItemIconPalette_ParkBall},
[ITEM_CHERISH_BALL] = {gItemIcon_CherishBall, gItemIconPalette_CherishBall},
[ITEM_DREAM_BALL] = {gItemIcon_DreamBall, gItemIconPalette_DreamBall},
[ITEM_BEAST_BALL] = {gItemIcon_BeastBall, gItemIconPalette_BeastBall},
then delete these lines
// ????????
[ITEM_034] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark},
[ITEM_035] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark},
[ITEM_036] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark},
[ITEM_037] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark},
[ITEM_038] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark},
[ITEM_039] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark},
[ITEM_03A] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark},
add after the section for [ITEM_PREMIER_BALL] = (around line 171)
[ITEM_HEAL_BALL] =
{
.name = _("HEAL BALL"),
.itemId = ITEM_HEAL_BALL,
.price = 1000,
.description = sHealBallDesc,
.pocket = POCKET_POKE_BALLS,
.type = ITEM_HEAL_BALL - FIRST_BALL,
.battleUsage = ITEM_B_USE_OTHER,
.battleUseFunc = ItemUseInBattle_PokeBall,
.secondaryId = ITEM_HEAL_BALL - FIRST_BALL,
},
[ITEM_DUSK_BALL] =
{
.name = _("DUSK BALL"),
.itemId = ITEM_DUSK_BALL,
.price = 1000,
.description = sDuskBallDesc,
.pocket = POCKET_POKE_BALLS,
.type = ITEM_DUSK_BALL - FIRST_BALL,
.battleUsage = ITEM_B_USE_OTHER,
.battleUseFunc = ItemUseInBattle_PokeBall,
.secondaryId = ITEM_DUSK_BALL - FIRST_BALL,
},
[ITEM_QUICK_BALL] =
{
.name = _("QUICK BALL"),
.itemId = ITEM_QUICK_BALL,
.price = 1000,
.description = sQuickBallDesc,
.pocket = POCKET_POKE_BALLS,
.type = ITEM_QUICK_BALL - FIRST_BALL,
.battleUsage = ITEM_B_USE_OTHER,
.battleUseFunc = ItemUseInBattle_PokeBall,
.secondaryId = ITEM_QUICK_BALL - FIRST_BALL,
},
[ITEM_PARK_BALL] =
{
.name = _("PARK BALL"),
.itemId = ITEM_PARK_BALL,
.price = 1000,
.description = sParkBallDesc,
.pocket = POCKET_POKE_BALLS,
.type = ITEM_PARK_BALL - FIRST_BALL,
.battleUsage = ITEM_B_USE_OTHER,
.battleUseFunc = ItemUseInBattle_PokeBall,
.secondaryId = ITEM_PARK_BALL - FIRST_BALL,
},
[ITEM_CHERISH_BALL] =
{
.name = _("CHERISH BALL"),
.itemId = ITEM_CHERISH_BALL,
.price = 100000,
.description = sCherishBallDesc,
.pocket = POCKET_POKE_BALLS,
.type = ITEM_USE_PARTY_MENU,
.battleUsage = ITEM_B_USE_OTHER,
.battleUseFunc = ItemUseInBattle_PokeBall,
.secondaryId = ITEM_CHERISH_BALL - FIRST_BALL,
},
[ITEM_DREAM_BALL] =
{
.name = _("DREAM BALL"),
.itemId = ITEM_DREAM_BALL,
.price = 1000,
.description = sDreamBallDesc,
.pocket = POCKET_POKE_BALLS,
.type = ITEM_DREAM_BALL - FIRST_BALL,
.battleUsage = ITEM_B_USE_OTHER,
.battleUseFunc = ItemUseInBattle_PokeBall,
.secondaryId = ITEM_DREAM_BALL - FIRST_BALL,
},
[ITEM_BEAST_BALL] =
{
.name = _("BEAST BALL"),
.itemId = ITEM_BEAST_BALL,
.price = 10000,
.description = sBeastBallDesc,
.pocket = POCKET_POKE_BALLS,
.type = ITEM_BEAST_BALL - FIRST_BALL,
.battleUsage = ITEM_B_USE_OTHER,
.battleUseFunc = ItemUseInBattle_PokeBall,
.secondaryId = ITEM_BEAST_BALL - FIRST_BALL,
},
/* Use if Cherish Ball is to be used as a Key Item instead and remove the above entry
[ITEM_CHERISH_BALL] =
{
.name = _("CHERISH BALL"),
.itemId = ITEM_CHERISH_BALL,
.price = 0,
.description = sCherishBallDesc,
.importance = 1,
.pocket = POCKET_KEY_ITEMS,
.type = ITEM_USE_BAG_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
},
*/
add after #define TAG_PARTICLES_PREMIERBALL 55031 (around line 141)
#define TAG_PARTICLES_HEALBALL 55032
#define TAG_PARTICLES_DUSKBALL 55033
#define TAG_PARTICLES_QUICKBALL 55034
#define TAG_PARTICLES_PARKBALL 55035
#define TAG_PARTICLES_CHERISHBALL 55036
#define TAG_PARTICLES_DREAMBALL 55037
#define TAG_PARTICLES_BEASTBALL 55038
__
in function static const struct CompressedSpriteSheet sBallParticleSpriteSheets[POKEBALL_COUNT] =
add after [BALL_PREMIER] = {gBattleAnimSpriteGfx_Particles, 0x100, TAG_PARTICLES_PREMIERBALL},
[BALL_HEAL] = {gBattleAnimSpriteGfx_Particles, 0x100, TAG_PARTICLES_HEALBALL},
[BALL_DUSK] = {gBattleAnimSpriteGfx_Particles, 0x100, TAG_PARTICLES_DUSKBALL},
[BALL_QUICK] = {gBattleAnimSpriteGfx_Particles, 0x100, TAG_PARTICLES_QUICKBALL},
[BALL_PARK] = {gBattleAnimSpriteGfx_Particles, 0x100, TAG_PARTICLES_PARKBALL},
[BALL_CHERISH] = {gBattleAnimSpriteGfx_Particles, 0x100, TAG_PARTICLES_CHERISHBALL},
[BALL_DREAM] = {gBattleAnimSpriteGfx_Particles, 0x100, TAG_PARTICLES_DREAMBALL},
[BALL_BEAST] = {gBattleAnimSpriteGfx_Particles, 0x100, TAG_PARTICLES_BEASTBALL},
__
in function static const struct CompressedSpritePalette sBallParticlePalettes[POKEBALL_COUNT] =
add after [BALL_PREMIER] = {gBattleAnimSpritePal_CircleImpact, TAG_PARTICLES_PREMIERBALL},
[BALL_HEAL] = {gBattleAnimSpritePal_CircleImpact, TAG_PARTICLES_HEALBALL},
[BALL_DUSK] = {gBattleAnimSpritePal_CircleImpact, TAG_PARTICLES_DUSKBALL},
[BALL_QUICK] = {gBattleAnimSpritePal_CircleImpact, TAG_PARTICLES_QUICKBALL},
[BALL_PARK] = {gBattleAnimSpritePal_CircleImpact, TAG_PARTICLES_PARKBALL},
[BALL_CHERISH] = {gBattleAnimSpritePal_CircleImpact, TAG_PARTICLES_CHERISHBALL},
[BALL_DREAM] = {gBattleAnimSpritePal_CircleImpact, TAG_PARTICLES_DREAMBALL},
[BALL_BEAST] = {gBattleAnimSpritePal_CircleImpact, TAG_PARTICLES_BEASTBALL},
__
in function static const u8 sBallParticleAnimNums[POKEBALL_COUNT] =
add after [BALL_PREMIER] = 4,
[BALL_HEAL] = 3,
[BALL_DUSK] = 5,
[BALL_QUICK] = 2,
[BALL_PARK] = 4,
[BALL_CHERISH] = 5,
[BALL_DREAM] = 5,
[BALL_BEAST] = 5,
note: the numbers determine which animation it will use from the section above it (0 = sAnim_RegularBall, 1 = sAnim_MasterBall, 2 = sAnim_NetDiveBall, 3 = sAnim_NestBall, 4 = sAnim_LuxuryPremierBall, 5= sAnim_UltraRepeatTimerBall,)
__
in function static const TaskFunc sBallParticleAnimationFuncs[POKEBALL_COUNT] =
add after [BALL_PREMIER] = PremierBallOpenParticleAnimation,
[BALL_HEAL] = PokeBallOpenParticleAnimation,
[BALL_DUSK] = UltraBallOpenParticleAnimation,
[BALL_QUICK] = UltraBallOpenParticleAnimation,
[BALL_PARK] = UltraBallOpenParticleAnimation,
[BALL_CHERISH] = MasterBallOpenParticleAnimation,
[BALL_DREAM] = UltraBallOpenParticleAnimation,
[BALL_BEAST] = UltraBallOpenParticleAnimation,
NOTE: feel free to change the open particle animations around and experiment with different combinations __
in function static const struct SpriteTemplate sBallParticleSpriteTemplates[POKEBALL_COUNT] =
add after the final section [BALL_PREMIER] = { ... },
[BALL_HEAL] = {
.tileTag = TAG_PARTICLES_HEALBALL,
.paletteTag = TAG_PARTICLES_HEALBALL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = sAnims_BallParticles,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
[BALL_DUSK] = {
.tileTag = TAG_PARTICLES_DUSKBALL,
.paletteTag = TAG_PARTICLES_DUSKBALL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = sAnims_BallParticles,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
[BALL_QUICK] = {
.tileTag = TAG_PARTICLES_QUICKBALL,
.paletteTag = TAG_PARTICLES_QUICKBALL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = sAnims_BallParticles,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
[BALL_PARK] = {
.tileTag = TAG_PARTICLES_PARKBALL,
.paletteTag = TAG_PARTICLES_PARKBALL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = sAnims_BallParticles,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
[BALL_CHERISH] = {
.tileTag = TAG_PARTICLES_CHERISHBALL,
.paletteTag = TAG_PARTICLES_CHERISHBALL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = sAnims_BallParticles,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
[BALL_DREAM] = {
.tileTag = TAG_PARTICLES_DREAMBALL,
.paletteTag = TAG_PARTICLES_DREAMBALL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = sAnims_BallParticles,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
[BALL_BEAST] = {
.tileTag = TAG_PARTICLES_BEASTBALL,
.paletteTag = TAG_PARTICLES_BEASTBALL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = sAnims_BallParticles,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
__
in function const u16 gBallOpenFadeColors[] =
add after [BALL_PREMIER] = RGB(31, 9, 10),
[BALL_HEAL] = RGB(31, 23, 27),
[BALL_DUSK] = RGB(7, 1, 13),
[BALL_QUICK] = RGB(16, 25, 30),
[BALL_PARK] = RGB(31, 31, 15),
[BALL_CHERISH] = RGB(25, 4, 3),
[BALL_DREAM] = RGB(31, 31, 15),
[BALL_BEAST] = RGB(16, 25, 30),
__
in function u8 ItemIdToBallId(u16 ballItem)
add after return BALL_PREMIER;
case ITEM_HEAL_BALL:
return BALL_HEAL;
case ITEM_DUSK_BALL:
return BALL_DUSK;
case ITEM_QUICK_BALL:
return BALL_QUICK;
case ITEM_PARK_BALL:
return BALL_PARK;
case ITEM_CHERISH_BALL:
return BALL_CHERISH;
case ITEM_DREAM_BALL:
return BALL_DREAM;
case ITEM_BEAST_BALL:
return BALL_BEAST;
This is where you can change what rules the balls have for giving bonuses
at top of file add:
#include "rtc.h"
#include "constants/species.h"
in function static void Cmd_handleballthrow(void)
replace all with:
{
u8 ballMultiplier = 0;
if (gBattleControllerExecFlags)
return;
gActiveBattler = gBattlerAttacker;
gBattlerTarget = BATTLE_OPPOSITE(gBattlerAttacker);
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
BtlController_EmitBallThrowAnim(B_COMM_TO_CONTROLLER, BALL_TRAINER_BLOCK);
MarkBattlerForControllerExec(gActiveBattler);
gBattlescriptCurrInstr = BattleScript_TrainerBallBlock;
}
else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
{
BtlController_EmitBallThrowAnim(B_COMM_TO_CONTROLLER, BALL_3_SHAKES_SUCCESS);
MarkBattlerForControllerExec(gActiveBattler);
gBattlescriptCurrInstr = BattleScript_WallyBallThrow;
}
else
{
u32 odds;
u8 catchRate;
if (gLastUsedItem == ITEM_SAFARI_BALL)
catchRate = gBattleStruct->safariCatchFactor * 1275 / 100;
else
catchRate = gSpeciesInfo[gBattleMons[gBattlerTarget].species].catchRate;
if (gLastUsedItem == ITEM_BEAST_BALL)
{
switch (gBattleMons[gBattlerTarget].species)
{
#ifdef SPECIES_NECROZMA
case SPECIES_NIHILEGO:
case SPECIES_BUZZWHOLE:
case SPECIES_PHEROMOSA:
case SPECIES_XURKITREE:
case SPECIES_CELESTEELA:
case SPECIES_KARTANA:
case SPECIES_GUZZLORD:
case SPECIES_POIPOLE:
case SPECIES_NAGANADEL:
case SPECIES_STAKATAKA:
case SPECIES_BLACEPHALON:
ballMultiplier = 50;
break;
default:
ballMultiplier = 1;
break;
#else
case SPECIES_RAIKOU:
case SPECIES_ENTEI:
case SPECIES_SUICUNE:
catchRate = (gSpeciesInfo[gBattleMons[gBattlerTarget].species].catchRate * 30);
ballMultiplier = 15;
break;
default:
ballMultiplier = 1;
break;
#endif
}
}
if (gLastUsedItem > ITEM_SAFARI_BALL)
{
switch (gLastUsedItem)
{
case ITEM_NET_BALL:
if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_WATER) || IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_BUG))
ballMultiplier = 30;
else
ballMultiplier = 10;
break;
case ITEM_DIVE_BALL:
if (GetCurrentMapType() == MAP_TYPE_UNDERWATER)
ballMultiplier = 35;
else
ballMultiplier = 10;
break;
case ITEM_NEST_BALL:
if (gBattleMons[gBattlerTarget].level < 40)
{
ballMultiplier = 40 - gBattleMons[gBattlerTarget].level;
if (ballMultiplier <= 9)
ballMultiplier = 10;
}
else
{
ballMultiplier = 10;
}
break;
case ITEM_REPEAT_BALL:
if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), FLAG_GET_CAUGHT))
ballMultiplier = 30;
else
ballMultiplier = 10;
break;
case ITEM_TIMER_BALL:
ballMultiplier = gBattleResults.battleTurnCounter + 10;
if (ballMultiplier > 40)
ballMultiplier = 40;
break;
case ITEM_LUXURY_BALL:
case ITEM_PREMIER_BALL:
ballMultiplier = 10;
break;
// sinnoh balls start
case ITEM_HEAL_BALL:
ballMultiplier = 10;
break;
case ITEM_DUSK_BALL:
RtcCalcLocalTime();
if ((gLocalTime.hours >= 20 && gLocalTime.hours <= 3) || gMapHeader.cave || gMapHeader.mapType == MAP_TYPE_UNDERGROUND)
ballMultiplier = 35;
else
ballMultiplier = 10;
break;
case ITEM_QUICK_BALL:
if (gBattleResults.battleTurnCounter == 0)
ballMultiplier = 40;
else
ballMultiplier = 10;
break;
case ITEM_PARK_BALL:
// set map type as MAP_TYPE_UNKNOWN in porymap
if (GetCurrentMapType() == MAP_TYPE_UNKNOWN)
ballMultiplier = 35;
break;
case ITEM_CHERISH_BALL:
ballMultiplier = 0;
break;
case ITEM_DREAM_BALL:
if (gBattleMons[gBattlerTarget].status1 & STATUS1_SLEEP)
ballMultiplier = 40;
else
ballMultiplier = 10;
break;
}
}
else
{
ballMultiplier = sBallCatchBonuses[gLastUsedItem - ITEM_ULTRA_BALL];
}
odds = (catchRate * ballMultiplier / 10)
* (gBattleMons[gBattlerTarget].maxHP * 3 - gBattleMons[gBattlerTarget].hp * 2)
/ (3 * gBattleMons[gBattlerTarget].maxHP);
if (gBattleMons[gBattlerTarget].status1 & (STATUS1_SLEEP | STATUS1_FREEZE))
odds *= 2;
if (gBattleMons[gBattlerTarget].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON))
odds = (odds * 15) / 10;
if (gLastUsedItem != ITEM_SAFARI_BALL)
{
if (gLastUsedItem == ITEM_MASTER_BALL)
{
gBattleResults.usedMasterBall = TRUE;
}
else
{
if (gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL] < 255)
gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL]++;
}
}
if (odds > 254) // mon caught
{
BtlController_EmitBallThrowAnim(B_COMM_TO_CONTROLLER, BALL_3_SHAKES_SUCCESS);
MarkBattlerForControllerExec(gActiveBattler);
gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
if (CalculatePlayerPartyCount() == PARTY_SIZE)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
// sinnoh heal ball start
if (gLastUsedItem == ITEM_HEAL_BALL)
{
MonRestorePP(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]);
HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], gBattlerPartyIndexes[gBattlerTarget], STATUS1_ANY, gBattlerTarget);
gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp);
}
// sinnoh heal ball end
}
else // mon may be caught, calculate shakes
{
u8 shakes;
odds = Sqrt(Sqrt(16711680 / odds));
odds = 1048560 / odds;
for (shakes = 0; shakes < BALL_3_SHAKES_SUCCESS && Random() < odds; shakes++);
if (gLastUsedItem == ITEM_MASTER_BALL)
shakes = BALL_3_SHAKES_SUCCESS; // why calculate the shakes before that check?
BtlController_EmitBallThrowAnim(B_COMM_TO_CONTROLLER, shakes);
MarkBattlerForControllerExec(gActiveBattler);
if (shakes == BALL_3_SHAKES_SUCCESS) // mon caught, copy of the code above
{
gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
if (CalculatePlayerPartyCount() == PARTY_SIZE)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
// sinnoh heal ball start
if (gLastUsedItem == ITEM_HEAL_BALL)
{
MonRestorePP(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]);
HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], gBattlerPartyIndexes[gBattlerTarget], STATUS1_ANY, gBattlerTarget);
gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp);
}
// sinnoh heal ball end
}
else // not caught
{
gBattleCommunication[MULTISTRING_CHOOSER] = shakes;
gBattlescriptCurrInstr = BattleScript_ShakeBallThrow;
}
}
}
}
near the top of the file, add after #define GFX_TAG_PREMIER_BALL 55011
#define GFX_TAG_HEAL_BALL 55012
#define GFX_TAG_DUSK_BALL 55013
#define GFX_TAG_QUICK_BALL 55014
#define GFX_TAG_PARK_BALL 55015
#define GFX_TAG_CHERISH_BALL 55016
#define GFX_TAG_DREAM_BALL 55017
#define GFX_TAG_BEAST_BALL 55018
__
in function const struct CompressedSpriteSheet gBallSpriteSheets[POKEBALL_COUNT] =
add after [BALL_PREMIER] = {gBallGfx_Premier, 384, GFX_TAG_PREMIER_BALL},
[BALL_HEAL] = {gBallGfx_Heal, 384, GFX_TAG_HEAL_BALL},
[BALL_DUSK] = {gBallGfx_Dusk, 384, GFX_TAG_DUSK_BALL},
[BALL_QUICK] = {gBallGfx_Quick, 384, GFX_TAG_QUICK_BALL},
[BALL_PARK] = {gBallGfx_Park, 384, GFX_TAG_PARK_BALL},
[BALL_CHERISH] = {gBallGfx_Cherish, 384, GFX_TAG_CHERISH_BALL},
[BALL_DREAM] = {gBallGfx_Dream, 384, GFX_TAG_DREAM_BALL},
[BALL_BEAST] = {gBallGfx_Beast, 384, GFX_TAG_BEAST_BALL},
__
in function const struct CompressedSpritePalette gBallSpritePalettes[POKEBALL_COUNT] =
add after [BALL_PREMIER] = {gBallPal_Premier, GFX_TAG_PREMIER_BALL},
[BALL_HEAL] = {gBallPal_Heal, GFX_TAG_HEAL_BALL},
[BALL_DUSK] = {gBallPal_Dusk, GFX_TAG_DUSK_BALL},
[BALL_QUICK] = {gBallPal_Quick, GFX_TAG_QUICK_BALL},
[BALL_PARK] = {gBallPal_Park, GFX_TAG_PARK_BALL},
[BALL_CHERISH] = {gBallPal_Cherish, GFX_TAG_CHERISH_BALL},
[BALL_DREAM] = {gBallPal_Dream, GFX_TAG_DREAM_BALL},
[BALL_BEAST] = {gBallPal_Beast, GFX_TAG_BEAST_BALL},
__
in function const struct SpriteTemplate gBallSpriteTemplates[POKEBALL_COUNT] =
add after section for [BALL_PREMIER] =
[BALL_HEAL] =
{
.tileTag = GFX_TAG_HEAL_BALL,
.paletteTag = GFX_TAG_HEAL_BALL,
.oam = &sBallOamData,
.anims = sBallAnimSequences,
.images = NULL,
.affineAnims = sAffineAnim_BallRotate,
.callback = SpriteCB_BallThrow,
},
[BALL_DUSK] =
{
.tileTag = GFX_TAG_DUSK_BALL,
.paletteTag = GFX_TAG_DUSK_BALL,
.oam = &sBallOamData,
.anims = sBallAnimSequences,
.images = NULL,
.affineAnims = sAffineAnim_BallRotate,
.callback = SpriteCB_BallThrow,
},
[BALL_QUICK] =
{
.tileTag = GFX_TAG_QUICK_BALL,
.paletteTag = GFX_TAG_QUICK_BALL,
.oam = &sBallOamData,
.anims = sBallAnimSequences,
.images = NULL,
.affineAnims = sAffineAnim_BallRotate,
.callback = SpriteCB_BallThrow,
},
[BALL_PARK] =
{
.tileTag = GFX_TAG_PARK_BALL,
.paletteTag = GFX_TAG_PARK_BALL,
.oam = &sBallOamData,
.anims = sBallAnimSequences,
.images = NULL,
.affineAnims = sAffineAnim_BallRotate,
.callback = SpriteCB_BallThrow,
},
[BALL_CHERISH] =
{
.tileTag = GFX_TAG_CHERISH_BALL,
.paletteTag = GFX_TAG_CHERISH_BALL,
.oam = &sBallOamData,
.anims = sBallAnimSequences,
.images = NULL,
.affineAnims = sAffineAnim_BallRotate,
.callback = SpriteCB_BallThrow,
},
[BALL_DREAM] =
{
.tileTag = GFX_TAG_DREAM_BALL,
.paletteTag = GFX_TAG_DREAM_BALL,
.oam = &sBallOamData,
.anims = sBallAnimSequences,
.images = NULL,
.affineAnims = sAffineAnim_BallRotate,
.callback = SpriteCB_BallThrow,
},
[BALL_BEAST] =
{
.tileTag = GFX_TAG_BEAST_BALL,
.paletteTag = GFX_TAG_BEAST_BALL,
.oam = &sBallOamData,
.anims = sBallAnimSequences,
.images = NULL,
.affineAnims = sAffineAnim_BallRotate,
.callback = SpriteCB_BallThrow,
},
end of guide
Before you run the make command to compile your rom, run a make clean first to make sure there's no errors with the newly added graphics files.