get battlers' speed only once

This commit is contained in:
DizzyEggg 2023-09-13 14:04:25 +02:00
parent 1a64938c9b
commit 9031f5a063
3 changed files with 33 additions and 41 deletions

View File

@ -50,7 +50,7 @@ bool32 BattlerWillFaintFromWeather(u8 battler, u16 ability);
bool32 BattlerWillFaintFromSecondaryDamage(u8 battler, u16 ability); bool32 BattlerWillFaintFromSecondaryDamage(u8 battler, u16 ability);
bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u16 atkAbility, u16 defAbility, u16 move); bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u16 atkAbility, u16 defAbility, u16 move);
bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u8 moveIndex); bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u8 moveIndex);
u16 GetBattlerSideSpeedAverage(u8 battler); u32 GetBattlerSideSpeedAverage(u32 battler);
bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u16 move, s32 damage); bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u16 move, s32 damage);
bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u16 move, u8 healPercent); bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u16 move, u8 healPercent);
bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, u16 moveEffect); bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, u16 moveEffect);
@ -157,6 +157,7 @@ bool32 IsWakeupTurn(u8 battler);
bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId); bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId);
// partner logic // partner logic
#define IS_TARGETING_PARTNER(battlerAtk, battlerDef)((battlerAtk) == (battlerDef ^ BIT_FLANK))
u16 GetAllyChosenMove(u8 battlerId); u16 GetAllyChosenMove(u8 battlerId);
bool32 IsValidDoubleBattle(u32 battlerAtk); bool32 IsValidDoubleBattle(u32 battlerAtk);
bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef); bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef);

View File

@ -726,11 +726,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
u32 i; u32 i;
u16 predictedMove = AI_DATA->predictedMoves[battlerDef]; u16 predictedMove = AI_DATA->predictedMoves[battlerDef];
SetTypeBeforeUsingMove(move, battlerAtk); SetTypeBeforeUsingMove(move, battlerAtk);
GET_MOVE_TYPE(move, moveType); GET_MOVE_TYPE(move, moveType);
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
return score; return score;
GET_MOVE_TYPE(move, moveType); GET_MOVE_TYPE(move, moveType);
@ -880,7 +879,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
break; break;
case ABILITY_DEFIANT: case ABILITY_DEFIANT:
case ABILITY_COMPETITIVE: case ABILITY_COMPETITIVE:
if (IsStatLoweringMoveEffect(moveEffect) && !IsTargetingPartner(battlerAtk, battlerDef)) if (IsStatLoweringMoveEffect(moveEffect) && !IS_TARGETING_PARTNER(battlerAtk, battlerDef))
RETURN_SCORE_MINUS(8); RETURN_SCORE_MINUS(8);
break; break;
case ABILITY_COMATOSE: case ABILITY_COMATOSE:
@ -2103,7 +2102,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
// evasion check // evasion check
if (gBattleMons[battlerDef].statStages[STAT_EVASION] == MIN_STAT_STAGE if (gBattleMons[battlerDef].statStages[STAT_EVASION] == MIN_STAT_STAGE
|| ((AI_DATA->abilities[battlerDef] == ABILITY_CONTRARY) && !IsTargetingPartner(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner || ((AI_DATA->abilities[battlerDef] == ABILITY_CONTRARY) && !IS_TARGETING_PARTNER(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner
score -= 10; score -= 10;
break; break;
@ -2231,27 +2230,27 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
score -= 10; score -= 10;
break; break;
case EFFECT_POWER_TRICK: case EFFECT_POWER_TRICK:
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
score -= 10; score -= 10;
else if (gBattleMons[battlerAtk].defense >= gBattleMons[battlerAtk].attack && !HasMoveWithSplit(battlerAtk, SPLIT_PHYSICAL)) else if (gBattleMons[battlerAtk].defense >= gBattleMons[battlerAtk].attack && !HasMoveWithSplit(battlerAtk, SPLIT_PHYSICAL))
score -= 10; score -= 10;
break; break;
case EFFECT_POWER_SWAP: // Don't use if attacker's stat stages are higher than opponents case EFFECT_POWER_SWAP: // Don't use if attacker's stat stages are higher than opponents
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
score -= 10; score -= 10;
else if (gBattleMons[battlerAtk].statStages[STAT_ATK] >= gBattleMons[battlerDef].statStages[STAT_ATK] else if (gBattleMons[battlerAtk].statStages[STAT_ATK] >= gBattleMons[battlerDef].statStages[STAT_ATK]
&& gBattleMons[battlerAtk].statStages[STAT_SPATK] >= gBattleMons[battlerDef].statStages[STAT_SPATK]) && gBattleMons[battlerAtk].statStages[STAT_SPATK] >= gBattleMons[battlerDef].statStages[STAT_SPATK])
score -= 10; score -= 10;
break; break;
case EFFECT_GUARD_SWAP: // Don't use if attacker's stat stages are higher than opponents case EFFECT_GUARD_SWAP: // Don't use if attacker's stat stages are higher than opponents
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
score -= 10; score -= 10;
else if (gBattleMons[battlerAtk].statStages[STAT_DEF] >= gBattleMons[battlerDef].statStages[STAT_DEF] else if (gBattleMons[battlerAtk].statStages[STAT_DEF] >= gBattleMons[battlerDef].statStages[STAT_DEF]
&& gBattleMons[battlerAtk].statStages[STAT_SPDEF] >= gBattleMons[battlerDef].statStages[STAT_SPDEF]) && gBattleMons[battlerAtk].statStages[STAT_SPDEF] >= gBattleMons[battlerDef].statStages[STAT_SPDEF])
score -= 10; score -= 10;
break; break;
case EFFECT_SPEED_SWAP: case EFFECT_SPEED_SWAP:
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
{ {
score -= 10; score -= 10;
} }
@ -2264,7 +2263,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
} }
break; break;
case EFFECT_HEART_SWAP: case EFFECT_HEART_SWAP:
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
{ {
score -= 10; score -= 10;
} }
@ -2281,7 +2280,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
} }
break; break;
case EFFECT_POWER_SPLIT: case EFFECT_POWER_SPLIT:
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
{ {
score -= 10; score -= 10;
} }
@ -2298,7 +2297,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
} }
break; break;
case EFFECT_GUARD_SPLIT: case EFFECT_GUARD_SPLIT:
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
{ {
score -= 10; score -= 10;
} }
@ -2481,14 +2480,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
} }
break; break;
case EFFECT_HEAL_PULSE: // and floral healing case EFFECT_HEAL_PULSE: // and floral healing
if (!IsTargetingPartner(battlerAtk, battlerDef)) // Don't heal enemies if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) // Don't heal enemies
{ {
score -= 10; score -= 10;
break; break;
} }
// fallthrough // fallthrough
case EFFECT_HIT_ENEMY_HEAL_ALLY: // pollen puff case EFFECT_HIT_ENEMY_HEAL_ALLY: // pollen puff
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
{ {
if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK) if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK)
return 0; return 0;
@ -2505,7 +2504,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
score -= 10; score -= 10;
break; break;
case EFFECT_TOPSY_TURVY: case EFFECT_TOPSY_TURVY:
if (!IsTargetingPartner(battlerAtk, battlerDef)) if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef))
{ {
u8 targetPositiveStages = CountPositiveStatStages(battlerDef); u8 targetPositiveStages = CountPositiveStatStages(battlerDef);
u8 targetNegativeStages = CountNegativeStatStages(battlerDef); u8 targetNegativeStages = CountNegativeStatStages(battlerDef);
@ -2546,7 +2545,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
} }
else if (isDoubleBattle) else if (isDoubleBattle)
{ {
if (!IsTargetingPartner(battlerAtk, battlerDef)) if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef))
score -= 10; score -= 10;
} }
else else
@ -2571,7 +2570,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
score -= 10; score -= 10;
break; break;
case EFFECT_AFTER_YOU: case EFFECT_AFTER_YOU:
if (!IsTargetingPartner(battlerAtk, battlerDef) if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)
|| !isDoubleBattle || !isDoubleBattle
|| AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, AI_DATA->partnerMove)) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, AI_DATA->partnerMove))
@ -2703,7 +2702,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
u32 movesetIndex = AI_THINKING_STRUCT->movesetIndex; u32 movesetIndex = AI_THINKING_STRUCT->movesetIndex;
bool32 aiFaster; bool32 aiFaster;
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
return score; return score;
if (gBattleMoves[move].power == 0) if (gBattleMoves[move].power == 0)
@ -2868,7 +2867,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
} // global move effect check } // global move effect check
// check specific target // check specific target
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
{ {
if (GetMoveDamageResult(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex) == MOVE_POWER_OTHER) if (GetMoveDamageResult(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex) == MOVE_POWER_OTHER)
{ {
@ -3181,7 +3180,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u16 move, s32 score
bool32 sereneGraceBoost = (AI_DATA->abilities[battlerAtk] == ABILITY_SERENE_GRACE && (gBattleMoves[move].secondaryEffectChance >= 20 && gBattleMoves[move].secondaryEffectChance < 100)); bool32 sereneGraceBoost = (AI_DATA->abilities[battlerAtk] == ABILITY_SERENE_GRACE && (gBattleMoves[move].secondaryEffectChance >= 20 && gBattleMoves[move].secondaryEffectChance < 100));
// Targeting partner, check benefits of doing that instead // Targeting partner, check benefits of doing that instead
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
return score; return score;
// check always hits // check always hits
@ -4972,7 +4971,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u16 move, s32 score
// Effects that are encouraged on the first turn of battle // Effects that are encouraged on the first turn of battle
static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u16 move, s32 score) static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)
|| gBattleResults.battleTurnCounter != 0) || gBattleResults.battleTurnCounter != 0)
return score; return score;
@ -5083,7 +5082,7 @@ static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u16 move, s32 score
// Adds score bonus to 'riskier' move effects and high crit moves // Adds score bonus to 'riskier' move effects and high crit moves
static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u16 move, s32 score) static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
return score; return score;
if (gBattleMoves[move].highCritRatio) if (gBattleMoves[move].highCritRatio)
@ -5122,7 +5121,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
// Adds score bonus to best powered move // Adds score bonus to best powered move
static s32 AI_PreferStrongestMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score) static s32 AI_PreferStrongestMove(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
return score; return score;
if (GetMoveDamageResult(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex) == MOVE_POWER_BEST) if (GetMoveDamageResult(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex) == MOVE_POWER_BEST)
@ -5136,7 +5135,7 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u16 move, s32 scor
{ {
u32 i; u32 i;
if (IsTargetingPartner(battlerAtk, battlerDef) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)
|| CountUsablePartyMons(battlerAtk) == 0 || CountUsablePartyMons(battlerAtk) == 0
|| GetMoveDamageResult(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex) != MOVE_POWER_OTHER || GetMoveDamageResult(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex) != MOVE_POWER_OTHER
|| !HasMoveEffect(battlerAtk, EFFECT_BATON_PASS) || !HasMoveEffect(battlerAtk, EFFECT_BATON_PASS)
@ -5195,7 +5194,7 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u16 move, s32 score)
SetTypeBeforeUsingMove(move, battlerAtk); SetTypeBeforeUsingMove(move, battlerAtk);
GET_MOVE_TYPE(move, moveType); GET_MOVE_TYPE(move, moveType);
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
{ {
if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY) if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY)
|| (moveType == TYPE_ELECTRIC && AI_DATA->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_VOLT_ABSORB) || (moveType == TYPE_ELECTRIC && AI_DATA->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_VOLT_ABSORB)

View File

@ -3066,21 +3066,21 @@ bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof)
return FALSE; return FALSE;
} }
u16 GetBattlerSideSpeedAverage(u8 battler) u32 GetBattlerSideSpeedAverage(u32 battler)
{ {
u16 speed1 = 0; u32 speed1 = 0;
u16 speed2 = 0; u32 speed2 = 0;
u8 numBattlersAlive = 0; u32 numBattlersAlive = 0;
if (IsBattlerAlive(battler)) if (IsBattlerAlive(battler))
{ {
speed1 = GetBattlerTotalSpeedStat(battler); speed1 = AI_DATA->speedStats[battler];
numBattlersAlive++; numBattlersAlive++;
} }
if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler)))
{ {
speed2 = GetBattlerTotalSpeedStat(BATTLE_PARTNER(battler)); speed2 = AI_DATA->speedStats[BATTLE_PARTNER(battler)];
numBattlersAlive++; numBattlersAlive++;
} }
@ -3196,14 +3196,6 @@ u16 GetAllyChosenMove(u8 battlerId)
return gBattleMons[partnerBattler].moves[gBattleStruct->chosenMovePositions[partnerBattler]]; return gBattleMons[partnerBattler].moves[gBattleStruct->chosenMovePositions[partnerBattler]];
} }
bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef)
{
if ((battlerAtk & BIT_SIDE) == (battlerDef & BIT_SIDE))
return TRUE;
return FALSE;
}
//PARTNER_MOVE_EFFECT_IS_SAME //PARTNER_MOVE_EFFECT_IS_SAME
bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u16 move, u16 partnerMove) bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u16 move, u16 partnerMove)
{ {
@ -3739,8 +3731,8 @@ void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u16 move, s32 *score)
if (AI_CanParalyze(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_DATA->partnerMove)) if (AI_CanParalyze(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_DATA->partnerMove))
{ {
u8 atkSpeed = GetBattlerTotalSpeedStat(battlerAtk); u32 atkSpeed = AI_DATA->speedStats[battlerAtk];
u8 defSpeed = GetBattlerTotalSpeedStat(battlerDef); u32 defSpeed = AI_DATA->speedStats[battlerDef];
if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe
|| HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(battlerAtk, EFFECT_HEX)