From 3c85089428e1fa4a1f127dd221b60e8cb02c959b Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:32:11 +0200 Subject: [PATCH] Fixes Gulp Missile Dive / Power Herb interaction (#4371) * Fixed Cramorant Dive / Power Herb interaction * remove file * leftover --- asm/macros/battle_script.inc | 6 +- data/battle_scripts_1.s | 6 ++ include/battle_scripts.h | 1 + src/battle_script_commands.c | 13 +++ src/battle_util.c | 3 +- test/battle/ability/gulp_missile.c | 137 +++++++++++++++++++++++++++++ 6 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 test/battle/ability/gulp_missile.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 561ea6d146..25e0110a51 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1360,7 +1360,7 @@ .byte \battler .4byte \jumpInstr .endm - + .macro itemstatchangeeffects battler:req callnative BS_RunStatChangeItems .byte \battler @@ -1632,6 +1632,10 @@ .4byte \jumpInstr .endm + .macro trygulpmissile + callnative BS_TryGulpMissile + .endm + @ various command changed to more readable macros .macro cancelmultiturnmoves battler:req various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c9662b783b..944ef87466 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3804,6 +3804,8 @@ BattleScript_FirstChargingTurnAfterAttackString: BattleScript_TwoTurnMovesSecondPowerHerbActivates: call BattleScript_PowerHerbActivation + trygulpmissile @ Edge case for Cramorant ability Gulp Missile +BattleScript_FromTwoTurnMovesSecondTurnRet: call BattleScript_TwoTurnMovesSecondTurnRet accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE @ before Gen 5, charge moves did not print an attack string on the charge turn @@ -7006,6 +7008,10 @@ BattleScript_UltraBurst:: switchinabilities BS_ATTACKER end3 +BattleScript_GulpMissileFormChange:: + call BattleScript_AttackerFormChange + goto BattleScript_FromTwoTurnMovesSecondTurnRet + BattleScript_AttackerFormChange:: pause 5 copybyte gBattlerAbility, gBattlerAttacker diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 319437c12f..3f99a90893 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -411,6 +411,7 @@ extern const u8 BattleScript_ElectricTerrainPrevents[]; extern const u8 BattleScript_DarkTypePreventsPrankster[]; extern const u8 BattleScript_GulpMissileGorging[]; extern const u8 BattleScript_GulpMissileGulping[]; +extern const u8 BattleScript_GulpMissileFormChange[]; extern const u8 BattleScript_BattleBondActivatesOnMoveEndAttacker[]; extern const u8 BattleScript_DesolateLandActivates[]; extern const u8 BattleScript_PrimordialSeaActivates[]; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2bc25cd786..1fb7947f57 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -16824,3 +16824,16 @@ void BS_TryTidyUp(void) gBattlescriptCurrInstr = cmd->nextInstr; } } + +void BS_TryGulpMissile(void) +{ + NATIVE_ARGS(); + + if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT) + && (gCurrentMove == MOVE_DIVE) + && (GetBattlerAbility(gBattlerAttacker) == ABILITY_GULP_MISSILE) + && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) + gBattlescriptCurrInstr = BattleScript_GulpMissileFormChange; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index 2eb8f97f62..3f106b553f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5716,7 +5716,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_GULP_MISSILE: - if (((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) + if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT) + && ((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) { BattleScriptPushCursor(); diff --git a/test/battle/ability/gulp_missile.c b/test/battle/ability/gulp_missile.c new file mode 100644 index 0000000000..680208506d --- /dev/null +++ b/test/battle/ability/gulp_missile.c @@ -0,0 +1,137 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + // ASSUME(gMovesInfo[MOVE_AERIAL_ACE].category == DAMAGE_CATEGORY_PHYSICAL); +} + +SINGLE_BATTLE_TEST("(Gulp Missile) If base Cramorant hits target with Surf it transforms into Gulping form if max HP is over 1/2") +{ + GIVEN { + PLAYER(SPECIES_CRAMORANT) { Ability(ABILITY_GULP_MISSILE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SURF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player); + HP_BAR(opponent); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + } THEN { + EXPECT_EQ(player->species, SPECIES_CRAMORANT_GULPING); + } +} + +SINGLE_BATTLE_TEST("(Gulp Missile) If base Cramorant hits target with Surf it transforms into Gorging form if max HP is under 1/2") +{ + GIVEN { + PLAYER(SPECIES_CRAMORANT) { HP(120); MaxHP(250); Ability(ABILITY_GULP_MISSILE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SURF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player); + HP_BAR(opponent); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + } THEN { + EXPECT_EQ(player->species, SPECIES_CRAMORANT_GORGING); + } +} + +SINGLE_BATTLE_TEST("(Gulp Missile) If base Cramorant is under water it transforms into one of its forms") +{ + GIVEN { + PLAYER(SPECIES_CRAMORANT) { Ability(ABILITY_GULP_MISSILE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DIVE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DIVE, player); + NOT HP_BAR(opponent); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + } THEN { + EXPECT_EQ(player->species, SPECIES_CRAMORANT_GULPING); + } +} + +SINGLE_BATTLE_TEST("(Gulp Missile) Power Herb does not prevent Cramaront from transforming") +{ + GIVEN { + PLAYER(SPECIES_CRAMORANT) { Ability(ABILITY_GULP_MISSILE); Item(ITEM_POWER_HERB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DIVE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DIVE, player); + MESSAGE("Cramorant became fully charged due to its Power Herb!"); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + HP_BAR(opponent); + } THEN { + EXPECT_EQ(player->species, SPECIES_CRAMORANT_GULPING); + } +} + +SINGLE_BATTLE_TEST("(Gulp Missile) Transformed Cramorant deal 1/4 of damage opposing mon if hit by a damaging move, Gulping also lowers defense") +{ + s16 gulpMissileDamage; + + GIVEN { + PLAYER(SPECIES_CRAMORANT) { Ability(ABILITY_GULP_MISSILE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SURF); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player); + HP_BAR(opponent); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + HP_BAR(opponent, captureDamage: &gulpMissileDamage); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Defense fell!"); + } THEN { + EXPECT_EQ(gulpMissileDamage, opponent->maxHP / 4); + } +} + +SINGLE_BATTLE_TEST("(Gulp Missile) Cramorant in Gorging paralyzes the target if hit by a damaging move") +{ + GIVEN { + PLAYER(SPECIES_CRAMORANT) { HP(120); MaxHP(250); Ability(ABILITY_GULP_MISSILE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SURF); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player); + HP_BAR(opponent); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent); + STATUS_ICON(opponent, paralysis: TRUE); + } +} + +SINGLE_BATTLE_TEST("(Gulp Missile) triggers even if the user is fainted by opposing mon") +{ + // See: https://github.com/rh-hideout/pokeemerald-expansion/issues/4143 + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_CRAMORANT) { HP(1); MaxHP(250); Ability(ABILITY_GULP_MISSILE); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SURF); MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player); + HP_BAR(opponent); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + HP_BAR(player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent); + STATUS_ICON(opponent, paralysis: TRUE); + } +}