Made AI_CheckBadMove take the primal weathers into account

Credits to Syreldar.
Also took the chance and removed trailing spaces from the file.
This commit is contained in:
LOuroboros 2021-08-30 19:48:59 -03:00
parent 216d8f0608
commit c0c6821f62

View file

@ -249,7 +249,7 @@ static u8 ChooseMoveOrAction_Singles(void)
RecordLastUsedMoveByTarget();
GetAiLogicData(sBattler_AI, gBattlerTarget);
while (flags != 0)
{
if (flags & 1)
@ -364,10 +364,10 @@ static u8 ChooseMoveOrAction_Doubles(void)
BattleAI_SetupAIData(gBattleStruct->palaceFlags >> 4);
else
BattleAI_SetupAIData(0xF);
gBattlerTarget = i;
GetAiLogicData(sBattler_AI, gBattlerTarget);
if ((i & BIT_SIDE) != (sBattler_AI & BIT_SIDE))
RecordLastUsedMoveByTarget();
@ -510,19 +510,21 @@ static void BattleAI_DoAIProcessing(void)
static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
// move data
s32 moveType;
u8 atkPriority = GetMovePriority(battlerAtk, move);
u16 moveEffect = gBattleMoves[move].effect;
u8 moveType = gBattleMoves[move].type;
u8 moveTarget = gBattleMoves[move].target;
u16 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, AI_DATA->atkHoldEffect, AI_DATA->defHoldEffect, move);
u8 effectiveness = AI_GetMoveEffectiveness(move, battlerAtk, battlerDef);
bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk);
u32 i;
u16 predictedMove = gLastMoves[battlerDef]; // TODO better move prediction
if (IsTargetingPartner(battlerAtk, battlerDef))
return score;
GET_MOVE_TYPE(move, move);
// check non-user target
if (!(gBattleMoves[move].target & MOVE_TARGET_USER))
{
@ -532,7 +534,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
RETURN_SCORE_MINUS(20);
}
// check ground immunities
if (moveType == TYPE_GROUND
&& !IsBattlerGrounded(battlerDef)
@ -544,11 +546,11 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
RETURN_SCORE_MINUS(20);
}
// check off screen
if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) != 1)
RETURN_SCORE_MINUS(20); // if target off screen and we go first, don't use move
// check if negates type
switch (effectiveness)
{
@ -559,7 +561,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
RETURN_SCORE_MINUS(10);
break;
}
// target ability checks
if (!DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move))
{
@ -674,7 +676,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
RETURN_SCORE_MINUS(10);
break;
} // def ability checks
// target partner ability checks & not attacking partner
if (isDoubleBattle)
{
@ -712,35 +714,35 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
} // def partner ability checks
} // ignore def ability check
// gen7+ dark type mons immune to priority->elevated moves from prankster
#if B_PRANKSTER >= GEN_7
if (AI_DATA->atkAbility == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) && IS_MOVE_STATUS(move)
&& !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER)))
RETURN_SCORE_MINUS(10);
#endif
// terrain & effect checks
if (AI_IsTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN))
{
if (moveEffect == EFFECT_SLEEP || moveEffect == EFFECT_YAWN)
RETURN_SCORE_MINUS(20);
}
if (AI_IsTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN))
{
if (IsNonVolatileStatusMoveEffect(moveEffect) || IsConfusionMoveEffect(moveEffect))
RETURN_SCORE_MINUS(20);
}
if (AI_IsTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && atkPriority > 0)
{
RETURN_SCORE_MINUS(20);
}
} // end check MOVE_TARGET_USER
// the following checks apply to any target (including user)
// throat chop check
if (gDisableStructs[battlerAtk].throatChopTimer && TestMoveFlags(move, FLAG_SOUND))
return 0; // Can't even select move at all
@ -748,8 +750,35 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(battlerAtk, move))
return 0; // Can't even select heal blocked move
// primal weather check
//TODO
if (WEATHER_HAS_EFFECT)
{
if (gBattleWeather & WEATHER_PRIMAL_ANY)
{
switch (move)
{
case MOVE_SUNNY_DAY:
case MOVE_RAIN_DANCE:
case MOVE_HAIL:
case MOVE_SANDSTORM:
RETURN_SCORE_MINUS(30);
}
}
if (!IS_MOVE_STATUS(move))
{
if (gBattleWeather & WEATHER_SUN_PRIMAL)
{
if (moveType == TYPE_WATER)
RETURN_SCORE_MINUS(30);
}
else if (gBattleWeather & WEATHER_RAIN_PRIMAL)
{
if (moveType == TYPE_FIRE)
RETURN_SCORE_MINUS(30);
}
}
}
// check move effects
switch (moveEffect)
{
@ -763,7 +792,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_EXPLOSION:
if (!(AI_THINKING_STRUCT->aiFlags & AI_FLAG_WILL_SUICIDE))
score -= 2;
if (effectiveness == AI_EFFECTIVENESS_x0)
{
score -= 10;
@ -813,7 +842,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_SPATK) || !HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL))
score -= 10;
break;
case EFFECT_SPECIAL_DEFENSE_UP:
case EFFECT_SPECIAL_DEFENSE_UP:
case EFFECT_SPECIAL_DEFENSE_UP_2:
if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_SPDEF))
score -= 10;
@ -1121,7 +1150,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_LOW_KICK:
// AI_CBM_HighRiskForDamage
if (AI_DATA->defAbility == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2)
score -= 10;
score -= 10;
break;
case EFFECT_COUNTER:
case EFFECT_MIRROR_COAT:
@ -1131,7 +1160,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|| DoesSubstituteBlockMove(battlerAtk, AI_DATA->battlerDefPartner, predictedMove))
score -= 10;
break;
case EFFECT_ROAR:
if (CountUsablePartyMons(battlerDef) == 0)
score -= 10;
@ -1279,7 +1308,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_SPIKES:
if (gSideTimers[GetBattlerSide(battlerDef)].spikesAmount >= 3)
score -= 10;
else if (PartnerMoveIsSameNoTarget(AI_DATA->battlerAtkPartner, move, AI_DATA->partnerMove)
else if (PartnerMoveIsSameNoTarget(AI_DATA->battlerAtkPartner, move, AI_DATA->partnerMove)
&& gSideTimers[GetBattlerSide(battlerDef)].spikesAmount == 2)
score -= 10; // only one mon needs to set up the last layer of Spikes
break;
@ -1457,7 +1486,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 10;
break;
}
if (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect == HOLD_EFFECT_CURE_ATTRACT)
score -= 6;
break;
@ -1687,7 +1716,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gBattleMons[battlerAtk].hp > (gBattleMons[battlerAtk].hp + gBattleMons[battlerDef].hp) / 2)
score -= 10;
break;
case EFFECT_CONVERSION_2:
//TODO
break;
@ -1747,7 +1776,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
} // move check
if (decreased)
break;
if (IsBattlerIncapacitated(battlerDef, AI_DATA->defAbility))
@ -1789,7 +1818,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
IncreaseAllyProtectionViability(&viability, 0xFF);
}*/
}
break;
break;
case EFFECT_MIRACLE_EYE:
if (gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED)
score -= 10;
@ -1837,7 +1866,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|| ((AI_DATA->defAbility == ABILITY_CONTRARY) && !IsTargetingPartner(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner
score -= 10;
break;
case EFFECT_PSYCH_UP: // haze stats check
{
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
@ -2001,7 +2030,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
u32 atkNegativeStages = CountNegativeStatStages(battlerAtk);
u32 defPositiveStages = CountPositiveStatStages(battlerDef);
u32 defNegativeStages = CountNegativeStatStages(battlerDef);
if (atkPositiveStages >= defPositiveStages && atkNegativeStages <= defNegativeStages)
score -= 10;
break;
@ -2399,21 +2428,21 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 10;
break;*/
} // move effect checks
if (score < 0)
score = 0;
return score;
}
static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
{
if (IsTargetingPartner(battlerAtk, battlerDef))
return score;
if (gBattleMoves[move].power == 0)
return score; // can't make anything faint with no power
if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION)
{
// this move can faint the target
@ -2427,24 +2456,43 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// this move isn't expected to faint the target
if (TestMoveFlags(move, FLAG_HIGH_CRIT))
score += 2; // crit makes it more likely to make them faint
if (GetMoveDamageResult(move) == MOVE_POWER_OTHER)
score--;
switch (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef))
{
case AI_EFFECTIVENESS_x4:
score += 4;
if (WEATHER_HAS_EFFECT
&& gBattleWeather & WEATHER_STRONG_WINDS
&& IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING))
{
if (AI_RandLessThan(176)) //Consider it supereffective instead of hypereffective.
score += 2;
else
score++;
}
else
score += 4;
break;
case AI_EFFECTIVENESS_x2:
if (AI_RandLessThan(176))
score += 2;
if (WEATHER_HAS_EFFECT
&& gBattleWeather & WEATHER_STRONG_WINDS
&& IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING))
{
break; // Don't increase score, consider it neutral.
}
else
score++;
{
if (AI_RandLessThan(176))
score += 2;
else
score++;
}
break;
}
}
//AI_TryToFaint_CheckIfDanger
if (!IsAiFaster(AI_CHECK_FASTER) && CanTargetFaintAi(battlerDef, battlerAtk))
{ // AI_TryToFaint_Danger
@ -2453,7 +2501,7 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
else
score++;
}
return score;
}
@ -2472,7 +2520,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
bool32 attackerHasBadAbility = (GetAbilityRating(AI_DATA->atkAbility) < 0);
bool32 partnerHasBadAbility = (GetAbilityRating(atkPartnerAbility) < 0);
u16 predictedMove = gLastMoves[battlerDef]; //for now
// check what effect partner is using
if (AI_DATA->partnerMove != 0)
{
@ -2506,8 +2554,8 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
}
} // check partner move effect
// consider our move effect relative to partner state
switch (effect)
{
@ -2528,8 +2576,8 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
} // our effect relative to partner
// consider global move effects
switch (effect)
{
@ -2559,8 +2607,8 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
} // global move effect check
// check specific target
if (IsTargetingPartner(battlerAtk, battlerDef))
{
@ -2667,11 +2715,11 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
RETURN_SCORE_PLUS(1);
}
break;
break;
}
} // ability checks
} // move power check
// attacker move effects specifically targeting partner
if (!partnerProtecting)
{
@ -2784,12 +2832,12 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
} // attacker move effects
} // check partner protecting
score -= 30; // otherwise, don't target partner
}
else // checking opponent
{
// these checks mostly handled in AI_CheckBadMove and AI_CheckViability
// these checks mostly handled in AI_CheckBadMove and AI_CheckViability
switch (effect)
{
case EFFECT_SKILL_SWAP:
@ -2812,10 +2860,10 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 3;
break;
}
// lightning rod, flash fire against enemy handled in AI_CheckBadMove
}
return score;
}
@ -2831,11 +2879,11 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
u32 i;
u8 atkHpPercent = GetHealthPercentage(battlerAtk);
u8 defHpPercent = GetHealthPercentage(battlerDef);
// Targeting partner, check benefits of doing that instead
if (IsTargetingPartner(battlerAtk, battlerDef))
return score;
// check always hits
if (!IS_MOVE_STATUS(move) && gBattleMoves[move].accuracy == 0)
{
@ -2844,22 +2892,22 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (AI_RandLessThan(100) && (gBattleMons[battlerDef].statStages[STAT_EVASION] >= 8 || gBattleMons[battlerAtk].statStages[STAT_ACC] <= 4))
score++;
}
// check high crit
if (TestMoveFlags(move, FLAG_HIGH_CRIT) && effectiveness >= AI_EFFECTIVENESS_x2 && AI_RandLessThan(128))
score++;
// check already dead
if (!IsBattlerIncapacitated(battlerDef, AI_DATA->defAbility)
&& CanTargetFaintAi(battlerAtk, battlerDef)
&& GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1) // opponent should go first
{
if (atkPriority > 0)
if (atkPriority > 0)
score++;
else
score--;
}
// check damage
if (gBattleMoves[move].power != 0 && GetMoveDamageResult(move) == MOVE_POWER_WEAK)
score--;
@ -2867,11 +2915,11 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// check status move preference
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_PREFER_STATUS_MOVES && IS_MOVE_STATUS(move) && effectiveness != AI_EFFECTIVENESS_x0)
score++;
// check thawing moves
if ((gBattleMons[battlerAtk].status1 & STATUS1_FREEZE) && TestMoveFlags(move, FLAG_THAW_USER))
score += (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) ? 20 : 10;
// check burn
if (gBattleMons[battlerAtk].status1 & STATUS1_BURN)
{
@ -2890,7 +2938,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
}
}
// ability checks
switch (AI_DATA->atkAbility)
{
@ -2917,12 +2965,12 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
}
break;
} // ability checks
} // ability checks
// move effect checks
switch (moveEffect)
{
case EFFECT_HIT:
break;
case EFFECT_SLEEP:
@ -2964,7 +3012,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
}
}
if (!AI_RandLessThan(100))
{
score--;
@ -3010,7 +3058,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
}
}
if (!AI_RandLessThan(100))
{
score--;
@ -3033,7 +3081,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 2;
else if (atkHpPercent <= 70)
score -= 2;
else
else
score++;
break;
case EFFECT_EVASION_UP:
@ -3163,7 +3211,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_ATTACK_SPATK_UP: // work up
if (GetHealthPercentage(battlerAtk) <= 40 || AI_DATA->atkAbility == ABILITY_CONTRARY)
break;
if (HasMoveWithSplit(battlerAtk, SPLIT_PHYSICAL))
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_ATK, &score);
else if (HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL))
@ -3215,7 +3263,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
default:
break;
}
if (ShouldRecover(battlerAtk, battlerDef, move, healPercent))
score += 2;
}
@ -3443,7 +3491,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (newHp > healthBenchmark && ShouldAbsorb(battlerAtk, battlerDef, move, AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]))
score += 2;
}
break;
break;
case EFFECT_SLEEP_TALK:
case EFFECT_SNORE:
if (!IsWakeupTurn(battlerAtk) && gBattleMons[battlerAtk].status1 & STATUS1_SLEEP)
@ -3478,13 +3526,13 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_THIEF:
{
bool32 canSteal = FALSE;
#if defined B_TRAINERS_KNOCK_OFF_ITEMS && B_TRAINERS_KNOCK_OFF_ITEMS == TRUE
canSteal = TRUE;
#endif
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || GetBattlerSide(battlerAtk) == B_SIDE_PLAYER)
canSteal = TRUE;
if (canSteal && AI_DATA->atkItem == ITEM_NONE
&& AI_DATA->defItem != ITEM_NONE
&& CanBattlerGetOrLoseItem(battlerDef, AI_DATA->defItem)
@ -3628,8 +3676,8 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (AI_DATA->defAbility == ABILITY_MAGIC_BOUNCE || CountUsablePartyMons(battlerDef) == 0)
break;
if (gDisableStructs[battlerAtk].isFirstTurn)
score += 2;
//TODO - track entire opponent party data to determine hazard effectiveness
score += 2;
//TODO - track entire opponent party data to determine hazard effectiveness
break;
case EFFECT_FORESIGHT:
if (AI_DATA->atkAbility == ABILITY_SCRAPPY)
@ -3658,7 +3706,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (HasMoveEffect(battlerDef, EFFECT_MORNING_SUN)
|| HasMoveEffect(battlerDef, EFFECT_SYNTHESIS)
|| HasMoveEffect(battlerDef, EFFECT_MOONLIGHT))
score += 2;
score += 2;
}
break;
case EFFECT_HAIL:
@ -3667,7 +3715,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if ((HasMoveEffect(battlerAtk, EFFECT_AURORA_VEIL) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_AURORA_VEIL))
&& ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL))
score += 3;
score++;
if (AI_DATA->atkHoldEffect == HOLD_EFFECT_ICY_ROCK)
score++;
@ -3726,7 +3774,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_SPECTRAL_THIEF:
// Want to copy positive stat changes
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
{
{
if (gBattleMons[battlerDef].statStages[i] > gBattleMons[battlerAtk].statStages[i])
{
switch (i)
@ -3785,7 +3833,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (HasMoveEffect(battlerAtk, EFFECT_SWALLOW)
|| HasMoveEffect(battlerAtk, EFFECT_SPIT_UP))
score += 2;
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_DEF, &score);
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score);
break;
@ -3802,20 +3850,20 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|| HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP)
|| HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF))
score++;
if (AI_DATA->defAbility == ABILITY_CONTRARY)
score += 2;
IncreaseConfusionScore(battlerAtk, battlerDef, move, &score);
break;
case EFFECT_FLATTER:
if (HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP)
|| HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF))
score += 2;
if (AI_DATA->defAbility == ABILITY_CONTRARY)
score += 2;
IncreaseConfusionScore(battlerAtk, battlerDef, move, &score);
break;
case EFFECT_FURY_CUTTER:
@ -3856,7 +3904,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score += 3;
break;
}
switch (move)
{
case MOVE_DEFOG:
@ -3872,7 +3920,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
&& GetWhoStrikesFirst(battlerAtk, AI_DATA->battlerAtkPartner, TRUE) == 1) // Partner going first
break; // Don't use Defog if partner is going to set up hazards
}
// check defog lowering evasion
if (ShouldLowerEvasion(battlerAtk, battlerDef, AI_DATA->defAbility))
{
@ -3912,7 +3960,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_CHARGE:
if (HasDamagingMoveOfType(battlerAtk, TYPE_ELECTRIC))
score += 2;
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score);
break;
case EFFECT_TAUNT:
@ -4081,7 +4129,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
if (AI_DATA->defAbility != AI_DATA->atkAbility && !(gStatuses3[battlerDef] & STATUS3_GASTRO_ACID))
score += 2;
}
}
break;
case EFFECT_IMPRISON:
if (predictedMove != MOVE_NONE && HasMove(battlerAtk, predictedMove))
@ -4152,7 +4200,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_SHELL_SMASH:
if (AI_DATA->atkHoldEffect == HOLD_EFFECT_POWER_HERB)
score += 3;
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPEED, &score);
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPATK, &score);
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_ATK, &score);
@ -4256,7 +4304,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk))
score += 10;
//fallthrough
case EFFECT_GRASSY_TERRAIN:
case EFFECT_GRASSY_TERRAIN:
case EFFECT_PSYCHIC_TERRAIN:
score += 2;
if (AI_DATA->atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER)
@ -4529,7 +4577,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
//case EFFECT_SKY_DROP
//break;
} // move effect checks
return score;
}
@ -4539,15 +4587,15 @@ static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (IsTargetingPartner(battlerAtk, battlerDef)
|| gBattleResults.battleTurnCounter != 0)
return score;
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING
&& GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1
&& CanTargetFaintAi(battlerDef, battlerAtk)
&& GetMovePriority(battlerAtk, move) == 0)
{
RETURN_SCORE_MINUS(20); // No point in setting up if you will faint. Should just switch if possible..
}
// check effects to prioritize first turn
switch (gBattleMoves[move].effect)
{
@ -4636,7 +4684,7 @@ static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
default:
break;
}
return score;
}
@ -4645,10 +4693,10 @@ static s16 AI_Risky(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
if (IsTargetingPartner(battlerAtk, battlerDef))
return score;
if (TestMoveFlags(move, FLAG_HIGH_CRIT))
score += 2;
switch (gBattleMoves[move].effect)
{
case EFFECT_SLEEP:
@ -4675,7 +4723,7 @@ static s16 AI_Risky(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
default:
break;
}
return score;
}
@ -4684,10 +4732,10 @@ static s16 AI_PreferStrongestMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 sc
{
if (IsTargetingPartner(battlerAtk, battlerDef))
return score;
if (GetMoveDamageResult(move) == MOVE_POWER_BEST)
score += 2;
return score;
}
@ -4695,14 +4743,14 @@ static s16 AI_PreferStrongestMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 sc
static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
u32 i;
if (IsTargetingPartner(battlerAtk, battlerDef)
|| CountUsablePartyMons(battlerAtk) == 0
|| GetMoveDamageResult(move) != MOVE_POWER_OTHER
|| !HasMoveEffect(battlerAtk, EFFECT_BATON_PASS)
|| IsBattlerTrapped(battlerAtk, TRUE))
return score;
if (IsStatRaisingEffect(gBattleMoves[move].effect))
{
if (gBattleResults.battleTurnCounter == 0)
@ -4710,9 +4758,9 @@ static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
else if (GetHealthPercentage(battlerAtk) < 60)
score -= 10;
else
score++;
score++;
}
// other specific checks
switch (gBattleMoves[move].effect)
{
@ -4738,12 +4786,12 @@ static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING))
score += 2;
if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED)
score -= 3;
score -= 3;
break;
default:
break;
}
return score;
}
@ -4751,7 +4799,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
u16 effect = gBattleMoves[move].effect;
u8 moveType = gBattleMoves[move].type;
if (IsTargetingPartner(battlerAtk, battlerDef))
{
if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY)
@ -4761,7 +4809,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (CanTargetFaintAi(FOE(battlerAtk), AI_DATA->battlerAtkPartner)
|| (CanTargetFaintAi(BATTLE_PARTNER(FOE(battlerAtk)), AI_DATA->battlerAtkPartner)))
score--;
if (GetHealthPercentage(battlerDef) <= 50)
score++;
}
@ -4800,7 +4848,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// med hp
if (IsStatRaisingEffect(effect) || IsStatLoweringEffect(effect))
score -= 2;
switch (effect)
{
case EFFECT_EXPLOSION:
@ -4823,7 +4871,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// low hp
if (IsStatRaisingEffect(effect) || IsStatLoweringEffect(effect))
score -= 2;
// check other discouraged low hp effects
switch (effect)
{
@ -4856,7 +4904,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
}
}
// consider target HP
if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
{
@ -4928,7 +4976,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 2; // don't use status moves if target is at low health
}
}
return score;
}
@ -4947,7 +4995,7 @@ static s16 AI_Roaming(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
if (IsBattlerTrapped(battlerAtk, FALSE))
return score;
AI_Flee();
return score;
}