mirror of
https://github.com/pret/pokefirered.git
synced 2026-05-24 06:36:49 -05:00
updated up to Cmd_handleballthrow
This commit is contained in:
parent
99a46831af
commit
6ec21fcd8a
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1741,3 +1741,12 @@ u8 GetAnimBattlerId(u8 wantedBattler)
|
|||
return wantedBattler - MAX_BATTLERS_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
// battle_anim_throw.c
|
||||
|
||||
bool32 IsCriticalCapture(void)
|
||||
{
|
||||
return gBattleSpritesDataPtr->animationData->isCriticalCapture;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user