Use stored values for ai switch-in effectiveness checks (#7794)
Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
This commit is contained in:
parent
66b7a7bf1e
commit
5e07d4a509
@ -172,6 +172,7 @@ uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef);
|
||||
u16 *GetMovesArray(u32 battler);
|
||||
bool32 IsConfusionMoveEffect(enum BattleMoveEffects moveEffect);
|
||||
bool32 HasMove(u32 battlerId, u32 move);
|
||||
u32 GetIndexInMoveArray(u32 battler, u32 move);
|
||||
bool32 HasOnlyMovesWithCategory(u32 battlerId, enum DamageCategory category, bool32 onlyOffensive);
|
||||
bool32 HasMoveWithCategory(u32 battler, enum DamageCategory category);
|
||||
bool32 HasMoveWithType(u32 battler, u32 type);
|
||||
@ -292,7 +293,7 @@ void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
|
||||
void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
|
||||
void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
|
||||
|
||||
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, enum DamageCalcContext calcContext);
|
||||
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, uq4_12_t *effectiveness, enum DamageCalcContext calcContext);
|
||||
u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority ConsiderPriority);
|
||||
s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle);
|
||||
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
|
||||
|
||||
@ -276,7 +276,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
if (!IsBattleMoveStatus(aiMove) && !AI_DoesChoiceEffectBlockMove(battler, aiMove))
|
||||
{
|
||||
// Check if mon has a super effective move
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0))
|
||||
hasSuperEffectiveMove = TRUE;
|
||||
|
||||
// Get maximum damage mon can deal
|
||||
@ -408,9 +408,10 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
aiMove = gBattleMons[battler].moves[moveIndex];
|
||||
if ((AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0)
|
||||
|| AI_GetMoveEffectiveness(aiMove, battler, opposingPartner) > UQ_4_12(0.0))
|
||||
&& aiMove != MOVE_NONE)
|
||||
if (aiMove == MOVE_NONE)
|
||||
continue;
|
||||
if (gAiLogicData->effectiveness[battler][opposingBattler][moveIndex] > UQ_4_12(0.0)
|
||||
|| gAiLogicData->effectiveness[battler][opposingPartner][moveIndex] > UQ_4_12(0.0))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -419,7 +420,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
aiMove = gBattleMons[battler].moves[moveIndex];
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) && aiMove != MOVE_NONE
|
||||
if (gAiLogicData->effectiveness[battler][opposingBattler][moveIndex] > UQ_4_12(0.0) && aiMove != MOVE_NONE
|
||||
&& !CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], aiMove, GetBattleMoveType(aiMove), AI_CHECK)
|
||||
&& !CanAbilityBlockMove(battler, opposingBattler, gBattleMons[battler].ability, gAiLogicData->abilities[opposingBattler], aiMove, AI_CHECK)
|
||||
&& (!ALL_MOVES_BAD_STATUS_MOVES_BAD || gMovesInfo[aiMove].power != 0)) // If using ALL_MOVES_BAD_STATUS_MOVES_BAD, then need power to be non-zero
|
||||
@ -441,7 +442,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
|
||||
static bool32 ShouldSwitchIfWonderGuard(u32 battler)
|
||||
{
|
||||
u32 opposingBattler = GetOppositeBattler(battler);
|
||||
u32 i, move;
|
||||
u32 i;
|
||||
|
||||
if (IsDoubleBattle())
|
||||
return FALSE;
|
||||
@ -452,12 +453,8 @@ static bool32 ShouldSwitchIfWonderGuard(u32 battler)
|
||||
// Check if Pokémon has a super effective move.
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
move = gBattleMons[battler].moves[i];
|
||||
if (move != MOVE_NONE)
|
||||
{
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
return FALSE;
|
||||
}
|
||||
if (gBattleMons[battler].moves[i] != MOVE_NONE && gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (RandomPercentage(RNG_AI_SWITCH_WONDER_GUARD, GetSwitchChance(SHOULD_SWITCH_WONDER_GUARD)))
|
||||
@ -707,8 +704,8 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler)
|
||||
|| monAbility == ABILITY_EARLY_BIRD)
|
||||
|| holdEffect == (HOLD_EFFECT_CURE_SLP | HOLD_EFFECT_CURE_STATUS)
|
||||
|| HasMove(battler, MOVE_SLEEP_TALK)
|
||||
|| (HasMoveWithEffect(battler, MOVE_SNORE) && AI_GetMoveEffectiveness(MOVE_SNORE, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
|| (IsBattlerGrounded(battler, gAiLogicData->abilities[battler], gAiLogicData->holdEffects[battler])
|
||||
|| (HasMove(battler, MOVE_SNORE) && gAiLogicData->effectiveness[battler][opposingBattler][GetIndexInMoveArray(battler, MOVE_SNORE)] >= UQ_4_12(2.0))
|
||||
|| (IsBattlerGrounded(battler, monAbility, gAiLogicData->holdEffects[battler])
|
||||
&& (HasMove(battler, MOVE_MISTY_TERRAIN) || HasMove(battler, MOVE_ELECTRIC_TERRAIN)))
|
||||
)
|
||||
switchMon = FALSE;
|
||||
@ -831,10 +828,8 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler)
|
||||
if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move))
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
{
|
||||
if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!IsDoubleBattle())
|
||||
@ -850,10 +845,8 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler)
|
||||
if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move))
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
{
|
||||
if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1020,7 +1013,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler)
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
// Stay in if effective move
|
||||
else if (AI_GetMoveEffectiveness(encoredMove, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
else if (gAiLogicData->effectiveness[battler][opposingBattler][GetIndexInMoveArray(battler, encoredMove)] >= UQ_4_12(2.0))
|
||||
return FALSE;
|
||||
|
||||
// Switch out 50% of the time otherwise
|
||||
@ -1495,8 +1488,8 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva
|
||||
int i, j;
|
||||
int dmg, bestDmg = 0;
|
||||
int bestMonId = PARTY_SIZE;
|
||||
|
||||
u32 aiMove;
|
||||
uq4_12_t effectiveness;
|
||||
|
||||
// If we couldn't find the best mon in terms of typing, find the one that deals most damage.
|
||||
for (i = firstId; i < lastId; i++)
|
||||
@ -1510,7 +1503,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva
|
||||
if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove))
|
||||
{
|
||||
aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j);
|
||||
dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING);
|
||||
dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &effectiveness, AI_ATTACKING);
|
||||
if (bestDmg < dmg)
|
||||
{
|
||||
bestDmg = dmg;
|
||||
@ -1987,13 +1980,14 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattle
|
||||
u32 playerMove;
|
||||
u16 *playerMoves = GetMovesArray(opposingBattler);
|
||||
s32 damageTaken = 0, maxDamageTaken = 0;
|
||||
uq4_12_t effectiveness;
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i];
|
||||
if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0)
|
||||
{
|
||||
damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING);
|
||||
damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, &effectiveness, AI_DEFENDING);
|
||||
if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move
|
||||
return damageTaken;
|
||||
if (damageTaken > maxDamageTaken)
|
||||
@ -2012,6 +2006,7 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposi
|
||||
u32 playerMove;
|
||||
u16 *playerMoves = GetMovesArray(opposingBattler);
|
||||
s32 damageTaken = 0, maxDamageTaken = 0;
|
||||
uq4_12_t effectiveness = UQ_4_12(1.0);
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
@ -2019,7 +2014,7 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposi
|
||||
if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0
|
||||
&& playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0)
|
||||
{
|
||||
damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING);
|
||||
damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, &effectiveness, AI_DEFENDING);
|
||||
if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move
|
||||
return damageTaken;
|
||||
if (damageTaken > maxDamageTaken)
|
||||
@ -2119,6 +2114,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
u32 bestResist = UQ_4_12(2.0), bestResistEffective = UQ_4_12(2.0), typeMatchup; // 2.0 is the default "Neutral" matchup from GetBattleMonTypeMatchup
|
||||
bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, isSwitchinFirstPriority, canSwitchinWin1v1;
|
||||
u32 invalidMons = 0;
|
||||
uq4_12_t effectiveness = UQ_4_12(1.0);
|
||||
|
||||
// Iterate through mons
|
||||
for (i = firstId; i < lastId; i++)
|
||||
@ -2163,7 +2159,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
continue;
|
||||
|
||||
aiMove = gAiLogicData->switchinCandidate.battleMon.moves[j];
|
||||
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING);
|
||||
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &effectiveness, AI_ATTACKING);
|
||||
hitsToKOPlayer = GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler);
|
||||
|
||||
// Offensive switchin decisions are based on which whether switchin moves first and whether it can win a 1v1
|
||||
@ -2204,7 +2200,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
{
|
||||
if (typeMatchup < bestResistEffective)
|
||||
{
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
if (effectiveness >= UQ_4_12(2.0))
|
||||
{
|
||||
if (canSwitchinWin1v1)
|
||||
{
|
||||
|
||||
@ -2313,6 +2313,18 @@ u16 *GetMovesArray(u32 battler)
|
||||
return gBattleHistory->usedMoves[battler];
|
||||
}
|
||||
|
||||
u32 GetIndexInMoveArray(u32 battler, u32 move)
|
||||
{
|
||||
u16 *moves = GetMovesArray(battler);
|
||||
u32 i;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i] == move)
|
||||
return i;
|
||||
}
|
||||
return MAX_MON_MOVES;
|
||||
}
|
||||
|
||||
bool32 HasOnlyMovesWithCategory(u32 battlerId, enum DamageCategory category, bool32 onlyOffensive)
|
||||
{
|
||||
u32 i;
|
||||
@ -4319,10 +4331,9 @@ static void SetBattlerFieldStatusForSwitchin(u32 battler)
|
||||
}
|
||||
|
||||
// party logic
|
||||
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, enum DamageCalcContext calcContext)
|
||||
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, uq4_12_t *effectiveness, enum DamageCalcContext calcContext)
|
||||
{
|
||||
struct SimulatedDamage dmg;
|
||||
uq4_12_t effectiveness;
|
||||
struct BattlePokemon *savedBattleMons = AllocSaveBattleMons();
|
||||
|
||||
if (calcContext == AI_ATTACKING)
|
||||
@ -4342,7 +4353,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl
|
||||
gAiThinkingStruct->saved[battlerAtk].saved = FALSE;
|
||||
}
|
||||
|
||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetSwitchinWeather(switchinCandidate));
|
||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetSwitchinWeather(switchinCandidate));
|
||||
// restores original gBattleMon struct
|
||||
FreeRestoreBattleMons(savedBattleMons);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user