Adds AI_IsFaster and AI_IsSlower functions (#4671)
This commit is contained in:
parent
bebc13b5a1
commit
d55e072747
4 changed files with 72 additions and 62 deletions
|
@ -3,8 +3,6 @@
|
|||
|
||||
#define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE)
|
||||
|
||||
#define AI_STRIKES_FIRST(battlerAi, battlerDef, move)((AI_WhoStrikesFirst(battlerAi, battlerDef, move) == AI_IS_FASTER))
|
||||
|
||||
// Roll boundaries used by AI when scoring. Doesn't affect actual damage dealt.
|
||||
#define MAX_ROLL_PERCENTAGE 100
|
||||
#define MIN_ROLL_PERCENTAGE 85
|
||||
|
@ -16,6 +14,8 @@ enum
|
|||
DMG_ROLL_HIGHEST,
|
||||
};
|
||||
|
||||
bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 move);
|
||||
bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move);
|
||||
bool32 AI_RandLessThan(u32 val);
|
||||
bool32 IsAiVsAiBattle(void);
|
||||
bool32 BattlerHasAi(u32 battlerId);
|
||||
|
|
|
@ -834,7 +834,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
if (gMovesInfo[move].powderMove && !IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))
|
||||
RETURN_SCORE_MINUS(10);
|
||||
|
||||
if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
|
||||
if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
RETURN_SCORE_MINUS(10);
|
||||
|
||||
if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
|
@ -1079,7 +1079,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_HIT: // only applies to Vital Throw
|
||||
if (gMovesInfo[move].priority < 0 && AI_STRIKES_FIRST(battlerAtk, battlerDef, move) && aiData->hpPercents[battlerAtk] < 40)
|
||||
if (gMovesInfo[move].priority < 0 && AI_IsFaster(battlerAtk, battlerDef, move) && aiData->hpPercents[battlerAtk] < 40)
|
||||
ADJUST_SCORE(-2); // don't want to move last
|
||||
break;
|
||||
default:
|
||||
|
@ -1523,7 +1523,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
&& (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB)
|
||||
&& !PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))
|
||||
{
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) // Attacker should go first
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first
|
||||
{
|
||||
if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF)
|
||||
ADJUST_SCORE(-10); // no anticipated move to disable
|
||||
|
@ -1545,7 +1545,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
&& (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB)
|
||||
&& !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
|
||||
{
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) // Attacker should go first
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first
|
||||
{
|
||||
if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF)
|
||||
ADJUST_SCORE(-10); // no anticipated move to encore
|
||||
|
@ -1923,7 +1923,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
break;
|
||||
case EFFECT_SPITE:
|
||||
case EFFECT_MIMIC:
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) // Attacker should go first
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first
|
||||
{
|
||||
if (gLastMoves[battlerDef] == MOVE_NONE
|
||||
|| gLastMoves[battlerDef] == 0xFFFF)
|
||||
|
@ -2068,7 +2068,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
if (isDoubleBattle)
|
||||
{
|
||||
if (IsHazardMoveEffect(gMovesInfo[aiData->partnerMove].effect) // partner is going to set up hazards
|
||||
&& AI_WhoStrikesFirst(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove) == AI_IS_FASTER) // partner is going to set up before the potential Defog
|
||||
&& AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove)) // partner is going to set up before the potential Defog
|
||||
{
|
||||
ADJUST_SCORE(-10);
|
||||
break; // Don't use Defog if partner is going to set up hazards
|
||||
|
@ -2096,7 +2096,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
break;
|
||||
case EFFECT_SEMI_INVULNERABLE:
|
||||
if (predictedMove != MOVE_NONE
|
||||
&& AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER
|
||||
&& AI_IsSlower(battlerAtk, battlerDef, move)
|
||||
&& gMovesInfo[predictedMove].effect == EFFECT_SEMI_INVULNERABLE)
|
||||
ADJUST_SCORE(-10); // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you
|
||||
|
||||
|
@ -2280,7 +2280,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case EFFECT_ME_FIRST:
|
||||
if (predictedMove != MOVE_NONE)
|
||||
{
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER)
|
||||
if (AI_IsSlower(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(-10); // Target is predicted to go first, Me First will fail
|
||||
else
|
||||
return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score);
|
||||
|
@ -2463,7 +2463,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
}
|
||||
break;
|
||||
case EFFECT_ELECTRIFY:
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER
|
||||
if (AI_IsSlower(battlerAtk, battlerDef, move)
|
||||
//|| GetMoveTypeSpecial(battlerDef, predictedMove) == TYPE_ELECTRIC // Move will already be electric type
|
||||
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
|
||||
ADJUST_SCORE(-10);
|
||||
|
@ -2492,7 +2492,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case EFFECT_INSTRUCT:
|
||||
{
|
||||
u16 instructedMove;
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER)
|
||||
if (AI_IsSlower(battlerAtk, battlerDef, move))
|
||||
instructedMove = predictedMove;
|
||||
else
|
||||
instructedMove = gLastMoves[battlerDef];
|
||||
|
@ -2531,21 +2531,21 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
break;
|
||||
case EFFECT_QUASH:
|
||||
if (!isDoubleBattle
|
||||
|| AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER
|
||||
|| AI_IsSlower(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_AFTER_YOU:
|
||||
if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)
|
||||
|| !isDoubleBattle
|
||||
|| AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER
|
||||
|| AI_IsSlower(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_SUCKER_PUNCH:
|
||||
if (predictedMove != MOVE_NONE)
|
||||
{
|
||||
if (IS_MOVE_STATUS(predictedMove) || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER) // Opponent going first
|
||||
if (IS_MOVE_STATUS(predictedMove) || AI_IsSlower(battlerAtk, battlerDef, move)) // Opponent going first
|
||||
ADJUST_SCORE(-10);
|
||||
}
|
||||
break;
|
||||
|
@ -2587,7 +2587,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
ADJUST_SCORE(-1);
|
||||
break;
|
||||
case EFFECT_FLAIL:
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER // Opponent should go first
|
||||
if (AI_IsSlower(battlerAtk, battlerDef, move) // Opponent should go first
|
||||
|| aiData->hpPercents[battlerAtk] > 50)
|
||||
ADJUST_SCORE(-4);
|
||||
break;
|
||||
|
@ -2624,7 +2624,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
else if (CanAIFaintTarget(battlerAtk, battlerDef, 0))
|
||||
ADJUST_SCORE(-10);
|
||||
else if (CanTargetFaintAi(battlerDef, battlerAtk)
|
||||
&& AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER)
|
||||
&& AI_IsSlower(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_JUNGLE_HEALING:
|
||||
|
@ -2652,7 +2652,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_UPPER_HAND:
|
||||
if (predictedMove == MOVE_NONE || IS_MOVE_STATUS(predictedMove) || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER || GetMovePriority(battlerDef, move) < 1 || GetMovePriority(battlerDef, move) > 3) // Opponent going first or not using priority move
|
||||
if (predictedMove == MOVE_NONE || IS_MOVE_STATUS(predictedMove) || AI_IsSlower(battlerAtk, battlerDef, move) || GetMovePriority(battlerDef, move) < 1 || GetMovePriority(battlerDef, move) > 3) // Opponent going first or not using priority move
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_PLACEHOLDER:
|
||||
|
@ -2677,7 +2677,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
|
||||
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, movesetIndex, 0) && gMovesInfo[move].effect != EFFECT_EXPLOSION)
|
||||
{
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, move))
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(FAST_KILL);
|
||||
else
|
||||
ADJUST_SCORE(SLOW_KILL);
|
||||
|
@ -2743,7 +2743,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
// Adjust for always crit moves
|
||||
if (gMovesInfo[aiData->partnerMove].alwaysCriticalHit && aiData->abilities[battlerAtk] == ABILITY_ANGER_POINT)
|
||||
{
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerAtkPartner, move) == AI_IS_SLOWER) // Partner moving first
|
||||
if (AI_IsSlower(battlerAtk, battlerAtkPartner, move)) // Partner moving first
|
||||
{
|
||||
// discourage raising our attack since it's about to be maxed out
|
||||
if (IsAttackBoostMoveEffect(effect))
|
||||
|
@ -3023,7 +3023,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case EFFECT_INSTRUCT:
|
||||
{
|
||||
u16 instructedMove;
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerAtkPartner, move) == AI_IS_FASTER)
|
||||
if (AI_IsFaster(battlerAtk, battlerAtkPartner, move))
|
||||
instructedMove = aiData->partnerMove;
|
||||
else
|
||||
instructedMove = gLastMoves[battlerAtkPartner];
|
||||
|
@ -3037,8 +3037,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
}
|
||||
break;
|
||||
case EFFECT_AFTER_YOU:
|
||||
if (AI_WhoStrikesFirst(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove) == AI_IS_SLOWER // Opponent mon 1 goes before partner
|
||||
|| AI_WhoStrikesFirst(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove) == AI_IS_SLOWER) // Opponent mon 2 goes before partner
|
||||
if (AI_IsSlower(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove) // Opponent mon 1 goes before partner
|
||||
|| AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove)) // Opponent mon 2 goes before partner
|
||||
{
|
||||
if (gMovesInfo[aiData->partnerMove].effect == EFFECT_COUNTER || gMovesInfo[aiData->partnerMove].effect == EFFECT_MIRROR_COAT)
|
||||
break; // These moves need to go last
|
||||
|
@ -3047,8 +3047,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
break;
|
||||
case EFFECT_HEAL_PULSE:
|
||||
case EFFECT_HIT_ENEMY_HEAL_ALLY:
|
||||
if (AI_WhoStrikesFirst(battlerAtk, FOE(battlerAtk), move) == AI_IS_FASTER
|
||||
&& AI_WhoStrikesFirst(battlerAtk, BATTLE_PARTNER(FOE(battlerAtk)), move) == AI_IS_FASTER
|
||||
if (AI_IsFaster(battlerAtk, FOE(battlerAtk), move)
|
||||
&& AI_IsFaster(battlerAtk, BATTLE_PARTNER(FOE(battlerAtk)), move)
|
||||
&& gBattleMons[battlerAtkPartner].hp < gBattleMons[battlerAtkPartner].maxHP / 2)
|
||||
RETURN_SCORE_PLUS(WEAK_EFFECT);
|
||||
break;
|
||||
|
@ -3343,7 +3343,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
break;
|
||||
case EFFECT_SPEED_DOWN:
|
||||
case EFFECT_SPEED_DOWN_2:
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, move))
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(-3);
|
||||
else if (!AI_RandLessThan(70))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
|
@ -3558,7 +3558,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
break;
|
||||
case EFFECT_MIMIC:
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
{
|
||||
if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF)
|
||||
return AI_CheckViability(battlerAtk, battlerDef, gLastMoves[battlerDef], score);
|
||||
|
@ -3620,7 +3620,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
&& (gLastMoves[battlerDef] != MOVE_NONE)
|
||||
&& (gLastMoves[battlerDef] != 0xFFFF)
|
||||
&& (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB)
|
||||
&& (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER))
|
||||
&& (AI_IsFaster(battlerAtk, battlerDef, move)))
|
||||
{
|
||||
if (CanTargetMoveFaintAi(gLastMoves[battlerDef], battlerDef, battlerAtk, 1))
|
||||
ADJUST_SCORE(GOOD_EFFECT); // Disable move that can kill attacker
|
||||
|
@ -3648,7 +3648,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
case EFFECT_DESTINY_BOND:
|
||||
if (IsDynamaxed(battlerDef))
|
||||
break;
|
||||
else if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER && CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
else if (AI_IsFaster(battlerAtk, battlerDef, move) && CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
case EFFECT_SPITE:
|
||||
|
@ -3848,7 +3848,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
case EFFECT_SEMI_INVULNERABLE:
|
||||
if (predictedMove != MOVE_NONE && !isDoubleBattle)
|
||||
{
|
||||
if ((AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
|
||||
if ((AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
&& (gMovesInfo[predictedMove].effect == EFFECT_EXPLOSION || gMovesInfo[predictedMove].effect == EFFECT_PROTECT))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
else if (gMovesInfo[predictedMove].effect == EFFECT_SEMI_INVULNERABLE && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE))
|
||||
|
@ -3890,7 +3890,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
break;
|
||||
case EFFECT_ATTRACT:
|
||||
if (!isDoubleBattle
|
||||
&& (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER)
|
||||
&& (AI_IsSlower(battlerAtk, battlerDef, move))
|
||||
&& BattlerWillFaintFromSecondaryDamage(battlerDef, aiData->abilities[battlerDef]))
|
||||
break; // Don't use if the attract won't have a change to activate
|
||||
if (gBattleMons[battlerDef].status1 & STATUS1_ANY
|
||||
|
@ -3924,7 +3924,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
if (isDoubleBattle)
|
||||
{
|
||||
if (IsHazardMoveEffect(gMovesInfo[aiData->partnerMove].effect) // Partner is going to set up hazards
|
||||
&& AI_WhoStrikesFirst(battlerAtk, BATTLE_PARTNER(battlerAtk), move) == AI_IS_SLOWER) // Partner going first
|
||||
&& AI_IsSlower(battlerAtk, BATTLE_PARTNER(battlerAtk), move)) // Partner going first
|
||||
break; // Don't use Defog if partner is going to set up hazards
|
||||
}
|
||||
if (ShouldLowerEvasion(battlerAtk, battlerDef, aiData->abilities[battlerDef]))
|
||||
|
@ -4350,7 +4350,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case EFFECT_HEAL_BLOCK:
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER && predictedMove != MOVE_NONE && IsHealingMove(predictedMove))
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move) && predictedMove != MOVE_NONE && IsHealingMove(predictedMove))
|
||||
ADJUST_SCORE(DECENT_EFFECT); // Try to cancel healing move
|
||||
else if (HasHealingEffect(battlerDef) || aiData->holdEffects[battlerDef] == HOLD_EFFECT_LEFTOVERS
|
||||
|| (aiData->holdEffects[battlerDef] == HOLD_EFFECT_BLACK_SLUDGE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_POISON)))
|
||||
|
@ -4382,7 +4382,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
ADJUST_SCORE(BEST_EFFECT);
|
||||
break;
|
||||
case EFFECT_QUASH:
|
||||
if (isDoubleBattle && AI_WhoStrikesFirst(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove) == AI_IS_SLOWER)
|
||||
if (isDoubleBattle && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove))
|
||||
ADJUST_SCORE(DECENT_EFFECT); // Attacker partner wouldn't go before target
|
||||
break;
|
||||
case EFFECT_TAILWIND:
|
||||
|
@ -4397,7 +4397,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
if (IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC)
|
||||
&& !(AI_GetTypeEffectiveness(MOVE_EARTHQUAKE, battlerDef, battlerAtk) == AI_EFFECTIVENESS_x0)) // Doesn't resist ground move
|
||||
{
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) // Attacker goes first
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first
|
||||
{
|
||||
if (gMovesInfo[predictedMove].type == TYPE_GROUND)
|
||||
ADJUST_SCORE(GOOD_EFFECT); // Cause the enemy's move to fail
|
||||
|
@ -4412,7 +4412,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
}
|
||||
break;
|
||||
case EFFECT_CAMOUFLAGE:
|
||||
if (predictedMove != MOVE_NONE && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER // Attacker goes first
|
||||
if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move) // Attacker goes first
|
||||
&& !IS_MOVE_STATUS(move) && AI_GetTypeEffectiveness(predictedMove, battlerDef, battlerAtk) != AI_EFFECTIVENESS_x0)
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
|
@ -4448,7 +4448,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
}
|
||||
break;
|
||||
case EFFECT_ENDEAVOR:
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER && !CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
if (AI_IsSlower(battlerAtk, battlerDef, move) && !CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case EFFECT_REVIVAL_BLESSING:
|
||||
|
@ -4708,7 +4708,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
case MOVE_EFFECT_THROAT_CHOP:
|
||||
if (gMovesInfo[GetBestDmgMoveFromBattler(battlerDef, battlerAtk)].soundMove)
|
||||
{
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
else
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
|
@ -4759,7 +4759,7 @@ static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
|||
return score;
|
||||
|
||||
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_SMART_SWITCHING
|
||||
&& AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER
|
||||
&& AI_IsSlower(battlerAtk, battlerDef, move)
|
||||
&& CanTargetFaintAi(battlerDef, battlerAtk)
|
||||
&& GetMovePriority(battlerAtk, move) == 0)
|
||||
{
|
||||
|
|
|
@ -162,7 +162,7 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult)
|
|||
// Check if current mon can outspeed and KO in spite of bad matchup, and don't switch out if it can
|
||||
if(damageDealt > gBattleMons[opposingBattler].hp)
|
||||
{
|
||||
if (AI_WhoStrikesFirst(battler, opposingBattler, aiBestMove) == AI_IS_FASTER)
|
||||
if (AI_IsFaster(battler, opposingBattler, aiBestMove))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -569,7 +569,7 @@ static bool32 ShouldSwitchIfGameStatePrompt(u32 battler, bool32 emitResult)
|
|||
&& AnyStatIsRaised(battler))
|
||||
switchMon = FALSE;
|
||||
if (AiExpectsToFaintPlayer(battler)
|
||||
&& !AI_STRIKES_FIRST(battler, opposingBattler, 0)
|
||||
&& AI_IsSlower(battler, opposingBattler, 0)
|
||||
&& !AI_OpponentCanFaintAiWithMod(battler, 0))
|
||||
switchMon = FALSE;
|
||||
}
|
||||
|
@ -2019,7 +2019,7 @@ static bool32 AiExpectsToFaintPlayer(u32 battler)
|
|||
|
||||
if (GetBattlerSide(target) != GetBattlerSide(battler)
|
||||
&& CanIndexMoveFaintTarget(battler, target, gBattleStruct->aiMoveOrAction[battler], 0)
|
||||
&& AI_WhoStrikesFirst(battler, target, GetAIChosenMove(battler)) == AI_IS_FASTER)
|
||||
&& AI_IsFaster(battler, target, GetAIChosenMove(battler)))
|
||||
{
|
||||
// We expect to faint the target and move first -> dont use an item
|
||||
return TRUE;
|
||||
|
|
|
@ -35,6 +35,16 @@
|
|||
static u32 AI_GetEffectiveness(uq4_12_t multiplier);
|
||||
|
||||
// Functions
|
||||
bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 move)
|
||||
{
|
||||
return (AI_WhoStrikesFirst(battlerAi, battlerDef, move) == AI_IS_FASTER);
|
||||
}
|
||||
|
||||
bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move)
|
||||
{
|
||||
return (AI_WhoStrikesFirst(battlerAi, battlerDef, move) == AI_IS_SLOWER);
|
||||
}
|
||||
|
||||
u32 GetAIChosenMove(u32 battlerId)
|
||||
{
|
||||
return (gBattleMons[battlerId].moves[gBattleStruct->aiMoveOrAction[battlerId]]);
|
||||
|
@ -311,7 +321,7 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler)
|
|||
u32 move = gBattleResources->battleHistory->usedMoves[opposingBattler][i];
|
||||
if (gMovesInfo[move].effect == EFFECT_PROTECT && move != MOVE_ENDURE)
|
||||
return TRUE;
|
||||
if (gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE && AI_WhoStrikesFirst(battlerAI, opposingBattler, GetAIChosenMove(battlerAI)) == AI_IS_SLOWER)
|
||||
if (gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE && AI_IsSlower(battlerAI, opposingBattler, GetAIChosenMove(battlerAI)))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
@ -1614,7 +1624,7 @@ bool32 ShouldLowerStat(u32 battler, u32 battlerAbility, u32 stat)
|
|||
return !(battlerAbility == ABILITY_BIG_PECKS);
|
||||
case STAT_SPEED:
|
||||
// If AI is faster and doesn't have any mons left, lowering speed doesn't give any
|
||||
return !(AI_WhoStrikesFirst(sBattler_AI, battler, AI_THINKING_STRUCT->moveConsidered) == AI_IS_FASTER
|
||||
return !(AI_IsFaster(sBattler_AI, battler, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& CountUsablePartyMons(sBattler_AI) == 0
|
||||
&& !HasMoveEffect(sBattler_AI, EFFECT_ELECTRO_BALL));
|
||||
case STAT_ACC:
|
||||
|
@ -1683,7 +1693,7 @@ u32 CountNegativeStatStages(u32 battlerId)
|
|||
|
||||
bool32 ShouldLowerAttack(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
{
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)
|
||||
&& CanAIFaintTarget(battlerAtk, battlerDef, 0))
|
||||
return FALSE; // Don't bother lowering stats if can kill enemy.
|
||||
|
@ -1702,7 +1712,7 @@ bool32 ShouldLowerAttack(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
|||
|
||||
bool32 ShouldLowerDefense(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
{
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)
|
||||
&& CanAIFaintTarget(battlerAtk, battlerDef, 0))
|
||||
return FALSE; // Don't bother lowering stats if can kill enemy.
|
||||
|
@ -1721,12 +1731,12 @@ bool32 ShouldLowerDefense(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
|||
|
||||
bool32 ShouldLowerSpeed(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
{
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)
|
||||
&& CanAIFaintTarget(battlerAtk, battlerDef, 0))
|
||||
return FALSE; // Don't bother lowering stats if can kill enemy.
|
||||
|
||||
if (!AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
if (AI_IsSlower(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& defAbility != ABILITY_CONTRARY
|
||||
&& defAbility != ABILITY_CLEAR_BODY
|
||||
&& defAbility != ABILITY_FULL_METAL_BODY
|
||||
|
@ -1738,7 +1748,7 @@ bool32 ShouldLowerSpeed(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
|||
|
||||
bool32 ShouldLowerSpAtk(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
{
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)
|
||||
&& CanAIFaintTarget(battlerAtk, battlerDef, 0))
|
||||
return FALSE; // Don't bother lowering stats if can kill enemy.
|
||||
|
@ -1756,7 +1766,7 @@ bool32 ShouldLowerSpAtk(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
|||
|
||||
bool32 ShouldLowerSpDef(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
{
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)
|
||||
&& CanAIFaintTarget(battlerAtk, battlerDef, 0))
|
||||
return FALSE; // Don't bother lowering stats if can kill enemy.
|
||||
|
@ -1774,7 +1784,7 @@ bool32 ShouldLowerSpDef(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
|||
|
||||
bool32 ShouldLowerAccuracy(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
{
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)
|
||||
&& CanAIFaintTarget(battlerAtk, battlerDef, 0))
|
||||
return FALSE; // Don't bother lowering stats if can kill enemy.
|
||||
|
@ -1793,7 +1803,7 @@ bool32 ShouldLowerAccuracy(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
|||
|
||||
bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
{
|
||||
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)
|
||||
&& (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)
|
||||
&& CanAIFaintTarget(battlerAtk, battlerDef, 0))
|
||||
return FALSE; // Don't bother lowering stats if can kill enemy.
|
||||
|
@ -2514,7 +2524,7 @@ bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32
|
|||
/*if (IsPredictedToSwitch(battlerDef, battlerAtk) && !hasStatBoost)
|
||||
return PIVOT; // Try pivoting so you can switch to a better matchup to counter your new opponent*/
|
||||
|
||||
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) // Attacker goes first
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first
|
||||
{
|
||||
if (!CanAIFaintTarget(battlerAtk, battlerDef, 0)) // Can't KO foe otherwise
|
||||
{
|
||||
|
@ -2898,7 +2908,7 @@ u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbi
|
|||
if (((!IsMoldBreakerTypeAbility(AI_DATA->abilities[battlerAtk]) && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS))
|
||||
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER)) // Opponent goes first
|
||||
|| AI_IsSlower(battlerAtk, battlerDef, move))) // Opponent goes first
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -2906,7 +2916,7 @@ u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbi
|
|||
|| gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS
|
||||
|| gBattleMons[battlerDef].status2 & STATUS2_INFATUATION
|
||||
|| gBattleMons[battlerDef].status2 & STATUS2_CONFUSION)
|
||||
|| ((AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) && CanTargetFaintAi(battlerDef, battlerAtk)))
|
||||
|| ((AI_IsFaster(battlerAtk, battlerDef, move)) && CanTargetFaintAi(battlerDef, battlerAtk)))
|
||||
{
|
||||
return 2; // good idea to flinch
|
||||
}
|
||||
|
@ -3024,7 +3034,7 @@ bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 mo
|
|||
|
||||
bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage)
|
||||
{
|
||||
if (move == 0xFFFF || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
|
||||
if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
{
|
||||
// using item or user goes first
|
||||
u32 healPercent = (gMovesInfo[move].argument == 0) ? 50 : gMovesInfo[move].argument;
|
||||
|
@ -3051,7 +3061,7 @@ bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage)
|
|||
|
||||
bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent)
|
||||
{
|
||||
if (move == 0xFFFF || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
|
||||
if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
{
|
||||
// using item or user going first
|
||||
s32 damage = AI_DATA->simulatedDmg[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex];
|
||||
|
@ -3510,7 +3520,7 @@ bool32 IsRecycleEncouragedItem(u32 item)
|
|||
static void IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score, bool32 considerContrary)
|
||||
{
|
||||
u32 noOfHitsToFaint = NoOfHitsForTargetToFaintAI(battlerDef, battlerAtk);
|
||||
u32 aiIsFaster = GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) == AI_IS_FASTER;
|
||||
u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, TRUE);
|
||||
u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS);
|
||||
|
||||
if (considerContrary && AI_DATA->abilities[battlerAtk] == ABILITY_CONTRARY)
|
||||
|
@ -3844,7 +3854,7 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
|||
if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerDef) != 0)
|
||||
ADJUST_SCORE_PTR(-2);
|
||||
|
||||
if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE && AI_STRIKES_FIRST(battlerAtk, battlerDef, move))
|
||||
if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE && AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE_PTR(-10);
|
||||
if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE)
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
|
@ -3890,6 +3900,6 @@ bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, st
|
|||
}
|
||||
|
||||
return (preventsStatLoss
|
||||
&& AI_STRIKES_FIRST(battlerAtk, battlerAtkPartner, TRUE)
|
||||
&& AI_IsFaster(battlerAtk, battlerAtkPartner, TRUE)
|
||||
&& HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue