From 45835a2c330f2637f300bb2ec6efcd209d90c0be Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Fri, 2 Aug 2024 20:48:20 +0200 Subject: [PATCH 1/3] Fixed stray transparent pixels in Urshifu sprites (#5071) Co-authored-by: Hedara --- graphics/pokemon/urshifu/front.png | Bin 1035 -> 1019 bytes .../urshifu/rapid_strike_style/front.png | Bin 983 -> 949 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/urshifu/front.png b/graphics/pokemon/urshifu/front.png index cbb462be2ea052767f9ffd76bac05e73774ba1ea..468ba31f70900970524a0e511cdb75474878c814 100644 GIT binary patch delta 951 zcmV;o14#Uf2>S<+7#0Wv0001;w}I>c0004VQb$4nuFf3kkv=|u19?eAK~z|UotJ@{ zt11kHO(GDE`u?wbX9Bo(S6h17t=sl9Ka-FFcUhi?ynIr7bL#`(8ltOxO-R{JhU&W7 zqF?Edl#^r`0vKPknCdhj=L~?H04=5HTBbC(QvgOvZY^FJU&_ZyAe2{i2uP0K8h{o) zQ%JAAH~|oVt5*PjS~#L-)CWLZD`v0iRZz7Rxz9y+f?#fSUaDk6`ey6=@u$3L-;{|0sFB*zy=A4{hZSbL2}HG z0m52mEVY!W;nB$B;06q5JVt zr39FXcK8Sgg47r^U}=c(av1V$AuJC9FRzF)#yf(Iu4#mve-N;9%&#Ic0mzb4BUL6J zDX<3Z%QpyrIRU2@?ez@xaHogB&pDi0+D;f%aAz8UcoOlG!^ugb3NR^}5jgA;=@B8< zaEVhv8$r?7L4cat5Fg6OrerBw0Rga1(6P_m6QqaZZ8SsfeFT?m#}0Q~6h73!`u-OH zuHyh09lnqH!Zc57aiT5+9x6)2milq|IX(dFXIhGXzv0ZK)h12t(snumRb)fjHA#6! zw8Qx%=;^5l!RiY1%X1DmkJ}p8 zmV79vdIh{Wo?>U#v10`w2pAW_yY0j@0R0w!l<)@N9{{T95fFq4zVGd00U%6L_t(Y$92^)Z`(!`0N`WT0y4Z<2*||9 z5u!k(N01cfK;RI#01Re}@V+35$E;7{=$94))1mYhEG8)ZDddVtfGLS{~ zf9X3iQAv@a20?tE-@SMDXp+LEWnYgRvgOi$vWP{ufgi_@RRZhc(Uv5JYwjWFIJSNC zyb74ytSfLNylzDbsSUV0bcofqg(#IF3GuJ_&=0|mBEvr7b_>ZUoJT} z`KSUsi&u9fSuIyzUDI{#(i++?i&cEH`;go|P(I=nV0=d(oW{c{rl;m;V81DYlRgDO z=`qk#{-OeK#(F}Cw%vvU4&62_0hjfEqA0S^0D!Or6oJk$g~48D0;frc=bM1@9%DQe z9ZYagFM~^lCmC8EU=0J#i^5busaHZwY~e}C-Mu_G#h9zW$W}#2OGtjXw*k~Oa8(h% zfA;K&9OQ+T#p?sy1mPu#4eb_+%_=GOfhBsM7N4=y_nhZa9Aezj8GDcW)VRBUUBqd| zd=(TY5y9&eyiAtZC}*YNJYg&Z@Mz;@jGMyxqzt0aZcl8W4%X8zPq(g)VstaLTD`*@mkhUYn@ zYK7uqs;TUq^r)OgAxsH9WUK;E=L|usHC3}y0q~9jVVHr!gMo8Ba#J9G&!cFb4p(tr z^cN!+@948N7;XY!d7xK-v?w~$w*bh1jv&ZD@ugM!28ct>Ga#Xz2VoTc^etx!&Y0iH z{~y}f`C$$8+C1$S;O2i2$2&XF`2NdD!QZRZI=;JD#yOzU&@*}aY5g;~|8oCtW1}yc pd$Z7lF6q`cek$}W?|VWP{sWa?RfUbb7IOdq002ovPDHLkV1f&fzS;l) diff --git a/graphics/pokemon/urshifu/rapid_strike_style/front.png b/graphics/pokemon/urshifu/rapid_strike_style/front.png index 09d72971424ba62cb1c2d9c01cc964795d38841a..d06637f4e1737c6c9ca55b62fd87953b837d01e7 100644 GIT binary patch delta 880 zcmV-$1CRXI2ek)~7#0Wv0001;w}I>c0004VQb$4nuFf3kkv=|u12aiPK~z|UrI(GC z>L3h+o09NT^!;D=&ID?!UMaflTKDW>z9wNB=(1c7!I+r#S-q}7e^8pad|h{as7fR7zj06iLr2c6-~P621IHA1aU>Mnk%mNwPwlLrz3_< z!#YP;?o1=*yRh!6ZUjXj>nwmJ%zDQ}++VEhRy+t}b0)J5CG&|{R)nJ-LX3|jhJbW~ z9HY%_08`WjPE?r#aLv+2BdydI%`TtGpcD``5OCQ%X9fU&7w1Dhcs@%l8S|k{DWUw- zS7u-^@@B-9z7h3B4Y*49nM|%x2+GCo*6JPh3|t@R$77U12@={>TmFaJv;myJT`8793D~nYja%vs$5%@Q zs|EmTST6y$#Qh8R)o%8EUo~`iE@B>*V9{ICFYaZ3>L0bV-O!^FEEJtxCUR86+zYV` z0WU-3@ROEig)&UxC7y8db11Y}jTWx9#8UunhdqeWo=E^^2|a+e3?2b2QV5tNNCyPJ zbT7Jo4xs)Rq5Sd=m?CsQ`=S|t0|ftq3-l?1nU)4C1~y;*s{H_1{6TD=6F|NsI6wjD zgl_?V>Mh*t4KUmnPlOW6GvKidlOYuOA3(kU;Nc6!OR(q}5Jr2;NzWcy-T*ocXkFNk zRt~U6(7DYK+XPOT#y)PXy>@`k0%FENDI0cmYi*JM1weE%fXq%@Bcksq;phsr%mNa2 zxvg$bbD=ibkIk0=oDq38e*?_+Wq-rDz3RnJY`U>4Hkvm8JmGIslZfS6Z#?u@tMh~x z9$#Xt;`p2X07yK8Z@&`M_|o+U0uWeOyt~ag;R8aKSNT7HIU+Z{(jCtL0000VGd00S^dL_t(Y$9>enYtv8|0Pr_RSH=)b+kw}8 zae{bSUl4Xn%}cil!sbl1?jl?FNX$iHS}48jV0j~_=_-bulwqK^ftF}*GAN8*^e^&D zyD3TD`c99$AK&-A?|p=1){J_SOj~L}Gp;><%xw@AKqrLr7t+(*9-d=>w;iXG6}c_~ z0F~ij+2EA1;`_!wu8eo{0d`A#T*W&TnzX45F+)kbxY3_6TkrEF9y1 zUWvi&6nOJ|^aXAoECmK(+{}Xf#c1>kpt2NLR@7+}B%poKf&$cowWzZbr%1k9Kw9Cj zcM4EHcEtER`K%|Of``54K7*wn$F?5>t&|9`HW1$!6AiZH+waC17Lys2$R7kBBhE|0 zx2tgmJ$1>z4+cW`oUaMLnyG-0Inf_~a4!}O|4Cm1Ege8%-Y(qd5el|;s8O1k%-JHw zMZviv4z*%B0FL|k>W&b7?i^~RWPo^z3o(HEn8Fi3QWbI`-ffKoz#T{Uj&PG;w!;PA z+brYN%NmyH`TQseJm2FS&oz_2#{``7qeO=M*NE?yH8TlG+GA3$C)XBW}WyVa+Bk#oaavo!C{Vjsn@XEZtA5C zW&B|#?v-Xaq7%q}5o%m1ta}KgKN)3t-0T%D`diB~FhjA`0C(|0x2PdI^eD zGSzrb1k8Ri1(-$Mz5>eorMpR_CaBDT!!pTLT%fRg1T&`gmF|hQKq{i9#`T2%|8>3dK$Uwef|MTZ0uA*+1 zBsJ!TVecQ1jdgxFJfG|;sx6&+c76pG?5+$D<1)kM!pZgqxqd13_I9&59W;BbS5pLg o8n(iaOcOm8GBQ;dlXF7;0)d<#pK;$)F8}}l07*qoM6N<$f@d15@&Et; From 841bac21cd9501182e8b4862fba7417dbd995ccc Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Fri, 2 Aug 2024 19:56:16 +0100 Subject: [PATCH 2/3] Improve 1.8 => 1.9 COMPETITIVE_PARTY_SYNTAX changelog entry --- docs/changelogs/1.9.x/1.9.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelogs/1.9.x/1.9.0.md b/docs/changelogs/1.9.x/1.9.0.md index 16947711d3..0d39f109ed 100644 --- a/docs/changelogs/1.9.x/1.9.0.md +++ b/docs/changelogs/1.9.x/1.9.0.md @@ -43,7 +43,7 @@ * Migration script available in `migration_scripts/egg_move_refactor.py` by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/5040 * Added documentation to `STATIC_ASSERTS` used by the `BoxPokemon` after 1.8.0 by @pkmnsnfrn in https://github.com/rh-hideout/pokeemerald-expansion/pull/4294 * #### Competitive-formatted parties by @mrgriffin in https://github.com/rh-hideout/pokeemerald-expansion/pull/3545 - * Can be disabled by setting `COMPETITIVE_PARTY_SYNTAX` to `FALSE` in `include/config/general.h`. + * Can be disabled by setting `COMPETITIVE_PARTY_SYNTAX` to `FALSE` in `include/config/general.h`. If migrating from 1.8, remove the first and last lines from `src/data/trainers.h` (`const struct Trainer gTrainers[] = {` and `};` respectively). * Introduces `trainerproc`, a tool which converts Competitive-formatted parties into Trainer Control-formatted parties. * If you made custom changes to the following files and want to use this new format, ***Do not accept the incoming changes for them.*** Instead, use the migration script present in `migration_scripts/convert_parties.py`: - `src/data/trainers.h` From 9d97537ee2d939dfef711d13799e0a2a91a49acf Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Sat, 3 Aug 2024 16:29:47 +0100 Subject: [PATCH 3/3] Fix speed ties (#4780) * Fix speed ties * fixup! Fix speed ties * fixup! Fix speed ties * fixup! fixup! Fix speed ties * fixup! Fix speed ties * Workaround for Comatose-Ditto interaction --- include/battle.h | 1 + include/battle_main.h | 1 + src/battle_ai_main.c | 4 +- src/battle_main.c | 76 +++++++++++++++++++++++++++++++--- test/battle/ability/comatose.c | 5 ++- test/battle/move.c | 59 ++++++++++++++++++++++++-- 6 files changed, 135 insertions(+), 11 deletions(-) diff --git a/include/battle.h b/include/battle.h index c48dc78835..1aa26a9470 100644 --- a/include/battle.h +++ b/include/battle.h @@ -795,6 +795,7 @@ struct BattleStruct u8 quickClawRandom[MAX_BATTLERS_COUNT]; u8 quickDrawRandom[MAX_BATTLERS_COUNT]; u8 shellSideArmCategory[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; + u8 speedTieBreaks; // MAX_BATTLERS_COUNT! values. u8 boosterEnergyActivates; u8 distortedTypeMatchups; u8 categoryOverride; // for Z-Moves and Max Moves diff --git a/include/battle_main.h b/include/battle_main.h index 59a515b508..eb0af5aa77 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -75,6 +75,7 @@ s8 GetChosenMovePriority(u32 battlerId); s8 GetMovePriority(u32 battlerId, u16 move); s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2); +s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); void RunBattleScriptCommands_PopCallbacksStack(void); void RunBattleScriptCommands(void); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 08b8e4335c..63bab46ec9 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2722,7 +2722,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(SLOW_KILL); } else if (CanTargetFaintAi(battlerDef, battlerAtk) - && GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER + && GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER && GetMovePriority(battlerAtk, move) > 0) { ADJUST_SCORE(LAST_CHANCE); @@ -4117,7 +4117,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (IsStatBoostingBerry(item) && aiData->hpPercents[battlerAtk] > 60) ADJUST_SCORE(WEAK_EFFECT); else if (ShouldRestoreHpBerry(battlerAtk, item) && !CanAIFaintTarget(battlerAtk, battlerDef, 0) - && ((GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0)) + && ((GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0)) || !CanTargetFaintAiWithMod(battlerDef, battlerAtk, toHeal, 0))) ADJUST_SCORE(WEAK_EFFECT); // Recycle healing berry if we can't otherwise faint the target and the target wont kill us after we activate the berry } diff --git a/src/battle_main.c b/src/battle_main.c index 2b95bad975..9df19b9566 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -120,6 +120,7 @@ static void SpriteCB_UnusedBattleInit(struct Sprite *sprite); static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite); static u32 Crc32B (const u8 *data, u32 size); static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i); +static s32 Factorial(s32); EWRAM_DATA u16 gBattle_BG0_X = 0; EWRAM_DATA u16 gBattle_BG0_Y = 0; @@ -3807,6 +3808,8 @@ static void TryDoEventsBeforeFirstTurn(void) } #endif // TESTING + gBattleStruct->speedTieBreaks = RandomUniform(RNG_SPEED_TIE, 0, Factorial(MAX_BATTLERS_COUNT) - 1); + for (i = 0; i < gBattlersCount; i++) gBattlerByTurnOrder[i] = i; for (i = 0; i < gBattlersCount - 1; i++) @@ -3977,6 +3980,8 @@ void BattleTurnPassed(void) { s32 i; + gBattleStruct->speedTieBreaks = RandomUniform(RNG_SPEED_TIE, 0, Factorial(MAX_BATTLERS_COUNT) - 1); + TurnValuesCleanUp(TRUE); if (gBattleOutcome == 0) { @@ -4865,9 +4870,10 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov strikesFirst = 1; else { - if (speedBattler1 == speedBattler2 && Random() & 1) + if (speedBattler1 == speedBattler2) { - strikesFirst = 0; // same speeds, same priorities + // same speeds, same priorities + strikesFirst = 0; } else if (speedBattler1 < speedBattler2) { @@ -4898,7 +4904,7 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov return strikesFirst; } -s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) +s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) { s32 priority1 = 0, priority2 = 0; u32 ability1 = GetBattlerAbility(battler1); @@ -4916,8 +4922,60 @@ s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) priority2 = GetChosenMovePriority(battler2); } - return GetWhichBattlerFasterArgs(battler1, battler2, ignoreChosenMoves, ability1, ability2, - holdEffectBattler1, holdEffectBattler2, speedBattler1, speedBattler2, priority1, priority2); + return GetWhichBattlerFasterArgs( + battler1, battler2, + ignoreChosenMoves, + ability1, ability2, + holdEffectBattler1, holdEffectBattler2, + speedBattler1, speedBattler2, + priority1, priority2 + ); +} + +// 24 == MAX_BATTLERS_COUNT!. +// These are the possible orders if all the battlers speed tie. An order +// is chosen at the start of the turn. +static const u8 sBattlerOrders[24][4] = +{ + { 0, 1, 2, 3 }, + { 0, 1, 3, 2 }, + { 0, 2, 1, 3 }, + { 0, 2, 3, 1 }, + { 0, 3, 1, 2 }, + { 0, 3, 2, 1 }, + { 1, 0, 2, 3 }, + { 1, 0, 3, 2 }, + { 1, 2, 0, 3 }, + { 1, 2, 3, 0 }, + { 1, 3, 0, 2 }, + { 1, 3, 2, 0 }, + { 2, 0, 1, 3 }, + { 2, 0, 3, 1 }, + { 2, 1, 0, 3 }, + { 2, 1, 3, 0 }, + { 2, 3, 0, 1 }, + { 2, 3, 1, 0 }, + { 3, 0, 1, 2 }, + { 3, 0, 2, 1 }, + { 3, 1, 0, 2 }, + { 3, 1, 2, 0 }, + { 3, 2, 0, 1 }, + { 3, 2, 1, 0 }, +}; + +s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) +{ + s32 strikesFirst = GetWhichBattlerFasterOrTies(battler1, battler2, ignoreChosenMoves); + if (strikesFirst == 0) + { + s32 order1 = sBattlerOrders[gBattleStruct->speedTieBreaks][battler1]; + s32 order2 = sBattlerOrders[gBattleStruct->speedTieBreaks][battler2]; + if (order1 < order2) + strikesFirst = 1; + else + strikesFirst = -1; + } + return strikesFirst; } static void SetActionsAndBattlersTurnOrder(void) @@ -5890,3 +5948,11 @@ bool32 IsWildMonSmart(void) return FALSE; #endif } + +static s32 Factorial(s32 n) +{ + s32 f = 1, i; + for (i = 2; i <= n; i++) + f *= i; + return f; +} diff --git a/test/battle/ability/comatose.c b/test/battle/ability/comatose.c index bd991c258e..cc65e9afac 100644 --- a/test/battle/ability/comatose.c +++ b/test/battle/ability/comatose.c @@ -34,7 +34,10 @@ SINGLE_BATTLE_TEST("Comatose may be suppressed if pokemon transformed into a pok PARAMETRIZE { move = MOVE_THUNDER_WAVE; } GIVEN { - PLAYER(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); Speed(30); } + // FIXME: Explicit moves currently required here because Ditto + // expects to find Celebrate in slot 1 during the second turn + // (after transforming). + PLAYER(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); Speed(30); Moves(MOVE_CELEBRATE, MOVE_GASTRO_ACID, move); } OPPONENT(SPECIES_DITTO) { Speed(20); } } WHEN { TURN { MOVE(player, MOVE_GASTRO_ACID); MOVE(opponent, MOVE_TRANSFORM); } diff --git a/test/battle/move.c b/test/battle/move.c index 936a821081..228a09a7c6 100644 --- a/test/battle/move.c +++ b/test/battle/move.c @@ -66,10 +66,9 @@ SINGLE_BATTLE_TEST("Turn order is determined by Speed if priority ties") } } -SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie") +SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie [singles]") { - KNOWN_FAILING; // The algorithm is significantly biased. - PASSES_RANDOMLY(1, 2); + PASSES_RANDOMLY(1, 2, RNG_SPEED_TIE); GIVEN { PLAYER(SPECIES_WOBBUFFET) { Speed(1); } OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } @@ -81,6 +80,60 @@ SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie" } } +DOUBLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie [doubles]") +{ + struct BattlePokemon *order[4] = { NULL, NULL, NULL, NULL }; + u32 a, b, c, d; + + // TODO: Test all of these in a single PASSES_RANDOMLY pass rather + // than 24 PARAMETRIZEd passes. + PARAMETRIZE { a = 0; b = 1; c = 2; d = 3; } + PARAMETRIZE { a = 0; b = 1; c = 3; d = 2; } + PARAMETRIZE { a = 0; b = 2; c = 1; d = 3; } + PARAMETRIZE { a = 0; b = 2; c = 3; d = 1; } + PARAMETRIZE { a = 0; b = 3; c = 1; d = 2; } + PARAMETRIZE { a = 0; b = 3; c = 2; d = 1; } + PARAMETRIZE { a = 1; b = 0; c = 2; d = 3; } + PARAMETRIZE { a = 1; b = 0; c = 3; d = 2; } + PARAMETRIZE { a = 1; b = 2; c = 0; d = 3; } + PARAMETRIZE { a = 1; b = 2; c = 3; d = 0; } + PARAMETRIZE { a = 1; b = 3; c = 0; d = 2; } + PARAMETRIZE { a = 1; b = 3; c = 2; d = 0; } + PARAMETRIZE { a = 2; b = 0; c = 1; d = 3; } + PARAMETRIZE { a = 2; b = 0; c = 3; d = 1; } + PARAMETRIZE { a = 2; b = 1; c = 0; d = 3; } + PARAMETRIZE { a = 2; b = 1; c = 3; d = 0; } + PARAMETRIZE { a = 2; b = 3; c = 0; d = 1; } + PARAMETRIZE { a = 2; b = 3; c = 1; d = 0; } + PARAMETRIZE { a = 3; b = 0; c = 1; d = 2; } + PARAMETRIZE { a = 3; b = 0; c = 2; d = 1; } + PARAMETRIZE { a = 3; b = 1; c = 0; d = 2; } + PARAMETRIZE { a = 3; b = 1; c = 2; d = 0; } + PARAMETRIZE { a = 3; b = 2; c = 0; d = 1; } + PARAMETRIZE { a = 3; b = 2; c = 1; d = 0; } + + order[a] = playerLeft; + order[b] = playerRight; + order[c] = opponentLeft; + order[d] = opponentRight; + + PASSES_RANDOMLY(1, 24, RNG_SPEED_TIE); + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(1); } + PLAYER(SPECIES_WYNAUT) { Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + OPPONENT(SPECIES_WYNAUT) { Speed(1); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPLASH); MOVE(playerRight, MOVE_SPLASH); MOVE(opponentLeft, MOVE_SPLASH); MOVE(opponentRight, MOVE_SPLASH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[2]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[3]); + } +} + SINGLE_BATTLE_TEST("Critical hits occur at a 1/24 rate") { ASSUME(B_CRIT_CHANCE >= GEN_7);