mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-25 19:24:16 +01:00
more optimizations
This commit is contained in:
parent
38dcb3c66c
commit
5ea66f3c0c
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
1125
src/battle_ai_main.c
1125
src/battle_ai_main.c
File diff suppressed because it is too large
Load Diff
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user