fix ai crit calculations
This commit is contained in:
parent
db15190508
commit
1ca4676c4c
3 changed files with 34 additions and 18 deletions
|
@ -24,7 +24,7 @@ struct PickupItem
|
||||||
|
|
||||||
s32 CalcCritChanceStageArgs(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, u32 holdEffectAtk);
|
s32 CalcCritChanceStageArgs(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, u32 holdEffectAtk);
|
||||||
s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility);
|
s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility);
|
||||||
s32 GetCritHitChance(s32 critChanceIndex);
|
s32 GetCritHitOdds(s32 critChanceIndex);
|
||||||
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 NoAliveMonsForPlayer(void);
|
bool32 NoAliveMonsForPlayer(void);
|
||||||
|
|
|
@ -515,15 +515,23 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
|
||||||
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
|
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
|
||||||
|
|
||||||
critChanceIndex = CalcCritChanceStageArgs(battlerAtk, battlerDef, move, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk]);
|
critChanceIndex = CalcCritChanceStageArgs(battlerAtk, battlerDef, move, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk]);
|
||||||
if (critChanceIndex > 1) // Consider crit damage only if a move has at least +1 crit chance
|
if (critChanceIndex > 1) // Consider crit damage only if a move has at least +2 crit chance
|
||||||
{
|
{
|
||||||
s32 critDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
|
s32 critDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
|
||||||
effectivenessMultiplier, weather, TRUE,
|
effectivenessMultiplier, weather, TRUE,
|
||||||
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
|
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
|
||||||
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
|
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
|
||||||
u32 critChance = GetCritHitChance(critChanceIndex);
|
u32 critOdds = GetCritHitOdds(critChanceIndex); // Crit chance is 1/critOdds
|
||||||
// With critChance getting closer to 1, dmg gets closer to critDmg.
|
// With critOdds getting closer to 1, dmg gets closer to critDmg.
|
||||||
dmg = LowestRollDmg((critDmg + normalDmg * (critChance - 1)) / (critChance));
|
dmg = LowestRollDmg((critDmg + normalDmg * (critOdds - 1)) / (critOdds));
|
||||||
|
}
|
||||||
|
else if (critChanceIndex == -2) // Guaranteed critical
|
||||||
|
{
|
||||||
|
s32 critDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
|
||||||
|
effectivenessMultiplier, weather, TRUE,
|
||||||
|
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
|
||||||
|
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
|
||||||
|
dmg = LowestRollDmg(critDmg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1905,11 +1905,11 @@ static void Cmd_ppreduce(void)
|
||||||
|
|
||||||
// The chance is 1/N for each stage.
|
// The chance is 1/N for each stage.
|
||||||
#if B_CRIT_CHANCE >= GEN_7
|
#if B_CRIT_CHANCE >= GEN_7
|
||||||
static const u8 sCriticalHitChance[] = {24, 8, 2, 1, 1};
|
static const u8 sCriticalHitOdds[] = {24, 8, 2, 1, 1};
|
||||||
#elif B_CRIT_CHANCE == GEN_6
|
#elif B_CRIT_CHANCE == GEN_6
|
||||||
static const u8 sCriticalHitChance[] = {16, 8, 2, 1, 1};
|
static const u8 sCriticalHitOdds[] = {16, 8, 2, 1, 1};
|
||||||
#else
|
#else
|
||||||
static const u8 sCriticalHitChance[] = {16, 8, 4, 3, 2}; // Gens 2,3,4,5
|
static const u8 sCriticalHitOdds[] = {16, 8, 4, 3, 2}; // Gens 2,3,4,5
|
||||||
#endif // B_CRIT_CHANCE
|
#endif // B_CRIT_CHANCE
|
||||||
|
|
||||||
#define BENEFITS_FROM_LEEK(battler, holdEffect)((holdEffect == HOLD_EFFECT_LEEK) && (GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_FARFETCHD || gBattleMons[battler].species == SPECIES_SIRFETCHD))
|
#define BENEFITS_FROM_LEEK(battler, holdEffect)((holdEffect == HOLD_EFFECT_LEEK) && (GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_FARFETCHD || gBattleMons[battler].species == SPECIES_SIRFETCHD))
|
||||||
|
@ -1917,8 +1917,7 @@ s32 CalcCritChanceStageArgs(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec
|
||||||
{
|
{
|
||||||
s32 critChance = 0;
|
s32 critChance = 0;
|
||||||
|
|
||||||
if (gSideStatuses[battlerDef] & SIDE_STATUS_LUCKY_CHANT
|
if (gSideStatuses[battlerDef] & SIDE_STATUS_LUCKY_CHANT)
|
||||||
|| abilityDef == ABILITY_BATTLE_ARMOR || abilityDef == ABILITY_SHELL_ARMOR)
|
|
||||||
{
|
{
|
||||||
critChance = -1;
|
critChance = -1;
|
||||||
}
|
}
|
||||||
|
@ -1940,12 +1939,21 @@ s32 CalcCritChanceStageArgs(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec
|
||||||
+ (abilityAtk == ABILITY_SUPER_LUCK)
|
+ (abilityAtk == ABILITY_SUPER_LUCK)
|
||||||
+ gBattleStruct->bonusCritStages[gBattlerAttacker];
|
+ gBattleStruct->bonusCritStages[gBattlerAttacker];
|
||||||
|
|
||||||
// Record ability only if move had at least +3 chance to get a crit
|
if (critChance >= ARRAY_COUNT(sCriticalHitOdds))
|
||||||
if (critChance >= 3 && recordAbility && (abilityDef == ABILITY_BATTLE_ARMOR || abilityDef == ABILITY_SHELL_ARMOR))
|
critChance = ARRAY_COUNT(sCriticalHitOdds) - 1;
|
||||||
RecordAbilityBattle(battlerDef, abilityDef);
|
}
|
||||||
|
|
||||||
if (critChance >= ARRAY_COUNT(sCriticalHitChance))
|
if (critChance != -1 && (abilityDef == ABILITY_BATTLE_ARMOR || abilityDef == ABILITY_SHELL_ARMOR))
|
||||||
critChance = ARRAY_COUNT(sCriticalHitChance) - 1;
|
{
|
||||||
|
// Record ability only if move had 100% chance to get a crit
|
||||||
|
if (recordAbility)
|
||||||
|
{
|
||||||
|
if (critChance == -2)
|
||||||
|
RecordAbilityBattle(battlerDef, abilityDef);
|
||||||
|
else if (sCriticalHitOdds[critChance] == 1)
|
||||||
|
RecordAbilityBattle(battlerDef, abilityDef);
|
||||||
|
}
|
||||||
|
critChance = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return critChance;
|
return critChance;
|
||||||
|
@ -1960,12 +1968,12 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA
|
||||||
}
|
}
|
||||||
#undef BENEFITS_FROM_LEEK
|
#undef BENEFITS_FROM_LEEK
|
||||||
|
|
||||||
s32 GetCritHitChance(s32 critChanceIndex)
|
s32 GetCritHitOdds(s32 critChanceIndex)
|
||||||
{
|
{
|
||||||
if (critChanceIndex < 0)
|
if (critChanceIndex < 0)
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
return sCriticalHitChance[critChanceIndex];
|
return sCriticalHitOdds[critChanceIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Cmd_critcalc(void)
|
static void Cmd_critcalc(void)
|
||||||
|
@ -1983,7 +1991,7 @@ static void Cmd_critcalc(void)
|
||||||
else if (critChance == -2)
|
else if (critChance == -2)
|
||||||
gIsCriticalHit = TRUE;
|
gIsCriticalHit = TRUE;
|
||||||
else
|
else
|
||||||
gIsCriticalHit = RandomWeighted(RNG_CRITICAL_HIT, sCriticalHitChance[critChance] - 1, 1);
|
gIsCriticalHit = RandomWeighted(RNG_CRITICAL_HIT, sCriticalHitOdds[critChance] - 1, 1);
|
||||||
|
|
||||||
// Counter for EVO_CRITICAL_HITS.
|
// Counter for EVO_CRITICAL_HITS.
|
||||||
partySlot = gBattlerPartyIndexes[gBattlerAttacker];
|
partySlot = gBattlerPartyIndexes[gBattlerAttacker];
|
||||||
|
|
Loading…
Reference in a new issue