From d3fe5c4640ebc14275d85d8a5d3bdaaf7ae8a441 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 23 Apr 2025 12:18:57 +0200 Subject: [PATCH] Some Me First tests plus minor clean up (#6678) --- include/constants/battle.h | 8 +-- src/battle_script_commands.c | 2 - src/battle_util.c | 6 +-- test/battle/move_effect/me_first.c | 80 ++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 test/battle/move_effect/me_first.c diff --git a/include/constants/battle.h b/include/constants/battle.h index 305315d919..8f019db3ef 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -172,10 +172,10 @@ #define STATUS3_GASTRO_ACID (1 << 16) #define STATUS3_EMBARGO (1 << 17) #define STATUS3_UNDERWATER (1 << 18) -#define STATUS3_INTIMIDATE_POKES (1 << 19) -#define STATUS3_TRACE (1 << 20) +#define STATUS3_UNUSED_19 (1 << 19) +#define STATUS3_UNUSED_20 (1 << 20) #define STATUS3_SMACKED_DOWN (1 << 21) -#define STATUS3_ME_FIRST (1 << 22) +#define STATUS3_UNUSED_22 (1 << 22) #define STATUS3_TELEKINESIS (1 << 23) #define STATUS3_PHANTOM_FORCE (1 << 24) #define STATUS3_MIRACLE_EYED (1 << 25) @@ -218,7 +218,7 @@ #define HITMARKER_ALLOW_NO_PP (1 << 23) #define HITMARKER_GRUDGE (1 << 24) #define HITMARKER_OBEYS (1 << 25) -#define HITMARKER_NEVER_SET (1 << 26) // Cleared as part of a large group. Never set or checked +#define HITMARKER_UNUSED_5 (1 << 26) #define HITMARKER_CHARGING (1 << 27) #define HITMARKER_FAINTED(battler) (1u << (battler + 28)) #define HITMARKER_FAINTED2(battler) HITMARKER_FAINTED(battler) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3cdcc305c7..e56d0c4761 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7616,7 +7616,6 @@ static void Cmd_moveend(void) } gProtectStructs[gBattlerAttacker].shellTrap = FALSE; gBattleStruct->ateBoost[gBattlerAttacker] = FALSE; - gStatuses3[gBattlerAttacker] &= ~STATUS3_ME_FIRST; gSpecialStatuses[gBattlerAttacker].gemBoost = FALSE; gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage = 0; gSpecialStatuses[gBattlerTarget].berryReduced = FALSE; @@ -11012,7 +11011,6 @@ static void Cmd_various(void) } gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gStatuses3[gBattlerAttacker] |= STATUS3_ME_FIRST; gBattlescriptCurrInstr = cmd->nextInstr; } return; diff --git a/src/battle_util.c b/src/battle_util.c index 0206122aec..5cf65a8007 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -832,7 +832,7 @@ void HandleAction_NothingIsFainted(void) gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_PASSIVE_DAMAGE | HITMARKER_OBEYS | HITMARKER_SYNCHRONISE_EFFECT - | HITMARKER_CHARGING | HITMARKER_NEVER_SET); + | HITMARKER_CHARGING); } void HandleAction_ActionFinished(void) @@ -846,7 +846,7 @@ void HandleAction_ActionFinished(void) gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_PASSIVE_DAMAGE | HITMARKER_OBEYS | HITMARKER_SYNCHRONISE_EFFECT - | HITMARKER_CHARGING | HITMARKER_NEVER_SET | HITMARKER_IGNORE_DISGUISE); + | HITMARKER_CHARGING | HITMARKER_IGNORE_DISGUISE); // check if Stellar type boost should be used up moveType = GetBattleMoveType(gCurrentMove); @@ -8153,7 +8153,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12(gSpecialStatuses[battlerAtk].gemParam))); if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP && moveType == TYPE_ELECTRIC) modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); - if (gStatuses3[battlerAtk] & STATUS3_ME_FIRST) + if (GetMoveEffect(gChosenMove) == EFFECT_ME_FIRST) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN) && moveType == TYPE_GRASS) modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); diff --git a/test/battle/move_effect/me_first.c b/test/battle/move_effect/me_first.c new file mode 100644 index 0000000000..f351c1a498 --- /dev/null +++ b/test/battle/move_effect/me_first.c @@ -0,0 +1,80 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Me First copies the move from the target and increases it's power by 1.5", s16 damage) +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_ME_FIRST; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Me First fails if target uses a status move") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ME_FIRST); MOVE(opponent, MOVE_GROWL); } + } SCENE { + MESSAGE("Wobbuffet used Me First!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Me First fails if target moves first") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(50); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); } + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_ME_FIRST); } + } SCENE { + MESSAGE("Wobbuffet used Me First!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Me First: If a Consecutively Executed Move is copied, the boost only applies to the first hit") +{ + s16 dmg[2]; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(100); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + } WHEN { + TURN { MOVE(player, MOVE_ME_FIRST); MOVE(opponent, MOVE_OUTRAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ME_FIRST, player); + HP_BAR(opponent, captureDamage: &dmg[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_OUTRAGE, player); + HP_BAR(opponent, captureDamage: &dmg[1]); + } THEN { + EXPECT_MUL_EQ(dmg[1], Q_4_12(1.5), dmg[0]); + } +} + +SINGLE_BATTLE_TEST("Me First can be selected if users holds Assault Vest") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(100); Item(ITEM_ASSAULT_VEST); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + } WHEN { + TURN { MOVE(player, MOVE_ME_FIRST); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ME_FIRST, player); + } +} + +// TO_DO_BATTLE_TEST: Not everything has been tested