diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 4a8570a1a..0c88815cb 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1858,6 +1858,12 @@ various BS_ATTACKER, VARIOUS_APPLY_PLASMA_FISTS .endm + .macro jumpifspecies battler:req, species:req, ptr:req + various \battler, VARIOUS_JUMP_IF_SPECIES + .2byte \species + .4byte \ptr + .endm + .macro photongeysercheck various BS_ATTACKER, VARIOUS_PHOTON_GEYSER_CHECK .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c6ae2e848..86ebf8042 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -11,6 +11,7 @@ #include "constants/game_stat.h" #include "constants/trainers.h" #include "constants/battle_config.h" +#include "constants/species.h" .include "asm/macros.inc" .include "asm/macros/battle_script.inc" .include "constants/constants.inc" @@ -390,6 +391,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectFreezyFrost @ EFFECT_FREEZY_FROST .4byte BattleScript_EffectSparklySwirl @ EFFECT_SPARKLY_SWIRL .4byte BattleScript_EffectPlasmaFists @ EFFECT_PLASMA_FISTS + .4byte BattleScript_EffectHyperspaceFury @ EFFECT_HYPERSPACE_FURY .4byte BattleScript_EffectPhotonGeyser @ EFFECT_PHOTON_GEYSER .4byte BattleScript_EffectShellSideArm @ EFFECT_SHELL_SIDE_ARM @@ -422,6 +424,34 @@ BattleScript_EffectPhotonGeyser: tryfaintmon BS_TARGET, FALSE, NULL goto BattleScript_MoveEnd +BattleScript_EffectHyperspaceFury: + jumpifspecies BS_ATTACKER, SPECIES_TREECKO, BattleScript_EffectHyperspaceFuryUnbound + jumpifspecies BS_ATTACKER, SPECIES_MUDKIP, BattleScript_ButHoopaCantUseIt + printstring STRINGID_BUTPOKEMONCANTUSETHEMOVE + waitmessage B_WAIT_TIME_LONG + goto BattleScript_MoveEnd + +BattleScript_EffectHyperspaceFuryUnbound:: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + pause B_WAIT_TIME_LONG + ppreduce + setmoveeffect MOVE_EFFECT_FEINT + seteffectwithchance + setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + goto BattleScript_HitFromCritCalc + +BattleScript_ButHoopaCantUseIt: + printstring STRINGID_BUTHOOPACANTUSEIT + waitmessage B_WAIT_TIME_LONG + goto BattleScript_MoveEnd + +BattleScript_HyperspaceFuryRemoveProtect:: + printstring STRINGID_BROKETHROUGHPROTECTION + waitmessage B_WAIT_TIME_LONG + return + BattleScript_EffectPlasmaFists: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE diff --git a/include/battle.h b/include/battle.h index b5dabaded..1ea3e2593 100644 --- a/include/battle.h +++ b/include/battle.h @@ -638,6 +638,16 @@ struct BattleStruct gBattleMons[battlerId].type3 = TYPE_MYSTERY; \ } +#define IS_BATTLER_PROTECTED(battlerId)(gProtectStructs[battlerId].protected \ + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD \ + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_QUICK_GUARD \ + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD \ + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_MAT_BLOCK \ + || gProtectStructs[battlerId].spikyShielded \ + || gProtectStructs[battlerId].kingsShielded \ + || gProtectStructs[battlerId].banefulBunkered \ + || gProtectStructs[battlerId].obstructed) \ + #define GET_STAT_BUFF_ID(n)((n & 7)) // first three bits 0x1, 0x2, 0x4 #define GET_STAT_BUFF_VALUE_WITH_SIGN(n)((n & 0xF8)) #define GET_STAT_BUFF_VALUE(n)(((n >> 3) & 0xF)) // 0x8, 0x10, 0x20, 0x40 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 1994aef50..ec95a4549 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -401,5 +401,6 @@ extern const u8 BattleScript_AttackWeakenedByStrongWinds[]; extern const u8 BattleScript_BlockedByPrimalWeatherEnd3[]; extern const u8 BattleScript_BlockedByPrimalWeatherRet[]; extern const u8 BattleScript_PrimalReversion[]; +extern const u8 BattleScript_HyperspaceFuryRemoveProtect[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index a3a385995..99ad7360a 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -45,6 +45,8 @@ #define SPECIES_CRAMORANT_GULPING 10016 #define SPECIES_GRENINJA_BATTLE_BOND 0 #define SPECIES_GRENINJA_ASH 10017 + #define SPECIES_HOOPA 0 + #define SPECIES_HOOPA_UNBOUND 10018 #endif // Items with peculiar battle effects. diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 31bd7c884..87666f8af 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -374,9 +374,10 @@ #define EFFECT_FREEZY_FROST 368 #define EFFECT_SPARKLY_SWIRL 369 #define EFFECT_PLASMA_FISTS 370 -#define EFFECT_PHOTON_GEYSER 371 -#define EFFECT_SHELL_SIDE_ARM 372 +#define EFFECT_HYPERSPACE_FURY 371 +#define EFFECT_PHOTON_GEYSER 372 +#define EFFECT_SHELL_SIDE_ARM 373 -#define NUM_BATTLE_MOVE_EFFECTS 373 +#define NUM_BATTLE_MOVE_EFFECTS 374 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 110aaf6f0..6911b4d83 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -193,8 +193,9 @@ #define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 120 #define VARIOUS_HANDLE_PRIMAL_REVERSION 121 #define VARIOUS_APPLY_PLASMA_FISTS 122 -#define VARIOUS_PHOTON_GEYSER_CHECK 123 -#define VARIOUS_SHELL_SIDE_ARM_CHECK 124 +#define VARIOUS_JUMP_IF_SPECIES 123 +#define VARIOUS_PHOTON_GEYSER_CHECK 124 +#define VARIOUS_SHELL_SIDE_ARM_CHECK 125 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 59f6ef73d..1d461e2a0 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -594,8 +594,11 @@ #define STRINGID_ATTACKWEAKENEDBSTRONGWINDS 590 #define STRINGID_STUFFCHEEKSCANTSELECT 592 #define STRINGID_PKMNREVERTEDTOPRIMAL 593 +#define STRINGID_BUTPOKEMONCANTUSETHEMOVE 594 +#define STRINGID_BUTHOOPACANTUSEIT 595 +#define STRINGID_BROKETHROUGHPROTECTION 596 -#define BATTLESTRINGS_COUNT 594 +#define BATTLESTRINGS_COUNT 597 // The below IDs are all indexes into battle message tables, // used to determine which of a set of messages to print. diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index bb176e464..4e776e592 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -281,32 +281,33 @@ #define EV_ITEM_RAISE_LIMIT 100 // Battle move flags -#define FLAG_MAKES_CONTACT (1 << 0) -#define FLAG_PROTECT_AFFECTED (1 << 1) -#define FLAG_MAGIC_COAT_AFFECTED (1 << 2) -#define FLAG_SNATCH_AFFECTED (1 << 3) -#define FLAG_MIRROR_MOVE_AFFECTED (1 << 4) -#define FLAG_KINGS_ROCK_AFFECTED (1 << 5) -#define FLAG_HIGH_CRIT (1 << 6) -#define FLAG_RECKLESS_BOOST (1 << 7) -#define FLAG_IRON_FIST_BOOST (1 << 8) -#define FLAG_SHEER_FORCE_BOOST (1 << 9) -#define FLAG_STRONG_JAW_BOOST (1 << 10) -#define FLAG_MEGA_LAUNCHER_BOOST (1 << 11) -#define FLAG_STAT_STAGES_IGNORED (1 << 12) -#define FLAG_DMG_MINIMIZE (1 << 13) -#define FLAG_DMG_UNDERGROUND (1 << 14) -#define FLAG_DMG_UNDERWATER (1 << 15) -#define FLAG_SOUND (1 << 16) -#define FLAG_BALLISTIC (1 << 17) -#define FLAG_PROTECTION_MOVE (1 << 18) -#define FLAG_POWDER (1 << 19) -#define FLAG_TARGET_ABILITY_IGNORED (1 << 20) -#define FLAG_DANCE (1 << 21) -#define FLAG_DMG_2X_IN_AIR (1 << 22) // If target is in the air, can hit and deal double damage. -#define FLAG_DMG_IN_AIR (1 << 23) // If target is in the air, can hit. +#define FLAG_MAKES_CONTACT (1 << 0) +#define FLAG_PROTECT_AFFECTED (1 << 1) +#define FLAG_MAGIC_COAT_AFFECTED (1 << 2) +#define FLAG_SNATCH_AFFECTED (1 << 3) +#define FLAG_MIRROR_MOVE_AFFECTED (1 << 4) +#define FLAG_KINGS_ROCK_AFFECTED (1 << 5) +#define FLAG_HIGH_CRIT (1 << 6) +#define FLAG_RECKLESS_BOOST (1 << 7) +#define FLAG_IRON_FIST_BOOST (1 << 8) +#define FLAG_SHEER_FORCE_BOOST (1 << 9) +#define FLAG_STRONG_JAW_BOOST (1 << 10) +#define FLAG_MEGA_LAUNCHER_BOOST (1 << 11) +#define FLAG_STAT_STAGES_IGNORED (1 << 12) +#define FLAG_DMG_MINIMIZE (1 << 13) +#define FLAG_DMG_UNDERGROUND (1 << 14) +#define FLAG_DMG_UNDERWATER (1 << 15) +#define FLAG_SOUND (1 << 16) +#define FLAG_BALLISTIC (1 << 17) +#define FLAG_PROTECTION_MOVE (1 << 18) +#define FLAG_POWDER (1 << 19) +#define FLAG_TARGET_ABILITY_IGNORED (1 << 20) +#define FLAG_DANCE (1 << 21) +#define FLAG_DMG_2X_IN_AIR (1 << 22) // If target is in the air, can hit and deal double damage. +#define FLAG_DMG_IN_AIR (1 << 23) // If target is in the air, can hit. #define FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING (1 << 24) // Makes a Ground type move do 1x damage to flying and levitating targets -#define FLAG_THAW_USER (1 << 25) +#define FLAG_THAW_USER (1 << 25) +#define FLAG_HIT_IN_SUBSTITUTE (1 << 26) // Hyperspace Fury // Split defines. #define SPLIT_PHYSICAL 0x0 diff --git a/src/battle_message.c b/src/battle_message.c index 444d32671..f26726a69 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -720,9 +720,15 @@ static const u8 sText_MysteriousAirCurrentBlowsOn[] = _("The mysterious air curr static const u8 sText_AttackWeakenedByStrongWinds[] = _("The mysterious strong winds\nweakened the attack!"); static const u8 sText_StuffCheeksCantSelect[] = _("Stuff Cheeks cannot be\nselected without a Berry!\p"); static const u8 sText_PkmnRevertedToPrimal[] = _("{B_ATK_NAME_WITH_PREFIX}'s Primal Reversion!\nIt reverted to its primal form!"); +static const u8 sText_ButPokemonCantUseTheMove[] = _("But {B_ATK_NAME_WITH_PREFIX} can't\nuse the move!"); +static const u8 sText_ButHoopaCantUseIt[] = _("But Hoopa can't use it\nthe way it is now!"); +static const u8 sText_BrokeThroughProtection[] = _("It broke through the\n{B_DEF_NAME_WITH_PREFIX}'s protection!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_BROKETHROUGHPROTECTION - 12] = sText_BrokeThroughProtection, + [STRINGID_BUTPOKEMONCANTUSETHEMOVE - 12] = sText_ButPokemonCantUseTheMove, + [STRINGID_BUTHOOPACANTUSEIT - 12] = sText_ButHoopaCantUseIt, [STRINGID_PKMNREVERTEDTOPRIMAL - 12] = sText_PkmnRevertedToPrimal, [STRINGID_STUFFCHEEKSCANTSELECT - 12] = sText_StuffCheeksCantSelect, [STRINGID_ATTACKWEAKENEDBSTRONGWINDS - 12] = sText_AttackWeakenedByStrongWinds, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2e25eb8ba..debd14a5a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3279,15 +3279,7 @@ void SetMoveEffect(bool32 primary, u32 certain) } break; case MOVE_EFFECT_FEINT: - if (gProtectStructs[gBattlerTarget].protected - || gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_WIDE_GUARD - || gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_QUICK_GUARD - || gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_CRAFTY_SHIELD - || gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_MAT_BLOCK - || gProtectStructs[gBattlerTarget].spikyShielded - || gProtectStructs[gBattlerTarget].kingsShielded - || gProtectStructs[gBattlerTarget].banefulBunkered - || gProtectStructs[gBattlerTarget].obstructed) + if (IS_BATTLER_PROTECTED(gBattlerTarget)) { gProtectStructs[gBattlerTarget].protected = 0; gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~(SIDE_STATUS_WIDE_GUARD); @@ -3303,6 +3295,11 @@ void SetMoveEffect(bool32 primary, u32 certain) BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectFeint; } + else if (gCurrentMove == MOVE_HYPERSPACE_FURY) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_HyperspaceFuryRemoveProtect; + } } break; case MOVE_EFFECT_SPECTRAL_THIEF: @@ -8978,6 +8975,12 @@ static void Cmd_various(void) for (i = 0; i < gBattlersCount; i++) gStatuses4[i] |= STATUS4_PLASMA_FISTS; break; + case VARIOUS_JUMP_IF_SPECIES: + if (gBattleMons[gActiveBattler].species == T1_READ_16(gBattlescriptCurrInstr + 3)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 5); + else + gBattlescriptCurrInstr += 9; + return; case VARIOUS_PHOTON_GEYSER_CHECK: { u32 attStat = gBattleMons[gActiveBattler].attack; @@ -12565,6 +12568,8 @@ bool32 DoesSubstituteBlockMove(u8 battlerAtk, u8 battlerDef, u32 move) return FALSE; else if (GetBattlerAbility(battlerAtk) == ABILITY_INFILTRATOR) return FALSE; + else if (gBattleMoves[move].flags & FLAG_HIT_IN_SUBSTITUTE) + return FALSE; else return TRUE; } diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 38c531b23..11de687de 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -7415,6 +7415,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, + .argument = MOVE_EFFECT_FEINT, }, [MOVE_HONE_CLAWS] = @@ -9691,15 +9692,15 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_HYPERSPACE_FURY] = { - .effect = EFFECT_PLACEHOLDER, - .power = 0, + .effect = EFFECT_HYPERSPACE_FURY, + .power = 100, .type = TYPE_DARK, .accuracy = 0, - .pp = 0, - .secondaryEffectChance = 0, + .pp = 5, + .secondaryEffectChance = 100, .target = MOVE_TARGET_SELECTED, .priority = 0, - .flags = 0, + .flags = FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_HIT_IN_SUBSTITUTE, .split = SPLIT_PHYSICAL, },