Improved Guaranteed Flinch logic (fake out et al) (#7501)
This commit is contained in:
parent
13a8f655b5
commit
e778d3cdfe
@ -197,7 +197,8 @@ bool32 IsHealingMove(u32 move);
|
||||
bool32 HasHealingEffect(u32 battler);
|
||||
bool32 IsTrappingMove(u32 move);
|
||||
bool32 HasTrappingMoveEffect(u32 battler);
|
||||
bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
bool32 IsFlinchGuaranteed(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
bool32 HasChoiceEffect(u32 battler);
|
||||
bool32 HasThawingMove(u32 battler);
|
||||
bool32 IsStatRaisingEffect(enum BattleMoveEffects effect);
|
||||
bool32 IsStatLoweringEffect(enum BattleMoveEffects effect);
|
||||
|
||||
@ -1138,6 +1138,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (DoesBattlerIgnoreAbilityChecks(battlerAtk, abilityAtk, move))
|
||||
abilityDef = ABILITY_NONE;
|
||||
|
||||
// If a pokemon can be guaranteed flinched, don't target the pokemon that can't be flinched.
|
||||
if (hasTwoOpponents
|
||||
&& !IsFlinchGuaranteed(battlerAtk, battlerDef, move) && IsFlinchGuaranteed(battlerAtk, BATTLE_PARTNER(battlerDef), move)
|
||||
&& aiData->effectiveness[battlerAtk][BATTLE_PARTNER(battlerDef)][gAiThinkingStruct->movesetIndex] != UQ_4_12(0.0))
|
||||
ADJUST_SCORE(-5);
|
||||
|
||||
// check non-user target
|
||||
if (!(moveTarget & MOVE_TARGET_USER))
|
||||
{
|
||||
@ -1999,6 +2005,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_FIRST_TURN_ONLY:
|
||||
if (!gDisableStructs[battlerAtk].isFirstTurn)
|
||||
ADJUST_SCORE(-10);
|
||||
if (HasChoiceEffect(battlerAtk))
|
||||
ADJUST_SCORE(-5);
|
||||
break;
|
||||
case EFFECT_STOCKPILE:
|
||||
if (gDisableStructs[battlerAtk].stockpileCounter >= 3)
|
||||
@ -3946,6 +3954,10 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
ADJUST_SCORE(-20); // Force switch if all your attacking moves are physical and you have Natural Cure.
|
||||
}
|
||||
|
||||
// check guaranteed flinch, a la Fake Out
|
||||
if (IsFlinchGuaranteed(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
|
||||
// Non-volatile statuses
|
||||
switch(GetMoveNonVolatileStatus(move))
|
||||
{
|
||||
@ -4551,9 +4563,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF));
|
||||
break;
|
||||
case EFFECT_FIRST_TURN_ONLY:
|
||||
if (ShouldFakeOut(battlerAtk, battlerDef, move) && MoveHasAdditionalEffectWithChance(move, MOVE_EFFECT_FLINCH, 100))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
else if (gDisableStructs[battlerAtk].isFirstTurn && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move)
|
||||
if (gDisableStructs[battlerAtk].isFirstTurn && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move)
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
break;
|
||||
case EFFECT_STOCKPILE:
|
||||
|
||||
@ -3502,18 +3502,57 @@ bool32 ShouldTrap(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
bool32 IsFlinchGuaranteed(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
{
|
||||
if ((!gDisableStructs[battlerAtk].isFirstTurn && MoveHasAdditionalEffectWithChance(move, MOVE_EFFECT_FLINCH, 100))
|
||||
|| gAiLogicData->abilities[battlerAtk] == ABILITY_GORILLA_TACTICS
|
||||
|| gAiLogicData->holdEffects[battlerAtk] == HOLD_EFFECT_CHOICE_BAND
|
||||
|| gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| (!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk])
|
||||
&& (gAiLogicData->abilities[battlerDef] == ABILITY_SHIELD_DUST || gAiLogicData->abilities[battlerDef] == ABILITY_INNER_FOCUS)))
|
||||
if (!MoveHasAdditionalEffect(move, MOVE_EFFECT_FLINCH))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
if (AI_IsSlower(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY))
|
||||
return FALSE;
|
||||
|
||||
u32 i;
|
||||
u32 additionalEffectCount = GetMoveAdditionalEffectCount(move);
|
||||
// check move additional effects that are likely to happen
|
||||
for (i = 0; i < additionalEffectCount; i++)
|
||||
{
|
||||
const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i);
|
||||
// Only consider effects with a guaranteed chance to happen
|
||||
if (!MoveEffectIsGuaranteed(battlerAtk, gAiLogicData->abilities[battlerAtk], additionalEffect))
|
||||
continue;
|
||||
|
||||
if (additionalEffect->moveEffect == MOVE_EFFECT_FLINCH)
|
||||
{
|
||||
if (gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| (!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk])
|
||||
&& (gAiLogicData->abilities[battlerDef] == ABILITY_SHIELD_DUST || gAiLogicData->abilities[battlerDef] == ABILITY_INNER_FOCUS)))
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasChoiceEffect(u32 battler)
|
||||
{
|
||||
u32 ability = gAiLogicData->abilities[battler];
|
||||
if (ability == ABILITY_GORILLA_TACTICS)
|
||||
return TRUE;
|
||||
|
||||
if (ability == ABILITY_KLUTZ)
|
||||
return FALSE;
|
||||
|
||||
enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battler];
|
||||
switch (holdEffect)
|
||||
{
|
||||
case HOLD_EFFECT_CHOICE_BAND:
|
||||
case HOLD_EFFECT_CHOICE_SCARF:
|
||||
case HOLD_EFFECT_CHOICE_SPECS:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 FindMoveUsedXTurnsAgo(u32 battlerId, u32 x)
|
||||
|
||||
@ -648,3 +648,16 @@ AI_DOUBLE_BATTLE_TEST("AI uses Power Split to improve its stats")
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI prefers to Fake Out the opponent vulnerable to flinching.")
|
||||
{
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }
|
||||
PLAYER(SPECIES_BRAIXEN) { Ability(ABILITY_BLAZE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_FAKE_OUT, MOVE_BRANCH_POKE, MOVE_ROCK_SMASH); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponentLeft, MOVE_FAKE_OUT, target:playerRight); }
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user