From 92969ef6f81b361059712999e8b605819a94ac58 Mon Sep 17 00:00:00 2001 From: ImperialSympathizer Date: Thu, 3 Oct 2024 19:32:11 -0400 Subject: [PATCH] balance changes and updates to various MEs --- public/images/items.json | 805 +++++++++--------- public/images/items.png | Bin 58664 -> 58657 bytes public/images/items/black_sludge.png | Bin 1026 -> 285 bytes public/images/items/pb_silver.png | Bin 0 -> 556 bytes public/images/trainer/future_self_f.json | 41 + public/images/trainer/future_self_f.png | Bin 0 -> 664 bytes public/images/trainer/future_self_m.json | 41 + public/images/trainer/future_self_m.png | Bin 0 -> 695 bytes ...pokemon-data.ts => custom-pokemon-data.ts} | 9 +- .../an-offer-you-cant-refuse-encounter.ts | 9 +- .../encounters/clowning-around-encounter.ts | 31 +- .../encounters/dark-deal-encounter.ts | 10 +- .../encounters/delibirdy-encounter.ts | 10 +- .../encounters/fiery-fallout-encounter.ts | 71 +- .../mysterious-challengers-encounter.ts | 8 +- .../shady-vitamin-dealer-encounter.ts | 2 +- .../slumbering-snorlax-encounter.ts | 4 +- .../the-expert-pokemon-breeder-encounter.ts | 20 +- .../encounters/the-strong-stuff-encounter.ts | 4 +- .../encounters/trash-to-treasure-encounter.ts | 2 +- .../encounters/weird-dream-encounter.ts | 378 +++++--- .../mystery-encounter-requirements.ts | 6 +- .../requirements/requirement-groups.ts | 14 + .../utils/encounter-phase-utils.ts | 8 +- .../utils/encounter-pokemon-utils.ts | 22 + src/data/pokemon-evolutions.ts | 6 +- src/data/trainer-config.ts | 18 +- src/enums/trainer-type.ts | 2 + src/field/pokemon.ts | 51 +- src/modifier/modifier-type.ts | 1 + src/modifier/modifier.ts | 78 +- src/phases/select-modifier-phase.ts | 11 +- src/system/pokemon-data.ts | 11 +- ...an-offer-you-cant-refuse-encounter.test.ts | 8 +- .../clowning-around-encounter.test.ts | 8 +- .../encounters/delibirdy-encounter.test.ts | 48 +- .../fiery-fallout-encounter.test.ts | 47 +- .../the-strong-stuff-encounter.test.ts | 4 +- .../trash-to-treasure-encounter.test.ts | 2 +- .../encounters/weird-dream-encounter.test.ts | 69 +- 40 files changed, 1143 insertions(+), 716 deletions(-) create mode 100644 public/images/items/pb_silver.png create mode 100644 public/images/trainer/future_self_f.json create mode 100644 public/images/trainer/future_self_f.png create mode 100644 public/images/trainer/future_self_m.json create mode 100644 public/images/trainer/future_self_m.png rename src/data/mystery-encounters/{mystery-encounter-pokemon-data.ts => custom-pokemon-data.ts} (68%) diff --git a/public/images/items.json b/public/images/items.json index 779823d1293..3c9cff7a35a 100644 --- a/public/images/items.json +++ b/public/images/items.json @@ -3416,12 +3416,12 @@ "rotated": false, "trimmed": true, "sourceSize": { - "w": 24, - "h": 24 + "w": 32, + "h": 32 }, "spriteSourceSize": { - "x": 1, - "y": 2, + "x": 5, + "y": 7, "w": 22, "h": 19 }, @@ -6583,7 +6583,7 @@ } }, { - "filename": "rb", + "filename": "pb_silver", "rotated": false, "trimmed": true, "sourceSize": { @@ -6666,6 +6666,27 @@ "h": 19 } }, + { + "filename": "rb", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 20, + "h": 20 + }, + "frame": { + "x": 254, + "y": 320, + "w": 20, + "h": 20 + } + }, { "filename": "smooth_meteorite", "rotated": false, @@ -6680,27 +6701,6 @@ "w": 20, "h": 20 }, - "frame": { - "x": 254, - "y": 320, - "w": 20, - "h": 20 - } - }, - { - "filename": "strange_ball", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 - }, "frame": { "x": 274, "y": 325, @@ -6709,7 +6709,7 @@ } }, { - "filename": "ub", + "filename": "strange_ball", "rotated": false, "trimmed": true, "sourceSize": { @@ -6751,7 +6751,7 @@ } }, { - "filename": "apicot_berry", + "filename": "ub", "rotated": false, "trimmed": true, "sourceSize": { @@ -6761,13 +6761,13 @@ "spriteSourceSize": { "x": 6, "y": 6, - "w": 19, + "w": 20, "h": 20 }, "frame": { "x": 221, "y": 337, - "w": 19, + "w": 20, "h": 20 } }, @@ -6793,7 +6793,7 @@ } }, { - "filename": "big_mushroom", + "filename": "apicot_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -6804,13 +6804,13 @@ "x": 6, "y": 6, "w": 19, - "h": 19 + "h": 20 }, "frame": { "x": 343, "y": 287, "w": 19, - "h": 19 + "h": 20 } }, { @@ -6834,6 +6834,27 @@ "h": 20 } }, + { + "filename": "big_mushroom", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 19 + }, + "frame": { + "x": 318, + "y": 306, + "w": 19, + "h": 19 + } + }, { "filename": "hard_stone", "rotated": false, @@ -6849,33 +6870,12 @@ "h": 20 }, "frame": { - "x": 318, - "y": 306, + "x": 314, + "y": 325, "w": 19, "h": 20 } }, - { - "filename": "miracle_seed", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 19, - "h": 19 - }, - "frame": { - "x": 337, - "y": 306, - "w": 19, - "h": 19 - } - }, { "filename": "wl_ability_urge", "rotated": false, @@ -6891,12 +6891,33 @@ "h": 18 }, "frame": { - "x": 314, - "y": 326, + "x": 337, + "y": 307, "w": 20, "h": 18 } }, + { + "filename": "miracle_seed", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 19, + "h": 19 + }, + "frame": { + "x": 333, + "y": 325, + "w": 19, + "h": 19 + } + }, { "filename": "wl_antidote", "rotated": false, @@ -6912,12 +6933,54 @@ "h": 18 }, "frame": { - "x": 356, + "x": 357, "y": 307, "w": 20, "h": 18 } }, + { + "filename": "wl_awakening", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 352, + "y": 325, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_burn_heal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 241, + "y": 340, + "w": 20, + "h": 18 + } + }, { "filename": "golden_egg", "rotated": false, @@ -6933,33 +6996,12 @@ "h": 20 }, "frame": { - "x": 376, - "y": 307, + "x": 372, + "y": 325, "w": 17, "h": 20 } }, - { - "filename": "wl_awakening", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 393, - "y": 241, - "w": 20, - "h": 18 - } - }, { "filename": "toxic_orb", "rotated": false, @@ -6975,96 +7017,12 @@ "h": 18 }, "frame": { - "x": 413, - "y": 258, + "x": 377, + "y": 307, "w": 18, "h": 18 } }, - { - "filename": "wl_burn_heal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 393, - "y": 259, - "w": 20, - "h": 18 - } - }, - { - "filename": "ampharosite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 377, - "y": 243, - "w": 16, - "h": 16 - } - }, - { - "filename": "audinite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 377, - "y": 259, - "w": 16, - "h": 16 - } - }, - { - "filename": "relic_gold", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 15, - "h": 11 - }, - "frame": { - "x": 377, - "y": 275, - "w": 15, - "h": 11 - } - }, { "filename": "lucky_egg", "rotated": false, @@ -7080,8 +7038,8 @@ "h": 20 }, "frame": { - "x": 381, - "y": 286, + "x": 389, + "y": 325, "w": 17, "h": 20 } @@ -7101,8 +7059,8 @@ "h": 18 }, "frame": { - "x": 398, - "y": 277, + "x": 352, + "y": 343, "w": 20, "h": 18 } @@ -7122,8 +7080,8 @@ "h": 18 }, "frame": { - "x": 398, - "y": 295, + "x": 372, + "y": 345, "w": 20, "h": 18 } @@ -7143,8 +7101,8 @@ "h": 18 }, "frame": { - "x": 393, - "y": 313, + "x": 392, + "y": 345, "w": 20, "h": 18 } @@ -7164,14 +7122,14 @@ "h": 18 }, "frame": { - "x": 240, - "y": 340, + "x": 378, + "y": 241, "w": 20, "h": 18 } }, { - "filename": "banettite", + "filename": "relic_gold", "rotated": false, "trimmed": true, "sourceSize": { @@ -7179,16 +7137,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 + "x": 9, + "y": 11, + "w": 15, + "h": 11 }, "frame": { - "x": 413, - "y": 313, - "w": 16, - "h": 16 + "x": 398, + "y": 241, + "w": 15, + "h": 11 } }, { @@ -7206,8 +7164,8 @@ "h": 18 }, "frame": { - "x": 202, - "y": 358, + "x": 377, + "y": 259, "w": 20, "h": 18 } @@ -7227,8 +7185,8 @@ "h": 18 }, "frame": { - "x": 201, - "y": 376, + "x": 381, + "y": 277, "w": 20, "h": 18 } @@ -7248,8 +7206,8 @@ "h": 18 }, "frame": { - "x": 201, - "y": 394, + "x": 397, + "y": 259, "w": 20, "h": 18 } @@ -7269,33 +7227,12 @@ "h": 18 }, "frame": { - "x": 201, - "y": 412, + "x": 401, + "y": 277, "w": 20, "h": 18 } }, - { - "filename": "beedrillite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 222, - "y": 357, - "w": 16, - "h": 16 - } - }, { "filename": "wl_ice_heal", "rotated": false, @@ -7311,14 +7248,14 @@ "h": 18 }, "frame": { - "x": 238, - "y": 358, + "x": 395, + "y": 295, "w": 20, "h": 18 } }, { - "filename": "blastoisinite", + "filename": "ampharosite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7332,8 +7269,29 @@ "h": 16 }, "frame": { - "x": 222, - "y": 373, + "x": 415, + "y": 295, + "w": 16, + "h": 16 + } + }, + { + "filename": "audinite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 415, + "y": 311, "w": 16, "h": 16 } @@ -7353,12 +7311,33 @@ "h": 18 }, "frame": { - "x": 221, - "y": 389, + "x": 406, + "y": 327, "w": 20, "h": 18 } }, + { + "filename": "banettite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 412, + "y": 345, + "w": 16, + "h": 16 + } + }, { "filename": "wl_item_urge", "rotated": false, @@ -7375,7 +7354,7 @@ }, "frame": { "x": 221, - "y": 407, + "y": 357, "w": 20, "h": 18 } @@ -7396,7 +7375,7 @@ }, "frame": { "x": 241, - "y": 376, + "y": 358, "w": 20, "h": 18 } @@ -7416,8 +7395,8 @@ "h": 18 }, "frame": { - "x": 241, - "y": 394, + "x": 201, + "y": 360, "w": 20, "h": 18 } @@ -7437,8 +7416,8 @@ "h": 18 }, "frame": { - "x": 241, - "y": 412, + "x": 201, + "y": 378, "w": 20, "h": 18 } @@ -7458,8 +7437,8 @@ "h": 18 }, "frame": { - "x": 258, - "y": 358, + "x": 221, + "y": 375, "w": 20, "h": 18 } @@ -7479,8 +7458,8 @@ "h": 18 }, "frame": { - "x": 261, - "y": 376, + "x": 201, + "y": 396, "w": 20, "h": 18 } @@ -7500,8 +7479,8 @@ "h": 18 }, "frame": { - "x": 261, - "y": 394, + "x": 221, + "y": 393, "w": 20, "h": 18 } @@ -7521,8 +7500,8 @@ "h": 18 }, "frame": { - "x": 261, - "y": 412, + "x": 241, + "y": 376, "w": 20, "h": 18 } @@ -7542,12 +7521,33 @@ "h": 18 }, "frame": { - "x": 278, - "y": 345, + "x": 241, + "y": 394, "w": 20, "h": 18 } }, + { + "filename": "beedrillite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 201, + "y": 414, + "w": 16, + "h": 16 + } + }, { "filename": "wl_super_potion", "rotated": false, @@ -7563,12 +7563,33 @@ "h": 18 }, "frame": { - "x": 298, + "x": 261, "y": 345, "w": 20, "h": 18 } }, + { + "filename": "blastoisinite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 261, + "y": 363, + "w": 16, + "h": 16 + } + }, { "filename": "blazikenite", "rotated": false, @@ -7584,8 +7605,8 @@ "h": 16 }, "frame": { - "x": 318, - "y": 344, + "x": 281, + "y": 345, "w": 16, "h": 16 } @@ -7605,8 +7626,8 @@ "h": 16 }, "frame": { - "x": 334, - "y": 326, + "x": 261, + "y": 379, "w": 16, "h": 16 } @@ -7626,8 +7647,8 @@ "h": 16 }, "frame": { - "x": 334, - "y": 342, + "x": 297, + "y": 345, "w": 16, "h": 16 } @@ -7647,8 +7668,8 @@ "h": 16 }, "frame": { - "x": 350, - "y": 325, + "x": 261, + "y": 395, "w": 16, "h": 16 } @@ -7668,8 +7689,8 @@ "h": 16 }, "frame": { - "x": 350, - "y": 341, + "x": 313, + "y": 345, "w": 16, "h": 16 } @@ -7689,8 +7710,8 @@ "h": 16 }, "frame": { - "x": 366, - "y": 327, + "x": 217, + "y": 414, "w": 16, "h": 16 } @@ -7710,8 +7731,8 @@ "h": 16 }, "frame": { - "x": 366, - "y": 343, + "x": 233, + "y": 412, "w": 16, "h": 16 } @@ -7731,8 +7752,8 @@ "h": 16 }, "frame": { - "x": 382, - "y": 331, + "x": 249, + "y": 412, "w": 16, "h": 16 } @@ -7752,8 +7773,8 @@ "h": 16 }, "frame": { - "x": 398, - "y": 331, + "x": 265, + "y": 411, "w": 16, "h": 16 } @@ -7773,8 +7794,8 @@ "h": 16 }, "frame": { - "x": 414, - "y": 329, + "x": 329, + "y": 345, "w": 16, "h": 16 } @@ -7794,8 +7815,8 @@ "h": 16 }, "frame": { - "x": 382, - "y": 347, + "x": 277, + "y": 363, "w": 16, "h": 16 } @@ -7815,8 +7836,8 @@ "h": 16 }, "frame": { - "x": 398, - "y": 347, + "x": 277, + "y": 379, "w": 16, "h": 16 } @@ -7836,8 +7857,8 @@ "h": 16 }, "frame": { - "x": 414, - "y": 345, + "x": 277, + "y": 395, "w": 16, "h": 16 } @@ -7857,8 +7878,8 @@ "h": 16 }, "frame": { - "x": 281, - "y": 363, + "x": 293, + "y": 361, "w": 16, "h": 16 } @@ -7878,8 +7899,8 @@ "h": 16 }, "frame": { - "x": 281, - "y": 379, + "x": 309, + "y": 361, "w": 16, "h": 16 } @@ -7899,8 +7920,8 @@ "h": 16 }, "frame": { - "x": 297, - "y": 363, + "x": 293, + "y": 377, "w": 16, "h": 16 } @@ -7920,8 +7941,8 @@ "h": 16 }, "frame": { - "x": 281, - "y": 395, + "x": 325, + "y": 361, "w": 16, "h": 16 } @@ -7941,8 +7962,8 @@ "h": 16 }, "frame": { - "x": 297, - "y": 379, + "x": 293, + "y": 393, "w": 16, "h": 16 } @@ -7961,6 +7982,90 @@ "w": 16, "h": 16 }, + "frame": { + "x": 309, + "y": 377, + "w": 16, + "h": 16 + } + }, + { + "filename": "mawilite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 309, + "y": 393, + "w": 16, + "h": 16 + } + }, + { + "filename": "medichamite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 325, + "y": 377, + "w": 16, + "h": 16 + } + }, + { + "filename": "metagrossite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 325, + "y": 393, + "w": 16, + "h": 16 + } + }, + { + "filename": "mewtwonite_x", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, "frame": { "x": 281, "y": 411, @@ -7968,90 +8073,6 @@ "h": 16 } }, - { - "filename": "mawilite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 297, - "y": 395, - "w": 16, - "h": 16 - } - }, - { - "filename": "medichamite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 297, - "y": 411, - "w": 16, - "h": 16 - } - }, - { - "filename": "metagrossite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 313, - "y": 363, - "w": 16, - "h": 16 - } - }, - { - "filename": "mewtwonite_x", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 313, - "y": 379, - "w": 16, - "h": 16 - } - }, { "filename": "mewtwonite_y", "rotated": false, @@ -8067,8 +8088,8 @@ "h": 16 }, "frame": { - "x": 313, - "y": 395, + "x": 297, + "y": 409, "w": 16, "h": 16 } @@ -8089,7 +8110,7 @@ }, "frame": { "x": 313, - "y": 411, + "y": 409, "w": 16, "h": 16 } @@ -8109,8 +8130,8 @@ "h": 16 }, "frame": { - "x": 350, - "y": 357, + "x": 329, + "y": 409, "w": 16, "h": 16 } @@ -8130,8 +8151,8 @@ "h": 16 }, "frame": { - "x": 366, - "y": 359, + "x": 341, + "y": 361, "w": 16, "h": 16 } @@ -8151,8 +8172,8 @@ "h": 16 }, "frame": { - "x": 334, - "y": 358, + "x": 341, + "y": 377, "w": 16, "h": 16 } @@ -8172,8 +8193,8 @@ "h": 16 }, "frame": { - "x": 382, - "y": 363, + "x": 341, + "y": 393, "w": 16, "h": 16 } @@ -8193,8 +8214,8 @@ "h": 16 }, "frame": { - "x": 398, - "y": 363, + "x": 345, + "y": 409, "w": 16, "h": 16 } @@ -8214,7 +8235,7 @@ "h": 16 }, "frame": { - "x": 414, + "x": 412, "y": 361, "w": 16, "h": 16 @@ -8235,8 +8256,8 @@ "h": 16 }, "frame": { - "x": 329, - "y": 374, + "x": 357, + "y": 363, "w": 16, "h": 16 } @@ -8256,8 +8277,8 @@ "h": 16 }, "frame": { - "x": 329, - "y": 390, + "x": 357, + "y": 379, "w": 16, "h": 16 } @@ -8277,8 +8298,8 @@ "h": 16 }, "frame": { - "x": 329, - "y": 406, + "x": 373, + "y": 363, "w": 16, "h": 16 } @@ -8298,8 +8319,8 @@ "h": 16 }, "frame": { - "x": 345, - "y": 374, + "x": 373, + "y": 379, "w": 16, "h": 16 } @@ -8319,8 +8340,8 @@ "h": 16 }, "frame": { - "x": 345, - "y": 390, + "x": 389, + "y": 363, "w": 16, "h": 16 } @@ -8340,8 +8361,8 @@ "h": 16 }, "frame": { - "x": 345, - "y": 406, + "x": 389, + "y": 379, "w": 16, "h": 16 } @@ -8361,8 +8382,8 @@ "h": 16 }, "frame": { - "x": 361, - "y": 375, + "x": 405, + "y": 377, "w": 16, "h": 16 } @@ -8383,7 +8404,7 @@ }, "frame": { "x": 361, - "y": 391, + "y": 395, "w": 16, "h": 16 } @@ -8403,8 +8424,8 @@ "h": 16 }, "frame": { - "x": 361, - "y": 407, + "x": 377, + "y": 395, "w": 16, "h": 16 } @@ -8415,6 +8436,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:934ea4080bad980d4fea720cc771f133:ed564bc47b79b15a763de57045178e88:110e074689c9edd2c54833ce2e4d9270$" + "smartupdate": "$TexturePacker:SmartUpdate:875c6d67e72590dfc6d319101aa31cfa:dd2bb865ecbc5ac7b975ddf70b993334:110e074689c9edd2c54833ce2e4d9270$" } } diff --git a/public/images/items.png b/public/images/items.png index 5f032b30cfb048c2d0cf71ec1e6ad3f051d832c9..1bd7b3af9c3314850fba4eed749f7e3aaf46d8f0 100644 GIT binary patch literal 58657 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

?z@lBAUfj?z?JaC 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 diff --git a/public/images/items/black_sludge.png b/public/images/items/black_sludge.png index 39684a403108232447925646dd56e61186de91c0..37aa31de43eaa5314563d42550b2fc912c1a4210 100644 GIT binary patch literal 285 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10LMXr|#1%--S+b?Odrfh1 zx0hFxf`UTZnx~V1qKqX$e!&b5&u*jvIklcHjv*Dd-cEMxVs_*?a%|F{|N8F}72Ch0 z*iCp5)pV$BSKXZryU%a@wP4MehToe0a=of8?ui-)?*3-$W_;rpDLg~+Oy4}-)iPfE z$-E4QSsur3VBF9WyhCiZBtyVCu8tzN)puSC_$&^3y5kU|f$gXIvT(NAy`NIzYwipE ZW0)Dp%oLNzu)Ha0{(J4HS} zS3f{kKR{VPK370NT0lZnLPAhNLRmvZT0}!yL_}0XL|sHhTSY@(MMPaiMqEZjPDV#y zMo3vkNmEBeU`Iw)M@CpjNMT1wTS!G@NJd~tM^H#dS4c-$NJv#lM`1}vV@XI|Nl8^n zNm)rrU`a`0NlIKwNMcG#WlBp@N=sBqO;t-tV@pj@OHNo!OJYn*WK2w4Oig1=PGwC_ zXH8I8PE1x#Ok++>R8CK3PflV_Qe96|TTo9{QBqrGXMJdBc4=yWYHNaOYlLfRd~Ium zZES;WZFy~Ngl%tpZfu5bY>IAegl=w!Zf}KeZHI4diEnR+Z*Ychaei=diE(d+a&L=r zZ;f(qkaBQ`a&U=qaf5PleR6Vta&wGxafx$ri*#|2ba9e&a*lL!h;(#|b#sk%bB}d& ziFI~}b#{t&c8GR&jdysCcz20-d60W~k$ZcKet(yLfSG@Rm4Jbof`XfZgO!7WoP&g# zgn^=jgq?(ikc5Ssg@l`hg_VVcmxYF$g@}}fhn|LqpoWN=hlQSphMI?mqlbu}hlrtv ziJ6CrmxzU=h=!hshnk6or-_M|iHV?ziK2>#qKb)}iix0#ikgawql$~6i;J0yi=B&$ zq>PKAjEtU)jiZf@rHziKj*F>|jH8Z^rjC!OkBym+jirx{p^%ZIl98yBl&X`Itdy0m zm6orUm#~&_Lxr7i+QEB~r zPKXBfybUXo)DjaFmRaf;#+2riE%t)C$~yn}o*4_)M>rOy7iL$)P2z$3gPnt~dF_#f w4PnbC?W$sQMhO%fejYAXRskL+HU|0u0CSsUMn*K#UjP6A07*qoM6N<$g7)&aN&o-= diff --git a/public/images/items/pb_silver.png b/public/images/items/pb_silver.png new file mode 100644 index 0000000000000000000000000000000000000000..f60a8348a94de2e587a94a66e2d0b4336b25763d GIT binary patch literal 556 zcmV+{0@MA8P)Px$=1D|BR9J=Wmd{G#Kpe+E{iBGD(%MtqOM6a2)4_jWw)gr4>f6Ol_aguOTIA7OlIcy{p6R)B;d-G zt0BwN=Q{CT@tiIY09vK(U-z{yK0N*bAUPd!9M=he(2b)ZC{#NGbzcYK_E(v;WZZUa zZ$IYdT9*_E0`MU+&2c6NZ$Bo-03uVazH0gwgsQ5xA#7zp4{T1m-q-g*zp?@_?%r%_ zu1A}_ixw9WwzFV&54;Ky4Yi9IqFSjKZB$amH3g=GcpxCq4On!Csb0>foV~!fNOt%2uJLj)H z7V`c9cAihl`lomP@z86!>@@t)3%E1ZZ$Xq}(@q~tZb!%L{a6Pv74CM0a}_L8or}6S zR5KZdt6hxImEv~SXcV_9sEwLssV*q=9$Dv{RdLb(Fzpv}GoeqE?kk_+TiBkx-&UIb&JYavlC?UY0EQ#Z8z3`e9qoXIwH>x=pqd z%35Sq>qmzv^CTe%oUfV}4yqwAZUt~i>7)61sNM}8P;br=s$(ZrlZK(vjAsUWM38U+ zr&)QP->kiGTmg*mJkJS+I`+I}KRnc`C{xKEdPLC}N;Oxf^~q{$aPvAo1Q<7u@*{@)RdMQ0{*wIZpce-YC+`B66=Hm#rS9 z%i`PcuPXOyFj)A1^nUO+-SD3k=fyMMs?i6of6#jWc(z?l<@v@Jr5k>0zjZ1vyuJtA y#ewheyXsUbi|VYIH!R!g?3LP&(Df*KfBywl*SaLA^$+XOa?;Me&zBUz_3=2Cwf6C~&~@LKwZ?SJ zE(wE97~16d?B;4H%K^`)c55OY#&D;a_3RAJ4PYgU)7YFM01p}4=;Tsp4yDdsA_GOq zHj$VF9zG>>tstHXDJ3?7#^!Pg8o5$8Hjza&V;TW-x*eovM&aRY_k_*ADM*R)`H4*PKWf!0(48sQn?===)i~112hN$mX3T1 zNb3q!MRVcoU^0@=a@~8`qj7$9tK=(GH*ofDuGS$J!DH*KY9U?MJ4kNh9R#?q2=(Ox zNzfGNF1y`8%XW2_-5!@i-9byY%H4I)C89N=CYraJyuF3a)e5zv?x3~#Z`4wE(AL~V zXGd>`^r#Le$9#<-=Y5X`@BKC?AC;htZMXHmsR`xnlLY!?+^B&cr~V77S8({jvAJ@F d&VQ%0%pa{9Auo9qX&wLo002ovPDHLkV1n*=KDGb= literal 0 HcmV?d00001 diff --git a/src/data/mystery-encounters/mystery-encounter-pokemon-data.ts b/src/data/mystery-encounters/custom-pokemon-data.ts similarity index 68% rename from src/data/mystery-encounters/mystery-encounter-pokemon-data.ts rename to src/data/mystery-encounters/custom-pokemon-data.ts index fc6ce313d41..36ecd133a4e 100644 --- a/src/data/mystery-encounters/mystery-encounter-pokemon-data.ts +++ b/src/data/mystery-encounters/custom-pokemon-data.ts @@ -1,18 +1,20 @@ import { Abilities } from "#enums/abilities"; import { Type } from "#app/data/type"; import { isNullOrUndefined } from "#app/utils"; +import { Nature } from "#enums/nature"; /** * Data that can customize a Pokemon in non-standard ways from its Species - * Currently only used by Mystery Encounters, may need to be renamed if it becomes more widely used + * Currently only used by Mystery Encounters and Mints */ -export class MysteryEncounterPokemonData { +export class CustomPokemonData { public spriteScale: number; public ability: Abilities | -1; public passive: Abilities | -1; + public nature: Nature | -1; public types: Type[]; - constructor(data?: MysteryEncounterPokemonData | Partial) { + constructor(data?: CustomPokemonData | Partial) { if (!isNullOrUndefined(data)) { Object.assign(this, data); } @@ -20,6 +22,7 @@ export class MysteryEncounterPokemonData { this.spriteScale = this.spriteScale ?? -1; this.ability = this.ability ?? -1; this.passive = this.passive ?? -1; + this.nature = this.nature ?? -1; this.types = this.types ?? []; } } diff --git a/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts b/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts index 1de83374db2..6c475070dc6 100644 --- a/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts +++ b/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts @@ -1,4 +1,4 @@ -import { leaveEncounterWithoutBattle, setEncounterExp, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { generateModifierType, leaveEncounterWithoutBattle, setEncounterExp, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { modifierTypes } from "#app/modifier/modifier-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { Species } from "#enums/species"; @@ -13,6 +13,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import i18next from "i18next"; /** the i18n namespace for this encounter */ const namespace = "mysteryEncounters/anOfferYouCantRefuse"; @@ -96,6 +97,8 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = } } + const silverPokeball = generateModifierType(scene, modifierTypes.SILVER_POKEBALL); + encounter.setDialogueToken("itemName", silverPokeball?.name ?? i18next.t("modifierType:ModifierType.SILVER_POKEBALL.name")); encounter.setDialogueToken("liepardName", getPokemonSpecies(Species.LIEPARD).getName()); return true; @@ -121,8 +124,8 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = return true; }) .withOptionPhase(async (scene: BattleScene) => { - // Give the player a Shiny charm - scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.SHINY_CHARM)); + // Give the player a Silver Pokeball + scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.SILVER_POKEBALL)); leaveEncounterWithoutBattle(scene, true); }) .build() diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index e2bf3bf79fe..79f29662ef0 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -11,7 +11,7 @@ import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { Abilities } from "#enums/abilities"; -import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; +import { applyAbilityOverrideToPokemon, applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { Type } from "#app/data/type"; import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; @@ -28,7 +28,7 @@ import { BattlerIndex } from "#app/battle"; import { Moves } from "#enums/moves"; import { EncounterBattleAnim } from "#app/data/battle-anims"; import { MoveCategory } from "#app/data/move"; -import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { EncounterAnim } from "#enums/encounter-anims"; import { Challenges } from "#enums/challenges"; @@ -133,7 +133,7 @@ export const ClowningAroundEncounter: MysteryEncounter = }, { // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter species: getPokemonSpecies(Species.BLACEPHALON), - mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ ability: ability, types: [randSeedInt(18), randSeedInt(18)] }), + mysteryEncounterPokemonData: new CustomPokemonData({ ability: ability, types: [randSeedInt(18), randSeedInt(18)] }), isBoss: true, moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN] }, @@ -352,15 +352,15 @@ export const ClowningAroundEncounter: MysteryEncounter = newTypes.push(secondType); // Apply the type changes (to both base and fusion, if pokemon is fused) - if (!pokemon.mysteryEncounterPokemonData) { - pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(); + if (!pokemon.customPokemonData) { + pokemon.customPokemonData = new CustomPokemonData(); } - pokemon.mysteryEncounterPokemonData.types = newTypes; + pokemon.customPokemonData.types = newTypes; if (pokemon.isFusion()) { - if (!pokemon.fusionMysteryEncounterPokemonData) { - pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData(); + if (!pokemon.fusionCustomPokemonData) { + pokemon.fusionCustomPokemonData = new CustomPokemonData(); } - pokemon.fusionMysteryEncounterPokemonData.types = newTypes; + pokemon.fusionCustomPokemonData.types = newTypes; } } }) @@ -424,17 +424,8 @@ function onYesAbilitySwap(scene: BattleScene, resolve) { const onPokemonSelected = (pokemon: PlayerPokemon) => { // Do ability swap const encounter = scene.currentBattle.mysteryEncounter!; - if (pokemon.isFusion()) { - if (!pokemon.fusionMysteryEncounterPokemonData) { - pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData(); - } - pokemon.fusionMysteryEncounterPokemonData.ability = encounter.misc.ability; - } else { - if (!pokemon.mysteryEncounterPokemonData) { - pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(); - } - pokemon.mysteryEncounterPokemonData.ability = encounter.misc.ability; - } + + applyAbilityOverrideToPokemon(pokemon, encounter.misc.ability); encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender()); scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true)); }; diff --git a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts index c511add0b28..1678c82649b 100644 --- a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts +++ b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts @@ -14,6 +14,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase"; import { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import { Challenges } from "#enums/challenges"; /** i18n namespace for encounter */ const namespace = "mysteryEncounters/darkDeal"; @@ -140,6 +141,7 @@ export const DarkDealEncounter: MysteryEncounter = // Removes random pokemon (including fainted) from party and adds name to dialogue data tokens // Will never return last battle able mon and instead pick fainted/unable to battle const removedPokemon = getRandomPlayerPokemon(scene, true, false, true); + // Get all the pokemon's held items const modifiers = removedPokemon.getHeldItems().filter(m => !(m instanceof PokemonFormChangeItemModifier)); scene.removePokemonFromPlayerParty(removedPokemon); @@ -159,7 +161,13 @@ export const DarkDealEncounter: MysteryEncounter = scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.ROGUE_BALL)); // Start encounter with random legendary (7-10 starter strength) that has level additive - const bossTypes: Type[] = encounter.misc.removedTypes; + // If this is a mono-type challenge, always ensure the required type is filtered for + let bossTypes: Type[] = encounter.misc.removedTypes; + const singleTypeChallenges = scene.gameMode.challenges.filter(c => c.id === Challenges.SINGLE_TYPE); + if (scene.gameMode.isChallenge && singleTypeChallenges.length > 0) { + bossTypes = singleTypeChallenges.map(c => c.value as Type); + } + const bossModifiers: PokemonHeldItemModifier[] = encounter.misc.modifiers; // Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+ const roll = randSeedInt(100); diff --git a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts index 1246572b680..4db0595db26 100644 --- a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts +++ b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts @@ -211,7 +211,7 @@ export const DelibirdyEncounter: MysteryEncounter = } } else { // Check if the player has max stacks of that Healing Charm already - const existing = scene.findModifier(m => m instanceof HealingBoosterModifier) as HealingBoosterModifier; + const existing = scene.findModifier(m => m instanceof PreserveBerryModifier) as PreserveBerryModifier; if (existing && existing.getStackCount() >= existing.getMaxStackCount(scene)) { // At max stacks, give the first party pokemon a Shell Bell instead @@ -220,7 +220,7 @@ export const DelibirdyEncounter: MysteryEncounter = scene.playSound("item_fanfare"); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true); } else { - scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.HEALING_CHARM)); + scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.BERRY_POUCH)); } } @@ -289,8 +289,8 @@ export const DelibirdyEncounter: MysteryEncounter = const encounter = scene.currentBattle.mysteryEncounter!; const modifier = encounter.misc.chosenModifier; - // Check if the player has max stacks of Berry Pouch already - const existing = scene.findModifier(m => m instanceof PreserveBerryModifier) as PreserveBerryModifier; + // Check if the player has max stacks of Healing Charm already + const existing = scene.findModifier(m => m instanceof HealingBoosterModifier) as HealingBoosterModifier; if (existing && existing.getStackCount() >= existing.getMaxStackCount(scene)) { // At max stacks, give the first party pokemon a Shell Bell instead @@ -299,7 +299,7 @@ export const DelibirdyEncounter: MysteryEncounter = scene.playSound("item_fanfare"); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true); } else { - scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.BERRY_POUCH)); + scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.HEALING_CHARM)); } // Remove the modifier if its stacks go to 0 diff --git a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts index cfb87a9e862..917395bf226 100644 --- a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts +++ b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts @@ -4,24 +4,30 @@ import { AttackTypeBoosterModifierType, modifierTypes, } from "#app/modifier/mod import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "#app/battle-scene"; import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; -import { TypeRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; +import { AbilityRequirement, CombinationPokemonRequirement, TypeRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { Species } from "#enums/species"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { Gender } from "#app/data/gender"; import { Type } from "#app/data/type"; import { BattlerIndex } from "#app/battle"; -import { PokemonMove } from "#app/field/pokemon"; +import Pokemon, { PokemonMove } from "#app/field/pokemon"; import { Moves } from "#enums/moves"; import { EncounterBattleAnim } from "#app/data/battle-anims"; import { WeatherType } from "#app/data/weather"; import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { StatusEffect } from "#app/data/status-effect"; import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; -import { applyDamageToPokemon, applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; +import { applyAbilityOverrideToPokemon, applyDamageToPokemon, applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { EncounterAnim } from "#enums/encounter-anims"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import { Abilities } from "#enums/abilities"; +import { BattlerTagType } from "#enums/battler-tag-type"; +import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; +import { Stat } from "#enums/stat"; +import { Ability } from "#app/data/ability"; +import { FIRE_RESISTANT_ABILITIES } from "#app/data/mystery-encounters/requirements/requirement-groups"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/fieryFallout"; @@ -62,16 +68,24 @@ export const FieryFalloutEncounter: MysteryEncounter = { species: volcaronaSpecies, isBoss: false, - gender: Gender.MALE + gender: Gender.MALE, + tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + mysteryEncounterBattleEffects: (pokemon: Pokemon) => { + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.SPDEF, Stat.SPD], 2)); + } }, { species: volcaronaSpecies, isBoss: false, - gender: Gender.FEMALE + gender: Gender.FEMALE, + tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + mysteryEncounterBattleEffects: (pokemon: Pokemon) => { + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.SPDEF, Stat.SPD], 2)); + } } ], doubleBattle: true, - disableSwitch: true + disableSwitch: true, }; encounter.enemyPartyConfigs = [config]; @@ -138,7 +152,7 @@ export const FieryFalloutEncounter: MysteryEncounter = async (scene: BattleScene) => { // Pick battle const encounter = scene.currentBattle.mysteryEncounter!; - setEncounterRewards(scene, { fillRemaining: true }, undefined, () => giveLeadPokemonCharcoal(scene)); + setEncounterRewards(scene, { fillRemaining: true }, undefined, () => giveLeadPokemonAttackTypeBoostItem(scene)); encounter.startOfBattleEffects.push( { @@ -152,18 +166,6 @@ export const FieryFalloutEncounter: MysteryEncounter = targets: [BattlerIndex.PLAYER_2], move: new PokemonMove(Moves.FIRE_SPIN), ignorePp: true - }, - { - sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.ENEMY], - move: new PokemonMove(Moves.QUIVER_DANCE), - ignorePp: true - }, - { - sourceBattlerIndex: BattlerIndex.ENEMY_2, - targets: [BattlerIndex.ENEMY_2], - move: new PokemonMove(Moves.QUIVER_DANCE), - ignorePp: true }); await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]); } @@ -179,7 +181,7 @@ export const FieryFalloutEncounter: MysteryEncounter = ], }, async (scene: BattleScene) => { - // Damage non-fire types and burn 1 random non-fire type member + // Damage non-fire types and burn 1 random non-fire type member + give it Heatproof const encounter = scene.currentBattle.mysteryEncounter!; const nonFireTypes = scene.getParty().filter((p) => p.isAllowedInBattle() && !p.getTypes().includes(Type.FIRE)); @@ -197,7 +199,11 @@ export const FieryFalloutEncounter: MysteryEncounter = if (chosenPokemon.trySetStatus(StatusEffect.BURN)) { // Burn applied encounter.setDialogueToken("burnedPokemon", chosenPokemon.getNameToRender()); + encounter.setDialogueToken("abilityName", new Ability(Abilities.HEATPROOF, 3).name); queueEncounterMessage(scene, `${namespace}:option.2.target_burned`); + + // Also permanently change the burned Pokemon's ability to Heatproof + applyAbilityOverrideToPokemon(chosenPokemon, Abilities.HEATPROOF); } } @@ -208,8 +214,10 @@ export const FieryFalloutEncounter: MysteryEncounter = .withOption( MysteryEncounterOptionBuilder .newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL) - .withPrimaryPokemonRequirement(new TypeRequirement(Type.FIRE, true, 1)) // Will set option3PrimaryName dialogue token automatically - .withSecondaryPokemonRequirement(new TypeRequirement(Type.FIRE, true, 1)) // Will set option3SecondaryName dialogue token automatically + .withPrimaryPokemonRequirement(new CombinationPokemonRequirement( + new TypeRequirement(Type.FIRE, true, 1), + new AbilityRequirement(FIRE_RESISTANT_ABILITIES) + )) // Will set option3PrimaryName dialogue token automatically .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, @@ -231,26 +239,27 @@ export const FieryFalloutEncounter: MysteryEncounter = { fillRemaining: true }, undefined, () => { - giveLeadPokemonCharcoal(scene); + giveLeadPokemonAttackTypeBoostItem(scene); }); const primary = encounter.options[2].primaryPokemon!; - const secondary = encounter.options[2].secondaryPokemon![0]; - setEncounterExp(scene, [primary.id, secondary.id], getPokemonSpecies(Species.VOLCARONA).baseExp * 2); + setEncounterExp(scene, [primary.id], getPokemonSpecies(Species.VOLCARONA).baseExp * 2); leaveEncounterWithoutBattle(scene); }) .build() ) .build(); -function giveLeadPokemonCharcoal(scene: BattleScene) { - // Give first party pokemon Charcoal for free at end of battle +function giveLeadPokemonAttackTypeBoostItem(scene: BattleScene) { + // Give first party pokemon attack type boost item for free at end of battle const leadPokemon = scene.getParty()?.[0]; if (leadPokemon) { - const charcoal = generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]) as AttackTypeBoosterModifierType; - applyModifierTypeToPlayerPokemon(scene, leadPokemon, charcoal); - scene.currentBattle.mysteryEncounter!.setDialogueToken("leadPokemon", leadPokemon.getNameToRender()); - queueEncounterMessage(scene, `${namespace}:found_charcoal`); + const encounter = scene.currentBattle.mysteryEncounter!; + const boosterModifierType = generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER) as AttackTypeBoosterModifierType; + applyModifierTypeToPlayerPokemon(scene, leadPokemon, boosterModifierType); + encounter.setDialogueToken("itemName", boosterModifierType.name); + encounter.setDialogueToken("leadPokemon", leadPokemon.getNameToRender()); + queueEncounterMessage(scene, `${namespace}:found_item`); } } diff --git a/src/data/mystery-encounters/encounters/mysterious-challengers-encounter.ts b/src/data/mystery-encounters/encounters/mysterious-challengers-encounter.ts index af01ecbb97c..abf19a5e2f9 100644 --- a/src/data/mystery-encounters/encounters/mysterious-challengers-encounter.ts +++ b/src/data/mystery-encounters/encounters/mysterious-challengers-encounter.ts @@ -56,7 +56,13 @@ export const MysteriousChallengersEncounter: MysteryEncounter = // Hard difficulty trainer is another random trainer, but with AVERAGE_BALANCED config // Number of mons is based off wave: 1-20 is 2, 20-40 is 3, etc. capping at 6 after wave 100 - const hardTrainerType = scene.arena.randomTrainerType(scene.currentBattle.waveIndex); + let retries = 0; + let hardTrainerType = scene.arena.randomTrainerType(scene.currentBattle.waveIndex); + while (retries < 5 && hardTrainerType === normalTrainerType) { + // Will try to use a different trainer from the normal trainer type + hardTrainerType = scene.arena.randomTrainerType(scene.currentBattle.waveIndex); + retries++; + } const hardTemplate = new TrainerPartyCompoundTemplate( new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER, false, true), new TrainerPartyTemplate( diff --git a/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts b/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts index a8ddfc28ae9..aaf08fadfcb 100644 --- a/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts +++ b/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts @@ -21,7 +21,7 @@ import i18next from "i18next"; const namespace = "mysteryEncounters/shadyVitaminDealer"; const VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER = 1.5; -const VITAMIN_DEALER_EXPENSIVE_PRICE_MULTIPLIER = 3.5; +const VITAMIN_DEALER_EXPENSIVE_PRICE_MULTIPLIER = 5; /** * Shady Vitamin Dealer encounter. diff --git a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts index 5abd4839c0c..0545fa5f0fd 100644 --- a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts +++ b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts @@ -18,7 +18,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode import { PartyHealPhase } from "#app/phases/party-heal-phase"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { BerryType } from "#enums/berry-type"; -import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; /** i18n namespace for the encounter */ const namespace = "mysteryEncounters/slumberingSnorlax"; @@ -72,7 +72,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = stackCount: 2 }, ], - mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }), + mysteryEncounterPokemonData: new CustomPokemonData({ spriteScale: 1.25 }), aiType: AiType.SMART // Required to ensure Snorlax uses Sleep Talk while it is asleep }; const config: EnemyPartyConfig = { diff --git a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts index 24e777d8c88..19b58a7f76e 100644 --- a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts @@ -162,7 +162,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = if (pokemon2CommonEggs > 0) { const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") }); pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText }); - encounter.setDialogueToken("pokemon1CommonEggs", eggsText); + encounter.setDialogueToken("pokemon2CommonEggs", eggsText); } encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip; @@ -219,7 +219,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = encounter.misc.chosenPokemon = pokemon1; encounter.setDialogueToken("chosenPokemon", pokemon1.getNameToRender()); const eggOptions = getEggOptions(scene, pokemon1CommonEggs, pokemon1RareEggs); - setEncounterRewards(scene, { fillRemaining: true }, eggOptions); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SOOTHE_BELL], fillRemaining: true }, eggOptions); // Remove all Pokemon from the party except the chosen Pokemon removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon1); @@ -271,7 +271,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = encounter.misc.chosenPokemon = pokemon2; encounter.setDialogueToken("chosenPokemon", pokemon2.getNameToRender()); const eggOptions = getEggOptions(scene, pokemon2CommonEggs, pokemon2RareEggs); - setEncounterRewards(scene, { fillRemaining: true }, eggOptions); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SOOTHE_BELL], fillRemaining: true }, eggOptions); // Remove all Pokemon from the party except the chosen Pokemon removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon2); @@ -323,7 +323,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = encounter.misc.chosenPokemon = pokemon3; encounter.setDialogueToken("chosenPokemon", pokemon3.getNameToRender()); const eggOptions = getEggOptions(scene, pokemon3CommonEggs, pokemon3RareEggs); - setEncounterRewards(scene, { fillRemaining: true }, eggOptions); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SOOTHE_BELL], fillRemaining: true }, eggOptions); // Remove all Pokemon from the party except the chosen Pokemon removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon3); @@ -460,12 +460,16 @@ function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number] } // Maximum of 30 points - const totalPoints = Math.min(pointsFromStarterTier + pointsFromBst, 30); + let totalPoints = Math.min(pointsFromStarterTier + pointsFromBst, 30); - // 1 Rare egg for every 6 points - const numRares = Math.floor(totalPoints / 6); + // First 5 points go to Common eggs + let numCommons = Math.min(totalPoints, 5); + totalPoints -= numCommons; + + // Then, 1 Rare egg for every 4 points + const numRares = Math.floor(totalPoints / 4); // 1 Common egg for every point leftover - const numCommons = totalPoints % 6; + numCommons += totalPoints % 4; return [numCommons, numRares]; } diff --git a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts index bd99c8babf7..4893d95d41b 100644 --- a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -14,7 +14,7 @@ import { BattlerIndex } from "#app/battle"; import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; -import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; import { Stat } from "#enums/stat"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; @@ -79,7 +79,7 @@ export const TheStrongStuffEncounter: MysteryEncounter = species: getPokemonSpecies(Species.SHUCKLE), isBoss: true, bossSegments: 5, - mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }), + mysteryEncounterPokemonData: new CustomPokemonData({ spriteScale: 1.25 }), nature: Nature.BOLD, moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER], modifierConfigs: [ diff --git a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts index 9673924e6d1..bbf52b0c118 100644 --- a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts +++ b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts @@ -70,7 +70,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = moveSet: [Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH] }; const config: EnemyPartyConfig = { - levelAdditiveModifier: 1, + levelAdditiveModifier: 0.5, pokemonConfigs: [pokemonConfig], disableSwitch: true }; diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index 1e68a894bc4..4842ec0a0ce 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -4,23 +4,31 @@ import { Species } from "#enums/species"; import BattleScene from "#app/battle-scene"; import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; -import { leaveEncounterWithoutBattle, setEncounterRewards, } from "../utils/encounter-phase-utils"; +import { EnemyPartyConfig, EnemyPokemonConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, } from "../utils/encounter-phase-utils"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import { IntegerHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils"; import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species"; -import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; +import { HiddenAbilityRateBoosterModifier, PokemonBaseStatFlatModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; import { achvs } from "#app/system/achv"; -import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; -import { modifierTypes } from "#app/modifier/modifier-type"; +import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; 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 { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { Challenges } from "#enums/challenges"; +import { ModifierTier } from "#app/modifier/modifier-tier"; +import { PlayerGender } from "#enums/player-gender"; +import { TrainerType } from "#enums/trainer-type"; +import PokemonData from "#app/system/pokemon-data"; +import { Nature } from "#enums/nature"; +import HeldModifierConfig from "#app/interfaces/held-modifier-config"; +import { trainerConfigs, TrainerPartyTemplate } from "#app/data/trainer-config"; +import { PartyMemberStrength } from "#enums/party-member-strength"; /** i18n namespace for encounter */ const namespace = "mysteryEncounters/weirdDream"; @@ -80,10 +88,9 @@ const EXCLUDED_TRANSFORMATION_SPECIES = [ const SUPER_LEGENDARY_BST_THRESHOLD = 600; const NON_LEGENDARY_BST_THRESHOLD = 570; -const GAIN_OLD_GATEAU_ITEM_BST_THRESHOLD = 450; /** 0-100 */ -const PERCENT_LEVEL_LOSS_ON_REFUSE = 12.5; +const PERCENT_LEVEL_LOSS_ON_REFUSE = 10; /** * Value ranges of the resulting species BST transformations after adding values to original species @@ -105,7 +112,8 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.WEIRD_DREAM) .withEncounterTier(MysteryEncounterTier.ROGUE) .withDisallowedChallenges(Challenges.SINGLE_TYPE, Challenges.SINGLE_GENERATION) - .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) + // TODO: should reset minimum wave to 10 when there are more Rogue tiers in pool. Matching Dark Deal minimum for now. + .withSceneWaveRangeRequirement(30, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1]) .withIntroSpriteConfigs([ { spriteKey: "weird_dream_woman", @@ -130,6 +138,15 @@ export const WeirdDreamEncounter: MysteryEncounter = .withQuery(`${namespace}:query`) .withOnInit((scene: BattleScene) => { scene.loadBgm("mystery_encounter_weird_dream", "mystery_encounter_weird_dream.mp3"); + + // Calculate all the newly transformed Pokemon and begin asset load + const teamTransformations = getTeamTransformations(scene); + const loadAssets = teamTransformations.map(t => (t.newPokemon as PlayerPokemon).loadAssets()); + scene.currentBattle.mysteryEncounter!.misc = { + teamTransformations, + loadAssets + }; + return true; }) .withOnVisualsStart((scene: BattleScene) => { @@ -155,13 +172,10 @@ export const WeirdDreamEncounter: MysteryEncounter = doShowDreamBackground(scene); }); - // Calculate all the newly transformed Pokemon and begin asset load - const teamTransformations = getTeamTransformations(scene); - const loadAssets = teamTransformations.map(t => (t.newPokemon as PlayerPokemon).loadAssets()); - scene.currentBattle.mysteryEncounter!.misc = { - teamTransformations, - loadAssets - }; + for (const transformation of scene.currentBattle.mysteryEncounter!.misc.teamTransformations) { + scene.removePokemonFromPlayerParty(transformation.previousPokemon, false); + scene.getParty().push(transformation.newPokemon); + } }) .withOptionPhase(async (scene: BattleScene) => { // Starts cutscene dialogue, but does not await so that cutscene plays as player goes through dialogue @@ -192,7 +206,7 @@ export const WeirdDreamEncounter: MysteryEncounter = await showEncounterText(scene, `${namespace}:option.1.dream_complete`); await doNewTeamPostProcess(scene, transformations); - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM, modifierTypes.ROGUE_BALL, modifierTypes.MINT, modifierTypes.MINT]}); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM, modifierTypes.ROGUE_BALL, modifierTypes.MINT, modifierTypes.MINT, modifierTypes.MINT], fillRemaining: false }); leaveEncounterWithoutBattle(scene, true); }) .build() @@ -208,7 +222,88 @@ export const WeirdDreamEncounter: MysteryEncounter = ], }, async (scene: BattleScene) => { - // Reduce party levels by 20% + // Battle your "future" team for some item rewards + const transformations: PokemonTransformation[] = scene.currentBattle.mysteryEncounter!.misc.teamTransformations; + + // Uses the pokemon that player's party would have transformed into + const enemyPokemonConfigs: EnemyPokemonConfig[] = []; + for (const transformation of transformations) { + const newPokemon = transformation.newPokemon; + const previousPokemon = transformation.previousPokemon; + + await postProcessTransformedPokemon(scene, previousPokemon, newPokemon, newPokemon.species.getRootSpeciesId(), true); + + const dataSource = new PokemonData(newPokemon); + dataSource.player = false; + + // Copy all held items + const heldItems = previousPokemon.getHeldItems(); + const newPokemonHeldItemConfigs: HeldModifierConfig[] = heldItems.map(previousMod => { + return { + modifier: previousMod.clone() as PokemonHeldItemModifier, + stackCount: previousMod.getStackCount(), + isTransferable: false + }; + }); + + if (newPokemonHeldItemConfigs.filter(config => config.modifier instanceof PokemonBaseStatFlatModifier).length === 0) { + // Also add Old Gateau (even on transformed mons that shouldn't normally get it) + newPokemonHeldItemConfigs.push({ + modifier: generateModifierType(scene, modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU) as PokemonHeldItemModifierType, + stackCount: 1, + isTransferable: false + }); + } + + const enemyConfig: EnemyPokemonConfig = { + species: transformation.newSpecies, + isBoss: newPokemon.getSpeciesForm().getBaseStatTotal() > NON_LEGENDARY_BST_THRESHOLD, + level: previousPokemon.level, + dataSource: dataSource, + modifierConfigs: newPokemonHeldItemConfigs + }; + + enemyPokemonConfigs.push(enemyConfig); + } + + const genderIndex = scene.gameData.gender ?? PlayerGender.UNSET; + const trainerConfig = trainerConfigs[genderIndex === PlayerGender.FEMALE ? TrainerType.FUTURE_SELF_F : TrainerType.FUTURE_SELF_M].clone(); + trainerConfig.setPartyTemplates(new TrainerPartyTemplate(transformations.length, PartyMemberStrength.STRONG)); + const enemyPartyConfig: EnemyPartyConfig = { + trainerConfig: trainerConfig, + pokemonConfigs: enemyPokemonConfigs, + female: genderIndex === PlayerGender.FEMALE + }; + + const onBeforeRewards = () => { + // Before battle rewards, unlock the passive on a pokemon in the player's team for the rest of the run (not permanently) + // One random pokemon will get its passive unlocked + const passiveDisabledPokemon = scene.getParty().filter(p => !p.passive); + if (passiveDisabledPokemon?.length > 0) { + const enablePassiveMon = passiveDisabledPokemon[randSeedInt(passiveDisabledPokemon.length)]; + enablePassiveMon.passive = true; + enablePassiveMon.updateInfo(true); + } + }; + + setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], fillRemaining: false }, undefined, onBeforeRewards); + + await showEncounterText(scene, `${namespace}:option.2.selected_2`, null, undefined, true); + await initBattleWithEnemyConfig(scene, enemyPartyConfig); + } + ) + .withSimpleOption( + { + buttonLabel: `${namespace}:option.3.label`, + buttonTooltip: `${namespace}:option.3.tooltip`, + selected: [ + { + text: `${namespace}:option.3.selected`, + }, + ], + }, + async (scene: BattleScene) => { + // Leave, reduce party levels by 10% for (const pokemon of scene.getParty()) { pokemon.level = Math.max(Math.ceil((100 - PERCENT_LEVEL_LOSS_ON_REFUSE) / 100 * pokemon.level), 1); pokemon.exp = getLevelTotalExp(pokemon.level, pokemon.species.growthRate); @@ -234,7 +329,7 @@ interface PokemonTransformation { function getTeamTransformations(scene: BattleScene): PokemonTransformation[] { const party = scene.getParty(); // Removes all pokemon from the party - const alreadyUsedSpecies: PokemonSpecies[] = []; + const alreadyUsedSpecies: PokemonSpecies[] = party.map(p => p.species); const pokemonTransformations: PokemonTransformation[] = party.map(p => { return { previousPokemon: p @@ -249,11 +344,11 @@ function getTeamTransformations(scene: BattleScene): PokemonTransformation[] { // First, roll 2 of the party members to new Pokemon at a +90 to +110 BST difference // Then, roll the remainder of the party members at a +40 to +50 BST difference const numPokemon = party.length; + const removedPokemon = randSeedShuffle(party.slice(0)); for (let i = 0; i < numPokemon; i++) { - const removed = party[randSeedInt(party.length)]; + const removed = removedPokemon[i]; const index = pokemonTransformations.findIndex(p => p.previousPokemon.id === removed.id); pokemonTransformations[index].heldItems = removed.getHeldItems().filter(m => !(m instanceof PokemonFormChangeItemModifier)); - scene.removePokemonFromPlayerParty(removed, false); const bst = removed.calculateBaseStats().reduce((a, b) => a + b, 0); let newBstRange: [number, number]; @@ -275,14 +370,13 @@ function getTeamTransformations(scene: BattleScene): PokemonTransformation[] { pokemonTransformations[index].newSpecies = newSpecies; + console.log("New species: " + JSON.stringify(newSpecies)); alreadyUsedSpecies.push(newSpecies); } for (const transformation of pokemonTransformations) { const newAbilityIndex = randSeedInt(transformation.newSpecies.getAbilityCount()); - const newPlayerPokemon = scene.addPlayerPokemon(transformation.newSpecies, transformation.previousPokemon.level, newAbilityIndex, undefined); - transformation.newPokemon = newPlayerPokemon; - scene.getParty().push(newPlayerPokemon); + transformation.newPokemon = scene.addPlayerPokemon(transformation.newSpecies, transformation.previousPokemon.level, newAbilityIndex, undefined); } return pokemonTransformations; @@ -295,119 +389,16 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon const newPokemon = transformation.newPokemon; const speciesRootForm = newPokemon.species.getRootSpeciesId(); - // Roll HA a second time - if (newPokemon.species.abilityHidden) { - const hiddenIndex = newPokemon.species.ability2 ? 2 : 1; - if (newPokemon.abilityIndex < hiddenIndex) { - const hiddenAbilityChance = new IntegerHolder(256); - scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); - - const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value); - - if (hasHiddenAbility) { - newPokemon.abilityIndex = hiddenIndex; - } - } + if (await postProcessTransformedPokemon(scene, previousPokemon, newPokemon, speciesRootForm)) { + atLeastOneNewStarter = true; } - // Roll IVs a second time - newPokemon.ivs = newPokemon.ivs.map(iv => { - const newValue = randSeedInt(31); - return newValue > iv ? newValue : iv; - }); - - // For pokemon at/below 570 BST or any shiny pokemon, unlock it permanently as if you had caught it - if (newPokemon.getSpeciesForm().getBaseStatTotal() <= NON_LEGENDARY_BST_THRESHOLD || newPokemon.isShiny()) { - if (newPokemon.getSpeciesForm().abilityHidden && newPokemon.abilityIndex === newPokemon.getSpeciesForm().getAbilityCount() - 1) { - scene.validateAchv(achvs.HIDDEN_ABILITY); - } - - if (newPokemon.species.subLegendary) { - scene.validateAchv(achvs.CATCH_SUB_LEGENDARY); - } - - if (newPokemon.species.legendary) { - scene.validateAchv(achvs.CATCH_LEGENDARY); - } - - if (newPokemon.species.mythical) { - scene.validateAchv(achvs.CATCH_MYTHICAL); - } - - scene.gameData.updateSpeciesDexIvs(newPokemon.species.getRootSpeciesId(true), newPokemon.ivs); - const newStarterUnlocked = await scene.gameData.setPokemonCaught(newPokemon, true, false, false); - if (newStarterUnlocked) { - atLeastOneNewStarter = true; - await showEncounterText(scene, i18next.t("battle:addedAsAStarter", { pokemonName: getPokemonSpecies(speciesRootForm).getName() })); - } - } - - // If the previous pokemon had pokerus, transfer to new pokemon - newPokemon.pokerus = previousPokemon.pokerus; - - // Transfer previous Pokemon's luck value - newPokemon.luck = previousPokemon.getLuck(); - - // If the previous pokemon had higher IVs, override to those (after updating dex IVs > prevents perfect 31s on a new unlock) - newPokemon.ivs = newPokemon.ivs.map((iv, index) => { - return previousPokemon.ivs[index] > iv ? previousPokemon.ivs[index] : iv; - }); - - // For pokemon that the player owns (including ones just caught), gain a candy - if (!!scene.gameData.dexData[speciesRootForm].caughtAttr) { - scene.gameData.addStarterCandy(getPokemonSpecies(speciesRootForm), 1); - } - - // Set the moveset of the new pokemon to be the same as previous, but with 1 egg move and 1 (attempted) STAB move of the new species - newPokemon.generateAndPopulateMoveset(); - // Store a copy of a "standard" generated moveset for the new pokemon, will be used later for finding a favored move - const newPokemonGeneratedMoveset = newPokemon.moveset; - - newPokemon.moveset = previousPokemon.moveset; - - const newEggMoveIndex = await addEggMoveToNewPokemonMoveset(scene, newPokemon, speciesRootForm); - - // Try to add a favored STAB move (might fail if Pokemon already knows a bunch of moves from newPokemonGeneratedMoveset) - addFavoredMoveToNewPokemonMoveset(newPokemon, newPokemonGeneratedMoveset, newEggMoveIndex); - - // Randomize the second type of the pokemon - // If the pokemon does not normally have a second type, it will gain 1 - const newTypes = [newPokemon.getTypes()[0]]; - let newType = randSeedInt(18) as Type; - while (newType === newTypes[0]) { - newType = randSeedInt(18) as Type; - } - newTypes.push(newType); - if (!newPokemon.mysteryEncounterPokemonData) { - newPokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(); - } - newPokemon.mysteryEncounterPokemonData.types = newTypes; - + // Copy old items to new pokemon for (const item of transformation.heldItems) { item.pokemonId = newPokemon.id; await scene.addModifier(item, false, false, false, true); } - // Any pokemon that is at or below 450 BST gets +20 permanent BST to 3 stats: HP (halved, +10), lowest of Atk/SpAtk, and lowest of Def/SpDef - if (newPokemon.getSpeciesForm().getBaseStatTotal() <= GAIN_OLD_GATEAU_ITEM_BST_THRESHOLD) { - const stats: Stat[] = [Stat.HP]; - const baseStats = newPokemon.getSpeciesForm().baseStats.slice(0); - // Attack or SpAtk - stats.push(baseStats[Stat.ATK] < baseStats[Stat.SPATK] ? Stat.ATK : Stat.SPATK); - // Def or SpDef - stats.push(baseStats[Stat.DEF] < baseStats[Stat.SPDEF] ? Stat.DEF : Stat.SPDEF); - const modType = modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU() - .generateType(scene.getParty(), [20, stats]) - ?.withIdFromFunc(modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU); - const modifier = modType?.newModifier(newPokemon); - if (modifier) { - await scene.addModifier(modifier, false, false, false, true); - } - } - - // Enable passive if previous had it - newPokemon.passive = previousPokemon.passive; - newPokemon.calculateStats(); await newPokemon.updateInfo(); } @@ -426,6 +417,133 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon } } +/** + * Applies special changes to the newly transformed pokemon, such as passing previous moves, gaining egg moves, etc. + * Returns whether the transformed pokemon unlocks a new starter for the player. + * @param scene + * @param previousPokemon + * @param newPokemon + * @param speciesRootForm + * @param forBattle Default `false`. If true, will perform notifications and dex unlocks for the player. + */ +async function postProcessTransformedPokemon(scene: BattleScene, previousPokemon: PlayerPokemon, newPokemon: PlayerPokemon, speciesRootForm: Species, forBattle: boolean = false): Promise { + let isNewStarter = false; + // Roll HA a second time + if (newPokemon.species.abilityHidden) { + const hiddenIndex = newPokemon.species.ability2 ? 2 : 1; + if (newPokemon.abilityIndex < hiddenIndex) { + const hiddenAbilityChance = new IntegerHolder(256); + scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); + + const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value); + + if (hasHiddenAbility) { + newPokemon.abilityIndex = hiddenIndex; + } + } + } + + // Roll IVs a second time + newPokemon.ivs = newPokemon.ivs.map(iv => { + const newValue = randSeedInt(31); + return newValue > iv ? newValue : iv; + }); + + // Roll a neutral nature + newPokemon.nature = [Nature.HARDY, Nature.DOCILE, Nature.BASHFUL, Nature.QUIRKY, Nature.SERIOUS][randSeedInt(5)]; + + // For pokemon at/below 570 BST or any shiny pokemon, unlock it permanently as if you had caught it + if (!forBattle && (newPokemon.getSpeciesForm().getBaseStatTotal() <= NON_LEGENDARY_BST_THRESHOLD || newPokemon.isShiny())) { + if (newPokemon.getSpeciesForm().abilityHidden && newPokemon.abilityIndex === newPokemon.getSpeciesForm().getAbilityCount() - 1) { + scene.validateAchv(achvs.HIDDEN_ABILITY); + } + + if (newPokemon.species.subLegendary) { + scene.validateAchv(achvs.CATCH_SUB_LEGENDARY); + } + + if (newPokemon.species.legendary) { + scene.validateAchv(achvs.CATCH_LEGENDARY); + } + + if (newPokemon.species.mythical) { + scene.validateAchv(achvs.CATCH_MYTHICAL); + } + + scene.gameData.updateSpeciesDexIvs(newPokemon.species.getRootSpeciesId(true), newPokemon.ivs); + const newStarterUnlocked = await scene.gameData.setPokemonCaught(newPokemon, true, false, false); + if (newStarterUnlocked) { + isNewStarter = true; + await showEncounterText(scene, i18next.t("battle:addedAsAStarter", { pokemonName: getPokemonSpecies(speciesRootForm).getName() })); + } + } + + // If the previous pokemon had pokerus, transfer to new pokemon + newPokemon.pokerus = previousPokemon.pokerus; + + // Transfer previous Pokemon's luck value + newPokemon.luck = previousPokemon.getLuck(); + + // If the previous pokemon had higher IVs, override to those (after updating dex IVs > prevents perfect 31s on a new unlock) + newPokemon.ivs = newPokemon.ivs.map((iv, index) => { + return previousPokemon.ivs[index] > iv ? previousPokemon.ivs[index] : iv; + }); + + // For pokemon that the player owns (including ones just caught), gain a candy + if (!forBattle && !!scene.gameData.dexData[speciesRootForm].caughtAttr) { + scene.gameData.addStarterCandy(getPokemonSpecies(speciesRootForm), 1); + } + + // Set the moveset of the new pokemon to be the same as previous, but with 1 egg move and 1 (attempted) STAB move of the new species + newPokemon.generateAndPopulateMoveset(); + // Store a copy of a "standard" generated moveset for the new pokemon, will be used later for finding a favored move + const newPokemonGeneratedMoveset = newPokemon.moveset; + + newPokemon.moveset = previousPokemon.moveset.slice(0); + + const newEggMoveIndex = await addEggMoveToNewPokemonMoveset(scene, newPokemon, speciesRootForm, forBattle); + + // Try to add a favored STAB move (might fail if Pokemon already knows a bunch of moves from newPokemonGeneratedMoveset) + addFavoredMoveToNewPokemonMoveset(newPokemon, newPokemonGeneratedMoveset, newEggMoveIndex); + + // Randomize the second type of the pokemon + // If the pokemon does not normally have a second type, it will gain 1 + const newTypes = [newPokemon.getTypes()[0]]; + let newType = randSeedInt(18) as Type; + while (newType === newTypes[0]) { + newType = randSeedInt(18) as Type; + } + newTypes.push(newType); + if (!newPokemon.customPokemonData) { + newPokemon.customPokemonData = new CustomPokemonData(); + } + newPokemon.customPokemonData.types = newTypes; + + // Any pokemon that is below 570 BST gets +20 permanent BST to 3 stats: lowest of HP/Spd, lowest of Atk/SpAtk, and lowest of Def/SpDef + if (newPokemon.getSpeciesForm().getBaseStatTotal() < NON_LEGENDARY_BST_THRESHOLD) { + const stats: Stat[] = []; + const baseStats = newPokemon.getSpeciesForm().baseStats.slice(0); + // HP or Speed + stats.push(baseStats[Stat.HP] < baseStats[Stat.SPD] ? Stat.HP : Stat.SPD); + // Attack or SpAtk + stats.push(baseStats[Stat.ATK] < baseStats[Stat.SPATK] ? Stat.ATK : Stat.SPATK); + // Def or SpDef + stats.push(baseStats[Stat.DEF] < baseStats[Stat.SPDEF] ? Stat.DEF : Stat.SPDEF); + const modType = modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU() + .generateType(scene.getParty(), [20, stats]) + ?.withIdFromFunc(modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU); + const modifier = modType?.newModifier(newPokemon); + if (modifier) { + await scene.addModifier(modifier, false, false, false, true); + } + } + + // Enable passive if previous had it + newPokemon.passive = previousPokemon.passive; + + return isNewStarter; +} + function getTransformedSpecies(originalBst: number, bstSearchRange: [number, number], hasPokemonBstHigherThan600: boolean, hasPokemonBstBetween570And600: boolean, alreadyUsedSpecies: PokemonSpecies[]): PokemonSpecies { let newSpecies: PokemonSpecies | undefined; while (isNullOrUndefined(newSpecies)) { @@ -549,7 +667,7 @@ function doSideBySideTransformations(scene: BattleScene, transformations: Pokemo * @param newPokemon * @param speciesRootForm */ -async function addEggMoveToNewPokemonMoveset(scene: BattleScene, newPokemon: PlayerPokemon, speciesRootForm: Species): Promise { +async function addEggMoveToNewPokemonMoveset(scene: BattleScene, newPokemon: PlayerPokemon, speciesRootForm: Species, forBattle: boolean = false): Promise { let eggMoveIndex: null | number = null; const eggMoves = newPokemon.getEggMoves()?.slice(0); if (eggMoves) { @@ -575,7 +693,7 @@ async function addEggMoveToNewPokemonMoveset(scene: BattleScene, newPokemon: Pla } // For pokemon that the player owns (including ones just caught), unlock the egg move - if (!isNullOrUndefined(randomEggMoveIndex) && !!scene.gameData.dexData[speciesRootForm].caughtAttr) { + if (!forBattle && !isNullOrUndefined(randomEggMoveIndex) && !!scene.gameData.dexData[speciesRootForm].caughtAttr) { await scene.gameData.setEggMoveUnlocked(getPokemonSpecies(speciesRootForm), randomEggMoveIndex, true); } } diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index 5fa2a7066a5..4eb15d31df8 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -577,10 +577,10 @@ export class AbilityRequirement extends EncounterPokemonRequirement { override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] { if (!this.invertQuery) { - return partyPokemon.filter((pokemon) => this.requiredAbilities.some((ability) => pokemon.getAbility().id === ability)); + return partyPokemon.filter((pokemon) => this.requiredAbilities.some((ability) => pokemon.getAbility().id === ability || pokemon.getPassiveAbility().id === ability)); } else { - // for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilitiess - return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((ability) => pokemon.getAbility().id === ability).length === 0); + // for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilities + return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((ability) => pokemon.getAbility().id === ability || pokemon.getPassiveAbility().id === ability).length === 0); } } diff --git a/src/data/mystery-encounters/requirements/requirement-groups.ts b/src/data/mystery-encounters/requirements/requirement-groups.ts index 63c899fc5e9..3eac6806407 100644 --- a/src/data/mystery-encounters/requirements/requirement-groups.ts +++ b/src/data/mystery-encounters/requirements/requirement-groups.ts @@ -118,3 +118,17 @@ export const EXTORTION_ABILITIES = [ Abilities.SUCTION_CUPS, Abilities.STICKY_HOLD ]; + +/** + * Abilities that signify resistance to fire + */ +export const FIRE_RESISTANT_ABILITIES = [ + Abilities.FLAME_BODY, + Abilities.FLASH_FIRE, + Abilities.WELL_BAKED_BODY, + Abilities.HEATPROOF, + Abilities.THERMAL_EXCHANGE, + Abilities.THICK_FAT, + Abilities.WATER_BUBBLE, + Abilities.MAGMA_ARMOR +]; diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index ca02c8bdfd6..6f7e6c259f3 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -27,7 +27,7 @@ import { Status, StatusEffect } from "#app/data/status-effect"; import { TrainerConfig, trainerConfigs, TrainerSlot } from "#app/data/trainer-config"; import PokemonSpecies from "#app/data/pokemon-species"; import { Egg, IEggOptions } from "#app/data/egg"; -import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; import HeldModifierConfig from "#app/interfaces/held-modifier-config"; import { MovePhase } from "#app/phases/move-phase"; import { EggLapsePhase } from "#app/phases/egg-lapse-phase"; @@ -71,7 +71,7 @@ export interface EnemyPokemonConfig { nickname?: string; bossSegments?: number; bossSegmentModifier?: number; // Additive to the determined segment number - mysteryEncounterPokemonData?: MysteryEncounterPokemonData; + mysteryEncounterPokemonData?: CustomPokemonData; formIndex?: number; abilityIndex?: number; level?: number; @@ -145,7 +145,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig: newTrainer.setVisible(false); scene.field.add(newTrainer); scene.currentBattle.trainer = newTrainer; - loadEnemyAssets.push(newTrainer.loadAssets()); + loadEnemyAssets.push(newTrainer.loadAssets().then(() => newTrainer.initSprite())); battle.enemyLevels = scene.currentBattle.trainer.getPartyLevels(scene.currentBattle.waveIndex); } else { @@ -251,7 +251,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig: // Set custom mystery encounter data fields (such as sprite scale, custom abilities, types, etc.) if (!isNullOrUndefined(config.mysteryEncounterPokemonData)) { - enemyPokemon.mysteryEncounterPokemonData = config.mysteryEncounterPokemonData; + enemyPokemon.customPokemonData = config.mysteryEncounterPokemonData; } // Set Boss diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index fb67305c78d..f6d4b8c38ae 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -20,6 +20,8 @@ import { Gender } from "#app/data/gender"; import { PermanentStat } from "#enums/stat"; import { VictoryPhase } from "#app/phases/victory-phase"; import { SummaryUiMode } from "#app/ui/summary-ui-handler"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; +import { Abilities } from "#enums/abilities"; /** Will give +1 level every 10 waves */ export const STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER = 1; @@ -832,3 +834,23 @@ export function isPokemonValidForEncounterOptionSelection(pokemon: Pokemon, scen return null; } + +/** + * Permanently overrides the ability (not passive) of a pokemon. + * If the pokemon is a fusion, instead overrides the fused pokemon's ability. + * @param pokemon + * @param ability + */ +export function applyAbilityOverrideToPokemon(pokemon: Pokemon, ability: Abilities) { + if (pokemon.isFusion()) { + if (!pokemon.fusionCustomPokemonData) { + pokemon.fusionCustomPokemonData = new CustomPokemonData(); + } + pokemon.fusionCustomPokemonData.ability = ability; + } else { + if (!pokemon.customPokemonData) { + pokemon.customPokemonData = new CustomPokemonData(); + } + pokemon.customPokemonData.ability = ability; + } +} diff --git a/src/data/pokemon-evolutions.ts b/src/data/pokemon-evolutions.ts index fc1dfffb1ec..aac48b57e90 100644 --- a/src/data/pokemon-evolutions.ts +++ b/src/data/pokemon-evolutions.ts @@ -10,7 +10,7 @@ import { Biome } from "#enums/biome"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import { TimeOfDay } from "#enums/time-of-day"; -import { DamageMoneyRewardModifier, ExtraModifierModifier, MoneyMultiplierModifier } from "#app/modifier/modifier"; +import { DamageMoneyRewardModifier, ExtraModifierModifier, MoneyMultiplierModifier, TempExtraModifierModifier } from "#app/modifier/modifier"; import { SpeciesFormKey } from "#enums/species-form-key"; @@ -1652,11 +1652,11 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesFormEvolution(Species.GHOLDENGO, "chest", "", 1, null, new SpeciesEvolutionCondition(p => p.evoCounter + p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length + p.scene.findModifiers(m => m instanceof MoneyMultiplierModifier - || m instanceof ExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG), + || m instanceof ExtraModifierModifier || m instanceof TempExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG), new SpeciesFormEvolution(Species.GHOLDENGO, "roaming", "", 1, null, new SpeciesEvolutionCondition(p => p.evoCounter + p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length + p.scene.findModifiers(m => m instanceof MoneyMultiplierModifier - || m instanceof ExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG) + || m instanceof ExtraModifierModifier || m instanceof TempExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG) ] }; diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 296e4e9b1b5..764cac5e901 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -2471,6 +2471,22 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.BUG_TYPE_SUPERFAN]: new TrainerConfig(++t).setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER) .setPartyTemplates(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE)), [TrainerType.EXPERT_POKEMON_BREEDER]: new TrainerConfig(++t).setMoneyMultiplier(3).setEncounterBgm(TrainerType.ACE_TRAINER).setLocalizedName("Expert Pokemon Breeder") - .setPartyTemplates(new TrainerPartyTemplate(3, PartyMemberStrength.STRONG)) + .setPartyTemplates(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE)), + [TrainerType.FUTURE_SELF_M]: new TrainerConfig(++t) + .setMoneyMultiplier(0) + .setEncounterBgm("mystery_encounter_weird_dream") + .setBattleBgm("mystery_encounter_weird_dream") + .setMixedBattleBgm("mystery_encounter_weird_dream") + .setVictoryBgm("mystery_encounter_weird_dream") + .setLocalizedName("Future Self M") + .setPartyTemplates(new TrainerPartyTemplate(6, PartyMemberStrength.STRONG)), + [TrainerType.FUTURE_SELF_F]: new TrainerConfig(++t) + .setMoneyMultiplier(0) + .setEncounterBgm("mystery_encounter_weird_dream") + .setBattleBgm("mystery_encounter_weird_dream") + .setMixedBattleBgm("mystery_encounter_weird_dream") + .setVictoryBgm("mystery_encounter_weird_dream") + .setLocalizedName("Future Self F") + .setPartyTemplates(new TrainerPartyTemplate(6, PartyMemberStrength.STRONG)) }; diff --git a/src/enums/trainer-type.ts b/src/enums/trainer-type.ts index cb7509067b5..708faf69196 100644 --- a/src/enums/trainer-type.ts +++ b/src/enums/trainer-type.ts @@ -116,6 +116,8 @@ export enum TrainerType { VITO, BUG_TYPE_SUPERFAN, EXPERT_POKEMON_BREEDER, + FUTURE_SELF_M, + FUTURE_SELF_F, BROCK = 200, MISTY, diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 6afc0770a7f..93a971cc3ef 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -60,7 +60,7 @@ import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-ph import { Challenges } from "#enums/challenges"; import { PokemonAnimType } from "#app/enums/pokemon-anim-type"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; -import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; import { SwitchType } from "#enums/switch-type"; import { SpeciesFormKey } from "#enums/species-form-key"; @@ -96,7 +96,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { public stats: integer[]; public ivs: integer[]; public nature: Nature; - public natureOverride: Nature | -1; public moveset: (PokemonMove | null)[]; public status: Status | null; public friendship: integer; @@ -117,7 +116,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { public fusionVariant: Variant; public fusionGender: Gender; public fusionLuck: integer; - public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData | null; + public fusionCustomPokemonData: CustomPokemonData | null; private summonDataPrimer: PokemonSummonData | null; @@ -125,7 +124,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { public battleData: PokemonBattleData; public battleSummonData: PokemonBattleSummonData; public turnData: PokemonTurnData; - public mysteryEncounterPokemonData: MysteryEncounterPokemonData; + public customPokemonData: CustomPokemonData; /** Used by Mystery Encounters to execute pokemon-specific logic (such as stat boosts) at start of battle */ public mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void; @@ -196,7 +195,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } this.nature = dataSource.nature || 0 as Nature; this.nickname = dataSource.nickname; - this.natureOverride = dataSource.natureOverride !== undefined ? dataSource.natureOverride : -1; this.moveset = dataSource.moveset; this.status = dataSource.status!; // TODO: is this bang correct? this.friendship = dataSource.friendship !== undefined ? dataSource.friendship : this.species.baseFriendship; @@ -215,9 +213,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.fusionVariant = dataSource.fusionVariant || 0; this.fusionGender = dataSource.fusionGender; this.fusionLuck = dataSource.fusionLuck; - this.fusionMysteryEncounterPokemonData = dataSource.fusionMysteryEncounterPokemonData; + this.fusionCustomPokemonData = dataSource.fusionCustomPokemonData; this.usedTMs = dataSource.usedTMs ?? []; - this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(dataSource.mysteryEncounterPokemonData); + this.customPokemonData = new CustomPokemonData(dataSource.customPokemonData); } else { this.id = Utils.randSeedInt(4294967296); this.ivs = ivs || Utils.getIvsFromId(this.id); @@ -238,7 +236,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.variant = this.shiny ? this.generateVariant() : 0; } - this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(); + this.customPokemonData = new CustomPokemonData(); if (nature !== undefined) { this.setNature(nature); @@ -246,8 +244,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.generateNature(); } - this.natureOverride = -1; - this.friendship = species.baseFriendship; this.metLevel = level; this.metBiome = scene.currentBattle ? scene.arena.biomeType : -1; @@ -596,8 +592,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const formKey = this.getFormKey(); if (this.isMax() === true || formKey === "segin-starmobile" || formKey === "schedar-starmobile" || formKey === "navi-starmobile" || formKey === "ruchbah-starmobile" || formKey === "caph-starmobile") { return 1.5; - } else if (this.mysteryEncounterPokemonData.spriteScale > 0) { - return this.mysteryEncounterPokemonData.spriteScale; + } else if (this.customPokemonData.spriteScale > 0) { + return this.customPokemonData.spriteScale; } return 1; } @@ -1013,7 +1009,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } getNature(): Nature { - return this.natureOverride !== -1 ? this.natureOverride : this.nature; + return this.customPokemonData.nature !== -1 ? this.customPokemonData.nature : this.nature; } setNature(nature: Nature): void { @@ -1179,15 +1175,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!types.length || !includeTeraType) { if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) { this.summonData.types.forEach(t => types.push(t)); - } else if (this.mysteryEncounterPokemonData.types && this.mysteryEncounterPokemonData.types.length > 0) { + } else if (this.customPokemonData.types && this.customPokemonData.types.length > 0) { // "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters - types.push(this.mysteryEncounterPokemonData.types[0]); + types.push(this.customPokemonData.types[0]); // Fusing a Pokemon onto something with "permanently changed" types will still apply the fusion's types as normal const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride); if (fusionSpeciesForm) { // Check if the fusion Pokemon also had "permanently changed" types - const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types; + const fusionMETypes = this.fusionCustomPokemonData?.types; if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) { types.push(fusionMETypes[1]); } else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) { @@ -1199,8 +1195,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - if (types.length === 1 && this.mysteryEncounterPokemonData.types.length >= 2) { - types.push(this.mysteryEncounterPokemonData.types[1]); + if (types.length === 1 && this.customPokemonData.types.length >= 2) { + types.push(this.customPokemonData.types[1]); } } else { const speciesForm = this.getSpeciesForm(ignoreOverride); @@ -1211,7 +1207,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (fusionSpeciesForm) { // Check if the fusion Pokemon also had "permanently changed" types // Otherwise, use standard fusion type logic - const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types; + const fusionMETypes = this.fusionCustomPokemonData?.types; if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) { types.push(fusionMETypes[1]); } else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) { @@ -1269,14 +1265,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return allAbilities[Overrides.OPP_ABILITY_OVERRIDE]; } if (this.isFusion()) { - if (!isNullOrUndefined(this.fusionMysteryEncounterPokemonData?.ability) && this.fusionMysteryEncounterPokemonData.ability !== -1) { - return allAbilities[this.fusionMysteryEncounterPokemonData.ability]; + if (!isNullOrUndefined(this.fusionCustomPokemonData?.ability) && this.fusionCustomPokemonData.ability !== -1) { + return allAbilities[this.fusionCustomPokemonData.ability]; } else { return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)]; } } - if (!isNullOrUndefined(this.mysteryEncounterPokemonData.ability) && this.mysteryEncounterPokemonData.ability !== -1) { - return allAbilities[this.mysteryEncounterPokemonData.ability]; + if (!isNullOrUndefined(this.customPokemonData.ability) && this.customPokemonData.ability !== -1) { + return allAbilities[this.customPokemonData.ability]; } let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex); if (abilityId === Abilities.NONE) { @@ -1299,8 +1295,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) { return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE]; } - if (!isNullOrUndefined(this.mysteryEncounterPokemonData.passive) && this.mysteryEncounterPokemonData.passive !== -1) { - return allAbilities[this.mysteryEncounterPokemonData.passive]; + if (!isNullOrUndefined(this.customPokemonData.passive) && this.customPokemonData.passive !== -1) { + return allAbilities[this.customPokemonData.passive]; } let starterSpeciesId = this.species.speciesId; @@ -1985,7 +1981,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.fusionVariant = 0; this.fusionGender = 0; this.fusionLuck = 0; - this.fusionMysteryEncounterPokemonData = null; + this.fusionCustomPokemonData = null; this.generateName(); this.calculateStats(); @@ -4209,7 +4205,6 @@ export class PlayerPokemon extends Pokemon { if (newEvolution.condition?.predicate(this)) { const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, undefined, this.shiny, this.variant, this.ivs, this.nature); - newPokemon.natureOverride = this.natureOverride; newPokemon.passive = this.passive; newPokemon.moveset = this.moveset.slice(); newPokemon.moveset = this.copyMoveset(); @@ -4293,7 +4288,7 @@ export class PlayerPokemon extends Pokemon { this.fusionVariant = pokemon.variant; this.fusionGender = pokemon.gender; this.fusionLuck = pokemon.luck; - this.fusionMysteryEncounterPokemonData = pokemon.mysteryEncounterPokemonData; + this.fusionCustomPokemonData = pokemon.customPokemonData; if ((pokemon.pauseEvolutions) || (this.pauseEvolutions)) { this.pauseEvolutions = true; } diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 7e4ef402ead..cbc842f2d9d 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1564,6 +1564,7 @@ export const modifierTypes = { VOUCHER_PREMIUM: () => new AddVoucherModifierType(VoucherType.PREMIUM, 1), GOLDEN_POKEBALL: () => new ModifierType("modifierType:ModifierType.GOLDEN_POKEBALL", "pb_gold", (type, _args) => new Modifiers.ExtraModifierModifier(type), undefined, "se/pb_bounce_1"), + SILVER_POKEBALL: () => new ModifierType("modifierType:ModifierType.SILVER_POKEBALL", "pb_silver", (type, _args) => new Modifiers.TempExtraModifierModifier(type, 100), undefined, "se/pb_bounce_1"), ENEMY_DAMAGE_BOOSTER: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_BOOSTER", "wl_item_drop", (type, _args) => new Modifiers.EnemyDamageBoosterModifier(type, 5)), ENEMY_DAMAGE_REDUCTION: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_REDUCTION", "wl_guard_spec", (type, _args) => new Modifiers.EnemyDamageReducerModifier(type, 2.5)), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 537e2327a21..fcd9cafba85 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -379,6 +379,15 @@ export abstract class LapsingPersistentModifier extends PersistentModifier { this.battleCount = this.maxBattles; } + /** + * Updates an existing modifier with a new `maxBattles` and `battleCount`. + * @param count + */ + setNewBattleCount(count: number): void { + this.maxBattles = count; + this.battleCount = count; + } + getMaxBattles(): number { return this.maxBattles; } @@ -876,7 +885,7 @@ export class EvoTrackerModifier extends PokemonHeldItemModifier { this.stackCount = pokemon ? pokemon.evoCounter + pokemon.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length - + pokemon.scene.findModifiers(m => m instanceof MoneyMultiplierModifier || m instanceof ExtraModifierModifier).length + + pokemon.scene.findModifiers(m => m instanceof MoneyMultiplierModifier || m instanceof ExtraModifierModifier || m instanceof TempExtraModifierModifier).length : this.stackCount; const text = scene.add.bitmapText(10, 15, "item-count", this.stackCount.toString(), 11); @@ -891,7 +900,7 @@ export class EvoTrackerModifier extends PokemonHeldItemModifier { getMaxHeldItemCount(pokemon: Pokemon): integer { this.stackCount = pokemon.evoCounter + pokemon.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length - + pokemon.scene.findModifiers(m => m instanceof MoneyMultiplierModifier || m instanceof ExtraModifierModifier).length; + + pokemon.scene.findModifiers(m => m instanceof MoneyMultiplierModifier || m instanceof ExtraModifierModifier || m instanceof TempExtraModifierModifier).length; return 999; } } @@ -1944,7 +1953,7 @@ export class PokemonNatureChangeModifier extends ConsumablePokemonModifier { apply(args: any[]): boolean { const pokemon = args[0] as Pokemon; - pokemon.natureOverride = this.nature; + pokemon.customPokemonData.nature = this.nature; let speciesId = pokemon.species.speciesId; pokemon.scene.gameData.dexData[speciesId].natureAttr |= 1 << (this.nature + 1); @@ -2900,6 +2909,69 @@ export class ExtraModifierModifier extends PersistentModifier { } } +/** + * Modifier used for timed boosts to the player's shop item rewards. + * @extends LapsingPersistentModifier + * @see {@linkcode apply} + */ +export class TempExtraModifierModifier extends LapsingPersistentModifier { + constructor(type: ModifierType, maxBattles: number, battleCount?: number, stackCount?: number) { + super(type, maxBattles, battleCount, stackCount); + } + + /** + * Goes through existing modifiers for any that match Silver Pokeball, + * which will then add the max count of the new item to the existing count of the current item. + * If no existing Silver Pokeballs are found, will add a new one. + * @param modifiers {@linkcode PersistentModifier} array of the player's modifiers + * @param _virtual N/A + * @param scene + * @returns true if the modifier was successfully added or applied, false otherwise + */ + add(modifiers: PersistentModifier[], _virtual: boolean, scene: BattleScene): boolean { + for (const modifier of modifiers) { + if (this.match(modifier)) { + const modifierInstance = modifier as TempExtraModifierModifier; + const newBattleCount = this.getMaxBattles() + modifierInstance.getBattleCount(); + + modifierInstance.setNewBattleCount(newBattleCount); + scene.playSound("se/restore"); + return true; + } + } + + modifiers.push(this); + return true; + } + + clone() { + return new TempExtraModifierModifier(this.type, this.getMaxBattles(), this.getBattleCount(), this.stackCount); + } + + match(modifier: Modifier): boolean { + return (modifier instanceof TempExtraModifierModifier); + } + + /** + * Checks if {@linkcode args} contains the necessary elements. + * @param args [1] {@linkcode Utils.NumberHolder} that holds the resulting shop item reward count + * @returns true if the shop reward number modifier applies successfully + */ + shouldApply(args: any[]): boolean { + return args && (args.length === 1) && (args[0] instanceof Utils.NumberHolder); + } + + /** + * Increases the current rewards in the battle by the stackCount. + * @param args [0] {@linkcode Utils.IntegerHolder} that holds the resulting shop item reward count + * @returns true if the shop reward number modifier applies successfully + */ + apply(args: any[]): boolean { + (args[0] as Utils.IntegerHolder).value += this.getStackCount(); + return true; + } +} + export abstract class EnemyPersistentModifier extends PersistentModifier { constructor(type: ModifierType, stackCount?: integer) { super(type, stackCount); diff --git a/src/phases/select-modifier-phase.ts b/src/phases/select-modifier-phase.ts index ba55340bd8d..a4442997bb4 100644 --- a/src/phases/select-modifier-phase.ts +++ b/src/phases/select-modifier-phase.ts @@ -1,7 +1,7 @@ import BattleScene from "#app/battle-scene"; import { ModifierTier } from "#app/modifier/modifier-tier"; import { regenerateModifierPoolThresholds, ModifierTypeOption, ModifierType, getPlayerShopModifierTypeOptionsForWave, PokemonModifierType, FusePokemonModifierType, PokemonMoveModifierType, TmModifierType, RememberMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, ModifierPoolType, getPlayerModifierTypeOptions } from "#app/modifier/modifier-type"; -import { ExtraModifierModifier, HealShopCostModifier, Modifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; +import { ExtraModifierModifier, HealShopCostModifier, Modifier, PokemonHeldItemModifier, TempExtraModifierModifier } from "#app/modifier/modifier"; import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "#app/ui/modifier-select-ui-handler"; import PartyUiHandler, { PartyUiMode, PartyOption } from "#app/ui/party-ui-handler"; import { Mode } from "#app/ui/ui"; @@ -39,6 +39,7 @@ export class SelectModifierPhase extends BattlePhase { const modifierCount = new Utils.IntegerHolder(3); if (this.isPlayer()) { this.scene.applyModifiers(ExtraModifierModifier, true, modifierCount); + this.scene.applyModifiers(TempExtraModifierModifier, true, modifierCount); } // If custom modifiers are specified, overrides default item count @@ -260,7 +261,13 @@ export class SelectModifierPhase extends BattlePhase { // Otherwise, continue with custom multiplier multiplier = this.customModifierSettings.rerollMultiplier; } - return Math.min(Math.ceil(this.scene.currentBattle.waveIndex / 10) * baseValue * Math.pow(2, this.rerollCount) * multiplier, Number.MAX_SAFE_INTEGER); + + const baseMultiplier = Math.min(Math.ceil(this.scene.currentBattle.waveIndex / 10) * baseValue * Math.pow(2, this.rerollCount) * multiplier, Number.MAX_SAFE_INTEGER); + + // Apply Black Sludge to reroll cost + const modifiedRerollCost = new NumberHolder(baseMultiplier); + this.scene.applyModifier(HealShopCostModifier, true, modifiedRerollCost); + return modifiedRerollCost.value; } getPoolType(): ModifierPoolType { diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 8240b6bcf84..0e551fb00a2 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -12,7 +12,7 @@ import { loadBattlerTag } from "../data/battler-tags"; import { Biome } from "#enums/biome"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; export default class PokemonData { public id: integer; @@ -33,7 +33,6 @@ export default class PokemonData { public stats: integer[]; public ivs: integer[]; public nature: Nature; - public natureOverride: Nature | -1; public moveset: (PokemonMove | null)[]; public status: Status | null; public friendship: integer; @@ -54,14 +53,14 @@ export default class PokemonData { public fusionVariant: Variant; public fusionGender: Gender; public fusionLuck: integer; - public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData; + public fusionCustomPokemonData: CustomPokemonData; public boss: boolean; public bossSegments?: integer; public summonData: PokemonSummonData; /** Data that can customize a Pokemon in non-standard ways from its Species */ - public mysteryEncounterPokemonData: MysteryEncounterPokemonData; + public customPokemonData: CustomPokemonData; constructor(source: Pokemon | any, forHistory: boolean = false) { const sourcePokemon = source instanceof Pokemon ? source : null; @@ -87,7 +86,6 @@ export default class PokemonData { this.stats = source.stats; this.ivs = source.ivs; this.nature = source.nature !== undefined ? source.nature : 0 as Nature; - this.natureOverride = source.natureOverride !== undefined ? source.natureOverride : -1; this.friendship = source.friendship !== undefined ? source.friendship : getPokemonSpecies(this.species).baseFriendship; this.metLevel = source.metLevel || 5; this.metBiome = source.metBiome !== undefined ? source.metBiome : -1; @@ -107,9 +105,10 @@ export default class PokemonData { this.fusionVariant = source.fusionVariant; this.fusionGender = source.fusionGender; this.fusionLuck = source.fusionLuck !== undefined ? source.fusionLuck : (source.fusionShiny ? source.fusionVariant + 1 : 0); + this.fusionCustomPokemonData = new CustomPokemonData(source.fusionMysteryEncounterPokemonData); this.usedTMs = source.usedTMs ?? []; - this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(source.mysteryEncounterPokemonData); + this.customPokemonData = new CustomPokemonData(source.customPokemonData); if (!forHistory) { this.boss = (source instanceof EnemyPokemon && !!source.bossSegments) || (!this.player && !!source.boss); diff --git a/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts b/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts index 54e780aba50..06492cae0d2 100644 --- a/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts @@ -15,7 +15,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { Moves } from "#enums/moves"; -import { ShinyRateBoosterModifier } from "#app/modifier/modifier"; +import { TempExtraModifierModifier } from "#app/modifier/modifier"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; const namespace = "mysteryEncounters/anOfferYouCantRefuse"; @@ -100,7 +100,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { expect(onInitResult).toBe(true); }); - describe("Option 1 - Sell your Pokemon for money and a Shiny Charm", () => { + describe("Option 1 - Sell your Pokemon for money and a Silver Pokeball", () => { it("should have the correct properties", () => { const option = AnOfferYouCantRefuseEncounter.options[0]; expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT); @@ -131,11 +131,11 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { expect(scene.money).toBe(initialMoney + price); }); - it("Should give the player a Shiny Charm", async () => { + it("Should give the player a Silver Pokeball", async () => { await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, defaultParty); await runMysteryEncounterToEnd(game, 1); - const itemModifier = scene.findModifier(m => m instanceof ShinyRateBoosterModifier) as ShinyRateBoosterModifier; + const itemModifier = scene.findModifier(m => m instanceof TempExtraModifierModifier) as TempExtraModifierModifier; expect(itemModifier).toBeDefined(); expect(itemModifier?.stackCount).toBe(1); diff --git a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts index 80434df2f44..e8c78eb09af 100644 --- a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts @@ -219,7 +219,7 @@ describe("Clowning Around - Mystery Encounter", () => { await game.phaseInterceptor.to(NewBattlePhase, false); const leadPokemon = scene.getParty()[0]; - expect(leadPokemon.mysteryEncounterPokemonData?.ability).toBe(abilityToTrain); + expect(leadPokemon.customPokemonData?.ability).toBe(abilityToTrain); }); }); @@ -340,9 +340,9 @@ describe("Clowning Around - Mystery Encounter", () => { scene.getParty()[2].moveset = []; await runMysteryEncounterToEnd(game, 3); - const leadTypesAfter = scene.getParty()[0].mysteryEncounterPokemonData?.types; - const secondaryTypesAfter = scene.getParty()[1].mysteryEncounterPokemonData?.types; - const thirdTypesAfter = scene.getParty()[2].mysteryEncounterPokemonData?.types; + const leadTypesAfter = scene.getParty()[0].customPokemonData?.types; + const secondaryTypesAfter = scene.getParty()[1].customPokemonData?.types; + const thirdTypesAfter = scene.getParty()[2].customPokemonData?.types; expect(leadTypesAfter.length).toBe(2); expect(leadTypesAfter[0]).toBe(Type.WATER); diff --git a/src/test/mystery-encounter/encounters/delibirdy-encounter.test.ts b/src/test/mystery-encounter/encounters/delibirdy-encounter.test.ts index e7a7c0bd50d..6003f2737f4 100644 --- a/src/test/mystery-encounter/encounters/delibirdy-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/delibirdy-encounter.test.ts @@ -206,7 +206,7 @@ describe("Delibird-y - Mystery Encounter", () => { expect(candyJarAfter?.stackCount).toBe(1); }); - it("Should remove Reviver Seed and give the player a Healing Charm", async () => { + it("Should remove Reviver Seed and give the player a Berry Pouch", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty); // Set 1 Reviver Seed on party lead @@ -220,11 +220,11 @@ describe("Delibird-y - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1}); const reviverSeedAfter = scene.findModifier(m => m instanceof PokemonInstantReviveModifier); - const healingCharmAfter = scene.findModifier(m => m instanceof HealingBoosterModifier); + const berryPouchAfter = scene.findModifier(m => m instanceof PreserveBerryModifier); expect(reviverSeedAfter).toBeUndefined(); - expect(healingCharmAfter).toBeDefined(); - expect(healingCharmAfter?.stackCount).toBe(1); + expect(berryPouchAfter).toBeDefined(); + expect(berryPouchAfter?.stackCount).toBe(1); }); it("Should give the player a Shell Bell if they have max stacks of Candy Jars", async () => { @@ -256,13 +256,13 @@ describe("Delibird-y - Mystery Encounter", () => { expect(shellBellAfter?.stackCount).toBe(1); }); - it("Should give the player a Shell Bell if they have max stacks of Healing Charms", async () => { + it("Should give the player a Shell Bell if they have max stacks of Berry Pouches", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty); - // 5 Healing Charms + // 3 Berry Pouches scene.modifiers = []; - const healingCharm = generateModifierType(scene, modifierTypes.HEALING_CHARM)!.newModifier() as HealingBoosterModifier; - healingCharm.stackCount = 5; + const healingCharm = generateModifierType(scene, modifierTypes.BERRY_POUCH)!.newModifier() as PreserveBerryModifier; + healingCharm.stackCount = 3; await scene.addModifier(healingCharm, true, false, false, true); // Set 1 Reviver Seed on party lead @@ -275,12 +275,12 @@ describe("Delibird-y - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1}); const reviverSeedAfter = scene.findModifier(m => m instanceof PokemonInstantReviveModifier); - const healingCharmAfter = scene.findModifier(m => m instanceof HealingBoosterModifier); + const healingCharmAfter = scene.findModifier(m => m instanceof PreserveBerryModifier); const shellBellAfter = scene.findModifier(m => m instanceof HitHealModifier); expect(reviverSeedAfter).toBeUndefined(); expect(healingCharmAfter).toBeDefined(); - expect(healingCharmAfter?.stackCount).toBe(5); + expect(healingCharmAfter?.stackCount).toBe(3); expect(shellBellAfter).toBeDefined(); expect(shellBellAfter?.stackCount).toBe(1); }); @@ -347,7 +347,7 @@ describe("Delibird-y - Mystery Encounter", () => { }); }); - it("Should decrease held item stacks and give the player a Berry Pouch", async () => { + it("Should decrease held item stacks and give the player a Healing Charm", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty); // Set 2 Soul Dew on party lead @@ -361,14 +361,14 @@ describe("Delibird-y - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); const soulDewAfter = scene.findModifier(m => m instanceof PokemonNatureWeightModifier); - const berryPouchAfter = scene.findModifier(m => m instanceof PreserveBerryModifier); + const healingCharmAfter = scene.findModifier(m => m instanceof HealingBoosterModifier); expect(soulDewAfter?.stackCount).toBe(1); - expect(berryPouchAfter).toBeDefined(); - expect(berryPouchAfter?.stackCount).toBe(1); + expect(healingCharmAfter).toBeDefined(); + expect(healingCharmAfter?.stackCount).toBe(1); }); - it("Should remove held item and give the player a Berry Pouch", async () => { + it("Should remove held item and give the player a Healing Charm", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty); // Set 1 Soul Dew on party lead @@ -382,20 +382,20 @@ describe("Delibird-y - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); const soulDewAfter = scene.findModifier(m => m instanceof PokemonNatureWeightModifier); - const berryPouchAfter = scene.findModifier(m => m instanceof PreserveBerryModifier); + const healingCharmAfter = scene.findModifier(m => m instanceof HealingBoosterModifier); expect(soulDewAfter).toBeUndefined(); - expect(berryPouchAfter).toBeDefined(); - expect(berryPouchAfter?.stackCount).toBe(1); + expect(healingCharmAfter).toBeDefined(); + expect(healingCharmAfter?.stackCount).toBe(1); }); - it("Should give the player a Shell Bell if they have max stacks of Berry Pouches", async () => { + it("Should give the player a Shell Bell if they have max stacks of Healing Charms", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty); // 5 Healing Charms scene.modifiers = []; - const healingCharm = generateModifierType(scene, modifierTypes.BERRY_POUCH)!.newModifier() as PreserveBerryModifier; - healingCharm.stackCount = 3; + const healingCharm = generateModifierType(scene, modifierTypes.HEALING_CHARM)!.newModifier() as HealingBoosterModifier; + healingCharm.stackCount = 5; await scene.addModifier(healingCharm, true, false, false, true); // Set 1 Soul Dew on party lead @@ -408,12 +408,12 @@ describe("Delibird-y - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); const soulDewAfter = scene.findModifier(m => m instanceof PokemonNatureWeightModifier); - const berryPouchAfter = scene.findModifier(m => m instanceof PreserveBerryModifier); + const healingCharmAfter = scene.findModifier(m => m instanceof HealingBoosterModifier); const shellBellAfter = scene.findModifier(m => m instanceof HitHealModifier); expect(soulDewAfter).toBeUndefined(); - expect(berryPouchAfter).toBeDefined(); - expect(berryPouchAfter?.stackCount).toBe(3); + expect(healingCharmAfter).toBeDefined(); + expect(healingCharmAfter?.stackCount).toBe(5); expect(shellBellAfter).toBeDefined(); expect(shellBellAfter?.stackCount).toBe(1); }); diff --git a/src/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts b/src/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts index 24c2e083a72..ae556ccebb6 100644 --- a/src/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts @@ -12,7 +12,7 @@ import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encount import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils"; import { Moves } from "#enums/moves"; import BattleScene from "#app/battle-scene"; -import { PokemonHeldItemModifier } from "#app/modifier/modifier"; +import { AttackTypeBoosterModifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; import { Type } from "#app/data/type"; import { Status, StatusEffect } from "#app/data/status-effect"; import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; @@ -22,6 +22,8 @@ import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; import { CommandPhase } from "#app/phases/command-phase"; import { MovePhase } from "#app/phases/move-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import { BattlerTagType } from "#enums/battler-tag-type"; +import { Abilities } from "#enums/abilities"; const namespace = "mysteryEncounters/fieryFallout"; /** Arcanine and Ninetails for 2 Fire types. Lapras, Gengar, Abra for burnable mon. */ @@ -41,10 +43,11 @@ describe("Fiery Fallout - Mystery Encounter", () => { beforeEach(async () => { game = new GameManager(phaserGame); scene = game.scene; - game.override.mysteryEncounterChance(100); - game.override.startingWave(defaultWave); - game.override.startingBiome(defaultBiome); - game.override.disableTrainerWaves(); + game.override.mysteryEncounterChance(100) + .startingWave(defaultWave) + .startingBiome(defaultBiome) + .disableTrainerWaves() + .moveset([Moves.PAYBACK, Moves.THUNDERBOLT]); // Required for attack type booster item generation vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ @@ -108,12 +111,16 @@ describe("Fiery Fallout - Mystery Encounter", () => { { species: getPokemonSpecies(Species.VOLCARONA), isBoss: false, - gender: Gender.MALE + gender: Gender.MALE, + tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + mysteryEncounterBattleEffects: expect.any(Function) }, { species: getPokemonSpecies(Species.VOLCARONA), isBoss: false, - gender: Gender.FEMALE + gender: Gender.FEMALE, + tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + mysteryEncounterBattleEffects: expect.any(Function) } ], doubleBattle: true, @@ -156,12 +163,11 @@ describe("Fiery Fallout - Mystery Encounter", () => { expect(enemyField[0].gender).not.toEqual(enemyField[1].gender); // Should be opposite gender const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); - expect(movePhases.length).toBe(4); + expect(movePhases.length).toBe(2); expect(movePhases.filter(p => (p as MovePhase).move.moveId === Moves.FIRE_SPIN).length).toBe(2); // Fire spin used twice before battle - expect(movePhases.filter(p => (p as MovePhase).move.moveId === Moves.QUIVER_DANCE).length).toBe(2); // Quiver Dance used twice before battle }); - it("should give charcoal to lead pokemon", async () => { + it("should give attack type boosting item to lead pokemon", async () => { await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); @@ -171,8 +177,8 @@ describe("Fiery Fallout - Mystery Encounter", () => { const leadPokemonId = scene.getParty()?.[0].id; const leadPokemonItems = scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === leadPokemonId, true) as PokemonHeldItemModifier[]; - const charcoal = leadPokemonItems.find(i => i.type.name === "Charcoal"); - expect(charcoal).toBeDefined; + const item = leadPokemonItems.find(i => i instanceof AttackTypeBoosterModifier); + expect(item).toBeDefined; }); }); @@ -192,7 +198,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { }); }); - it("should damage all non-fire party PKM by 20% and randomly burn 1", async () => { + it("should damage all non-fire party PKM by 20%, and burn + give Heatproof to a random Pokemon", async () => { await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty); const party = scene.getParty(); @@ -209,7 +215,8 @@ describe("Fiery Fallout - Mystery Encounter", () => { burnablePokemon.forEach((pkm) => { expect(pkm.hp, `${pkm.name} should have received 20% damage: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp() - Math.floor(pkm.getMaxHp() * 0.2)); }); - expect(burnablePokemon.some(pkm => pkm?.status?.effect === StatusEffect.BURN)).toBeTruthy(); + expect(burnablePokemon.some(pkm => pkm.status?.effect === StatusEffect.BURN)).toBeTruthy(); + expect(burnablePokemon.some(pkm => pkm.customPokemonData.ability === Abilities.HEATPROOF)); notBurnablePokemon.forEach((pkm) => expect(pkm.hp, `${pkm.name} should be full hp: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp())); }); @@ -240,17 +247,15 @@ describe("Fiery Fallout - Mystery Encounter", () => { }); }); - it("should give charcoal to lead pokemon", async () => { + it("should give attack type boosting item to lead pokemon", async () => { await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty); await runMysteryEncounterToEnd(game, 3); await game.phaseInterceptor.to(SelectModifierPhase, false); expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - const leadPokemonId = scene.getParty()?.[0].id; - const leadPokemonItems = scene.findModifiers(m => m instanceof PokemonHeldItemModifier - && (m as PokemonHeldItemModifier).pokemonId === leadPokemonId, true) as PokemonHeldItemModifier[]; - const charcoal = leadPokemonItems.find(i => i.type.name === "Charcoal"); - expect(charcoal).toBeDefined; + const leadPokemonItems = scene.getParty()?.[0].getHeldItems() as PokemonHeldItemModifier[]; + const item = leadPokemonItems.find(i => i instanceof AttackTypeBoosterModifier); + expect(item).toBeDefined; }); it("should leave encounter without battle", async () => { @@ -263,7 +268,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { }); it("should be disabled if not enough FIRE types are in party", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, [Species.MAGIKARP, Species.ARCANINE]); + await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, [Species.MAGIKARP]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); const encounterPhase = scene.getCurrentPhase(); diff --git a/src/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts b/src/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts index 3df2f35f02b..927e5cf0b02 100644 --- a/src/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts @@ -21,7 +21,7 @@ import { BerryModifier, PokemonBaseStatTotalModifier } from "#app/modifier/modif import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; -import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; +import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data"; import { CommandPhase } from "#app/phases/command-phase"; import { MovePhase } from "#app/phases/move-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; @@ -109,7 +109,7 @@ describe("The Strong Stuff - Mystery Encounter", () => { species: getPokemonSpecies(Species.SHUCKLE), isBoss: true, bossSegments: 5, - mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }), + mysteryEncounterPokemonData: new CustomPokemonData({ spriteScale: 1.25 }), nature: Nature.BOLD, moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER], modifierConfigs: expect.any(Array), diff --git a/src/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts b/src/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts index 7e92d17ba25..9120632f9e2 100644 --- a/src/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts @@ -86,7 +86,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { expect(TrashToTreasureEncounter.enemyPartyConfigs).toEqual([ { - levelAdditiveModifier: 1, + levelAdditiveModifier: 0.5, disableSwitch: true, pokemonConfigs: [ { diff --git a/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts b/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts index fdf9634e383..346e4235e6b 100644 --- a/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts @@ -5,7 +5,7 @@ import { Species } from "#app/enums/species"; import GameManager from "#app/test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; -import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounter-test-utils"; +import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils"; import BattleScene from "#app/battle-scene"; import { Mode } from "#app/ui/ui"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; @@ -15,6 +15,8 @@ import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; import { WeirdDreamEncounter } from "#app/data/mystery-encounters/encounters/weird-dream-encounter"; import * as EncounterTransformationSequence from "#app/data/mystery-encounters/utils/encounter-transformation-sequence"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import { CommandPhase } from "#app/phases/command-phase"; +import { ModifierTier } from "#app/modifier/modifier-tier"; const namespace = "mysteryEncounters/weirdDream"; const defaultParty = [Species.MAGBY, Species.HAUNTER, Species.ABRA]; @@ -70,7 +72,7 @@ describe("Weird Dream - Mystery Encounter", () => { expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}:description`); expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}:query`); - expect(WeirdDreamEncounter.options.length).toBe(2); + expect(WeirdDreamEncounter.options.length).toBe(3); }); it("should initialize fully", async () => { @@ -122,7 +124,7 @@ describe("Weird Dream - Mystery Encounter", () => { for (let i = 0; i < pokemonAfter.length; i++) { const newPokemon = pokemonAfter[i]; expect(newPokemon.getSpeciesForm().speciesId).not.toBe(pokemonPrior[i].getSpeciesForm().speciesId); - expect(newPokemon.mysteryEncounterPokemonData?.types.length).toBe(2); + expect(newPokemon.customPokemonData?.types.length).toBe(2); } const plus90To110 = bstDiff.filter(bst => bst > 80); @@ -132,7 +134,7 @@ describe("Weird Dream - Mystery Encounter", () => { expect(plus40To50.length).toBe(1); }); - it("should have 1 Memory Mushroom, 5 Rogue Balls, and 2 Mints in rewards", async () => { + it("should have 1 Memory Mushroom, 5 Rogue Balls, and 3 Mints in rewards", async () => { await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); await runMysteryEncounterToEnd(game, 1); await game.phaseInterceptor.to(SelectModifierPhase, false); @@ -141,11 +143,12 @@ describe("Weird Dream - Mystery Encounter", () => { expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; - expect(modifierSelectHandler.options.length).toEqual(4); + expect(modifierSelectHandler.options.length).toEqual(5); expect(modifierSelectHandler.options[0].modifierTypeOption.type.id).toEqual("MEMORY_MUSHROOM"); expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toEqual("ROGUE_BALL"); expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toEqual("MINT"); expect(modifierSelectHandler.options[3].modifierTypeOption.type.id).toEqual("MINT"); + expect(modifierSelectHandler.options[3].modifierTypeOption.type.id).toEqual("MINT"); }); it("should leave encounter without battle", async () => { @@ -158,7 +161,7 @@ describe("Weird Dream - Mystery Encounter", () => { }); }); - describe("Option 2 - Leave", () => { + describe("Option 2 - Battle Future Self", () => { it("should have the correct properties", () => { const option = WeirdDreamEncounter.options[1]; expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT); @@ -174,17 +177,63 @@ describe("Weird Dream - Mystery Encounter", () => { }); }); - it("should reduce party levels by 12.5%", async () => { + it("should start a battle against the player's transformation team", async () => { + await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); + await runMysteryEncounterToEnd(game, 2, undefined, true); + + const enemyField = scene.getEnemyField(); + expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(enemyField.length).toBe(1); + expect(scene.getEnemyParty().length).toBe(scene.getParty().length); + }); + + it("should have 2 Rogue/2 Ultra/2 Great items in rewards", async () => { + await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); + await runMysteryEncounterToEnd(game, 2, undefined, true); + await skipBattleRunMysteryEncounterRewardsPhase(game); + await game.phaseInterceptor.to(SelectModifierPhase, false); + expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + await game.phaseInterceptor.run(SelectModifierPhase); + + expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); + const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; + expect(modifierSelectHandler.options.length).toEqual(6); + expect(modifierSelectHandler.options[0].modifierTypeOption.type.tier - modifierSelectHandler.options[0].modifierTypeOption.upgradeCount).toEqual(ModifierTier.ROGUE); + expect(modifierSelectHandler.options[1].modifierTypeOption.type.tier - modifierSelectHandler.options[1].modifierTypeOption.upgradeCount).toEqual(ModifierTier.ROGUE); + expect(modifierSelectHandler.options[2].modifierTypeOption.type.tier - modifierSelectHandler.options[2].modifierTypeOption.upgradeCount).toEqual(ModifierTier.ULTRA); + expect(modifierSelectHandler.options[3].modifierTypeOption.type.tier - modifierSelectHandler.options[3].modifierTypeOption.upgradeCount).toEqual(ModifierTier.ULTRA); + expect(modifierSelectHandler.options[4].modifierTypeOption.type.tier - modifierSelectHandler.options[4].modifierTypeOption.upgradeCount).toEqual(ModifierTier.GREAT); + expect(modifierSelectHandler.options[5].modifierTypeOption.type.tier - modifierSelectHandler.options[5].modifierTypeOption.upgradeCount).toEqual(ModifierTier.GREAT); + }); + }); + + describe("Option 3 - Leave", () => { + it("should have the correct properties", () => { + const option = WeirdDreamEncounter.options[2]; + expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT); + expect(option.dialogue).toBeDefined(); + expect(option.dialogue).toStrictEqual({ + buttonLabel: `${namespace}:option.3.label`, + buttonTooltip: `${namespace}:option.3.tooltip`, + selected: [ + { + text: `${namespace}:option.3.selected`, + }, + ], + }); + }); + + it("should reduce party levels by 10%", async () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); const levelsPrior = scene.getParty().map(p => p.level); - await runMysteryEncounterToEnd(game, 2); + await runMysteryEncounterToEnd(game, 3); const levelsAfter = scene.getParty().map(p => p.level); for (let i = 0; i < levelsPrior.length; i++) { - expect(Math.max(Math.ceil(0.8875 * levelsPrior[i]), 1)).toBe(levelsAfter[i]); + expect(Math.max(Math.ceil(0.9 * levelsPrior[i]), 1)).toBe(levelsAfter[i]); expect(scene.getParty()[i].levelExp).toBe(0); } @@ -195,7 +244,7 @@ describe("Weird Dream - Mystery Encounter", () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); - await runMysteryEncounterToEnd(game, 2); + await runMysteryEncounterToEnd(game, 3); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); });