merge with be

This commit is contained in:
ghoulslash 2021-08-12 14:48:58 -06:00
commit a2d885c0d4
6 changed files with 166 additions and 149 deletions

View File

@ -1242,13 +1242,13 @@ BattleScript_ShellSmashTryDef::
setbyte sSTAT_ANIM_PLAYED, FALSE setbyte sSTAT_ANIM_PLAYED, FALSE
playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE | STAT_CHANGE_CANT_PREVENT playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE | STAT_CHANGE_CANT_PREVENT
setstatchanger STAT_DEF, 1, TRUE setstatchanger STAT_DEF, 1, TRUE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ShellSmashTrySpDef statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_ShellSmashTrySpDef
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpDef jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpDef
printfromtable gStatUpStringIds printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
BattleScript_ShellSmashTrySpDef: BattleScript_ShellSmashTrySpDef:
setstatchanger STAT_SPDEF, 1, TRUE setstatchanger STAT_SPDEF, 1, TRUE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ShellSmashTryAttack statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_ShellSmashTryAttack
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTryAttack jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTryAttack
printfromtable gStatUpStringIds printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG

View File

@ -192,7 +192,8 @@ struct SideTimer
u8 safeguardTimer; u8 safeguardTimer;
u8 safeguardBattlerId; u8 safeguardBattlerId;
u8 followmeTimer; u8 followmeTimer;
u8 followmeTarget; u8 followmeTarget:3;
u8 followmePowder:1; // Rage powder, does not affect grass type pokemon.
u8 spikesAmount; u8 spikesAmount;
u8 toxicSpikesAmount; u8 toxicSpikesAmount;
u8 stealthRockAmount; u8 stealthRockAmount;

View File

@ -47,6 +47,7 @@ struct TypePower
extern const struct TypePower gNaturalGiftTable[]; extern const struct TypePower gNaturalGiftTable[];
void HandleAction_ThrowBall(void); void HandleAction_ThrowBall(void);
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide);
void HandleAction_UseMove(void); void HandleAction_UseMove(void);
void HandleAction_Switch(void); void HandleAction_Switch(void);
void HandleAction_UseItem(void); void HandleAction_UseItem(void);

View File

@ -283,7 +283,7 @@ static const s8 sAiAbilityRatings[ABILITIES_COUNT] =
[ABILITY_GORILLA_TACTICS] = 4, [ABILITY_GORILLA_TACTICS] = 4,
}; };
static const u16 sEncouragedEncoreEffects[] = static const u16 sEncouragedEncoreEffects[] =
{ {
EFFECT_DREAM_EATER, EFFECT_DREAM_EATER,
EFFECT_ATTACK_UP, EFFECT_ATTACK_UP,
@ -365,7 +365,7 @@ static const u16 sDiscouragedPowerfulMoveEffects[] =
0xFFFF 0xFFFF
}; };
static const u16 sIgnoreMoldBreakerMoves[] = static const u16 sIgnoreMoldBreakerMoves[] =
{ {
MOVE_MOONGEIST_BEAM, MOVE_MOONGEIST_BEAM,
MOVE_SUNSTEEL_STRIKE, MOVE_SUNSTEEL_STRIKE,
@ -381,7 +381,7 @@ static const u16 sIgnoreMoldBreakerMoves[] =
#endif #endif
}; };
static const u16 sInstructBannedMoves[] = static const u16 sInstructBannedMoves[] =
{ {
MOVE_INSTRUCT, MOVE_INSTRUCT,
MOVE_BIDE, MOVE_BIDE,
@ -410,7 +410,7 @@ static const u16 sInstructBannedMoves[] =
MOVE_SOLAR_BLADE, MOVE_SOLAR_BLADE,
}; };
static const u16 sRechargeMoves[] = static const u16 sRechargeMoves[] =
{ {
MOVE_HYPER_BEAM, MOVE_HYPER_BEAM,
MOVE_BLAST_BURN, MOVE_BLAST_BURN,
@ -424,7 +424,7 @@ static const u16 sRechargeMoves[] =
MOVE_ETERNABEAM, MOVE_ETERNABEAM,
}; };
static const u16 sOtherMoveCallingMoves[] = static const u16 sOtherMoveCallingMoves[] =
{ {
MOVE_ASSIST, MOVE_ASSIST,
MOVE_COPYCAT, MOVE_COPYCAT,
@ -640,7 +640,7 @@ bool32 IsAffectedByPowder(u8 battler, u16 ability, u16 holdEffect)
{ {
if ((B_POWDER_GRASS >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) if ((B_POWDER_GRASS >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS))
|| ability == ABILITY_OVERCOAT || ability == ABILITY_OVERCOAT
|| GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SAFETY_GOOGLES) || holdEffect == HOLD_EFFECT_SAFETY_GOOGLES)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
@ -929,7 +929,7 @@ u8 AI_GetMoveEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef)
gMoveResultFlags = 0; gMoveResultFlags = 0;
gCurrentMove = move; gCurrentMove = move;
effectivenessMultiplier = AI_GetTypeEffectiveness(gCurrentMove, battlerAtk, battlerDef); effectivenessMultiplier = AI_GetTypeEffectiveness(gCurrentMove, battlerAtk, battlerDef);
switch (effectivenessMultiplier) switch (effectivenessMultiplier)
{ {
case UQ_4_12(0.0): case UQ_4_12(0.0):
@ -1047,7 +1047,7 @@ bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgM
u32 hpCheck = gBattleMons[battlerAtk].hp + hpMod; u32 hpCheck = gBattleMons[battlerAtk].hp + hpMod;
if (dmgMod) if (dmgMod)
dmg *= dmgMod; dmg *= dmgMod;
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i]) && dmg >= hpCheck) if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i]) && dmg >= hpCheck)
{ {
return TRUE; return TRUE;
@ -1091,22 +1091,22 @@ s32 AI_GetAbility(u32 battlerId)
u16 AI_GetHoldEffect(u32 battlerId) u16 AI_GetHoldEffect(u32 battlerId)
{ {
u32 holdEffect; u32 holdEffect;
if (!IsBattlerAIControlled(battlerId)) if (!IsBattlerAIControlled(battlerId))
holdEffect = BATTLE_HISTORY->itemEffects[battlerId]; holdEffect = BATTLE_HISTORY->itemEffects[battlerId];
else else
holdEffect = GetBattlerHoldEffect(battlerId, FALSE); holdEffect = GetBattlerHoldEffect(battlerId, FALSE);
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE) if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE)
return holdEffect; return holdEffect;
if (gStatuses3[battlerId] & STATUS3_EMBARGO) if (gStatuses3[battlerId] & STATUS3_EMBARGO)
return HOLD_EFFECT_NONE; return HOLD_EFFECT_NONE;
if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM)
return HOLD_EFFECT_NONE; return HOLD_EFFECT_NONE;
if (AI_GetAbility(battlerId) == ABILITY_KLUTZ && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID)) if (AI_GetAbility(battlerId) == ABILITY_KLUTZ && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID))
return HOLD_EFFECT_NONE; return HOLD_EFFECT_NONE;
return holdEffect; return holdEffect;
} }
@ -1123,7 +1123,7 @@ bool32 AI_IsTerrainAffected(u8 battlerId, u32 flags)
bool32 AI_IsBattlerGrounded(u8 battlerId) bool32 AI_IsBattlerGrounded(u8 battlerId)
{ {
u32 holdEffect = AI_GetHoldEffect(battlerId); u32 holdEffect = AI_GetHoldEffect(battlerId);
if (holdEffect == HOLD_EFFECT_IRON_BALL) if (holdEffect == HOLD_EFFECT_IRON_BALL)
return TRUE; return TRUE;
else if (gFieldStatuses & STATUS_FIELD_GRAVITY) else if (gFieldStatuses & STATUS_FIELD_GRAVITY)
@ -1149,10 +1149,10 @@ bool32 AI_IsBattlerGrounded(u8 battlerId)
bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move) bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move)
{ {
u32 i; u32 i;
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE) if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE)
return FALSE; // AI handicap flag: doesn't understand ability suppression concept return FALSE; // AI handicap flag: doesn't understand ability suppression concept
for (i = 0; i < ARRAY_COUNT(sIgnoreMoldBreakerMoves); i++) for (i = 0; i < ARRAY_COUNT(sIgnoreMoldBreakerMoves); i++)
{ {
if (move == sIgnoreMoldBreakerMoves[i]) if (move == sIgnoreMoldBreakerMoves[i])
@ -1172,7 +1172,7 @@ bool32 AI_WeatherHasEffect(void)
u32 i; u32 i;
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE) if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE)
return TRUE; // AI doesn't understand weather supression (handicap) return TRUE; // AI doesn't understand weather supression (handicap)
// need to manually check since we don't necessarily know opponent ability // need to manually check since we don't necessarily know opponent ability
for (i = 0; i < gBattlersCount; i++) for (i = 0; i < gBattlersCount; i++)
{ {
@ -1186,7 +1186,7 @@ bool32 AI_WeatherHasEffect(void)
bool32 IsAromaVeilProtectedMove(u16 move) bool32 IsAromaVeilProtectedMove(u16 move)
{ {
u32 i; u32 i;
switch (move) switch (move)
{ {
case MOVE_DISABLE: case MOVE_DISABLE:
@ -1273,7 +1273,7 @@ bool32 IsMoveRedirectionPrevented(u16 move, u16 atkAbility)
{ {
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE) if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE)
return FALSE; return FALSE;
if (move == MOVE_SKY_DROP if (move == MOVE_SKY_DROP
|| move == MOVE_SNIPE_SHOT || move == MOVE_SNIPE_SHOT
|| atkAbility == ABILITY_PROPELLER_TAIL || atkAbility == ABILITY_PROPELLER_TAIL
@ -1287,7 +1287,7 @@ u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbil
{ {
u32 calc, moveAcc, atkParam, defParam; u32 calc, moveAcc, atkParam, defParam;
s8 buff, accStage, evasionStage; s8 buff, accStage, evasionStage;
gPotentialItemEffectBattler = battlerDef; gPotentialItemEffectBattler = battlerDef;
accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; accStage = gBattleMons[battlerAtk].statStages[STAT_ACC];
evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION]; evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION];
@ -1366,25 +1366,25 @@ bool32 IsMoveEncouragedToHit(u8 battlerAtk, u8 battlerDef, u16 move)
{ {
if (IsSemiInvulnerable(battlerDef, move)) if (IsSemiInvulnerable(battlerDef, move))
return FALSE; return FALSE;
//TODO - anticipate protect move? //TODO - anticipate protect move?
// always hits // always hits
if (gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS || gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) if (gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS || gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk)
return TRUE; return TRUE;
if (AI_GetAbility(battlerDef) == ABILITY_NO_GUARD || AI_GetAbility(battlerAtk) == ABILITY_NO_GUARD) if (AI_GetAbility(battlerDef) == ABILITY_NO_GUARD || AI_GetAbility(battlerAtk) == ABILITY_NO_GUARD)
return TRUE; return TRUE;
if (B_TOXIC_NEVER_MISS >= GEN_6 && gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) if (B_TOXIC_NEVER_MISS >= GEN_6 && gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
return TRUE; return TRUE;
// discouraged from hitting // discouraged from hitting
if (AI_WeatherHasEffect() && (gBattleWeather & WEATHER_SUN_ANY) if (AI_WeatherHasEffect() && (gBattleWeather & WEATHER_SUN_ANY)
&& (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE)) && (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
return FALSE; return FALSE;
// increased accuracy but don't always hit // increased accuracy but don't always hit
if ((AI_WeatherHasEffect() && if ((AI_WeatherHasEffect() &&
(((gBattleWeather & WEATHER_RAIN_ANY) && (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE)) (((gBattleWeather & WEATHER_RAIN_ANY) && (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
|| (((gBattleWeather & WEATHER_HAIL_ANY) && move == MOVE_BLIZZARD)))) || (((gBattleWeather & WEATHER_HAIL_ANY) && move == MOVE_BLIZZARD))))
@ -1394,23 +1394,23 @@ bool32 IsMoveEncouragedToHit(u8 battlerAtk, u8 battlerDef, u16 move)
{ {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
bool32 ShouldTryOHKO(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u32 accuracy, u16 move) bool32 ShouldTryOHKO(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u32 accuracy, u16 move)
{ {
u32 holdEffect = AI_GetHoldEffect(battlerDef); u32 holdEffect = AI_GetHoldEffect(battlerDef);
gPotentialItemEffectBattler = battlerDef; gPotentialItemEffectBattler = battlerDef;
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < GetBattlerHoldEffectParam(battlerDef)) if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < GetBattlerHoldEffectParam(battlerDef))
return FALSE; //probabilistically speaking, focus band should activate so dont OHKO return FALSE; //probabilistically speaking, focus band should activate so dont OHKO
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && AtMaxHp(battlerDef)) else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && AtMaxHp(battlerDef))
return FALSE; return FALSE;
if (!DoesBattlerIgnoreAbilityChecks(atkAbility, move) && defAbility == ABILITY_STURDY) if (!DoesBattlerIgnoreAbilityChecks(atkAbility, move) && defAbility == ABILITY_STURDY)
return FALSE; return FALSE;
if ((((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS) if ((((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS)
&& gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk)
|| atkAbility == ABILITY_NO_GUARD || defAbility == ABILITY_NO_GUARD) || atkAbility == ABILITY_NO_GUARD || defAbility == ABILITY_NO_GUARD)
@ -1433,7 +1433,7 @@ bool32 ShouldSetSandstorm(u8 battler, u16 ability, u16 holdEffect)
return FALSE; return FALSE;
else if (gBattleWeather & WEATHER_SANDSTORM_ANY) else if (gBattleWeather & WEATHER_SANDSTORM_ANY)
return FALSE; return FALSE;
if (ability == ABILITY_SAND_VEIL if (ability == ABILITY_SAND_VEIL
|| ability == ABILITY_SAND_RUSH || ability == ABILITY_SAND_RUSH
|| ability == ABILITY_SAND_FORCE || ability == ABILITY_SAND_FORCE
@ -1458,7 +1458,7 @@ bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect)
return FALSE; return FALSE;
else if (gBattleWeather & WEATHER_HAIL_ANY) else if (gBattleWeather & WEATHER_HAIL_ANY)
return FALSE; return FALSE;
if (ability == ABILITY_SNOW_CLOAK if (ability == ABILITY_SNOW_CLOAK
|| ability == ABILITY_ICE_BODY || ability == ABILITY_ICE_BODY
|| ability == ABILITY_FORECAST || ability == ABILITY_FORECAST
@ -1472,7 +1472,7 @@ bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect)
|| HasMoveEffect(battler, EFFECT_WEATHER_BALL)) || HasMoveEffect(battler, EFFECT_WEATHER_BALL))
{ {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
@ -1482,7 +1482,7 @@ bool32 ShouldSetRain(u8 battlerAtk, u16 atkAbility, u16 holdEffect)
return FALSE; return FALSE;
else if (gBattleWeather & WEATHER_RAIN_ANY) else if (gBattleWeather & WEATHER_RAIN_ANY)
return FALSE; return FALSE;
if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA
&& (atkAbility == ABILITY_SWIFT_SWIM && (atkAbility == ABILITY_SWIFT_SWIM
|| atkAbility == ABILITY_FORECAST || atkAbility == ABILITY_FORECAST
@ -1505,7 +1505,7 @@ bool32 ShouldSetSun(u8 battlerAtk, u16 atkAbility, u16 holdEffect)
return FALSE; return FALSE;
else if (gBattleWeather & WEATHER_SUN_ANY) else if (gBattleWeather & WEATHER_SUN_ANY)
return FALSE; return FALSE;
if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA
&& (atkAbility == ABILITY_CHLOROPHYLL && (atkAbility == ABILITY_CHLOROPHYLL
|| atkAbility == ABILITY_FLOWER_GIFT || atkAbility == ABILITY_FLOWER_GIFT
@ -1533,13 +1533,13 @@ void ProtectChecks(u8 battlerAtk, u8 battlerDef, u16 move, u16 predictedMove, s1
u16 predictedEffect = gBattleMoves[predictedMove].effect; u16 predictedEffect = gBattleMoves[predictedMove].effect;
u8 defAbility = AI_GetAbility(battlerDef); u8 defAbility = AI_GetAbility(battlerDef);
u32 uses = gDisableStructs[battlerAtk].protectUses; u32 uses = gDisableStructs[battlerAtk].protectUses;
/*if (GetMoveResultFlags(predictedMove) & (MOVE_RESULT_NO_EFFECT | MOVE_RESULT_MISSED)) /*if (GetMoveResultFlags(predictedMove) & (MOVE_RESULT_NO_EFFECT | MOVE_RESULT_MISSED))
{ {
(*score) -= 5; (*score) -= 5;
return; return;
}*/ }*/
if (uses == 0) if (uses == 0)
{ {
if (predictedMove != MOVE_NONE && predictedMove != 0xFFFF && !IS_MOVE_STATUS(predictedMove)) if (predictedMove != MOVE_NONE && predictedMove != 0xFFFF && !IS_MOVE_STATUS(predictedMove))
@ -1561,7 +1561,7 @@ void ProtectChecks(u8 battlerAtk, u8 battlerDef, u16 move, u16 predictedMove, s1
{ {
(*score)--; (*score)--;
} }
if (gBattleMons[battlerDef].status1 & STATUS1_TOXIC_POISON if (gBattleMons[battlerDef].status1 & STATUS1_TOXIC_POISON
|| gBattleMons[battlerDef].status2 & (STATUS2_CURSED | STATUS2_INFATUATION) || gBattleMons[battlerDef].status2 & (STATUS2_CURSED | STATUS2_INFATUATION)
|| gStatuses3[battlerDef] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED | STATUS3_YAWN)) || gStatuses3[battlerDef] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED | STATUS3_YAWN))
@ -1578,10 +1578,10 @@ bool32 ShouldLowerStat(u8 battler, u16 battlerAbility, u8 stat)
|| battlerAbility == ABILITY_WHITE_SMOKE || battlerAbility == ABILITY_WHITE_SMOKE
|| battlerAbility == ABILITY_FULL_METAL_BODY) || battlerAbility == ABILITY_FULL_METAL_BODY)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
@ -1595,7 +1595,7 @@ bool32 BattlerStatCanRise(u8 battler, u16 battlerAbility, u8 stat)
bool32 AreBattlersStatsMaxed(u8 battlerId) bool32 AreBattlersStatsMaxed(u8 battlerId)
{ {
u32 i; u32 i;
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
{ {
if (gBattleMons[battlerId].statStages[i] < MAX_STAT_STAGE) if (gBattleMons[battlerId].statStages[i] < MAX_STAT_STAGE)
@ -1607,7 +1607,7 @@ bool32 AreBattlersStatsMaxed(u8 battlerId)
bool32 AnyStatIsRaised(u8 battlerId) bool32 AnyStatIsRaised(u8 battlerId)
{ {
u32 i; u32 i;
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
{ {
if (gBattleMons[battlerId].statStages[i] > DEFAULT_STAT_STAGE) if (gBattleMons[battlerId].statStages[i] > DEFAULT_STAT_STAGE)
@ -1747,10 +1747,10 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility)
bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits) bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits)
{ {
s32 dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][index]; s32 dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][index];
if (numHits) if (numHits)
dmg *= numHits; dmg *= numHits;
if (gBattleMons[battlerDef].hp <= dmg) if (gBattleMons[battlerDef].hp <= dmg)
return TRUE; return TRUE;
return FALSE; return FALSE;
@ -1776,7 +1776,7 @@ bool32 HasOnlyMovesWithSplit(u32 battlerId, u32 split, bool32 onlyOffensive)
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && GetBattleMoveSplit(moves[i]) != split) if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && GetBattleMoveSplit(moves[i]) != split)
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
@ -1841,12 +1841,12 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32
s32 i; s32 i;
u16 *moves = GetMovesArray(battlerAtk); u16 *moves = GetMovesArray(battlerAtk);
u8 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF); u8 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF);
for (i = 0; i < MAX_MON_MOVES; i++) for (i = 0; i < MAX_MON_MOVES; i++)
{ {
if (moves[i] == MOVE_NONE || moves[i] == 0xFFFF) if (moves[i] == MOVE_NONE || moves[i] == 0xFFFF)
continue; continue;
if (!(gBitTable[i] & moveLimitations)) if (!(gBitTable[i] & moveLimitations))
{ {
if (ignoreStatus && IS_MOVE_STATUS(moves[i])) if (ignoreStatus && IS_MOVE_STATUS(moves[i]))
@ -1854,12 +1854,12 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32
else if ((!IS_MOVE_STATUS(moves[i]) && gBattleMoves[moves[i]].accuracy == 0) else if ((!IS_MOVE_STATUS(moves[i]) && gBattleMoves[moves[i]].accuracy == 0)
|| gBattleMoves[moves[i]].target & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD)) || gBattleMoves[moves[i]].target & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
continue; continue;
if (AI_GetMoveAccuracy(battlerAtk, battlerDef, atkAbility, defAbility, atkHoldEffect, defHoldEffect, moves[i]) <= accCheck) if (AI_GetMoveAccuracy(battlerAtk, battlerDef, atkAbility, defAbility, atkHoldEffect, defHoldEffect, moves[i]) <= accCheck)
return TRUE; return TRUE;
} }
} }
return FALSE; return FALSE;
} }
@ -1868,7 +1868,7 @@ bool32 HasSleepMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef)
u8 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF); u8 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF);
u32 i; u32 i;
u16 *moves = GetMovesArray(battlerAtk); u16 *moves = GetMovesArray(battlerAtk);
for (i = 0; i < MAX_MON_MOVES; i++) for (i = 0; i < MAX_MON_MOVES; i++)
{ {
if (moves[i] == MOVE_NONE) if (moves[i] == MOVE_NONE)
@ -2067,7 +2067,7 @@ bool32 HasDamagingMove(u8 battlerId)
{ {
u32 i; u32 i;
u16 *moves = GetMovesArray(battlerId); u16 *moves = GetMovesArray(battlerId);
for (i = 0; i < MAX_MON_MOVES; i++) for (i = 0; i < MAX_MON_MOVES; i++)
{ {
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && gBattleMoves[moves[i]].power != 0) if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && gBattleMoves[moves[i]].power != 0)
@ -2106,7 +2106,7 @@ bool32 IsInstructBannedMove(u16 move)
bool32 IsEncoreEncouragedEffect(u16 moveEffect) bool32 IsEncoreEncouragedEffect(u16 moveEffect)
{ {
u32 i; u32 i;
for (i = 0; i < ARRAY_COUNT(sEncouragedEncoreEffects); i++) for (i = 0; i < ARRAY_COUNT(sEncouragedEncoreEffects); i++)
{ {
if (moveEffect == sEncouragedEncoreEffects[i]) if (moveEffect == sEncouragedEncoreEffects[i])
@ -2208,10 +2208,10 @@ static u32 GetTrapDamage(u8 battlerId)
static u32 GetPoisonDamage(u8 battlerId) static u32 GetPoisonDamage(u8 battlerId)
{ {
u32 damage = 0; u32 damage = 0;
if (AI_GetAbility(battlerId) == ABILITY_POISON_HEAL) if (AI_GetAbility(battlerId) == ABILITY_POISON_HEAL)
return damage; return damage;
if (gBattleMons[battlerId].status1 & STATUS1_POISON) if (gBattleMons[battlerId].status1 & STATUS1_POISON)
{ {
damage = gBattleMons[battlerId].maxHP / 8; damage = gBattleMons[battlerId].maxHP / 8;
@ -2260,7 +2260,7 @@ static u32 GetWeatherDamage(u8 battlerId)
u32 damage = 0; u32 damage = 0;
if (!AI_WeatherHasEffect()) if (!AI_WeatherHasEffect())
return 0; return 0;
if (gBattleWeather & WEATHER_SANDSTORM_ANY) if (gBattleWeather & WEATHER_SANDSTORM_ANY)
{ {
if (BattlerAffectedBySandstorm(battlerId, ability) if (BattlerAffectedBySandstorm(battlerId, ability)
@ -2289,17 +2289,17 @@ static u32 GetWeatherDamage(u8 battlerId)
u32 GetBattlerSecondaryDamage(u8 battlerId) u32 GetBattlerSecondaryDamage(u8 battlerId)
{ {
u32 secondaryDamage; u32 secondaryDamage;
if (AI_GetAbility(battlerId) == ABILITY_MAGIC_GUARD) if (AI_GetAbility(battlerId) == ABILITY_MAGIC_GUARD)
return FALSE; return FALSE;
secondaryDamage = GetLeechSeedDamage(battlerId) secondaryDamage = GetLeechSeedDamage(battlerId)
+ GetNightmareDamage(battlerId) + GetNightmareDamage(battlerId)
+ GetCurseDamage(battlerId) + GetCurseDamage(battlerId)
+ GetTrapDamage(battlerId) + GetTrapDamage(battlerId)
+ GetPoisonDamage(battlerId) + GetPoisonDamage(battlerId)
+ GetWeatherDamage(battlerId); + GetWeatherDamage(battlerId);
return secondaryDamage; return secondaryDamage;
} }
@ -2323,7 +2323,7 @@ bool32 BattlerWillFaintFromSecondaryDamage(u8 battler, u16 ability)
static bool32 AnyUsefulStatIsRaised(u8 battler) static bool32 AnyUsefulStatIsRaised(u8 battler)
{ {
u8 statId; u8 statId;
for (statId = STAT_ATK; statId < NUM_BATTLE_STATS; statId++) for (statId = STAT_ATK; statId < NUM_BATTLE_STATS; statId++)
{ {
if (gBattleMons[battler].statStages[statId] > DEFAULT_STAT_STAGE) if (gBattleMons[battler].statStages[statId] > DEFAULT_STAT_STAGE)
@ -2353,17 +2353,17 @@ static bool32 PartyBattlerShouldAvoidHazards(u8 currBattler, u8 switchBattler)
u16 ability = GetMonAbility(mon); // we know our own party data u16 ability = GetMonAbility(mon); // we know our own party data
u16 holdEffect = GetBattlerHoldEffect(GetMonData(mon, MON_DATA_HELD_ITEM), TRUE); u16 holdEffect = GetBattlerHoldEffect(GetMonData(mon, MON_DATA_HELD_ITEM), TRUE);
u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES); u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES);
if (flags == 0) if (flags == 0)
return FALSE; return FALSE;
if (ability == ABILITY_MAGIC_GUARD || ability == ABILITY_LEVITATE if (ability == ABILITY_MAGIC_GUARD || ability == ABILITY_LEVITATE
|| holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS) || holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS)
return FALSE; return FALSE;
if (flags & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK) && GetMonData(mon, MON_DATA_HP) < (GetMonData(mon, MON_DATA_MAX_HP) / 8)) if (flags & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK) && GetMonData(mon, MON_DATA_HP) < (GetMonData(mon, MON_DATA_MAX_HP) / 8))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
@ -2378,9 +2378,9 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo
u8 backupBattler = gActiveBattler; u8 backupBattler = gActiveBattler;
bool32 shouldSwitch; bool32 shouldSwitch;
u8 battlerToSwitch; u8 battlerToSwitch;
gActiveBattler = battlerAtk; gActiveBattler = battlerAtk;
shouldSwitch = ShouldSwitch(); shouldSwitch = ShouldSwitch();
battlerToSwitch = *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler); battlerToSwitch = *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler);
gActiveBattler = backupBattler; gActiveBattler = backupBattler;
@ -2558,7 +2558,7 @@ bool32 CanKnockOffItem(u8 battler, u16 item)
#endif #endif
)) && GetBattlerSide(battler) == B_SIDE_PLAYER) )) && GetBattlerSide(battler) == B_SIDE_PLAYER)
return FALSE; return FALSE;
if (AI_GetAbility(battler) == ABILITY_STICKY_HOLD) if (AI_GetAbility(battler) == ABILITY_STICKY_HOLD)
return FALSE; return FALSE;
@ -2573,7 +2573,7 @@ bool32 IsBattlerIncapacitated(u8 battler, u16 ability)
{ {
if ((gBattleMons[battler].status1 & STATUS1_FREEZE) && !HasThawingMove(battler)) if ((gBattleMons[battler].status1 & STATUS1_FREEZE) && !HasThawingMove(battler))
return TRUE; // if battler has thawing move we assume they will definitely use it, and thus being frozen should be neglected return TRUE; // if battler has thawing move we assume they will definitely use it, and thus being frozen should be neglected
if (gBattleMons[battler].status1 & STATUS1_SLEEP) if (gBattleMons[battler].status1 & STATUS1_SLEEP)
return TRUE; return TRUE;
@ -2686,7 +2686,7 @@ bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtk
{ {
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
@ -2767,7 +2767,7 @@ bool32 ShouldTrap(u8 battlerAtk, u8 battlerDef, u16 move)
{ {
if (BattlerWillFaintFromSecondaryDamage(battlerDef, AI_DATA->defAbility)) if (BattlerWillFaintFromSecondaryDamage(battlerDef, AI_DATA->defAbility))
return TRUE; // battler is taking secondary damage with low HP return TRUE; // battler is taking secondary damage with low HP
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL) if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL)
{ {
if (!CanTargetFaintAi(battlerDef, battlerAtk)) if (!CanTargetFaintAi(battlerDef, battlerAtk))
@ -2781,12 +2781,12 @@ bool32 ShouldFakeOut(u8 battlerAtk, u8 battlerDef, u16 move)
{ {
if (AI_DATA->atkHoldEffect == HOLD_EFFECT_CHOICE_BAND && CountUsablePartyMons(battlerAtk) == 0) if (AI_DATA->atkHoldEffect == HOLD_EFFECT_CHOICE_BAND && CountUsablePartyMons(battlerAtk) == 0)
return FALSE; // don't lock attacker into fake out if can't switch out return FALSE; // don't lock attacker into fake out if can't switch out
if (gDisableStructs[battlerAtk].isFirstTurn if (gDisableStructs[battlerAtk].isFirstTurn
&& ShouldTryToFlinch(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, move) && ShouldTryToFlinch(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, move)
&& !DoesSubstituteBlockMove(battlerAtk, battlerDef, move)) && !DoesSubstituteBlockMove(battlerAtk, battlerDef, move))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
@ -2814,12 +2814,12 @@ bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof)
{ {
struct Pokemon *party; struct Pokemon *party;
u32 i; u32 i;
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
party = gPlayerParty; party = gPlayerParty;
else else
party = gEnemyParty; party = gEnemyParty;
for (i = 0; i < PARTY_SIZE; i++) for (i = 0; i < PARTY_SIZE; i++)
{ {
if (checkSoundproof && GetMonAbility(&party[i]) == ABILITY_SOUNDPROOF) if (checkSoundproof && GetMonAbility(&party[i]) == ABILITY_SOUNDPROOF)
@ -2863,21 +2863,21 @@ bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveI
else else
return FALSE; //Not as good to use move if you'll faint and not win return FALSE; //Not as good to use move if you'll faint and not win
} }
return TRUE; return TRUE;
} }
bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage) bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage)
{ {
if (move == 0xFFFF || GetWhoStrikesFirst(battlerAtk, gBattlerTarget, TRUE) == 0) if (move == 0xFFFF || GetWhoStrikesFirst(battlerAtk, gBattlerTarget, TRUE) == 0)
{ {
// using item or user goes first // using item or user goes first
u8 healPercent = (gBattleMoves[move].argument == 0) ? 50 : gBattleMoves[move].argument; u8 healPercent = (gBattleMoves[move].argument == 0) ? 50 : gBattleMoves[move].argument;
s32 healDmg = (healPercent * damage) / 100; s32 healDmg = (healPercent * damage) / 100;
if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK)
healDmg = 0; healDmg = 0;
if (CanTargetFaintAi(battlerDef, battlerAtk) if (CanTargetFaintAi(battlerDef, battlerAtk)
&& !CanTargetFaintAiWithMod(battlerDef, battlerAtk, healDmg, 0)) && !CanTargetFaintAiWithMod(battlerDef, battlerAtk, healDmg, 0))
return TRUE; // target can faint attacker unless they heal return TRUE; // target can faint attacker unless they heal
@ -2890,7 +2890,7 @@ bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage)
if (!CanTargetFaintAi(battlerDef, battlerAtk)) if (!CanTargetFaintAi(battlerDef, battlerAtk))
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
@ -2953,7 +2953,7 @@ bool32 IsValidDoubleBattle(u8 battlerAtk)
u16 GetAllyChosenMove(void) u16 GetAllyChosenMove(void)
{ {
u8 partnerBattler = BATTLE_PARTNER(sBattler_AI); u8 partnerBattler = BATTLE_PARTNER(sBattler_AI);
if (!IsBattlerAlive(partnerBattler) || !IsBattlerAIControlled(partnerBattler)) if (!IsBattlerAlive(partnerBattler) || !IsBattlerAIControlled(partnerBattler))
return MOVE_NONE; // TODO: prediction? return MOVE_NONE; // TODO: prediction?
else if (partnerBattler > sBattler_AI) // Battler with the lower id chooses the move first. else if (partnerBattler > sBattler_AI) // Battler with the lower id chooses the move first.
@ -2966,7 +2966,7 @@ bool32 IsTargetingPartner(u8 battlerAtk, u8 battlerDef)
{ {
if ((battlerAtk & BIT_SIDE) == (battlerDef & BIT_SIDE)) if ((battlerAtk & BIT_SIDE) == (battlerDef & BIT_SIDE))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
@ -2975,7 +2975,7 @@ bool32 DoesPartnerHaveSameMoveEffect(u8 battlerAtkPartner, u8 battlerDef, u16 mo
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
if (gBattleMoves[move].effect == gBattleMoves[partnerMove].effect if (gBattleMoves[move].effect == gBattleMoves[partnerMove].effect
&& gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE && gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE
&& gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef) && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef)
@ -2990,7 +2990,7 @@ bool32 PartnerHasSameMoveEffectWithoutTarget(u8 battlerAtkPartner, u16 move, u16
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
if (gBattleMoves[move].effect == gBattleMoves[partnerMove].effect if (gBattleMoves[move].effect == gBattleMoves[partnerMove].effect
&& gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE) && gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE)
return TRUE; return TRUE;
@ -3002,7 +3002,7 @@ bool32 PartnerMoveEffectIsStatusSameTarget(u8 battlerAtkPartner, u8 battlerDef,
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE
&& gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef
&& (gBattleMoves[partnerMove].effect == EFFECT_SLEEP && (gBattleMoves[partnerMove].effect == EFFECT_SLEEP
@ -3020,14 +3020,14 @@ bool32 PartnerMoveEffectIsWeather(u8 battlerAtkPartner, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE
&& (gBattleMoves[partnerMove].effect == EFFECT_SUNNY_DAY && (gBattleMoves[partnerMove].effect == EFFECT_SUNNY_DAY
|| gBattleMoves[partnerMove].effect == EFFECT_RAIN_DANCE || gBattleMoves[partnerMove].effect == EFFECT_RAIN_DANCE
|| gBattleMoves[partnerMove].effect == EFFECT_SANDSTORM || gBattleMoves[partnerMove].effect == EFFECT_SANDSTORM
|| gBattleMoves[partnerMove].effect == EFFECT_HAIL)) || gBattleMoves[partnerMove].effect == EFFECT_HAIL))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
@ -3036,14 +3036,14 @@ bool32 PartnerMoveEffectIsTerrain(u8 battlerAtkPartner, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE
&& (gBattleMoves[partnerMove].effect == EFFECT_GRASSY_TERRAIN && (gBattleMoves[partnerMove].effect == EFFECT_GRASSY_TERRAIN
|| gBattleMoves[partnerMove].effect == EFFECT_MISTY_TERRAIN || gBattleMoves[partnerMove].effect == EFFECT_MISTY_TERRAIN
|| gBattleMoves[partnerMove].effect == EFFECT_ELECTRIC_TERRAIN || gBattleMoves[partnerMove].effect == EFFECT_ELECTRIC_TERRAIN
|| gBattleMoves[partnerMove].effect == EFFECT_PSYCHIC_TERRAIN)) || gBattleMoves[partnerMove].effect == EFFECT_PSYCHIC_TERRAIN))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
@ -3052,7 +3052,7 @@ bool32 PartnerMoveIs(u8 battlerAtkPartner, u16 partnerMove, u16 moveCheck)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE && partnerMove == moveCheck) if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE && partnerMove == moveCheck)
return TRUE; return TRUE;
return FALSE; return FALSE;
@ -3063,7 +3063,7 @@ bool32 PartnerMoveIsSameAsAttacker(u8 battlerAtkPartner, u8 battlerDef, u16 move
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE && move == partnerMove && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef) if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE && move == partnerMove && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef)
return TRUE; return TRUE;
return FALSE; return FALSE;
@ -3088,7 +3088,7 @@ bool32 ShouldUseWishAromatherapy(u8 battlerAtk, u8 battlerDef, u16 move)
bool32 needHealing = FALSE; bool32 needHealing = FALSE;
GetAIPartyIndexes(battlerAtk, &firstId, &lastId); GetAIPartyIndexes(battlerAtk, &firstId, &lastId);
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
party = gPlayerParty; party = gPlayerParty;
else else
@ -3208,12 +3208,12 @@ bool32 IsPartyFullyHealedExceptBattler(u8 battlerId)
{ {
struct Pokemon *party; struct Pokemon *party;
u32 i; u32 i;
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
party = gPlayerParty; party = gPlayerParty;
else else
party = gEnemyParty; party = gEnemyParty;
for (i = 0; i < PARTY_SIZE; i++) for (i = 0; i < PARTY_SIZE; i++)
{ {
if (i != gBattlerPartyIndexes[battlerId] if (i != gBattlerPartyIndexes[battlerId]
@ -3236,7 +3236,7 @@ bool32 PartyHasMoveSplit(u8 battlerId, u8 split)
{ {
if (GetMonData(&party[i], MON_DATA_HP, NULL) == 0) if (GetMonData(&party[i], MON_DATA_HP, NULL) == 0)
continue; continue;
for (j = 0; j < MAX_MON_MOVES; j++) for (j = 0; j < MAX_MON_MOVES; j++)
{ {
u16 move = GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL); u16 move = GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL);
@ -3281,7 +3281,7 @@ s8 GetAbilityRating(u16 ability)
return sAiAbilityRatings[ability]; return sAiAbilityRatings[ability];
} }
static const u16 sRecycleEncouragedItems[] = static const u16 sRecycleEncouragedItems[] =
{ {
ITEM_CHESTO_BERRY, ITEM_CHESTO_BERRY,
ITEM_LUM_BERRY, ITEM_LUM_BERRY,
@ -3309,15 +3309,15 @@ bool32 IsRecycleEncouragedItem(u16 item)
// score increases // score increases
#define STAT_UP_2_STAGE 8 #define STAT_UP_2_STAGE 8
#define STAT_UP_STAGE 10 #define STAT_UP_STAGE 10
void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score) void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score)
{ {
if (AI_DATA->atkAbility == ABILITY_CONTRARY) if (AI_DATA->atkAbility == ABILITY_CONTRARY)
return; return;
if (GetHealthPercentage(battlerAtk) < 80 && AI_RandLessThan(128)) if (GetHealthPercentage(battlerAtk) < 80 && AI_RandLessThan(128))
return; return;
switch (statId) switch (statId)
{ {
case STAT_ATK: case STAT_ATK:
@ -3393,10 +3393,10 @@ void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
{ {
if (!HasDamagingMove(battlerDef)) if (!HasDamagingMove(battlerDef))
*score += 2; *score += 2;
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL && HasMoveEffect(battlerAtk, EFFECT_PROTECT)) if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL && HasMoveEffect(battlerAtk, EFFECT_PROTECT))
(*score)++; // stall tactic (*score)++; // stall tactic
if (HasMoveEffect(battlerAtk, EFFECT_VENOSHOCK) if (HasMoveEffect(battlerAtk, EFFECT_VENOSHOCK)
|| HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(battlerAtk, EFFECT_HEX)
|| HasMoveEffect(battlerAtk, EFFECT_VENOM_DRENCH) || HasMoveEffect(battlerAtk, EFFECT_VENOM_DRENCH)
@ -3417,7 +3417,7 @@ void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
if (CanTargetFaintAi(battlerDef, battlerAtk)) if (CanTargetFaintAi(battlerDef, battlerAtk))
*score += 2; // burning the target to stay alive is cool *score += 2; // burning the target to stay alive is cool
} }
if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_HEX)) if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_HEX))
(*score)++; (*score)++;
} }
@ -3429,7 +3429,7 @@ void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
{ {
u8 atkSpeed = GetBattlerTotalSpeedStat(battlerAtk); u8 atkSpeed = GetBattlerTotalSpeedStat(battlerAtk);
u8 defSpeed = GetBattlerTotalSpeedStat(battlerDef); u8 defSpeed = GetBattlerTotalSpeedStat(battlerDef);
if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe
|| HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(battlerAtk, EFFECT_HEX)
|| HasMoveEffect(battlerAtk, EFFECT_FLINCH_HIT) || HasMoveEffect(battlerAtk, EFFECT_FLINCH_HIT)
@ -3447,11 +3447,11 @@ void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
*score += 2; *score += 2;
else else
return; return;
if ((HasMoveEffect(battlerAtk, EFFECT_DREAM_EATER) || HasMoveEffect(battlerAtk, EFFECT_NIGHTMARE)) if ((HasMoveEffect(battlerAtk, EFFECT_DREAM_EATER) || HasMoveEffect(battlerAtk, EFFECT_NIGHTMARE))
&& !(HasMoveEffect(battlerDef, EFFECT_SNORE) || HasMoveEffect(battlerDef, EFFECT_SLEEP_TALK))) && !(HasMoveEffect(battlerDef, EFFECT_SNORE) || HasMoveEffect(battlerDef, EFFECT_SLEEP_TALK)))
(*score)++; (*score)++;
if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_HEX)) if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_HEX))
(*score)++; (*score)++;
} }

View File

@ -7408,7 +7408,7 @@ static void Cmd_various(void)
case VARIOUS_SET_MAGIC_COAT_TARGET: case VARIOUS_SET_MAGIC_COAT_TARGET:
gBattlerAttacker = gBattlerTarget; gBattlerAttacker = gBattlerTarget;
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
if (gSideTimers[side].followmeTimer != 0 && gBattleMons[gSideTimers[side].followmeTarget].hp != 0) if (IsAffectedByFollowMe(gBattlerAttacker, side))
gBattlerTarget = gSideTimers[side].followmeTarget; gBattlerTarget = gSideTimers[side].followmeTarget;
else else
gBattlerTarget = gActiveBattler; gBattlerTarget = gActiveBattler;
@ -9980,7 +9980,7 @@ static void Cmd_counterdamagecalculator(void)
{ {
gBattleMoveDamage = gProtectStructs[gBattlerAttacker].physicalDmg * 2; gBattleMoveDamage = gProtectStructs[gBattlerAttacker].physicalDmg * 2;
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp) if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget))
gBattlerTarget = gSideTimers[sideTarget].followmeTarget; gBattlerTarget = gSideTimers[sideTarget].followmeTarget;
else else
gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId;
@ -9999,11 +9999,13 @@ static void Cmd_mirrorcoatdamagecalculator(void) // a copy of atkA1 with the phy
u8 sideAttacker = GetBattlerSide(gBattlerAttacker); u8 sideAttacker = GetBattlerSide(gBattlerAttacker);
u8 sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId); u8 sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId);
if (gProtectStructs[gBattlerAttacker].specialDmg && sideAttacker != sideTarget && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) if (gProtectStructs[gBattlerAttacker].specialDmg
&& sideAttacker != sideTarget
&& gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp)
{ {
gBattleMoveDamage = gProtectStructs[gBattlerAttacker].specialDmg * 2; gBattleMoveDamage = gProtectStructs[gBattlerAttacker].specialDmg * 2;
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp) if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget))
gBattlerTarget = gSideTimers[sideTarget].followmeTarget; gBattlerTarget = gSideTimers[sideTarget].followmeTarget;
else else
gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId;
@ -11084,6 +11086,7 @@ static void Cmd_setforcedtarget(void) // follow me
{ {
gSideTimers[GetBattlerSide(gBattlerAttacker)].followmeTimer = 1; gSideTimers[GetBattlerSide(gBattlerAttacker)].followmeTimer = 1;
gSideTimers[GetBattlerSide(gBattlerAttacker)].followmeTarget = gBattlerAttacker; gSideTimers[GetBattlerSide(gBattlerAttacker)].followmeTarget = gBattlerAttacker;
gSideTimers[GetBattlerSide(gBattlerAttacker)].followmePowder = TestMoveFlags(gCurrentMove, FLAG_POWDER);
gBattlescriptCurrInstr++; gBattlescriptCurrInstr++;
} }
@ -12557,7 +12560,7 @@ static void Cmd_metalburstdamagecalculator(void)
{ {
gBattleMoveDamage = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100; gBattleMoveDamage = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100;
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp) if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget))
gBattlerTarget = gSideTimers[sideTarget].followmeTarget; gBattlerTarget = gSideTimers[sideTarget].followmeTarget;
else else
gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId;
@ -12570,7 +12573,7 @@ static void Cmd_metalburstdamagecalculator(void)
{ {
gBattleMoveDamage = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100; gBattleMoveDamage = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100;
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp) if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget))
gBattlerTarget = gSideTimers[sideTarget].followmeTarget; gBattlerTarget = gSideTimers[sideTarget].followmeTarget;
else else
gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId;

View File

@ -90,7 +90,7 @@ static const u8 sPkblToEscapeFactor[][3] = {
static const u8 sGoNearCounterToCatchFactor[] = {4, 3, 2, 1}; static const u8 sGoNearCounterToCatchFactor[] = {4, 3, 2, 1};
static const u8 sGoNearCounterToEscapeFactor[] = {4, 4, 4, 4}; static const u8 sGoNearCounterToEscapeFactor[] = {4, 4, 4, 4};
static const u16 sSkillSwapBannedAbilities[] = static const u16 sSkillSwapBannedAbilities[] =
{ {
ABILITY_WONDER_GUARD, ABILITY_WONDER_GUARD,
ABILITY_MULTITYPE, ABILITY_MULTITYPE,
@ -109,9 +109,9 @@ static const u16 sSkillSwapBannedAbilities[] =
ABILITY_GULP_MISSILE, ABILITY_GULP_MISSILE,
}; };
static const u16 sRolePlayBannedAbilities[] = static const u16 sRolePlayBannedAbilities[] =
{ {
ABILITY_TRACE, ABILITY_TRACE,
ABILITY_WONDER_GUARD, ABILITY_WONDER_GUARD,
ABILITY_FORECAST, ABILITY_FORECAST,
ABILITY_FLOWER_GIFT, ABILITY_FLOWER_GIFT,
@ -134,7 +134,7 @@ static const u16 sRolePlayBannedAbilities[] =
ABILITY_GULP_MISSILE, ABILITY_GULP_MISSILE,
}; };
static const u16 sRolePlayBannedAttackerAbilities[] = static const u16 sRolePlayBannedAttackerAbilities[] =
{ {
ABILITY_MULTITYPE, ABILITY_MULTITYPE,
ABILITY_ZEN_MODE, ABILITY_ZEN_MODE,
@ -150,7 +150,7 @@ static const u16 sRolePlayBannedAttackerAbilities[] =
ABILITY_GULP_MISSILE, ABILITY_GULP_MISSILE,
}; };
static const u16 sWorrySeedBannedAbilities[] = static const u16 sWorrySeedBannedAbilities[] =
{ {
ABILITY_MULTITYPE, ABILITY_MULTITYPE,
ABILITY_STANCE_CHANGE, ABILITY_STANCE_CHANGE,
@ -166,7 +166,7 @@ static const u16 sWorrySeedBannedAbilities[] =
ABILITY_GULP_MISSILE, ABILITY_GULP_MISSILE,
}; };
static const u16 sGastroAcidBannedAbilities[] = static const u16 sGastroAcidBannedAbilities[] =
{ {
ABILITY_AS_ONE_ICE_RIDER, ABILITY_AS_ONE_ICE_RIDER,
ABILITY_AS_ONE_SHADOW_RIDER, ABILITY_AS_ONE_SHADOW_RIDER,
@ -184,7 +184,7 @@ static const u16 sGastroAcidBannedAbilities[] =
ABILITY_ZEN_MODE, ABILITY_ZEN_MODE,
}; };
static const u16 sEntrainmentBannedAttackerAbilities[] = static const u16 sEntrainmentBannedAttackerAbilities[] =
{ {
ABILITY_TRACE, ABILITY_TRACE,
ABILITY_FORECAST, ABILITY_FORECAST,
@ -202,7 +202,7 @@ static const u16 sEntrainmentBannedAttackerAbilities[] =
ABILITY_GULP_MISSILE, ABILITY_GULP_MISSILE,
}; };
static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] = static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
{ {
ABILITY_TRUANT, ABILITY_TRUANT,
ABILITY_MULTITYPE, ABILITY_MULTITYPE,
@ -217,6 +217,21 @@ static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
ABILITY_GULP_MISSILE, ABILITY_GULP_MISSILE,
}; };
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide)
{
u32 ability = GetBattlerAbility(battlerAtk);
if (gSideTimers[defSide].followmeTimer == 0
|| gBattleMons[gSideTimers[defSide].followmeTarget].hp == 0
|| ability == ABILITY_PROPELLER_TAIL || ability == ABILITY_STALWART)
return FALSE;
if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE)))
return FALSE;
return TRUE;
}
// Functions // Functions
void HandleAction_UseMove(void) void HandleAction_UseMove(void)
{ {
@ -292,12 +307,9 @@ void HandleAction_UseMove(void)
// choose target // choose target
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
if (gSideTimers[side].followmeTimer != 0 if (IsAffectedByFollowMe(gBattlerAttacker, side)
&& gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED && gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget) && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget))
&& gBattleMons[gSideTimers[side].followmeTarget].hp != 0
&& (GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL
|| GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART))
{ {
gBattlerTarget = gSideTimers[side].followmeTarget; gBattlerTarget = gSideTimers[side].followmeTarget;
} }
@ -1553,7 +1565,7 @@ bool32 IsHealBlockPreventingMove(u32 battler, u32 move)
{ {
if (!(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) if (!(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
return FALSE; return FALSE;
switch (gBattleMoves[move].effect) switch (gBattleMoves[move].effect)
{ {
case EFFECT_ABSORB: case EFFECT_ABSORB:
@ -3842,7 +3854,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
gBattleCommunication[MULTISTRING_CHOOSER] = 3; gBattleCommunication[MULTISTRING_CHOOSER] = 3;
break; break;
} }
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++; effect++;
} }
@ -5410,13 +5422,13 @@ static u8 HealConfuseBerry(u32 battlerId, u32 itemId, u8 flavorId, bool32 end2)
if (gBattleMoveDamage == 0) if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1; gBattleMoveDamage = 1;
gBattleMoveDamage *= -1; gBattleMoveDamage *= -1;
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
{ {
gBattleMoveDamage *= 2; gBattleMoveDamage *= 2;
gBattlerAbility = battlerId; gBattlerAbility = battlerId;
} }
if (end2) if (end2)
{ {
if (GetFlavorRelationByPersonality(gBattleMons[battlerId].personality, flavorId) < 0) if (GetFlavorRelationByPersonality(gBattleMons[battlerId].personality, flavorId) < 0)
@ -5450,10 +5462,10 @@ static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId, bool32 end2)
SET_STATCHANGER(statId, 2, FALSE); SET_STATCHANGER(statId, 2, FALSE);
else else
SET_STATCHANGER(statId, 1, FALSE); SET_STATCHANGER(statId, 1, FALSE);
gBattleScripting.animArg1 = 14 + statId; gBattleScripting.animArg1 = 14 + statId;
gBattleScripting.animArg2 = 0; gBattleScripting.animArg2 = 0;
if (end2) if (end2)
{ {
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
@ -5496,15 +5508,15 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2)
gBattleTextBuff2[7] = EOS; gBattleTextBuff2[7] = EOS;
gEffectBattler = battlerId; gEffectBattler = battlerId;
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
SET_STATCHANGER(i + 1, 4, FALSE); SET_STATCHANGER(i + 1, 4, FALSE);
else else
SET_STATCHANGER(i + 1, 2, FALSE); SET_STATCHANGER(i + 1, 2, FALSE);
gBattleScripting.animArg1 = 0x21 + i + 6; gBattleScripting.animArg1 = 0x21 + i + 6;
gBattleScripting.animArg2 = 0; gBattleScripting.animArg2 = 0;
if (end2) if (end2)
{ {
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
@ -5524,7 +5536,7 @@ static u8 TrySetMicleBerry(u32 battlerId, u32 itemId, bool32 end2)
if (HasEnoughHpToEatBerry(battlerId, 4, itemId)) if (HasEnoughHpToEatBerry(battlerId, 4, itemId))
{ {
gProtectStructs[battlerId].micle = TRUE; // battler's next attack has increased accuracy gProtectStructs[battlerId].micle = TRUE; // battler's next attack has increased accuracy
if (end2) if (end2)
{ {
BattleScriptExecute(BattleScript_MicleBerryActivateEnd2); BattleScriptExecute(BattleScript_MicleBerryActivateEnd2);
@ -5547,7 +5559,7 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove) && !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove)
&& GetBattleMoveSplit(gCurrentMove) == split) && GetBattleMoveSplit(gCurrentMove) == split)
{ {
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE);
@ -5556,7 +5568,7 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split)
SET_STATCHANGER(statId, 2, FALSE); SET_STATCHANGER(statId, 2, FALSE);
else else
SET_STATCHANGER(statId, 1, FALSE); SET_STATCHANGER(statId, 1, FALSE);
gBattleScripting.animArg1 = 14 + statId; gBattleScripting.animArg1 = 14 + statId;
gBattleScripting.animArg2 = 0; gBattleScripting.animArg2 = 0;
BattleScriptPushCursor(); BattleScriptPushCursor();
@ -5574,11 +5586,11 @@ static u8 ItemHealHp(u32 battlerId, u32 itemId, bool32 end2, bool32 percentHeal)
gBattleMoveDamage = (gBattleMons[battlerId].maxHP * GetBattlerHoldEffectParam(battlerId) / 100) * -1; gBattleMoveDamage = (gBattleMons[battlerId].maxHP * GetBattlerHoldEffectParam(battlerId) / 100) * -1;
else else
gBattleMoveDamage = GetBattlerHoldEffectParam(battlerId) * -1; gBattleMoveDamage = GetBattlerHoldEffectParam(battlerId) * -1;
// check ripen // check ripen
if (ItemId_GetPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battlerId) == ABILITY_RIPEN) if (ItemId_GetPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battlerId) == ABILITY_RIPEN)
gBattleMoveDamage *= 2; gBattleMoveDamage *= 2;
gBattlerAbility = battlerId; // in SWSH, berry juice shows ability pop up but has no effect. This is mimicked here gBattlerAbility = battlerId; // in SWSH, berry juice shows ability pop up but has no effect. This is mimicked here
if (end2) if (end2)
{ {
@ -5850,7 +5862,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
{ {
u8 maxPP = CalculatePPWithBonus(move, ppBonuses, i); u8 maxPP = CalculatePPWithBonus(move, ppBonuses, i);
u8 ppRestored = GetBattlerHoldEffectParam(battlerId); u8 ppRestored = GetBattlerHoldEffectParam(battlerId);
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
{ {
ppRestored *= 2; ppRestored *= 2;
@ -6428,7 +6440,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
gBattleMoveDamage = 1; gBattleMoveDamage = 1;
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
gBattleMoveDamage *= 2; gBattleMoveDamage *= 2;
effect = ITEM_HP_CHANGE; effect = ITEM_HP_CHANGE;
BattleScriptPushCursor(); BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates; gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates;
@ -6448,7 +6460,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
gBattleMoveDamage = 1; gBattleMoveDamage = 1;
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
gBattleMoveDamage *= 2; gBattleMoveDamage *= 2;
effect = ITEM_HP_CHANGE; effect = ITEM_HP_CHANGE;
BattleScriptPushCursor(); BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates; gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates;
@ -6563,7 +6575,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget)
{ {
case MOVE_TARGET_SELECTED: case MOVE_TARGET_SELECTED:
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp) if (IsAffectedByFollowMe(gBattlerAttacker, side))
{ {
targetBattler = gSideTimers[side].followmeTarget; targetBattler = gSideTimers[side].followmeTarget;
} }
@ -6598,7 +6610,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget)
break; break;
case MOVE_TARGET_RANDOM: case MOVE_TARGET_RANDOM:
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp) if (IsAffectedByFollowMe(gBattlerAttacker, side))
targetBattler = gSideTimers[side].followmeTarget; targetBattler = gSideTimers[side].followmeTarget;
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & MOVE_TARGET_RANDOM) else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & MOVE_TARGET_RANDOM)
targetBattler = SetRandomTarget(gBattlerAttacker); targetBattler = SetRandomTarget(gBattlerAttacker);
@ -7628,7 +7640,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
break; break;
case ABILITY_ICE_SCALES: case ABILITY_ICE_SCALES:
if (IS_MOVE_SPECIAL(move)) if (IS_MOVE_SPECIAL(move))
MulModifier(&modifier, UQ_4_12(0.5)); MulModifier(&modifier, UQ_4_12(0.5));
break; break;
} }
@ -8507,7 +8519,7 @@ static bool32 TryRemoveScreens(u8 battler)
bool32 removed = FALSE; bool32 removed = FALSE;
u8 battlerSide = GetBattlerSide(battler); u8 battlerSide = GetBattlerSide(battler);
u8 enemySide = GetBattlerSide(BATTLE_OPPOSITE(battler)); u8 enemySide = GetBattlerSide(BATTLE_OPPOSITE(battler));
// try to remove from battler's side // try to remove from battler's side
if (gSideStatuses[battlerSide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL)) if (gSideStatuses[battlerSide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL))
{ {
@ -8517,7 +8529,7 @@ static bool32 TryRemoveScreens(u8 battler)
gSideTimers[battlerSide].auroraVeilTimer = 0; gSideTimers[battlerSide].auroraVeilTimer = 0;
removed = TRUE; removed = TRUE;
} }
// try to remove from battler opponent's side // try to remove from battler opponent's side
if (gSideStatuses[enemySide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL)) if (gSideStatuses[enemySide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL))
{ {
@ -8527,7 +8539,7 @@ static bool32 TryRemoveScreens(u8 battler)
gSideTimers[enemySide].auroraVeilTimer = 0; gSideTimers[enemySide].auroraVeilTimer = 0;
removed = TRUE; removed = TRUE;
} }
return removed; return removed;
} }
@ -8554,7 +8566,7 @@ struct Pokemon *GetBattlerPartyData(u8 battlerId)
mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]]; mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]];
else else
mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]]; mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]];
return mon; return mon;
} }