updated up to Cmd_handleballthrow

This commit is contained in:
cawtds 2024-05-02 12:24:35 +02:00
parent 99a46831af
commit 6ec21fcd8a
7 changed files with 336 additions and 87 deletions

View File

@ -97,6 +97,7 @@ ViridianCity_Mart_Items::
.2byte ITEM_ABILITY_PATCH
.2byte ITEM_STICKY_BARB
.2byte ITEM_ORAN_BERRY
.2byte ITEM_BEAST_BALL
.2byte ITEM_NONE
release
end

View File

@ -842,7 +842,9 @@ struct BattleAnimationInfo
u8 field_5;
u8 field_6;
u8 field_7;
u8 ballThrowCaseId;
u8 ballThrowCaseId:6;
u8 isCriticalCapture:1;
u8 criticalCaptureSuccess:1;
u8 introAnimActive:1;
u8 wildMonInvisible:1;
u8 field_9_x1C:3;
@ -1042,6 +1044,8 @@ extern u8 gIsCriticalHit;
extern struct FieldTimer gFieldTimers;
extern bool8 gHasFetchedBall;
extern u8 gLastUsedBall;
extern u16 gLastThrownBall;
extern u16 gBallToDisplay;
extern struct QueuedStatBoost gQueuedStatBoosts[MAX_BATTLERS_COUNT];
static inline u32 GetBattlerPosition(u32 battler)

View File

@ -187,6 +187,10 @@ extern const u16 gMovesWithQuietBGM[];
u8 GetAnimBattlerId(u8 wantedBattler);
// battle_anim_throw.c
bool32 IsCriticalCapture(void);
//
void MoveBattlerSpriteToBG(u8 battlerId, u8);
void ResetBattleAnimBg(u8);
void ClearBattleAnimationVars(void);

View File

@ -4,39 +4,74 @@
#define ITEM_NONE 0
// Poké Balls
#define ITEM_MASTER_BALL 1
#define ITEM_ULTRA_BALL 2
#define ITEM_GREAT_BALL 3
#define ITEM_POKE_BALL 4
#define ITEM_SAFARI_BALL 5
#define ITEM_NET_BALL 6
#define ITEM_DIVE_BALL 7
#define ITEM_POKE_BALL 1
#define ITEM_GREAT_BALL 2
#define ITEM_ULTRA_BALL 3
#define ITEM_MASTER_BALL 4
#define ITEM_PREMIER_BALL 5
#define ITEM_HEAL_BALL 6
#define ITEM_NET_BALL 7
#define ITEM_NEST_BALL 8
#define ITEM_REPEAT_BALL 9
#define ITEM_TIMER_BALL 10
#define ITEM_LUXURY_BALL 11
#define ITEM_PREMIER_BALL 12
#define ITEM_HEAL_BALL 13
#define ITEM_DUSK_BALL 14
#define ITEM_QUICK_BALL 15
#define ITEM_LEVEL_BALL 16
#define ITEM_LURE_BALL 17
#define ITEM_MOON_BALL 18
#define ITEM_FRIEND_BALL 19
#define ITEM_LOVE_BALL 20
#define ITEM_FAST_BALL 21
#define ITEM_HEAVY_BALL 22
#define ITEM_DREAM_BALL 23
#define ITEM_DIVE_BALL 9
#define ITEM_DUSK_BALL 10
#define ITEM_TIMER_BALL 11
#define ITEM_QUICK_BALL 12
#define ITEM_REPEAT_BALL 13
#define ITEM_LUXURY_BALL 14
#define ITEM_LEVEL_BALL 15
#define ITEM_LURE_BALL 16
#define ITEM_MOON_BALL 17
#define ITEM_FRIEND_BALL 18
#define ITEM_LOVE_BALL 19
#define ITEM_FAST_BALL 20
#define ITEM_HEAVY_BALL 21
#define ITEM_DREAM_BALL 22
#define ITEM_SAFARI_BALL 23
#define ITEM_SPORT_BALL 24
#define ITEM_PARK_BALL 25
#define ITEM_BEAST_BALL 26
#define ITEM_CHERISH_BALL 27
#define ITEM_CHERISH_BALL 27 // TODO: throwing CHERISH_BALL restarts game, intended?
// 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. 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
#define FIRST_BALL ITEM_POKE_BALL
#define LAST_BALL ITEM_CHERISH_BALL
// // Poké Balls
// #define ITEM_MASTER_BALL 1
// #define ITEM_ULTRA_BALL 2
// #define ITEM_GREAT_BALL 3
// #define ITEM_POKE_BALL 4
// #define ITEM_SAFARI_BALL 5
// #define ITEM_NET_BALL 6
// #define ITEM_DIVE_BALL 7
// #define ITEM_NEST_BALL 8
// #define ITEM_REPEAT_BALL 9
// #define ITEM_TIMER_BALL 10
// #define ITEM_LUXURY_BALL 11
// #define ITEM_PREMIER_BALL 12
// #define ITEM_HEAL_BALL 13
// #define ITEM_DUSK_BALL 14
// #define ITEM_QUICK_BALL 15
// #define ITEM_LEVEL_BALL 16
// #define ITEM_LURE_BALL 17
// #define ITEM_MOON_BALL 18
// #define ITEM_FRIEND_BALL 19
// #define ITEM_LOVE_BALL 20
// #define ITEM_FAST_BALL 21
// #define ITEM_HEAVY_BALL 22
// #define ITEM_DREAM_BALL 23
// #define ITEM_SPORT_BALL 24
// #define ITEM_PARK_BALL 25
// #define ITEM_BEAST_BALL 26
// #define ITEM_CHERISH_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. 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_CHERISH_BALL
// Medicine
#define ITEM_POTION 28

View File

@ -1741,3 +1741,12 @@ u8 GetAnimBattlerId(u8 wantedBattler)
return wantedBattler - MAX_BATTLERS_COUNT;
}
}
// battle_anim_throw.c
bool32 IsCriticalCapture(void)
{
return gBattleSpritesDataPtr->animationData->isCriticalCapture;
}
//

View File

@ -229,6 +229,8 @@ EWRAM_DATA u8 gIsCriticalHit = FALSE;
EWRAM_DATA struct FieldTimer gFieldTimers = {0};
EWRAM_DATA bool8 gHasFetchedBall = FALSE;
EWRAM_DATA u8 gLastUsedBall = 0;
EWRAM_DATA u16 gLastThrownBall = 0;
EWRAM_DATA u16 gBallToDisplay = 0;
EWRAM_DATA struct QueuedStatBoost gQueuedStatBoosts[MAX_BATTLERS_COUNT] = {0};
void (*gPreBattleCallback1)(void);

View File

@ -340,6 +340,7 @@ static bool8 CanBurnHitThaw(u16 move);
static bool32 ChangeOrderTargetAfterAttacker(void);
static void TryUpdateEvolutionTracker(u32 evolutionMethod, u32 upAmount);
static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 isIntimidate);
static bool32 CriticalCapture(u32 odds);
static void Cmd_attackcanceler(void);
static void Cmd_accuracycheck(void);
@ -832,7 +833,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_pursuitdoubles, //0xEC // done
Cmd_snatchsetbattlers, //0xED // done
Cmd_removelightscreenreflect, //0xEE // done
Cmd_handleballthrow, //0xEF
Cmd_handleballthrow, //0xEF // done
Cmd_givecaughtmon, //0xF0
Cmd_trysetcaughtmondexflags, //0xF1
Cmd_displaydexinfo, //0xF2
@ -1182,15 +1183,6 @@ static const u16 sWeightToDamageTable[] =
0xFFFF, 0xFFFF
};
// - 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
};
static bool32 NoTargetPresent(u8 battler, u32 move)
{
if (!IsBattlerAlive(gBattlerTarget))
@ -15328,12 +15320,16 @@ u8 GetCatchingBattler(void)
static void Cmd_handleballthrow(void)
{
u8 ballMultiplier = 0;
CMD_ARGS();
u16 ballMultiplier = 100;
s8 ballAddition = 0;
if (gBattleControllerExecFlags)
return;
gActiveBattler = gBattlerAttacker;
gBattlerTarget = gBattlerAttacker ^ BIT_SIDE;
gBattlerTarget = GetCatchingBattler();
if (gBattleTypeFlags & BATTLE_TYPE_GHOST)
{
@ -15344,7 +15340,7 @@ static void Cmd_handleballthrow(void)
else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
BtlController_EmitBallThrowAnim(BUFFER_A, BALL_TRAINER_BLOCK);
MarkBattlerForControllerExec(gActiveBattler);
MarkBattlerForControllerExec(gBattlerAttacker);
gBattlescriptCurrInstr = BattleScript_TrainerBallBlock;
}
else if (gBattleTypeFlags & (BATTLE_TYPE_POKEDUDE | BATTLE_TYPE_OLD_MAN_TUTORIAL))
@ -15355,88 +15351,209 @@ static void Cmd_handleballthrow(void)
}
else
{
u32 odds;
u32 odds, i;
u8 catchRate;
if (gLastUsedItem == ITEM_SAFARI_BALL)
gLastThrownBall = gLastUsedItem;
gBallToDisplay = gLastThrownBall;
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
catchRate = gBattleStruct->safariCatchFactor * 1275 / 100;
else
catchRate = gSpeciesInfo[gBattleMons[gBattlerTarget].species].catchRate;
if (gLastUsedItem > ITEM_SAFARI_BALL)
if (gSpeciesInfo[gBattleMons[gBattlerTarget].species].isUltraBeast)
{
if (gLastUsedItem == ITEM_BEAST_BALL)
ballMultiplier = 500;
else
ballMultiplier = 10;
}
else
{
switch (gLastUsedItem)
{
case ITEM_ULTRA_BALL:
ballMultiplier = 200;
break;
case ITEM_SPORT_BALL:
if (B_SPORT_BALL_MODIFIER <= GEN_7)
ballMultiplier = 150;
break;
case ITEM_GREAT_BALL:
ballMultiplier = 150;
break;
case ITEM_SAFARI_BALL:
if (B_SAFARI_BALL_MODIFIER <= GEN_7)
ballMultiplier = 150;
break;
case ITEM_NET_BALL:
if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_WATER) || IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_BUG))
ballMultiplier = 30;
else
ballMultiplier = 10;
ballMultiplier = B_NET_BALL_MODIFIER >= GEN_7 ? 350 : 300;
break;
case ITEM_DIVE_BALL:
if (GetCurrentMapType() == MAP_TYPE_UNDERWATER)
ballMultiplier = 35;
else
ballMultiplier = 10;
// TODO: gIsFishingEncounter and gIsSurfingEncounter
// if (GetCurrentMapType() == MAP_TYPE_UNDERWATER
// || (B_DIVE_BALL_MODIFIER >= GEN_4 && (gIsFishingEncounter || gIsSurfingEncounter)))
// ballMultiplier = 350;
break;
case ITEM_NEST_BALL:
if (gBattleMons[gBattlerTarget].level < 40)
if (B_NEST_BALL_MODIFIER >= GEN_6)
{
ballMultiplier = 40 - gBattleMons[gBattlerTarget].level;
if (ballMultiplier <= 9)
ballMultiplier = 10;
//((41 - Pokémon's level) ÷ 10)× if Pokémon's level is between 1 and 29, 1× otherwise.
if (gBattleMons[gBattlerTarget].level < 30)
ballMultiplier = 410 - (gBattleMons[gBattlerTarget].level * 10);
}
else
else if (B_NEST_BALL_MODIFIER >= GEN_5)
{
ballMultiplier = 10;
//((41 - Pokémon's level) ÷ 10)×, minimum 1×
if (gBattleMons[gBattlerTarget].level < 31)
ballMultiplier = 410 - (gBattleMons[gBattlerTarget].level * 10);
}
else if (gBattleMons[gBattlerTarget].level < 40)
{
//((40 - Pokémon's level) ÷ 10)×, minimum 1×
ballMultiplier = 400 - (gBattleMons[gBattlerTarget].level * 10);
if (ballMultiplier <= 90)
ballMultiplier = 100;
}
break;
case ITEM_REPEAT_BALL:
if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), FLAG_GET_CAUGHT))
ballMultiplier = 30;
else
ballMultiplier = 10;
ballMultiplier = (B_REPEAT_BALL_MODIFIER >= GEN_7 ? 350 : 300);
break;
case ITEM_TIMER_BALL:
ballMultiplier = gBattleResults.battleTurnCounter + 10;
if (ballMultiplier > 40)
ballMultiplier = 40;
ballMultiplier = 100 + (gBattleResults.battleTurnCounter * (B_TIMER_BALL_MODIFIER >= GEN_5 ? 30 : 10));
if (ballMultiplier > 400)
ballMultiplier = 400;
break;
case ITEM_LUXURY_BALL:
case ITEM_PREMIER_BALL:
case ITEM_DUSK_BALL:
// TODO: RTC
// i = GetTimeOfDay();
// if (i == TIME_EVENING || i == TIME_NIGHT || gMapHeader.cave || gMapHeader.mapType == MAP_TYPE_UNDERGROUND)
// ballMultiplier = (B_DUSK_BALL_MODIFIER >= GEN_7 ? 300 : 350);
break;
case ITEM_QUICK_BALL:
if (gBattleResults.battleTurnCounter == 0)
ballMultiplier = (B_QUICK_BALL_MODIFIER >= GEN_5 ? 500 : 400);
break;
case ITEM_LEVEL_BALL:
if (gBattleMons[gBattlerAttacker].level >= 4 * gBattleMons[gBattlerTarget].level)
ballMultiplier = 800;
else if (gBattleMons[gBattlerAttacker].level > 2 * gBattleMons[gBattlerTarget].level)
ballMultiplier = 400;
else if (gBattleMons[gBattlerAttacker].level > gBattleMons[gBattlerTarget].level)
ballMultiplier = 200;
break;
case ITEM_LURE_BALL:
// TODO: gIsFishingEncounter
// if (gIsFishingEncounter)
// {
// if (B_LURE_BALL_MODIFIER >= GEN_8)
// ballMultiplier = 400;
// else if (B_LURE_BALL_MODIFIER >= GEN_7)
// ballMultiplier = 500;
// else
// ballMultiplier = 300;
// }
break;
case ITEM_MOON_BALL:
{
const struct Evolution *evolutions = GetSpeciesEvolutions(gBattleMons[gBattlerTarget].species);
if (evolutions == NULL)
break;
for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++)
{
if (evolutions[i].method == EVO_ITEM
&& evolutions[i].param == ITEM_MOON_STONE)
ballMultiplier = 400;
}
}
break;
case ITEM_LOVE_BALL:
if (gBattleMons[gBattlerTarget].species == gBattleMons[gBattlerAttacker].species)
{
u8 gender1 = GetMonGender(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]);
u8 gender2 = GetMonGender(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]);
if (gender1 != gender2 && gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS)
ballMultiplier = 800;
}
break;
case ITEM_FAST_BALL:
if (gSpeciesInfo[gBattleMons[gBattlerTarget].species].baseSpeed >= 100)
ballMultiplier = 400;
break;
case ITEM_HEAVY_BALL:
i = GetSpeciesWeight(gBattleMons[gBattlerTarget].species);
if (B_HEAVY_BALL_MODIFIER >= GEN_7)
{
if (i < 1000)
ballAddition = -20;
else if (i < 2000)
ballAddition = 0;
else if (i < 3000)
ballAddition = 20;
else
ballAddition = 30;
}
else if (B_HEAVY_BALL_MODIFIER >= GEN_4)
{
if (i < 2048)
ballAddition = -20;
else if (i < 3072)
ballAddition = 20;
else if (i < 4096)
ballAddition = 30;
else
ballAddition = 40;
}
else
{
if (i < 1024)
ballAddition = -20;
else if (i < 2048)
ballAddition = 0;
else if (i < 3072)
ballAddition = 20;
else if (i < 4096)
ballAddition = 30;
else
ballAddition = 40;
}
break;
case ITEM_DREAM_BALL:
if (B_DREAM_BALL_MODIFIER >= GEN_8 && (gBattleMons[gBattlerTarget].status1 & STATUS1_SLEEP || GetBattlerAbility(gBattlerTarget) == ABILITY_COMATOSE))
ballMultiplier = 400;
break;
case ITEM_BEAST_BALL:
ballMultiplier = 10;
break;
}
}
else
ballMultiplier = sBallCatchBonuses[gLastUsedItem - ITEM_ULTRA_BALL];
odds = (catchRate * ballMultiplier / 10)
// catchRate is unsigned, which means that it may potentially overflow if sum is applied directly.
if (catchRate < 21 && ballAddition == -20)
catchRate = 1;
else
catchRate = catchRate + ballAddition;
odds = (catchRate * ballMultiplier / 100)
* (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))
if (gBattleMons[gBattlerTarget].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE))
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 (gBattleResults.catchAttempts[gLastUsedItem - FIRST_BALL] < 255)
gBattleResults.catchAttempts[gLastUsedItem - FIRST_BALL]++;
if (odds > 254) // mon caught
{
BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS);
MarkBattlerForControllerExec(gActiveBattler);
MarkBattlerForControllerExec(gBattlerAttacker);
TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE);
gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
@ -15444,24 +15561,54 @@ static void Cmd_handleballthrow(void)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
if (gLastUsedItem == ITEM_HEAL_BALL)
{
MonRestorePP(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]);
HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], STATUS1_ANY, gBattlerTarget);
gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp);
}
}
else // mon may be caught, calculate shakes
{
u8 shakes;
u8 maxShakes;
odds = Sqrt(Sqrt(16711680 / odds));
odds = 1048560 / odds;
// TODO: critical capture
gBattleSpritesDataPtr->animationData->isCriticalCapture = FALSE;
gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = FALSE;
for (shakes = 0; shakes < BALL_3_SHAKES_SUCCESS && Random() < odds; shakes++);
if (CriticalCapture(odds))
{
maxShakes = BALL_1_SHAKE; // critical capture doesn't guarantee capture
gBattleSpritesDataPtr->animationData->isCriticalCapture = TRUE;
}
else
{
maxShakes = BALL_3_SHAKES_SUCCESS;
}
if (gLastUsedItem == ITEM_MASTER_BALL)
shakes = BALL_3_SHAKES_SUCCESS; // why calculate the shakes before that check?
{
shakes = maxShakes;
}
else
{
odds = Sqrt(Sqrt(16711680 / odds));
odds = 1048560 / odds;
for (shakes = 0; shakes < maxShakes && Random() < odds; shakes++);
}
BtlController_EmitBallThrowAnim(BUFFER_A, shakes);
MarkBattlerForControllerExec(gActiveBattler);
MarkBattlerForControllerExec(gBattlerAttacker);
if (shakes == BALL_3_SHAKES_SUCCESS) // mon caught, copy of the code above
if (shakes == maxShakes) // mon caught, copy of the code above
{
if (IsCriticalCapture())
gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE;
TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE);
gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
@ -15469,10 +15616,25 @@ static void Cmd_handleballthrow(void)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
if (gLastUsedItem == ITEM_HEAL_BALL)
{
MonRestorePP(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]);
HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], STATUS1_ANY, gBattlerTarget);
gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp);
}
}
else // not caught
{
gBattleCommunication[MULTISTRING_CHOOSER] = shakes;
if (!gHasFetchedBall)
gLastUsedBall = gLastUsedItem;
if (IsCriticalCapture())
gBattleCommunication[MULTISTRING_CHOOSER] = BALL_3_SHAKES_FAIL;
else
gBattleCommunication[MULTISTRING_CHOOSER] = shakes;
gBattlescriptCurrInstr = BattleScript_ShakeBallThrow;
}
}
@ -15958,6 +16120,38 @@ void BS_RunStatChangeItems(void)
ItemBattleEffects(ITEMEFFECT_STATS_CHANGED, GetBattlerForBattleScript(cmd->battler), FALSE); // TODO: update
}
static bool32 CriticalCapture(u32 odds)
{
u32 numCaught;
if (B_CRITICAL_CAPTURE == FALSE)
return FALSE;
numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT);
if (numCaught <= (NATIONAL_DEX_COUNT * 30) / 650)
odds = 0;
else if (numCaught <= (NATIONAL_DEX_COUNT * 150) / 650)
odds /= 2;
else if (numCaught <= (NATIONAL_DEX_COUNT * 300) / 650)
; // odds = (odds * 100) / 100;
else if (numCaught <= (NATIONAL_DEX_COUNT * 450) / 650)
odds = (odds * 150) / 100;
else if (numCaught <= (NATIONAL_DEX_COUNT * 600) / 650)
odds *= 2;
else
odds = (odds * 250) / 100;
if (CheckBagHasItem(ITEM_CATCHING_CHARM, 1))
odds = (odds * (100 + B_CATCHING_CHARM_BOOST)) / 100;
odds /= 6;
if ((Random() % 255) < odds)
return TRUE;
return FALSE;
}
bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler)
{
if (move != MOVE_NONE && move != MOVE_UNAVAILABLE && move != MOVE_STRUGGLE