diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 40ca3c091..7e94460ef 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1995,7 +1995,6 @@ BattleScript_EffectHitSwitchTarget: resultmessage waitmessage B_WAIT_TIME_LONG tryfaintmon BS_TARGET - checkparentalbondcounter 2, BattleScript_EffectHitSwitchTargetMoveEnd moveendall jumpifability BS_TARGET, ABILITY_SUCTION_CUPS, BattleScript_AbilityPreventsPhasingOut jumpifstatus3 BS_TARGET, STATUS3_ROOTED, BattleScript_PrintMonIsRooted diff --git a/include/battle.h b/include/battle.h index b452f16cd..8e9f6c300 100644 --- a/include/battle.h +++ b/include/battle.h @@ -174,7 +174,7 @@ struct SpecialStatus u8 berryReduced:1; u8 gemBoost:1; u8 rototillerAffected:1; // to be affected by rototiller - u8 parentalBondOn:2; + u8 parentalBondState:2; u8 multiHitOn:1; // End of byte, two bits unused u8 gemParam; diff --git a/include/constants/battle.h b/include/constants/battle.h index 0cb022758..1592a7af4 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -307,66 +307,65 @@ #define MOVE_EFFECT_PAYDAY 0xB #define MOVE_EFFECT_CHARGING 0xC #define MOVE_EFFECT_WRAP 0xD -#define MOVE_EFFECT_ATK_PLUS_1 0xE -#define MOVE_EFFECT_DEF_PLUS_1 0xF -#define MOVE_EFFECT_SPD_PLUS_1 0x10 -#define MOVE_EFFECT_SP_ATK_PLUS_1 0x11 -#define MOVE_EFFECT_SP_DEF_PLUS_1 0x12 -#define MOVE_EFFECT_ACC_PLUS_1 0x13 -#define MOVE_EFFECT_EVS_PLUS_1 0x14 -#define MOVE_EFFECT_ATK_MINUS_1 0x15 -#define MOVE_EFFECT_DEF_MINUS_1 0x16 -#define MOVE_EFFECT_SPD_MINUS_1 0x17 -#define MOVE_EFFECT_SP_ATK_MINUS_1 0x18 -#define MOVE_EFFECT_SP_DEF_MINUS_1 0x19 -#define MOVE_EFFECT_ACC_MINUS_1 0x1A -#define MOVE_EFFECT_EVS_MINUS_1 0x1B -#define MOVE_EFFECT_RECHARGE 0x1C -#define MOVE_EFFECT_RAGE 0x1D -#define MOVE_EFFECT_STEAL_ITEM 0x1E -#define MOVE_EFFECT_PREVENT_ESCAPE 0x1F -#define MOVE_EFFECT_NIGHTMARE 0x20 -#define MOVE_EFFECT_ALL_STATS_UP 0x21 -#define MOVE_EFFECT_RAPIDSPIN 0x22 -#define MOVE_EFFECT_REMOVE_STATUS 0x23 -#define MOVE_EFFECT_ATK_DEF_DOWN 0x24 -#define MOVE_EFFECT_ATK_PLUS_2 0x25 -#define MOVE_EFFECT_DEF_PLUS_2 0x26 -#define MOVE_EFFECT_SPD_PLUS_2 0x27 -#define MOVE_EFFECT_SP_ATK_PLUS_2 0x28 -#define MOVE_EFFECT_SP_DEF_PLUS_2 0x29 -#define MOVE_EFFECT_ACC_PLUS_2 0x2A -#define MOVE_EFFECT_EVS_PLUS_2 0x2B -#define MOVE_EFFECT_ATK_MINUS_2 0x2C -#define MOVE_EFFECT_DEF_MINUS_2 0x2D -#define MOVE_EFFECT_SPD_MINUS_2 0x2E -#define MOVE_EFFECT_SP_ATK_MINUS_2 0x2F -#define MOVE_EFFECT_SP_DEF_MINUS_2 0x30 -#define MOVE_EFFECT_ACC_MINUS_2 0x31 -#define MOVE_EFFECT_EVS_MINUS_2 0x32 -#define MOVE_EFFECT_THRASH 0x33 -#define MOVE_EFFECT_KNOCK_OFF 0x34 -#define MOVE_EFFECT_DEF_SPDEF_DOWN 0x35 -#define MOVE_EFFECT_CLEAR_SMOG 0x36 -#define MOVE_EFFECT_SP_ATK_TWO_DOWN 0x37 -#define MOVE_EFFECT_SMACK_DOWN 0x38 -#define MOVE_EFFECT_FLAME_BURST 0x39 -#define MOVE_EFFECT_FEINT 0x3A -#define MOVE_EFFECT_SPECTRAL_THIEF 0x3B -#define MOVE_EFFECT_V_CREATE 0x3C -#define MOVE_EFFECT_HAPPY_HOUR 0x3D -#define MOVE_EFFECT_CORE_ENFORCER 0x3E -#define MOVE_EFFECT_THROAT_CHOP 0x3F -#define MOVE_EFFECT_INCINERATE 0x40 -#define MOVE_EFFECT_BUG_BITE 0x41 -#define MOVE_EFFECT_RECOIL_HP_25 0x42 -#define MOVE_EFFECT_RELIC_SONG 0x43 -#define MOVE_EFFECT_TRAP_BOTH 0x44 -#define MOVE_EFFECT_SKY_DROP 0x45 -#define MOVE_EFFECT_SCALE_SHOT 0x46 -#define MOVE_EFFECT_BURN_UP 0x47 - -#define NUM_MOVE_EFFECTS 0x48 +#define MOVE_EFFECT_BURN_UP 0xE // MOVE_EFFECT_BURN_UP replaces unused MOVE_EFFECT_RECOIL_25 so that stat change animations don't break +#define MOVE_EFFECT_ATK_PLUS_1 0xF +#define MOVE_EFFECT_DEF_PLUS_1 0x10 +#define MOVE_EFFECT_SPD_PLUS_1 0x11 +#define MOVE_EFFECT_SP_ATK_PLUS_1 0x12 +#define MOVE_EFFECT_SP_DEF_PLUS_1 0x13 +#define MOVE_EFFECT_ACC_PLUS_1 0x14 +#define MOVE_EFFECT_EVS_PLUS_1 0x15 +#define MOVE_EFFECT_ATK_MINUS_1 0x16 +#define MOVE_EFFECT_DEF_MINUS_1 0x17 +#define MOVE_EFFECT_SPD_MINUS_1 0x18 +#define MOVE_EFFECT_SP_ATK_MINUS_1 0x19 +#define MOVE_EFFECT_SP_DEF_MINUS_1 0x1A +#define MOVE_EFFECT_ACC_MINUS_1 0x1B +#define MOVE_EFFECT_EVS_MINUS_1 0x1C +#define MOVE_EFFECT_RECHARGE 0x1D +#define MOVE_EFFECT_RAGE 0x1E +#define MOVE_EFFECT_STEAL_ITEM 0x1F +#define MOVE_EFFECT_PREVENT_ESCAPE 0x20 +#define MOVE_EFFECT_NIGHTMARE 0x21 +#define MOVE_EFFECT_ALL_STATS_UP 0x22 +#define MOVE_EFFECT_RAPIDSPIN 0x23 +#define MOVE_EFFECT_REMOVE_STATUS 0x24 +#define MOVE_EFFECT_ATK_DEF_DOWN 0x25 +#define MOVE_EFFECT_SCALE_SHOT 0x26 // MOVE_EFFECT_SCALE_SHOT replaces unused MOVE_EFFECT_RECOIL_33 so that stat change animations don't break +#define MOVE_EFFECT_ATK_PLUS_2 0x27 +#define MOVE_EFFECT_DEF_PLUS_2 0x28 +#define MOVE_EFFECT_SPD_PLUS_2 0x29 +#define MOVE_EFFECT_SP_ATK_PLUS_2 0x2A +#define MOVE_EFFECT_SP_DEF_PLUS_2 0x2B +#define MOVE_EFFECT_ACC_PLUS_2 0x2C +#define MOVE_EFFECT_EVS_PLUS_2 0x2D +#define MOVE_EFFECT_ATK_MINUS_2 0x2E +#define MOVE_EFFECT_DEF_MINUS_2 0x2F +#define MOVE_EFFECT_SPD_MINUS_2 0x30 +#define MOVE_EFFECT_SP_ATK_MINUS_2 0x31 +#define MOVE_EFFECT_SP_DEF_MINUS_2 0x32 +#define MOVE_EFFECT_ACC_MINUS_2 0x33 +#define MOVE_EFFECT_EVS_MINUS_2 0x34 +#define MOVE_EFFECT_THRASH 0x35 +#define MOVE_EFFECT_KNOCK_OFF 0x36 +#define MOVE_EFFECT_DEF_SPDEF_DOWN 0x37 +#define MOVE_EFFECT_CLEAR_SMOG 0x38 +#define MOVE_EFFECT_SP_ATK_TWO_DOWN 0x39 +#define MOVE_EFFECT_SMACK_DOWN 0x3A +#define MOVE_EFFECT_FLAME_BURST 0x3B +#define MOVE_EFFECT_FEINT 0x3C +#define MOVE_EFFECT_SPECTRAL_THIEF 0x3D +#define MOVE_EFFECT_V_CREATE 0x3E +#define MOVE_EFFECT_HAPPY_HOUR 0x3F +#define MOVE_EFFECT_CORE_ENFORCER 0x40 +#define MOVE_EFFECT_THROAT_CHOP 0x41 +#define MOVE_EFFECT_INCINERATE 0x42 +#define MOVE_EFFECT_BUG_BITE 0x43 +#define MOVE_EFFECT_RECOIL_HP_25 0x44 +#define MOVE_EFFECT_RELIC_SONG 0x45 +#define MOVE_EFFECT_TRAP_BOTH 0x46 + +#define NUM_MOVE_EFFECTS 0x47 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 @@ -480,4 +479,9 @@ // For the second argument of GetMoveTarget, when no target override is needed #define NO_TARGET_OVERRIDE 0 +// Constants for Parental Bond +#define PARENTAL_BOND_1ST_HIT 2 +#define PARENTAL_BOND_2ND_HIT 1 +#define PARENTAL_BOND_OFF 0 + #endif // GUARD_CONSTANTS_BATTLE_H diff --git a/src/battle_main.c b/src/battle_main.c index bf2c92fee..b47085248 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4843,7 +4843,7 @@ static void TurnValuesCleanUp(bool8 var0) if (gDisableStructs[gActiveBattler].substituteHP == 0) gBattleMons[gActiveBattler].status2 &= ~(STATUS2_SUBSTITUTE); - gSpecialStatuses[gActiveBattler].parentalBondOn = 0; + gSpecialStatuses[gActiveBattler].parentalBondState = PARENTAL_BOND_OFF; } gSideStatuses[0] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 24ec0426e..e6192700e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1138,6 +1138,7 @@ static const u16 sFinalStrikeOnlyEffects[] = EFFECT_HIT_ESCAPE, EFFECT_RECOIL_HP_25, EFFECT_HIT_PREVENT_ESCAPE, + EFFECT_HIT_SWITCH_TARGET, }; static const u16 sNaturePowerMoves[BATTLE_TERRAIN_COUNT] = @@ -1449,12 +1450,13 @@ static void Cmd_attackcanceler(void) if (AtkCanceller_UnableToUseMove()) return; - if (!gSpecialStatuses[gBattlerAttacker].parentalBondOn + if (!gSpecialStatuses[gBattlerAttacker].parentalBondState && GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND && IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker) - && !(gAbsentBattlerFlags & gBitTable[gBattlerTarget])) + && !(gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + && gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE) { - gSpecialStatuses[gBattlerAttacker].parentalBondOn = 2; + gSpecialStatuses[gBattlerAttacker].parentalBondState = PARENTAL_BOND_1ST_HIT; gMultiHitCounter = 2; PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) return; @@ -1591,6 +1593,13 @@ static void Cmd_attackcanceler(void) gMoveResultFlags |= MOVE_RESULT_MISSED; gLastLandedMoves[gBattlerTarget] = 0; gLastHitByType[gBattlerTarget] = 0; + + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT) + { + gSpecialStatuses[gBattlerAttacker].parentalBondState = PARENTAL_BOND_OFF; // No second hit if first hit was blocked + gSpecialStatuses[gBattlerAttacker].multiHitOn = 0; + gMultiHitCounter = 0; + } gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; gBattlescriptCurrInstr++; } @@ -1840,7 +1849,7 @@ static void Cmd_accuracycheck(void) else if (!JumpIfMoveAffectedByProtect(0)) gBattlescriptCurrInstr += 7; } - else if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1 + else if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT || (gSpecialStatuses[gBattlerAttacker].multiHitOn && (gBattleMoves[move].effect != EFFECT_TRIPLE_KICK || GetBattlerAbility(gBattlerAttacker) == ABILITY_SKILL_LINK))) { @@ -1930,7 +1939,7 @@ static void Cmd_ppreduce(void) if (gCurrentMove == gLastResultingMoves[gBattlerAttacker] && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !WasUnableToUseMove(gBattlerAttacker) - && gSpecialStatuses[gBattlerAttacker].parentalBondOn != 2) // Don't increment counter on first hit + && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) // Don't increment counter on first hit gBattleStruct->sameMoveTurns[gBattlerAttacker]++; else gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0; @@ -2247,7 +2256,7 @@ static void Cmd_attackanimation(void) } else { - if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1) // No animation on second hit + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT) // No animation on second hit { gBattlescriptCurrInstr++; return; @@ -2780,7 +2789,7 @@ void SetMoveEffect(bool32 primary, u32 certain) u32 flags = 0; u16 battlerAbility; - if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 2 + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && gBattleMons[gBattlerTarget].hp != 0 && IsFinalStrikeEffect(gCurrentMove)) { @@ -3156,7 +3165,7 @@ void SetMoveEffect(bool32 primary, u32 certain) break; case MOVE_EFFECT_PAYDAY: // Don't scatter coins on the second hit of Parental Bond - if (GET_BATTLER_SIDE(gBattlerAttacker) == B_SIDE_PLAYER && gSpecialStatuses[gBattlerAttacker].parentalBondOn != 1) + if (GET_BATTLER_SIDE(gBattlerAttacker) == B_SIDE_PLAYER && gSpecialStatuses[gBattlerAttacker].parentalBondState!= PARENTAL_BOND_2ND_HIT) { u16 payday = gPaydayMoney; gPaydayMoney += (gBattleMons[gBattlerAttacker].level * 5); @@ -5682,8 +5691,8 @@ static void Cmd_moveend(void) && (gChosenMove == MOVE_SLEEP_TALK || !(gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)) && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE)) { - if (gSpecialStatuses[gBattlerAttacker].parentalBondOn) - gSpecialStatuses[gBattlerAttacker].parentalBondOn--; + if (gSpecialStatuses[gBattlerAttacker].parentalBondState) + gSpecialStatuses[gBattlerAttacker].parentalBondState--; gHitMarker |= (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING); gBattleScripting.animTargetsHit = 0; @@ -5706,7 +5715,7 @@ static void Cmd_moveend(void) } } gMultiHitCounter = 0; - gSpecialStatuses[gBattlerAttacker].parentalBondOn = 0; + gSpecialStatuses[gBattlerAttacker].parentalBondState = PARENTAL_BOND_OFF; gSpecialStatuses[gBattlerAttacker].multiHitOn = 0; gBattleScripting.moveendState++; break; @@ -10059,7 +10068,7 @@ static void Cmd_various(void) // Some effects should only happen on the first or second strike of Parental Bond, // so a way to check this in battle scripts is useful u8 counter = T1_READ_8(gBattlescriptCurrInstr + 3); - if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == counter && gBattleMons[gBattlerTarget].hp != 0) + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == counter && gBattleMons[gBattlerTarget].hp != 0) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 4); else gBattlescriptCurrInstr += 8; @@ -10540,7 +10549,7 @@ static void Cmd_stockpiletobasedamage(void) if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; - if (!(gSpecialStatuses[gBattlerAttacker].parentalBondOn == 2 && gBattleMons[gBattlerTarget].hp != 0)) + if (!(gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && gBattleMons[gBattlerTarget].hp != 0)) { gDisableStructs[gBattlerAttacker].stockpileCounter = 0; // Restore stat changes from stockpile. @@ -12438,7 +12447,7 @@ static void Cmd_handlefurycutter(void) else { if (gDisableStructs[gBattlerAttacker].furyCutterCounter != 5 - && gSpecialStatuses[gBattlerAttacker].parentalBondOn != 2) // Don't increment counter on first hit + && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) // Don't increment counter on first hit gDisableStructs[gBattlerAttacker].furyCutterCounter++; gBattlescriptCurrInstr++; @@ -12469,7 +12478,7 @@ static void Cmd_presentdamagecalculation(void) * damage, the second strike will always deal damage too. This is a simple way * to replicate that effect. */ - if (gSpecialStatuses[gBattlerAttacker].parentalBondOn != 1) + if (gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_2ND_HIT) { if (rand < 102) { diff --git a/src/battle_util.c b/src/battle_util.c index 698d676f1..1e99a2301 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9292,7 +9292,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move } // Parental Bond Second Strike - if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1) + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT) { if (B_PARENTAL_BOND_DAMAGE < GEN_7) MulModifier(&finalModifier, UQ_4_12(0.5));