New crit calculator.

This commit is contained in:
DizzyEggg 2018-07-23 21:36:05 +02:00
parent 56120e35d4
commit 6570324432
8 changed files with 100 additions and 26 deletions

View file

@ -117,7 +117,7 @@ gBattleScriptsForMoveEffects:: @ 82D86A8
.4byte BattleScript_EffectSpite
.4byte BattleScript_EffectFalseSwipe
.4byte BattleScript_EffectHealBell
.4byte BattleScript_EffectPlaceholder103
.4byte BattleScript_EffectAlwaysCrit
.4byte BattleScript_EffectTripleKick
.4byte BattleScript_EffectThief
.4byte BattleScript_EffectMeanLook
@ -488,7 +488,7 @@ BattleScript_EffectEvasionDownHit:
BattleScript_EffectVitalThrow:
BattleScript_EffectUnused60:
BattleScript_EffectFalseSwipe:
BattleScript_EffectPlaceholder103:
BattleScript_EffectAlwaysCrit:
BattleScript_EffectUnused6e:
BattleScript_EffectPursuit:
BattleScript_EffectUnused8d:

View file

@ -178,6 +178,7 @@ struct DisableStruct
u8 magnetRiseTimer;
u8 telekinesisTimer;
u8 healBlockTimer;
u8 laserFocusTimer;
};
struct ProtectStruct

View file

@ -4,6 +4,7 @@
#define WINDOW_CLEAR 0x1
#define WINDOW_x80 0x80
s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility);
u8 GetBattlerTurnOrderNum(u8 battlerId);
void SetMoveEffect(bool8 primary, u8 certain);
void BattleDestroyYesNoCursorAt(u8 cursorPosition);

View file

@ -156,6 +156,7 @@
#define STATUS3_MAGNET_RISE 0x4000000
#define STATUS3_HEAL_BLOCK 0x8000000
#define STATUS3_AQUA_RING 0x10000000
#define STATUS3_LASER_FOCUS 0x20000000
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER)
// Not really sure what a "hitmarker" is.

View file

@ -104,7 +104,7 @@
#define EFFECT_SPITE 100
#define EFFECT_FALSE_SWIPE 101
#define EFFECT_HEAL_BELL 102
#define EFFECT_PLACEHOLDER_103 103
#define EFFECT_ALWAYS_CRIT 103
#define EFFECT_TRIPLE_KICK 104
#define EFFECT_THIEF 105
#define EFFECT_MEAN_LOOK 106

View file

@ -727,6 +727,40 @@ static void RestoreBattlerData(u8 battlerId)
}
}
static bool32 AI_GetIfCrit(u32 move, u8 battlerAtk, u8 battlerDef)
{
bool32 isCrit;
switch (CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE))
{
case -1:
case 0:
default:
isCrit = FALSE;
break;
case 1:
if (gBattleMoves[move].flags & FLAG_HIGH_CRIT && (Random() % 5 == 0))
isCrit = TRUE;
else
isCrit = FALSE;
break;
case 2:
if (gBattleMoves[move].flags & FLAG_HIGH_CRIT && (Random() % 2 == 0))
isCrit = TRUE;
else if (!(gBattleMoves[move].flags & FLAG_HIGH_CRIT) && (Random() % 4) == 0)
isCrit = TRUE;
else
isCrit = FALSE;
break;
case 3:
case 4:
isCrit = TRUE;
break;
}
return isCrit;
}
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
{
s32 dmg;
@ -737,7 +771,7 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
SetBattlerData(battlerAtk);
SetBattlerData(battlerDef);
dmg = CalculateMoveDamage(move, battlerAtk, battlerDef, gBattleMoves[move].type, 0, FALSE, FALSE);
dmg = CalculateMoveDamage(move, battlerAtk, battlerDef, gBattleMoves[move].type, 0, AI_GetIfCrit(move, battlerAtk, battlerDef), FALSE);
RestoreBattlerData(battlerAtk);
RestoreBattlerData(battlerDef);

View file

@ -627,9 +627,6 @@ static const struct StatFractions sAccuracyStageRatios[] =
{ 3, 1}, // +6
};
// The chance is 1/N for each stage.
static const u16 sCriticalHitChance[] = {16, 8, 4, 3, 2};
static const u32 sStatusFlagsForMoveEffects[] =
{
0x00000000,
@ -1298,33 +1295,62 @@ static void atk03_ppreduce(void)
gBattlescriptCurrInstr++;
}
static void atk04_critcalc(void)
s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility)
{
u8 holdEffect;
u16 item, critChance;
s32 critChance = 0;
u32 abilityAtk = GetBattlerAbility(gBattlerAttacker);
u32 abilityDef = GetBattlerAbility(gBattlerTarget);
item = gBattleMons[gBattlerAttacker].item;
if (item == ITEM_ENIGMA_BERRY)
holdEffect = gEnigmaBerries[gBattlerAttacker].holdEffect;
if (gSideStatuses[battlerDef] & SIDE_STATUS_LUCKY_CHANT
|| gStatuses3[gBattlerAttacker] & STATUS3_CANT_SCORE_A_CRIT)
{
critChance = -1;
}
else if (abilityDef == ABILITY_BATTLE_ARMOR || abilityDef == ABILITY_SHELL_ARMOR)
{
if (recordAbility)
RecordAbilityBattle(battlerDef, abilityDef);
critChance = -1;
}
else if (gStatuses3[battlerAtk] & STATUS3_LASER_FOCUS
|| gBattleMoves[move].effect == EFFECT_ALWAYS_CRIT
|| (abilityAtk == ABILITY_MERCILESS && gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY))
{
critChance = 4;
}
else
holdEffect = ItemId_GetHoldEffect(item);
{
u32 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE);
gPotentialItemEffectBattler = gBattlerAttacker;
critChance = 2 * ((gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY) != 0)
+ ((gBattleMoves[gCurrentMove].flags & FLAG_HIGH_CRIT) != 0)
+ (holdEffect == HOLD_EFFECT_SCOPE_LENS)
+ 2 * (holdEffect == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY)
+ 2 * (holdEffect == HOLD_EFFECT_STICK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD);
critChance = 2 * ((gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY) != 0)
+ ((gBattleMoves[gCurrentMove].flags & FLAG_HIGH_CRIT) != 0)
+ (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS)
+ 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY)
+ 2 * (holdEffectAtk == HOLD_EFFECT_STICK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD)
+ (abilityAtk == ABILITY_SUPER_LUCK);
}
if (critChance > 4)
critChance = 4;
if ((gBattleMons[gBattlerTarget].ability != ABILITY_BATTLE_ARMOR && gBattleMons[gBattlerTarget].ability != ABILITY_SHELL_ARMOR)
&& !(gStatuses3[gBattlerAttacker] & STATUS3_CANT_SCORE_A_CRIT)
&& !(gBattleTypeFlags & (BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
&& !(Random() % sCriticalHitChance[critChance]))
return critChance;
}
// The chance is 1/N for each stage.
static const u8 sCriticalHitChanceGen3[] = {16, 8, 4, 3, 2}; // Gens 2,3,4,5
static const u8 sCriticalHitChanceGen6[] = {16, 8, 2, 1, 1};
static const u8 sCriticalHitChanceGen7[] = {24, 8, 2, 1, 1};
static void atk04_critcalc(void)
{
s32 critChance = CalcCritChanceStage(gBattlerAttacker, gBattlerTarget, gCurrentMove, TRUE);
gPotentialItemEffectBattler = gBattlerAttacker;
if (gBattleTypeFlags & (BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
gIsCriticalHit = FALSE;
else if (critChance == -1)
gIsCriticalHit = FALSE;
else if (Random() % sCriticalHitChanceGen3[critChance] == 0)
gIsCriticalHit = TRUE;
else
gIsCriticalHit = FALSE;

View file

@ -1209,6 +1209,7 @@ enum
ENDTURN_EMBARGO,
ENDTURN_LOCK_ON,
ENDTURN_CHARGE,
ENDTURN_LASER_FOCUS,
ENDTURN_TAUNT,
ENDTURN_YAWN,
ENDTURN_ITEMS2,
@ -1581,6 +1582,16 @@ u8 DoBattlerEndTurnEffects(void)
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_LASER_FOCUS:
if (gStatuses3[gActiveBattler] & STATUS3_LASER_FOCUS)
{
if (gDisableStructs[gActiveBattler].laserFocusTimer != 0)
gDisableStructs[gActiveBattler].laserFocusTimer--;
if (gDisableStructs[gActiveBattler].laserFocusTimer == 0)
gStatuses3[gActiveBattler] &= ~(STATUS3_LASER_FOCUS);
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_EMBARGO:
if (gStatuses3[gActiveBattler] & STATUS3_EMBARGO)
{