Use 9th roll instead of average in AI calcs (#4679)
* Use 9th roll instead of average in AI calcs * damage_roll * duke suggestion
This commit is contained in:
parent
240b69d032
commit
4eda5f61af
4 changed files with 13 additions and 12 deletions
|
@ -6,11 +6,12 @@
|
||||||
// Roll boundaries used by AI when scoring. Doesn't affect actual damage dealt.
|
// Roll boundaries used by AI when scoring. Doesn't affect actual damage dealt.
|
||||||
#define MAX_ROLL_PERCENTAGE DMG_ROLL_PERCENT_HI
|
#define MAX_ROLL_PERCENTAGE DMG_ROLL_PERCENT_HI
|
||||||
#define MIN_ROLL_PERCENTAGE DMG_ROLL_PERCENT_LO
|
#define MIN_ROLL_PERCENTAGE DMG_ROLL_PERCENT_LO
|
||||||
|
#define DMG_ROLL_PERCENTAGE ((MAX_ROLL_PERCENTAGE + MIN_ROLL_PERCENTAGE + 1) / 2) // Controls the damage roll the AI sees for the default roll. By default the 9th roll is seen
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
DMG_ROLL_LOWEST,
|
DMG_ROLL_LOWEST,
|
||||||
DMG_ROLL_AVERAGE,
|
DMG_ROLL_DEFAULT,
|
||||||
DMG_ROLL_HIGHEST,
|
DMG_ROLL_HIGHEST,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -464,7 +464,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3
|
||||||
else if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE)
|
else if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE)
|
||||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_LOWEST);
|
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_LOWEST);
|
||||||
else
|
else
|
||||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_AVERAGE);
|
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_DEFAULT);
|
||||||
aiData->moveAccuracy[battlerAtk][battlerDef][i] = Ai_SetMoveAccuracy(aiData, battlerAtk, battlerDef, move);
|
aiData->moveAccuracy[battlerAtk][battlerDef][i] = Ai_SetMoveAccuracy(aiData, battlerAtk, battlerDef, move);
|
||||||
}
|
}
|
||||||
aiData->simulatedDmg[battlerAtk][battlerDef][i] = dmg;
|
aiData->simulatedDmg[battlerAtk][battlerDef][i] = dmg;
|
||||||
|
|
|
@ -1279,7 +1279,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva
|
||||||
if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0)
|
if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0)
|
||||||
{
|
{
|
||||||
aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j);
|
aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j);
|
||||||
dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_AVERAGE);
|
dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT);
|
||||||
if (bestDmg < dmg)
|
if (bestDmg < dmg)
|
||||||
{
|
{
|
||||||
bestDmg = dmg;
|
bestDmg = dmg;
|
||||||
|
@ -1840,7 +1840,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||||
|
|
||||||
// Only do damage calc if switching after KO, don't need it otherwise and saves ~0.02s per turn
|
// Only do damage calc if switching after KO, don't need it otherwise and saves ~0.02s per turn
|
||||||
if (isSwitchAfterKO && aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0)
|
if (isSwitchAfterKO && aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0)
|
||||||
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_AVERAGE);
|
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT);
|
||||||
|
|
||||||
// Check for Baton Pass; hitsToKO requirements mean mon can boost and BP without dying whether it's slower or not
|
// Check for Baton Pass; hitsToKO requirements mean mon can boost and BP without dying whether it's slower or not
|
||||||
if (aiMove == MOVE_BATON_PASS && ((hitsToKOAI > hitsToKOAIThreshold + 1 && AI_DATA->switchinCandidate.battleMon.speed < playerMonSpeed) || (hitsToKOAI > hitsToKOAIThreshold && AI_DATA->switchinCandidate.battleMon.speed > playerMonSpeed)))
|
if (aiMove == MOVE_BATON_PASS && ((hitsToKOAI > hitsToKOAIThreshold + 1 && AI_DATA->switchinCandidate.battleMon.speed < playerMonSpeed) || (hitsToKOAI > hitsToKOAIThreshold && AI_DATA->switchinCandidate.battleMon.speed > playerMonSpeed)))
|
||||||
|
|
|
@ -391,9 +391,9 @@ static inline s32 HighestRollDmg(s32 dmg)
|
||||||
return dmg;
|
return dmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline s32 AverageDmg(s32 dmg)
|
static inline s32 DmgRoll(s32 dmg)
|
||||||
{
|
{
|
||||||
dmg = (dmg * (MIN_ROLL_PERCENTAGE + MAX_ROLL_PERCENTAGE)) / 2;
|
dmg *= DMG_ROLL_PERCENTAGE;
|
||||||
dmg /= 100;
|
dmg /= 100;
|
||||||
return dmg;
|
return dmg;
|
||||||
}
|
}
|
||||||
|
@ -566,8 +566,8 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
|
||||||
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
|
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
|
||||||
u32 critChance = GetCritHitChance(critChanceIndex);
|
u32 critChance = GetCritHitChance(critChanceIndex);
|
||||||
// With critChance getting closer to 1, dmg gets closer to critDmg.
|
// With critChance getting closer to 1, dmg gets closer to critDmg.
|
||||||
if (dmgRoll == DMG_ROLL_AVERAGE)
|
if (dmgRoll == DMG_ROLL_DEFAULT)
|
||||||
dmg = AverageDmg((critDmg + normalDmg * (critChance - 1)) / (critChance));
|
dmg = DmgRoll((critDmg + normalDmg * (critChance - 1)) / (critChance));
|
||||||
else if (dmgRoll == DMG_ROLL_HIGHEST)
|
else if (dmgRoll == DMG_ROLL_HIGHEST)
|
||||||
dmg = HighestRollDmg((critDmg + normalDmg * (critChance - 1)) / (critChance));
|
dmg = HighestRollDmg((critDmg + normalDmg * (critChance - 1)) / (critChance));
|
||||||
else
|
else
|
||||||
|
@ -575,8 +575,8 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (dmgRoll == DMG_ROLL_AVERAGE)
|
if (dmgRoll == DMG_ROLL_DEFAULT)
|
||||||
dmg = AverageDmg(normalDmg);
|
dmg = DmgRoll(normalDmg);
|
||||||
else if (dmgRoll == DMG_ROLL_HIGHEST)
|
else if (dmgRoll == DMG_ROLL_HIGHEST)
|
||||||
dmg = HighestRollDmg(normalDmg);
|
dmg = HighestRollDmg(normalDmg);
|
||||||
else
|
else
|
||||||
|
@ -3763,7 +3763,7 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||||
else if (!IS_MOVE_STATUS(chosenMove) && IS_MOVE_STATUS(gBattleStruct->zmove.chosenZMove))
|
else if (!IS_MOVE_STATUS(chosenMove) && IS_MOVE_STATUS(gBattleStruct->zmove.chosenZMove))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!IS_MOVE_STATUS(chosenMove) && AI_CalcDamageSaveBattlers(chosenMove, battlerAtk, battlerDef, &effectiveness, FALSE, DMG_ROLL_AVERAGE) >= gBattleMons[battlerDef].hp)
|
if (!IS_MOVE_STATUS(chosenMove) && AI_CalcDamageSaveBattlers(chosenMove, battlerAtk, battlerDef, &effectiveness, FALSE, DMG_ROLL_DEFAULT) >= gBattleMons[battlerDef].hp)
|
||||||
return FALSE; // don't waste damaging z move if can otherwise faint target
|
return FALSE; // don't waste damaging z move if can otherwise faint target
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in a new issue