Refactor Poke Ball code to not rely on Master Ball being the first item internally.

This commit is contained in:
ultima-soul 2021-06-11 18:22:50 -07:00
parent b7706f1b99
commit bca67ac683
6 changed files with 50 additions and 139 deletions

View file

@ -11,37 +11,6 @@
.section script_data, "aw", %progbits
.align 2
gBattlescriptsForBallThrow:: @ 82DBD08
.4byte BattleScript_BallThrow @ ITEM_NONE
.4byte BattleScript_BallThrow @ ITEM_MASTER_BALL
.4byte BattleScript_BallThrow @ ITEM_ULTRA_BALL
.4byte BattleScript_BallThrow @ ITEM_GREAT_BALL
.4byte BattleScript_BallThrow @ ITEM_POKE_BALL
.4byte BattleScript_SafariBallThrow @ ITEM_SAFARI_BALL
.4byte BattleScript_BallThrow @ ITEM_NET_BALL
.4byte BattleScript_BallThrow @ ITEM_DIVE_BALL
.4byte BattleScript_BallThrow @ ITEM_NEST_BALL
.4byte BattleScript_BallThrow @ ITEM_REPEAT_BALL
.4byte BattleScript_BallThrow @ ITEM_TIMER_BALL
.4byte BattleScript_BallThrow @ ITEM_LUXURY_BALL
.4byte BattleScript_BallThrow @ ITEM_DUSK_BALL
.4byte BattleScript_BallThrow @ ITEM_HEAL_BALL
.4byte BattleScript_BallThrow @ ITEM_QUICK_BALL
.4byte BattleScript_BallThrow @ ITEM_CHERISH_BALL
.4byte BattleScript_BallThrow @ ITEM_FAST_BALL
.4byte BattleScript_BallThrow @ ITEM_LEVEL_BALL
.4byte BattleScript_BallThrow @ ITEM_LURE_BALL
.4byte BattleScript_BallThrow @ ITEM_HEAVY_BALL
.4byte BattleScript_BallThrow @ ITEM_LOVE_BALL
.4byte BattleScript_BallThrow @ ITEM_FRIEND_BALL
.4byte BattleScript_BallThrow @ ITEM_MOON_BALL
.4byte BattleScript_BallThrow @ ITEM_SPORT_BALL
.4byte BattleScript_BallThrow @ ITEM_PARK_BALL
.4byte BattleScript_BallThrow @ ITEM_DREAM_BALL
.4byte BattleScript_BallThrow @ ITEM_BEAST_BALL
.4byte BattleScript_BallThrow @ ITEM_PREMIER_BALL
.align 2
gBattlescriptsForUsingItem:: @ 82DBD3C
.4byte BattleScript_PlayerUsesItem
@ -77,7 +46,6 @@ BattleScript_SafariBallThrow::
handleballthrow
BattleScript_SuccessBallThrow::
jumpifhalfword CMP_EQUAL, gLastUsedItem, ITEM_SAFARI_BALL, BattleScript_PrintCaughtMonInfo
incrementgamestat GAME_STAT_POKEMON_CAPTURES
BattleScript_PrintCaughtMonInfo::
printstring STRINGID_GOTCHAPKMNCAUGHT

View file

@ -242,7 +242,6 @@ struct BattleResults
u8 numHealingItemsUsed; // 0x3
u8 numRevivesUsed; // 0x4
u8 playerMonWasDamaged:1; // 0x5
u8 usedMasterBall:1; // 0x5
u8 caughtMonBall:4; // 0x5
u8 shinyWildMon:1; // 0x5
u16 playerMon1Species; // 0x6
@ -257,7 +256,7 @@ struct BattleResults
u16 caughtMonSpecies; // 0x28
u8 caughtMonNick[POKEMON_NAME_LENGTH + 1]; // 0x2A
u8 filler35; // 0x35
u8 catchAttempts[POKEBALL_COUNT - 1]; // 0x36 Doesn't include Master ball
u8 catchAttempts[POKEBALL_COUNT]; // 0x36
};
struct BattleTv_Side

View file

@ -32,7 +32,7 @@
#define ITEM_PREMIER_BALL 27
// 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)
// Several places expect the ball IDs to be first and contiguous (e.g. 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_PREMIER_BALL

View file

@ -830,15 +830,6 @@ static const u8 sTerrainToType[] =
[BATTLE_TERRAIN_PLAIN] = TYPE_NORMAL,
};
// - ITEM_ULTRA_BALL skips Master Ball and ITEM_NONE
static const u8 sBallCatchBonuses[] =
{
[ITEM_ULTRA_BALL - ITEM_ULTRA_BALL] = 20,
[ITEM_GREAT_BALL - ITEM_ULTRA_BALL] = 15,
[ITEM_POKE_BALL - ITEM_ULTRA_BALL] = 10,
[ITEM_SAFARI_BALL - ITEM_ULTRA_BALL] = 15
};
// In Battle Palace, moves are chosen based on the pokemons nature rather than by the player
// Moves are grouped into "Attack", "Defense", or "Support" (see PALACE_MOVE_GROUP_*)
// Each nature has a certain percent chance of selecting a move from a particular group
@ -9754,7 +9745,7 @@ static void Cmd_removelightscreenreflect(void) // brick break
static void Cmd_handleballthrow(void)
{
u8 ballMultiplier = 0;
u8 ballMultiplier = 10;
if (gBattleControllerExecFlags)
return;
@ -9779,58 +9770,44 @@ static void Cmd_handleballthrow(void)
u32 odds;
u8 catchRate;
if (gLastUsedItem == ITEM_SAFARI_BALL)
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
catchRate = gBattleStruct->safariCatchFactor * 1275 / 100;
else
catchRate = gBaseStats[gBattleMons[gBattlerTarget].species].catchRate;
if (gLastUsedItem > ITEM_SAFARI_BALL)
switch (gLastUsedItem)
{
switch (gLastUsedItem)
case ITEM_ULTRA_BALL:
ballMultiplier = 20;
case ITEM_GREAT_BALL:
case ITEM_SAFARI_BALL:
ballMultiplier = 15;
case ITEM_NET_BALL:
if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_WATER) || IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_BUG))
ballMultiplier = 30;
break;
case ITEM_DIVE_BALL:
if (GetCurrentMapType() == MAP_TYPE_UNDERWATER)
ballMultiplier = 35;
break;
case ITEM_NEST_BALL:
if (gBattleMons[gBattlerTarget].level < 40)
{
case ITEM_NET_BALL:
if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_WATER) || IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_BUG))
ballMultiplier = 30;
else
ballMultiplier = 40 - gBattleMons[gBattlerTarget].level;
if (ballMultiplier <= 9)
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;
}
break;
case ITEM_REPEAT_BALL:
if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), FLAG_GET_CAUGHT))
ballMultiplier = 30;
break;
case ITEM_TIMER_BALL:
ballMultiplier = gBattleResults.battleTurnCounter + 10;
if (ballMultiplier > 40)
ballMultiplier = 40;
break;
}
else
ballMultiplier = sBallCatchBonuses[gLastUsedItem - ITEM_ULTRA_BALL];
odds = (catchRate * ballMultiplier / 10)
* (gBattleMons[gBattlerTarget].maxHP * 3 - gBattleMons[gBattlerTarget].hp * 2)
@ -9841,18 +9818,8 @@ static void Cmd_handleballthrow(void)
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] < 0xFF)
gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL]++;
}
}
if (gBattleResults.catchAttempts[gLastUsedItem - FIRST_BALL] < 0xFF)
gBattleResults.catchAttempts[gLastUsedItem - FIRST_BALL]++;
if (odds > 254) // mon caught
{

View file

@ -44,7 +44,6 @@ functions instead of at the top of the file with the other declarations.
*/
extern const u8 *const gBattleScriptsForMoveEffects[];
extern const u8 *const gBattlescriptsForBallThrow[];
extern const u8 *const gBattlescriptsForRunningByItem[];
extern const u8 *const gBattlescriptsForUsingItem[];
extern const u8 *const gBattlescriptsForSafariActions[];
@ -319,7 +318,7 @@ void HandleAction_UseItem(void)
if (gLastUsedItem <= LAST_BALL) // is ball
{
gBattlescriptCurrInstr = gBattlescriptsForBallThrow[gLastUsedItem];
gBattlescriptCurrInstr = BattleScript_BallThrow;
}
else if (gLastUsedItem == ITEM_POKE_DOLL || gLastUsedItem == ITEM_FLUFFY_TAIL)
{
@ -550,7 +549,7 @@ void HandleAction_SafariZoneBallThrow(void)
gBattle_BG0_Y = 0;
gNumSafariBalls--;
gLastUsedItem = ITEM_SAFARI_BALL;
gBattlescriptCurrInstr = gBattlescriptsForBallThrow[ITEM_SAFARI_BALL];
gBattlescriptCurrInstr = BattleScript_SafariBallThrow;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
}

View file

@ -955,22 +955,14 @@ void GabbyAndTyBeforeInterview(void)
else
gSaveBlock1Ptr->gabbyAndTyData.playerUsedHealingItem = FALSE;
if (!gBattleResults.usedMasterBall)
for (i = 0; i < POKEBALL_COUNT; i++)
{
for (i = 0; i < POKEBALL_COUNT - 1; i++)
if (gBattleResults.catchAttempts[i])
{
if (gBattleResults.catchAttempts[i])
{
gSaveBlock1Ptr->gabbyAndTyData.playerThrewABall = TRUE;
break;
}
gSaveBlock1Ptr->gabbyAndTyData.playerThrewABall = TRUE;
break;
}
}
else
{
// Player threw a Master Ball at Gabby and Ty
gSaveBlock1Ptr->gabbyAndTyData.playerThrewABall = TRUE;
}
TakeGabbyAndTyOffTheAir();
if (gSaveBlock1Ptr->gabbyAndTyData.lastMove == MOVE_NONE)
@ -1128,28 +1120,20 @@ void TryPutPokemonTodayOnAir(void)
sCurTVShowSlot = FindFirstEmptyRecordMixTVShowSlot(gSaveBlock1Ptr->tvShows);
if (sCurTVShowSlot != -1 && IsRecordMixShowAlreadySpawned(TVSHOW_POKEMON_TODAY_CAUGHT, FALSE) != TRUE)
{
for (i = 0; i < POKEBALL_COUNT - 1; i++)
for (i = 0; i < POKEBALL_COUNT; i++)
ballsUsed += gBattleResults.catchAttempts[i];
if (ballsUsed != 0 || gBattleResults.usedMasterBall)
if (ballsUsed != 0)
{
ballsUsed = 0;
show = &gSaveBlock1Ptr->tvShows[sCurTVShowSlot];
show->pokemonToday.kind = TVSHOW_POKEMON_TODAY_CAUGHT;
show->pokemonToday.active = FALSE; // NOTE: Show is not active until passed via Record Mix.
if (gBattleResults.usedMasterBall)
{
ballsUsed = 1;
itemLastUsed = ITEM_MASTER_BALL;
}
else
{
for (i = 0; i < POKEBALL_COUNT - 1; i++)
ballsUsed += gBattleResults.catchAttempts[i];
if (ballsUsed > 255)
ballsUsed = 255;
itemLastUsed = gLastUsedItem;
}
for (i = 0; i < POKEBALL_COUNT; i++)
ballsUsed += gBattleResults.catchAttempts[i];
if (ballsUsed > 255)
ballsUsed = 255;
itemLastUsed = gLastUsedItem;
show->pokemonToday.nBallsUsed = ballsUsed;
show->pokemonToday.ball = itemLastUsed;
StringCopy(show->pokemonToday.playerName, gSaveBlock2Ptr->playerName);
@ -1191,7 +1175,7 @@ static void TryPutPokemonTodayFailedOnTheAir(void)
if (!rbernoulli(1, 1))
{
for (i = 0, ballsUsed = 0; i < POKEBALL_COUNT - 1; i++)
for (i = 0, ballsUsed = 0; i < POKEBALL_COUNT; i++)
ballsUsed += gBattleResults.catchAttempts[i];
if (ballsUsed > 255)
ballsUsed = 255;
@ -2123,11 +2107,8 @@ void TryPutBreakingNewsOnAir(void)
show->breakingNews.kind = TVSHOW_BREAKING_NEWS;
show->breakingNews.active = FALSE; // NOTE: Show is not active until passed via Record Mix.
balls = 0;
for (i = 0; i < POKEBALL_COUNT - 1; i++)
for (i = 0; i < POKEBALL_COUNT; i++)
balls += gBattleResults.catchAttempts[i];
if (gBattleResults.usedMasterBall)
balls++;
show->breakingNews.location = gMapHeader.regionMapSectionId;
StringCopy(show->breakingNews.playerName, gSaveBlock2Ptr->playerName);
show->breakingNews.poke1Species = gBattleResults.playerMon1Species;
@ -2157,10 +2138,7 @@ void TryPutBreakingNewsOnAir(void)
switch (show->breakingNews.outcome)
{
case 0:
if (gBattleResults.usedMasterBall)
show->breakingNews.caughtMonBall = ITEM_MASTER_BALL;
else
show->breakingNews.caughtMonBall = gBattleResults.caughtMonBall;
show->breakingNews.caughtMonBall = gBattleResults.caughtMonBall;
show->breakingNews.balls = balls;
break;
case 1: