[Feature] Add Mystery Encounters to the game (#3938)
* add .github/workflows/mystery-event.yml * update mystery-event.yml * mystery encounters: resolve review comments: Lost at Sea: -fix typo in handlePokemonGuidingYouPhase function Mysterious Chest: - remove obsolete commented code mystery-encounter.ts - remove unused `onDone` field from MysteryEncounterBuilder * fix typo in CanLearnMoveRequirementOptions * remove redundance from Pokemon.isAllowedInBattle() * chore: jsdoc formatting * fix lost-at-sea tests * add fallback for biomeMysteryEncounters if empty * lost-at-sea-encounter: fix and extend tests * move "battle:fainted" into `koPlayerPokemon` * add retries to quick-draw tests * fix lost-at-sea-encounter tests * clean up battle animation logic * Update and rename mystery-event.yml to mystery-events.yml * Update mystery-events.yml * Fix typo * Update mystery-events.yml Fix debug runs * clean up unit tests and utils * attach github issues to all encounter jsdocs * start dialogue refactor * update sleeping snorlax encounter * migrate encounters dialogue to new format * cleanup and add jsdocs * finish fiery fallout encounter * fix unit test breaks * add skeleton tests to fiery fallout * commit latest test changes * finish unit tests for fiery fallout * bug fix for empty modifier shop * stash working changes * stash changes * Update src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/test/utils/overridesHelper.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/test/utils/overridesHelper.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/test/utils/overridesHelper.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/test/utils/overridesHelper.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/data/battle-anims.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * nit updates and cleanup * Update src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * add jsdocs and more cleanup * add more jsdoc * add the strong stuff encounter * add the strong stuff encounter and more unit tests * cleanup container length checks in ME ui * add retries to tests * add retries to tests * fix trainer wave disable override * add shuckle juice modifier * add dialogue bug fixes * add dialogue bug fixes * add pokemon salesman encounter and affects pokedex UI display * add unit tests for pokemon salesman * temp stash * add offer you can't refuse * add unit tests for offer you can't refuse encounter * remove unnecessary prompt handlers * add tests for disabled encounter options * add delibird-y encounter * add delibird-y encounter * add absolute avarice encounter * finish absolute avarice encounter * add unit tests and enhancements for item overrides in tests * fix unit test * cleanup absolute avarice PR * small bug fixes with latest sync from main * update visuals loading for safari and stat trainer visuals * update visuals loading for safari and stat trainer visuals * update a trainer's test encounter and add unit tests * add Trash to Treasure encounter * clean up trash to treasure encounter * clean up trash to treasure encounter * add berries abound encounter * start clowning around encounter * first implementation pass at clowning around * add unit tests for clowning around * add unit tests for clowning around * clean up ME unit tests * clean up unit tests * update unit tests * add part timer and dancing lessons encounters * add unit tests for Dancing Lessons and Part-Timer * reordered biome list and adjusted redirection for project and labels * Add Weird Dream encounter and slight reworks to Berries Abound/Fight or Flight * adjusting yml to match new labels * fix yml whoopsie * Expanded 'Weird Dream' banlist and fixed a bug with the BST bump range * adds Winstrate Challenge mystery encounter * small cleanup for winstrates * add unit tests for Winstrate Challenge * fix pokemon not returning after winstrate battle * commit latest beta merge updates * fix ME null checks and unit tests with beta update * fix ME null checks and unit tests with beta update * MEs to pokerogue beta branch * test dialogue changes * test patch fix * test patch fix * test patch fix * adds teleporting hijinks encounter * add unit tests for Teleporting Hijinks * small change to teleporting hijinks dialogue * migrate ME translations to json * add retries to berries-abound.Option1: should reward the player with X berries based on wave * add missing ME dialogue back in * revert template changes * add ME unique trainer dialogue to both dialogue jsons * fix hanging comma in json * fix broken imports * resolve lint issues * fix flaky test * balance tweaks to a few MEs, updates to bug superfan * add unit tests for Bug-Type Superfan and clean up dialogue * Adds Fun and Games mystery encounter * add unit tests for Fun and Games encounter * update jsdoc * small ME balance changes * small ME balance changes * Adds Uncommon Breed ME and misc. ME bug fixes * Update getFinalSessionData() to collect Mystery Encounter data * adds GTS encounter * various ME bug fixes and balance changes * latest ME bug fixes * clean up GTS Encounter and add unit tests * small cleanup to MEs branch * add BGM music names for ME music * bug fixes and balance changes for MEs * ME data schema updates * balance changes and bug fixes to MEs * balance changes and bug fixes to MEs * update tests for MEs * add jsdoc to party exp function * dialogue updates and test fixes for MEs * dialogue updates and test fixes for MEs * PR suggestions and fixees * stash PR feedback and bugfixes * fix all tests for MEs and cleanup * PR feedback * update flaky ME test * update tests, bug fix MEs, and sprite assets * remove unintentional console log * re-enable stubbed function for Phaser text styling * handle undefined introVisuals properly * PR feedback from NightKev * disable Uncommon Breed tests * locales updates and bug fixes for safari zone * more PR feedback and update field trip with Rarer Candy * fix unit test * Change how reroll button gets disabled in Modifier Shop Phase * update continue button text logic * Update src/ui/modifier-select-ui-handler.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * fix money formatting and some nits * more nits * more nits * update ME tsdocs with links * update ME tsdocs with links --------- Co-authored-by: Felix Staud <felix.staud@headwire.com> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> Co-authored-by: ImperialSympathizer <imperialsympathizer@gmail.com> Co-authored-by: InnocentGameDev <asdargmng@gmail.com> Co-authored-by: Mumble <171087428+frutescens@users.noreply.github.com>
BIN
public/audio/bgm/mystery_encounter_fun_and_games.mp3
Normal file
BIN
public/audio/bgm/mystery_encounter_gen_5_gts.mp3
Normal file
BIN
public/audio/bgm/mystery_encounter_gen_6_gts.mp3
Normal file
BIN
public/audio/bgm/mystery_encounter_weird_dream.mp3
Normal file
951
public/battle-anims/encounter-dance.json
Normal file
@ -0,0 +1,951 @@
|
||||
{
|
||||
"id": 686,
|
||||
"graphic": "PRAS- Dragon Dance",
|
||||
"frames": [
|
||||
[
|
||||
{
|
||||
"x": 4,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 12,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 70,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -12,
|
||||
"y": -0.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 70,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 12,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 16,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -16,
|
||||
"y": -0.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 24,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 20,
|
||||
"y": 0,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -20,
|
||||
"y": -0.5,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 32,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 24,
|
||||
"y": 0,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -24,
|
||||
"y": -0.5,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 36,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 28,
|
||||
"y": 0,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 70,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -28,
|
||||
"y": -0.5,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 70,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 36,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 36,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 32,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 24,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 12,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 4,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -4,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 12,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 70,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -12,
|
||||
"y": -0.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 70,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -12,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 16,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -16,
|
||||
"y": -0.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -24,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 20,
|
||||
"y": 0,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -20,
|
||||
"y": -0.5,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -32,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 24,
|
||||
"y": 0,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -24,
|
||||
"y": -0.5,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 155,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -36,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 28,
|
||||
"y": 0,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 70,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": -28,
|
||||
"y": -0.5,
|
||||
"zoomX": 108,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"blendType": 1,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 70,
|
||||
"tone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
255
|
||||
],
|
||||
"priority": 1,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -36,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -36,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -32,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -24,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -12,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -4,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
]
|
||||
],
|
||||
"frameTimedEvents": {
|
||||
"0": [
|
||||
{
|
||||
"frameIndex": 0,
|
||||
"resourceName": "PRSFX- Attract.wav",
|
||||
"volume": 100,
|
||||
"pitch": 100,
|
||||
"eventType": "AnimTimedSoundEvent"
|
||||
}
|
||||
],
|
||||
"1": [
|
||||
{
|
||||
"frameIndex": 0,
|
||||
"resourceName": "PRSFX- Ally Switch.wav",
|
||||
"volume": 80,
|
||||
"pitch": 100,
|
||||
"eventType": "AnimTimedSoundEvent"
|
||||
}
|
||||
]
|
||||
},
|
||||
"position": 4,
|
||||
"hue": 0
|
||||
}
|
66
public/battle-anims/encounter-magma-bg.json
Normal file
@ -0,0 +1,66 @@
|
||||
{
|
||||
"frames": [
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[]
|
||||
],
|
||||
"frameTimedEvents": {
|
||||
"0": [
|
||||
{
|
||||
"frameIndex": 0,
|
||||
"resourceName": "PRAS- Fire BG",
|
||||
"bgX": 0,
|
||||
"bgY": 0,
|
||||
"opacity": 0,
|
||||
"duration": 35,
|
||||
"eventType": "AnimTimedAddBgEvent"
|
||||
},
|
||||
{
|
||||
"frameIndex": 0,
|
||||
"resourceName": "",
|
||||
"bgX": 0,
|
||||
"bgY": 0,
|
||||
"opacity": 255,
|
||||
"duration": 12,
|
||||
"eventType": "AnimTimedUpdateBgEvent"
|
||||
}
|
||||
],
|
||||
"25": [
|
||||
{
|
||||
"frameIndex": 25,
|
||||
"resourceName": "",
|
||||
"bgX": 0,
|
||||
"bgY": 0,
|
||||
"opacity": 0,
|
||||
"duration": 8,
|
||||
"eventType": "AnimTimedUpdateBgEvent"
|
||||
}
|
||||
]
|
||||
},
|
||||
"position": 1,
|
||||
"hue": 0
|
||||
}
|
902
public/battle-anims/encounter-magma-spout.json
Normal file
@ -0,0 +1,902 @@
|
||||
{
|
||||
"graphic": "PRAS- Magma Storm",
|
||||
"frames": [
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 120,
|
||||
"y": -56,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 144,
|
||||
"y": -84,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 100,
|
||||
"y": -86.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 140,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 9,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 136,
|
||||
"y": -92,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 9,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 108,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 9,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 152,
|
||||
"y": -76,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 10,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 116,
|
||||
"y": -88,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 10,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -62.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 10,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 136,
|
||||
"y": -96,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 100,
|
||||
"y": -76,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 148,
|
||||
"y": -66.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 108,
|
||||
"y": -92,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 120,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 144,
|
||||
"y": -86.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 100,
|
||||
"y": -76,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 9,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 136,
|
||||
"y": -68,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 9,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -94.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 9,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 100.5,
|
||||
"y": -70,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 10,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 144,
|
||||
"y": -66,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 10,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 126,
|
||||
"y": -86.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 10,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 101,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 130,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 152,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 130,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 124.5,
|
||||
"y": -78.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 140,
|
||||
"priority": 4,
|
||||
"focus": 1
|
||||
}
|
||||
]
|
||||
],
|
||||
"frameTimedEvents": {
|
||||
"0": [
|
||||
{
|
||||
"frameIndex": 0,
|
||||
"resourceName": "PRSFX- Magma Storm1.wav",
|
||||
"volume": 100,
|
||||
"pitch": 100,
|
||||
"eventType": "AnimTimedSoundEvent"
|
||||
}
|
||||
],
|
||||
"8": [
|
||||
{
|
||||
"frameIndex": 8,
|
||||
"resourceName": "PRSFX- Magma Storm2.wav",
|
||||
"volume": 100,
|
||||
"pitch": 100,
|
||||
"eventType": "AnimTimedSoundEvent"
|
||||
}
|
||||
]
|
||||
},
|
||||
"position": 1,
|
||||
"hue": 0
|
||||
}
|
822
public/battle-anims/encounter-smokescreen.json
Normal file
@ -0,0 +1,822 @@
|
||||
{
|
||||
"graphic": "PRAS- Smokescreen",
|
||||
"frames": [
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": 12.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": 8.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": 0.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -4,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": -3.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -4,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -11,
|
||||
"y": 21.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": -7.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -8,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -11,
|
||||
"y": 17.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": -11.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -12,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -11,
|
||||
"y": 13.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 21,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": -15.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -16,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -11,
|
||||
"y": 5.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 17,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": -19.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -11,
|
||||
"y": 0.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 13,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": 8.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 15.5,
|
||||
"y": -23.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -24,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -11,
|
||||
"y": -2.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 9,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": 4.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -11,
|
||||
"y": -6.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -28,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": 0.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 8,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": 23,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -11,
|
||||
"y": -10.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -32,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 1,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": -3.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 7,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": 19,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -11,
|
||||
"y": -14.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -36,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": -3,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": -7.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": 15,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -11,
|
||||
"y": -18.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": -7,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": -11.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 6,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": 7,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": -15.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": -11,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": 3,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": -19.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": -15,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": -1,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 2,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": -12.5,
|
||||
"y": -23.5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"mirror": true,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 5,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": -5,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 3,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": -9,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 150,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": -13,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 100,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 4.5,
|
||||
"y": -17,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 4,
|
||||
"opacity": 50,
|
||||
"priority": 4,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 4,
|
||||
"focus": 3
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 4,
|
||||
"focus": 3
|
||||
}
|
||||
],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[]
|
||||
],
|
||||
"frameTimedEvents": {
|
||||
"0": [
|
||||
{
|
||||
"frameIndex": 0,
|
||||
"resourceName": "PRSFX- Haze.wav",
|
||||
"volume": 100,
|
||||
"pitch": 85,
|
||||
"eventType": "AnimTimedSoundEvent"
|
||||
},
|
||||
{
|
||||
"frameIndex": 0,
|
||||
"resourceName": "Explosion1.m4a",
|
||||
"volume": 100,
|
||||
"pitch": 85,
|
||||
"eventType": "AnimTimedSoundEvent"
|
||||
}
|
||||
]
|
||||
},
|
||||
"position": 2,
|
||||
"hue": 0
|
||||
}
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 57 KiB |
BIN
public/images/items/berry_juice.png
Normal file
After Width: | Height: | Size: 318 B |
BIN
public/images/items/black_sludge.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
public/images/items/golden_net.png
Normal file
After Width: | Height: | Size: 561 B |
BIN
public/images/items/macho_brace.png
Normal file
After Width: | Height: | Size: 372 B |
BIN
public/images/items/old_gateau.png
Normal file
After Width: | Height: | Size: 240 B |
734
public/images/mystery-encounters/b2w2_lady.json
Normal file
@ -0,0 +1,734 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "b2w2_lady.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 399,
|
||||
"h": 360
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 8,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 8,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 57,
|
||||
"y": 0,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 8,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 114,
|
||||
"y": 0,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 9,
|
||||
"y": 8,
|
||||
"w": 55,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 171,
|
||||
"y": 0,
|
||||
"w": 55,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 11,
|
||||
"y": 8,
|
||||
"w": 54,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 228,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 11,
|
||||
"y": 8,
|
||||
"w": 54,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 285,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 14,
|
||||
"y": 8,
|
||||
"w": 52,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 342,
|
||||
"y": 0,
|
||||
"w": 52,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 72,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 47,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 57,
|
||||
"y": 72,
|
||||
"w": 47,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 47,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 114,
|
||||
"y": 72,
|
||||
"w": 47,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 171,
|
||||
"y": 72,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 228,
|
||||
"y": 72,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 285,
|
||||
"y": 72,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0013.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 342,
|
||||
"y": 72,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0014.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 49,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 144,
|
||||
"w": 49,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0015.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 49,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 57,
|
||||
"y": 144,
|
||||
"w": 49,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0016.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 49,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 114,
|
||||
"y": 144,
|
||||
"w": 49,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0017.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 49,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 171,
|
||||
"y": 144,
|
||||
"w": 49,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0018.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 228,
|
||||
"y": 144,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0019.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 285,
|
||||
"y": 144,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0020.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 342,
|
||||
"y": 144,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0021.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 216,
|
||||
"w": 48,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0022.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 8,
|
||||
"w": 50,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 57,
|
||||
"y": 216,
|
||||
"w": 50,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0023.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 18,
|
||||
"y": 8,
|
||||
"w": 51,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 114,
|
||||
"y": 216,
|
||||
"w": 51,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0024.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 18,
|
||||
"y": 8,
|
||||
"w": 51,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 171,
|
||||
"y": 216,
|
||||
"w": 51,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0025.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 15,
|
||||
"y": 8,
|
||||
"w": 53,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 228,
|
||||
"y": 216,
|
||||
"w": 53,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0026.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 10,
|
||||
"y": 8,
|
||||
"w": 57,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 285,
|
||||
"y": 216,
|
||||
"w": 57,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0027.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 10,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 342,
|
||||
"y": 216,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0028.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 10,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 288,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0029.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 9,
|
||||
"y": 8,
|
||||
"w": 55,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 57,
|
||||
"y": 288,
|
||||
"w": 55,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0030.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 8,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 114,
|
||||
"y": 288,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0031.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 8,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 171,
|
||||
"y": 288,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0032.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 8,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 228,
|
||||
"y": 288,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0033.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 8,
|
||||
"y": 8,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 285,
|
||||
"y": 288,
|
||||
"w": 56,
|
||||
"h": 72
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:e7f062304401dbd7b3ec79512f0ff4cb:0136dac01331f88892a3df26aeab78f5:1ed1e22abb9b55d76337a5a599835c06$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/b2w2_lady.png
Normal file
After Width: | Height: | Size: 23 KiB |
797
public/images/mystery-encounters/b2w2_veteran_m.json
Normal file
@ -0,0 +1,797 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "b2w2_veteran_m.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 424,
|
||||
"h": 390
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 53,
|
||||
"y": 0,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 106,
|
||||
"y": 0,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 159,
|
||||
"y": 0,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 212,
|
||||
"y": 0,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 265,
|
||||
"y": 0,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 318,
|
||||
"y": 0,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 371,
|
||||
"y": 0,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 78,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 53,
|
||||
"y": 78,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 48,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 106,
|
||||
"y": 78,
|
||||
"w": 48,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 50,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 159,
|
||||
"y": 78,
|
||||
"w": 50,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 212,
|
||||
"y": 78,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0013.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 265,
|
||||
"y": 78,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0014.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 52,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 318,
|
||||
"y": 78,
|
||||
"w": 52,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0015.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 51,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 371,
|
||||
"y": 78,
|
||||
"w": 51,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0016.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 52,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 156,
|
||||
"w": 52,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0017.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 52,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 53,
|
||||
"y": 156,
|
||||
"w": 52,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0018.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 106,
|
||||
"y": 156,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0019.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 159,
|
||||
"y": 156,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0020.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 212,
|
||||
"y": 156,
|
||||
"w": 53,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0021.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 52,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 265,
|
||||
"y": 156,
|
||||
"w": 52,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0022.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 51,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 318,
|
||||
"y": 156,
|
||||
"w": 51,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0023.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 51,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 371,
|
||||
"y": 156,
|
||||
"w": 51,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0024.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 51,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 234,
|
||||
"w": 51,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0025.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 50,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 53,
|
||||
"y": 234,
|
||||
"w": 50,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0026.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 48,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 106,
|
||||
"y": 234,
|
||||
"w": 48,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0027.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 46,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 159,
|
||||
"y": 234,
|
||||
"w": 46,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0028.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 46,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 212,
|
||||
"y": 234,
|
||||
"w": 46,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0029.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 265,
|
||||
"y": 234,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0030.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 318,
|
||||
"y": 234,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0031.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 371,
|
||||
"y": 234,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0032.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 312,
|
||||
"w": 44,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0033.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 53,
|
||||
"y": 312,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0034.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 106,
|
||||
"y": 312,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0035.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 159,
|
||||
"y": 312,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0036.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 2,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 212,
|
||||
"y": 312,
|
||||
"w": 43,
|
||||
"h": 78
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:4deb068879a8ac195cb4f00c8b17b7f5:b32f0f90436649264b6f3c49b09ac06a:05e903aa75b8e50c28334d9b5e14c85a$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/b2w2_veteran_m.png
Normal file
After Width: | Height: | Size: 19 KiB |
83
public/images/mystery-encounters/bait.json
Normal file
@ -0,0 +1,83 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "bait.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 14,
|
||||
"h": 43
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 12,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 3,
|
||||
"w": 12,
|
||||
"h": 13
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 12,
|
||||
"h": 13
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 12,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 3,
|
||||
"w": 12,
|
||||
"h": 13
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 16,
|
||||
"w": 12,
|
||||
"h": 13
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 12,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 5,
|
||||
"w": 11,
|
||||
"h": 11
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 31,
|
||||
"w": 11,
|
||||
"h": 11
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:f0ec04fcd67ac346dce973693711d032:b697e09191c4312b8faaa0a080a309b7:1af241a52e61fa01ca849aa03c112f85$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/bait.png
Normal file
After Width: | Height: | Size: 277 B |
41
public/images/mystery-encounters/berry_bush.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "berry_bush.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 49,
|
||||
"h": 53
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 53
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 49,
|
||||
"h": 53
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 49,
|
||||
"h": 53
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:d5f83625477b5f98b726343f4a3a396f:f4665258986e97345cfeee041b4b8bcf:e7781fcc447e6d12deb2af78c9493c7f$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/berry_bush.png
Normal file
After Width: | Height: | Size: 719 B |
19
public/images/mystery-encounters/buoy.json
Normal file
@ -0,0 +1,19 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 46, "h": 60 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 46, "h": 60 },
|
||||
"sourceSize": { "w": 46, "h": 60 }
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.aseprite.org/",
|
||||
"version": "1.3.7-x64",
|
||||
"image": "buoy-sheet.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 46, "h": 60 },
|
||||
"scale": "1"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/buoy.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
41
public/images/mystery-encounters/carnival_game.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "carnival_game.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 38,
|
||||
"h": 82
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 38,
|
||||
"h": 82
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 38,
|
||||
"h": 82
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 38,
|
||||
"h": 82
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:d40b6742392c2fe8ca0735b3f561e319:5dcda5410b12f0aa75eb0dd1fbcbe4f9:d171fb17d3017d1f655cd8dd14c252b7$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/carnival_game.png
Normal file
After Width: | Height: | Size: 517 B |
41
public/images/mystery-encounters/carnival_man.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "carnival_man.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 50,
|
||||
"h": 77
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 15,
|
||||
"y": 3,
|
||||
"w": 50,
|
||||
"h": 77
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 50,
|
||||
"h": 77
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:e80aa9a809a7cca6d05992cb82f6dbd9:ea9962edd1cdc1e503deecf2ce1863c1:55647352b6547cf03212506309f2abf5$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/carnival_man.png
Normal file
After Width: | Height: | Size: 833 B |
41
public/images/mystery-encounters/carnival_wobbuffet.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "carnival_wobbuffet.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 45,
|
||||
"h": 55
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 45,
|
||||
"h": 55
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 55
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 55
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:879de17da906ea52e5a71afacb88fcf6:90f64e8eaac4ff1e67373f60c3d98d36:a090cb3294ca1218a4f90ecb97df81d7$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/carnival_wobbuffet.png
Normal file
After Width: | Height: | Size: 772 B |
209
public/images/mystery-encounters/chest_blue.json
Normal file
@ -0,0 +1,209 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "chest_blue.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 54,
|
||||
"h": 492
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 46,
|
||||
"h": 39
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 39
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 39
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 47,
|
||||
"h": 35
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 47,
|
||||
"h": 35
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 39,
|
||||
"w": 47,
|
||||
"h": 35
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 46,
|
||||
"h": 39
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 39
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 74,
|
||||
"w": 46,
|
||||
"h": 39
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 46,
|
||||
"h": 46
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 46
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 113,
|
||||
"w": 46,
|
||||
"h": 46
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 53,
|
||||
"h": 65
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 53,
|
||||
"h": 65
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 159,
|
||||
"w": 53,
|
||||
"h": 65
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 224,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 291,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 358,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 425,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:017ecc2437e580a185f9843f97e80da5:f44ef1c27a4a17183a5bcf1f7fc8ce6a:f4f3c064e6c93b8d1290f93bee927f60$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/chest_blue.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
209
public/images/mystery-encounters/chest_red.json
Normal file
@ -0,0 +1,209 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "chest_red.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 54,
|
||||
"h": 492
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 46,
|
||||
"h": 39
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 39
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 39
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 47,
|
||||
"h": 35
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 47,
|
||||
"h": 35
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 39,
|
||||
"w": 47,
|
||||
"h": 35
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 46,
|
||||
"h": 39
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 39
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 74,
|
||||
"w": 46,
|
||||
"h": 39
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 46,
|
||||
"h": 46
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 46
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 113,
|
||||
"w": 46,
|
||||
"h": 46
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 53,
|
||||
"h": 65
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 53,
|
||||
"h": 65
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 159,
|
||||
"w": 53,
|
||||
"h": 65
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 224,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 291,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 358,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 425,
|
||||
"w": 54,
|
||||
"h": 67
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:2a0b6c93c5be115efa635d40780603f0:b5fde49f991c2ecc49afedd80cc8a544:a163d960e9966469ae4dde4b53c13496$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/chest_red.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
41
public/images/mystery-encounters/dark_deal_porygon.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "dark_deal_porygon.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 36,
|
||||
"h": 45
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 36,
|
||||
"h": 45
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 44,
|
||||
"h": 44
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 36,
|
||||
"h": 45
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:895f0a79b89fa0fb44167f4584fd9a22:357b46953b7e17c6b2f43a62d52855d8:cc1ed0e4f90aaa9dcf1b39a0af1283b0$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/dark_deal_porygon.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
public/images/mystery-encounters/encounter_radar.png
Normal file
After Width: | Height: | Size: 255 B |
BIN
public/images/mystery-encounters/exclaim.png
Normal file
After Width: | Height: | Size: 378 B |
41
public/images/mystery-encounters/global_trade_system.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "global_trade_system.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 77,
|
||||
"h": 78
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 77,
|
||||
"h": 78
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 77,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 77,
|
||||
"h": 78
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:8a51d7a17b3d8c32f0e5e4a0f15daeb4:6eba29c5345847f735d8b69a05fc49d1:98ad8b8b8d8c4865d7d23ec97b516594$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/global_trade_system.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
41
public/images/mystery-encounters/mad_scientist_m.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "mad_scientist_m.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 46,
|
||||
"h": 76
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 44,
|
||||
"h": 74
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 44,
|
||||
"h": 74
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 44,
|
||||
"h": 74
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:a7f8ff2bbb362868f51125c254eb6681:cf76e61ddd31a8f46af67ced168c44a2:4fc09abe16c0608828269e5da81d0744$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/mad_scientist_m.png
Normal file
After Width: | Height: | Size: 920 B |
104
public/images/mystery-encounters/mud.json
Normal file
@ -0,0 +1,104 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "mud.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 14,
|
||||
"h": 68
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 12,
|
||||
"h": 20
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 12,
|
||||
"h": 13
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 12,
|
||||
"h": 13
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 12,
|
||||
"h": 20
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 12,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 16,
|
||||
"w": 12,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 12,
|
||||
"h": 20
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 1,
|
||||
"w": 12,
|
||||
"h": 16
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 32,
|
||||
"w": 12,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 12,
|
||||
"h": 20
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 3,
|
||||
"w": 12,
|
||||
"h": 17
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 50,
|
||||
"w": 12,
|
||||
"h": 17
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:4f18a8effb8f01eb70f9f25b8294c1bf:ad663a73c51f780bbf45d00a52519553:c64f6b8befc3d5e9f836246d2b9536be$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/mud.png
Normal file
After Width: | Height: | Size: 375 B |
41
public/images/mystery-encounters/pokemon_salesman.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "pokemon_salesman.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 40,
|
||||
"h": 80
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 21,
|
||||
"y": 2,
|
||||
"w": 38,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 38,
|
||||
"h": 78
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:dd57e3db21f3933c15be65bec261f4c1:05c7ef32252a5c2d3ad007b7e26fabd7:ae82f52e471ed81e2558206f05476cd7$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/pokemon_salesman.png
Normal file
After Width: | Height: | Size: 839 B |
41
public/images/mystery-encounters/safari_zone.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "safari_zone.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 120,
|
||||
"h": 84
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 118,
|
||||
"h": 82
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 118,
|
||||
"h": 82
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 118,
|
||||
"h": 82
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:6fad7a61e47043b974153148b4fd3997:5ec4d0890f2f03446daf22c8ae8ba77b:87aa745cd95eef6cbf38935230f4e10f$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/safari_zone.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
41
public/images/mystery-encounters/teacher.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "teacher.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 43,
|
||||
"h": 74
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 19,
|
||||
"y": 8,
|
||||
"w": 41,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 72
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:506e5a4ce79c134a7b4af90a90aef244:1b81d3d84bf12cedc419805eaff82548:59bc5dd000b5e72588320b473e31c312$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/teacher.png
Normal file
After Width: | Height: | Size: 727 B |
41
public/images/mystery-encounters/teleporter.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "teleporter.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 74,
|
||||
"h": 79
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 74,
|
||||
"h": 79
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 74,
|
||||
"h": 79
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 74,
|
||||
"h": 79
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:937d8502b98f79720118061b6021e108:2b4f9db00d5b0997b42a5466f808509b:ce1615396ce7b0a146766d50b319bb81$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/teleporter.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
41
public/images/mystery-encounters/training_gear.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "training_gear.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 76,
|
||||
"h": 57
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 76,
|
||||
"h": 57
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 10,
|
||||
"y": 3,
|
||||
"w": 56,
|
||||
"h": 54
|
||||
},
|
||||
"frame": {
|
||||
"x": 8,
|
||||
"y": 0,
|
||||
"w": 56,
|
||||
"h": 54
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:895f0a79b89fa0fb44167f4584fd9a22:357b46953b7e17c6b2f43a62d52855d8:cc1ed0e4f90aaa9dcf1b39a0af1283b0$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/training_gear.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
41
public/images/mystery-encounters/warehouse_crate.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "warehouse_crate.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 71,
|
||||
"h": 52
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 56
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 4,
|
||||
"w": 71,
|
||||
"h": 52
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 71,
|
||||
"h": 52
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:c8df5f0b35fb9c2a69b0e4aaa9fa9f91:f1d4643c26f2aed86ad77d354e669aaf:0c073e3c2048ea0779db9429e5e1d8bc$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/warehouse_crate.png
Normal file
After Width: | Height: | Size: 868 B |
41
public/images/mystery-encounters/weird_dream_woman.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "weird_dream_woman.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 78,
|
||||
"h": 87
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 87
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
"w": 78,
|
||||
"h": 87
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 78,
|
||||
"h": 87
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:d3cce87ee0e3a880d840bffe9373d5d4:7c776d33b75abad1fe36b14a5e5734af:56468b7a2883e66dadcd2af13ebd8010$"
|
||||
}
|
||||
}
|
BIN
public/images/mystery-encounters/weird_dream_woman.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
524
public/images/trainer/buck.json
Normal file
@ -0,0 +1,524 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "buck.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 120,
|
||||
"h": 78
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 33,
|
||||
"y": 4,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 33,
|
||||
"y": 4,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 33,
|
||||
"y": 4,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 33,
|
||||
"y": 4,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 33,
|
||||
"y": 4,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 33,
|
||||
"y": 4,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0014.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 33,
|
||||
"y": 4,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0015.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 33,
|
||||
"y": 4,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0018.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 18,
|
||||
"y": 8,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 38,
|
||||
"y": 1,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0019.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 18,
|
||||
"y": 8,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 38,
|
||||
"y": 1,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0020.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 15,
|
||||
"y": 8,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 38,
|
||||
"y": 1,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0021.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 15,
|
||||
"y": 8,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 38,
|
||||
"y": 1,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0022.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 8,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 38,
|
||||
"y": 1,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0023.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 8,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 38,
|
||||
"y": 1,
|
||||
"w": 44,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0013.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0016.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0017.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 34,
|
||||
"y": 5,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 1,
|
||||
"w": 35,
|
||||
"h": 75
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:033f3d363b4192f64c92e02c19622c15:0d06141bef5af87ef82da967253207cb:3347efe478119141b0e3e6eccdecd0f5$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/buck.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
1469
public/images/trainer/bug_type_superfan.json
Normal file
BIN
public/images/trainer/bug_type_superfan.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
398
public/images/trainer/cheryl.json
Normal file
@ -0,0 +1,398 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "cheryl.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 154,
|
||||
"h": 83
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 25,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 25,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 26,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 26,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 27,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 44,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 27,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 44,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 24,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 44,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0013.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 24,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 44,
|
||||
"y": 1,
|
||||
"w": 41,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0014.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 27,
|
||||
"y": 0,
|
||||
"w": 33,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 87,
|
||||
"y": 1,
|
||||
"w": 33,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0015.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 27,
|
||||
"y": 0,
|
||||
"w": 33,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 87,
|
||||
"y": 1,
|
||||
"w": 33,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0016.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 26,
|
||||
"y": 0,
|
||||
"w": 33,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 87,
|
||||
"y": 1,
|
||||
"w": 33,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0017.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 26,
|
||||
"y": 0,
|
||||
"w": 33,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 87,
|
||||
"y": 1,
|
||||
"w": 33,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 0,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 122,
|
||||
"y": 1,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 0,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 122,
|
||||
"y": 1,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 0,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 122,
|
||||
"y": 1,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 0,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 122,
|
||||
"y": 1,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 21,
|
||||
"y": 0,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 122,
|
||||
"y": 1,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 81
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 21,
|
||||
"y": 0,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
},
|
||||
"frame": {
|
||||
"x": 122,
|
||||
"y": 1,
|
||||
"w": 31,
|
||||
"h": 81
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:dfcf7aedbd588c4e42427a2e17c171bf:206549943a0e3325d20a017ef01eefee:a233cd27590422717866c66e366b68fb$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/cheryl.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
83
public/images/trainer/marley.json
Normal file
@ -0,0 +1,83 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 31, "h": 77 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 26, "y": 2, "w": 31, "h": 77 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 31, "h": 77 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 26, "y": 2, "w": 31, "h": 77 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 31, "h": 77 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 26, "y": 2, "w": 31, "h": 77 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 31, "h": 77 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 26, "y": 2, "w": 31, "h": 77 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"frame": { "x": 32, "y": 0, "w": 28, "h": 78 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 28, "y": 1, "w": 28, "h": 78 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"frame": { "x": 32, "y": 0, "w": 28, "h": 78 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 28, "y": 1, "w": 28, "h": 78 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"frame": { "x": 0, "y": 78, "w": 31, "h": 77 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 28, "y": 2, "w": 31, "h": 77 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"frame": { "x": 0, "y": 78, "w": 31, "h": 77 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 28, "y": 2, "w": 31, "h": 77 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.pngprite.org/",
|
||||
"version": "1.3.7-x64",
|
||||
"image": "marley.png",
|
||||
"format": "I8",
|
||||
"size": { "w": 60, "h": 155 },
|
||||
"scale": "1"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/marley.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
209
public/images/trainer/mira.json
Normal file
@ -0,0 +1,209 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 23, "y": 14, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 23, "y": 14, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 22, "y": 13, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 11, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 53, "h": 63 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 11, "w": 53, "h": 63 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 53, "h": 63 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 12, "w": 53, "h": 63 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"frame": { "x": 0, "y": 63, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 13, "y": 11, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"frame": { "x": 0, "y": 63, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 13, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"frame": { "x": 0, "y": 63, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 11, "y": 14, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"frame": { "x": 0, "y": 63, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 13, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"frame": { "x": 0, "y": 63, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 13, "y": 11, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 53, "h": 63 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 11, "w": 53, "h": 63 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 53, "h": 63 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 12, "w": 53, "h": 63 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0013.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 11, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0014.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 22, "y": 13, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0015.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 23, "y": 14, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0016.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 22, "y": 13, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0017.png",
|
||||
"frame": { "x": 53, "y": 0, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 11, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0018.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 53, "h": 63 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 11, "w": 53, "h": 63 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0019.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 53, "h": 63 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 21, "y": 12, "w": 53, "h": 63 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0020.png",
|
||||
"frame": { "x": 0, "y": 63, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 13, "y": 11, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0021.png",
|
||||
"frame": { "x": 0, "y": 63, "w": 44, "h": 65 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 13, "w": 44, "h": 65 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.aseprite.org/",
|
||||
"version": "1.3.7-x64",
|
||||
"image": "mira.png",
|
||||
"format": "I8",
|
||||
"size": { "w": 97, "h": 128 },
|
||||
"scale": "1"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/mira.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
209
public/images/trainer/riley.json
Normal file
@ -0,0 +1,209 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "0000.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 11, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 11, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 11, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 11, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"frame": { "x": 55, "y": 80, "w": 37, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 31, "y": 0, "w": 37, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"frame": { "x": 55, "y": 80, "w": 37, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 31, "y": 0, "w": 37, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"frame": { "x": 55, "y": 80, "w": 37, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 30, "y": 0, "w": 37, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"frame": { "x": 55, "y": 80, "w": 37, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 30, "y": 0, "w": 37, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"frame": { "x": 55, "y": 80, "w": 37, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 28, "y": 0, "w": 37, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"frame": { "x": 55, "y": 80, "w": 37, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 28, "y": 0, "w": 37, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 10, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 10, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 11, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0013.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 11, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0014.png",
|
||||
"frame": { "x": 55, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0015.png",
|
||||
"frame": { "x": 55, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0016.png",
|
||||
"frame": { "x": 0, "y": 80, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0017.png",
|
||||
"frame": { "x": 0, "y": 80, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0018.png",
|
||||
"frame": { "x": 55, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0019.png",
|
||||
"frame": { "x": 55, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0020.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "0021.png",
|
||||
"frame": { "x": 0, "y": 0, "w": 55, "h": 80 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 12, "y": 0, "w": 55, "h": 80 },
|
||||
"sourceSize": { "w": 80, "h": 80 },
|
||||
"duration": 100
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.aseprite.org/",
|
||||
"version": "1.3.7-x64",
|
||||
"image": "riley.png",
|
||||
"format": "I8",
|
||||
"size": { "w": 110, "h": 160 },
|
||||
"scale": "1"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/riley.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
41
public/images/trainer/vicky.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "vicky.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 52,
|
||||
"h": 53
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 27,
|
||||
"w": 52,
|
||||
"h": 53
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 52,
|
||||
"h": 53
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:bf9d2d417a1982282dd711456ac71206:101e07828e3d6e2a2a7a80aebfa802ad:cabe44a4410c334298b1984a219f8160$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/vicky.png
Normal file
After Width: | Height: | Size: 765 B |
41
public/images/trainer/victor.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "victor.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 55,
|
||||
"h": 53
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 12,
|
||||
"y": 27,
|
||||
"w": 55,
|
||||
"h": 53
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 55,
|
||||
"h": 53
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:64eff0f697754cdf9552b46342c9292a:611e0e2cacbd90c1229ce5443b2414f0:0cc0f5a2c1b2eedb46dd8318e8feb1d8$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/victor.png
Normal file
After Width: | Height: | Size: 794 B |
41
public/images/trainer/victoria.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "victoria.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 52,
|
||||
"h": 54
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 14,
|
||||
"y": 26,
|
||||
"w": 52,
|
||||
"h": 54
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 52,
|
||||
"h": 54
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:4dafeae3674d63b12cc4d8044f67b5a3:7834687d784c31169256927f419c7958:cf0eb39e0a3f2e42f23ca29747d73c40$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/victoria.png
Normal file
After Width: | Height: | Size: 813 B |
41
public/images/trainer/vito.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "vito.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 41,
|
||||
"h": 78
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 2,
|
||||
"w": 41,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 78
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:cb988be58fcd5381174e9d120b051e38:4d4723dbbcd9713ee0ed3c2d84ef4bfb:1c7723b536b218346e3138016d865ce9$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/vito.png
Normal file
After Width: | Height: | Size: 765 B |
41
public/images/trainer/vivi.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "vivi.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 48,
|
||||
"h": 69
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 13,
|
||||
"y": 11,
|
||||
"w": 48,
|
||||
"h": 69
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 48,
|
||||
"h": 69
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:0a51b4df0b2ed0fed7e3bdb5dffd9e28:af1f3b1480023b3e3761c49e49faf5f1:4fc6bf2bec74c4bb8809df38231deb01$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/vivi.png
Normal file
After Width: | Height: | Size: 713 B |
@ -2,18 +2,28 @@ import Phaser from "phaser";
|
||||
import UI from "./ui/ui";
|
||||
import Pokemon, { PlayerPokemon, EnemyPokemon } from "./field/pokemon";
|
||||
import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies } from "./data/pokemon-species";
|
||||
import { Constructor } from "#app/utils";
|
||||
import { Constructor, isNullOrUndefined } from "#app/utils";
|
||||
import * as Utils from "./utils";
|
||||
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, TurnHeldItemTransferModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems } from "./modifier/modifier";
|
||||
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, TurnHeldItemTransferModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems, PokemonIncrementingStatModifier, ExpShareModifier, ExpBalanceModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "./modifier/modifier";
|
||||
import { PokeballType } from "./data/pokeball";
|
||||
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "./data/battle-anims";
|
||||
import { Phase } from "./phase";
|
||||
import { initGameSpeed } from "./system/game-speed";
|
||||
import { Arena, ArenaBase } from "./field/arena";
|
||||
import { GameData } from "./system/game-data";
|
||||
import { TextStyle, addTextObject, getTextColor } from "./ui/text";
|
||||
import { addTextObject, getTextColor, TextStyle } from "./ui/text";
|
||||
import { allMoves } from "./data/move";
|
||||
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, modifierTypes } from "./modifier/modifier-type";
|
||||
import {
|
||||
ModifierPoolType,
|
||||
getDefaultModifierTypeForTier,
|
||||
getEnemyModifierTypesForWave,
|
||||
getLuckString,
|
||||
getLuckTextTint,
|
||||
getModifierPoolForType,
|
||||
getModifierType,
|
||||
getPartyLuckValue,
|
||||
modifierTypes, PokemonHeldItemModifierType
|
||||
} from "./modifier/modifier-type";
|
||||
import AbilityBar from "./ui/ability-bar";
|
||||
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
|
||||
import { allAbilities } from "./data/ability";
|
||||
@ -22,14 +32,14 @@ import { GameMode, GameModes, getGameMode } from "./game-mode";
|
||||
import FieldSpritePipeline from "./pipelines/field-sprite";
|
||||
import SpritePipeline from "./pipelines/sprite";
|
||||
import PartyExpBar from "./ui/party-exp-bar";
|
||||
import { TrainerSlot, trainerConfigs } from "./data/trainer-config";
|
||||
import { trainerConfigs, TrainerSlot } from "./data/trainer-config";
|
||||
import Trainer, { TrainerVariant } from "./field/trainer";
|
||||
import TrainerData from "./system/trainer-data";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { pokemonPrevolutions } from "./data/pokemon-evolutions";
|
||||
import PokeballTray from "./ui/pokeball-tray";
|
||||
import InvertPostFX from "./pipelines/invert";
|
||||
import { Achv, ModifierAchv, MoneyAchv, achvs } from "./system/achv";
|
||||
import { Achv, achvs, ModifierAchv, MoneyAchv } from "./system/achv";
|
||||
import { Voucher, vouchers } from "./system/voucher";
|
||||
import { Gender } from "./data/gender";
|
||||
import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin";
|
||||
@ -86,6 +96,15 @@ import { TitlePhase } from "./phases/title-phase";
|
||||
import { ToggleDoublePositionPhase } from "./phases/toggle-double-position-phase";
|
||||
import { TurnInitPhase } from "./phases/turn-init-phase";
|
||||
import { ShopCursorTarget } from "./enums/shop-cursor-target";
|
||||
import MysteryEncounter from "./data/mystery-encounters/mystery-encounter";
|
||||
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters";
|
||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import { ExpPhase } from "#app/phases/exp-phase";
|
||||
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
|
||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||
|
||||
@ -246,6 +265,10 @@ export default class BattleScene extends SceneBase {
|
||||
public money: integer;
|
||||
public pokemonInfoContainer: PokemonInfoContainer;
|
||||
private party: PlayerPokemon[];
|
||||
/** Session save data that pertains to Mystery Encounters */
|
||||
public mysteryEncounterSaveData: MysteryEncounterSaveData = new MysteryEncounterSaveData();
|
||||
/** If the previous wave was a MysteryEncounter, tracks the object with this variable. Mostly used for visual object cleanup */
|
||||
public lastMysteryEncounter?: MysteryEncounter;
|
||||
/** Combined Biome and Wave count text */
|
||||
private biomeWaveText: Phaser.GameObjects.Text;
|
||||
private moneyText: Phaser.GameObjects.Text;
|
||||
@ -884,6 +907,26 @@ export default class BattleScene extends SceneBase {
|
||||
return pokemon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@linkcode PlayerPokemon} from the party, and clears modifiers for that Pokemon's id
|
||||
* Useful for MEs/Challenges that remove Pokemon from the player party temporarily or permanently
|
||||
* @param pokemon
|
||||
* @param destroy Default true. If true, will destroy the {@linkcode PlayerPokemon} after removing
|
||||
*/
|
||||
removePokemonFromPlayerParty(pokemon: PlayerPokemon, destroy: boolean = true) {
|
||||
if (!pokemon) {
|
||||
return;
|
||||
}
|
||||
|
||||
const partyIndex = this.party.indexOf(pokemon);
|
||||
this.party.splice(partyIndex, 1);
|
||||
if (destroy) {
|
||||
this.field.remove(pokemon, true);
|
||||
pokemon.destroy();
|
||||
}
|
||||
this.updateModifiers(true);
|
||||
}
|
||||
|
||||
addPokemonIcon(pokemon: Pokemon, x: number, y: number, originX: number = 0.5, originY: number = 0.5, ignoreOverride: boolean = false): Phaser.GameObjects.Container {
|
||||
const container = this.add.container(x, y);
|
||||
container.setName(`${pokemon.name}-icon`);
|
||||
@ -1086,7 +1129,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
}
|
||||
|
||||
newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean): Battle | null {
|
||||
newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean, mysteryEncounterType?: MysteryEncounterType): Battle | null {
|
||||
const _startingWave = Overrides.STARTING_WAVE_OVERRIDE || startingWave;
|
||||
const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (_startingWave - 1)) + 1);
|
||||
let newDouble: boolean | undefined;
|
||||
@ -1135,6 +1178,36 @@ export default class BattleScene extends SceneBase {
|
||||
newTrainer = trainerData !== undefined ? trainerData.toTrainer(this) : new Trainer(this, trainerType, variant);
|
||||
this.field.add(newTrainer);
|
||||
}
|
||||
|
||||
// Check for mystery encounter
|
||||
// Can only occur in place of a standard (non-boss) wild battle, waves 10-180
|
||||
const [lowestMysteryEncounterWave, highestMysteryEncounterWave] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(newWaveIndex) && newWaveIndex < highestMysteryEncounterWave && newWaveIndex > lowestMysteryEncounterWave) {
|
||||
const roll = Utils.randSeedInt(MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT);
|
||||
|
||||
// Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor
|
||||
const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
|
||||
const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents;
|
||||
|
||||
// If total number of encounters is lower than expected for the run, slightly favor a new encounter spawn (reverse as well)
|
||||
// Reduces occurrence of runs with total encounters significantly different from AVERAGE_ENCOUNTERS_PER_RUN_TARGET
|
||||
const expectedEncountersByFloor = AVERAGE_ENCOUNTERS_PER_RUN_TARGET / (highestMysteryEncounterWave - lowestMysteryEncounterWave) * (newWaveIndex - lowestMysteryEncounterWave);
|
||||
const currentRunDiffFromAvg = expectedEncountersByFloor - encounteredEvents.length;
|
||||
const favoredEncounterRate = sessionEncounterRate + currentRunDiffFromAvg * ANTI_VARIANCE_WEIGHT_MODIFIER;
|
||||
|
||||
const successRate = isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_RATE_OVERRIDE) ? favoredEncounterRate : Overrides.MYSTERY_ENCOUNTER_RATE_OVERRIDE!;
|
||||
|
||||
// If the most recent ME was 3 or fewer waves ago, can never spawn a ME
|
||||
const canSpawn = encounteredEvents.length === 0 || (newWaveIndex - encounteredEvents[encounteredEvents.length - 1].waveIndex) > 3 || !isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_RATE_OVERRIDE);
|
||||
|
||||
if (canSpawn && roll < successRate) {
|
||||
newBattleType = BattleType.MYSTERY_ENCOUNTER;
|
||||
// Reset base spawn weight
|
||||
this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
|
||||
} else {
|
||||
this.mysteryEncounterSaveData.encounterSpawnChance = sessionEncounterRate + WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (double === undefined && newWaveIndex > 1) {
|
||||
@ -1167,12 +1240,21 @@ export default class BattleScene extends SceneBase {
|
||||
const maxExpLevel = this.getMaxExpLevel();
|
||||
|
||||
this.lastEnemyTrainer = lastBattle?.trainer ?? null;
|
||||
this.lastMysteryEncounter = lastBattle?.mysteryEncounter;
|
||||
|
||||
this.executeWithSeedOffset(() => {
|
||||
this.currentBattle = new Battle(this.gameMode, newWaveIndex, newBattleType, newTrainer, newDouble);
|
||||
}, newWaveIndex << 3, this.waveSeed);
|
||||
this.currentBattle.incrementTurn(this);
|
||||
|
||||
if (newBattleType === BattleType.MYSTERY_ENCOUNTER) {
|
||||
// Disable double battle on mystery encounters (it may be re-enabled as part of encounter)
|
||||
this.currentBattle.double = false;
|
||||
this.executeWithSeedOffset(() => {
|
||||
this.currentBattle.mysteryEncounter = this.getMysteryEncounter(mysteryEncounterType);
|
||||
}, this.currentBattle.waveIndex << 4);
|
||||
}
|
||||
|
||||
//this.pushPhase(new TrainerMessageTestPhase(this, TrainerType.RIVAL, TrainerType.RIVAL_2, TrainerType.RIVAL_3, TrainerType.RIVAL_4, TrainerType.RIVAL_5, TrainerType.RIVAL_6));
|
||||
|
||||
if (!waveIndex && lastBattle) {
|
||||
@ -1181,7 +1263,7 @@ export default class BattleScene extends SceneBase {
|
||||
const isEndlessFifthWave = this.gameMode.hasShortBiomes && (lastBattle.waveIndex % 5) === 0;
|
||||
const isWaveIndexMultipleOfFiftyMinusOne = (lastBattle.waveIndex % 50) === 49;
|
||||
const isNewBiome = isWaveIndexMultipleOfTen || isEndlessFifthWave || (isEndlessOrDaily && isWaveIndexMultipleOfFiftyMinusOne);
|
||||
const resetArenaState = isNewBiome || this.currentBattle.battleType === BattleType.TRAINER || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
||||
const resetArenaState = isNewBiome || [BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.currentBattle.battleType) || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
||||
this.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy());
|
||||
this.trySpreadPokerus();
|
||||
if (!isNewBiome && (newWaveIndex % 10) === 5) {
|
||||
@ -1189,14 +1271,21 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
if (resetArenaState) {
|
||||
this.arena.resetArenaEffects();
|
||||
playerField.forEach((_, p) => this.pushPhase(new ReturnPhase(this, p)));
|
||||
|
||||
playerField.forEach((pokemon, p) => {
|
||||
if (pokemon.isOnField()) {
|
||||
this.pushPhase(new ReturnPhase(this, p));
|
||||
}
|
||||
});
|
||||
|
||||
for (const pokemon of this.getParty()) {
|
||||
pokemon.resetBattleData();
|
||||
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
||||
}
|
||||
|
||||
this.pushPhase(new ShowTrainerPhase(this));
|
||||
if (!this.trainer.visible) {
|
||||
this.pushPhase(new ShowTrainerPhase(this));
|
||||
}
|
||||
}
|
||||
|
||||
for (const pokemon of this.getParty()) {
|
||||
@ -1290,7 +1379,6 @@ export default class BattleScene extends SceneBase {
|
||||
case Species.ZARUDE:
|
||||
case Species.SQUAWKABILLY:
|
||||
case Species.TATSUGIRI:
|
||||
case Species.GIMMIGHOUL:
|
||||
case Species.PALDEA_TAUROS:
|
||||
return Utils.randSeedInt(species.forms.length);
|
||||
case Species.PIKACHU:
|
||||
@ -1316,6 +1404,13 @@ export default class BattleScene extends SceneBase {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
case Species.GIMMIGHOUL:
|
||||
// Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs
|
||||
if (this.gameMode.hasMysteryEncounters) {
|
||||
return 1; // Wandering form
|
||||
} else {
|
||||
return Utils.randSeedInt(species.forms.length);
|
||||
}
|
||||
}
|
||||
|
||||
if (ignoreArena) {
|
||||
@ -2485,7 +2580,7 @@ export default class BattleScene extends SceneBase {
|
||||
});
|
||||
}
|
||||
|
||||
generateEnemyModifiers(): Promise<void> {
|
||||
generateEnemyModifiers(heldModifiersConfigs?: HeldModifierConfig[][]): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) {
|
||||
return resolve();
|
||||
@ -2507,29 +2602,47 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
party.forEach((enemyPokemon: EnemyPokemon, i: integer) => {
|
||||
const isBoss = enemyPokemon.isBoss() || (this.currentBattle.battleType === BattleType.TRAINER && !!this.currentBattle.trainer?.config.isBoss);
|
||||
let upgradeChance = 32;
|
||||
if (isBoss) {
|
||||
upgradeChance /= 2;
|
||||
}
|
||||
if (isFinalBoss) {
|
||||
upgradeChance /= 8;
|
||||
}
|
||||
const modifierChance = this.gameMode.getEnemyModifierChance(isBoss);
|
||||
let pokemonModifierChance = modifierChance;
|
||||
if (this.currentBattle.battleType === BattleType.TRAINER && this.currentBattle.trainer)
|
||||
pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); // eslint-disable-line
|
||||
let count = 0;
|
||||
for (let c = 0; c < chances; c++) {
|
||||
if (!Utils.randSeedInt(modifierChance)) {
|
||||
count++;
|
||||
if (heldModifiersConfigs && i < heldModifiersConfigs.length && heldModifiersConfigs[i] && heldModifiersConfigs[i].length > 0) {
|
||||
heldModifiersConfigs[i].forEach(mt => {
|
||||
let modifier: PokemonHeldItemModifier;
|
||||
if (mt.modifier instanceof PokemonHeldItemModifierType) {
|
||||
modifier = mt.modifier.newModifier(enemyPokemon);
|
||||
} else {
|
||||
modifier = mt.modifier as PokemonHeldItemModifier;
|
||||
modifier.pokemonId = enemyPokemon.id;
|
||||
}
|
||||
const stackCount = mt.stackCount ?? 1;
|
||||
modifier.stackCount = stackCount;
|
||||
// TODO: set isTransferable
|
||||
// modifier.isTransferrable = mt.isTransferable ?? true;
|
||||
this.addEnemyModifier(modifier, true);
|
||||
});
|
||||
} else {
|
||||
const isBoss = enemyPokemon.isBoss() || (this.currentBattle.battleType === BattleType.TRAINER && !!this.currentBattle.trainer?.config.isBoss);
|
||||
let upgradeChance = 32;
|
||||
if (isBoss) {
|
||||
upgradeChance /= 2;
|
||||
}
|
||||
if (isFinalBoss) {
|
||||
upgradeChance /= 8;
|
||||
}
|
||||
const modifierChance = this.gameMode.getEnemyModifierChance(isBoss);
|
||||
let pokemonModifierChance = modifierChance;
|
||||
if (this.currentBattle.battleType === BattleType.TRAINER && this.currentBattle.trainer)
|
||||
pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); // eslint-disable-line
|
||||
let count = 0;
|
||||
for (let c = 0; c < chances; c++) {
|
||||
if (!Utils.randSeedInt(modifierChance)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (isBoss) {
|
||||
count = Math.max(count, Math.floor(chances / 2));
|
||||
}
|
||||
getEnemyModifierTypesForWave(difficultyWaveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance)
|
||||
.map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this));
|
||||
}
|
||||
if (isBoss) {
|
||||
count = Math.max(count, Math.floor(chances / 2));
|
||||
}
|
||||
getEnemyModifierTypesForWave(difficultyWaveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance)
|
||||
.map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this));
|
||||
return true;
|
||||
});
|
||||
this.updateModifiers(false).then(() => resolve());
|
||||
});
|
||||
@ -2837,4 +2950,220 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
this.shiftPhase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates Exp and level values for Player's party, adding new level up phases as required
|
||||
* @param expValue raw value of exp to split among participants, OR the base multiplier to use with waveIndex
|
||||
* @param pokemonDefeated If true, will increment Macho Brace stacks and give the party Pokemon friendship increases
|
||||
* @param useWaveIndexMultiplier Default false. If true, will multiply expValue by a scaling waveIndex multiplier. Not needed if expValue is already scaled by level/wave
|
||||
* @param pokemonParticipantIds Participants. If none are defined, no exp will be given. To spread evenly among the party, should pass all ids of party members.
|
||||
*/
|
||||
applyPartyExp(expValue: number, pokemonDefeated: boolean, useWaveIndexMultiplier?: boolean, pokemonParticipantIds?: Set<number>): void {
|
||||
const participantIds = pokemonParticipantIds ?? this.currentBattle.playerParticipantIds;
|
||||
const party = this.getParty();
|
||||
const expShareModifier = this.findModifier(m => m instanceof ExpShareModifier) as ExpShareModifier;
|
||||
const expBalanceModifier = this.findModifier(m => m instanceof ExpBalanceModifier) as ExpBalanceModifier;
|
||||
const multipleParticipantExpBonusModifier = this.findModifier(m => m instanceof MultipleParticipantExpBonusModifier) as MultipleParticipantExpBonusModifier;
|
||||
const nonFaintedPartyMembers = party.filter(p => p.hp);
|
||||
const expPartyMembers = nonFaintedPartyMembers.filter(p => p.level < this.getMaxExpLevel());
|
||||
const partyMemberExp: number[] = [];
|
||||
// EXP value calculation is based off Pokemon.getExpValue
|
||||
if (useWaveIndexMultiplier) {
|
||||
expValue = Math.floor(expValue * this.currentBattle.waveIndex / 5 + 1);
|
||||
}
|
||||
|
||||
if (participantIds.size > 0) {
|
||||
if (this.currentBattle.battleType === BattleType.TRAINER || this.currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||
expValue = Math.floor(expValue * 1.5);
|
||||
} else if (this.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER && this.currentBattle.mysteryEncounter) {
|
||||
expValue = Math.floor(expValue * this.currentBattle.mysteryEncounter.expMultiplier);
|
||||
}
|
||||
for (const partyMember of nonFaintedPartyMembers) {
|
||||
const pId = partyMember.id;
|
||||
const participated = participantIds.has(pId);
|
||||
if (participated && pokemonDefeated) {
|
||||
partyMember.addFriendship(2);
|
||||
const machoBraceModifier = partyMember.getHeldItems().find(m => m instanceof PokemonIncrementingStatModifier);
|
||||
if (machoBraceModifier && machoBraceModifier.stackCount < machoBraceModifier.getMaxStackCount(this)) {
|
||||
machoBraceModifier.stackCount++;
|
||||
this.updateModifiers(true, true);
|
||||
partyMember.updateInfo();
|
||||
}
|
||||
}
|
||||
if (!expPartyMembers.includes(partyMember)) {
|
||||
continue;
|
||||
}
|
||||
if (!participated && !expShareModifier) {
|
||||
partyMemberExp.push(0);
|
||||
continue;
|
||||
}
|
||||
let expMultiplier = 0;
|
||||
if (participated) {
|
||||
expMultiplier += (1 / participantIds.size);
|
||||
if (participantIds.size > 1 && multipleParticipantExpBonusModifier) {
|
||||
expMultiplier += multipleParticipantExpBonusModifier.getStackCount() * 0.2;
|
||||
}
|
||||
} else if (expShareModifier) {
|
||||
expMultiplier += (expShareModifier.getStackCount() * 0.2) / participantIds.size;
|
||||
}
|
||||
if (partyMember.pokerus) {
|
||||
expMultiplier *= 1.5;
|
||||
}
|
||||
if (Overrides.XP_MULTIPLIER_OVERRIDE !== null) {
|
||||
expMultiplier = Overrides.XP_MULTIPLIER_OVERRIDE;
|
||||
}
|
||||
const pokemonExp = new Utils.NumberHolder(expValue * expMultiplier);
|
||||
this.applyModifiers(PokemonExpBoosterModifier, true, partyMember, pokemonExp);
|
||||
partyMemberExp.push(Math.floor(pokemonExp.value));
|
||||
}
|
||||
|
||||
if (expBalanceModifier) {
|
||||
let totalLevel = 0;
|
||||
let totalExp = 0;
|
||||
expPartyMembers.forEach((expPartyMember, epm) => {
|
||||
totalExp += partyMemberExp[epm];
|
||||
totalLevel += expPartyMember.level;
|
||||
});
|
||||
|
||||
const medianLevel = Math.floor(totalLevel / expPartyMembers.length);
|
||||
|
||||
const recipientExpPartyMemberIndexes: number[] = [];
|
||||
expPartyMembers.forEach((expPartyMember, epm) => {
|
||||
if (expPartyMember.level <= medianLevel) {
|
||||
recipientExpPartyMemberIndexes.push(epm);
|
||||
}
|
||||
});
|
||||
|
||||
const splitExp = Math.floor(totalExp / recipientExpPartyMemberIndexes.length);
|
||||
|
||||
expPartyMembers.forEach((_partyMember, pm) => {
|
||||
partyMemberExp[pm] = Phaser.Math.Linear(partyMemberExp[pm], recipientExpPartyMemberIndexes.indexOf(pm) > -1 ? splitExp : 0, 0.2 * expBalanceModifier.getStackCount());
|
||||
});
|
||||
}
|
||||
|
||||
for (let pm = 0; pm < expPartyMembers.length; pm++) {
|
||||
const exp = partyMemberExp[pm];
|
||||
|
||||
if (exp) {
|
||||
const partyMemberIndex = party.indexOf(expPartyMembers[pm]);
|
||||
this.unshiftPhase(expPartyMembers[pm].isOnField() ? new ExpPhase(this, partyMemberIndex, exp) : new ShowPartyExpBarPhase(this, partyMemberIndex, exp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads or generates a mystery encounter
|
||||
* @param encounterType used to load session encounter when restarting game, etc.
|
||||
* @returns
|
||||
*/
|
||||
getMysteryEncounter(encounterType?: MysteryEncounterType): MysteryEncounter {
|
||||
// Loading override or session encounter
|
||||
let encounter: MysteryEncounter | null;
|
||||
if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_OVERRIDE) && allMysteryEncounters.hasOwnProperty(Overrides.MYSTERY_ENCOUNTER_OVERRIDE!)) {
|
||||
encounter = allMysteryEncounters[Overrides.MYSTERY_ENCOUNTER_OVERRIDE!];
|
||||
} else {
|
||||
encounter = !isNullOrUndefined(encounterType) ? allMysteryEncounters[encounterType!] : null;
|
||||
}
|
||||
|
||||
// Check for queued encounters first
|
||||
if (!encounter && this.mysteryEncounterSaveData?.queuedEncounters && this.mysteryEncounterSaveData.queuedEncounters.length > 0) {
|
||||
let i = 0;
|
||||
while (i < this.mysteryEncounterSaveData.queuedEncounters.length && !!encounter) {
|
||||
const candidate = this.mysteryEncounterSaveData.queuedEncounters[i];
|
||||
const forcedChance = candidate.spawnPercent;
|
||||
if (Utils.randSeedInt(100) < forcedChance) {
|
||||
encounter = allMysteryEncounters[candidate.type];
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (encounter) {
|
||||
encounter = new MysteryEncounter(encounter);
|
||||
encounter.populateDialogueTokensFromRequirements(this);
|
||||
return encounter;
|
||||
}
|
||||
|
||||
// See Enum values for base tier weights
|
||||
const tierWeights = [MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE];
|
||||
|
||||
// Adjust tier weights by previously encountered events to lower odds of only Common/Great in run
|
||||
this.mysteryEncounterSaveData.encounteredEvents.forEach(seenEncounterData => {
|
||||
if (seenEncounterData.tier === MysteryEncounterTier.COMMON) {
|
||||
tierWeights[0] = tierWeights[0] - 6;
|
||||
} else if (seenEncounterData.tier === MysteryEncounterTier.GREAT) {
|
||||
tierWeights[1] = tierWeights[1] - 4;
|
||||
}
|
||||
});
|
||||
|
||||
const totalWeight = tierWeights.reduce((a, b) => a + b);
|
||||
const tierValue = Utils.randSeedInt(totalWeight);
|
||||
const commonThreshold = totalWeight - tierWeights[0];
|
||||
const greatThreshold = totalWeight - tierWeights[0] - tierWeights[1];
|
||||
const ultraThreshold = totalWeight - tierWeights[0] - tierWeights[1] - tierWeights[2];
|
||||
let tier: MysteryEncounterTier | null = tierValue > commonThreshold ? MysteryEncounterTier.COMMON : tierValue > greatThreshold ? MysteryEncounterTier.GREAT : tierValue > ultraThreshold ? MysteryEncounterTier.ULTRA : MysteryEncounterTier.ROGUE;
|
||||
|
||||
if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_TIER_OVERRIDE)) {
|
||||
tier = Overrides.MYSTERY_ENCOUNTER_TIER_OVERRIDE!;
|
||||
}
|
||||
|
||||
let availableEncounters: MysteryEncounter[] = [];
|
||||
// New encounter should never be the same as the most recent encounter
|
||||
const previousEncounter = this.mysteryEncounterSaveData.encounteredEvents.length > 0 ? this.mysteryEncounterSaveData.encounteredEvents[this.mysteryEncounterSaveData.encounteredEvents.length - 1].type : null;
|
||||
const biomeMysteryEncounters = mysteryEncountersByBiome.get(this.arena.biomeType) ?? [];
|
||||
// If no valid encounters exist at tier, checks next tier down, continuing until there are some encounters available
|
||||
while (availableEncounters.length === 0 && tier !== null) {
|
||||
availableEncounters = biomeMysteryEncounters
|
||||
.filter((encounterType) => {
|
||||
const encounterCandidate = allMysteryEncounters[encounterType];
|
||||
if (!encounterCandidate) {
|
||||
return false;
|
||||
}
|
||||
if (encounterCandidate.encounterTier !== tier) { // Encounter is in tier
|
||||
return false;
|
||||
}
|
||||
const disabledModes = encounterCandidate.disabledGameModes;
|
||||
if (disabledModes && disabledModes.length > 0
|
||||
&& disabledModes.includes(this.gameMode.modeId)) { // Encounter is enabled for game mode
|
||||
return false;
|
||||
}
|
||||
if (!encounterCandidate.meetsRequirements(this)) { // Meets encounter requirements
|
||||
return false;
|
||||
}
|
||||
if (previousEncounter !== null && encounterType === previousEncounter) { // Previous encounter was not this one
|
||||
return false;
|
||||
}
|
||||
if (this.mysteryEncounterSaveData.encounteredEvents.length > 0 && // Encounter has not exceeded max allowed encounters
|
||||
(encounterCandidate.maxAllowedEncounters && encounterCandidate.maxAllowedEncounters > 0)
|
||||
&& this.mysteryEncounterSaveData.encounteredEvents.filter(e => e.type === encounterType).length >= encounterCandidate.maxAllowedEncounters) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((m) => (allMysteryEncounters[m]));
|
||||
// Decrement tier
|
||||
if (tier === MysteryEncounterTier.ROGUE) {
|
||||
tier = MysteryEncounterTier.ULTRA;
|
||||
} else if (tier === MysteryEncounterTier.ULTRA) {
|
||||
tier = MysteryEncounterTier.GREAT;
|
||||
} else if (tier === MysteryEncounterTier.GREAT) {
|
||||
tier = MysteryEncounterTier.COMMON;
|
||||
} else {
|
||||
tier = null; // Ends loop
|
||||
}
|
||||
}
|
||||
|
||||
// If absolutely no encounters are available, spawn 0th encounter
|
||||
if (availableEncounters.length === 0) {
|
||||
console.log("No Mystery Encounters found, falling back to Mysterious Challengers.");
|
||||
return allMysteryEncounters[MysteryEncounterType.MYSTERIOUS_CHALLENGERS];
|
||||
}
|
||||
encounter = availableEncounters[Utils.randSeedInt(availableEncounters.length)];
|
||||
// New encounter object to not dirty flags
|
||||
encounter = new MysteryEncounter(encounter);
|
||||
encounter.populateDialogueTokensFromRequirements(this);
|
||||
return encounter;
|
||||
}
|
||||
}
|
||||
|
@ -14,28 +14,31 @@ import { PlayerGender } from "#enums/player-gender";
|
||||
import { Species } from "#enums/species";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
import MysteryEncounter from "./data/mystery-encounters/mystery-encounter";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
|
||||
export enum BattleType {
|
||||
WILD,
|
||||
TRAINER,
|
||||
CLEAR
|
||||
WILD,
|
||||
TRAINER,
|
||||
CLEAR,
|
||||
MYSTERY_ENCOUNTER
|
||||
}
|
||||
|
||||
export enum BattlerIndex {
|
||||
ATTACKER = -1,
|
||||
PLAYER,
|
||||
PLAYER_2,
|
||||
ENEMY,
|
||||
ENEMY_2
|
||||
ATTACKER = -1,
|
||||
PLAYER,
|
||||
PLAYER_2,
|
||||
ENEMY,
|
||||
ENEMY_2
|
||||
}
|
||||
|
||||
export interface TurnCommand {
|
||||
command: Command;
|
||||
cursor?: number;
|
||||
move?: QueuedMove;
|
||||
targets?: BattlerIndex[];
|
||||
skip?: boolean;
|
||||
args?: any[];
|
||||
command: Command;
|
||||
cursor?: number;
|
||||
move?: QueuedMove;
|
||||
targets?: BattlerIndex[];
|
||||
skip?: boolean;
|
||||
args?: any[];
|
||||
}
|
||||
|
||||
export interface FaintLogEntry {
|
||||
@ -44,7 +47,7 @@ export interface FaintLogEntry {
|
||||
}
|
||||
|
||||
interface TurnCommands {
|
||||
[key: number]: TurnCommand | null
|
||||
[key: number]: TurnCommand | null
|
||||
}
|
||||
|
||||
export default class Battle {
|
||||
@ -77,6 +80,9 @@ export default class Battle {
|
||||
public playerFaintsHistory: FaintLogEntry[] = [];
|
||||
public enemyFaintsHistory: FaintLogEntry[] = [];
|
||||
|
||||
/** If the current battle is a Mystery Encounter, this will always be defined */
|
||||
public mysteryEncounter?: MysteryEncounter;
|
||||
|
||||
private rngCounter: number = 0;
|
||||
|
||||
constructor(gameMode: GameMode, waveIndex: number, battleType: BattleType, trainer?: Trainer, double?: boolean) {
|
||||
@ -99,7 +105,7 @@ export default class Battle {
|
||||
this.battleSpec = spec;
|
||||
}
|
||||
|
||||
private getLevelForWave(): number {
|
||||
public getLevelForWave(): number {
|
||||
const levelWaveIndex = this.gameMode.getWaveForDifficulty(this.waveIndex);
|
||||
const baseLevel = 1 + levelWaveIndex / 2 + Math.pow(levelWaveIndex / 25, 2);
|
||||
const bossMultiplier = 1.2;
|
||||
@ -197,7 +203,11 @@ export default class Battle {
|
||||
|
||||
getBgmOverride(scene: BattleScene): string | null {
|
||||
const battlers = this.enemyParty.slice(0, this.getBattlerCount());
|
||||
if (this.battleType === BattleType.TRAINER) {
|
||||
if (this.battleType === BattleType.MYSTERY_ENCOUNTER && this.mysteryEncounter?.encounterMode === MysteryEncounterMode.DEFAULT) {
|
||||
// Music is overridden for MEs during ME onInit()
|
||||
// Should not use any BGM overrides before swapping from DEFAULT mode
|
||||
return null;
|
||||
} else if (this.battleType === BattleType.TRAINER || this.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||
if (!this.started && this.trainer?.config.encounterBgm && this.trainer?.getEncounterMessages()?.length) {
|
||||
return `encounter_${this.trainer?.getEncounterBgm()}`;
|
||||
}
|
||||
|
@ -7,6 +7,9 @@ import { BattlerIndex } from "../battle";
|
||||
import { Element } from "json-stable-stringify";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { SubstituteTag } from "./battler-tags";
|
||||
import { isNullOrUndefined } from "../utils";
|
||||
import Phaser from "phaser";
|
||||
import { EncounterAnim } from "#enums/encounter-anims";
|
||||
//import fs from 'vite-plugin-fs/browser';
|
||||
|
||||
export enum AnimFrameTarget {
|
||||
@ -304,7 +307,7 @@ abstract class AnimTimedEvent {
|
||||
this.resourceName = resourceName;
|
||||
}
|
||||
|
||||
abstract execute(scene: BattleScene, battleAnim: BattleAnim): integer;
|
||||
abstract execute(scene: BattleScene, battleAnim: BattleAnim, priority?: number): integer;
|
||||
|
||||
abstract getEventType(): string;
|
||||
}
|
||||
@ -322,7 +325,7 @@ class AnimTimedSoundEvent extends AnimTimedEvent {
|
||||
}
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, battleAnim: BattleAnim): integer {
|
||||
execute(scene: BattleScene, battleAnim: BattleAnim, priority?: number): integer {
|
||||
const soundConfig = { rate: (this.pitch * 0.01), volume: (this.volume * 0.01) };
|
||||
if (this.resourceName) {
|
||||
try {
|
||||
@ -384,7 +387,7 @@ class AnimTimedUpdateBgEvent extends AnimTimedBgEvent {
|
||||
super(frameIndex, resourceName, source);
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): integer {
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim, priority?: number): integer {
|
||||
const tweenProps = {};
|
||||
if (this.bgX !== undefined) {
|
||||
tweenProps["x"] = (this.bgX * 0.5) - 320;
|
||||
@ -414,7 +417,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
||||
super(frameIndex, resourceName, source);
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): integer {
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim, priority?: number): integer {
|
||||
if (moveAnim.bgSprite) {
|
||||
moveAnim.bgSprite.destroy();
|
||||
}
|
||||
@ -426,7 +429,9 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
||||
moveAnim.bgSprite.setAlpha(this.opacity / 255);
|
||||
scene.field.add(moveAnim.bgSprite);
|
||||
const fieldPokemon = scene.getEnemyPokemon() || scene.getPlayerPokemon();
|
||||
if (fieldPokemon?.isOnField()) {
|
||||
if (!isNullOrUndefined(priority)) {
|
||||
scene.field.moveTo(moveAnim.bgSprite as Phaser.GameObjects.GameObject, priority!);
|
||||
} else if (fieldPokemon?.isOnField()) {
|
||||
scene.field.moveBelow(moveAnim.bgSprite as Phaser.GameObjects.GameObject, fieldPokemon);
|
||||
}
|
||||
|
||||
@ -446,6 +451,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
||||
export const moveAnims = new Map<Moves, AnimConfig | [AnimConfig, AnimConfig] | null>();
|
||||
export const chargeAnims = new Map<ChargeAnim, AnimConfig | [AnimConfig, AnimConfig] | null>();
|
||||
export const commonAnims = new Map<CommonAnim, AnimConfig>();
|
||||
export const encounterAnims = new Map<EncounterAnim, AnimConfig>();
|
||||
|
||||
export function initCommonAnims(scene: BattleScene): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
@ -516,6 +522,26 @@ export function initMoveAnim(scene: BattleScene, move: Moves): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches animation configs to be used in a Mystery Encounter
|
||||
* @param scene
|
||||
* @param encounterAnim one or more animations to fetch
|
||||
*/
|
||||
export async function initEncounterAnims(scene: BattleScene, encounterAnim: EncounterAnim | EncounterAnim[]): Promise<void> {
|
||||
const anims = Array.isArray(encounterAnim) ? encounterAnim : [encounterAnim];
|
||||
const encounterAnimNames = Utils.getEnumKeys(EncounterAnim);
|
||||
const encounterAnimFetches: Promise<Map<EncounterAnim, AnimConfig>>[] = [];
|
||||
for (const anim of anims) {
|
||||
if (encounterAnims.has(anim) && !isNullOrUndefined(encounterAnims.get(anim))) {
|
||||
continue;
|
||||
}
|
||||
encounterAnimFetches.push(scene.cachedFetch(`./battle-anims/encounter-${encounterAnimNames[anim].toLowerCase().replace(/\_/g, "-")}.json`)
|
||||
.then(response => response.json())
|
||||
.then(cas => encounterAnims.set(anim, new AnimConfig(cas))));
|
||||
}
|
||||
await Promise.allSettled(encounterAnimFetches);
|
||||
}
|
||||
|
||||
export function initMoveChargeAnim(scene: BattleScene, chargeAnim: ChargeAnim): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (chargeAnims.has(chargeAnim)) {
|
||||
@ -570,6 +596,16 @@ export function loadCommonAnimAssets(scene: BattleScene, startLoad?: boolean): P
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads encounter animation assets to scene
|
||||
* MUST be called after {@linkcode initEncounterAnims()} to load all required animations properly
|
||||
* @param scene
|
||||
* @param startLoad
|
||||
*/
|
||||
export async function loadEncounterAnimAssets(scene: BattleScene, startLoad?: boolean): Promise<void> {
|
||||
await loadAnimAssets(scene, Array.from(encounterAnims.values()), startLoad);
|
||||
}
|
||||
|
||||
export function loadMoveAnimAssets(scene: BattleScene, moveIds: Moves[], startLoad?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const moveAnimations = moveIds.map(m => moveAnims.get(m) as AnimConfig).flat();
|
||||
@ -679,14 +715,16 @@ export abstract class BattleAnim {
|
||||
public target: Pokemon | null;
|
||||
public sprites: Phaser.GameObjects.Sprite[];
|
||||
public bgSprite: Phaser.GameObjects.TileSprite | Phaser.GameObjects.Rectangle;
|
||||
public playOnEmptyField: boolean;
|
||||
|
||||
private srcLine: number[];
|
||||
private dstLine: number[];
|
||||
|
||||
constructor(user?: Pokemon, target?: Pokemon) {
|
||||
constructor(user?: Pokemon, target?: Pokemon, playOnEmptyField: boolean = false) {
|
||||
this.user = user ?? null;
|
||||
this.target = target ?? null;
|
||||
this.sprites = [];
|
||||
this.playOnEmptyField = playOnEmptyField;
|
||||
}
|
||||
|
||||
abstract getAnim(): AnimConfig | null;
|
||||
@ -761,9 +799,9 @@ export abstract class BattleAnim {
|
||||
play(scene: BattleScene, onSubstitute?: boolean, callback?: Function) {
|
||||
const isOppAnim = this.isOppAnim();
|
||||
const user = !isOppAnim ? this.user! : this.target!; // TODO: are those bangs correct?
|
||||
const target = !isOppAnim ? this.target : this.user;
|
||||
const target = !isOppAnim ? this.target! : this.user!;
|
||||
|
||||
if (!target?.isOnField()) {
|
||||
if (!target?.isOnField() && !this.playOnEmptyField) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
@ -866,6 +904,8 @@ export abstract class BattleAnim {
|
||||
const isUser = frame.target === AnimFrameTarget.USER;
|
||||
if (isUser && target === user) {
|
||||
continue;
|
||||
} else if (this.playOnEmptyField && frame.target === AnimFrameTarget.TARGET && !target.isOnField()) {
|
||||
continue;
|
||||
}
|
||||
const sprites = spriteCache[isUser ? AnimFrameTarget.USER : AnimFrameTarget.TARGET];
|
||||
const spriteSource = isUser ? userSprite : targetSprite;
|
||||
@ -1017,13 +1057,175 @@ export abstract class BattleAnim {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getGraphicFrameDataWithoutTarget(frames: AnimFrame[], targetInitialX: number, targetInitialY: number): Map<integer, Map<AnimFrameTarget, GraphicFrameData>> {
|
||||
const ret: Map<integer, Map<AnimFrameTarget, GraphicFrameData>> = new Map([
|
||||
[AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
]);
|
||||
|
||||
let g = 0;
|
||||
let u = 0;
|
||||
let t = 0;
|
||||
|
||||
for (const frame of frames) {
|
||||
let { x, y } = frame;
|
||||
const scaleX = (frame.zoomX / 100) * (!frame.mirror ? 1 : -1);
|
||||
const scaleY = (frame.zoomY / 100);
|
||||
x += targetInitialX;
|
||||
y += targetInitialY;
|
||||
const angle = -frame.angle;
|
||||
const key = frame.target === AnimFrameTarget.GRAPHIC ? g++ : frame.target === AnimFrameTarget.USER ? u++ : t++;
|
||||
ret.get(frame.target)?.set(key, { x: x, y: y, scaleX: scaleX, scaleY: scaleY, angle: angle });
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param scene
|
||||
* @param targetInitialX
|
||||
* @param targetInitialY
|
||||
* @param frameTimeMult
|
||||
* @param frameTimedEventPriority
|
||||
* - 0 is behind all other sprites (except BG)
|
||||
* - 1 on top of player field
|
||||
* - 3 is on top of both fields
|
||||
* - 5 is on top of player sprite
|
||||
* @param callback
|
||||
*/
|
||||
playWithoutTargets(scene: BattleScene, targetInitialX: number, targetInitialY: number, frameTimeMult: number, frameTimedEventPriority?: 0 | 1 | 3 | 5, callback?: Function) {
|
||||
const spriteCache: SpriteCache = {
|
||||
[AnimFrameTarget.GRAPHIC]: [],
|
||||
[AnimFrameTarget.USER]: [],
|
||||
[AnimFrameTarget.TARGET]: []
|
||||
};
|
||||
|
||||
const cleanUpAndComplete = () => {
|
||||
for (const ms of Object.values(spriteCache).flat()) {
|
||||
if (ms) {
|
||||
ms.destroy();
|
||||
}
|
||||
}
|
||||
if (this.bgSprite) {
|
||||
this.bgSprite.destroy();
|
||||
}
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
if (!scene.moveAnimations) {
|
||||
return cleanUpAndComplete();
|
||||
}
|
||||
|
||||
const anim = this.getAnim();
|
||||
|
||||
this.srcLine = [ userFocusX, userFocusY, targetFocusX, targetFocusY ];
|
||||
this.dstLine = [ 150, 75, targetInitialX, targetInitialY ];
|
||||
|
||||
let totalFrames = anim!.frames.length;
|
||||
let frameCount = 0;
|
||||
|
||||
let existingFieldSprites = scene.field.getAll().slice(0);
|
||||
|
||||
scene.tweens.addCounter({
|
||||
duration: Utils.getFrameMs(3) * frameTimeMult,
|
||||
repeat: anim!.frames.length,
|
||||
onRepeat: () => {
|
||||
existingFieldSprites = scene.field.getAll().slice(0);
|
||||
const spriteFrames = anim!.frames[frameCount];
|
||||
const frameData = this.getGraphicFrameDataWithoutTarget(anim!.frames[frameCount], targetInitialX, targetInitialY);
|
||||
let graphicFrameCount = 0;
|
||||
for (const frame of spriteFrames) {
|
||||
if (frame.target !== AnimFrameTarget.GRAPHIC) {
|
||||
console.log("Encounter animations do not support targets");
|
||||
continue;
|
||||
}
|
||||
|
||||
const sprites = spriteCache[AnimFrameTarget.GRAPHIC];
|
||||
if (graphicFrameCount === sprites.length) {
|
||||
const newSprite: Phaser.GameObjects.Sprite = scene.addFieldSprite(0, 0, anim!.graphic, 1);
|
||||
sprites.push(newSprite);
|
||||
scene.field.add(newSprite);
|
||||
}
|
||||
|
||||
const graphicIndex = graphicFrameCount++;
|
||||
const moveSprite = sprites[graphicIndex];
|
||||
if (!isNullOrUndefined(frame.priority)) {
|
||||
const setSpritePriority = (priority: integer) => {
|
||||
if (existingFieldSprites.length > priority) {
|
||||
// Move to specified priority index
|
||||
const index = scene.field.getIndex(existingFieldSprites[priority]);
|
||||
scene.field.moveTo(moveSprite, index);
|
||||
} else {
|
||||
// Move to top of scene
|
||||
scene.field.moveTo(moveSprite, scene.field.getAll().length - 1);
|
||||
}
|
||||
};
|
||||
setSpritePriority(frame.priority);
|
||||
}
|
||||
moveSprite.setFrame(frame.graphicFrame);
|
||||
|
||||
const graphicFrameData = frameData.get(frame.target)?.get(graphicIndex);
|
||||
if (graphicFrameData) {
|
||||
moveSprite.setPosition(graphicFrameData.x, graphicFrameData.y);
|
||||
moveSprite.setAngle(graphicFrameData.angle);
|
||||
moveSprite.setScale(graphicFrameData.scaleX, graphicFrameData.scaleY);
|
||||
|
||||
moveSprite.setAlpha(frame.opacity / 255);
|
||||
moveSprite.setVisible(frame.visible);
|
||||
moveSprite.setBlendMode(frame.blendType === AnimBlendType.NORMAL ? Phaser.BlendModes.NORMAL : frame.blendType === AnimBlendType.ADD ? Phaser.BlendModes.ADD : Phaser.BlendModes.DIFFERENCE);
|
||||
}
|
||||
}
|
||||
if (anim?.frameTimedEvents.get(frameCount)) {
|
||||
for (const event of anim.frameTimedEvents.get(frameCount)!) {
|
||||
totalFrames = Math.max((anim.frames.length - frameCount) + event.execute(scene, this, frameTimedEventPriority), totalFrames);
|
||||
}
|
||||
}
|
||||
const targets = Utils.getEnumValues(AnimFrameTarget);
|
||||
for (const i of targets) {
|
||||
const count = graphicFrameCount;
|
||||
if (count < spriteCache[i].length) {
|
||||
const spritesToRemove = spriteCache[i].slice(count, spriteCache[i].length);
|
||||
for (const sprite of spritesToRemove) {
|
||||
if (!sprite.getData("locked") as boolean) {
|
||||
const spriteCacheIndex = spriteCache[i].indexOf(sprite);
|
||||
spriteCache[i].splice(spriteCacheIndex, 1);
|
||||
sprite.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
frameCount++;
|
||||
totalFrames--;
|
||||
},
|
||||
onComplete: () => {
|
||||
for (const sprite of Object.values(spriteCache).flat()) {
|
||||
if (sprite && !sprite.getData("locked")) {
|
||||
sprite.destroy();
|
||||
}
|
||||
}
|
||||
if (totalFrames) {
|
||||
scene.tweens.addCounter({
|
||||
duration: Utils.getFrameMs(totalFrames),
|
||||
onComplete: () => cleanUpAndComplete()
|
||||
});
|
||||
} else {
|
||||
cleanUpAndComplete();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class CommonBattleAnim extends BattleAnim {
|
||||
public commonAnim: CommonAnim | null;
|
||||
|
||||
constructor(commonAnim: CommonAnim | null, user: Pokemon, target?: Pokemon) {
|
||||
super(user, target || user);
|
||||
constructor(commonAnim: CommonAnim | null, user: Pokemon, target?: Pokemon, playOnEmptyField: boolean = false) {
|
||||
super(user, target || user, playOnEmptyField);
|
||||
|
||||
this.commonAnim = commonAnim;
|
||||
}
|
||||
@ -1040,8 +1242,8 @@ export class CommonBattleAnim extends BattleAnim {
|
||||
export class MoveAnim extends BattleAnim {
|
||||
public move: Moves;
|
||||
|
||||
constructor(move: Moves, user: Pokemon, target: BattlerIndex) {
|
||||
super(user, user.scene.getField()[target]);
|
||||
constructor(move: Moves, user: Pokemon, target: BattlerIndex, playOnEmptyField: boolean = false) {
|
||||
super(user, user.scene.getField()[target], playOnEmptyField);
|
||||
|
||||
this.move = move;
|
||||
}
|
||||
@ -1085,6 +1287,26 @@ export class MoveChargeAnim extends MoveAnim {
|
||||
}
|
||||
}
|
||||
|
||||
export class EncounterBattleAnim extends BattleAnim {
|
||||
public encounterAnim: EncounterAnim;
|
||||
public oppAnim: boolean;
|
||||
|
||||
constructor(encounterAnim: EncounterAnim, user: Pokemon, target?: Pokemon, oppAnim?: boolean) {
|
||||
super(user, target ?? user, true);
|
||||
|
||||
this.encounterAnim = encounterAnim;
|
||||
this.oppAnim = oppAnim ?? false;
|
||||
}
|
||||
|
||||
getAnim(): AnimConfig | null {
|
||||
return encounterAnims.get(this.encounterAnim) ?? null;
|
||||
}
|
||||
|
||||
isOppAnim(): boolean {
|
||||
return this.oppAnim;
|
||||
}
|
||||
}
|
||||
|
||||
export async function populateAnims() {
|
||||
const commonAnimNames = Utils.getEnumKeys(CommonAnim).map(k => k.toLowerCase());
|
||||
const commonAnimMatchNames = commonAnimNames.map(k => k.replace(/\_/g, ""));
|
||||
|
@ -5,7 +5,7 @@ import { StatusEffect } from "./status-effect";
|
||||
import * as Utils from "../utils";
|
||||
import { ChargeAttr, MoveFlags, allMoves } from "./move";
|
||||
import { Type } from "./type";
|
||||
import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs } from "./ability";
|
||||
import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs, ProtectStatAbAttr } from "./ability";
|
||||
import { TerrainType } from "./terrain";
|
||||
import { WeatherType } from "./weather";
|
||||
import { allAbilities } from "./ability";
|
||||
@ -2304,6 +2304,45 @@ export class SubstituteTag extends BattlerTag {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag that adds extra post-summon effects to a battle for a specific Pokemon.
|
||||
* These post-summon effects are performed through {@linkcode Pokemon.mysteryEncounterBattleEffects},
|
||||
* and can be used to unshift special phases, etc.
|
||||
* Currently used only in MysteryEncounters to provide start of fight stat buffs.
|
||||
*/
|
||||
export class MysteryEncounterPostSummonTag extends BattlerTag {
|
||||
constructor() {
|
||||
super(BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON, BattlerTagLapseType.CUSTOM, 1);
|
||||
}
|
||||
|
||||
/** Event when tag is added */
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
}
|
||||
|
||||
/** Performs post-summon effects through {@linkcode Pokemon.mysteryEncounterBattleEffects} */
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
const ret = super.lapse(pokemon, lapseType);
|
||||
|
||||
if (lapseType === BattlerTagLapseType.CUSTOM) {
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled);
|
||||
if (!cancelled.value) {
|
||||
if (pokemon.mysteryEncounterBattleEffects) {
|
||||
pokemon.mysteryEncounterBattleEffects(pokemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Event when tag is removed */
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
super.onRemove(pokemon);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@linkcode BattlerTag} based on the provided tag type, turn count, source move, and source ID.
|
||||
*
|
||||
@ -2465,6 +2504,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
return new GorillaTacticsTag();
|
||||
case BattlerTagType.SUBSTITUTE:
|
||||
return new SubstituteTag(sourceMove, sourceId);
|
||||
case BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON:
|
||||
return new MysteryEncounterPostSummonTag();
|
||||
case BattlerTagType.NONE:
|
||||
default:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
|
@ -1093,6 +1093,136 @@ export const trainerTypeDialogue: TrainerTypeDialogue = {
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.BUCK]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:stat_trainer_buck.encounter.1",
|
||||
"dialogue:stat_trainer_buck.encounter.2"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:stat_trainer_buck.victory.1",
|
||||
"dialogue:stat_trainer_buck.victory.2"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:stat_trainer_buck.defeat.1",
|
||||
"dialogue:stat_trainer_buck.defeat.2"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.CHERYL]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:stat_trainer_cheryl.encounter.1",
|
||||
"dialogue:stat_trainer_cheryl.encounter.2"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:stat_trainer_cheryl.victory.1",
|
||||
"dialogue:stat_trainer_cheryl.victory.2"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:stat_trainer_cheryl.defeat.1",
|
||||
"dialogue:stat_trainer_cheryl.defeat.2"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.MARLEY]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:stat_trainer_marley.encounter.1",
|
||||
"dialogue:stat_trainer_marley.encounter.2"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:stat_trainer_marley.victory.1",
|
||||
"dialogue:stat_trainer_marley.victory.2"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:stat_trainer_marley.defeat.1",
|
||||
"dialogue:stat_trainer_marley.defeat.2"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.MIRA]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:stat_trainer_mira.encounter.1",
|
||||
"dialogue:stat_trainer_mira.encounter.2"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:stat_trainer_mira.victory.1",
|
||||
"dialogue:stat_trainer_mira.victory.2"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:stat_trainer_mira.defeat.1",
|
||||
"dialogue:stat_trainer_mira.defeat.2"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.RILEY]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:stat_trainer_riley.encounter.1",
|
||||
"dialogue:stat_trainer_riley.encounter.2"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:stat_trainer_riley.victory.1",
|
||||
"dialogue:stat_trainer_riley.victory.2"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:stat_trainer_riley.defeat.1",
|
||||
"dialogue:stat_trainer_riley.defeat.2"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.VICTOR]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:winstrates_victor.encounter.1",
|
||||
],
|
||||
victory: [
|
||||
"dialogue:winstrates_victor.victory.1"
|
||||
],
|
||||
}
|
||||
],
|
||||
[TrainerType.VICTORIA]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:winstrates_victoria.encounter.1",
|
||||
],
|
||||
victory: [
|
||||
"dialogue:winstrates_victoria.victory.1"
|
||||
],
|
||||
}
|
||||
],
|
||||
[TrainerType.VIVI]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:winstrates_vivi.encounter.1",
|
||||
],
|
||||
victory: [
|
||||
"dialogue:winstrates_vivi.victory.1"
|
||||
],
|
||||
}
|
||||
],
|
||||
[TrainerType.VICKY]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:winstrates_vicky.encounter.1",
|
||||
],
|
||||
victory: [
|
||||
"dialogue:winstrates_vicky.victory.1"
|
||||
],
|
||||
}
|
||||
],
|
||||
[TrainerType.VITO]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:winstrates_vito.encounter.1",
|
||||
],
|
||||
victory: [
|
||||
"dialogue:winstrates_vito.victory.1"
|
||||
],
|
||||
}
|
||||
],
|
||||
[TrainerType.BROCK]: {
|
||||
encounter: [
|
||||
"dialogue:brock.encounter.1",
|
||||
|
@ -61,7 +61,10 @@ export interface IEggOptions {
|
||||
/** Defines if the egg will hatch with the hidden ability of this species.
|
||||
* If no hidden ability exist, a random one will get choosen.
|
||||
*/
|
||||
overrideHiddenAbility?: boolean
|
||||
overrideHiddenAbility?: boolean,
|
||||
|
||||
/** Can customize the message displayed for where the egg was obtained */
|
||||
eggDescriptor?: string;
|
||||
}
|
||||
|
||||
export class Egg {
|
||||
@ -83,6 +86,8 @@ export class Egg {
|
||||
|
||||
private _overrideHiddenAbility: boolean;
|
||||
|
||||
private _eggDescriptor?: string;
|
||||
|
||||
////
|
||||
// #endregion
|
||||
////
|
||||
@ -191,6 +196,8 @@ export class Egg {
|
||||
} else { // For legacy eggs without scene
|
||||
generateEggProperties(eggOptions);
|
||||
}
|
||||
|
||||
this._eggDescriptor = eggOptions?.eggDescriptor;
|
||||
}
|
||||
|
||||
////
|
||||
@ -292,13 +299,15 @@ export class Egg {
|
||||
public getEggTypeDescriptor(scene: BattleScene): string {
|
||||
switch (this.sourceType) {
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
return i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName()});
|
||||
return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName()});
|
||||
case EggSourceType.GACHA_LEGENDARY:
|
||||
return `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`;
|
||||
return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`;
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
return i18next.t("egg:gachaTypeShiny");
|
||||
return this._eggDescriptor ?? i18next.t("egg:gachaTypeShiny");
|
||||
case EggSourceType.GACHA_MOVE:
|
||||
return i18next.t("egg:gachaTypeMove");
|
||||
return this._eggDescriptor ?? i18next.t("egg:gachaTypeMove");
|
||||
case EggSourceType.EVENT:
|
||||
return this._eggDescriptor ?? i18next.t("egg:eventType");
|
||||
default:
|
||||
console.warn("getEggTypeDescriptor case not defined. Returning default empty string");
|
||||
return "";
|
||||
|
@ -0,0 +1,186 @@
|
||||
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { trainerConfigs, } from "#app/data/trainer-config";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Species } from "#enums/species";
|
||||
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { randSeedInt } from "#app/utils";
|
||||
import i18next from "i18next";
|
||||
import { IEggOptions } from "#app/data/egg";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:aTrainersTest";
|
||||
|
||||
/**
|
||||
* A Trainer's Test encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3816 | GitHub Issue #3816}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const ATrainersTestEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.A_TRAINERS_TEST)
|
||||
.withEncounterTier(MysteryEncounterTier.ROGUE)
|
||||
.withSceneWaveRangeRequirement(100, 180)
|
||||
.withIntroSpriteConfigs([]) // These are set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
// Randomly pick from 1 of the 5 stat trainers to spawn
|
||||
let trainerType: TrainerType;
|
||||
let spriteKeys;
|
||||
let trainerNameKey: string;
|
||||
switch (randSeedInt(5)) {
|
||||
default:
|
||||
case 0:
|
||||
trainerType = TrainerType.BUCK;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL);
|
||||
trainerNameKey = "buck";
|
||||
break;
|
||||
case 1:
|
||||
trainerType = TrainerType.CHERYL;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY);
|
||||
trainerNameKey = "cheryl";
|
||||
break;
|
||||
case 2:
|
||||
trainerType = TrainerType.MARLEY;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE);
|
||||
trainerNameKey = "marley";
|
||||
break;
|
||||
case 3:
|
||||
trainerType = TrainerType.MIRA;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1);
|
||||
trainerNameKey = "mira";
|
||||
break;
|
||||
case 4:
|
||||
trainerType = TrainerType.RILEY;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1);
|
||||
trainerNameKey = "riley";
|
||||
break;
|
||||
}
|
||||
|
||||
// Dialogue and tokens for trainer
|
||||
encounter.dialogue.intro = [
|
||||
{
|
||||
speaker: `trainerNames:${trainerNameKey}`,
|
||||
text: `${namespace}.${trainerNameKey}.intro_dialogue`
|
||||
}
|
||||
];
|
||||
encounter.options[0].dialogue!.selected = [
|
||||
{
|
||||
speaker: `trainerNames:${trainerNameKey}`,
|
||||
text: `${namespace}.${trainerNameKey}.accept`
|
||||
}
|
||||
];
|
||||
encounter.options[1].dialogue!.selected = [
|
||||
{
|
||||
speaker: `trainerNames:${trainerNameKey}`,
|
||||
text: `${namespace}.${trainerNameKey}.decline`
|
||||
}
|
||||
];
|
||||
|
||||
encounter.setDialogueToken("statTrainerName", i18next.t(`trainerNames:${trainerNameKey}`));
|
||||
const eggDescription = i18next.t(`${namespace}.title`) + ":\n" + i18next.t(`trainerNames:${trainerNameKey}`);
|
||||
encounter.misc = { trainerType, trainerNameKey, trainerEggDescription: eggDescription };
|
||||
|
||||
// Trainer config
|
||||
const trainerConfig = trainerConfigs[trainerType].clone();
|
||||
const trainerSpriteKey = trainerConfig.getSpriteKey();
|
||||
encounter.enemyPartyConfigs.push({
|
||||
levelAdditiveMultiplier: 1,
|
||||
trainerConfig: trainerConfig
|
||||
});
|
||||
|
||||
encounter.spriteConfigs = [
|
||||
{
|
||||
spriteKey: spriteKeys.spriteKey,
|
||||
fileRoot: spriteKeys.fileRoot,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
isPokemon: true,
|
||||
x: 22,
|
||||
y: -2,
|
||||
yShadow: -2
|
||||
},
|
||||
{
|
||||
spriteKey: trainerSpriteKey,
|
||||
fileRoot: "trainer",
|
||||
hasShadow: true,
|
||||
disableAnimation: true,
|
||||
x: -24,
|
||||
y: 4,
|
||||
yShadow: 4
|
||||
}
|
||||
];
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withIntroDialogue()
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Battle the stat trainer for an Egg and great rewards
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
|
||||
const eggOptions: IEggOptions = {
|
||||
scene,
|
||||
pulled: false,
|
||||
sourceType: EggSourceType.EVENT,
|
||||
eggDescriptor: encounter.misc.trainerEggDescription,
|
||||
tier: EggTier.ULTRA
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.epic`));
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
||||
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Full heal party
|
||||
scene.unshiftPhase(new PartyHealPhase(scene, true));
|
||||
|
||||
const eggOptions: IEggOptions = {
|
||||
scene,
|
||||
pulled: false,
|
||||
sourceType: EggSourceType.EVENT,
|
||||
eggDescriptor: encounter.misc.trainerEggDescription,
|
||||
tier: EggTier.GREAT
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.rare`));
|
||||
setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [eggOptions]);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
@ -0,0 +1,521 @@
|
||||
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import Pokemon, { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { BerryModifierType, modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Species } from "#enums/species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||
import { PersistentModifierRequirement } from "../mystery-encounter-requirements";
|
||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { BerryModifier } from "#app/modifier/modifier";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { randInt } from "#app/utils";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { applyModifierTypeToPlayerPokemon, catchPokemon, getHighestLevelPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { TrainerSlot } from "#app/data/trainer-config";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:absoluteAvarice";
|
||||
|
||||
/**
|
||||
* Absolute Avarice encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3805 | GitHub Issue #3805}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.ABSOLUTE_AVARICE)
|
||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withSceneRequirement(new PersistentModifierRequirement("BerryModifier", 4)) // Must have at least 4 berries to spawn
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
// This sprite has the shadow
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.GREEDENT,
|
||||
hasShadow: true,
|
||||
alpha: 0.001,
|
||||
repeat: true,
|
||||
x: -5
|
||||
},
|
||||
{
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.GREEDENT,
|
||||
hasShadow: false,
|
||||
repeat: true,
|
||||
x: -5
|
||||
},
|
||||
{
|
||||
spriteKey: "lum_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 7,
|
||||
y: -14,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "salac_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 2,
|
||||
y: 4,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "lansat_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 32,
|
||||
y: 5,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "liechi_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 6,
|
||||
y: -5,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "sitrus_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 7,
|
||||
y: 8,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "enigma_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 26,
|
||||
y: -4,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "leppa_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 16,
|
||||
y: -27,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "petaya_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 30,
|
||||
y: -17,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "ganlon_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 16,
|
||||
y: -11,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "apicot_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 14,
|
||||
y: -2,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: "starf_berry",
|
||||
fileRoot: "items",
|
||||
isItem: true,
|
||||
x: 18,
|
||||
y: 9,
|
||||
hidden: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
])
|
||||
.withHideWildIntroMessage(true)
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withOnVisualsStart((scene: BattleScene) => {
|
||||
doGreedentSpriteSteal(scene);
|
||||
doBerrySpritePile(scene);
|
||||
|
||||
return true;
|
||||
})
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
scene.loadSe("PRSFX- Bug Bite", "battle_anims", "PRSFX- Bug Bite.wav");
|
||||
scene.loadSe("Follow Me", "battle_anims", "Follow Me.mp3");
|
||||
|
||||
// Get all player berry items, remove from party, and store reference
|
||||
const berryItems = scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[];
|
||||
|
||||
// Sort berries by party member ID to more easily re-add later if necessary
|
||||
const berryItemsMap = new Map<number, BerryModifier[]>();
|
||||
scene.getParty().forEach(pokemon => {
|
||||
const pokemonBerries = berryItems.filter(b => b.pokemonId === pokemon.id);
|
||||
if (pokemonBerries?.length > 0) {
|
||||
berryItemsMap.set(pokemon.id, pokemonBerries);
|
||||
}
|
||||
});
|
||||
|
||||
encounter.misc = { berryItemsMap };
|
||||
|
||||
// Generates copies of the stolen berries to put on the Greedent
|
||||
const bossModifierConfigs: HeldModifierConfig[] = [];
|
||||
berryItems.forEach(berryMod => {
|
||||
// Can't define stack count on a ModifierType, have to just create separate instances for each stack
|
||||
// Overflow berries will be "lost" on the boss, but it's un-catchable anyway
|
||||
for (let i = 0; i < berryMod.stackCount; i++) {
|
||||
const modifierType = generateModifierType(scene, modifierTypes.BERRY, [berryMod.berryType]) as PokemonHeldItemModifierType;
|
||||
bossModifierConfigs.push({ modifier: modifierType });
|
||||
}
|
||||
|
||||
scene.removeModifier(berryMod);
|
||||
});
|
||||
|
||||
// Calculate boss mon
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveMultiplier: 1,
|
||||
pokemonConfigs: [
|
||||
{
|
||||
species: getPokemonSpecies(Species.GREEDENT),
|
||||
isBoss: true,
|
||||
bossSegments: 3,
|
||||
moveSet: [Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.SLACK_OFF],
|
||||
modifierConfigs: bossModifierConfigs,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD], 1));
|
||||
}
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.setDialogueToken("greedentName", getPokemonSpecies(Species.GREEDENT).getName());
|
||||
|
||||
return true;
|
||||
})
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
// Provides 1x Reviver Seed to each party member at end of battle
|
||||
const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED);
|
||||
const givePartyPokemonReviverSeeds = () => {
|
||||
const party = scene.getParty();
|
||||
party.forEach(p => {
|
||||
if (revSeed) {
|
||||
const seedModifier = revSeed.newModifier(p);
|
||||
if (seedModifier) {
|
||||
encounter.setDialogueToken("foodReward", seedModifier.type.name);
|
||||
}
|
||||
scene.addModifier(seedModifier, false, false, false, true);
|
||||
}
|
||||
});
|
||||
queueEncounterMessage(scene, `${namespace}.option.1.food_stash`);
|
||||
};
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, givePartyPokemonReviverSeeds);
|
||||
encounter.startOfBattleEffects.push({
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
move: new PokemonMove(Moves.STUFF_CHEEKS),
|
||||
ignorePp: true
|
||||
});
|
||||
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const berryMap = encounter.misc.berryItemsMap;
|
||||
|
||||
// Returns 2/5 of the berries stolen from each Pokemon
|
||||
const party = scene.getParty();
|
||||
party.forEach(pokemon => {
|
||||
const stolenBerries: BerryModifier[] = berryMap.get(pokemon.id);
|
||||
const berryTypesAsArray: BerryType[] = [];
|
||||
stolenBerries?.forEach(bMod => berryTypesAsArray.push(...new Array(bMod.stackCount).fill(bMod.berryType)));
|
||||
const returnedBerryCount = Math.floor((berryTypesAsArray.length ?? 0) * 2 / 5);
|
||||
|
||||
if (returnedBerryCount > 0) {
|
||||
for (let i = 0; i < returnedBerryCount; i++) {
|
||||
// Shuffle remaining berry types and pop
|
||||
Phaser.Math.RND.shuffle(berryTypesAsArray);
|
||||
const randBerryType = berryTypesAsArray.pop();
|
||||
|
||||
const berryModType = generateModifierType(scene, modifierTypes.BERRY, [randBerryType]) as BerryModifierType;
|
||||
applyModifierTypeToPlayerPokemon(scene, pokemon, berryModType);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Animate berries being eaten
|
||||
doGreedentEatBerries(scene);
|
||||
doBerrySpritePile(scene, true);
|
||||
return true;
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Let it have the food
|
||||
// Greedent joins the team, level equal to 2 below highest party member
|
||||
const level = getHighestLevelPlayerPokemon(scene).level - 2;
|
||||
const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false);
|
||||
greedent.moveset = [new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF)];
|
||||
greedent.passive = true;
|
||||
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await catchPokemon(scene, greedent, null, PokeballType.POKEBALL, false);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
|
||||
function doGreedentSpriteSteal(scene: BattleScene) {
|
||||
const shakeDelay = 50;
|
||||
const slideDelay = 500;
|
||||
|
||||
const greedentSprites = scene.currentBattle.mysteryEncounter!.introVisuals?.getSpriteAtIndex(1);
|
||||
|
||||
scene.playSound("battle_anims/Follow Me");
|
||||
scene.tweens.chain({
|
||||
targets: greedentSprites,
|
||||
tweens: [
|
||||
{ // Slide Greedent diagonally
|
||||
duration: slideDelay,
|
||||
ease: "Cubic.easeOut",
|
||||
y: "+=75",
|
||||
x: "-=65",
|
||||
scale: 1.1
|
||||
},
|
||||
{ // Shake
|
||||
duration: shakeDelay,
|
||||
ease: "Cubic.easeOut",
|
||||
yoyo: true,
|
||||
x: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
y: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
},
|
||||
{ // Shake
|
||||
duration: shakeDelay,
|
||||
ease: "Cubic.easeOut",
|
||||
yoyo: true,
|
||||
x: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
y: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
},
|
||||
{ // Shake
|
||||
duration: shakeDelay,
|
||||
ease: "Cubic.easeOut",
|
||||
yoyo: true,
|
||||
x: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
y: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
},
|
||||
{ // Shake
|
||||
duration: shakeDelay,
|
||||
ease: "Cubic.easeOut",
|
||||
yoyo: true,
|
||||
x: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
y: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
},
|
||||
{ // Shake
|
||||
duration: shakeDelay,
|
||||
ease: "Cubic.easeOut",
|
||||
yoyo: true,
|
||||
x: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
y: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
},
|
||||
{ // Shake
|
||||
duration: shakeDelay,
|
||||
ease: "Cubic.easeOut",
|
||||
yoyo: true,
|
||||
x: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
y: (randInt(2) > 0 ? "-=" : "+=") + 5,
|
||||
},
|
||||
{ // Slide Greedent diagonally
|
||||
duration: slideDelay,
|
||||
ease: "Cubic.easeOut",
|
||||
y: "-=75",
|
||||
x: "+=65",
|
||||
scale: 1
|
||||
},
|
||||
{ // Bounce at the end
|
||||
duration: 300,
|
||||
ease: "Cubic.easeOut",
|
||||
yoyo: true,
|
||||
y: "-=20",
|
||||
loop: 1,
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
function doGreedentEatBerries(scene: BattleScene) {
|
||||
const greedentSprites = scene.currentBattle.mysteryEncounter!.introVisuals?.getSpriteAtIndex(1);
|
||||
let index = 1;
|
||||
scene.tweens.add({
|
||||
targets: greedentSprites,
|
||||
duration: 150,
|
||||
ease: "Cubic.easeOut",
|
||||
yoyo: true,
|
||||
y: "-=8",
|
||||
loop: 5,
|
||||
onStart: () => {
|
||||
scene.playSound("battle_anims/PRSFX- Bug Bite");
|
||||
},
|
||||
onLoop: () => {
|
||||
if (index % 2 === 0) {
|
||||
scene.playSound("battle_anims/PRSFX- Bug Bite");
|
||||
}
|
||||
index++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param scene
|
||||
* @param isEat Default false. Will "create" pile when false, and remove pile when true.
|
||||
*/
|
||||
function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) {
|
||||
const berryAddDelay = 150;
|
||||
let animationOrder = ["starf", "sitrus", "lansat", "salac", "apicot", "enigma", "liechi", "ganlon", "lum", "petaya", "leppa"];
|
||||
if (isEat) {
|
||||
animationOrder = animationOrder.reverse();
|
||||
}
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
animationOrder.forEach((berry, i) => {
|
||||
const introVisualsIndex = encounter.spriteConfigs.findIndex(config => config.spriteKey?.includes(berry));
|
||||
let sprite: Phaser.GameObjects.Sprite, tintSprite: Phaser.GameObjects.Sprite;
|
||||
const sprites = encounter.introVisuals?.getSpriteAtIndex(introVisualsIndex);
|
||||
if (sprites) {
|
||||
sprite = sprites[0];
|
||||
tintSprite = sprites[1];
|
||||
}
|
||||
scene.time.delayedCall(berryAddDelay * i + 400, () => {
|
||||
if (sprite) {
|
||||
sprite.setVisible(!isEat);
|
||||
}
|
||||
if (tintSprite) {
|
||||
tintSprite.setVisible(!isEat);
|
||||
}
|
||||
|
||||
// Animate Petaya berry falling off the pile
|
||||
if (berry === "petaya" && sprite && tintSprite && !isEat) {
|
||||
scene.time.delayedCall(200, () => {
|
||||
doBerryBounce(scene, [sprite, tintSprite], 30, 500);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function doBerryBounce(scene: BattleScene, berrySprites: Phaser.GameObjects.Sprite[], yd: number, baseBounceDuration: number) {
|
||||
let bouncePower = 1;
|
||||
let bounceYOffset = yd;
|
||||
|
||||
const doBounce = () => {
|
||||
scene.tweens.add({
|
||||
targets: berrySprites,
|
||||
y: "+=" + bounceYOffset,
|
||||
x: { value: "+=" + (bouncePower * bouncePower * 10), ease: "Linear" },
|
||||
duration: bouncePower * baseBounceDuration,
|
||||
ease: "Cubic.easeIn",
|
||||
onComplete: () => {
|
||||
bouncePower = bouncePower > 0.01 ? bouncePower * 0.5 : 0;
|
||||
|
||||
if (bouncePower) {
|
||||
bounceYOffset = bounceYOffset * bouncePower;
|
||||
|
||||
scene.tweens.add({
|
||||
targets: berrySprites,
|
||||
y: "-=" + bounceYOffset,
|
||||
x: { value: "+=" + (bouncePower * bouncePower * 10), ease: "Linear" },
|
||||
duration: bouncePower * baseBounceDuration,
|
||||
ease: "Cubic.easeOut",
|
||||
onComplete: () => doBounce()
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
doBounce();
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
import { 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";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||
import { AbilityRequirement, CombinationPokemonRequirement, MoveRequirement } from "../mystery-encounter-requirements";
|
||||
import { getHighestStatTotalPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { EXTORTION_ABILITIES, EXTORTION_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
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";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:offerYouCantRefuse";
|
||||
|
||||
/**
|
||||
* An Offer You Can't Refuse encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3808 | GitHub Issue #3808}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE)
|
||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withScenePartySizeRequirement(2, 6) // Must have at least 2 pokemon in party
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: Species.LIEPARD.toString(),
|
||||
fileRoot: "pokemon",
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
x: 0,
|
||||
y: -4,
|
||||
yShadow: -4
|
||||
},
|
||||
{
|
||||
spriteKey: "rich_kid_m",
|
||||
fileRoot: "trainer",
|
||||
hasShadow: true,
|
||||
x: 2,
|
||||
y: 5,
|
||||
yShadow: 5
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const pokemon = getHighestStatTotalPlayerPokemon(scene, false);
|
||||
const price = scene.getWaveMoneyAmount(10);
|
||||
|
||||
encounter.setDialogueToken("strongestPokemon", pokemon.getNameToRender());
|
||||
encounter.setDialogueToken("price", price.toString());
|
||||
|
||||
// Store pokemon and price
|
||||
encounter.misc = {
|
||||
pokemon: pokemon,
|
||||
price: price
|
||||
};
|
||||
|
||||
// If player meets the combo OR requirements for option 2, populate the token
|
||||
const opt2Req = encounter.options[1].primaryPokemonRequirements[0];
|
||||
if (opt2Req.meetsRequirement(scene)) {
|
||||
const abilityToken = encounter.dialogueTokens["option2PrimaryAbility"];
|
||||
const moveToken = encounter.dialogueTokens["option2PrimaryMove"];
|
||||
if (abilityToken) {
|
||||
encounter.setDialogueToken("moveOrAbility", abilityToken);
|
||||
} else if (moveToken) {
|
||||
encounter.setDialogueToken("moveOrAbility", moveToken);
|
||||
}
|
||||
}
|
||||
|
||||
encounter.setDialogueToken("liepardName", getPokemonSpecies(Species.LIEPARD).getName());
|
||||
|
||||
return true;
|
||||
})
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Update money and remove pokemon from party
|
||||
updatePlayerMoney(scene, encounter.misc.price);
|
||||
scene.removePokemonFromPlayerParty(encounter.misc.pokemon);
|
||||
return true;
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Give the player a Shiny charm
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.SHINY_CHARM));
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||
new MoveRequirement(EXTORTION_MOVES),
|
||||
new AbilityRequirement(EXTORTION_ABILITIES))
|
||||
)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.tooltip_disabled`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Extort the rich kid for money
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Update money and remove pokemon from party
|
||||
updatePlayerMoney(scene, encounter.misc.price);
|
||||
|
||||
setEncounterExp(scene, encounter.options[1].primaryPokemon!.id, getPokemonSpecies(Species.LIEPARD).baseExp, true);
|
||||
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.3.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Leave encounter with no rewards or exp
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
return true;
|
||||
}
|
||||
)
|
||||
.build();
|
@ -0,0 +1,273 @@
|
||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import {
|
||||
EnemyPartyConfig, generateModifierType, generateModifierTypeOption,
|
||||
initBattleWithEnemyConfig,
|
||||
leaveEncounterWithoutBattle, setEncounterExp,
|
||||
setEncounterRewards
|
||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
|
||||
import {
|
||||
BerryModifierType,
|
||||
getPartyLuckValue,
|
||||
ModifierPoolType,
|
||||
ModifierTypeOption, modifierTypes,
|
||||
regenerateModifierPoolThresholds,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { randSeedInt } from "#app/utils";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { TrainerSlot } from "#app/data/trainer-config";
|
||||
import { applyModifierTypeToPlayerPokemon, getHighestStatPlayerPokemon, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { BerryModifier } from "#app/modifier/modifier";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:berriesAbound";
|
||||
|
||||
/**
|
||||
* Berries Abound encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3810 | GitHub Issue #3810}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const BerriesAboundEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.BERRIES_ABOUND)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withCatchAllowed(true)
|
||||
.withHideWildIntroMessage(true)
|
||||
.withIntroSpriteConfigs([]) // Set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
// Calculate boss mon
|
||||
const level = (scene.currentBattle.enemyLevels?.[0] ?? scene.currentBattle.waveIndex) + Math.max(Math.round((scene.currentBattle.waveIndex / 10)), 0);
|
||||
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
||||
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveMultiplier: 1,
|
||||
pokemonConfigs: [{
|
||||
level: level,
|
||||
species: bossSpecies,
|
||||
dataSource: new PokemonData(bossPokemon),
|
||||
isBoss: true
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
|
||||
// Calculate the number of extra berries that player receives
|
||||
// 10-40: 2, 40-120: 4, 120-160: 5, 160-180: 7
|
||||
const numBerries =
|
||||
scene.currentBattle.waveIndex > 160 ? 7
|
||||
: scene.currentBattle.waveIndex > 120 ? 5
|
||||
: scene.currentBattle.waveIndex > 40 ? 4 : 2;
|
||||
regenerateModifierPoolThresholds(scene.getParty(), ModifierPoolType.PLAYER, 0);
|
||||
encounter.misc = { numBerries };
|
||||
|
||||
const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(bossPokemon);
|
||||
encounter.spriteConfigs = [
|
||||
{
|
||||
spriteKey: "berry_bush",
|
||||
fileRoot: "mystery-encounters",
|
||||
x: 25,
|
||||
y: -6,
|
||||
yShadow: -7,
|
||||
disableAnimation: true,
|
||||
hasShadow: true
|
||||
},
|
||||
{
|
||||
spriteKey: spriteKey,
|
||||
fileRoot: fileRoot,
|
||||
hasShadow: true,
|
||||
tint: 0.25,
|
||||
x: -5,
|
||||
repeat: true,
|
||||
isPokemon: true
|
||||
}
|
||||
];
|
||||
|
||||
// Get fastest party pokemon for option 2
|
||||
const fastestPokemon = getHighestStatPlayerPokemon(scene, PERMANENT_STATS[Stat.SPD], true);
|
||||
encounter.misc.fastestPokemon = fastestPokemon;
|
||||
encounter.misc.enemySpeed = bossPokemon.getStat(Stat.SPD);
|
||||
encounter.setDialogueToken("fastestPokemon", fastestPokemon.getNameToRender());
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const numBerries = encounter.misc.numBerries;
|
||||
|
||||
const doBerryRewards = async () => {
|
||||
const berryText = numBerries + " " + i18next.t(`${namespace}.berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText }));
|
||||
|
||||
// Generate a random berry and give it to the first Pokemon with room for it
|
||||
for (let i = 0; i < numBerries; i++) {
|
||||
await tryGiveBerry(scene);
|
||||
}
|
||||
};
|
||||
|
||||
const shopOptions: ModifierTypeOption[] = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// Generate shop berries
|
||||
const mod = generateModifierTypeOption(scene, modifierTypes.BERRY);
|
||||
if (mod) {
|
||||
shopOptions.push(mod);
|
||||
}
|
||||
}
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards);
|
||||
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]);
|
||||
}
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Pick race for berries
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const fastestPokemon = encounter.misc.fastestPokemon;
|
||||
const enemySpeed = encounter.misc.enemySpeed;
|
||||
const speedDiff = fastestPokemon.getStat(Stat.SPD) / (enemySpeed * 1.1);
|
||||
const numBerries = encounter.misc.numBerries;
|
||||
|
||||
const shopOptions: ModifierTypeOption[] = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// Generate shop berries
|
||||
const mod = generateModifierTypeOption(scene, modifierTypes.BERRY);
|
||||
if (mod) {
|
||||
shopOptions.push(mod);
|
||||
}
|
||||
}
|
||||
|
||||
if (speedDiff < 1) {
|
||||
// Caught and attacked by boss, gets +1 to all stats at start of fight
|
||||
const doBerryRewards = async () => {
|
||||
const berryText = numBerries + " " + i18next.t(`${namespace}.berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText }));
|
||||
|
||||
// Generate a random berry and give it to the first Pokemon with room for it
|
||||
for (let i = 0; i < numBerries; i++) {
|
||||
await tryGiveBerry(scene);
|
||||
}
|
||||
};
|
||||
|
||||
const config = scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
|
||||
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.2.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD], 1));
|
||||
};
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards);
|
||||
await showEncounterText(scene, `${namespace}.option.2.selected_bad`);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
return;
|
||||
} else {
|
||||
// Gains 1 berry for every 10% faster the player's pokemon is than the enemy, up to a max of numBerries, minimum of 2
|
||||
const numBerriesGrabbed = Math.max(Math.min(Math.round((speedDiff - 1)/0.08), numBerries), 2);
|
||||
encounter.setDialogueToken("numBerries", String(numBerriesGrabbed));
|
||||
const doFasterBerryRewards = async () => {
|
||||
const berryText = numBerriesGrabbed + " " + i18next.t(`${namespace}.berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText }));
|
||||
|
||||
// Generate a random berry and give it to the first Pokemon with room for it (trying to give to fastest first)
|
||||
for (let i = 0; i < numBerriesGrabbed; i++) {
|
||||
await tryGiveBerry(scene, fastestPokemon);
|
||||
}
|
||||
};
|
||||
|
||||
setEncounterExp(scene, fastestPokemon.id, encounter.enemyPartyConfigs[0].pokemonConfigs![0].species.baseExp);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doFasterBerryRewards);
|
||||
await showEncounterText(scene, `${namespace}.option.2.selected`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Leave encounter with no rewards or exp
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
return true;
|
||||
}
|
||||
)
|
||||
.build();
|
||||
|
||||
async function tryGiveBerry(scene: BattleScene, prioritizedPokemon?: PlayerPokemon) {
|
||||
const berryType = randSeedInt(Object.keys(BerryType).filter(s => !isNaN(Number(s))).length) as BerryType;
|
||||
const berry = generateModifierType(scene, modifierTypes.BERRY, [berryType]) as BerryModifierType;
|
||||
|
||||
const party = scene.getParty();
|
||||
|
||||
// Will try to apply to prioritized pokemon first, then do normal application method if it fails
|
||||
if (prioritizedPokemon) {
|
||||
const heldBerriesOfType = scene.findModifier(m => m instanceof BerryModifier
|
||||
&& m.pokemonId === prioritizedPokemon.id && (m as BerryModifier).berryType === berryType, true) as BerryModifier;
|
||||
|
||||
if (!heldBerriesOfType || heldBerriesOfType.getStackCount() < heldBerriesOfType.getMaxStackCount(scene)) {
|
||||
await applyModifierTypeToPlayerPokemon(scene, prioritizedPokemon, berry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over the party until berry was successfully given
|
||||
for (const pokemon of party) {
|
||||
const heldBerriesOfType = scene.findModifier(m => m instanceof BerryModifier
|
||||
&& m.pokemonId === pokemon.id && (m as BerryModifier).berryType === berryType, true) as BerryModifier;
|
||||
|
||||
if (!heldBerriesOfType || heldBerriesOfType.getStackCount() < heldBerriesOfType.getMaxStackCount(scene)) {
|
||||
await applyModifierTypeToPlayerPokemon(scene, pokemon, berry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,670 @@
|
||||
import {
|
||||
EnemyPartyConfig, generateModifierType,
|
||||
generateModifierTypeOption,
|
||||
initBattleWithEnemyConfig,
|
||||
leaveEncounterWithoutBattle,
|
||||
selectOptionThenPokemon,
|
||||
selectPokemonForOption,
|
||||
setEncounterRewards,
|
||||
transitionMysteryEncounterIntroVisuals,
|
||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import {
|
||||
trainerConfigs,
|
||||
TrainerPartyCompoundTemplate,
|
||||
TrainerPartyTemplate,
|
||||
TrainerSlot,
|
||||
} from "#app/data/trainer-config";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import * as Utils from "#app/utils";
|
||||
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Species } from "#enums/species";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { getEncounterText, showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import {
|
||||
AttackTypeBoosterHeldItemTypeRequirement,
|
||||
CombinationPokemonRequirement,
|
||||
HeldItemRequirement,
|
||||
TypeRequirement
|
||||
} from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||
import { Type } from "#app/data/type";
|
||||
import { AttackTypeBoosterModifierType, ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type";
|
||||
import {
|
||||
AttackTypeBoosterModifier,
|
||||
BypassSpeedChanceModifier,
|
||||
ContactHeldItemTransferChanceModifier,
|
||||
PokemonHeldItemModifier
|
||||
} from "#app/modifier/modifier";
|
||||
import i18next from "i18next";
|
||||
import MoveInfoOverlay from "#app/ui/move-info-overlay";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:bugTypeSuperfan";
|
||||
|
||||
const POOL_1_POKEMON = [
|
||||
Species.PARASECT,
|
||||
Species.VENOMOTH,
|
||||
Species.LEDIAN,
|
||||
Species.ARIADOS,
|
||||
Species.YANMA,
|
||||
Species.BEAUTIFLY,
|
||||
Species.DUSTOX,
|
||||
Species.MASQUERAIN,
|
||||
Species.NINJASK,
|
||||
Species.VOLBEAT,
|
||||
Species.ILLUMISE,
|
||||
Species.ANORITH,
|
||||
Species.KRICKETUNE,
|
||||
Species.WORMADAM,
|
||||
Species.MOTHIM,
|
||||
Species.SKORUPI,
|
||||
Species.JOLTIK,
|
||||
Species.LARVESTA,
|
||||
Species.VIVILLON,
|
||||
Species.CHARJABUG,
|
||||
Species.RIBOMBEE,
|
||||
Species.SPIDOPS,
|
||||
Species.LOKIX
|
||||
];
|
||||
|
||||
const POOL_2_POKEMON = [
|
||||
Species.SCYTHER,
|
||||
Species.PINSIR,
|
||||
Species.HERACROSS,
|
||||
Species.FORRETRESS,
|
||||
Species.SCIZOR,
|
||||
Species.SHUCKLE,
|
||||
Species.SHEDINJA,
|
||||
Species.ARMALDO,
|
||||
Species.VESPIQUEN,
|
||||
Species.DRAPION,
|
||||
Species.YANMEGA,
|
||||
Species.LEAVANNY,
|
||||
Species.SCOLIPEDE,
|
||||
Species.CRUSTLE,
|
||||
Species.ESCAVALIER,
|
||||
Species.ACCELGOR,
|
||||
Species.GALVANTULA,
|
||||
Species.VIKAVOLT,
|
||||
Species.ARAQUANID,
|
||||
Species.ORBEETLE,
|
||||
Species.CENTISKORCH,
|
||||
Species.FROSMOTH,
|
||||
Species.KLEAVOR,
|
||||
];
|
||||
|
||||
const POOL_3_POKEMON: { species: Species, formIndex?: number }[] = [
|
||||
{
|
||||
species: Species.PINSIR,
|
||||
formIndex: 1
|
||||
},
|
||||
{
|
||||
species: Species.SCIZOR,
|
||||
formIndex: 1
|
||||
},
|
||||
{
|
||||
species: Species.HERACROSS,
|
||||
formIndex: 1
|
||||
},
|
||||
{
|
||||
species: Species.ORBEETLE,
|
||||
formIndex: 1
|
||||
},
|
||||
{
|
||||
species: Species.CENTISKORCH,
|
||||
formIndex: 1
|
||||
},
|
||||
{
|
||||
species: Species.DURANT,
|
||||
},
|
||||
{
|
||||
species: Species.VOLCARONA,
|
||||
},
|
||||
{
|
||||
species: Species.GOLISOPOD,
|
||||
},
|
||||
];
|
||||
|
||||
const POOL_4_POKEMON = [
|
||||
Species.GENESECT,
|
||||
Species.SLITHER_WING,
|
||||
Species.BUZZWOLE,
|
||||
Species.PHEROMOSA
|
||||
];
|
||||
|
||||
const PHYSICAL_TUTOR_MOVES = [
|
||||
Moves.MEGAHORN,
|
||||
Moves.X_SCISSOR,
|
||||
Moves.ATTACK_ORDER,
|
||||
Moves.PIN_MISSILE,
|
||||
Moves.FIRST_IMPRESSION
|
||||
];
|
||||
|
||||
const SPECIAL_TUTOR_MOVES = [
|
||||
Moves.SILVER_WIND,
|
||||
Moves.BUG_BUZZ,
|
||||
Moves.SIGNAL_BEAM,
|
||||
Moves.POLLEN_PUFF
|
||||
];
|
||||
|
||||
const STATUS_TUTOR_MOVES = [
|
||||
Moves.STRING_SHOT,
|
||||
Moves.STICKY_WEB,
|
||||
Moves.SILK_TRAP,
|
||||
Moves.RAGE_POWDER,
|
||||
Moves.HEAL_ORDER
|
||||
];
|
||||
|
||||
const MISC_TUTOR_MOVES = [
|
||||
Moves.BUG_BITE,
|
||||
Moves.LEECH_LIFE,
|
||||
Moves.DEFEND_ORDER,
|
||||
Moves.QUIVER_DANCE,
|
||||
Moves.TAIL_GLOW,
|
||||
Moves.INFESTATION,
|
||||
Moves.U_TURN
|
||||
];
|
||||
|
||||
/**
|
||||
* Bug Type Superfan encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3810 | GitHub Issue #3810}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.BUG_TYPE_SUPERFAN)
|
||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||
// Must have at least 1 Bug type on team, OR have a bug item somewhere on the team
|
||||
new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1),
|
||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1),
|
||||
new TypeRequirement(Type.BUG, false, 1)
|
||||
))
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withIntroSpriteConfigs([]) // These are set in onInit()
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Calculates what trainers are available for battle in the encounter
|
||||
|
||||
// Bug type superfan trainer config
|
||||
const config = getTrainerConfigForWave(scene.currentBattle.waveIndex);
|
||||
const spriteKey = config.getSpriteKey();
|
||||
encounter.enemyPartyConfigs.push({
|
||||
trainerConfig: config,
|
||||
female: true,
|
||||
});
|
||||
|
||||
encounter.spriteConfigs = [
|
||||
{
|
||||
spriteKey: spriteKey,
|
||||
fileRoot: "trainer",
|
||||
hasShadow: true,
|
||||
},
|
||||
];
|
||||
|
||||
const requiredItems = [
|
||||
generateModifierType(scene, modifierTypes.QUICK_CLAW),
|
||||
generateModifierType(scene, modifierTypes.GRIP_CLAW),
|
||||
generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.BUG]),
|
||||
];
|
||||
|
||||
const requiredItemString = requiredItems.map(m => m?.name ?? "unknown").join("/");
|
||||
encounter.setDialogueToken("requiredBugItems", requiredItemString);
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Select battle the bug trainer
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||
|
||||
// Init the moves available for tutor
|
||||
const moveTutorOptions: PokemonMove[] = [];
|
||||
moveTutorOptions.push(new PokemonMove(PHYSICAL_TUTOR_MOVES[randSeedInt(PHYSICAL_TUTOR_MOVES.length)]));
|
||||
moveTutorOptions.push(new PokemonMove(SPECIAL_TUTOR_MOVES[randSeedInt(SPECIAL_TUTOR_MOVES.length)]));
|
||||
moveTutorOptions.push(new PokemonMove(STATUS_TUTOR_MOVES[randSeedInt(STATUS_TUTOR_MOVES.length)]));
|
||||
moveTutorOptions.push(new PokemonMove(MISC_TUTOR_MOVES[randSeedInt(MISC_TUTOR_MOVES.length)]));
|
||||
encounter.misc = {
|
||||
moveTutorOptions
|
||||
};
|
||||
|
||||
// Assigns callback that teaches move before continuing to rewards
|
||||
encounter.onRewards = doBugTypeMoveTutor;
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
)
|
||||
.withOption(MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new TypeRequirement(Type.BUG, false, 1)) // Must have 1 Bug type on team
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.disabled_tooltip`
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Player shows off their bug types
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
// Player gets different rewards depending on the number of bug types they have
|
||||
const numBugTypes = scene.getParty().filter(p => p.isOfType(Type.BUG, true)).length;
|
||||
encounter.setDialogueToken("numBugTypes", numBugTypes.toString());
|
||||
|
||||
if (numBugTypes < 2) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected_0_to_1`,
|
||||
},
|
||||
];
|
||||
} else if (numBugTypes < 4) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.QUICK_CLAW, modifierTypes.MAX_LURE, modifierTypes.ULTRA_BALL], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected_2_to_3`,
|
||||
},
|
||||
];
|
||||
} else if (numBugTypes < 6) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.GRIP_CLAW, modifierTypes.MAX_LURE, modifierTypes.ROGUE_BALL], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected_4_to_5`,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
// If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to a Master Ball
|
||||
const modifierOptions: ModifierTypeOption[] = [generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)!];
|
||||
const specialOptions: ModifierTypeOption[] = [];
|
||||
|
||||
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
|
||||
if (nonRareEvolutionModifier) {
|
||||
specialOptions.push(nonRareEvolutionModifier);
|
||||
}
|
||||
const rareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.RARE_EVOLUTION_ITEM);
|
||||
if (rareEvolutionModifier) {
|
||||
specialOptions.push(rareEvolutionModifier);
|
||||
}
|
||||
const formChangeModifier = generateModifierTypeOption(scene, modifierTypes.FORM_CHANGE_ITEM);
|
||||
if (formChangeModifier) {
|
||||
specialOptions.push(formChangeModifier);
|
||||
}
|
||||
if (specialOptions.length > 0) {
|
||||
modifierOptions.push(specialOptions[randSeedInt(specialOptions.length)]);
|
||||
}
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifierOptions, fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected_6`,
|
||||
},
|
||||
];
|
||||
}
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Player shows off their bug types
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.build())
|
||||
.withOption(MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||
// Meets one or both of the below reqs
|
||||
new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1),
|
||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1)
|
||||
))
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.3.selected_dialogue`,
|
||||
},
|
||||
],
|
||||
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Get Pokemon held items and filter for valid ones
|
||||
const validItems = pokemon.getHeldItems().filter(item => {
|
||||
return item instanceof BypassSpeedChanceModifier ||
|
||||
item instanceof ContactHeldItemTransferChanceModifier ||
|
||||
(item instanceof AttackTypeBoosterModifier && (item.type as AttackTypeBoosterModifierType).moveType === Type.BUG);
|
||||
});
|
||||
|
||||
return validItems.map((modifier: PokemonHeldItemModifier) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: modifier.type.name,
|
||||
handler: () => {
|
||||
// Pokemon and item selected
|
||||
encounter.setDialogueToken("selectedItem", modifier.type.name);
|
||||
encounter.misc = {
|
||||
chosenPokemon: pokemon,
|
||||
chosenModifier: modifier,
|
||||
};
|
||||
return true;
|
||||
},
|
||||
};
|
||||
return option;
|
||||
});
|
||||
};
|
||||
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
// If pokemon has valid item, it can be selected
|
||||
const hasValidItem = pokemon.getHeldItems().some(item => {
|
||||
return item instanceof BypassSpeedChanceModifier ||
|
||||
item instanceof ContactHeldItemTransferChanceModifier ||
|
||||
(item instanceof AttackTypeBoosterModifier && (item.type as AttackTypeBoosterModifierType).moveType === Type.BUG);
|
||||
});
|
||||
if (!hasValidItem) {
|
||||
return getEncounterText(scene, `${namespace}.option.3.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const modifier = encounter.misc.chosenModifier;
|
||||
|
||||
// Remove the modifier if its stacks go to 0
|
||||
modifier.stackCount -= 1;
|
||||
if (modifier.stackCount === 0) {
|
||||
scene.removeModifier(modifier);
|
||||
}
|
||||
scene.updateModifiers(true, true);
|
||||
|
||||
const bugNet = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!;
|
||||
bugNet.type.tier = ModifierTier.ROGUE;
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [bugNet], guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED], fillRemaining: false });
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build())
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
||||
|
||||
function getTrainerConfigForWave(waveIndex: number) {
|
||||
// Bug type superfan trainer config
|
||||
const config = trainerConfigs[TrainerType.BUG_TYPE_SUPERFAN].clone();
|
||||
config.name = i18next.t("trainerNames:bug_type_superfan");
|
||||
|
||||
const pool3Copy = POOL_3_POKEMON.slice(0);
|
||||
randSeedShuffle(pool3Copy);
|
||||
const pool3Mon = pool3Copy.pop()!;
|
||||
|
||||
if (waveIndex < 30) {
|
||||
// Use default template (2 AVG)
|
||||
config
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true));
|
||||
} else if (waveIndex < 50) {
|
||||
config
|
||||
.setPartyTemplates(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE))
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true));
|
||||
} else if (waveIndex < 70) {
|
||||
config
|
||||
.setPartyTemplates(new TrainerPartyTemplate(4, PartyMemberStrength.AVERAGE))
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true));
|
||||
} else if (waveIndex < 100) {
|
||||
config
|
||||
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true));
|
||||
} else if (waveIndex < 120) {
|
||||
config
|
||||
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex!;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}));
|
||||
} else if (waveIndex < 140) {
|
||||
randSeedShuffle(pool3Copy);
|
||||
const pool3Mon2 = pool3Copy.pop()!;
|
||||
config
|
||||
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex!;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon2.species], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon2.formIndex)) {
|
||||
p.formIndex = pool3Mon2.formIndex!;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}));
|
||||
} else if (waveIndex < 160) {
|
||||
config
|
||||
.setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(4, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)))
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex!;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc(POOL_4_POKEMON, TrainerSlot.TRAINER, true));
|
||||
} else {
|
||||
config
|
||||
.setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(4, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)))
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex!;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex!;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc(POOL_4_POKEMON, TrainerSlot.TRAINER, true));
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void) {
|
||||
return (scene: BattleScene, level: number, strength: PartyMemberStrength) => {
|
||||
let species = Utils.randSeedItem(speciesPool);
|
||||
if (!ignoreEvolution) {
|
||||
species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength);
|
||||
}
|
||||
return scene.addEnemyPokemon(getPokemonSpecies(species), level, trainerSlot, undefined, undefined, postProcess);
|
||||
};
|
||||
}
|
||||
|
||||
function doBugTypeMoveTutor(scene: BattleScene): Promise<void> {
|
||||
return new Promise<void>(async resolve => {
|
||||
const moveOptions = scene.currentBattle.mysteryEncounter!.misc.moveTutorOptions;
|
||||
await showEncounterDialogue(scene, `${namespace}.battle_won`, `${namespace}.speaker`);
|
||||
|
||||
const overlayScale = 1;
|
||||
const moveInfoOverlay = new MoveInfoOverlay(scene, {
|
||||
delayVisibility: false,
|
||||
scale: overlayScale,
|
||||
onSide: true,
|
||||
right: true,
|
||||
x: 1,
|
||||
y: -MoveInfoOverlay.getHeight(overlayScale, true) - 1,
|
||||
width: (scene.game.canvas.width / 6) - 2,
|
||||
});
|
||||
scene.ui.add(moveInfoOverlay);
|
||||
|
||||
const optionSelectItems = moveOptions.map((move: PokemonMove) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: move.getName(),
|
||||
handler: () => {
|
||||
moveInfoOverlay.active = false;
|
||||
moveInfoOverlay.setVisible(false);
|
||||
return true;
|
||||
},
|
||||
onHover: () => {
|
||||
moveInfoOverlay.active = true;
|
||||
moveInfoOverlay.show(allMoves[move.moveId]);
|
||||
},
|
||||
};
|
||||
return option;
|
||||
});
|
||||
|
||||
const onHoverOverCancel = () => {
|
||||
moveInfoOverlay.active = false;
|
||||
moveInfoOverlay.setVisible(false);
|
||||
};
|
||||
|
||||
const result = await selectOptionThenPokemon(scene, optionSelectItems, `${namespace}.teach_move_prompt`, undefined, onHoverOverCancel);
|
||||
// let forceExit = !!result;
|
||||
if (!result) {
|
||||
moveInfoOverlay.active = false;
|
||||
moveInfoOverlay.setVisible(false);
|
||||
}
|
||||
|
||||
// TODO: add menu to confirm player doesn't want to teach a move
|
||||
// while (!result && !forceExit) {
|
||||
// // Didn't teach a move, ask the player to confirm they don't want to teach a move
|
||||
// await showEncounterDialogue(scene, `${namespace}.confirm_no_teach`, `${namespace}.speaker`);
|
||||
// const confirm = await new Promise<boolean>(confirmResolve => {
|
||||
// scene.ui.setMode(Mode.CONFIRM, () => confirmResolve(true), () => confirmResolve(false));
|
||||
// });
|
||||
// scene.ui.clearText();
|
||||
// await scene.ui.setMode(Mode.MESSAGE);
|
||||
// if (confirm) {
|
||||
// // No teach, break out of loop
|
||||
// forceExit = true;
|
||||
// } else {
|
||||
// // Re-show learn menu
|
||||
// result = await selectOptionThenPokemon(scene, optionSelectItems, `${namespace}.teach_move_prompt`, undefined, onHoverOverCancel);
|
||||
// if (!result) {
|
||||
// moveInfoOverlay.active = false;
|
||||
// moveInfoOverlay.setVisible(false);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Option select complete, handle if they are learning a move
|
||||
if (result && result.selectedOptionIndex < moveOptions.length) {
|
||||
scene.unshiftPhase(new LearnMovePhase(scene, result.selectedPokemonIndex, moveOptions[result.selectedOptionIndex].moveId));
|
||||
}
|
||||
|
||||
// Complete battle and go to rewards
|
||||
resolve();
|
||||
});
|
||||
}
|
@ -0,0 +1,496 @@
|
||||
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { trainerConfigs, TrainerPartyCompoundTemplate, TrainerPartyTemplate, } from "#app/data/trainer-config";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
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 { Type } from "#app/data/type";
|
||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { randSeedInt, randSeedShuffle } from "#app/utils";
|
||||
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import i18next from "i18next";
|
||||
import { OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { Ability } from "#app/data/ability";
|
||||
import { BerryModifier } from "#app/modifier/modifier";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
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 { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES, GameModes } from "#app/game-mode";
|
||||
import { EncounterAnim } from "#enums/encounter-anims";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:clowningAround";
|
||||
|
||||
const RANDOM_ABILITY_POOL = [
|
||||
Abilities.STURDY,
|
||||
Abilities.PICKUP,
|
||||
Abilities.INTIMIDATE,
|
||||
Abilities.GUTS,
|
||||
Abilities.DROUGHT,
|
||||
Abilities.DRIZZLE,
|
||||
Abilities.SNOW_WARNING,
|
||||
Abilities.SAND_STREAM,
|
||||
Abilities.ELECTRIC_SURGE,
|
||||
Abilities.PSYCHIC_SURGE,
|
||||
Abilities.GRASSY_SURGE,
|
||||
Abilities.MISTY_SURGE,
|
||||
Abilities.MAGICIAN,
|
||||
Abilities.SHEER_FORCE,
|
||||
Abilities.PRANKSTER
|
||||
];
|
||||
|
||||
/**
|
||||
* Clowning Around encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3807 | GitHub Issue #3807}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const ClowningAroundEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.CLOWNING_AROUND)
|
||||
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
||||
.withDisabledGameModes(GameModes.CHALLENGE)
|
||||
.withSceneWaveRangeRequirement(80, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1])
|
||||
.withAnimations(EncounterAnim.SMOKESCREEN)
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: Species.MR_MIME.toString(),
|
||||
fileRoot: "pokemon",
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
x: -25,
|
||||
tint: 0.3,
|
||||
y: -3,
|
||||
yShadow: -3
|
||||
},
|
||||
{
|
||||
spriteKey: Species.BLACEPHALON.toString(),
|
||||
fileRoot: "pokemon/exp",
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
x: 25,
|
||||
tint: 0.3,
|
||||
y: -3,
|
||||
yShadow: -3
|
||||
},
|
||||
{
|
||||
spriteKey: "harlequin",
|
||||
fileRoot: "trainer",
|
||||
hasShadow: true,
|
||||
x: 0,
|
||||
y: 2,
|
||||
yShadow: 2
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
const clownTrainerType = TrainerType.HARLEQUIN;
|
||||
const clownConfig = trainerConfigs[clownTrainerType].clone();
|
||||
const clownPartyTemplate = new TrainerPartyCompoundTemplate(
|
||||
new TrainerPartyTemplate(1, PartyMemberStrength.STRONG),
|
||||
new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER));
|
||||
clownConfig.setPartyTemplates(clownPartyTemplate);
|
||||
clownConfig.setDoubleOnly();
|
||||
// @ts-ignore
|
||||
clownConfig.partyTemplateFunc = null; // Overrides party template func if it exists
|
||||
|
||||
// Generate random ability for Blacephalon from pool
|
||||
const ability = RANDOM_ABILITY_POOL[randSeedInt(RANDOM_ABILITY_POOL.length)];
|
||||
encounter.setDialogueToken("ability", new Ability(ability, 3).name);
|
||||
encounter.misc = { ability };
|
||||
|
||||
encounter.enemyPartyConfigs.push({
|
||||
trainerConfig: clownConfig,
|
||||
pokemonConfigs: [ // Overrides first 2 pokemon to be Mr. Mime and Blacephalon
|
||||
{
|
||||
species: getPokemonSpecies(Species.MR_MIME),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC]
|
||||
},
|
||||
{ // 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)] }),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN]
|
||||
},
|
||||
],
|
||||
doubleBattle: true
|
||||
});
|
||||
|
||||
// Load animations/sfx for start of fight moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.ROLE_PLAY, Moves.TAUNT]);
|
||||
|
||||
encounter.setDialogueToken("blacephalonName", getPokemonSpecies(Species.BLACEPHALON).getName());
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
speaker: `${namespace}.speaker`
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Spawn battle
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
|
||||
// TODO: when Magic Room and Wonder Room are implemented, add those to start of battle
|
||||
encounter.startOfBattleEffects.push(
|
||||
{ // Mr. Mime copies the Blacephalon's random ability
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY_2],
|
||||
move: new PokemonMove(Moves.ROLE_PLAY),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.TAUNT),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER_2],
|
||||
move: new PokemonMove(Moves.TAUNT),
|
||||
ignorePp: true
|
||||
});
|
||||
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
// After the battle, offer the player the opportunity to permanently swap ability
|
||||
const abilityWasSwapped = await handleSwapAbility(scene);
|
||||
if (abilityWasSwapped) {
|
||||
await showEncounterText(scene, `${namespace}.option.1.ability_gained`);
|
||||
}
|
||||
|
||||
// Play animations once ability swap is complete
|
||||
// Trainer sprite that is shown at end of battle is not the same as mystery encounter intro visuals
|
||||
scene.tweens.add({
|
||||
targets: scene.currentBattle.trainer,
|
||||
x: "+=16",
|
||||
y: "-=16",
|
||||
alpha: 0,
|
||||
ease: "Sine.easeInOut",
|
||||
duration: 250
|
||||
});
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
background.playWithoutTargets(scene, 230, 40, 2);
|
||||
return true;
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
speaker: `${namespace}.speaker`
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.2.selected_2`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.2.selected_3`,
|
||||
speaker: `${namespace}.speaker`
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Swap player's items on pokemon with the most items
|
||||
// Item comparisons look at whichever Pokemon has the greatest number of TRANSFERABLE, non-berry items
|
||||
// So Vitamins, form change items, etc. are not included
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
const party = scene.getParty();
|
||||
let mostHeldItemsPokemon = party[0];
|
||||
let count = mostHeldItemsPokemon.getHeldItems()
|
||||
.filter(m => m.isTransferrable && !(m instanceof BerryModifier))
|
||||
.reduce((v, m) => v + m.stackCount, 0);
|
||||
|
||||
party.forEach(pokemon => {
|
||||
const nextCount = pokemon.getHeldItems()
|
||||
.filter(m => m.isTransferrable && !(m instanceof BerryModifier))
|
||||
.reduce((v, m) => v + m.stackCount, 0);
|
||||
if (nextCount > count) {
|
||||
mostHeldItemsPokemon = pokemon;
|
||||
count = nextCount;
|
||||
}
|
||||
});
|
||||
|
||||
encounter.setDialogueToken("switchPokemon", mostHeldItemsPokemon.getNameToRender());
|
||||
|
||||
const items = mostHeldItemsPokemon.getHeldItems();
|
||||
|
||||
// Shuffles Berries (if they have any)
|
||||
let numBerries = 0;
|
||||
items.filter(m => m instanceof BerryModifier)
|
||||
.forEach(m => {
|
||||
numBerries += m.stackCount;
|
||||
scene.removeModifier(m);
|
||||
});
|
||||
|
||||
generateItemsOfTier(scene, mostHeldItemsPokemon, numBerries, "Berries");
|
||||
|
||||
// Shuffle Transferable held items in the same tier (only shuffles Ultra and Rogue atm)
|
||||
let numUltra = 0;
|
||||
let numRogue = 0;
|
||||
items.filter(m => m.isTransferrable && !(m instanceof BerryModifier))
|
||||
.forEach(m => {
|
||||
const type = m.type.withTierFromPool();
|
||||
const tier = type.tier ?? ModifierTier.ULTRA;
|
||||
if (type.id === "GOLDEN_EGG" || tier === ModifierTier.ROGUE) {
|
||||
numRogue += m.stackCount;
|
||||
scene.removeModifier(m);
|
||||
} else if (type.id === "LUCKY_EGG" || tier === ModifierTier.ULTRA) {
|
||||
numUltra += m.stackCount;
|
||||
scene.removeModifier(m);
|
||||
}
|
||||
});
|
||||
|
||||
generateItemsOfTier(scene, mostHeldItemsPokemon, numUltra, ModifierTier.ULTRA);
|
||||
generateItemsOfTier(scene, mostHeldItemsPokemon, numRogue, ModifierTier.ROGUE);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
// Play animations
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
background.playWithoutTargets(scene, 230, 40, 2);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true, 200);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
speaker: `${namespace}.speaker`
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.3.selected_2`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.3.selected_3`,
|
||||
speaker: `${namespace}.speaker`
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Randomize the second type of all player's pokemon
|
||||
// If the pokemon does not normally have a second type, it will gain 1
|
||||
for (const pokemon of scene.getParty()) {
|
||||
const originalTypes = pokemon.getTypes(false, false, true);
|
||||
|
||||
// If the Pokemon has non-status moves that don't match the Pokemon's type, prioritizes those as the new type
|
||||
// Makes the "randomness" of the shuffle slightly less punishing
|
||||
let priorityTypes = pokemon.moveset
|
||||
.filter(move => move && !originalTypes.includes(move.getMove().type) && move.getMove().category !== MoveCategory.STATUS)
|
||||
.map(move => move!.getMove().type);
|
||||
if (priorityTypes?.length > 0) {
|
||||
priorityTypes = [...new Set(priorityTypes)];
|
||||
randSeedShuffle(priorityTypes);
|
||||
}
|
||||
|
||||
const newTypes = [originalTypes[0]];
|
||||
let secondType: Type | null = null;
|
||||
while (secondType === null || secondType === newTypes[0] || originalTypes.includes(secondType)) {
|
||||
if (priorityTypes.length > 0) {
|
||||
secondType = priorityTypes.pop() ?? null;
|
||||
} else {
|
||||
secondType = randSeedInt(18) as Type;
|
||||
}
|
||||
}
|
||||
newTypes.push(secondType);
|
||||
if (!pokemon.mysteryEncounterPokemonData) {
|
||||
pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
||||
}
|
||||
pokemon.mysteryEncounterPokemonData.types = newTypes;
|
||||
}
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
// Play animations
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
background.playWithoutTargets(scene, 230, 40, 2);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true, 200);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
||||
|
||||
async function handleSwapAbility(scene: BattleScene) {
|
||||
return new Promise<boolean>(async resolve => {
|
||||
await showEncounterDialogue(scene, `${namespace}.option.1.apply_ability_dialogue`, `${namespace}.speaker`);
|
||||
await showEncounterText(scene, `${namespace}.option.1.apply_ability_message`);
|
||||
|
||||
scene.ui.setMode(Mode.MESSAGE).then(() => {
|
||||
displayYesNoOptions(scene, resolve);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function displayYesNoOptions(scene: BattleScene, resolve) {
|
||||
showEncounterText(scene, `${namespace}.option.1.ability_prompt`, null, 500, false);
|
||||
const fullOptions = [
|
||||
{
|
||||
label: i18next.t("menu:yes"),
|
||||
handler: () => {
|
||||
onYesAbilitySwap(scene, resolve);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: i18next.t("menu:no"),
|
||||
handler: () => {
|
||||
resolve(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const config: OptionSelectConfig = {
|
||||
options: fullOptions,
|
||||
maxOptions: 7,
|
||||
yOffset: 0
|
||||
};
|
||||
scene.ui.setModeWithoutClear(Mode.OPTION_SELECT, config, null, true);
|
||||
}
|
||||
|
||||
function onYesAbilitySwap(scene: BattleScene, resolve) {
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Do ability swap
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (!pokemon.mysteryEncounterPokemonData) {
|
||||
pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
||||
}
|
||||
pokemon.mysteryEncounterPokemonData.ability = encounter.misc.ability;
|
||||
encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender());
|
||||
scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true));
|
||||
};
|
||||
|
||||
const onPokemonNotSelected = () => {
|
||||
scene.ui.setMode(Mode.MESSAGE).then(() => {
|
||||
displayYesNoOptions(scene, resolve);
|
||||
});
|
||||
};
|
||||
|
||||
selectPokemonForOption(scene, onPokemonSelected, onPokemonNotSelected);
|
||||
}
|
||||
|
||||
function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItems: number, tier: ModifierTier | "Berries") {
|
||||
// These pools have to be defined at runtime so that modifierTypes exist
|
||||
// Pools have instances of the modifier type equal to the max stacks that modifier can be applied to any one pokemon
|
||||
// This is to prevent "over-generating" a random item of a certain type during item swaps
|
||||
const ultraPool = [
|
||||
[modifierTypes.REVIVER_SEED, 1],
|
||||
[modifierTypes.GOLDEN_PUNCH, 5],
|
||||
[modifierTypes.ATTACK_TYPE_BOOSTER, 99],
|
||||
[modifierTypes.QUICK_CLAW, 3],
|
||||
[modifierTypes.WIDE_LENS, 3]
|
||||
];
|
||||
|
||||
const roguePool = [
|
||||
[modifierTypes.LEFTOVERS, 4],
|
||||
[modifierTypes.SHELL_BELL, 4],
|
||||
[modifierTypes.SOUL_DEW, 10],
|
||||
[modifierTypes.SOOTHE_BELL, 3],
|
||||
[modifierTypes.SCOPE_LENS, 1],
|
||||
[modifierTypes.BATON, 1],
|
||||
[modifierTypes.FOCUS_BAND, 5],
|
||||
[modifierTypes.KINGS_ROCK, 3],
|
||||
[modifierTypes.GRIP_CLAW, 5]
|
||||
];
|
||||
|
||||
const berryPool = [
|
||||
[BerryType.APICOT, 3],
|
||||
[BerryType.ENIGMA, 2],
|
||||
[BerryType.GANLON, 3],
|
||||
[BerryType.LANSAT, 3],
|
||||
[BerryType.LEPPA, 2],
|
||||
[BerryType.LIECHI, 3],
|
||||
[BerryType.LUM, 2],
|
||||
[BerryType.PETAYA, 3],
|
||||
[BerryType.SALAC, 2],
|
||||
[BerryType.SITRUS, 2],
|
||||
[BerryType.STARF, 3]
|
||||
];
|
||||
|
||||
let pool: any[];
|
||||
if (tier === "Berries") {
|
||||
pool = berryPool;
|
||||
} else {
|
||||
pool = tier === ModifierTier.ULTRA ? ultraPool : roguePool;
|
||||
}
|
||||
|
||||
for (let i = 0; i < numItems; i++) {
|
||||
const randIndex = randSeedInt(pool.length);
|
||||
const newItemType = pool[randIndex];
|
||||
let newMod;
|
||||
if (tier === "Berries") {
|
||||
newMod = generateModifierType(scene, modifierTypes.BERRY, [newItemType[0]]) as PokemonHeldItemModifierType;
|
||||
} else {
|
||||
newMod = generateModifierType(scene, newItemType[0]) as PokemonHeldItemModifierType;
|
||||
}
|
||||
applyModifierTypeToPlayerPokemon(scene, pokemon, newMod);
|
||||
// Decrement max stacks and remove from pool if at max
|
||||
newItemType[1]--;
|
||||
if (newItemType[1] <= 0) {
|
||||
pool.splice(randIndex, 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,325 @@
|
||||
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Species } from "#enums/species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { TrainerSlot } from "#app/data/trainer-config";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||
import { DANCING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { catchPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { EncounterAnim } from "#enums/encounter-anims";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:dancingLessons";
|
||||
|
||||
// Fire form
|
||||
const BAILE_STYLE_BIOMES = [
|
||||
Biome.VOLCANO,
|
||||
Biome.BEACH,
|
||||
Biome.ISLAND,
|
||||
Biome.WASTELAND,
|
||||
Biome.MOUNTAIN,
|
||||
Biome.BADLANDS,
|
||||
Biome.DESERT
|
||||
];
|
||||
|
||||
// Electric form
|
||||
const POM_POM_STYLE_BIOMES = [
|
||||
Biome.CONSTRUCTION_SITE,
|
||||
Biome.POWER_PLANT,
|
||||
Biome.FACTORY,
|
||||
Biome.LABORATORY,
|
||||
Biome.SLUM,
|
||||
Biome.METROPOLIS,
|
||||
Biome.DOJO
|
||||
];
|
||||
|
||||
// Psychic form
|
||||
const PAU_STYLE_BIOMES = [
|
||||
Biome.JUNGLE,
|
||||
Biome.FAIRY_CAVE,
|
||||
Biome.MEADOW,
|
||||
Biome.PLAINS,
|
||||
Biome.GRASS,
|
||||
Biome.TALL_GRASS,
|
||||
Biome.FOREST
|
||||
];
|
||||
|
||||
// Ghost form
|
||||
const SENSU_STYLE_BIOMES = [
|
||||
Biome.RUINS,
|
||||
Biome.SWAMP,
|
||||
Biome.CAVE,
|
||||
Biome.ABYSS,
|
||||
Biome.GRAVEYARD,
|
||||
Biome.LAKE,
|
||||
Biome.TEMPLE
|
||||
];
|
||||
|
||||
/**
|
||||
* Dancing Lessons encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3823 | GitHub Issue #3823}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const DancingLessonsEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DANCING_LESSONS)
|
||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withIntroSpriteConfigs([]) // Uses a real Pokemon sprite instead of ME Intro Visuals
|
||||
.withAnimations(EncounterAnim.DANCE)
|
||||
.withHideWildIntroMessage(true)
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withCatchAllowed(true)
|
||||
.withOnVisualsStart((scene: BattleScene) => {
|
||||
const danceAnim = new EncounterBattleAnim(EncounterAnim.DANCE, scene.getEnemyPokemon()!, scene.getParty()[0]);
|
||||
danceAnim.play(scene);
|
||||
|
||||
return true;
|
||||
})
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
const species = getPokemonSpecies(Species.ORICORIO);
|
||||
const level = (scene.currentBattle.enemyLevels?.[0] ?? scene.currentBattle.waveIndex) + Math.max(Math.round((scene.currentBattle.waveIndex / 10)), 0);
|
||||
const enemyPokemon = new EnemyPokemon(scene, species, level, TrainerSlot.NONE, false);
|
||||
if (!enemyPokemon.moveset.some(m => m && m.getMove().id === Moves.REVELATION_DANCE)) {
|
||||
if (enemyPokemon.moveset.length < 4) {
|
||||
enemyPokemon.moveset.push(new PokemonMove(Moves.REVELATION_DANCE));
|
||||
} else {
|
||||
enemyPokemon.moveset[0] = new PokemonMove(Moves.REVELATION_DANCE);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the form index based on the biome
|
||||
// Defaults to Baile style if somehow nothing matches
|
||||
const currentBiome = scene.arena.biomeType;
|
||||
if (BAILE_STYLE_BIOMES.includes(currentBiome)) {
|
||||
enemyPokemon.formIndex = 0;
|
||||
} else if (POM_POM_STYLE_BIOMES.includes(currentBiome)) {
|
||||
enemyPokemon.formIndex = 1;
|
||||
} else if (PAU_STYLE_BIOMES.includes(currentBiome)) {
|
||||
enemyPokemon.formIndex = 2;
|
||||
} else if (SENSU_STYLE_BIOMES.includes(currentBiome)) {
|
||||
enemyPokemon.formIndex = 3;
|
||||
} else {
|
||||
enemyPokemon.formIndex = 0;
|
||||
}
|
||||
|
||||
const oricorioData = new PokemonData(enemyPokemon);
|
||||
const oricorio = scene.addEnemyPokemon(species, scene.currentBattle.enemyLevels![0], TrainerSlot.NONE, false, oricorioData);
|
||||
|
||||
// Adds a real Pokemon sprite to the field (required for the animation)
|
||||
scene.getEnemyParty().forEach(enemyPokemon => {
|
||||
scene.field.remove(enemyPokemon, true);
|
||||
});
|
||||
scene.currentBattle.enemyParty = [oricorio];
|
||||
scene.field.add(oricorio);
|
||||
// Spawns on offscreen field
|
||||
oricorio.x -= 300;
|
||||
encounter.loadAssets.push(oricorio.loadAssets());
|
||||
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveMultiplier: 1,
|
||||
pokemonConfigs: [{
|
||||
species: species,
|
||||
dataSource: oricorioData,
|
||||
isBoss: true,
|
||||
// Gets +1 to all stats except SPD on battle start
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF], 1));
|
||||
}
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.misc = {
|
||||
oricorioData
|
||||
};
|
||||
|
||||
encounter.setDialogueToken("oricorioName", getPokemonSpecies(Species.ORICORIO).getName());
|
||||
|
||||
return true;
|
||||
})
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
encounter.startOfBattleEffects.push({
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.REVELATION_DANCE),
|
||||
ignorePp: true
|
||||
});
|
||||
|
||||
await hideOricorioPokemon(scene);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.BATON], fillRemaining: true });
|
||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Learn its Dance
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
encounter.setDialogueToken("selectedPokemon", pokemon.getNameToRender());
|
||||
scene.unshiftPhase(new LearnMovePhase(scene, scene.getParty().indexOf(pokemon), Moves.REVELATION_DANCE));
|
||||
|
||||
// Play animation again to "learn" the dance
|
||||
const danceAnim = new EncounterBattleAnim(EncounterAnim.DANCE, scene.getEnemyPokemon()!, scene.getPlayerPokemon());
|
||||
danceAnim.play(scene);
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Learn its Dance
|
||||
hideOricorioPokemon(scene);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(DANCING_MOVES)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Open menu for selecting pokemon with a Dancing move
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Return the options for nature selection
|
||||
return pokemon.moveset
|
||||
.filter(move => move && DANCING_MOVES.includes(move.getMove().id))
|
||||
.map((move: PokemonMove) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: move.getName(),
|
||||
handler: () => {
|
||||
// Pokemon and second option selected
|
||||
encounter.setDialogueToken("selectedPokemon", pokemon.getNameToRender());
|
||||
encounter.setDialogueToken("selectedMove", move.getName());
|
||||
encounter.misc.selectedMove = move;
|
||||
|
||||
return true;
|
||||
},
|
||||
};
|
||||
return option;
|
||||
});
|
||||
};
|
||||
|
||||
// Only Pokemon that have a Dancing move can be selected
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
// If pokemon meets primary pokemon reqs, it can be selected
|
||||
const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Show the Oricorio a dance, and recruit it
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const oricorio = encounter.misc.oricorioData.toPokemon(scene);
|
||||
oricorio.passive = true;
|
||||
|
||||
// Ensure the Oricorio's moveset gains the Dance move the player used
|
||||
const move = encounter.misc.selectedMove?.getMove().id;
|
||||
if (!oricorio.moveset.some(m => m.getMove().id === move)) {
|
||||
if (oricorio.moveset.length < 4) {
|
||||
oricorio.moveset.push(new PokemonMove(move));
|
||||
} else {
|
||||
oricorio.moveset[3] = new PokemonMove(move);
|
||||
}
|
||||
}
|
||||
|
||||
hideOricorioPokemon(scene);
|
||||
await catchPokemon(scene, oricorio, null, PokeballType.POKEBALL, false);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
|
||||
function hideOricorioPokemon(scene: BattleScene) {
|
||||
return new Promise<void>(resolve => {
|
||||
const oricorioSprite = scene.getEnemyParty()[0];
|
||||
scene.tweens.add({
|
||||
targets: oricorioSprite,
|
||||
x: "+=16",
|
||||
y: "-=16",
|
||||
alpha: 0,
|
||||
ease: "Sine.easeInOut",
|
||||
duration: 750,
|
||||
onComplete: () => {
|
||||
scene.field.remove(oricorioSprite, true);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
197
src/data/mystery-encounters/encounters/dark-deal-encounter.ts
Normal file
@ -0,0 +1,197 @@
|
||||
import { Type } from "#app/data/type";
|
||||
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Species } from "#enums/species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, } from "../utils/encounter-phase-utils";
|
||||
import { getRandomPlayerPokemon, getRandomSpeciesByStarterTier } 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 { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** i18n namespace for encounter */
|
||||
const namespace = "mysteryEncounter:darkDeal";
|
||||
|
||||
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, and egg-locked mythicals */
|
||||
const excludedBosses = [
|
||||
Species.NECROZMA,
|
||||
Species.COSMOG,
|
||||
Species.COSMOEM,
|
||||
Species.SOLGALEO,
|
||||
Species.LUNALA,
|
||||
Species.ETERNATUS,
|
||||
Species.NIHILEGO,
|
||||
Species.BUZZWOLE,
|
||||
Species.PHEROMOSA,
|
||||
Species.XURKITREE,
|
||||
Species.CELESTEELA,
|
||||
Species.KARTANA,
|
||||
Species.GUZZLORD,
|
||||
Species.POIPOLE,
|
||||
Species.NAGANADEL,
|
||||
Species.STAKATAKA,
|
||||
Species.BLACEPHALON,
|
||||
Species.GREAT_TUSK,
|
||||
Species.SCREAM_TAIL,
|
||||
Species.BRUTE_BONNET,
|
||||
Species.FLUTTER_MANE,
|
||||
Species.SLITHER_WING,
|
||||
Species.SANDY_SHOCKS,
|
||||
Species.ROARING_MOON,
|
||||
Species.KORAIDON,
|
||||
Species.WALKING_WAKE,
|
||||
Species.GOUGING_FIRE,
|
||||
Species.RAGING_BOLT,
|
||||
Species.IRON_TREADS,
|
||||
Species.IRON_BUNDLE,
|
||||
Species.IRON_HANDS,
|
||||
Species.IRON_JUGULIS,
|
||||
Species.IRON_MOTH,
|
||||
Species.IRON_THORNS,
|
||||
Species.IRON_VALIANT,
|
||||
Species.MIRAIDON,
|
||||
Species.IRON_LEAVES,
|
||||
Species.IRON_BOULDER,
|
||||
Species.IRON_CROWN,
|
||||
Species.MEW,
|
||||
Species.CELEBI,
|
||||
Species.DEOXYS,
|
||||
Species.JIRACHI,
|
||||
Species.PHIONE,
|
||||
Species.MANAPHY,
|
||||
Species.ARCEUS,
|
||||
Species.VICTINI,
|
||||
Species.MELTAN,
|
||||
Species.PECHARUNT,
|
||||
];
|
||||
|
||||
/**
|
||||
* Dark Deal encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3806 | GitHub Issue #3806}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const DarkDealEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DARK_DEAL)
|
||||
.withEncounterTier(MysteryEncounterTier.ROGUE)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: "mad_scientist_m",
|
||||
fileRoot: "mystery-encounters",
|
||||
hasShadow: true,
|
||||
},
|
||||
{
|
||||
spriteKey: "dark_deal_porygon",
|
||||
fileRoot: "mystery-encounters",
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withSceneWaveRangeRequirement(30, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1])
|
||||
.withScenePartySizeRequirement(2, 6) // Must have at least 2 pokemon in party
|
||||
.withCatchAllowed(true)
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.1.selected_dialogue`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.1.selected_message`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// 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, false, true);
|
||||
// Get all the pokemon's held items
|
||||
const modifiers = removedPokemon.getHeldItems().filter(m => !(m instanceof PokemonFormChangeItemModifier));
|
||||
scene.removePokemonFromPlayerParty(removedPokemon);
|
||||
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
encounter.setDialogueToken("pokeName", removedPokemon.getNameToRender());
|
||||
|
||||
// Store removed pokemon types
|
||||
encounter.misc = {
|
||||
removedTypes: removedPokemon.getTypes(),
|
||||
modifiers
|
||||
};
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Give the player 5 Rogue Balls
|
||||
const encounter = scene.currentBattle.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;
|
||||
const bossModifiers: PokemonHeldItemModifier[] = encounter.misc.modifiers;
|
||||
// Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+
|
||||
const roll = randSeedInt(100);
|
||||
const starterTier: number | [number, number] =
|
||||
roll > 65 ? 6 : roll > 15 ? 7 : roll > 5 ? 8 : [9, 10];
|
||||
const bossSpecies = getPokemonSpecies(getRandomSpeciesByStarterTier(starterTier, excludedBosses, bossTypes));
|
||||
const pokemonConfig: EnemyPokemonConfig = {
|
||||
species: bossSpecies,
|
||||
isBoss: true,
|
||||
modifierConfigs: bossModifiers.map(m => {
|
||||
return {
|
||||
modifier: m
|
||||
};
|
||||
})
|
||||
};
|
||||
if (!isNullOrUndefined(bossSpecies.forms) && bossSpecies.forms.length > 0) {
|
||||
pokemonConfig.formIndex = 0;
|
||||
}
|
||||
const config: EnemyPartyConfig = {
|
||||
pokemonConfigs: [pokemonConfig],
|
||||
};
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Leave encounter with no rewards or exp
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
return true;
|
||||
}
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`
|
||||
}
|
||||
])
|
||||
.build();
|
309
src/data/mystery-encounters/encounters/delibirdy-encounter.ts
Normal file
@ -0,0 +1,309 @@
|
||||
import { generateModifierType, leaveEncounterWithoutBattle, selectPokemonForOption, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Species } from "#enums/species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||
import { CombinationPokemonRequirement, HeldItemRequirement, MoneyRequirement } from "../mystery-encounter-requirements";
|
||||
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { HealingBoosterModifier, HiddenAbilityRateBoosterModifier, LevelIncrementBoosterModifier, PokemonHeldItemModifier, PreserveBerryModifier } from "#app/modifier/modifier";
|
||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:delibirdy";
|
||||
|
||||
/** Berries only */
|
||||
const OPTION_2_ALLOWED_MODIFIERS = ["BerryModifier", "PokemonInstantReviveModifier"];
|
||||
|
||||
/** Disallowed items are berries, Reviver Seeds, and Vitamins (form change items and fusion items are not PokemonHeldItemModifiers) */
|
||||
const OPTION_3_DISALLOWED_MODIFIERS = [
|
||||
"BerryModifier",
|
||||
"PokemonInstantReviveModifier",
|
||||
"TerastallizeModifier",
|
||||
"PokemonBaseStatModifier",
|
||||
"PokemonBaseStatTotalModifier"
|
||||
];
|
||||
|
||||
/**
|
||||
* Delibird-y encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3804 | GitHub Issue #3804}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const DelibirdyEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DELIBIRDY)
|
||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withSceneRequirement(new MoneyRequirement(0, 2)) // Must have enough money for it to spawn at the very least
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement( // Must also have either option 2 or 3 available to spawn
|
||||
new HeldItemRequirement(OPTION_2_ALLOWED_MODIFIERS),
|
||||
new HeldItemRequirement(OPTION_3_DISALLOWED_MODIFIERS, 1, true)
|
||||
))
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.DELIBIRD,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
startFrame: 38,
|
||||
scale: 0.94
|
||||
},
|
||||
{
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.DELIBIRD,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
scale: 1.06
|
||||
},
|
||||
{
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.DELIBIRD,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
startFrame: 65,
|
||||
x: 1,
|
||||
y: 5,
|
||||
yShadow: 5
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
}
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
encounter.setDialogueToken("delibirdName", getPokemonSpecies(Species.DELIBIRD).getName());
|
||||
return true;
|
||||
})
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneMoneyRequirement(0, 2) // Must have money to spawn
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
updatePlayerMoney(scene, -(encounter.options[0].requirements[0] as MoneyRequirement).requiredMoney, true, false);
|
||||
return true;
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Give the player an Ability Charm
|
||||
// Check if the player has max stacks of that item already
|
||||
const existing = scene.findModifier(m => m instanceof HiddenAbilityRateBoosterModifier) as HiddenAbilityRateBoosterModifier;
|
||||
|
||||
if (existing && existing.getStackCount() >= existing.getMaxStackCount(scene)) {
|
||||
// At max stacks, give the first party pokemon a Shell Bell instead
|
||||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
||||
} else {
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.ABILITY_CHARM));
|
||||
}
|
||||
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new HeldItemRequirement(OPTION_2_ALLOWED_MODIFIERS))
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.2.select_prompt`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Get Pokemon held items and filter for valid ones
|
||||
const validItems = pokemon.getHeldItems().filter((it) => {
|
||||
return OPTION_2_ALLOWED_MODIFIERS.some(heldItem => it.constructor.name === heldItem);
|
||||
});
|
||||
|
||||
return validItems.map((modifier: PokemonHeldItemModifier) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: modifier.type.name,
|
||||
handler: () => {
|
||||
// Pokemon and item selected
|
||||
encounter.setDialogueToken("chosenItem", modifier.type.name);
|
||||
encounter.misc = {
|
||||
chosenPokemon: pokemon,
|
||||
chosenModifier: modifier,
|
||||
};
|
||||
return true;
|
||||
},
|
||||
};
|
||||
return option;
|
||||
});
|
||||
};
|
||||
|
||||
// Only Pokemon that can gain benefits are above 1/3rd HP with no status
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
// If pokemon meets primary pokemon reqs, it can be selected
|
||||
const meetsReqs = encounter.options[1].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const modifier = encounter.misc.chosenModifier;
|
||||
|
||||
// Give the player a Candy Jar if they gave a Berry, and a Healing Charm for Reviver Seed
|
||||
if (modifier.type.name.includes("Berry")) {
|
||||
// Check if the player has max stacks of that Candy Jar already
|
||||
const existing = scene.findModifier(m => m instanceof LevelIncrementBoosterModifier) as LevelIncrementBoosterModifier;
|
||||
|
||||
if (existing && existing.getStackCount() >= existing.getMaxStackCount(scene)) {
|
||||
// At max stacks, give the first party pokemon a Shell Bell instead
|
||||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
||||
} else {
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.CANDY_JAR));
|
||||
}
|
||||
} else {
|
||||
// Check if the player has max stacks of that 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
|
||||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the modifier if its stacks go to 0
|
||||
modifier.stackCount -= 1;
|
||||
if (modifier.stackCount === 0) {
|
||||
scene.removeModifier(modifier);
|
||||
}
|
||||
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new HeldItemRequirement(OPTION_3_DISALLOWED_MODIFIERS, 1, true))
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Get Pokemon held items and filter for valid ones
|
||||
const validItems = pokemon.getHeldItems().filter((it) => {
|
||||
return !OPTION_3_DISALLOWED_MODIFIERS.some(heldItem => it.constructor.name === heldItem);
|
||||
});
|
||||
|
||||
return validItems.map((modifier: PokemonHeldItemModifier) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: modifier.type.name,
|
||||
handler: () => {
|
||||
// Pokemon and item selected
|
||||
encounter.setDialogueToken("chosenItem", modifier.type.name);
|
||||
encounter.misc = {
|
||||
chosenPokemon: pokemon,
|
||||
chosenModifier: modifier,
|
||||
};
|
||||
return true;
|
||||
},
|
||||
};
|
||||
return option;
|
||||
});
|
||||
};
|
||||
|
||||
// Only Pokemon that can gain benefits are above 1/3rd HP with no status
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
// If pokemon meets primary pokemon reqs, it can be selected
|
||||
const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
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;
|
||||
|
||||
if (existing && existing.getStackCount() >= existing.getMaxStackCount(scene)) {
|
||||
// At max stacks, give the first party pokemon a Shell Bell instead
|
||||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
|
||||
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));
|
||||
}
|
||||
|
||||
// Remove the modifier if its stacks go to 0
|
||||
modifier.stackCount -= 1;
|
||||
if (modifier.stackCount === 0) {
|
||||
scene.removeModifier(modifier);
|
||||
}
|
||||
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.build();
|
@ -0,0 +1,164 @@
|
||||
import {
|
||||
leaveEncounterWithoutBattle,
|
||||
setEncounterRewards,
|
||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { ModifierTypeFunc, modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { randSeedInt } from "#app/utils";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Species } from "#enums/species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, {
|
||||
MysteryEncounterBuilder,
|
||||
} from "../mystery-encounter";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** i18n namespace for encounter */
|
||||
const namespace = "mysteryEncounter:departmentStoreSale";
|
||||
|
||||
/**
|
||||
* Department Store Sale encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3797 | GitHub Issue #3797}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DEPARTMENT_STORE_SALE)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[0], 100)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: "b2w2_lady",
|
||||
fileRoot: "mystery-encounters",
|
||||
hasShadow: true,
|
||||
x: -20,
|
||||
},
|
||||
{
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.FURFROU,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
x: 30,
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose TMs
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 4) {
|
||||
// 2/2/1 weight on TM rarity
|
||||
const roll = randSeedInt(5);
|
||||
if (roll < 2) {
|
||||
modifiers.push(modifierTypes.TM_COMMON);
|
||||
} else if (roll < 4) {
|
||||
modifiers.push(modifierTypes.TM_GREAT);
|
||||
} else {
|
||||
modifiers.push(modifierTypes.TM_ULTRA);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: modifiers, fillRemaining: false, });
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose Vitamins
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 3) {
|
||||
// 2/1 weight on base stat booster vs PP Up
|
||||
const roll = randSeedInt(3);
|
||||
if (roll === 0) {
|
||||
modifiers.push(modifierTypes.PP_UP);
|
||||
} else {
|
||||
modifiers.push(modifierTypes.BASE_STAT_BOOSTER);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: modifiers, fillRemaining: false, });
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose X Items
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 5) {
|
||||
// 4/1 weight on base stat booster vs Dire Hit
|
||||
const roll = randSeedInt(5);
|
||||
if (roll === 0) {
|
||||
modifiers.push(modifierTypes.DIRE_HIT);
|
||||
} else {
|
||||
modifiers.push(modifierTypes.TEMP_STAT_STAGE_BOOSTER);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: modifiers, fillRemaining: false, });
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.4.label`,
|
||||
buttonTooltip: `${namespace}.option.4.tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose Pokeballs
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 4) {
|
||||
// 10/30/20/5 weight on pokeballs
|
||||
const roll = randSeedInt(65);
|
||||
if (roll < 10) {
|
||||
modifiers.push(modifierTypes.POKEBALL);
|
||||
} else if (roll < 40) {
|
||||
modifiers.push(modifierTypes.GREAT_BALL);
|
||||
} else if (roll < 60) {
|
||||
modifiers.push(modifierTypes.ULTRA_BALL);
|
||||
} else {
|
||||
modifiers.push(modifierTypes.ROGUE_BALL);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: modifiers, fillRemaining: false, });
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
}
|
||||
])
|
||||
.build();
|
235
src/data/mystery-encounters/encounters/field-trip-encounter.ts
Normal file
@ -0,0 +1,235 @@
|
||||
import { MoveCategory } from "#app/data/move";
|
||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { generateModifierTypeOption, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { Stat } from "#enums/stat";
|
||||
import i18next from "i18next";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:fieldTrip";
|
||||
|
||||
/**
|
||||
* Field Trip encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3794 | GitHub Issue #3794}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const FieldTripEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.FIELD_TRIP)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: "preschooler_m",
|
||||
fileRoot: "trainer",
|
||||
hasShadow: true,
|
||||
},
|
||||
{
|
||||
spriteKey: "teacher",
|
||||
fileRoot: "mystery-encounters",
|
||||
hasShadow: true,
|
||||
},
|
||||
{
|
||||
spriteKey: "preschooler_f",
|
||||
fileRoot: "trainer",
|
||||
hasShadow: true,
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.second_option_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Return the options for Pokemon move valid for this option
|
||||
return pokemon.moveset.map((move: PokemonMove) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: move.getName(),
|
||||
handler: () => {
|
||||
// Pokemon and move selected
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}.physical`));
|
||||
pokemonAndMoveChosen(scene, pokemon, move, MoveCategory.PHYSICAL);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
return option;
|
||||
});
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ATK])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.DEF])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||
}
|
||||
|
||||
leaveEncounterWithoutBattle(scene, !encounter.misc.correctMove);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.second_option_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Return the options for Pokemon move valid for this option
|
||||
return pokemon.moveset.map((move: PokemonMove) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: move.getName(),
|
||||
handler: () => {
|
||||
// Pokemon and move selected
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}.special`));
|
||||
pokemonAndMoveChosen(scene, pokemon, move, MoveCategory.SPECIAL);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
return option;
|
||||
});
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPATK])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPDEF])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||
}
|
||||
|
||||
leaveEncounterWithoutBattle(scene, !encounter.misc.correctMove);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.second_option_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Return the options for Pokemon move valid for this option
|
||||
return pokemon.moveset.map((move: PokemonMove) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: move.getName(),
|
||||
handler: () => {
|
||||
// Pokemon and move selected
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}.status`));
|
||||
pokemonAndMoveChosen(scene, pokemon, move, MoveCategory.STATUS);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
return option;
|
||||
});
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ACC])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.GREAT_BALL)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.IV_SCANNER)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||
}
|
||||
|
||||
leaveEncounterWithoutBattle(scene, !encounter.misc.correctMove);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
|
||||
function pokemonAndMoveChosen(scene: BattleScene, pokemon: PlayerPokemon, move: PokemonMove, correctMoveCategory: MoveCategory) {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const correctMove = move.getMove().category === correctMoveCategory;
|
||||
encounter.setDialogueToken("pokeName", pokemon.getNameToRender());
|
||||
encounter.setDialogueToken("move", move.getName());
|
||||
if (!correctMove) {
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.incorrect`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.incorrect_exp`,
|
||||
},
|
||||
];
|
||||
setEncounterExp(scene, scene.getParty().map((p) => p.id), 50);
|
||||
} else {
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.correct`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.correct_exp`,
|
||||
},
|
||||
];
|
||||
setEncounterExp(scene, [pokemon.id], 100);
|
||||
}
|
||||
encounter.misc = {
|
||||
correctMove: correctMove,
|
||||
};
|
||||
}
|
@ -0,0 +1,255 @@
|
||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { EnemyPartyConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { AttackTypeBoosterModifierType, modifierTypes, } from "#app/modifier/modifier-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { TypeRequirement } from "../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 { 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 { 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";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:fieryFallout";
|
||||
|
||||
/**
|
||||
* Damage percentage taken when suffering the heat.
|
||||
* Can be a number between `0` - `100`.
|
||||
* The higher the more damage taken (100% = instant KO).
|
||||
*/
|
||||
const DAMAGE_PERCENTAGE: number = 20;
|
||||
|
||||
/**
|
||||
* Fiery Fallout encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3814 | GitHub Issue #3814}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const FieryFalloutEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.FIERY_FALLOUT)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(40, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1])
|
||||
.withCatchAllowed(true)
|
||||
.withIntroSpriteConfigs([]) // Set in onInit()
|
||||
.withAnimations(EncounterAnim.MAGMA_BG, EncounterAnim.MAGMA_SPOUT)
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
// Calculate boss mons
|
||||
const volcaronaSpecies = getPokemonSpecies(Species.VOLCARONA);
|
||||
const config: EnemyPartyConfig = {
|
||||
pokemonConfigs: [
|
||||
{
|
||||
species: volcaronaSpecies,
|
||||
isBoss: false,
|
||||
gender: Gender.MALE
|
||||
},
|
||||
{
|
||||
species: volcaronaSpecies,
|
||||
isBoss: false,
|
||||
gender: Gender.FEMALE
|
||||
}
|
||||
],
|
||||
doubleBattle: true,
|
||||
disableSwitch: true
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
|
||||
// Load hidden Volcarona sprites
|
||||
encounter.spriteConfigs = [
|
||||
{
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.VOLCARONA,
|
||||
repeat: true,
|
||||
hidden: true,
|
||||
hasShadow: true,
|
||||
x: -20,
|
||||
startFrame: 20
|
||||
},
|
||||
{
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.VOLCARONA,
|
||||
repeat: true,
|
||||
hidden: true,
|
||||
hasShadow: true,
|
||||
x: 20
|
||||
},
|
||||
];
|
||||
|
||||
// Load animations/sfx for Volcarona moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.FIRE_SPIN, Moves.QUIVER_DANCE]);
|
||||
|
||||
scene.arena.trySetWeather(WeatherType.SUNNY, true);
|
||||
|
||||
encounter.setDialogueToken("volcaronaName", getPokemonSpecies(Species.VOLCARONA).getName());
|
||||
|
||||
return true;
|
||||
})
|
||||
.withOnVisualsStart((scene: BattleScene) => {
|
||||
// Play animations
|
||||
const background = new EncounterBattleAnim(EncounterAnim.MAGMA_BG, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
background.playWithoutTargets(scene, 200, 70, 2, 3);
|
||||
const animation = new EncounterBattleAnim(EncounterAnim.MAGMA_SPOUT, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
animation.playWithoutTargets(scene, 80, 100, 2);
|
||||
scene.time.delayedCall(600, () => {
|
||||
animation.playWithoutTargets(scene, -20, 100, 2);
|
||||
});
|
||||
scene.time.delayedCall(1200, () => {
|
||||
animation.playWithoutTargets(scene, 140, 150, 2);
|
||||
});
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, () => giveLeadPokemonCharcoal(scene));
|
||||
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
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]);
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Damage non-fire types and burn 1 random non-fire type member
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const nonFireTypes = scene.getParty().filter((p) => p.isAllowedInBattle() && !p.getTypes().includes(Type.FIRE));
|
||||
|
||||
for (const pkm of nonFireTypes) {
|
||||
const percentage = DAMAGE_PERCENTAGE / 100;
|
||||
const damage = Math.floor(pkm.getMaxHp() * percentage);
|
||||
applyDamageToPokemon(scene, pkm, damage);
|
||||
}
|
||||
|
||||
// Burn random member
|
||||
const burnable = nonFireTypes.filter(p => isNullOrUndefined(p.status) || isNullOrUndefined(p.status!.effect) || p.status?.effect === StatusEffect.BURN);
|
||||
if (burnable?.length > 0) {
|
||||
const roll = randSeedInt(burnable.length);
|
||||
const chosenPokemon = burnable[roll];
|
||||
if (chosenPokemon.trySetStatus(StatusEffect.BURN)) {
|
||||
// Burn applied
|
||||
encounter.setDialogueToken("burnedPokemon", chosenPokemon.getNameToRender());
|
||||
queueEncounterMessage(scene, `${namespace}.option.2.target_burned`);
|
||||
}
|
||||
}
|
||||
|
||||
// No rewards
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
}
|
||||
)
|
||||
.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
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
transitionMysteryEncounterIntroVisuals(scene, false, false, 2000);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Fire types help calm the Volcarona
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
transitionMysteryEncounterIntroVisuals(scene);
|
||||
setEncounterRewards(scene,
|
||||
{ fillRemaining: true },
|
||||
undefined,
|
||||
() => {
|
||||
giveLeadPokemonCharcoal(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);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
|
||||
function giveLeadPokemonCharcoal(scene: BattleScene) {
|
||||
// Give first party pokemon Charcoal 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`);
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import {
|
||||
EnemyPartyConfig,
|
||||
initBattleWithEnemyConfig,
|
||||
leaveEncounterWithoutBattle, setEncounterExp,
|
||||
setEncounterRewards
|
||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||
import Pokemon, { EnemyPokemon } from "#app/field/pokemon";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import {
|
||||
getPartyLuckValue,
|
||||
getPlayerModifierTypeOptions,
|
||||
ModifierPoolType,
|
||||
ModifierTypeOption,
|
||||
regenerateModifierPoolThresholds,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { TrainerSlot } from "#app/data/trainer-config";
|
||||
import { getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { randSeedInt } from "#app/utils";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:fightOrFlight";
|
||||
|
||||
/**
|
||||
* Fight or Flight encounter.
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3795 | GitHub Issue #3795}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const FightOrFlightEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.FIGHT_OR_FLIGHT)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withCatchAllowed(true)
|
||||
.withHideWildIntroMessage(true)
|
||||
.withIntroSpriteConfigs([]) // Set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
// Calculate boss mon
|
||||
const level = (scene.currentBattle.enemyLevels?.[0] ?? scene.currentBattle.waveIndex) + Math.max(Math.round((scene.currentBattle.waveIndex / 10)), 0);
|
||||
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
||||
encounter.setDialogueToken("enemyPokemon", bossPokemon.getNameToRender());
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveMultiplier: 1,
|
||||
pokemonConfigs: [{
|
||||
level: level,
|
||||
species: bossSpecies,
|
||||
dataSource: new PokemonData(bossPokemon),
|
||||
isBoss: true,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.stat_boost`);
|
||||
// Randomly boost 1 stat 2 stages
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [randSeedInt(5)], 2));
|
||||
}
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
|
||||
// Calculate item
|
||||
// Waves 10-40 GREAT, 60-120 ULTRA, 120-160 ROGUE, 160-180 MASTER
|
||||
const tier =
|
||||
scene.currentBattle.waveIndex > 160
|
||||
? ModifierTier.MASTER
|
||||
: scene.currentBattle.waveIndex > 120
|
||||
? ModifierTier.ROGUE
|
||||
: scene.currentBattle.waveIndex > 40
|
||||
? ModifierTier.ULTRA
|
||||
: ModifierTier.GREAT;
|
||||
regenerateModifierPoolThresholds(scene.getParty(), ModifierPoolType.PLAYER, 0);
|
||||
let item: ModifierTypeOption | null = null;
|
||||
// TMs and Candy Jar excluded from possible rewards as they're too swingy in value for a singular item reward
|
||||
while (!item || item.type.id.includes("TM_") || item.type.id === "CANDY_JAR") {
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier], allowLuckUpgrades: false })[0];
|
||||
}
|
||||
encounter.setDialogueToken("itemName", item.type.name);
|
||||
encounter.misc = item;
|
||||
|
||||
const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(bossPokemon);
|
||||
encounter.spriteConfigs = [
|
||||
{
|
||||
spriteKey: item.type.iconImage,
|
||||
fileRoot: "items",
|
||||
hasShadow: false,
|
||||
x: 35,
|
||||
y: -5,
|
||||
scale: 0.75,
|
||||
isItem: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: spriteKey,
|
||||
fileRoot: fileRoot,
|
||||
hasShadow: true,
|
||||
tint: 0.25,
|
||||
x: -5,
|
||||
repeat: true,
|
||||
isPokemon: true
|
||||
},
|
||||
];
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
// Pokemon will randomly boost 1 stat by 2 stages
|
||||
const item = scene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]);
|
||||
}
|
||||
)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`
|
||||
}
|
||||
]
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Pick steal
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const item = scene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
|
||||
// Use primaryPokemon to execute the thievery
|
||||
const primaryPokemon = encounter.options[1].primaryPokemon!;
|
||||
setEncounterExp(scene, primaryPokemon.id, encounter.enemyPartyConfigs[0].pokemonConfigs![0].species.baseExp);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Leave encounter with no rewards or exp
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
return true;
|
||||
}
|
||||
)
|
||||
.build();
|