updated tests

This commit is contained in:
AgustinGDLV 2023-05-11 22:13:43 -07:00
parent aec51b5b04
commit 3b6389ec21
7 changed files with 222 additions and 173 deletions

View file

@ -470,12 +470,6 @@ BattleScript_SpikesActivates::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
return return
BattleScript_SteelsurgeActivates::
setsteelsurge BattleScript_MoveEnd
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectAttackUpUserAlly: BattleScript_EffectAttackUpUserAlly:
jumpifnoally BS_ATTACKER, BattleScript_EffectAttackUp jumpifnoally BS_ATTACKER, BattleScript_EffectAttackUp
attackcanceler attackcanceler
@ -10507,8 +10501,8 @@ BattleScript_EffectMaxMove::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
resultmessage resultmessage
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET
setmaxmoveeffect setmaxmoveeffect
tryfaintmon BS_TARGET
moveendall moveendall
end end
@ -10529,7 +10523,7 @@ BattleScript_RaiseSideStatsIncrement:
setallytonexttarget BattleScript_RaiseSideStatsLoop setallytonexttarget BattleScript_RaiseSideStatsLoop
BattleScript_RaiseSideStatsEnd: BattleScript_RaiseSideStatsEnd:
restoretarget restoretarget
return goto BattleScript_MoveEnd
BattleScript_EffectLowerStatFoes:: BattleScript_EffectLowerStatFoes::
savetarget savetarget
@ -10548,26 +10542,26 @@ BattleScript_LowerSideStatsIncrement:
setallytonexttarget BattleScript_LowerSideStatsLoop setallytonexttarget BattleScript_LowerSideStatsLoop
BattleScript_LowerSideStatsEnd: BattleScript_LowerSideStatsEnd:
restoretarget restoretarget
return goto BattleScript_MoveEnd
BattleScript_EffectSetWeather:: BattleScript_EffectSetWeather::
playanimation 0, B_ANIM_MAX_SET_WEATHER playanimation 0, B_ANIM_MAX_SET_WEATHER
printfromtable gMoveWeatherChangeStringIds printfromtable gMoveWeatherChangeStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
return goto BattleScript_MoveEnd
BattleScript_EffectSetTerrain:: BattleScript_EffectSetTerrain::
printfromtable gTerrainStringIds printfromtable gTerrainStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
playanimation BS_ATTACKER, B_ANIM_RESTORE_BG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG
call BattleScript_ActivateTerrainEffects call BattleScript_ActivateTerrainEffects
return goto BattleScript_MoveEnd
BattleScript_DamageNonTypesStarts:: BattleScript_DamageNonTypesStarts::
printfromtable gDamageNonTypesStartStringIds printfromtable gDamageNonTypesStartStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
return goto BattleScript_MoveEnd
BattleScript_DamageNonTypesContinues:: BattleScript_DamageNonTypesContinues::
setbyte gBattleCommunication, 0 setbyte gBattleCommunication, 0
@ -10596,7 +10590,7 @@ BattleScript_EffectTryReducePP::
tryspiteppreduce BattleScript_MoveEnd tryspiteppreduce BattleScript_MoveEnd
printstring STRINGID_PKMNREDUCEDPP printstring STRINGID_PKMNREDUCEDPP
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
return goto BattleScript_MoveEnd
BattleScript_EffectStatus1Foes:: BattleScript_EffectStatus1Foes::
savetarget savetarget
@ -10615,7 +10609,7 @@ BattleScript_Status1FoesIncrement:
setallytonexttarget BattleScript_Status1FoesLoop setallytonexttarget BattleScript_Status1FoesLoop
BattleScript_Status1FoesEnd: BattleScript_Status1FoesEnd:
restoretarget restoretarget
return goto BattleScript_MoveEnd
BattleScript_EffectStatus2Foes:: BattleScript_EffectStatus2Foes::
savetarget savetarget
@ -10634,7 +10628,7 @@ BattleScript_Status2FoesIncrement:
BattleScript_Status2FoesEnd: BattleScript_Status2FoesEnd:
restoretarget restoretarget
jumpifbyte CMP_EQUAL, gBattleCommunication + 1, 1, BattleScript_PrintCoinsScattered @ Gold Rush jumpifbyte CMP_EQUAL, gBattleCommunication + 1, 1, BattleScript_PrintCoinsScattered @ Gold Rush
return goto BattleScript_MoveEnd
BattleScript_DoConfuseAnim: BattleScript_DoConfuseAnim:
status2animation BS_EFFECT_BATTLER, STATUS2_CONFUSION status2animation BS_EFFECT_BATTLER, STATUS2_CONFUSION
@ -10671,7 +10665,7 @@ BattleScript_RaiseCritAlliesIncrement:
setallytonexttarget BattleScript_RaiseCritAlliesLoop setallytonexttarget BattleScript_RaiseCritAlliesLoop
BattleScript_RaiseCritAlliesEnd: BattleScript_RaiseCritAlliesEnd:
restoretarget restoretarget
return goto BattleScript_MoveEnd
BattleScript_EffectHealOneSixthAllies:: BattleScript_EffectHealOneSixthAllies::
jumpifteamhealthy BS_ATTACKER, BattleScript_MoveEnd jumpifteamhealthy BS_ATTACKER, BattleScript_MoveEnd
@ -10690,7 +10684,7 @@ BattleScript_HealOneSixthAlliesIncrement:
setallytonexttarget BattleScript_HealOneSixthAlliesLoop setallytonexttarget BattleScript_HealOneSixthAlliesLoop
BattleScript_HealOneSixthAlliesEnd: BattleScript_HealOneSixthAlliesEnd:
restoretarget restoretarget
return goto BattleScript_MoveEnd
BattleScript_EffectCureStatusAllies:: BattleScript_EffectCureStatusAllies::
jumpifteamhealthy BS_ATTACKER, BattleScript_MoveEnd jumpifteamhealthy BS_ATTACKER, BattleScript_MoveEnd
@ -10704,7 +10698,7 @@ BattleScript_CureStatusAlliesIncrement:
setallytonexttarget BattleScript_CureStatusAlliesLoop setallytonexttarget BattleScript_CureStatusAlliesLoop
BattleScript_CureStatusAlliesEnd: BattleScript_CureStatusAlliesEnd:
restoretarget restoretarget
return goto BattleScript_MoveEnd
BattleScript_CureStatusActivate: BattleScript_CureStatusActivate:
curestatus BS_TARGET curestatus BS_TARGET
@ -10730,7 +10724,19 @@ BattleScript_RecycleBerriesAlliesIncrement:
setallytonexttarget BattleScript_RecycleBerriesAlliesLoop setallytonexttarget BattleScript_RecycleBerriesAlliesLoop
BattleScript_RecycleBerriesAlliesEnd: BattleScript_RecycleBerriesAlliesEnd:
restoretarget restoretarget
return goto BattleScript_MoveEnd
BattleScript_EffectStonesurge::
setstealthrock BattleScript_MoveEnd
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectSteelsurge::
setsteelsurge BattleScript_MoveEnd
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
@@@ END MAX MOVES @@@ @@@ END MAX MOVES @@@

View file

@ -485,7 +485,8 @@ extern const u8 BattleScript_EffectRaiseStatAllies[];
extern const u8 BattleScript_EffectLowerStatFoes[]; extern const u8 BattleScript_EffectLowerStatFoes[];
extern const u8 BattleScript_EffectSetWeather[]; extern const u8 BattleScript_EffectSetWeather[];
extern const u8 BattleScript_EffectSetTerrain[]; extern const u8 BattleScript_EffectSetTerrain[];
extern const u8 BattleScript_SteelsurgeActivates[]; extern const u8 BattleScript_EffectStonesurge[];
extern const u8 BattleScript_EffectSteelsurge[];
extern const u8 BattleScript_SteelsurgeFree[]; extern const u8 BattleScript_SteelsurgeFree[];
extern const u8 BattleScript_SteelsurgeDefog[]; extern const u8 BattleScript_SteelsurgeDefog[];
extern const u8 BattleScript_DamageNonTypesStarts[]; extern const u8 BattleScript_DamageNonTypesStarts[];

View file

@ -6,7 +6,7 @@
// still has them in the ROM. This is because the developers forgot // still has them in the ROM. This is because the developers forgot
// to define NDEBUG before release, however this has been changed as // to define NDEBUG before release, however this has been changed as
// Ruby's actual debug build does not use the AGBPrint features. // Ruby's actual debug build does not use the AGBPrint features.
// #define NDEBUG #define NDEBUG
// To enable printf debugging, comment out "#define NDEBUG". This allows // To enable printf debugging, comment out "#define NDEBUG". This allows
// the various AGBPrint functions to be used. (See include/gba/isagbprint.h). // the various AGBPrint functions to be used. (See include/gba/isagbprint.h).

View file

@ -67,6 +67,10 @@ enum RandomTag
RNG_STATIC, RNG_STATIC,
RNG_STENCH, RNG_STENCH,
RNG_TRI_ATTACK, RNG_TRI_ATTACK,
RNG_G_MAX_STUN_SHOCK,
RNG_G_MAX_BEFUDDLE,
RNG_G_MAX_REPLENISH,
RNG_G_MAX_SNOOZE,
}; };
#define RandomWeighted(tag, ...) \ #define RandomWeighted(tag, ...) \

View file

@ -525,19 +525,14 @@ u32 GetMaxMoveStatusEffect(u16 move)
case MAX_EFFECT_POISON_FOES: case MAX_EFFECT_POISON_FOES:
return STATUS1_POISON; return STATUS1_POISON;
case MAX_EFFECT_POISON_PARALYZE_FOES: case MAX_EFFECT_POISON_PARALYZE_FOES:
if (Random() % 2) {
return STATUS1_POISON; static const u8 sStunShockEffects[] = {STATUS1_PARALYSIS, STATUS1_POISON};
else return RandomElement(RNG_G_MAX_STUN_SHOCK, sStunShockEffects);
return STATUS1_PARALYSIS; }
case MAX_EFFECT_EFFECT_SPORE_FOES: case MAX_EFFECT_EFFECT_SPORE_FOES:
{ {
u8 effect = Random() % 3; static const u8 sBefuddleEffects[] = {STATUS1_PARALYSIS, STATUS1_POISON, STATUS1_SLEEP};
if (effect == 0) return RandomElement(RNG_G_MAX_BEFUDDLE, sBefuddleEffects);
return STATUS1_PARALYSIS;
else if (effect == 1)
return STATUS1_POISON;
else
return STATUS1_SLEEP;
} }
// Status 2 // Status 2
case MAX_EFFECT_CONFUSE_FOES: case MAX_EFFECT_CONFUSE_FOES:
@ -705,7 +700,7 @@ u16 SetMaxMoveEffect(u16 move)
{ {
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT;
BattleScriptPush(gBattlescriptCurrInstr + 1); BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StealthRockActivates; gBattlescriptCurrInstr = BattleScript_EffectStonesurge;
effect++; effect++;
} }
break; break;
@ -714,7 +709,7 @@ u16 SetMaxMoveEffect(u16 move)
{ {
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SHARPSTEELFLOATS; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SHARPSTEELFLOATS;
BattleScriptPush(gBattlescriptCurrInstr + 1); BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_SteelsurgeActivates; gBattlescriptCurrInstr = BattleScript_EffectSteelsurge;
effect++; effect++;
} }
break; break;
@ -787,9 +782,11 @@ u16 SetMaxMoveEffect(u16 move)
break; break;
} }
case MAX_EFFECT_YAWN_FOE: case MAX_EFFECT_YAWN_FOE:
{
static const u8 sSnoozeEffects[] = {TRUE, FALSE};
if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN) if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN)
&& CanSleep(gBattlerTarget) && CanSleep(gBattlerTarget)
&& Random() % 2) // 50% chance of success && RandomElement(RNG_G_MAX_SNOOZE, sSnoozeEffects)) // 50% chance of success
{ {
gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2);
BattleScriptPush(gBattlescriptCurrInstr + 1); BattleScriptPush(gBattlescriptCurrInstr + 1);
@ -797,6 +794,7 @@ u16 SetMaxMoveEffect(u16 move)
effect++; effect++;
} }
break; break;
}
case MAX_EFFECT_SPITE: case MAX_EFFECT_SPITE:
if (gLastMoves[gBattlerTarget] != MOVE_NONE if (gLastMoves[gBattlerTarget] != MOVE_NONE
&& gLastMoves[gBattlerTarget] != MOVE_UNAVAILABLE) && gLastMoves[gBattlerTarget] != MOVE_UNAVAILABLE)
@ -850,14 +848,16 @@ u16 SetMaxMoveEffect(u16 move)
effect++; effect++;
break; break;
case MAX_EFFECT_RECYCLE_BERRIES: case MAX_EFFECT_RECYCLE_BERRIES:
if (Random() % 2) // 50% chance of success {
static const u8 sReplenishEffects[] = {TRUE, FALSE};
if (RandomElement(RNG_G_MAX_REPLENISH, sReplenishEffects)) // 50% chance of success
{ {
BattleScriptPush(gBattlescriptCurrInstr + 1); BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectRecycleBerriesAllies; gBattlescriptCurrInstr = BattleScript_EffectRecycleBerriesAllies;
effect++; effect++;
} }
break; break;
}
} }
return effect; return effect;
} }

View file

@ -13495,7 +13495,7 @@ static void Cmd_painsplitdmgcalc(void)
if (!(DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))) if (!(DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)))
{ {
s32 hpDiff = (gBattleMons[gBattlerAttacker].hp + GetNonDynamaxHP(gBattlerTarget)) / 2; s32 hpDiff = (gBattleMons[gBattlerAttacker].hp + GetNonDynamaxHP(gBattlerTarget)) / 2;
s32 painSplitHp = gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - hpDiff; s32 painSplitHp = gBattleMoveDamage = GetNonDynamaxHP(gBattlerTarget) - hpDiff;
u8 *storeLoc = (void *)(&gBattleScripting.painSplitHp); u8 *storeLoc = (void *)(&gBattleScripting.painSplitHp);
storeLoc[0] = (painSplitHp); storeLoc[0] = (painSplitHp);

View file

@ -13,12 +13,10 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax increases HP and max HP by 1.5x", u16 hp)
} WHEN { } WHEN {
TURN { MOVE(player, MOVE_TACKLE, dynamax: dynamax); MOVE(opponent, MOVE_CELEBRATE); } TURN { MOVE(player, MOVE_TACKLE, dynamax: dynamax); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE { } SCENE {
if (dynamax) if (dynamax) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player);
MESSAGE("Wobbuffet used Max Strike!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player);
MESSAGE("Wobbuffet used Max Strike!"); MESSAGE("Wobbuffet used Max Strike!");
}
MESSAGE("Foe Wobbuffet used Celebrate!"); MESSAGE("Foe Wobbuffet used Celebrate!");
} THEN { } THEN {
results[i].hp = player->hp; results[i].hp = player->hp;
@ -520,91 +518,99 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon cannot use Max Guard while holdi
// Anything that is conditional based off max HP still uses gBattleMons[battler].maxHP. // Anything that is conditional based off max HP still uses gBattleMons[battler].maxHP.
// Below are some tests, but very far from all encompassing: // Below are some tests, but very far from all encompassing:
SINGLE_BATTLE_TEST("(DYNAMAX) Endeavor uses a Pokemon's non-Dynamax HP") SINGLE_BATTLE_TEST("(DYNAMAX) Endeavor uses a Pokemon's non-Dynamax HP", s16 damage)
{ {
s16 damage; bool32 dynamax;
PARAMETRIZE { dynamax = TRUE; }
PARAMETRIZE { dynamax = FALSE; }
GIVEN { GIVEN {
ASSUME(gBattleMoves[MOVE_ENDEAVOR].effect == EFFECT_ENDEAVOR); ASSUME(gBattleMoves[MOVE_ENDEAVOR].effect == EFFECT_ENDEAVOR);
PLAYER(SPECIES_WOBBUFFET) { MaxHP(100); Speed(50); } PLAYER(SPECIES_WOBBUFFET) { Speed(50); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); MaxHP(100); Speed(100); } OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(100); }
} WHEN { } WHEN {
TURN { MOVE(opponent, MOVE_ENDEAVOR); MOVE(player, MOVE_TACKLE, dynamax: TRUE); } TURN { MOVE(opponent, MOVE_ENDEAVOR); MOVE(player, MOVE_TACKLE, dynamax: dynamax); }
} SCENE { } SCENE {
MESSAGE("Foe Wobbuffet used Endeavor!"); MESSAGE("Foe Wobbuffet used Endeavor!");
HP_BAR(player, captureDamage: &damage); HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY { } FINALLY {
EXPECT_EQ(damage, 99); // difference between foe's HP and player's non-dynamax HP EXPECT_EQ(results[0].damage, results[1].damage);
} }
} }
SINGLE_BATTLE_TEST("(DYNAMAX) Super Fang uses a Pokemon's non-Dynamax HP") SINGLE_BATTLE_TEST("(DYNAMAX) Super Fang uses a Pokemon's non-Dynamax HP", s16 damage)
{ {
s16 damage; bool32 dynamax;
PARAMETRIZE { dynamax = TRUE; }
PARAMETRIZE { dynamax = FALSE; }
GIVEN { GIVEN {
ASSUME(gBattleMoves[MOVE_SUPER_FANG].effect == EFFECT_SUPER_FANG); ASSUME(gBattleMoves[MOVE_SUPER_FANG].effect == EFFECT_SUPER_FANG);
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); Speed(50); } PLAYER(SPECIES_WOBBUFFET) { Speed(50); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); } OPPONENT(SPECIES_WOBBUFFET) { Speed(100); }
} WHEN { } WHEN {
TURN { MOVE(opponent, MOVE_SUPER_FANG); MOVE(player, MOVE_TACKLE, dynamax: TRUE); } TURN { MOVE(opponent, MOVE_SUPER_FANG); MOVE(player, MOVE_TACKLE, dynamax: dynamax); }
} SCENE { } SCENE {
MESSAGE("Foe Wobbuffet used Super Fang!"); MESSAGE("Foe Wobbuffet used Super Fang!");
HP_BAR(player, captureDamage: &damage); HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY { } FINALLY {
EXPECT_EQ(damage, 25); EXPECT_EQ(results[0].damage, results[1].damage);
} }
} }
SINGLE_BATTLE_TEST("(DYNAMAX) Pain Split uses a Pokemon's non-Dynamax HP") SINGLE_BATTLE_TEST("(DYNAMAX) Pain Split uses a Pokemon's non-Dynamax HP", s16 damage)
{ {
s16 damage; bool32 dynamax;
PARAMETRIZE { dynamax = TRUE; }
PARAMETRIZE { dynamax = FALSE; }
GIVEN { GIVEN {
ASSUME(gBattleMoves[MOVE_PAIN_SPLIT].effect == EFFECT_PAIN_SPLIT); ASSUME(gBattleMoves[MOVE_PAIN_SPLIT].effect == EFFECT_PAIN_SPLIT);
PLAYER(SPECIES_WOBBUFFET) { HP(60); MaxHP(100); Speed(50); } PLAYER(SPECIES_WOBBUFFET) { Speed(50); }
OPPONENT(SPECIES_WOBBUFFET) { HP(40); MaxHP(100); Speed(100); } OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(100); }
} WHEN { } WHEN {
TURN { MOVE(opponent, MOVE_PAIN_SPLIT); MOVE(player, MOVE_TACKLE, dynamax: TRUE); } TURN { MOVE(opponent, MOVE_PAIN_SPLIT); MOVE(player, MOVE_TACKLE, dynamax: dynamax); }
} SCENE { } SCENE {
MESSAGE("Foe Wobbuffet used Pain Split!"); MESSAGE("Foe Wobbuffet used Pain Split!");
HP_BAR(player, captureDamage: &damage); HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY { } FINALLY {
EXPECT_EQ(damage, 10); EXPECT_EQ(results[0].damage, results[1].damage);
} }
} }
SINGLE_BATTLE_TEST("(DYNAMAX) Sitrus Berries heal based on a Pokemon's non-Dynamax HP") SINGLE_BATTLE_TEST("(DYNAMAX) Sitrus Berries heal based on a Pokemon's non-Dynamax HP", s16 damage)
{ {
s16 damage; bool32 dynamax;
PARAMETRIZE { dynamax = TRUE; }
PARAMETRIZE { dynamax = FALSE; }
GIVEN { GIVEN {
ASSUME(I_SITRUS_BERRY_HEAL >= GEN_4); ASSUME(I_SITRUS_BERRY_HEAL >= GEN_4);
ASSUME(gItems[ITEM_SITRUS_BERRY].holdEffect == HOLD_EFFECT_RESTORE_PCT_HP); ASSUME(gItems[ITEM_SITRUS_BERRY].holdEffect == HOLD_EFFECT_RESTORE_PCT_HP);
PLAYER(SPECIES_WOBBUFFET) { HP(60); MaxHP(100); Speed(50); Item(ITEM_SITRUS_BERRY); } PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(40); MaxHP(100); Speed(100); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); }
} WHEN { } WHEN {
TURN { MOVE(opponent, MOVE_PAIN_SPLIT); MOVE(player, MOVE_TACKLE, dynamax: TRUE); } TURN { MOVE(opponent, MOVE_FLING); MOVE(player, MOVE_TACKLE, dynamax: dynamax); }
} SCENE { } SCENE {
MESSAGE("Foe Wobbuffet used Pain Split!");
HP_BAR(player);
MESSAGE("Wobbuffet's Sitrus Berry restored health!"); MESSAGE("Wobbuffet's Sitrus Berry restored health!");
HP_BAR(player, captureDamage: &damage); HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY { } FINALLY {
EXPECT_EQ(damage, 25); EXPECT_EQ(results[0].damage, results[1].damage);
} }
} }
SINGLE_BATTLE_TEST("(DYNAMAX) Heal Pulse heals based on a Pokemon's non-Dynamax HP") SINGLE_BATTLE_TEST("(DYNAMAX) Heal Pulse heals based on a Pokemon's non-Dynamax HP", s16 damage)
{ {
s16 damage; bool32 dynamax;
PARAMETRIZE { dynamax = TRUE; }
PARAMETRIZE { dynamax = FALSE; }
GIVEN { GIVEN {
ASSUME(gBattleMoves[MOVE_HEAL_PULSE].effect == EFFECT_HEAL_PULSE); ASSUME(gBattleMoves[MOVE_HEAL_PULSE].effect == EFFECT_HEAL_PULSE);
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); Speed(50); } PLAYER(SPECIES_WOBBUFFET) { HP(1); Speed(50); }
OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); Speed(100); } OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); Speed(100); }
} WHEN { } WHEN {
TURN { MOVE(opponent, MOVE_HEAL_PULSE); MOVE(player, MOVE_TACKLE, dynamax: TRUE); } TURN { MOVE(opponent, MOVE_HEAL_PULSE); MOVE(player, MOVE_TACKLE, dynamax: dynamax); }
} SCENE { } SCENE {
MESSAGE("Foe Wobbuffet used Heal Pulse!"); MESSAGE("Foe Wobbuffet used Heal Pulse!");
HP_BAR(player, captureDamage: &damage); HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY { } FINALLY {
EXPECT_EQ(damage, 50); EXPECT_EQ(results[0].damage, results[1].damage);
} }
} }
@ -624,11 +630,11 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers single opponent's speed")
MESSAGE("Foe Wobbuffet used Tackle!"); MESSAGE("Foe Wobbuffet used Tackle!");
MESSAGE("Wobbuffet used Max Strike!"); MESSAGE("Wobbuffet used Max Strike!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Wobbuffet's speed fell!"); MESSAGE("Foe Wobbuffet's Speed fell!");
// turn 2 // turn 2
MESSAGE("Wobbuffet used Max Strike!"); MESSAGE("Wobbuffet used Max Strike!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Wobbuffet's speed fell!"); MESSAGE("Foe Wobbuffet's Speed fell!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
} }
} }
@ -637,7 +643,6 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers single opponent's speed")
DOUBLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers both opponents' speed") DOUBLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers both opponents' speed")
{ {
GIVEN { GIVEN {
// Fails? ASSUME(GetMaxMove(B_POSITION_PLAYER_LEFT, MOVE_TACKLE) == MOVE_MAX_STRIKE);
ASSUME(gBattleMoves[MOVE_MAX_STRIKE].argument == MAX_EFFECT_LOWER_SPEED); ASSUME(gBattleMoves[MOVE_MAX_STRIKE].argument == MAX_EFFECT_LOWER_SPEED);
PLAYER(SPECIES_WOBBUFFET) { Speed(80); } PLAYER(SPECIES_WOBBUFFET) { Speed(80); }
PLAYER(SPECIES_WOBBUFFET) { Speed(79); } PLAYER(SPECIES_WOBBUFFET) { Speed(79); }
@ -656,15 +661,15 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers both opponents' speed")
MESSAGE("Foe Wobbuffet used Tackle!"); MESSAGE("Foe Wobbuffet used Tackle!");
MESSAGE("Wobbuffet used Max Strike!"); MESSAGE("Wobbuffet used Max Strike!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("Foe Wobbuffet's speed fell!"); MESSAGE("Foe Wobbuffet's Speed fell!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
MESSAGE("Foe Wobbuffet's speed fell!"); MESSAGE("Foe Wobbuffet's Speed fell!");
// turn 2 // turn 2
MESSAGE("Wobbuffet used Max Strike!"); MESSAGE("Wobbuffet used Max Strike!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("Foe Wobbuffet's speed fell!"); MESSAGE("Foe Wobbuffet's Speed fell!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
MESSAGE("Foe Wobbuffet's speed fell!"); MESSAGE("Foe Wobbuffet's Speed fell!");
MESSAGE("Foe Wobbuffet used Tackle!"); MESSAGE("Foe Wobbuffet used Tackle!");
MESSAGE("Foe Wobbuffet used Tackle!"); MESSAGE("Foe Wobbuffet used Tackle!");
} }
@ -690,9 +695,9 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Max Knuckle raises both allies' attack")
MESSAGE("Wobbuffet used Max Knuckle!"); MESSAGE("Wobbuffet used Max Knuckle!");
HP_BAR(opponentLeft, captureDamage: &damage[0]); HP_BAR(opponentLeft, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Wobbuffet's attack rose!"); MESSAGE("Wobbuffet's Attack rose!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
MESSAGE("Wynaut's attack rose!"); MESSAGE("Wynaut's Attack rose!");
MESSAGE("Wynaut used Tackle!"); MESSAGE("Wynaut used Tackle!");
HP_BAR(opponentRight, captureDamage: &damage[1]); HP_BAR(opponentRight, captureDamage: &damage[1]);
MESSAGE("Foe Wobbuffet used Celebrate!"); MESSAGE("Foe Wobbuffet used Celebrate!");
@ -701,12 +706,12 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Max Knuckle raises both allies' attack")
MESSAGE("Wobbuffet used Max Knuckle!"); MESSAGE("Wobbuffet used Max Knuckle!");
HP_BAR(opponentLeft, captureDamage: &damage[2]); HP_BAR(opponentLeft, captureDamage: &damage[2]);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Wobbuffet's attack rose!"); MESSAGE("Wobbuffet's Attack rose!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
MESSAGE("Wynaut's attack rose!"); MESSAGE("Wynaut's Attack rose!");
MESSAGE("Wynaut used Tackle!"); MESSAGE("Wynaut used Tackle!");
HP_BAR(opponentRight, captureDamage: &damage[3]); HP_BAR(opponentRight, captureDamage: &damage[3]);
} FINALLY { } THEN {
EXPECT_GT(damage[2], damage[0]); EXPECT_GT(damage[2], damage[0]);
EXPECT_GT(damage[3], damage[1]); EXPECT_GT(damage[3], damage[1]);
} }
@ -863,13 +868,12 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Stonesurge sets up Stealth Rocks")
// The test below also tests that sharp steel does type-based damage and can be Defogged away. // The test below also tests that sharp steel does type-based damage and can be Defogged away.
SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Steelsurge sets up sharp steel") SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Steelsurge sets up sharp steel")
{ {
s16 damage;
GIVEN { GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE); ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_STEELSURGE].argument == MAX_EFFECT_STEELSURGE); ASSUME(gBattleMoves[MOVE_G_MAX_STEELSURGE].argument == MAX_EFFECT_STEELSURGE);
PLAYER(SPECIES_COPPERAJAH); PLAYER(SPECIES_COPPERAJAH);
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_CLEFABLE) { MaxHP(100); } OPPONENT(SPECIES_HATTERENE);
} WHEN { } WHEN {
TURN { MOVE(player, MOVE_IRON_HEAD, dynamax: TRUE); } TURN { MOVE(player, MOVE_IRON_HEAD, dynamax: TRUE); }
TURN { SWITCH(opponent, 1); } TURN { SWITCH(opponent, 1); }
@ -880,13 +884,13 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Steelsurge sets up sharp steel")
MESSAGE("Copperajah used G-Max Steelsurge!"); MESSAGE("Copperajah used G-Max Steelsurge!");
MESSAGE("Sharp-pointed steel floats around the opposing team!"); MESSAGE("Sharp-pointed steel floats around the opposing team!");
// turn 2 // turn 2
HP_BAR(opponent, captureDamage: &damage); MESSAGE("2 sent out Hatterene!");
MESSAGE("Sharp steel bit into Foe Clefable!"); MESSAGE("Sharp steel bit into Foe Hatterene!");
// turn 4 // turn 4
MESSAGE("Foe Clefable used Defog!"); MESSAGE("Foe Hatterene used Defog!");
MESSAGE("The sharp steel disappeared from the ground around the opposing team!"); MESSAGE("The sharp steel disappeared from the ground around the opposing team!");
} FINALLY { } THEN {
EXPECT_EQ(damage, 25); EXPECT_MUL_EQ(opponent->maxHP, Q_4_12(0.75), opponent->hp);
} }
} }
@ -932,9 +936,15 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Volt Crash paralyzes both opponents")
} }
} }
// G-Max Stun Shock can apply different statuses to each opponent, but this isn't
// compatible with the test RNG set-up.
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock paralyzes or poisons both opponents") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock paralyzes or poisons both opponents")
{ {
KNOWN_FAILING; // RNG issues u8 statusAnim;
u16 species;
u32 rng;
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = STATUS1_PARALYSIS; }
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = STATUS1_POISON; }
GIVEN { GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE); ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_STUN_SHOCK].argument == MAX_EFFECT_POISON_PARALYZE_FOES); ASSUME(gBattleMoves[MOVE_G_MAX_STUN_SHOCK].argument == MAX_EFFECT_POISON_PARALYZE_FOES);
@ -943,22 +953,36 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock paralyzes or poisons both opponen
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT); OPPONENT(SPECIES_WYNAUT);
} WHEN { } WHEN {
TURN { MOVE(playerLeft, MOVE_THUNDERBOLT, target: opponentLeft, dynamax: TRUE); } TURN { MOVE(playerLeft, MOVE_THUNDERBOLT, target: opponentLeft, dynamax: TRUE, \
WITH_RNG(RNG_G_MAX_STUN_SHOCK, rng)); }
} SCENE { } SCENE {
MESSAGE("Toxtricity used G-Max Stun Shock!"); MESSAGE("Toxtricity used G-Max Stun Shock!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponentLeft); // opponent left
STATUS_ICON(opponentLeft, poison: TRUE); ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentLeft);
MESSAGE("Foe Wobbuffet was poisoned!"); if (statusAnim == B_ANIM_STATUS_PSN) {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentRight); STATUS_ICON(opponentLeft, poison: TRUE);
STATUS_ICON(opponentRight, paralysis: TRUE); MESSAGE("Foe Wobbuffet was poisoned!");
MESSAGE("Foe Wynaut is paralyzed! It may be unable to move!"); }
else {
STATUS_ICON(opponentLeft, paralysis: TRUE);
MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!");
}
// opponent right
ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentRight);
if (statusAnim == B_ANIM_STATUS_PSN) {
STATUS_ICON(opponentRight, poison: TRUE);
MESSAGE("Foe Wynaut was poisoned!");
}
else {
STATUS_ICON(opponentRight, paralysis: TRUE);
MESSAGE("Foe Wynaut is paralyzed! It may be unable to move!");
}
} }
} }
// This test extends to G-Max Befuddle, too. // This test extends to G-Max Befuddle, too.
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock chooses statuses before considering immunities") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock chooses statuses before considering immunities")
{ {
KNOWN_FAILING; // RNG issues
GIVEN { GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE); ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_STUN_SHOCK].argument == MAX_EFFECT_POISON_PARALYZE_FOES); ASSUME(gBattleMoves[MOVE_G_MAX_STUN_SHOCK].argument == MAX_EFFECT_POISON_PARALYZE_FOES);
@ -967,53 +991,72 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock chooses statuses before consideri
OPPONENT(SPECIES_GARBODOR); OPPONENT(SPECIES_GARBODOR);
OPPONENT(SPECIES_TRUBBISH); OPPONENT(SPECIES_TRUBBISH);
} WHEN { } WHEN {
TURN { MOVE(playerLeft, MOVE_NUZZLE, target: opponentLeft, dynamax: TRUE); } TURN { MOVE(playerLeft, MOVE_NUZZLE, target: opponentLeft, dynamax: TRUE, \
WITH_RNG(RNG_G_MAX_STUN_SHOCK, STATUS1_POISON)); }
} SCENE { } SCENE {
MESSAGE("Toxtricity used G-Max Stun Shock!"); MESSAGE("Toxtricity used G-Max Stun Shock!");
NONE_OF { NONE_OF {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentLeft); // opponent left
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponentLeft); STATUS_ICON(opponentLeft, poison: TRUE);
MESSAGE("Foe Garbodor was poisoned!");
STATUS_ICON(opponentLeft, paralysis: TRUE);
MESSAGE("Foe Garbodor is paralyzed! It may be unable to move!");
// opponent right
STATUS_ICON(opponentRight, poison: TRUE);
MESSAGE("Foe Trubbish was poisoned!");
STATUS_ICON(opponentRight, paralysis: TRUE);
MESSAGE("Foe Trubbish is paralyzed! It may be unable to move!");
} }
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentRight);
MESSAGE("Foe Trubbish is paralyzed! It may be unable to move!");
STATUS_ICON(opponentRight, paralysis: TRUE);
} FINALLY {
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].status1, STATUS1_NONE);
} }
} }
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Befuddle paralyzes, poisons, or sleeps both opponents") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Befuddle paralyzes, poisons, or sleeps both opponents")
{ {
KNOWN_FAILING; // RNG issues u8 statusAnim;
u16 species;
u32 rng;
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = STATUS1_PARALYSIS; }
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = STATUS1_POISON; }
PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = STATUS1_SLEEP; }
GIVEN { GIVEN {
RNGSeed(0x10000);
ASSUME(gBattleMoves[MOVE_G_MAX_BEFUDDLE].argument == MAX_EFFECT_EFFECT_SPORE_FOES); ASSUME(gBattleMoves[MOVE_G_MAX_BEFUDDLE].argument == MAX_EFFECT_EFFECT_SPORE_FOES);
PLAYER(SPECIES_BUTTERFREE); PLAYER(SPECIES_BUTTERFREE);
PLAYER(SPECIES_CATERPIE); PLAYER(SPECIES_CATERPIE);
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN { } WHEN {
TURN { MOVE(playerLeft, MOVE_BUG_BITE, target: opponentLeft, dynamax: TRUE); } TURN { MOVE(playerLeft, MOVE_BUG_BITE, target: opponentLeft, dynamax: TRUE,
TURN { SWITCH(opponentLeft, 2); SWITCH(opponentRight, 3); \ WITH_RNG(RNG_G_MAX_BEFUDDLE, rng)); }
MOVE(playerLeft, MOVE_BUG_BITE, target: opponentLeft); }
} SCENE { } SCENE {
// turn 1
MESSAGE("Butterfree used G-Max Befuddle!"); MESSAGE("Butterfree used G-Max Befuddle!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponentLeft); // opponent left
STATUS_ICON(opponentLeft, poison: TRUE); ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentLeft);
MESSAGE("Foe Wobbuffet was poisoned!"); if (statusAnim == B_ANIM_STATUS_PSN) {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); STATUS_ICON(opponentLeft, poison: TRUE);
STATUS_ICON(opponentRight, sleep: TRUE); MESSAGE("Foe Wobbuffet was poisoned!");
MESSAGE("Foe Wobbuffet fell asleep!"); }
// turn 2 else if (statusAnim == B_ANIM_STATUS_PRZ) {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentLeft); STATUS_ICON(opponentLeft, paralysis: TRUE);
MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!"); MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!");
STATUS_ICON(opponentLeft, paralysis: TRUE); }
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponentRight); else {
MESSAGE("Foe Wobbuffet was poisoned!"); STATUS_ICON(opponentLeft, sleep: TRUE);
STATUS_ICON(opponentRight, poison: TRUE); MESSAGE("Foe Wobbuffet fell asleep!");
}
// opponent right
ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentRight);
if (statusAnim == B_ANIM_STATUS_PSN) {
STATUS_ICON(opponentRight, poison: TRUE);
MESSAGE("Foe Wobbuffet was poisoned!");
}
else if (statusAnim == B_ANIM_STATUS_PRZ) {
STATUS_ICON(opponentRight, paralysis: TRUE);
MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!");
}
else {
STATUS_ICON(opponentRight, sleep: TRUE);
MESSAGE("Foe Wobbuffet fell asleep!");
}
} }
} }
@ -1073,7 +1116,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Cuddle infatuates both opponents, if possibl
MESSAGE("Foe Wobbuffet fell in love!"); MESSAGE("Foe Wobbuffet fell in love!");
NONE_OF { NONE_OF {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_INFATUATION, opponentRight); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_INFATUATION, opponentRight);
MESSAGE("Foe Wobbuffet became confused!"); MESSAGE("Foe Wobbuffet fell in love!");
} }
} }
} }
@ -1092,8 +1135,8 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Terror traps both opponents")
MESSAGE("Gengar used G-Max Terror!"); MESSAGE("Gengar used G-Max Terror!");
MESSAGE("Foe Wobbuffet can't escape now!"); MESSAGE("Foe Wobbuffet can't escape now!");
MESSAGE("Foe Wobbuffet can't escape now!"); MESSAGE("Foe Wobbuffet can't escape now!");
} FINALLY { // Can't find good way to test trapping } THEN { // Can't find good way to test trapping
EXPECT(gBattleMons[B_POSITION_OPPONENT_LEFT].status2 & STATUS2_ESCAPE_PREVENTION); EXPECT(opponentLeft->status2 & STATUS2_ESCAPE_PREVENTION);
} }
} }
@ -1175,16 +1218,14 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Wildfire sets a field effect that damages no
HP_BAR(opponentRight); HP_BAR(opponentRight);
MESSAGE("Foe Wynaut is burning up within G-Max Wildfire's flames!"); MESSAGE("Foe Wynaut is burning up within G-Max Wildfire's flames!");
} }
} FINALLY { } THEN {
EXPECT_EQ(damage, 100); EXPECT_EQ(damage, 100);
} }
} }
// This should probably be tested to only occur 50% of the time. DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Replenish recycles allies' berries 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")
{ {
PASSES_RANDOMLY(1, 2, RNG_G_MAX_REPLENISH);
GIVEN { GIVEN {
ASSUME(gBattleMoves[MOVE_G_MAX_REPLENISH].argument == MAX_EFFECT_RECYCLE_BERRIES); ASSUME(gBattleMoves[MOVE_G_MAX_REPLENISH].argument == MAX_EFFECT_RECYCLE_BERRIES);
PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); } PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); }
@ -1199,10 +1240,10 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Replenish recycles allies' berries")
TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft, dynamax: TRUE); } TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft, dynamax: TRUE); }
} SCENE { } SCENE {
// turn 1 // turn 1
MESSAGE("Using Apicot Berry, the sp. defense of Snorlax rose!"); MESSAGE("Using Apicot Berry, the Sp. Def of Snorlax rose!");
MESSAGE("Using Apicot Berry, the sp. defense of Munchlax rose!"); MESSAGE("Using Apicot Berry, the Sp. Def of Munchlax rose!");
MESSAGE("Using Apicot Berry, the sp. defense of Foe Wobbuffet rose!"); MESSAGE("Using Apicot Berry, the Sp. Def of Foe Wobbuffet rose!");
MESSAGE("Using Apicot Berry, the sp. defense of Foe Wobbuffet rose!"); MESSAGE("Using Apicot Berry, the Sp. Def of Foe Wobbuffet rose!");
// turn 2 // turn 2
MESSAGE("Snorlax used G-Max Replenish!"); MESSAGE("Snorlax used G-Max Replenish!");
MESSAGE("Snorlax found one Apicot Berry!"); MESSAGE("Snorlax found one Apicot Berry!");
@ -1212,7 +1253,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Replenish recycles allies' berries")
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Snooze makes only the target drowsy") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Snooze makes only the target drowsy")
{ {
KNOWN_FAILING; // RNG issues PASSES_RANDOMLY(1, 2, RNG_G_MAX_SNOOZE);
GIVEN { GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE); ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_SNOOZE].argument == MAX_EFFECT_YAWN_FOE); ASSUME(gBattleMoves[MOVE_G_MAX_SNOOZE].argument == MAX_EFFECT_YAWN_FOE);
@ -1227,15 +1268,10 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Snooze makes only the target drowsy")
// turn 1 // turn 1
MESSAGE("Grimmsnarl used G-Max Snooze!"); MESSAGE("Grimmsnarl used G-Max Snooze!");
MESSAGE("Grimmsnarl made Foe Blissey drowsy!"); MESSAGE("Grimmsnarl made Foe Blissey drowsy!");
NONE_OF { MESSAGE("Grimmsnarl made Foe Chansey drowsy!"); }
// turn 2 // turn 2
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft);
MESSAGE("Foe Blissey fell asleep!"); MESSAGE("Foe Blissey fell asleep!");
STATUS_ICON(opponentLeft, sleep: TRUE); STATUS_ICON(opponentLeft, sleep: TRUE);
NONE_OF {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight);
STATUS_ICON(opponentRight, sleep: TRUE);
}
} }
} }
@ -1245,20 +1281,19 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Finale heals allies by 1/6 of their health")
GIVEN { GIVEN {
ASSUME(P_GEN_8_POKEMON == TRUE); ASSUME(P_GEN_8_POKEMON == TRUE);
ASSUME(gBattleMoves[MOVE_G_MAX_FINALE].argument == MAX_EFFECT_HEAL_TEAM); ASSUME(gBattleMoves[MOVE_G_MAX_FINALE].argument == MAX_EFFECT_HEAL_TEAM);
PLAYER(SPECIES_ALCREMIE) { HP(200); MaxHP(300); } PLAYER(SPECIES_ALCREMIE) { HP(1); }
PLAYER(SPECIES_MILCERY) { HP(200); MaxHP(300); } PLAYER(SPECIES_MILCERY) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
} WHEN { } WHEN {
TURN { MOVE(playerLeft, MOVE_MOONBLAST, target: opponentLeft, dynamax: TRUE); } TURN { MOVE(playerLeft, MOVE_MOONBLAST, target: opponentLeft, dynamax: TRUE); }
} SCENE { } SCENE {
// turn 1
MESSAGE("Alcremie used G-Max Finale!"); MESSAGE("Alcremie used G-Max Finale!");
HP_BAR(playerLeft, captureDamage: &damage1); HP_BAR(playerLeft, captureDamage: &damage1);
HP_BAR(playerRight, captureDamage: &damage2); HP_BAR(playerRight, captureDamage: &damage2);
} FINALLY { } THEN {
EXPECT_EQ(damage1, -75); // heals based on Dynamax HP EXPECT_MUL_EQ(playerLeft->hp - 1, Q_4_12(6), playerLeft->maxHP); // heals based on Dynamax HP
EXPECT_EQ(damage2, -50); EXPECT_MUL_EQ(playerRight->hp - 1, Q_4_12(6), playerRight->maxHP);
} }
} }
@ -1283,7 +1318,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions")
} }
} }
// This test should apply to G-Max Sandblast, too. // This test applies to G-Max Sandblast, too.
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Centiferno traps both opponents in Fire Spin") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Centiferno traps both opponents in Fire Spin")
{ {
s16 damage1, damage2; s16 damage1, damage2;
@ -1316,7 +1351,8 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Centiferno traps both opponents in Fire Spin
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Chi Strike boosts allies' crit chance") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Chi Strike boosts allies' crit chance")
{ {
s16 damage1, damage2; s16 damage1, damage2;
KNOWN_FAILING; u32 j;
KNOWN_FAILING; // Debug printing confirms Machop is at +5 crit stages. Not sure what's broken.
GIVEN { GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_6); ASSUME(B_CRIT_CHANCE >= GEN_6);
ASSUME(gBattleMoves[MOVE_G_MAX_CHI_STRIKE].argument == MAX_EFFECT_CRIT_PLUS); ASSUME(gBattleMoves[MOVE_G_MAX_CHI_STRIKE].argument == MAX_EFFECT_CRIT_PLUS);
@ -1325,20 +1361,22 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Chi Strike boosts allies' crit chance")
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
} WHEN { } WHEN {
TURN { MOVE(playerLeft, MOVE_FORCE_PALM, target: opponentLeft, dynamax: TRUE); \ TURN { MOVE(playerLeft, MOVE_FORCE_PALM, target: opponentLeft, dynamax: TRUE); }
TURN { MOVE(playerLeft, MOVE_FORCE_PALM, target: opponentLeft); }
TURN { MOVE(playerLeft, MOVE_FORCE_PALM, target: opponentLeft); \
MOVE(playerRight, MOVE_FOCUS_ENERGY); } MOVE(playerRight, MOVE_FOCUS_ENERGY); }
TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); } TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE { } SCENE {
// turn 1 // turn 1 - 3
MESSAGE("Machamp used G-Max Chi Strike!"); for (j = 0; j < 3; ++j) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); MESSAGE("Machamp used G-Max Chi Strike!");
MESSAGE("Machamp is getting pumped!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); MESSAGE("Machamp is getting pumped!");
MESSAGE("Machop is getting pumped!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
MESSAGE("Machop used Focus Energy!"); MESSAGE("Machop is getting pumped!");
MESSAGE("Machop is getting pumped!"); }
// turn 2 // turn 4
MESSAGE("Machop used Tackle!"); // Machop is at +3 crit stages, 100% crit chance MESSAGE("Machop used Tackle!"); // Machop is at +5 crit stages
MESSAGE("A critical hit!"); MESSAGE("A critical hit!");
} }
} }
@ -1362,7 +1400,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Depletion takes away 2 PP from the target's
} }
} }
// This test should apply to G-Max Rapid Flow, too. // This test applies to G-Max Rapid Flow, too.
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max One Blow bypasses Max Guard for full damage", s16 damage) DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max One Blow bypasses Max Guard for full damage", s16 damage)
{ {
bool32 protect; bool32 protect;