Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes Recoil if Miss effect if crashed into absorb ability #5774

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 10 additions & 46 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -3435,52 +3435,6 @@ BattleScript_EffectSuperFang::
damagetohalftargethp
goto BattleScript_HitFromAtkAnimation

BattleScript_EffectRecoilIfMiss::
attackcanceler
accuracycheck BattleScript_MoveMissedDoDamage, ACC_CURR_MOVE
.if B_CRASH_IF_TARGET_IMMUNE >= GEN_4
typecalc
jumpifhalfword CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_MoveMissedDoDamage
.endif
goto BattleScript_HitFromAtkString
BattleScript_MoveMissedDoDamage::
jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_PrintMoveMissed
attackstring
ppreduce
pause B_WAIT_TIME_LONG
resultmessage
waitmessage B_WAIT_TIME_LONG
.if B_CRASH_IF_TARGET_IMMUNE < GEN_4
jumpifhalfword CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_MoveEnd
.endif
moveendcase MOVEEND_PROTECT_LIKE_EFFECT @ Spiky Shield's damage happens before recoil.
jumpifhasnohp BS_ATTACKER, BattleScript_MoveEnd
printstring STRINGID_PKMNCRASHED
waitmessage B_WAIT_TIME_LONG
damagecalc
typecalc
adjustdamage
.if B_CRASH_IF_TARGET_IMMUNE == GEN_4
manipulatedamage DMG_RECOIL_FROM_IMMUNE
.else
manipulatedamage DMG_RECOIL_FROM_MISS
.endif
.if B_CRASH_IF_TARGET_IMMUNE >= GEN_4
bichalfword gMoveResultFlags, MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE
.else
bichalfword gMoveResultFlags, MOVE_RESULT_MISSED
.endif
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
tryfaintmon BS_ATTACKER
.if B_CRASH_IF_TARGET_IMMUNE >= GEN_4
orhalfword gMoveResultFlags, MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE
.else
orhalfword gMoveResultFlags, MOVE_RESULT_MISSED
.endif
goto BattleScript_MoveEnd

BattleScript_EffectMist::
attackcanceler
attackstring
Expand Down Expand Up @@ -7550,6 +7504,16 @@ BattleScript_MoveEffectConfusion::
waitmessage B_WAIT_TIME_LONG
return

BattleScript_MoveEffectRecoilIfMiss::
printstring STRINGID_PKMNCRASHED
waitmessage B_WAIT_TIME_LONG
jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_RecoilEnd
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_IGNORE_DISGUISE
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
tryfaintmon BS_ATTACKER
return

BattleScript_MoveEffectRecoil::
jumpifmove MOVE_STRUGGLE, BattleScript_DoRecoil
jumpifability BS_ATTACKER, ABILITY_ROCK_HEAD, BattleScript_RecoilEnd
Expand Down
3 changes: 2 additions & 1 deletion include/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,8 @@ struct BattleStruct
u16 commanderActive[MAX_BATTLERS_COUNT];
u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side
u8 redCardActivates:1;
u8 padding:7;
u8 noTargetPresent:1;
u8 padding:6;
u8 usedEjectItem;
u8 usedMicleBerry;
};
Expand Down
2 changes: 1 addition & 1 deletion include/battle_scripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ extern const u8 BattleScript_MoveEffectToxic[];
extern const u8 BattleScript_MoveEffectPayDay[];
extern const u8 BattleScript_MoveEffectWrap[];
extern const u8 BattleScript_MoveEffectConfusion[];
extern const u8 BattleScript_MoveEffectRecoilIfMiss[];
extern const u8 BattleScript_MoveEffectRecoil[];
extern const u8 BattleScript_FaintAttackerForExplosion[];
extern const u8 BattleScript_MaxHp50Recoil[];
Expand Down Expand Up @@ -596,7 +597,6 @@ extern const u8 BattleScript_EffectOHKO[];
extern const u8 BattleScript_EffectSuperFang[];
extern const u8 BattleScript_EffectFixedDamageArg[];
extern const u8 BattleScript_EffectHealBlock[];
extern const u8 BattleScript_EffectRecoilIfMiss[];
extern const u8 BattleScript_EffectMist[];
extern const u8 BattleScript_EffectFocusEnergy[];
extern const u8 BattleScript_EffectConfuse[];
Expand Down
1 change: 1 addition & 0 deletions include/constants/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@
#define MOVE_RESULT_FOE_HUNG_ON (1 << 7)
#define MOVE_RESULT_STURDIED (1 << 8)
#define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9)
#define MOVE_RESULT_ABSORBED (1 << 10)
#define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED)

// Battle Weather flags
Expand Down
12 changes: 5 additions & 7 deletions include/constants/battle_script_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,11 @@

// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0
#define DMG_RECOIL_FROM_MISS 1
#define DMG_DOUBLED 2
#define DMG_1_8_TARGET_HP 3
#define DMG_FULL_ATTACKER_HP 4
#define DMG_CURR_ATTACKER_HP 5
#define DMG_BIG_ROOT 6
#define DMG_RECOIL_FROM_IMMUNE 7 // Used to calculate recoil for the Gen 4 version of Jump Kick
#define DMG_DOUBLED 1
#define DMG_1_8_TARGET_HP 2
#define DMG_FULL_ATTACKER_HP 3
#define DMG_CURR_ATTACKER_HP 4
#define DMG_BIG_ROOT 5

// Cmd_jumpifcantswitch
#define SWITCH_IGNORE_ESCAPE_PREVENTION (1 << 7)
Expand Down
51 changes: 28 additions & 23 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,7 @@ static void Cmd_attackcanceler(void)
gBattlescriptCurrInstr = BattleScript_FlingFailConsumeItem;
else
gBattlescriptCurrInstr = BattleScript_FailedFromAtkString;

gBattleStruct->noTargetPresent = TRUE;
if (!gBattleMoveEffects[gMovesInfo[gCurrentMove].effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
CancelMultiTurnMoves(gBattlerAttacker);
return;
Expand Down Expand Up @@ -1359,6 +1359,7 @@ static void Cmd_attackcanceler(void)

if (gSpecialStatuses[gBattlerTarget].lightningRodRedirected)
{
gMoveResultFlags |= MOVE_RESULT_ABSORBED;
gSpecialStatuses[gBattlerTarget].lightningRodRedirected = FALSE;
gLastUsedAbility = ABILITY_LIGHTNING_ROD;
BattleScriptPushCursor();
Expand All @@ -1367,6 +1368,7 @@ static void Cmd_attackcanceler(void)
}
else if (gSpecialStatuses[gBattlerTarget].stormDrainRedirected)
{
gMoveResultFlags |= MOVE_RESULT_ABSORBED;
gSpecialStatuses[gBattlerTarget].stormDrainRedirected = FALSE;
gLastUsedAbility = ABILITY_STORM_DRAIN;
BattleScriptPushCursor();
Expand Down Expand Up @@ -1419,7 +1421,10 @@ static bool32 JumpIfMoveFailed(u8 adder, u16 move)
{
TrySetDestinyBondToHappen();
if (AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBattlerTarget, 0, 0, move))
{
gMoveResultFlags |= MOVE_RESULT_ABSORBED;
return TRUE;
}
}
gBattlescriptCurrInstr += adder;
return FALSE;
Expand Down Expand Up @@ -5756,6 +5761,25 @@ static void Cmd_moveend(void)
gBattleScripting.moveendState++;
break;
}
else if (gMovesInfo[gCurrentMove].effect == EFFECT_RECOIL_IF_MISS
&& gMoveResultFlags & (MOVE_RESULT_NO_EFFECT | MOVE_RESULT_ABSORBED)
&& !gBattleStruct->noTargetPresent
&& IsBattlerAlive(gBattlerAttacker))
{
if (B_RECOIL_IF_MISS_DMG >= GEN_5 || (B_CRASH_IF_TARGET_IMMUNE == GEN_4 && gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE))
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
else if (B_RECOIL_IF_MISS_DMG == GEN_4 && (gBattleMons[gBattlerTarget].maxHP / 2) < gBattleMoveDamage)
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerTarget) / 2;
else
gBattleMoveDamage /= 2;
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;

BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoilIfMiss;
effect = TRUE;
}
else if (gMovesInfo[gCurrentMove].recoil > 0
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& IsBattlerAlive(gBattlerAttacker)
Expand Down Expand Up @@ -6641,6 +6665,7 @@ static void Cmd_moveend(void)
gBattleStruct->fickleBeamBoosted = FALSE;
gBattleStruct->redCardActivates = FALSE;
gBattleStruct->usedMicleBerry &= ~(1u << gBattlerAttacker);
gBattleStruct->noTargetPresent = FALSE;
if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
gBattleStruct->pledgeMove = FALSE;
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
Expand Down Expand Up @@ -11308,23 +11333,6 @@ static void Cmd_manipulatedamage(void)
case DMG_CHANGE_SIGN:
gBattleMoveDamage *= -1;
break;
case DMG_RECOIL_FROM_MISS:
if (B_RECOIL_IF_MISS_DMG >= GEN_5)
{
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
}
else if (B_RECOIL_IF_MISS_DMG == GEN_4)
{
if ((gBattleMons[gBattlerTarget].maxHP / 2) < gBattleMoveDamage)
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerTarget) / 2;
}
else
{
gBattleMoveDamage /= 2;
}
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
break;
case DMG_DOUBLED:
gBattleMoveDamage *= 2;
break;
Expand All @@ -11336,14 +11344,11 @@ static void Cmd_manipulatedamage(void)
case DMG_FULL_ATTACKER_HP:
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker);
break;
case DMG_BIG_ROOT:
gBattleMoveDamage = GetDrainedBigRootHp(gBattlerAttacker, gBattleMoveDamage);
break;
case DMG_CURR_ATTACKER_HP:
gBattleMoveDamage = GetNonDynamaxHP(gBattlerAttacker);
break;
case DMG_RECOIL_FROM_IMMUNE:
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerTarget) / 2;
case DMG_BIG_ROOT:
gBattleMoveDamage = GetDrainedBigRootHp(gBattlerAttacker, gBattleMoveDamage);
break;
}

Expand Down
2 changes: 1 addition & 1 deletion src/data/battle_move_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =

[EFFECT_RECOIL_IF_MISS] =
{
.battleScript = BattleScript_EffectRecoilIfMiss,
.battleScript = BattleScript_EffectHit,
.battleTvScore = 1,
},

Expand Down
43 changes: 38 additions & 5 deletions test/battle/move_effect/recoil_if_miss.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ASSUMPTIONS
ASSUME(gMovesInfo[MOVE_JUMP_KICK].effect == EFFECT_RECOIL_IF_MISS);
}

SINGLE_BATTLE_TEST("Jump Kick has 50% recoil on miss")
SINGLE_BATTLE_TEST("Recoil If Miss: Jump Kick has 50% recoil on miss")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
Expand All @@ -22,14 +22,14 @@ SINGLE_BATTLE_TEST("Jump Kick has 50% recoil on miss")
}
}

SINGLE_BATTLE_TEST("Jump Kick has 50% recoil on protect")
SINGLE_BATTLE_TEST("Recoil If Miss: Jump Kick has 50% recoil on protect")
{
GIVEN {
ASSUME(!gMovesInfo[MOVE_JUMP_KICK].ignoresProtect);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_JUMP_KICK, hit: FALSE); }
TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_JUMP_KICK); }
} SCENE {
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent);
Expand All @@ -38,7 +38,25 @@ SINGLE_BATTLE_TEST("Jump Kick has 50% recoil on protect")
}
}

SINGLE_BATTLE_TEST("Jump Kick has no recoil if no target")
SINGLE_BATTLE_TEST("Recoil If Miss: Jump Kick recoil happens after Spiky Shield damage")
{
GIVEN {
ASSUME(!gMovesInfo[MOVE_JUMP_KICK].ignoresProtect);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SPIKY_SHIELD); MOVE(player, MOVE_JUMP_KICK); }
} SCENE {
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKY_SHIELD, opponent);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_JUMP_KICK, player);
MESSAGE("Wobbuffet was hurt by the opposing Wobbuffet's Spiky Shield!");
MESSAGE("Wobbuffet kept going and crashed!");
HP_BAR(player, damage: maxHP / 2);
}
}

SINGLE_BATTLE_TEST("Recoil If Miss: Jump Kick has no recoil if no target")
{
GIVEN {
ASSUME(B_HEALING_WISH_SWITCH >= GEN_5);
Expand All @@ -54,7 +72,7 @@ SINGLE_BATTLE_TEST("Jump Kick has no recoil if no target")
}
}

SINGLE_BATTLE_TEST("Jump Kick's recoil happens after Spiky Shield damage and Pokemon can faint from either of these")
SINGLE_BATTLE_TEST("Recoil If Miss: Jump Kick's recoil happens after Spiky Shield damage and Pokemon can faint from either of these")
{
s16 hp, maxHp = 256;
bool32 faintOnSpiky = FALSE, faintOnJumpKick = FALSE;
Expand Down Expand Up @@ -98,3 +116,18 @@ SINGLE_BATTLE_TEST("Jump Kick's recoil happens after Spiky Shield damage and Pok
}
}
}

SINGLE_BATTLE_TEST("Recoil If Miss: Supercell Slam causes recoil if it is absorbed")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_PIKACHU) { Ability(ABILITY_LIGHTNING_ROD); }
} WHEN {
TURN { MOVE(player, MOVE_SUPERCELL_SLAM); }
} SCENE {
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
ABILITY_POPUP(opponent, ABILITY_LIGHTNING_ROD);
MESSAGE("Wobbuffet kept going and crashed!");
HP_BAR(player, damage: maxHP / 2);
}
}
Loading