more optimizations

This commit is contained in:
DizzyEggg 2023-09-14 00:07:41 +02:00
parent 38dcb3c66c
commit 5ea66f3c0c
8 changed files with 633 additions and 640 deletions

View File

@ -19,11 +19,11 @@
return score; \ return score; \
} }
u8 ComputeBattleAiScores(u8 battler); u32 ComputeBattleAiScores(u32 battler);
void BattleAI_SetupItems(void); void BattleAI_SetupItems(void);
void BattleAI_SetupFlags(void); void BattleAI_SetupFlags(void);
void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler); void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler);
u8 BattleAI_ChooseMoveOrAction(void); u32 BattleAI_ChooseMoveOrAction(void);
void Ai_InitPartyStruct(void); void Ai_InitPartyStruct(void);
void Ai_UpdateSwitchInData(u32 battler); void Ai_UpdateSwitchInData(u32 battler);
void Ai_UpdateFaintData(u32 battler); void Ai_UpdateFaintData(u32 battler);

View File

@ -17,7 +17,7 @@ struct StatFractions
}; };
s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility); s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility);
s8 GetInverseCritChance(u32 battlerAtk, u32 battlerDef, u32 move); s32 GetInverseCritChance(u32 battlerAtk, u32 battlerDef, u32 move);
u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect);
u8 GetBattlerTurnOrderNum(u8 battlerId); u8 GetBattlerTurnOrderNum(u8 battlerId);
bool32 NoAliveMonsForEitherParty(void); bool32 NoAliveMonsForEitherParty(void);

View File

@ -172,7 +172,8 @@ u32 GetBattlerWeight(u32 battler);
u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer); u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer);
u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter); u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter);
s32 CalculateMoveDamage(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, bool32 isCrit, bool32 randomFactor, bool32 updateFlags); s32 CalculateMoveDamage(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, bool32 isCrit, bool32 randomFactor, bool32 updateFlags);
s32 CalculateMoveDamageWithEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, uq4_12_t typeEffectivenessModifier, bool32 isCrit, u32 weather); s32 CalculateMoveDamageVars(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, uq4_12_t typeEffectivenessModifier,
u32 weather, bool32 isCrit, u32 holdEffectAtk, u32 holdEffectDef, u32 abilityAtk, u32 abilityDef);
uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, bool32 recordAbilities); uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, bool32 recordAbilities);
uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef);
uq4_12_t GetTypeModifier(u32 atkType, u32 defType); uq4_12_t GetTypeModifier(u32 atkType, u32 defType);

File diff suppressed because it is too large Load Diff

View File

@ -777,7 +777,6 @@ s32 AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *type
s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, u32 weather) s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, u32 weather)
{ {
s32 dmg, moveType, critDmg, normalDmg, fixedBasePower, n; s32 dmg, moveType, critDmg, normalDmg, fixedBasePower, n;
s8 critChance;
uq4_12_t effectivenessMultiplier; uq4_12_t effectivenessMultiplier;
SetBattlerData(battlerAtk); SetBattlerData(battlerAtk);
@ -801,7 +800,10 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
effectivenessMultiplier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, FALSE); effectivenessMultiplier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, FALSE);
if (gBattleMoves[move].power) if (gBattleMoves[move].power)
{ {
ProteanTryChangeType(battlerAtk, AI_DATA->abilities[battlerAtk], move, moveType); s32 critChance;
struct AiLogicData *aiData = AI_DATA;
ProteanTryChangeType(battlerAtk, aiData->abilities[battlerAtk], move, moveType);
critChance = GetInverseCritChance(battlerAtk, battlerDef, move); critChance = GetInverseCritChance(battlerAtk, battlerDef, move);
// Certain moves like Rollout calculate damage based on values which change during the move execution, but before calling dmg calc. // Certain moves like Rollout calculate damage based on values which change during the move execution, but before calling dmg calc.
switch (gBattleMoves[move].effect) switch (gBattleMoves[move].effect)
@ -817,13 +819,19 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
fixedBasePower = 0; fixedBasePower = 0;
break; break;
} }
normalDmg = CalculateMoveDamageWithEffectiveness(move, battlerAtk, battlerDef, moveType, fixedBasePower, effectivenessMultiplier, FALSE, weather); normalDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
critDmg = CalculateMoveDamageWithEffectiveness(move, battlerAtk, battlerDef, moveType, fixedBasePower, effectivenessMultiplier, TRUE, weather); effectivenessMultiplier, weather, FALSE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
critDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
effectivenessMultiplier, weather, TRUE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
if (critChance == -1) if (critChance == -1)
dmg = normalDmg; dmg = normalDmg;
else else
dmg = (critDmg + normalDmg * (critChance - 1)) / critChance; dmg = (critDmg + normalDmg * (critChance - 1)) / (critChance);
if (!gBattleStruct->zmove.active) if (!gBattleStruct->zmove.active)
{ {
@ -832,23 +840,23 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
{ {
case EFFECT_LEVEL_DAMAGE: case EFFECT_LEVEL_DAMAGE:
case EFFECT_PSYWAVE: case EFFECT_PSYWAVE:
dmg = gBattleMons[battlerAtk].level * (AI_DATA->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1); dmg = gBattleMons[battlerAtk].level * (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1);
break; break;
case EFFECT_DRAGON_RAGE: case EFFECT_DRAGON_RAGE:
dmg = 40 * (AI_DATA->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1); dmg = 40 * (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1);
break; break;
case EFFECT_SONICBOOM: case EFFECT_SONICBOOM:
dmg = 20 * (AI_DATA->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1); dmg = 20 * (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1);
break; break;
case EFFECT_MULTI_HIT: case EFFECT_MULTI_HIT:
dmg *= (AI_DATA->abilities[battlerAtk] == ABILITY_SKILL_LINK ? 5 : 3); dmg *= (aiData->abilities[battlerAtk] == ABILITY_SKILL_LINK ? 5 : 3);
break; break;
case EFFECT_ENDEAVOR: case EFFECT_ENDEAVOR:
// If target has less HP than user, Endeavor does no damage // If target has less HP than user, Endeavor does no damage
dmg = max(0, gBattleMons[battlerDef].hp - gBattleMons[battlerAtk].hp); dmg = max(0, gBattleMons[battlerDef].hp - gBattleMons[battlerAtk].hp);
break; break;
case EFFECT_SUPER_FANG: case EFFECT_SUPER_FANG:
dmg = (AI_DATA->abilities[battlerAtk] == ABILITY_PARENTAL_BOND dmg = (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND
? max(2, gBattleMons[battlerDef].hp * 3 / 4) ? max(2, gBattleMons[battlerDef].hp * 3 / 4)
: max(1, gBattleMons[battlerDef].hp / 2)); : max(1, gBattleMons[battlerDef].hp / 2));
break; break;
@ -1565,7 +1573,7 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil
{ {
u16 odds = accuracy + (gBattleMons[battlerAtk].level - gBattleMons[battlerDef].level); u16 odds = accuracy + (gBattleMons[battlerAtk].level - gBattleMons[battlerDef].level);
#if B_SHEER_COLD_ACC >= GEN_7 #if B_SHEER_COLD_ACC >= GEN_7
if (gCurrentMove == MOVE_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)) if (move == MOVE_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE))
odds -= 10; odds -= 10;
#endif #endif
if (Random() % 100 + 1 < odds && gBattleMons[battlerAtk].level >= gBattleMons[battlerDef].level) if (Random() % 100 + 1 < odds && gBattleMons[battlerAtk].level >= gBattleMons[battlerDef].level)
@ -2808,17 +2816,17 @@ bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move
return TRUE; return TRUE;
} }
static bool32 AI_CanPoisonType(u32 battlerAttacker, u32 battlerTarget) static bool32 AI_CanPoisonType(u32 battlerAttacker, u32 battlerTarget, u32 move)
{ {
return ((AI_DATA->abilities[battlerAttacker] == ABILITY_CORROSION && gBattleMoves[gCurrentMove].split == SPLIT_STATUS) return ((AI_DATA->abilities[battlerAttacker] == ABILITY_CORROSION && gBattleMoves[move].split == SPLIT_STATUS)
|| !(IS_BATTLER_OF_TYPE(battlerTarget, TYPE_POISON) || IS_BATTLER_OF_TYPE(battlerTarget, TYPE_STEEL))); || !(IS_BATTLER_OF_TYPE(battlerTarget, TYPE_POISON) || IS_BATTLER_OF_TYPE(battlerTarget, TYPE_STEEL)));
} }
static bool32 AI_CanBePoisoned(u32 battlerAtk, u32 battlerDef) static bool32 AI_CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 move)
{ {
u32 ability = AI_DATA->abilities[battlerDef]; u32 ability = AI_DATA->abilities[battlerDef];
if (!(AI_CanPoisonType(battlerAtk, battlerDef)) if (!(AI_CanPoisonType(battlerAtk, battlerDef, move))
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD || gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| gBattleMons[battlerDef].status1 & STATUS1_ANY || gBattleMons[battlerDef].status1 & STATUS1_ANY
|| ability == ABILITY_IMMUNITY || ability == ABILITY_IMMUNITY
@ -2833,7 +2841,7 @@ static bool32 AI_CanBePoisoned(u32 battlerAtk, u32 battlerDef)
bool32 ShouldPoisonSelf(u32 battler, u32 ability) bool32 ShouldPoisonSelf(u32 battler, u32 ability)
{ {
if (AI_CanBePoisoned(battler, battler) && ( if (AI_CanBePoisoned(battler, battler, 0) && (
ability == ABILITY_MARVEL_SCALE ability == ABILITY_MARVEL_SCALE
|| ability == ABILITY_POISON_HEAL || ability == ABILITY_POISON_HEAL
|| ability == ABILITY_QUICK_FEET || ability == ABILITY_QUICK_FEET
@ -2848,7 +2856,7 @@ bool32 ShouldPoisonSelf(u32 battler, u32 ability)
bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove)
{ {
if (!AI_CanBePoisoned(battlerAtk, battlerDef) if (!AI_CanBePoisoned(battlerAtk, battlerDef, move)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) || PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove))

View File

@ -4071,7 +4071,7 @@ static void HandleTurnActionSelectionState(void)
gBattleCommunication[ACTIONS_CONFIRMED_COUNT] = 0; gBattleCommunication[ACTIONS_CONFIRMED_COUNT] = 0;
for (battler = 0; battler < gBattlersCount; battler++) for (battler = 0; battler < gBattlersCount; battler++)
{ {
u8 position = GetBattlerPosition(battler); u32 position = GetBattlerPosition(battler);
switch (gBattleCommunication[battler]) switch (gBattleCommunication[battler])
{ {
case STATE_TURN_START_RECORD: // Recorded battle related action on start of every turn. case STATE_TURN_START_RECORD: // Recorded battle related action on start of every turn.
@ -4084,7 +4084,7 @@ static void HandleTurnActionSelectionState(void)
{ {
gBattleStruct->aiMoveOrAction[battler] = ComputeBattleAiScores(battler); gBattleStruct->aiMoveOrAction[battler] = ComputeBattleAiScores(battler);
} }
break; // fallthrough
case STATE_BEFORE_ACTION_CHOSEN: // Choose an action. case STATE_BEFORE_ACTION_CHOSEN: // Choose an action.
*(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE; *(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE;
if (gBattleTypeFlags & BATTLE_TYPE_MULTI if (gBattleTypeFlags & BATTLE_TYPE_MULTI

View File

@ -1952,10 +1952,10 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA
} }
#undef BENEFITS_FROM_LEEK #undef BENEFITS_FROM_LEEK
s8 GetInverseCritChance(u32 battlerAtk, u32 battlerDef, u32 move) s32 GetInverseCritChance(u32 battlerAtk, u32 battlerDef, u32 move)
{ {
s32 critChanceIndex = CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE); s32 critChanceIndex = CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE);
if(critChanceIndex < 0) if (critChanceIndex < 0)
return -1; return -1;
else else
return sCriticalHitChance[critChanceIndex]; return sCriticalHitChance[critChanceIndex];

View File

@ -9758,19 +9758,13 @@ static inline uq4_12_t GetOtherModifiers(u32 move, u32 moveType, u32 battlerAtk,
dmg = uq4_12_multiply_by_int_half_down(modifier, dmg); \ dmg = uq4_12_multiply_by_int_half_down(modifier, dmg); \
} while (0) } while (0)
static inline s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, static inline s32 DoMoveDamageCalcVars(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower,
bool32 isCrit, bool32 randomFactor, bool32 updateFlags, uq4_12_t typeEffectivenessModifier, u32 weather) bool32 isCrit, bool32 randomFactor, bool32 updateFlags, uq4_12_t typeEffectivenessModifier, u32 weather,
u32 holdEffectAtk, u32 holdEffectDef, u32 abilityAtk, u32 abilityDef)
{ {
s32 dmg; s32 dmg;
u32 userFinalAttack; u32 userFinalAttack;
u32 targetFinalDefense; u32 targetFinalDefense;
u32 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE);
u32 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE);
u32 abilityAtk = GetBattlerAbility(battlerAtk);
u32 abilityDef = GetBattlerAbility(battlerDef);
if (typeEffectivenessModifier == UQ_4_12(0.0))
return 0;
if (fixedBasePower) if (fixedBasePower)
gBattleMovePower = fixedBasePower; gBattleMovePower = fixedBasePower;
@ -9803,6 +9797,23 @@ static inline s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32
return dmg; return dmg;
} }
static inline s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower,
bool32 isCrit, bool32 randomFactor, bool32 updateFlags, uq4_12_t typeEffectivenessModifier, u32 weather)
{
u32 holdEffectAtk, holdEffectDef, abilityAtk, abilityDef;
if (typeEffectivenessModifier == UQ_4_12(0.0))
return 0;
holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE);
holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE);
abilityAtk = GetBattlerAbility(battlerAtk);
abilityDef = GetBattlerAbility(battlerDef);
return DoMoveDamageCalcVars(move, battlerAtk, battlerDef, moveType, fixedBasePower, isCrit, randomFactor,
updateFlags, typeEffectivenessModifier, weather, holdEffectAtk, holdEffectDef, abilityAtk, abilityDef);
}
#undef DAMAGE_APPLY_MODIFIER #undef DAMAGE_APPLY_MODIFIER
static u32 GetWeather(void) static u32 GetWeather(void)
@ -9819,10 +9830,12 @@ s32 CalculateMoveDamage(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType,
updateFlags, CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, updateFlags), GetWeather()); updateFlags, CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, updateFlags), GetWeather());
} }
// for AI so that typeEffectivenessModifier is calculated only once // for AI so that typeEffectivenessModifier, weather, abilities and holdEffects are calculated only once
s32 CalculateMoveDamageWithEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, uq4_12_t typeEffectivenessModifier, bool32 isCrit, u32 weather) s32 CalculateMoveDamageVars(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, uq4_12_t typeEffectivenessModifier,
u32 weather, bool32 isCrit, u32 holdEffectAtk, u32 holdEffectDef, u32 abilityAtk, u32 abilityDef)
{ {
return DoMoveDamageCalc(move, battlerAtk, battlerDef, moveType, fixedBasePower, isCrit, FALSE, FALSE, typeEffectivenessModifier, weather); return DoMoveDamageCalcVars(move, battlerAtk, battlerDef, moveType, fixedBasePower, isCrit, FALSE, FALSE,
typeEffectivenessModifier, weather, holdEffectAtk, holdEffectDef, abilityAtk, abilityDef);
} }
static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 moveType, u32 battlerDef, u32 defType, u32 battlerAtk, bool32 recordAbilities) static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 moveType, u32 battlerDef, u32 defType, u32 battlerAtk, bool32 recordAbilities)