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; \
}
u8 ComputeBattleAiScores(u8 battler);
u32 ComputeBattleAiScores(u32 battler);
void BattleAI_SetupItems(void);
void BattleAI_SetupFlags(void);
void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler);
u8 BattleAI_ChooseMoveOrAction(void);
u32 BattleAI_ChooseMoveOrAction(void);
void Ai_InitPartyStruct(void);
void Ai_UpdateSwitchInData(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);
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);
u8 GetBattlerTurnOrderNum(u8 battlerId);
bool32 NoAliveMonsForEitherParty(void);

View File

@ -172,7 +172,8 @@ u32 GetBattlerWeight(u32 battler);
u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer);
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 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 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef);
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 dmg, moveType, critDmg, normalDmg, fixedBasePower, n;
s8 critChance;
uq4_12_t effectivenessMultiplier;
SetBattlerData(battlerAtk);
@ -801,7 +800,10 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
effectivenessMultiplier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, FALSE);
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);
// Certain moves like Rollout calculate damage based on values which change during the move execution, but before calling dmg calc.
switch (gBattleMoves[move].effect)
@ -817,13 +819,19 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
fixedBasePower = 0;
break;
}
normalDmg = CalculateMoveDamageWithEffectiveness(move, battlerAtk, battlerDef, moveType, fixedBasePower, effectivenessMultiplier, FALSE, weather);
critDmg = CalculateMoveDamageWithEffectiveness(move, battlerAtk, battlerDef, moveType, fixedBasePower, effectivenessMultiplier, TRUE, weather);
normalDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
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)
dmg = normalDmg;
else
dmg = (critDmg + normalDmg * (critChance - 1)) / critChance;
dmg = (critDmg + normalDmg * (critChance - 1)) / (critChance);
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_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;
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;
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;
case EFFECT_MULTI_HIT:
dmg *= (AI_DATA->abilities[battlerAtk] == ABILITY_SKILL_LINK ? 5 : 3);
dmg *= (aiData->abilities[battlerAtk] == ABILITY_SKILL_LINK ? 5 : 3);
break;
case EFFECT_ENDEAVOR:
// If target has less HP than user, Endeavor does no damage
dmg = max(0, gBattleMons[battlerDef].hp - gBattleMons[battlerAtk].hp);
break;
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(1, gBattleMons[battlerDef].hp / 2));
break;
@ -1565,7 +1573,7 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil
{
u16 odds = accuracy + (gBattleMons[battlerAtk].level - gBattleMons[battlerDef].level);
#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;
#endif
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;
}
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)));
}
static bool32 AI_CanBePoisoned(u32 battlerAtk, u32 battlerDef)
static bool32 AI_CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 move)
{
u32 ability = AI_DATA->abilities[battlerDef];
if (!(AI_CanPoisonType(battlerAtk, battlerDef))
if (!(AI_CanPoisonType(battlerAtk, battlerDef, move))
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| gBattleMons[battlerDef].status1 & STATUS1_ANY
|| ability == ABILITY_IMMUNITY
@ -2833,7 +2841,7 @@ static bool32 AI_CanBePoisoned(u32 battlerAtk, u32 battlerDef)
bool32 ShouldPoisonSelf(u32 battler, u32 ability)
{
if (AI_CanBePoisoned(battler, battler) && (
if (AI_CanBePoisoned(battler, battler, 0) && (
ability == ABILITY_MARVEL_SCALE
|| ability == ABILITY_POISON_HEAL
|| 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)
{
if (!AI_CanBePoisoned(battlerAtk, battlerDef)
if (!AI_CanBePoisoned(battlerAtk, battlerDef, move)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove))

View File

@ -4071,7 +4071,7 @@ static void HandleTurnActionSelectionState(void)
gBattleCommunication[ACTIONS_CONFIRMED_COUNT] = 0;
for (battler = 0; battler < gBattlersCount; battler++)
{
u8 position = GetBattlerPosition(battler);
u32 position = GetBattlerPosition(battler);
switch (gBattleCommunication[battler])
{
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);
}
break;
// fallthrough
case STATE_BEFORE_ACTION_CHOSEN: // Choose an action.
*(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE;
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
s8 GetInverseCritChance(u32 battlerAtk, u32 battlerDef, u32 move)
s32 GetInverseCritChance(u32 battlerAtk, u32 battlerDef, u32 move)
{
s32 critChanceIndex = CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE);
if(critChanceIndex < 0)
if (critChanceIndex < 0)
return -1;
else
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); \
} while (0)
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)
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,
u32 holdEffectAtk, u32 holdEffectDef, u32 abilityAtk, u32 abilityDef)
{
s32 dmg;
u32 userFinalAttack;
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)
gBattleMovePower = fixedBasePower;
@ -9803,6 +9797,23 @@ static inline s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32
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
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());
}
// for AI so that typeEffectivenessModifier is calculated only once
s32 CalculateMoveDamageWithEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, uq4_12_t typeEffectivenessModifier, bool32 isCrit, u32 weather)
// for AI so that typeEffectivenessModifier, weather, abilities and holdEffects are calculated only once
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)