From 3531086a6734ed6e344b01e5fb10dbf86ab9e073 Mon Sep 17 00:00:00 2001 From: ImperialSympathizer Date: Thu, 12 Sep 2024 20:05:22 -0400 Subject: [PATCH] update tests, bug fix MEs, and sprite assets --- .../images/mystery-encounters/girawitch.png | Bin 1021 -> 0 bytes ...irawitch.json => global_trade_system.json} | 20 +++---- .../global_trade_system.png | Bin 0 -> 1337 bytes .../mystery-encounters/gts_placeholder.png | Bin 707 -> 0 bytes ..._placeholder.json => warehouse_crate.json} | 24 ++++---- .../mystery-encounters/warehouse_crate.png | Bin 0 -> 868 bytes .../mystery-encounters/weird_dream_woman.json | 41 +++++++++++++ .../mystery-encounters/weird_dream_woman.png | Bin 0 -> 1349 bytes src/battle-scene.ts | 8 ++- .../encounters/berries-abound-encounter.ts | 2 +- .../encounters/bug-type-superfan-encounter.ts | 2 +- .../encounters/clowning-around-encounter.ts | 2 + .../global-trade-system-encounter.ts | 54 +++++++++--------- .../encounters/part-timer-encounter.ts | 18 +++--- .../the-winstrate-challenge-encounter.ts | 10 +++- .../encounters/training-session-encounter.ts | 2 +- .../encounters/uncommon-breed-encounter.ts | 11 ++-- .../encounters/weird-dream-encounter.ts | 10 +++- .../mystery-encounters/mystery-encounter.ts | 16 ++++++ .../utils/encounter-phase-utils.ts | 4 +- src/game-mode.ts | 23 ++++++-- .../berries-abound-encounter.test.ts | 3 +- .../uncommon-breed-encounter.test.ts | 6 +- 23 files changed, 170 insertions(+), 86 deletions(-) delete mode 100644 public/images/mystery-encounters/girawitch.png rename public/images/mystery-encounters/{girawitch.json => global_trade_system.json} (58%) create mode 100644 public/images/mystery-encounters/global_trade_system.png delete mode 100644 public/images/mystery-encounters/gts_placeholder.png rename public/images/mystery-encounters/{gts_placeholder.json => warehouse_crate.json} (53%) create mode 100644 public/images/mystery-encounters/warehouse_crate.png create mode 100644 public/images/mystery-encounters/weird_dream_woman.json create mode 100644 public/images/mystery-encounters/weird_dream_woman.png diff --git a/public/images/mystery-encounters/girawitch.png b/public/images/mystery-encounters/girawitch.png deleted file mode 100644 index a1cc7e8448dde6114fc76dc6583621af0d79d51c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1021 zcmVuL@r@OMpQ>IQdU-GTR(GV4k>4ck85vza}X|gQcQSN5R8nRl$4~VA2_Me z)Ub0d!JMQvg8b*k%9#010qNS#tmY z3ljhU3ljkVnw%H_00TuyL_t(Y$Ca1uf}&GAFyP<@gO?!DT6N9NDu)1WHC4{KB@zljH16;WJS^mKh7_zA@(Z9jrS4f zQc{yg8i>EbwO-*H5-suDJf|x8ff%`To9fJKExeAWo>GuUX!b8HIKKWyQ}D@p;0niM z4~r3LmUGIpa*?x%KfwVLAXcRf0l;$3aD0JEcw$ISQs1UK5T2!r_?YW%C*^J`at-52 zJRCM&G$&0WOW(fkXEovEaKMjijE}t_DY^=mXW@7_al1#_7Zz{A@hp=b9)c@bCvfBJ z%ZG~$l5x{KD)E@AjxNi}^PSxtVu-Ut@f$)Fx1oij`B334cK`Aukr z$9%j>xbb0E$HW(z$6dv{pnSfoO|HD~vT3Ysd*spLro{%3czfcLe*GJe{!%$qUR&B| z)N`b<9UXQx#n95CV9m|*)Fbs*;Qj?^kPlEJ`&1-0wl$tSP_;;U7CYZZ{<6qlkyhW1 rkCHUO6IVq}Jr%OF?t(jM$W87qvGQf@b%O%m00000NkvXXu0mjf)lS`E diff --git a/public/images/mystery-encounters/girawitch.json b/public/images/mystery-encounters/global_trade_system.json similarity index 58% rename from public/images/mystery-encounters/girawitch.json rename to public/images/mystery-encounters/global_trade_system.json index 98830a00a72..ae5d96127b7 100644 --- a/public/images/mystery-encounters/girawitch.json +++ b/public/images/mystery-encounters/global_trade_system.json @@ -1,11 +1,11 @@ { "textures": [ { - "image": "girawitch.png", + "image": "global_trade_system.png", "format": "RGBA8888", "size": { - "w": 46, - "h": 76 + "w": 77, + "h": 78 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 46, - "h": 76 + "w": 77, + "h": 78 }, "spriteSourceSize": { "x": 0, "y": 0, - "w": 46, - "h": 76 + "w": 77, + "h": 78 }, "frame": { "x": 0, "y": 0, - "w": 46, - "h": 76 + "w": 77, + "h": 78 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:e68bbc186f511d505c53b2beec3c3741:7108795fc29d953a1d3729ad93d70936:1661aeeeb2f0e4561c644aff254770b3$" + "smartupdate": "$TexturePacker:SmartUpdate:8a51d7a17b3d8c32f0e5e4a0f15daeb4:6eba29c5345847f735d8b69a05fc49d1:98ad8b8b8d8c4865d7d23ec97b516594$" } } diff --git a/public/images/mystery-encounters/global_trade_system.png b/public/images/mystery-encounters/global_trade_system.png new file mode 100644 index 0000000000000000000000000000000000000000..cb0ffb0ab200a918065e8de17dae5160473552f9 GIT binary patch literal 1337 zcmV-91;+Y`P)Hu`Nmmjg zf-hWDhWF_Q{}(JK5e5{+&km`tmqbgyjVh_eygV7mYd54D0LbtLUYSzI#fmmVhNx!y>ct zQv6<&@r{sCkX175`&)U6dy$qoMwR|2uy5um4qxgwNtdu22UT2#5l%w^FJW^CEvkyE zw2Y&I_K&c`sCg8}xp)km7nsLJnh{q6C%y*%fKzF{m1f0#eQQ?Jd&qlrO7r0u(`;JB zxa2UHJvNdyq2)kY7VQR@(+DO>KtB;Ddkab-&c&tJE3HpLo8{U@P!<`KiT5n+7&>ai znH~_b7dLU-wV!Ar&h`_YIYU>eG2XYy;FIF zBU;MUQOA`<*?1!3u)Z1SJ=2F1F46R+^pdl}Yzg?2yJq%e)X3HHL09uqVfF+7L2GF^ zqM_nIN1+vqK9;|pG}!8?l@W(OM;qHIwuAnhE{g9$8pS%CNeZTWqK5GjjKIQ z9D{DxrLywN@`*UhlPEPUm@F;pmgO^XmB(X%wq!eO)2egYU0j|NSh}4(2pmt+8l0&Y zP9{RvGyU-fTl`%d1Z=zuhJ}wbuQNJ}hIva};g0vbs_x1rx%fv-JfI&R} z`K@+d5j0O2oqOa_?&%hHaF?KG;$`i;&PZ;Omr3NGKZlzmX`~+VX`aGGym($v?K*$e zQwbme1v%OWhcq!w9r5BBCBdBJ_?u`@Sq6BAxm@E%;V~`n=Zqkis1?Kj$LbQPnAD^5KYu&dHs3lm3^ zr=793Oex~zDvL|f))9@OwAQb6+a@$|-xX;!ZkA?Y^iQ-INWL)QNLry8k!v(d^Rsd7 zXpOkt(AGQcmIW>S2~7j%+*&rA4dB|_zRhWCZJN}Pg?Epiu_~jZ-8;Ig$dlYhfyaB}BqYPJDE=Q@!=x{37)C%djD*e^TUr|#{C2ys1dp=>hd-Ywzbl}_89czJ z;Yko8qRaAq^_s71ZxCI&rQF4}Pz#U4{?dm9t%AnKOD=P51uicl9^yT-*+`J^h^s+M z`%Q@iK-};u%Aw!-qBsG}R}o)=J5vZh4=Y3wb;M7ee>{v3;a$v+&~=@0U@`pQS&Eor zzSV*Xj9M5_eduh&HRhE7<|}B&Wmy0{+zE?Ed|QE5plU}7cv#%88(s^_0H}1p!FPuz zd|QRlf}#lz`HzCw;vv5gROu-n32nmf;ECWBm?p7@n*$sOCWLF=E~Q8sgmT6)#)+S2 z#U`|OC;>jvw%KO`YjiyA;tZ_#MsEl9^97owQAZ4!PcOv-vhlz0P#of+IK)G7h&K<9 z(|FTDT>Hu5gKJglLSnX%C^;Ub44R;nxoOZmg%1_S;QKXP{`Kl#J-yEwpN6KN=+7Jf zT>jYlhmW}-d+N=0^BIt{o5SSBPlDNUq<_g={TSlv%^3g4bcM|0AatT3%lxr+1pelHnyL-Bye8eL=d} pMljvEk297@f0p?r_1kR^{sm7RJM6VI!f*fp002ovPDHLkV1jQaN3j3^ diff --git a/public/images/mystery-encounters/gts_placeholder.json b/public/images/mystery-encounters/warehouse_crate.json similarity index 53% rename from public/images/mystery-encounters/gts_placeholder.json rename to public/images/mystery-encounters/warehouse_crate.json index dd96e5892cd..fa86d1a511d 100644 --- a/public/images/mystery-encounters/gts_placeholder.json +++ b/public/images/mystery-encounters/warehouse_crate.json @@ -1,33 +1,33 @@ { "textures": [ { - "image": "gts_placeholder.png", + "image": "warehouse_crate.png", "format": "RGBA8888", "size": { - "w": 47, - "h": 79 + "w": 71, + "h": 52 }, "scale": 1, "frames": [ { - "filename": "0000.png", + "filename": "0001.png", "rotated": false, "trimmed": true, "sourceSize": { "w": 80, - "h": 80 + "h": 56 }, "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 47, - "h": 79 + "x": 5, + "y": 4, + "w": 71, + "h": 52 }, "frame": { "x": 0, "y": 0, - "w": 47, - "h": 79 + "w": 71, + "h": 52 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:4e95cf5cd2b0329629c40dfe871e5ae0:cf1cd6aef867fcde2439177ebb561178:39ec800be807afcf5dd13b9cc59fc386$" + "smartupdate": "$TexturePacker:SmartUpdate:c8df5f0b35fb9c2a69b0e4aaa9fa9f91:f1d4643c26f2aed86ad77d354e669aaf:0c073e3c2048ea0779db9429e5e1d8bc$" } } diff --git a/public/images/mystery-encounters/warehouse_crate.png b/public/images/mystery-encounters/warehouse_crate.png new file mode 100644 index 0000000000000000000000000000000000000000..fb70a6e534a8266d6afb46b6175a7a2c106a3cd2 GIT binary patch literal 868 zcmV-q1DpJbP)>00001bW%=J06^y0W&i*H z32;bRa{vGi!~g&e!~vBn4jTXf0@+DKK~zY`z1NF!;~)$L&;kNv{Qv*ExU z(quEU{adiW6Z-*6N0+AI=SeT*>Va2rUy6lFGv;^#$^ zWxstX*7`|+(j6yZYo|pgu+>!S*TDK%ol?A8<0LMLE#-@9PO1Ov?gD>QLi!LF0gI4Y zEO1DAqrX1>`jOP!w}|Ild+=H)$pelv$7Pr89nGfoz?`-<&~&l;Bc*KI8iM(b|93tJMSE+ zFI!!(td?c|!s$R}BcDC_-a zIN|Kna}ak-x!OIE4k@EWKRR-jbcfFlGxwAA$&q7uIC5h@K+;|w2lH^k!IAN&&Kq{V zW1EzOk9uRK00012P)t-sOlfh{ zH$(@A(E@Qi84onj8n zGrf6%<}(9;g*P_RASsKm@#Ev8@LKK5NkxWzj6Q1nnsB|3B}3qi#=L;*U@$p1MybIo z@;dLM&jNF8u?8A z^M}^~lE*;bNV6wg31Ui#ak&RunkCIc1ZJ#>oMaF$@pem$^hOh zh*oj?d5H+Pl^rBfD~@Sz!lgp6idK2Cfp#Pwlkh6VR@(8H4qDgoSmo`(C7~^Gniv0` z#fctMr*Zjm$(!dNK~oMPWEzZDG`z078D`9nvhVqJT_=ogDc=*o2i2ej$(Se)+kWVNu0GB5YQ^|HmA9uJL!@h5AGv{S)#)8jI2 z^B|VuAkNl;cQ&u^71seS^QJw^fF&NhR@gJqY~@X$ZyycEL%_a8|7d;P9Va~4#EdECHS;VxNAGvVyha{d7o+Sn@uhT&b%vst7u#^!x?&z2 zeta8`d#$PyBb#uu!PAIXr~chqgulaO;1}HXn*Q{Kr>7j}1&+S!_n#E;APqF5f-n00 zXJR`2_Wi6`Gr{(qv7IY8JgfH_=l34jT?o#>3&`T7WJKr66~0h7eD3$69DWYN5CY&3 zsNRmFy3B7o@K|`R`v%It4j6=kF#Q5YAM{JW=jIQGTHHbz{Thhp$AY6M@_Gr61L)x{ zYY9#(V_AqDe9_R?FblqyA!U&8Dh>4IpS-k*rfD1&hX)0vMR0UY{tbRMs!hJ~xYlS8 zm1EF6C&{z3<7`%KLR5pgq$B%T28rWJ9*~OWjH~Xe@ahvLjB{+0@I>7pMaO?&qO(JU z!{(}>{0GI(V|8s!8%m*uQFv$+84=v5@}wW5*A)yU)fEmZ%Q)wHsT1?a|17rm;}Tc; zgnO|T-BTYsDG%S^xZQEQvGpfQi93 z4=Mub#qXRekH_(gNjAt>DU!^`FE~z+mkj(2-{A5?7xR!G5%d&fWxQmBlC{oOMmkk0 zF1HvMgr+PF&uAnMzjsyBpssiX-{;&4x2Oazc+7LkF_mzcOod!K&bc*B<}IgFSD0a$ zT8t+UwbHn&+<3<=6MsqLbHHfgeP lowestMysteryEncounterWave) { const roll = Utils.randSeedInt(MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT); @@ -2923,6 +2922,7 @@ export default class BattleScene extends SceneBase { } } + console.log("shiftPhase from initFinalBossPhaseTwo"); this.shiftPhase(); }); return; @@ -3104,6 +3104,10 @@ export default class BattleScene extends SceneBase { if (encounterCandidate.encounterTier !== tier) { // Encounter is in tier return false; } + const disabledModes = encounterCandidate.disabledGameModes; + if (disabledModes && disabledModes.length > 0 && disabledModes.includes(this.gameMode.modeId)) { // Encounter is enabled for game mode + return false; + } if (!encounterCandidate.meetsRequirements!(this)) { // Meets encounter requirements return false; } diff --git a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts index 0d26036120f..e00a9c1ad38 100644 --- a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts +++ b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts @@ -266,7 +266,7 @@ async function tryGiveBerry(scene: BattleScene, prioritizedPokemon?: PlayerPokem if (!heldBerriesOfType || heldBerriesOfType.getStackCount() < heldBerriesOfType.getMaxStackCount(scene)) { await applyModifierTypeToPlayerPokemon(scene, pokemon, berry); - break; + return; } } } diff --git a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts index 5266ff4859f..9a94ac9bbbe 100644 --- a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts +++ b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts @@ -424,7 +424,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = scene.updateModifiers(true, true); const bugNet = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!; - bugNet.type.tier = ModifierTier.MASTER; + bugNet.type.tier = ModifierTier.ROGUE; setEncounterRewards(scene, { guaranteedModifierTypeOptions: [bugNet], guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED], fillRemaining: false }); leaveEncounterWithoutBattle(scene, true); diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index 4fb33a982ff..7c8503c3921 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -29,6 +29,7 @@ import { Moves } from "#enums/moves"; import { EncounterAnim, EncounterBattleAnim } from "#app/data/battle-anims"; import { MoveCategory } from "#app/data/move"; import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { GameModes } from "#app/game-mode"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounter:clowningAround"; @@ -59,6 +60,7 @@ const RANDOM_ABILITY_POOL = [ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.CLOWNING_AROUND) .withEncounterTier(MysteryEncounterTier.ULTRA) + .withDisabledGameModes(GameModes.CHALLENGE) .withSceneWaveRangeRequirement(80, 180) .withAnimations(EncounterAnim.SMOKESCREEN) .withAutoHideIntroVisuals(false) diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index 6484cab184a..0b8f590e3ba 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -19,7 +19,7 @@ import PokemonData from "#app/system/pokemon-data"; import i18next from "i18next"; import { Gender, getGenderSymbol } from "#app/data/gender"; import { getNatureName } from "#app/data/nature"; -import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball"; +import { getPokeballAtlasKey, getPokeballTintColor, PokeballType } from "#app/data/pokeball"; import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { trainerNamePools } from "#app/data/trainer-names"; @@ -74,10 +74,13 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = .withAutoHideIntroVisuals(false) .withIntroSpriteConfigs([ { - spriteKey: "gts_placeholder", + spriteKey: "global_trade_system", fileRoot: "mystery-encounters", - hasShadow: false, - disableAnimation: true + hasShadow: true, + disableAnimation: true, + x: 3, + y: 5, + yShadow: 1 } ]) .withIntroDialogue([ @@ -92,11 +95,14 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = const encounter = scene.currentBattle.mysteryEncounter!; // Load bgm + let bgmKey: string; if (scene.musicPreference === 0) { - scene.loadBgm("mystery_encounter_gen_5_gts", "mystery_encounter_gen_5_gts.mp3"); + bgmKey = "mystery_encounter_gen_5_gts"; + scene.loadBgm(bgmKey, `${bgmKey}.mp3`); } else { // Mixed option - scene.loadBgm("mystery_encounter_gen_6_gts", "mystery_encounter_gen_6_gts.mp3"); + bgmKey = "mystery_encounter_gen_6_gts"; + scene.loadBgm(bgmKey, `${bgmKey}.mp3`); } // Load possible trade options @@ -104,7 +110,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = // None of the trade options can be the same species const tradeOptionsMap: Map = getPokemonTradeOptions(scene); encounter.misc = { - tradeOptionsMap + tradeOptionsMap, + bgmKey }; return true; @@ -113,11 +120,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = // Change the bgm scene.fadeOutBgm(1500, false); scene.time.delayedCall(1500, () => { - if (scene.musicPreference === 0) { - scene.playBgm("mystery_encounter_gen_5_gts"); - } else { - scene.playBgm("mystery_encounter_gen_6_gts"); - } + scene.playBgm(scene.currentBattle.mysteryEncounter!.misc.bgmKey); }); return true; @@ -147,17 +150,15 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = // Pokemon trade selected encounter.setDialogueToken("tradedPokemon", pokemon.getNameToRender()); encounter.setDialogueToken("received", tradePokemon.getNameToRender()); - encounter.misc = { - tradedPokemon: pokemon, - receivedPokemon: tradePokemon, - }; + encounter.misc.tradedPokemon = pokemon; + encounter.misc.receivedPokemon = tradePokemon; return true; }, onHover: () => { const formName = tradePokemon.species.forms?.[pokemon.formIndex]?.formName; const line1 = i18next.t("pokemonInfoContainer:ability") + " " + tradePokemon.getAbility().name + (tradePokemon.getGender() !== Gender.GENDERLESS ? " | " + i18next.t("pokemonInfoContainer:gender") + " " + getGenderSymbol(tradePokemon.getGender()) : ""); const line2 = i18next.t("pokemonInfoContainer:nature") + " " + getNatureName(tradePokemon.getNature()) + (formName ? " | " + i18next.t("pokemonInfoContainer:form") + " " + formName : ""); - showEncounterText(scene, `${line1}\n${line2}`, 0); + showEncounterText(scene, `${line1}\n${line2}`, 0, 0, false); }, }; return option; @@ -181,7 +182,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = // Set data properly, then generate the new Pokemon's assets receivedPokemonData.passive = tradedPokemon.passive; - receivedPokemonData.pokeball = randSeedInt(5); + // Pokeball to Ultra ball, randomly + receivedPokemonData.pokeball = randInt(4) as PokeballType; const dataSource = new PokemonData(receivedPokemonData); const newPlayerPokemon = scene.addPlayerPokemon(receivedPokemonData.species, receivedPokemonData.level, dataSource.abilityIndex, dataSource.formIndex, dataSource.gender, dataSource.shiny, dataSource.variant, dataSource.ivs, dataSource.nature, dataSource); scene.getParty().push(newPlayerPokemon); @@ -196,7 +198,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = await showTradeBackground(scene); await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon); await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000); - scene.playBgm("mystery_encounter_gts"); + scene.playBgm(encounter.misc.bgmKey); await hideTradeBackground(scene); tradedPokemon.destroy(); @@ -241,10 +243,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = encounter.setDialogueToken("tradedPokemon", pokemon.getNameToRender()); encounter.setDialogueToken("received", tradePokemon.getNameToRender()); - encounter.misc = { - tradedPokemon: pokemon, - receivedPokemon: tradePokemon, - }; + encounter.misc.tradedPokemon = pokemon; + encounter.misc.receivedPokemon = tradePokemon; }; return selectPokemonForOption(scene, onPokemonSelected); @@ -264,7 +264,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = // Set data properly, then generate the new Pokemon's assets receivedPokemonData.passive = tradedPokemon.passive; - receivedPokemonData.pokeball = randSeedInt(5); + receivedPokemonData.pokeball = randInt(4) as PokeballType; const dataSource = new PokemonData(receivedPokemonData); const newPlayerPokemon = scene.addPlayerPokemon(receivedPokemonData.species, receivedPokemonData.level, dataSource.abilityIndex, dataSource.formIndex, dataSource.gender, dataSource.shiny, dataSource.variant, dataSource.ivs, dataSource.nature, dataSource); scene.getParty().push(newPlayerPokemon); @@ -279,7 +279,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = await showTradeBackground(scene); await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon); await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000); - scene.playBgm("mystery_encounter_gts"); + scene.playBgm(scene.currentBattle.mysteryEncounter!.misc.bgmKey); await hideTradeBackground(scene); tradedPokemon.destroy(); @@ -309,9 +309,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = handler: () => { // Pokemon and item selected encounter.setDialogueToken("chosenItem", modifier.type.name); - encounter.misc = { - chosenModifier: modifier, - }; + encounter.misc.chosenModifier = modifier; return true; }, }; diff --git a/src/data/mystery-encounters/encounters/part-timer-encounter.ts b/src/data/mystery-encounters/encounters/part-timer-encounter.ts index 8dffeac6cb2..dff12a18cd3 100644 --- a/src/data/mystery-encounters/encounters/part-timer-encounter.ts +++ b/src/data/mystery-encounters/encounters/part-timer-encounter.ts @@ -25,19 +25,19 @@ export const PartTimerEncounter: MysteryEncounter = .withEncounterTier(MysteryEncounterTier.COMMON) .withSceneWaveRangeRequirement(10, 180) .withIntroSpriteConfigs([ + { + spriteKey: "warehouse_crate", + fileRoot: "mystery-encounters", + hasShadow: false, + y: 6, + x: 15 + }, { spriteKey: "worker_f", fileRoot: "trainer", hasShadow: true, - x: -20 - }, - { - spriteKey: "training_gear", - fileRoot: "mystery-encounters", - hasShadow: true, - y: 6, - x: 20, - yShadow: -2 + x: -18, + y: 4 } ]) .withAutoHideIntroVisuals(false) diff --git a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts index 05ce57b5e47..06a1de56fae 100644 --- a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts @@ -1,4 +1,4 @@ -import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { EnemyPartyConfig, generateModifierType, generateModifierTypeOption, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "#app/battle-scene"; @@ -21,6 +21,7 @@ import { PartyHealPhase } from "#app/phases/party-heal-phase"; import { ShowTrainerPhase } from "#app/phases/show-trainer-phase"; import { ReturnPhase } from "#app/phases/return-phase"; import i18next from "i18next"; +import { ModifierTier } from "#app/modifier/modifier-tier"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounter:theWinstrateChallenge"; @@ -149,9 +150,12 @@ async function spawnNextTrainerOrEndEncounter(scene: BattleScene) { await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name })); await showEncounterDialogue(scene, `${namespace}.victory_2`, `${namespace}.speaker`); - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE], fillRemaining: false }); + scene.ui.clearText(); // Clears "Winstrate" title from screen as rewards get animated in + const machoBrace = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE)!; + machoBrace.type.tier = ModifierTier.MASTER; + setEncounterRewards(scene, { guaranteedModifierTypeOptions: [machoBrace], fillRemaining: false }); encounter.doContinueEncounter = undefined; - leaveEncounterWithoutBattle(scene, false, MysteryEncounterMode.TRAINER_BATTLE); + leaveEncounterWithoutBattle(scene, false, MysteryEncounterMode.NO_BATTLE); } else { await initBattleWithEnemyConfig(scene, nextConfig); } diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index 92308594f79..1416ad971e0 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -305,7 +305,7 @@ export const TrainingSessionEncounter: MysteryEncounter = return true; }, onHover: () => { - showEncounterText(scene, ability.description, 0); + showEncounterText(scene, ability.description, 0, 0, false); }, }; optionSelectItems.push(option); diff --git a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts index 27e82a37f2d..3b7b507af75 100644 --- a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts +++ b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts @@ -53,16 +53,15 @@ export const UncommonBreedEncounter: MysteryEncounter = const species = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true); const pokemon = new EnemyPokemon(scene, species, level, TrainerSlot.NONE, true); const speciesRootForm = pokemon.species.getRootSpeciesId(); - encounter.misc = { - pokemon - }; // Pokemon will always have one of its egg moves in its moveset if (speciesEggMoves.hasOwnProperty(speciesRootForm)) { const eggMoves: Moves[] = speciesEggMoves[speciesRootForm]; const eggMoveIndex = randSeedInt(4); const randomEggMove: Moves = eggMoves[eggMoveIndex]; - encounter.misc.eggMove = randomEggMove; + encounter.misc = { + eggMove: randomEggMove + }; if (pokemon.moveset.length < 4) { pokemon.moveset.push(new PokemonMove(randomEggMove)); } else { @@ -70,6 +69,8 @@ export const UncommonBreedEncounter: MysteryEncounter = } } + encounter.misc.pokemon = pokemon; + const config: EnemyPartyConfig = { pokemonConfigs: [{ level: level, @@ -184,7 +185,7 @@ export const UncommonBreedEncounter: MysteryEncounter = berryItems.splice(index, 1); } } - scene.updateModifiers(true, true); + await scene.updateModifiers(true, true); // Pokemon joins the team, with 2 egg moves const encounter = scene.currentBattle.mysteryEncounter!; diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index 5ece733b7f5..7cdf1e12ded 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -20,6 +20,7 @@ import i18next from "#app/plugins/i18n"; import { doPokemonTransformationSequence, TransformationScreenPosition } from "#app/data/mystery-encounters/utils/encounter-transformation-sequence"; import { getLevelTotalExp } from "#app/data/exp"; import { Stat } from "#enums/stat"; +import { GameModes } from "#app/game-mode"; /** i18n namespace for encounter */ const namespace = "mysteryEncounter:weirdDream"; @@ -94,13 +95,16 @@ const STANDARD_BST_TRANSFORM_BASE_VALUES = [40, 50]; export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.WEIRD_DREAM) .withEncounterTier(MysteryEncounterTier.ROGUE) + .withDisabledGameModes(GameModes.CHALLENGE) .withSceneWaveRangeRequirement(10, 180) .withIntroSpriteConfigs([ { - spriteKey: "girawitch", + spriteKey: "weird_dream_woman", fileRoot: "mystery-encounters", - hasShadow: false, - y: 4 + hasShadow: true, + y: 11, + yShadow: 6, + x: 4 }, ]) .withIntroDialogue([ diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index 7871c459fae..9b7a1635794 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -14,6 +14,7 @@ import { EncounterAnim } from "#app/data/battle-anims"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; +import { GameModes } from "#app/game-mode"; export interface EncounterStartOfBattleEffect { sourcePokemon?: Pokemon; @@ -36,6 +37,7 @@ export interface IMysteryEncounter { spriteConfigs: MysteryEncounterSpriteConfig[]; encounterTier: MysteryEncounterTier; encounterAnimations?: EncounterAnim[]; + disabledGameModes?: GameModes[]; hideBattleIntroMessage: boolean; autoHideIntroVisuals: boolean; enterIntroVisualsFromRight: boolean; @@ -85,6 +87,10 @@ export default class MysteryEncounter implements IMysteryEncounter { * Specify here so that assets are loaded on initialization of encounter */ encounterAnimations?: EncounterAnim[]; + /** + * If specified, defines any game modes where the MysteryEncounter should *NOT* spawn + */ + disabledGameModes?: GameModes[]; /** * If true, hides "A Wild X Appeared" etc. messages * Default true @@ -630,6 +636,16 @@ export class MysteryEncounterBuilder implements Partial { return Object.assign(this, { encounterAnimations: animations }); } + /** + * Defines any game modes where the Mystery Encounter should *NOT* spawn + * @returns + * @param disabledGameModes + */ + withDisabledGameModes(...disabledGameModes: GameModes[]): this & Required> { + const gameModes = Array.isArray(disabledGameModes) ? disabledGameModes : [disabledGameModes]; + return Object.assign(this, { disabledGameModes: gameModes }); + } + /** * If true, encounter will continuously run through multiple battles/puzzles/etc. instead of going to next wave * MUST EVENTUALLY BE DISABLED TO CONTINUE TO NEXT WAVE diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index f3997706f16..55d3a598d0c 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -456,7 +456,7 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p return true; }, onHover: () => { - showEncounterText(scene, i18next.t("mysteryEncounterMessages:cancel_option"), 0); + showEncounterText(scene, i18next.t("mysteryEncounterMessages:cancel_option"), 0, 0, false); } }); @@ -570,7 +570,7 @@ export function selectOptionThenPokemon(scene: BattleScene, options: OptionSelec if (onHoverOverCancelOption) { onHoverOverCancelOption(); } - scene.ui.showText(i18next.t("mysteryEncounterMessages:cancel_option")); + showEncounterText(scene, i18next.t("mysteryEncounterMessages:cancel_option"), 0, 0, false); } }); diff --git a/src/game-mode.ts b/src/game-mode.ts index 0a35e60057c..f3140445d85 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -30,10 +30,12 @@ interface GameModeConfig { isSplicedOnly?: boolean; isChallenge?: boolean; hasMysteryEncounters?: boolean; - minMysteryEncounterWave?: number; - maxMysteryEncounterWave?: number; } +// Describes min and max waves for MEs in specific game modes +const CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [10, 180]; +const CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [10, 180]; + export class GameMode implements GameModeConfig { public modeId: GameModes; public isClassic: boolean; @@ -60,8 +62,6 @@ export class GameMode implements GameModeConfig { this.challenges = allChallenges.map(c => copyChallenge(c)); } this.battleConfig = battleConfig || {}; - this.minMysteryEncounterWave = this.minMysteryEncounterWave ?? 0; - this.maxMysteryEncounterWave = this.maxMysteryEncounterWave ?? 100000; } /** @@ -325,6 +325,17 @@ export class GameMode implements GameModeConfig { } } + getMysteryEncounterLegalWaves(): [number, number] { + switch (this.modeId) { + default: + return [0, 0]; + case GameModes.CLASSIC: + return CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES; + case GameModes.CHALLENGE: + return CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES; + } + } + static getModeName(modeId: GameModes): string { switch (modeId) { case GameModes.CLASSIC: @@ -344,7 +355,7 @@ export class GameMode implements GameModeConfig { export function getGameMode(gameMode: GameModes): GameMode { switch (gameMode) { case GameModes.CLASSIC: - return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true, maxMysteryEncounterWave: 180, minMysteryEncounterWave: 10 }, classicFixedBattles); + return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true }, classicFixedBattles); case GameModes.ENDLESS: return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true }); case GameModes.SPLICED_ENDLESS: @@ -352,6 +363,6 @@ export function getGameMode(gameMode: GameModes): GameMode { case GameModes.DAILY: return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true }); case GameModes.CHALLENGE: - return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true }, classicFixedBattles); + return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true, hasMysteryEncounters: true }, classicFixedBattles); } } diff --git a/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts b/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts index 52ee49faee0..3bad3e0d0da 100644 --- a/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts @@ -36,6 +36,7 @@ describe("Berries Abound - Mystery Encounter", () => { game = new GameManager(phaserGame); scene = game.scene; game.override.mysteryEncounterChance(100); + game.override.mysteryEncounterTier(MysteryEncounterTier.COMMON); game.override.startingWave(defaultWave); game.override.startingBiome(defaultBiome); game.override.disableTrainerWaves(); @@ -132,7 +133,7 @@ describe("Berries Abound - Mystery Encounter", () => { expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); }); - it("should reward the player with X berries based on wave", async () => { + it("should reward the player with X berries based on wave", { retry: 5 }, async () => { await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty); const numBerries = game.scene.currentBattle.mysteryEncounter!.misc.numBerries; diff --git a/src/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts b/src/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts index 0e576dd4dba..5f424ffea2c 100644 --- a/src/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts @@ -12,6 +12,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; import { CommandPhase } from "#app/phases/command-phase"; import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter"; @@ -22,7 +23,6 @@ import { BerryType } from "#enums/berry-type"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { Stat } from "#enums/stat"; import { BerryModifier } from "#app/modifier/modifier"; -import { generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { modifierTypes } from "#app/modifier/modifier-type"; const namespace = "mysteryEncounter:uncommonBreed"; @@ -43,6 +43,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { game = new GameManager(phaserGame); scene = game.scene; game.override.mysteryEncounterChance(100); + game.override.mysteryEncounterTier(MysteryEncounterTier.COMMON); game.override.startingWave(defaultWave); game.override.startingBiome(defaultBiome); game.override.disableTrainerWaves(); @@ -166,12 +167,13 @@ describe("Uncommon Breed - Mystery Encounter", () => { }); }); - it("should NOT be selectable if the player doesn't have enough berries", async () => { + it("should NOT be selectable if the player doesn't have enough berries", { retry: 5 }, async () => { await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty); // Clear out any pesky mods that slipped through test spin-up scene.modifiers.forEach(mod => { scene.removeModifier(mod); }); + await scene.updateModifiers(true); await game.phaseInterceptor.to(MysteryEncounterPhase, false); const encounterPhase = scene.getCurrentPhase();