Fixed AI not handling type effectiveness beyond x8 (#6127)
This commit is contained in:
parent
a34a3cad36
commit
927bb8f833
@ -350,7 +350,7 @@ struct AiLogicData
|
||||
u16 partnerMove;
|
||||
u16 speedStats[MAX_BATTLERS_COUNT]; // Speed stats for all battles, calculated only once, same way as damages
|
||||
struct SimulatedDamage simulatedDmg[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // attacker, target, moveIndex
|
||||
u8 effectiveness[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // attacker, target, moveIndex
|
||||
uq4_12_t effectiveness[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // attacker, target, moveIndex
|
||||
u8 moveAccuracy[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // attacker, target, moveIndex
|
||||
u8 moveLimitations[MAX_BATTLERS_COUNT];
|
||||
u8 monToSwitchInId[MAX_BATTLERS_COUNT]; // ID of the mon to switch in.
|
||||
|
||||
@ -101,15 +101,14 @@ bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u32 defAbility);
|
||||
bool32 IsAffectedByPowder(u32 battler, u32 ability, u32 holdEffect);
|
||||
bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, u32 category);
|
||||
s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo);
|
||||
struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, enum DamageRollType rollType);
|
||||
struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, u32 weather, enum DamageRollType rollType);
|
||||
struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, bool32 considerZPower, enum DamageRollType rollType);
|
||||
struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, bool32 considerZPower, u32 weather, enum DamageRollType rollType);
|
||||
bool32 AI_IsDamagedByRecoil(u32 battler);
|
||||
u32 GetNoOfHitsToKO(u32 dmg, s32 hp);
|
||||
u32 GetNoOfHitsToKOBattlerDmg(u32 dmg, u32 battlerDef);
|
||||
u32 GetNoOfHitsToKOBattler(u32 battlerAtk, u32 battlerDef, u32 moveIndex);
|
||||
u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef);
|
||||
uq4_12_t AI_GetTypeEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef);
|
||||
u32 AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef);
|
||||
uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef);
|
||||
u16 *GetMovesArray(u32 battler);
|
||||
bool32 IsConfusionMoveEffect(u32 moveEffect);
|
||||
bool32 HasMove(u32 battlerId, u32 move);
|
||||
|
||||
@ -14,16 +14,6 @@
|
||||
#define AI_TYPE2_USER 3
|
||||
#define AI_TYPE_MOVE 4
|
||||
|
||||
// type effectiveness
|
||||
#define AI_EFFECTIVENESS_x8 7
|
||||
#define AI_EFFECTIVENESS_x4 6
|
||||
#define AI_EFFECTIVENESS_x2 5
|
||||
#define AI_EFFECTIVENESS_x1 4
|
||||
#define AI_EFFECTIVENESS_x0_5 3
|
||||
#define AI_EFFECTIVENESS_x0_25 2
|
||||
#define AI_EFFECTIVENESS_x0_125 1
|
||||
#define AI_EFFECTIVENESS_x0 0
|
||||
|
||||
// AI Flags. Most run specific functions to update score, new flags are used for internal logic in other scripts
|
||||
// See docs/ai_flags.md for more details.
|
||||
#define AI_FLAG_CHECK_BAD_MOVE (1 << 0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation.
|
||||
|
||||
@ -421,7 +421,7 @@ static void CalcBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
struct SimulatedDamage dmg = {0};
|
||||
u8 effectiveness = AI_EFFECTIVENESS_x0;
|
||||
uq4_12_t effectiveness = Q_4_12(0.0);
|
||||
move = moves[moveIndex];
|
||||
|
||||
if (move != MOVE_NONE
|
||||
@ -722,14 +722,14 @@ static inline void BattleAI_DoAIProcessing(struct AI_ThinkingStruct *aiThink, u3
|
||||
void BattleAI_DoAIProcessing_PredictedSwitchin(struct AI_ThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
struct BattlePokemon switchoutCandidate = gBattleMons[battlerDef];
|
||||
struct SimulatedDamage simulatedDamageSwitchout[4];
|
||||
u8 effectivenessSwitchout[4];
|
||||
u8 moveAccuracySwitchout[4];
|
||||
struct SimulatedDamage simulatedDamageSwitchout[MAX_MON_MOVES];
|
||||
uq4_12_t effectivenessSwitchout[MAX_MON_MOVES];
|
||||
u8 moveAccuracySwitchout[MAX_MON_MOVES];
|
||||
|
||||
struct BattlePokemon switchinCandidate;
|
||||
struct SimulatedDamage simulatedDamageSwitchin[4];
|
||||
u8 effectivenessSwitchin[4];
|
||||
u8 moveAccuracySwitchin[4];
|
||||
struct SimulatedDamage simulatedDamageSwitchin[MAX_MON_MOVES];
|
||||
uq4_12_t effectivenessSwitchin[MAX_MON_MOVES];
|
||||
u8 moveAccuracySwitchin[MAX_MON_MOVES];
|
||||
|
||||
struct Pokemon *party = GetBattlerParty(battlerDef);
|
||||
struct BattlePokemon *savedBattleMons = AllocSaveBattleMons();
|
||||
@ -839,7 +839,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
s32 moveType;
|
||||
u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move);
|
||||
struct AiLogicData *aiData = AI_DATA;
|
||||
u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex];
|
||||
uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex];
|
||||
bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk);
|
||||
u32 i;
|
||||
u32 weather;
|
||||
@ -863,14 +863,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (gBattleStruct->battlerState[battlerDef].commandingDondozo)
|
||||
RETURN_SCORE_MINUS(20);
|
||||
|
||||
// check if negates type
|
||||
switch (effectiveness)
|
||||
if (effectiveness == UQ_4_12(0.0))
|
||||
{
|
||||
case AI_EFFECTIVENESS_x0:
|
||||
RETURN_SCORE_MINUS(20);
|
||||
break;
|
||||
case AI_EFFECTIVENESS_x0_125:
|
||||
case AI_EFFECTIVENESS_x0_25:
|
||||
}
|
||||
else if (effectiveness < UQ_4_12(0.5))
|
||||
{
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_FIXED_DAMAGE_ARG:
|
||||
@ -889,7 +887,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
default:
|
||||
RETURN_SCORE_MINUS(10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// check non-user target
|
||||
@ -922,7 +919,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
}
|
||||
break;
|
||||
case ABILITY_WONDER_GUARD:
|
||||
if (effectiveness < AI_EFFECTIVENESS_x2)
|
||||
if (effectiveness < UQ_4_12(2.0))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
break;
|
||||
case ABILITY_JUSTIFIED:
|
||||
@ -1117,7 +1114,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_WILL_SUICIDE))
|
||||
ADJUST_SCORE(-2);
|
||||
|
||||
if (effectiveness == AI_EFFECTIVENESS_x0)
|
||||
if (effectiveness == UQ_4_12(0.0))
|
||||
{
|
||||
ADJUST_SCORE(-10);
|
||||
}
|
||||
@ -1452,7 +1449,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_FIXED_DAMAGE_ARG:
|
||||
case EFFECT_FOCUS_PUNCH:
|
||||
// AI_CBM_HighRiskForDamage
|
||||
if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2)
|
||||
if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < UQ_4_12(2.0))
|
||||
ADJUST_SCORE(-10);
|
||||
if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE)
|
||||
|| IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef])
|
||||
@ -2840,7 +2837,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_MAGNET_RISE:
|
||||
if (IsBattlerGrounded(battlerAtk)
|
||||
&& (HasMove(battlerAtkPartner, MOVE_EARTHQUAKE) || HasMove(battlerAtkPartner, MOVE_MAGNITUDE))
|
||||
&& (AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerAtk, battlerAtkPartner) != AI_EFFECTIVENESS_x0)) // Doesn't resist ground move
|
||||
&& (AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerAtk, battlerAtkPartner) != UQ_4_12(0.0))) // Doesn't resist ground move
|
||||
{
|
||||
RETURN_SCORE_PLUS(DECENT_EFFECT); // partner has earthquake or magnitude -> good idea to use magnet rise
|
||||
}
|
||||
@ -3309,7 +3306,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
u32 moveEffect = GetMoveEffect(move);
|
||||
struct AiLogicData *aiData = AI_DATA;
|
||||
u32 movesetIndex = AI_THINKING_STRUCT->movesetIndex;
|
||||
u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][movesetIndex];
|
||||
uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][movesetIndex];
|
||||
|
||||
s32 score = 0;
|
||||
u32 predictedMove = aiData->lastUsedMove[battlerDef];
|
||||
@ -3323,7 +3320,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
moveEffect = EFFECT_PROTECT;
|
||||
|
||||
// check status move preference
|
||||
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_PREFER_STATUS_MOVES && IsBattleMoveStatus(move) && effectiveness != AI_EFFECTIVENESS_x0)
|
||||
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_PREFER_STATUS_MOVES && IsBattleMoveStatus(move) && effectiveness != UQ_4_12(0.0))
|
||||
ADJUST_SCORE(10);
|
||||
|
||||
// check thawing moves
|
||||
@ -3346,7 +3343,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
IncreaseSleepScore(battlerAtk, battlerDef, move, &score);
|
||||
break;
|
||||
case EFFECT_ABSORB:
|
||||
if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT && effectiveness >= AI_EFFECTIVENESS_x1)
|
||||
if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT && effectiveness >= UQ_4_12(1.0))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case EFFECT_EXPLOSION:
|
||||
@ -4488,7 +4485,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
break;
|
||||
case EFFECT_MAGNET_RISE:
|
||||
if (IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC)
|
||||
&& !(AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerDef, battlerAtk) == AI_EFFECTIVENESS_x0)) // Doesn't resist ground move
|
||||
&& !(effectiveness == UQ_4_12(0.0))) // Doesn't resist ground move
|
||||
{
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first
|
||||
{
|
||||
@ -4506,7 +4503,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
break;
|
||||
case EFFECT_CAMOUFLAGE:
|
||||
if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move) // Attacker goes first
|
||||
&& !IsBattleMoveStatus(move) && AI_GetMoveEffectiveness(predictedMove, battlerDef, battlerAtk) != AI_EFFECTIVENESS_x0)
|
||||
&& !IsBattleMoveStatus(move) && effectiveness != UQ_4_12(0.0))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case EFFECT_TOXIC_THREAD:
|
||||
@ -5408,7 +5405,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
u32 aiHazardFlags = gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_HAZARDS_ANY);
|
||||
u32 moveEffect = gMovesInfo[move].effect;
|
||||
struct AiLogicData *aiData = AI_DATA;
|
||||
u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex];
|
||||
uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex];
|
||||
|
||||
// Switch benefit
|
||||
switch (moveEffect)
|
||||
@ -5429,7 +5426,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_CHECK_BAD_MOVE)
|
||||
{
|
||||
if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2)
|
||||
if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < UQ_4_12(2.0))
|
||||
ADJUST_SCORE(10);
|
||||
if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE)
|
||||
|| IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef])
|
||||
|
||||
@ -88,11 +88,12 @@ static inline bool32 SetSwitchinAndSwitch(u32 battler, u32 switchinId)
|
||||
static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
{
|
||||
//Variable initialization
|
||||
u8 opposingPosition, atkType1, atkType2, defType1, defType2, effectiveness;
|
||||
u8 opposingPosition, atkType1, atkType2, defType1, defType2;
|
||||
s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0;
|
||||
u32 aiMove, playerMove, aiBestMove = MOVE_NONE, aiAbility = AI_DATA->abilities[battler], opposingBattler, weather = AI_GetWeather(AI_DATA);
|
||||
bool32 getsOneShot = FALSE, hasStatusMove = FALSE, hasSuperEffectiveMove = FALSE;
|
||||
u16 typeEffectiveness = UQ_4_12(1.0), aiMoveEffect; //baseline typing damage
|
||||
uq4_12_t effectiveness;
|
||||
|
||||
// Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer
|
||||
if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING))
|
||||
@ -133,7 +134,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
if (!IsBattleMoveStatus(aiMove))
|
||||
{
|
||||
// Check if mon has a super effective move
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
hasSuperEffectiveMove = TRUE;
|
||||
|
||||
// Get maximum damage mon can deal
|
||||
@ -254,8 +255,8 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
aiMove = gBattleMons[battler].moves[moveIndex];
|
||||
if ((AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > AI_EFFECTIVENESS_x0
|
||||
|| AI_GetMoveEffectiveness(aiMove, battler, opposingPartner) > AI_EFFECTIVENESS_x0)
|
||||
if ((AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0)
|
||||
|| AI_GetMoveEffectiveness(aiMove, battler, opposingPartner) > UQ_4_12(0.0))
|
||||
&& aiMove != MOVE_NONE)
|
||||
return FALSE;
|
||||
}
|
||||
@ -265,7 +266,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) > AI_EFFECTIVENESS_x0 && aiMove != MOVE_NONE)
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) && aiMove != MOVE_NONE)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -294,7 +295,7 @@ static bool32 FindMonThatHitsWonderGuard(u32 battler)
|
||||
move = gBattleMons[battler].moves[i];
|
||||
if (move != MOVE_NONE)
|
||||
{
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -319,7 +320,7 @@ static bool32 FindMonThatHitsWonderGuard(u32 battler)
|
||||
if (move != MOVE_NONE)
|
||||
{
|
||||
// Found a mon
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
return SetSwitchinAndSwitch(battler, i);
|
||||
}
|
||||
}
|
||||
@ -527,7 +528,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler)
|
||||
|| monAbility == ABILITY_EARLY_BIRD)
|
||||
|| holdEffect == (HOLD_EFFECT_CURE_SLP | HOLD_EFFECT_CURE_STATUS)
|
||||
|| HasMove(battler, MOVE_SLEEP_TALK)
|
||||
|| (HasMoveEffect(battler, MOVE_SNORE) && AI_GetMoveEffectiveness(MOVE_SNORE, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
|| (HasMoveEffect(battler, MOVE_SNORE) && AI_GetMoveEffectiveness(MOVE_SNORE, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
|| (IsBattlerGrounded(battler)
|
||||
&& (HasMove(battler, MOVE_MISTY_TERRAIN) || HasMove(battler, MOVE_ELECTRIC_TERRAIN)))
|
||||
)
|
||||
@ -643,7 +644,7 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng)
|
||||
if (move == MOVE_NONE)
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
{
|
||||
if (noRng)
|
||||
return TRUE;
|
||||
@ -665,7 +666,7 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng)
|
||||
if (move == MOVE_NONE)
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
{
|
||||
if (noRng)
|
||||
return TRUE;
|
||||
@ -764,7 +765,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc
|
||||
if (move == 0)
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= AI_EFFECTIVENESS_x2 && (RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance) || AI_DATA->aiSwitchPredictionInProgress))
|
||||
if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= UQ_4_12(2.0) && (RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance) || AI_DATA->aiSwitchPredictionInProgress))
|
||||
return SetSwitchinAndSwitch(battler, i);
|
||||
}
|
||||
}
|
||||
@ -858,7 +859,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler)
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
// Stay in if effective move
|
||||
else if (AI_GetMoveEffectiveness(encoredMove, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
else if (AI_GetMoveEffectiveness(encoredMove, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
return FALSE;
|
||||
|
||||
// Switch out 50% of the time otherwise
|
||||
@ -1210,7 +1211,7 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId,
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
u32 move = GetMonData(&party[bestMonId], MON_DATA_MOVE1 + i);
|
||||
if (move != MOVE_NONE && AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
if (move != MOVE_NONE && AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1866,7 +1867,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
{
|
||||
if (typeMatchup < bestResistEffective)
|
||||
{
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= AI_EFFECTIVENESS_x2)
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
{
|
||||
if (canSwitchinWin1v1)
|
||||
{
|
||||
|
||||
@ -23,8 +23,6 @@
|
||||
#include "constants/moves.h"
|
||||
#include "constants/items.h"
|
||||
|
||||
static u32 AI_GetEffectiveness(uq4_12_t multiplier);
|
||||
|
||||
// Functions
|
||||
u32 GetDmgRollType(u32 battlerAtk)
|
||||
{
|
||||
@ -387,7 +385,7 @@ bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, u32 category)
|
||||
}
|
||||
|
||||
// To save computation time this function has 2 variants. One saves, sets and restores battlers, while the other doesn't.
|
||||
struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, enum DamageRollType rollType)
|
||||
struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, bool32 considerZPower, enum DamageRollType rollType)
|
||||
{
|
||||
struct SimulatedDamage dmg;
|
||||
|
||||
@ -395,7 +393,7 @@ struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 b
|
||||
SaveBattlerData(battlerDef);
|
||||
SetBattlerData(battlerAtk);
|
||||
SetBattlerData(battlerDef);
|
||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower, AI_GetWeather(AI_DATA), rollType);
|
||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower, AI_GetWeather(AI_DATA), rollType);
|
||||
RestoreBattlerData(battlerAtk);
|
||||
RestoreBattlerData(battlerDef);
|
||||
return dmg;
|
||||
@ -631,7 +629,7 @@ static inline void CalcDynamicMoveDamage(struct DamageCalculationData *damageCal
|
||||
*minimumDamage = minimum;
|
||||
}
|
||||
|
||||
struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, u32 weather, enum DamageRollType rollType)
|
||||
struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, bool32 considerZPower, u32 weather, enum DamageRollType rollType)
|
||||
{
|
||||
struct SimulatedDamage simDamage;
|
||||
s32 moveType;
|
||||
@ -755,7 +753,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
|
||||
}
|
||||
|
||||
// convert multiper to AI_EFFECTIVENESS_xX
|
||||
*typeEffectiveness = AI_GetEffectiveness(effectivenessMultiplier);
|
||||
*typeEffectiveness = effectivenessMultiplier;
|
||||
|
||||
// Undo temporary settings
|
||||
gBattleStruct->dynamicMoveType = 0;
|
||||
@ -1040,7 +1038,7 @@ u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef)
|
||||
return (bestDmg * 100) / gBattleMons[battlerDef].maxHP;
|
||||
}
|
||||
|
||||
uq4_12_t AI_GetTypeEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef)
|
||||
uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
uq4_12_t typeEffectiveness;
|
||||
u32 moveType;
|
||||
@ -1062,35 +1060,6 @@ uq4_12_t AI_GetTypeEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef)
|
||||
return typeEffectiveness;
|
||||
}
|
||||
|
||||
u32 AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
return AI_GetEffectiveness(AI_GetTypeEffectiveness(move, battlerAtk, battlerDef));
|
||||
}
|
||||
|
||||
static u32 AI_GetEffectiveness(uq4_12_t multiplier)
|
||||
{
|
||||
switch (multiplier)
|
||||
{
|
||||
case UQ_4_12(0.0):
|
||||
return AI_EFFECTIVENESS_x0;
|
||||
case UQ_4_12(0.125):
|
||||
return AI_EFFECTIVENESS_x0_125;
|
||||
case UQ_4_12(0.25):
|
||||
return AI_EFFECTIVENESS_x0_25;
|
||||
case UQ_4_12(0.5):
|
||||
return AI_EFFECTIVENESS_x0_5;
|
||||
case UQ_4_12(1.0):
|
||||
default:
|
||||
return AI_EFFECTIVENESS_x1;
|
||||
case UQ_4_12(2.0):
|
||||
return AI_EFFECTIVENESS_x2;
|
||||
case UQ_4_12(4.0):
|
||||
return AI_EFFECTIVENESS_x4;
|
||||
case UQ_4_12(8.0):
|
||||
return AI_EFFECTIVENESS_x8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks to see if AI will move ahead of another battler
|
||||
* The function uses a stripped down version of the checks from GetWhichBattlerFasterArgs
|
||||
* Output:
|
||||
@ -3012,7 +2981,7 @@ bool32 ShouldPoisonSelf(u32 battler, u32 ability)
|
||||
bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove)
|
||||
{
|
||||
if (!CanBePoisoned(battlerAtk, battlerDef, GetBattlerAbility(battlerDef))
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0)
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove))
|
||||
return FALSE;
|
||||
@ -3027,7 +2996,7 @@ bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u3
|
||||
bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove)
|
||||
{
|
||||
if (!CanBeParalyzed(battlerDef, defAbility)
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0)
|
||||
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove))
|
||||
@ -3089,7 +3058,7 @@ bool32 ShouldBurnSelf(u32 battler, u32 ability)
|
||||
bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove)
|
||||
{
|
||||
if (!CanBeBurned(battlerDef, defAbility)
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0)
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveEffectIsStatusSameTarget(battlerAtkPartner, battlerDef, partnerMove))
|
||||
{
|
||||
@ -3101,7 +3070,7 @@ bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtk
|
||||
bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove)
|
||||
{
|
||||
if (!AI_CanGetFrostbite(battlerDef, defAbility)
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0)
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveEffectIsStatusSameTarget(battlerAtkPartner, battlerDef, partnerMove))
|
||||
{
|
||||
@ -3113,7 +3082,7 @@ bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 b
|
||||
bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
{
|
||||
if ((gBattleMons[battlerDef].status2 & STATUS2_INFATUATION)
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0
|
||||
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0)
|
||||
|| defAbility == ABILITY_OBLIVIOUS
|
||||
|| !AreBattlersOfOppositeGender(battlerAtk, battlerDef)
|
||||
|| AI_IsAbilityOnSide(battlerDef, ABILITY_AROMA_VEIL))
|
||||
@ -3575,7 +3544,7 @@ void FreeRestoreBattleMons(struct BattlePokemon *savedBattleMons)
|
||||
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, bool32 isPartyMonAttacker, enum DamageRollType rollType)
|
||||
{
|
||||
struct SimulatedDamage dmg;
|
||||
u8 effectiveness;
|
||||
uq4_12_t effectiveness;
|
||||
struct BattlePokemon *savedBattleMons = AllocSaveBattleMons();
|
||||
|
||||
if (isPartyMonAttacker)
|
||||
@ -4048,7 +4017,7 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||
|
||||
if (IsViableZMove(battlerAtk, chosenMove))
|
||||
{
|
||||
u8 effectiveness;
|
||||
uq4_12_t effectiveness;
|
||||
u32 zMove = GetUsableZMove(battlerAtk, chosenMove);
|
||||
struct SimulatedDamage dmg;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user