Fix Anticipation type effectiveness check (#7840)
This commit is contained in:
parent
f6c6ed6956
commit
de3c031fc5
@ -165,7 +165,8 @@ struct DamageContext
|
|||||||
u32 isCrit:1;
|
u32 isCrit:1;
|
||||||
u32 randomFactor:1;
|
u32 randomFactor:1;
|
||||||
u32 updateFlags:1;
|
u32 updateFlags:1;
|
||||||
u32 padding1:2;
|
u32 isAnticipation:1;
|
||||||
|
u32 padding1:1;
|
||||||
u32 weather:16;
|
u32 weather:16;
|
||||||
u32 fixedBasePower:8;
|
u32 fixedBasePower:8;
|
||||||
u32 padding2:8;
|
u32 padding2:8;
|
||||||
|
|||||||
@ -3690,8 +3690,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
|||||||
case ABILITY_ANTICIPATION:
|
case ABILITY_ANTICIPATION:
|
||||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||||
{
|
{
|
||||||
u32 types[3];
|
struct DamageContext ctx = {0};
|
||||||
GetBattlerTypes(battler, FALSE, types);
|
uq4_12_t modifier = UQ_4_12(1.0);
|
||||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||||
{
|
{
|
||||||
if (IsBattlerAlive(i) && !IsBattlerAlly(i, battler))
|
if (IsBattlerAlive(i) && !IsBattlerAlly(i, battler))
|
||||||
@ -3702,9 +3702,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
|||||||
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
|
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
|
||||||
moveType = GetBattleMoveType(move);
|
moveType = GetBattleMoveType(move);
|
||||||
|
|
||||||
if (GetTypeModifier(moveType, types[0]) >= UQ_4_12(2.0)
|
ctx.battlerAtk = i;
|
||||||
|| (types[0] != types[1] && GetTypeModifier(moveType, types[1]) >= UQ_4_12(2.0))
|
ctx.battlerDef = battler;
|
||||||
|| (types[2] != TYPE_MYSTERY && GetTypeModifier(moveType, types[2]) >= UQ_4_12(2.0))
|
ctx.move = move;
|
||||||
|
ctx.moveType = moveType;
|
||||||
|
ctx.isAnticipation = TRUE;
|
||||||
|
modifier = CalcTypeEffectivenessMultiplier(&ctx);
|
||||||
|
|
||||||
|
if (modifier >= UQ_4_12(2.0)
|
||||||
|| moveEffect == EFFECT_OHKO
|
|| moveEffect == EFFECT_OHKO
|
||||||
|| moveEffect == EFFECT_SHEER_COLD)
|
|| moveEffect == EFFECT_SHEER_COLD)
|
||||||
{
|
{
|
||||||
@ -7639,13 +7644,13 @@ enum IronBallCheck
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Only called directly when calculating damage type effectiveness, and Iron Ball's type effectiveness mechanics
|
// Only called directly when calculating damage type effectiveness, and Iron Ball's type effectiveness mechanics
|
||||||
static bool32 IsBattlerGroundedInverseCheck(u32 battler, u32 ability, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall)
|
static bool32 IsBattlerGroundedInverseCheck(u32 battler, u32 ability, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall, bool32 isAnticipation)
|
||||||
{
|
{
|
||||||
enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE);
|
enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE);
|
||||||
|
|
||||||
if (!(checkIronBall == IGNORE_IRON_BALL) && holdEffect == HOLD_EFFECT_IRON_BALL)
|
if (!(checkIronBall == IGNORE_IRON_BALL) && holdEffect == HOLD_EFFECT_IRON_BALL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (gFieldStatuses & STATUS_FIELD_GRAVITY)
|
if (gFieldStatuses & STATUS_FIELD_GRAVITY && isAnticipation == FALSE)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (B_ROOTED_GROUNDING >= GEN_4 && gBattleMons[battler].volatiles.root)
|
if (B_ROOTED_GROUNDING >= GEN_4 && gBattleMons[battler].volatiles.root)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -7666,7 +7671,7 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, u32 ability, enum Inver
|
|||||||
|
|
||||||
bool32 IsBattlerGrounded(u32 battler)
|
bool32 IsBattlerGrounded(u32 battler)
|
||||||
{
|
{
|
||||||
return IsBattlerGroundedInverseCheck(battler, GetBattlerAbility(battler), NOT_INVERSE_BATTLE, CHECK_IRON_BALL);
|
return IsBattlerGroundedInverseCheck(battler, GetBattlerAbility(battler), NOT_INVERSE_BATTLE, CHECK_IRON_BALL, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetMoveSlot(u16 *moves, u32 move)
|
u32 GetMoveSlot(u16 *moves, u32 move)
|
||||||
@ -9522,7 +9527,7 @@ static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *m
|
|||||||
|
|
||||||
if (ctx->moveType == TYPE_PSYCHIC && defType == TYPE_DARK && gBattleMons[ctx->battlerDef].volatiles.miracleEye && mod == UQ_4_12(0.0))
|
if (ctx->moveType == TYPE_PSYCHIC && defType == TYPE_DARK && gBattleMons[ctx->battlerDef].volatiles.miracleEye && mod == UQ_4_12(0.0))
|
||||||
mod = UQ_4_12(1.0);
|
mod = UQ_4_12(1.0);
|
||||||
if (GetMoveEffect(ctx->move) == EFFECT_SUPER_EFFECTIVE_ON_ARG && defType == GetMoveArgType(ctx->move))
|
if (GetMoveEffect(ctx->move) == EFFECT_SUPER_EFFECTIVE_ON_ARG && defType == GetMoveArgType(ctx->move) && !ctx->isAnticipation)
|
||||||
mod = UQ_4_12(2.0);
|
mod = UQ_4_12(2.0);
|
||||||
if (ctx->moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(ctx->battlerDef) && mod == UQ_4_12(0.0))
|
if (ctx->moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(ctx->battlerDef) && mod == UQ_4_12(0.0))
|
||||||
mod = UQ_4_12(1.0);
|
mod = UQ_4_12(1.0);
|
||||||
@ -9530,7 +9535,7 @@ static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *m
|
|||||||
mod = UQ_4_12(2.0);
|
mod = UQ_4_12(2.0);
|
||||||
|
|
||||||
// B_WEATHER_STRONG_WINDS weakens Super Effective moves against Flying-type Pokémon
|
// B_WEATHER_STRONG_WINDS weakens Super Effective moves against Flying-type Pokémon
|
||||||
if (gBattleWeather & B_WEATHER_STRONG_WINDS && HasWeatherEffect())
|
if (gBattleWeather & B_WEATHER_STRONG_WINDS && HasWeatherEffect() && !ctx->isAnticipation)
|
||||||
{
|
{
|
||||||
if (defType == TYPE_FLYING && mod >= UQ_4_12(2.0))
|
if (defType == TYPE_FLYING && mod >= UQ_4_12(2.0))
|
||||||
mod = UQ_4_12(1.0);
|
mod = UQ_4_12(1.0);
|
||||||
@ -9621,7 +9626,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont
|
|||||||
if (B_GLARE_GHOST < GEN_4 && ctx->move == MOVE_GLARE && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_GHOST))
|
if (B_GLARE_GHOST < GEN_4 && ctx->move == MOVE_GLARE && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_GHOST))
|
||||||
modifier = UQ_4_12(0.0);
|
modifier = UQ_4_12(0.0);
|
||||||
}
|
}
|
||||||
else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, INVERSE_BATTLE, CHECK_IRON_BALL) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move)))
|
else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, INVERSE_BATTLE, CHECK_IRON_BALL, ctx->isAnticipation) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move)))
|
||||||
{
|
{
|
||||||
modifier = UQ_4_12(0.0);
|
modifier = UQ_4_12(0.0);
|
||||||
if (ctx->updateFlags && ctx->abilityDef == ABILITY_LEVITATE)
|
if (ctx->updateFlags && ctx->abilityDef == ABILITY_LEVITATE)
|
||||||
@ -9651,7 +9656,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont
|
|||||||
&& ctx->moveType == TYPE_GROUND
|
&& ctx->moveType == TYPE_GROUND
|
||||||
&& IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING)
|
&& IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING)
|
||||||
&& GetBattlerHoldEffect(ctx->battlerDef, TRUE) == HOLD_EFFECT_IRON_BALL
|
&& GetBattlerHoldEffect(ctx->battlerDef, TRUE) == HOLD_EFFECT_IRON_BALL
|
||||||
&& !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL)
|
&& !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL, FALSE)
|
||||||
&& !FlagGet(B_FLAG_INVERSE_BATTLE))
|
&& !FlagGet(B_FLAG_INVERSE_BATTLE))
|
||||||
{
|
{
|
||||||
modifier = UQ_4_12(1.0);
|
modifier = UQ_4_12(1.0);
|
||||||
@ -9685,7 +9690,7 @@ uq4_12_t CalcTypeEffectivenessMultiplier(struct DamageContext *ctx)
|
|||||||
if (ctx->move != MOVE_STRUGGLE && ctx->moveType != TYPE_MYSTERY)
|
if (ctx->move != MOVE_STRUGGLE && ctx->moveType != TYPE_MYSTERY)
|
||||||
{
|
{
|
||||||
modifier = CalcTypeEffectivenessMultiplierInternal(ctx, modifier);
|
modifier = CalcTypeEffectivenessMultiplierInternal(ctx, modifier);
|
||||||
if (GetMoveEffect(ctx->move) == EFFECT_TWO_TYPED_MOVE)
|
if (GetMoveEffect(ctx->move) == EFFECT_TWO_TYPED_MOVE && !ctx->isAnticipation)
|
||||||
{
|
{
|
||||||
ctx->moveType = GetMoveArgType(ctx->move);
|
ctx->moveType = GetMoveArgType(ctx->move);
|
||||||
modifier = CalcTypeEffectivenessMultiplierInternal(ctx, modifier);
|
modifier = CalcTypeEffectivenessMultiplierInternal(ctx, modifier);
|
||||||
|
|||||||
@ -16,6 +16,18 @@ SINGLE_BATTLE_TEST("Anticipation causes notifies if an opponent has a super-effe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Anticipation does not trigger even when a move is super effective on only 1 type")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WHISCASH) { Ability(ABILITY_ANTICIPATION); }
|
||||||
|
OPPONENT(SPECIES_PIKACHU) { Moves(MOVE_CELEBRATE, MOVE_THUNDERBOLT); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { }
|
||||||
|
} SCENE {
|
||||||
|
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SINGLE_BATTLE_TEST("Anticipation causes notifies if an opponent has a One-hit KO move")
|
SINGLE_BATTLE_TEST("Anticipation causes notifies if an opponent has a One-hit KO move")
|
||||||
{
|
{
|
||||||
GIVEN {
|
GIVEN {
|
||||||
@ -59,28 +71,21 @@ SINGLE_BATTLE_TEST("Anticipation doesn't consider Normalize into their effective
|
|||||||
|
|
||||||
SINGLE_BATTLE_TEST("Anticipation doesn't consider Scrappy into their effectiveness (Gen5+)")
|
SINGLE_BATTLE_TEST("Anticipation doesn't consider Scrappy into their effectiveness (Gen5+)")
|
||||||
{
|
{
|
||||||
KNOWN_FAILING;
|
|
||||||
GIVEN {
|
GIVEN {
|
||||||
ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING);
|
ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING);
|
||||||
ASSUME(GetSpeciesType(SPECIES_EEVEE, 0) == TYPE_NORMAL);
|
ASSUME(GetSpeciesType(SPECIES_DOUBLADE, 0) == TYPE_STEEL);
|
||||||
ASSUME(GetSpeciesType(SPECIES_EEVEE, 1) == TYPE_NORMAL);
|
ASSUME(GetSpeciesType(SPECIES_DOUBLADE, 1) == TYPE_GHOST);
|
||||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
PLAYER(SPECIES_DOUBLADE) { Ability(ABILITY_ANTICIPATION); }
|
||||||
OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); Moves(MOVE_CLOSE_COMBAT, MOVE_TRICK_OR_TREAT, MOVE_SKILL_SWAP, MOVE_CELEBRATE); }
|
OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); Moves(MOVE_CLOSE_COMBAT, MOVE_CELEBRATE); }
|
||||||
} WHEN {
|
} WHEN {
|
||||||
TURN { MOVE(opponent, MOVE_TRICK_OR_TREAT); MOVE(player, MOVE_SKILL_SWAP); }
|
TURN { }
|
||||||
TURN { MOVE(opponent, MOVE_SKILL_SWAP); }
|
|
||||||
} SCENE {
|
} SCENE {
|
||||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
|
||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK_OR_TREAT, opponent);
|
|
||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player);
|
|
||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
|
|
||||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SINGLE_BATTLE_TEST("Anticipation doesn't consider Gravity into their effectiveness (Gen5+)")
|
SINGLE_BATTLE_TEST("Anticipation doesn't consider Gravity into their effectiveness (Gen5+)")
|
||||||
{
|
{
|
||||||
KNOWN_FAILING;
|
|
||||||
GIVEN {
|
GIVEN {
|
||||||
PLAYER(SPECIES_SKARMORY);
|
PLAYER(SPECIES_SKARMORY);
|
||||||
OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_EARTHQUAKE, MOVE_GRAVITY, MOVE_SCRATCH, MOVE_POUND); }
|
OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_EARTHQUAKE, MOVE_GRAVITY, MOVE_SCRATCH, MOVE_POUND); }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user