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:
parent
216d8f0608
commit
c0c6821f62
1 changed files with 163 additions and 115 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue