Fix Choice'd AI not switching if player immune to move (#6464)
This commit is contained in:
commit
4c7ac8066e
@ -164,6 +164,14 @@ static inline bool32 SetSwitchinAndSwitch(u32 battler, u32 switchinId)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool32 AI_DoesChoiceItemBlockMove(u32 battler, u32 move)
|
||||||
|
{
|
||||||
|
// Choice locked into something else
|
||||||
|
if (AI_DATA->lastUsedMove[battler] != MOVE_NONE && AI_DATA->lastUsedMove[battler] != move && HOLD_EFFECT_CHOICE(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// Note that as many return statements as possible are INTENTIONALLY put after all of the loops;
|
// Note that as many return statements as possible are INTENTIONALLY put after all of the loops;
|
||||||
// the function can take a max of about 0.06s to run, and this prevents the player from identifying
|
// the function can take a max of about 0.06s to run, and this prevents the player from identifying
|
||||||
// whether the mon will switch or not by seeing how long the delay is before they select a move
|
// whether the mon will switch or not by seeing how long the delay is before they select a move
|
||||||
@ -194,7 +202,6 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
|||||||
defType1 = gBattleMons[battler].types[0];
|
defType1 = gBattleMons[battler].types[0];
|
||||||
defType2 = gBattleMons[battler].types[1];
|
defType2 = gBattleMons[battler].types[1];
|
||||||
|
|
||||||
// Check AI moves for damage dealt
|
|
||||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||||
{
|
{
|
||||||
aiMove = gBattleMons[battler].moves[i];
|
aiMove = gBattleMons[battler].moves[i];
|
||||||
@ -216,17 +223,16 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
|||||||
if (!IsBattleMoveStatus(aiMove))
|
if (!IsBattleMoveStatus(aiMove))
|
||||||
{
|
{
|
||||||
// Check if mon has a super effective move
|
// Check if mon has a super effective move
|
||||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0))
|
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0) && !AI_DoesChoiceItemBlockMove(battler, aiMove))
|
||||||
hasSuperEffectiveMove = TRUE;
|
hasSuperEffectiveMove = TRUE;
|
||||||
|
|
||||||
// Get maximum damage mon can deal
|
// Get maximum damage mon can deal
|
||||||
damageDealt = AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, AI_DATA);
|
damageDealt = AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, AI_DATA);
|
||||||
if(damageDealt > maxDamageDealt)
|
if(damageDealt > maxDamageDealt && !AI_DoesChoiceItemBlockMove(battler, aiMove))
|
||||||
{
|
{
|
||||||
maxDamageDealt = damageDealt;
|
maxDamageDealt = damageDealt;
|
||||||
aiBestMove = aiMove;
|
aiBestMove = aiMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -987,10 +993,18 @@ static bool32 ShouldSwitchIfEncored(u32 battler)
|
|||||||
static bool32 ShouldSwitchIfBadChoiceLock(u32 battler)
|
static bool32 ShouldSwitchIfBadChoiceLock(u32 battler)
|
||||||
{
|
{
|
||||||
u32 holdEffect = GetBattlerHoldEffect(battler, FALSE);
|
u32 holdEffect = GetBattlerHoldEffect(battler, FALSE);
|
||||||
|
u32 lastUsedMove = AI_DATA->lastUsedMove[battler];
|
||||||
|
u32 opposingBattler = GetOppositeBattler(battler);
|
||||||
|
bool32 moveAffectsTarget = TRUE;
|
||||||
|
|
||||||
|
if (lastUsedMove != MOVE_NONE && (AI_GetMoveEffectiveness(lastUsedMove, battler, opposingBattler) == UQ_4_12(0.0)
|
||||||
|
|| CanAbilityAbsorbMove(battler, opposingBattler, AI_DATA->abilities[opposingBattler], lastUsedMove, GetMoveType(lastUsedMove), ABILITY_CHECK_TRIGGER)
|
||||||
|
|| CanAbilityBlockMove(battler, opposingBattler, lastUsedMove, AI_DATA->abilities[opposingBattler], ABILITY_CHECK_TRIGGER)))
|
||||||
|
moveAffectsTarget = FALSE;
|
||||||
|
|
||||||
if (HOLD_EFFECT_CHOICE(holdEffect) && IsBattlerItemEnabled(battler))
|
if (HOLD_EFFECT_CHOICE(holdEffect) && IsBattlerItemEnabled(battler))
|
||||||
{
|
{
|
||||||
if (GetMoveCategory(AI_DATA->lastUsedMove[battler]) == DAMAGE_CATEGORY_STATUS && RandomPercentage(RNG_AI_SWITCH_CHOICE_LOCKED, GetSwitchChance(SHOULD_SWITCH_CHOICE_LOCKED)))
|
if ((GetMoveCategory(lastUsedMove) == DAMAGE_CATEGORY_STATUS || !moveAffectsTarget) && RandomPercentage(RNG_AI_SWITCH_CHOICE_LOCKED, GetSwitchChance(SHOULD_SWITCH_CHOICE_LOCKED)))
|
||||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -195,3 +195,38 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use status move if they are trappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AI_SINGLE_BATTLE_TEST("Choiced Pokémon will switch if locked into a move the player is immune to")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gSpeciesInfo[SPECIES_GASTLY].types[0] == TYPE_GHOST);
|
||||||
|
ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER);
|
||||||
|
ASSUME(GetMoveType(MOVE_BODY_SLAM) == TYPE_NORMAL);
|
||||||
|
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
|
||||||
|
PLAYER(SPECIES_GASTLY) { Level(1); Moves(MOVE_CELEBRATE); }
|
||||||
|
PLAYER(SPECIES_VAPOREON) { Ability(ABILITY_WATER_ABSORB); Moves(MOVE_SURF); }
|
||||||
|
OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_CHOICE_BAND); Moves(MOVE_SURF, MOVE_BODY_SLAM); }
|
||||||
|
OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_CHOICE_BAND); Moves(MOVE_SURF, MOVE_BODY_SLAM); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_SURF); SEND_OUT(player, 1); }
|
||||||
|
TURN { MOVE(player, MOVE_SURF); EXPECT_SWITCH(opponent, 1); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AI_SINGLE_BATTLE_TEST("Choiced Pokémon will only see choiced moves when considering switching with ShouldSwitchIfHasBadOdds")
|
||||||
|
{
|
||||||
|
PASSES_RANDOMLY(SHOULD_SWITCH_HASBADODDS_PERCENTAGE, 100, RNG_AI_SWITCH_HASBADODDS);
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gSpeciesInfo[SPECIES_GASTLY].types[0] == TYPE_GHOST);
|
||||||
|
ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER);
|
||||||
|
ASSUME(GetMoveType(MOVE_BODY_SLAM) == TYPE_NORMAL);
|
||||||
|
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES);
|
||||||
|
PLAYER(SPECIES_GASTLY) { Level(1); Moves(MOVE_CELEBRATE); }
|
||||||
|
PLAYER(SPECIES_ZIGZAGOON) { Item(ITEM_CHOICE_BAND); Moves(MOVE_CLOSE_COMBAT); }
|
||||||
|
OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_CHOICE_BAND); Moves(MOVE_SURF, MOVE_CLOSE_COMBAT); }
|
||||||
|
OPPONENT(SPECIES_BRONZONG) { Moves(MOVE_CLOSE_COMBAT); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_SURF); SEND_OUT(player, 1); }
|
||||||
|
TURN { MOVE(player, MOVE_CLOSE_COMBAT); EXPECT_SWITCH(opponent, 1); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user