mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-01-27 13:53:52 +01:00
New crit calculator.
This commit is contained in:
parent
56120e35d4
commit
6570324432
@ -117,7 +117,7 @@ gBattleScriptsForMoveEffects:: @ 82D86A8
|
|||||||
.4byte BattleScript_EffectSpite
|
.4byte BattleScript_EffectSpite
|
||||||
.4byte BattleScript_EffectFalseSwipe
|
.4byte BattleScript_EffectFalseSwipe
|
||||||
.4byte BattleScript_EffectHealBell
|
.4byte BattleScript_EffectHealBell
|
||||||
.4byte BattleScript_EffectPlaceholder103
|
.4byte BattleScript_EffectAlwaysCrit
|
||||||
.4byte BattleScript_EffectTripleKick
|
.4byte BattleScript_EffectTripleKick
|
||||||
.4byte BattleScript_EffectThief
|
.4byte BattleScript_EffectThief
|
||||||
.4byte BattleScript_EffectMeanLook
|
.4byte BattleScript_EffectMeanLook
|
||||||
@ -488,7 +488,7 @@ BattleScript_EffectEvasionDownHit:
|
|||||||
BattleScript_EffectVitalThrow:
|
BattleScript_EffectVitalThrow:
|
||||||
BattleScript_EffectUnused60:
|
BattleScript_EffectUnused60:
|
||||||
BattleScript_EffectFalseSwipe:
|
BattleScript_EffectFalseSwipe:
|
||||||
BattleScript_EffectPlaceholder103:
|
BattleScript_EffectAlwaysCrit:
|
||||||
BattleScript_EffectUnused6e:
|
BattleScript_EffectUnused6e:
|
||||||
BattleScript_EffectPursuit:
|
BattleScript_EffectPursuit:
|
||||||
BattleScript_EffectUnused8d:
|
BattleScript_EffectUnused8d:
|
||||||
|
@ -178,6 +178,7 @@ struct DisableStruct
|
|||||||
u8 magnetRiseTimer;
|
u8 magnetRiseTimer;
|
||||||
u8 telekinesisTimer;
|
u8 telekinesisTimer;
|
||||||
u8 healBlockTimer;
|
u8 healBlockTimer;
|
||||||
|
u8 laserFocusTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProtectStruct
|
struct ProtectStruct
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#define WINDOW_CLEAR 0x1
|
#define WINDOW_CLEAR 0x1
|
||||||
#define WINDOW_x80 0x80
|
#define WINDOW_x80 0x80
|
||||||
|
|
||||||
|
s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility);
|
||||||
u8 GetBattlerTurnOrderNum(u8 battlerId);
|
u8 GetBattlerTurnOrderNum(u8 battlerId);
|
||||||
void SetMoveEffect(bool8 primary, u8 certain);
|
void SetMoveEffect(bool8 primary, u8 certain);
|
||||||
void BattleDestroyYesNoCursorAt(u8 cursorPosition);
|
void BattleDestroyYesNoCursorAt(u8 cursorPosition);
|
||||||
|
@ -156,6 +156,7 @@
|
|||||||
#define STATUS3_MAGNET_RISE 0x4000000
|
#define STATUS3_MAGNET_RISE 0x4000000
|
||||||
#define STATUS3_HEAL_BLOCK 0x8000000
|
#define STATUS3_HEAL_BLOCK 0x8000000
|
||||||
#define STATUS3_AQUA_RING 0x10000000
|
#define STATUS3_AQUA_RING 0x10000000
|
||||||
|
#define STATUS3_LASER_FOCUS 0x20000000
|
||||||
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER)
|
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER)
|
||||||
|
|
||||||
// Not really sure what a "hitmarker" is.
|
// Not really sure what a "hitmarker" is.
|
||||||
|
@ -104,7 +104,7 @@
|
|||||||
#define EFFECT_SPITE 100
|
#define EFFECT_SPITE 100
|
||||||
#define EFFECT_FALSE_SWIPE 101
|
#define EFFECT_FALSE_SWIPE 101
|
||||||
#define EFFECT_HEAL_BELL 102
|
#define EFFECT_HEAL_BELL 102
|
||||||
#define EFFECT_PLACEHOLDER_103 103
|
#define EFFECT_ALWAYS_CRIT 103
|
||||||
#define EFFECT_TRIPLE_KICK 104
|
#define EFFECT_TRIPLE_KICK 104
|
||||||
#define EFFECT_THIEF 105
|
#define EFFECT_THIEF 105
|
||||||
#define EFFECT_MEAN_LOOK 106
|
#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 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
|
||||||
{
|
{
|
||||||
s32 dmg;
|
s32 dmg;
|
||||||
@ -737,7 +771,7 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
|
|||||||
SetBattlerData(battlerAtk);
|
SetBattlerData(battlerAtk);
|
||||||
SetBattlerData(battlerDef);
|
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(battlerAtk);
|
||||||
RestoreBattlerData(battlerDef);
|
RestoreBattlerData(battlerDef);
|
||||||
|
@ -627,9 +627,6 @@ static const struct StatFractions sAccuracyStageRatios[] =
|
|||||||
{ 3, 1}, // +6
|
{ 3, 1}, // +6
|
||||||
};
|
};
|
||||||
|
|
||||||
// The chance is 1/N for each stage.
|
|
||||||
static const u16 sCriticalHitChance[] = {16, 8, 4, 3, 2};
|
|
||||||
|
|
||||||
static const u32 sStatusFlagsForMoveEffects[] =
|
static const u32 sStatusFlagsForMoveEffects[] =
|
||||||
{
|
{
|
||||||
0x00000000,
|
0x00000000,
|
||||||
@ -1298,33 +1295,62 @@ static void atk03_ppreduce(void)
|
|||||||
gBattlescriptCurrInstr++;
|
gBattlescriptCurrInstr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void atk04_critcalc(void)
|
s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility)
|
||||||
{
|
{
|
||||||
u8 holdEffect;
|
s32 critChance = 0;
|
||||||
u16 item, critChance;
|
u32 abilityAtk = GetBattlerAbility(gBattlerAttacker);
|
||||||
|
u32 abilityDef = GetBattlerAbility(gBattlerTarget);
|
||||||
|
|
||||||
item = gBattleMons[gBattlerAttacker].item;
|
if (gSideStatuses[battlerDef] & SIDE_STATUS_LUCKY_CHANT
|
||||||
|
|| gStatuses3[gBattlerAttacker] & STATUS3_CANT_SCORE_A_CRIT)
|
||||||
if (item == ITEM_ENIGMA_BERRY)
|
{
|
||||||
holdEffect = gEnigmaBerries[gBattlerAttacker].holdEffect;
|
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
|
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)
|
||||||
critChance = 2 * ((gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY) != 0)
|
+ (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS)
|
||||||
+ ((gBattleMoves[gCurrentMove].flags & FLAG_HIGH_CRIT) != 0)
|
+ 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY)
|
||||||
+ (holdEffect == HOLD_EFFECT_SCOPE_LENS)
|
+ 2 * (holdEffectAtk == HOLD_EFFECT_STICK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD)
|
||||||
+ 2 * (holdEffect == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY)
|
+ (abilityAtk == ABILITY_SUPER_LUCK);
|
||||||
+ 2 * (holdEffect == HOLD_EFFECT_STICK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD);
|
}
|
||||||
|
|
||||||
if (critChance > 4)
|
if (critChance > 4)
|
||||||
critChance = 4;
|
critChance = 4;
|
||||||
|
|
||||||
if ((gBattleMons[gBattlerTarget].ability != ABILITY_BATTLE_ARMOR && gBattleMons[gBattlerTarget].ability != ABILITY_SHELL_ARMOR)
|
return critChance;
|
||||||
&& !(gStatuses3[gBattlerAttacker] & STATUS3_CANT_SCORE_A_CRIT)
|
}
|
||||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
|
|
||||||
&& !(Random() % sCriticalHitChance[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;
|
gIsCriticalHit = TRUE;
|
||||||
else
|
else
|
||||||
gIsCriticalHit = FALSE;
|
gIsCriticalHit = FALSE;
|
||||||
|
@ -1209,6 +1209,7 @@ enum
|
|||||||
ENDTURN_EMBARGO,
|
ENDTURN_EMBARGO,
|
||||||
ENDTURN_LOCK_ON,
|
ENDTURN_LOCK_ON,
|
||||||
ENDTURN_CHARGE,
|
ENDTURN_CHARGE,
|
||||||
|
ENDTURN_LASER_FOCUS,
|
||||||
ENDTURN_TAUNT,
|
ENDTURN_TAUNT,
|
||||||
ENDTURN_YAWN,
|
ENDTURN_YAWN,
|
||||||
ENDTURN_ITEMS2,
|
ENDTURN_ITEMS2,
|
||||||
@ -1581,6 +1582,16 @@ u8 DoBattlerEndTurnEffects(void)
|
|||||||
}
|
}
|
||||||
gBattleStruct->turnEffectsTracker++;
|
gBattleStruct->turnEffectsTracker++;
|
||||||
break;
|
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:
|
case ENDTURN_EMBARGO:
|
||||||
if (gStatuses3[gActiveBattler] & STATUS3_EMBARGO)
|
if (gStatuses3[gActiveBattler] & STATUS3_EMBARGO)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user