finished G-Max Move tests

This commit is contained in:
AgustinGDLV 2023-03-22 22:31:08 -07:00
parent 019b39c7ad
commit 038649594a
5 changed files with 287 additions and 25 deletions

View file

@ -10475,8 +10475,6 @@ BattleScript_DamageNonTypesStarts::
goto BattleScript_MoveEnd
BattleScript_DamageNonTypesContinues::
@printfromtable gDamageNonTypesStartStringIds
@waitmessage B_WAIT_TIME_LONG
setbyte gBattleCommunication, 0
BattleScript_DamageNonTypesLoop::
copyarraywithindex gBattlerAttacker, gBattlerByTurnOrder, gBattleCommunication, 1
@ -10486,8 +10484,6 @@ BattleScript_DamageNonTypesLoop::
waitmessage B_WAIT_TIME_LONG
effectivenesssound
hitanimation BS_ATTACKER
goto BattleScript_DamageNonTypesHpChange
BattleScript_DamageNonTypesHpChange:
orword gHitMarker, HITMARKER_SKIP_DMG_TRACK | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
@ -10499,7 +10495,7 @@ BattleScript_DamageNonTypesLoopIncrement::
jumpifbytenotequal gBattleCommunication, gBattlersCount, BattleScript_DamageNonTypesLoop
BattleScript_DamageNonTypesContinuesEnd::
bicword gHitMarker, HITMARKER_SKIP_DMG_TRACK | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE
end2
end
BattleScript_EffectTryReducePP::
tryspiteppreduce BattleScript_MoveEnd
@ -10570,8 +10566,10 @@ BattleScript_RaiseCritAlliesLoop:
setstatchanger STAT_ATK, 0, FALSE @ for animation
setgraphicalstatchangevalues
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
swapattackerwithtarget
printstring STRINGID_PKMNGETTINGPUMPED
waitmessage B_WAIT_TIME_LONG
swapattackerwithtarget
BattleScript_RaiseCritAlliesIncrement:
setbyte sSTAT_ANIM_PLAYED, FALSE
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_RaiseCritAlliesEnd
@ -10607,7 +10605,7 @@ BattleScript_CureStatusAlliesLoop:
jumpifabsent BS_TARGET, BattleScript_CureStatusAlliesIncrement
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_CureStatusActivate
BattleScript_CureStatusAlliesIncrement:
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_CureStatusAlliesLoop
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_CureStatusAlliesEnd
setallytonexttarget BattleScript_CureStatusAlliesLoop
BattleScript_CureStatusAlliesEnd:
restoretarget
@ -10616,19 +10614,22 @@ BattleScript_CureStatusAlliesEnd:
BattleScript_CureStatusActivate:
curestatus BS_TARGET
updatestatusicon BS_TARGET
swapattackerwithtarget
printstring STRINGID_PKMNSTATUSNORMAL
waitmessage B_WAIT_TIME_LONG
swapattackerwithtarget
goto BattleScript_CureStatusAlliesIncrement
BattleScript_EffectRecycleBerriesAllies::
jumpifteamhealthy BS_ATTACKER, BattleScript_MoveEnd
savetarget
copybyte gBattlerTarget, gBattlerAttacker
BattleScript_RecycleBerriesAlliesLoop:
jumpifabsent BS_TARGET, BattleScript_RecycleBerriesAlliesIncrement
tryrecycleberry BattleScript_RecycleBerriesAlliesIncrement
swapattackerwithtarget
printstring STRINGID_XFOUNDONEY
waitmessage B_WAIT_TIME_LONG
swapattackerwithtarget
BattleScript_RecycleBerriesAlliesIncrement:
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_RecycleBerriesAlliesEnd
setallytonexttarget BattleScript_RecycleBerriesAlliesLoop

View file

@ -125,8 +125,8 @@ void ApplyDynamaxHPMultiplier(u16 battlerId, struct Pokemon* mon)
else
{
u16 mult = UQ_4_12(1.5); // placeholder
u16 hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP, NULL) * mult) + UQ_4_12_ROUND);
u16 maxHP = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_MAX_HP, NULL) * mult) + UQ_4_12_ROUND);
u16 hp = UQ_4_12_TO_INT((gBattleMons[battlerId].hp * mult) + UQ_4_12_ROUND);
u16 maxHP = UQ_4_12_TO_INT((gBattleMons[battlerId].maxHP * mult) + UQ_4_12_ROUND);
SetMonData(mon, MON_DATA_HP, &hp);
SetMonData(mon, MON_DATA_MAX_HP, &maxHP);
}
@ -521,7 +521,7 @@ u16 SetMaxMoveEffect(u16 move)
if (!(gSideStatuses[side] & SIDE_STATUS_DAMAGE_NON_TYPES))
{
gSideStatuses[side] |= SIDE_STATUS_DAMAGE_NON_TYPES;
gSideTimers[side].damageNonTypesTimer = 4;
gSideTimers[side].damageNonTypesTimer = 5; // damage is dealt for 4 turns, ends on 5th
gSideTimers[side].damageNonTypesType = gBattleMoves[gCurrentMove].type;
BattleScriptPush(gBattlescriptCurrInstr + 1);
ChooseDamageNonTypesString(gBattleMoves[gCurrentMove].type);
@ -604,7 +604,8 @@ u16 SetMaxMoveEffect(u16 move)
else
gDisableStructs[battler].wrapTurns = (Random() % 4) + 2;
#endif
gBattleStruct->wrappedBy[battler] = gBattlerAttacker;
// The Wrap effect does not expire when the user switches, so here's some cheese.
gBattleStruct->wrappedBy[battler] = gBattlerTarget;
if (maxEffect == MAX_EFFECT_SANDBLAST_FOES)
gBattleStruct->wrappedMove[battler] = MOVE_SAND_TOMB;
else
@ -615,7 +616,8 @@ u16 SetMaxMoveEffect(u16 move)
}
case MAX_EFFECT_YAWN_FOE:
if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN)
&& CanSleep(gBattlerTarget))
&& CanSleep(gBattlerTarget)
&& Random() % 2) // 50% chance of success
{
gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2);
BattleScriptPush(gBattlescriptCurrInstr + 1);
@ -676,9 +678,12 @@ u16 SetMaxMoveEffect(u16 move)
effect++;
break;
case MAX_EFFECT_RECYCLE_BERRIES:
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectRecycleBerriesAllies;
effect++;
if (Random() % 2) // 50% chance of success
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectRecycleBerriesAllies;
effect++;
}
break;
}

View file

@ -11311,15 +11311,14 @@ static void Cmd_various(void)
u16* usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)];
if (gBattleMons[gBattlerTarget].item == ITEM_NONE
&& gBattleStruct->changedItems[gBattlerTarget] == ITEM_NONE // Will not inherit an item
&& ItemId_GetPocket(*usedHeldItem) == POCKET_BERRIES
&& Random() % 2 == 0)
&& ItemId_GetPocket(*usedHeldItem) == POCKET_BERRIES)
{
gLastUsedItem = *usedHeldItem;
*usedHeldItem = ITEM_NONE;
gBattleMons[gActiveBattler].item = gLastUsedItem;
gBattleMons[gBattlerTarget].item = gLastUsedItem;
BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item);
MarkBattlerForControllerExec(gActiveBattler);
MarkBattlerForControllerExec(gBattlerTarget);
gBattlescriptCurrInstr = cmd->nextInstr;
}

View file

@ -1829,7 +1829,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if !gBattleStruct->dynamax.playerSelect && gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && IsGravityPreventingMove(move))
if (!gBattleStruct->dynamax.playerSelect && gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && IsGravityPreventingMove(move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -2481,8 +2481,8 @@ u8 DoFieldEndTurnEffects(void)
{
if (--gSideTimers[side].damageNonTypesTimer == 0)
{
// There is no in-game message when this side status ends.
gSideStatuses[side] &= ~SIDE_STATUS_DAMAGE_NON_TYPES;
//gBattlescriptCurrInstr = BattleScript_DamageNonTypesEnds; TODO: no end message in-game?
effect++;
}
else

View file

@ -7,15 +7,12 @@
// TEST: Imprison doesn't stop Max Moves. (YES!)
// TEST: Max Moves change type as you'd expect with Normalize, Weather Ball, etc. (YES!)
// TEST: You use Struggle while Dynamaxed if out of PP. (YES!)
// TEST: G-Max Befuddle applies statuses before considering immunities. (YES!)
// Refactor code to remove dynamax.usingMaxMove? Might keep for Raids
// Ditto cannot turn into a Gigantamax form. (NO)
// Interactions with a Dynamaxed Pokemon with Magic Bounce. (???)
// Dynamax should not reset Speed Swap, Soak, or anything else from form changing. (NO)
// Multi Attack is treated in Max Move power calcs like a Fighting or Poison type move. (NO)
// Max Moves cannot be used against allies. (NO)
// G-Max Replenish guarantees either both allies' berries or neither's. (NO)
// G-Max Sandwhatever still keeps Sand Tomb up when Sandaconda switches.
// ============= DYNAMAX AND MAX MOVE INTERACTIONS ===================
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax increases HP and max HP by 1.5x")
@ -378,7 +375,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon take double damage from Dynamax
SINGLE_BATTLE_TEST("(DYNAMAX) Max Moves deal 1/4 damage through protect", s16 damage)
{
bool32 protected;
KNOWN_FAILING; // rounding error? also messages are wonky
KNOWN_FAILING; // // damage isn't equal because RNG misbehaves
PARAMETRIZE { protected = FALSE; }
PARAMETRIZE { protected = TRUE; }
GIVEN {
@ -641,6 +638,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers single opponent's speed")
}
}
// This test should apply to all stat-lowering Max Moves, including G-Max Foam Burst and G-Max Tartness.
DOUBLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers both opponents' speed")
{
GIVEN {
@ -677,6 +675,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers both opponents' speed")
}
}
// This test should apply to all stat-boosting Max Moves, too.
DOUBLE_BATTLE_TEST("(DYNAMAX) Max Knuckle raises both allies' attack")
{
s16 damage[4];
@ -1136,3 +1135,261 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Meltdown torments both opponents for 3 turns
MESSAGE("Foe Wynaut is tormented no more!");
}
}
// This test applies to G-Max Cannonade, G-Max Vine Lash, and G-Max Volcalith, too.
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Wildfire sets a field effect that damages non-Fire types")
{
s16 damage;
GIVEN {
ASSUME(gBattleMoves[MOVE_G_MAX_WILDFIRE].argument == MAX_EFFECT_WILDFIRE);
PLAYER(SPECIES_CHARIZARD);
PLAYER(SPECIES_CHARMANDER);
OPPONENT(SPECIES_WOBBUFFET) { HP(600); MaxHP(600); }
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_ARCANINE);
} WHEN {
TURN { MOVE(playerLeft, MOVE_EMBER, target: opponentLeft, dynamax: TRUE); }
TURN { }
TURN { SWITCH(opponentLeft, 2); }
TURN { }
TURN { }
} SCENE {
// turn 1
MESSAGE("Charizard used G-Max Wildfire!");
MESSAGE("The opposing team was surrounded by flames!");
MESSAGE("Foe Wobbuffet is burning up within G-Max Wildfire's flames!");
HP_BAR(opponentLeft, captureDamage: &damage);
MESSAGE("Foe Wynaut is burning up within G-Max Wildfire's flames!");
HP_BAR(opponentRight);
// turn 2
MESSAGE("Foe Wobbuffet is burning up within G-Max Wildfire's flames!");
HP_BAR(opponentLeft);
MESSAGE("Foe Wynaut is burning up within G-Max Wildfire's flames!");
HP_BAR(opponentRight);
// turn 3
NONE_OF { MESSAGE("Foe Arcanine is burning up within G-Max Wildfire's flames!"); }
MESSAGE("Foe Wynaut is burning up within G-Max Wildfire's flames!");
HP_BAR(opponentRight);
// turn 4
MESSAGE("Foe Wynaut is burning up within G-Max Wildfire's flames!");
HP_BAR(opponentRight);
// turn 5
NONE_OF {
HP_BAR(opponentRight);
MESSAGE("Foe Wynaut is burning up within G-Max Wildfire's flames!");
}
} FINALLY {
EXPECT_EQ(damage, 100);
}
}
// This should probably be tested to only occur 50% of the time.
// I had some problems specific to Teatime with this where Snorlax stored
// the used berry in usedHeldItem, while Munchlax stored it in changedItem.
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Replenish recycles allies' berries")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_G_MAX_REPLENISH].argument == MAX_EFFECT_RECYCLE_BERRIES);
PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); }
PLAYER(SPECIES_MUNCHLAX) { Item(ITEM_APICOT_BERRY); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_STUFF_CHEEKS); \
MOVE(playerRight, MOVE_STUFF_CHEEKS); \
MOVE(opponentLeft, MOVE_STUFF_CHEEKS); \
MOVE(opponentRight, MOVE_STUFF_CHEEKS); }
TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft, dynamax: TRUE); }
} SCENE {
// turn 1
MESSAGE("Using Apicot Berry, the sp. defense of Snorlax rose!");
MESSAGE("Using Apicot Berry, the sp. defense of Munchlax rose!");
MESSAGE("Using Apicot Berry, the sp. defense of Foe Wobbuffet rose!");
MESSAGE("Using Apicot Berry, the sp. defense of Foe Wobbuffet rose!");
// turn 2
MESSAGE("Snorlax used G-Max Replenish!");
MESSAGE("Snorlax found one Apicot Berry!");
MESSAGE("Munchlax found one Apicot Berry!");
}
}
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Snooze makes only the target drowsy")
{
GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_SNOOZE].argument == MAX_EFFECT_YAWN_FOE);
PLAYER(SPECIES_GRIMMSNARL);
PLAYER(SPECIES_IMPIDIMP);
OPPONENT(SPECIES_BLISSEY);
OPPONENT(SPECIES_CHANSEY);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DARK_PULSE, target: opponentLeft, dynamax: TRUE); }
TURN { }
} SCENE {
// turn 1
MESSAGE("Grimmsnarl used G-Max Snooze!");
MESSAGE("Grimmsnarl made Foe Blissey drowsy!");
NONE_OF { MESSAGE("Grimmsnarl made Foe Chansey drowsy!"); }
// turn 2
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft);
MESSAGE("Foe Blissey fell asleep!");
STATUS_ICON(opponentLeft, sleep: TRUE);
NONE_OF {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight);
STATUS_ICON(opponentRight, sleep: TRUE);
}
}
}
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Finale heals allies by 1/6 of their health")
{
s16 damage1, damage2;
GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_FINALE].argument == MAX_EFFECT_HEAL_TEAM);
PLAYER(SPECIES_ALCREMIE) { HP(200); MaxHP(300); }
PLAYER(SPECIES_MILCERY) { HP(200); MaxHP(300); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MOONBLAST, target: opponentLeft, dynamax: TRUE); }
} SCENE {
// turn 1
MESSAGE("Alcremie used G-Max Finale!");
HP_BAR(playerLeft, captureDamage: &damage1);
HP_BAR(playerRight, captureDamage: &damage2);
} FINALLY {
EXPECT_EQ(damage1, -75); // heals based on Dynamax HP
EXPECT_EQ(damage2, -50);
}
}
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions")
{
s16 damage1, damage2;
GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_SWEETNESS].argument == MAX_EFFECT_AROMATHERAPY);
PLAYER(SPECIES_APPLETUN) { Status1(STATUS1_POISON); }
PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_VINE_WHIP, target: opponentLeft, dynamax: TRUE); }
} SCENE {
MESSAGE("Appletun used G-Max Sweetness!");
STATUS_ICON(playerLeft, none: TRUE);
MESSAGE("Appletun's status returned to normal!");
STATUS_ICON(playerRight, none: TRUE);
MESSAGE("Applin's status returned to normal!");
}
}
// This test should apply to G-Max Sandblast, too.
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Centiferno traps both opponents in Fire Spin")
{
s16 damage1, damage2;
GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_CENTIFERNO].argument == MAX_EFFECT_FIRE_SPIN_FOES);
PLAYER(SPECIES_CENTISKORCH);
PLAYER(SPECIES_SIZZLIPEDE);
PLAYER(SPECIES_SIZZLIPEDE);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FLAME_CHARGE, target: opponentLeft, dynamax: TRUE); }
TURN { SWITCH(playerLeft, 2); }
} SCENE {
// turn 1
MESSAGE("Centiskorc used G-Max Centiferno!");
MESSAGE("Foe Wobbuffet is hurt by Fire Spin!");
HP_BAR(opponentLeft);
MESSAGE("Foe Wynaut is hurt by Fire Spin!");
HP_BAR(opponentRight);
// turn 2 - Fire Spin continues even after Centiskorch switches out
MESSAGE("Foe Wobbuffet is hurt by Fire Spin!");
HP_BAR(opponentLeft);
MESSAGE("Foe Wynaut is hurt by Fire Spin!");
HP_BAR(opponentRight);
}
}
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Chi Strike boosts allies' crit chance")
{
s16 damage1, damage2;
GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_6);
ASSUME(gBattleMoves[MOVE_G_MAX_CHI_STRIKE].argument == MAX_EFFECT_CRIT_PLUS);
PLAYER(SPECIES_MACHAMP);
PLAYER(SPECIES_MACHOP);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FORCE_PALM, target: opponentLeft, dynamax: TRUE); \
MOVE(playerRight, MOVE_FOCUS_ENERGY); }
TURN { MOVE(playerRight, MOVE_FORCE_PALM, target: opponentLeft); }
} SCENE {
// turn 1
MESSAGE("Machamp used G-Max Chi Strike!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Machamp is getting pumped!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
MESSAGE("Machop is getting pumped!");
MESSAGE("Machop used Focus Energy!");
MESSAGE("Machop is getting pumped!");
// turn 2
MESSAGE("Machop used Force Palm!"); // Machop is at +3 crit stages, 100% crit chance
MESSAGE("A critical hit!");
}
}
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Depletion takes away 2 PP from the target's last move")
{
GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_DEPLETION].argument == MAX_EFFECT_SPITE);
PLAYER(SPECIES_DURALUDON);
PLAYER(SPECIES_WYNAUT);
// Dynamax behaves weird with test turn order because stats are recalculated.
OPPONENT(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); }
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CLAW, target: opponentLeft, dynamax: TRUE); }
} SCENE {
MESSAGE("Foe Sableye used Celebrate!");
MESSAGE("Duraludon used G-Max Depletion!");
MESSAGE("Reduced Foe Sableye's Celebrate by 2!");
}
}
// This test should apply to G-Max Rapid Flow, too.
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max One Blow bypasses Max Guard for full damage", s16 damage)
{
bool32 protect;
KNOWN_FAILING; // damage isn't equal because RNG misbehaves
PARAMETRIZE { protect = TRUE; }
PARAMETRIZE { protect = FALSE; }
GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_ONE_BLOW].argument == MAX_EFFECT_BYPASS_PROTECT);
PLAYER(SPECIES_URSHIFU);
PLAYER(SPECIES_KUBFU);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
if (protect)
TURN { MOVE(playerLeft, MOVE_WICKED_BLOW, target: opponentLeft, dynamax: TRUE); \
MOVE(opponentLeft, MOVE_PROTECT, dynamax: TRUE); }
else
TURN { MOVE(playerLeft, MOVE_WICKED_BLOW, target: opponentLeft, dynamax: TRUE); \
MOVE(opponentLeft, MOVE_PSYCHIC, target: playerLeft, dynamax: TRUE); }
} SCENE {
if (protect)
MESSAGE("Foe Wobbuffet used Max Guard!");
MESSAGE("Urshifu used G-Max One Blow!");
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_EQ(results[0].damage, results[1].damage);
}
}