New crit calculator.
This commit is contained in:
parent
56120e35d4
commit
6570324432
8 changed files with 100 additions and 26 deletions
|
@ -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:
|
||||
|
|
|
@ -178,6 +178,7 @@ struct DisableStruct
|
|||
u8 magnetRiseTimer;
|
||||
u8 telekinesisTimer;
|
||||
u8 healBlockTimer;
|
||||
u8 laserFocusTimer;
|
||||
};
|
||||
|
||||
struct ProtectStruct
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue