diff --git a/.env b/.env index fb05bbc8f2b..076cf6fbaf5 100644 --- a/.env +++ b/.env @@ -1,3 +1,4 @@ VITE_BYPASS_LOGIN=0 VITE_BYPASS_TUTORIAL=0 +VITE_SERVER_URL=http://localhost:8001 VITE_MOCK_API=0 \ No newline at end of file diff --git a/.env.development b/.env.development index bac1e696e94..453e64ce9e3 100644 --- a/.env.development +++ b/.env.development @@ -1,3 +1,4 @@ VITE_BYPASS_LOGIN=1 VITE_BYPASS_TUTORIAL=0 +VITE_SERVER_URL=http://localhost:8001 VITE_MOCK_API=1 \ No newline at end of file diff --git a/README.md b/README.md index 9e88163f2d7..839bfa3ae45 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,14 @@ Check out [Github Issues](https://github.com/pagefaultgames/pokerogue/issues) to - Keisuke Ito - Arata Iiyoshi - Atsuhiro Ishizuna + - Pokémon HeartGold/SoulSilver - Pokémon Black/White 2 + - Pokémon X/Y + - Pokémon Omega Ruby/Alpha Sapphire + - Pokémon Sun/Moon + - Pokémon Ultra Sun/Ultra Moon + - Pokémon Sword/Shield + - Pokémon Scarlet/Violet - Firel (Custom Metropolis and Laboratory biome music) - Lmz (Custom Jungle biome music) diff --git a/index.css b/index.css index c0791259002..1b2f0211692 100644 --- a/index.css +++ b/index.css @@ -146,13 +146,13 @@ body { margin-left: 10%; } -#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_DISPLAY']):not([data-ui-mode='SETTINGS_AUDIO']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadRectBtnContainer > .apadSqBtn, -#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_DISPLAY']):not([data-ui-mode='SETTINGS_AUDIO']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadSqBtnContainer +#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_DISPLAY']):not([data-ui-mode='SETTINGS_AUDIO']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadRectBtnContainer > .apadSqBtn:not(.apadBattle), +#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_DISPLAY']):not([data-ui-mode='SETTINGS_AUDIO']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadSqBtnContainer > .apadSqBtn:not(.apadBattle) { display: none; } -#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']) #apad .apadBattle { +#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']):not([data-ui-mode='MODIFIER_SELECT']) #apad .apadBattle { display: none; } diff --git a/package.json b/package.json index 69997b2a094..c0191e37af6 100644 --- a/package.json +++ b/package.json @@ -1,61 +1,62 @@ { - "name": "pokemon-rogue-battle", - "private": true, - "version": "1.0.4", - "type": "module", - "scripts": { - "start": "vite", - "start:dev": "vite --mode development", - "build": "vite build", - "preview": "vite preview", - "test": "vitest run", - "test:cov": "vitest run --coverage", - "test:watch": "vitest watch --coverage", - "eslint": "eslint --fix .", - "eslint-ci": "eslint .", - "docs": "typedoc" - }, - "devDependencies": { - "@eslint/js": "^9.3.0", - "@types/node": "^20.12.13", - "@typescript-eslint/eslint-plugin": "^7.10.0", - "@typescript-eslint/parser": "^7.10.0", - "@vitest/coverage-istanbul": "^1.4.0", - "axios": "^1.6.2", - "axios-cache-interceptor": "^1.3.2", - "eslint": "^8.57.0", - "eslint-plugin-import": "^2.29.1", - "jsdom": "^24.0.0", - "json-beautify": "^1.1.1", - "lefthook": "^1.6.12", + "name": "pokemon-rogue-battle", + "private": true, + "version": "1.0.4", + "type": "module", + "scripts": { + "start": "vite", + "start:dev": "vite --mode development", + "build": "vite build", + "preview": "vite preview", + "test": "vitest run", + "test:cov": "vitest run --coverage", + "test:watch": "vitest watch --coverage", + "test:silent": "vitest run --silent", + "eslint": "eslint --fix .", + "eslint-ci": "eslint .", + "docs": "typedoc" + }, + "devDependencies": { + "@eslint/js": "^9.3.0", + "@types/node": "^20.12.13", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", + "@vitest/coverage-istanbul": "^1.4.0", + "axios": "^1.6.2", + "axios-cache-interceptor": "^1.3.2", + "eslint": "^8.57.0", + "eslint-plugin-import": "^2.29.1", + "jsdom": "^24.0.0", + "json-beautify": "^1.1.1", + "lefthook": "^1.6.12", "msw": "^2.3.1", - "phaser3spectorjs": "^0.0.8", - "pokenode-ts": "^1.20.0", - "typedoc": "^0.25.13", - "typescript": "^5.4.5", - "typescript-eslint": "^7.10.0", - "vite": "^4.5.0", - "vite-plugin-fs": "^0.4.4", - "vitest": "^1.4.0", - "vitest-canvas-mock": "^0.3.3" - }, - "dependencies": { - "@material/material-color-utilities": "^0.2.7", - "crypto-js": "^4.2.0", - "i18next": "^23.11.1", - "i18next-browser-languagedetector": "^7.2.1", - "i18next-korean-postposition-processor": "^1.0.0", - "json-stable-stringify": "^1.1.0", - "phaser": "^3.70.0", - "phaser3-rex-plugins": "^1.1.84" - }, - "engines": { - "node": ">=20.0.0" - }, - "imports": { - "#app": "./src/main.js", - "#app/*": "./src/*" - }, + "phaser3spectorjs": "^0.0.8", + "pokenode-ts": "^1.20.0", + "typedoc": "^0.25.13", + "typescript": "^5.4.5", + "typescript-eslint": "^7.10.0", + "vite": "^4.5.0", + "vite-plugin-fs": "^0.4.4", + "vitest": "^1.4.0", + "vitest-canvas-mock": "^0.3.3" + }, + "dependencies": { + "@material/material-color-utilities": "^0.2.7", + "crypto-js": "^4.2.0", + "i18next": "^23.11.1", + "i18next-browser-languagedetector": "^7.2.1", + "i18next-korean-postposition-processor": "^1.0.0", + "json-stable-stringify": "^1.1.0", + "phaser": "^3.70.0", + "phaser3-rex-plugins": "^1.1.84" + }, + "engines": { + "node": ">=20.0.0" + }, + "imports": { + "#app": "./src/main.js", + "#app/*": "./src/*" + }, "msw": { "workerDirectory": [ "public" diff --git a/public/audio/bgm/battle_alola_champion.mp3 b/public/audio/bgm/battle_alola_champion.mp3 new file mode 100644 index 00000000000..94173ca69fd Binary files /dev/null and b/public/audio/bgm/battle_alola_champion.mp3 differ diff --git a/public/audio/bgm/battle_alola_elite.mp3 b/public/audio/bgm/battle_alola_elite.mp3 new file mode 100644 index 00000000000..d87a4a89968 Binary files /dev/null and b/public/audio/bgm/battle_alola_elite.mp3 differ diff --git a/public/audio/bgm/battle_bb_elite.mp3 b/public/audio/bgm/battle_bb_elite.mp3 new file mode 100644 index 00000000000..e0ec0dbd518 Binary files /dev/null and b/public/audio/bgm/battle_bb_elite.mp3 differ diff --git a/public/audio/bgm/battle_champion_geeta.mp3 b/public/audio/bgm/battle_champion_geeta.mp3 new file mode 100644 index 00000000000..1b654e33ee2 Binary files /dev/null and b/public/audio/bgm/battle_champion_geeta.mp3 differ diff --git a/public/audio/bgm/battle_champion_kieran.mp3 b/public/audio/bgm/battle_champion_kieran.mp3 new file mode 100644 index 00000000000..e43a1c904cd Binary files /dev/null and b/public/audio/bgm/battle_champion_kieran.mp3 differ diff --git a/public/audio/bgm/battle_champion_nemona.mp3 b/public/audio/bgm/battle_champion_nemona.mp3 new file mode 100644 index 00000000000..9d835030e49 Binary files /dev/null and b/public/audio/bgm/battle_champion_nemona.mp3 differ diff --git a/public/audio/bgm/battle_galar_champion.mp3 b/public/audio/bgm/battle_galar_champion.mp3 new file mode 100644 index 00000000000..9dd43f9bbc8 Binary files /dev/null and b/public/audio/bgm/battle_galar_champion.mp3 differ diff --git a/public/audio/bgm/battle_galar_elite.mp3 b/public/audio/bgm/battle_galar_elite.mp3 new file mode 100644 index 00000000000..34587edcbd1 Binary files /dev/null and b/public/audio/bgm/battle_galar_elite.mp3 differ diff --git a/public/audio/bgm/battle_galar_gym.mp3 b/public/audio/bgm/battle_galar_gym.mp3 new file mode 100644 index 00000000000..a10b284cf4b Binary files /dev/null and b/public/audio/bgm/battle_galar_gym.mp3 differ diff --git a/public/audio/bgm/battle_hoenn_elite.mp3 b/public/audio/bgm/battle_hoenn_elite.mp3 new file mode 100644 index 00000000000..7d352d4332a Binary files /dev/null and b/public/audio/bgm/battle_hoenn_elite.mp3 differ diff --git a/public/audio/bgm/battle_kalos_champion.mp3 b/public/audio/bgm/battle_kalos_champion.mp3 new file mode 100644 index 00000000000..c9dd6b80133 Binary files /dev/null and b/public/audio/bgm/battle_kalos_champion.mp3 differ diff --git a/public/audio/bgm/battle_kalos_elite.mp3 b/public/audio/bgm/battle_kalos_elite.mp3 new file mode 100644 index 00000000000..f4a0181544d Binary files /dev/null and b/public/audio/bgm/battle_kalos_elite.mp3 differ diff --git a/public/audio/bgm/battle_kalos_gym.mp3 b/public/audio/bgm/battle_kalos_gym.mp3 new file mode 100644 index 00000000000..9031274519f Binary files /dev/null and b/public/audio/bgm/battle_kalos_gym.mp3 differ diff --git a/public/audio/bgm/battle_legendary_arceus.mp3 b/public/audio/bgm/battle_legendary_arceus.mp3 new file mode 100644 index 00000000000..03dab3878f2 Binary files /dev/null and b/public/audio/bgm/battle_legendary_arceus.mp3 differ diff --git a/public/audio/bgm/battle_legendary_birds_galar.mp3 b/public/audio/bgm/battle_legendary_birds_galar.mp3 new file mode 100644 index 00000000000..79bedb5c500 Binary files /dev/null and b/public/audio/bgm/battle_legendary_birds_galar.mp3 differ diff --git a/public/audio/bgm/battle_legendary_calyrex.mp3 b/public/audio/bgm/battle_legendary_calyrex.mp3 new file mode 100644 index 00000000000..8d22a5df963 Binary files /dev/null and b/public/audio/bgm/battle_legendary_calyrex.mp3 differ diff --git a/public/audio/bgm/battle_legendary_deoxys.mp3 b/public/audio/bgm/battle_legendary_deoxys.mp3 new file mode 100644 index 00000000000..da91a5f76bc Binary files /dev/null and b/public/audio/bgm/battle_legendary_deoxys.mp3 differ diff --git a/public/audio/bgm/battle_legendary_dia_pal.mp3 b/public/audio/bgm/battle_legendary_dia_pal.mp3 new file mode 100644 index 00000000000..07998098afe Binary files /dev/null and b/public/audio/bgm/battle_legendary_dia_pal.mp3 differ diff --git a/public/audio/bgm/battle_legendary_dusk_dawn.mp3 b/public/audio/bgm/battle_legendary_dusk_dawn.mp3 new file mode 100644 index 00000000000..20b883a4ca7 Binary files /dev/null and b/public/audio/bgm/battle_legendary_dusk_dawn.mp3 differ diff --git a/public/audio/bgm/battle_legendary_entei.mp3 b/public/audio/bgm/battle_legendary_entei.mp3 new file mode 100644 index 00000000000..30d1f87748c Binary files /dev/null and b/public/audio/bgm/battle_legendary_entei.mp3 differ diff --git a/public/audio/bgm/battle_legendary_giratina.mp3 b/public/audio/bgm/battle_legendary_giratina.mp3 new file mode 100644 index 00000000000..87674e003ca Binary files /dev/null and b/public/audio/bgm/battle_legendary_giratina.mp3 differ diff --git a/public/audio/bgm/battle_legendary_glas_spec.mp3 b/public/audio/bgm/battle_legendary_glas_spec.mp3 new file mode 100644 index 00000000000..52988510ea6 Binary files /dev/null and b/public/audio/bgm/battle_legendary_glas_spec.mp3 differ diff --git a/public/audio/bgm/battle_legendary_gro_kyo.mp3 b/public/audio/bgm/battle_legendary_gro_kyo.mp3 new file mode 100644 index 00000000000..b3401da3f6e Binary files /dev/null and b/public/audio/bgm/battle_legendary_gro_kyo.mp3 differ diff --git a/public/audio/bgm/battle_legendary_ho_oh.mp3 b/public/audio/bgm/battle_legendary_ho_oh.mp3 new file mode 100644 index 00000000000..46740297f77 Binary files /dev/null and b/public/audio/bgm/battle_legendary_ho_oh.mp3 differ diff --git a/public/audio/bgm/battle_legendary_kanto.mp3 b/public/audio/bgm/battle_legendary_kanto.mp3 new file mode 100644 index 00000000000..0b9946ec9fe Binary files /dev/null and b/public/audio/bgm/battle_legendary_kanto.mp3 differ diff --git a/public/audio/bgm/battle_legendary_lake_trio.mp3 b/public/audio/bgm/battle_legendary_lake_trio.mp3 new file mode 100644 index 00000000000..dc6bb08d13f Binary files /dev/null and b/public/audio/bgm/battle_legendary_lake_trio.mp3 differ diff --git a/public/audio/bgm/battle_legendary_loyal_three.mp3 b/public/audio/bgm/battle_legendary_loyal_three.mp3 new file mode 100644 index 00000000000..d753e58a0a7 Binary files /dev/null and b/public/audio/bgm/battle_legendary_loyal_three.mp3 differ diff --git a/public/audio/bgm/battle_legendary_lugia.mp3 b/public/audio/bgm/battle_legendary_lugia.mp3 new file mode 100644 index 00000000000..37031c8a642 Binary files /dev/null and b/public/audio/bgm/battle_legendary_lugia.mp3 differ diff --git a/public/audio/bgm/battle_legendary_ogerpon.mp3 b/public/audio/bgm/battle_legendary_ogerpon.mp3 new file mode 100644 index 00000000000..2ac0d9756a8 Binary files /dev/null and b/public/audio/bgm/battle_legendary_ogerpon.mp3 differ diff --git a/public/audio/bgm/battle_legendary_pecharunt.mp3 b/public/audio/bgm/battle_legendary_pecharunt.mp3 new file mode 100644 index 00000000000..48f205d97d1 Binary files /dev/null and b/public/audio/bgm/battle_legendary_pecharunt.mp3 differ diff --git a/public/audio/bgm/battle_legendary_raikou.mp3 b/public/audio/bgm/battle_legendary_raikou.mp3 new file mode 100644 index 00000000000..8daa7083faa Binary files /dev/null and b/public/audio/bgm/battle_legendary_raikou.mp3 differ diff --git a/public/audio/bgm/battle_legendary_rayquaza.mp3 b/public/audio/bgm/battle_legendary_rayquaza.mp3 new file mode 100644 index 00000000000..843596779bd Binary files /dev/null and b/public/audio/bgm/battle_legendary_rayquaza.mp3 differ diff --git a/public/audio/bgm/battle_legendary_regis.mp3 b/public/audio/bgm/battle_legendary_regis_g5.mp3 similarity index 100% rename from public/audio/bgm/battle_legendary_regis.mp3 rename to public/audio/bgm/battle_legendary_regis_g5.mp3 diff --git a/public/audio/bgm/battle_legendary_regis_g6.mp3 b/public/audio/bgm/battle_legendary_regis_g6.mp3 new file mode 100644 index 00000000000..ebe1a44d18a Binary files /dev/null and b/public/audio/bgm/battle_legendary_regis_g6.mp3 differ diff --git a/public/audio/bgm/battle_legendary_ruinous.mp3 b/public/audio/bgm/battle_legendary_ruinous.mp3 new file mode 100644 index 00000000000..dc1aeeaee26 Binary files /dev/null and b/public/audio/bgm/battle_legendary_ruinous.mp3 differ diff --git a/public/audio/bgm/battle_legendary_sinnoh.mp3 b/public/audio/bgm/battle_legendary_sinnoh.mp3 new file mode 100644 index 00000000000..6332a3e1cc2 Binary files /dev/null and b/public/audio/bgm/battle_legendary_sinnoh.mp3 differ diff --git a/public/audio/bgm/battle_legendary_sol_lun.mp3 b/public/audio/bgm/battle_legendary_sol_lun.mp3 new file mode 100644 index 00000000000..4aa9d5111b8 Binary files /dev/null and b/public/audio/bgm/battle_legendary_sol_lun.mp3 differ diff --git a/public/audio/bgm/battle_legendary_suicune.mp3 b/public/audio/bgm/battle_legendary_suicune.mp3 new file mode 100644 index 00000000000..7e7e4901386 Binary files /dev/null and b/public/audio/bgm/battle_legendary_suicune.mp3 differ diff --git a/public/audio/bgm/battle_legendary_tapu.mp3 b/public/audio/bgm/battle_legendary_tapu.mp3 new file mode 100644 index 00000000000..7f251a387a2 Binary files /dev/null and b/public/audio/bgm/battle_legendary_tapu.mp3 differ diff --git a/public/audio/bgm/battle_legendary_terapagos.mp3 b/public/audio/bgm/battle_legendary_terapagos.mp3 new file mode 100644 index 00000000000..b820d7dba6a Binary files /dev/null and b/public/audio/bgm/battle_legendary_terapagos.mp3 differ diff --git a/public/audio/bgm/battle_legendary_ub.mp3 b/public/audio/bgm/battle_legendary_ub.mp3 new file mode 100644 index 00000000000..7a6bdb3a678 Binary files /dev/null and b/public/audio/bgm/battle_legendary_ub.mp3 differ diff --git a/public/audio/bgm/battle_legendary_ultra_nec.mp3 b/public/audio/bgm/battle_legendary_ultra_nec.mp3 new file mode 100644 index 00000000000..63d8b0fa505 Binary files /dev/null and b/public/audio/bgm/battle_legendary_ultra_nec.mp3 differ diff --git a/public/audio/bgm/battle_legendary_xern_yvel.mp3 b/public/audio/bgm/battle_legendary_xern_yvel.mp3 new file mode 100644 index 00000000000..856bebb0f61 Binary files /dev/null and b/public/audio/bgm/battle_legendary_xern_yvel.mp3 differ diff --git a/public/audio/bgm/battle_legendary_zac_zam.mp3 b/public/audio/bgm/battle_legendary_zac_zam.mp3 new file mode 100644 index 00000000000..6725625bedf Binary files /dev/null and b/public/audio/bgm/battle_legendary_zac_zam.mp3 differ diff --git a/public/audio/bgm/battle_paldea_elite.mp3 b/public/audio/bgm/battle_paldea_elite.mp3 new file mode 100644 index 00000000000..9a598dfaf64 Binary files /dev/null and b/public/audio/bgm/battle_paldea_elite.mp3 differ diff --git a/public/audio/bgm/battle_paldea_gym.mp3 b/public/audio/bgm/battle_paldea_gym.mp3 new file mode 100644 index 00000000000..eb9a19bacfe Binary files /dev/null and b/public/audio/bgm/battle_paldea_gym.mp3 differ diff --git a/public/audio/bgm/battle_elite.mp3 b/public/audio/bgm/battle_unova_elite.mp3 similarity index 100% rename from public/audio/bgm/battle_elite.mp3 rename to public/audio/bgm/battle_unova_elite.mp3 diff --git a/public/images/pokemon/133-partner.json b/public/images/pokemon/133-partner.json new file mode 100644 index 00000000000..f53a88c52a5 --- /dev/null +++ b/public/images/pokemon/133-partner.json @@ -0,0 +1,2834 @@ +{ + "textures": [ + { + "image": "133-partner.png", + "format": "RGBA8888", + "size": { + "w": 245, + "h": 245 + }, + "scale": 1, + "frames": [ + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 0, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 0, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 35, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 35, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 70, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 70, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 105, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 105, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 36, + "h": 45 + }, + "frame": { + "x": 0, + "y": 44, + "w": 36, + "h": 45 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 34, + "h": 45 + }, + "frame": { + "x": 36, + "y": 44, + "w": 34, + "h": 45 + } + }, + { + "filename": "0126.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 70, + "y": 44, + "w": 44, + "h": 45 + } + }, + { + "filename": "0127.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 70, + "y": 44, + "w": 44, + "h": 45 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 0, + "y": 89, + "w": 36, + "h": 46 + } + }, + { + "filename": "0125.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 36, + "y": 89, + "w": 44, + "h": 46 + } + }, + { + "filename": "0128.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 80, + "y": 91, + "w": 44, + "h": 46 + } + }, + { + "filename": "0129.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 80, + "y": 91, + "w": 44, + "h": 46 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0118.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0119.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 42, + "y": 135, + "w": 38, + "h": 47 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 42, + "y": 135, + "w": 38, + "h": 47 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 164, + "y": 138, + "w": 38, + "h": 47 + } + }, + { + "filename": "0117.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 164, + "y": 138, + "w": 38, + "h": 47 + } + }, + { + "filename": "0120.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 202, + "y": 138, + "w": 41, + "h": 47 + } + }, + { + "filename": "0121.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 182, + "w": 42, + "h": 47 + } + }, + { + "filename": "0122.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 182, + "w": 42, + "h": 47 + } + }, + { + "filename": "0123.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 44, + "h": 47 + }, + "frame": { + "x": 42, + "y": 184, + "w": 44, + "h": 47 + } + }, + { + "filename": "0124.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 44, + "h": 47 + }, + "frame": { + "x": 42, + "y": 184, + "w": 44, + "h": 47 + } + }, + { + "filename": "0130.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 44, + "h": 47 + }, + "frame": { + "x": 86, + "y": 185, + "w": 44, + "h": 47 + } + }, + { + "filename": "0131.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 130, + "y": 185, + "w": 42, + "h": 47 + } + }, + { + "filename": "0132.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 130, + "y": 185, + "w": 42, + "h": 47 + } + }, + { + "filename": "0133.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 172, + "y": 185, + "w": 41, + "h": 47 + } + }, + { + "filename": "0134.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 172, + "y": 185, + "w": 41, + "h": 47 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:a12f810e0c533df6c81afe00a33144eb:fd50f6a2654aabba8f54e3bb2ba922b1:4e938f9dc8bce1cd7822677c800d242b$" + } +} diff --git a/public/images/pokemon/133-partner.png b/public/images/pokemon/133-partner.png new file mode 100644 index 00000000000..b8b1c2a4070 Binary files /dev/null and b/public/images/pokemon/133-partner.png differ diff --git a/public/images/pokemon/25-partner.json b/public/images/pokemon/25-partner.json new file mode 100644 index 00000000000..cce520937e9 --- /dev/null +++ b/public/images/pokemon/25-partner.json @@ -0,0 +1,2456 @@ +{ + "textures": [ + { + "image": "25-partner.png", + "format": "RGBA8888", + "size": { + "w": 315, + "h": 315 + }, + "scale": 1, + "frames": [ + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 0, + "y": 0, + "w": 46, + "h": 46 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 0, + "y": 0, + "w": 46, + "h": 46 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 46, + "w": 50, + "h": 43 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 46, + "w": 50, + "h": 43 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 46, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 46, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 45, + "h": 46 + }, + "frame": { + "x": 50, + "y": 43, + "w": 45, + "h": 46 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 45, + "h": 46 + }, + "frame": { + "x": 50, + "y": 43, + "w": 45, + "h": 46 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 45, + "h": 46 + }, + "frame": { + "x": 50, + "y": 43, + "w": 45, + "h": 46 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 95, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 95, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 96, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 96, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 138, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 138, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 145, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 145, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 181, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 181, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 194, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 194, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 224, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 224, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 243, + "y": 0, + "w": 48, + "h": 43 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 243, + "y": 0, + "w": 48, + "h": 43 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 267, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 267, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 0, + "y": 89, + "w": 49, + "h": 44 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 0, + "y": 89, + "w": 49, + "h": 44 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 49, + "y": 89, + "w": 49, + "h": 44 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 49, + "y": 89, + "w": 49, + "h": 44 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 98, + "y": 89, + "w": 43, + "h": 46 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 98, + "y": 89, + "w": 43, + "h": 46 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 43, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 43, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 141, + "y": 89, + "w": 43, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 141, + "y": 89, + "w": 43, + "h": 46 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 184, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 184, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 226, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 226, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 268, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 268, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 86, + "y": 135, + "w": 49, + "h": 44 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 86, + "y": 135, + "w": 49, + "h": 44 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 135, + "y": 135, + "w": 49, + "h": 44 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 135, + "y": 135, + "w": 49, + "h": 44 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 184, + "y": 135, + "w": 42, + "h": 46 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 184, + "y": 135, + "w": 42, + "h": 46 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 226, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 226, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 267, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 267, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 267, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 267, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 0, + "y": 179, + "w": 48, + "h": 44 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 0, + "y": 179, + "w": 48, + "h": 44 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 48, + "y": 179, + "w": 47, + "h": 44 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 48, + "y": 179, + "w": 47, + "h": 44 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 95, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 95, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 223, + "w": 47, + "h": 44 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 223, + "w": 47, + "h": 44 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 267, + "w": 47, + "h": 44 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 267, + "w": 47, + "h": 44 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 267, + "w": 47, + "h": 44 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 267, + "w": 47, + "h": 44 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 136, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 136, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 136, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 136, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 177, + "y": 181, + "w": 48, + "h": 43 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 177, + "y": 181, + "w": 48, + "h": 43 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 225, + "y": 181, + "w": 41, + "h": 46 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 225, + "y": 181, + "w": 41, + "h": 46 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 225, + "y": 181, + "w": 41, + "h": 46 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 225, + "y": 181, + "w": 41, + "h": 46 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 177, + "y": 224, + "w": 41, + "h": 46 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 177, + "y": 224, + "w": 41, + "h": 46 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 177, + "y": 224, + "w": 41, + "h": 46 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 177, + "y": 224, + "w": 41, + "h": 46 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 88, + "y": 225, + "w": 46, + "h": 44 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 88, + "y": 225, + "w": 46, + "h": 44 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 134, + "y": 225, + "w": 41, + "h": 46 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 134, + "y": 225, + "w": 41, + "h": 46 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 47, + "y": 269, + "w": 48, + "h": 43 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 47, + "y": 269, + "w": 48, + "h": 43 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 218, + "y": 227, + "w": 48, + "h": 43 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 218, + "y": 227, + "w": 48, + "h": 43 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 266, + "y": 181, + "w": 46, + "h": 44 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 266, + "y": 181, + "w": 46, + "h": 44 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 266, + "y": 225, + "w": 46, + "h": 44 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 266, + "y": 225, + "w": 46, + "h": 44 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 47, + "h": 43 + }, + "frame": { + "x": 266, + "y": 269, + "w": 47, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 47, + "h": 43 + }, + "frame": { + "x": 266, + "y": 269, + "w": 47, + "h": 43 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 175, + "y": 270, + "w": 45, + "h": 44 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 175, + "y": 270, + "w": 45, + "h": 44 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 220, + "y": 270, + "w": 45, + "h": 44 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 220, + "y": 270, + "w": 45, + "h": 44 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 95, + "y": 271, + "w": 45, + "h": 44 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 95, + "y": 271, + "w": 45, + "h": 44 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:6dc7963b6e2b4f0a9df10c958d473654:b388b88edf60945ac1b6cf301ebd3094:d7d9e845c71962a58076b5efe962284e$" + } +} diff --git a/public/images/pokemon/25-partner.png b/public/images/pokemon/25-partner.png new file mode 100644 index 00000000000..7b1104a3a55 Binary files /dev/null and b/public/images/pokemon/25-partner.png differ diff --git a/public/images/pokemon/back/133-partner.json b/public/images/pokemon/back/133-partner.json new file mode 100644 index 00000000000..e5fe317d53d --- /dev/null +++ b/public/images/pokemon/back/133-partner.json @@ -0,0 +1,2834 @@ +{ + "textures": [ + { + "image": "133-partner.png", + "format": "RGBA8888", + "size": { + "w": 245, + "h": 245 + }, + "scale": 1, + "frames": [ + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 13, + "y": 4, + "w": 36, + "h": 45 + }, + "frame": { + "x": 0, + "y": 0, + "w": 36, + "h": 45 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 36, + "h": 47 + }, + "frame": { + "x": 81, + "y": 0, + "w": 36, + "h": 47 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 36, + "h": 47 + }, + "frame": { + "x": 81, + "y": 0, + "w": 36, + "h": 47 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 36, + "h": 47 + }, + "frame": { + "x": 117, + "y": 0, + "w": 36, + "h": 47 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 36, + "h": 47 + }, + "frame": { + "x": 117, + "y": 0, + "w": 36, + "h": 47 + } + }, + { + "filename": "0125.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 44, + "h": 47 + }, + "frame": { + "x": 153, + "y": 0, + "w": 44, + "h": 47 + } + }, + { + "filename": "0126.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 45, + "h": 47 + }, + "frame": { + "x": 197, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0127.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 45, + "h": 47 + }, + "frame": { + "x": 197, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 36, + "h": 48 + }, + "frame": { + "x": 0, + "y": 45, + "w": 36, + "h": 48 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 36, + "h": 48 + }, + "frame": { + "x": 0, + "y": 45, + "w": 36, + "h": 48 + } + }, + { + "filename": "0128.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 44, + "h": 47 + }, + "frame": { + "x": 36, + "y": 47, + "w": 44, + "h": 47 + } + }, + { + "filename": "0129.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 44, + "h": 47 + }, + "frame": { + "x": 36, + "y": 47, + "w": 44, + "h": 47 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0118.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0119.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 36, + "h": 48 + }, + "frame": { + "x": 209, + "y": 47, + "w": 36, + "h": 48 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 36, + "h": 48 + }, + "frame": { + "x": 209, + "y": 47, + "w": 36, + "h": 48 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 9, + "y": 1, + "w": 37, + "h": 48 + }, + "frame": { + "x": 45, + "y": 95, + "w": 37, + "h": 48 + } + }, + { + "filename": "0123.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 43, + "h": 48 + }, + "frame": { + "x": 82, + "y": 95, + "w": 43, + "h": 48 + } + }, + { + "filename": "0124.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 43, + "h": 48 + }, + "frame": { + "x": 82, + "y": 95, + "w": 43, + "h": 48 + } + }, + { + "filename": "0130.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 43, + "h": 48 + }, + "frame": { + "x": 125, + "y": 95, + "w": 43, + "h": 48 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 9, + "y": 0, + "w": 37, + "h": 49 + }, + "frame": { + "x": 208, + "y": 95, + "w": 37, + "h": 49 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 37, + "h": 49 + }, + "frame": { + "x": 208, + "y": 144, + "w": 37, + "h": 49 + } + }, + { + "filename": "0117.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 37, + "h": 49 + }, + "frame": { + "x": 208, + "y": 144, + "w": 37, + "h": 49 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 42, + "y": 192, + "w": 38, + "h": 49 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 42, + "y": 192, + "w": 38, + "h": 49 + } + }, + { + "filename": "0120.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 80, + "y": 192, + "w": 40, + "h": 49 + } + }, + { + "filename": "0121.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 120, + "y": 192, + "w": 41, + "h": 49 + } + }, + { + "filename": "0122.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 120, + "y": 192, + "w": 41, + "h": 49 + } + }, + { + "filename": "0131.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 161, + "y": 193, + "w": 41, + "h": 49 + } + }, + { + "filename": "0132.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 161, + "y": 193, + "w": 41, + "h": 49 + } + }, + { + "filename": "0133.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 39, + "h": 49 + }, + "frame": { + "x": 202, + "y": 193, + "w": 39, + "h": 49 + } + }, + { + "filename": "0134.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 39, + "h": 49 + }, + "frame": { + "x": 202, + "y": 193, + "w": 39, + "h": 49 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:17629ce8c8a380688fdc9acf34c5cbbb:944bb4be78739c5b736be4525f997374:4e938f9dc8bce1cd7822677c800d242b$" + } +} diff --git a/public/images/pokemon/back/133-partner.png b/public/images/pokemon/back/133-partner.png new file mode 100644 index 00000000000..6cc7446032f Binary files /dev/null and b/public/images/pokemon/back/133-partner.png differ diff --git a/public/images/pokemon/back/25-partner.json b/public/images/pokemon/back/25-partner.json new file mode 100644 index 00000000000..3776dc1bbca --- /dev/null +++ b/public/images/pokemon/back/25-partner.json @@ -0,0 +1,2456 @@ +{ + "textures": [ + { + "image": "25-partner.png", + "format": "RGBA8888", + "size": { + "w": 302, + "h": 302 + }, + "scale": 1, + "frames": [ + { + "filename": "0107.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 39, + "h": 47 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 39, + "h": 47 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 39, + "h": 47 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 41, + "y": 0, + "w": 37, + "h": 47 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 41, + "y": 0, + "w": 37, + "h": 47 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 0, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 0, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 78, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 78, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 0, + "y": 141, + "w": 37, + "h": 46 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 0, + "y": 141, + "w": 37, + "h": 46 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 37, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 37, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 115, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 115, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 0, + "y": 187, + "w": 37, + "h": 46 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 0, + "y": 187, + "w": 37, + "h": 46 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 37, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 37, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 0, + "y": 233, + "w": 36, + "h": 47 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 0, + "y": 233, + "w": 36, + "h": 47 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 152, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 152, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 189, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 189, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 226, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 226, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 0, + "w": 39, + "h": 43 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 0, + "w": 39, + "h": 43 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 43, + "w": 39, + "h": 43 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 43, + "w": 39, + "h": 43 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 37, + "y": 188, + "w": 36, + "h": 46 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 37, + "y": 188, + "w": 36, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 36, + "y": 234, + "w": 37, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 36, + "y": 234, + "w": 37, + "h": 46 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 75, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 75, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 188, + "w": 36, + "h": 47 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 188, + "w": 36, + "h": 47 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 38, + "h": 45 + }, + "frame": { + "x": 111, + "y": 46, + "w": 38, + "h": 45 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 38, + "h": 45 + }, + "frame": { + "x": 111, + "y": 46, + "w": 38, + "h": 45 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 46, + "w": 39, + "h": 43 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 46, + "w": 39, + "h": 43 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 188, + "y": 46, + "w": 39, + "h": 43 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 188, + "y": 46, + "w": 39, + "h": 43 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 227, + "y": 46, + "w": 36, + "h": 47 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 227, + "y": 46, + "w": 36, + "h": 47 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 86, + "w": 39, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 86, + "w": 39, + "h": 43 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 73, + "y": 235, + "w": 36, + "h": 46 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 73, + "y": 235, + "w": 36, + "h": 46 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 109, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 109, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 109, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 109, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 109, + "y": 188, + "w": 36, + "h": 46 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 109, + "y": 188, + "w": 36, + "h": 46 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 36, + "h": 45 + }, + "frame": { + "x": 109, + "y": 234, + "w": 36, + "h": 45 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 36, + "h": 45 + }, + "frame": { + "x": 109, + "y": 234, + "w": 36, + "h": 45 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 37, + "h": 44 + }, + "frame": { + "x": 145, + "y": 91, + "w": 37, + "h": 44 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 37, + "h": 44 + }, + "frame": { + "x": 145, + "y": 91, + "w": 37, + "h": 44 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 135, + "w": 38, + "h": 43 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 135, + "w": 38, + "h": 43 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 178, + "w": 38, + "h": 43 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 178, + "w": 38, + "h": 43 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 221, + "w": 38, + "h": 43 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 221, + "w": 38, + "h": 43 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 182, + "y": 89, + "w": 40, + "h": 40 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 182, + "y": 89, + "w": 40, + "h": 40 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 222, + "y": 93, + "w": 41, + "h": 35 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 222, + "y": 93, + "w": 41, + "h": 35 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 37, + "h": 43 + }, + "frame": { + "x": 183, + "y": 129, + "w": 37, + "h": 43 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 37, + "h": 43 + }, + "frame": { + "x": 183, + "y": 129, + "w": 37, + "h": 43 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 37, + "h": 43 + }, + "frame": { + "x": 183, + "y": 172, + "w": 37, + "h": 43 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 37, + "h": 43 + }, + "frame": { + "x": 183, + "y": 172, + "w": 37, + "h": 43 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 183, + "y": 215, + "w": 40, + "h": 40 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 183, + "y": 215, + "w": 40, + "h": 40 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 12, + "w": 40, + "h": 35 + }, + "frame": { + "x": 145, + "y": 264, + "w": 40, + "h": 35 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 12, + "w": 40, + "h": 35 + }, + "frame": { + "x": 145, + "y": 264, + "w": 40, + "h": 35 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 185, + "y": 255, + "w": 39, + "h": 40 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 185, + "y": 255, + "w": 39, + "h": 40 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 13, + "w": 41, + "h": 34 + }, + "frame": { + "x": 222, + "y": 128, + "w": 41, + "h": 34 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 13, + "w": 41, + "h": 34 + }, + "frame": { + "x": 222, + "y": 128, + "w": 41, + "h": 34 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 263, + "y": 129, + "w": 39, + "h": 40 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 263, + "y": 129, + "w": 39, + "h": 40 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 220, + "y": 162, + "w": 40, + "h": 40 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 220, + "y": 162, + "w": 40, + "h": 40 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 260, + "y": 169, + "w": 40, + "h": 40 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 260, + "y": 169, + "w": 40, + "h": 40 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 7, + "w": 38, + "h": 40 + }, + "frame": { + "x": 223, + "y": 209, + "w": 38, + "h": 40 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 7, + "w": 38, + "h": 40 + }, + "frame": { + "x": 223, + "y": 209, + "w": 38, + "h": 40 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 7, + "w": 38, + "h": 40 + }, + "frame": { + "x": 261, + "y": 209, + "w": 38, + "h": 40 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 7, + "w": 38, + "h": 40 + }, + "frame": { + "x": 261, + "y": 209, + "w": 38, + "h": 40 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 39, + "h": 39 + }, + "frame": { + "x": 224, + "y": 249, + "w": 39, + "h": 39 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 39, + "h": 39 + }, + "frame": { + "x": 224, + "y": 249, + "w": 39, + "h": 39 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 12, + "w": 39, + "h": 35 + }, + "frame": { + "x": 263, + "y": 249, + "w": 39, + "h": 35 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 12, + "w": 39, + "h": 35 + }, + "frame": { + "x": 263, + "y": 249, + "w": 39, + "h": 35 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:cfdc5980d26f5e9ff2936babc0854215:6c08d027c2bbef936a8cbfa5e456edbf:d7d9e845c71962a58076b5efe962284e$" + } +} diff --git a/public/images/pokemon/back/25-partner.png b/public/images/pokemon/back/25-partner.png new file mode 100644 index 00000000000..8085a963e28 Binary files /dev/null and b/public/images/pokemon/back/25-partner.png differ diff --git a/public/images/pokemon/back/female/25-partner.json b/public/images/pokemon/back/female/25-partner.json new file mode 100644 index 00000000000..8f72e804e93 --- /dev/null +++ b/public/images/pokemon/back/female/25-partner.json @@ -0,0 +1,2456 @@ +{ + "textures": [ + { + "image": "25-partner.png", + "format": "RGBA8888", + "size": { + "w": 309, + "h": 309 + }, + "scale": 1, + "frames": [ + { + "filename": "0107.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 40, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 40, + "h": 47 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 40, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 40, + "h": 47 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 40, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 40, + "h": 47 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 41, + "y": 0, + "w": 38, + "h": 47 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 41, + "y": 0, + "w": 38, + "h": 47 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 0, + "y": 94, + "w": 38, + "h": 47 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 0, + "y": 94, + "w": 38, + "h": 47 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 79, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 79, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 0, + "y": 141, + "w": 38, + "h": 46 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 0, + "y": 141, + "w": 38, + "h": 46 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 38, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 38, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 117, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 117, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 0, + "y": 187, + "w": 38, + "h": 46 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 0, + "y": 187, + "w": 38, + "h": 46 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 38, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 38, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 0, + "y": 233, + "w": 37, + "h": 47 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 0, + "y": 233, + "w": 37, + "h": 47 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 155, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 155, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 193, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 193, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 231, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 231, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 269, + "y": 0, + "w": 40, + "h": 43 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 269, + "y": 0, + "w": 40, + "h": 43 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 269, + "y": 43, + "w": 40, + "h": 43 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 269, + "y": 43, + "w": 40, + "h": 43 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 38, + "y": 188, + "w": 37, + "h": 46 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 38, + "y": 188, + "w": 37, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 37, + "y": 234, + "w": 38, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 37, + "y": 234, + "w": 38, + "h": 46 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 77, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 77, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 188, + "w": 37, + "h": 47 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 188, + "w": 37, + "h": 47 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 39, + "h": 45 + }, + "frame": { + "x": 114, + "y": 46, + "w": 39, + "h": 45 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 39, + "h": 45 + }, + "frame": { + "x": 114, + "y": 46, + "w": 39, + "h": 45 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 153, + "y": 46, + "w": 40, + "h": 43 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 153, + "y": 46, + "w": 40, + "h": 43 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 193, + "y": 46, + "w": 40, + "h": 43 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 193, + "y": 46, + "w": 40, + "h": 43 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 235, + "w": 37, + "h": 47 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 235, + "w": 37, + "h": 47 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 112, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 112, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 112, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 112, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 112, + "y": 188, + "w": 37, + "h": 46 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 112, + "y": 188, + "w": 37, + "h": 46 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 112, + "y": 234, + "w": 37, + "h": 46 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 112, + "y": 234, + "w": 37, + "h": 46 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 37, + "h": 45 + }, + "frame": { + "x": 149, + "y": 91, + "w": 37, + "h": 45 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 37, + "h": 45 + }, + "frame": { + "x": 149, + "y": 91, + "w": 37, + "h": 45 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 186, + "y": 89, + "w": 40, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 186, + "y": 89, + "w": 40, + "h": 43 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 38, + "h": 44 + }, + "frame": { + "x": 149, + "y": 136, + "w": 38, + "h": 44 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 38, + "h": 44 + }, + "frame": { + "x": 149, + "y": 136, + "w": 38, + "h": 44 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 180, + "w": 39, + "h": 43 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 180, + "w": 39, + "h": 43 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 223, + "w": 39, + "h": 43 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 223, + "w": 39, + "h": 43 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 266, + "w": 39, + "h": 43 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 266, + "w": 39, + "h": 43 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 187, + "y": 132, + "w": 38, + "h": 43 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 187, + "y": 132, + "w": 38, + "h": 43 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 188, + "y": 175, + "w": 38, + "h": 43 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 188, + "y": 175, + "w": 38, + "h": 43 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 188, + "y": 218, + "w": 41, + "h": 40 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 188, + "y": 218, + "w": 41, + "h": 40 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 188, + "y": 258, + "w": 41, + "h": 40 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 188, + "y": 258, + "w": 41, + "h": 40 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 226, + "y": 89, + "w": 40, + "h": 40 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 226, + "y": 89, + "w": 40, + "h": 40 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 266, + "y": 86, + "w": 41, + "h": 40 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 266, + "y": 86, + "w": 41, + "h": 40 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 266, + "y": 126, + "w": 41, + "h": 35 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 266, + "y": 126, + "w": 41, + "h": 35 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 226, + "y": 129, + "w": 40, + "h": 40 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 226, + "y": 129, + "w": 40, + "h": 40 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 226, + "y": 169, + "w": 41, + "h": 40 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 226, + "y": 169, + "w": 41, + "h": 40 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 267, + "y": 161, + "w": 39, + "h": 40 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 267, + "y": 161, + "w": 39, + "h": 40 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 229, + "y": 209, + "w": 39, + "h": 40 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 229, + "y": 209, + "w": 39, + "h": 40 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 268, + "y": 201, + "w": 41, + "h": 35 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 268, + "y": 201, + "w": 41, + "h": 35 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 13, + "w": 41, + "h": 34 + }, + "frame": { + "x": 268, + "y": 236, + "w": 41, + "h": 34 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 13, + "w": 41, + "h": 34 + }, + "frame": { + "x": 268, + "y": 236, + "w": 41, + "h": 34 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 8, + "w": 40, + "h": 39 + }, + "frame": { + "x": 229, + "y": 270, + "w": 40, + "h": 39 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 8, + "w": 40, + "h": 39 + }, + "frame": { + "x": 229, + "y": 270, + "w": 40, + "h": 39 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 12, + "w": 40, + "h": 35 + }, + "frame": { + "x": 269, + "y": 270, + "w": 40, + "h": 35 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 12, + "w": 40, + "h": 35 + }, + "frame": { + "x": 269, + "y": 270, + "w": 40, + "h": 35 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:d372b1d86228d032e58b8f44f5ba88b7:831f141a266f419c1af619c4e93c6c16:d7d9e845c71962a58076b5efe962284e$" + } +} diff --git a/public/images/pokemon/back/female/25-partner.png b/public/images/pokemon/back/female/25-partner.png new file mode 100644 index 00000000000..97ceaa8bb2f Binary files /dev/null and b/public/images/pokemon/back/female/25-partner.png differ diff --git a/public/images/pokemon/back/shiny/133-partner.json b/public/images/pokemon/back/shiny/133-partner.json new file mode 100644 index 00000000000..dc90bd7b683 --- /dev/null +++ b/public/images/pokemon/back/shiny/133-partner.json @@ -0,0 +1,2834 @@ +{ + "textures": [ + { + "image": "133-partner.png", + "format": "RGBA8888", + "size": { + "w": 245, + "h": 245 + }, + "scale": 1, + "frames": [ + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 13, + "y": 4, + "w": 36, + "h": 45 + }, + "frame": { + "x": 0, + "y": 0, + "w": 36, + "h": 45 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 45, + "h": 47 + }, + "frame": { + "x": 36, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 36, + "h": 47 + }, + "frame": { + "x": 81, + "y": 0, + "w": 36, + "h": 47 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 36, + "h": 47 + }, + "frame": { + "x": 81, + "y": 0, + "w": 36, + "h": 47 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 36, + "h": 47 + }, + "frame": { + "x": 117, + "y": 0, + "w": 36, + "h": 47 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 36, + "h": 47 + }, + "frame": { + "x": 117, + "y": 0, + "w": 36, + "h": 47 + } + }, + { + "filename": "0125.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 44, + "h": 47 + }, + "frame": { + "x": 153, + "y": 0, + "w": 44, + "h": 47 + } + }, + { + "filename": "0126.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 45, + "h": 47 + }, + "frame": { + "x": 197, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0127.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 45, + "h": 47 + }, + "frame": { + "x": 197, + "y": 0, + "w": 45, + "h": 47 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 36, + "h": 48 + }, + "frame": { + "x": 0, + "y": 45, + "w": 36, + "h": 48 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 36, + "h": 48 + }, + "frame": { + "x": 0, + "y": 45, + "w": 36, + "h": 48 + } + }, + { + "filename": "0128.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 44, + "h": 47 + }, + "frame": { + "x": 36, + "y": 47, + "w": 44, + "h": 47 + } + }, + { + "filename": "0129.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 44, + "h": 47 + }, + "frame": { + "x": 36, + "y": 47, + "w": 44, + "h": 47 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0118.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0119.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 48 + }, + "frame": { + "x": 80, + "y": 47, + "w": 38, + "h": 48 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 46, + "h": 48 + }, + "frame": { + "x": 118, + "y": 47, + "w": 46, + "h": 48 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 164, + "y": 47, + "w": 45, + "h": 48 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 36, + "h": 48 + }, + "frame": { + "x": 209, + "y": 47, + "w": 36, + "h": 48 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 36, + "h": 48 + }, + "frame": { + "x": 209, + "y": 47, + "w": 36, + "h": 48 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 45, + "h": 48 + }, + "frame": { + "x": 0, + "y": 94, + "w": 45, + "h": 48 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 9, + "y": 1, + "w": 37, + "h": 48 + }, + "frame": { + "x": 45, + "y": 95, + "w": 37, + "h": 48 + } + }, + { + "filename": "0123.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 43, + "h": 48 + }, + "frame": { + "x": 82, + "y": 95, + "w": 43, + "h": 48 + } + }, + { + "filename": "0124.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 43, + "h": 48 + }, + "frame": { + "x": 82, + "y": 95, + "w": 43, + "h": 48 + } + }, + { + "filename": "0130.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 43, + "h": 48 + }, + "frame": { + "x": 125, + "y": 95, + "w": 43, + "h": 48 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 168, + "y": 95, + "w": 40, + "h": 49 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 9, + "y": 0, + "w": 37, + "h": 49 + }, + "frame": { + "x": 208, + "y": 95, + "w": 37, + "h": 49 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 142, + "w": 42, + "h": 49 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 49 + }, + "frame": { + "x": 42, + "y": 143, + "w": 44, + "h": 49 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 49 + }, + "frame": { + "x": 86, + "y": 143, + "w": 43, + "h": 49 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 129, + "y": 143, + "w": 38, + "h": 49 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 167, + "y": 144, + "w": 41, + "h": 49 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 37, + "h": 49 + }, + "frame": { + "x": 208, + "y": 144, + "w": 37, + "h": 49 + } + }, + { + "filename": "0117.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 37, + "h": 49 + }, + "frame": { + "x": 208, + "y": 144, + "w": 37, + "h": 49 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 49 + }, + "frame": { + "x": 0, + "y": 191, + "w": 42, + "h": 49 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 42, + "y": 192, + "w": 38, + "h": 49 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 38, + "h": 49 + }, + "frame": { + "x": 42, + "y": 192, + "w": 38, + "h": 49 + } + }, + { + "filename": "0120.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 40, + "h": 49 + }, + "frame": { + "x": 80, + "y": 192, + "w": 40, + "h": 49 + } + }, + { + "filename": "0121.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 120, + "y": 192, + "w": 41, + "h": 49 + } + }, + { + "filename": "0122.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 120, + "y": 192, + "w": 41, + "h": 49 + } + }, + { + "filename": "0131.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 161, + "y": 193, + "w": 41, + "h": 49 + } + }, + { + "filename": "0132.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 49 + }, + "frame": { + "x": 161, + "y": 193, + "w": 41, + "h": 49 + } + }, + { + "filename": "0133.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 39, + "h": 49 + }, + "frame": { + "x": 202, + "y": 193, + "w": 39, + "h": 49 + } + }, + { + "filename": "0134.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 50 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 39, + "h": 49 + }, + "frame": { + "x": 202, + "y": 193, + "w": 39, + "h": 49 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:5e94f60a2f7a7dc3f5d699bd3107f486:44eae6b3793ef296999ef086d542c6a4:4e938f9dc8bce1cd7822677c800d242b$" + } +} diff --git a/public/images/pokemon/back/shiny/133-partner.png b/public/images/pokemon/back/shiny/133-partner.png new file mode 100644 index 00000000000..a1f95b24496 Binary files /dev/null and b/public/images/pokemon/back/shiny/133-partner.png differ diff --git a/public/images/pokemon/back/shiny/25-partner.json b/public/images/pokemon/back/shiny/25-partner.json new file mode 100644 index 00000000000..d9f755885d2 --- /dev/null +++ b/public/images/pokemon/back/shiny/25-partner.json @@ -0,0 +1,2456 @@ +{ + "textures": [ + { + "image": "25-partner.png", + "format": "RGBA8888", + "size": { + "w": 302, + "h": 302 + }, + "scale": 1, + "frames": [ + { + "filename": "0107.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 39, + "h": 47 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 39, + "h": 47 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 39, + "h": 47 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 41, + "y": 0, + "w": 37, + "h": 47 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 41, + "y": 0, + "w": 37, + "h": 47 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 0, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 0, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 39, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 78, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 78, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 0, + "y": 141, + "w": 37, + "h": 46 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 0, + "y": 141, + "w": 37, + "h": 46 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 37, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 37, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 115, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 115, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 0, + "y": 187, + "w": 37, + "h": 46 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 0, + "y": 187, + "w": 37, + "h": 46 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 37, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 37, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 0, + "y": 233, + "w": 36, + "h": 47 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 0, + "y": 233, + "w": 36, + "h": 47 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 152, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 152, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 189, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 189, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 226, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 226, + "y": 0, + "w": 37, + "h": 46 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 0, + "w": 39, + "h": 43 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 0, + "w": 39, + "h": 43 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 43, + "w": 39, + "h": 43 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 43, + "w": 39, + "h": 43 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 37, + "y": 188, + "w": 36, + "h": 46 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 37, + "y": 188, + "w": 36, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 36, + "y": 234, + "w": 37, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 36, + "y": 234, + "w": 37, + "h": 46 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 75, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 75, + "y": 47, + "w": 36, + "h": 47 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 188, + "w": 36, + "h": 47 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 73, + "y": 188, + "w": 36, + "h": 47 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 38, + "h": 45 + }, + "frame": { + "x": 111, + "y": 46, + "w": 38, + "h": 45 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 38, + "h": 45 + }, + "frame": { + "x": 111, + "y": 46, + "w": 38, + "h": 45 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 46, + "w": 39, + "h": 43 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 46, + "w": 39, + "h": 43 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 188, + "y": 46, + "w": 39, + "h": 43 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 188, + "y": 46, + "w": 39, + "h": 43 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 227, + "y": 46, + "w": 36, + "h": 47 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 227, + "y": 46, + "w": 36, + "h": 47 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 86, + "w": 39, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 263, + "y": 86, + "w": 39, + "h": 43 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 73, + "y": 235, + "w": 36, + "h": 46 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 73, + "y": 235, + "w": 36, + "h": 46 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 109, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 109, + "y": 94, + "w": 36, + "h": 47 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 109, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 36, + "h": 47 + }, + "frame": { + "x": 109, + "y": 141, + "w": 36, + "h": 47 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 109, + "y": 188, + "w": 36, + "h": 46 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 109, + "y": 188, + "w": 36, + "h": 46 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 36, + "h": 45 + }, + "frame": { + "x": 109, + "y": 234, + "w": 36, + "h": 45 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 36, + "h": 45 + }, + "frame": { + "x": 109, + "y": 234, + "w": 36, + "h": 45 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 37, + "h": 44 + }, + "frame": { + "x": 145, + "y": 91, + "w": 37, + "h": 44 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 37, + "h": 44 + }, + "frame": { + "x": 145, + "y": 91, + "w": 37, + "h": 44 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 135, + "w": 38, + "h": 43 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 135, + "w": 38, + "h": 43 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 178, + "w": 38, + "h": 43 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 178, + "w": 38, + "h": 43 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 221, + "w": 38, + "h": 43 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 145, + "y": 221, + "w": 38, + "h": 43 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 182, + "y": 89, + "w": 40, + "h": 40 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 182, + "y": 89, + "w": 40, + "h": 40 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 222, + "y": 93, + "w": 41, + "h": 35 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 222, + "y": 93, + "w": 41, + "h": 35 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 37, + "h": 43 + }, + "frame": { + "x": 183, + "y": 129, + "w": 37, + "h": 43 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 37, + "h": 43 + }, + "frame": { + "x": 183, + "y": 129, + "w": 37, + "h": 43 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 37, + "h": 43 + }, + "frame": { + "x": 183, + "y": 172, + "w": 37, + "h": 43 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 37, + "h": 43 + }, + "frame": { + "x": 183, + "y": 172, + "w": 37, + "h": 43 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 183, + "y": 215, + "w": 40, + "h": 40 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 183, + "y": 215, + "w": 40, + "h": 40 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 12, + "w": 40, + "h": 35 + }, + "frame": { + "x": 145, + "y": 264, + "w": 40, + "h": 35 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 12, + "w": 40, + "h": 35 + }, + "frame": { + "x": 145, + "y": 264, + "w": 40, + "h": 35 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 185, + "y": 255, + "w": 39, + "h": 40 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 185, + "y": 255, + "w": 39, + "h": 40 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 13, + "w": 41, + "h": 34 + }, + "frame": { + "x": 222, + "y": 128, + "w": 41, + "h": 34 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 13, + "w": 41, + "h": 34 + }, + "frame": { + "x": 222, + "y": 128, + "w": 41, + "h": 34 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 263, + "y": 129, + "w": 39, + "h": 40 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 263, + "y": 129, + "w": 39, + "h": 40 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 220, + "y": 162, + "w": 40, + "h": 40 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 220, + "y": 162, + "w": 40, + "h": 40 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 260, + "y": 169, + "w": 40, + "h": 40 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 260, + "y": 169, + "w": 40, + "h": 40 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 7, + "w": 38, + "h": 40 + }, + "frame": { + "x": 223, + "y": 209, + "w": 38, + "h": 40 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 7, + "w": 38, + "h": 40 + }, + "frame": { + "x": 223, + "y": 209, + "w": 38, + "h": 40 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 7, + "w": 38, + "h": 40 + }, + "frame": { + "x": 261, + "y": 209, + "w": 38, + "h": 40 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 7, + "w": 38, + "h": 40 + }, + "frame": { + "x": 261, + "y": 209, + "w": 38, + "h": 40 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 39, + "h": 39 + }, + "frame": { + "x": 224, + "y": 249, + "w": 39, + "h": 39 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 39, + "h": 39 + }, + "frame": { + "x": 224, + "y": 249, + "w": 39, + "h": 39 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 12, + "w": 39, + "h": 35 + }, + "frame": { + "x": 263, + "y": 249, + "w": 39, + "h": 35 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 12, + "w": 39, + "h": 35 + }, + "frame": { + "x": 263, + "y": 249, + "w": 39, + "h": 35 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:11d6f26f5786e76420a96085163ce189:617f0fbd4eb98368acc7dc3c1484aeb6:d7d9e845c71962a58076b5efe962284e$" + } +} diff --git a/public/images/pokemon/back/shiny/25-partner.png b/public/images/pokemon/back/shiny/25-partner.png new file mode 100644 index 00000000000..f4fb2eab219 Binary files /dev/null and b/public/images/pokemon/back/shiny/25-partner.png differ diff --git a/public/images/pokemon/back/shiny/female/25-partner.json b/public/images/pokemon/back/shiny/female/25-partner.json new file mode 100644 index 00000000000..6d76db3b6df --- /dev/null +++ b/public/images/pokemon/back/shiny/female/25-partner.json @@ -0,0 +1,2456 @@ +{ + "textures": [ + { + "image": "25-partner.png", + "format": "RGBA8888", + "size": { + "w": 309, + "h": 309 + }, + "scale": 1, + "frames": [ + { + "filename": "0107.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 0, + "y": 0, + "w": 41, + "h": 47 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 40, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 40, + "h": 47 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 40, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 40, + "h": 47 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 40, + "h": 47 + }, + "frame": { + "x": 0, + "y": 47, + "w": 40, + "h": 47 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 41, + "y": 0, + "w": 38, + "h": 47 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 41, + "y": 0, + "w": 38, + "h": 47 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 0, + "y": 94, + "w": 38, + "h": 47 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 0, + "y": 94, + "w": 38, + "h": 47 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 40, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 79, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 79, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 0, + "y": 141, + "w": 38, + "h": 46 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 0, + "y": 141, + "w": 38, + "h": 46 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 38, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 38, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 117, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 117, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 0, + "y": 187, + "w": 38, + "h": 46 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 0, + "y": 187, + "w": 38, + "h": 46 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 38, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 38, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 0, + "y": 233, + "w": 37, + "h": 47 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 0, + "y": 233, + "w": 37, + "h": 47 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 155, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 155, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 193, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 193, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 231, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 231, + "y": 0, + "w": 38, + "h": 46 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 269, + "y": 0, + "w": 40, + "h": 43 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 269, + "y": 0, + "w": 40, + "h": 43 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 269, + "y": 43, + "w": 40, + "h": 43 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 269, + "y": 43, + "w": 40, + "h": 43 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 38, + "y": 188, + "w": 37, + "h": 46 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 38, + "y": 188, + "w": 37, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 37, + "y": 234, + "w": 38, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 38, + "h": 46 + }, + "frame": { + "x": 37, + "y": 234, + "w": 38, + "h": 46 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 77, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 77, + "y": 47, + "w": 37, + "h": 47 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 188, + "w": 37, + "h": 47 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 188, + "w": 37, + "h": 47 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 39, + "h": 45 + }, + "frame": { + "x": 114, + "y": 46, + "w": 39, + "h": 45 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 39, + "h": 45 + }, + "frame": { + "x": 114, + "y": 46, + "w": 39, + "h": 45 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 153, + "y": 46, + "w": 40, + "h": 43 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 153, + "y": 46, + "w": 40, + "h": 43 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 193, + "y": 46, + "w": 40, + "h": 43 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 193, + "y": 46, + "w": 40, + "h": 43 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 235, + "w": 37, + "h": 47 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 75, + "y": 235, + "w": 37, + "h": 47 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 112, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 112, + "y": 94, + "w": 37, + "h": 47 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 112, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 37, + "h": 47 + }, + "frame": { + "x": 112, + "y": 141, + "w": 37, + "h": 47 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 112, + "y": 188, + "w": 37, + "h": 46 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 112, + "y": 188, + "w": 37, + "h": 46 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 112, + "y": 234, + "w": 37, + "h": 46 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 37, + "h": 46 + }, + "frame": { + "x": 112, + "y": 234, + "w": 37, + "h": 46 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 37, + "h": 45 + }, + "frame": { + "x": 149, + "y": 91, + "w": 37, + "h": 45 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 37, + "h": 45 + }, + "frame": { + "x": 149, + "y": 91, + "w": 37, + "h": 45 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 186, + "y": 89, + "w": 40, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 4, + "w": 40, + "h": 43 + }, + "frame": { + "x": 186, + "y": 89, + "w": 40, + "h": 43 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 38, + "h": 44 + }, + "frame": { + "x": 149, + "y": 136, + "w": 38, + "h": 44 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 38, + "h": 44 + }, + "frame": { + "x": 149, + "y": 136, + "w": 38, + "h": 44 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 180, + "w": 39, + "h": 43 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 180, + "w": 39, + "h": 43 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 223, + "w": 39, + "h": 43 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 223, + "w": 39, + "h": 43 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 266, + "w": 39, + "h": 43 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 39, + "h": 43 + }, + "frame": { + "x": 149, + "y": 266, + "w": 39, + "h": 43 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 187, + "y": 132, + "w": 38, + "h": 43 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 187, + "y": 132, + "w": 38, + "h": 43 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 188, + "y": 175, + "w": 38, + "h": 43 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 38, + "h": 43 + }, + "frame": { + "x": 188, + "y": 175, + "w": 38, + "h": 43 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 188, + "y": 218, + "w": 41, + "h": 40 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 188, + "y": 218, + "w": 41, + "h": 40 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 188, + "y": 258, + "w": 41, + "h": 40 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 188, + "y": 258, + "w": 41, + "h": 40 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 226, + "y": 89, + "w": 40, + "h": 40 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 226, + "y": 89, + "w": 40, + "h": 40 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 266, + "y": 86, + "w": 41, + "h": 40 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 266, + "y": 86, + "w": 41, + "h": 40 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 266, + "y": 126, + "w": 41, + "h": 35 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 266, + "y": 126, + "w": 41, + "h": 35 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 226, + "y": 129, + "w": 40, + "h": 40 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 7, + "w": 40, + "h": 40 + }, + "frame": { + "x": 226, + "y": 129, + "w": 40, + "h": 40 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 226, + "y": 169, + "w": 41, + "h": 40 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 7, + "w": 41, + "h": 40 + }, + "frame": { + "x": 226, + "y": 169, + "w": 41, + "h": 40 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 267, + "y": 161, + "w": 39, + "h": 40 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 267, + "y": 161, + "w": 39, + "h": 40 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 229, + "y": 209, + "w": 39, + "h": 40 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 7, + "w": 39, + "h": 40 + }, + "frame": { + "x": 229, + "y": 209, + "w": 39, + "h": 40 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 268, + "y": 201, + "w": 41, + "h": 35 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 12, + "w": 41, + "h": 35 + }, + "frame": { + "x": 268, + "y": 201, + "w": 41, + "h": 35 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 13, + "w": 41, + "h": 34 + }, + "frame": { + "x": 268, + "y": 236, + "w": 41, + "h": 34 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 13, + "w": 41, + "h": 34 + }, + "frame": { + "x": 268, + "y": 236, + "w": 41, + "h": 34 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 8, + "w": 40, + "h": 39 + }, + "frame": { + "x": 229, + "y": 270, + "w": 40, + "h": 39 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 8, + "w": 40, + "h": 39 + }, + "frame": { + "x": 229, + "y": 270, + "w": 40, + "h": 39 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 12, + "w": 40, + "h": 35 + }, + "frame": { + "x": 269, + "y": 270, + "w": 40, + "h": 35 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 41, + "h": 47 + }, + "spriteSourceSize": { + "x": 1, + "y": 12, + "w": 40, + "h": 35 + }, + "frame": { + "x": 269, + "y": 270, + "w": 40, + "h": 35 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:c2491c1baeaa6ad79265c83724d14b58:4d021c74e090acb4be617ac0f9f4914b:d7d9e845c71962a58076b5efe962284e$" + } +} diff --git a/public/images/pokemon/back/shiny/female/25-partner.png b/public/images/pokemon/back/shiny/female/25-partner.png new file mode 100644 index 00000000000..efc1fc1c0e3 Binary files /dev/null and b/public/images/pokemon/back/shiny/female/25-partner.png differ diff --git a/public/images/pokemon/female/25-partner.json b/public/images/pokemon/female/25-partner.json new file mode 100644 index 00000000000..c662ec8a3c6 --- /dev/null +++ b/public/images/pokemon/female/25-partner.json @@ -0,0 +1,2456 @@ +{ + "textures": [ + { + "image": "25-partner.png", + "format": "RGBA8888", + "size": { + "w": 330, + "h": 330 + }, + "scale": 1, + "frames": [ + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 51, + "h": 43 + }, + "frame": { + "x": 50, + "y": 0, + "w": 51, + "h": 43 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 51, + "h": 43 + }, + "frame": { + "x": 50, + "y": 0, + "w": 51, + "h": 43 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 101, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 101, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 150, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 150, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 200, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 200, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 249, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 249, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 43, + "w": 50, + "h": 43 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 43, + "w": 50, + "h": 43 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 51, + "h": 43 + }, + "frame": { + "x": 50, + "y": 43, + "w": 51, + "h": 43 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 51, + "h": 43 + }, + "frame": { + "x": 50, + "y": 43, + "w": 51, + "h": 43 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 101, + "y": 43, + "w": 48, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 101, + "y": 43, + "w": 48, + "h": 43 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 149, + "y": 43, + "w": 49, + "h": 43 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 149, + "y": 43, + "w": 49, + "h": 43 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 198, + "y": 43, + "w": 48, + "h": 44 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 198, + "y": 43, + "w": 48, + "h": 44 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 246, + "y": 43, + "w": 50, + "h": 44 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 246, + "y": 43, + "w": 50, + "h": 44 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 0, + "y": 86, + "w": 48, + "h": 44 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 0, + "y": 86, + "w": 48, + "h": 44 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 48, + "y": 86, + "w": 47, + "h": 44 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 48, + "y": 86, + "w": 47, + "h": 44 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 95, + "y": 86, + "w": 50, + "h": 44 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 95, + "y": 86, + "w": 50, + "h": 44 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 145, + "y": 86, + "w": 47, + "h": 44 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 145, + "y": 86, + "w": 47, + "h": 44 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 192, + "y": 87, + "w": 46, + "h": 44 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 192, + "y": 87, + "w": 46, + "h": 44 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 238, + "y": 87, + "w": 50, + "h": 44 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 238, + "y": 87, + "w": 50, + "h": 44 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 288, + "y": 87, + "w": 42, + "h": 46 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 288, + "y": 87, + "w": 42, + "h": 46 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 0, + "y": 130, + "w": 46, + "h": 44 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 0, + "y": 130, + "w": 46, + "h": 44 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 46, + "y": 130, + "w": 48, + "h": 44 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 46, + "y": 130, + "w": 48, + "h": 44 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 46, + "y": 130, + "w": 48, + "h": 44 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 46, + "y": 130, + "w": 48, + "h": 44 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 94, + "y": 130, + "w": 50, + "h": 44 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 94, + "y": 130, + "w": 50, + "h": 44 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 144, + "y": 130, + "w": 47, + "h": 44 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 144, + "y": 130, + "w": 47, + "h": 44 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 191, + "y": 131, + "w": 49, + "h": 44 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 191, + "y": 131, + "w": 49, + "h": 44 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 240, + "y": 131, + "w": 46, + "h": 44 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 240, + "y": 131, + "w": 46, + "h": 44 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 286, + "y": 133, + "w": 44, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 286, + "y": 133, + "w": 44, + "h": 46 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 44, + "h": 46 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 44, + "h": 46 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 44, + "y": 174, + "w": 42, + "h": 46 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 44, + "y": 174, + "w": 42, + "h": 46 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 44, + "y": 174, + "w": 42, + "h": 46 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 44, + "y": 174, + "w": 42, + "h": 46 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 86, + "y": 174, + "w": 43, + "h": 46 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 86, + "y": 174, + "w": 43, + "h": 46 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 129, + "y": 174, + "w": 44, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 129, + "y": 174, + "w": 44, + "h": 46 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 173, + "y": 175, + "w": 44, + "h": 46 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 173, + "y": 175, + "w": 44, + "h": 46 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 217, + "y": 175, + "w": 43, + "h": 46 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 217, + "y": 175, + "w": 43, + "h": 46 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 260, + "y": 179, + "w": 44, + "h": 46 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 260, + "y": 179, + "w": 44, + "h": 46 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 220, + "w": 43, + "h": 46 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 220, + "w": 43, + "h": 46 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 127, + "y": 220, + "w": 44, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 127, + "y": 220, + "w": 44, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 127, + "y": 220, + "w": 44, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 127, + "y": 220, + "w": 44, + "h": 46 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 171, + "y": 221, + "w": 42, + "h": 46 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 171, + "y": 221, + "w": 42, + "h": 46 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 171, + "y": 221, + "w": 42, + "h": 46 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 171, + "y": 221, + "w": 42, + "h": 46 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 213, + "y": 221, + "w": 43, + "h": 46 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 213, + "y": 221, + "w": 43, + "h": 46 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 256, + "y": 225, + "w": 44, + "h": 46 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 256, + "y": 225, + "w": 44, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 266, + "w": 43, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 266, + "w": 43, + "h": 46 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 127, + "y": 266, + "w": 43, + "h": 46 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 127, + "y": 266, + "w": 43, + "h": 46 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 47, + "h": 46 + }, + "frame": { + "x": 170, + "y": 267, + "w": 47, + "h": 46 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 47, + "h": 46 + }, + "frame": { + "x": 170, + "y": 267, + "w": 47, + "h": 46 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 217, + "y": 271, + "w": 46, + "h": 46 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 217, + "y": 271, + "w": 46, + "h": 46 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 217, + "y": 271, + "w": 46, + "h": 46 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 263, + "y": 271, + "w": 42, + "h": 46 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 263, + "y": 271, + "w": 42, + "h": 46 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:3c3f1d7c0f960de57a2195aba3e404a1:d500cdc0e036449780ce01accec9c0d5:d7d9e845c71962a58076b5efe962284e$" + } +} diff --git a/public/images/pokemon/female/25-partner.png b/public/images/pokemon/female/25-partner.png new file mode 100644 index 00000000000..e500db2a3be Binary files /dev/null and b/public/images/pokemon/female/25-partner.png differ diff --git a/public/images/pokemon/icons/1/133-partner.png b/public/images/pokemon/icons/1/133-partner.png new file mode 100644 index 00000000000..b4022e26441 Binary files /dev/null and b/public/images/pokemon/icons/1/133-partner.png differ diff --git a/public/images/pokemon/icons/1/133s-partner.png b/public/images/pokemon/icons/1/133s-partner.png new file mode 100644 index 00000000000..4cc0f1c73b4 Binary files /dev/null and b/public/images/pokemon/icons/1/133s-partner.png differ diff --git a/public/images/pokemon/icons/1/25-partner.png b/public/images/pokemon/icons/1/25-partner.png new file mode 100644 index 00000000000..5b00a2025a3 Binary files /dev/null and b/public/images/pokemon/icons/1/25-partner.png differ diff --git a/public/images/pokemon/icons/1/25s-partner.png b/public/images/pokemon/icons/1/25s-partner.png new file mode 100644 index 00000000000..58e2b3a35d1 Binary files /dev/null and b/public/images/pokemon/icons/1/25s-partner.png differ diff --git a/public/images/pokemon/shiny/133-partner.json b/public/images/pokemon/shiny/133-partner.json new file mode 100644 index 00000000000..5d0e112e570 --- /dev/null +++ b/public/images/pokemon/shiny/133-partner.json @@ -0,0 +1,2834 @@ +{ + "textures": [ + { + "image": "133-partner.png", + "format": "RGBA8888", + "size": { + "w": 245, + "h": 245 + }, + "scale": 1, + "frames": [ + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 0, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 0, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 35, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 35, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 70, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 70, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 105, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 35, + "h": 44 + }, + "frame": { + "x": 105, + "y": 0, + "w": 35, + "h": 44 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 140, + "y": 0, + "w": 44, + "h": 45 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 45, + "h": 45 + }, + "frame": { + "x": 184, + "y": 0, + "w": 45, + "h": 45 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 36, + "h": 45 + }, + "frame": { + "x": 0, + "y": 44, + "w": 36, + "h": 45 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 34, + "h": 45 + }, + "frame": { + "x": 36, + "y": 44, + "w": 34, + "h": 45 + } + }, + { + "filename": "0126.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 70, + "y": 44, + "w": 44, + "h": 45 + } + }, + { + "filename": "0127.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 44, + "h": 45 + }, + "frame": { + "x": 70, + "y": 44, + "w": 44, + "h": 45 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 42, + "h": 46 + }, + "frame": { + "x": 114, + "y": 45, + "w": 42, + "h": 46 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 43, + "h": 46 + }, + "frame": { + "x": 156, + "y": 45, + "w": 43, + "h": 46 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 199, + "y": 45, + "w": 44, + "h": 46 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 36, + "h": 46 + }, + "frame": { + "x": 0, + "y": 89, + "w": 36, + "h": 46 + } + }, + { + "filename": "0125.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 36, + "y": 89, + "w": 44, + "h": 46 + } + }, + { + "filename": "0128.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 80, + "y": 91, + "w": 44, + "h": 46 + } + }, + { + "filename": "0129.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 44, + "h": 46 + }, + "frame": { + "x": 80, + "y": 91, + "w": 44, + "h": 46 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0118.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0119.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 39, + "h": 47 + }, + "frame": { + "x": 124, + "y": 91, + "w": 39, + "h": 47 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 163, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 204, + "y": 91, + "w": 41, + "h": 47 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 135, + "w": 42, + "h": 47 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 42, + "y": 135, + "w": 38, + "h": 47 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 42, + "y": 135, + "w": 38, + "h": 47 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 80, + "y": 137, + "w": 42, + "h": 47 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 122, + "y": 138, + "w": 42, + "h": 47 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 164, + "y": 138, + "w": 38, + "h": 47 + } + }, + { + "filename": "0117.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 38, + "h": 47 + }, + "frame": { + "x": 164, + "y": 138, + "w": 38, + "h": 47 + } + }, + { + "filename": "0120.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 202, + "y": 138, + "w": 41, + "h": 47 + } + }, + { + "filename": "0121.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 182, + "w": 42, + "h": 47 + } + }, + { + "filename": "0122.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 0, + "y": 182, + "w": 42, + "h": 47 + } + }, + { + "filename": "0123.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 44, + "h": 47 + }, + "frame": { + "x": 42, + "y": 184, + "w": 44, + "h": 47 + } + }, + { + "filename": "0124.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 44, + "h": 47 + }, + "frame": { + "x": 42, + "y": 184, + "w": 44, + "h": 47 + } + }, + { + "filename": "0130.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 44, + "h": 47 + }, + "frame": { + "x": 86, + "y": 185, + "w": 44, + "h": 47 + } + }, + { + "filename": "0131.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 130, + "y": 185, + "w": 42, + "h": 47 + } + }, + { + "filename": "0132.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 42, + "h": 47 + }, + "frame": { + "x": 130, + "y": 185, + "w": 42, + "h": 47 + } + }, + { + "filename": "0133.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 172, + "y": 185, + "w": 41, + "h": 47 + } + }, + { + "filename": "0134.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 49, + "h": 47 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 41, + "h": 47 + }, + "frame": { + "x": 172, + "y": 185, + "w": 41, + "h": 47 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:39a6c90c2230b79cc97f35268535285c:583262468c88ec48aa6c02458d89d8c8:4e938f9dc8bce1cd7822677c800d242b$" + } +} diff --git a/public/images/pokemon/shiny/133-partner.png b/public/images/pokemon/shiny/133-partner.png new file mode 100644 index 00000000000..01352931fca Binary files /dev/null and b/public/images/pokemon/shiny/133-partner.png differ diff --git a/public/images/pokemon/shiny/25-partner.json b/public/images/pokemon/shiny/25-partner.json new file mode 100644 index 00000000000..1ae56902c87 --- /dev/null +++ b/public/images/pokemon/shiny/25-partner.json @@ -0,0 +1,2456 @@ +{ + "textures": [ + { + "image": "25-partner.png", + "format": "RGBA8888", + "size": { + "w": 315, + "h": 315 + }, + "scale": 1, + "frames": [ + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 0, + "y": 0, + "w": 46, + "h": 46 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 0, + "y": 0, + "w": 46, + "h": 46 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 46, + "w": 50, + "h": 43 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 46, + "w": 50, + "h": 43 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 46, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 46, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 45, + "h": 46 + }, + "frame": { + "x": 50, + "y": 43, + "w": 45, + "h": 46 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 45, + "h": 46 + }, + "frame": { + "x": 50, + "y": 43, + "w": 45, + "h": 46 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 45, + "h": 46 + }, + "frame": { + "x": 50, + "y": 43, + "w": 45, + "h": 46 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 95, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 95, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 96, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 96, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 138, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 138, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 145, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 145, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 181, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 181, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 194, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 194, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 224, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 224, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 243, + "y": 0, + "w": 48, + "h": 43 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 243, + "y": 0, + "w": 48, + "h": 43 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 267, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 267, + "y": 43, + "w": 43, + "h": 46 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 0, + "y": 89, + "w": 49, + "h": 44 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 0, + "y": 89, + "w": 49, + "h": 44 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 49, + "y": 89, + "w": 49, + "h": 44 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 49, + "y": 89, + "w": 49, + "h": 44 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 98, + "y": 89, + "w": 43, + "h": 46 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 98, + "y": 89, + "w": 43, + "h": 46 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 43, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 43, + "y": 133, + "w": 43, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 141, + "y": 89, + "w": 43, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 141, + "y": 89, + "w": 43, + "h": 46 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 184, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 184, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 226, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 226, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 268, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 268, + "y": 89, + "w": 42, + "h": 46 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 86, + "y": 135, + "w": 49, + "h": 44 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 86, + "y": 135, + "w": 49, + "h": 44 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 135, + "y": 135, + "w": 49, + "h": 44 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 135, + "y": 135, + "w": 49, + "h": 44 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 184, + "y": 135, + "w": 42, + "h": 46 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 184, + "y": 135, + "w": 42, + "h": 46 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 226, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 226, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 267, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 267, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 267, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 267, + "y": 135, + "w": 41, + "h": 46 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 0, + "y": 179, + "w": 48, + "h": 44 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 0, + "y": 179, + "w": 48, + "h": 44 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 48, + "y": 179, + "w": 47, + "h": 44 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 48, + "y": 179, + "w": 47, + "h": 44 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 95, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 95, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 223, + "w": 47, + "h": 44 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 223, + "w": 47, + "h": 44 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 47, + "y": 223, + "w": 41, + "h": 46 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 267, + "w": 47, + "h": 44 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 267, + "w": 47, + "h": 44 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 267, + "w": 47, + "h": 44 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 0, + "y": 267, + "w": 47, + "h": 44 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 136, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 136, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 136, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 136, + "y": 179, + "w": 41, + "h": 46 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 177, + "y": 181, + "w": 48, + "h": 43 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 177, + "y": 181, + "w": 48, + "h": 43 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 225, + "y": 181, + "w": 41, + "h": 46 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 225, + "y": 181, + "w": 41, + "h": 46 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 225, + "y": 181, + "w": 41, + "h": 46 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 225, + "y": 181, + "w": 41, + "h": 46 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 177, + "y": 224, + "w": 41, + "h": 46 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 177, + "y": 224, + "w": 41, + "h": 46 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 177, + "y": 224, + "w": 41, + "h": 46 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 177, + "y": 224, + "w": 41, + "h": 46 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 88, + "y": 225, + "w": 46, + "h": 44 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 88, + "y": 225, + "w": 46, + "h": 44 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 134, + "y": 225, + "w": 41, + "h": 46 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 41, + "h": 46 + }, + "frame": { + "x": 134, + "y": 225, + "w": 41, + "h": 46 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 47, + "y": 269, + "w": 48, + "h": 43 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 47, + "y": 269, + "w": 48, + "h": 43 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 218, + "y": 227, + "w": 48, + "h": 43 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 218, + "y": 227, + "w": 48, + "h": 43 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 266, + "y": 181, + "w": 46, + "h": 44 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 266, + "y": 181, + "w": 46, + "h": 44 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 266, + "y": 225, + "w": 46, + "h": 44 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 266, + "y": 225, + "w": 46, + "h": 44 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 47, + "h": 43 + }, + "frame": { + "x": 266, + "y": 269, + "w": 47, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 47, + "h": 43 + }, + "frame": { + "x": 266, + "y": 269, + "w": 47, + "h": 43 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 175, + "y": 270, + "w": 45, + "h": 44 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 175, + "y": 270, + "w": 45, + "h": 44 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 220, + "y": 270, + "w": 45, + "h": 44 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 220, + "y": 270, + "w": 45, + "h": 44 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 95, + "y": 271, + "w": 45, + "h": 44 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 50, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 45, + "h": 44 + }, + "frame": { + "x": 95, + "y": 271, + "w": 45, + "h": 44 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:239dc9087257cf612b8033daa61c26f6:0a7b6d5d19d801ba0223fe8a8ce12706:d7d9e845c71962a58076b5efe962284e$" + } +} diff --git a/public/images/pokemon/shiny/25-partner.png b/public/images/pokemon/shiny/25-partner.png new file mode 100644 index 00000000000..0e961ba8338 Binary files /dev/null and b/public/images/pokemon/shiny/25-partner.png differ diff --git a/public/images/pokemon/shiny/female/25-partner.json b/public/images/pokemon/shiny/female/25-partner.json new file mode 100644 index 00000000000..b08b66a18b1 --- /dev/null +++ b/public/images/pokemon/shiny/female/25-partner.json @@ -0,0 +1,2456 @@ +{ + "textures": [ + { + "image": "25-partner.png", + "format": "RGBA8888", + "size": { + "w": 330, + "h": 330 + }, + "scale": 1, + "frames": [ + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 51, + "h": 43 + }, + "frame": { + "x": 50, + "y": 0, + "w": 51, + "h": 43 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 51, + "h": 43 + }, + "frame": { + "x": 50, + "y": 0, + "w": 51, + "h": 43 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 101, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 101, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 150, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 150, + "y": 0, + "w": 50, + "h": 43 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 200, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 200, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 249, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 249, + "y": 0, + "w": 49, + "h": 43 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 43, + "w": 50, + "h": 43 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 50, + "h": 43 + }, + "frame": { + "x": 0, + "y": 43, + "w": 50, + "h": 43 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 51, + "h": 43 + }, + "frame": { + "x": 50, + "y": 43, + "w": 51, + "h": 43 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 51, + "h": 43 + }, + "frame": { + "x": 50, + "y": 43, + "w": 51, + "h": 43 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 101, + "y": 43, + "w": 48, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 3, + "w": 48, + "h": 43 + }, + "frame": { + "x": 101, + "y": 43, + "w": 48, + "h": 43 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 149, + "y": 43, + "w": 49, + "h": 43 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 3, + "w": 49, + "h": 43 + }, + "frame": { + "x": 149, + "y": 43, + "w": 49, + "h": 43 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 198, + "y": 43, + "w": 48, + "h": 44 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 198, + "y": 43, + "w": 48, + "h": 44 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 246, + "y": 43, + "w": 50, + "h": 44 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 246, + "y": 43, + "w": 50, + "h": 44 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 0, + "y": 86, + "w": 48, + "h": 44 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 0, + "y": 86, + "w": 48, + "h": 44 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 48, + "y": 86, + "w": 47, + "h": 44 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 48, + "y": 86, + "w": 47, + "h": 44 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 95, + "y": 86, + "w": 50, + "h": 44 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 95, + "y": 86, + "w": 50, + "h": 44 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 145, + "y": 86, + "w": 47, + "h": 44 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 145, + "y": 86, + "w": 47, + "h": 44 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 192, + "y": 87, + "w": 46, + "h": 44 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 192, + "y": 87, + "w": 46, + "h": 44 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 238, + "y": 87, + "w": 50, + "h": 44 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 238, + "y": 87, + "w": 50, + "h": 44 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 288, + "y": 87, + "w": 42, + "h": 46 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 288, + "y": 87, + "w": 42, + "h": 46 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 0, + "y": 130, + "w": 46, + "h": 44 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 0, + "y": 130, + "w": 46, + "h": 44 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 46, + "y": 130, + "w": 48, + "h": 44 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 46, + "y": 130, + "w": 48, + "h": 44 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 46, + "y": 130, + "w": 48, + "h": 44 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 48, + "h": 44 + }, + "frame": { + "x": 46, + "y": 130, + "w": 48, + "h": 44 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 94, + "y": 130, + "w": 50, + "h": 44 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 50, + "h": 44 + }, + "frame": { + "x": 94, + "y": 130, + "w": 50, + "h": 44 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 144, + "y": 130, + "w": 47, + "h": 44 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 47, + "h": 44 + }, + "frame": { + "x": 144, + "y": 130, + "w": 47, + "h": 44 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 191, + "y": 131, + "w": 49, + "h": 44 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 49, + "h": 44 + }, + "frame": { + "x": 191, + "y": 131, + "w": 49, + "h": 44 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 240, + "y": 131, + "w": 46, + "h": 44 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 46, + "h": 44 + }, + "frame": { + "x": 240, + "y": 131, + "w": 46, + "h": 44 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 286, + "y": 133, + "w": 44, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 286, + "y": 133, + "w": 44, + "h": 46 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 44, + "h": 46 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 44, + "h": 46 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 44, + "y": 174, + "w": 42, + "h": 46 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 44, + "y": 174, + "w": 42, + "h": 46 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 44, + "y": 174, + "w": 42, + "h": 46 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 44, + "y": 174, + "w": 42, + "h": 46 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 86, + "y": 174, + "w": 43, + "h": 46 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 86, + "y": 174, + "w": 43, + "h": 46 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 129, + "y": 174, + "w": 44, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 129, + "y": 174, + "w": 44, + "h": 46 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 173, + "y": 175, + "w": 44, + "h": 46 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 173, + "y": 175, + "w": 44, + "h": 46 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 217, + "y": 175, + "w": 43, + "h": 46 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 217, + "y": 175, + "w": 43, + "h": 46 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 260, + "y": 179, + "w": 44, + "h": 46 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 260, + "y": 179, + "w": 44, + "h": 46 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 220, + "w": 43, + "h": 46 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 220, + "w": 43, + "h": 46 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 220, + "w": 42, + "h": 46 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 127, + "y": 220, + "w": 44, + "h": 46 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 127, + "y": 220, + "w": 44, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 127, + "y": 220, + "w": 44, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 127, + "y": 220, + "w": 44, + "h": 46 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 171, + "y": 221, + "w": 42, + "h": 46 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 171, + "y": 221, + "w": 42, + "h": 46 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 171, + "y": 221, + "w": 42, + "h": 46 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 171, + "y": 221, + "w": 42, + "h": 46 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 213, + "y": 221, + "w": 43, + "h": 46 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 213, + "y": 221, + "w": 43, + "h": 46 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 256, + "y": 225, + "w": 44, + "h": 46 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 44, + "h": 46 + }, + "frame": { + "x": 256, + "y": 225, + "w": 44, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 266, + "w": 43, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 266, + "w": 43, + "h": 46 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 43, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 85, + "y": 266, + "w": 42, + "h": 46 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 127, + "y": 266, + "w": 43, + "h": 46 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 43, + "h": 46 + }, + "frame": { + "x": 127, + "y": 266, + "w": 43, + "h": 46 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 47, + "h": 46 + }, + "frame": { + "x": 170, + "y": 267, + "w": 47, + "h": 46 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 47, + "h": 46 + }, + "frame": { + "x": 170, + "y": 267, + "w": 47, + "h": 46 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 217, + "y": 271, + "w": 46, + "h": 46 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 217, + "y": 271, + "w": 46, + "h": 46 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 46, + "h": 46 + }, + "frame": { + "x": 217, + "y": 271, + "w": 46, + "h": 46 + } + }, + { + "filename": "0115.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 263, + "y": 271, + "w": 42, + "h": 46 + } + }, + { + "filename": "0116.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 42, + "h": 46 + }, + "frame": { + "x": 263, + "y": 271, + "w": 42, + "h": 46 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:a8eb580b04fb8bb2d490c8d497e097a7:a3da2c0b291ef91b4a6f8e0d1a1dd17f:d7d9e845c71962a58076b5efe962284e$" + } +} diff --git a/public/images/pokemon/shiny/female/25-partner.png b/public/images/pokemon/shiny/female/25-partner.png new file mode 100644 index 00000000000..030091ce605 Binary files /dev/null and b/public/images/pokemon/shiny/female/25-partner.png differ diff --git a/public/images/pokemon/variant/_masterlist.json b/public/images/pokemon/variant/_masterlist.json index adca124fc89..bc03c8cc517 100644 --- a/public/images/pokemon/variant/_masterlist.json +++ b/public/images/pokemon/variant/_masterlist.json @@ -1745,27 +1745,27 @@ 1 ], "641-incarnate": [ - 1, + 0, 0, 0 ], "641-therian": [ - 1, + 0, 0, 0 ], "642-incarnate": [ - 1, + 0, 0, 0 ], "642-therian": [ - 1, + 0, 0, 0 ], "645-incarnate": [ - 1, + 0, 0, 0 ], @@ -4608,32 +4608,32 @@ 1 ], "641-incarnate": [ - 1, + 0, 0, 0 ], "641-therian": [ - 1, + 0, 0, 0 ], "642-incarnate": [ - 1, + 0, 0, 0 ], "642-therian": [ - 1, + 0, 0, 0 ], "645-incarnate": [ - 1, + 0, 0, 0 ], "645-therian": [ - 1, + 0, 0, 0 ], diff --git a/public/images/pokemon_icons_1.json b/public/images/pokemon_icons_1.json index dfae7b4d57d..e313cec5d7d 100644 --- a/public/images/pokemon_icons_1.json +++ b/public/images/pokemon_icons_1.json @@ -4,8 +4,8 @@ "image": "pokemon_icons_1.png", "format": "RGBA8888", "size": { - "w": 256, - "h": 781 + "w": 255, + "h": 790 }, "scale": 1, "frames": [ @@ -639,27 +639,6 @@ "h": 27 } }, - { - "filename": "48", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 17, - "h": 26 - }, - "frame": { - "x": 239, - "y": 0, - "w": 17, - "h": 26 - } - }, { "filename": "131-gigantamax", "rotated": false, @@ -744,6 +723,48 @@ "h": 28 } }, + { + "filename": "74", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 13, + "w": 24, + "h": 15 + }, + "frame": { + "x": 0, + "y": 775, + "w": 24, + "h": 15 + } + }, + { + "filename": "66", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 16, + "h": 20 + }, + "frame": { + "x": 239, + "y": 0, + "w": 16, + "h": 20 + } + }, { "filename": "34", "rotated": false, @@ -850,7 +871,7 @@ } }, { - "filename": "89", + "filename": "80-mega", "rotated": false, "trimmed": true, "sourceSize": { @@ -858,16 +879,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 3, - "w": 26, - "h": 25 + "x": 7, + "y": 2, + "w": 25, + "h": 26 }, "frame": { "x": 230, "y": 27, - "w": 26, - "h": 25 + "w": 25, + "h": 26 } }, { @@ -1011,8 +1032,8 @@ "h": 27 }, "frame": { - "x": 223, - "y": 52, + "x": 34, + "y": 76, "w": 30, "h": 27 } @@ -1033,28 +1054,7 @@ }, "frame": { "x": 34, - "y": 76, - "w": 29, - "h": 28 - } - }, - { - "filename": "130s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 2, - "w": 29, - "h": 28 - }, - "frame": { - "x": 63, - "y": 76, + "y": 103, "w": 29, "h": 28 } @@ -1074,35 +1074,14 @@ "h": 27 }, "frame": { - "x": 34, - "y": 104, + "x": 64, + "y": 76, "w": 29, "h": 27 } }, { - "filename": "59s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 29, - "h": 27 - }, - "frame": { - "x": 63, - "y": 104, - "w": 29, - "h": 27 - } - }, - { - "filename": "133-gigantamax", + "filename": "130s", "rotated": false, "trimmed": true, "sourceSize": { @@ -1111,15 +1090,15 @@ }, "spriteSourceSize": { "x": 6, - "y": 0, - "w": 27, - "h": 30 + "y": 2, + "w": 29, + "h": 28 }, "frame": { - "x": 92, - "y": 77, - "w": 27, - "h": 30 + "x": 63, + "y": 103, + "w": 29, + "h": 28 } }, { @@ -1137,8 +1116,8 @@ "h": 26 }, "frame": { - "x": 92, - "y": 107, + "x": 223, + "y": 53, "w": 29, "h": 26 } @@ -1158,14 +1137,14 @@ "h": 26 }, "frame": { - "x": 119, - "y": 78, + "x": 93, + "y": 77, "w": 29, "h": 26 } }, { - "filename": "78", + "filename": "59s", "rotated": false, "trimmed": true, "sourceSize": { @@ -1176,17 +1155,17 @@ "x": 7, "y": 2, "w": 29, - "h": 26 + "h": 27 }, "frame": { - "x": 148, - "y": 78, + "x": 92, + "y": 103, "w": 29, - "h": 26 + "h": 27 } }, { - "filename": "133s-gigantamax", + "filename": "74s", "rotated": false, "trimmed": true, "sourceSize": { @@ -1194,37 +1173,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 27, - "h": 30 + "x": 8, + "y": 13, + "w": 24, + "h": 15 }, "frame": { - "x": 121, - "y": 104, - "w": 27, - "h": 30 - } - }, - { - "filename": "78s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 29, - "h": 26 - }, - "frame": { - "x": 148, - "y": 104, - "w": 29, - "h": 26 + "x": 24, + "y": 775, + "w": 24, + "h": 15 } }, { @@ -1242,12 +1200,33 @@ "h": 25 }, "frame": { - "x": 177, - "y": 79, + "x": 122, + "y": 78, "w": 30, "h": 25 } }, + { + "filename": "78", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 2, + "w": 29, + "h": 26 + }, + "frame": { + "x": 121, + "y": 103, + "w": 29, + "h": 26 + } + }, { "filename": "99s", "rotated": false, @@ -1263,12 +1242,33 @@ "h": 25 }, "frame": { - "x": 177, - "y": 104, + "x": 152, + "y": 78, "w": 30, "h": 25 } }, + { + "filename": "78s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 2, + "w": 29, + "h": 26 + }, + "frame": { + "x": 150, + "y": 103, + "w": 29, + "h": 26 + } + }, { "filename": "3", "rotated": false, @@ -1284,33 +1284,12 @@ "h": 24 }, "frame": { - "x": 207, + "x": 182, "y": 79, "w": 30, "h": 24 } }, - { - "filename": "30", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 19, - "h": 22 - }, - "frame": { - "x": 237, - "y": 79, - "w": 19, - "h": 22 - } - }, { "filename": "3s", "rotated": false, @@ -1326,14 +1305,14 @@ "h": 24 }, "frame": { - "x": 207, + "x": 179, "y": 103, "w": 30, "h": 24 } }, { - "filename": "30s", + "filename": "64", "rotated": false, "trimmed": true, "sourceSize": { @@ -1341,37 +1320,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 19, - "h": 22 + "x": 5, + "y": 3, + "w": 29, + "h": 25 }, "frame": { - "x": 237, - "y": 101, - "w": 19, - "h": 22 - } - }, - { - "filename": "33", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 19, - "h": 22 - }, - "frame": { - "x": 237, - "y": 123, - "w": 19, - "h": 22 + "x": 212, + "y": 79, + "w": 29, + "h": 25 } }, { @@ -1389,12 +1347,75 @@ "h": 22 }, "frame": { - "x": 207, - "y": 127, + "x": 209, + "y": 104, "w": 30, "h": 22 } }, + { + "filename": "10", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 12, + "w": 14, + "h": 16 + }, + "frame": { + "x": 241, + "y": 79, + "w": 14, + "h": 16 + } + }, + { + "filename": "66s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 16, + "h": 20 + }, + "frame": { + "x": 239, + "y": 104, + "w": 16, + "h": 20 + } + }, + { + "filename": "13", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 16, + "h": 17 + }, + "frame": { + "x": 239, + "y": 124, + "w": 16, + "h": 17 + } + }, { "filename": "22s", "rotated": false, @@ -1410,54 +1431,12 @@ "h": 22 }, "frame": { - "x": 177, - "y": 129, + "x": 209, + "y": 126, "w": 30, "h": 22 } }, - { - "filename": "62", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 29, - "h": 21 - }, - "frame": { - "x": 148, - "y": 130, - "w": 29, - "h": 21 - } - }, - { - "filename": "33s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 19, - "h": 22 - }, - "frame": { - "x": 237, - "y": 145, - "w": 19, - "h": 22 - } - }, { "filename": "115-mega", "rotated": false, @@ -1473,14 +1452,14 @@ "h": 22 }, "frame": { - "x": 207, - "y": 149, + "x": 179, + "y": 127, "w": 30, "h": 22 } }, { - "filename": "141", + "filename": "13s", "rotated": false, "trimmed": true, "sourceSize": { @@ -1488,16 +1467,58 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 19, - "h": 21 + "x": 12, + "y": 11, + "w": 16, + "h": 17 }, "frame": { - "x": 237, - "y": 167, - "w": 19, - "h": 21 + "x": 239, + "y": 141, + "w": 16, + "h": 17 + } + }, + { + "filename": "115s-mega", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 30, + "h": 22 + }, + "frame": { + "x": 209, + "y": 148, + "w": 30, + "h": 22 + } + }, + { + "filename": "101", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 12, + "w": 16, + "h": 16 + }, + "frame": { + "x": 239, + "y": 158, + "w": 16, + "h": 16 } }, { @@ -1521,6 +1542,48 @@ "h": 30 } }, + { + "filename": "15-mega", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 3, + "w": 27, + "h": 26 + }, + "frame": { + "x": 29, + "y": 749, + "w": 27, + "h": 26 + } + }, + { + "filename": "81", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 12, + "w": 23, + "h": 15 + }, + "frame": { + "x": 48, + "y": 775, + "w": 23, + "h": 15 + } + }, { "filename": "6s-gigantamax", "rotated": false, @@ -1536,14 +1599,14 @@ "h": 30 }, "frame": { - "x": 29, - "y": 749, + "x": 32, + "y": 133, "w": 24, "h": 30 } }, { - "filename": "25-gigantamax", + "filename": "133-gigantamax", "rotated": false, "trimmed": true, "sourceSize": { @@ -1551,41 +1614,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, + "x": 6, "y": 0, - "w": 21, + "w": 27, "h": 30 }, "frame": { - "x": 32, - "y": 133, - "w": 21, - "h": 30 - } - }, - { - "filename": "64", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 5, - "y": 3, - "w": 29, - "h": 25 - }, - "frame": { - "x": 53, + "x": 56, "y": 131, - "w": 29, - "h": 25 + "w": 27, + "h": 30 } }, { - "filename": "25s-gigantamax", + "filename": "133s-gigantamax", "rotated": false, "trimmed": true, "sourceSize": { @@ -1593,20 +1635,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, + "x": 6, "y": 0, - "w": 21, + "w": 27, "h": 30 }, "frame": { "x": 32, "y": 163, - "w": 21, + "w": 27, "h": 30 } }, { - "filename": "64s", + "filename": "15s-mega", "rotated": false, "trimmed": true, "sourceSize": { @@ -1614,16 +1656,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 5, + "x": 7, "y": 3, - "w": 29, - "h": 25 + "w": 27, + "h": 26 }, "frame": { - "x": 53, - "y": 156, - "w": 29, - "h": 25 + "x": 32, + "y": 193, + "w": 27, + "h": 26 } }, { @@ -1642,7 +1684,7 @@ }, "frame": { "x": 32, - "y": 193, + "y": 219, "w": 23, "h": 30 } @@ -1663,11 +1705,53 @@ }, "frame": { "x": 32, - "y": 223, + "y": 249, "w": 23, "h": 30 } }, + { + "filename": "25-gigantamax", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 21, + "h": 30 + }, + "frame": { + "x": 32, + "y": 279, + "w": 21, + "h": 30 + } + }, + { + "filename": "25s-gigantamax", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 21, + "h": 30 + }, + "frame": { + "x": 59, + "y": 161, + "w": 21, + "h": 30 + } + }, { "filename": "150-mega-y", "rotated": false, @@ -1683,306 +1767,12 @@ "h": 30 }, "frame": { - "x": 32, - "y": 253, + "x": 59, + "y": 191, "w": 20, "h": 30 } }, - { - "filename": "150s-mega-y", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 0, - "w": 20, - "h": 30 - }, - "frame": { - "x": 32, - "y": 283, - "w": 20, - "h": 30 - } - }, - { - "filename": "15-mega", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 27, - "h": 26 - }, - "frame": { - "x": 31, - "y": 313, - "w": 27, - "h": 26 - } - }, - { - "filename": "15s-mega", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 27, - "h": 26 - }, - "frame": { - "x": 31, - "y": 339, - "w": 27, - "h": 26 - } - }, - { - "filename": "85", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 5, - "y": 3, - "w": 29, - "h": 25 - }, - "frame": { - "x": 82, - "y": 133, - "w": 29, - "h": 25 - } - }, - { - "filename": "85s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 5, - "y": 3, - "w": 29, - "h": 25 - }, - "frame": { - "x": 82, - "y": 158, - "w": 29, - "h": 25 - } - }, - { - "filename": "97", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 27, - "h": 26 - }, - "frame": { - "x": 111, - "y": 134, - "w": 27, - "h": 26 - } - }, - { - "filename": "57", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 28, - "h": 23 - }, - "frame": { - "x": 111, - "y": 160, - "w": 28, - "h": 23 - } - }, - { - "filename": "97s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 27, - "h": 26 - }, - "frame": { - "x": 55, - "y": 181, - "w": 27, - "h": 26 - } - }, - { - "filename": "115s-mega", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 30, - "h": 22 - }, - "frame": { - "x": 82, - "y": 183, - "w": 30, - "h": 22 - } - }, - { - "filename": "80-mega", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 25, - "h": 26 - }, - "frame": { - "x": 55, - "y": 207, - "w": 25, - "h": 26 - } - }, - { - "filename": "57s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 28, - "h": 23 - }, - "frame": { - "x": 112, - "y": 183, - "w": 28, - "h": 23 - } - }, - { - "filename": "9", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 25, - "h": 24 - }, - "frame": { - "x": 55, - "y": 233, - "w": 25, - "h": 24 - } - }, - { - "filename": "71", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 28, - "h": 23 - }, - "frame": { - "x": 52, - "y": 257, - "w": 28, - "h": 23 - } - }, - { - "filename": "71s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 28, - "h": 23 - }, - "frame": { - "x": 52, - "y": 280, - "w": 28, - "h": 23 - } - }, { "filename": "80s-mega", "rotated": false, @@ -1998,12 +1788,75 @@ "h": 26 }, "frame": { - "x": 58, - "y": 303, + "x": 55, + "y": 221, "w": 25, "h": 26 } }, + { + "filename": "97", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 3, + "w": 27, + "h": 26 + }, + "frame": { + "x": 55, + "y": 247, + "w": 27, + "h": 26 + } + }, + { + "filename": "150s-mega-y", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 20, + "h": 30 + }, + "frame": { + "x": 83, + "y": 131, + "w": 20, + "h": 30 + } + }, + { + "filename": "97s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 3, + "w": 27, + "h": 26 + }, + "frame": { + "x": 80, + "y": 161, + "w": 27, + "h": 26 + } + }, { "filename": "109", "rotated": false, @@ -2019,14 +1872,350 @@ "h": 26 }, "frame": { - "x": 58, - "y": 329, + "x": 103, + "y": 130, "w": 25, "h": 26 } }, { - "filename": "9s", + "filename": "64s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 5, + "y": 3, + "w": 29, + "h": 25 + }, + "frame": { + "x": 128, + "y": 129, + "w": 29, + "h": 25 + } + }, + { + "filename": "25-beauty-cosplay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 3, + "w": 22, + "h": 25 + }, + "frame": { + "x": 157, + "y": 129, + "w": 22, + "h": 25 + } + }, + { + "filename": "109s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 25, + "h": 26 + }, + "frame": { + "x": 107, + "y": 156, + "w": 25, + "h": 26 + } + }, + { + "filename": "85", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 5, + "y": 3, + "w": 29, + "h": 25 + }, + "frame": { + "x": 132, + "y": 154, + "w": 29, + "h": 25 + } + }, + { + "filename": "25s-beauty-cosplay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 3, + "w": 22, + "h": 25 + }, + "frame": { + "x": 161, + "y": 154, + "w": 22, + "h": 25 + } + }, + { + "filename": "89", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 3, + "w": 26, + "h": 25 + }, + "frame": { + "x": 183, + "y": 149, + "w": 26, + "h": 25 + } + }, + { + "filename": "56", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 8, + "w": 28, + "h": 20 + }, + "frame": { + "x": 55, + "y": 273, + "w": 28, + "h": 20 + } + }, + { + "filename": "62", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 29, + "h": 21 + }, + "frame": { + "x": 53, + "y": 293, + "w": 29, + "h": 21 + } + }, + { + "filename": "62s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 29, + "h": 21 + }, + "frame": { + "x": 209, + "y": 170, + "w": 29, + "h": 21 + } + }, + { + "filename": "48", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 17, + "h": 26 + }, + "frame": { + "x": 238, + "y": 174, + "w": 17, + "h": 26 + } + }, + { + "filename": "25-partner", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 26, + "h": 22 + }, + "frame": { + "x": 183, + "y": 174, + "w": 26, + "h": 22 + } + }, + { + "filename": "85s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 5, + "y": 3, + "w": 29, + "h": 25 + }, + "frame": { + "x": 209, + "y": 191, + "w": 29, + "h": 25 + } + }, + { + "filename": "48s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 17, + "h": 26 + }, + "frame": { + "x": 238, + "y": 200, + "w": 17, + "h": 26 + } + }, + { + "filename": "142", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 29, + "h": 22 + }, + "frame": { + "x": 132, + "y": 179, + "w": 29, + "h": 22 + } + }, + { + "filename": "5", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 161, + "y": 179, + "w": 22, + "h": 23 + } + }, + { + "filename": "25s-partner", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 26, + "h": 22 + }, + "frame": { + "x": 183, + "y": 196, + "w": 26, + "h": 22 + } + }, + { + "filename": "9", "rotated": false, "trimmed": true, "sourceSize": { @@ -2040,8 +2229,8 @@ "h": 24 }, "frame": { - "x": 58, - "y": 355, + "x": 107, + "y": 182, "w": 25, "h": 24 } @@ -2061,369 +2250,12 @@ "h": 22 }, "frame": { - "x": 31, - "y": 365, + "x": 80, + "y": 187, "w": 27, "h": 22 } }, - { - "filename": "89s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 3, - "w": 26, - "h": 25 - }, - "frame": { - "x": 30, - "y": 387, - "w": 26, - "h": 25 - } - }, - { - "filename": "109s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 25, - "h": 26 - }, - "frame": { - "x": 30, - "y": 412, - "w": 25, - "h": 26 - } - }, - { - "filename": "26", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 25, - "h": 24 - }, - "frame": { - "x": 30, - "y": 438, - "w": 25, - "h": 24 - } - }, - { - "filename": "26s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 25, - "h": 24 - }, - "frame": { - "x": 30, - "y": 462, - "w": 25, - "h": 24 - } - }, - { - "filename": "91", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 25, - "h": 24 - }, - "frame": { - "x": 30, - "y": 486, - "w": 25, - "h": 24 - } - }, - { - "filename": "91s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 25, - "h": 24 - }, - "frame": { - "x": 30, - "y": 510, - "w": 25, - "h": 24 - } - }, - { - "filename": "143", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 27, - "h": 24 - }, - "frame": { - "x": 30, - "y": 534, - "w": 27, - "h": 24 - } - }, - { - "filename": "143s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 27, - "h": 24 - }, - "frame": { - "x": 30, - "y": 558, - "w": 27, - "h": 24 - } - }, - { - "filename": "80", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 27, - "h": 23 - }, - "frame": { - "x": 30, - "y": 582, - "w": 27, - "h": 23 - } - }, - { - "filename": "80s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 27, - "h": 23 - }, - "frame": { - "x": 30, - "y": 605, - "w": 27, - "h": 23 - } - }, - { - "filename": "68s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 27, - "h": 22 - }, - "frame": { - "x": 30, - "y": 628, - "w": 27, - "h": 22 - } - }, - { - "filename": "12", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 3, - "w": 24, - "h": 24 - }, - "frame": { - "x": 31, - "y": 650, - "w": 24, - "h": 24 - } - }, - { - "filename": "12s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 3, - "w": 24, - "h": 24 - }, - "frame": { - "x": 31, - "y": 674, - "w": 24, - "h": 24 - } - }, - { - "filename": "20", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 25, - "h": 21 - }, - "frame": { - "x": 31, - "y": 698, - "w": 25, - "h": 21 - } - }, - { - "filename": "15", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 25, - "h": 23 - }, - "frame": { - "x": 58, - "y": 379, - "w": 25, - "h": 23 - } - }, - { - "filename": "56", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 28, - "h": 20 - }, - "frame": { - "x": 56, - "y": 402, - "w": 28, - "h": 20 - } - }, - { - "filename": "142", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 29, - "h": 22 - }, - "frame": { - "x": 55, - "y": 422, - "w": 29, - "h": 22 - } - }, { "filename": "142s", "rotated": false, @@ -2439,14 +2271,14 @@ "h": 22 }, "frame": { - "x": 55, - "y": 444, + "x": 209, + "y": 216, "w": 29, "h": 22 } }, { - "filename": "62s", + "filename": "40", "rotated": false, "trimmed": true, "sourceSize": { @@ -2454,62 +2286,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 29, - "h": 21 + "x": 12, + "y": 3, + "w": 17, + "h": 25 }, "frame": { - "x": 55, - "y": 466, - "w": 29, - "h": 21 + "x": 238, + "y": 226, + "w": 17, + "h": 25 } }, { - "filename": "98", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 28, - "h": 21 - }, - "frame": { - "x": 55, - "y": 487, - "w": 28, - "h": 21 - } - }, - { - "filename": "98s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 28, - "h": 21 - }, - "frame": { - "x": 55, - "y": 508, - "w": 28, - "h": 21 - } - }, - { - "filename": "15s", + "filename": "89s", "rotated": false, "trimmed": true, "sourceSize": { @@ -2518,19 +2308,40 @@ }, "spriteSourceSize": { "x": 8, + "y": 3, + "w": 26, + "h": 25 + }, + "frame": { + "x": 80, + "y": 209, + "w": 26, + "h": 25 + } + }, + { + "filename": "9s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, "y": 4, "w": 25, - "h": 23 + "h": 24 }, "frame": { - "x": 57, - "y": 529, + "x": 82, + "y": 234, "w": 25, - "h": 23 + "h": 24 } }, { - "filename": "18", + "filename": "81s", "rotated": false, "trimmed": true, "sourceSize": { @@ -2538,104 +2349,41 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, + "x": 9, + "y": 12, + "w": 23, + "h": 15 + }, + "frame": { + "x": 82, + "y": 258, + "w": 23, + "h": 15 + } + }, + { + "filename": "5s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, "y": 5, - "w": 25, + "w": 22, "h": 23 }, "frame": { - "x": 57, - "y": 552, - "w": 25, + "x": 83, + "y": 273, + "w": 22, "h": 23 } }, { - "filename": "18s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 25, - "h": 23 - }, - "frame": { - "x": 57, - "y": 575, - "w": 25, - "h": 23 - } - }, - { - "filename": "86", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 25, - "h": 23 - }, - "frame": { - "x": 57, - "y": 598, - "w": 25, - "h": 23 - } - }, - { - "filename": "86s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 25, - "h": 23 - }, - "frame": { - "x": 57, - "y": 621, - "w": 25, - "h": 23 - } - }, - { - "filename": "20s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 25, - "h": 21 - }, - "frame": { - "x": 57, - "y": 644, - "w": 25, - "h": 21 - } - }, - { - "filename": "42", + "filename": "8", "rotated": false, "trimmed": true, "sourceSize": { @@ -2644,98 +2392,14 @@ }, "spriteSourceSize": { "x": 10, - "y": 5, - "w": 26, - "h": 22 - }, - "frame": { - "x": 55, - "y": 665, - "w": 26, - "h": 22 - } - }, - { - "filename": "87", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 25, - "h": 23 - }, - "frame": { - "x": 56, - "y": 687, - "w": 25, - "h": 23 - } - }, - { - "filename": "28", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, "y": 6, - "w": 25, + "w": 24, "h": 22 }, "frame": { - "x": 56, - "y": 710, - "w": 25, - "h": 22 - } - }, - { - "filename": "42s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 26, - "h": 22 - }, - "frame": { - "x": 53, - "y": 732, - "w": 26, - "h": 22 - } - }, - { - "filename": "67", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 26, - "h": 22 - }, - "frame": { - "x": 53, - "y": 754, - "w": 26, + "x": 82, + "y": 296, + "w": 24, "h": 22 } }, @@ -2754,12 +2418,201 @@ "h": 19 }, "frame": { - "x": 82, - "y": 205, + "x": 132, + "y": 201, "w": 29, "h": 19 } }, + { + "filename": "44", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 22, + "h": 21 + }, + "frame": { + "x": 161, + "y": 202, + "w": 22, + "h": 21 + } + }, + { + "filename": "42", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 26, + "h": 22 + }, + "frame": { + "x": 183, + "y": 218, + "w": 26, + "h": 22 + } + }, + { + "filename": "145s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 29, + "h": 19 + }, + "frame": { + "x": 209, + "y": 238, + "w": 29, + "h": 19 + } + }, + { + "filename": "40s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 3, + "w": 17, + "h": 25 + }, + "frame": { + "x": 238, + "y": 251, + "w": 17, + "h": 25 + } + }, + { + "filename": "15", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 25, + "h": 23 + }, + "frame": { + "x": 107, + "y": 206, + "w": 25, + "h": 23 + } + }, + { + "filename": "26", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 25, + "h": 24 + }, + "frame": { + "x": 107, + "y": 229, + "w": 25, + "h": 24 + } + }, + { + "filename": "57", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 28, + "h": 23 + }, + "frame": { + "x": 132, + "y": 220, + "w": 28, + "h": 23 + } + }, + { + "filename": "31", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 23, + "h": 23 + }, + "frame": { + "x": 160, + "y": 223, + "w": 23, + "h": 23 + } + }, + { + "filename": "42s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 26, + "h": 22 + }, + "frame": { + "x": 183, + "y": 240, + "w": 26, + "h": 22 + } + }, { "filename": "56s", "rotated": false, @@ -2775,12 +2628,558 @@ "h": 20 }, "frame": { - "x": 80, - "y": 224, + "x": 132, + "y": 243, "w": 28, "h": 20 } }, + { + "filename": "31s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 23, + "h": 23 + }, + "frame": { + "x": 160, + "y": 246, + "w": 23, + "h": 23 + } + }, + { + "filename": "15s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 25, + "h": 23 + }, + "frame": { + "x": 107, + "y": 253, + "w": 25, + "h": 23 + } + }, + { + "filename": "57s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 28, + "h": 23 + }, + "frame": { + "x": 132, + "y": 263, + "w": 28, + "h": 23 + } + }, + { + "filename": "144", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 27, + "h": 20 + }, + "frame": { + "x": 105, + "y": 276, + "w": 27, + "h": 20 + } + }, + { + "filename": "67", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 26, + "h": 22 + }, + "frame": { + "x": 106, + "y": 296, + "w": 26, + "h": 22 + } + }, + { + "filename": "71", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 28, + "h": 23 + }, + "frame": { + "x": 132, + "y": 286, + "w": 28, + "h": 23 + } + }, + { + "filename": "151", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 2, + "w": 23, + "h": 25 + }, + "frame": { + "x": 160, + "y": 269, + "w": 23, + "h": 25 + } + }, + { + "filename": "143", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 27, + "h": 24 + }, + "frame": { + "x": 183, + "y": 262, + "w": 27, + "h": 24 + } + }, + { + "filename": "71s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 28, + "h": 23 + }, + "frame": { + "x": 210, + "y": 257, + "w": 28, + "h": 23 + } + }, + { + "filename": "103", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 4, + "w": 17, + "h": 24 + }, + "frame": { + "x": 238, + "y": 276, + "w": 17, + "h": 24 + } + }, + { + "filename": "98", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 28, + "h": 21 + }, + "frame": { + "x": 210, + "y": 280, + "w": 28, + "h": 21 + } + }, + { + "filename": "68s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 27, + "h": 22 + }, + "frame": { + "x": 183, + "y": 286, + "w": 27, + "h": 22 + } + }, + { + "filename": "49", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 160, + "y": 294, + "w": 23, + "h": 24 + } + }, + { + "filename": "98s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 28, + "h": 21 + }, + "frame": { + "x": 132, + "y": 309, + "w": 28, + "h": 21 + } + }, + { + "filename": "103s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 4, + "w": 17, + "h": 24 + }, + "frame": { + "x": 238, + "y": 300, + "w": 17, + "h": 24 + } + }, + { + "filename": "146", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 8, + "w": 28, + "h": 18 + }, + "frame": { + "x": 210, + "y": 301, + "w": 28, + "h": 18 + } + }, + { + "filename": "80", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 27, + "h": 23 + }, + "frame": { + "x": 183, + "y": 308, + "w": 27, + "h": 23 + } + }, + { + "filename": "49s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 160, + "y": 318, + "w": 23, + "h": 24 + } + }, + { + "filename": "146s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 8, + "w": 28, + "h": 18 + }, + "frame": { + "x": 210, + "y": 319, + "w": 28, + "h": 18 + } + }, + { + "filename": "43", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 9, + "w": 17, + "h": 19 + }, + "frame": { + "x": 238, + "y": 324, + "w": 17, + "h": 19 + } + }, + { + "filename": "80s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 27, + "h": 23 + }, + "frame": { + "x": 183, + "y": 331, + "w": 27, + "h": 23 + } + }, + { + "filename": "143s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 27, + "h": 24 + }, + "frame": { + "x": 210, + "y": 337, + "w": 27, + "h": 24 + } + }, + { + "filename": "23", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 18, + "h": 21 + }, + "frame": { + "x": 237, + "y": 343, + "w": 18, + "h": 21 + } + }, + { + "filename": "2", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 32, + "y": 309, + "w": 21, + "h": 20 + } + }, + { + "filename": "150-mega-x", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 2, + "w": 21, + "h": 26 + }, + "frame": { + "x": 31, + "y": 329, + "w": 21, + "h": 26 + } + }, + { + "filename": "144s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 27, + "h": 20 + }, + "frame": { + "x": 53, + "y": 314, + "w": 27, + "h": 20 + } + }, { "filename": "67s", "rotated": false, @@ -2796,8 +3195,8 @@ "h": 22 }, "frame": { - "x": 80, - "y": 244, + "x": 52, + "y": 334, "w": 26, "h": 22 } @@ -2818,53 +3217,11 @@ }, "frame": { "x": 80, - "y": 266, + "y": 318, "w": 26, "h": 22 } }, - { - "filename": "145s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 29, - "h": 19 - }, - "frame": { - "x": 111, - "y": 206, - "w": 29, - "h": 19 - } - }, - { - "filename": "144", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 27, - "h": 20 - }, - "frame": { - "x": 108, - "y": 225, - "w": 27, - "h": 20 - } - }, { "filename": "75s", "rotated": false, @@ -2881,7 +3238,7 @@ }, "frame": { "x": 106, - "y": 245, + "y": 318, "w": 26, "h": 22 } @@ -2901,14 +3258,14 @@ "h": 21 }, "frame": { - "x": 106, - "y": 267, + "x": 78, + "y": 340, "w": 26, "h": 21 } }, { - "filename": "74", + "filename": "76s", "rotated": false, "trimmed": true, "sourceSize": { @@ -2916,20 +3273,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 13, - "w": 24, - "h": 15 + "x": 6, + "y": 7, + "w": 26, + "h": 21 }, "frame": { - "x": 80, - "y": 288, - "w": 24, - "h": 15 + "x": 104, + "y": 340, + "w": 26, + "h": 21 } }, { - "filename": "150-mega-x", + "filename": "2s", "rotated": false, "trimmed": true, "sourceSize": { @@ -2937,16 +3294,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 2, + "x": 10, + "y": 8, "w": 21, - "h": 26 + "h": 20 }, "frame": { - "x": 83, - "y": 303, + "x": 31, + "y": 355, "w": 21, - "h": 26 + "h": 20 } }, { @@ -2964,14 +3321,14 @@ "h": 22 }, "frame": { - "x": 104, - "y": 288, + "x": 52, + "y": 356, "w": 26, "h": 22 } }, { - "filename": "150s-mega-x", + "filename": "129", "rotated": false, "trimmed": true, "sourceSize": { @@ -2979,16 +3336,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 2, - "w": 21, - "h": 26 + "x": 10, + "y": 5, + "w": 22, + "h": 24 }, "frame": { - "x": 83, - "y": 329, - "w": 21, - "h": 26 + "x": 30, + "y": 375, + "w": 22, + "h": 24 } }, { @@ -3006,14 +3363,77 @@ "h": 22 }, "frame": { - "x": 104, - "y": 310, + "x": 52, + "y": 378, "w": 26, "h": 22 } }, { - "filename": "87s", + "filename": "26s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 25, + "h": 24 + }, + "frame": { + "x": 78, + "y": 361, + "w": 25, + "h": 24 + } + }, + { + "filename": "91", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 25, + "h": 24 + }, + "frame": { + "x": 103, + "y": 361, + "w": 25, + "h": 24 + } + }, + { + "filename": "129s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 22, + "h": 24 + }, + "frame": { + "x": 30, + "y": 399, + "w": 22, + "h": 24 + } + }, + { + "filename": "18", "rotated": false, "trimmed": true, "sourceSize": { @@ -3027,12 +3447,75 @@ "h": 23 }, "frame": { - "x": 104, - "y": 332, + "x": 52, + "y": 400, "w": 25, "h": 23 } }, + { + "filename": "91s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 25, + "h": 24 + }, + "frame": { + "x": 30, + "y": 423, + "w": 25, + "h": 24 + } + }, + { + "filename": "12", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 3, + "w": 24, + "h": 24 + }, + "frame": { + "x": 30, + "y": 447, + "w": 24, + "h": 24 + } + }, + { + "filename": "12s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 3, + "w": 24, + "h": 24 + }, + "frame": { + "x": 30, + "y": 471, + "w": 24, + "h": 24 + } + }, { "filename": "94", "rotated": false, @@ -3048,159 +3531,12 @@ "h": 24 }, "frame": { - "x": 83, - "y": 355, + "x": 30, + "y": 495, "w": 24, "h": 24 } }, - { - "filename": "38", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 24, - "h": 23 - }, - "frame": { - "x": 83, - "y": 379, - "w": 24, - "h": 23 - } - }, - { - "filename": "151", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 2, - "w": 23, - "h": 25 - }, - "frame": { - "x": 84, - "y": 402, - "w": 23, - "h": 25 - } - }, - { - "filename": "151s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 2, - "w": 23, - "h": 25 - }, - "frame": { - "x": 84, - "y": 427, - "w": 23, - "h": 25 - } - }, - { - "filename": "25-beauty-cosplay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 3, - "w": 22, - "h": 25 - }, - "frame": { - "x": 107, - "y": 355, - "w": 22, - "h": 25 - } - }, - { - "filename": "25s-beauty-cosplay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 3, - "w": 22, - "h": 25 - }, - "frame": { - "x": 84, - "y": 452, - "w": 22, - "h": 25 - } - }, - { - "filename": "49", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 107, - "y": 380, - "w": 23, - "h": 24 - } - }, - { - "filename": "49s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 107, - "y": 404, - "w": 23, - "h": 24 - } - }, { "filename": "94s", "rotated": false, @@ -3216,35 +3552,14 @@ "h": 24 }, "frame": { - "x": 107, - "y": 428, + "x": 30, + "y": 519, "w": 24, "h": 24 } }, { - "filename": "112", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 25, - "h": 23 - }, - "frame": { - "x": 106, - "y": 452, - "w": 25, - "h": 23 - } - }, - { - "filename": "5", + "filename": "151s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3253,40 +3568,19 @@ }, "spriteSourceSize": { "x": 9, - "y": 5, - "w": 22, - "h": 23 + "y": 2, + "w": 23, + "h": 25 }, "frame": { - "x": 84, - "y": 477, - "w": 22, - "h": 23 + "x": 30, + "y": 543, + "w": 23, + "h": 25 } }, { - "filename": "112s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 25, - "h": 23 - }, - "frame": { - "x": 106, - "y": 475, - "w": 25, - "h": 23 - } - }, - { - "filename": "31", + "filename": "150s-mega-x", "rotated": false, "trimmed": true, "sourceSize": { @@ -3295,19 +3589,19 @@ }, "spriteSourceSize": { "x": 9, - "y": 5, - "w": 23, - "h": 23 + "y": 2, + "w": 21, + "h": 26 }, "frame": { - "x": 83, - "y": 500, - "w": 23, - "h": 23 + "x": 30, + "y": 568, + "w": 21, + "h": 26 } }, { - "filename": "28s", + "filename": "18s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3316,19 +3610,19 @@ }, "spriteSourceSize": { "x": 8, - "y": 6, + "y": 5, "w": 25, - "h": 22 + "h": 23 }, "frame": { - "x": 106, - "y": 498, + "x": 55, + "y": 423, "w": 25, - "h": 22 + "h": 23 } }, { - "filename": "8", + "filename": "38", "rotated": false, "trimmed": true, "sourceSize": { @@ -3336,16 +3630,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 6, + "x": 8, + "y": 5, "w": 24, - "h": 22 + "h": 23 }, "frame": { - "x": 83, - "y": 523, + "x": 30, + "y": 594, "w": 24, - "h": 22 + "h": 23 } }, { @@ -3363,8 +3657,8 @@ "h": 23 }, "frame": { - "x": 82, - "y": 545, + "x": 30, + "y": 617, "w": 24, "h": 23 } @@ -3384,8 +3678,8 @@ "h": 23 }, "frame": { - "x": 82, - "y": 568, + "x": 30, + "y": 640, "w": 24, "h": 23 } @@ -3405,14 +3699,77 @@ "h": 23 }, "frame": { - "x": 82, - "y": 591, + "x": 31, + "y": 663, "w": 24, "h": 23 } }, { - "filename": "8s", + "filename": "86", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 25, + "h": 23 + }, + "frame": { + "x": 31, + "y": 686, + "w": 25, + "h": 23 + } + }, + { + "filename": "20", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 78, + "y": 385, + "w": 25, + "h": 21 + } + }, + { + "filename": "20s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 103, + "y": 385, + "w": 25, + "h": 21 + } + }, + { + "filename": "7", "rotated": false, "trimmed": true, "sourceSize": { @@ -3421,19 +3778,40 @@ }, "spriteSourceSize": { "x": 10, + "y": 11, + "w": 21, + "h": 17 + }, + "frame": { + "x": 77, + "y": 406, + "w": 21, + "h": 17 + } + }, + { + "filename": "28", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, "y": 6, - "w": 24, + "w": 25, "h": 22 }, "frame": { - "x": 82, - "y": 614, - "w": 24, + "x": 98, + "y": 406, + "w": 25, "h": 22 } }, { - "filename": "31s", + "filename": "23s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3441,41 +3819,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 23, - "h": 23 - }, - "frame": { - "x": 82, - "y": 636, - "w": 23, - "h": 23 - } - }, - { - "filename": "72", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, + "x": 11, "y": 7, - "w": 24, - "h": 22 + "w": 18, + "h": 21 }, "frame": { - "x": 107, - "y": 520, - "w": 24, - "h": 22 + "x": 80, + "y": 423, + "w": 18, + "h": 21 } }, { - "filename": "25-cute-cosplay", + "filename": "28s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3483,56 +3840,14 @@ "h": 30 }, "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 24, - "h": 20 - }, - "frame": { - "x": 82, - "y": 659, - "w": 24, - "h": 20 - } - }, - { - "filename": "73", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, + "x": 8, + "y": 6, "w": 25, "h": 22 }, "frame": { - "x": 81, - "y": 679, - "w": 25, - "h": 22 - } - }, - { - "filename": "73s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 25, - "h": 22 - }, - "frame": { - "x": 81, - "y": 701, + "x": 98, + "y": 428, "w": 25, "h": 22 } @@ -3551,788 +3866,11 @@ "w": 25, "h": 21 }, - "frame": { - "x": 81, - "y": 723, - "w": 25, - "h": 21 - } - }, - { - "filename": "76s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 26, - "h": 21 - }, - "frame": { - "x": 79, - "y": 744, - "w": 26, - "h": 21 - } - }, - { - "filename": "21", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 12, - "w": 19, - "h": 16 - }, - "frame": { - "x": 79, - "y": 765, - "w": 19, - "h": 16 - } - }, - { - "filename": "21s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 12, - "w": 19, - "h": 16 - }, - "frame": { - "x": 98, - "y": 765, - "w": 19, - "h": 16 - } - }, - { - "filename": "19", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 20, - "h": 21 - }, - "frame": { - "x": 105, - "y": 744, - "w": 20, - "h": 21 - } - }, - { - "filename": "101", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 12, - "w": 16, - "h": 16 - }, - "frame": { - "x": 117, - "y": 765, - "w": 16, - "h": 16 - } - }, - { - "filename": "48s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 17, - "h": 26 - }, "frame": { "x": 132, - "y": 245, - "w": 17, - "h": 26 - } - }, - { - "filename": "2", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 135, - "y": 225, - "w": 21, - "h": 20 - } - }, - { - "filename": "1", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 9, - "w": 20, - "h": 19 - }, - "frame": { - "x": 132, - "y": 271, - "w": 20, - "h": 19 - } - }, - { - "filename": "129", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 22, - "h": 24 - }, - "frame": { - "x": 130, - "y": 290, - "w": 22, - "h": 24 - } - }, - { - "filename": "5s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 130, - "y": 314, - "w": 22, - "h": 23 - } - }, - { - "filename": "129s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 22, - "h": 24 - }, - "frame": { - "x": 129, - "y": 337, - "w": 22, - "h": 24 - } - }, - { - "filename": "61", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 9, - "w": 22, - "h": 19 - }, - "frame": { - "x": 129, - "y": 361, - "w": 22, - "h": 19 - } - }, - { - "filename": "45", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 130, - "y": 380, - "w": 22, - "h": 23 - } - }, - { - "filename": "45s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 130, - "y": 403, - "w": 22, - "h": 23 - } - }, - { - "filename": "126", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 131, - "y": 426, - "w": 22, - "h": 23 - } - }, - { - "filename": "126s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 131, - "y": 449, - "w": 22, - "h": 23 - } - }, - { - "filename": "47", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 22 - }, - "frame": { - "x": 131, - "y": 472, - "w": 22, - "h": 22 - } - }, - { - "filename": "47s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 22 - }, - "frame": { - "x": 131, - "y": 494, - "w": 22, - "h": 22 - } - }, - { - "filename": "51", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 22 - }, - "frame": { - "x": 131, - "y": 516, - "w": 22, - "h": 22 - } - }, - { - "filename": "40", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 17, - "h": 25 - }, - "frame": { - "x": 149, - "y": 245, - "w": 17, - "h": 25 - } - }, - { - "filename": "40s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 17, - "h": 25 - }, - "frame": { - "x": 152, - "y": 270, - "w": 17, - "h": 25 - } - }, - { - "filename": "103", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 4, - "w": 17, - "h": 24 - }, - "frame": { - "x": 152, - "y": 295, - "w": 17, - "h": 24 - } - }, - { - "filename": "1s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 9, - "w": 20, - "h": 19 - }, - "frame": { - "x": 152, - "y": 319, - "w": 20, - "h": 19 - } - }, - { - "filename": "24", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 20, - "h": 23 - }, - "frame": { - "x": 151, - "y": 338, - "w": 20, - "h": 23 - } - }, - { - "filename": "4", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 9, - "w": 21, - "h": 19 - }, - "frame": { - "x": 151, - "y": 361, - "w": 21, - "h": 19 - } - }, - { - "filename": "24s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 20, - "h": 23 - }, - "frame": { - "x": 152, - "y": 380, - "w": 20, - "h": 23 - } - }, - { - "filename": "36", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 20, - "h": 23 - }, - "frame": { - "x": 152, - "y": 403, - "w": 20, - "h": 23 - } - }, - { - "filename": "36s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 20, - "h": 23 - }, - "frame": { - "x": 153, - "y": 426, - "w": 20, - "h": 23 - } - }, - { - "filename": "150", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 5, - "w": 20, - "h": 23 - }, - "frame": { - "x": 153, - "y": 449, - "w": 20, - "h": 23 - } - }, - { - "filename": "150s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 5, - "w": 20, - "h": 23 - }, - "frame": { - "x": 153, - "y": 472, - "w": 20, - "h": 23 - } - }, - { - "filename": "51s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 22 - }, - "frame": { - "x": 153, - "y": 495, - "w": 22, - "h": 22 - } - }, - { - "filename": "44", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 22, + "y": 330, + "w": 25, "h": 21 - }, - "frame": { - "x": 153, - "y": 517, - "w": 22, - "h": 21 - } - }, - { - "filename": "146", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 28, - "h": 18 - }, - "frame": { - "x": 131, - "y": 538, - "w": 28, - "h": 18 - } - }, - { - "filename": "25s-cute-cosplay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 24, - "h": 20 - }, - "frame": { - "x": 107, - "y": 542, - "w": 24, - "h": 20 - } - }, - { - "filename": "149", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 25, - "h": 22 - }, - "frame": { - "x": 106, - "y": 562, - "w": 25, - "h": 22 - } - }, - { - "filename": "144s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 27, - "h": 20 - }, - "frame": { - "x": 131, - "y": 556, - "w": 27, - "h": 20 - } - }, - { - "filename": "149s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 25, - "h": 22 - }, - "frame": { - "x": 106, - "y": 584, - "w": 25, - "h": 22 } }, { @@ -4350,14 +3888,14 @@ "h": 21 }, "frame": { - "x": 131, - "y": 576, + "x": 130, + "y": 351, "w": 25, "h": 21 } }, { - "filename": "72s", + "filename": "86s", "rotated": false, "trimmed": true, "sourceSize": { @@ -4365,78 +3903,162 @@ "h": 30 }, "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 24, - "h": 22 - }, - "frame": { - "x": 106, - "y": 606, - "w": 24, - "h": 22 - } - }, - { - "filename": "2s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 159, - "y": 538, - "w": 21, - "h": 20 - } - }, - { - "filename": "44s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 22, - "h": 21 - }, - "frame": { - "x": 158, - "y": 558, - "w": 22, - "h": 21 - } - }, - { - "filename": "82", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, + "x": 8, "y": 5, - "w": 24, + "w": 25, + "h": 23 + }, + "frame": { + "x": 128, + "y": 372, + "w": 25, + "h": 23 + } + }, + { + "filename": "73", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 25, "h": 22 }, "frame": { - "x": 156, - "y": 579, - "w": 24, + "x": 128, + "y": 395, + "w": 25, + "h": 22 + } + }, + { + "filename": "87", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 25, + "h": 23 + }, + "frame": { + "x": 123, + "y": 417, + "w": 25, + "h": 23 + } + }, + { + "filename": "73s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 25, + "h": 22 + }, + "frame": { + "x": 123, + "y": 440, + "w": 25, + "h": 22 + } + }, + { + "filename": "87s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 25, + "h": 23 + }, + "frame": { + "x": 157, + "y": 342, + "w": 25, + "h": 23 + } + }, + { + "filename": "112", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 25, + "h": 23 + }, + "frame": { + "x": 182, + "y": 354, + "w": 25, + "h": 23 + } + }, + { + "filename": "112s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 25, + "h": 23 + }, + "frame": { + "x": 207, + "y": 361, + "w": 25, + "h": 23 + } + }, + { + "filename": "53", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 6, + "w": 23, + "h": 22 + }, + "frame": { + "x": 232, + "y": 364, + "w": 23, "h": 22 } }, @@ -4455,14 +4077,14 @@ "h": 20 }, "frame": { - "x": 131, - "y": 597, + "x": 155, + "y": 365, "w": 25, "h": 20 } }, { - "filename": "82s", + "filename": "149", "rotated": false, "trimmed": true, "sourceSize": { @@ -4470,15 +4092,15 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 24, + "x": 7, + "y": 6, + "w": 25, "h": 22 }, "frame": { - "x": 156, - "y": 601, - "w": 24, + "x": 153, + "y": 385, + "w": 25, "h": 22 } }, @@ -4497,14 +4119,14 @@ "h": 20 }, "frame": { - "x": 130, - "y": 617, + "x": 153, + "y": 407, "w": 25, "h": 20 } }, { - "filename": "74s", + "filename": "149s", "rotated": false, "trimmed": true, "sourceSize": { @@ -4512,16 +4134,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 13, - "w": 24, - "h": 15 + "x": 7, + "y": 6, + "w": 25, + "h": 22 }, "frame": { - "x": 106, - "y": 628, - "w": 24, - "h": 15 + "x": 148, + "y": 427, + "w": 25, + "h": 22 } }, { @@ -4539,8 +4161,8 @@ "h": 21 }, "frame": { - "x": 155, - "y": 623, + "x": 148, + "y": 449, "w": 25, "h": 21 } @@ -4560,12 +4182,201 @@ "h": 21 }, "frame": { - "x": 130, - "y": 637, + "x": 180, + "y": 377, "w": 25, "h": 21 } }, + { + "filename": "8s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 6, + "w": 24, + "h": 22 + }, + "frame": { + "x": 178, + "y": 398, + "w": 24, + "h": 22 + } + }, + { + "filename": "133-partner", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 8, + "w": 25, + "h": 20 + }, + "frame": { + "x": 205, + "y": 384, + "w": 25, + "h": 20 + } + }, + { + "filename": "133s-partner", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 8, + "w": 25, + "h": 20 + }, + "frame": { + "x": 230, + "y": 386, + "w": 25, + "h": 20 + } + }, + { + "filename": "25-cute-cosplay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 8, + "w": 24, + "h": 20 + }, + "frame": { + "x": 202, + "y": 404, + "w": 24, + "h": 20 + } + }, + { + "filename": "25s-cute-cosplay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 8, + "w": 24, + "h": 20 + }, + "frame": { + "x": 226, + "y": 406, + "w": 24, + "h": 20 + } + }, + { + "filename": "72", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 24, + "h": 22 + }, + "frame": { + "x": 178, + "y": 420, + "w": 24, + "h": 22 + } + }, + { + "filename": "72s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 24, + "h": 22 + }, + "frame": { + "x": 202, + "y": 424, + "w": 24, + "h": 22 + } + }, + { + "filename": "82", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 24, + "h": 22 + }, + "frame": { + "x": 226, + "y": 426, + "w": 24, + "h": 22 + } + }, + { + "filename": "82s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 24, + "h": 22 + }, + "frame": { + "x": 173, + "y": 442, + "w": 24, + "h": 22 + } + }, { "filename": "96", "rotated": false, @@ -4581,8 +4392,8 @@ "h": 22 }, "frame": { - "x": 106, - "y": 643, + "x": 197, + "y": 446, "w": 24, "h": 22 } @@ -4602,14 +4413,14 @@ "h": 22 }, "frame": { - "x": 106, - "y": 665, + "x": 221, + "y": 448, "w": 24, "h": 22 } }, { - "filename": "53", + "filename": "102", "rotated": false, "trimmed": true, "sourceSize": { @@ -4618,98 +4429,35 @@ }, "spriteSourceSize": { "x": 8, - "y": 6, - "w": 23, - "h": 22 - }, - "frame": { - "x": 130, - "y": 658, - "w": 23, - "h": 22 - } - }, - { - "filename": "53s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 6, - "w": 23, - "h": 22 - }, - "frame": { - "x": 106, - "y": 687, - "w": 23, - "h": 22 - } - }, - { - "filename": "63", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 8, - "w": 23, - "h": 21 - }, - "frame": { - "x": 106, - "y": 709, - "w": 23, - "h": 21 - } - }, - { - "filename": "50", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 14, - "w": 15, - "h": 14 - }, - "frame": { - "x": 106, - "y": 730, - "w": 15, - "h": 14 - } - }, - { - "filename": "146s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 28, + "y": 10, + "w": 24, "h": 18 }, "frame": { - "x": 155, - "y": 644, - "w": 28, + "x": 173, + "y": 464, + "w": 24, + "h": 18 + } + }, + { + "filename": "102s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 10, + "w": 24, + "h": 18 + }, + "frame": { + "x": 197, + "y": 468, + "w": 24, "h": 18 } }, @@ -4728,14 +4476,14 @@ "h": 20 }, "frame": { - "x": 183, - "y": 151, + "x": 221, + "y": 470, "w": 24, "h": 20 } }, { - "filename": "102", + "filename": "16", "rotated": false, "trimmed": true, "sourceSize": { @@ -4743,100 +4491,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 10, - "w": 24, - "h": 18 + "x": 11, + "y": 11, + "w": 18, + "h": 17 }, "frame": { - "x": 153, - "y": 662, - "w": 24, - "h": 18 - } - }, - { - "filename": "103s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 4, - "w": 17, - "h": 24 - }, - "frame": { - "x": 166, - "y": 151, - "w": 17, - "h": 24 - } - }, - { - "filename": "102s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 10, - "w": 24, - "h": 18 - }, - "frame": { - "x": 130, - "y": 680, - "w": 24, - "h": 18 - } - }, - { - "filename": "131", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 24, - "h": 21 - }, - "frame": { - "x": 129, - "y": 698, - "w": 24, - "h": 21 - } - }, - { - "filename": "63s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 8, - "w": 23, - "h": 21 - }, - "frame": { - "x": 154, - "y": 680, - "w": 23, - "h": 21 + "x": 80, + "y": 444, + "w": 18, + "h": 17 } }, { @@ -4854,12 +4518,75 @@ "h": 20 }, "frame": { - "x": 153, - "y": 701, + "x": 56, + "y": 446, "w": 24, "h": 20 } }, + { + "filename": "45", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 54, + "y": 466, + "w": 22, + "h": 23 + } + }, + { + "filename": "45s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 54, + "y": 489, + "w": 22, + "h": 23 + } + }, + { + "filename": "126", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 54, + "y": 512, + "w": 22, + "h": 23 + } + }, { "filename": "117", "rotated": false, @@ -4875,14 +4602,161 @@ "h": 20 }, "frame": { - "x": 129, - "y": 719, + "x": 98, + "y": 450, "w": 24, "h": 20 } }, { - "filename": "117s", + "filename": "16s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 11, + "w": 18, + "h": 17 + }, + "frame": { + "x": 80, + "y": 461, + "w": 18, + "h": 17 + } + }, + { + "filename": "126s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 76, + "y": 478, + "w": 22, + "h": 23 + } + }, + { + "filename": "53s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 6, + "w": 23, + "h": 22 + }, + "frame": { + "x": 98, + "y": 470, + "w": 23, + "h": 22 + } + }, + { + "filename": "47", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 6, + "w": 22, + "h": 22 + }, + "frame": { + "x": 76, + "y": 501, + "w": 22, + "h": 22 + } + }, + { + "filename": "47s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 6, + "w": 22, + "h": 22 + }, + "frame": { + "x": 98, + "y": 492, + "w": 22, + "h": 22 + } + }, + { + "filename": "44s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 22, + "h": 21 + }, + "frame": { + "x": 76, + "y": 523, + "w": 22, + "h": 21 + } + }, + { + "filename": "51", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 6, + "w": 22, + "h": 22 + }, + "frame": { + "x": 98, + "y": 514, + "w": 22, + "h": 22 + } + }, + { + "filename": "46", "rotated": false, "trimmed": true, "sourceSize": { @@ -4892,16 +4766,352 @@ "spriteSourceSize": { "x": 9, "y": 8, - "w": 24, + "w": 22, "h": 20 }, "frame": { - "x": 153, - "y": 721, - "w": 24, + "x": 54, + "y": 535, + "w": 22, "h": 20 } }, + { + "filename": "63", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 23, + "h": 21 + }, + "frame": { + "x": 53, + "y": 555, + "w": 23, + "h": 21 + } + }, + { + "filename": "51s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 6, + "w": 22, + "h": 22 + }, + "frame": { + "x": 76, + "y": 544, + "w": 22, + "h": 22 + } + }, + { + "filename": "139", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 6, + "w": 22, + "h": 22 + }, + "frame": { + "x": 98, + "y": 536, + "w": 22, + "h": 22 + } + }, + { + "filename": "108", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 11, + "w": 23, + "h": 18 + }, + "frame": { + "x": 51, + "y": 576, + "w": 23, + "h": 18 + } + }, + { + "filename": "24", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 20, + "h": 23 + }, + "frame": { + "x": 54, + "y": 594, + "w": 20, + "h": 23 + } + }, + { + "filename": "24s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 20, + "h": 23 + }, + "frame": { + "x": 54, + "y": 617, + "w": 20, + "h": 23 + } + }, + { + "filename": "36", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 20, + "h": 23 + }, + "frame": { + "x": 54, + "y": 640, + "w": 20, + "h": 23 + } + }, + { + "filename": "36s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 20, + "h": 23 + }, + "frame": { + "x": 55, + "y": 663, + "w": 20, + "h": 23 + } + }, + { + "filename": "150", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 5, + "w": 20, + "h": 23 + }, + "frame": { + "x": 56, + "y": 686, + "w": 20, + "h": 23 + } + }, + { + "filename": "63s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 23, + "h": 21 + }, + "frame": { + "x": 53, + "y": 709, + "w": 23, + "h": 21 + } + }, + { + "filename": "106", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 23, + "h": 19 + }, + "frame": { + "x": 53, + "y": 730, + "w": 23, + "h": 19 + } + }, + { + "filename": "150s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 5, + "w": 20, + "h": 23 + }, + "frame": { + "x": 56, + "y": 749, + "w": 20, + "h": 23 + } + }, + { + "filename": "108s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 11, + "w": 23, + "h": 18 + }, + "frame": { + "x": 71, + "y": 772, + "w": 23, + "h": 18 + } + }, + { + "filename": "46s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 22, + "h": 20 + }, + "frame": { + "x": 76, + "y": 566, + "w": 22, + "h": 20 + } + }, + { + "filename": "139s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 6, + "w": 22, + "h": 22 + }, + "frame": { + "x": 98, + "y": 558, + "w": 22, + "h": 22 + } + }, + { + "filename": "131", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 24, + "h": 21 + }, + "frame": { + "x": 74, + "y": 586, + "w": 24, + "h": 21 + } + }, { "filename": "131s", "rotated": false, @@ -4917,8 +5127,8 @@ "h": 21 }, "frame": { - "x": 125, - "y": 739, + "x": 74, + "y": 607, "w": 24, "h": 21 } @@ -4938,491 +5148,8 @@ "h": 21 }, "frame": { - "x": 133, - "y": 760, - "w": 23, - "h": 21 - } - }, - { - "filename": "118", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 9, - "w": 24, - "h": 19 - }, - "frame": { - "x": 149, - "y": 741, - "w": 24, - "h": 19 - } - }, - { - "filename": "92s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 23, - "h": 21 - }, - "frame": { - "x": 156, - "y": 760, - "w": 23, - "h": 21 - } - }, - { - "filename": "4s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 9, - "w": 21, - "h": 19 - }, - "frame": { - "x": 173, - "y": 741, - "w": 21, - "h": 19 - } - }, - { - "filename": "115", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 7, - "w": 23, - "h": 21 - }, - "frame": { - "x": 179, - "y": 760, - "w": 23, - "h": 21 - } - }, - { - "filename": "58", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 21, - "h": 22 - }, - "frame": { - "x": 177, - "y": 662, - "w": 21, - "h": 22 - } - }, - { - "filename": "58s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 21, - "h": 22 - }, - "frame": { - "x": 177, - "y": 684, - "w": 21, - "h": 22 - } - }, - { - "filename": "125", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 6, - "w": 21, - "h": 22 - }, - "frame": { - "x": 177, - "y": 706, - "w": 21, - "h": 22 - } - }, - { - "filename": "132", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 15, - "w": 16, - "h": 13 - }, - "frame": { - "x": 177, - "y": 728, - "w": 16, - "h": 13 - } - }, - { - "filename": "118s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 9, - "w": 24, - "h": 19 - }, - "frame": { - "x": 183, - "y": 171, - "w": 24, - "h": 19 - } - }, - { - "filename": "106", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 9, - "w": 23, - "h": 19 - }, - "frame": { - "x": 207, - "y": 171, - "w": 23, - "h": 19 - } - }, - { - "filename": "43", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 9, - "w": 17, - "h": 19 - }, - "frame": { - "x": 166, - "y": 175, - "w": 17, - "h": 19 - } - }, - { - "filename": "81", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 12, - "w": 23, - "h": 15 - }, - "frame": { - "x": 183, - "y": 190, - "w": 23, - "h": 15 - } - }, - { - "filename": "81s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 12, - "w": 23, - "h": 15 - }, - "frame": { - "x": 206, - "y": 190, - "w": 23, - "h": 15 - } - }, - { - "filename": "17", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 140, - "y": 205, - "w": 21, - "h": 20 - } - }, - { - "filename": "139", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 22 - }, - "frame": { - "x": 161, - "y": 194, - "w": 22, - "h": 22 - } - }, - { - "filename": "17s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 156, - "y": 225, - "w": 21, - "h": 20 - } - }, - { - "filename": "106s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 9, - "w": 23, - "h": 19 - }, - "frame": { - "x": 183, - "y": 205, - "w": 23, - "h": 19 - } - }, - { - "filename": "115s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 7, - "w": 23, - "h": 21 - }, - "frame": { - "x": 206, - "y": 205, - "w": 23, - "h": 21 - } - }, - { - "filename": "127", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 23, - "h": 21 - }, - "frame": { - "x": 177, - "y": 224, - "w": 23, - "h": 21 - } - }, - { - "filename": "127s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 23, - "h": 21 - }, - "frame": { - "x": 166, - "y": 245, - "w": 23, - "h": 21 - } - }, - { - "filename": "125s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 6, - "w": 21, - "h": 22 - }, - "frame": { - "x": 169, - "y": 266, - "w": 21, - "h": 22 - } - }, - { - "filename": "139s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 22 - }, - "frame": { - "x": 169, - "y": 288, - "w": 22, - "h": 22 - } - }, - { - "filename": "134", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 7, - "w": 23, - "h": 21 - }, - "frame": { - "x": 200, - "y": 226, + "x": 74, + "y": 628, "w": 23, "h": 21 } @@ -5442,33 +5169,12 @@ "h": 22 }, "frame": { - "x": 172, - "y": 310, + "x": 98, + "y": 580, "w": 22, "h": 22 } }, - { - "filename": "61s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 9, - "w": 22, - "h": 19 - }, - "frame": { - "x": 189, - "y": 247, - "w": 22, - "h": 19 - } - }, { "filename": "148s", "rotated": false, @@ -5484,308 +5190,14 @@ "h": 22 }, "frame": { - "x": 190, - "y": 266, + "x": 98, + "y": 602, "w": 22, "h": 22 } }, { - "filename": "52", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 191, - "y": 288, - "w": 21, - "h": 21 - } - }, - { - "filename": "19s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 20, - "h": 21 - }, - "frame": { - "x": 194, - "y": 309, - "w": 20, - "h": 21 - } - }, - { - "filename": "29", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 18, - "h": 19 - }, - "frame": { - "x": 211, - "y": 247, - "w": 18, - "h": 19 - } - }, - { - "filename": "23", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 18, - "h": 21 - }, - "frame": { - "x": 212, - "y": 266, - "w": 18, - "h": 21 - } - }, - { - "filename": "23s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 18, - "h": 21 - }, - "frame": { - "x": 212, - "y": 287, - "w": 18, - "h": 21 - } - }, - { - "filename": "52s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 214, - "y": 308, - "w": 21, - "h": 21 - } - }, - { - "filename": "79", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 235, - "y": 188, - "w": 21, - "h": 21 - } - }, - { - "filename": "79s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 235, - "y": 209, - "w": 21, - "h": 21 - } - }, - { - "filename": "25-cool-cosplay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 235, - "y": 230, - "w": 21, - "h": 20 - } - }, - { - "filename": "11", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 14, - "y": 10, - "w": 12, - "h": 18 - }, - "frame": { - "x": 223, - "y": 226, - "w": 12, - "h": 18 - } - }, - { - "filename": "25-cosplay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 235, - "y": 250, - "w": 21, - "h": 20 - } - }, - { - "filename": "25-smart-cosplay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 235, - "y": 270, - "w": 21, - "h": 20 - } - }, - { - "filename": "25-tough-cosplay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 235, - "y": 290, - "w": 21, - "h": 20 - } - }, - { - "filename": "25", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 235, - "y": 310, - "w": 21, - "h": 20 - } - }, - { - "filename": "46", + "filename": "117s", "rotated": false, "trimmed": true, "sourceSize": { @@ -5795,18 +5207,18 @@ "spriteSourceSize": { "x": 9, "y": 8, - "w": 22, + "w": 24, "h": 20 }, "frame": { - "x": 172, - "y": 332, - "w": 22, + "x": 122, + "y": 462, + "w": 24, "h": 20 } }, { - "filename": "105", + "filename": "118", "rotated": false, "trimmed": true, "sourceSize": { @@ -5814,20 +5226,41 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 22, - "h": 21 + "x": 9, + "y": 9, + "w": 24, + "h": 19 }, "frame": { - "x": 194, - "y": 330, - "w": 22, - "h": 21 + "x": 146, + "y": 470, + "w": 24, + "h": 19 } }, { - "filename": "141s", + "filename": "118s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 9, + "w": 24, + "h": 19 + }, + "frame": { + "x": 121, + "y": 482, + "w": 24, + "h": 19 + } + }, + { + "filename": "92s", "rotated": false, "trimmed": true, "sourceSize": { @@ -5837,18 +5270,18 @@ "spriteSourceSize": { "x": 10, "y": 7, - "w": 19, + "w": 23, "h": 21 }, "frame": { - "x": 216, - "y": 329, - "w": 19, + "x": 120, + "y": 501, + "w": 23, "h": 21 } }, { - "filename": "25s-cool-cosplay", + "filename": "115", "rotated": false, "trimmed": true, "sourceSize": { @@ -5856,20 +5289,41 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 21, - "h": 20 + "x": 9, + "y": 7, + "w": 23, + "h": 21 }, "frame": { - "x": 235, - "y": 330, - "w": 21, - "h": 20 + "x": 120, + "y": 522, + "w": 23, + "h": 21 } }, { - "filename": "105s", + "filename": "115s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 7, + "w": 23, + "h": 21 + }, + "frame": { + "x": 120, + "y": 543, + "w": 23, + "h": 21 + } + }, + { + "filename": "127", "rotated": false, "trimmed": true, "sourceSize": { @@ -5879,13 +5333,76 @@ "spriteSourceSize": { "x": 8, "y": 7, - "w": 22, + "w": 23, "h": 21 }, "frame": { - "x": 172, - "y": 352, - "w": 22, + "x": 120, + "y": 564, + "w": 23, + "h": 21 + } + }, + { + "filename": "127s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 23, + "h": 21 + }, + "frame": { + "x": 120, + "y": 585, + "w": 23, + "h": 21 + } + }, + { + "filename": "106s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 23, + "h": 19 + }, + "frame": { + "x": 120, + "y": 606, + "w": 23, + "h": 19 + } + }, + { + "filename": "134", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 7, + "w": 23, + "h": 21 + }, + "frame": { + "x": 145, + "y": 489, + "w": 23, "h": 21 } }, @@ -5904,8 +5421,8 @@ "h": 21 }, "frame": { - "x": 194, - "y": 351, + "x": 143, + "y": 510, "w": 23, "h": 21 } @@ -5925,8 +5442,8 @@ "h": 21 }, "frame": { - "x": 172, - "y": 373, + "x": 143, + "y": 531, "w": 23, "h": 21 } @@ -5946,14 +5463,14 @@ "h": 21 }, "frame": { - "x": 172, - "y": 394, + "x": 143, + "y": 552, "w": 23, "h": 21 } }, { - "filename": "46s", + "filename": "58", "rotated": false, "trimmed": true, "sourceSize": { @@ -5961,20 +5478,41 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 8, - "w": 22, - "h": 20 + "x": 11, + "y": 6, + "w": 21, + "h": 22 }, "frame": { - "x": 217, - "y": 350, - "w": 22, - "h": 20 + "x": 143, + "y": 573, + "w": 21, + "h": 22 } }, { - "filename": "43s", + "filename": "58s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 21, + "h": 22 + }, + "frame": { + "x": 143, + "y": 595, + "w": 21, + "h": 22 + } + }, + { + "filename": "50", "rotated": false, "trimmed": true, "sourceSize": { @@ -5983,17 +5521,290 @@ }, "spriteSourceSize": { "x": 13, + "y": 14, + "w": 15, + "h": 14 + }, + "frame": { + "x": 74, + "y": 649, + "w": 15, + "h": 14 + } + }, + { + "filename": "30", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 19, + "h": 22 + }, + "frame": { + "x": 75, + "y": 663, + "w": 19, + "h": 22 + } + }, + { + "filename": "30s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 19, + "h": 22 + }, + "frame": { + "x": 76, + "y": 685, + "w": 19, + "h": 22 + } + }, + { + "filename": "33", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 19, + "h": 22 + }, + "frame": { + "x": 76, + "y": 707, + "w": 19, + "h": 22 + } + }, + { + "filename": "33s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 19, + "h": 22 + }, + "frame": { + "x": 76, + "y": 729, + "w": 19, + "h": 22 + } + }, + { + "filename": "19", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 20, + "h": 21 + }, + "frame": { + "x": 76, + "y": 751, + "w": 20, + "h": 21 + } + }, + { + "filename": "84", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 10, + "w": 21, + "h": 18 + }, + "frame": { + "x": 94, + "y": 772, + "w": 21, + "h": 18 + } + }, + { + "filename": "4", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, "y": 9, - "w": 17, + "w": 21, "h": 19 }, "frame": { - "x": 239, - "y": 350, - "w": 17, + "x": 143, + "y": 617, + "w": 21, "h": 19 } }, + { + "filename": "50s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 14, + "w": 15, + "h": 14 + }, + "frame": { + "x": 89, + "y": 649, + "w": 15, + "h": 14 + } + }, + { + "filename": "125", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 6, + "w": 21, + "h": 22 + }, + "frame": { + "x": 94, + "y": 663, + "w": 21, + "h": 22 + } + }, + { + "filename": "125s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 6, + "w": 21, + "h": 22 + }, + "frame": { + "x": 95, + "y": 685, + "w": 21, + "h": 22 + } + }, + { + "filename": "52", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 95, + "y": 707, + "w": 21, + "h": 21 + } + }, + { + "filename": "52s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 95, + "y": 728, + "w": 21, + "h": 21 + } + }, + { + "filename": "19s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 20, + "h": 21 + }, + "frame": { + "x": 96, + "y": 749, + "w": 20, + "h": 21 + } + }, { "filename": "70", "rotated": false, @@ -6009,12 +5820,96 @@ "h": 20 }, "frame": { - "x": 195, - "y": 372, + "x": 115, + "y": 770, "w": 22, "h": 20 } }, + { + "filename": "54", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 7, + "w": 18, + "h": 21 + }, + "frame": { + "x": 97, + "y": 628, + "w": 18, + "h": 21 + } + }, + { + "filename": "100", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 14, + "w": 14, + "h": 14 + }, + "frame": { + "x": 104, + "y": 649, + "w": 14, + "h": 14 + } + }, + { + "filename": "105", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 22, + "h": 21 + }, + "frame": { + "x": 115, + "y": 625, + "w": 22, + "h": 21 + } + }, + { + "filename": "1", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 9, + "w": 20, + "h": 19 + }, + "frame": { + "x": 118, + "y": 646, + "w": 20, + "h": 19 + } + }, { "filename": "70s", "rotated": false, @@ -6030,14 +5925,14 @@ "h": 20 }, "frame": { - "x": 217, - "y": 370, + "x": 115, + "y": 665, "w": 22, "h": 20 } }, { - "filename": "122", + "filename": "79", "rotated": false, "trimmed": true, "sourceSize": { @@ -6045,20 +5940,62 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 10, - "w": 17, - "h": 18 + "x": 10, + "y": 7, + "w": 21, + "h": 21 }, "frame": { - "x": 239, - "y": 369, - "w": 17, - "h": 18 + "x": 116, + "y": 685, + "w": 21, + "h": 21 } }, { - "filename": "25s-cosplay", + "filename": "79s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 116, + "y": 706, + "w": 21, + "h": 21 + } + }, + { + "filename": "105s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 22, + "h": 21 + }, + "frame": { + "x": 116, + "y": 727, + "w": 22, + "h": 21 + } + }, + { + "filename": "17", "rotated": false, "trimmed": true, "sourceSize": { @@ -6072,161 +6009,14 @@ "h": 20 }, "frame": { - "x": 195, - "y": 392, + "x": 116, + "y": 748, "w": 21, "h": 20 } }, { - "filename": "122s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 10, - "w": 17, - "h": 18 - }, - "frame": { - "x": 239, - "y": 387, - "w": 17, - "h": 18 - } - }, - { - "filename": "108", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 23, - "h": 18 - }, - "frame": { - "x": 216, - "y": 392, - "w": 23, - "h": 18 - } - }, - { - "filename": "133", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 10, - "w": 17, - "h": 18 - }, - "frame": { - "x": 239, - "y": 405, - "w": 17, - "h": 18 - } - }, - { - "filename": "108s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 23, - "h": 18 - }, - "frame": { - "x": 216, - "y": 410, - "w": 23, - "h": 18 - } - }, - { - "filename": "7", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 21, - "h": 17 - }, - "frame": { - "x": 195, - "y": 412, - "w": 21, - "h": 17 - } - }, - { - "filename": "133s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 10, - "w": 17, - "h": 18 - }, - "frame": { - "x": 239, - "y": 423, - "w": 17, - "h": 18 - } - }, - { - "filename": "27", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 20, - "h": 18 - }, - "frame": { - "x": 175, - "y": 415, - "w": 20, - "h": 18 - } - }, - { - "filename": "25s-smart-cosplay", + "filename": "17s", "rotated": false, "trimmed": true, "sourceSize": { @@ -6240,14 +6030,35 @@ "h": 20 }, "frame": { - "x": 173, - "y": 433, + "x": 138, + "y": 636, "w": 21, "h": 20 } }, { - "filename": "25s-tough-cosplay", + "filename": "4s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 9, + "w": 21, + "h": 19 + }, + "frame": { + "x": 138, + "y": 656, + "w": 21, + "h": 19 + } + }, + { + "filename": "25-cool-cosplay", "rotated": false, "trimmed": true, "sourceSize": { @@ -6261,14 +6072,14 @@ "h": 20 }, "frame": { - "x": 173, - "y": 453, + "x": 137, + "y": 675, "w": 21, "h": 20 } }, { - "filename": "25s", + "filename": "25-cosplay", "rotated": false, "trimmed": true, "sourceSize": { @@ -6282,8 +6093,8 @@ "h": 20 }, "frame": { - "x": 173, - "y": 473, + "x": 137, + "y": 695, "w": 21, "h": 20 } @@ -6303,14 +6114,14 @@ "h": 21 }, "frame": { - "x": 175, - "y": 493, + "x": 138, + "y": 715, "w": 20, "h": 21 } }, { - "filename": "135s", + "filename": "1s", "rotated": false, "trimmed": true, "sourceSize": { @@ -6319,355 +6130,19 @@ }, "spriteSourceSize": { "x": 10, - "y": 7, - "w": 20, - "h": 21 - }, - "frame": { - "x": 175, - "y": 514, - "w": 20, - "h": 21 - } - }, - { - "filename": "54", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 7, - "w": 18, - "h": 21 - }, - "frame": { - "x": 180, - "y": 535, - "w": 18, - "h": 21 - } - }, - { - "filename": "54s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 7, - "w": 18, - "h": 21 - }, - "frame": { - "x": 180, - "y": 556, - "w": 18, - "h": 21 - } - }, - { - "filename": "32", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 18, - "h": 20 - }, - "frame": { - "x": 180, - "y": 577, - "w": 18, - "h": 20 - } - }, - { - "filename": "32s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 18, - "h": 20 - }, - "frame": { - "x": 180, - "y": 597, - "w": 18, - "h": 20 - } - }, - { - "filename": "37", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 20, - "h": 20 - }, - "frame": { - "x": 180, - "y": 617, - "w": 20, - "h": 20 - } - }, - { - "filename": "37s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 20, - "h": 20 - }, - "frame": { - "x": 183, - "y": 637, - "w": 20, - "h": 20 - } - }, - { - "filename": "7s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 21, - "h": 17 - }, - "frame": { - "x": 195, - "y": 429, - "w": 21, - "h": 17 - } - }, - { - "filename": "41", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 21, - "h": 20 - }, - "frame": { - "x": 194, - "y": 446, - "w": 21, - "h": 20 - } - }, - { - "filename": "41s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 21, - "h": 20 - }, - "frame": { - "x": 194, - "y": 466, - "w": 21, - "h": 20 - } - }, - { - "filename": "84", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 21, - "h": 18 - }, - "frame": { - "x": 216, - "y": 428, - "w": 21, - "h": 18 - } - }, - { - "filename": "113", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 19, - "h": 20 - }, - "frame": { - "x": 237, - "y": 441, - "w": 19, - "h": 20 - } - }, - { - "filename": "107", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 215, - "y": 446, - "w": 21, - "h": 20 - } - }, - { - "filename": "104", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, "y": 9, "w": 20, "h": 19 }, "frame": { - "x": 236, - "y": 461, + "x": 138, + "y": 736, "w": 20, "h": 19 } }, { - "filename": "107s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 215, - "y": 466, - "w": 21, - "h": 20 - } - }, - { - "filename": "104s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 9, - "w": 20, - "h": 19 - }, - "frame": { - "x": 236, - "y": 480, - "w": 20, - "h": 19 - } - }, - { - "filename": "124", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 195, - "y": 486, - "w": 21, - "h": 20 - } - }, - { - "filename": "27s", + "filename": "25-smart-cosplay", "rotated": false, "trimmed": true, "sourceSize": { @@ -6676,80 +6151,17 @@ }, "spriteSourceSize": { "x": 10, - "y": 10, - "w": 20, - "h": 18 - }, - "frame": { - "x": 216, - "y": 486, - "w": 20, - "h": 18 - } - }, - { - "filename": "147", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 10, - "w": 20, - "h": 18 - }, - "frame": { - "x": 236, - "y": 499, - "w": 20, - "h": 18 - } - }, - { - "filename": "124s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, "y": 8, "w": 21, "h": 20 }, "frame": { - "x": 195, - "y": 506, + "x": 137, + "y": 755, "w": 21, "h": 20 } }, - { - "filename": "147s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 10, - "w": 20, - "h": 18 - }, - "frame": { - "x": 216, - "y": 504, - "w": 20, - "h": 18 - } - }, { "filename": "60", "rotated": false, @@ -6765,8 +6177,8 @@ "h": 15 }, "frame": { - "x": 236, - "y": 517, + "x": 137, + "y": 775, "w": 20, "h": 15 } @@ -6786,161 +6198,14 @@ "h": 15 }, "frame": { - "x": 216, - "y": 522, + "x": 157, + "y": 775, "w": 20, "h": 15 } }, { - "filename": "39", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 18, - "h": 20 - }, - "frame": { - "x": 198, - "y": 526, - "w": 18, - "h": 20 - } - }, - { - "filename": "69", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 13, - "w": 20, - "h": 15 - }, - "frame": { - "x": 236, - "y": 532, - "w": 20, - "h": 15 - } - }, - { - "filename": "69s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 13, - "w": 20, - "h": 15 - }, - "frame": { - "x": 216, - "y": 537, - "w": 20, - "h": 15 - } - }, - { - "filename": "39s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 18, - "h": 20 - }, - "frame": { - "x": 198, - "y": 546, - "w": 18, - "h": 20 - } - }, - { - "filename": "113s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 19, - "h": 20 - }, - "frame": { - "x": 198, - "y": 566, - "w": 19, - "h": 20 - } - }, - { - "filename": "123", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 19, - "h": 19 - }, - "frame": { - "x": 198, - "y": 586, - "w": 19, - "h": 19 - } - }, - { - "filename": "50s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 14, - "w": 15, - "h": 14 - }, - "frame": { - "x": 216, - "y": 552, - "w": 15, - "h": 14 - } - }, - { - "filename": "66", + "filename": "54s", "rotated": false, "trimmed": true, "sourceSize": { @@ -6949,19 +6214,19 @@ }, "spriteSourceSize": { "x": 12, - "y": 8, - "w": 16, - "h": 20 + "y": 7, + "w": 18, + "h": 21 }, "frame": { - "x": 217, - "y": 566, - "w": 16, - "h": 20 + "x": 159, + "y": 636, + "w": 18, + "h": 21 } }, { - "filename": "29s", + "filename": "25-tough-cosplay", "rotated": false, "trimmed": true, "sourceSize": { @@ -6969,16 +6234,100 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 18, - "h": 19 + "x": 10, + "y": 8, + "w": 21, + "h": 20 }, "frame": { - "x": 217, - "y": 586, - "w": 18, - "h": 19 + "x": 159, + "y": 657, + "w": 21, + "h": 20 + } + }, + { + "filename": "25", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 158, + "y": 677, + "w": 21, + "h": 20 + } + }, + { + "filename": "25s-cool-cosplay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 158, + "y": 697, + "w": 21, + "h": 20 + } + }, + { + "filename": "25s-cosplay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 158, + "y": 717, + "w": 21, + "h": 20 + } + }, + { + "filename": "25s-smart-cosplay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 158, + "y": 737, + "w": 21, + "h": 20 } }, { @@ -6996,14 +6345,14 @@ "h": 18 }, "frame": { - "x": 200, - "y": 605, + "x": 158, + "y": 757, "w": 21, "h": 18 } }, { - "filename": "35", + "filename": "69", "rotated": false, "trimmed": true, "sourceSize": { @@ -7011,20 +6360,41 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, + "x": 11, + "y": 13, + "w": 20, + "h": 15 + }, + "frame": { + "x": 177, + "y": 775, + "w": 20, + "h": 15 + } + }, + { + "filename": "61", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, "y": 9, - "w": 18, + "w": 22, "h": 19 }, "frame": { - "x": 221, - "y": 605, - "w": 18, + "x": 170, + "y": 482, + "w": 22, "h": 19 } }, { - "filename": "120", + "filename": "61s", "rotated": false, "trimmed": true, "sourceSize": { @@ -7032,18 +6402,165 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, + "x": 10, + "y": 9, + "w": 22, + "h": 19 + }, + "frame": { + "x": 192, + "y": 486, + "w": 22, + "h": 19 + } + }, + { + "filename": "7s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, "y": 11, - "w": 17, + "w": 21, "h": 17 }, "frame": { - "x": 239, - "y": 547, - "w": 17, + "x": 214, + "y": 490, + "w": 21, "h": 17 } }, + { + "filename": "135s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 20, + "h": 21 + }, + "frame": { + "x": 235, + "y": 490, + "w": 20, + "h": 21 + } + }, + { + "filename": "25s-tough-cosplay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 168, + "y": 501, + "w": 21, + "h": 20 + } + }, + { + "filename": "25s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 166, + "y": 521, + "w": 21, + "h": 20 + } + }, + { + "filename": "41", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 21, + "h": 20 + }, + "frame": { + "x": 166, + "y": 541, + "w": 21, + "h": 20 + } + }, + { + "filename": "41s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 21, + "h": 20 + }, + "frame": { + "x": 189, + "y": 505, + "w": 21, + "h": 20 + } + }, + { + "filename": "107", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 187, + "y": 525, + "w": 21, + "h": 20 + } + }, { "filename": "88", "rotated": false, @@ -7059,8 +6576,8 @@ "h": 18 }, "frame": { - "x": 235, - "y": 564, + "x": 187, + "y": 545, "w": 21, "h": 18 } @@ -7080,14 +6597,14 @@ "h": 18 }, "frame": { - "x": 235, - "y": 582, + "x": 210, + "y": 507, "w": 21, "h": 18 } }, { - "filename": "120s", + "filename": "107s", "rotated": false, "trimmed": true, "sourceSize": { @@ -7095,62 +6612,125 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 11, - "w": 17, - "h": 17 - }, - "frame": { - "x": 239, - "y": 600, - "w": 17, - "h": 17 - } - }, - { - "filename": "100", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 14, - "w": 14, - "h": 14 - }, - "frame": { - "x": 200, - "y": 623, - "w": 14, - "h": 14 - } - }, - { - "filename": "66s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, + "x": 7, "y": 8, - "w": 16, + "w": 21, "h": 20 }, "frame": { - "x": 203, - "y": 637, - "w": 16, + "x": 208, + "y": 525, + "w": 21, "h": 20 } }, { - "filename": "123s", + "filename": "124", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 208, + "y": 545, + "w": 21, + "h": 20 + } + }, + { + "filename": "124s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 166, + "y": 561, + "w": 21, + "h": 20 + } + }, + { + "filename": "27", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 10, + "w": 20, + "h": 18 + }, + "frame": { + "x": 187, + "y": 563, + "w": 20, + "h": 18 + } + }, + { + "filename": "37", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 20, + "h": 20 + }, + "frame": { + "x": 164, + "y": 581, + "w": 20, + "h": 20 + } + }, + { + "filename": "37s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 20, + "h": 20 + }, + "frame": { + "x": 164, + "y": 601, + "w": 20, + "h": 20 + } + }, + { + "filename": "69s", "rotated": false, "trimmed": true, "sourceSize": { @@ -7159,19 +6739,19 @@ }, "spriteSourceSize": { "x": 11, - "y": 9, - "w": 19, - "h": 19 + "y": 13, + "w": 20, + "h": 15 }, "frame": { - "x": 198, - "y": 657, - "w": 19, - "h": 19 + "x": 164, + "y": 621, + "w": 20, + "h": 15 } }, { - "filename": "35s", + "filename": "141", "rotated": false, "trimmed": true, "sourceSize": { @@ -7179,18 +6759,270 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, + "x": 10, + "y": 7, + "w": 19, + "h": 21 + }, + "frame": { + "x": 184, + "y": 581, + "w": 19, + "h": 21 + } + }, + { + "filename": "141s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 19, + "h": 21 + }, + "frame": { + "x": 184, + "y": 602, + "w": 19, + "h": 21 + } + }, + { + "filename": "27s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 10, + "w": 20, + "h": 18 + }, + "frame": { + "x": 207, + "y": 565, + "w": 20, + "h": 18 + } + }, + { + "filename": "104", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, "y": 9, - "w": 18, + "w": 20, "h": 19 }, "frame": { - "x": 198, - "y": 676, - "w": 18, + "x": 203, + "y": 583, + "w": 20, "h": 19 } }, + { + "filename": "104s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 20, + "h": 19 + }, + "frame": { + "x": 203, + "y": 602, + "w": 20, + "h": 19 + } + }, + { + "filename": "21", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 19, + "h": 16 + }, + "frame": { + "x": 184, + "y": 623, + "w": 19, + "h": 16 + } + }, + { + "filename": "147", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 10, + "w": 20, + "h": 18 + }, + "frame": { + "x": 203, + "y": 621, + "w": 20, + "h": 18 + } + }, + { + "filename": "147s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 10, + "w": 20, + "h": 18 + }, + "frame": { + "x": 177, + "y": 639, + "w": 20, + "h": 18 + } + }, + { + "filename": "32", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 8, + "w": 18, + "h": 20 + }, + "frame": { + "x": 180, + "y": 657, + "w": 18, + "h": 20 + } + }, + { + "filename": "113", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 19, + "h": 20 + }, + "frame": { + "x": 179, + "y": 677, + "w": 19, + "h": 20 + } + }, + { + "filename": "113s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 19, + "h": 20 + }, + "frame": { + "x": 179, + "y": 697, + "w": 19, + "h": 20 + } + }, + { + "filename": "32s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 8, + "w": 18, + "h": 20 + }, + "frame": { + "x": 179, + "y": 717, + "w": 18, + "h": 20 + } + }, + { + "filename": "39", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 18, + "h": 20 + }, + "frame": { + "x": 179, + "y": 737, + "w": 18, + "h": 20 + } + }, { "filename": "90", "rotated": false, @@ -7206,8 +7038,8 @@ "h": 18 }, "frame": { - "x": 198, - "y": 695, + "x": 179, + "y": 757, "w": 19, "h": 18 } @@ -7227,14 +7059,14 @@ "h": 18 }, "frame": { - "x": 198, - "y": 713, + "x": 197, + "y": 639, "w": 19, "h": 18 } }, { - "filename": "132s", + "filename": "39s", "rotated": false, "trimmed": true, "sourceSize": { @@ -7242,20 +7074,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 15, - "w": 16, - "h": 13 + "x": 10, + "y": 8, + "w": 18, + "h": 20 }, "frame": { - "x": 214, - "y": 624, - "w": 16, - "h": 13 + "x": 198, + "y": 657, + "w": 18, + "h": 20 } }, { - "filename": "11s", + "filename": "29", "rotated": false, "trimmed": true, "sourceSize": { @@ -7263,20 +7095,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 14, - "y": 10, - "w": 12, - "h": 18 + "x": 11, + "y": 9, + "w": 18, + "h": 19 }, "frame": { - "x": 219, - "y": 637, - "w": 12, - "h": 18 + "x": 198, + "y": 677, + "w": 18, + "h": 19 } }, { - "filename": "13", + "filename": "29s", "rotated": false, "trimmed": true, "sourceSize": { @@ -7284,16 +7116,79 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 11, - "w": 16, - "h": 17 + "x": 11, + "y": 9, + "w": 18, + "h": 19 }, "frame": { - "x": 239, - "y": 617, - "w": 16, - "h": 17 + "x": 198, + "y": 696, + "w": 18, + "h": 19 + } + }, + { + "filename": "21s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 19, + "h": 16 + }, + "frame": { + "x": 231, + "y": 511, + "w": 19, + "h": 16 + } + }, + { + "filename": "123", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 9, + "w": 19, + "h": 19 + }, + "frame": { + "x": 229, + "y": 527, + "w": 19, + "h": 19 + } + }, + { + "filename": "123s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 9, + "w": 19, + "h": 19 + }, + "frame": { + "x": 229, + "y": 546, + "w": 19, + "h": 19 } }, { @@ -7311,12 +7206,96 @@ "h": 18 }, "frame": { - "x": 231, - "y": 634, + "x": 227, + "y": 565, "w": 19, "h": 18 } }, + { + "filename": "35", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 9, + "w": 18, + "h": 19 + }, + "frame": { + "x": 223, + "y": 583, + "w": 18, + "h": 19 + } + }, + { + "filename": "10s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 12, + "w": 14, + "h": 16 + }, + "frame": { + "x": 241, + "y": 583, + "w": 14, + "h": 16 + } + }, + { + "filename": "35s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 9, + "w": 18, + "h": 19 + }, + "frame": { + "x": 223, + "y": 602, + "w": 18, + "h": 19 + } + }, + { + "filename": "100s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 14, + "w": 14, + "h": 14 + }, + "frame": { + "x": 241, + "y": 599, + "w": 14, + "h": 14 + } + }, { "filename": "114s", "rotated": false, @@ -7332,8 +7311,8 @@ "h": 18 }, "frame": { - "x": 194, - "y": 731, + "x": 223, + "y": 621, "w": 19, "h": 18 } @@ -7353,8 +7332,29 @@ "h": 18 }, "frame": { - "x": 213, - "y": 731, + "x": 242, + "y": 613, + "w": 13, + "h": 18 + } + }, + { + "filename": "14s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 10, + "w": 13, + "h": 18 + }, + "frame": { + "x": 242, + "y": 631, "w": 13, "h": 18 } @@ -7374,75 +7374,12 @@ "h": 18 }, "frame": { - "x": 202, - "y": 749, + "x": 216, + "y": 639, "w": 19, "h": 18 } }, - { - "filename": "100s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 14, - "w": 14, - "h": 14 - }, - "frame": { - "x": 202, - "y": 767, - "w": 14, - "h": 14 - } - }, - { - "filename": "14s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 10, - "w": 13, - "h": 18 - }, - "frame": { - "x": 221, - "y": 749, - "w": 13, - "h": 18 - } - }, - { - "filename": "140", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 15, - "w": 16, - "h": 13 - }, - "frame": { - "x": 216, - "y": 767, - "w": 16, - "h": 13 - } - }, { "filename": "121s", "rotated": false, @@ -7458,33 +7395,12 @@ "h": 18 }, "frame": { - "x": 231, - "y": 652, + "x": 216, + "y": 657, "w": 19, "h": 18 } }, - { - "filename": "10", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 12, - "w": 14, - "h": 16 - }, - "frame": { - "x": 217, - "y": 657, - "w": 14, - "h": 16 - } - }, { "filename": "137", "rotated": false, @@ -7500,33 +7416,12 @@ "h": 18 }, "frame": { - "x": 231, - "y": 670, + "x": 216, + "y": 675, "w": 19, "h": 18 } }, - { - "filename": "10s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 12, - "w": 14, - "h": 16 - }, - "frame": { - "x": 217, - "y": 673, - "w": 14, - "h": 16 - } - }, { "filename": "137s", "rotated": false, @@ -7542,14 +7437,14 @@ "h": 18 }, "frame": { - "x": 217, - "y": 689, + "x": 216, + "y": 693, "w": 19, "h": 18 } }, { - "filename": "138", + "filename": "43s", "rotated": false, "trimmed": true, "sourceSize": { @@ -7557,41 +7452,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 10, - "w": 18, - "h": 18 + "x": 13, + "y": 9, + "w": 17, + "h": 19 }, "frame": { - "x": 217, - "y": 707, - "w": 18, - "h": 18 + "x": 235, + "y": 649, + "w": 17, + "h": 19 } }, { - "filename": "138s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 10, - "w": 18, - "h": 18 - }, - "frame": { - "x": 236, - "y": 688, - "w": 18, - "h": 18 - } - }, - { - "filename": "13s", + "filename": "122", "rotated": false, "trimmed": true, "sourceSize": { @@ -7600,19 +7474,19 @@ }, "spriteSourceSize": { "x": 12, - "y": 11, - "w": 16, - "h": 17 + "y": 10, + "w": 17, + "h": 18 }, "frame": { - "x": 226, - "y": 725, - "w": 16, - "h": 17 + "x": 235, + "y": 668, + "w": 17, + "h": 18 } }, { - "filename": "16", + "filename": "122s", "rotated": false, "trimmed": true, "sourceSize": { @@ -7620,37 +7494,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 11, - "w": 18, - "h": 17 + "x": 12, + "y": 10, + "w": 17, + "h": 18 }, "frame": { - "x": 236, - "y": 706, - "w": 18, - "h": 17 - } - }, - { - "filename": "16s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 11, - "w": 18, - "h": 17 - }, - "frame": { - "x": 234, - "y": 742, - "w": 18, - "h": 17 + "x": 235, + "y": 686, + "w": 17, + "h": 18 } }, { @@ -7668,8 +7521,8 @@ "h": 17 }, "frame": { - "x": 234, - "y": 759, + "x": 235, + "y": 704, "w": 18, "h": 17 } @@ -7689,14 +7542,56 @@ "h": 17 }, "frame": { - "x": 139, - "y": 151, + "x": 216, + "y": 711, "w": 18, "h": 17 } }, { - "filename": "140s", + "filename": "138", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 10, + "w": 18, + "h": 18 + }, + "frame": { + "x": 198, + "y": 715, + "w": 18, + "h": 18 + } + }, + { + "filename": "138s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 10, + "w": 18, + "h": 18 + }, + "frame": { + "x": 197, + "y": 733, + "w": 18, + "h": 18 + } + }, + { + "filename": "133", "rotated": false, "trimmed": true, "sourceSize": { @@ -7705,15 +7600,78 @@ }, "spriteSourceSize": { "x": 12, - "y": 15, - "w": 16, - "h": 13 + "y": 10, + "w": 17, + "h": 18 }, "frame": { - "x": 139, - "y": 168, - "w": 16, - "h": 13 + "x": 198, + "y": 751, + "w": 17, + "h": 18 + } + }, + { + "filename": "120", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 17, + "h": 17 + }, + "frame": { + "x": 234, + "y": 721, + "w": 17, + "h": 17 + } + }, + { + "filename": "120s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 17, + "h": 17 + }, + "frame": { + "x": 198, + "y": 769, + "w": 17, + "h": 17 + } + }, + { + "filename": "133s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 10, + "w": 17, + "h": 18 + }, + "frame": { + "x": 216, + "y": 728, + "w": 17, + "h": 18 } }, { @@ -7731,11 +7689,137 @@ "h": 16 }, "frame": { - "x": 140, - "y": 181, + "x": 215, + "y": 746, "w": 16, "h": 16 } + }, + { + "filename": "11", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 14, + "y": 10, + "w": 12, + "h": 18 + }, + "frame": { + "x": 215, + "y": 762, + "w": 12, + "h": 18 + } + }, + { + "filename": "132", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 16, + "h": 13 + }, + "frame": { + "x": 233, + "y": 738, + "w": 16, + "h": 13 + } + }, + { + "filename": "132s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 16, + "h": 13 + }, + "frame": { + "x": 231, + "y": 751, + "w": 16, + "h": 13 + } + }, + { + "filename": "140", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 16, + "h": 13 + }, + "frame": { + "x": 227, + "y": 764, + "w": 16, + "h": 13 + } + }, + { + "filename": "11s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 14, + "y": 10, + "w": 12, + "h": 18 + }, + "frame": { + "x": 243, + "y": 764, + "w": 12, + "h": 18 + } + }, + { + "filename": "140s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 16, + "h": 13 + }, + "frame": { + "x": 227, + "y": 777, + "w": 16, + "h": 13 + } } ] } @@ -7743,6 +7827,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:d0b3eae5bc789f80cb01f31ccda54100:9236111734280a77fd4ebe99bdec6143:e0e302e76ca76d7185883646a41dda84$" + "smartupdate": "$TexturePacker:SmartUpdate:67cbb69780250451ffff0dda6617c079:95ec22440af6402ebbc5ded9fb8ffd09:e0e302e76ca76d7185883646a41dda84$" } } diff --git a/public/images/pokemon_icons_1.png b/public/images/pokemon_icons_1.png index d30fa5bb3cd..ee3a10ef113 100644 Binary files a/public/images/pokemon_icons_1.png and b/public/images/pokemon_icons_1.png differ diff --git a/public/images/trainer/sailor.json b/public/images/trainer/sailor.json new file mode 100644 index 00000000000..6a9331dbaf6 --- /dev/null +++ b/public/images/trainer/sailor.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "sailor.png", + "format": "RGBA8888", + "size": { + "w": 72, + "h": 72 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 72, + "h": 72 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 73, + "h": 73 + }, + "frame": { + "x": 0, + "y": 0, + "w": 39, + "h": 72 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:f692676a166fc1915532cd94d5799af4:fb833f76fb6797474657726bb59a7eee:aeb55e30992938f494b6cd2420158dda$" + } +} diff --git a/public/images/trainer/sailor.png b/public/images/trainer/sailor.png new file mode 100644 index 00000000000..ec61152bce3 Binary files /dev/null and b/public/images/trainer/sailor.png differ diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 638314b3444..c2097391894 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -13,15 +13,15 @@ import { Biome } from "./data/enums/biome"; import { Arena, ArenaBase } from "./field/arena"; import { GameData } from "./system/game-data"; import { PlayerGender } from "./data/enums/player-gender"; -import { TextStyle, addTextObject } from "./ui/text"; +import { TextStyle, addTextObject, getTextColor } from "./ui/text"; import { Moves } from "./data/enums/moves"; import { allMoves } from "./data/move"; import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getPartyLuckValue } from "./modifier/modifier-type"; import AbilityBar from "./ui/ability-bar"; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability"; import { allAbilities } from "./data/ability"; -import Battle, { BattleType, FixedBattleConfig, fixedBattles } from "./battle"; -import { GameMode, GameModes, gameModes } from "./game-mode"; +import Battle, { BattleType, FixedBattleConfig } from "./battle"; +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"; @@ -62,6 +62,7 @@ import { NewArenaEvent } from "./battle-scene-events"; import { Abilities } from "./data/enums/abilities"; import ArenaFlyout from "./ui/arena-flyout"; import { EaseType } from "./ui/enums/ease-type"; +import { ExpNotification } from "./enums/exp-notification"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -125,6 +126,7 @@ export default class BattleScene extends SceneBase { public uiTheme: UiTheme = UiTheme.DEFAULT; public windowType: integer = 0; public experimentalSprites: boolean = false; + public musicPreference: integer = 0; public moveAnimations: boolean = true; public expGainsSpeed: integer = 0; public skipSeenDialogues: boolean = false; @@ -141,7 +143,7 @@ export default class BattleScene extends SceneBase { * Modes `1` and `2` are still compatible with stats display, level up, new move, etc. * @default 0 - Uses the default normal experience gain display. */ - public expParty: integer = 0; + public expParty: ExpNotification = 0; public hpBarSpeed: integer = 0; public fusionPaletteSwaps: boolean = true; public enableTouchControls: boolean = false; @@ -153,12 +155,19 @@ export default class BattleScene extends SceneBase { */ public battleStyle: integer = 0; + /** + * Defines whether or not to show type effectiveness hints + * - true: No hints + * - false: Show hints for moves + */ + public typeHints: boolean = false; + public disableMenu: boolean = false; public gameData: GameData; public sessionSlotId: integer; - private phaseQueue: Phase[]; + public phaseQueue: Phase[]; private phaseQueuePrepend: Phase[]; private phaseQueuePrependSpliceIndex: integer; private nextCommandPhaseQueue: Phase[]; @@ -200,7 +209,7 @@ export default class BattleScene extends SceneBase { public arenaFlyout: ArenaFlyout; private fieldOverlay: Phaser.GameObjects.Rectangle; - private modifiers: PersistentModifier[]; + public modifiers: PersistentModifier[]; private enemyModifiers: PersistentModifier[]; public uiContainer: Phaser.GameObjects.Container; public ui: UI; @@ -225,6 +234,7 @@ export default class BattleScene extends SceneBase { public rngSeedOverride: string = ""; public rngOffset: integer = 0; + public inputMethod: string; private infoToggles: InfoToggle[] = []; /** @@ -299,7 +309,8 @@ export default class BattleScene extends SceneBase { this.fieldSpritePipeline = new FieldSpritePipeline(this.game); (this.renderer as Phaser.Renderer.WebGL.WebGLRenderer).pipelines.add("FieldSprite", this.fieldSpritePipeline); - this.time.delayedCall(20, () => this.launchBattle()); + + this.launchBattle(); } update() { @@ -320,6 +331,7 @@ export default class BattleScene extends SceneBase { const field = this.add.container(0, 0); field.setScale(6); + field.setName("container-field"); this.field = field; @@ -409,28 +421,28 @@ export default class BattleScene extends SceneBase { this.biomeWaveText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, startingWave.toString(), TextStyle.BATTLE_INFO); this.biomeWaveText.setName("text-biome-wave"); - this.biomeWaveText.setOrigin(1, 0); + this.biomeWaveText.setOrigin(1, 0.5); this.fieldUI.add(this.biomeWaveText); this.moneyText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, "", TextStyle.MONEY); this.moneyText.setName("text-money"); - this.moneyText.setOrigin(1, 0); + this.moneyText.setOrigin(1, 0.5); this.fieldUI.add(this.moneyText); this.scoreText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, "", TextStyle.PARTY, { fontSize: "54px" }); this.scoreText.setName("text-score"); - this.scoreText.setOrigin(1, 0); + this.scoreText.setOrigin(1, 0.5); this.fieldUI.add(this.scoreText); this.luckText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, "", TextStyle.PARTY, { fontSize: "54px" }); this.luckText.setName("text-luck"); - this.luckText.setOrigin(1, 0); + this.luckText.setOrigin(1, 0.5); this.luckText.setVisible(false); this.fieldUI.add(this.luckText); this.luckLabelText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, "Luck:", TextStyle.PARTY, { fontSize: "54px" }); this.luckLabelText.setName("text-luck-label"); - this.luckLabelText.setOrigin(1, 0); + this.luckLabelText.setOrigin(1, 0.5); this.luckLabelText.setVisible(false); this.fieldUI.add(this.luckLabelText); @@ -455,9 +467,13 @@ export default class BattleScene extends SceneBase { const loadPokemonAssets = []; this.arenaPlayer = new ArenaBase(this, true); + this.arenaPlayer.setName("container-arena-player"); this.arenaPlayerTransition = new ArenaBase(this, true); + this.arenaPlayerTransition.setName("container-arena-player-transition"); this.arenaEnemy = new ArenaBase(this, false); + this.arenaEnemy.setName("container-arena-enemy"); this.arenaNextEnemy = new ArenaBase(this, false); + this.arenaNextEnemy.setName("container-arena-next-enemy"); this.arenaBgTransition.setVisible(false); this.arenaPlayerTransition.setVisible(false); @@ -472,6 +488,7 @@ export default class BattleScene extends SceneBase { const trainer = this.addFieldSprite(0, 0, `trainer_${this.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`); trainer.setOrigin(0.5, 1); + trainer.setName("sprite-trainer"); field.add(trainer); @@ -844,7 +861,7 @@ export default class BattleScene extends SceneBase { this.gameData = new GameData(this); } - this.gameMode = gameModes[GameModes.CLASSIC]; + this.gameMode = getGameMode(GameModes.CLASSIC); this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24)); console.log("Seed:", this.seed); @@ -940,7 +957,8 @@ export default class BattleScene extends SceneBase { } newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean): Battle { - const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (startingWave - 1)) + 1); + const _startingWave = Overrides.STARTING_WAVE_OVERRIDE || startingWave; + const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (_startingWave - 1)) + 1); let newDouble: boolean; let newBattleType: BattleType; let newTrainer: Trainer; @@ -951,8 +969,8 @@ export default class BattleScene extends SceneBase { const playerField = this.getPlayerField(); - if (this.gameMode.hasFixedBattles && fixedBattles.hasOwnProperty(newWaveIndex) && trainerData === undefined) { - battleConfig = fixedBattles[newWaveIndex]; + if (this.gameMode.isFixedBattle(newWaveIndex) && trainerData === undefined) { + battleConfig = this.gameMode.getFixedBattle(newWaveIndex); newDouble = battleConfig.double; newBattleType = battleConfig.battleType; this.executeWithSeedOffset(() => newTrainer = battleConfig.getTrainer(this), (battleConfig.seedOffsetWaveIndex || newWaveIndex) << 8); @@ -1000,6 +1018,10 @@ export default class BattleScene extends SceneBase { if (Overrides.DOUBLE_BATTLE_OVERRIDE) { newDouble = true; } + /* Override battles into single only if not fighting with trainers */ + if (newBattleType !== BattleType.TRAINER && Overrides.SINGLE_BATTLE_OVERRIDE) { + newDouble = false; + } const lastBattle = this.currentBattle; @@ -1369,8 +1391,7 @@ export default class BattleScene extends SceneBase { if (this.money === undefined) { return; } - const formattedMoney = - this.moneyFormat === MoneyFormat.ABBREVIATED ? Utils.formatFancyLargeNumber(this.money, 3) : this.money.toLocaleString(); + const formattedMoney = Utils.formatMoney(this.moneyFormat, this.money); this.moneyText.setText(`₽${formattedMoney}`); this.fieldUI.moveAbove(this.moneyText, this.luckText); if (forceVisible) { @@ -1378,6 +1399,22 @@ export default class BattleScene extends SceneBase { } } + animateMoneyChanged(positiveChange: boolean): void { + if (this.tweens.getTweensOf(this.moneyText).length > 0) { + return; + } + const deltaScale = this.moneyText.scale * 0.14 * (positiveChange ? 1 : -1); + this.moneyText.setShadowColor(positiveChange ? "#008000" : "#FF0000"); + this.tweens.add({ + targets: this.moneyText, + duration: 250, + scale: this.moneyText.scale + deltaScale, + loop: 0, + yoyo: true, + onComplete: (_) => this.moneyText.setShadowColor(getTextColor(TextStyle.MONEY, true)), + }); + } + updateScoreText(): void { this.scoreText.setText(`Score: ${this.score.toString()}`); this.scoreText.setVisible(this.gameMode.isDaily); @@ -1421,7 +1458,10 @@ export default class BattleScene extends SceneBase { updateUIPositions(): void { const enemyModifierCount = this.enemyModifiers.filter(m => m.isIconVisible(this)).length; - this.biomeWaveText.setY(-(this.game.canvas.height / 6) + (enemyModifierCount ? enemyModifierCount <= 12 ? 15 : 24 : 0)); + const biomeWaveTextHeight = this.biomeWaveText.getBottomLeft().y - this.biomeWaveText.getTopLeft().y; + this.biomeWaveText.setY( + -(this.game.canvas.height / 6) + (enemyModifierCount ? enemyModifierCount <= 12 ? 15 : 24 : 0) + (biomeWaveTextHeight / 2) + ); this.moneyText.setY(this.biomeWaveText.y + 10); this.scoreText.setY(this.moneyText.y + 10); [ this.luckLabelText, this.luckText ].map(l => l.setY((this.scoreText.visible ? this.scoreText : this.moneyText).y + 10)); @@ -1640,55 +1680,145 @@ export default class BattleScene extends SceneBase { getBgmLoopPoint(bgmName: string): number { switch (bgmName) { - case "battle_kanto_champion": + case "battle_kanto_champion": //B2W2 Kanto Champion Battle return 13.950; - case "battle_johto_champion": + case "battle_johto_champion": //B2W2 Johto Champion Battle return 23.498; - case "battle_hoenn_champion": + case "battle_hoenn_champion": //B2W2 Hoenn Champion Battle return 11.328; - case "battle_sinnoh_champion": + case "battle_sinnoh_champion": //B2W2 Sinnoh Champion Battle return 12.235; - case "battle_champion_alder": + case "battle_champion_alder": //BW Unova Champion Battle return 27.653; - case "battle_champion_iris": + case "battle_champion_iris": //B2W2 Unova Champion Battle return 10.145; - case "battle_elite": + case "battle_kalos_champion": //XY Kalos Champion Battle + return 10.380; + case "battle_alola_champion": //USUM Alola Champion Battle + return 13.025; + case "battle_galar_champion": //SWSH Galar Champion Battle + return 61.635; + case "battle_champion_geeta": //SV Champion Geeta Battle + return 37.447; + case "battle_champion_nemona": //SV Champion Nemona Battle + return 14.914; + case "battle_champion_kieran": //SV Champion Kieran Battle + return 7.206; + case "battle_hoenn_elite": //ORAS Elite Four Battle + return 11.350; + case "battle_unova_elite": //BW Elite Four Battle return 17.730; - case "battle_final_encounter": + case "battle_kalos_elite": //XY Elite Four Battle + return 12.340; + case "battle_alola_elite": //SM Elite Four Battle + return 19.212; + case "battle_galar_elite": //SWSH League Tournament Battle + return 164.069; + case "battle_paldea_elite": //SV Elite Four Battle + return 12.770; + case "battle_bb_elite": //SV BB League Elite Four Battle + return 19.434; + case "battle_final_encounter": //PMD RTDX Rayquaza's Domain return 19.159; - case "battle_final": + case "battle_final": //BW Ghetsis Battle return 16.453; - case "battle_kanto_gym": + case "battle_kanto_gym": //B2W2 Kanto Gym Battle return 13.857; - case "battle_johto_gym": + case "battle_johto_gym": //B2W2 Johto Gym Battle return 12.911; - case "battle_hoenn_gym": + case "battle_hoenn_gym": //B2W2 Hoenn Gym Battle return 12.379; - case "battle_sinnoh_gym": + case "battle_sinnoh_gym": //B2W2 Sinnoh Gym Battle return 13.122; - case "battle_unova_gym": + case "battle_unova_gym": //BW Unova Gym Battle return 19.145; - case "battle_legendary_regis": //B2W2 Legendary Titan Battle + case "battle_kalos_gym": //XY Kalos Gym Battle + return 44.810; + case "battle_galar_gym": //SWSH Galar Gym Battle + return 171.262; + case "battle_paldea_gym": //SV Paldea Gym Battle + return 127.489; + case "battle_legendary_kanto": //XY Kanto Legendary Battle + return 32.966; + case "battle_legendary_raikou": //HGSS Raikou Battle + return 12.632; + case "battle_legendary_entei": //HGSS Entei Battle + return 2.905; + case "battle_legendary_suicune": //HGSS Suicune Battle + return 12.636; + case "battle_legendary_lugia": //HGSS Lugia Battle + return 19.770; + case "battle_legendary_ho_oh": //HGSS Ho-oh Battle + return 17.668; + case "battle_legendary_regis_g5": //B2W2 Legendary Titan Battle return 49.500; + case "battle_legendary_regis_g6": //ORAS Legendary Titan Battle + return 21.130; + case "battle_legendary_gro_kyo": //ORAS Groudon & Kyogre Battle + return 10.547; + case "battle_legendary_rayquaza": //ORAS Rayquaza Battle + return 10.495; + case "battle_legendary_deoxys": //ORAS Deoxys Battle + return 13.333; + case "battle_legendary_lake_trio": //ORAS Lake Guardians Battle + return 16.887; + case "battle_legendary_sinnoh": //ORAS Sinnoh Legendary Battle + return 22.770; + case "battle_legendary_dia_pal": //ORAS Dialga & Palkia Battle + return 16.009; + case "battle_legendary_giratina": //ORAS Giratina Battle + return 10.451; + case "battle_legendary_arceus": //HGSS Arceus Battle + return 9.595; case "battle_legendary_unova": //BW Unova Legendary Battle return 13.855; case "battle_legendary_kyurem": //BW Kyurem Battle return 18.314; case "battle_legendary_res_zek": //BW Reshiram & Zekrom Battle return 18.329; - case "battle_rival": + case "battle_legendary_xern_yvel": //XY Xerneas & Yveltal Battle + return 26.468; + case "battle_legendary_tapu": //SM Tapu Battle + return 0.000; + case "battle_legendary_sol_lun": //SM Solgaleo & Lunala Battle + return 6.525; + case "battle_legendary_ub": //SM Ultra Beast Battle + return 9.818; + case "battle_legendary_dusk_dawn": //USUM Dusk Mane & Dawn Wings Necrozma Battle + return 5.211; + case "battle_legendary_ultra_nec": //USUM Ultra Necrozma Battle + return 10.344; + case "battle_legendary_zac_zam": //SWSH Zacian & Zamazenta Battle + return 11.424; + case "battle_legendary_glas_spec": //SWSH Glastrier & Spectrier Battle + return 12.503; + case "battle_legendary_calyrex": //SWSH Calyrex Battle + return 50.641; + case "battle_legendary_birds_galar": //SWSH Galarian Legendary Birds Battle + return 0.175; + case "battle_legendary_ruinous": //SV Treasures of Ruin Battle + return 6.333; + case "battle_legendary_loyal_three": //SV Loyal Three Battle + return 6.500; + case "battle_legendary_ogerpon": //SV Ogerpon Battle + return 14.335; + case "battle_legendary_terapagos": //SV Terapagos Battle + return 24.377; + case "battle_legendary_pecharunt": //SV Pecharunt Battle + return 6.508; + case "battle_rival": //BW Rival Battle return 13.689; - case "battle_rival_2": + case "battle_rival_2": //BW N Battle return 17.714; - case "battle_rival_3": + case "battle_rival_3": //BW Final N Battle return 17.586; - case "battle_trainer": + case "battle_trainer": //BW Trainer Battle return 13.686; - case "battle_wild": + case "battle_wild": //BW Wild Battle return 12.703; - case "battle_wild_strong": + case "battle_wild_strong": //BW Strong Wild Battle return 13.940; - case "end_summit": + case "end_summit": //PMD RTDX Sky Tower Summit return 30.025; } @@ -1823,6 +1953,7 @@ export default class BattleScene extends SceneBase { addMoney(amount: integer): void { this.money = Math.min(this.money + amount, Number.MAX_SAFE_INTEGER); this.updateMoneyText(); + this.animateMoneyChanged(true); this.validateAchvs(MoneyAchv); } diff --git a/src/battle.ts b/src/battle.ts index c857a8766ed..104c35a5e9f 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -197,7 +197,11 @@ export default class Battle { if (!this.started && this.trainer.config.encounterBgm && this.trainer.getEncounterMessages()?.length) { return `encounter_${this.trainer.getEncounterBgm()}`; } - return this.trainer.getBattleBgm(); + if (scene.musicPreference === 0) { + return this.trainer.getBattleBgm(); + } else { + return this.trainer.getMixedBattleBgm(); + } } else if (this.gameMode.isClassic && this.waveIndex > 195 && this.battleSpec !== BattleSpec.FINAL_BOSS) { return "end_summit"; } @@ -209,22 +213,116 @@ export default class Battle { return "battle_final_encounter"; } if (pokemon.species.legendary || pokemon.species.subLegendary || pokemon.species.mythical) { - if (pokemon.species.speciesId === Species.REGIROCK || pokemon.species.speciesId === Species.REGICE || pokemon.species.speciesId === Species.REGISTEEL || pokemon.species.speciesId === Species.REGIGIGAS || pokemon.species.speciesId === Species.REGIELEKI || pokemon.species.speciesId === Species.REGIDRAGO) { - return "battle_legendary_regis"; - } - if (pokemon.species.speciesId === Species.COBALION || pokemon.species.speciesId === Species.TERRAKION || pokemon.species.speciesId === Species.VIRIZION || pokemon.species.speciesId === Species.TORNADUS || pokemon.species.speciesId === Species.THUNDURUS || pokemon.species.speciesId === Species.LANDORUS || pokemon.species.speciesId === Species.KELDEO || pokemon.species.speciesId === Species.MELOETTA || pokemon.species.speciesId === Species.GENESECT) { + if (scene.musicPreference === 0) { + if (pokemon.species.speciesId === Species.REGIROCK || pokemon.species.speciesId === Species.REGICE || pokemon.species.speciesId === Species.REGISTEEL || pokemon.species.speciesId === Species.REGIGIGAS || pokemon.species.speciesId === Species.REGIELEKI || pokemon.species.speciesId === Species.REGIDRAGO) { + return "battle_legendary_regis_g5"; + } + if (pokemon.species.speciesId === Species.COBALION || pokemon.species.speciesId === Species.TERRAKION || pokemon.species.speciesId === Species.VIRIZION || pokemon.species.speciesId === Species.TORNADUS || pokemon.species.speciesId === Species.THUNDURUS || pokemon.species.speciesId === Species.LANDORUS || pokemon.species.speciesId === Species.KELDEO || pokemon.species.speciesId === Species.MELOETTA || pokemon.species.speciesId === Species.GENESECT) { + return "battle_legendary_unova"; + } + if (pokemon.species.speciesId === Species.KYUREM) { + return "battle_legendary_kyurem"; + } + if (pokemon.species.legendary) { + return "battle_legendary_res_zek"; + } + return "battle_legendary_unova"; + } else { + if (pokemon.species.speciesId === Species.ARTICUNO || pokemon.species.speciesId === Species.ZAPDOS || pokemon.species.speciesId === Species.MOLTRES || pokemon.species.speciesId === Species.MEWTWO || pokemon.species.speciesId === Species.MEW) { + return "battle_legendary_kanto"; + } + if (pokemon.species.speciesId === Species.RAIKOU) { + return "battle_legendary_raikou"; + } + if (pokemon.species.speciesId === Species.ENTEI) { + return "battle_legendary_entei"; + } + if (pokemon.species.speciesId === Species.SUICUNE) { + return "battle_legendary_suicune"; + } + if (pokemon.species.speciesId === Species.LUGIA) { + return "battle_legendary_lugia"; + } + if (pokemon.species.speciesId === Species.HO_OH) { + return "battle_legendary_ho_oh"; + } + if (pokemon.species.speciesId === Species.REGIROCK || pokemon.species.speciesId === Species.REGICE || pokemon.species.speciesId === Species.REGISTEEL || pokemon.species.speciesId === Species.REGIGIGAS || pokemon.species.speciesId === Species.REGIELEKI || pokemon.species.speciesId === Species.REGIDRAGO) { + return "battle_legendary_regis_g6"; + } + if (pokemon.species.speciesId === Species.GROUDON || pokemon.species.speciesId === Species.KYOGRE) { + return "battle_legendary_gro_kyo"; + } + if (pokemon.species.speciesId === Species.RAYQUAZA) { + return "battle_legendary_rayquaza"; + } + if (pokemon.species.speciesId === Species.DEOXYS) { + return "battle_legendary_deoxys"; + } + if (pokemon.species.speciesId === Species.UXIE || pokemon.species.speciesId === Species.MESPRIT || pokemon.species.speciesId === Species.AZELF) { + return "battle_legendary_lake_trio"; + } + if (pokemon.species.speciesId === Species.HEATRAN || pokemon.species.speciesId === Species.CRESSELIA || pokemon.species.speciesId === Species.DARKRAI || pokemon.species.speciesId === Species.SHAYMIN) { + return "battle_legendary_sinnoh"; + } + if (pokemon.species.speciesId === Species.DIALGA || pokemon.species.speciesId === Species.PALKIA) { + return "battle_legendary_dia_pal"; + } + if (pokemon.species.speciesId === Species.GIRATINA) { + return "battle_legendary_giratina"; + } + if (pokemon.species.speciesId === Species.ARCEUS) { + return "battle_legendary_arceus"; + } + if (pokemon.species.speciesId === Species.COBALION || pokemon.species.speciesId === Species.TERRAKION || pokemon.species.speciesId === Species.VIRIZION || pokemon.species.speciesId === Species.TORNADUS || pokemon.species.speciesId === Species.THUNDURUS || pokemon.species.speciesId === Species.LANDORUS || pokemon.species.speciesId === Species.KELDEO || pokemon.species.speciesId === Species.MELOETTA || pokemon.species.speciesId === Species.GENESECT) { + return "battle_legendary_unova"; + } + if (pokemon.species.speciesId === Species.KYUREM) { + return "battle_legendary_kyurem"; + } + if (pokemon.species.speciesId === Species.XERNEAS || pokemon.species.speciesId === Species.YVELTAL || pokemon.species.speciesId === Species.ZYGARDE) { + return "battle_legendary_xern_yvel"; + } + if (pokemon.species.speciesId === Species.TAPU_KOKO || pokemon.species.speciesId === Species.TAPU_LELE || pokemon.species.speciesId === Species.TAPU_BULU || pokemon.species.speciesId === Species.TAPU_FINI) { + return "battle_legendary_tapu"; + } + if (pokemon.species.speciesId === Species.COSMOG || pokemon.species.speciesId === Species.COSMOEM || pokemon.species.speciesId === Species.SOLGALEO || pokemon.species.speciesId === Species.LUNALA || pokemon.species.speciesId === Species.NECROZMA) { + return "battle_legendary_sol_lun"; + } + if (pokemon.species.speciesId === Species.NIHILEGO || pokemon.species.speciesId === Species.BUZZWOLE || pokemon.species.speciesId === Species.PHEROMOSA || pokemon.species.speciesId === Species.XURKITREE || pokemon.species.speciesId === Species.CELESTEELA || pokemon.species.speciesId === Species.KARTANA || pokemon.species.speciesId === Species.GUZZLORD || pokemon.species.speciesId === Species.POIPOLE || pokemon.species.speciesId === Species.NAGANADEL || pokemon.species.speciesId === Species.STAKATAKA || pokemon.species.speciesId === Species.BLACEPHALON) { + return "battle_legendary_ub"; + } + if (pokemon.species.speciesId === Species.ZACIAN || pokemon.species.speciesId === Species.ZAMAZENTA) { + return "battle_legendary_zac_zam"; + } + if (pokemon.species.speciesId === Species.GLASTRIER || pokemon.species.speciesId === Species.SPECTRIER) { + return "battle_legendary_glas_spec"; + } + if (pokemon.species.speciesId === Species.CALYREX) { + return "battle_legendary_calyrex"; + } + if (pokemon.species.speciesId === Species.GALAR_ARTICUNO || pokemon.species.speciesId === Species.GALAR_ZAPDOS || pokemon.species.speciesId === Species.GALAR_MOLTRES) { + return "battle_legendary_birds_galar"; + } + if (pokemon.species.speciesId === Species.WO_CHIEN || pokemon.species.speciesId === Species.CHIEN_PAO || pokemon.species.speciesId === Species.TING_LU || pokemon.species.speciesId === Species.CHI_YU) { + return "battle_legendary_ruinous"; + } + if (pokemon.species.speciesId === Species.OKIDOGI || pokemon.species.speciesId === Species.MUNKIDORI || pokemon.species.speciesId === Species.FEZANDIPITI) { + return "battle_legendary_loyal_three"; + } + if (pokemon.species.speciesId === Species.OGERPON) { + return "battle_legendary_ogerpon"; + } + if (pokemon.species.speciesId === Species.TERAPAGOS) { + return "battle_legendary_terapagos"; + } + if (pokemon.species.speciesId === Species.PECHARUNT) { + return "battle_legendary_pecharunt"; + } + if (pokemon.species.legendary) { + return "battle_legendary_res_zek"; + } return "battle_legendary_unova"; } - if (pokemon.species.speciesId === Species.RESHIRAM || pokemon.species.speciesId === Species.ZEKROM) { - return "battle_legendary_res_zek"; - } - if (pokemon.species.speciesId === Species.KYUREM) { - return "battle_legendary_kyurem"; - } - if (pokemon.species.legendary) { - return "battle_legendary_res_zek"; - } - return "battle_legendary_unova"; } } @@ -322,11 +420,11 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[]): Get }; } -interface FixedBattleConfigs { +export interface FixedBattleConfigs { [key: integer]: FixedBattleConfig } -export const fixedBattles: FixedBattleConfigs = { +export const classicFixedBattles: FixedBattleConfigs = { [5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), [8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) @@ -340,13 +438,13 @@ export const fixedBattles: FixedBattleConfigs = { [145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), [182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ],TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])), + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])), [184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY, TrainerType.AMARYS ])), [186]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, [TrainerType.BEA_ELITE,TrainerType.ALLISTER_ELITE], TrainerType.LARRY_ELITE, TrainerType.LACEY ])), + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, [ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ], TrainerType.LARRY_ELITE, TrainerType.LACEY ])), [188]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI,TrainerType.RAIHAN_ELITE, TrainerType.HASSEL, TrainerType.DRAYTON ])), + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL, TrainerType.DRAYTON ])), [190]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])), [195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) diff --git a/src/data/ability.ts b/src/data/ability.ts index db44835a86a..f36ce64adef 100755 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -235,10 +235,10 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr { } } -type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: PokemonMove) => boolean; +type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: Move) => boolean; export class PreDefendAbAttr extends AbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -252,7 +252,7 @@ export class PreDefendFormChangeAbAttr extends PreDefendAbAttr { this.formFunc = formFunc; } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); @@ -263,7 +263,7 @@ export class PreDefendFormChangeAbAttr extends PreDefendAbAttr { } } export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (pokemon.hp === pokemon.getMaxHp() && pokemon.getMaxHp() > 1 && //Checks if pokemon has wonder_guard (which forces 1hp) (args[0] as Utils.NumberHolder).value >= pokemon.hp) { //Damage >= hp @@ -308,8 +308,8 @@ export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.condition(pokemon, attacker, move.getMove())) { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (this.condition(pokemon, attacker, move)) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; return true; } @@ -329,8 +329,8 @@ export class PreDefendMovePowerToOneAbAttr extends ReceivedMoveDamageMultiplierA super(condition, 1); } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.condition(pokemon, attacker, move.getMove())) { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (this.condition(pokemon, attacker, move)) { (args[0] as Utils.NumberHolder).value = 1; return true; } @@ -339,6 +339,12 @@ export class PreDefendMovePowerToOneAbAttr extends ReceivedMoveDamageMultiplierA } } +/** + * Determines whether a Pokemon is immune to a move because of an ability. + * @extends PreDefendAbAttr + * @see {@linkcode applyPreDefend} + * @see {@linkcode getCondition} + */ export class TypeImmunityAbAttr extends PreDefendAbAttr { private immuneType: Type; private condition: AbAttrCondition; @@ -350,8 +356,17 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr { this.condition = condition; } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if ((move.getMove() instanceof AttackMove || move.getMove().getAttrs(StatusMoveTypeImmunityAttr).find(attr => attr.immuneType === this.immuneType)) && move.getMove().type === this.immuneType) { + /** + * @param pokemon {@linkcode Pokemon} the defending Pokemon + * @param passive N/A + * @param attacker {@linkcode Pokemon} the attacking Pokemon + * @param move {@linkcode Move} the attacking move + * @param cancelled N/A + * @param args [0] {@linkcode Utils.NumberHolder} gets set to 0 if move is immuned by an ability. + * @param args [1] {@linkcode Utils.NumberHolder} type of move being defended against in case it has changed from default type + */ + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if ((move instanceof AttackMove || move.getAttrs(StatusMoveTypeImmunityAttr).find(attr => attr.immuneType === this.immuneType)) && move.type === this.immuneType) { (args[0] as Utils.NumberHolder).value = 0; return true; } @@ -369,7 +384,7 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr { super(immuneType); } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { @@ -399,7 +414,7 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr { this.levels = levels; } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { @@ -425,7 +440,7 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr { this.turnCount = turnCount; } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { @@ -445,8 +460,8 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { super(null, condition); } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, attacker) < 2) { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (move instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.type, attacker) < 2) { cancelled.value = true; (args[0] as Utils.NumberHolder).value = 0; return true; @@ -461,15 +476,15 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { } export class PostDefendAbAttr extends AbAttr { - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise { return false; } } export class PostDefendDisguiseAbAttr extends PostDefendAbAttr { - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (pokemon.formIndex === 0 && pokemon.battleData.hitCount !== 0 && (move.getMove().category === MoveCategory.SPECIAL || move.getMove().category === MoveCategory.PHYSICAL)) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (pokemon.formIndex === 0 && pokemon.battleData.hitCount !== 0 && (move.category === MoveCategory.SPECIAL || move.category === MoveCategory.PHYSICAL)) { const recoilDamage = Math.ceil((pokemon.getMaxHp() / 8) - attacker.turnData.damageDealt); if (!recoilDamage) { @@ -494,7 +509,7 @@ export class PostDefendFormChangeAbAttr extends PostDefendAbAttr { this.formFunc = formFunc; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); @@ -506,16 +521,16 @@ export class PostDefendFormChangeAbAttr extends PostDefendAbAttr { } export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const attackPriority = new Utils.IntegerHolder(move.getMove().priority); - applyMoveAttrs(IncrementMovePriorityAttr,attacker,null,move.getMove(),attackPriority); - applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move.getMove(), attackPriority); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const attackPriority = new Utils.IntegerHolder(move.priority); + applyMoveAttrs(IncrementMovePriorityAttr,attacker,null,move,attackPriority); + applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move, attackPriority); - if (move.getMove().moveTarget===MoveTarget.USER || move.getMove().moveTarget===MoveTarget.NEAR_ALLY) { + if (move.moveTarget===MoveTarget.USER || move.moveTarget===MoveTarget.NEAR_ALLY) { return false; } - if (attackPriority.value > 0 && !move.getMove().isMultiTarget()) { + if (attackPriority.value > 0 && !move.isMultiTarget()) { cancelled.value = true; return true; } @@ -539,7 +554,7 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { this.immuneCondition = immuneCondition; } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.immuneCondition(pokemon, attacker, move)) { cancelled.value = true; return true; @@ -563,7 +578,7 @@ export class MoveImmunityStatChangeAbAttr extends MoveImmunityAbAttr { this.levels = levels; } - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { const simulated = args.length > 1 && args[1]; @@ -593,8 +608,8 @@ export class ReverseDrainAbAttr extends PostDefendAbAttr { * @args N/A * @returns true if healing should be reversed on a healing move, false otherwise. */ - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (move.getMove().hasAttr(HitHealAttr)) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.hasAttr(HitHealAttr)) { pokemon.scene.queueMessage(getPokemonMessage(attacker, " sucked up the liquid ooze!")); return true; } @@ -619,8 +634,8 @@ export class PostDefendStatChangeAbAttr extends PostDefendAbAttr { this.allOthers = allOthers; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (this.condition(pokemon, attacker, move.getMove())) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (this.condition(pokemon, attacker, move)) { if (this.allOthers) { const otherPokemon = pokemon.getAlly() ? pokemon.getOpponents().concat([ pokemon.getAlly() ]) : pokemon.getOpponents(); for (const other of otherPokemon) { @@ -653,10 +668,10 @@ export class PostDefendHpGatedStatChangeAbAttr extends PostDefendAbAttr { this.selfTarget = selfTarget; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { const hpGateFlat: integer = Math.ceil(pokemon.getMaxHp() * this.hpGate); const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1]; - if (this.condition(pokemon, attacker, move.getMove()) && (pokemon.hp <= hpGateFlat && (pokemon.hp + lastAttackReceived.damage) > hpGateFlat)) { + if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + lastAttackReceived.damage) > hpGateFlat)) { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.levels)); return true; } @@ -676,8 +691,8 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr { this.tagType = tagType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (this.condition(pokemon, attacker, move.getMove())) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (this.condition(pokemon, attacker, move)) { const tag = pokemon.scene.arena.getTag(this.tagType) as ArenaTrapTag; if (!pokemon.scene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers) { pokemon.scene.arena.addTag(this.tagType, 0, undefined, pokemon.id, pokemon.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER); @@ -698,11 +713,11 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { this.tagType = tagType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (this.condition(pokemon, attacker, move.getMove())) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (this.condition(pokemon, attacker, move)) { if (!pokemon.getTag(this.tagType)) { pokemon.addTag(this.tagType, undefined, undefined, pokemon.id); - pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.getName() })); + pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.name })); } return true; } @@ -711,9 +726,9 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { } export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (hitResult < HitResult.NO_EFFECT) { - const type = move.getMove().type; + const type = move.type; const pokemonTypes = pokemon.getTypes(true); if (pokemonTypes.length !== 1 || pokemonTypes[0] !== type) { pokemon.summonData.types = [ type ]; @@ -738,7 +753,7 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr { this.terrainType = terrainType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (hitResult < HitResult.NO_EFFECT) { return pokemon.scene.arena.trySetTerrain(this.terrainType, true); } @@ -758,8 +773,8 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { this.effects = effects; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return attacker.trySetStatus(effect, true, pokemon); } @@ -773,7 +788,7 @@ export class EffectSporeAbAttr extends PostDefendContactApplyStatusEffectAbAttr super(10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP); } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (attacker.hasAbility(Abilities.OVERCOAT) || attacker.isOfType(Type.GRASS)) { return false; } @@ -794,9 +809,9 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { this.turnCount = turnCount; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) { - return attacker.addTag(this.tagType, this.turnCount, move.moveId, attacker.id); + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) { + return attacker.addTag(this.tagType, this.turnCount, move.id, attacker.id); } return false; @@ -814,7 +829,7 @@ export class PostDefendCritStatChangeAbAttr extends PostDefendAbAttr { this.levels = levels; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); return true; @@ -834,8 +849,8 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { this.damageRatio = damageRatio; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); attacker.turnData.damageTaken += Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)); return true; @@ -864,8 +879,8 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr { this.turns = turns; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { if (pokemon.getTag(BattlerTagType.PERISH_SONG) || attacker.getTag(BattlerTagType.PERISH_SONG)) { return false; } else { @@ -891,7 +906,7 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { this.weatherType = weatherType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (!pokemon.scene.arena.weather?.isImmutable()) { return pokemon.scene.arena.trySetWeather(this.weatherType, true); } @@ -905,8 +920,8 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr { super(); } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) { const tempAbilityId = attacker.getAbility().id; attacker.summonData.ability = pokemon.getAbility().id; pokemon.summonData.ability = tempAbilityId; @@ -929,8 +944,8 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr { this.ability = ability; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) { attacker.summonData.ability = this.ability; return true; @@ -947,7 +962,7 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr { export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { private chance: integer; private attacker: Pokemon; - private move: PokemonMove; + private move: Move; constructor(chance: integer) { super(); @@ -955,13 +970,13 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { this.chance = chance; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (!attacker.summonData.disabledMove) { - if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !attacker.isMax()) { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !attacker.isMax()) { this.attacker = attacker; this.move = move; - attacker.summonData.disabledMove = move.moveId; + attacker.summonData.disabledMove = move.id; attacker.summonData.disabledTurns = 4; return true; } @@ -970,7 +985,7 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(this.attacker, `'s ${this.move.getName()}\nwas disabled!`); + return getPokemonMessage(this.attacker, `'s ${this.move.name}\nwas disabled!`); } } @@ -998,49 +1013,18 @@ export class PostStatChangeStatChangeAbAttr extends PostStatChangeAbAttr { } export class PreAttackAbAttr extends AbAttr { - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean | Promise { return false; } } export class VariableMovePowerAbAttr extends PreAttackAbAttr { - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; return false; } } -export class VariableMoveTypeAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - //const power = args[0] as Utils.IntegerHolder; - return false; - } -} - -export class MoveTypeChangePowerMultiplierAbAttr extends VariableMoveTypeAbAttr { - private matchType: Type; - private newType: Type; - private powerMultiplier: number; - - constructor(matchType: Type, newType: Type, powerMultiplier: number) { - super(true); - this.matchType = matchType; - this.newType = newType; - this.powerMultiplier = powerMultiplier; - } - - apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const type = (args[0] as Utils.IntegerHolder); - if (type.value === this.matchType) { - type.value = this.newType; - (args[1] as Utils.NumberHolder).value *= this.powerMultiplier; - return true; - } - - return false; - } -} - export class FieldPreventExplosiveMovesAbAttr extends AbAttr { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { cancelled.value = true; @@ -1060,11 +1044,10 @@ export class MoveTypeChangeAttr extends PreAttackAbAttr { this.condition = condition; } - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { - if (this.condition(pokemon, defender, move.getMove())) { - const type = (args[0] as Utils.IntegerHolder); - type.value = this.newType; - (args[1] as Utils.NumberHolder).value *= this.powerMultiplier; + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + if (this.condition(pokemon, defender, move)) { + move.type = this.newType; + (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; return true; } @@ -1097,8 +1080,8 @@ export class DamageBoostAbAttr extends PreAttackAbAttr { * @param args Utils.NumberHolder as damage * @returns true if the function succeeds */ - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { - if (this.condition(pokemon, defender, move.getMove())) { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + if (this.condition(pokemon, defender, move)) { const power = args[0] as Utils.NumberHolder; power.value = Math.floor(power.value * this.damageMultiplier); return true; @@ -1118,8 +1101,8 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { - if (this.condition(pokemon, defender, move.getMove())) { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + if (this.condition(pokemon, defender, move)) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; return true; @@ -1165,8 +1148,8 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr { /** * @override */ - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { - const multiplier = this.mult(pokemon, defender, move.getMove()); + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move, args: any[]): boolean { + const multiplier = this.mult(pokemon, defender, move); if (multiplier !== 1) { (args[0] as Utils.NumberHolder).value *= multiplier; return true; @@ -1177,7 +1160,7 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr { } export class FieldVariableMovePowerAbAttr extends AbAttr { - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; return false; } @@ -1193,8 +1176,8 @@ export class FieldMovePowerBoostAbAttr extends FieldVariableMovePowerAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { - if (this.condition(pokemon, defender, move.getMove())) { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + if (this.condition(pokemon, defender, move)) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; return true; @@ -1235,7 +1218,7 @@ export class BattleStatMultiplierAbAttr extends AbAttr { } export class PostAttackAbAttr extends AbAttr { - applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise { return false; } } @@ -1249,9 +1232,9 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { this.condition = condition; } - applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { - if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, defender, move.getMove()))) { + if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, defender, move))) { const heldItems = this.getTargetHeldItems(defender).filter(i => i.getTransferrable(false)); if (heldItems.length) { const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; @@ -1287,8 +1270,8 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { this.effects = effects; } - applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (pokemon !== attacker && (!this.contactRequired || move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { + applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return attacker.trySetStatus(effect, true, pokemon); } @@ -1305,11 +1288,11 @@ export class PostAttackContactApplyStatusEffectAbAttr extends PostAttackApplySta export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { private contactRequired: boolean; - private chance: (user: Pokemon, target: Pokemon, move: PokemonMove) => integer; + private chance: (user: Pokemon, target: Pokemon, move: Move) => integer; private effects: BattlerTagType[]; - constructor(contactRequired: boolean, chance: (user: Pokemon, target: Pokemon, move: PokemonMove) => integer, ...effects: BattlerTagType[]) { + constructor(contactRequired: boolean, chance: (user: Pokemon, target: Pokemon, move: Move) => integer, ...effects: BattlerTagType[]) { super(); this.contactRequired = contactRequired; @@ -1317,8 +1300,8 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { this.effects = effects; } - applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (pokemon !== attacker && (!this.contactRequired || move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status) { + applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; @@ -1338,9 +1321,9 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { this.condition = condition; } - applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { - if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move.getMove()))) { + if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) { const heldItems = this.getTargetHeldItems(attacker).filter(i => i.getTransferrable(false)); if (heldItems.length) { const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; @@ -1693,15 +1676,13 @@ export class DownloadAbAttr extends PostSummonAbAttr { this.enemySpDef = 0; this.enemyCountTally = 0; - if (pokemon.getOpponents()[0].summonData !== undefined) { - for (const opponent of pokemon.getOpponents()) { - this.enemyCountTally++; - this.enemyDef += opponent.getBattleStat(Stat.DEF); - this.enemySpDef += opponent.getBattleStat(Stat.SPDEF); - } - this.enemyDef = Math.round(this.enemyDef / this.enemyCountTally); - this.enemySpDef = Math.round(this.enemySpDef / this.enemyCountTally); + for (const opponent of pokemon.getOpponents()) { + this.enemyCountTally++; + this.enemyDef += opponent.getBattleStat(Stat.DEF); + this.enemySpDef += opponent.getBattleStat(Stat.SPDEF); } + this.enemyDef = Math.round(this.enemyDef / this.enemyCountTally); + this.enemySpDef = Math.round(this.enemySpDef / this.enemyCountTally); if (this.enemyDef < this.enemySpDef) { this.stats = [BattleStat.ATK]; @@ -1728,7 +1709,9 @@ export class PostSummonWeatherChangeAbAttr extends PostSummonAbAttr { } applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { - if (!pokemon.scene.arena.weather?.isImmutable()) { + if ((this.weatherType === WeatherType.HEAVY_RAIN || + this.weatherType === WeatherType.HARSH_SUN || + this.weatherType === WeatherType.STRONG_WINDS) || !pokemon.scene.arena.weather?.isImmutable()) { return pokemon.scene.arena.trySetWeather(this.weatherType, true); } @@ -1856,6 +1839,52 @@ export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr { } } +/** + * Clears Desolate Land/Primordial Sea/Delta Stream upon the Pokemon switching out. + */ +export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr { + + /** + * @param pokemon The {@linkcode Pokemon} with the ability + * @param passive N/A + * @param args N/A + * @returns {boolean} Returns true if the weather clears, otherwise false. + */ + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { + const weatherType = pokemon.scene.arena.weather.weatherType; + let turnOffWeather = false; + + // Clear weather only if user's ability matches the weather and no other pokemon has the ability. + switch (weatherType) { + case (WeatherType.HARSH_SUN): + if (pokemon.hasAbility(Abilities.DESOLATE_LAND) + && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) { + turnOffWeather = true; + } + break; + case (WeatherType.HEAVY_RAIN): + if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) + && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) { + turnOffWeather = true; + } + break; + case (WeatherType.STRONG_WINDS): + if (pokemon.hasAbility(Abilities.DELTA_STREAM) + && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) { + turnOffWeather = true; + } + break; + } + + if (turnOffWeather) { + pokemon.scene.arena.trySetWeather(WeatherType.NONE, false); + return true; + } + + return false; + } +} + export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (pokemon.getHpRatio() < 1 ) { @@ -1956,9 +1985,9 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { * @param args [0] {@linkcode StatusEffect} applied by move * @returns true if defender is confused */ - applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (this.effects.indexOf(args[0]) > -1 && !defender.isFainted()) { - return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedInt(3,2), move.moveId, defender.id); + return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedInt(3,2), move.id, defender.id); } return false; } @@ -2216,7 +2245,7 @@ function getAnticipationCondition(): AbAttrCondition { for (const opponent of pokemon.getOpponents()) { for (const move of opponent.moveset) { // move is super effective - if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent) >= 2) { + if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent, true) >= 2) { return true; } // move is a OHKO @@ -2561,7 +2590,7 @@ export class PostTurnLootAbAttr extends PostTurnAbAttr { if (!berryModifier) { pokemon.scene.addModifier(new BerryModifier(chosenBerry, pokemon.id, chosenBerryType, 1)); - } else { + } else if (berryModifier.stackCount < berryModifier.getMaxHeldItemCount(pokemon)) { berryModifier.stackCount++; } @@ -2920,6 +2949,7 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr { /** * Checks if enemy Pokemon is trapped by an Arena Trap-esque ability * If the enemy is a Ghost type, it is not trapped + * If the enemy has the ability Run Away, it is not trapped. * If the user has Magnet Pull and the enemy is not a Steel type, it is not trapped. * If the user has Arena Trap and the enemy is not grounded, it is not trapped. * @param pokemon The {@link Pokemon} with this {@link AbAttr} @@ -2934,6 +2964,9 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr { if (otherPokemon.getTypes(true).includes(Type.GHOST) || (otherPokemon.getTypes(true).includes(Type.STELLAR) && otherPokemon.getTypes().includes(Type.GHOST))) { trapped.value = false; return false; + } else if (otherPokemon.hasAbility(Abilities.RUN_AWAY)) { + trapped.value = false; + return false; } trapped.value = true; return true; @@ -2982,7 +3015,56 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr { } export class PostFaintAbAttr extends AbAttr { - applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + return false; + } +} + +/** + * Clears Desolate Land/Primordial Sea/Delta Stream upon the Pokemon fainting + */ +export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr { + + /** + * @param pokemon The {@linkcode Pokemon} with the ability + * @param passive N/A + * @param attacker N/A + * @param move N/A + * @param hitResult N/A + * @param args N/A + * @returns {boolean} Returns true if the weather clears, otherwise false. + */ + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + const weatherType = pokemon.scene.arena.weather.weatherType; + let turnOffWeather = false; + + // Clear weather only if user's ability matches the weather and no other pokemon has the ability. + switch (weatherType) { + case (WeatherType.HARSH_SUN): + if (pokemon.hasAbility(Abilities.DESOLATE_LAND) + && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) { + turnOffWeather = true; + } + break; + case (WeatherType.HEAVY_RAIN): + if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) + && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) { + turnOffWeather = true; + } + break; + case (WeatherType.STRONG_WINDS): + if (pokemon.hasAbility(Abilities.DELTA_STREAM) + && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) { + turnOffWeather = true; + } + break; + } + + if (turnOffWeather) { + pokemon.scene.arena.trySetWeather(WeatherType.NONE, false); + return true; + } + return false; } } @@ -2996,8 +3078,8 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { this.damageRatio = damageRatio; } - applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { const cancelled = new Utils.BooleanHolder(false); pokemon.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled)); if (cancelled.value) { @@ -3024,7 +3106,7 @@ export class PostFaintHPDamageAbAttr extends PostFaintAbAttr { super (); } - applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { const damage = pokemon.turnData.attacksReceived[0].damage; attacker.damageAndUpdate((damage), HitResult.OTHER); attacker.turnData.damageTaken += damage; @@ -3361,7 +3443,7 @@ export class IceFaceMoveImmunityAbAttr extends MoveImmunityAbAttr { * @param {any[]} args - Additional arguments. * @returns {boolean} - Whether the immunity was applied. */ - applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { const isImmune = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (isImmune) { @@ -3471,13 +3553,13 @@ export function applyPostBattleInitAbAttrs(attrType: { new(...args: any[]): Post } export function applyPreDefendAbAttrs(attrType: { new(...args: any[]): PreDefendAbAttr }, - pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { + pokemon: Pokemon, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { const simulated = args.length > 1 && args[1]; return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreDefend(pokemon, passive, attacker, move, cancelled, args), args, false, false, simulated); } export function applyPostDefendAbAttrs(attrType: { new(...args: any[]): PostDefendAbAttr }, - pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { + pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostDefend(pokemon, passive, attacker, move, hitResult, args), args); } @@ -3492,12 +3574,12 @@ export function applyBattleStatMultiplierAbAttrs(attrType: { new(...args: any[]) } export function applyPreAttackAbAttrs(attrType: { new(...args: any[]): PreAttackAbAttr }, - pokemon: Pokemon, defender: Pokemon, move: PokemonMove, ...args: any[]): Promise { + pokemon: Pokemon, defender: Pokemon, move: Move, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, defender, move, args), args); } export function applyPostAttackAbAttrs(attrType: { new(...args: any[]): PostAttackAbAttr }, - pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { + pokemon: Pokemon, defender: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, defender, move, hitResult, args), args); } @@ -3578,7 +3660,7 @@ export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBatt } export function applyPostFaintAbAttrs(attrType: { new(...args: any[]): PostFaintAbAttr }, - pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { + pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, attacker, move, hitResult, args), args); } @@ -3597,7 +3679,7 @@ export const allAbilities = [ new Ability(Abilities.NONE, 3) ]; export function initAbilities() { allAbilities.push( new Ability(Abilities.STENCH, 3) - .attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => (move.getMove().category !== MoveCategory.STATUS && !move.getMove().hasAttr(FlinchAttr)) ? 10 : 0, BattlerTagType.FLINCHED), + .attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => (move.category !== MoveCategory.STATUS && !move.hasAttr(FlinchAttr)) ? 10 : 0, BattlerTagType.FLINCHED), new Ability(Abilities.DRIZZLE, 3) .attr(PostSummonWeatherChangeAbAttr, WeatherType.RAIN) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.RAIN), @@ -3734,7 +3816,7 @@ export function initAbilities() { return false; }), new Ability(Abilities.SOUNDPROOF, 3) - .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.SOUND_BASED)) + .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.SOUND_BASED)) .ignorable(), new Ability(Abilities.RAIN_DISH, 3) .attr(PostWeatherLapseHealAbAttr, 1, WeatherType.RAIN, WeatherType.HEAVY_RAIN) @@ -4020,13 +4102,13 @@ export function initAbilities() { ) .partial(), new Ability(Abilities.TELEPATHY, 5) - .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move.getMove() instanceof AttackMove) + .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move instanceof AttackMove) .ignorable(), new Ability(Abilities.MOODY, 5) .attr(MoodyAbAttr), new Ability(Abilities.OVERCOAT, 5) .attr(BlockWeatherDamageAttr) - .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.POWDER_MOVE)) + .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.POWDER_MOVE)) .ignorable(), new Ability(Abilities.POISON_TOUCH, 5) .attr(PostAttackContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON), @@ -4115,14 +4197,14 @@ export function initAbilities() { new Ability(Abilities.MAGICIAN, 6) .attr(PostAttackStealHeldItemAbAttr), new Ability(Abilities.BULLETPROOF, 6) - .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.BALLBOMB_MOVE)) + .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.BALLBOMB_MOVE)) .ignorable(), new Ability(Abilities.COMPETITIVE, 6) .attr(PostStatChangeStatChangeAbAttr, (target, statsChanged, levels) => levels < 0, [BattleStat.SPATK], 2), new Ability(Abilities.STRONG_JAW, 6) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.BITING_MOVE), 1.5), new Ability(Abilities.REFRIGERATE, 6) - .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ICE, 1.2), + .attr(MoveTypeChangeAttr, Type.ICE, 1.2, (user, target, move) => move.type === Type.NORMAL), new Ability(Abilities.SWEET_VEIL, 6) .attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) @@ -4145,11 +4227,11 @@ export function initAbilities() { new Ability(Abilities.TOUGH_CLAWS, 6) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 1.3), new Ability(Abilities.PIXILATE, 6) - .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.FAIRY, 1.2), + .attr(MoveTypeChangeAttr, Type.FAIRY, 1.2, (user, target, move) => move.type === Type.NORMAL), new Ability(Abilities.GOOEY, 6) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), BattleStat.SPD, -1, false), new Ability(Abilities.AERILATE, 6) - .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.FLYING, 1.2), + .attr(MoveTypeChangeAttr, Type.FLYING, 1.2, (user, target, move) => move.type === Type.NORMAL), new Ability(Abilities.PARENTAL_BOND, 6) .unimplemented(), new Ability(Abilities.DARK_AURA, 6) @@ -4163,13 +4245,22 @@ export function initAbilities() { .unimplemented(), new Ability(Abilities.PRIMORDIAL_SEA, 6) .attr(PostSummonWeatherChangeAbAttr, WeatherType.HEAVY_RAIN) - .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HEAVY_RAIN), + .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HEAVY_RAIN) + .attr(PreSwitchOutClearWeatherAbAttr) + .attr(PostFaintClearWeatherAbAttr) + .bypassFaint(), new Ability(Abilities.DESOLATE_LAND, 6) .attr(PostSummonWeatherChangeAbAttr, WeatherType.HARSH_SUN) - .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HARSH_SUN), + .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HARSH_SUN) + .attr(PreSwitchOutClearWeatherAbAttr) + .attr(PostFaintClearWeatherAbAttr) + .bypassFaint(), new Ability(Abilities.DELTA_STREAM, 6) .attr(PostSummonWeatherChangeAbAttr, WeatherType.STRONG_WINDS) - .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.STRONG_WINDS), + .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.STRONG_WINDS) + .attr(PreSwitchOutClearWeatherAbAttr) + .attr(PostFaintClearWeatherAbAttr) + .bypassFaint(), new Ability(Abilities.STAMINA, 7) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattleStat.DEF, 1), new Ability(Abilities.WIMP_OUT, 7) @@ -4210,7 +4301,7 @@ export function initAbilities() { new Ability(Abilities.TRIAGE, 7) .attr(IncrementMovePriorityAbAttr, (pokemon, move) => move.hasFlag(MoveFlags.TRIAGE_MOVE), 3), new Ability(Abilities.GALVANIZE, 7) - .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ELECTRIC, 1.2), + .attr(MoveTypeChangeAttr, Type.ELECTRIC, 1.2, (user, target, move) => move.type === Type.NORMAL), new Ability(Abilities.SURGE_SURFER, 7) .conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), BattleStatMultiplierAbAttr, BattleStat.SPD, 2), new Ability(Abilities.SCHOOLING, 7) @@ -4378,7 +4469,7 @@ export function initAbilities() { .conditionalAttr(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW), PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0) // When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE .attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW) - .attr(IceFaceMoveImmunityAbAttr, (target, user, move) => move.getMove().category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE)) + .attr(IceFaceMoveImmunityAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE)) .ignorable(), new Ability(Abilities.POWER_SPOT, 8) .unimplemented(), @@ -4463,7 +4554,7 @@ export function initAbilities() { .attr(TypeImmunityStatChangeAbAttr, Type.FIRE, BattleStat.DEF, 2) .ignorable(), new Ability(Abilities.WIND_RIDER, 9) - .attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE) && move.getMove().category !== MoveCategory.STATUS, BattleStat.ATK, 1) + .attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.WIND_MOVE) && move.category !== MoveCategory.STATUS, BattleStat.ATK, 1) .attr(PostSummonStatChangeOnArenaAbAttr, ArenaTagType.TAILWIND) .ignorable(), new Ability(Abilities.GUARD_DOG, 9) @@ -4503,7 +4594,7 @@ export function initAbilities() { .attr(NoTransformAbilityAbAttr) .partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages new Ability(Abilities.GOOD_AS_GOLD, 9) - .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().category === MoveCategory.STATUS) + .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS) .ignorable() .partial(), new Ability(Abilities.VESSEL_OF_RUIN, 9) diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 37de1af2efa..37420c2ac0b 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -29,6 +29,7 @@ export abstract class ArenaTag { public sourceId: integer; public side: ArenaTagSide; + constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId?: integer, side: ArenaTagSide = ArenaTagSide.BOTH) { this.tagType = tagType; this.turnCount = turnCount; @@ -41,10 +42,12 @@ export abstract class ArenaTag { return true; } - onAdd(arena: Arena): void { } + onAdd(arena: Arena, quiet: boolean = false): void { } - onRemove(arena: Arena): void { - arena.scene.queueMessage(`${this.getMoveName()}\'s effect wore off${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`); + onRemove(arena: Arena, quiet: boolean = false): void { + if (!quiet) { + arena.scene.queueMessage(`${this.getMoveName()}\'s effect wore off${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`); + } } onOverlap(arena: Arena): void { } @@ -65,11 +68,13 @@ export class MistTag extends ArenaTag { super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side); } - onAdd(arena: Arena): void { + onAdd(arena: Arena, quiet: boolean = false): void { super.onAdd(arena); const source = arena.scene.getPokemonById(this.sourceId); - arena.scene.queueMessage(getPokemonMessage(source, "'s team became\nshrouded in mist!")); + if (!quiet) { + arena.scene.queueMessage(getPokemonMessage(source, "'s team became\nshrouded in mist!")); + } } apply(arena: Arena, args: any[]): boolean { @@ -113,8 +118,10 @@ class ReflectTag extends WeakenMoveScreenTag { return false; } - onAdd(arena: Arena): void { - arena.scene.queueMessage(`Reflect reduced the damage of physical moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`); + onAdd(arena: Arena, quiet: boolean = false): void { + if (!quiet) { + arena.scene.queueMessage(`Reflect reduced the damage of physical moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`); + } } } @@ -135,8 +142,10 @@ class LightScreenTag extends WeakenMoveScreenTag { return false; } - onAdd(arena: Arena): void { - arena.scene.queueMessage(`Light Screen reduced the damage of special moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`); + onAdd(arena: Arena, quiet: boolean = false): void { + if (!quiet) { + arena.scene.queueMessage(`Light Screen reduced the damage of special moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`); + } } } @@ -145,8 +154,10 @@ class AuroraVeilTag extends WeakenMoveScreenTag { super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side); } - onAdd(arena: Arena): void { - arena.scene.queueMessage(`Aurora Veil reduced the damage of moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`); + onAdd(arena: Arena, quiet: boolean = false): void { + if (!quiet) { + arena.scene.queueMessage(`Aurora Veil reduced the damage of moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`); + } } } @@ -386,11 +397,13 @@ class SpikesTag extends ArenaTrapTag { super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3); } - onAdd(arena: Arena): void { + onAdd(arena: Arena, quiet: boolean = false): void { super.onAdd(arena); const source = arena.scene.getPokemonById(this.sourceId); - arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${source.getOpponentDescriptor()}'s feet!`); + if (!quiet) { + arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${source.getOpponentDescriptor()}'s feet!`); + } } activateTrap(pokemon: Pokemon): boolean { @@ -423,11 +436,13 @@ class ToxicSpikesTag extends ArenaTrapTag { this.neutralized = false; } - onAdd(arena: Arena): void { + onAdd(arena: Arena, quiet: boolean = false): void { super.onAdd(arena); const source = arena.scene.getPokemonById(this.sourceId); - arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${source.getOpponentDescriptor()}'s feet!`); + if (!quiet) { + arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${source.getOpponentDescriptor()}'s feet!`); + } } onRemove(arena: Arena): void { @@ -493,15 +508,17 @@ class StealthRockTag extends ArenaTrapTag { super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1); } - onAdd(arena: Arena): void { + onAdd(arena: Arena, quiet: boolean = false): void { super.onAdd(arena); const source = arena.scene.getPokemonById(this.sourceId); - arena.scene.queueMessage(`Pointed stones float in the air\naround ${source.getOpponentDescriptor()}!`); + if (!quiet) { + arena.scene.queueMessage(`Pointed stones float in the air\naround ${source.getOpponentDescriptor()}!`); + } } getDamageHpRatio(pokemon: Pokemon): number { - const effectiveness = pokemon.getAttackTypeEffectiveness(Type.ROCK); + const effectiveness = pokemon.getAttackTypeEffectiveness(Type.ROCK, undefined, true); let damageHpRatio: number; @@ -562,13 +579,15 @@ class StickyWebTag extends ArenaTrapTag { super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1); } - onAdd(arena: Arena): void { + onAdd(arena: Arena, quiet: boolean = false): void { super.onAdd(arena); // does not seem to be used anywhere // eslint-disable-next-line @typescript-eslint/no-unused-vars const source = arena.scene.getPokemonById(this.sourceId); - arena.scene.queueMessage(`A ${this.getMoveName()} has been laid out on the ground around the opposing team!`); + if (!quiet) { + arena.scene.queueMessage(`A ${this.getMoveName()} has been laid out on the ground around the opposing team!`); + } } activateTrap(pokemon: Pokemon): boolean { @@ -626,8 +645,10 @@ class TailwindTag extends ArenaTag { super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side); } - onAdd(arena: Arena): void { - arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? "\nyour" : this.side === ArenaTagSide.ENEMY ? "\nthe opposing" : ""} team!`); + onAdd(arena: Arena, quiet: boolean = false): void { + if (!quiet) { + arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? "\nyour" : this.side === ArenaTagSide.ENEMY ? "\nthe opposing" : ""} team!`); + } const source = arena.scene.getPokemonById(this.sourceId); const party = source.isPlayer() ? source.scene.getPlayerField() : source.scene.getEnemyField(); @@ -646,8 +667,10 @@ class TailwindTag extends ArenaTag { } } - onRemove(arena: Arena): void { - arena.scene.queueMessage(`${this.side === ArenaTagSide.PLAYER ? "Your" : this.side === ArenaTagSide.ENEMY ? "The opposing" : ""} team's Tailwind petered out!`); + onRemove(arena: Arena, quiet: boolean = false): void { + if (!quiet) { + arena.scene.queueMessage(`${this.side === ArenaTagSide.PLAYER ? "Your" : this.side === ArenaTagSide.ENEMY ? "The opposing" : ""} team's Tailwind petered out!`); + } } } diff --git a/src/data/biomes.ts b/src/data/biomes.ts index bfee8904c46..43cafb46fce 100644 --- a/src/data/biomes.ts +++ b/src/data/biomes.ts @@ -1691,7 +1691,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { [BiomePoolTier.BOSS_ULTRA_RARE]: [] }, [Biome.SEA]: { - [BiomePoolTier.COMMON]: [ TrainerType.SWIMMER ], + [BiomePoolTier.COMMON]: [ TrainerType.SWIMMER, TrainerType.SAILOR ], [BiomePoolTier.UNCOMMON]: [], [BiomePoolTier.RARE]: [], [BiomePoolTier.SUPER_RARE]: [], @@ -1713,7 +1713,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { [BiomePoolTier.BOSS_ULTRA_RARE]: [] }, [Biome.BEACH]: { - [BiomePoolTier.COMMON]: [ TrainerType.FISHERMAN, TrainerType.PARASOL_LADY ], + [BiomePoolTier.COMMON]: [ TrainerType.FISHERMAN, TrainerType.PARASOL_LADY, TrainerType.SAILOR ], [BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER, TrainerType.BREEDER ], [BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ], [BiomePoolTier.SUPER_RARE]: [], @@ -7308,6 +7308,11 @@ export function initBiomes() { [ Biome.VOLCANO, BiomePoolTier.COMMON ] ] ], + [ TrainerType.SAILOR, [ + [ Biome.SEA, BiomePoolTier.COMMON ], + [ Biome.BEACH, BiomePoolTier.COMMON ] + ] + ], [ TrainerType.BROCK, [ [ Biome.CAVE, BiomePoolTier.BOSS ] ] diff --git a/src/data/challenge.ts b/src/data/challenge.ts new file mode 100644 index 00000000000..916f59ab2c2 --- /dev/null +++ b/src/data/challenge.ts @@ -0,0 +1,577 @@ +import * as Utils from "../utils"; +import { Challenges } from "./enums/challenges"; +import i18next from "#app/plugins/i18n.js"; +import { GameData } from "#app/system/game-data.js"; +import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species"; +import Pokemon from "#app/field/pokemon.js"; +import { BattleType, FixedBattleConfig } from "#app/battle.js"; +import { TrainerType } from "./enums/trainer-type"; +import Trainer, { TrainerVariant } from "#app/field/trainer.js"; +import { GameMode } from "#app/game-mode.js"; +import { Species } from "./enums/species"; +import { Type } from "./type"; + +/** + * An enum for all the challenge types. The parameter entries on these describe the + * parameters to use when calling the applyChallenges function. + */ +export enum ChallengeType { + /** + * Challenges which modify what starters you can choose + * @param args [0] {@link PokemonSpecies} The species to check + * [1] {@link Utils.BooleanHolder} Sets to false if illegal, pass in true. + */ + STARTER_CHOICE, + /** + * Challenges which modify how many starter points you have + * @param args [0] {@link Utils.NumberHolder} The amount of starter points you have + */ + STARTER_POINTS, + /** + * Challenges which modify your starters in some way + * Not Fully Implemented + */ + STARTER_MODIFY, + /** + * Challenges which limit which pokemon you can have in battle. + * @param args [0] {@link Pokemon} The pokemon to check + * [1] {@link Utils.BooleanHolder} Sets to false if illegal, pass in true. + */ + POKEMON_IN_BATTLE, + /** + * Adds or modifies the fixed battles in a run + * @param args [0] integer The wave to get a battle for + * [1] {@link FixedBattleConfig} A new fixed battle. It'll be modified if a battle exists. + */ + FIXED_BATTLES, +} + +/** + * A challenge object. Exists only to serve as a base class. + */ +export abstract class Challenge { + public id: Challenges; // The id of the challenge + + public value: integer; // The "strength" of the challenge, all challenges have a numerical value. + public maxValue: integer; // The maximum strength of the challenge. + public severity: integer; // The current severity of the challenge. Some challenges have multiple severities in addition to strength. + public maxSeverity: integer; // The maximum severity of the challenge. + + public conditions: ChallengeCondition[]; + public challengeTypes: ChallengeType[]; + + /** + * @param {Challenges} id The enum value for the challenge + */ + constructor(id: Challenges, maxValue: integer = Number.MAX_SAFE_INTEGER) { + this.id = id; + + this.value = 0; + this.maxValue = maxValue; + this.severity = 0; + this.maxSeverity = 0; + this.conditions = []; + this.challengeTypes = []; + } + + /** + * Reset the challenge to a base state. + */ + reset(): void { + this.value = 0; + this.severity = 0; + } + + /** + * Gets the localisation key for the challenge + * @returns The i18n key for this challenge + */ + geti18nKey(): string { + return Challenges[this.id].split("_").map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join(""); + } + + /** + * Used for unlockable challenges to check if they're unlocked. + * @param {GameData} data The save data. + * @returns {boolean} Whether this challenge is unlocked. + */ + isUnlocked(data: GameData): boolean { + return this.conditions.every(f => f(data)); + } + + /** + * Adds an unlock condition to this challenge. + * @param {ChallengeCondition} condition The condition to add. + * @returns {Challenge} This challenge + */ + condition(condition: ChallengeCondition): Challenge { + this.conditions.push(condition); + + return this; + } + + /** + * If this challenge is of a particular type + * @param {ChallengeType} challengeType The challenge type to check. + * @returns {Challenge} This challenge + */ + isOfType(challengeType: ChallengeType): boolean { + return this.challengeTypes.some(c => c === challengeType); + } + + /** + * Adds a challenge type to this challenge. + * @param {ChallengeType} challengeType The challenge type to add. + * @returns {Challenge} This challenge + */ + addChallengeType(challengeType: ChallengeType): Challenge { + this.challengeTypes.push(challengeType); + + return this; + } + + /** + * @returns {string} The localised name of this challenge. + */ + getName(): string { + return i18next.t(`challenges:${this.geti18nKey()}.name`); + } + + /** + * Returns the textual representation of a challenge's current value. + * @param {value} overrideValue The value to check for. If undefined, gets the current value. + * @returns {string} The localised name for the current value. + */ + getValue(overrideValue?: integer): string { + if (overrideValue === undefined) { + overrideValue = this.value; + } + return i18next.t(`challenges:${this.geti18nKey()}.value.${this.value}`); + } + + /** + * Returns the description of a challenge's current value. + * @param {value} overrideValue The value to check for. If undefined, gets the current value. + * @returns {string} The localised description for the current value. + */ + getDescription(overrideValue?: integer): string { + if (overrideValue === undefined) { + overrideValue = this.value; + } + return i18next.t(`challenges:${this.geti18nKey()}.desc.${this.value}`); + } + + /** + * Increase the value of the challenge + * @returns {boolean} Returns true if the value changed + */ + increaseValue(): boolean { + if (this.value < this.maxValue) { + this.value = Math.min(this.value + 1, this.maxValue); + return true; + } + return false; + } + + /** + * Decrease the value of the challenge + * @returns {boolean} Returns true if the value changed + */ + decreaseValue(): boolean { + if (this.value > 0) { + this.value = Math.max(this.value - 1, 0); + return true; + } + return false; + } + + /** + * Whether to allow choosing this challenge's severity. + */ + hasSeverity(): boolean { + return this.value !== 0 && this.maxSeverity > 0; + } + + /** + * Decrease the severity of the challenge + * @returns {boolean} Returns true if the value changed + */ + decreaseSeverity(): boolean { + if (this.severity > 0) { + this.severity = Math.max(this.severity - 1, 0); + return true; + } + return false; + } + + /** + * Increase the severity of the challenge + * @returns {boolean} Returns true if the value changed + */ + increaseSeverity(): boolean { + if (this.severity < this.maxSeverity) { + this.severity = Math.min(this.severity + 1, this.maxSeverity); + return true; + } + return false; + } + + /** + * Gets the "difficulty" value of this challenge. + * @returns {integer} The difficulty value. + */ + getDifficulty(): integer { + return this.value; + } + + /** + * Gets the minimum difficulty added by this challenge. + * @returns {integer} The difficulty value. + */ + getMinDifficulty(): integer { + return 0; + } + + /** + * Modifies the data or game state in some way to apply the challenge. + * @param {ChallengeType} challengeType Which challenge type this is being applied for. + * @param args Irrelevant. See the specific challenge's apply function for additional information. + */ + abstract apply(challengeType: ChallengeType, args: any[]): boolean; + + /** + * Clones a challenge, either from another challenge or json. Chainable. + * @param {Challenge | any} source The source challenge of json. + * @returns {Challenge} This challenge. + */ + static loadChallenge(source: Challenge | any): Challenge { + throw new Error("Method not implemented! Use derived class"); + } +} + +type ChallengeCondition = (data: GameData) => boolean; + +/** + * Implements a mono generation challenge. + */ +export class SingleGenerationChallenge extends Challenge { + constructor() { + super(Challenges.SINGLE_GENERATION, 9); + this.addChallengeType(ChallengeType.STARTER_CHOICE); + this.addChallengeType(ChallengeType.POKEMON_IN_BATTLE); + this.addChallengeType(ChallengeType.FIXED_BATTLES); + } + + apply(challengeType: ChallengeType, args: any[]): boolean { + if (this.value === 0) { + return false; + } + + /** + * We have special code below for victini because it is classed as a generation 4 pokemon in the code + * despite being a generation 5 pokemon. This is due to UI constraints, the starter select screen has + * no more room for pokemon so victini is put in the gen 4 section instead. This code just overrides the + * normal generation check to correctly treat victini as gen 5. + */ + switch (challengeType) { + case ChallengeType.STARTER_CHOICE: + const species = args[0] as PokemonSpecies; + const isValidStarter = args[1] as Utils.BooleanHolder; + const starterGeneration = species.speciesId === Species.VICTINI ? 5 : species.generation; + if (starterGeneration !== this.value) { + isValidStarter.value = false; + return true; + } + break; + case ChallengeType.POKEMON_IN_BATTLE: + const pokemon = args[0] as Pokemon; + const isValidPokemon = args[1] as Utils.BooleanHolder; + const baseGeneration = pokemon.species.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.species.speciesId).generation; + const fusionGeneration = pokemon.isFusion() ? pokemon.fusionSpecies.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.fusionSpecies.speciesId).generation : 0; + if (pokemon.isPlayer() && (baseGeneration !== this.value || (pokemon.isFusion() && fusionGeneration !== this.value))) { + isValidPokemon.value = false; + return true; + } + break; + case ChallengeType.FIXED_BATTLES: + const waveIndex = args[0] as integer; + const battleConfig = args[1] as FixedBattleConfig; + let trainerTypes: TrainerType[] = []; + switch (waveIndex) { + case 182: + trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]),TrainerType.MARNIE_ELITE, TrainerType.RIKA ]; + break; + case 184: + trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ]; + break; + case 186: + trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([TrainerType.BEA_ELITE,TrainerType.ALLISTER_ELITE]), TrainerType.LARRY_ELITE ]; + break; + case 188: + trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ]; + break; + case 190: + trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ]; + break; + } + if (trainerTypes.length === 0) { + return false; + } else { + battleConfig.setBattleType(BattleType.TRAINER).setGetTrainerFunc(scene => new Trainer(scene, trainerTypes[this.value - 1], TrainerVariant.DEFAULT)); + return true; + } + } + return false; + } + + /** + * @overrides + */ + getDifficulty(): number { + return this.value > 0 ? 1 : 0; + } + + static loadChallenge(source: SingleGenerationChallenge | any): SingleGenerationChallenge { + const newChallenge = new SingleGenerationChallenge(); + newChallenge.value = source.value; + newChallenge.severity = source.severity; + return newChallenge; + } +} + +interface monotypeOverride { + /** The species to override */ + species: Species; + /** The type to count as */ + type: Type; + /** If part of a fusion, should we check the fused species instead of the base species? */ + fusion: boolean; +} + +/** + * Implements a mono type challenge. + */ +export class SingleTypeChallenge extends Challenge { + private static TYPE_OVERRIDES: monotypeOverride[] = [ + {species: Species.MELOETTA, type: Type.PSYCHIC, fusion: true}, + {species: Species.CASTFORM, type: Type.NORMAL, fusion: false}, + ]; + + constructor() { + super(Challenges.SINGLE_TYPE, 18); + this.addChallengeType(ChallengeType.STARTER_CHOICE); + this.addChallengeType(ChallengeType.POKEMON_IN_BATTLE); + } + + apply(challengeType: ChallengeType, args: any[]): boolean { + if (this.value === 0) { + return false; + } + + switch (challengeType) { + case ChallengeType.STARTER_CHOICE: + const species = args[0] as PokemonSpecies; + const isValidStarter = args[1] as Utils.BooleanHolder; + if (!species.isOfType(this.value - 1)) { + isValidStarter.value = false; + return true; + } + break; + case ChallengeType.POKEMON_IN_BATTLE: + const pokemon = args[0] as Pokemon; + const isValidPokemon = args[1] as Utils.BooleanHolder; + if (pokemon.isPlayer() && !pokemon.isOfType(this.value - 1, false, false, true) + && !SingleTypeChallenge.TYPE_OVERRIDES.some(o => o.type === (this.value - 1) && (pokemon.isFusion() && o.fusion ? pokemon.fusionSpecies : pokemon.species).speciesId === o.species)) { + isValidPokemon.value = false; + return true; + } + break; + } + return false; + } + + /** + * @overrides + */ + getDifficulty(): number { + return this.value > 0 ? 1 : 0; + } + + static loadChallenge(source: SingleTypeChallenge | any): SingleTypeChallenge { + const newChallenge = new SingleTypeChallenge(); + newChallenge.value = source.value; + newChallenge.severity = source.severity; + return newChallenge; + } +} + +/** + * Implements a fresh start challenge. + */ +export class FreshStartChallenge extends Challenge { + constructor() { + super(Challenges.FRESH_START, 1); + this.addChallengeType(ChallengeType.STARTER_CHOICE); + this.addChallengeType(ChallengeType.STARTER_MODIFY); + } + + apply(challengeType: ChallengeType, args: any[]): boolean { + if (this.value === 0) { + return false; + } + + switch (challengeType) { + case ChallengeType.STARTER_CHOICE: + const species = args[0] as PokemonSpecies; + const isValidStarter = args[1] as Utils.BooleanHolder; + if (species) { + isValidStarter.value = false; + return true; + } + break; + } + return false; + } + + /** + * @overrides + */ + getDifficulty(): number { + return 0; + } + + static loadChallenge(source: FreshStartChallenge | any): FreshStartChallenge { + const newChallenge = new FreshStartChallenge(); + newChallenge.value = source.value; + newChallenge.severity = source.severity; + return newChallenge; + } +} + +/** + * Lowers the amount of starter points available. + */ +export class LowerStarterMaxCostChallenge extends Challenge { + constructor() { + super(Challenges.LOWER_MAX_STARTER_COST, 9); + this.addChallengeType(ChallengeType.STARTER_CHOICE); + } + + /** + * @override + */ + getValue(overrideValue?: integer): string { + if (overrideValue === undefined) { + overrideValue = this.value; + } + return (10 - overrideValue).toString(); + } + + apply(challengeType: ChallengeType, args: any[]): boolean { + if (this.value === 0) { + return false; + } + + switch (challengeType) { + case ChallengeType.STARTER_CHOICE: + const species = args[0] as PokemonSpecies; + const isValid = args[1] as Utils.BooleanHolder; + if (speciesStarters[species.speciesId] > 10 - this.value) { + isValid.value = false; + return true; + } + } + return false; + } + + static loadChallenge(source: LowerStarterMaxCostChallenge | any): LowerStarterMaxCostChallenge { + const newChallenge = new LowerStarterMaxCostChallenge(); + newChallenge.value = source.value; + newChallenge.severity = source.severity; + return newChallenge; + } +} + +/** + * Lowers the maximum cost of starters available. + */ +export class LowerStarterPointsChallenge extends Challenge { + constructor() { + super(Challenges.LOWER_STARTER_POINTS, 9); + this.addChallengeType(ChallengeType.STARTER_POINTS); + } + + /** + * @override + */ + getValue(overrideValue?: integer): string { + if (overrideValue === undefined) { + overrideValue = this.value; + } + return (10 - overrideValue).toString(); + } + + apply(challengeType: ChallengeType, args: any[]): boolean { + if (this.value === 0) { + return false; + } + + switch (challengeType) { + case ChallengeType.STARTER_POINTS: + const points = args[0] as Utils.NumberHolder; + points.value -= this.value; + return true; + } + return false; + } + + static loadChallenge(source: LowerStarterPointsChallenge | any): LowerStarterPointsChallenge { + const newChallenge = new LowerStarterPointsChallenge(); + newChallenge.value = source.value; + newChallenge.severity = source.severity; + return newChallenge; + } +} + +/** + * Apply all challenges of a given challenge type. + * @param {BattleScene} scene The current scene + * @param {ChallengeType} challengeType What challenge type to apply + * @param {any[]} args Any args for that challenge type + * @returns {boolean} True if any challenge was successfully applied. + */ +export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean { + let ret = false; + gameMode.challenges.forEach(v => { + if (v.isOfType(challengeType)) { + ret ||= v.apply(challengeType, args); + } + }); + return ret; +} + +export function copyChallenge(source: Challenge | any): Challenge { + switch (source.id) { + case Challenges.SINGLE_GENERATION: + return SingleGenerationChallenge.loadChallenge(source); + case Challenges.SINGLE_TYPE: + return SingleTypeChallenge.loadChallenge(source); + case Challenges.LOWER_MAX_STARTER_COST: + return LowerStarterMaxCostChallenge.loadChallenge(source); + case Challenges.LOWER_STARTER_POINTS: + return LowerStarterPointsChallenge.loadChallenge(source); + } + throw new Error("Unknown challenge copied"); +} + +export const allChallenges: Challenge[] = []; + +export function initChallenges() { + allChallenges.push( + new SingleGenerationChallenge(), + new SingleTypeChallenge(), + // new LowerStarterMaxCostChallenge(), + // new LowerStarterPointsChallenge(), + // new FreshStartChallenge() + ); +} diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index cb4bfddc685..c9b097bfcc0 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -1,6 +1,5 @@ import BattleScene from "../battle-scene"; import { PlayerPokemon } from "../field/pokemon"; -import { GameModes, gameModes } from "../game-mode"; import { Starter } from "../ui/starter-select-ui-handler"; import * as Utils from "../utils"; import { Species } from "./enums/species"; @@ -29,7 +28,7 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[] const starters: Starter[] = []; scene.executeWithSeedOffset(() => { - const startingLevel = gameModes[GameModes.DAILY].getStartingLevel(); + const startingLevel = scene.gameMode.getStartingLevel(); if (/\d{18}$/.test(seed)) { for (let s = 0; s < 3; s++) { diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index bed72ceb9bb..2076123610f 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -435,6 +435,20 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { ] } ], + [TrainerType.SAILOR]: [ + { + encounter: [ + "dialogue:sailor.encounter.1", + "dialogue:sailor.encounter.2", + "dialogue:sailor.encounter.3", + ], + victory: [ + "dialogue:sailor.victory.1", + "dialogue:sailor.victory.2", + "dialogue:sailor.victory.3", + ] + } + ], [TrainerType.BROCK]: { encounter: [ "dialogue:brock.encounter.1", diff --git a/src/data/egg.ts b/src/data/egg.ts index 74371049363..da6100446ec 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -1,6 +1,6 @@ import BattleScene from "../battle-scene"; import { Species } from "./enums/species"; -import { getPokemonSpecies, speciesStarters } from "./pokemon-species"; +import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species"; import { EggTier } from "./enums/egg-type"; import i18next from "../plugins/i18n"; @@ -111,3 +111,20 @@ export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timesta return ret; } + +/** + * Check for a given species EggTier Value + * @param species - Species for wich we will check the egg tier it belongs to + * @returns The egg tier of a given pokemon species + */ +export function getEggTierForSpecies(pokemonSpecies :PokemonSpecies): EggTier { + const speciesBaseValue = speciesStarters[pokemonSpecies.getRootSpeciesId()]; + if (speciesBaseValue <= 3) { + return EggTier.COMMON; + } else if (speciesBaseValue <= 5) { + return EggTier.GREAT; + } else if (speciesBaseValue <= 7) { + return EggTier.ULTRA; + } + return EggTier.MASTER; +} diff --git a/src/data/enums/challenges.ts b/src/data/enums/challenges.ts new file mode 100644 index 00000000000..690e1cdc32d --- /dev/null +++ b/src/data/enums/challenges.ts @@ -0,0 +1,7 @@ +export enum Challenges { + SINGLE_GENERATION, + SINGLE_TYPE, + LOWER_MAX_STARTER_COST, + LOWER_STARTER_POINTS, + FRESH_START +} diff --git a/src/data/enums/trainer-type.ts b/src/data/enums/trainer-type.ts index 3b7e27a49e1..64eb07e22ce 100644 --- a/src/data/enums/trainer-type.ts +++ b/src/data/enums/trainer-type.ts @@ -40,6 +40,7 @@ export enum TrainerType { RICH, RICH_KID, ROUGHNECK, + SAILOR, SCIENTIST, SMASHER, SNOW_WORKER, diff --git a/src/data/move.ts b/src/data/move.ts old mode 100755 new mode 100644 index 1e2c5e7485b..103f4840ef7 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -42,7 +42,7 @@ export enum MoveTarget { /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_Pok%C3%A9mon Moves that target all adjacent Pokemon} */ ALL_NEAR_OTHERS, NEAR_ENEMY, - /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_foes Moves that taret all adjacent foes} */ + /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_foes Moves that target all adjacent foes} */ ALL_NEAR_ENEMIES, RANDOM_NEAR_ENEMY, ALL_ENEMIES, @@ -99,6 +99,7 @@ export default class Move implements Localizable { public id: Moves; public name: string; public type: Type; + public defaultType: Type; public category: MoveCategory; public moveTarget: MoveTarget; public power: integer; @@ -118,6 +119,7 @@ export default class Move implements Localizable { this.nameAppend = ""; this.type = type; + this.defaultType = type; this.category = category; this.moveTarget = defaultMoveTarget; this.power = power; @@ -166,10 +168,22 @@ export default class Move implements Localizable { return this.attrs.some((attr) => attr instanceof attrType); } + /** + * Takes as input a boolean function and returns the first MoveAttr in attrs that matches true + * @param attrPredicate + * @returns the first {@linkcode MoveAttr} element in attrs that makes the input function return true + */ findAttr(attrPredicate: (attr: MoveAttr) => boolean): MoveAttr { return this.attrs.find(attrPredicate); } + /** + * Adds a new MoveAttr to the move (appends to the attr array) + * if the MoveAttr also comes with a condition, also adds that to the conditions array: {@linkcode MoveCondition} + * @param AttrType {@linkcode MoveAttr} the constructor of a MoveAttr class + * @param args the args needed to instantiate a the given class + * @returns the called object {@linkcode Move} + */ attr MoveAttr>(AttrType: T, ...args: ConstructorParameters): this { const attr = new AttrType(...args); this.attrs.push(attr); @@ -184,9 +198,16 @@ export default class Move implements Localizable { return this; } - addAttr(attr: MoveAttr): this { - this.attrs.push(attr); - let attrCondition = attr.getCondition(); + /** + * Adds a new MoveAttr to the move (appends to the attr array) + * if the MoveAttr also comes with a condition, also adds that to the conditions array: {@linkcode MoveCondition} + * Almost identical to {@link attr}, except you are passing in a MoveAttr object, instead of a constructor and it's arguments + * @param attrAdd {@linkcode MoveAttr} the attribute to add + * @returns the called object {@linkcode Move} + */ + addAttr(attrAdd: MoveAttr): this { + this.attrs.push(attrAdd); + let attrCondition = attrAdd.getCondition(); if (attrCondition) { if (typeof attrCondition === "function") { attrCondition = new MoveCondition(attrCondition); @@ -197,15 +218,30 @@ export default class Move implements Localizable { return this; } + /** + * Sets the move target of this move + * @param moveTarget {@linkcode MoveTarget} the move target to set + * @returns the called object {@linkcode Move} + */ target(moveTarget: MoveTarget): this { this.moveTarget = moveTarget; return this; } + /** + * Getter function that returns if this Move has a MoveFlag + * @param flag {@linkcode MoveFlags} to check + * @returns boolean + */ hasFlag(flag: MoveFlags): boolean { + // internally it is taking the bitwise AND (MoveFlags are represented as bit-shifts) and returning False if result is 0 and true otherwise return !!(this.flags & flag); } + /** + * Getter function that returns if the move hits multiple targets + * @returns boolean + */ isMultiTarget(): boolean { switch (this.moveTarget) { case MoveTarget.ALL_OTHERS: @@ -222,6 +258,11 @@ export default class Move implements Localizable { return false; } + /** + * Getter function that returns if the move targets itself or an ally + * @returns boolean + */ + isAllyTarget(): boolean { switch (this.moveTarget) { case MoveTarget.USER: @@ -235,6 +276,12 @@ export default class Move implements Localizable { return false; } + /** + * Checks if the move is immune to certain types + * currently only look at case of Grass types and powder moves + * @param type {@linkcode Type} enum + * @returns boolean + */ isTypeImmune(type: Type): boolean { switch (type) { case Type.GRASS: @@ -246,6 +293,11 @@ export default class Move implements Localizable { return false; } + /** + * Adds a move condition to the move + * @param condition {@linkcode MoveCondition} or {@linkcode MoveConditionFunc}, appends to conditions array a new MoveCondition object + * @returns the called object {@linkcode Move} + */ condition(condition: MoveCondition | MoveConditionFunc): this { if (typeof condition === "function") { condition = new MoveCondition(condition as MoveConditionFunc); @@ -255,17 +307,31 @@ export default class Move implements Localizable { return this; } + /** + * Marks the move as "partial": appends texts to the move name + * @returns the called object {@linkcode Move} + */ partial(): this { this.nameAppend += " (P)"; return this; } + /** + * Marks the move as "unimplemented": appends texts to the move name + * @returns the called object {@linkcode Move} + */ unimplemented(): this { this.nameAppend += " (N)"; return this; } + /** + * Sets the flags of the move + * @param flag {@linkcode MoveFlags} + * @param on a boolean, if True, then "ORs" the flag onto existing ones, if False then "XORs" the flag onto existing ones + */ private setFlag(flag: MoveFlags, on: boolean): void { + // bitwise OR and bitwise XOR respectively if (on) { this.flags |= flag; } else { @@ -273,51 +339,110 @@ export default class Move implements Localizable { } } + /** + * Sets the {@linkcode MoveFlags.MAKES_CONTACT} flag for the calling Move + * @param makesContact The value (boolean) to set the flag to + * @returns The {@linkcode Move} that called this function + */ makesContact(makesContact?: boolean): this { this.setFlag(MoveFlags.MAKES_CONTACT, makesContact); return this; } + /** + * Sets the {@linkcode MoveFlags.IGNORE_PROTECT} flag for the calling Move + * @param ignoresProtect The value (boolean) to set the flag to + * example: @see {@linkcode Moves.CURSE} + * @returns The {@linkcode Move} that called this function + */ ignoresProtect(ignoresProtect?: boolean): this { this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect); return this; } + /** + * Sets the {@linkcode MoveFlags.IGNORE_VIRTUAL} flag for the calling Move + * @param ignoresVirtual The value (boolean) to set the flag to + * example: @see {@linkcode Moves.NATURE_POWER} + * @returns The {@linkcode Move} that called this function + */ ignoresVirtual(ignoresVirtual?: boolean): this { this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual); return this; } + /** + * Sets the {@linkcode MoveFlags.SOUND_BASED} flag for the calling Move + * @param soundBased The value (boolean) to set the flag to + * example: @see {@linkcode Moves.UPROAR} + * @returns The {@linkcode Move} that called this function + */ soundBased(soundBased?: boolean): this { this.setFlag(MoveFlags.SOUND_BASED, soundBased); return this; } + /** + * Sets the {@linkcode MoveFlags.HIDE_USER} flag for the calling Move + * @param hidesUser The value (boolean) to set the flag to + * example: @see {@linkcode Moves.TELEPORT} + * @returns The {@linkcode Move} that called this function + */ hidesUser(hidesUser?: boolean): this { this.setFlag(MoveFlags.HIDE_USER, hidesUser); return this; } + /** + * Sets the {@linkcode MoveFlags.HIDE_TARGET} flag for the calling Move + * @param hidesTarget The value (boolean) to set the flag to + * example: @see {@linkcode Moves.WHIRLWIND} + * @returns The {@linkcode Move} that called this function + */ hidesTarget(hidesTarget?: boolean): this { this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget); return this; } + /** + * Sets the {@linkcode MoveFlags.BITING_MOVE} flag for the calling Move + * @param bitingMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.BITE} + * @returns The {@linkcode Move} that called this function + */ bitingMove(bitingMove?: boolean): this { this.setFlag(MoveFlags.BITING_MOVE, bitingMove); return this; } + /** + * Sets the {@linkcode MoveFlags.PULSE_MOVE} flag for the calling Move + * @param pulseMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.WATER_PULSE} + * @returns The {@linkcode Move} that called this function + */ pulseMove(pulseMove?: boolean): this { this.setFlag(MoveFlags.PULSE_MOVE, pulseMove); return this; } + /** + * Sets the {@linkcode MoveFlags.PUNCHING_MOVE} flag for the calling Move + * @param punchingMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.DRAIN_PUNCH} + * @returns The {@linkcode Move} that called this function + */ punchingMove(punchingMove?: boolean): this { this.setFlag(MoveFlags.PUNCHING_MOVE, punchingMove); return this; } + /** + * Sets the {@linkcode MoveFlags.SLICING_MOVE} flag for the calling Move + * @param slicingMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.X_SCISSOR} + * @returns The {@linkcode Move} that called this function + */ slicingMove(slicingMove?: boolean): this { this.setFlag(MoveFlags.SLICING_MOVE, slicingMove); return this; @@ -334,42 +459,92 @@ export default class Move implements Localizable { return this; } + /** + * Sets the {@linkcode MoveFlags.BALLBOMB_MOVE} flag for the calling Move + * @param ballBombMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.ELECTRO_BALL} + * @returns The {@linkcode Move} that called this function + */ ballBombMove(ballBombMove?: boolean): this { this.setFlag(MoveFlags.BALLBOMB_MOVE, ballBombMove); return this; } + /** + * Sets the {@linkcode MoveFlags.POWDER_MOVE} flag for the calling Move + * @param powderMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.STUN_SPORE} + * @returns The {@linkcode Move} that called this function + */ powderMove(powderMove?: boolean): this { this.setFlag(MoveFlags.POWDER_MOVE, powderMove); return this; } + /** + * Sets the {@linkcode MoveFlags.DANCE_MOVE} flag for the calling Move + * @param danceMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.PETAL_DANCE} + * @returns The {@linkcode Move} that called this function + */ danceMove(danceMove?: boolean): this { this.setFlag(MoveFlags.DANCE_MOVE, danceMove); return this; } + /** + * Sets the {@linkcode MoveFlags.WIND_MOVE} flag for the calling Move + * @param windMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.HURRICANE} + * @returns The {@linkcode Move} that called this function + */ windMove(windMove?: boolean): this { this.setFlag(MoveFlags.WIND_MOVE, windMove); return this; } + /** + * Sets the {@linkcode MoveFlags.TRIAGE_MOVE} flag for the calling Move + * @param triageMove The value (boolean) to set the flag to + * example: @see {@linkcode Moves.ABSORB} + * @returns The {@linkcode Move} that called this function + */ triageMove(triageMove?: boolean): this { this.setFlag(MoveFlags.TRIAGE_MOVE, triageMove); return this; } + /** + * Sets the {@linkcode MoveFlags.IGNORE_ABILITIES} flag for the calling Move + * @param ignoresAbilities sThe value (boolean) to set the flag to + * example: @see {@linkcode Moves.SUNSTEEL_STRIKE} + * @returns The {@linkcode Move} that called this function + */ ignoresAbilities(ignoresAbilities?: boolean): this { this.setFlag(MoveFlags.IGNORE_ABILITIES, ignoresAbilities); return this; } + /** + * Sets the {@linkcode MoveFlags.CHECK_ALL_HITS} flag for the calling Move + * @param checkAllHits The value (boolean) to set the flag to + * example: @see {@linkcode Moves.TRIPLE_AXEL} + * @returns The {@linkcode Move} that called this function + */ checkAllHits(checkAllHits?: boolean): this { this.setFlag(MoveFlags.CHECK_ALL_HITS, checkAllHits); return this; } + /** + * Checks if the move flag applies to the pokemon(s) using/receiving the move + * @param flag {@linkcode MoveFlags} MoveFlag to check on user and/or target + * @param user {@linkcode Pokemon} the Pokemon using the move + * @param target {@linkcode Pokemon} the Pokemon receiving the move + * @returns boolean + */ checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean { + // special cases below, eg: if the move flag is MAKES_CONTACT, and the user pokemon has an ability that ignores contact (like "Long Reach"), then overrides and move does not make contact switch (flag) { case MoveFlags.MAKES_CONTACT: if (user.hasAbilityWithAttr(IgnoreContactAbAttr)) { @@ -389,6 +564,13 @@ export default class Move implements Localizable { return !!(this.flags & flag); } + /** + * Applies each {@linkcode MoveCondition} of this move to the params + * @param user {@linkcode Pokemon} to apply conditions to + * @param target {@linkcode Pokemon} to apply conditions to + * @param move {@linkcode Move} to apply conditions to + * @returns boolean: false if any of the apply()'s return false, else true + */ applyConditions(user: Pokemon, target: Pokemon, move: Move): boolean { for (const condition of this.conditions) { if (!condition.apply(user, target, move)) { @@ -399,6 +581,14 @@ export default class Move implements Localizable { return true; } + /** + * Sees if, given the target pokemon, a move fails on it (by looking at each {@linkcode MoveAttr} of this move + * @param user {@linkcode Pokemon} using the move + * @param target {@linkcode Pokemon} receiving the move + * @param move {@linkcode Move} using the move + * @param cancelled {@linkcode Utils.BooleanHolder} to hold boolean value + * @returns string of the failed text, or null + */ getFailedText(user: Pokemon, target: Pokemon, move: Move, cancelled: Utils.BooleanHolder): string | null { for (const attr of this.attrs) { const failedText = attr.getFailedText(user, target, move, cancelled); @@ -409,6 +599,13 @@ export default class Move implements Localizable { return null; } + /** + * Calculates the userBenefitScore across all the attributes and conditions + * @param user {@linkcode Pokemon} using the move + * @param target {@linkcode Pokemon} receiving the move + * @param move {@linkcode Move} using the move + * @returns integer representing the total benefitScore + */ getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { let score = 0; @@ -423,10 +620,18 @@ export default class Move implements Localizable { return score; } + /** + * Calculates the targetBenefitScore across all the attributes + * @param user {@linkcode Pokemon} using the move + * @param target {@linkcode Pokemon} receiving the move + * @param move {@linkcode Move} using the move + * @returns integer representing the total benefitScore + */ getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { let score = 0; for (const attr of this.attrs) { + // conditionals to check if the move is self targeting (if so then you are applying the move to yourself, not the target) score += attr.getTargetBenefitScore(user, !attr.selfTarget ? target : user, move) * (target !== user && attr.selfTarget ? -1 : 1); } @@ -1046,11 +1251,18 @@ export class PartyStatusCureAttr extends MoveEffectAttr { this.abilityCondition = abilityCondition; } + //The same as MoveEffectAttr.canApply, except it doesn't check for the target's HP. + canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]) { + const isTargetValid = + (this.selfTarget && user.hp && !user.getTag(BattlerTagType.FRENZY)) || + (!this.selfTarget && (!target.getTag(BattlerTagType.PROTECTED) || move.hasFlag(MoveFlags.IGNORE_PROTECT))); + return !!isTargetValid; + } + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - if (!super.apply(user, target, move, args)) { + if (!this.canApply(user, target, move, args)) { return false; } - this.addPartyCurePhase(user); } @@ -1262,7 +1474,7 @@ export class HitHealAttr extends MoveEffectAttr { message = i18next.t("battle:drainMessage", {pokemonName: target.name}); } else { // Default healing formula used by draining moves like Absorb, Draining Kiss, Bitter Blade, etc. - healAmount = Math.max(Math.floor(user.turnData.damageDealt * this.healRatio), 1); + healAmount = Math.max(Math.floor(user.turnData.currDamageDealt * this.healRatio), 1); message = i18next.t("battle:regainHealth", {pokemonName: user.name}); } if (reverseDrain) { @@ -1426,7 +1638,7 @@ export class StatusEffectAttr extends MoveEffectAttr { } if ((!pokemon.status || (pokemon.status.effect === this.effect && move.chance < 0)) && pokemon.trySetStatus(this.effect, true, user, this.cureTurn)) { - applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, new PokemonMove(move.id), null,this.effect); + applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null,this.effect); return true; } } @@ -1992,7 +2204,7 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr { (args[0] as Utils.BooleanHolder).value = true; user.scene.queueMessage(getPokemonMessage(user, ` ${this.chargeText.replace("{TARGET}", target.name)}`)); user.pushMoveHistory({ move: move.id, targets: [ target.getBattlerIndex() ], result: MoveResult.OTHER }); - user.scene.arena.addTag(this.tagType, 3, move.id, user.id, ArenaTagSide.BOTH, target.getBattlerIndex()); + user.scene.arena.addTag(this.tagType, 3, move.id, user.id, ArenaTagSide.BOTH, false, target.getBattlerIndex()); resolve(true); }); @@ -3120,23 +3332,22 @@ export class TechnoBlastTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.GENESECT)) { const form = user.species.speciesId === Species.GENESECT ? user.formIndex : user.fusionSpecies.formIndex; - const type = (args[0] as Utils.IntegerHolder); switch (form) { case 1: // Shock Drive - type.value = Type.ELECTRIC; + move.type = Type.ELECTRIC; break; case 2: // Burn Drive - type.value = Type.FIRE; + move.type = Type.FIRE; break; case 3: // Chill Drive - type.value = Type.ICE; + move.type = Type.ICE; break; case 4: // Douse Drive - type.value = Type.WATER; + move.type = Type.WATER; break; default: - type.value = Type.NORMAL; + move.type = Type.NORMAL; break; } return true; @@ -3150,14 +3361,13 @@ export class AuraWheelTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.MORPEKO)) { const form = user.species.speciesId === Species.MORPEKO ? user.formIndex : user.fusionSpecies.formIndex; - const type = (args[0] as Utils.IntegerHolder); switch (form) { case 1: // Hangry Mode - type.value = Type.DARK; + move.type = Type.DARK; break; default: // Full Belly Mode - type.value = Type.ELECTRIC; + move.type = Type.ELECTRIC; break; } return true; @@ -3171,17 +3381,16 @@ export class RagingBullTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.PALDEA_TAUROS)) { const form = user.species.speciesId === Species.PALDEA_TAUROS ? user.formIndex : user.fusionSpecies.formIndex; - const type = (args[0] as Utils.IntegerHolder); switch (form) { case 1: // Blaze breed - type.value = Type.FIRE; + move.type = Type.FIRE; break; case 2: // Aqua breed - type.value = Type.WATER; + move.type = Type.WATER; break; default: - type.value = Type.FIGHTING; + move.type = Type.FIGHTING; break; } return true; @@ -3195,32 +3404,31 @@ export class IvyCudgelTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.OGERPON)) { const form = user.species.speciesId === Species.OGERPON ? user.formIndex : user.fusionSpecies.formIndex; - const type = (args[0] as Utils.IntegerHolder); switch (form) { case 1: // Wellspring Mask - type.value = Type.WATER; + move.type = Type.WATER; break; case 2: // Hearthflame Mask - type.value = Type.FIRE; + move.type = Type.FIRE; break; case 3: // Cornerstone Mask - type.value = Type.ROCK; + move.type = Type.ROCK; break; case 4: // Teal Mask Tera - type.value = Type.GRASS; + move.type = Type.GRASS; break; case 5: // Wellspring Mask Tera - type.value = Type.WATER; + move.type = Type.WATER; break; case 6: // Hearthflame Mask Tera - type.value = Type.FIRE; + move.type = Type.FIRE; break; case 7: // Cornerstone Mask Tera - type.value = Type.ROCK; + move.type = Type.ROCK; break; default: - type.value = Type.GRASS; + move.type = Type.GRASS; break; } return true; @@ -3233,23 +3441,21 @@ export class IvyCudgelTypeAttr extends VariableMoveTypeAttr { export class WeatherBallTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if (!user.scene.arena.weather?.isEffectSuppressed(user.scene)) { - const type = (args[0] as Utils.IntegerHolder); - switch (user.scene.arena.weather?.weatherType) { case WeatherType.SUNNY: case WeatherType.HARSH_SUN: - type.value = Type.FIRE; + move.type = Type.FIRE; break; case WeatherType.RAIN: case WeatherType.HEAVY_RAIN: - type.value = Type.WATER; + move.type = Type.WATER; break; case WeatherType.SANDSTORM: - type.value = Type.ROCK; + move.type = Type.ROCK; break; case WeatherType.HAIL: case WeatherType.SNOW: - type.value = Type.ICE; + move.type = Type.ICE; break; default: return false; @@ -3281,20 +3487,18 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr { } const currentTerrain = user.scene.arena.getTerrainType(); - const type = (args[0] as Utils.IntegerHolder); - switch (currentTerrain) { case TerrainType.MISTY: - type.value = Type.FAIRY; + move.type = Type.FAIRY; break; case TerrainType.ELECTRIC: - type.value = Type.ELECTRIC; + move.type = Type.ELECTRIC; break; case TerrainType.GRASSY: - type.value = Type.GRASS; + move.type = Type.GRASS; break; case TerrainType.PSYCHIC: - type.value = Type.PSYCHIC; + move.type = Type.PSYCHIC; break; default: return false; @@ -3305,8 +3509,6 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr { export class HiddenPowerTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const type = (args[0] as Utils.IntegerHolder); - const iv_val = Math.floor(((user.ivs[Stat.HP] & 1) +(user.ivs[Stat.ATK] & 1) * 2 +(user.ivs[Stat.DEF] & 1) * 4 @@ -3314,7 +3516,7 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr { +(user.ivs[Stat.SPATK] & 1) * 16 +(user.ivs[Stat.SPDEF] & 1) * 32) * 15/63); - type.value = [ + move.type = [ Type.FIGHTING, Type.FLYING, Type.POISON, Type.GROUND, Type.ROCK, Type.BUG, Type.GHOST, Type.STEEL, Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC, @@ -3326,16 +3528,14 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr { export class MatchUserTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const type = (args[0] as Utils.IntegerHolder); - const userTypes = user.getTypes(true); if (userTypes.includes(Type.STELLAR)) { // will not change to stellar type const nonTeraTypes = user.getTypes(); - type.value = nonTeraTypes[0]; + move.type = nonTeraTypes[0]; return true; } else if (userTypes.length > 0) { - type.value = userTypes[0]; + move.type = userTypes[0]; return true; } else { return false; @@ -4021,6 +4221,48 @@ export class RemoveScreensAttr extends MoveEffectAttr { } } + +/*Swaps arena effects between the player and enemy side + * @extends MoveEffectAttr + * @see {@linkcode apply} +*/ +export class SwapArenaTagsAttr extends MoveEffectAttr { + public SwapTags: ArenaTagType[]; + + + constructor(SwapTags: ArenaTagType[]) { + super(true, MoveEffectTrigger.POST_APPLY); + this.SwapTags = SwapTags; + } + + apply(user:Pokemon, target:Pokemon, move:Move, args: any[]): boolean { + if (!super.apply(user, target, move, args)) { + return false; + } + + const tagPlayerTemp = user.scene.arena.findTagsOnSide((t => this.SwapTags.includes(t.tagType)), ArenaTagSide.PLAYER); + const tagEnemyTemp = user.scene.arena.findTagsOnSide((t => this.SwapTags.includes(t.tagType)), ArenaTagSide.ENEMY); + + + if (tagPlayerTemp) { + for (const swapTagsType of tagPlayerTemp) { + user.scene.arena.removeTagOnSide(swapTagsType.tagType, ArenaTagSide.PLAYER, true); + user.scene.arena.addTag(swapTagsType.tagType, swapTagsType.turnCount, swapTagsType.sourceMove, swapTagsType.sourceId, ArenaTagSide.ENEMY, true); + } + } + if (tagEnemyTemp) { + for (const swapTagsType of tagEnemyTemp) { + user.scene.arena.removeTagOnSide(swapTagsType.tagType, ArenaTagSide.ENEMY, true); + user.scene.arena.addTag(swapTagsType.tagType, swapTagsType.turnCount, swapTagsType.sourceMove, swapTagsType.sourceId, ArenaTagSide.PLAYER, true); + } + } + + + user.scene.queueMessage( `${user.name} swapped the battle effects affecting each side of the field!`); + return true; + } +} + /** * Attribute used for Revival Blessing. * @extends MoveEffectAttr @@ -4100,7 +4342,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { // Check if the move category is not STATUS or if the switch out condition is not met if (!this.getSwitchOutCondition()(user, target, move)) { //Apply effects before switch out i.e. poison point, flame body, etc - applyPostDefendAbAttrs(PostDefendContactApplyStatusEffectAbAttr, target, user, new PokemonMove(move.id), null); + applyPostDefendAbAttrs(PostDefendContactApplyStatusEffectAbAttr, target, user, move, null); return resolve(false); } @@ -4181,7 +4423,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { } const party = player ? user.scene.getParty() : user.scene.getEnemyParty(); - return (!player && !user.scene.currentBattle.battleType) || party.filter(p => !p.isFainted() && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > user.scene.currentBattle.getBattlerCount(); + return (!player && !user.scene.currentBattle.battleType) || party.filter(p => p.isAllowedInBattle() && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > user.scene.currentBattle.getBattlerCount(); }; } @@ -5710,6 +5952,7 @@ export function initMoves() { .attr(BypassSleepAttr) .attr(RandomMovesetMoveAttr) .condition(userSleptOrComatoseCondition) + .target(MoveTarget.ALL_ENEMIES) .ignoresVirtual(), new StatusMove(Moves.HEAL_BELL, Type.NORMAL, -1, 5, -1, 0, 2) .attr(PartyStatusCureAttr, "A bell chimed!", Abilities.SOUNDPROOF) @@ -5769,7 +6012,7 @@ export function initMoves() { ], true) .attr(RemoveArenaTrapAttr), new StatusMove(Moves.SWEET_SCENT, Type.NORMAL, 100, 20, -1, 0, 2) - .attr(StatChangeAttr, BattleStat.EVA, -1) + .attr(StatChangeAttr, BattleStat.EVA, -2) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.IRON_TAIL, Type.STEEL, MoveCategory.PHYSICAL, 100, 75, 15, 30, 0, 2) .attr(StatChangeAttr, BattleStat.DEF, -1), @@ -6683,7 +6926,11 @@ export function initMoves() { .condition((user, target, move) => user.battleData.berriesEaten.length > 0), new StatusMove(Moves.ROTOTILLER, Type.GROUND, -1, 10, 100, 0, 6) .target(MoveTarget.ALL) - .unimplemented(), + .condition((user,target,move) => { + // If any fielded pokémon is grass-type and grounded. + return [...user.scene.getEnemyParty(),...user.scene.getParty()].some((poke) => poke.isOfType(Type.GRASS) && poke.isGrounded()); + }) + .attr(StatChangeAttr, [BattleStat.ATK, BattleStat.SPATK], 1, false, (user, target, move) => target.isOfType(Type.GRASS) && target.isGrounded()), new StatusMove(Moves.STICKY_WEB, Type.BUG, -1, 20, -1, 0, 6) .attr(AddArenaTrapTagAttr, ArenaTagType.STICKY_WEB) .target(MoveTarget.ENEMY_SIDE), @@ -7253,9 +7500,7 @@ export function initMoves() { .attr(FirstAttackDoublePowerAttr) .bitingMove(), new StatusMove(Moves.COURT_CHANGE, Type.NORMAL, 100, 10, -1, 0, 8) - .target(MoveTarget.BOTH_SIDES) - .unimplemented(), - /* Unused */ + .attr(SwapArenaTagsAttr, [ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.MIST, ArenaTagType.REFLECT, ArenaTagType.SPIKES, ArenaTagType.STEALTH_ROCK, ArenaTagType.STICKY_WEB, ArenaTagType.TAILWIND, ArenaTagType.TOXIC_SPIKES]), new AttackMove(Moves.MAX_FLARE, Type.FIRE, MoveCategory.PHYSICAL, 10, -1, 10, -1, 0, 8) .target(MoveTarget.NEAR_ENEMY) .unimplemented() diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index da6bac42ac7..77991ee6434 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -363,7 +363,8 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.PIDGEOT, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.PIDGEOTITE)) ], [Species.PIKACHU]: [ - new SpeciesFormChange(Species.PIKACHU, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) + new SpeciesFormChange(Species.PIKACHU, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)), + new SpeciesFormChange(Species.PIKACHU, "partner", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) ], [Species.MEOWTH]: [ new SpeciesFormChange(Species.MEOWTH, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) @@ -397,7 +398,8 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.LAPRAS, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) ], [Species.EEVEE]: [ - new SpeciesFormChange(Species.EEVEE, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) + new SpeciesFormChange(Species.EEVEE, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)), + new SpeciesFormChange(Species.EEVEE, "partner", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) ], [Species.SNORLAX]: [ new SpeciesFormChange(Species.SNORLAX, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 562a79ea333..4f6098734ec 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -917,7 +917,7 @@ export function initSpecies() { new PokemonSpecies(Species.ARBOK, 1, false, false, false, "Cobra Pokémon", Type.POISON, null, 3.5, 65, Abilities.INTIMIDATE, Abilities.SHED_SKIN, Abilities.UNNERVE, 448, 60, 95, 69, 65, 79, 80, 90, 70, 157, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.PIKACHU, 1, false, false, false, "Mouse Pokémon", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 320, 35, 55, 40, 50, 50, 90, 190, 50, 112, GrowthRate.MEDIUM_FAST, 50, true, true, new PokemonForm("Normal", "", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 320, 35, 55, 40, 50, 50, 90, 190, 50, 112, true, null, true), - new PokemonForm("Partner", "partner", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, "", true), + new PokemonForm("Partner", "partner", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), new PokemonForm("Cosplay", "cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom new PokemonForm("Cool Cosplay", "cool-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom new PokemonForm("Beauty Cosplay", "beauty-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom @@ -1066,7 +1066,7 @@ export function initSpecies() { new PokemonSpecies(Species.DITTO, 1, false, false, false, "Transform Pokémon", Type.NORMAL, null, 0.3, 4, Abilities.LIMBER, Abilities.NONE, Abilities.IMPOSTER, 288, 48, 48, 48, 48, 48, 48, 35, 50, 101, GrowthRate.MEDIUM_FAST, null, false), new PokemonSpecies(Species.EEVEE, 1, false, false, false, "Evolution Pokémon", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 325, 55, 55, 50, 45, 65, 55, 45, 50, 65, GrowthRate.MEDIUM_FAST, 87.5, false, true, new PokemonForm("Normal", "", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 325, 55, 55, 50, 45, 65, 55, 45, 50, 65, false, null, true), - new PokemonForm("Partner", "partner", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 435, 65, 75, 70, 65, 85, 75, 45, 50, 65, false, "", true), + new PokemonForm("Partner", "partner", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 435, 65, 75, 70, 65, 85, 75, 45, 50, 65, false, null, true), new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 18, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 425, 70, 75, 80, 60, 95, 45, 45, 50, 65), ), new PokemonSpecies(Species.VAPOREON, 1, false, false, false, "Bubble Jet Pokémon", Type.WATER, null, 1, 29, Abilities.WATER_ABSORB, Abilities.NONE, Abilities.HYDRATION, 525, 130, 65, 60, 110, 95, 65, 45, 50, 184, GrowthRate.MEDIUM_FAST, 87.5, false), @@ -1286,7 +1286,7 @@ export function initSpecies() { new PokemonSpecies(Species.PELIPPER, 3, false, false, false, "Water Bird Pokémon", Type.WATER, Type.FLYING, 1.2, 28, Abilities.KEEN_EYE, Abilities.DRIZZLE, Abilities.RAIN_DISH, 440, 60, 50, 100, 95, 70, 65, 45, 50, 154, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.RALTS, 3, false, false, false, "Feeling Pokémon", Type.PSYCHIC, Type.FAIRY, 0.4, 6.6, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 198, 28, 25, 25, 45, 35, 40, 235, 35, 40, GrowthRate.SLOW, 50, false), new PokemonSpecies(Species.KIRLIA, 3, false, false, false, "Emotion Pokémon", Type.PSYCHIC, Type.FAIRY, 0.8, 20.2, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 278, 38, 35, 35, 65, 55, 50, 120, 35, 97, GrowthRate.SLOW, 50, false), - new PokemonSpecies(Species.GARDEVOIR, 3, false, false, false, "Embrace Pokémon", Type.PSYCHIC, Type.FAIRY, 1.6, 48.4, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 518, 68, 65, 65, 125, 115, 80, 45, 35, 259, GrowthRate.SLOW, 0, false, true, + new PokemonSpecies(Species.GARDEVOIR, 3, false, false, false, "Embrace Pokémon", Type.PSYCHIC, Type.FAIRY, 1.6, 48.4, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 518, 68, 65, 65, 125, 115, 80, 45, 35, 259, GrowthRate.SLOW, 50, false, true, new PokemonForm("Normal", "", Type.PSYCHIC, Type.FAIRY, 1.6, 48.4, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 518, 68, 65, 65, 125, 115, 80, 45, 35, 259, false, null, true), new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.PSYCHIC, Type.FAIRY, 1.6, 48.4, Abilities.PIXILATE, Abilities.PIXILATE, Abilities.PIXILATE, 618, 68, 85, 65, 165, 135, 100, 45, 35, 259), ), @@ -1404,7 +1404,7 @@ export function initSpecies() { ), new PokemonSpecies(Species.WYNAUT, 3, false, false, false, "Bright Pokémon", Type.PSYCHIC, null, 0.6, 14, Abilities.SHADOW_TAG, Abilities.NONE, Abilities.TELEPATHY, 260, 95, 23, 48, 23, 48, 23, 125, 50, 52, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.SNORUNT, 3, false, false, false, "Snow Hat Pokémon", Type.ICE, null, 0.7, 16.8, Abilities.INNER_FOCUS, Abilities.ICE_BODY, Abilities.MOODY, 300, 50, 50, 50, 50, 50, 50, 190, 50, 60, GrowthRate.MEDIUM_FAST, 50, false), - new PokemonSpecies(Species.GLALIE, 3, false, false, false, "Face Pokémon", Type.ICE, null, 1.5, 256.5, Abilities.INNER_FOCUS, Abilities.ICE_BODY, Abilities.MOODY, 480, 80, 80, 80, 80, 80, 80, 75, 50, 168, GrowthRate.MEDIUM_FAST, 100, false, true, + new PokemonSpecies(Species.GLALIE, 3, false, false, false, "Face Pokémon", Type.ICE, null, 1.5, 256.5, Abilities.INNER_FOCUS, Abilities.ICE_BODY, Abilities.MOODY, 480, 80, 80, 80, 80, 80, 80, 75, 50, 168, GrowthRate.MEDIUM_FAST, 50, false, true, new PokemonForm("Normal", "", Type.ICE, null, 1.5, 256.5, Abilities.INNER_FOCUS, Abilities.ICE_BODY, Abilities.MOODY, 480, 80, 80, 80, 80, 80, 80, 75, 50, 168, false, null, true), new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.ICE, null, 2.1, 350.2, Abilities.REFRIGERATE, Abilities.REFRIGERATE, Abilities.REFRIGERATE, 580, 80, 120, 80, 120, 80, 100, 75, 50, 168), ), @@ -1829,7 +1829,7 @@ export function initSpecies() { new PokemonForm("Ordinary Form", "ordinary", Type.WATER, Type.FIGHTING, 1.4, 48.5, Abilities.JUSTIFIED, Abilities.NONE, Abilities.NONE, 580, 91, 72, 90, 129, 90, 108, 3, 35, 290, false, null, true), new PokemonForm("Resolute", "resolute", Type.WATER, Type.FIGHTING, 1.4, 48.5, Abilities.JUSTIFIED, Abilities.NONE, Abilities.NONE, 580, 91, 72, 90, 129, 90, 108, 3, 35, 290), ), - new PokemonSpecies(Species.MELOETTA, 5, false, false, true, "Melody Pokémon", Type.NORMAL, Type.PSYCHIC, 0.6, 6.5, Abilities.SERENE_GRACE, Abilities.NONE, Abilities.NONE, 600, 100, 77, 77, 128, 128, 90, 3, 100, 270, GrowthRate.SLOW, 0, false, true, + new PokemonSpecies(Species.MELOETTA, 5, false, false, true, "Melody Pokémon", Type.NORMAL, Type.PSYCHIC, 0.6, 6.5, Abilities.SERENE_GRACE, Abilities.NONE, Abilities.NONE, 600, 100, 77, 77, 128, 128, 90, 3, 100, 270, GrowthRate.SLOW, null, false, true, new PokemonForm("Aria Forme", "aria", Type.NORMAL, Type.PSYCHIC, 0.6, 6.5, Abilities.SERENE_GRACE, Abilities.NONE, Abilities.NONE, 600, 100, 77, 77, 128, 128, 90, 3, 100, 270, false, null, true), new PokemonForm("Pirouette Forme", "pirouette", Type.NORMAL, Type.FIGHTING, 0.6, 6.5, Abilities.SERENE_GRACE, Abilities.NONE, Abilities.NONE, 600, 100, 128, 90, 77, 77, 128, 3, 100, 270), ), diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index af47991ad14..12c3bdb52d9 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -187,6 +187,7 @@ export class TrainerConfig { public isBoss: boolean = false; public hasStaticParty: boolean = false; public useSameSeedForAllMembers: boolean = false; + public mixedBattleBgm: string; public battleBgm: string; public encounterBgm: string; public femaleEncounterBgm: string; @@ -217,6 +218,7 @@ export class TrainerConfig { this.trainerType = trainerType; this.name = Utils.toReadableString(TrainerType[this.getDerivedType()]); this.battleBgm = "battle_trainer"; + this.mixedBattleBgm = "battle_trainer"; this.victoryBgm = "victory_trainer"; this.partyTemplates = [trainerPartyTemplates.TWO_AVG]; this.speciesFilter = species => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden(); @@ -440,6 +442,11 @@ export class TrainerConfig { return this; } + setMixedBattleBgm(mixedBattleBgm: string): TrainerConfig { + this.mixedBattleBgm = mixedBattleBgm; + return this; + } + setBattleBgm(battleBgm: string): TrainerConfig { this.battleBgm = battleBgm; return this; @@ -605,7 +612,7 @@ export class TrainerConfig { this.setMoneyMultiplier(3.25); this.setBoss(); this.setStaticParty(); - this.setBattleBgm("battle_elite"); + this.setBattleBgm("battle_unova_elite"); this.setVictoryBgm("victory_gym"); this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 2, specialtyTypes.length ? specialtyTypes : null)); @@ -876,22 +883,22 @@ export const signatureSpecies: SignatureSpecies = { RYME: [Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], TULIP: [Species.GIRAFARIG, Species.FLITTLE, Species.RALTS], GRUSHA: [Species.CETODDLE, Species.ALOLA_VULPIX, Species.CUBCHOO], - LORELEI: [Species.SLOWBRO, Species.LAPRAS, Species.DEWGONG, Species.ALOLA_SANDSLASH], - BRUNO: [Species.ONIX, Species.HITMONCHAN, Species.HITMONLEE, Species.ALOLA_GOLEM], - AGATHA: [Species.GENGAR, Species.ARBOK, Species.CROBAT, Species.ALOLA_MAROWAK], + LORELEI: [Species.JYNX, [Species.SLOWBRO, Species.GALAR_SLOWBRO], Species.LAPRAS, [Species.ALOLA_SANDSLASH, Species.CLOYSTER]], + BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.ALOLA_GOLEM, Species.GOLEM]], + AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK], LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR], - WILL: [Species.XATU, Species.JYNX, Species.SLOWBRO, Species.EXEGGUTOR], - KOGA: [Species.WEEZING, Species.VENOMOTH, Species.CROBAT, Species.TENTACRUEL], + WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR], + KOGA: [[Species.WEEZING, Species.MUK], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL], KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE], - SIDNEY: [Species.SHIFTRY, Species.SHARPEDO, Species.ABSOL, Species.ZOROARK], - PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, Species.CHANDELURE], + SIDNEY: [[Species.SHIFTRY, Species.CACTURNE], [Species.SHARPEDO, Species.CRAWDAUNT], Species.ABSOL, Species.MIGHTYENA], + PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.MISMAGIUS, Species.DRIFBLIM]], GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW], DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA], - AARON: [Species.SCIZOR, Species.HERACROSS, Species.VESPIQUEN, Species.DRAPION], + AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION], BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR], - FLINT: [Species.FLAREON, Species.HOUNDOOM, Species.RAPIDASH, Species.INFERNAPE], - LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, Species.ALAKAZAM], - SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.DRIFBLIM], + FLINT: [[Species.FLAREON, Species.RAPIDASH], Species.MAGMORTAR, [Species.STEELIX, Species.LOPUNNY], Species.INFERNAPE], + LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]], + SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT], MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK], GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE], CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS], @@ -899,35 +906,35 @@ export const signatureSpecies: SignatureSpecies = { SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE], WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH], DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN], - HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, Species.POLIWRATH], + HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]], MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO], - OLIVIA: [Species.ARMALDO, Species.CRADILY, Species.ALOLA_GOLEM, Species.LYCANROC], - ACEROLA: [Species.BANETTE, Species.DRIFBLIM, Species.DHELMISE, Species.PALOSSAND], - KAHILI: [Species.BRAVIARY, Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON], - MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, Species.TOXICROAK, Species.SCRAFTY, Species.GRIMMSNARL], - NESSA_ELITE: [Species.GOLISOPOD, Species.PELIPPER, Species.QUAGSIRE, Species.TOXAPEX, Species.DREDNAW], - BEA_ELITE: [Species.HAWLUCHA, Species.GRAPPLOCT, Species.SIRFETCHD, Species.FALINKS, Species.MACHAMP], - ALLISTER_ELITE:[Species.DUSKNOIR, Species.CHANDELURE, Species.CURSOLA, Species.RUNERIGUS, Species.GENGAR], - RAIHAN_ELITE: [Species.TORKOAL, Species.GOODRA, Species.TURTONATOR, Species.FLYGON, Species.DURALUDON], - RIKA: [Species.WHISCASH, Species.DONPHAN, Species.CAMERUPT, Species.CLODSIRE], + OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC], + ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND], + KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON], + MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL], + NESSA_ELITE: [Species.GOLISOPOD, [Species.PELIPPER, Species.QUAGSIRE], Species.TOXAPEX, Species.DREDNAW], + BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP], + ALLISTER_ELITE:[Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR], + RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON], + RIKA: [Species.WHISCASH, [Species.DONPHAN, Species.DUGTRIO], Species.CAMERUPT, Species.CLODSIRE], POPPY: [Species.COPPERAJAH, Species.BRONZONG, Species.CORVIKNIGHT, Species.TINKATON], LARRY_ELITE: [Species.STARAPTOR, Species.FLAMIGO, Species.ALTARIA, Species.TROPIUS], - HASSEL: [Species.NOIVERN, Species.HAXORUS, Species.DRAGALGE, Species.BAXCALIBUR], + HASSEL: [Species.NOIVERN, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.BAXCALIBUR], CRISPIN: [Species.TALONFLAME, Species.CAMERUPT, Species.MAGMORTAR, Species.BLAZIKEN], AMARYS: [Species.SKARMORY, Species.EMPOLEON, Species.SCIZOR, Species.METAGROSS], - LACEY: [Species.EXCADRILL, Species.PRIMARINA, Species.ALCREMIE, Species.GALAR_SLOWBRO], - DRAYTON: [Species.DRAGONITE, Species.ARCHALUDON, Species.FLYGON, Species.SCEPTILE], + LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.ALCREMIE, Species.GRANBULL], Species.WHIMSICOTT], + DRAYTON: [Species.DRAGONITE, Species.ARCHALUDON, Species.HAXORUS, Species.SCEPTILE], BLUE: [[Species.GYARADOS, Species.EXEGGUTOR, Species.ARCANINE], Species.HO_OH, [Species.RHYPERIOR, Species.MAGNEZONE]], // Alakazam lead, Mega Pidgeot RED: [Species.LUGIA, Species.SNORLAX, [Species.ESPEON, Species.UMBREON, Species.SYLVEON]], // GMax Pikachu lead, Mega gen 1 starter - LANCE_CHAMPION: [Species.DRAGONITE, Species.KINGDRA, Species.ALOLA_EXEGGUTOR], // Aerodactyl lead, Mega Lati@s - STEVEN: [Species.AGGRON, [Species.ARMALDO, Species.CRADILY], Species.DIALGA], // Skarmorly lead, Mega Metagross + LANCE_CHAMPION: [Species.DRAGONITE, Species.KINGDRA, Species.ALOLA_EXEGGUTOR], // Aerodactyl lead, Mega Latias/Latios + STEVEN: [Species.AGGRON, [Species.ARMALDO, Species.CRADILY], Species.DIALGA], // Skarmory lead, Mega Metagross WALLACE: [Species.MILOTIC, Species.PALKIA, Species.LUDICOLO], // Pelipper lead, Mega Swampert CYNTHIA: [Species.GIRATINA, Species.LUCARIO, Species.TOGEKISS], // Spiritomb lead, Mega Garchomp ALDER: [Species.VOLCARONA, Species.ZEKROM, [Species.ACCELGOR, Species.ESCAVALIER], Species.KELDEO], // Bouffalant/Braviary lead IRIS: [Species.HAXORUS, Species.RESHIRAM, Species.ARCHEOPS], // Druddigon lead, Gmax Lapras DIANTHA: [Species.HAWLUCHA, Species.XERNEAS, Species.GOODRA], // Gourgeist lead, Mega Gardevoir HAU: [[Species.SOLGALEO, Species.LUNALA], Species.NOIVERN, [Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA], [Species.TAPU_BULU, Species.TAPU_FINI, Species.TAPU_KOKO, Species.TAPU_LELE]], // Alola Raichu lead - LEON: [Species.DRAGAPULT, [Species.ZACIAN, Species.ZAMAZENTA], Species.AEGISLASH], // Rillaboom/Cinderace/Inteleon lead + LEON: [Species.DRAGAPULT, [Species.ZACIAN, Species.ZAMAZENTA], Species.AEGISLASH], // Rillaboom/Cinderace/Inteleon lead, GMax Charizard GEETA: [Species.MIRAIDON, [Species.ESPATHRA, Species.VELUZA], [Species.AVALUGG, Species.HISUI_AVALUGG], Species.KINGAMBIT], // Glimmora lead NEMONA: [Species.KORAIDON, Species.PAWMOT, [Species.DUDUNSPARCE, Species.ORTHWORM], [Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL]], // Lycanroc lead KIERAN: [[Species.GRIMMSNARL, Species.INCINEROAR, Species.PORYGON_Z], Species.OGERPON, Species.TERAPAGOS, Species.HYDRAPPLE], // Poliwrath/Politoed lead @@ -1059,6 +1066,7 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.RICH]: new TrainerConfig(++t).setMoneyMultiplier(5).setName("Gentleman").setHasGenders("Madame").setHasDouble("Rich Couple"), [TrainerType.RICH_KID]: new TrainerConfig(++t).setMoneyMultiplier(3.75).setName("Rich Boy").setHasGenders("Lady").setHasDouble("Rich Kids").setEncounterBgm(TrainerType.RICH), [TrainerType.ROUGHNECK]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.DARK)), + [TrainerType.SAILOR]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.BACKPACKER).setSpeciesFilter(s => s.isOfType(Type.WATER) || s.isOfType(Type.FIGHTING)), [TrainerType.SCIENTIST]: new TrainerConfig(++t).setHasGenders("Scientist Female").setHasDouble("Scientists").setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.SCIENTIST) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [Species.MAGNEMITE, Species.GRIMER, Species.DROWZEE, Species.VOLTORB, Species.KOFFING], @@ -1095,124 +1103,124 @@ export const trainerConfigs: TrainerConfigs = { .setSpeciesPools( [Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP] ), - [TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(signatureSpecies["BROCK"],true, Type.ROCK).setBattleBgm("battle_kanto_gym"), - [TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MISTY"],false, Type.WATER).setBattleBgm("battle_kanto_gym"), - [TrainerType.LT_SURGE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LT_SURGE"],true, Type.ELECTRIC).setBattleBgm("battle_kanto_gym"), - [TrainerType.ERIKA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ERIKA"],false, Type.GRASS).setBattleBgm("battle_kanto_gym"), - [TrainerType.JANINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JANINE"],false, Type.POISON).setBattleBgm("battle_kanto_gym"), - [TrainerType.SABRINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["SABRINA"],false, Type.PSYCHIC).setBattleBgm("battle_kanto_gym"), - [TrainerType.BLAINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BLAINE"],true, Type.FIRE).setBattleBgm("battle_kanto_gym"), - [TrainerType.GIOVANNI]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GIOVANNI"],true, Type.DARK).setBattleBgm("battle_kanto_gym"), - [TrainerType.FALKNER]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FALKNER"],true, Type.FLYING).setBattleBgm("battle_johto_gym"), - [TrainerType.BUGSY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BUGSY"],true, Type.BUG).setBattleBgm("battle_johto_gym"), - [TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WHITNEY"],false, Type.NORMAL).setBattleBgm("battle_johto_gym"), - [TrainerType.MORTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MORTY"],true, Type.GHOST).setBattleBgm("battle_johto_gym"), - [TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHUCK"],true, Type.FIGHTING).setBattleBgm("battle_johto_gym"), - [TrainerType.JASMINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JASMINE"],false, Type.STEEL).setBattleBgm("battle_johto_gym"), - [TrainerType.PRYCE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["PRYCE"],true, Type.ICE).setBattleBgm("battle_johto_gym"), - [TrainerType.CLAIR]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLAIR"],false, Type.DRAGON).setBattleBgm("battle_johto_gym"), - [TrainerType.ROXANNE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROXANNE"],false, Type.ROCK).setBattleBgm("battle_hoenn_gym"), - [TrainerType.BRAWLY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRAWLY"],true, Type.FIGHTING).setBattleBgm("battle_hoenn_gym"), - [TrainerType.WATTSON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WATTSON"],true, Type.ELECTRIC).setBattleBgm("battle_hoenn_gym"), - [TrainerType.FLANNERY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FLANNERY"],false, Type.FIRE).setBattleBgm("battle_hoenn_gym"), - [TrainerType.NORMAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["NORMAN"],true, Type.NORMAL).setBattleBgm("battle_hoenn_gym"), - [TrainerType.WINONA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WINONA"],false, Type.FLYING).setBattleBgm("battle_hoenn_gym"), - [TrainerType.TATE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["TATE"],true, Type.PSYCHIC).setBattleBgm("battle_hoenn_gym").setHasDouble("tate_liza_double").setDoubleTrainerType(TrainerType.LIZA).setDoubleTitle("gym_leader_double"), - [TrainerType.LIZA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LIZA"],false, Type.PSYCHIC).setBattleBgm("battle_hoenn_gym").setHasDouble("liza_tate_double").setDoubleTrainerType(TrainerType.TATE).setDoubleTitle("gym_leader_double"), - [TrainerType.JUAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JUAN"],true, Type.WATER).setBattleBgm("battle_hoenn_gym"), - [TrainerType.ROARK]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROARK"],true, Type.ROCK).setBattleBgm("battle_sinnoh_gym"), - [TrainerType.GARDENIA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GARDENIA"],false, Type.GRASS).setBattleBgm("battle_sinnoh_gym"), - [TrainerType.MAYLENE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MAYLENE"],false, Type.FIGHTING).setBattleBgm("battle_sinnoh_gym"), - [TrainerType.CRASHER_WAKE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CRASHER_WAKE"],true, Type.WATER).setBattleBgm("battle_sinnoh_gym"), - [TrainerType.FANTINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FANTINA"],false, Type.GHOST).setBattleBgm("battle_sinnoh_gym"), - [TrainerType.BYRON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BYRON"],true, Type.STEEL).setBattleBgm("battle_sinnoh_gym"), - [TrainerType.CANDICE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CANDICE"],false, Type.ICE).setBattleBgm("battle_sinnoh_gym"), - [TrainerType.VOLKNER]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VOLKNER"],true, Type.ELECTRIC).setBattleBgm("battle_sinnoh_gym"), - [TrainerType.CILAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CILAN"],true, Type.GRASS), - [TrainerType.CHILI]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHILI"],true, Type.FIRE), - [TrainerType.CRESS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CRESS"],true, Type.WATER), - [TrainerType.CHEREN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHEREN"],true, Type.NORMAL), - [TrainerType.LENORA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LENORA"],false, Type.NORMAL), - [TrainerType.ROXIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROXIE"],false, Type.POISON), - [TrainerType.BURGH]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BURGH"],true, Type.BUG), - [TrainerType.ELESA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ELESA"],false, Type.ELECTRIC), - [TrainerType.CLAY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLAY"],true, Type.GROUND), - [TrainerType.SKYLA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["SKYLA"],false, Type.FLYING), - [TrainerType.BRYCEN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRYCEN"],true, Type.ICE), - [TrainerType.DRAYDEN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["DRAYDEN"],true, Type.DRAGON), - [TrainerType.MARLON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MARLON"],true, Type.WATER), - [TrainerType.VIOLA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VIOLA"],false, Type.BUG), - [TrainerType.GRANT]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GRANT"],true, Type.ROCK), - [TrainerType.KORRINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KORRINA"],false, Type.FIGHTING), - [TrainerType.RAMOS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["RAMOS"],true, Type.GRASS), - [TrainerType.CLEMONT]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLEMONT"],true, Type.ELECTRIC), - [TrainerType.VALERIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VALERIE"],false, Type.FAIRY), - [TrainerType.OLYMPIA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["OLYMPIA"],false, Type.PSYCHIC), - [TrainerType.WULFRIC]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WULFRIC"],true, Type.ICE), - [TrainerType.MILO]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MILO"],true, Type.GRASS), - [TrainerType.NESSA]: new TrainerConfig(++t).setName("Nessa").initForGymLeader(signatureSpecies["NESSA"],false, Type.WATER), - [TrainerType.KABU]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KABU"],true, Type.FIRE), - [TrainerType.BEA]: new TrainerConfig(++t).setName("Bea").initForGymLeader(signatureSpecies["BEA"],false, Type.FIGHTING), - [TrainerType.ALLISTER]: new TrainerConfig(++t).setName("Allister").initForGymLeader(signatureSpecies["ALLISTER"],true, Type.GHOST), - [TrainerType.OPAL]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["OPAL"],false, Type.FAIRY), - [TrainerType.BEDE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BEDE"],true, Type.FAIRY), - [TrainerType.GORDIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GORDIE"],true, Type.ROCK), - [TrainerType.MELONY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MELONY"],false, Type.ICE), - [TrainerType.PIERS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["PIERS"],true, Type.DARK).setHasDouble("piers_marnie_double").setDoubleTrainerType(TrainerType.MARNIE).setDoubleTitle("gym_leader_double"), - [TrainerType.MARNIE]: new TrainerConfig(++t).setName("Marnie").initForGymLeader(signatureSpecies["MARNIE"],false, Type.DARK).setHasDouble("marnie_piers_double").setDoubleTrainerType(TrainerType.PIERS).setDoubleTitle("gym_leader_double"), - [TrainerType.RAIHAN]: new TrainerConfig(++t).setName("Raihan").initForGymLeader(signatureSpecies["RAIHAN"],true, Type.DRAGON), - [TrainerType.KATY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KATY"],false, Type.BUG), - [TrainerType.BRASSIUS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRASSIUS"],true, Type.GRASS), - [TrainerType.IONO]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["IONO"],false, Type.ELECTRIC), - [TrainerType.KOFU]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KOFU"],true, Type.WATER), - [TrainerType.LARRY]: new TrainerConfig(++t).setName("Larry").initForGymLeader(signatureSpecies["LARRY"],true, Type.NORMAL), - [TrainerType.RYME]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["RYME"],false, Type.GHOST), - [TrainerType.TULIP]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["TULIP"],false, Type.PSYCHIC), - [TrainerType.GRUSHA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GRUSHA"],true, Type.ICE), + [TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(signatureSpecies["BROCK"],true, Type.ROCK).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MISTY"],false, Type.WATER).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.LT_SURGE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LT_SURGE"],true, Type.ELECTRIC).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.ERIKA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ERIKA"],false, Type.GRASS).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.JANINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JANINE"],false, Type.POISON).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.SABRINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["SABRINA"],false, Type.PSYCHIC).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.BLAINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BLAINE"],true, Type.FIRE).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.GIOVANNI]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GIOVANNI"],true, Type.DARK).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.FALKNER]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FALKNER"],true, Type.FLYING).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.BUGSY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BUGSY"],true, Type.BUG).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WHITNEY"],false, Type.NORMAL).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.MORTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MORTY"],true, Type.GHOST).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHUCK"],true, Type.FIGHTING).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.JASMINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JASMINE"],false, Type.STEEL).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.PRYCE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["PRYCE"],true, Type.ICE).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.CLAIR]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLAIR"],false, Type.DRAGON).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.ROXANNE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROXANNE"],false, Type.ROCK).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"), + [TrainerType.BRAWLY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRAWLY"],true, Type.FIGHTING).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"), + [TrainerType.WATTSON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WATTSON"],true, Type.ELECTRIC).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"), + [TrainerType.FLANNERY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FLANNERY"],false, Type.FIRE).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"), + [TrainerType.NORMAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["NORMAN"],true, Type.NORMAL).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"), + [TrainerType.WINONA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WINONA"],false, Type.FLYING).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"), + [TrainerType.TATE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["TATE"],true, Type.PSYCHIC).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym").setHasDouble("tate_liza_double").setDoubleTrainerType(TrainerType.LIZA).setDoubleTitle("gym_leader_double"), + [TrainerType.LIZA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LIZA"],false, Type.PSYCHIC).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym").setHasDouble("liza_tate_double").setDoubleTrainerType(TrainerType.TATE).setDoubleTitle("gym_leader_double"), + [TrainerType.JUAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JUAN"],true, Type.WATER).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"), + [TrainerType.ROARK]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROARK"],true, Type.ROCK).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.GARDENIA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GARDENIA"],false, Type.GRASS).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.MAYLENE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MAYLENE"],false, Type.FIGHTING).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.CRASHER_WAKE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CRASHER_WAKE"],true, Type.WATER).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.FANTINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FANTINA"],false, Type.GHOST).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.BYRON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BYRON"],true, Type.STEEL).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.CANDICE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CANDICE"],false, Type.ICE).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.VOLKNER]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VOLKNER"],true, Type.ELECTRIC).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.CILAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CILAN"],true, Type.GRASS).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.CHILI]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHILI"],true, Type.FIRE).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.CRESS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CRESS"],true, Type.WATER).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.CHEREN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHEREN"],true, Type.NORMAL).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.LENORA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LENORA"],false, Type.NORMAL).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.ROXIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROXIE"],false, Type.POISON).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.BURGH]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BURGH"],true, Type.BUG).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.ELESA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ELESA"],false, Type.ELECTRIC).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.CLAY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLAY"],true, Type.GROUND).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.SKYLA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["SKYLA"],false, Type.FLYING).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.BRYCEN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRYCEN"],true, Type.ICE).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.DRAYDEN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["DRAYDEN"],true, Type.DRAGON).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.MARLON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MARLON"],true, Type.WATER).setMixedBattleBgm("battle_unova_gym"), + [TrainerType.VIOLA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VIOLA"],false, Type.BUG).setMixedBattleBgm("battle_kalos_gym"), + [TrainerType.GRANT]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GRANT"],true, Type.ROCK).setMixedBattleBgm("battle_kalos_gym"), + [TrainerType.KORRINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KORRINA"],false, Type.FIGHTING).setMixedBattleBgm("battle_kalos_gym"), + [TrainerType.RAMOS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["RAMOS"],true, Type.GRASS).setMixedBattleBgm("battle_kalos_gym"), + [TrainerType.CLEMONT]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLEMONT"],true, Type.ELECTRIC).setMixedBattleBgm("battle_kalos_gym"), + [TrainerType.VALERIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VALERIE"],false, Type.FAIRY).setMixedBattleBgm("battle_kalos_gym"), + [TrainerType.OLYMPIA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["OLYMPIA"],false, Type.PSYCHIC).setMixedBattleBgm("battle_kalos_gym"), + [TrainerType.WULFRIC]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WULFRIC"],true, Type.ICE).setMixedBattleBgm("battle_kalos_gym"), + [TrainerType.MILO]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MILO"],true, Type.GRASS).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.NESSA]: new TrainerConfig(++t).setName("Nessa").initForGymLeader(signatureSpecies["NESSA"],false, Type.WATER).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.KABU]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KABU"],true, Type.FIRE).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.BEA]: new TrainerConfig(++t).setName("Bea").initForGymLeader(signatureSpecies["BEA"],false, Type.FIGHTING).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.ALLISTER]: new TrainerConfig(++t).setName("Allister").initForGymLeader(signatureSpecies["ALLISTER"],true, Type.GHOST).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.OPAL]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["OPAL"],false, Type.FAIRY).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.BEDE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BEDE"],true, Type.FAIRY).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.GORDIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GORDIE"],true, Type.ROCK).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.MELONY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MELONY"],false, Type.ICE).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.PIERS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["PIERS"],true, Type.DARK).setHasDouble("piers_marnie_double").setDoubleTrainerType(TrainerType.MARNIE).setDoubleTitle("gym_leader_double").setMixedBattleBgm("battle_galar_gym"), + [TrainerType.MARNIE]: new TrainerConfig(++t).setName("Marnie").initForGymLeader(signatureSpecies["MARNIE"],false, Type.DARK).setHasDouble("marnie_piers_double").setDoubleTrainerType(TrainerType.PIERS).setDoubleTitle("gym_leader_double").setMixedBattleBgm("battle_galar_gym"), + [TrainerType.RAIHAN]: new TrainerConfig(++t).setName("Raihan").initForGymLeader(signatureSpecies["RAIHAN"],true, Type.DRAGON).setMixedBattleBgm("battle_galar_gym"), + [TrainerType.KATY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KATY"],false, Type.BUG).setMixedBattleBgm("battle_paldea_gym"), + [TrainerType.BRASSIUS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRASSIUS"],true, Type.GRASS).setMixedBattleBgm("battle_paldea_gym"), + [TrainerType.IONO]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["IONO"],false, Type.ELECTRIC).setMixedBattleBgm("battle_paldea_gym"), + [TrainerType.KOFU]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KOFU"],true, Type.WATER).setMixedBattleBgm("battle_paldea_gym"), + [TrainerType.LARRY]: new TrainerConfig(++t).setName("Larry").initForGymLeader(signatureSpecies["LARRY"],true, Type.NORMAL).setMixedBattleBgm("battle_paldea_gym"), + [TrainerType.RYME]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["RYME"],false, Type.GHOST).setMixedBattleBgm("battle_paldea_gym"), + [TrainerType.TULIP]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["TULIP"],false, Type.PSYCHIC).setMixedBattleBgm("battle_paldea_gym"), + [TrainerType.GRUSHA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GRUSHA"],true, Type.ICE).setMixedBattleBgm("battle_paldea_gym"), - [TrainerType.LORELEI]: new TrainerConfig((t = TrainerType.LORELEI)).initForEliteFour(signatureSpecies["LORELEI"],false, Type.ICE), - [TrainerType.BRUNO]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["BRUNO"], true, Type.FIGHTING), - [TrainerType.AGATHA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AGATHA"], false,Type.GHOST), - [TrainerType.LANCE]: new TrainerConfig(++t).setName("Lance").initForEliteFour(signatureSpecies["LANCE"],true, Type.DRAGON), - [TrainerType.WILL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["WILL"],true, Type.PSYCHIC), - [TrainerType.KOGA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KOGA"], true, Type.POISON), - [TrainerType.KAREN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KAREN"],false, Type.DARK), - [TrainerType.SIDNEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SIDNEY"],true, Type.DARK), - [TrainerType.PHOEBE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["PHOEBE"],false, Type.GHOST), - [TrainerType.GLACIA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["GLACIA"],false, Type.ICE), - [TrainerType.DRAKE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAKE"],true, Type.DRAGON), - [TrainerType.AARON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AARON"],true, Type.BUG), - [TrainerType.BERTHA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["BERTHA"],false, Type.GROUND), - [TrainerType.FLINT]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["FLINT"],true, Type.FIRE), - [TrainerType.LUCIAN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LUCIAN"], true,Type.PSYCHIC), - [TrainerType.SHAUNTAL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SHAUNTAL"],false, Type.GHOST), - [TrainerType.MARSHAL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MARSHAL"],true, Type.FIGHTING), - [TrainerType.GRIMSLEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["GRIMSLEY"],true, Type.DARK), - [TrainerType.CAITLIN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["CAITLIN"],false, Type.PSYCHIC), - [TrainerType.MALVA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MALVA"], false,Type.FIRE), - [TrainerType.SIEBOLD]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SIEBOLD"], true,Type.WATER), - [TrainerType.WIKSTROM]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["WIKSTROM"],true, Type.STEEL), - [TrainerType.DRASNA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRASNA"],false, Type.DRAGON), - [TrainerType.HALA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["HALA"],true, Type.FIGHTING), - [TrainerType.MOLAYNE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MOLAYNE"],true, Type.STEEL), - [TrainerType.OLIVIA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["OLIVIA"],false, Type.ROCK), - [TrainerType.ACEROLA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["ACEROLA"],false, Type.GHOST), - [TrainerType.KAHILI]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KAHILI"],false, Type.FLYING), - [TrainerType.MARNIE_ELITE]: new TrainerConfig(++t).setName("Marnie").initForEliteFour(signatureSpecies["MARNIE_ELITE"],false, Type.DARK), - [TrainerType.NESSA_ELITE]: new TrainerConfig(++t).setName("Nessa").initForEliteFour(signatureSpecies["NESSA_ELITE"],false, Type.WATER), - [TrainerType.BEA_ELITE]: new TrainerConfig(++t).setName("Bea").initForEliteFour(signatureSpecies["BEA_ELITE"],false, Type.FIGHTING), - [TrainerType.ALLISTER_ELITE]: new TrainerConfig(++t).setName("Allister").initForEliteFour(signatureSpecies["ALLISTER_ELITE"],true, Type.GHOST), - [TrainerType.RAIHAN_ELITE]: new TrainerConfig(++t).setName("Raihan").initForEliteFour(signatureSpecies["RAIHAN_ELITE"],true, Type.DRAGON), - [TrainerType.RIKA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["RIKA"],false, Type.GROUND), - [TrainerType.POPPY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["POPPY"],false, Type.STEEL), - [TrainerType.LARRY_ELITE]: new TrainerConfig(++t).setName("Larry").initForEliteFour(signatureSpecies["LARRY_ELITE"],true, Type.NORMAL, Type.FLYING), - [TrainerType.HASSEL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["HASSEL"],true, Type.DRAGON), - [TrainerType.CRISPIN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["CRISPIN"],true, Type.FIRE), - [TrainerType.AMARYS]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AMARYS"],false, Type.STEEL), - [TrainerType.LACEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LACEY"],false, Type.FAIRY), - [TrainerType.DRAYTON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAYTON"],true, Type.DRAGON), + [TrainerType.LORELEI]: new TrainerConfig((t = TrainerType.LORELEI)).initForEliteFour(signatureSpecies["LORELEI"],false, Type.ICE).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.BRUNO]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["BRUNO"], true, Type.FIGHTING).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.AGATHA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AGATHA"], false,Type.GHOST).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.LANCE]: new TrainerConfig(++t).setName("Lance").initForEliteFour(signatureSpecies["LANCE"],true, Type.DRAGON).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), + [TrainerType.WILL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["WILL"],true, Type.PSYCHIC).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.KOGA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KOGA"], true, Type.POISON).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.KAREN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KAREN"],false, Type.DARK).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"), + [TrainerType.SIDNEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SIDNEY"],true, Type.DARK).setMixedBattleBgm("battle_hoenn_elite"), + [TrainerType.PHOEBE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["PHOEBE"],false, Type.GHOST).setMixedBattleBgm("battle_hoenn_elite"), + [TrainerType.GLACIA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["GLACIA"],false, Type.ICE).setMixedBattleBgm("battle_hoenn_elite"), + [TrainerType.DRAKE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAKE"],true, Type.DRAGON).setMixedBattleBgm("battle_hoenn_elite"), + [TrainerType.AARON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AARON"],true, Type.BUG).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.BERTHA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["BERTHA"],false, Type.GROUND).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.FLINT]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["FLINT"],true, Type.FIRE).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.LUCIAN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LUCIAN"], true,Type.PSYCHIC).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"), + [TrainerType.SHAUNTAL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SHAUNTAL"],false, Type.GHOST).setMixedBattleBgm("battle_unova_elite"), + [TrainerType.MARSHAL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MARSHAL"],true, Type.FIGHTING).setMixedBattleBgm("battle_unova_elite"), + [TrainerType.GRIMSLEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["GRIMSLEY"],true, Type.DARK).setMixedBattleBgm("battle_unova_elite"), + [TrainerType.CAITLIN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["CAITLIN"],false, Type.PSYCHIC).setMixedBattleBgm("battle_unova_elite"), + [TrainerType.MALVA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MALVA"], false,Type.FIRE).setMixedBattleBgm("battle_kalos_elite"), + [TrainerType.SIEBOLD]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SIEBOLD"], true,Type.WATER).setMixedBattleBgm("battle_kalos_elite"), + [TrainerType.WIKSTROM]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["WIKSTROM"],true, Type.STEEL).setMixedBattleBgm("battle_kalos_elite"), + [TrainerType.DRASNA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRASNA"],false, Type.DRAGON).setMixedBattleBgm("battle_kalos_elite"), + [TrainerType.HALA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["HALA"],true, Type.FIGHTING).setMixedBattleBgm("battle_alola_elite"), + [TrainerType.MOLAYNE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MOLAYNE"],true, Type.STEEL).setMixedBattleBgm("battle_alola_elite"), + [TrainerType.OLIVIA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["OLIVIA"],false, Type.ROCK).setMixedBattleBgm("battle_alola_elite"), + [TrainerType.ACEROLA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["ACEROLA"],false, Type.GHOST).setMixedBattleBgm("battle_alola_elite"), + [TrainerType.KAHILI]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KAHILI"],false, Type.FLYING).setMixedBattleBgm("battle_alola_elite"), + [TrainerType.MARNIE_ELITE]: new TrainerConfig(++t).setName("Marnie").initForEliteFour(signatureSpecies["MARNIE_ELITE"],false, Type.DARK).setMixedBattleBgm("battle_galar_elite"), + [TrainerType.NESSA_ELITE]: new TrainerConfig(++t).setName("Nessa").initForEliteFour(signatureSpecies["NESSA_ELITE"],false, Type.WATER).setMixedBattleBgm("battle_galar_elite"), + [TrainerType.BEA_ELITE]: new TrainerConfig(++t).setName("Bea").initForEliteFour(signatureSpecies["BEA_ELITE"],false, Type.FIGHTING).setMixedBattleBgm("battle_galar_elite"), + [TrainerType.ALLISTER_ELITE]: new TrainerConfig(++t).setName("Allister").initForEliteFour(signatureSpecies["ALLISTER_ELITE"],true, Type.GHOST).setMixedBattleBgm("battle_galar_elite"), + [TrainerType.RAIHAN_ELITE]: new TrainerConfig(++t).setName("Raihan").initForEliteFour(signatureSpecies["RAIHAN_ELITE"],true, Type.DRAGON).setMixedBattleBgm("battle_galar_elite"), + [TrainerType.RIKA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["RIKA"],false, Type.GROUND).setMixedBattleBgm("battle_paldea_elite"), + [TrainerType.POPPY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["POPPY"],false, Type.STEEL).setMixedBattleBgm("battle_paldea_elite"), + [TrainerType.LARRY_ELITE]: new TrainerConfig(++t).setName("Larry").initForEliteFour(signatureSpecies["LARRY_ELITE"],true, Type.NORMAL, Type.FLYING).setMixedBattleBgm("battle_paldea_elite"), + [TrainerType.HASSEL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["HASSEL"],true, Type.DRAGON).setMixedBattleBgm("battle_paldea_elite"), + [TrainerType.CRISPIN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["CRISPIN"],true, Type.FIRE).setMixedBattleBgm("battle_bb_elite"), + [TrainerType.AMARYS]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AMARYS"],false, Type.STEEL).setMixedBattleBgm("battle_bb_elite"), + [TrainerType.LACEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LACEY"],false, Type.FAIRY).setMixedBattleBgm("battle_bb_elite"), + [TrainerType.DRAYTON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAYTON"],true, Type.DRAGON).setMixedBattleBgm("battle_bb_elite"), - [TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(signatureSpecies["BLUE"],true).setBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double") + [TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(signatureSpecies["BLUE"],true).setBattleBgm("battle_kanto_champion").setMixedBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALAKAZAM], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) @@ -1220,7 +1228,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; p.generateAndPopulateMoveset(); })), - [TrainerType.RED]: new TrainerConfig(++t).initForChampion(signatureSpecies["RED"],true).setBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double") + [TrainerType.RED]: new TrainerConfig(++t).initForChampion(signatureSpecies["RED"],true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PIKACHU], TrainerSlot.TRAINER, true, p => { p.formIndex = 8; p.generateAndPopulateMoveset(); @@ -1229,7 +1237,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; p.generateAndPopulateMoveset(); })), - [TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(signatureSpecies["LANCE_CHAMPION"],true).setBattleBgm("battle_johto_champion") + [TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(signatureSpecies["LANCE_CHAMPION"],true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.AERODACTYL], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) @@ -1237,7 +1245,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; p.generateAndPopulateMoveset(); })), - [TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(signatureSpecies["STEVEN"],true).setBattleBgm("battle_hoenn_champion").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double") + [TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(signatureSpecies["STEVEN"],true).setBattleBgm("battle_hoenn_champion").setMixedBattleBgm("battle_hoenn_champion").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SKARMORY], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) @@ -1245,7 +1253,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; p.generateAndPopulateMoveset(); })), - [TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(signatureSpecies["WALLACE"],true).setBattleBgm("battle_hoenn_champion").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double") + [TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(signatureSpecies["WALLACE"],true).setBattleBgm("battle_hoenn_champion").setMixedBattleBgm("battle_hoenn_champion").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drizzle p.generateAndPopulateMoveset(); @@ -1254,7 +1262,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; p.generateAndPopulateMoveset(); })), - [TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(signatureSpecies["CYNTHIA"],false).setBattleBgm("battle_sinnoh_champion") + [TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(signatureSpecies["CYNTHIA"],false).setBattleBgm("battle_sinnoh_champion").setMixedBattleBgm("battle_sinnoh_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SPIRITOMB], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) @@ -1262,11 +1270,11 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; p.generateAndPopulateMoveset(); })), - [TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(signatureSpecies["ALDER"],true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder") + [TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(signatureSpecies["ALDER"],true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder").setMixedBattleBgm("battle_champion_alder") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BOUFFALANT, Species.BRAVIARY], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })), - [TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(signatureSpecies["IRIS"],false).setBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double") + [TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(signatureSpecies["IRIS"],false).setBattleBgm("battle_champion_iris").setMixedBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DRUDDIGON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) @@ -1274,7 +1282,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; p.generateAndPopulateMoveset(); })), - [TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(signatureSpecies["DIANTHA"],false) + [TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(signatureSpecies["DIANTHA"],false).setMixedBattleBgm("battle_kalos_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GOURGEIST], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) @@ -1282,11 +1290,11 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; p.generateAndPopulateMoveset(); })), - [TrainerType.HAU]: new TrainerConfig(++t).initForChampion(signatureSpecies["HAU"],true) + [TrainerType.HAU]: new TrainerConfig(++t).initForChampion(signatureSpecies["HAU"],true).setMixedBattleBgm("battle_alola_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALOLA_RAICHU], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })), - [TrainerType.LEON]: new TrainerConfig(++t).initForChampion(signatureSpecies["LEON"],true) + [TrainerType.LEON]: new TrainerConfig(++t).initForChampion(signatureSpecies["LEON"],true).setMixedBattleBgm("battle_galar_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.RILLABOOM, Species.CINDERACE, Species.INTELEON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) @@ -1294,15 +1302,16 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 3; p.generateAndPopulateMoveset(); })), - [TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(signatureSpecies["GEETA"],false) + [TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(signatureSpecies["GEETA"],false).setMixedBattleBgm("battle_champion_geeta") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GLIMMORA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })), - [TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(signatureSpecies["NEMONA"],false) + [TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(signatureSpecies["NEMONA"],false).setMixedBattleBgm("battle_champion_nemona") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { + p.formIndex = 0; // Midday form p.generateAndPopulateMoveset(); })), - [TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(signatureSpecies["KIERAN"],true) + [TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(signatureSpecies["KIERAN"],true).setMixedBattleBgm("battle_champion_kieran") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.POLIWRATH, Species.POLITOED], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })), diff --git a/src/data/trainer-names.ts b/src/data/trainer-names.ts index 0aa5bb594d4..5cd6850fba0 100644 --- a/src/data/trainer-names.ts +++ b/src/data/trainer-names.ts @@ -60,6 +60,7 @@ const trainerNameConfigs: TrainerNameConfigs = { [TrainerType.RICH]: new TrainerNameConfig(TrainerType.RICH, "Gentleman").hasGenderVariant("Madame"), [TrainerType.RICH_KID]: new TrainerNameConfig(TrainerType.RICH_KID, "Rich_Boy").hasGenderVariant("Lady"), [TrainerType.ROUGHNECK]: new TrainerNameConfig(TrainerType.ROUGHNECK), + [TrainerType.SAILOR]: new TrainerNameConfig(TrainerType.SAILOR), [TrainerType.SCIENTIST]: new TrainerNameConfig(TrainerType.SCIENTIST), [TrainerType.SMASHER]: new TrainerNameConfig(TrainerType.SMASHER), [TrainerType.SNOW_WORKER]: new TrainerNameConfig(TrainerType.SNOW_WORKER, "Worker"), @@ -77,7 +78,7 @@ export const trainerNamePools = { [TrainerType.ACE_TRAINER]: [["Aaron","Allen","Blake","Brian","Gaven","Jake","Kevin","Mike","Nick","Paul","Ryan","Sean","Darin","Albert","Berke","Clyde","Edgar","George","Leroy","Owen","Parker","Randall","Ruben","Samuel","Vincent","Warren","Wilton","Zane","Alfred","Braxton","Felix","Gerald","Jonathan","Leonel","Marcel","Mitchell","Quincy","Roderick","Colby","Rolando","Yuji","Abel","Anton","Arthur","Cesar","Dalton","Dennis","Ernest","Garrett","Graham","Henry","Isaiah","Jonah","Jose","Keenan","Micah","Omar","Quinn","Rodolfo","Saul","Sergio","Skylar","Stefan","Zachery","Alton","Arabella","Bonita","Cal","Cody","French","Kobe","Paulo","Shaye","Austin","Beckett","Charlie","Corky","David","Dwayne","Elmer","Jesse","Jared","Johan","Jordan","Kipp","Lou","Terry","Tom","Webster","Billy","Doyle","Enzio","Geoff","Grant","Kelsey","Miguel","Pierce","Ray","Santino","Shel","Adelbert","Bence","Emil","Evan","Mathis","Maxim","Neil","Rico","Robbie","Theo","Viktor","Benedict","Cornelius","Hisato","Leopold","Neville","Vito","Chase","Cole","Hiroshi","Jackson","Jim","Kekoa","Makana","Yuki","Elwood","Seth","Alvin","Arjun","Arnold","Cameron","Carl","Carlton","Christopher","Dave","Dax","Dominic","Edmund","Finn","Fred","Garret","Grayson","Jace","Jaxson","Jay","Jirard","Johnson","Kayden","Kite","Louis","Mac","Marty","Percy","Raymond","Ronnie","Satch","Tim","Zach","Conner","Vince","Bedro","Boda","Botan","Daras","Dury","Herton","Rewn","Stum","Tock","Trilo","Berki","Cruik","Dazon","Desid","Dillot","Farfin","Forgon","Hebel","Morfon","Moril","Shadd","Vanhub","Bardo","Carben","Degin","Gorps","Klept","Lask","Malex","Mopar","Niled","Noxon","Teslor","Tetil"],["Beth","Carol","Cybil","Emma","Fran","Gwen","Irene","Jenn","Joyce","Kate","Kelly","Lois","Lola","Megan","Quinn","Reena","Cara","Alexa","Brooke","Caroline","Elaine","Hope","Jennifer","Jody","Julie","Lori","Mary","Michelle","Shannon","Wendy","Alexia","Alicia","Athena","Carolina","Cristin","Darcy","Dianne","Halle","Jazmyn","Katelynn","Keira","Marley","Allyson","Kathleen","Naomi","Alyssa","Ariana","Brandi","Breanna","Brenda","Brenna","Catherine","Clarice","Dana","Deanna","Destiny","Jamie","Jasmin","Kassandra","Laura","Maria","Mariah","Maya","Meagan","Mikayla","Monique","Natasha","Olivia","Sandra","Savannah","Sydney","Moira","Piper","Salma","Allison","Beverly","Cathy","Cheyenne","Clara","Dara","Eileen","Glinda","Junko","Lena","Lucille","Mariana","Olwen","Shanta","Stella","Angi","Belle","Chandra","Cora","Eve","Jacqueline","Jeanne","Juliet","Kathrine","Layla","Lucca","Melina","Miki","Nina","Sable","Shelly","Summer","Trish","Vicki","Alanza","Cordelia","Hilde","Imelda","Michele","Mireille","Claudia","Constance","Harriet","Honor","Melba","Portia","Alexis","Angela","Karla","Lindsey","Tori","Sheri","Jada","Kailee","Amanda","Annie","Kindra","Kyla","Sofia","Yvette","Becky","Flora","Gloria","Buna","Ferda","Lehan","Liqui","Lomen","Neira","Atilo","Detta","Gilly","Gosney","Levens","Moden","Rask","Rateis","Rosno","Tynan","Veron","Zoel","Cida","Dibsin","Dodin","Ebson","Equin","Flostin","Gabsen","Halsion","Hileon","Quelor","Rapeel","Roze","Tensin"]], [TrainerType.ARTIST]: [["Ismael","William","Horton","Pierre","Zach","Gough","Salvador","Vincent","Duncan"],["Georgia"]], [TrainerType.BACKERS]: [["Alf & Fred","Hawk & Dar","Joe & Ross","Les & Web","Masa & Yas","Stu & Art"],["Ai & Ciel","Ami & Eira","Cam & Abby","Fey & Sue","Kat & Phae","Kay & Ali","Ava & Aya","Cleo & Rio","May & Mal"]], - [TrainerType.BACKPACKER]: [["Alexander","Carlos","Herman","Jerome","Keane","Kelsey","Kiyo","Michael","Nate","Peter","Sam","Stephen","Talon","Terrance","Toru","Waylon","Boone","Clifford","Ivan","Kendall","Lowell","Randall","Reece","Roland","Shane","Walt","Farid","Heike","Joren","Lane","Roderick","Darnell","Deon","Emory","Graeme","Grayson","Ashley","Mikiko","Kiana","Perdy","Maria","Yuho","Peren","Barbara","Diane","Ruth","Aitor","Alex","Arturo","Asier","Jaime","Jonathan","Julio","Kevin","Kosuke","Lander","Markel","Mateo","Nil","Pau","Samuel"],["Anna","Corin","Elaine","Emi","Jill","Kumiko","Liz","Lois","Lora","Molly","Patty","Ruth","Vicki","Annie","Blossom","Clara","Eileen","Mae","Myra","Rachel","Tami"]], + [TrainerType.BACKPACKER]: [["Alexander","Carlos","Herman","Jerome","Keane","Kelsey","Kiyo","Michael","Nate","Peter","Sam","Stephen","Talon","Terrance","Toru","Waylon","Boone","Clifford","Ivan","Kendall","Lowell","Randall","Reece","Roland","Shane","Walt","Farid","Heike","Joren","Lane","Roderick","Darnell","Deon","Emory","Graeme","Grayson","Aitor","Alex","Arturo","Asier","Jaime","Jonathan","Julio","Kevin","Kosuke","Lander","Markel","Mateo","Nil","Pau","Samuel"],["Anna","Corin","Elaine","Emi","Jill","Kumiko","Liz","Lois","Lora","Molly","Patty","Ruth","Vicki","Annie","Blossom","Clara","Eileen","Mae","Myra","Rachel","Tami","Ashley","Mikiko","Kiana","Perdy","Maria","Yuho","Peren","Barbara","Diane"]], [TrainerType.BAKER]: ["Chris","Jenn","Lilly"], [TrainerType.BEAUTY]: ["Cassie","Julia","Olivia","Samantha","Valerie","Victoria","Bridget","Connie","Jessica","Johanna","Melissa","Sheila","Shirley","Tiffany","Namiko","Thalia","Grace","Lola","Lori","Maura","Tamia","Cyndy","Devon","Gabriella","Harley","Lindsay","Nicola","Callie","Charlotte","Kassandra","December","Fleming","Nikola","Aimee","Anais","Brigitte","Cassandra","Andrea","Brittney","Carolyn","Krystal","Alexis","Alice","Aina","Anya","Arianna","Aubrey","Beverly","Camille","Beauty","Evette","Hansol","Haruka","Jill","Jo","Lana","Lois","Lucy","Mai","Nickie","Nicole","Prita","Rose","Shelly","Suzy","Tessa","Anita","Alissa","Rita","Cudsy","Eloff","Miru","Minot","Nevah","Niven","Ogoin"], [TrainerType.BIKER]: ["Charles","Dwayne","Glenn","Harris","Joel","Riley","Zeke","Alex","Billy","Ernest","Gerald","Hideo","Isaac","Jared","Jaren","Jaxon","Jordy","Lao","Lukas","Malik","Nikolas","Ricardo","Ruben","Virgil","William","Aiden","Dale","Dan","Jacob","Markey","Reese","Teddy","Theron","Jeremy","Morgann","Phillip","Philip","Stanley","Dillon"], @@ -92,7 +93,7 @@ export const trainerNamePools = { [TrainerType.FISHERMAN]: ["Andre","Arnold","Barney","Chris","Edgar","Henry","Jonah","Justin","Kyle","Martin","Marvin","Ralph","Raymond","Scott","Stephen","Wilton","Tully","Andrew","Barny","Carter","Claude","Dale","Elliot","Eugene","Ivan","Ned","Nolan","Roger","Ronald","Wade","Wayne","Darian","Kai","Chip","Hank","Kaden","Tommy","Tylor","Alec","Brett","Cameron","Cody","Cole","Cory","Erick","George","Joseph","Juan","Kenneth","Luc","Miguel","Travis","Walter","Zachary","Josh","Gideon","Kyler","Liam","Murphy","Bruce","Damon","Devon","Hubert","Jones","Lydon","Mick","Pete","Sean","Sid","Vince","Bucky","Dean","Eustace","Kenzo","Leroy","Mack","Ryder","Ewan","Finn","Murray","Seward","Shad","Wharton","Finley","Fisher","Fisk","River","Sheaffer","Timin","Carl","Ernest","Hal","Herbert","Hisato","Mike","Vernon","Harriet","Marina","Chase"], [TrainerType.GUITARIST]: ["Anna","Beverly","January","Tina","Alicia","Claudia","Julia","Lidia","Mireia","Noelia","Sara","Sheila","Tatiana"], [TrainerType.HARLEQUIN]: ["Charley","Ian","Jack","Kerry","Louis","Pat","Paul","Rick","Anders","Clarence","Gary"], - [TrainerType.HIKER]: ["Anthony","Bailey","Benjamin","Daniel","Erik","Jim","Kenny","Leonard","Michael","Parry","Phillip","Russell","Sidney","Tim","Timothy","Alan","Brice","Clark","Eric","Lenny","Lucas","Mike","Trent","Devan","Eli","Marc","Sawyer","Allen","Daryl","Dudley","Earl","Franklin","Jeremy","Marcos","Nob","Oliver","Wayne","Alexander","Damon","Jonathan","Justin","Kevin","Lorenzo","Louis","Maurice","Nicholas","Reginald","Robert","Theodore","Bruce","Clarke","Devin","Dwight","Edwin","Eoin","Noland","Russel","Andy","Bret","Darrell","Gene","Hardy","Hugh","Jebediah","Jeremiah","Kit","Neil","Terrell","Don","Doug","Hunter","Jared","Jerome","Keith","Manuel","Markus","Otto","Shelby","Stephen","Teppei","Tobias","Wade","Zaiem","Aaron","Alain","Bergin","Bernard","Brent","Corwin","Craig","Delmon","Dunstan","Orestes","Ross","Davian","Calhoun","David","Gabriel","Ryan","Thomas","Travis","Zachary","Anuhea","Barnaby","Claus","Collin","Colson","Dexter","Dillan","Eugine","Farkas","Hisato","Julius","Kenji","Irwin","Lionel","Paul","Richter","Valentino","Donald","Douglas","Kevyn","Angela","Carla","Celia","Daniela","Estela","Fatima","Helena","Leire","Lucia","Luna","Manuela","Mar","Marina","Miyu","Nancy","Nerea","Paula","Rocio","Yanira","Chester"], + [TrainerType.HIKER]: ["Anthony","Bailey","Benjamin","Daniel","Erik","Jim","Kenny","Leonard","Michael","Parry","Phillip","Russell","Sidney","Tim","Timothy","Alan","Brice","Clark","Eric","Lenny","Lucas","Mike","Trent","Devan","Eli","Marc","Sawyer","Allen","Daryl","Dudley","Earl","Franklin","Jeremy","Marcos","Nob","Oliver","Wayne","Alexander","Damon","Jonathan","Justin","Kevin","Lorenzo","Louis","Maurice","Nicholas","Reginald","Robert","Theodore","Bruce","Clarke","Devin","Dwight","Edwin","Eoin","Noland","Russel","Andy","Bret","Darrell","Gene","Hardy","Hugh","Jebediah","Jeremiah","Kit","Neil","Terrell","Don","Doug","Hunter","Jared","Jerome","Keith","Manuel","Markus","Otto","Shelby","Stephen","Teppei","Tobias","Wade","Zaiem","Aaron","Alain","Bergin","Bernard","Brent","Corwin","Craig","Delmon","Dunstan","Orestes","Ross","Davian","Calhoun","David","Gabriel","Ryan","Thomas","Travis","Zachary","Anuhea","Barnaby","Claus","Collin","Colson","Dexter","Dillan","Eugine","Farkas","Hisato","Julius","Kenji","Irwin","Lionel","Paul","Richter","Valentino","Donald","Douglas","Kevyn","Chester"], //["Angela","Carla","Celia","Daniela","Estela","Fatima","Helena","Leire","Lucia","Luna","Manuela","Mar","Marina","Miyu","Nancy","Nerea","Paula","Rocio","Yanira"] [TrainerType.HOOLIGANS]: ["Jim & Cas","Rob & Sal"], [TrainerType.HOOPSTER]: ["Bobby","John","Lamarcus","Derrick","Nicolas"], [TrainerType.INFIELDER]: ["Alex","Connor","Todd"], @@ -111,6 +112,7 @@ export const trainerNamePools = { [TrainerType.RICH]: [["Alfred","Edward","Gregory","Preston","Thomas","Tucker","Walter","Clifford","Everett","Micah","Nate","Pierre","Terrance","Arthur","Brooks","Emanuel","Lamar","Jeremy","Leonardo","Milton","Frederic","Renaud","Robert","Yan","Daniel","Sheldon","Stonewall","Gerald","Ronald","Smith","Stanley","Reginald","Orson","Wilco","Caden","Glenn"],["Rebecca","Reina","Cassandra","Emilia","Grace","Marian","Elizabeth","Kathleen","Sayuri","Caroline","Judy"]], [TrainerType.RICH_KID]: [["Garret","Winston","Dawson","Enrique","Jason","Roman","Trey","Liam","Anthony","Brad","Cody","Manuel","Martin","Pierce","Rolan","Keenan","Filbert","Antoin","Cyus","Diek","Dugo","Flitz","Jurek","Lond","Perd","Quint","Basto","Benit","Brot","Denc","Guyit","Marcon","Perc","Puros","Roex","Sainz","Symin","Tark","Venak"],["Anette","Brianna","Cindy","Colleen","Daphne","Elizabeth","Naomi","Sarah","Charlotte","Gillian","Jacki","Lady","Melissa","Celeste","Colette","Elizandra","Isabel","Lynette","Magnolia","Sophie","Lina","Dulcie","Auro","Brin","Caril","Eloos","Gwin","Illa","Kowly","Rima","Ristin","Vesey","Brena","Deasy","Denslon","Kylet","Nemi","Rene","Sanol","Stouner","Sturk","Talmen","Zoila"]], [TrainerType.ROUGHNECK]: ["Camron","Corey","Gabriel","Isaiah","Jamal","Koji","Luke","Paxton","Raul","Zeek","Kirby","Chance","Dave","Fletcher","Johnny","Reese","Joey","Ricky","Silvester","Martin"], + [TrainerType.SAILOR]: ["Alberto","Bost","Brennan","Brenden","Claude","Cory","Damian","Dirk","Duncan","Dwayne","Dylan","Eddie","Edmond","Elijah","Ernest","Eugene","Garrett","Golos","Gratin","Grestly","Harry","Hols","Hudson","Huey","Jebol","Jeff","Leonald","Luther","Kelvin","Kenneth","Kent","Knook","Marc","Mifis","Monar","Morkor","Ordes","Oxlin","Parker","Paul","Philip","Roberto","Samson","Skyler","Stanly","Tebu","Terrell","Trevor","Yasu","Zachariah"], [TrainerType.SCIENTIST]: [["Jed","Marc","Mitch","Rich","Ross","Beau","Braydon","Connor","Ed","Ivan","Jerry","Jose","Joshua","Parker","Rodney","Taylor","Ted","Travis","Zackery","Darrius","Emilio","Fredrick","Shaun","Stefano","Travon","Daniel","Garett","Gregg","Linden","Lowell","Trenton","Dudley","Luke","Markus","Nathan","Orville","Randall","Ron","Ronald","Simon","Steve","William","Franklin","Clarke","Jacques","Terrance","Ernst","Justus","Ikaika","Jayson","Kyle","Reid","Tyrone","Adam","Albert","Alphonse","Cory","Donnie","Elton","Francis","Gordon","Herbert","Humphrey","Jordan","Julian","Keaton","Levi","Melvin","Murray","West","Craig","Coren","Dubik","Kotan","Lethco","Mante","Mort","Myron","Odlow","Ribek","Roeck","Vogi","Vonder","Zogo","Doimo","Doton","Durel","Hildon","Kukla","Messa","Nanot","Platen","Raburn","Reman","Acrod","Coffy","Elrok","Foss","Hardig","Hombol","Hospel","Kaller","Klots","Krilok","Limar","Loket","Mesak","Morbit","Newin","Orill","Tabor","Tekot"],["Blythe","Chan","Kathrine","Marie","Maria","Naoko","Samantha","Satomi","Shannon","Athena","Caroline","Lumi","Lumina","Marissa","Sonia"]], [TrainerType.SMASHER]: ["Aspen","Elena","Mari","Amy","Lizzy"], [TrainerType.SNOW_WORKER]: [["Braden","Brendon","Colin","Conrad","Dillan","Gary","Gerardo","Holden","Jackson","Mason","Quentin","Willy","Noel","Arnold","Brady","Brand","Cairn","Cliff","Don","Eddie","Felix","Filipe","Glenn","Gus","Heath","Matthew","Patton","Rich","Rob","Ryan","Scott","Shelby","Sterling","Tyler","Victor","Zack","Friedrich","Herman","Isaac","Leo","Maynard","Mitchell","Morgann","Nathan","Niel","Pasqual","Paul","Tavarius","Tibor","Dimitri","Narek","Yusif","Frank","Jeff","Vaclav","Ovid","Francis","Keith","Russel","Sangon","Toway","Bomber","Chean","Demit","Hubor","Kebile","Laber","Ordo","Retay","Ronix","Wagel","Dobit","Kaster","Lobel","Releo","Saken","Rustix"],["Georgia","Sandra","Yvonne"]], diff --git a/src/data/type.ts b/src/data/type.ts index b2bf8117249..c92416afca9 100644 --- a/src/data/type.ts +++ b/src/data/type.ts @@ -501,6 +501,52 @@ export function getTypeDamageMultiplier(attackType: integer, defType: integer): } } +/** + * Retrieve the color corresponding to a specific damage multiplier + * @returns A color or undefined if the default color should be used + */ +export function getTypeDamageMultiplierColor(multiplier: TypeDamageMultiplier, side: "defense" | "offense"): string | undefined { + if (side === "offense") { + switch (multiplier) { + case 0: + return "#929292"; + case 0.125: + return "#FF5500"; + case 0.25: + return "#FF7400"; + case 0.5: + return "#FE8E00"; + case 1: + return undefined; + case 2: + return "#4AA500"; + case 4: + return "#4BB400"; + case 8: + return "#52C200"; + } + } else if (side === "defense") { + switch (multiplier) { + case 0: + return "#B1B100"; + case 0.125: + return "#2DB4FF"; + case 0.25: + return "#00A4FF"; + case 0.5: + return "#0093FF"; + case 1: + return undefined; + case 2: + return "#FE8E00"; + case 4: + return "#FF7400"; + case 8: + return "#FF5500"; + } + } +} + export function getTypeRgb(type: Type): [ integer, integer, integer ] { switch (type) { case Type.NORMAL: diff --git a/src/enums/exp-notification.ts b/src/enums/exp-notification.ts new file mode 100644 index 00000000000..b7f50814d3a --- /dev/null +++ b/src/enums/exp-notification.ts @@ -0,0 +1,11 @@ +/** + * Determines exp notification style. + * - Default - the normal exp gain display, nothing changed + * - Only level up - we display the level up in the small frame instead of a message + * - Skip - no level up frame nor message +*/ +export enum ExpNotification { + DEFAULT, + ONLY_LEVEL_UP, + SKIP +} diff --git a/src/evolution-phase.ts b/src/evolution-phase.ts index 29382807ccb..c7986f6664f 100644 --- a/src/evolution-phase.ts +++ b/src/evolution-phase.ts @@ -531,6 +531,11 @@ export class EvolutionPhase extends Phase { } export class EndEvolutionPhase extends Phase { + + constructor(scene: BattleScene) { + super(scene); + } + start() { super.start(); diff --git a/src/field/arena.ts b/src/field/arena.ts index 6999eb39785..d34cd2c9bea 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -545,7 +545,7 @@ export class Arena { this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args); } - addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, targetIndex?: BattlerIndex): boolean { + addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, quiet: boolean = false, targetIndex?: BattlerIndex): boolean { const existingTag = this.getTagOnSide(tagType, side); if (existingTag) { existingTag.onOverlap(this); @@ -554,7 +554,7 @@ export class Arena { const newTag = getArenaTag(tagType, turnCount || 0, sourceMove, sourceId, targetIndex, side); this.tags.push(newTag); - newTag.onAdd(this); + newTag.onAdd(this, quiet); this.eventTarget.dispatchEvent(new TagAddedEvent(newTag.tagType, newTag.side, newTag.turnCount)); @@ -600,10 +600,10 @@ export class Arena { return !!tag; } - removeTagOnSide(tagType: ArenaTagType, side: ArenaTagSide): boolean { + removeTagOnSide(tagType: ArenaTagType, side: ArenaTagSide, quiet: boolean = false): boolean { const tag = this.getTagOnSide(tagType, side); if (tag) { - tag.onRemove(this); + tag.onRemove(this, quiet); this.tags.splice(this.tags.indexOf(tag), 1); this.eventTarget.dispatchEvent(new TagRemovedEvent(tag.tagType, tag.side, tag.turnCount)); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 285583bd05a..9ac45c4c299 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -4,7 +4,7 @@ import { Variant, VariantSet, variantColorCache } from "#app/data/variant"; import { variantData } from "#app/data/variant"; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "../ui/battle-info"; import { Moves } from "../data/enums/moves"; -import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, MoveFlags } from "../data/move"; +import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, VariableMoveTypeAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, MoveFlags } from "../data/move"; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species"; import * as Utils from "../utils"; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type"; @@ -27,7 +27,7 @@ import { TempBattleStat } from "../data/temp-battle-stat"; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from "../data/arena-tag"; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr } from "../data/ability"; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, MoveTypeChangeAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr } from "../data/ability"; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from "../system/pokemon-data"; import { BattlerIndex } from "../battle"; @@ -48,6 +48,7 @@ import { BerryType } from "../data/enums/berry-type"; import i18next from "../plugins/i18n"; import { speciesEggMoves } from "../data/egg-moves"; import { ModifierTier } from "../modifier/modifier-tier"; +import { applyChallenges, ChallengeType } from "#app/data/challenge.js"; export enum FieldPosition { CENTER, @@ -266,11 +267,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return !this.hp && (!checkStatus || this.status?.effect === StatusEffect.FAINT); } + /** + * Check if this pokemon is both not fainted and allowed to be in battle. + * This is frequently a better alternative to {@link isFainted} + * @returns {boolean} True if pokemon is allowed in battle + */ + isAllowedInBattle(): boolean { + const challengeAllowed = new Utils.BooleanHolder(true); + applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed); + return !this.isFainted() && challengeAllowed.value; + } + isActive(onField?: boolean): boolean { if (!this.scene) { return false; } - return !this.isFainted() && !!this.scene && (!onField || this.isOnField()); + return this.isAllowedInBattle() && !!this.scene && (!onField || this.isOnField()); } getDexAttr(): bigint { @@ -845,11 +857,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!ignoreOverride && this.summonData?.types) { this.summonData.types.forEach(t => types.push(t)); } else { - const speciesForm = this.getSpeciesForm(); + const speciesForm = this.getSpeciesForm(ignoreOverride); types.push(speciesForm.type1); - const fusionSpeciesForm = this.getFusionSpeciesForm(); + const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride); if (fusionSpeciesForm) { if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== speciesForm.type1) { types.push(fusionSpeciesForm.type2); @@ -885,8 +897,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return types; } - isOfType(type: Type, forDefend: boolean = false): boolean { - return !!this.getTypes(true, forDefend).find(t => t === type); + isOfType(type: Type, includeTeraType: boolean = true, forDefend: boolean = false, ignoreOverride?: boolean): boolean { + return !!this.getTypes(includeTeraType, forDefend, ignoreOverride).some(t => t === type); } /** @@ -1054,13 +1066,26 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } isGrounded(): boolean { - return !this.isOfType(Type.FLYING, true) && !this.hasAbility(Abilities.LEVITATE); + return !this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE); } - getAttackMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier { - const typeless = move.getMove().hasAttr(TypelessAttr); - const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.getMove().type, source)); + /** + * @returns The type damage multiplier or undefined if it's a status move + */ + getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier | undefined { + if (move.getMove().category === MoveCategory.STATUS) { + return undefined; + } + + return this.getAttackMoveEffectiveness(source, move); + } + + getAttackMoveEffectiveness(source: Pokemon, pokemonMove: PokemonMove): TypeDamageMultiplier { + const move = pokemonMove.getMove(); + const typeless = move.hasAttr(TypelessAttr); + const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.type, source)); const cancelled = new Utils.BooleanHolder(false); + applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier); if (!typeless) { applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true); } @@ -1070,7 +1095,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return (!cancelled.value ? typeMultiplier.value : 0) as TypeDamageMultiplier; } - getAttackTypeEffectiveness(moveType: Type, source?: Pokemon): TypeDamageMultiplier { + getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false): TypeDamageMultiplier { if (moveType === Type.STELLAR) { return this.isTerastallized() ? 2 : 1; } @@ -1089,7 +1114,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier; // Handle strong winds lowering effectiveness of types super effective against pure flying - if (this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && multiplier >= 2 && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) { + if (!ignoreStrongWinds && this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && multiplier >= 2 && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) { multiplier /= 2; } return multiplier; @@ -1575,11 +1600,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.battleInfo.updateInfo(this, instant); } + /** + * Show or hide the type effectiveness multiplier window + * Passing undefined will hide the window + */ + updateEffectiveness(effectiveness?: string) { + this.battleInfo.updateEffectiveness(effectiveness); + } + toggleStats(visible: boolean): void { this.battleInfo.toggleStats(visible); } + toggleFlyout(visible: boolean): void { - this.battleInfo.flyoutMenu?.toggleFlyout(visible); + this.battleInfo.toggleFlyout(visible); } addExp(exp: integer) { @@ -1620,9 +1654,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return (this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.getFieldIndex() ? 0 : 1]; } - apply(source: Pokemon, battlerMove: PokemonMove): HitResult { + apply(source: Pokemon, move: Move): HitResult { let result: HitResult; - const move = battlerMove.getMove(); const damage = new Utils.NumberHolder(0); const defendingSidePlayField = this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField(); @@ -1630,19 +1663,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory); const moveCategory = variableCategory.value as MoveCategory; - const variableType = new Utils.IntegerHolder(move.type); const typeChangeMovePowerMultiplier = new Utils.NumberHolder(1); - applyMoveAttrs(VariableMoveTypeAttr, source, this, move, variableType); - // 2nd argument is for MoveTypeChangePowerMultiplierAbAttr - applyAbAttrs(VariableMoveTypeAbAttr, source, null, variableType, typeChangeMovePowerMultiplier); - applyPreAttackAbAttrs(MoveTypeChangeAttr, source, this, battlerMove, variableType, typeChangeMovePowerMultiplier); - const type = variableType.value as Type; + applyMoveAttrs(VariableMoveTypeAttr, source, this, move); + applyPreAttackAbAttrs(MoveTypeChangeAttr, source, this, move, typeChangeMovePowerMultiplier); const types = this.getTypes(true, true); const cancelled = new Utils.BooleanHolder(false); const typeless = move.hasAttr(TypelessAttr); const typeMultiplier = new Utils.NumberHolder(!typeless && (moveCategory !== MoveCategory.STATUS || move.getAttrs(StatusMoveTypeImmunityAttr).find(attr => types.includes(attr.immuneType))) - ? this.getAttackTypeEffectiveness(type, source) + ? this.getAttackTypeEffectiveness(move.type, source) : 1); applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier); if (typeless) { @@ -1667,44 +1696,44 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const isPhysical = moveCategory === MoveCategory.PHYSICAL; const power = new Utils.NumberHolder(move.power); const sourceTeraType = source.getTeraType(); - if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === type && power.value < 60 && move.priority <= 0 && !move.hasAttr(MultiHitAttr) && !this.scene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) { + if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === move.type && power.value < 60 && move.priority <= 0 && !move.hasAttr(MultiHitAttr) && !this.scene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) { power.value = 60; } - applyPreAttackAbAttrs(VariableMovePowerAbAttr, source, this, battlerMove, power); - this.scene.getField(true).map(p => applyPreAttackAbAttrs(FieldVariableMovePowerAbAttr, this, source, battlerMove, power)); + applyPreAttackAbAttrs(VariableMovePowerAbAttr, source, this, move, power); + this.scene.getField(true).map(p => applyPreAttackAbAttrs(FieldVariableMovePowerAbAttr, this, source, move, power)); - applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, battlerMove, cancelled, power); + applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, move, cancelled, power); power.value *= typeChangeMovePowerMultiplier.value; if (!typeless) { - applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier); + applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier); } if (!cancelled.value) { - applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier); - defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier)); + applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier); + defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, typeMultiplier)); } if (cancelled.value) { result = HitResult.NO_EFFECT; } else { - const typeBoost = source.findTag(t => t instanceof TypeBoostTag && (t as TypeBoostTag).boostedType === type) as TypeBoostTag; + const typeBoost = source.findTag(t => t instanceof TypeBoostTag && t.boostedType === move.type) as TypeBoostTag; if (typeBoost) { power.value *= typeBoost.boostValue; if (typeBoost.oneUse) { source.removeTag(typeBoost.tagType); } } - const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(type, source.isGrounded())); + const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(move.type, source.isGrounded())); applyMoveAttrs(IgnoreWeatherTypeDebuffAttr, source, this, move, arenaAttackTypeMultiplier); - if (this.scene.arena.getTerrainType() === TerrainType.GRASSY && this.isGrounded() && type === Type.GROUND && move.moveTarget === MoveTarget.ALL_NEAR_OTHERS) { + if (this.scene.arena.getTerrainType() === TerrainType.GRASSY && this.isGrounded() && move.type === Type.GROUND && move.moveTarget === MoveTarget.ALL_NEAR_OTHERS) { power.value /= 2; } applyMoveAttrs(VariablePowerAttr, source, this, move, power); this.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, new Utils.IntegerHolder(0), power); if (!typeless) { - this.scene.arena.applyTags(WeakenMoveTypeTag, type, power); - this.scene.applyModifiers(AttackTypeBoosterModifier, source.isPlayer(), source, type, power); + this.scene.arena.applyTags(WeakenMoveTypeTag, move.type, power); + this.scene.applyModifiers(AttackTypeBoosterModifier, source.isPlayer(), source, move.type, power); } if (source.getTag(HelpingHandTag)) { power.value *= 1.5; @@ -1731,6 +1760,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } const critChance = [24, 8, 2, 1][Math.max(0, Math.min(critLevel.value, 3))]; isCritical = !source.getTag(BattlerTagType.NO_CRIT) && (critChance === 1 || !this.scene.randBattleSeedInt(critChance)); + if (Overrides.NEVER_CRIT_OVERRIDE) { + isCritical = false; + } } if (isCritical) { const blockCrit = new Utils.BooleanHolder(false); @@ -1749,11 +1781,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } const isTypeImmune = (typeMultiplier.value * arenaAttackTypeMultiplier.value) === 0; const sourceTypes = source.getTypes(); - const matchesSourceType = sourceTypes[0] === type || (sourceTypes.length > 1 && sourceTypes[1] === type); + const matchesSourceType = sourceTypes[0] === move.type || (sourceTypes.length > 1 && sourceTypes[1] === move.type); const stabMultiplier = new Utils.NumberHolder(1); if (sourceTeraType === Type.UNKNOWN && matchesSourceType) { stabMultiplier.value += 0.5; - } else if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === type) { + } else if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === move.type) { stabMultiplier.value += 0.5; } @@ -1778,7 +1810,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - applyPreAttackAbAttrs(DamageBoostAbAttr, source, this, battlerMove, damage); + applyPreAttackAbAttrs(DamageBoostAbAttr, source, this, move, damage); /** * For each {@link HitsTagAttr} the move has, doubles the damage of the move if: @@ -1793,7 +1825,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }); } - if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && type === Type.DRAGON) { + if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && move.type === Type.DRAGON) { damage.value = Math.floor(damage.value / 2); } @@ -1848,7 +1880,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const oneHitKo = result === HitResult.ONE_HIT_KO; if (damage.value) { if (this.getHpRatio() === 1) { - applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, battlerMove, cancelled, damage); + applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, move, cancelled, damage); } else if (!this.isPlayer() && damage.value >= this.hp) { this.scene.applyModifiers(EnemyEndureChanceModifier, false, this); } @@ -1913,11 +1945,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { break; case MoveCategory.STATUS: if (!typeless) { - applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier); + applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier); } if (!cancelled.value) { - applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier); - defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier)); + applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier); + defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, typeMultiplier)); } if (!typeMultiplier.value) { this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: this.name })); @@ -3381,10 +3413,6 @@ export class EnemyPokemon extends Pokemon { const pokemonMove = movePool[m]; const move = pokemonMove.getMove(); - const variableType = new Utils.IntegerHolder(move.type); - applyAbAttrs(VariableMoveTypeAbAttr, this, null, variableType); - const moveType = variableType.value as Type; - let moveScore = moveScores[m]; const targetScores: integer[] = []; @@ -3396,18 +3424,18 @@ export class EnemyPokemon extends Pokemon { const target = this.scene.getField()[mt]; let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1); - if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![Moves.SUCKER_PUNCH, Moves.UPPER_HAND].includes(move.id)) { + if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id)) { targetScore = -20; } else if (move instanceof AttackMove) { const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove); if (target.isPlayer() !== this.isPlayer()) { targetScore *= effectiveness; - if (this.isOfType(moveType)) { + if (this.isOfType(move.type)) { targetScore *= 1.5; } } else if (effectiveness) { targetScore /= effectiveness; - if (this.isOfType(moveType)) { + if (this.isOfType(move.type)) { targetScore /= 1.5; } } @@ -3789,6 +3817,19 @@ export enum HitResult { export type DamageResult = HitResult.EFFECTIVE | HitResult.SUPER_EFFECTIVE | HitResult.NOT_VERY_EFFECTIVE | HitResult.ONE_HIT_KO | HitResult.OTHER; +/** + * Wrapper class for the {@linkcode Move} class for Pokemon to interact with. + * These are the moves assigned to a {@linkcode Pokemon} object. + * It links to {@linkcode Move} class via the move ID. + * Compared to {@linkcode Move}, this class also tracks if a move has received. + * PP Ups, amount of PP used, and things like that. + * @see {@linkcode isUsable} - checks if move is disabled, out of PP, or not implemented. + * @see {@linkcode getMove} - returns {@linkcode Move} object by looking it up via ID. + * @see {@linkcode usePp} - removes a point of PP from the move. + * @see {@linkcode getMovePp} - returns amount of PP a move currently has. + * @see {@linkcode getPpRatio} - returns the current PP amount / max PP amount. + * @see {@linkcode getName} - returns name of {@linkcode Move}. + **/ export class PokemonMove { public moveId: Moves; public ppUsed: integer; diff --git a/src/field/trainer.ts b/src/field/trainer.ts index fb85bfbe8b7..5a86d5c4502 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -166,6 +166,10 @@ export default class Trainer extends Phaser.GameObjects.Container { return this.config.doubleOnly || this.variant === TrainerVariant.DOUBLE; } + getMixedBattleBgm(): string { + return this.config.mixedBattleBgm; + } + getBattleBgm(): string { return this.config.battleBgm; } diff --git a/src/game-mode.ts b/src/game-mode.ts index 4d46971dcb5..cb042b2757c 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -1,17 +1,20 @@ -import { fixedBattles } from "./battle"; +import i18next from "i18next"; +import { classicFixedBattles, FixedBattleConfig, FixedBattleConfigs } from "./battle"; import BattleScene from "./battle-scene"; +import { allChallenges, applyChallenges, Challenge, ChallengeType, copyChallenge } from "./data/challenge"; import { Biome } from "./data/enums/biome"; import { Species } from "./data/enums/species"; import PokemonSpecies, { allSpecies } from "./data/pokemon-species"; import { Arena } from "./field/arena"; -import * as Utils from "./utils"; import * as Overrides from "./overrides"; +import * as Utils from "./utils"; export enum GameModes { CLASSIC, ENDLESS, SPLICED_ENDLESS, - DAILY + DAILY, + CHALLENGE } interface GameModeConfig { @@ -19,12 +22,12 @@ interface GameModeConfig { isEndless?: boolean; isDaily?: boolean; hasTrainers?: boolean; - hasFixedBattles?: boolean; hasNoShop?: boolean; hasShortBiomes?: boolean; hasRandomBiomes?: boolean; hasRandomBosses?: boolean; isSplicedOnly?: boolean; + isChallenge?: boolean; } export class GameMode implements GameModeConfig { @@ -33,16 +36,23 @@ export class GameMode implements GameModeConfig { public isEndless: boolean; public isDaily: boolean; public hasTrainers: boolean; - public hasFixedBattles: boolean; public hasNoShop: boolean; public hasShortBiomes: boolean; public hasRandomBiomes: boolean; public hasRandomBosses: boolean; public isSplicedOnly: boolean; + public isChallenge: boolean; + public challenges: Challenge[]; + public battleConfig: FixedBattleConfigs; - constructor(modeId: GameModes, config: GameModeConfig) { + constructor(modeId: GameModes, config: GameModeConfig, battleConfig?: FixedBattleConfigs) { this.modeId = modeId; + this.challenges = []; Object.assign(this, config); + if (this.isChallenge) { + this.challenges = allChallenges.map(c => copyChallenge(c)); + } + this.battleConfig = battleConfig || {}; } /** @@ -112,7 +122,7 @@ export class GameMode implements GameModeConfig { if (w === waveIndex) { continue; } - if ((w % 30) === (arena.scene.offsetGym ? 0 : 20) || fixedBattles.hasOwnProperty(w)) { + if ((w % 30) === (arena.scene.offsetGym ? 0 : 20) || this.isFixedBattle(waveIndex)) { allowTrainerBattle = false; break; } else if (w < waveIndex) { @@ -161,6 +171,7 @@ export class GameMode implements GameModeConfig { isWaveFinal(waveIndex: integer, modeId: GameModes = this.modeId): boolean { switch (modeId) { case GameModes.CLASSIC: + case GameModes.CHALLENGE: return waveIndex === 200; case GameModes.ENDLESS: case GameModes.SPLICED_ENDLESS: @@ -208,10 +219,36 @@ export class GameMode implements GameModeConfig { (this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS); } + /** + * Checks whether there is a fixed battle on this gamemode on a given wave. + * @param {integer} waveIndex The wave to check. + * @returns {boolean} If this game mode has a fixed battle on this wave + */ + isFixedBattle(waveIndex: integer): boolean { + const dummyConfig = new FixedBattleConfig(); + return this.battleConfig.hasOwnProperty(waveIndex) || applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, dummyConfig); + + } + + /** + * Returns the config for the fixed battle for a particular wave. + * @param {integer} waveIndex The wave to check. + * @returns {boolean} The fixed battle for this wave. + */ + getFixedBattle(waveIndex: integer): FixedBattleConfig { + const challengeConfig = new FixedBattleConfig(); + if (applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, challengeConfig)) { + return challengeConfig; + } else { + return this.battleConfig[waveIndex]; + } + } + getClearScoreBonus(): integer { switch (this.modeId) { case GameModes.CLASSIC: + case GameModes.CHALLENGE: return 5000; case GameModes.DAILY: return 2500; @@ -221,6 +258,7 @@ export class GameMode implements GameModeConfig { getEnemyModifierChance(isBoss: boolean): integer { switch (this.modeId) { case GameModes.CLASSIC: + case GameModes.CHALLENGE: case GameModes.DAILY: return !isBoss ? 18 : 6; case GameModes.ENDLESS: @@ -232,20 +270,45 @@ export class GameMode implements GameModeConfig { getName(): string { switch (this.modeId) { case GameModes.CLASSIC: - return "Classic"; + return i18next.t("gameMode:classic"); case GameModes.ENDLESS: - return "Endless"; + return i18next.t("gameMode:endless"); case GameModes.SPLICED_ENDLESS: - return "Endless (Spliced)"; + return i18next.t("gameMode:endlessSpliced"); case GameModes.DAILY: - return "Daily Run"; + return i18next.t("gameMode:dailyRun"); + case GameModes.CHALLENGE: + return i18next.t("gameMode:challenge"); + } + } + + static getModeName(modeId: GameModes): string { + switch (modeId) { + case GameModes.CLASSIC: + return i18next.t("gameMode:classic"); + case GameModes.ENDLESS: + return i18next.t("gameMode:endless"); + case GameModes.SPLICED_ENDLESS: + return i18next.t("gameMode:endlessSpliced"); + case GameModes.DAILY: + return i18next.t("gameMode:dailyRun"); + case GameModes.CHALLENGE: + return i18next.t("gameMode:challenge"); } } } -export const gameModes = Object.freeze({ - [GameModes.CLASSIC]: new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasFixedBattles: true }), - [GameModes.ENDLESS]: new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true }), - [GameModes.SPLICED_ENDLESS]: new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true }), - [GameModes.DAILY]: new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true }) -}); +export function getGameMode(gameMode: GameModes): GameMode { + switch (gameMode) { + case GameModes.CLASSIC: + return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true }, classicFixedBattles); + case GameModes.ENDLESS: + return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true }); + case GameModes.SPLICED_ENDLESS: + return new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true }); + case GameModes.DAILY: + return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true }); + case GameModes.CHALLENGE: + return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true }, classicFixedBattles); + } +} diff --git a/src/inputs-controller.ts b/src/inputs-controller.ts index aa0f781cfef..3ef8fa24115 100644 --- a/src/inputs-controller.ts +++ b/src/inputs-controller.ts @@ -48,7 +48,7 @@ export interface InterfaceConfig { custom?: MappingLayout; } -const repeatInputDelayMillis = 250; +const repeatInputDelayMillis = 500; // Phaser.Input.Gamepad.GamepadPlugin#refreshPads declare module "phaser" { @@ -88,14 +88,12 @@ declare module "phaser" { * providing a unified interface for all input-related interactions. */ export class InputsController { - private buttonKeys: Phaser.Input.Keyboard.Key[][]; private gamepads: Array = new Array(); private scene: BattleScene; public events: Phaser.Events.EventEmitter; private buttonLock: Button; private interactions: Map> = new Map(); - private time: Phaser.Time.Clock; private configs: Map = new Map(); public gamepadSupport: boolean = true; @@ -122,8 +120,6 @@ export class InputsController { constructor(scene: BattleScene) { this.scene = scene; - this.time = this.scene.time; - this.buttonKeys = []; this.selectedDevice = { [Device.GAMEPAD]: null, [Device.KEYBOARD]: "default" @@ -248,6 +244,9 @@ export class InputsController { * If an interaction is valid and should be processed, it emits an 'input_down' event with details of the interaction. */ update(): void { + if (this.pauseUpdate) { + return; + } for (const b of Utils.getEnumValues(Button).reverse()) { if ( this.interactions.hasOwnProperty(b) && @@ -258,8 +257,7 @@ export class InputsController { if ( (!this.gamepadSupport && this.interactions[b].source === "gamepad") || (this.interactions[b].source === "gamepad" && this.interactions[b].sourceName && this.interactions[b].sourceName !== this.selectedDevice[Device.GAMEPAD]) || - (this.interactions[b].source === "keyboard" && this.interactions[b].sourceName && this.interactions[b].sourceName !== this.selectedDevice[Device.KEYBOARD]) || - this.pauseUpdate + (this.interactions[b].source === "keyboard" && this.interactions[b].sourceName && this.interactions[b].sourceName !== this.selectedDevice[Device.KEYBOARD]) ) { // Deletes the last interaction for a button if gamepad is disabled. this.delLastProcessedMovementTime(b as Button); @@ -550,7 +548,8 @@ export class InputsController { if (!this.isButtonLocked(button)) { return false; } - if (this.time.now - this.interactions[button].pressTime >= repeatInputDelayMillis) { + const duration = Date.now() - this.interactions[button].pressTime; + if (duration >= repeatInputDelayMillis) { return true; } } @@ -575,7 +574,7 @@ export class InputsController { return; } this.setButtonLock(button); - this.interactions[button].pressTime = this.time.now; + this.interactions[button].pressTime = Date.now(); this.interactions[button].isPressed = true; this.interactions[button].source = source; this.interactions[button].sourceName = sourceName.toLowerCase(); @@ -635,7 +634,7 @@ export class InputsController { this.interactions[b].sourceName = null; } } - setTimeout(() => this.pauseUpdate = false, 500); + this.pauseUpdate = false; } /** diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 9f3cf631907..fb6b0303e04 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -16,9 +16,12 @@ import {initPokemonForms} from "#app/data/pokemon-forms"; import {initSpecies} from "#app/data/pokemon-species"; import {initMoves} from "#app/data/move"; import {initAbilities} from "#app/data/ability"; +import {initAchievements} from "#app/system/achv"; import {initTrainerTypeDialogue} from "#app/data/dialogue"; +import { initChallenges } from "./data/challenge"; import i18next from "i18next"; import { initStatsKeys } from "./ui/game-stats-ui-handler"; +import { initVouchers } from "./system/voucher"; export class LoadingScene extends SceneBase { constructor() { @@ -134,7 +137,6 @@ export class LoadingScene extends SceneBase { this.loadImage("summary_stats_overlay_exp", "ui"); this.loadImage("summary_moves", "ui"); this.loadImage("summary_moves_effect", "ui"); - this.loadImage("summary_moves_effect_type", "ui"); this.loadImage("summary_moves_overlay_row", "ui"); this.loadImage("summary_moves_overlay_pp", "ui"); this.loadAtlas("summary_moves_cursor", "ui"); @@ -328,6 +330,8 @@ export class LoadingScene extends SceneBase { this.loadLoadingScreen(); + initVouchers(); + initAchievements(); initStatsKeys(); initPokemonPrevolutions(); initBiomes(); @@ -337,6 +341,7 @@ export class LoadingScene extends SceneBase { initSpecies(); initMoves(); initAbilities(); + initChallenges(); } loadLoadingScreen() { @@ -430,7 +435,7 @@ export class LoadingScene extends SceneBase { }); this.load.on("fileprogress", file => { - assetText.setText(`Loading asset: ${file.key}`); + assetText.setText(i18next.t("menu:loadingAsset", { assetName: file.key })); }); loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText); diff --git a/src/locales/de/ability-trigger.ts b/src/locales/de/ability-trigger.ts index d3fbdfc1b77..652c16eb662 100644 --- a/src/locales/de/ability-trigger.ts +++ b/src/locales/de/ability-trigger.ts @@ -3,6 +3,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!", "badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!", - "windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!", - "iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!" + "windPowerCharged": "Der Treffer durch {{moveName}} läd die Stärke von {{pokemonName}} auf!", + "iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!", } as const; diff --git a/src/locales/de/achv.ts b/src/locales/de/achv.ts index 42f2b2cf86c..64721e48af6 100644 --- a/src/locales/de/achv.ts +++ b/src/locales/de/achv.ts @@ -1,6 +1,7 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import {AchievementTranslationEntries} from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "Errungenschaften", }, @@ -10,7 +11,7 @@ export const achv: AchievementTranslationEntries = { "MoneyAchv": { - description:"Häufe eine Gesamtsumme von {{moneyAmount}} ₽ an", + description: "Häufe eine Gesamtsumme von {{moneyAmount}} ₽ an.", }, "10K_MONEY": { name: "Besserverdiener", @@ -26,7 +27,7 @@ export const achv: AchievementTranslationEntries = { }, "DamageAchv": { - description: "Füge mit einem Treffer {{damageAmount}} Schaden zu", + description: "Füge mit einem Treffer {{damageAmount}} Schaden zu.", }, "250_DMG": { name: "Harte Treffer", @@ -42,7 +43,7 @@ export const achv: AchievementTranslationEntries = { }, "HealAchv": { - description: "Heile {{healAmount}} {{HP}} auf einmal. Mit einer Attacke, Fähigkeit oder einem gehaltenen Gegenstand", + description: "Heile {{healAmount}} {{HP}} auf einmal. Mit einer Attacke, Fähigkeit oder einem gehaltenen Gegenstand.", }, "250_HEAL": { name: "Anfänger-Heiler", @@ -58,7 +59,7 @@ export const achv: AchievementTranslationEntries = { }, "LevelAchv": { - description: "Erhöhe das Level eines Pokémon auf {{level}}", + description: "Erhöhe das Level eines Pokémon auf {{level}}.", }, "LV_100": { name: "Warte, es gibt mehr!", @@ -67,14 +68,14 @@ export const achv: AchievementTranslationEntries = { name: "Elite", }, "LV_1000": { - name: "Geh noch höher hinaus!", + name: "Geh noch höher hinaus!", }, "RibbonAchv": { - description: "Sammle insgesamt {{ribbonAmount}} Bänder", + description: "Sammle insgesamt {{ribbonAmount}} Bänder.", }, "10_RIBBONS": { - name: "Champion der Pokémon Liga", + name: "Champion der Pokémon Liga", }, "25_RIBBONS": { name: "Bänder-Sammler", @@ -91,82 +92,286 @@ export const achv: AchievementTranslationEntries = { "TRANSFER_MAX_BATTLE_STAT": { name: "Teamwork", - description: "Nutze Staffette, während der Anwender mindestens eines Statuswertes maximiert hat", + description: "Nutze Staffette, während der Anwender mindestens eines Statuswertes maximiert hat.", }, "MAX_FRIENDSHIP": { - name: "Freundschaftsmaximierung", - description: "Erreiche maximale Freundschaft bei einem Pokémon", + name: "Freundschaftsmaximierung", + description: "Erreiche maximale Freundschaft bei einem Pokémon.", }, "MEGA_EVOLVE": { name: "Megaverwandlung", - description: "Megaentwickle ein Pokémon", + description: "Megaentwickle ein Pokémon.", }, "GIGANTAMAX": { name: "Absolute Einheit", - description: "Gigadynamaximiere ein Pokémon", + description: "Gigadynamaximiere ein Pokémon.", }, "TERASTALLIZE": { name: "Typen-Bonus Enthusiast", - description: "Terrakristallisiere ein Pokémon", + description: "Terrakristallisiere ein Pokémon.", }, "STELLAR_TERASTALLIZE": { name: "Der geheime Typ", - description: "Terrakristallisiere ein Pokémon zum Typen Stellar", + description: "Terrakristallisiere ein Pokémon zum Typen Stellar.", }, "SPLICE": { name: "Unendliche Fusion", - description: "Kombiniere zwei Pokémon mit einem DNS-Keil", + description: "Kombiniere zwei Pokémon mit einem DNS-Keil.", }, "MINI_BLACK_HOLE": { name: "Ein Loch voller Items", - description: "Erlange ein Mini-Schwarzes Loch", + description: "Erlange ein Mini-Schwarzes Loch.", }, "CATCH_MYTHICAL": { - name: "Mysteriöses!", - description: "Fange ein mysteriöses Pokémon", + name: "Mysteriöses!", + description: "Fange ein mysteriöses Pokémon.", }, "CATCH_SUB_LEGENDARY": { name: "Sub-Legendär", - description: "Fange ein sub-legendäres Pokémon", + description: "Fange ein sub-legendäres Pokémon.", }, "CATCH_LEGENDARY": { name: "Legendär", - description: "Fange ein legendäres Pokémon", + description: "Fange ein legendäres Pokémon.", }, "SEE_SHINY": { name: "Schillerndes Licht", - description: "Finde ein wildes schillerndes Pokémon", + description: "Finde ein wildes schillerndes Pokémon.", }, "SHINY_PARTY": { name: "Das ist Hingabe", - description: "Habe ein Team aus schillernden Pokémon", + description: "Habe ein Team aus schillernden Pokémon.", }, "HATCH_MYTHICAL": { name: "Mysteriöses Ei", - description: "Lass ein mysteriöses Pokémon aus einem Ei schlüpfen", + description: "Lass ein mysteriöses Pokémon aus einem Ei schlüpfen.", }, "HATCH_SUB_LEGENDARY": { name: "Sub-Legendäres Ei", - description: "Lass ein sub-legendäres Pokémon aus einem Ei schlüpfen", + description: "Lass ein sub-legendäres Pokémon aus einem Ei schlüpfen.", }, "HATCH_LEGENDARY": { name: "Legendäres Ei", - description: "Lass ein legendäres Pokémon aus einem Ei schlüpfen", + description: "Lass ein legendäres Pokémon aus einem Ei schlüpfen.", }, "HATCH_SHINY": { name: "Schillerndes Ei", - description: "Lass ein schillerndes Pokémon aus einem Ei schlüpfen", + description: "Lass ein schillerndes Pokémon aus einem Ei schlüpfen.", }, "HIDDEN_ABILITY": { name: "Geheimes Talent", - description: "Fang ein Pokémon mit versteckter Fähigkeit", + description: "Fang ein Pokémon mit versteckter Fähigkeit.", }, "PERFECT_IVS": { name: "Zertifikat der Echtheit", - description: "Erhalte ein Pokémon mit perfekten IS-Werten", + description: "Erhalte ein Pokémon mit perfekten IS-Werten.", }, "CLASSIC_VICTORY": { name: "Ungeschlagen", - description: "Beende den klassischen Modus erfolgreich", + description: "Beende den klassischen Modus erfolgreich.", + }, + "MONO_GEN_ONE": { + name: "Der originale Rivale", + description: "Schließe die 'Nur 1. Generation' Herausforderung ab.", + }, + "MONO_GEN_TWO": { + name: "Generation 1.5", + description: "Schließe die 'Nur 2. Generation' Herausforderung ab.", + }, + "MONO_GEN_THREE": { + name: "Zu viel Wasser?", + description: "Schließe die 'Nur 3. Generation' Herausforderung ab.", + }, + "MONO_GEN_FOUR": { + name: "Ist SIE wirklich die Stärkste?", + description: "Schließe die 'Nur 4. Generation' Herausforderung ab.", + }, + "MONO_GEN_FIVE": { + name: "Komplett Original", + description: "Schließe die 'Nur 5. Generation' Herausforderung ab.", + }, + "MONO_GEN_SIX": { + name: "Fast Königlich", + description: "Schließe die 'Nur 6. Generation' Herausforderung ab." + }, + "MONO_GEN_SEVEN": { + name: "Technisch gesehen", + description: "Schließe die 'Nur 7. Generation' Herausforderung ab." + }, + "MONO_GEN_EIGHT": { + name: "Die Zeit des Champions", + description: "Schließe die 'Nur 8. Generation' Herausforderung ab." + }, + "MONO_GEN_NINE": { + name: "Sie hat es dir leicht gemacht...", + description: "Schließe die 'Nur 9. Generation' Herausforderung ab." + }, + + "MonoType": { + description: "Beende die Monotyp-{{type}} Herausforderung." + }, + "MONO_NORMAL": { + name: "Normaler Typ", + }, + "MONO_FIGHTING": { + name: "Ich kenne Kung Fu." + }, + "MONO_FLYING": { + name: "Ich glaube ich kann fliegen.", + }, + "MONO_POISON": { + name: "Kantos Liebling", + }, + "MONO_GROUND": { + name: "Auf dem Boden bleiben.", + }, + "MONO_ROCK": { + name: "So hart wie Rocko.", + }, + "MONO_BUG": { + name: "Steche wie ein Bibor.", + }, + "MONO_GHOST": { + name: "Wer wird angerufen?", + }, + "MONO_STEEL": { + name: "Stahlharte Entschlossenheit", + }, + "MONO_FIRE": { + name: "Brennende Leidenschaft", + }, + "MONO_WATER": { + name: "Wenn es regnet, schüttet es!", + }, + "MONO_GRASS": { + name: "Grüner Daumen", + }, + "MONO_ELECTRIC": { + name: "Elektrisierend", + }, + "MONO_PSYCHIC": { + name: "Übernatürliches Talent", + }, + "MONO_ICE": { + name: "Eis Eis Baby", + }, + "MONO_DRAGON": { + name: "Siegfried bist du es?", + }, + "MONO_DARK": { + name: "Es ist nur eine Phase!", + }, + "MONO_FAIRY": { + name: "Ein ewiges Abenteuer!", }, } as const; + +// Achievement translations for the when the player character is female +export const PGFachv: AchievementTranslationEntries = { + "Achievements": { + name: PGMachv.Achievements.name, + }, + "Locked": { + name: PGMachv.Locked.name, + }, + + + "MoneyAchv": PGMachv.MoneyAchv, + "10K_MONEY": { + name: "Besserverdienerin", + }, + "100K_MONEY": PGMachv["100K_MONEY"], + "1M_MONEY": { + name: "Millionärin", + }, + "10M_MONEY": PGMachv["10M_MONEY"], + + "DamageAchv": PGMachv.DamageAchv, + "250_DMG": PGMachv["250_DMG"], + "1000_DMG": PGMachv["1000_DMG"], + "2500_DMG": PGMachv["2500_DMG"], + "10000_DMG": { + name: "One Punch Woman", + }, + + "HealAchv": PGMachv.HealAchv, + "250_HEAL": { + name: "Anfänger-Heilerin", + }, + "1000_HEAL": PGMachv["1000_HEAL"], + "2500_HEAL": { + name: "Klerikerin", + }, + "10000_HEAL": { + name: "Wiederherstellungsmeisterin", + }, + + "LevelAchv": PGMachv.LevelAchv, + "LV_100": PGMachv["LV_100"], + "LV_250": PGMachv["LV_250"], + "LV_1000": PGMachv["LV_1000"], + + "RibbonAchv": PGMachv.RibbonAchv, + "10_RIBBONS": PGMachv["10_RIBBONS"], + "25_RIBBONS": { + name: "Bänder-Sammlerin", + }, + "50_RIBBONS": { + name: "Bänder-Expertin", + }, + "75_RIBBONS": PGMachv["75_RIBBONS"], + "100_RIBBONS": { + name: "Bänder-Meisterin", + }, + + "TRANSFER_MAX_BATTLE_STAT": PGMachv.TRANSFER_MAX_BATTLE_STAT, + "MAX_FRIENDSHIP": PGMachv.MAX_FRIENDSHIP, + "MEGA_EVOLVE": PGMachv.MEGA_EVOLVE, + "GIGANTAMAX": PGMachv.GIGANTAMAX, + "TERASTALLIZE": PGMachv.TERASTALLIZE, + "STELLAR_TERASTALLIZE": PGMachv.STELLAR_TERASTALLIZE, + "SPLICE": PGMachv.SPLICE, + "MINI_BLACK_HOLE": PGMachv.MINI_BLACK_HOLE, + "CATCH_MYTHICAL": PGMachv.CATCH_MYTHICAL, + "CATCH_SUB_LEGENDARY": PGMachv.CATCH_SUB_LEGENDARY, + "CATCH_LEGENDARY": PGMachv.CATCH_LEGENDARY, + "SEE_SHINY": PGMachv.SEE_SHINY, + "SHINY_PARTY": PGMachv.SHINY_PARTY, + "HATCH_MYTHICAL": PGMachv.HATCH_MYTHICAL, + "HATCH_SUB_LEGENDARY": PGMachv.HATCH_SUB_LEGENDARY, + "HATCH_LEGENDARY": PGMachv.HATCH_LEGENDARY, + "HATCH_SHINY": PGMachv.HATCH_SHINY, + "HIDDEN_ABILITY": PGMachv.HIDDEN_ABILITY, + "PERFECT_IVS": PGMachv.PERFECT_IVS, + "CLASSIC_VICTORY": PGMachv.CLASSIC_VICTORY, + "MONO_GEN_ONE": PGMachv.MONO_GEN_ONE, + "MONO_GEN_TWO": PGMachv.MONO_GEN_TWO, + "MONO_GEN_THREE": PGMachv.MONO_GEN_THREE, + "MONO_GEN_FOUR": PGMachv.MONO_GEN_FOUR, + "MONO_GEN_FIVE": PGMachv.MONO_GEN_FIVE, + "MONO_GEN_SIX": PGMachv.MONO_GEN_SIX, + "MONO_GEN_SEVEN": PGMachv.MONO_GEN_SEVEN, + "MONO_GEN_EIGHT": PGMachv.MONO_GEN_EIGHT, + "MONO_GEN_NINE": PGMachv.MONO_GEN_NINE, + + "MonoType": PGMachv.MonoType, + "MONO_NORMAL": PGMachv.MONO_NORMAL, + "MONO_FIGHTING": PGMachv.MONO_FIGHTING, + "MONO_FLYING": PGMachv.MONO_FLYING, + "MONO_POISON": PGMachv.MONO_POISON, + "MONO_GROUND": PGMachv.MONO_GROUND, + "MONO_ROCK": PGMachv.MONO_ROCK, + "MONO_BUG": PGMachv.MONO_BUG, + "MONO_GHOST": PGMachv.MONO_GHOST, + "MONO_STEEL": PGMachv.MONO_STEEL, + "MONO_FIRE": PGMachv.MONO_FIRE, + "MONO_WATER": PGMachv.MONO_WATER, + "MONO_GRASS": PGMachv.MONO_GRASS, + "MONO_ELECTRIC": PGMachv.MONO_ELECTRIC, + "MONO_PSYCHIC": PGMachv.MONO_PSYCHIC, + "MONO_ICE": PGMachv.MONO_ICE, + "MONO_DRAGON": PGMachv.MONO_DRAGON, + "MONO_DARK": PGMachv.MONO_DARK, + "MONO_FAIRY": PGMachv.MONO_FAIRY, +} as const; + diff --git a/src/locales/de/berry.ts b/src/locales/de/berry.ts index 330b36fffc8..093c3f708eb 100644 --- a/src/locales/de/berry.ts +++ b/src/locales/de/berry.ts @@ -3,46 +3,46 @@ import { BerryTranslationEntries } from "#app/plugins/i18n"; export const berry: BerryTranslationEntries = { "SITRUS": { name: "Tsitrubeere", - effect: "Stellt 25% der KP wieder her, wenn die KP unter 50% sind" + effect: "Stellt 25% der KP wieder her, wenn die KP unter 50% sind." }, "LUM": { name: "Prunusbeere", - effect: "Heilt jede nichtflüchtige Statusveränderung und Verwirrung" + effect: "Heilt jede nichtflüchtige Statusveränderung und Verwirrung." }, "ENIGMA": { name: "Enigmabeere", - effect: "Stellt 25% der KP wieder her, wenn der Träger von einer sehr effektiven Attacke getroffen wird", + effect: "Stellt 25% der KP wieder her, wenn der Träger von einer sehr effektiven Attacke getroffen wird.", }, "LIECHI": { name: "Lydzibeere", - effect: "Steigert den Angriff, wenn die KP unter 25% sind" + effect: "Steigert den Angriff, wenn die KP unter 25% sind." }, "GANLON": { name: "Linganbeere", - effect: "Steigert die Verteidigung, wenn die KP unter 25% sind" + effect: "Steigert die Verteidigung, wenn die KP unter 25% sind." }, "PETAYA": { name: "Tahaybeere", - effect: "Steigert den Spezial-Angriff, wenn die KP unter 25% sind" + effect: "Steigert den Spezial-Angriff, wenn die KP unter 25% sind." }, "APICOT": { name: "Apikobeere", - effect: "Steigert die Spezial-Verteidigung, wenn die KP unter 25% sind" + effect: "Steigert die Spezial-Verteidigung, wenn die KP unter 25% sind." }, "SALAC": { name: "Salkabeere", - effect: "Steigert die Initiative, wenn die KP unter 25% sind" + effect: "Steigert die Initiative, wenn die KP unter 25% sind." }, "LANSAT": { name: "Lansatbeere", - effect: "Erhöht die Volltrefferchance, wenn die KP unter 25% sind" + effect: "Erhöht die Volltrefferchance, wenn die KP unter 25% sind." }, "STARF": { name: "Krambobeere", - effect: "Erhöht einen zufälligen Statuswert stark, wenn die KP unter 25% sind" + effect: "Erhöht einen zufälligen Statuswert stark, wenn die KP unter 25% sind." }, "LEPPA": { name: "Jonagobeere", - effect: "Stellt 10 AP für eine Attacke wieder her, wenn deren AP auf 0 fallen" + effect: "Stellt 10 AP für eine Attacke wieder her, wenn deren AP auf 0 fallen." }, } as const; diff --git a/src/locales/de/challenges.ts b/src/locales/de/challenges.ts new file mode 100644 index 00000000000..1dbd4505986 --- /dev/null +++ b/src/locales/de/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "Herausforderungsmodifikatoren", + "confirm_start": "Mit diesen Modifikatoren fortfahren?", + "singleGeneration.name": "Mono-Generation", + "singleGeneration.value.0": "Aus", + "singleGeneration.desc.0": "Du kannst nur Pokémon aus der gewählten Generation verwenden.", + "singleGeneration.value.1": "Generation 1", + "singleGeneration.desc.1": "Du kannst nur Pokémon aus der ersten Generation verwenden.", + "singleGeneration.value.2": "Generation 2", + "singleGeneration.desc.2": "Du kannst nur Pokémon aus der zweiten Generation verwenden.", + "singleGeneration.value.3": "Generation 3", + "singleGeneration.desc.3": "Du kannst nur Pokémon aus der dritten Generation verwenden.", + "singleGeneration.value.4": "Generation 4", + "singleGeneration.desc.4": "Du kannst nur Pokémon aus der vierten Generation verwenden.", + "singleGeneration.value.5": "Generation 5", + "singleGeneration.desc.5": "Du kannst nur Pokémon aus der fünften Generation verwenden.", + "singleGeneration.value.6": "Generation 6", + "singleGeneration.desc.6": "Du kannst nur Pokémon aus der sechsten Generation verwenden.", + "singleGeneration.value.7": "Generation 7", + "singleGeneration.desc.7": "Du kannst nur Pokémon aus der siebten Generation verwenden.", + "singleGeneration.value.8": "Generation 8", + "singleGeneration.desc.8": "Du kannst nur Pokémon aus der achten Generation verwenden.", + "singleGeneration.value.9": "Generation 9", + "singleGeneration.desc.9": "Du kannst nur Pokémon aus der neunten Generation verwenden.", + "singleType.name": "Mono-Typ", + "singleType.value.0": "Aus", + "singleType.desc.0": "Du kannst nur Pokémon des gewählten Typs verwenden.", + "singleType.value.1": "Normal", + "singleType.desc.1": "Du kannst nur Pokémon des Typs Normal verwenden.", + "singleType.value.2": "Kampf", + "singleType.desc.2": "Du kannst nur Pokémon des Typs Kampf verwenden.", + "singleType.value.3": "Flug", + "singleType.desc.3": "Du kannst nur Pokémon des Typs Flug verwenden.", + "singleType.value.4": "Gift", + "singleType.desc.4": "Du kannst nur Pokémon des Typs Gift verwenden.", + "singleType.value.5": "Boden", + "singleType.desc.5": "Du kannst nur Pokémon des Typs Boden verwenden.", + "singleType.value.6": "Gestein", + "singleType.desc.6": "Du kannst nur Pokémon des Typs Gestein verwenden.", + "singleType.value.7": "Käfer", + "singleType.desc.7": "Du kannst nur Pokémon des Typs Käfer verwenden.", + "singleType.value.8": "Geist", + "singleType.desc.8": "Du kannst nur Pokémon des Typs Geist verwenden.", + "singleType.value.9": "Stahl", + "singleType.desc.9": "Du kannst nur Pokémon des Typs Stahl verwenden.", + "singleType.value.10": "Feuer", + "singleType.desc.10": "Du kannst nur Pokémon des Typs Feuer verwenden.", + "singleType.value.11": "Wasser", + "singleType.desc.11": "Du kannst nur Pokémon des Typs Wasser verwenden.", + "singleType.value.12": "Pflanze", + "singleType.desc.12": "Du kannst nur Pokémon des Typs Pflanze verwenden.", + "singleType.value.13": "Elektro", + "singleType.desc.13": "Du kannst nur Pokémon des Typs Elektro verwenden.", + "singleType.value.14": "Psycho", + "singleType.desc.14": "Du kannst nur Pokémon des Typs Psycho verwenden.", + "singleType.value.15": "Eis", + "singleType.desc.15": "Du kannst nur Pokémon des Typs Eis verwenden.", + "singleType.value.16": "Drache", + "singleType.desc.16": "Du kannst nur Pokémon des Typs Drache verwenden.", + "singleType.value.17": "Unlicht", + "singleType.desc.17": "Du kannst nur Pokémon des Typs Unlicht verwenden.", + "singleType.value.18": "Fee", + "singleType.desc.18": "Du kannst nur Pokémon des Typs Fee verwenden." + +} as const; diff --git a/src/locales/de/config.ts b/src/locales/de/config.ts index e243aac135d..b02bd5aeee6 100644 --- a/src/locales/de/config.ts +++ b/src/locales/de/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -29,22 +31,26 @@ import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; +import { partyUiHandler } from "./party-ui-handler"; export const deConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const deConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -66,6 +73,7 @@ export const deConfig = { pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +81,6 @@ export const deConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, + partyUiHandler: partyUiHandler }; diff --git a/src/locales/de/dialogue.ts b/src/locales/de/dialogue.ts index c69fb1aacd0..6b0bdc7c16a 100644 --- a/src/locales/de/dialogue.ts +++ b/src/locales/de/dialogue.ts @@ -369,14 +369,26 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "firebreather": { "encounter": { - 1: "My flames shall devour you!", - 2: "My soul is on fire. I'll show you how hot it burns!", - 3: "Step right up and take a look!" + 1: "Meine Flammen werden dich verschlingen!", + 2: "Meine Seele hat Feuer gefangen. Ich werde dir zeigen, wie heiß sie brennt!", + 3: "Komm näher und sieh dir meine Flammen an!" }, "victory": { - 1: "I burned down to ashes...", - 2: "Yow! That's hot!", - 3: "Ow! I scorched the tip of my nose!" + 1: "Verbrannt bis zur Asche...", + 2: "Yow! Das ist heiß!", + 3: "Auuu! Ich habe mir die Nasenspitze verbrannt!" + }, + }, + "sailor": { + "encounter": { + 1: "Matrose, du gehst über Bord, wenn du verlierst!", + 2: "Komm schon! Mein Stolz als Seemann steht auf dem Spiel!", + 3: "Ahoj! Bist du seekrank?" + }, + "victory": { + 1: "Argh! Von einem Kind besiegt!", + 2: "Dein Geist hat mich versenkt!", + 3: "Ich glaube, ich bin der der seekrank ist..." }, }, "brock": { diff --git a/src/locales/de/egg.ts b/src/locales/de/egg.ts index 1551d832bfc..b55c3a229d0 100644 --- a/src/locales/de/egg.ts +++ b/src/locales/de/egg.ts @@ -10,10 +10,10 @@ export const egg: SimpleTranslationEntries = { "hatchWavesMessageClose": "Manchmal bewegt es sich! Es braucht wohl noch ein Weilchen.", "hatchWavesMessageNotClose": "Was wird da wohl schlüpfen? Es wird sicher noch lange dauern.", "hatchWavesMessageLongTime": "Dieses Ei braucht sicher noch sehr viel Zeit.", - "gachaTypeLegendary": "Erhöhte Chance auf legendäre Eier", - "gachaTypeMove": "Erhöhte Chance auf Eier mit seltenen Attacken", - "gachaTypeShiny": "Erhöhte Chance auf schillernde Eier", - "selectMachine": "Wähle eine Maschine", + "gachaTypeLegendary": "Erhöhte Chance auf legendäre Eier.", + "gachaTypeMove": "Erhöhte Chance auf Eier mit seltenen Attacken.", + "gachaTypeShiny": "Erhöhte Chance auf schillernde Eier.", + "selectMachine": "Wähle eine Maschine.", "notEnoughVouchers": "Du hast nicht genug Ei-Gutscheine!", "tooManyEggs": "Du hast schon zu viele Eier!", "pull": "Pull", diff --git a/src/locales/de/game-mode.ts b/src/locales/de/game-mode.ts new file mode 100644 index 00000000000..59058a6ab49 --- /dev/null +++ b/src/locales/de/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "Klassik", + "endless": "Endlos", + "endlessSpliced": "Endlos (Fusion)", + "dailyRun": "Täglicher Run", + "unknown": "Unbekannt", + "challenge": "Challenge", +} as const; diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index e1e5db72b9c..d8987fcf77b 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -18,19 +18,19 @@ export const menu: SimpleTranslationEntries = { "password": "Passwort", "login": "Anmelden", "register": "Registrieren", - "emptyUsername": "Benutzername darf nicht leer sein", - "invalidLoginUsername": "Der eingegebene Benutzername ist ungültig", - "invalidRegisterUsername": "Benutzername darf nur Buchstaben, Zahlen oder Unterstriche enthalten", - "invalidLoginPassword": "Das eingegebene Passwort ist ungültig", - "invalidRegisterPassword": "Passwort muss 6 Zeichen oder länger sein", - "usernameAlreadyUsed": "Der eingegebene Benutzername wird bereits verwendet", - "accountNonExistent": "Der eingegebene Benutzer existiert nicht", - "unmatchingPassword": "Das eingegebene Passwort stimmt nicht überein", - "passwordNotMatchingConfirmPassword": "Passwort muss mit Bestätigungspasswort übereinstimmen", + "emptyUsername": "Benutzername darf nicht leer sein.", + "invalidLoginUsername": "Der eingegebene Benutzername ist ungültig.", + "invalidRegisterUsername": "Benutzername darf nur Buchstaben, Zahlen oder Unterstriche enthalten.", + "invalidLoginPassword": "Das eingegebene Passwort ist ungültig.", + "invalidRegisterPassword": "Passwort muss 6 Zeichen oder länger sein.", + "usernameAlreadyUsed": "Der eingegebene Benutzername wird bereits verwendet.", + "accountNonExistent": "Der eingegebene Benutzer existiert nicht.", + "unmatchingPassword": "Das eingegebene Passwort stimmt nicht überein.", + "passwordNotMatchingConfirmPassword": "Passwort muss mit Bestätigungspasswort übereinstimmen.", "confirmPassword": "Bestätige Passwort", "registrationAgeWarning": "Mit der Registrierung bestätigen Sie, dass Sie 13 Jahre oder älter sind.", "backToLogin": "Zurück zur Anmeldung", - "failedToLoadSaveData": "Speicherdaten konnten nicht geladen werden. Bitte laden Sie die Seite neu.\nÜberprüfe den #announcements-Kanal im Discord bei anhaltenden Problemen", + "failedToLoadSaveData": "Speicherdaten konnten nicht geladen werden. Bitte laden Sie die Seite neu.\nÜberprüfe den #announcements-Kanal im Discord bei anhaltenden Problemen.", "sessionSuccess": "Sitzung erfolgreich geladen.", "failedToLoadSession": "Ihre Sitzungsdaten konnten nicht geladen werden.\nSie könnten beschädigt sein.", "boyOrGirl": "Bist du ein Junge oder ein Mädchen?", @@ -45,8 +45,8 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Wöchentliche Rangliste", "noRankings": "Keine Rangliste", "loading": "Lade…", + "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "Spieler Online", - "empty":"Leer", "yes":"Ja", "no":"Nein", "disclaimer": "DISCLAIMER", diff --git a/src/locales/de/modifier-type.ts b/src/locales/de/modifier-type.ts index ff9cf28632c..d2cd6965ad3 100644 --- a/src/locales/de/modifier-type.ts +++ b/src/locales/de/modifier-type.ts @@ -4,11 +4,11 @@ export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { "AddPokeballModifierType": { name: "{{modifierCount}}x {{pokeballName}}", - description: "Erhalte {{pokeballName}} x{{modifierCount}} (Inventar: {{pokeballAmount}}) \nFangrate: {{catchRate}}", + description: "Erhalte {{pokeballName}} x{{modifierCount}}. (Inventar: {{pokeballAmount}}) \nFangrate: {{catchRate}}", }, "AddVoucherModifierType": { name: "{{modifierCount}}x {{voucherTypeName}}", - description: "Erhalte {{voucherTypeName}} x{{modifierCount}}", + description: "Erhalte {{voucherTypeName}} x{{modifierCount}}.", }, "PokemonHeldItemModifierType": { extra: { @@ -17,32 +17,32 @@ export const modifierType: ModifierTypeTranslationEntries = { } }, "PokemonHpRestoreModifierType": { - description: "Füllt {{restorePoints}} KP oder {{restorePercent}}% der KP für ein Pokémon auf. Je nachdem, welcher Wert höher ist", + description: "Füllt {{restorePoints}} KP oder {{restorePercent}}% der KP für ein Pokémon auf. Je nachdem, welcher Wert höher ist.", extra: { "fully": "Füllt die KP eines Pokémon wieder vollständig auf.", - "fullyWithStatus": "Füllt die KP eines Pokémon wieder vollständig auf und behebt alle Statusprobleme", + "fullyWithStatus": "Füllt die KP eines Pokémon wieder vollständig auf und behebt alle Statusprobleme.", } }, "PokemonReviveModifierType": { - description: "Belebt ein kampunfähiges Pokémon wieder und stellt {{restorePercent}}% KP wieder her", + description: "Belebt ein kampunfähiges Pokémon wieder und stellt {{restorePercent}}% KP wieder her.", }, "PokemonStatusHealModifierType": { - description: "Behebt alle Statusprobleme eines Pokémon", + description: "Behebt alle Statusprobleme eines Pokémon.", }, "PokemonPpRestoreModifierType": { - description: "Füllt {{restorePoints}} AP der ausgewählten Attacke eines Pokémon auf", + description: "Füllt {{restorePoints}} AP der ausgewählten Attacke eines Pokémon auf.", extra: { - "fully": "Füllt alle AP der ausgewählten Attacke eines Pokémon auf", + "fully": "Füllt alle AP der ausgewählten Attacke eines Pokémon auf.", } }, "PokemonAllMovePpRestoreModifierType": { - description: "Stellt {{restorePoints}} AP für alle Attacken eines Pokémon auf", + description: "Stellt {{restorePoints}} AP für alle Attacken eines Pokémon auf.", extra: { - "fully": "Füllt alle AP für alle Attacken eines Pokémon auf", + "fully": "Füllt alle AP für alle Attacken eines Pokémon auf.", } }, "PokemonPpUpModifierType": { - description: "Erhöht die maximale Anzahl der AP der ausgewählten Attacke um {{upPoints}} für jede 5 maximale AP (maximal 3)", + description: "Erhöht die maximale Anzahl der AP der ausgewählten Attacke um {{upPoints}} für jede 5 maximale AP (maximal 3).", }, "PokemonNatureChangeModifierType": { name: "{{natureName}} Minze", @@ -52,28 +52,28 @@ export const modifierType: ModifierTypeTranslationEntries = { description: "Verdoppelt die Wahrscheinlichkeit, dass die nächsten {{battleCount}} Begegnungen mit wilden Pokémon ein Doppelkampf sind.", }, "TempBattleStatBoosterModifierType": { - description: "Erhöht die {{tempBattleStatName}} aller Teammitglieder für 5 Kämpfe um eine Stufe", + description: "Erhöht die {{tempBattleStatName}} aller Teammitglieder für 5 Kämpfe um eine Stufe.", }, "AttackTypeBoosterModifierType": { - description: "Erhöht die Stärke aller {{moveType}}-Attacken eines Pokémon um 20%", + description: "Erhöht die Stärke aller {{moveType}}-Attacken eines Pokémon um 20%.", }, "PokemonLevelIncrementModifierType": { - description: "Erhöht das Level eines Pokémon um 1", + description: "Erhöht das Level eines Pokémon um 1.", }, "AllPokemonLevelIncrementModifierType": { - description: "Erhöht das Level aller Teammitglieder um 1", + description: "Erhöht das Level aller Teammitglieder um 1.", }, "PokemonBaseStatBoosterModifierType": { description: "Erhöht den {{statName}} Basiswert des Trägers um 10%. Das Stapellimit erhöht sich, je höher dein IS-Wert ist.", }, "AllPokemonFullHpRestoreModifierType": { - description: "Stellt 100% der KP aller Pokémon her", + description: "Stellt 100% der KP aller Pokémon her.", }, "AllPokemonFullReviveModifierType": { - description: "Belebt alle kampunfähigen Pokémon wieder und stellt ihre KP vollständig wieder her", + description: "Belebt alle kampunfähigen Pokémon wieder und stellt ihre KP vollständig wieder her.", }, "MoneyRewardModifierType": { - description:"Gewährt einen {{moneyMultiplier}} Geldbetrag von (₽{{moneyAmount}})", + description:"Gewährt einen {{moneyMultiplier}} Geldbetrag von (₽{{moneyAmount}}).", extra: { "small": "kleinen", "moderate": "moderaten", @@ -81,60 +81,60 @@ export const modifierType: ModifierTypeTranslationEntries = { }, }, "ExpBoosterModifierType": { - description: "Erhöht die erhaltenen Erfahrungspunkte um {{boostPercent}}%", + description: "Erhöht die erhaltenen Erfahrungspunkte um {{boostPercent}}%.", }, "PokemonExpBoosterModifierType": { - description: "Erhöht die Menge der erhaltenen Erfahrungspunkte für den Träger um {{boostPercent}}%", + description: "Erhöht die Menge der erhaltenen Erfahrungspunkte für den Träger um {{boostPercent}}%.", }, "PokemonFriendshipBoosterModifierType": { description: "Erhöht den Freundschaftszuwachs pro Sieg um 50%.", }, "PokemonMoveAccuracyBoosterModifierType": { - description: "Erhöht die Genauigkeit der Angriffe um {{accuracyAmount}} (maximal 100)", + description: "Erhöht die Genauigkeit der Angriffe um {{accuracyAmount}} (maximal 100).", }, "PokemonMultiHitModifierType": { - description: "Attacken treffen ein weiteres mal mit einer Reduktion von 60/75/82,5% der Stärke", + description: "Attacken treffen ein weiteres mal mit einer Reduktion von 60/75/82,5% der Stärke.", }, "TmModifierType": { name: "TM{{moveId}} - {{moveName}}", - description: "Bringt einem Pokémon {{moveName}} bei", + description: "Bringt einem Pokémon {{moveName}} bei.", }, "TmModifierTypeWithInfo": { name: "TM{{moveId}} - {{moveName}}", - description: "Bringt einem Pokémon {{moveName}} bei\n(Halte C oder Shift für mehr Infos)", + description: "Bringt einem Pokémon {{moveName}} bei\n(Halte C oder Shift für mehr Infos).", }, "EvolutionItemModifierType": { - description: "Erlaubt es bestimmten Pokémon sich zu entwickeln", + description: "Erlaubt es bestimmten Pokémon sich zu entwickeln.", }, "FormChangeItemModifierType": { - description: "Erlaubt es bestimmten Pokémon ihre Form zu ändern", + description: "Erlaubt es bestimmten Pokémon ihre Form zu ändern.", }, "FusePokemonModifierType": { - description: "Fusioniert zwei Pokémon (überträgt die Fähigkeit, teilt Basiswerte und Typ auf, gemeinsamer Attackenpool)", + description: "Fusioniert zwei Pokémon (überträgt die Fähigkeit, teilt Basiswerte und Typ auf, gemeinsamer Attackenpool).", }, "TerastallizeModifierType": { name: "{{teraType}} Terra-Stück", - description: "{{teraType}} Terakristallisiert den Träger für bis zu 10 Kämpfe", + description: "{{teraType}} Terakristallisiert den Träger für bis zu 10 Kämpfe.", }, "ContactHeldItemTransferChanceModifierType": { description:"Beim Angriff besteht eine {{chancePercent}}%ige Chance, dass das getragene Item des Gegners gestohlen wird." }, "TurnHeldItemTransferModifierType": { - description: "Jede Runde erhält der Träger ein getragenes Item des Gegners", + description: "Jede Runde erhält der Träger ein getragenes Item des Gegners.", }, "EnemyAttackStatusEffectChanceModifierType": { - description: "Fügt Angriffen eine {{chancePercent}}%ige Chance hinzu, {{statusEffect}} zu verursachen", + description: "Fügt Angriffen eine {{chancePercent}}%ige Chance hinzu, {{statusEffect}} zu verursachen.", }, "EnemyEndureChanceModifierType": { - description: "Gibt den Träger eine {{chancePercent}}%ige Chance, einen Angriff zu überleben", + description: "Gibt den Träger eine {{chancePercent}}%ige Chance, einen Angriff zu überleben.", }, "RARE_CANDY": { name: "Sonderbonbon" }, "RARER_CANDY": { name: "Supersondererbonbon" }, - "MEGA_BRACELET": { name: "Mega-Armband", description: "Mega-Steine werden verfügbar" }, - "DYNAMAX_BAND": { name: "Dynamax-Band", description: "Dyna-Pilze werden verfügbar" }, - "TERA_ORB": { name: "Terakristall-Orb", description: "Tera-Stücke werden verfügbar" }, + "MEGA_BRACELET": { name: "Mega-Armband", description: "Mega-Steine werden verfügbar." }, + "DYNAMAX_BAND": { name: "Dynamax-Band", description: "Dyna-Pilze werden verfügbar."}, + "TERA_ORB": { name: "Terakristall-Orb", description: "Tera-Stücke werden verfügbar." }, "MAP": { name: "Karte", description: "Ermöglicht es dir, an einer Kreuzung dein Ziel zu wählen." }, @@ -151,7 +151,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "SACRED_ASH": { name: "Zauberasche" }, - "REVIVER_SEED": { name: "Belebersamen", description: "Belebt den Träger mit der Hälfte seiner KP wieder sollte er kampfunfähig werden" }, + "REVIVER_SEED": { name: "Belebersamen", description: "Belebt den Träger mit der Hälfte seiner KP wieder sollte er kampfunfähig werden." }, "ETHER": { name: "Äther" }, "MAX_ETHER": { name: "Top-Äther" }, @@ -166,12 +166,12 @@ export const modifierType: ModifierTypeTranslationEntries = { "SUPER_LURE": { name: "Super-Lockparfüm" }, "MAX_LURE": { name: "Top-Lockparfüm" }, - "MEMORY_MUSHROOM": { name: "Erinnerungspilz", description: "Lässt ein Pokémon eine vergessene Attacke wiedererlernen" }, + "MEMORY_MUSHROOM": { name: "Erinnerungspilz", description: "Lässt ein Pokémon eine vergessene Attacke wiedererlernen." }, - "EXP_SHARE": { name: "EP-Teiler", description: "Pokémon, die nicht am Kampf teilgenommen haben, bekommen 20% der Erfahrungspunkte eines Kampfteilnehmers" }, + "EXP_SHARE": { name: "EP-Teiler", description: "Pokémon, die nicht am Kampf teilgenommen haben, bekommen 20% der Erfahrungspunkte eines Kampfteilnehmers." }, "EXP_BALANCE": { name: "EP-Ausgleicher", description: "Gewichtet die in Kämpfen erhaltenen Erfahrungspunkte auf niedrigstufigere Gruppenmitglieder." }, - "OVAL_CHARM": { name: "Ovalpin", description: "Wenn mehrere Pokémon am Kampf teilnehmen, erhählt jeder von ihnen 10% extra Erfahrungspunkte" }, + "OVAL_CHARM": { name: "Ovalpin", description: "Wenn mehrere Pokémon am Kampf teilnehmen, erhählt jeder von ihnen 10% extra Erfahrungspunkte." }, "EXP_CHARM": { name: "EP-Pin" }, "SUPER_EXP_CHARM": { name: "Super-EP-Pin" }, @@ -182,62 +182,62 @@ export const modifierType: ModifierTypeTranslationEntries = { "SOOTHE_BELL": { name: "Sanftglocke" }, - "SOUL_DEW": { name: "Seelentau", description: "Erhöht den Einfluss des Wesens eines Pokemon auf seine Werte um 10% (additiv)" }, + "SOUL_DEW": { name: "Seelentau", description: "Erhöht den Einfluss des Wesens eines Pokemon auf seine Werte um 10% (additiv)." }, "NUGGET": { name: "Nugget" }, "BIG_NUGGET": { name: "Riesennugget" }, "RELIC_GOLD": { name: "Alter Dukat" }, - "AMULET_COIN": { name: "Münzamulett", description: "Erhöht das Preisgeld um 20%" }, - "GOLDEN_PUNCH": { name: "Goldschlag", description: "Gewährt Geld in Höhe von 50% des zugefügten Schadens" }, - "COIN_CASE": { name: "Münzkorb", description: "Erhalte nach jedem 10ten Kampf 10% Zinsen auf dein Geld" }, + "AMULET_COIN": { name: "Münzamulett", description: "Erhöht das Preisgeld um 20%." }, + "GOLDEN_PUNCH": { name: "Goldschlag", description: "Gewährt Geld in Höhe von 50% des zugefügten Schadens." }, + "COIN_CASE": { name: "Münzkorb", description: "Erhalte nach jedem 10ten Kampf 10% Zinsen auf dein Geld." }, - "LOCK_CAPSULE": { name: "Tresorkapsel", description: "Erlaubt es die Seltenheitsstufe der Items festzusetzen wenn diese neu gerollt werden" }, + "LOCK_CAPSULE": { name: "Tresorkapsel", description: "Erlaubt es die Seltenheitsstufe der Items festzusetzen wenn diese neu gerollt werden." }, "GRIP_CLAW": { name: "Griffklaue" }, "WIDE_LENS": { name: "Großlinse" }, "MULTI_LENS": { name: "Mehrfachlinse" }, - "HEALING_CHARM": { name: "Heilungspin", description: "Erhöht die Effektivität von Heilungsattacken sowie Heilitems um 10% (Beleber ausgenommen)" }, - "CANDY_JAR": { name: "Bonbonglas", description: "Erhöht die Anzahl der Level die ein Sonderbonbon erhöht um 1" }, + "HEALING_CHARM": { name: "Heilungspin", description: "Erhöht die Effektivität von Heilungsattacken sowie Heilitems um 10% (Beleber ausgenommen)." }, + "CANDY_JAR": { name: "Bonbonglas", description: "Erhöht die Anzahl der Level die ein Sonderbonbon erhöht um 1." }, - "BERRY_POUCH": { name: "Beerentüte", description: "Fügt eine 30% Chance hinzu, dass Beeren nicht verbraucht werden" }, + "BERRY_POUCH": { name: "Beerentüte", description: "Fügt eine 30% Chance hinzu, dass Beeren nicht verbraucht werden." }, - "FOCUS_BAND": { name: "Fokusband", description: "Fügt eine 10% Chance hinzu, dass Angriffe die zur Kampfunfähigkeit führen mit 1 KP überlebt werden" }, + "FOCUS_BAND": { name: "Fokusband", description: "Fügt eine 10% Chance hinzu, dass Angriffe die zur Kampfunfähigkeit führen mit 1 KP überlebt werden." }, - "QUICK_CLAW": { name: "Quick Claw", description: "Fügt eine 10% Change hinzu als erster anzugreifen. (Nach Prioritätsangriffen)" }, + "QUICK_CLAW": { name: "Quick Claw", description: "Fügt eine 10% Change hinzu als erster anzugreifen. (Nach Prioritätsangriffen)." }, - "KINGS_ROCK": { name: "King-Stein", description: "Fügt eine 10% Chance hinzu, dass der Gegner nach einem Angriff zurückschreckt" }, + "KINGS_ROCK": { name: "King-Stein", description: "Fügt eine 10% Chance hinzu, dass der Gegner nach einem Angriff zurückschreckt." }, - "LEFTOVERS": { name: "Überreste", description: "Heilt 1/16 der maximalen KP eines Pokémon pro Runde" }, - "SHELL_BELL": { name: "Muschelglocke", description: "Heilt den Anwender um 1/8 des von ihm zugefügten Schadens" }, + "LEFTOVERS": { name: "Überreste", description: "Heilt 1/16 der maximalen KP eines Pokémon pro Runde." }, + "SHELL_BELL": { name: "Muschelglocke", description: "Heilt den Anwender um 1/8 des von ihm zugefügten Schadens." }, - "TOXIC_ORB": { name: "Toxik-Orb", description: "Dieser bizarre Orb vergiftet seinen Träger im Kampf schwer" }, - "FLAME_ORB": { name: "Heiß-Orb", description: "Dieser bizarre Orb fügt seinem Träger im Kampf Verbrennungen zu" }, + "TOXIC_ORB": { name: "Toxik-Orb", description: "Dieser bizarre Orb vergiftet seinen Träger im Kampf schwer." }, + "FLAME_ORB": { name: "Heiß-Orb", description: "Dieser bizarre Orb fügt seinem Träger im Kampf Verbrennungen zu." }, "BATON": { name: "Stab", description: "Ermöglicht das Weitergeben von Effekten beim Wechseln von Pokémon, wodurch auch Fallen umgangen werden." }, - "SHINY_CHARM": { name: "Schillerpin", description: "Erhöht die Chance deutlich, dass ein wildes Pokémon ein schillernd ist" }, - "ABILITY_CHARM": { name: "Ability Charm", description: "Erhöht die Chance deutlich, dass ein wildes Pokémon eine versteckte Fähigkeit hat" }, + "SHINY_CHARM": { name: "Schillerpin", description: "Erhöht die Chance deutlich, dass ein wildes Pokémon ein schillernd ist." }, + "ABILITY_CHARM": { name: "Ability Charm", description: "Erhöht die Chance deutlich, dass ein wildes Pokémon eine versteckte Fähigkeit hat." }, - "IV_SCANNER": { name: "IS-Scanner", description: "Erlaubt es die IS-Werte von wilden Pokémon zu scannen.\n(2 IS-Werte pro Staplung. Die besten IS-Werte zuerst)" }, + "IV_SCANNER": { name: "IS-Scanner", description: "Erlaubt es die IS-Werte von wilden Pokémon zu scannen.\n(2 IS-Werte pro Staplung. Die besten IS-Werte zuerst)." }, "DNA_SPLICERS": { name: "DNS-Keil" }, "MINI_BLACK_HOLE": { name: "Mini schwarzes Loch" }, - "GOLDEN_POKEBALL": { name: "Goldener Pokéball", description: "Fügt eine zusätzliche Item-Auswahlmöglichkeit nach jedem Kampf hinzu" }, + "GOLDEN_POKEBALL": { name: "Goldener Pokéball", description: "Fügt eine zusätzliche Item-Auswahlmöglichkeit nach jedem Kampf hinzu." }, - "ENEMY_DAMAGE_BOOSTER": { name: "Schadensmarke", description: "Erhöht den Schaden um 5%" }, - "ENEMY_DAMAGE_REDUCTION": { name: "Schutzmarke", description: "Verringert den erhaltenen Schaden um 2,5%" }, - "ENEMY_HEAL": { name: "Wiederherstellungsmarke", description: "Heilt 2% der maximalen KP pro Runde" }, + "ENEMY_DAMAGE_BOOSTER": { name: "Schadensmarke", description: "Erhöht den Schaden um 5%." }, + "ENEMY_DAMAGE_REDUCTION": { name: "Schutzmarke", description: "Verringert den erhaltenen Schaden um 2,5%." }, + "ENEMY_HEAL": { name: "Wiederherstellungsmarke", description: "Heilt 2% der maximalen KP pro Runde." }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Giftmarke" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { "name": "Lähmungsmarke" }, "ENEMY_ATTACK_BURN_CHANCE": { "name": "Brandmarke" }, - "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { "name": "Vollheilungsmarke", "description": "Fügt eine 2,5%ige Chance hinzu, jede Runde einen Statuszustand zu heilen" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { "name": "Vollheilungsmarke", "description": "Fügt eine 2,5%ige Chance hinzu, jede Runde einen Statuszustand zu heilen." }, "ENEMY_ENDURE_CHANCE": { "name": "Ausdauer-Marke" }, - "ENEMY_FUSED_CHANCE": { "name": "Fusionsmarke", "description": "Fügt eine 1%ige Chance hinzu, dass ein wildes Pokémon eine Fusion ist" }, + "ENEMY_FUSED_CHANCE": { "name": "Fusionsmarke", "description": "Fügt eine 1%ige Chance hinzu, dass ein wildes Pokémon eine Fusion ist." }, }, TempBattleStatBoosterItem: { @@ -380,8 +380,8 @@ export const modifierType: ModifierTypeTranslationEntries = { "N_SOLARIZER": "Necrosol", "RUSTED_SWORD": "Rostiges Schwert", "RUSTED_SHIELD": "Rostiges Schild", - "ICY_REINS_OF_UNITY": "eisige Zügel des Bundes", - "SHADOW_REINS_OF_UNITY": "schattige Zügel des Bundes", + "ICY_REINS_OF_UNITY": "Eisige Zügel des Bundes", + "SHADOW_REINS_OF_UNITY": "Schattige Zügel des Bundes", "WELLSPRING_MASK": "Brunnenmaske", "HEARTHFLAME_MASK": "Ofenmaske", "CORNERSTONE_MASK": "Fundamentmaske", diff --git a/src/locales/de/party-ui-handler.ts b/src/locales/de/party-ui-handler.ts new file mode 100644 index 00000000000..103c6837889 --- /dev/null +++ b/src/locales/de/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "Einwechseln", + "SUMMARY": "Bericht", + "CANCEL": "Abbrechen", + "RELEASE": "Freilassen", + "APPLY": "Anwenden", + "TEACH": "Erlernen" +} as const; diff --git a/src/locales/de/pokemon.ts b/src/locales/de/pokemon.ts index 91b97052879..bd2ff964a9b 100644 --- a/src/locales/de/pokemon.ts +++ b/src/locales/de/pokemon.ts @@ -283,7 +283,7 @@ export const pokemon: SimpleTranslationEntries = { "ralts": "Trasla", "kirlia": "Kirlia", "gardevoir": "Gardevoir", - "surskit": "Geweiher", + "surskit": "Gehweiher", "masquerain": "Maskeregen", "shroomish": "Knilz", "breloom": "Kapilz", diff --git a/src/locales/de/save-slot-select-ui-handler.ts b/src/locales/de/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..fbbfebae6ee --- /dev/null +++ b/src/locales/de/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "Den ausgewählten Speicherstand überschreiben?", + "loading": "Läd...", + "wave": "Welle", + "lv": "Lvl", + "empty": "Leer", +} as const; diff --git a/src/locales/de/trainers.ts b/src/locales/de/trainers.ts index 6ac1abbcabf..b7d7ec01617 100644 --- a/src/locales/de/trainers.ts +++ b/src/locales/de/trainers.ts @@ -95,6 +95,7 @@ export const trainerClasses: SimpleTranslationEntries = { "rich_kid_female": "Rich Kid", "rich_kids": "Schnösel", "roughneck": "Raufbold", + "sailor": "Matrose", "scientist": "Forscher", "scientist_female": "Forscherin", "scientists": "Forscher", diff --git a/src/locales/en/achv.ts b/src/locales/en/achv.ts index 42b1995bcde..bf1bfc295e8 100644 --- a/src/locales/en/achv.ts +++ b/src/locales/en/achv.ts @@ -1,6 +1,7 @@ import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "Achievements", }, @@ -168,4 +169,102 @@ export const achv: AchievementTranslationEntries = { name: "Undefeated", description: "Beat the game in classic mode", }, + + "MONO_GEN_ONE": { + name: "The Original Rival", + description: "Complete the generation one only challenge.", + }, + "MONO_GEN_TWO": { + name: "Generation 1.5", + description: "Complete the generation two only challenge.", + }, + "MONO_GEN_THREE": { + name: "Too much water?", + description: "Complete the generation three only challenge.", + }, + "MONO_GEN_FOUR": { + name: "Is she really the hardest?", + description: "Complete the generation four only challenge.", + }, + "MONO_GEN_FIVE": { + name: "All Original", + description: "Complete the generation five only challenge.", + }, + "MONO_GEN_SIX": { + name: "Almost Royalty", + description: "Complete the generation six only challenge.", + }, + "MONO_GEN_SEVEN": { + name: "Only Technically", + description: "Complete the generation seven only challenge.", + }, + "MONO_GEN_EIGHT": { + name: "A Champion Time!", + description: "Complete the generation eight only challenge.", + }, + "MONO_GEN_NINE": { + name: "She was going easy on you", + description: "Complete the generation nine only challenge.", + }, + + "MonoType": { + description: "Complete the {{type}} monotype challenge.", + }, + "MONO_NORMAL": { + name: "Mono NORMAL", + }, + "MONO_FIGHTING": { + name: "I Know Kung Fu", + }, + "MONO_FLYING": { + name: "Mono FLYING", + }, + "MONO_POISON": { + name: "Kanto's Favourite", + }, + "MONO_GROUND": { + name: "Mono GROUND", + }, + "MONO_ROCK": { + name: "Brock Hard", + }, + "MONO_BUG": { + name: "Sting Like A Beedrill", + }, + "MONO_GHOST": { + name: "Who you gonna call?", + }, + "MONO_STEEL": { + name: "Mono STEEL", + }, + "MONO_FIRE": { + name: "Mono FIRE", + }, + "MONO_WATER": { + name: "When It Rains, It Pours", + }, + "MONO_GRASS": { + name: "Mono GRASS", + }, + "MONO_ELECTRIC": { + name: "Mono ELECTRIC", + }, + "MONO_PSYCHIC": { + name: "Mono PSYCHIC", + }, + "MONO_ICE": { + name: "Mono ICE", + }, + "MONO_DRAGON": { + name: "Mono DRAGON", + }, + "MONO_DARK": { + name: "It's just a phase", + }, + "MONO_FAIRY": { + name: "Mono FAIRY", + }, } as const; + +// Achievement translations for the when the player character is female (it for now uses the same translations as the male version) +export const PGFachv: AchievementTranslationEntries = PGMachv; diff --git a/src/locales/en/challenges.ts b/src/locales/en/challenges.ts new file mode 100644 index 00000000000..7401104e1a3 --- /dev/null +++ b/src/locales/en/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "Challenge Modifiers", + "start": "Start", + "illegalEvolution": "{{pokemon}} changed into an ineligble pokemon\nfor this challenge!", + "singleGeneration.name": "Mono Gen", + "singleGeneration.value.0": "Off", + "singleGeneration.desc.0": "You can only use pokemon from the chosen generation.", + "singleGeneration.value.1": "Gen 1", + "singleGeneration.desc.1": "You can only use pokemon from generation one.", + "singleGeneration.value.2": "Gen 2", + "singleGeneration.desc.2": "You can only use pokemon from generation two.", + "singleGeneration.value.3": "Gen 3", + "singleGeneration.desc.3": "You can only use pokemon from generation three.", + "singleGeneration.value.4": "Gen 4", + "singleGeneration.desc.4": "You can only use pokemon from generation four.", + "singleGeneration.value.5": "Gen 5", + "singleGeneration.desc.5": "You can only use pokemon from generation five.", + "singleGeneration.value.6": "Gen 6", + "singleGeneration.desc.6": "You can only use pokemon from generation six.", + "singleGeneration.value.7": "Gen 7", + "singleGeneration.desc.7": "You can only use pokemon from generation seven.", + "singleGeneration.value.8": "Gen 8", + "singleGeneration.desc.8": "You can only use pokemon from generation eight.", + "singleGeneration.value.9": "Gen 9", + "singleGeneration.desc.9": "You can only use pokemon from generation nine.", + "singleType.name": "Mono Type", + "singleType.value.0": "Off", + "singleType.desc.0": "You can only use pokemon of the chosen type.", + "singleType.value.1": "Normal", + "singleType.desc.1": "You can only use pokemon with the Normal type.", + "singleType.value.2": "Fighting", + "singleType.desc.2": "You can only use pokemon with the Fighting type.", + "singleType.value.3": "Flying", + "singleType.desc.3": "You can only use pokemon with the Flying type.", + "singleType.value.4": "Poison", + "singleType.desc.4": "You can only use pokemon with the Poison type.", + "singleType.value.5": "Ground", + "singleType.desc.5": "You can only use pokemon with the Ground type.", + "singleType.value.6": "Rock", + "singleType.desc.6": "You can only use pokemon with the Rock type.", + "singleType.value.7": "Bug", + "singleType.desc.7": "You can only use pokemon with the Bug type.", + "singleType.value.8": "Ghost", + "singleType.desc.8": "You can only use pokemon with the Ghost type.", + "singleType.value.9": "Steel", + "singleType.desc.9": "You can only use pokemon with the Steel type.", + "singleType.value.10": "Fire", + "singleType.desc.10": "You can only use pokemon with the Fire type.", + "singleType.value.11": "Water", + "singleType.desc.11": "You can only use pokemon with the Water type.", + "singleType.value.12": "Grass", + "singleType.desc.12": "You can only use pokemon with the Grass type.", + "singleType.value.13": "Electric", + "singleType.desc.13": "You can only use pokemon with the Electric type.", + "singleType.value.14": "Psychic", + "singleType.desc.14": "You can only use pokemon with the Psychic type.", + "singleType.value.15": "Ice", + "singleType.desc.15": "You can only use pokemon with the Ice type.", + "singleType.value.16": "Dragon", + "singleType.desc.16": "You can only use pokemon with the Dragon type.", + "singleType.value.17": "Dark", + "singleType.desc.17": "You can only use pokemon with the Dark type.", + "singleType.value.18": "Fairy", + "singleType.desc.18": "You can only use pokemon with the Fairy type.", +} as const; diff --git a/src/locales/en/config.ts b/src/locales/en/config.ts index 0891a6a4c10..89f809b266d 100644 --- a/src/locales/en/config.ts +++ b/src/locales/en/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -29,22 +31,26 @@ import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; +import { partyUiHandler } from "./party-ui-handler"; export const enConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const enConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -66,6 +73,7 @@ export const enConfig = { pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +81,6 @@ export const enConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, + partyUiHandler: partyUiHandler }; diff --git a/src/locales/en/dialogue.ts b/src/locales/en/dialogue.ts index c5b0d72d3d7..86167da696c 100644 --- a/src/locales/en/dialogue.ts +++ b/src/locales/en/dialogue.ts @@ -371,6 +371,18 @@ export const PGMdialogue: DialogueTranslationEntries = { 3: "Ow! I scorched the tip of my nose!" }, }, + "sailor": { + "encounter": { + 1: "Matey, you're walking the plank if you lose!", + 2: "Come on then! My sailor's pride is at stake!", + 3: "Ahoy there! Are you seasick?" + }, + "victory": { + 1: "Argh! Beaten by a kid!", + 2: "Your spirit sank me!", + 3: "I think it's me that's seasick..." + }, + }, "brock": { "encounter": { 1: "My expertise on Rock-type Pokémon will take you down! Come on!", @@ -2360,7 +2372,7 @@ export const PGMdoubleBattleDialogue: DialogueTranslationEntries = { }, "tate_liza_double": { "encounter": { - 1: `Tate: Are you suprised? + 1: `Tate: Are you surprised? $Liza: We are two gym leaders at once! $Tate: We are twins! $Liza: We dont need to talk to understand each other! @@ -2374,7 +2386,7 @@ export const PGMdoubleBattleDialogue: DialogueTranslationEntries = { }, "liza_tate_double": { "encounter": { - 1: `Liza: Hihihi... Are you suprised? + 1: `Liza: Hihihi... Are you surprised? $Tate: Yes, we are really two gym leaders at once! $Liza: This is my twin brother Tate! $Tate: And this is my twin sister Liza! diff --git a/src/locales/en/game-mode.ts b/src/locales/en/game-mode.ts new file mode 100644 index 00000000000..be342b4c390 --- /dev/null +++ b/src/locales/en/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "Classic", + "endless": "Endless", + "endlessSpliced": "Endless (Spliced)", + "dailyRun": "Daily Run", + "unknown": "Unknown", + "challenge": "Challenge", +} as const; diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index d43ac0983f4..03b8f22332d 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -45,8 +45,8 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", + "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "Players Online", - "empty":"Empty", "yes":"Yes", "no":"No", "disclaimer": "DISCLAIMER", diff --git a/src/locales/en/modifier-type.ts b/src/locales/en/modifier-type.ts index 0f7b83d2b3e..2a6923d82cd 100644 --- a/src/locales/en/modifier-type.ts +++ b/src/locales/en/modifier-type.ts @@ -8,7 +8,7 @@ export const modifierType: ModifierTypeTranslationEntries = { }, "AddVoucherModifierType": { name: "{{modifierCount}}x {{voucherTypeName}}", - description: "Receive {{voucherTypeName}} x{{modifierCount}}", + description: "Receive {{voucherTypeName}} x{{modifierCount}}.", }, "PokemonHeldItemModifierType": { extra: { @@ -17,63 +17,63 @@ export const modifierType: ModifierTypeTranslationEntries = { } }, "PokemonHpRestoreModifierType": { - description: "Restores {{restorePoints}} HP or {{restorePercent}}% HP for one Pokémon, whichever is higher", + description: "Restores {{restorePoints}} HP or {{restorePercent}}% HP for one Pokémon, whichever is higher.", extra: { - "fully": "Fully restores HP for one Pokémon", - "fullyWithStatus": "Fully restores HP for one Pokémon and heals any status ailment", + "fully": "Fully restores HP for one Pokémon.", + "fullyWithStatus": "Fully restores HP for one Pokémon and heals any status ailment.", } }, "PokemonReviveModifierType": { - description: "Revives one Pokémon and restores {{restorePercent}}% HP", + description: "Revives one Pokémon and restores {{restorePercent}}% HP.", }, "PokemonStatusHealModifierType": { - description: "Heals any status ailment for one Pokémon", + description: "Heals any status ailment for one Pokémon.", }, "PokemonPpRestoreModifierType": { - description: "Restores {{restorePoints}} PP for one Pokémon move", + description: "Restores {{restorePoints}} PP for one Pokémon move.", extra: { - "fully": "Restores all PP for one Pokémon move", + "fully": "Restores all PP for one Pokémon move.", } }, "PokemonAllMovePpRestoreModifierType": { - description: "Restores {{restorePoints}} PP for all of one Pokémon's moves", + description: "Restores {{restorePoints}} PP for all of one Pokémon's moves.", extra: { - "fully": "Restores all PP for all of one Pokémon's moves", + "fully": "Restores all PP for all of one Pokémon's moves.", } }, "PokemonPpUpModifierType": { - description: "Permanently increases PP for one Pokémon move by {{upPoints}} for every 5 maximum PP (maximum 3)", + description: "Permanently increases PP for one Pokémon move by {{upPoints}} for every 5 maximum PP (maximum 3).", }, "PokemonNatureChangeModifierType": { name: "{{natureName}} Mint", description: "Changes a Pokémon's nature to {{natureName}} and permanently unlocks the nature for the starter.", }, "DoubleBattleChanceBoosterModifierType": { - description: "Doubles the chance of an encounter being a double battle for {{battleCount}} battles", + description: "Doubles the chance of an encounter being a double battle for {{battleCount}} battles.", }, "TempBattleStatBoosterModifierType": { - description: "Increases the {{tempBattleStatName}} of all party members by 1 stage for 5 battles", + description: "Increases the {{tempBattleStatName}} of all party members by 1 stage for 5 battles.", }, "AttackTypeBoosterModifierType": { - description: "Increases the power of a Pokémon's {{moveType}}-type moves by 20%", + description: "Increases the power of a Pokémon's {{moveType}}-type moves by 20%.", }, "PokemonLevelIncrementModifierType": { - description: "Increases a Pokémon's level by 1", + description: "Increases a Pokémon's level by 1.", }, "AllPokemonLevelIncrementModifierType": { - description: "Increases all party members' level by 1", + description: "Increases all party members' level by 1.", }, "PokemonBaseStatBoosterModifierType": { description: "Increases the holder's base {{statName}} by 10%. The higher your IVs, the higher the stack limit.", }, "AllPokemonFullHpRestoreModifierType": { - description: "Restores 100% HP for all Pokémon", + description: "Restores 100% HP for all Pokémon.", }, "AllPokemonFullReviveModifierType": { - description: "Revives all fainted Pokémon, fully restoring HP", + description: "Revives all fainted Pokémon, fully restoring HP.", }, "MoneyRewardModifierType": { - description: "Grants a {{moneyMultiplier}} amount of money (₽{{moneyAmount}})", + description: "Grants a {{moneyMultiplier}} amount of money (₽{{moneyAmount}}).", extra: { "small": "small", "moderate": "moderate", @@ -81,62 +81,62 @@ export const modifierType: ModifierTypeTranslationEntries = { }, }, "ExpBoosterModifierType": { - description: "Increases gain of EXP. Points by {{boostPercent}}%", + description: "Increases gain of EXP. Points by {{boostPercent}}%.", }, "PokemonExpBoosterModifierType": { - description: "Increases the holder's gain of EXP. Points by {{boostPercent}}%", + description: "Increases the holder's gain of EXP. Points by {{boostPercent}}%.", }, "PokemonFriendshipBoosterModifierType": { - description: "Increases friendship gain per victory by 50%", + description: "Increases friendship gain per victory by 50%.", }, "PokemonMoveAccuracyBoosterModifierType": { - description: "Increases move accuracy by {{accuracyAmount}} (maximum 100)", + description: "Increases move accuracy by {{accuracyAmount}} (maximum 100).", }, "PokemonMultiHitModifierType": { - description: "Attacks hit one additional time at the cost of a 60/75/82.5% power reduction per stack respectively", + description: "Attacks hit one additional time at the cost of a 60/75/82.5% power reduction per stack respectively.", }, "TmModifierType": { name: "TM{{moveId}} - {{moveName}}", - description: "Teach {{moveName}} to a Pokémon", + description: "Teach {{moveName}} to a Pokémon.", }, "TmModifierTypeWithInfo": { name: "TM{{moveId}} - {{moveName}}", - description: "Teach {{moveName}} to a Pokémon\n(Hold C or Shift for more info)", + description: "Teach {{moveName}} to a Pokémon\n(Hold C or Shift for more info).", }, "EvolutionItemModifierType": { - description: "Causes certain Pokémon to evolve", + description: "Causes certain Pokémon to evolve.", }, "FormChangeItemModifierType": { - description: "Causes certain Pokémon to change form", + description: "Causes certain Pokémon to change form.", }, "FusePokemonModifierType": { - description: "Combines two Pokémon (transfers Ability, splits base stats and types, shares move pool)", + description: "Combines two Pokémon (transfers Ability, splits base stats and types, shares move pool).", }, "TerastallizeModifierType": { name: "{{teraType}} Tera Shard", - description: "{{teraType}} Terastallizes the holder for up to 10 battles", + description: "{{teraType}} Terastallizes the holder for up to 10 battles.", }, "ContactHeldItemTransferChanceModifierType": { - description: "Upon attacking, there is a {{chancePercent}}% chance the foe's held item will be stolen", + description: "Upon attacking, there is a {{chancePercent}}% chance the foe's held item will be stolen.", }, "TurnHeldItemTransferModifierType": { - description: "Every turn, the holder acquires one held item from the foe", + description: "Every turn, the holder acquires one held item from the foe.", }, "EnemyAttackStatusEffectChanceModifierType": { - description: "Adds a {{chancePercent}}% chance to inflict {{statusEffect}} with attack moves", + description: "Adds a {{chancePercent}}% chance to inflict {{statusEffect}} with attack moves.", }, "EnemyEndureChanceModifierType": { - description: "Adds a {{chancePercent}}% chance of enduring a hit", + description: "Adds a {{chancePercent}}% chance of enduring a hit.", }, "RARE_CANDY": { name: "Rare Candy" }, "RARER_CANDY": { name: "Rarer Candy" }, - "MEGA_BRACELET": { name: "Mega Bracelet", description: "Mega Stones become available" }, - "DYNAMAX_BAND": { name: "Dynamax Band", description: "Max Mushrooms become available" }, - "TERA_ORB": { name: "Tera Orb", description: "Tera Shards become available" }, + "MEGA_BRACELET": { name: "Mega Bracelet", description: "Mega Stones become available." }, + "DYNAMAX_BAND": { name: "Dynamax Band", description: "Max Mushrooms become available." }, + "TERA_ORB": { name: "Tera Orb", description: "Tera Shards become available." }, - "MAP": { name: "Map", description: "Allows you to choose your destination at a crossroads" }, + "MAP": { name: "Map", description: "Allows you to choose your destination at a crossroads." }, "POTION": { name: "Potion" }, "SUPER_POTION": { name: "Super Potion" }, @@ -151,7 +151,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "SACRED_ASH": { name: "Sacred Ash" }, - "REVIVER_SEED": { name: "Reviver Seed", description: "Revives the holder for 1/2 HP upon fainting" }, + "REVIVER_SEED": { name: "Reviver Seed", description: "Revives the holder for 1/2 HP upon fainting." }, "ETHER": { name: "Ether" }, "MAX_ETHER": { name: "Max Ether" }, @@ -166,12 +166,12 @@ export const modifierType: ModifierTypeTranslationEntries = { "SUPER_LURE": { name: "Super Lure" }, "MAX_LURE": { name: "Max Lure" }, - "MEMORY_MUSHROOM": { name: "Memory Mushroom", description: "Recall one Pokémon's forgotten move" }, + "MEMORY_MUSHROOM": { name: "Memory Mushroom", description: "Recall one Pokémon's forgotten move." }, - "EXP_SHARE": { name: "EXP. All", description: "Non-participants receive 20% of a single participant's EXP. Points" }, - "EXP_BALANCE": { name: "EXP. Balance", description: "Weighs EXP. Points received from battles towards lower-leveled party members" }, + "EXP_SHARE": { name: "EXP. All", description: "Non-participants receive 20% of a single participant's EXP. Points." }, + "EXP_BALANCE": { name: "EXP. Balance", description: "Weighs EXP. Points received from battles towards lower-leveled party members." }, - "OVAL_CHARM": { name: "Oval Charm", description: "When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP" }, + "OVAL_CHARM": { name: "Oval Charm", description: "When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP." }, "EXP_CHARM": { name: "EXP. Charm" }, "SUPER_EXP_CHARM": { name: "Super EXP. Charm" }, @@ -182,62 +182,62 @@ export const modifierType: ModifierTypeTranslationEntries = { "SOOTHE_BELL": { name: "Soothe Bell" }, - "SOUL_DEW": { name: "Soul Dew", description: "Increases the influence of a Pokémon's nature on its stats by 10% (additive)" }, + "SOUL_DEW": { name: "Soul Dew", description: "Increases the influence of a Pokémon's nature on its stats by 10% (additive)." }, "NUGGET": { name: "Nugget" }, "BIG_NUGGET": { name: "Big Nugget" }, "RELIC_GOLD": { name: "Relic Gold" }, - "AMULET_COIN": { name: "Amulet Coin", description: "Increases money rewards by 20%" }, - "GOLDEN_PUNCH": { name: "Golden Punch", description: "Grants 50% of direct damage inflicted as money" }, - "COIN_CASE": { name: "Coin Case", description: "After every 10th battle, receive 10% of your money in interest" }, + "AMULET_COIN": { name: "Amulet Coin", description: "Increases money rewards by 20%." }, + "GOLDEN_PUNCH": { name: "Golden Punch", description: "Grants 50% of direct damage inflicted as money." }, + "COIN_CASE": { name: "Coin Case", description: "After every 10th battle, receive 10% of your money in interest." }, - "LOCK_CAPSULE": { name: "Lock Capsule", description: "Allows you to lock item rarities when rerolling items" }, + "LOCK_CAPSULE": { name: "Lock Capsule", description: "Allows you to lock item rarities when rerolling items." }, "GRIP_CLAW": { name: "Grip Claw" }, "WIDE_LENS": { name: "Wide Lens" }, "MULTI_LENS": { name: "Multi Lens" }, - "HEALING_CHARM": { name: "Healing Charm", description: "Increases the effectiveness of HP restoring moves and items by 10% (excludes Revives)" }, - "CANDY_JAR": { name: "Candy Jar", description: "Increases the number of levels added by Rare Candy items by 1" }, + "HEALING_CHARM": { name: "Healing Charm", description: "Increases the effectiveness of HP restoring moves and items by 10% (excludes Revives)." }, + "CANDY_JAR": { name: "Candy Jar", description: "Increases the number of levels added by Rare Candy items by 1." }, - "BERRY_POUCH": { name: "Berry Pouch", description: "Adds a 30% chance that a used berry will not be consumed" }, + "BERRY_POUCH": { name: "Berry Pouch", description: "Adds a 30% chance that a used berry will not be consumed." }, - "FOCUS_BAND": { name: "Focus Band", description: "Adds a 10% chance to survive with 1 HP after being damaged enough to faint" }, + "FOCUS_BAND": { name: "Focus Band", description: "Adds a 10% chance to survive with 1 HP after being damaged enough to faint." }, - "QUICK_CLAW": { name: "Quick Claw", description: "Adds a 10% chance to move first regardless of speed (after priority)" }, + "QUICK_CLAW": { name: "Quick Claw", description: "Adds a 10% chance to move first regardless of speed (after priority)." }, - "KINGS_ROCK": { name: "King's Rock", description: "Adds a 10% chance an attack move will cause the opponent to flinch" }, + "KINGS_ROCK": { name: "King's Rock", description: "Adds a 10% chance an attack move will cause the opponent to flinch." }, - "LEFTOVERS": { name: "Leftovers", description: "Heals 1/16 of a Pokémon's maximum HP every turn" }, - "SHELL_BELL": { name: "Shell Bell", description: "Heals 1/8 of a Pokémon's dealt damage" }, + "LEFTOVERS": { name: "Leftovers", description: "Heals 1/16 of a Pokémon's maximum HP every turn." }, + "SHELL_BELL": { name: "Shell Bell", description: "Heals 1/8 of a Pokémon's dealt damage." }, - "TOXIC_ORB": { name: "Toxic Orb", description: "Badly poisons its holder at the end of the turn if they do not have a status condition already" }, - "FLAME_ORB": { name: "Flame Orb", description: "Burns its holder at the end of the turn if they do not have a status condition already" }, + "TOXIC_ORB": { name: "Toxic Orb", description: "It's a bizarre orb that exudes toxins when touched and will badly poison the holder during battle." }, + "FLAME_ORB": { name: "Flame Orb", description: "It's a bizarre orb that gives off heat when touched and will affect the holder with a burn during battle." }, - "BATON": { name: "Baton", description: "Allows passing along effects when switching Pokémon, which also bypasses traps" }, + "BATON": { name: "Baton", description: "Allows passing along effects when switching Pokémon, which also bypasses traps." }, - "SHINY_CHARM": { name: "Shiny Charm", description: "Dramatically increases the chance of a wild Pokémon being Shiny" }, - "ABILITY_CHARM": { name: "Ability Charm", description: "Dramatically increases the chance of a wild Pokémon having a Hidden Ability" }, + "SHINY_CHARM": { name: "Shiny Charm", description: "Dramatically increases the chance of a wild Pokémon being Shiny." }, + "ABILITY_CHARM": { name: "Ability Charm", description: "Dramatically increases the chance of a wild Pokémon having a Hidden Ability." }, - "IV_SCANNER": { name: "IV Scanner", description: "Allows scanning the IVs of wild Pokémon. 2 IVs are revealed per stack. The best IVs are shown first" }, + "IV_SCANNER": { name: "IV Scanner", description: "Allows scanning the IVs of wild Pokémon. 2 IVs are revealed per stack. The best IVs are shown first." }, "DNA_SPLICERS": { name: "DNA Splicers" }, "MINI_BLACK_HOLE": { name: "Mini Black Hole" }, - "GOLDEN_POKEBALL": { name: "Golden Poké Ball", description: "Adds 1 extra item option at the end of every battle" }, + "GOLDEN_POKEBALL": { name: "Golden Poké Ball", description: "Adds 1 extra item option at the end of every battle." }, - "ENEMY_DAMAGE_BOOSTER": { name: "Damage Token", description: "Increases damage by 5%" }, - "ENEMY_DAMAGE_REDUCTION": { name: "Protection Token", description: "Reduces incoming damage by 2.5%" }, - "ENEMY_HEAL": { name: "Recovery Token", description: "Heals 2% of max HP every turn" }, + "ENEMY_DAMAGE_BOOSTER": { name: "Damage Token", description: "Increases damage by 5%." }, + "ENEMY_DAMAGE_REDUCTION": { name: "Protection Token", description: "Reduces incoming damage by 2.5%." }, + "ENEMY_HEAL": { name: "Recovery Token", description: "Heals 2% of max HP every turn." }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" }, - "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 2.5% chance every turn to heal a status condition" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 2.5% chance every turn to heal a status condition." }, "ENEMY_ENDURE_CHANCE": { name: "Endure Token" }, - "ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion" }, + "ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion." }, }, TempBattleStatBoosterItem: { "x_attack": "X Attack", diff --git a/src/locales/en/party-ui-handler.ts b/src/locales/en/party-ui-handler.ts new file mode 100644 index 00000000000..9d3c7baa9ae --- /dev/null +++ b/src/locales/en/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "Send Out", + "SUMMARY": "Summary", + "CANCEL": "Cancel", + "RELEASE": "Release", + "APPLY": "Apply", + "TEACH": "Teach" +} as const; diff --git a/src/locales/en/save-slot-select-ui-handler.ts b/src/locales/en/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..5aaa675fc4d --- /dev/null +++ b/src/locales/en/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "Overwrite the data in the selected slot?", + "loading": "Loading...", + "wave": "Wave", + "lv": "Lv", + "empty": "Empty", +} as const; diff --git a/src/locales/en/starter-select-ui-handler.ts b/src/locales/en/starter-select-ui-handler.ts index 857ba4d805c..f001c621cc4 100644 --- a/src/locales/en/starter-select-ui-handler.ts +++ b/src/locales/en/starter-select-ui-handler.ts @@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "selectMoveSwapWith": "Select a move to swap with", "unlockPassive": "Unlock Passive", "reduceCost": "Reduce Cost", - "cycleShiny": "R: Cycle Shiny", - "cycleForm": "F: Cycle Form", - "cycleGender": "G: Cycle Gender", - "cycleAbility": "E: Cycle Ability", - "cycleNature": "N: Cycle Nature", - "cycleVariant": "V: Cycle Variant", + "cycleShiny": ": Cycle Shiny", + "cycleForm": ": Cycle Form", + "cycleGender": ": Cycle Gender", + "cycleAbility": ": Cycle Ability", + "cycleNature": ": Cycle Nature", + "cycleVariant": ": Cycle Variant", "enablePassive": "Enable Passive", "disablePassive": "Disable Passive", "locked": "Locked", diff --git a/src/locales/en/trainers.ts b/src/locales/en/trainers.ts index cd6f78ccc13..701980f8d37 100644 --- a/src/locales/en/trainers.ts +++ b/src/locales/en/trainers.ts @@ -95,6 +95,7 @@ export const trainerClasses: SimpleTranslationEntries = { "rich_kid_female": "Rich Kid", "rich_kids": "Rich Kids", "roughneck": "Roughneck", + "sailor": "Sailor", "scientist": "Scientist", "scientist_female": "Scientist", "scientists": "Scientists", diff --git a/src/locales/es/achv.ts b/src/locales/es/achv.ts index 071c0cbb860..8d9ebc7d457 100644 --- a/src/locales/es/achv.ts +++ b/src/locales/es/achv.ts @@ -1,6 +1,7 @@ import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "Logros", }, @@ -168,4 +169,102 @@ export const achv: AchievementTranslationEntries = { name: "Imbatible", description: "Completa el juego en modo clásico.", }, + + "MONO_GEN_ONE": { + name: "The Original Rival", + description: "Complete the generation one only challenge.", + }, + "MONO_GEN_TWO": { + name: "Generation 1.5", + description: "Complete the generation two only challenge.", + }, + "MONO_GEN_THREE": { + name: "Too much water?", + description: "Complete the generation three only challenge.", + }, + "MONO_GEN_FOUR": { + name: "Is she really the hardest?", + description: "Complete the generation four only challenge.", + }, + "MONO_GEN_FIVE": { + name: "All Original", + description: "Complete the generation five only challenge.", + }, + "MONO_GEN_SIX": { + name: "Almost Royalty", + description: "Complete the generation six only challenge.", + }, + "MONO_GEN_SEVEN": { + name: "Only Technically", + description: "Complete the generation seven only challenge.", + }, + "MONO_GEN_EIGHT": { + name: "A Champion Time!", + description: "Complete the generation eight only challenge.", + }, + "MONO_GEN_NINE": { + name: "She was going easy on you", + description: "Complete the generation nine only challenge.", + }, + + "MonoType": { + description: "Complete the {{type}} monotype challenge.", + }, + "MONO_NORMAL": { + name: "Mono NORMAL", + }, + "MONO_FIGHTING": { + name: "I Know Kung Fu", + }, + "MONO_FLYING": { + name: "Mono FLYING", + }, + "MONO_POISON": { + name: "Kanto's Favourite", + }, + "MONO_GROUND": { + name: "Mono GROUND", + }, + "MONO_ROCK": { + name: "Brock Hard", + }, + "MONO_BUG": { + name: "Sting Like A Beedrill", + }, + "MONO_GHOST": { + name: "Who you gonna call?", + }, + "MONO_STEEL": { + name: "Mono STEEL", + }, + "MONO_FIRE": { + name: "Mono FIRE", + }, + "MONO_WATER": { + name: "When It Rains, It Pours", + }, + "MONO_GRASS": { + name: "Mono GRASS", + }, + "MONO_ELECTRIC": { + name: "Mono ELECTRIC", + }, + "MONO_PSYCHIC": { + name: "Mono PSYCHIC", + }, + "MONO_ICE": { + name: "Mono ICE", + }, + "MONO_DRAGON": { + name: "Mono DRAGON", + }, + "MONO_DARK": { + name: "It's just a phase", + }, + "MONO_FAIRY": { + name: "Mono FAIRY", + }, } as const; + +// Achievement translations for the when the player character is female (it for now uses the same translations as the male version) +export const PGFachv: AchievementTranslationEntries = PGMachv; diff --git a/src/locales/es/battle.ts b/src/locales/es/battle.ts index c4d79cfdb93..4f60ab28d8a 100644 --- a/src/locales/es/battle.ts +++ b/src/locales/es/battle.ts @@ -18,11 +18,11 @@ export const battle: SimpleTranslationEntries = { "partyFull": "Tu equipo esta completo.\n¿Quieres liberar un Pokémon para meter a {{pokemonName}}?", "pokemon": "Pokémon", "sendOutPokemon": "¡Adelante, {{pokemonName}}!", - "hitResultCriticalHit": "!Un golpe crítico!", - "hitResultSuperEffective": "!Es supereficaz!", + "hitResultCriticalHit": "¡Un golpe crítico!", + "hitResultSuperEffective": "¡Es supereficaz!", "hitResultNotVeryEffective": "No es muy eficaz…", "hitResultNoEffect": "No afecta a {{pokemonName}}!", - "hitResultOneHitKO": "!KO en 1 golpe!", + "hitResultOneHitKO": "¡KO en 1 golpe!", "attackFailed": "¡Pero ha fallado!", "attackHitsCount": "N.º de golpes: {{count}}.", "expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.", @@ -56,9 +56,9 @@ export const battle: SimpleTranslationEntries = { "skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?", "eggHatching": "¿Y esto?", "ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?", - "wildPokemonWithAffix": "Wild {{pokemonName}}", - "foePokemonWithAffix": "Foe {{pokemonName}}", - "useMove": "{{pokemonNameWithAffix}} used {{moveName}}!", - "drainMessage": "{{pokemonName}} had its\nenergy drained!", - "regainHealth": "{{pokemonName}} regained\nhealth!" + "wildPokemonWithAffix": "El {{pokemonName}} salvaje", + "foePokemonWithAffix": "El {{pokemonName}} enemigo", + "useMove": "¡{{pokemonNameWithAffix}} usó {{moveName}}!", + "drainMessage": "¡{{pokemonName}} tuvo su\nenergía absorbida!", + "regainHealth": "¡{{pokemonName}} recuperó\nPS!" } as const; diff --git a/src/locales/es/challenges.ts b/src/locales/es/challenges.ts new file mode 100644 index 00000000000..6c994e5f4b3 --- /dev/null +++ b/src/locales/es/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "Parámetros de Desafíos", + "points": "Malas Ideas", + "confirm_start": "¿Continuar con estos desafíos?", + "singleGeneration.name": "Monogeneración", + "singleGeneration.value.0": "No", + "singleGeneration.desc.0": "Solo puedes usar Pokémon de la generación elegida.", + "singleGeneration.value.1": "Gen 1", + "singleGeneration.desc.1": "Solo puedes usar Pokémon de primera generación.", + "singleGeneration.value.2": "Gen 2", + "singleGeneration.desc.2": "Solo puedes usar Pokémon de segunda generación.", + "singleGeneration.value.3": "Gen 3", + "singleGeneration.desc.3": "Solo puedes usar Pokémon de tercera generación.", + "singleGeneration.value.4": "Gen 4", + "singleGeneration.desc.4": "Solo puedes usar Pokémon de cuarta generación.", + "singleGeneration.value.5": "Gen 5", + "singleGeneration.desc.5": "Solo puedes usar Pokémon de quinta generación.", + "singleGeneration.value.6": "Gen 6", + "singleGeneration.desc.6": "Solo puedes usar Pokémon de sexta generación.", + "singleGeneration.value.7": "Gen 7", + "singleGeneration.desc.7": "Solo puedes usar Pokémon de séptima generación.", + "singleGeneration.value.8": "Gen 8", + "singleGeneration.desc.8": "Solo puedes usar Pokémon de octava generación.", + "singleGeneration.value.9": "Gen 9", + "singleGeneration.desc.9": "Solo puedes usar Pokémon de novena generación.", + "singleType.name": "Monotipo", + "singleType.value.0": "No", + "singleType.desc.0": "Solo puedes usar Pokémon del tipo elegido", + "singleType.value.1": "Normal", + "singleType.desc.1": "Solo puedes usar Pokémon de tipo Normal.", + "singleType.value.2": "Lucha", + "singleType.desc.2": "Solo puedes usar Pokémon de tipo Lucha.", + "singleType.value.3": "Volador", + "singleType.desc.3": "Solo puedes usar Pokémon de tipo Volador.", + "singleType.value.4": "Veneno", + "singleType.desc.4": "Solo puedes usar Pokémon de tipo Veneno.", + "singleType.value.5": "Tierra", + "singleType.desc.5": "Solo puedes usar Pokémon de tipo Tierra.", + "singleType.value.6": "Roca", + "singleType.desc.6": "Solo puedes usar Pokémon de tipo Roca.", + "singleType.value.7": "Bicho", + "singleType.desc.7": "Solo puedes usar Pokémon de tipo Bicho.", + "singleType.value.8": "Fantasma", + "singleType.desc.8": "Solo puedes usar Pokémon de tipo Fantasma.", + "singleType.value.9": "Acero", + "singleType.desc.9": "Solo puedes usar Pokémon de tipo Acero.", + "singleType.value.10": "Fuego", + "singleType.desc.10": "Solo puedes usar Pokémon de tipo Fuego.", + "singleType.value.11": "Agua", + "singleType.desc.11": "Solo puedes usar Pokémon de tipo Agua.", + "singleType.value.12": "Planta", + "singleType.desc.12": "Solo puedes usar Pokémon de tipo Planta.", + "singleType.value.13": "Eléctrico", + "singleType.desc.13": "Solo puedes usar Pokémon de tipo Eléctrico.", + "singleType.value.14": "Psíquico", + "singleType.desc.14": "Solo puedes usar Pokémon de tipo Psíquico.", + "singleType.value.15": "Hielo", + "singleType.desc.15": "Solo puedes usar Pokémon de tipo Hielo.", + "singleType.value.16": "Dragón", + "singleType.desc.16": "Solo puedes usar Pokémon de tipo Dragón.", + "singleType.value.17": "Siniestro", + "singleType.desc.17": "Solo puedes usar Pokémon de tipo Siniestro.", + "singleType.value.18": "Hada", + "singleType.desc.18": "Solo puedes usar Pokémon de tipo Hada.", +} as const; diff --git a/src/locales/es/config.ts b/src/locales/es/config.ts index 7e1935a23a0..8b482de5c78 100644 --- a/src/locales/es/config.ts +++ b/src/locales/es/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -29,22 +31,26 @@ import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; +import { partyUiHandler } from "./party-ui-handler"; export const esConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const esConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -66,6 +73,7 @@ export const esConfig = { pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +81,6 @@ export const esConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, + partyUiHandler: partyUiHandler }; diff --git a/src/locales/es/dialogue.ts b/src/locales/es/dialogue.ts index faabab3077d..b27f5a7570c 100644 --- a/src/locales/es/dialogue.ts +++ b/src/locales/es/dialogue.ts @@ -4,104 +4,104 @@ import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/plugins export const PGMdialogue: DialogueTranslationEntries = { "youngster": { "encounter": { - 1: "Hey, wanna battle?", - 2: "Are you a new trainer too?", - 3: "Hey, I haven't seen you before. Let's battle!", - 4: "I just lost, so I'm trying to find more Pokémon.\nWait! You look weak! Come on, let's battle!", - 5: "Have we met or not? I don't really remember. Well, I guess it's nice to meet you anyway!", - 6: "All right! Let's go!", - 7: "All right! Here I come! I'll show you my power!", - 8: "Haw haw haw... I'll show you how hawesome my Pokémon are!", - 9: "No need to waste time saying hello. Bring it on whenever you're ready!", - 10: "Don't let your guard down, or you may be crying when a kid beats you.", - 11: "I've raised my Pokémon with great care. You're not allowed to hurt them!", - 12: "Glad you made it! It won't be an easy job from here.", - 13: "The battles continue forever! Welcome to the world with no end!" + 1: "Hey, ¿quieres luchar?", + 2: "¿También eres un entrenador novato?", + 3: "No te había visto antes. ¡Vamos a luchar!", + 4: "Perdí y estoy intentando buscar nuevos Pokémon.\n¡Espera, pareces débil! ¡Vamos, a luchar!", + 5: "¿Nos conocimos o no? Ni me acuerdo. ¡Supongo que es un gusto conocerte!", + 6: "¡Venga, vamos!", + 7: "¡Allá voy! ¡Te enseñaré mi poder!", + 8: "¡Ja ja ja! ¡Te enseñaré lo jimpresionante que es mi equipo!", + 9: "No pierdas tiempo saludando. ¡Adelante, cuando estés listo!", + 10: "No bajes la guardia o llorarás porque un niño te ganó.", + 11: "He cuidado a mis Pokémon con cariño. ¡Prohibido hacerles daño!", + 12: "¡Encantado de que lo lograses! A partir de aquí no será fácil.", + 13: "¡Las batallas continúan para siempre! ¡Bienvenido al mundo sin fin!" }, "victory": { - 1: "Wow! You're strong!", - 2: "I didn't stand a chance, huh?", - 3: "I'll find you again when I'm older and beat you!", - 4: "Ugh. I don't have any more Pokémon.", - 5: "No way… NO WAY! How could I lose again…", - 6: "No! I lost!", - 7: "Whoa! You are incredible! I'm amazed and surprised!", - 8: "Could it be… How… My Pokémon and I are the strongest, though…", - 9: "I won't lose next time! Let's battle again sometime!", - 10: "Sheesh! Can't you see that I'm just a kid! It wasn't fair of you to go all out like that!", - 11: "Your Pokémon are more amazing! Trade with me!", - 12: "I got a little carried away earlier, but what job was I talking about?", - 13: "Ahaha! There it is! That's right! You're already right at home in this world!" + 1: "¡Guau! ¡Eres fuerte!", + 2: "¿No tuve oportunidad, eh?", + 3: "¡Cuando sea mayor te encontraré y te ganaré!", + 4: "Ay. No tengo más Pokémon.", + 5: "Imposible… ¡IMPOSIBLE! Cómo pude perder de nuevo…", + 6: "¡No! ¡Perdí!", + 7: "¡Guau! ¡Eres increíble! ¡Estoy alucinado y sorprendido!", + 8: "Puede ser… Cómo… Aunque mis Pokémon y yo somos los más fuertes…", + 9: "¡No perderé a la próxima! ¡Luchemos otra vez pronto!", + 10: "¡Oye! ¡No ves que solo soy un niño! ¡No es justo que vayas así conmigo!", + 11: "¡Tus Pokémon molan más! ¡Intercámbiamelos!", + 12: "Me perdí antes pero, ¿de qué tarea estaba hablando antes?", + 13: "¡Jajaja! ¡Esa es! ¡Correcto! ¡Ya te sientes como en casa en este mundo!" } }, "lass": { "encounter": { - 1: "Let's have a battle, shall we?", - 2: "You look like a new trainer. Let's have a battle!", - 3: "I don't recognize you. How about a battle?", - 4: "Let's have a fun Pokémon battle!", - 5: "I'll show you the ropes of how to really use Pokémon!", - 6: "A serious battle starts from a serious beginning! Are you sure you're ready?", - 7: "You're only young once. And you only get one shot at a given battle. Soon, you'll be nothing but a memory.", - 8: "You'd better go easy on me, OK? Though I'll be seriously fighting!", - 9: "School is boring. I've got nothing to do. Yawn. I'm only battling to kill the time." + 1: "¿Luchemos, podría ser?", + 2: "Pareces novato. ¡Luchemos!", + 3: "No te reconozco. ¿Un combate?", + 4: "¡Tengamos un combate Pokémon divertido!", + 5: "¡Te enseñaré lo básico de cómo entrenar Pokémon!", + 6: "¡Un combate serio empieza por un comienzo serio! ¿Seguro que estás listo?", + 7: "Solo se es joven una vez. Y solo tienes una oportunidad en una batalla. Pronto, solo serás un recuerdo.", + 8: "Asegúrate de ir fácil conmigo, ¿vale? ¡Pero seré seria luchando!", + 9: "El colegio es aburrido. No hay nada que hacer. Uaa. Solo lucho para pasar el tiempo." }, "victory": { - 1: "That was impressive! I've got a lot to learn.", - 2: "I didn't think you'd beat me that bad…", - 3: "I hope we get to have a rematch some day.", - 4: "That was pretty amazingly fun! You've totally exhausted me…", - 5: "You actually taught me a lesson! You're pretty amazing!", - 6: "Seriously, I lost. That is, like, seriously depressing, but you were seriously cool.", - 7: "I don't need memories like this. Deleting memory…", - 8: "Hey! I told you to go easy on me! Still, you're pretty cool when you're serious.", - 9: "I'm actually getting tired of battling… There's gotta be something new to do…" + 1: "¡Impresionante! Tengo mucho que aprender.", + 2: "No pensé que me vencerías así…", + 3: "Espero la revancha algún día.", + 4: "¡Fue increíblemente divertido! Me dejaste cansada…", + 5: "¡Me enseñaste una lección! ¡Eres increíble!", + 6: "En serio, he perdido. O sea, es seriamente decepcionante, pero tú eres realmente guay.", + 7: "No necesito estos recuerdos. Borrando recuerdos…", + 8: "¡Te dije que fueses fácil conmigo! Aun así, me gusta cuando eres serio.", + 9: "Me canso de luchar… Habrá algo nuevo que hacer…" } }, "breeder": { "encounter": { - 1: "Obedient Pokémon, selfish Pokémon… Pokémon have unique characteristics.", - 2: "Even though my upbringing and behavior are poor, I've raised my Pokémon well.", - 3: "Hmm, do you discipline your Pokémon? Pampering them too much is no good.", + 1: "Pokémon obedientes, Pokémon egoístas… Los Pokémon tienen características únicas.", + 2: "Aunque tengo descendencia y comportamiento pobre, he cuidado muy bien a mis Pokémon.", + 3: "¿Tienes disciplina con tus Pokémon? Malcriarlos mucho no es bueno.", }, "victory": { - 1: "It is important to nurture and train each Pokémon's characteristics.", - 2: "Unlike my diabolical self, these are some good Pokémon.", - 3: "Too much praise can spoil both Pokémon and people.", + 1: "Es importante cuidar y mimar todas las características de los Pokémon.", + 2: "No como mi diabólica personalidad, mis Pokémon son muy buenos.", + 3: "Malcriar puede arruinar a los Pokémon y a los humanos.", }, "defeat": { - 1: "You should not get angry at your Pokémon, even if you lose a battle.", - 2: "Right? Pretty good Pokémon, huh? I'm suited to raising things.", - 3: "No matter how much you love your Pokémon, you still have to discipline them when they misbehave." + 1: "No deberías enfadarte con tu Pokémon, aún tras un combate perdido.", + 2: "¿Eh? ¿Buen Pokémon? Me acostumbro a cuidarlos.", + 3: "No importa el cariño que le tengas a tus Pokémon, tienes que ser serio si se portan mal." } }, "breeder_female": { "encounter": { - 1: "Pokémon never betray you. They return all the love you give them.", - 2: "Shall I give you a tip for training good Pokémon?", - 3: "I have raised these very special Pokémon using a special method." + 1: "Los Pokémon nunca te traicionan, te devuelven el amor que les diste.", + 2: "¿Puedo darte un consejo para entrenar bien tus Pokémon?", + 3: "Cuidé estos Pokémon con un método especial." }, "victory": { - 1: "Ugh… It wasn't supposed to be like this. Did I administer the wrong blend?", - 2: "How could that happen to my Pokémon… What are you feeding your Pokémon?", - 3: "If I lose, that tells you I was just killing time. It doesn't damage my ego at all." + 1: "Ugh… No se supone que acabaría así. ¿Les cuidé de forma errónea?", + 2: "Cómo pudo pasarle esto a mi Pokémon... ¿Qué le das a tu Pokémon?", + 3: "Si pierdo, solo fue un pasatiempo. Mi ego se ve intacto." }, "defeat": { - 1: "This proves my Pokémon have accepted my love.", - 2: "The real trick behind training good Pokémon is catching good Pokémon.", - 3: "Pokémon will be strong or weak depending on how you raise them." + 1: "Esto demuestra que los Pokémon aceptaron mi amor.", + 2: "El truco detrás de atrapar buenos Pokémon es cuidar buenos Pokémon.", + 3: "Los Pokémon serán fuertes o débiles según los cuides." } }, "fisherman": { "encounter": { - 1: "Aack! You made me lose a bite!\nWhat are you going to do about it?", - 2: "Go away! You're scaring the Pokémon!", - 3: "Let's see if you can reel in a victory!", + 1: "¡Uy uy uy! ¡Hiciste que huyera un pez!\n¿Qué harás al respecto?", + 2: "¡Vete! ¡Espantas los Pokémon!", + 3: "¡Veamos si pescas una victoria!", }, "victory": { - 1: "Just forget about it.", - 2: "Next time, I'll be reelin' in the triumph!", - 3: "Guess I underestimated the currents this time.", + 1: "Olvídalo.", + 2: "A la siguiente, ¡pescaré mi victoria!", + 3: "Infravaloré la corriente esta vez.", }, }, "fisherman_female": { @@ -371,6 +371,18 @@ export const PGMdialogue: DialogueTranslationEntries = { 3: "Ow! I scorched the tip of my nose!" }, }, + "sailor": { + "encounter": { + 1: "¡Amigo, te haré caminar por la borda si pierdes!", + 2: "¡Adelante! ¡Mi orgullo como marinero está en auge!", + 3: "¡Ah del barco! ¿Estás mareado?" + }, + "victory": { + 1: "¡Argh! ¡Derrotado por un niño!", + 2: "¡Tu espíritu me ha hundido!", + 3: "Creo que soy yo quien está mareado..." + }, + }, "brock": { "encounter": { 1: "My expertise on Rock-type Pokémon will take you down! Come on!", diff --git a/src/locales/es/game-mode.ts b/src/locales/es/game-mode.ts new file mode 100644 index 00000000000..dcff983791f --- /dev/null +++ b/src/locales/es/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "Clásica", + "endless": "Infinita", + "endlessSpliced": "Infinita (Fusión)", + "dailyRun": "Diaria", + "unknown": "Desconicido", + "challenge": "Desafío", +} as const; diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 517569ff40b..4bd6d750d69 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -45,10 +45,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Rankings Semanales", "noRankings": "Sin Rankings", "loading": "Cargando…", + "loadingAsset": "Cargando recurso: {{assetName}}", "playersOnline": "Jugadores en Línea", - "empty":"Vacío", "yes":"Sí", "no":"No", - "disclaimer": "DISCLAIMER", - "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed." + "disclaimer": "AVISO", + "disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida de datos de guardado),\ncambiar sin avisar, y puede o no puede ser actualizado hasta ser completado." } as const; diff --git a/src/locales/es/modifier-type.ts b/src/locales/es/modifier-type.ts index f6565486bb1..e00a55740a5 100644 --- a/src/locales/es/modifier-type.ts +++ b/src/locales/es/modifier-type.ts @@ -4,11 +4,11 @@ export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { "AddPokeballModifierType": { name: "{{modifierCount}}x {{pokeballName}}", - description: "Recibes {{modifierCount}}x {{pokeballName}} (En inventario: {{pokeballAmount}}) \nRatio de captura: {{catchRate}}", + description: "Recibes {{modifierCount}}x {{pokeballName}} (En inventario: {{pokeballAmount}}) \nRatio de captura: {{catchRate}}.", }, "AddVoucherModifierType": { name: "{{modifierCount}}x {{voucherTypeName}}", - description: "Recibes {{modifierCount}}x {{voucherTypeName}}", + description: "Recibes {{modifierCount}}x {{voucherTypeName}}.", }, "PokemonHeldItemModifierType": { extra: { @@ -17,63 +17,63 @@ export const modifierType: ModifierTypeTranslationEntries = { } }, "PokemonHpRestoreModifierType": { - description: "Restaura {{restorePoints}} PS o, al menos, un {{restorePercent}}% PS de un Pokémon", + description: "Restaura {{restorePoints}} PS o, al menos, un {{restorePercent}}% PS de un Pokémon.", extra: { - "fully": "Restaura todos los PS de un Pokémon", - "fullyWithStatus": "Restaura todos los PS de un Pokémon y cura todos los problemas de estados", + "fully": "Restaura todos los PS de un Pokémon.", + "fullyWithStatus": "Restaura todos los PS de un Pokémon y cura todos los problemas de estados.", } }, "PokemonReviveModifierType": { - description: "Revive a un Pokémon y restaura {{restorePercent}}% PS", + description: "Revive a un Pokémon y restaura {{restorePercent}}% PS.", }, "PokemonStatusHealModifierType": { - description: "Cura todos los problemas de estados de un Pokémon", + description: "Cura todos los problemas de estados de un Pokémon.", }, "PokemonPpRestoreModifierType": { - description: "Restaura {{restorePoints}} PP del movimiento que elijas de un Pokémon", + description: "Restaura {{restorePoints}} PP del movimiento que elijas de un Pokémon.", extra: { - "fully": "Restaura todos los PP del movimiento que elijas de un Pokémon", + "fully": "Restaura todos los PP del movimiento que elijas de un Pokémon.", } }, "PokemonAllMovePpRestoreModifierType": { - description: "Restaura {{restorePoints}} PP de todos los movimientos de un Pokémon", + description: "Restaura {{restorePoints}} PP de todos los movimientos de un Pokémon.", extra: { - "fully": "Restaura todos los PP de todos los movimientos de un Pokémon", + "fully": "Restaura todos los PP de todos los movimientos de un Pokémon.", } }, "PokemonPpUpModifierType": { - description: "Aumenta permanentemente los PP para un movimiento de un Pokémon en {{upPoints}} por cada 5 PP máximo (máximo 3)", + description: "Aumenta permanentemente los PP para un movimiento de un Pokémon en {{upPoints}} por cada 5 PP máximo (máximo 3).", }, "PokemonNatureChangeModifierType": { name: "Menta {{natureName}}", - description: "Cambia la naturaleza de un Pokémon a {{natureName}} y desbloquea permanentemente dicha naturaleza para el inicial", + description: "Cambia la naturaleza de un Pokémon a {{natureName}} y desbloquea permanentemente dicha naturaleza para el inicial.", }, "DoubleBattleChanceBoosterModifierType": { - description: "Duplica la posibilidad de que un encuentro sea una combate doble durante {{battleCount}} combates", + description: "Duplica la posibilidad de que un encuentro sea una combate doble durante {{battleCount}} combates.", }, "TempBattleStatBoosterModifierType": { - description: "Aumenta la est. {{tempBattleStatName}} de todos los miembros del equipo en 1 nivel durante 5 combates", + description: "Aumenta la est. {{tempBattleStatName}} de todos los miembros del equipo en 1 nivel durante 5 combates.", }, "AttackTypeBoosterModifierType": { - description: "Aumenta la potencia de los movimientos de tipo {{moveType}} de un Pokémon en un 20%", + description: "Aumenta la potencia de los movimientos de tipo {{moveType}} de un Pokémon en un 20%.", }, "PokemonLevelIncrementModifierType": { - description: "Aumenta el nivel de un Pokémon en 1", + description: "Aumenta el nivel de un Pokémon en 1.", }, "AllPokemonLevelIncrementModifierType": { - description: "Aumenta el nivel de todos los miembros del equipo en 1", + description: "Aumenta el nivel de todos los miembros del equipo en 1.", }, "PokemonBaseStatBoosterModifierType": { - description: "Aumenta la est. {{statName}} base del portador en un 10%.\nCuanto mayores sean tus IVs, mayor será el límite de acumulación", + description: "Aumenta la est. {{statName}} base del portador en un 10%.\nCuanto mayores sean tus IVs, mayor será el límite de acumulación.", }, "AllPokemonFullHpRestoreModifierType": { - description: "Restaura el 100% de los PS de todos los Pokémon", + description: "Restaura el 100% de los PS de todos los Pokémon.", }, "AllPokemonFullReviveModifierType": { - description: "Revive a todos los Pokémon debilitados y restaura completamente sus PS", + description: "Revive a todos los Pokémon debilitados y restaura completamente sus PS.", }, "MoneyRewardModifierType": { - description: "Otorga una {{moneyMultiplier}} cantidad de dinero (₽{{moneyAmount}})", + description: "Otorga una {{moneyMultiplier}} cantidad de dinero (₽{{moneyAmount}}).", extra: { "small": "pequeña", "moderate": "moderada", @@ -81,62 +81,62 @@ export const modifierType: ModifierTypeTranslationEntries = { }, }, "ExpBoosterModifierType": { - description: "Aumenta la ganancia de EXP en un {{boostPercent}}%", + description: "Aumenta la ganancia de EXP en un {{boostPercent}}%.", }, "PokemonExpBoosterModifierType": { - description: "Aumenta la ganancia de EXP del portador en un {{boostPercent}}%", + description: "Aumenta la ganancia de EXP del portador en un {{boostPercent}}%.", }, "PokemonFriendshipBoosterModifierType": { - description: "Aumenta la ganancia de amistad por victoria en un 50%", + description: "Aumenta la ganancia de amistad por victoria en un 50%.", }, "PokemonMoveAccuracyBoosterModifierType": { - description: "Aumenta la precisión de los movimiento en un {{accuracyAmount}} (máximo 100)", + description: "Aumenta la precisión de los movimiento en un {{accuracyAmount}} (máximo 100).", }, "PokemonMultiHitModifierType": { - description: "Los ataques golpean una vez más a costa de una reducción de poder del 60/75/82,5% por cada objeto", + description: "Los ataques golpean una vez más a costa de una reducción de poder del 60/75/82,5% por cada objeto.", }, "TmModifierType": { name: "MT{{moveId}} - {{moveName}}", - description: "Enseña {{moveName}} a un Pokémon", + description: "Enseña {{moveName}} a un Pokémon.", }, "TmModifierTypeWithInfo": { name: "MT{{moveId}} - {{moveName}}", - description: "Enseña {{moveName}} a un Pokémon\n(Hold C or Shift for more info)", + description: "Enseña {{moveName}} a un Pokémon\n(Hold C or Shift for more info).", }, "EvolutionItemModifierType": { - description: "Hace que ciertos Pokémon evolucionen", + description: "Hace que ciertos Pokémon evolucionen.", }, "FormChangeItemModifierType": { - description: "Hace que ciertos Pokémon cambien de forma", + description: "Hace que ciertos Pokémon cambien de forma.", }, "FusePokemonModifierType": { - description: "Fusiona dos Pokémon (transfiere habilidades, divide estadísticas bases y tipos, comparte movimientos)", + description: "Fusiona dos Pokémon (transfiere habilidades, divide estadísticas bases y tipos, comparte movimientos).", }, "TerastallizeModifierType": { name: "Teralito {{teraType}}", - description: "Teracristaliza al portador al tipo {{teraType}} durante 10 combates", + description: "Teracristaliza al portador al tipo {{teraType}} durante 10 combates.", }, "ContactHeldItemTransferChanceModifierType": { - description: "Al atacar, hay un {{chancePercent}}% de posibilidades de que robes el objeto que tiene el enemigo", + description: "Al atacar, hay un {{chancePercent}}% de posibilidades de que robes el objeto que tiene el enemigo.", }, "TurnHeldItemTransferModifierType": { - description: "Cada turno, el portador roba un objeto del enemigo", + description: "Cada turno, el portador roba un objeto del enemigo.", }, "EnemyAttackStatusEffectChanceModifierType": { - description: "Agrega un {{chancePercent}}% de probabilidad de infligir {{statusEffect}} con movimientos de ataque", + description: "Agrega un {{chancePercent}}% de probabilidad de infligir {{statusEffect}} con movimientos de ataque.", }, "EnemyEndureChanceModifierType": { - description: "Agrega un {{chancePercent}}% de probabilidad de resistir un ataque que lo debilitaría", + description: "Agrega un {{chancePercent}}% de probabilidad de resistir un ataque que lo debilitaría.", }, "RARE_CANDY": { name: "Carameloraro" }, - "RARER_CANDY": { name: "Rarer Candy" }, + "RARER_CANDY": { name: "Caramelorarísimo" }, - "MEGA_BRACELET": { name: "Mega-aro", description: "Las Megapiedras están disponibles" }, - "DYNAMAX_BAND": { name: "Maximuñequera", description: "Las Maxisetas están disponibles" }, - "TERA_ORB": { name: "Orbe Teracristal", description: "Los Teralitos están disponibles" }, + "MEGA_BRACELET": { name: "Mega-aro", description: "Las Megapiedras están disponibles." }, + "DYNAMAX_BAND": { name: "Maximuñequera", description: "Las Maxisetas están disponibles." }, + "TERA_ORB": { name: "Orbe Teracristal", description: "Los Teralitos están disponibles." }, - "MAP": { name: "Mapa", description: "Te permite elegir tu camino al final del bioma" }, + "MAP": { name: "Mapa", description: "Te permite elegir tu camino al final del bioma." }, "POTION": { name: "Poción" }, "SUPER_POTION": { name: "Superpoción" }, @@ -151,7 +151,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "SACRED_ASH": { name: "Cen. Sagrada" }, - "REVIVER_SEED": { name: "Semilla Revivir", description: "Revive al portador con la mitad de sus PS al debilitarse" }, + "REVIVER_SEED": { name: "Semilla Revivir", description: "Revive al portador con la mitad de sus PS al debilitarse." }, "ETHER": { name: "Éter" }, "MAX_ETHER": { name: "Éter Máx." }, @@ -162,16 +162,16 @@ export const modifierType: ModifierTypeTranslationEntries = { "PP_UP": { name: "Más PP" }, "PP_MAX": { name: "Máx PP" }, - "LURE": { name: "Lure" }, - "SUPER_LURE": { name: "Super Lure" }, - "MAX_LURE": { name: "Max Lure" }, + "LURE": { name: "Incienso" }, + "SUPER_LURE": { name: "Superincienso" }, + "MAX_LURE": { name: "Incienso Máximo" }, - "MEMORY_MUSHROOM": { name: "Memory Mushroom", description: "Recall one Pokémon's forgotten move" }, + "MEMORY_MUSHROOM": { name: "Seta Recuerdo", description: "Recuerda un movimiento olvidado de un Pokémon." }, - "EXP_SHARE": { name: "Repartir EXP", description: "Los que no combatan reciben el 20% de la EXP" }, - "EXP_BALANCE": { name: "EXP. Balance", description: "Da mayor parte de la EXP recibida a los miembros del equipo que tengan menos nivel" }, + "EXP_SHARE": { name: "Repartir EXP", description: "Los que no combatan reciben el 20% de la EXP." }, + "EXP_BALANCE": { name: "Equilibrar EXP", description: "Da mayor parte de la EXP recibida a los miembros del equipo que tengan menos nivel." }, - "OVAL_CHARM": { name: "Amuleto Oval", description: "Cada Pokémon combatiente recibe un 10% adicional de la EXP total" }, + "OVAL_CHARM": { name: "Amuleto Oval", description: "Cada Pokémon combatiente recibe un 10% adicional de la EXP total." }, "EXP_CHARM": { name: "Amuleto EXP" }, "SUPER_EXP_CHARM": { name: "Super Amuleto EXP" }, @@ -182,62 +182,62 @@ export const modifierType: ModifierTypeTranslationEntries = { "SOOTHE_BELL": { name: "Camp. Alivio" }, - "SOUL_DEW": { name: "Rocío bondad", description: "Aumenta la influencia de la naturaleza de un Pokémon en sus estadísticas en un 10% (aditivo)" }, + "SOUL_DEW": { name: "Rocío bondad", description: "Aumenta la influencia de la naturaleza de un Pokémon en sus estadísticas en un 10% (aditivo)." }, "NUGGET": { name: "Pepita" }, "BIG_NUGGET": { name: "Maxipepita" }, "RELIC_GOLD": { name: "Real de oro" }, - "AMULET_COIN": { name: "Moneda Amuleto", description: "Aumenta el dinero ganado en un 20%" }, - "GOLDEN_PUNCH": { name: "Puño Dorado", description: "Otorga el 50% del daño infligido como dinero" }, - "COIN_CASE": { name: "Monedero", description: "Después de cada 10 combates, recibe el 10% de tu dinero en intereses" }, + "AMULET_COIN": { name: "Moneda Amuleto", description: "Aumenta el dinero ganado en un 20%." }, + "GOLDEN_PUNCH": { name: "Puño Dorado", description: "Otorga el 50% del daño infligido como dinero." }, + "COIN_CASE": { name: "Monedero", description: "Después de cada 10 combates, recibe el 10% de tu dinero en intereses." }, - "LOCK_CAPSULE": { name: "Cápsula candado", description: "Le permite bloquear las rarezas de los objetos al cambiar de objetos" }, + "LOCK_CAPSULE": { name: "Cápsula candado", description: "Le permite bloquear las rarezas de los objetos al cambiar de objetos." }, "GRIP_CLAW": { name: "Garra Garfio" }, "WIDE_LENS": { name: "Lupa" }, - "MULTI_LENS": { name: "Multi Lens" }, + "MULTI_LENS": { name: "Multilupa" }, - "HEALING_CHARM": { name: "Amuleto curación", description: "Aumenta la efectividad de los movimientos y objetos de curacion de PS en un 10% (excepto revivir)" }, - "CANDY_JAR": { name: "Candy Jar", description: "Aumenta en 1 el número de niveles añadidos por los carameloraros" }, + "HEALING_CHARM": { name: "Amuleto curación", description: "Aumenta la efectividad de los movimientos y objetos de curacion de PS en un 10% (excepto revivir)." }, + "CANDY_JAR": { name: "Candy Jar", description: "Aumenta en 1 el número de niveles añadidos por los carameloraros." }, - "BERRY_POUCH": { name: "Saco Bayas", description: "Agrega un 30% de posibilidades de que una baya usada no se consuma" }, + "BERRY_POUCH": { name: "Saco Bayas", description: "Agrega un 30% de posibilidades de que una baya usada no se consuma." }, - "FOCUS_BAND": { name: "Cinta Focus", description: "Agrega un 10% de probabilidad de resistir un ataque que lo debilitaría" }, + "FOCUS_BAND": { name: "Cinta Focus", description: "Agrega un 10% de probabilidad de resistir un ataque que lo debilitaría." }, - "QUICK_CLAW": { name: "Garra Rápida", description: "Agrega un 10% de probabilidad de atacar primero independientemente de la velocidad (después de la prioridad)" }, + "QUICK_CLAW": { name: "Garra Rápida", description: "Agrega un 10% de probabilidad de atacar primero independientemente de la velocidad (después de la prioridad)." }, - "KINGS_ROCK": { name: "Roca del Rey", description: "Agrega un 10% de probabilidad de que un ataque haga que el oponente retroceda" }, + "KINGS_ROCK": { name: "Roca del Rey", description: "Agrega un 10% de probabilidad de que un ataque haga que el oponente retroceda." }, - "LEFTOVERS": { name: "Restos", description: "Cura 1/16 de los PS máximo de un Pokémon cada turno" }, - "SHELL_BELL": { name: "Camp Concha", description: "Cura 1/8 del daño infligido por un Pokémon" }, + "LEFTOVERS": { name: "Restos", description: "Cura 1/16 de los PS máximo de un Pokémon cada turno." }, + "SHELL_BELL": { name: "Camp Concha", description: "Cura 1/8 del daño infligido por un Pokémon." }, - "TOXIC_ORB": { name: "Toxiesfera", description: "Extraña esfera que envenena gravemente a quien la usa en combate" }, - "FLAME_ORB": { name: "Llamasfera", description: "Extraña esfera que causa quemaduras a quien la usa en combate" }, + "TOXIC_ORB": { name: "Toxiesfera", description: "Extraña esfera que envenena gravemente a quien la usa en combate." }, + "FLAME_ORB": { name: "Llamasfera", description: "Extraña esfera que causa quemaduras a quien la usa en combate." }, - "BATON": { name: "Baton", description: "Permite pasar los efectos al cambiar de Pokémon, también evita las trampas" }, + "BATON": { name: "Relevo", description: "Permite pasar los efectos al cambiar de Pokémon, también evita las trampas." }, - "SHINY_CHARM": { name: "Amuleto Iris", description: "Aumenta drásticamente la posibilidad de que un Pokémon salvaje sea Shiny" }, - "ABILITY_CHARM": { name: "Amuleto Habilidad", description: "Aumenta drásticamente la posibilidad de que un Pokémon salvaje tenga una habilidad oculta" }, + "SHINY_CHARM": { name: "Amuleto Iris", description: "Aumenta drásticamente la posibilidad de que un Pokémon salvaje sea Shiny." }, + "ABILITY_CHARM": { name: "Amuleto Habilidad", description: "Aumenta drásticamente la posibilidad de que un Pokémon salvaje tenga una habilidad oculta." }, - "IV_SCANNER": { name: "Escáner IV", description: "Permite escanear los IVs de Pokémon salvajes. Se revelan 2 IVs por cada objeto.\nLos mejores IVs se muestran primero" }, + "IV_SCANNER": { name: "Escáner IV", description: "Permite escanear los IVs de Pokémon salvajes. Se revelan 2 IVs por cada objeto.\nLos mejores IVs se muestran primero." }, "DNA_SPLICERS": { name: "Punta ADN" }, "MINI_BLACK_HOLE": { name: "Mini Agujero Negro" }, - "GOLDEN_POKEBALL": { name: "Poké Ball Dorada", description: "Agrega 1 opción de objeto extra al final de cada combate" }, + "GOLDEN_POKEBALL": { name: "Poké Ball Dorada", description: "Agrega 1 opción de objeto extra al final de cada combate." }, - "ENEMY_DAMAGE_BOOSTER": { name: "Damage Token", description: "Aumenta el daño en un 5%" }, - "ENEMY_DAMAGE_REDUCTION": { name: "Protection Token", description: "Reduce el daño recibido en un 2,5%" }, - "ENEMY_HEAL": { name: "Recovery Token", description: "Cura el 2% de los PS máximo en cada turno" }, - "ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" }, - "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" }, - "ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" }, - "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Agrega un 2.5% de probabilidad cada turno de curar un problema de estado" }, - "ENEMY_ENDURE_CHANCE": { name: "Endure Token" }, - "ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Agrega un 1% de probabilidad de que un Pokémon salvaje sea una fusión" }, + "ENEMY_DAMAGE_BOOSTER": { name: "Ficha Daño", description: "Aumenta el daño en un 5%." }, + "ENEMY_DAMAGE_REDUCTION": { name: "Ficha Protección", description: "Reduce el daño recibido en un 2,5%." }, + "ENEMY_HEAL": { name: "Ficha Curación", description: "Cura el 2% de los PS máximo en cada turno." }, + "ENEMY_ATTACK_POISON_CHANCE": { name: "Ficha Veneno" }, + "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Ficha Parálisis" }, + "ENEMY_ATTACK_BURN_CHANCE": { name: "Ficha Quemadura" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Ficha Cura Total", description: "Agrega un 2.5% de probabilidad cada turno de curar un problema de estado." }, + "ENEMY_ENDURE_CHANCE": { name: "Ficha Aguante" }, + "ENEMY_FUSED_CHANCE": { name: "Ficha Fusión", description: "Agrega un 1% de probabilidad de que un Pokémon salvaje sea una fusión." }, }, TempBattleStatBoosterItem: { "x_attack": "Ataque X", diff --git a/src/locales/es/party-ui-handler.ts b/src/locales/es/party-ui-handler.ts new file mode 100644 index 00000000000..9d3c7baa9ae --- /dev/null +++ b/src/locales/es/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "Send Out", + "SUMMARY": "Summary", + "CANCEL": "Cancel", + "RELEASE": "Release", + "APPLY": "Apply", + "TEACH": "Teach" +} as const; diff --git a/src/locales/es/save-slot-select-ui-handler.ts b/src/locales/es/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..7939518ceed --- /dev/null +++ b/src/locales/es/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "¿Sobrescribir los datos en la ranura seleccionada?", + "loading": "Cargando...", + "wave": "Oleada", + "lv": "Nv", + "empty": "Vacío", +} as const; diff --git a/src/locales/es/starter-select-ui-handler.ts b/src/locales/es/starter-select-ui-handler.ts index 81455418c7d..e41f151965a 100644 --- a/src/locales/es/starter-select-ui-handler.ts +++ b/src/locales/es/starter-select-ui-handler.ts @@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "selectMoveSwapWith": "Elige el movimiento que sustituirá a", "unlockPassive": "Añadir Pasiva", "reduceCost": "Reducir Coste", - "cycleShiny": "R: Cambiar Shiny", - "cycleForm": "F: Cambiar Forma", - "cycleGender": "G: Cambiar Género", - "cycleAbility": "E: Cambiar Habilidad", - "cycleNature": "N: Cambiar Naturaleza", - "cycleVariant": "V: Cambiar Variante", + "cycleShiny": ": Cambiar Shiny", + "cycleForm": ": Cambiar Forma", + "cycleGender": ": Cambiar Género", + "cycleAbility": ": Cambiar Habilidad", + "cycleNature": ": Cambiar Naturaleza", + "cycleVariant": ": Cambiar Variante", "enablePassive": "Activar Pasiva", "disablePassive": "Desactivar Pasiva", "locked": "Bloqueado", diff --git a/src/locales/es/trainers.ts b/src/locales/es/trainers.ts index 3e2b2b1a788..6d776f44c9c 100644 --- a/src/locales/es/trainers.ts +++ b/src/locales/es/trainers.ts @@ -94,6 +94,7 @@ export const trainerClasses: SimpleTranslationEntries = { "rich_kid_female": "Niña Bien", "rich_kids": "Niños Bien", "roughneck": "Calvo", + "sailor": "Marinero", "scientist": "Científico", "scientist_female": "Científica", "scientists": "Científicos", diff --git a/src/locales/fr/achv.ts b/src/locales/fr/achv.ts index 6383c6817c0..ddec9086892 100644 --- a/src/locales/fr/achv.ts +++ b/src/locales/fr/achv.ts @@ -1,6 +1,7 @@ import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "Succès", }, @@ -168,4 +169,102 @@ export const achv: AchievementTranslationEntries = { name: "Invaincu·e", description: "Terminer le jeu en mode classique", }, + + "MONO_GEN_ONE": { + name: "The Original Rival", + description: "Complete the generation one only challenge.", + }, + "MONO_GEN_TWO": { + name: "Generation 1.5", + description: "Complete the generation two only challenge.", + }, + "MONO_GEN_THREE": { + name: "Too much water?", + description: "Complete the generation three only challenge.", + }, + "MONO_GEN_FOUR": { + name: "Is she really the hardest?", + description: "Complete the generation four only challenge.", + }, + "MONO_GEN_FIVE": { + name: "All Original", + description: "Complete the generation five only challenge.", + }, + "MONO_GEN_SIX": { + name: "Almost Royalty", + description: "Complete the generation six only challenge.", + }, + "MONO_GEN_SEVEN": { + name: "Only Technically", + description: "Complete the generation seven only challenge.", + }, + "MONO_GEN_EIGHT": { + name: "A Champion Time!", + description: "Complete the generation eight only challenge.", + }, + "MONO_GEN_NINE": { + name: "She was going easy on you", + description: "Complete the generation nine only challenge.", + }, + + "MonoType": { + description: "Complete the {{type}} monotype challenge.", + }, + "MONO_NORMAL": { + name: "Mono NORMAL", + }, + "MONO_FIGHTING": { + name: "I Know Kung Fu", + }, + "MONO_FLYING": { + name: "Mono FLYING", + }, + "MONO_POISON": { + name: "Kanto's Favourite", + }, + "MONO_GROUND": { + name: "Mono GROUND", + }, + "MONO_ROCK": { + name: "Brock Hard", + }, + "MONO_BUG": { + name: "Sting Like A Beedrill", + }, + "MONO_GHOST": { + name: "Who you gonna call?", + }, + "MONO_STEEL": { + name: "Mono STEEL", + }, + "MONO_FIRE": { + name: "Mono FIRE", + }, + "MONO_WATER": { + name: "When It Rains, It Pours", + }, + "MONO_GRASS": { + name: "Mono GRASS", + }, + "MONO_ELECTRIC": { + name: "Mono ELECTRIC", + }, + "MONO_PSYCHIC": { + name: "Mono PSYCHIC", + }, + "MONO_ICE": { + name: "Mono ICE", + }, + "MONO_DRAGON": { + name: "Mono DRAGON", + }, + "MONO_DARK": { + name: "It's just a phase", + }, + "MONO_FAIRY": { + name: "Mono FAIRY", + }, } as const; + +// Achievement translations for the when the player character is female (it for now uses the same translations as the male version) +export const PGFachv: AchievementTranslationEntries = PGMachv; diff --git a/src/locales/fr/biome.ts b/src/locales/fr/biome.ts index bc9fa4239e6..2f3dffb28f6 100644 --- a/src/locales/fr/biome.ts +++ b/src/locales/fr/biome.ts @@ -16,7 +16,7 @@ export const biome: SimpleTranslationEntries = { "MOUNTAIN": "Montagne", "BADLANDS": "Terres Sauvages", "CAVE": "Grotte", - "DESERT": "Desert", + "DESERT": "Désert", "ICE_CAVE": "Caverne Gelée", "MEADOW": "Prairie", "POWER_PLANT": "Centrale", diff --git a/src/locales/fr/challenges.ts b/src/locales/fr/challenges.ts new file mode 100644 index 00000000000..f655caf4807 --- /dev/null +++ b/src/locales/fr/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "Paramètres du Challenge", + "points": "Bad Ideas", + "confirm_start": "Continuer avec ces paramètres ?", + "singleGeneration.name": "Mono-génération", + "singleGeneration.value.0": "Désactivé", + "singleGeneration.desc.0": "Vous ne pouvez choisir que des Pokémon de la génération sélectionnée.", + "singleGeneration.value.1": "1G", + "singleGeneration.desc.1": "Vous ne pouvez choisir que des Pokémon de 1re génération.", + "singleGeneration.value.2": "2G", + "singleGeneration.desc.2": "Vous ne pouvez choisir que des Pokémon de 2e génération.", + "singleGeneration.value.3": "3G", + "singleGeneration.desc.3": "Vous ne pouvez choisir que des Pokémon de 3e génération.", + "singleGeneration.value.4": "4G", + "singleGeneration.desc.4": "Vous ne pouvez choisir que des Pokémon de 4e génération.", + "singleGeneration.value.5": "5G", + "singleGeneration.desc.5": "Vous ne pouvez choisir que des Pokémon de 5e génération.", + "singleGeneration.value.6": "6G", + "singleGeneration.desc.6": "Vous ne pouvez choisir que des Pokémon de 6e génération.", + "singleGeneration.value.7": "7G", + "singleGeneration.desc.7": "Vous ne pouvez choisir que des Pokémon de 7e génération.", + "singleGeneration.value.8": "8G", + "singleGeneration.desc.8": "Vous ne pouvez choisir que des Pokémon de 8e génération.", + "singleGeneration.value.9": "9G", + "singleGeneration.desc.9": "Vous ne pouvez choisir que des Pokémon de 9e génération.", + "singleType.name": "Mono-type", + "singleType.value.0": "Désactivé", + "singleType.desc.0": "Vous ne pouvez choisir que des Pokémon du type sélectionné.", + "singleType.value.1": "Normal", + "singleType.desc.1": "Vous ne pouvez choisir que des Pokémon de type Normal.", + "singleType.value.2": "Combat", + "singleType.desc.2": "Vous ne pouvez choisir que des Pokémon de type Combat.", + "singleType.value.3": "Vol", + "singleType.desc.3": "Vous ne pouvez choisir que des Pokémon de type Vol.", + "singleType.value.4": "Poison", + "singleType.desc.4": "Vous ne pouvez choisir que des Pokémon de type Poison.", + "singleType.value.5": "Sol", + "singleType.desc.5": "Vous ne pouvez choisir que des Pokémon de type Sol.", + "singleType.value.6": "Roche", + "singleType.desc.6": "Vous ne pouvez choisir que des Pokémon de type Roche.", + "singleType.value.7": "Insecte", + "singleType.desc.7": "Vous ne pouvez choisir que des Pokémon de type Insecte.", + "singleType.value.8": "Spectre", + "singleType.desc.8": "Vous ne pouvez choisir que des Pokémon de type Spectre.", + "singleType.value.9": "Acier", + "singleType.desc.9": "Vous ne pouvez choisir que des Pokémon de type Acier.", + "singleType.value.10": "Feu", + "singleType.desc.10": "Vous ne pouvez choisir que des Pokémon de type Feu.", + "singleType.value.11": "Eau", + "singleType.desc.11": "Vous ne pouvez choisir que des Pokémon de type Eau.", + "singleType.value.12": "Plante", + "singleType.desc.12": "Vous ne pouvez choisir que des Pokémon de type Plante.", + "singleType.value.13": "Électrik", + "singleType.desc.13": "Vous ne pouvez choisir que des Pokémon de type Électrik.", + "singleType.value.14": "Psy", + "singleType.desc.14": "Vous ne pouvez choisir que des Pokémon de type Psy.", + "singleType.value.15": "Glace", + "singleType.desc.15": "Vous ne pouvez choisir que des Pokémon de type Glace.", + "singleType.value.16": "Dragon", + "singleType.desc.16": "Vous ne pouvez choisir que des Pokémon de type Dragon.", + "singleType.value.17": "Ténèbres", + "singleType.desc.17": "Vous ne pouvez choisir que des Pokémon de type Ténèbres.", + "singleType.value.18": "Fée", + "singleType.desc.18": "Vous ne pouvez choisir que des Pokémon de type Fée.", +} as const; diff --git a/src/locales/fr/config.ts b/src/locales/fr/config.ts index ee9e9a1e2ac..f7b7467c4bc 100644 --- a/src/locales/fr/config.ts +++ b/src/locales/fr/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -29,22 +31,26 @@ import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; +import { partyUiHandler } from "./party-ui-handler"; export const frConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const frConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -66,6 +73,7 @@ export const frConfig = { pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +81,6 @@ export const frConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, + partyUiHandler: partyUiHandler }; diff --git a/src/locales/fr/dialogue.ts b/src/locales/fr/dialogue.ts index befc9d96caa..950703bfded 100644 --- a/src/locales/fr/dialogue.ts +++ b/src/locales/fr/dialogue.ts @@ -371,6 +371,18 @@ export const PGMdialogue: DialogueTranslationEntries = { 3: "Ow! I scorched the tip of my nose!" }, }, + "sailor": { + "encounter": { + 1: "Matey, you're walking the plank if you lose!", + 2: "Come on then! My sailor's pride is at stake!", + 3: "Ahoy there! Are you seasick?" + }, + "victory": { + 1: "Argh! Beaten by a kid!", + 2: "Your spirit sank me!", + 3: "I think it's me that's seasick..." + }, + }, "brock": { "encounter": { 1: "My expertise on Rock-type Pokémon will take you down! Come on!", diff --git a/src/locales/fr/game-mode.ts b/src/locales/fr/game-mode.ts new file mode 100644 index 00000000000..28858e46bfa --- /dev/null +++ b/src/locales/fr/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "Classique", + "endless": "Infini", + "endlessSpliced": "Infini (Fusions)", + "dailyRun": "Défi du jour", + "unknown": "Inconnu", + "challenge": "Challenge", +} as const; diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index e955d4970c0..f9538e9d26c 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -40,10 +40,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Classement de la Semaine", "noRankings": "Pas de Classement", "loading": "Chargement…", + "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "Joueurs Connectés", - "empty":"Vide", "yes":"Oui", "no":"Non", - "disclaimer": "DISCLAIMER", - "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed." + "disclaimer": "AVERTISSEMENT", + "disclaimerDescription": "Ce jeu n’est pas un produit fini et peut contenir des problèmes de jouabilité, dont de possibles pertes de sauvegardes,\ndes modifications sans avertissement et pourrait ou non encore être mis à jour ou terminé." } as const; diff --git a/src/locales/fr/modifier-type.ts b/src/locales/fr/modifier-type.ts index dd70fd9205e..7accfbc849b 100644 --- a/src/locales/fr/modifier-type.ts +++ b/src/locales/fr/modifier-type.ts @@ -4,76 +4,76 @@ export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { "AddPokeballModifierType": { name: "{{pokeballName}} x{{modifierCount}}", - description: "Recevez {{modifierCount}} {{pokeballName}}s (Inventaire : {{pokeballAmount}}) \nTaux de capture : {{catchRate}}", + description: "Recevez {{modifierCount}} {{pokeballName}}s (Inventaire : {{pokeballAmount}}) \nTaux de capture : {{catchRate}}.", }, "AddVoucherModifierType": { name: "{{voucherTypeName}} x{{modifierCount}}", - description: "Recevez {{modifierCount}} {{voucherTypeName}}", + description: "Recevez {{modifierCount}} {{voucherTypeName}}.", }, "PokemonHeldItemModifierType": { extra: { - "inoperable": "{{pokemonName}} ne peut pas\nporter cet objet !", - "tooMany": "{{pokemonName}} possède trop\nd’exemplaires de cet objet !", + "inoperable": "{{pokemonName}} ne peut pas\nporter cet objet !", + "tooMany": "{{pokemonName}} possède trop\nd’exemplaires de cet objet !", } }, "PokemonHpRestoreModifierType": { description: "Restaure {{restorePoints}} PV ou {{restorePercent}}% des PV totaux d’un Pokémon, en fonction duquel des deux est le plus élevé", extra: { - "fully": "Restaure tous les PV d’un Pokémon", - "fullyWithStatus": "Restaure tous les PV d’un Pokémon et soigne tous ses problèmes de statut", + "fully": "Restaure tous les PV d’un Pokémon.", + "fullyWithStatus": "Restaure tous les PV d’un Pokémon et soigne tous ses problèmes de statut.", } }, "PokemonReviveModifierType": { - description: "Réanime un Pokémon et restaure {{restorePercent}}% de ses PV", + description: "Réanime un Pokémon et restaure {{restorePercent}}% de ses PV.", }, "PokemonStatusHealModifierType": { - description: "Soigne tous les problèmes de statut d’un Pokémon", + description: "Soigne tous les problèmes de statut d’un Pokémon.", }, "PokemonPpRestoreModifierType": { - description: "Restaure {{restorePoints}} PP à une capacité d’un Pokémon", + description: "Restaure {{restorePoints}} PP à une capacité d’un Pokémon.", extra: { - "fully": "Restaure tous les PP à une capacité d’un Pokémon", + "fully": "Restaure tous les PP à une capacité d’un Pokémon.", } }, "PokemonAllMovePpRestoreModifierType": { - description: "Restaure {{restorePoints}} PP à toutes les capacités d’un Pokémon", + description: "Restaure {{restorePoints}} PP à toutes les capacités d’un Pokémon.", extra: { - "fully": "Restaure tous les PP à toutes les capacités d’un Pokémon", + "fully": "Restaure tous les PP à toutes les capacités d’un Pokémon.", } }, "PokemonPpUpModifierType": { - description: "Augmente le max de PP de {{upPoints}} à une capacité d’un Pokémon pour chaque 5 PP max (max : 3)", + description: "Augmente le max de PP de {{upPoints}} à une capacité d’un Pokémon pour chaque 5 PP max (max : 3).", }, "PokemonNatureChangeModifierType": { name: "Aromate {{natureName}}", description: "Donne la nature {{natureName}} à un Pokémon et la débloque pour le starter lui étant lié.", }, "DoubleBattleChanceBoosterModifierType": { - description: "Double les chances de tomber sur un combat double pendant {{battleCount}} combats", + description: "Double les chances de tomber sur un combat double pendant {{battleCount}} combats.", }, "TempBattleStatBoosterModifierType": { - description: "Augmente d’un cran {{tempBattleStatName}} pour toute l’équipe pendant 5 combats", + description: "Augmente d’un cran {{tempBattleStatName}} pour toute l’équipe pendant 5 combats.", }, "AttackTypeBoosterModifierType": { - description: "Augmente de 20% la puissance des capacités de type {{moveType}} d’un Pokémon", + description: "Augmente de 20% la puissance des capacités de type {{moveType}} d’un Pokémon.", }, "PokemonLevelIncrementModifierType": { - description: "Fait monter un Pokémon d’un niveau", + description: "Fait monter un Pokémon d’un niveau.", }, "AllPokemonLevelIncrementModifierType": { - description: "Fait monter toute l’équipe d’un niveau", + description: "Fait monter toute l’équipe d’un niveau.", }, "PokemonBaseStatBoosterModifierType": { description: "Augmente de 10% {{statName}} de base de son porteur. Plus les IV sont hauts, plus il peut en porter.", }, "AllPokemonFullHpRestoreModifierType": { - description: "Restaure tous les PV de toute l'équipe", + description: "Restaure tous les PV de toute l'équipe.", }, "AllPokemonFullReviveModifierType": { description: "Réanime et restaure tous les PV de tous les Pokémon K.O.", }, "MoneyRewardModifierType": { - description: "Octroie une {{moneyMultiplier}} somme d’argent ({{moneyAmount}}₽)", + description: "Octroie une {{moneyMultiplier}} somme d’argent ({{moneyAmount}}₽).", extra: { "small": "petite", "moderate": "moyenne", @@ -81,62 +81,62 @@ export const modifierType: ModifierTypeTranslationEntries = { }, }, "ExpBoosterModifierType": { - description: "Augmente de {{boostPercent}}% le gain de Points d’Exp", + description: "Augmente de {{boostPercent}}% le gain de Points d’Exp.", }, "PokemonExpBoosterModifierType": { - description: "Augmente de {{boostPercent}}% le gain de Points d’Exp du porteur", + description: "Augmente de {{boostPercent}}% le gain de Points d’Exp du porteur.", }, "PokemonFriendshipBoosterModifierType": { - description: "Augmente le gain d’amitié de 50% par victoire", + description: "Augmente le gain d’amitié de 50% par victoire.", }, "PokemonMoveAccuracyBoosterModifierType": { - description: "Augmente de {{accuracyAmount}} la précision des capacités (maximum 100)", + description: "Augmente de {{accuracyAmount}} la précision des capacités (maximum 100).", }, "PokemonMultiHitModifierType": { - description: "Frappe une fois de plus en échange d’une baisse de puissance de respectivement 60/75/82,5% par cumul", + description: "Frappe une fois de plus en échange d’une baisse de puissance de respectivement 60/75/82,5% par cumul.", }, "TmModifierType": { name: "CT{{moveId}} - {{moveName}}", - description: "Apprend la capacité {{moveName}} à un Pokémon", + description: "Apprend la capacité {{moveName}} à un Pokémon.", }, "TmModifierTypeWithInfo": { name: "CT{{moveId}} - {{moveName}}", - description: "Apprend la capacité {{moveName}} à un Pokémon\n(Hold C or Shift for more info)", + description: "Apprend la capacité {{moveName}} à un Pokémon\n(Hold C or Shift for more info).", }, "EvolutionItemModifierType": { - description: "Permet à certains Pokémon d’évoluer", + description: "Permet à certains Pokémon d’évoluer.", }, "FormChangeItemModifierType": { - description: "Permet à certains Pokémon de changer de forme", + description: "Permet à certains Pokémon de changer de forme.", }, "FusePokemonModifierType": { - description: "Fusionne deux Pokémon (transfère le Talent, sépare les stats de base et les types, partage le movepool)", + description: "Fusionne deux Pokémon (transfère le Talent, sépare les stats de base et les types, partage le movepool).", }, "TerastallizeModifierType": { name: "Téra-Éclat {{teraType}}", - description: "{{teraType}} Téracristallise son porteur pendant 10 combats", + description: "{{teraType}} Téracristallise son porteur pendant 10 combats.", }, "ContactHeldItemTransferChanceModifierType": { - description: "{{chancePercent}}% de chances de voler un objet de l’adversaire en l’attaquant", + description: "{{chancePercent}}% de chances de voler un objet de l’adversaire en l’attaquant.", }, "TurnHeldItemTransferModifierType": { - description: "À chaque tour, son porteur obtient un objet de son adversaire", + description: "À chaque tour, son porteur obtient un objet de son adversaire.", }, "EnemyAttackStatusEffectChanceModifierType": { - description: "Ajoute {{chancePercent}}% de chances d’infliger le statut {{statusEffect}} avec des capacités offensives", + description: "Ajoute {{chancePercent}}% de chances d’infliger le statut {{statusEffect}} avec des capacités offensives.", }, "EnemyEndureChanceModifierType": { - description: "Ajoute {{chancePercent}}% de chances d’encaisser un coup", + description: "Ajoute {{chancePercent}}% de chances d’encaisser un coup.", }, "RARE_CANDY": { name: "Super Bonbon" }, "RARER_CANDY": { name: "Hyper Bonbon" }, - "MEGA_BRACELET": { name: "Méga-Bracelet", description: "Débloque les Méga-Gemmes" }, - "DYNAMAX_BAND": { name: "Poignet Dynamax", description: "Débloque le Dynamax" }, - "TERA_ORB": { name: "Orbe Téracristal", description: "Débloque les Téra-Éclats" }, + "MEGA_BRACELET": { name: "Méga-Bracelet", description: "Débloque les Méga-Gemmes." }, + "DYNAMAX_BAND": { name: "Poignet Dynamax", description: "Débloque le Dynamax." }, + "TERA_ORB": { name: "Orbe Téracristal", description: "Débloque les Téra-Éclats." }, - "MAP": { name: "Carte", description: "Vous permet de choisir votre destination à un croisement" }, + "MAP": { name: "Carte", description: "Vous permet de choisir votre destination à un croisement." }, "POTION": { name: "Potion" }, "SUPER_POTION": { name: "Super Potion" }, @@ -166,12 +166,12 @@ export const modifierType: ModifierTypeTranslationEntries = { "SUPER_LURE": { name: "Super Parfum" }, "MAX_LURE": { name: "Parfum Max" }, - "MEMORY_MUSHROOM": { name: "Champi Mémoriel", description: "Remémore une capacité à un Pokémon" }, + "MEMORY_MUSHROOM": { name: "Champi Mémoriel", description: "Remémore une capacité à un Pokémon." }, - "EXP_SHARE": { name: "Multi Exp", description: "Tous les non-participants reçoivent 20% des Points d’Exp d’un participant" }, - "EXP_BALANCE": { name: "Équilibr’Exp", description: "Équilibre les Points d’Exp à l’avantage des membres de l’équipe aux plus bas niveaux" }, + "EXP_SHARE": { name: "Multi Exp", description: "Tous les non-participants reçoivent 20% des Points d’Exp d’un participant." }, + "EXP_BALANCE": { name: "Équilibr’Exp", description: "Équilibre les Points d’Exp à l’avantage des membres de l’équipe aux plus bas niveaux." }, - "OVAL_CHARM": { name: "Charme Ovale", description: "Quand plusieurs Pokémon sont en combat, chacun gagne 10% supplémentaires du total d’Exp" }, + "OVAL_CHARM": { name: "Charme Ovale", description: "Quand plusieurs Pokémon sont en combat, chacun gagne 10% supplémentaires du total d’Exp." }, "EXP_CHARM": { name: "Charme Exp" }, "SUPER_EXP_CHARM": { name: "Super Charme Exp" }, @@ -182,44 +182,44 @@ export const modifierType: ModifierTypeTranslationEntries = { "SOOTHE_BELL": { name: "Grelot Zen" }, - "SOUL_DEW": { name: "Rosée Âme", description: "Augmente de 10% l’influence de la nature d’un Pokémon sur ses statistiques (cumulatif)" }, + "SOUL_DEW": { name: "Rosée Âme", description: "Augmente de 10% l’influence de la nature d’un Pokémon sur ses statistiques (cumulatif)." }, "NUGGET": { name: "Pépite" }, "BIG_NUGGET": { name: "Maxi Pépite" }, "RELIC_GOLD": { name: "Vieux Ducat" }, - "AMULET_COIN": { name: "Pièce Rune", description: "Augmente de 20% les gains d’argent" }, - "GOLDEN_PUNCH": { name: "Poing Doré", description: "50% des dégâts infligés sont convertis en argent" }, - "COIN_CASE": { name: "Boite Jetons", description: "Tous les 10 combats, recevez 10% de votre argent en intérêts" }, + "AMULET_COIN": { name: "Pièce Rune", description: "Augmente de 20% les gains d’argent." }, + "GOLDEN_PUNCH": { name: "Poing Doré", description: "50% des dégâts infligés sont convertis en argent." }, + "COIN_CASE": { name: "Boite Jetons", description: "Tous les 10 combats, recevez 10% de votre argent en intérêts." }, - "LOCK_CAPSULE": { name: "Poké Écrin", description: "Permet de verrouiller des objets rares si vous relancez les objets proposés" }, + "LOCK_CAPSULE": { name: "Poké Écrin", description: "Permet de verrouiller des objets rares si vous relancez les objets proposés." }, "GRIP_CLAW": { name: "Accro Griffe" }, "WIDE_LENS": { name: "Loupe" }, "MULTI_LENS": { name: "Lentille Multi" }, - "HEALING_CHARM": { name: "Charme Soin", description: "Augmente de 10% l’efficacité des capacités et objets de soin de PV (hors Rappels)" }, - "CANDY_JAR": { name: "Bonbonnière", description: "Augmente de 1 le nombre de niveaux gagnés à l’utilisation d’un Super Bonbon" }, + "HEALING_CHARM": { name: "Charme Soin", description: "Augmente de 10% l’efficacité des capacités et objets de soin de PV (hors Rappels)." }, + "CANDY_JAR": { name: "Bonbonnière", description: "Augmente de 1 le nombre de niveaux gagnés à l’utilisation d’un Super Bonbon." }, - "BERRY_POUCH": { name: "Sac à Baies", description: "Ajoute 30% de chances qu’une Baie utilisée ne soit pas consommée" }, + "BERRY_POUCH": { name: "Sac à Baies", description: "Ajoute 30% de chances qu’une Baie utilisée ne soit pas consommée." }, "FOCUS_BAND": { name: "Bandeau", description: "Ajoute 10% de chances de survivre avec 1 PV si les dégâts reçus pouvaient mettre K.O." }, - "QUICK_CLAW": { name: "Vive Griffe", description: "Ajoute 10% de chances d’agir en premier, indépendamment de la vitesse (après la priorité)" }, + "QUICK_CLAW": { name: "Vive Griffe", description: "Ajoute 10% de chances d’agir en premier, indépendamment de la vitesse (après la priorité)." }, - "KINGS_ROCK": { name: "Roche Royale", description: "Ajoute 10% de chances qu’une capacité offensive apeure l’adversaire" }, + "KINGS_ROCK": { name: "Roche Royale", description: "Ajoute 10% de chances qu’une capacité offensive apeure l’adversaire." }, - "LEFTOVERS": { name: "Restes", description: "Soigne à chaque tour 1/16 des PV max d’un Pokémon" }, - "SHELL_BELL": { name: "Grelot Coque", description: "Soigne 1/8 des dégâts infligés par un Pokémon" }, + "LEFTOVERS": { name: "Restes", description: "Soigne à chaque tour 1/16 des PV max d’un Pokémon." }, + "SHELL_BELL": { name: "Grelot Coque", description: "Soigne 1/8 des dégâts infligés par un Pokémon." }, - "TOXIC_ORB": { name: "Orbe Toxique", description: "Un orbe bizarre qui empoisonne gravement son porteur durant le combat" }, - "FLAME_ORB": { name: "Orbe Flamme", description: "Un orbe bizarre qui brûle son porteur durant le combat" }, + "TOXIC_ORB": { name: "Orbe Toxique", description: "Un orbe bizarre qui empoisonne gravement son porteur durant le combat." }, + "FLAME_ORB": { name: "Orbe Flamme", description: "Un orbe bizarre qui brûle son porteur durant le combat." }, "BATON": { name: "Bâton", description: "Permet de transmettre les effets en cas de changement de Pokémon. Ignore les pièges." }, - "SHINY_CHARM": { name: "Charme Chroma", description: "Augmente énormément les chances de rencontrer un Pokémon sauvage chromatique" }, - "ABILITY_CHARM": { name: "Charme Talent", description: "Augmente énormément les chances de rencontrer un Pokémon sauvage avec un Talent Caché" }, + "SHINY_CHARM": { name: "Charme Chroma", description: "Augmente énormément les chances de rencontrer un Pokémon sauvage chromatique." }, + "ABILITY_CHARM": { name: "Charme Talent", description: "Augmente énormément les chances de rencontrer un Pokémon sauvage avec un Talent Caché." }, "IV_SCANNER": { name: "Scanner d’IV", description: "Révèle la qualité de deux IV d’un Pokémon sauvage par scanner possédé. Les meilleurs IV sont révélés en priorité." }, @@ -229,9 +229,9 @@ export const modifierType: ModifierTypeTranslationEntries = { "GOLDEN_POKEBALL": { name: "Poké Ball Dorée", description: "Ajoute un choix d’objet à la fin de chaque combat" }, - "ENEMY_DAMAGE_BOOSTER": { name: "Jeton Dégâts", description: "Augmente les dégâts de 5%" }, - "ENEMY_DAMAGE_REDUCTION": { name: "Jeton Protection", description: "Diminue les dégâts reçus de 2,5%" }, - "ENEMY_HEAL": { name: "Jeton Soin", description: "Soigne 2% des PV max à chaque tour" }, + "ENEMY_DAMAGE_BOOSTER": { name: "Jeton Dégâts", description: "Augmente les dégâts de 5%." }, + "ENEMY_DAMAGE_REDUCTION": { name: "Jeton Protection", description: "Diminue les dégâts reçus de 2,5%." }, + "ENEMY_HEAL": { name: "Jeton Soin", description: "Soigne 2% des PV max à chaque tour." }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Jeton Poison" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Jeton Paralysie" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Jeton Brulure" }, diff --git a/src/locales/fr/party-ui-handler.ts b/src/locales/fr/party-ui-handler.ts new file mode 100644 index 00000000000..9d3c7baa9ae --- /dev/null +++ b/src/locales/fr/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "Send Out", + "SUMMARY": "Summary", + "CANCEL": "Cancel", + "RELEASE": "Release", + "APPLY": "Apply", + "TEACH": "Teach" +} as const; diff --git a/src/locales/fr/save-slot-select-ui-handler.ts b/src/locales/fr/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..53b68191b9f --- /dev/null +++ b/src/locales/fr/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "Effacer les données de l’emplacement sélectionné ?", + "loading": "Chargement…", + "wave": "Vague", + "lv": "N.", + "empty": "Vide", +} as const; diff --git a/src/locales/fr/starter-select-ui-handler.ts b/src/locales/fr/starter-select-ui-handler.ts index 4aa6185b439..9f504cab11e 100644 --- a/src/locales/fr/starter-select-ui-handler.ts +++ b/src/locales/fr/starter-select-ui-handler.ts @@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "selectMoveSwapWith": "Sélectionnez laquelle échanger avec", "unlockPassive": "Débloquer Passif", "reduceCost": "Diminuer le cout", - "cycleShiny": "R: » Chromatiques", - "cycleForm": "F: » Formes", - "cycleGender": "G: » Sexes", - "cycleAbility": "E: » Talents", - "cycleNature": "N: » Natures", - "cycleVariant": "V: » Variants", + "cycleShiny": ": » Chromatiques", + "cycleForm": ": » Formes", + "cycleGender": ": » Sexes", + "cycleAbility": ": » Talents", + "cycleNature": ": » Natures", + "cycleVariant": ": » Variants", "enablePassive": "Activer Passif", "disablePassive": "Désactiver Passif", "locked": "Verrouillé", diff --git a/src/locales/fr/trainers.ts b/src/locales/fr/trainers.ts index 6ed221a7b86..a44c03e1b68 100644 --- a/src/locales/fr/trainers.ts +++ b/src/locales/fr/trainers.ts @@ -95,6 +95,7 @@ export const trainerClasses: SimpleTranslationEntries = { "rich_kid_female": "Mademoiselle", "rich_kids": "Richards", "roughneck": "Loubard", + "sailor": "Marin", "scientist": "Scientifique", "scientist_female": "Scientifique", "scientists": "Scientifiques", diff --git a/src/locales/it/achv.ts b/src/locales/it/achv.ts index 42b1995bcde..bf1bfc295e8 100644 --- a/src/locales/it/achv.ts +++ b/src/locales/it/achv.ts @@ -1,6 +1,7 @@ import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "Achievements", }, @@ -168,4 +169,102 @@ export const achv: AchievementTranslationEntries = { name: "Undefeated", description: "Beat the game in classic mode", }, + + "MONO_GEN_ONE": { + name: "The Original Rival", + description: "Complete the generation one only challenge.", + }, + "MONO_GEN_TWO": { + name: "Generation 1.5", + description: "Complete the generation two only challenge.", + }, + "MONO_GEN_THREE": { + name: "Too much water?", + description: "Complete the generation three only challenge.", + }, + "MONO_GEN_FOUR": { + name: "Is she really the hardest?", + description: "Complete the generation four only challenge.", + }, + "MONO_GEN_FIVE": { + name: "All Original", + description: "Complete the generation five only challenge.", + }, + "MONO_GEN_SIX": { + name: "Almost Royalty", + description: "Complete the generation six only challenge.", + }, + "MONO_GEN_SEVEN": { + name: "Only Technically", + description: "Complete the generation seven only challenge.", + }, + "MONO_GEN_EIGHT": { + name: "A Champion Time!", + description: "Complete the generation eight only challenge.", + }, + "MONO_GEN_NINE": { + name: "She was going easy on you", + description: "Complete the generation nine only challenge.", + }, + + "MonoType": { + description: "Complete the {{type}} monotype challenge.", + }, + "MONO_NORMAL": { + name: "Mono NORMAL", + }, + "MONO_FIGHTING": { + name: "I Know Kung Fu", + }, + "MONO_FLYING": { + name: "Mono FLYING", + }, + "MONO_POISON": { + name: "Kanto's Favourite", + }, + "MONO_GROUND": { + name: "Mono GROUND", + }, + "MONO_ROCK": { + name: "Brock Hard", + }, + "MONO_BUG": { + name: "Sting Like A Beedrill", + }, + "MONO_GHOST": { + name: "Who you gonna call?", + }, + "MONO_STEEL": { + name: "Mono STEEL", + }, + "MONO_FIRE": { + name: "Mono FIRE", + }, + "MONO_WATER": { + name: "When It Rains, It Pours", + }, + "MONO_GRASS": { + name: "Mono GRASS", + }, + "MONO_ELECTRIC": { + name: "Mono ELECTRIC", + }, + "MONO_PSYCHIC": { + name: "Mono PSYCHIC", + }, + "MONO_ICE": { + name: "Mono ICE", + }, + "MONO_DRAGON": { + name: "Mono DRAGON", + }, + "MONO_DARK": { + name: "It's just a phase", + }, + "MONO_FAIRY": { + name: "Mono FAIRY", + }, } as const; + +// Achievement translations for the when the player character is female (it for now uses the same translations as the male version) +export const PGFachv: AchievementTranslationEntries = PGMachv; diff --git a/src/locales/it/challenges.ts b/src/locales/it/challenges.ts new file mode 100644 index 00000000000..149037be740 --- /dev/null +++ b/src/locales/it/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "Challenge Modifiers", + "points": "Bad Ideas", + "confirm_start": "Proceed with these challenges?", + "singleGeneration.name": "Mono Gen", + "singleGeneration.value.0": "Off", + "singleGeneration.desc.0": "You can only use pokemon from the chosen generation.", + "singleGeneration.value.1": "Gen 1", + "singleGeneration.desc.1": "You can only use pokemon from generation one.", + "singleGeneration.value.2": "Gen 2", + "singleGeneration.desc.2": "You can only use pokemon from generation two.", + "singleGeneration.value.3": "Gen 3", + "singleGeneration.desc.3": "You can only use pokemon from generation three.", + "singleGeneration.value.4": "Gen 4", + "singleGeneration.desc.4": "You can only use pokemon from generation four.", + "singleGeneration.value.5": "Gen 5", + "singleGeneration.desc.5": "You can only use pokemon from generation five.", + "singleGeneration.value.6": "Gen 6", + "singleGeneration.desc.6": "You can only use pokemon from generation six.", + "singleGeneration.value.7": "Gen 7", + "singleGeneration.desc.7": "You can only use pokemon from generation seven.", + "singleGeneration.value.8": "Gen 8", + "singleGeneration.desc.8": "You can only use pokemon from generation eight.", + "singleGeneration.value.9": "Gen 9", + "singleGeneration.desc.9": "You can only use pokemon from generation nine.", + "singleType.name": "Mono Type", + "singleType.value.0": "Off", + "singleType.desc.0": "You can only use pokemon of the chosen type.", + "singleType.value.1": "Normal", + "singleType.desc.1": "You can only use pokemon with the Normal type.", + "singleType.value.2": "Fighting", + "singleType.desc.2": "You can only use pokemon with the Fighting type.", + "singleType.value.3": "Flying", + "singleType.desc.3": "You can only use pokemon with the Flying type.", + "singleType.value.4": "Poison", + "singleType.desc.4": "You can only use pokemon with the Poison type.", + "singleType.value.5": "Ground", + "singleType.desc.5": "You can only use pokemon with the Ground type.", + "singleType.value.6": "Rock", + "singleType.desc.6": "You can only use pokemon with the Rock type.", + "singleType.value.7": "Bug", + "singleType.desc.7": "You can only use pokemon with the Bug type.", + "singleType.value.8": "Ghost", + "singleType.desc.8": "You can only use pokemon with the Ghost type.", + "singleType.value.9": "Steel", + "singleType.desc.9": "You can only use pokemon with the Steel type.", + "singleType.value.10": "Fire", + "singleType.desc.10": "You can only use pokemon with the Fire type.", + "singleType.value.11": "Water", + "singleType.desc.11": "You can only use pokemon with the Water type.", + "singleType.value.12": "Grass", + "singleType.desc.12": "You can only use pokemon with the Grass type.", + "singleType.value.13": "Electric", + "singleType.desc.13": "You can only use pokemon with the Electric type.", + "singleType.value.14": "Psychic", + "singleType.desc.14": "You can only use pokemon with the Psychic type.", + "singleType.value.15": "Ice", + "singleType.desc.15": "You can only use pokemon with the Ice type.", + "singleType.value.16": "Dragon", + "singleType.desc.16": "You can only use pokemon with the Dragon type.", + "singleType.value.17": "Dark", + "singleType.desc.17": "You can only use pokemon with the Dark type.", + "singleType.value.18": "Fairy", + "singleType.desc.18": "You can only use pokemon with the Fairy type.", +} as const; diff --git a/src/locales/it/config.ts b/src/locales/it/config.ts index 8549afb12be..333c11ae6a8 100644 --- a/src/locales/it/config.ts +++ b/src/locales/it/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -29,22 +31,26 @@ import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; +import { partyUiHandler } from "./party-ui-handler"; export const itConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const itConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -66,6 +73,7 @@ export const itConfig = { pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +81,6 @@ export const itConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, + partyUiHandler: partyUiHandler }; diff --git a/src/locales/it/dialogue.ts b/src/locales/it/dialogue.ts index faabab3077d..26602079f65 100644 --- a/src/locales/it/dialogue.ts +++ b/src/locales/it/dialogue.ts @@ -371,6 +371,18 @@ export const PGMdialogue: DialogueTranslationEntries = { 3: "Ow! I scorched the tip of my nose!" }, }, + "sailor": { + "encounter": { + 1: "Matey, you're walking the plank if you lose!", + 2: "Come on then! My sailor's pride is at stake!", + 3: "Ahoy there! Are you seasick?" + }, + "victory": { + 1: "Argh! Beaten by a kid!", + 2: "Your spirit sank me!", + 3: "I think it's me that's seasick..." + }, + }, "brock": { "encounter": { 1: "My expertise on Rock-type Pokémon will take you down! Come on!", diff --git a/src/locales/it/game-mode.ts b/src/locales/it/game-mode.ts new file mode 100644 index 00000000000..be342b4c390 --- /dev/null +++ b/src/locales/it/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "Classic", + "endless": "Endless", + "endlessSpliced": "Endless (Spliced)", + "dailyRun": "Daily Run", + "unknown": "Unknown", + "challenge": "Challenge", +} as const; diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index e891146f754..4e3da7ca992 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -40,13 +40,13 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Classifica Settimanale", "noRankings": "Nessuna Classifica", "loading": "Caricamento…", + "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "Giocatori Online", "evolving": "Cosa?\n{{pokemonName}} si evolvendo!", "stoppedEvolving": "{{pokemonName}} ha smesso di evolversi.", "pauseEvolutionsQuestion": "Vuoi sospendere le evoluzioni per {{pokemonName}}?\nLe evoluzioni possono essere riattivate dalla schermata del party.", "evolutionsPaused": "Le evoluzioni sono state sospese per {{pokemonName}}.", "evolutionDone": "Congratulazioni!\n{{pokemonName}} si è evoluto in {{evolvedPokemonName}}!", - "empty":"Vuoto", "yes":"Si", "no":"No", "disclaimer": "DISCLAIMER", diff --git a/src/locales/it/modifier-type.ts b/src/locales/it/modifier-type.ts index ac313e2444c..746f4a31eed 100644 --- a/src/locales/it/modifier-type.ts +++ b/src/locales/it/modifier-type.ts @@ -4,11 +4,11 @@ export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { "AddPokeballModifierType": { name: "{{modifierCount}}x {{pokeballName}}", - description: "Ricevi {{pokeballName}} x{{modifierCount}} (Inventario: {{pokeballAmount}}) \nTasso di cattura: {{catchRate}}", + description: "Ricevi {{pokeballName}} x{{modifierCount}} (Inventario: {{pokeballAmount}}) \nTasso di cattura: {{catchRate}}.", }, "AddVoucherModifierType": { - name: "{{modifierCount}}x {{voucherTypeName}}", - description: "Ricevi {{voucherTypeName}} x{{modifierCount}}", + name: "{{modifierCount}}x {{voucherTypeName}}.", + description: "Ricevi {{voucherTypeName}} x{{modifierCount}}.", }, "PokemonHeldItemModifierType": { extra: { @@ -17,63 +17,63 @@ export const modifierType: ModifierTypeTranslationEntries = { } }, "PokemonHpRestoreModifierType": { - description: "Restituisce {{restorePoints}} PS o {{restorePercent}}% PS ad un Pokémon, a seconda del valore più alto", + description: "Restituisce {{restorePoints}} PS o {{restorePercent}}% PS ad un Pokémon, a seconda del valore più alto.", extra: { - "fully": "Restituisce tutti i PS ad un Pokémon", - "fullyWithStatus": "Restituisce tutti i PS ad un Pokémon e lo cura da ogni stato", + "fully": "Restituisce tutti i PS ad un Pokémon.", + "fullyWithStatus": "Restituisce tutti i PS ad un Pokémon e lo cura da ogni stato.", } }, "PokemonReviveModifierType": { - description: "Rianima un Pokémon esausto e gli restituisce il {{restorePercent}}% PS", + description: "Rianima un Pokémon esausto e gli restituisce il {{restorePercent}}% PS.", }, "PokemonStatusHealModifierType": { - description: "Cura tutti i problemi di stato di un Pokémon", + description: "Cura tutti i problemi di stato di un Pokémon.", }, "PokemonPpRestoreModifierType": { - description: "Restituisce {{restorePoints}} PP per una mossa di un Pokémon ", + description: "Restituisce {{restorePoints}} PP per una mossa di un Pokémon.", extra: { - "fully": "Restituisce tutti i PP di una mossa", + "fully": "Restituisce tutti i PP di una mossa.", } }, "PokemonAllMovePpRestoreModifierType": { - description: "Restituisce {{restorePoints}} PP a tutte le mosse di un Pokémon", + description: "Restituisce {{restorePoints}} PP a tutte le mosse di un Pokémon.", extra: { - "fully": "Restituisce tutti i PP a tutte le mosse di un Pokémon", + "fully": "Restituisce tutti i PP a tutte le mosse di un Pokémon.", } }, "PokemonPpUpModifierType": { - description: "Aumenta i PP di una mossa di {{upPoints}} per ogni 5 PP (massimo 3)", + description: "Aumenta i PP di una mossa di {{upPoints}} per ogni 5 PP (massimo 3).", }, "PokemonNatureChangeModifierType": { - name: "Menta {{natureName}}", - description: "Cambia la natura del Pokémon in {{natureName}} e sblocca la natura per il Pokémon iniziale", + name: "Menta {{natureName}}.", + description: "Cambia la natura del Pokémon in {{natureName}} e sblocca la natura per il Pokémon iniziale.", }, "DoubleBattleChanceBoosterModifierType": { - description: "Raddoppia la possibilità di imbattersi in doppie battaglie per {{battleCount}} battaglie", + description: "Raddoppia la possibilità di imbattersi in doppie battaglie per {{battleCount}} battaglie.", }, "TempBattleStatBoosterModifierType": { - description: "Aumenta {{tempBattleStatName}} di un livello a tutti i Pokémon nel gruppo per 5 battaglie", + description: "Aumenta {{tempBattleStatName}} di un livello a tutti i Pokémon nel gruppo per 5 battaglie.", }, "AttackTypeBoosterModifierType": { - description: "Aumenta la potenza delle mosse di tipo {{moveType}} del 20% per un Pokémon", + description: "Aumenta la potenza delle mosse di tipo {{moveType}} del 20% per un Pokémon.", }, "PokemonLevelIncrementModifierType": { - description: "Fa salire un Pokémon di un livello", + description: "Fa salire un Pokémon di un livello.", }, "AllPokemonLevelIncrementModifierType": { - description: "Aumenta il livello di tutti i Pokémon nel gruppo di 1", + description: "Aumenta il livello di tutti i Pokémon nel gruppo di 1.", }, "PokemonBaseStatBoosterModifierType": { - description: "Aumenta {{statName}} di base del possessore del 10%", + description: "Aumenta {{statName}} di base del possessore del 10%.", }, "AllPokemonFullHpRestoreModifierType": { - description: "Recupera il 100% dei PS per tutti i Pokémon", + description: "Recupera il 100% dei PS per tutti i Pokémon.", }, "AllPokemonFullReviveModifierType": { - description: "Rianima tutti i Pokémon esausti restituendogli tutti i PS", + description: "Rianima tutti i Pokémon esausti restituendogli tutti i PS.", }, "MoneyRewardModifierType": { - description: "Garantisce una {{moneyMultiplier}} quantità di soldi (₽{{moneyAmount}})", + description: "Garantisce una {{moneyMultiplier}} quantità di soldi (₽{{moneyAmount}}).", extra: { "small": "poca", "moderate": "moderata", @@ -81,62 +81,62 @@ export const modifierType: ModifierTypeTranslationEntries = { }, }, "ExpBoosterModifierType": { - description: "Aumenta il guadagno di Punti Esperienza del {{boostPercent}}%", + description: "Aumenta il guadagno di Punti Esperienza del {{boostPercent}}%.", }, "PokemonExpBoosterModifierType": { - description: "Aumenta il guadagno di Punti Esperienza del possessore del {{boostPercent}}%", + description: "Aumenta il guadagno di Punti Esperienza del possessore del {{boostPercent}}%.", }, "PokemonFriendshipBoosterModifierType": { - description: "Aumenta del 50% il guadagno di amicizia per vittoria", + description: "Aumenta del 50% il guadagno di amicizia per vittoria.", }, "PokemonMoveAccuracyBoosterModifierType": { - description: "Aumenta l'accuratezza delle mosse di {{accuracyAmount}} (massimo 100)", + description: "Aumenta l'accuratezza delle mosse di {{accuracyAmount}} (massimo 100).", }, "PokemonMultiHitModifierType": { - description: "Gli attacchi colpiscono una volta in più al costo di una riduzione di potenza del 60/75/82,5% per mossa", + description: "Gli attacchi colpiscono una volta in più al costo di una riduzione di potenza del 60/75/82,5% per mossa.", }, "TmModifierType": { - name: "MT{{moveId}} - {{moveName}}", - description: "Insegna {{moveName}} a un Pokémon", + name: "MT{{moveId}} - {{moveName}}.", + description: "Insegna {{moveName}} a un Pokémon.", }, "TmModifierTypeWithInfo": { name: "MT{{moveId}} - {{moveName}}", - description: "Insegna {{moveName}} a un Pokémon\n(Hold C or Shift for more info)", + description: "Insegna {{moveName}} a un Pokémon\n(Hold C or Shift for more info).", }, "EvolutionItemModifierType": { - description: "Fa evolvere determinate specie di Pokémon", + description: "Fa evolvere determinate specie di Pokémon.", }, "FormChangeItemModifierType": { - description: "Fa cambiare forma a determinati Pokémon", + description: "Fa cambiare forma a determinati Pokémon.", }, "FusePokemonModifierType": { - description: "Combina due Pokémon (trasferisce i poteri, divide le statistiche e i tipi base, condivide il pool di mosse)", + description: "Combina due Pokémon (trasferisce i poteri, divide le statistiche e i tipi base, condivide il pool di mosse).", }, "TerastallizeModifierType": { name: "Teralite {{teraType}}", - description: "Teracristallizza in {{teraType}} il possessore per massimo 10 battaglie", + description: "Teracristallizza in {{teraType}} il possessore per massimo 10 battaglie.", }, "ContactHeldItemTransferChanceModifierType": { - description: "Quando si attacca, c'è una probabilità del {{chancePercent}}% che l'oggetto in possesso del nemico venga rubato", + description: "Quando si attacca, c'è una probabilità del {{chancePercent}}% che l'oggetto in possesso del nemico venga rubato.", }, "TurnHeldItemTransferModifierType": { - description: "Ogni turno, il possessore acquisisce un oggetto posseduto dal nemico", + description: "Ogni turno, il possessore acquisisce un oggetto posseduto dal nemico.", }, "EnemyAttackStatusEffectChanceModifierType": { - description: "Aggiunge una probabilità del {{chancePercent}}% di infliggere {{statusEffect}} con le mosse d'attacco", + description: "Aggiunge una probabilità del {{chancePercent}}% di infliggere {{statusEffect}} con le mosse d'attacco.", }, "EnemyEndureChanceModifierType": { - description: "Aggiunge una probabilità del {{probabilitàPercent}}% di resistere ad un colpo", + description: "Aggiunge una probabilità del {{probabilitàPercent}}% di resistere ad un colpo.", }, "RARE_CANDY": { name: "Caramella Rara" }, "RARER_CANDY": { name: "Caramella Molto Rara" }, - "MEGA_BRACELET": { name: "Megapolsiera", description: "Le Megapietre sono disponibili" }, - "DYNAMAX_BAND": { name: "Polsino Dynamax", description: "I Fungomax sono disponibili" }, - "TERA_ORB": { name: "Terasfera", description: "I Teraliti sono disponibili" }, + "MEGA_BRACELET": { name: "Megapolsiera", description: "Le Megapietre sono disponibili." }, + "DYNAMAX_BAND": { name: "Polsino Dynamax", description: "I Fungomax sono disponibili." }, + "TERA_ORB": { name: "Terasfera", description: "I Teraliti sono disponibili." }, - "MAP": { name: "Mappa", description: "Permette di scegliere la propria strada a un bivio" }, + "MAP": { name: "Mappa", description: "Permette di scegliere la propria strada a un bivio." }, "POTION": { name: "Pozione" }, "SUPER_POTION": { name: "Superpozione" }, @@ -151,7 +151,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "SACRED_ASH": { name: "Cenere Magica" }, - "REVIVER_SEED": { name: "Revitalseme", description: "Il possessore recupera 1/2 di PS in caso di svenimento" }, + "REVIVER_SEED": { name: "Revitalseme", description: "Il possessore recupera 1/2 di PS in caso di svenimento." }, "ETHER": { name: "Etere" }, "MAX_ETHER": { name: "Etere Max" }, @@ -166,12 +166,12 @@ export const modifierType: ModifierTypeTranslationEntries = { "SUPER_LURE": { name: "Profumo Invito Super" }, "MAX_LURE": { name: "Profumo Invito Max" }, - "MEMORY_MUSHROOM": { name: "Fungo della Memoria", description: "Ricorda la mossa dimenticata di un Pokémon" }, + "MEMORY_MUSHROOM": { name: "Fungo della Memoria", description: "Ricorda la mossa dimenticata di un Pokémon." }, - "EXP_SHARE": { name: "Condividi Esperienza", description: "Tutti i Pokémon della squadra ricevono il 20% dei Punti Esperienza dalla lotta anche se non vi hanno partecipato" }, - "EXP_BALANCE": { name: "Bilancia Esperienza", description: "Bilancia i Punti Esperienza ricevuti verso i Pokémon del gruppo di livello inferiore" }, + "EXP_SHARE": { name: "Condividi Esperienza", description: "Tutti i Pokémon della squadra ricevono il 20% dei Punti Esperienza dalla lotta anche se non vi hanno partecipato." }, + "EXP_BALANCE": { name: "Bilancia Esperienza", description: "Bilancia i Punti Esperienza ricevuti verso i Pokémon del gruppo di livello inferiore." }, - "OVAL_CHARM": { name: "Ovamuleto", description: "Quando più Pokémon partecipano a una battaglia, ognuno di essi riceve il 10% in più dell'esperienza totale" }, + "OVAL_CHARM": { name: "Ovamuleto", description: "Quando più Pokémon partecipano a una battaglia, ognuno di essi riceve il 10% in più dell'esperienza totale." }, "EXP_CHARM": { name: "Esperienzamuleto" }, "SUPER_EXP_CHARM": { name: "Esperienzamuleto Super" }, @@ -182,62 +182,62 @@ export const modifierType: ModifierTypeTranslationEntries = { "SOOTHE_BELL": { name: "Calmanella" }, - "SOUL_DEW": { name: "Cuorugiada", description: "Aumenta del 10% l'influenza della natura di un Pokémon sulle sue statistiche (Aggiuntivo)" }, + "SOUL_DEW": { name: "Cuorugiada", description: "Aumenta del 10% l'influenza della natura di un Pokémon sulle sue statistiche (Aggiuntivo)." }, "NUGGET": { name: "Pepita" }, "BIG_NUGGET": { name: "Granpepita" }, "RELIC_GOLD": { name: " Dobloantico" }, - "AMULET_COIN": { name: "Monetamuleto", description: "Aumenta le ricompense in denaro del 20%" }, - "GOLDEN_PUNCH": { name: "Pugno Dorato", description: "Garantisce il 50% dei danni inflitti come denaro" }, - "COIN_CASE": { name: " Salvadanaio", description: "Dopo ogni 10° battaglia, riceverete il 10% del vostro denaro in interessi" }, + "AMULET_COIN": { name: "Monetamuleto", description: "Aumenta le ricompense in denaro del 20%." }, + "GOLDEN_PUNCH": { name: "Pugno Dorato", description: "Garantisce il 50% dei danni inflitti come denaro." }, + "COIN_CASE": { name: " Salvadanaio", description: "Dopo ogni 10° battaglia, riceverete il 10% del vostro denaro in interessi." }, - "LOCK_CAPSULE": { name: "Capsula Scrigno", description: "Permette di bloccare le rarità degli oggetti quando si fa un reroll degli oggetti" }, + "LOCK_CAPSULE": { name: "Capsula Scrigno", description: "Permette di bloccare le rarità degli oggetti quando si fa un reroll degli oggetti." }, "GRIP_CLAW": { name: "Presartigli" }, "WIDE_LENS": { name: "Grandelente" }, "MULTI_LENS": { name: "Multilente" }, - "HEALING_CHARM": { name: "Curamuleto", description: "Aumenta del 10% l'efficacia delle mosse e degli oggetti che ripristinano i PS (escluse le rianimazioni)" }, - "CANDY_JAR": { name: "Barattolo di caramelle", description: "Aumenta di 1 il numero di livelli aggiunti dalle Caramelle Rare" }, + "HEALING_CHARM": { name: "Curamuleto", description: "Aumenta del 10% l'efficacia delle mosse e degli oggetti che ripristinano i PS (escluse le rianimazioni)." }, + "CANDY_JAR": { name: "Barattolo di caramelle", description: "Aumenta di 1 il numero di livelli aggiunti dalle Caramelle Rare." }, - "BERRY_POUCH": { name: "Porta Bacche", description: "Aggiunge il 30% di possibilità che una bacca usata non venga consumata" }, + "BERRY_POUCH": { name: "Porta Bacche", description: "Aggiunge il 30% di possibilità che una bacca usata non venga consumata." }, - "FOCUS_BAND": { name: "Bandana", description: "Chi ce l'ha ottiene il 10% di possibilità aggiuntivo di evitare un potenziale KO e rimanere con un solo PS" }, + "FOCUS_BAND": { name: "Bandana", description: "Chi ce l'ha ottiene il 10% di possibilità aggiuntivo di evitare un potenziale KO e rimanere con un solo PS." }, - "QUICK_CLAW": { name: "Rapidartigli", description: "Aggiunge una probabilità del 10% di muoversi per primi, indipendentemente dalla velocità (dopo la priorità)" }, + "QUICK_CLAW": { name: "Rapidartigli", description: "Aggiunge una probabilità del 10% di muoversi per primi, indipendentemente dalla velocità (dopo la priorità)." }, - "KINGS_ROCK": { name: "Roccia di re", description: "Aggiunge il 10% di possibilità che una mossa d'attacco faccia tentennare l'avversario" }, + "KINGS_ROCK": { name: "Roccia di re", description: "Aggiunge il 10% di possibilità che una mossa d'attacco faccia tentennare l'avversario." }, - "LEFTOVERS": { name: "Avanzi", description: "Ripristina 1/16 dei PS massimi di un Pokémon ogni turno" }, - "SHELL_BELL": { name: "Conchinella", description: "Guarisce 1/8 del danno inflitto a un Pokémon" }, + "LEFTOVERS": { name: "Avanzi", description: "Ripristina 1/16 dei PS massimi di un Pokémon ogni turno." }, + "SHELL_BELL": { name: "Conchinella", description: "Guarisce 1/8 del danno inflitto a un Pokémon." }, - "TOXIC_ORB": { name: "Tossicsfera", description: "Sfera bizzarra che iperavvelena chi l’ha con sé in una lotta" }, - "FLAME_ORB": { name: "Fiammosfera", description: "Sfera bizzarra che procura una scottatura a chi l’ha con sé in una lotta" }, + "TOXIC_ORB": { name: "Tossicsfera", description: "Sfera bizzarra che iperavvelena chi l’ha con sé in una lotta." }, + "FLAME_ORB": { name: "Fiammosfera", description: "Sfera bizzarra che procura una scottatura a chi l’ha con sé in una lotta." }, - "BATON": { name: "Staffetta", description: "Permette di trasmettere gli effetti quando si cambia Pokémon, aggirando anche le trappole" }, + "BATON": { name: "Staffetta", description: "Permette di trasmettere gli effetti quando si cambia Pokémon, aggirando anche le trappole." }, - "SHINY_CHARM": { name: "Cromamuleto", description: "Misterioso amuleto luminoso che aumenta la probabilità di incontrare Pokémon cromatici" }, - "ABILITY_CHARM": { name: "Abilitamuleto", description: "Aumenta drasticamente la possibilità che un Pokémon selvatico abbia un'abilità nascosta" }, + "SHINY_CHARM": { name: "Cromamuleto", description: "Misterioso amuleto luminoso che aumenta la probabilità di incontrare Pokémon cromatici." }, + "ABILITY_CHARM": { name: "Abilitamuleto", description: "Aumenta drasticamente la possibilità che un Pokémon selvatico abbia un'abilità nascosta." }, - "IV_SCANNER": { name: "Scanner IV", description: "Permette di scansionare gli IV dei Pokémon selvatici. Vengono rivelati 2 IV per pila. I migliori IV vengono mostrati per primi" }, + "IV_SCANNER": { name: "Scanner IV", description: "Permette di scansionare gli IV dei Pokémon selvatici. Vengono rivelati 2 IV per pila. I migliori IV vengono mostrati per primi." }, "DNA_SPLICERS": { name: " Cuneo DNA" }, "MINI_BLACK_HOLE": { name: "Piccolo Buco Nero" }, - "GOLDEN_POKEBALL": { name: "Poké Ball Oro", description: "Aggiunge 1 opzione di oggetto extra alla fine di ogni battaglia" }, + "GOLDEN_POKEBALL": { name: "Poké Ball Oro", description: "Aggiunge 1 opzione di oggetto extra alla fine di ogni battaglia." }, - "ENEMY_DAMAGE_BOOSTER": { name: "Gettone del Danno", description: "Aumenta il danno del 5%" }, - "ENEMY_DAMAGE_REDUCTION": { name: "Gettone della Protezione", description: "Riduce i danni ricevuti del 2.5%" }, - "ENEMY_HEAL": { name: "Gettone del Recupero", description: "Cura il 2% dei PS massimi ogni turno" }, + "ENEMY_DAMAGE_BOOSTER": { name: "Gettone del Danno", description: "Aumenta il danno del 5%." }, + "ENEMY_DAMAGE_REDUCTION": { name: "Gettone della Protezione", description: "Riduce i danni ricevuti del 2.5%." }, + "ENEMY_HEAL": { name: "Gettone del Recupero", description: "Cura il 2% dei PS massimi ogni turno." }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Gettone del Veleno" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Gettone della Paralisi" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Gettone della Bruciatura" }, - "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone Guarigione Completa", description: "Aggiunge una probabilità del 2.5% a ogni turno di curare una condizione di stato" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone Guarigione Completa", description: "Aggiunge una probabilità del 2.5% a ogni turno di curare una condizione di stato." }, "ENEMY_ENDURE_CHANCE": { name: "Gettone di Resistenza" }, - "ENEMY_FUSED_CHANCE": { name: "Gettone della fusione", description: "Aggiunge l'1% di possibilità che un Pokémon selvatico sia una fusione" }, + "ENEMY_FUSED_CHANCE": { name: "Gettone della fusione", description: "Aggiunge l'1% di possibilità che un Pokémon selvatico sia una fusione." }, }, TempBattleStatBoosterItem: { "x_attack": "Attacco X", diff --git a/src/locales/it/party-ui-handler.ts b/src/locales/it/party-ui-handler.ts new file mode 100644 index 00000000000..9d3c7baa9ae --- /dev/null +++ b/src/locales/it/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "Send Out", + "SUMMARY": "Summary", + "CANCEL": "Cancel", + "RELEASE": "Release", + "APPLY": "Apply", + "TEACH": "Teach" +} as const; diff --git a/src/locales/it/save-slot-select-ui-handler.ts b/src/locales/it/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..16e36e471a5 --- /dev/null +++ b/src/locales/it/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "Overwrite the data in the selected slot?", + "loading": "Loading...", + "wave": "Wave", + "lv": "Lv", + "empty": "Vuoto", +} as const; diff --git a/src/locales/it/starter-select-ui-handler.ts b/src/locales/it/starter-select-ui-handler.ts index 0f3f9df421a..ae406183a90 100644 --- a/src/locales/it/starter-select-ui-handler.ts +++ b/src/locales/it/starter-select-ui-handler.ts @@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "selectMoveSwapWith": "Seleziona una mossa da scambiare con", "unlockPassive": "Sblocca Passiva", "reduceCost": "Riduci Costo", - "cycleShiny": "R: Alterna Shiny", - "cycleForm": "F: Alterna Forma", - "cycleGender": "G: Alterna Sesso", - "cycleAbility": "E: Alterna Abilità", - "cycleNature": "N: Alterna Natura", - "cycleVariant": "V: Alterna Variante", + "cycleShiny": ": Alterna Shiny", + "cycleForm": ": Alterna Forma", + "cycleGender": ": Alterna Sesso", + "cycleAbility": ": Alterna Abilità", + "cycleNature": ": Alterna Natura", + "cycleVariant": ": Alterna Variante", "enablePassive": "Attiva Passiva", "disablePassive": "Disattiva Passiva", "locked": "Bloccato", diff --git a/src/locales/it/trainers.ts b/src/locales/it/trainers.ts index 9c3f025541e..9c0a644c1c6 100644 --- a/src/locales/it/trainers.ts +++ b/src/locales/it/trainers.ts @@ -95,6 +95,7 @@ export const trainerClasses: SimpleTranslationEntries = { "rich_kid_female": "Rich Kid", "rich_kids": "Rich Kids", "roughneck": "Roughneck", + "sailor": "Sailor", "scientist": "Scientist", "scientist_female": "Scientist", "scientists": "Scientists", diff --git a/src/locales/ko/ability-trigger.ts b/src/locales/ko/ability-trigger.ts index 8fed1208fff..3ce78178081 100644 --- a/src/locales/ko/ability-trigger.ts +++ b/src/locales/ko/ability-trigger.ts @@ -3,5 +3,8 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{pokemonName}}[[는]] {{abilityName}} 때문에\n반동 데미지를 받지 않는다!", "badDreams": "{{pokemonName}}[[는]]\n나이트메어 때문에 시달리고 있다!", - "iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!" + "windPowerCharged": "{{pokemonName}}[[는]]\n{{moveName}}에 맞아 충전되었다!", + "perishBody": "{{pokemonName}}의 {{abilityName}} 때문에\n양쪽 포켓몬 모두는 3턴 후에 쓰러져 버린다!", + "poisonHeal": "{{pokemonName}}[[는]] {{abilityName}}[[로]]인해\n조금 회복했다.", + "iceFaceAvoidedDamage": "{{pokemonName}}[[는]] {{abilityName}} 때문에\n데미지를 받지 않는다!", } as const; diff --git a/src/locales/ko/achv.ts b/src/locales/ko/achv.ts index d48a63868b1..e1e9ae74ece 100644 --- a/src/locales/ko/achv.ts +++ b/src/locales/ko/achv.ts @@ -1,6 +1,7 @@ import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "업적", }, @@ -168,4 +169,102 @@ export const achv: AchievementTranslationEntries = { name: "무패", description: "클래식 모드 클리어", }, + + "MONO_GEN_ONE": { + name: "The Original Rival", + description: "Complete the generation one only challenge.", + }, + "MONO_GEN_TWO": { + name: "Generation 1.5", + description: "Complete the generation two only challenge.", + }, + "MONO_GEN_THREE": { + name: "Too much water?", + description: "Complete the generation three only challenge.", + }, + "MONO_GEN_FOUR": { + name: "Is she really the hardest?", + description: "Complete the generation four only challenge.", + }, + "MONO_GEN_FIVE": { + name: "All Original", + description: "Complete the generation five only challenge.", + }, + "MONO_GEN_SIX": { + name: "Almost Royalty", + description: "Complete the generation six only challenge.", + }, + "MONO_GEN_SEVEN": { + name: "Only Technically", + description: "Complete the generation seven only challenge.", + }, + "MONO_GEN_EIGHT": { + name: "A Champion Time!", + description: "Complete the generation eight only challenge.", + }, + "MONO_GEN_NINE": { + name: "She was going easy on you", + description: "Complete the generation nine only challenge.", + }, + + "MonoType": { + description: "Complete the {{type}} monotype challenge.", + }, + "MONO_NORMAL": { + name: "Mono NORMAL", + }, + "MONO_FIGHTING": { + name: "I Know Kung Fu", + }, + "MONO_FLYING": { + name: "Mono FLYING", + }, + "MONO_POISON": { + name: "Kanto's Favourite", + }, + "MONO_GROUND": { + name: "Mono GROUND", + }, + "MONO_ROCK": { + name: "Brock Hard", + }, + "MONO_BUG": { + name: "Sting Like A Beedrill", + }, + "MONO_GHOST": { + name: "Who you gonna call?", + }, + "MONO_STEEL": { + name: "Mono STEEL", + }, + "MONO_FIRE": { + name: "Mono FIRE", + }, + "MONO_WATER": { + name: "When It Rains, It Pours", + }, + "MONO_GRASS": { + name: "Mono GRASS", + }, + "MONO_ELECTRIC": { + name: "Mono ELECTRIC", + }, + "MONO_PSYCHIC": { + name: "Mono PSYCHIC", + }, + "MONO_ICE": { + name: "Mono ICE", + }, + "MONO_DRAGON": { + name: "Mono DRAGON", + }, + "MONO_DARK": { + name: "It's just a phase", + }, + "MONO_FAIRY": { + name: "Mono FAIRY", + }, } as const; + +// Achievement translations for the when the player character is female (it for now uses the same translations as the male version) +export const PGFachv: AchievementTranslationEntries = PGMachv; diff --git a/src/locales/ko/challenges.ts b/src/locales/ko/challenges.ts new file mode 100644 index 00000000000..7c7f6199b1d --- /dev/null +++ b/src/locales/ko/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "챌린지 조건 설정", + "points": "Bad Ideas", + "confirm_start": "이 조건으로 챌린지를 진행하시겠습니까?", + "singleGeneration.name": "단일 세대", + "singleGeneration.value.0": "설정 안함", + "singleGeneration.desc.0": "선택한 세대의 포켓몬만 사용할 수 있습니다.", + "singleGeneration.value.1": "1세대", + "singleGeneration.desc.1": "1세대의 포켓몬만 사용할 수 있습니다.", + "singleGeneration.value.2": "2세대", + "singleGeneration.desc.2": "2세대의 포켓몬만 사용할 수 있습니다.", + "singleGeneration.value.3": "3세대", + "singleGeneration.desc.3": "3세대의 포켓몬만 사용할 수 있습니다.", + "singleGeneration.value.4": "4세대", + "singleGeneration.desc.4": "4세대의 포켓몬만 사용할 수 있습니다r", + "singleGeneration.value.5": "5세대", + "singleGeneration.desc.5": "5세대의 포켓몬만 사용할 수 있습니다.", + "singleGeneration.value.6": "6세대", + "singleGeneration.desc.6": "6세대의 포켓몬만 사용할 수 있습니다.", + "singleGeneration.value.7": "7세대", + "singleGeneration.desc.7": "7세대의 포켓몬만 사용할 수 있습니다.", + "singleGeneration.value.8": "8세대", + "singleGeneration.desc.8": "8세대의 포켓몬만 사용할 수 있습니다.", + "singleGeneration.value.9": "9세대", + "singleGeneration.desc.9": "9세대의 포켓몬만 사용할 수 있습니다.", + "singleType.name": "단일 타입", + "singleType.value.0": "설정 안함", + "singleType.desc.0": "선택한 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.1": "노말", + "singleType.desc.1": "노말 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.2": "격투", + "singleType.desc.2": "격투 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.3": "비행", + "singleType.desc.3": "비행 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.4": "독", + "singleType.desc.4": "독 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.5": "땅", + "singleType.desc.5": "땅 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.6": "바위 ", + "singleType.desc.6": "바위 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.7": "벌레", + "singleType.desc.7": "벌레 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.8": "고스트", + "singleType.desc.8": "고스트 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.9": "강철", + "singleType.desc.9": "강철 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.10": "불꽃", + "singleType.desc.10": "불꽃 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.11": "물", + "singleType.desc.11": "물 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.12": "풀", + "singleType.desc.12": "풀 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.13": "전기", + "singleType.desc.13": "전기 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.14": "에스퍼", + "singleType.desc.14": "에스퍼 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.15": "얼음", + "singleType.desc.15": "얼음 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.16": "드래곤", + "singleType.desc.16": "드래곤 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.17": "악", + "singleType.desc.17": "악 타입의 포켓몬만 사용할 수 있습니다.", + "singleType.value.18": "페어리", + "singleType.desc.18": "페어리 타입의 포켓몬만 사용할 수 있습니다.", +} as const; diff --git a/src/locales/ko/config.ts b/src/locales/ko/config.ts index ad0035ede0f..ca14d87cc10 100644 --- a/src/locales/ko/config.ts +++ b/src/locales/ko/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -29,22 +31,26 @@ import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; +import { partyUiHandler } from "./party-ui-handler"; export const koConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const koConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -66,6 +73,7 @@ export const koConfig = { pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +81,6 @@ export const koConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, + partyUiHandler: partyUiHandler }; diff --git a/src/locales/ko/dialogue.ts b/src/locales/ko/dialogue.ts index 83e49e33923..73c9a7facba 100644 --- a/src/locales/ko/dialogue.ts +++ b/src/locales/ko/dialogue.ts @@ -144,231 +144,243 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "ace_trainer": { "encounter": { - 1: "You seem quite confident.", - 2: "Your Pokémon… Show them to me…", - 3: "Because I'm an Ace Trainer, people think I'm strong.", - 4: "Are you aware of what it takes to be an Ace Trainer?" + 1: "너는 꽤 자신만만해 보이는구나.", + 2: "너의 포켓몬들… 나에게 보여줘…", + 3: "내가 엘리트 트레이너라서, 사람들은 내가 강하다고 생각해.", + 4: "엘리트 트레이너가 되려면 무엇이 필요한지 알고 있니?" }, "victory": { - 1: "Yes… You have good Pokémon…", - 2: "What?! But I'm a battling genius!", - 3: "Of course, you are the main character!", - 4: "OK! OK! You could be an Ace Trainer!" + 1: "그러네… 넌 좋은 포켓몬을 가졌구나…", + 2: "뭐? 말도 안 돼, 난 배틀 천재라구!", + 3: "그래도 역시, 네가 주인공이구나!", + 4: "좋아! 좋아! 너도 엘리트 트레이너가 될 수 있겠어!" }, "defeat": { - 1: "I am devoting my body and soul to Pokémon battles!", - 2: "All within my expectations… Nothing to be surprised about…", - 3: "I thought I'd grow up to be a frail person who looked like they would break if you squeezed them too hard.", - 4: "Of course I'm strong and don't lose. It's important that I win gracefully." + 1: "난 내 몸과 마음을 포켓몬 배틀에 바치고 있어!", + 2: "모두 예상된 일이었어… 이건 놀랄 일이 아니야…", + 3: "난 내가 강하게 압박하면 무너질 연약한 사람이라고 생각했어.", + 4: "난 강하고, 지지 않아. 그저 멋지게 이길 수 없었기 때문이야." } }, "parasol_lady": { "encounter": { - 1: "Time to grace the battlefield with elegance and poise!", + 1: "우아함과 침착함으로 승부하겠습니다!", }, "victory": { - 1: "My elegance remains unbroken!", + 1: "그래도 제 우아함은 무너지지 않아요!", } }, "twins": { "encounter": { - 1: "Get ready, because when we team up, it's double the trouble!", - 2: "Two hearts, one strategy – let's see if you can keep up with our twin power!", - 3: "Hope you're ready for double trouble, because we're about to bring the heat!" + 1: "각오해, 우리가 한 팀이 되면 두 배로 강해진다구!", + 2: "마음은 두 개지만 우리는 하나 – 네가 쌍둥이의 파워를 따라잡을 수 있는지 보겠어!", + 3: "두 배로 각오하는 게 좋을 거야. 우리가 곧 화나게 할 거거든!" }, "victory": { - 1: "We may have lost this round, but our bond remains unbreakable!", - 2: "Our twin spirit won't be dimmed for long.", - 3: "We'll come back stronger as a dynamic duo!" + 1: "비록 우리는 졌지만, 우리의 관계는 깨지지 않아!", + 2: "그래도 우리의 영혼은 오랫동안 흐려지지 않을 거야.", + 3: "더 강력한 듀오로 강해져서 돌아오겠어!" }, "defeat": { - 1: "Twin power reigns supreme!", - 2: "Two hearts, one triumph!", - 3: "Double the smiles, double the victory dance!" + 1: "우리 쌍둥이의 파워는 최고야!", + 2: "마음은 두 개지만 승리는 하나!", + 3: "미소도 두 배, 승리의 댄스도 두 배!" } }, "cyclist": { "encounter": { - 1: "Get ready to eat my dust!", - 2: "Gear up, challenger! I'm about to leave you in the dust!", - 3: "Pedal to the metal, let's see if you can keep pace!" + 1: "내가 만든 먼지나 마실 준비하시지!", + 2: "준비하라구! 난 널 먼지 속에 놓고 올 거니까!", + 3: "전력을 다해야 할 거야, 네가 날 따라올 수 있는지 지켜보겠어!" }, "victory": { - 1: "Spokes may be still, but determination pedals on.", - 2: "Outpaced!", - 3: "The road to victory has many twists and turns yet to explore." + 1: "바퀴가 움직이지 않더라도, 나의 페달은 그렇지 않아.", + 2: "이런, 따라잡혔어!", + 3: "승리로 가는 길에는 아직 만나지 못한 우여곡절이 많이 있구나." }, }, "black_belt": { "encounter": { - 1: "I praise your courage in challenging me! For I am the one with the strongest kick!", - 2: "Oh, I see. Would you like to be cut to pieces? Or do you prefer the role of punching bag?" + 1: "네 용기가 대단하구나! 난 최고의 발차기 실력을 갖추고 있다구!", + 2: "오, 알겠어. 산산조각이 나고 싶구나? 아니면 샌드백이 되고 싶은 거야?" }, "victory": { - 1: "Oh. The Pokémon did the fighting. My strong kick didn't help a bit.", - 2: "Hmmm… If I was going to lose anyway, I was hoping to get totally messed up in the process." + 1: "이런, 포켓몬이 배틀을 하는 동안 내 발차기는 전혀 도움이 되지 않았어.", + 2: "음… 어차피 내가 질거라면, 완전 엉망진창이 되길 바랬는데…" }, }, "battle_girl": { "encounter": { - 1: "You don't have to try to impress me. You can lose against me.", + 1: "감동을 주려고 노력할 필요는 없어. 네가 질 수도 있으니까.", }, "victory": { - 1: "It's hard to say good-bye, but we are running out of time…", + 1: "작별인사는 어렵지만, 우리에겐 시간이 얼마 안 남았네…", }, }, "hiker": { "encounter": { - 1: "My middle-age spread has given me as much gravitas as the mountains I hike!", - 2: "I inherited this big-boned body from my parents… I'm like a living mountain range…", + 1: "중년으로 접어들면서 등산해왔던 산처럼 진중해졌습니다!", + 2: "살아있는 산같은… 큰 체격을 부모님이 물려주셨죠…", }, "victory": { - 1: "At least I cannot lose when it comes to BMI!", - 2: "It's not enough… It's never enough. My bad cholesterol isn't high enough…" + 1: "적어도 BMI에 대하서는 질 수 없습니다!", + 2: "부족해… 절대로 충분하지 않아. 저의 콜레스테롤이 부족합니다…" }, }, "ranger": { "encounter": { - 1: "When I am surrounded by nature, most other things cease to matter.", - 2: "When I'm living without nature in my life, sometimes I'll suddenly feel an anxiety attack coming on." + 1: "자연에 둘러싸여 있으면, 다른 건 중요하지 않게 느껴져.", + 2: "인생에서 자연을 빼고 살면, 가끔 갑자기 마음이 불안해지지." }, "victory": { - 1: "It doesn't matter to the vastness of nature whether I win or lose…", - 2: "Something like this is pretty trivial compared to the stifling feelings of city life." + 1: "광활한 자연 앞에서는 내가 이기든 지든 상관없어…", + 2: "도시 생활의 답답한 느낌에 비하면 이런 것은 아주 사소한 일지." }, "defeat": { - 1: "I won the battle. But victory is nothing compared to the vastness of nature…", - 2: "I'm sure how you feel is not so bad if you compare it to my anxiety attacks…" + 1: "내가 이겼네. 그러나 승리는 광대한 자연에 비하면 아무것도 아니야…", + 2: "내 마음속 불안함과 비교하면, 당신 기분은 그렇게 나쁘지 않을텐데…" } }, "scientist": { "encounter": { - 1: "My research will lead this world to peace and joy.", + 1: "제 연구는 이 세상을 평화와 기쁨으로 이끌 겁니다.", }, "victory": { - 1: "I am a genius… I am not supposed to lose against someone like you…", + 1: "전 천재니까… 당신 같은 사람에게 질 수 없는데…", }, }, "school_kid": { "encounter": { - 1: "…Heehee. I'm confident in my calculations and analysis.", - 2: "I'm gaining as much experience as I can because I want to be a Gym Leader someday." + 1: "…헤헷. 계산과 분석에는 자신 있어.", + 2: "언젠가 체육관 관장이 되고 싶어서, 최대한 많은 경험을 쌓고 있어." }, "victory": { - 1: "Ohhhh… Calculation and analysis are perhaps no match for chance…", - 2: "Even difficult, trying experiences have their purpose, I suppose." + 1: "으아아… 이번에는 아마 계산과 분석이 빗나간 것 같아…", + 2: "내가 보기엔, 어렵고 힘든 경험도 나름의 의미가 있는 것 같아." } }, "artist": { "encounter": { - 1: "I used to be popular, but now I am all washed up.", + 1: "예전엔 인기가 많았지만, 지금은 모두 사라졌다네.", }, "victory": { - 1: "As times change, values also change. I realized that too late.", + 1: "시대가 변하면, 가치관도 변하지. 난 그걸 너무 늦게 깨달았어.", }, }, "guitarist": { "encounter": { - 1: "Get ready to feel the rhythm of defeat as I strum my way to victory!", + 1: "패배의 리듬을 느낄 준비는 됐겠지? 내가 승리할 거니까!", }, "victory": { - 1: "Silenced for now, but my melody of resilience will play on.", + 1: "지금은 조용하지만, 회복의 멜로디를 연주할 거야.", }, }, "worker": { "encounter": { - 1: "It bothers me that people always misunderstand me. I'm a lot more pure than everyone thinks.", + 1: "사람들이 저를 오해하는 게 신경 쓰여요. 전 생각보다 훨씬 깨끗하답니다.", }, "victory": { - 1: "I really don't want my skin to burn, so I want to stay in the shade while I work.", + 1: "피부가 타는 게 싫어서, 일하는 동안엔 그늘에 머물고 싶어요.", }, }, "worker_female": { "encounter": { - 1: `It bothers me that people always misunderstand me. - $I'm a lot more pure than everyone thinks.` + 1: `사람들이 나를 오해하는 게 신경 쓰여. + $나는 생각보다 훨씬 깨끗한데.` }, "victory": { - 1: "I really don't want my skin to burn, so I want to stay in the shade while I work." + 1: "피부가 타는 게 싫어서, 일하는 동안엔 그늘에 머물고 싶어." }, "defeat": { - 1: "My body and mind aren't necessarily always in sync." + 1: "생각처럼 몸이 잘 안따라주네." } }, "worker_double": { "encounter": { - 1: "I'll show you we can break you. We've been training in the field!", + 1: "너를 무너뜨릴 수 있다는 것을 보여줄게. 우리는 실전 경험이 있거든!", }, "victory": { - 1: "How strange… How could this be… I shouldn't have been outmuscled.", + 1: "이상하네… 어떻게 이럴 수 있지… 힘으로 압도할 수 없다니.", }, }, "hex_maniac": { "encounter": { - 1: "I normally only ever listen to classical music, but if I lose, I think I shall try a bit of new age!", - 2: "I grow stronger with each tear I cry." + 1: "평소에는 클래식 음악만 들었는데, 지면 뉴에이지도 좀 들어볼까!", + 2: "눈물을 흘릴 때마다 더 강해지는 것 같아." }, "victory": { - 1: "Is this the dawning of the age of Aquarius?", - 2: "Now I can get even stronger. I grow with every grudge." + 1: "지금이 물병자리 시대의 시작일까?", + 2: "이제 나는 더 강해지겠지. 모든 원한과 함께 성장하겠어." }, "defeat": { - 1: "New age simply refers to twentieth century classical composers, right?", - 2: "Don't get hung up on sadness or frustration. You can use your grudges to motivate yourself." + 1: "뉴에이지란 단순히 20세기 클래식 작곡가들을 말하는 거, 맞지?", + 2: "슬픔이나 좌절에 얽매이지 마. 넌 그 원한을 원동력으로 사용할 수 있어." } }, "psychic": { "encounter": { - 1: "Hi! Focus!", + 1: "안녕! 집중해!", }, "victory": { - 1: "Eeeeek!", + 1: "에에에에엣!", }, }, "officer": { "encounter": { - 1: "Brace yourself, because justice is about to be served!", - 2: "Ready to uphold the law and serve justice on the battlefield!" + 1: "마음의 준비를 하시죠, 정의가 곧 실행될 거니까요!", + 2: "법을 지키고 정의를 위해 봉사할 준비가 되었습니다!" }, "victory": { - 1: "The weight of justice feels heavier than ever…", - 2: "The shadows of defeat linger in the precinct." + 1: "정의의 무게가 그 어느 때보다 무겁게 느껴집니다…", + 2: "패배의 그림자가 관할 경찰서에 남았습니다." } }, "beauty": { "encounter": { - 1: "My last ever battle… That's the way I'd like us to view this match…", + 1: "나의 마지막 배틀… 이 승부를 그렇게 봐주셨으면 좋겠어요…", }, "victory": { - 1: "It's been fun… Let's have another last battle again someday…", + 1: "즐거웠어요… 언젠가 또 다른 마지막 승부를 하죠…", }, }, "baker": { "encounter": { - 1: "Hope you're ready to taste defeat!" + 1: "패배의 맛을 볼 준비는 됐겠지!" }, "victory": { - 1: "I'll bake a comeback." + 1: "실력이든 빵이든, 굽고 나면 단단해지는 법이라네." }, }, "biker": { "encounter": { - 1: "Time to rev up and leave you in the dust!" + 1: "힘차게 먼지 속으로 출발할 시간입니다!" }, "victory": { - 1: "I'll tune up for the next race." + 1: "다음 경주를 위해 준비해야겠습니다." }, }, "firebreather": { "encounter": { - 1: "My flames shall devour you!", - 2: "My soul is on fire. I'll show you how hot it burns!", - 3: "Step right up and take a look!" + 1: "내 불꽃이 너를 삼킬 테니까!", + 2: "내 영혼은 불타고 있다. 얼마나 뜨겁게 타는지 보여주지!", + 3: "이리 올라와서 보도록!" }, "victory": { - 1: "I burned down to ashes...", - 2: "Yow! That's hot!", - 3: "Ow! I scorched the tip of my nose!" + 1: "하얗게 불태웠다………", + 2: "큭! 제법 뜨겁군!", + 3: "으윽! 코끝에 화상을 입었다!" + }, + }, + "sailor": { + "encounter": { + 1: "친구여, 진다면 널빤지 행이야!", + 2: "덤벼! 내 선원으로서 자존심이 위태롭군!", + 3: "여어 거기! 뱃멀미 하나?" + }, + "victory": { + 1: "크윽! 꼬맹이한테 지다니!", + 2: "네 영혼이 나를 침몰시켰어!", + 3: "내가 뱃멀미가 나는 것 같군…" }, }, "brock": { @@ -685,19 +697,19 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "falkner": { "encounter": { - 1: "I'll show you the real power of the magnificent bird Pokémon!", - 2: "Winds, stay with me!", - 3: "Dad! I hope you're watching me battle from above!" + 1: "넓은 하늘을 화려하게 나는 새 포켓몬의 진정한 강함을 알게 해주겠다!", + 2: "바람이여, 나에게 오라!", + 3: "아버지, 내 시합을 하늘에서도 봐줘!" }, "victory": { - 1: "I understand… I'll bow out gracefully.", - 2: "A defeat is a defeat. You are strong indeed.", - 3: "…Shoot! Yeah, I lost." + 1: "알았다… 미련없이 땅에 내려가지.", + 2: "패배는 패배니까. 넌 정말 강하군.", + 3: "…큭! 그래, 내가 졌다." }, "defeat": { - 1: "Dad! I won with your cherished bird Pokémon…", - 2: "Bird Pokémon are the best after all!", - 3: "Feels like I'm catching up to my dad!" + 1: "아버지! 소중히 여기던 새 포켓몬으로 이겼어…", + 2: "언제나 새 포켓몬이 최강이다!", + 3: "아버지를 따라 잡은 기분이군!" } }, "nessa": { @@ -842,103 +854,103 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "roark": { "encounter": { - 1: "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!", - 2: "Here goes! These are my rocking Pokémon, my pride and joy!", - 3: "Rock-type Pokémon are simply the best!", - 4: "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!" + 1: "트레이너로서 너의 실력이 어느 정도인지 그리고 함께 싸울 포켓몬이 얼마나 강한지 확인해보겠어!", + 2: "자 간다! 내 자랑이자 기쁨인 바위타입 포켓몬들이야!", + 3: "바위타입 포켓몬이야말로 최고지!", + 4: "트레이너로서 너의 실력이 어느 정도인지 그리고 함께 싸울 포켓몬이 얼마나 강한지 확인해보겠어!" }, "victory": { - 1: "W-what? That can't be! My buffed-up Pokémon!", - 2: "…We lost control there. Next time I'd like to challenge you to a Fossil-digging race underground.", - 3: "With skill like yours, it's natural for you to win.", - 4: "Wh-what?! It can't be! Even that wasn't enough?", - 5: "I blew it." + 1: "이-이럴수가! 열심히 단련시킨 포켓몬들이!", + 2: "…져버린 건가. 다음엔 지하통로에서 화석캐기 승부를 하고 싶구나.", + 3: "네 실력이라면 승리는 당연한 결과겠지.", + 4: "뭐-뭐야?! 이럴 수가! 이것도 부족했단 말인가?", + 5: "내가 실수했군." }, "defeat": { - 1: "See? I'm proud of my rocking battle style!", - 2: "Thanks! The battle gave me confidence that I may be able to beat my dad!", - 3: "I feel like I just smashed through a really stubborn boulder!" + 1: "봤지? 이게 바로 내가 자랑하는 바위 스타일 전투야!", + 2: "고마워! 이번 승부로 아버지를 이길 수 있겠다는 자신감이 생겼어!", + 3: "정말 단단한 바위를 뚫고 나온 기분인데!" } }, "morty": { "encounter": { - 1: `With a little more, I could see a future in which I meet the legendary Pokémon. - $You're going to help me reach that level!`, - 2: `It's said that a rainbow-hued Pokémon will come down to appear before a truly powerful Trainer. - $I believed that tale, so I have secretly trained here all my life. As a result, I can now see what others cannot. - $I see a shadow of the person who will make the Pokémon appear. - $I believe that person is me! You're going to help me reach that level!`, - 3: "Whether you choose to believe or not, mystic power does exist.", - 4: "You can bear witness to the fruits of my training.", - 5: "You must make your soul one with that of Pokémon. Can you do this?", - 6: "Say, do you want to be part of my training?" + 1: `조금만 더 노력하면, 내가 전설의 포켓몬을 만나는 미래가 보여. + $내가 그 수준에 도달할 수 있게 도와줘!`, + 2: `커다란 무지개색 포켓몬은 진정한 강함을 가진 트레이너 앞에 나타난다는 이야기가 있어. + $난 그 이야기를 믿고, 줄곧 이 곳에서 몰래 수행하고 있어. 그 결과로, 다른 사람들은 볼 수 없는 것을 볼 수 있게 됐지. + $내겐 그 포켓몬을 나타나게 할 사람의 그림자가 보이거든. + $난 그게 나라고 믿어! 넌 내가 그 수준에 올라갈 수 있도록 도와줘야겠어!`, + 3: "네가 믿든 믿지 않든, 불가사의한 힘은 존재해.", + 4: "넌 내 수련의 결실을 보게 될 거야.", + 5: "포켓몬과 너의 영혼을 하나로 만들어야 해. 가능하겠어?", + 6: "저기, 너 내 수행의 일부분이 되고 싶은거지?" }, "victory": { - 1: "I'm not good enough yet…", - 2: `I see… Your journey has taken you to far-away places and you have witnessed much more than I. - $I envy you for that…`, - 3: "How is this possible…", - 4: `I don't think our potentials are so different. - $But you seem to have something more than that… So be it.`, - 5: "Guess I need more training.", - 6: "That's a shame." + 1: "나는 아직 멀었구나…", + 2: `그래… 여행으로 먼 곳을 돌아다니면서, 나보다 훨씬 많은 것을 봐왔구나. + $네가 조금 부럽네…`, + 3: "이게 어떻게 가능한 거지…", + 4: `우리의 잠재력은 그렇게 다르진 않은 것 같아. + $그치만 넌 그것과 다른 무언가를 많이 갖고 있는 것 같네… 흐음.`, + 5: "수련이 더 필요하겠군.", + 6: "안타깝게 됐네." }, "defeat": { - 1: "I moved… one step ahead again.", - 2: "Fufufu…", - 3: "Wh-what?! It can't be! Even that wasn't enough?", - 4: "I feel like I just smashed through a really stubborn boulder!", - 5: "Ahahahah!", - 6: "I knew I would win!" + 1: "내가…다시 한 발짝 앞섰어.", + 2: "후후훗…", + 3: "뭐-뭐야?! 이럴 수가! 그것도 부족해?", + 4: "정말 단단한 바위를 뚫고 나온 기분인데!", + 5: "아하하하하!", + 6: "내가 이길 줄 알았어!" } }, "crispin": { "encounter": { - 1: "I wanna win, so that's exactly what I'll do!", - 2: "I battle because I wanna battle! And you know what? That's how it should be!" + 1: "이기고 싶으니까 이기고 말겠어!", + 2: "싸우고 싶으면 싸운다! 이거면 충분하지 않아!?" }, "victory": { - 1: "I wanted to win…but I lost!", - 2: "I lost…'cause I couldn't win!" + 1: "이기고 싶었는데…졌잖아!", + 2: "이기지 못해서…지고 말았어!" }, "defeat": { - 1: "Hey, wait a sec. Did I just win? I think I just won! Talk about satisfying!", - 2: "Wooo! That was amazing!" + 1: "잠시만. 나 지금 이긴거지? 이긴 거 맞지! 기분 좋은데!", + 2: "우와아! 이거 굉장한데!" } }, "amarys": { "encounter": { - 1: `I want to be the one to help a certain person. That being the case, I cannot afford to lose. - $… Our battle starts now.`, + 1: `네리네는 그 사람을 구원하고 싶습니다. 그렇기에 패배는 용납되지 않습니다. + $… 승부를 시작합니다.`, }, "victory": { - 1: "I am… not enough, I see." + 1: "네리네는… 안 된다는 건가요." }, "defeat": { - 1: "Victory belongs to me. Well fought." + 1: "네리네가 승리했습니다. 수고하셨습니다." } }, "lacey": { "encounter": { - 1: "I'll be facing you with my usual party as a member of the Elite Four." + 1: "이번에는 사천왕으로서 승부하는 거니까 평소 사용하는 아이들로 상대해 드릴게요!" }, "victory": { - 1: "That was a great battle!" + 1: "멋진 포켓몬 배틀이었어요!" }, "defeat": { - 1: "Let's give your Pokémon a nice round of applause for their efforts!" + 1: "당신의 포켓몬의 노력에 박수를 보내주세요!" } }, "drayton": { "encounter": { - 1: `Man, I love chairs. Don't you love chairs? What lifesavers. - $I don't get why everyone doesn't just sit all the time. Standing up's tiring work!`, + 1: `의자는 좋은 거야. 너도 그렇게 생각해? 정말 고마운 물건이지. + $왜 다들 앉지 않는 걸까. 서 있는 건 힘들잖아!`, }, "victory": { - 1: "Guess I should've expected that!" + 1: "전보다 더 강해질 줄이야!" }, "defeat": { - 1: "Heh heh! Don't mind me, just scooping up a W over here. I get it if you're upset, but don't go full Kieran on me, OK?" + 1: "헤헤헷! 내 승리야. 분한 건 알겠지만 카지처럼 나가떨어지지마, 응?" } }, "ramos": { @@ -989,13 +1001,13 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "gardenia": { "encounter": { - 1: "You have a winning aura about you. So, anyway, this will be fun. Let's have our battle!" + 1: "너에게선 승리의 기운이 느껴져. 어쨌든 재밌을 것 같아. 포켓몬 승부하자!" }, "victory": { - 1: "Amazing! You're very good, aren't you?" + 1: "대단해! 너 정말 강하구나!" }, "defeat": { - 1: "Yes! My Pokémon and I are perfectly good!" + 1: "그렇지! 나와 포켓몬은 완벽해!" } }, "aaron": { @@ -1134,26 +1146,26 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "lorelei": { "encounter": { - 1: `No one can best me when it comes to icy Pokémon! Freezing moves are powerful! - $Your Pokémon will be at my mercy when they are frozen solid! Hahaha! Are you ready?`, + 1: `얼음포켓몬을 내보내면 대적할 사람이 없지! 상대를 얼린다는 건 매우 강력한 공격이야. + $네 포켓몬이 꽁꽁 얼면 그때부턴 내 손바닥 위거든! 아하하! 준비됐어?`, }, "victory": { - 1: "How dare you!" + 1: "어떻게 감히!" }, "defeat": { - 1: "There's nothing you can do once you're frozen." + 1: "얼어붙은 넌 아무것도 할 수 없어." } }, "will": { "encounter": { - 1: `I have trained all around the world, making my psychic Pokémon powerful. - $I can only keep getting better! Losing is not an option!`, + 1: `나는 전세계를 돌아다니며, 강한 에스퍼 포켓몬을 만들도록 수행해왔다. + $계속 더 정진하겠다! 패배는 선택지에 없어!`, }, "victory": { - 1: "I… I can't… believe it…" + 1: "이… 내가… 믿을수 없어…" }, "defeat": { - 1: "That was close. I wonder what it is that you lack." + 1: "근소한 차이였다. 네게 부족한 것이 무엇인지 궁금하군." } }, "malva": { @@ -1204,35 +1216,35 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "bruno": { "encounter": { - 1: "We will grind you down with our superior power! Hoo hah!" + 1: "우월한 힘으로 너를 부숴주지! 우! 하~앗!" }, "victory": { - 1: "Why? How could I lose?" + 1: "하? 어떻게 내가 진 거지?" }, "defeat": { - 1: "You can challenge me all you like, but the results will never change!" + 1: "얼마든지 내게 도전 할 수 있지만, 결과는 절대 바뀌지 않을 거다!" } }, "bugsy": { "encounter": { - 1: "I'm Bugsy! I never lose when it comes to bug Pokémon!" + 1: "내 이름은 호일! 벌레 포켓몬에 대해서라면 누구에게도 지지 않아!" }, "victory": { - 1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win." + 1: "우와, 대단해! 넌 포켓몬 전문가구나!\n내 연구는 아직 안 끝났네. 응, 네가 이겼어." }, "defeat": { - 1: "Thanks! Thanks to our battle, I was also able to make progress in my research!" + 1: "고마워! 방금 승부 덕분에, 내 연구도 진전을 이룬 것 같아!" } }, "koga": { "encounter": { - 1: "Fwahahahaha! Pokémon are not merely about brute force--you shall see soon enough!" + 1: "후하하하! 포켓몬은 딘순히 강한 것만이 아니다--곧 알려주지!" }, "victory": { - 1: "Ah! You've proven your worth!" + 1: "하! 스스로 증명해냈군!" }, "defeat": { - 1: "Have you learned to fear the techniques of the ninja?" + 1: "인술을 피하는 방법을 배워보겠나?" } }, "bertha": { @@ -1307,13 +1319,13 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "agatha": { "encounter": { - 1: "Pokémon are for battling! I'll show you how a real Trainer battles!" + 1: "포켓몬은 싸우게 하려고 있는 것이야! 진정한 싸움이라는 것을 보여주겠다!" }, "victory": { - 1: "Oh my! You're something special, child!" + 1: "이런! 넌 무언가 특별하구나, 꼬마야!" }, "defeat": { - 1: "Bahaha. That's how a proper battle's done!" + 1: "바하하하. 제대로 된 승부는 이렇게 하는거다!" } }, "flint": { @@ -1402,33 +1414,33 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "lance": { "encounter": { - 1: "I've been waiting for you. Allow me to test your skill.", - 2: "I thought that you would be able to get this far. Let's get this started." + 1: "널 기다리고 있었다. 그 실력을 시험해보겠어.", + 2: "여기까지 올 수 있을거라고 생각했다. 슬슬 시작해볼까." }, "victory": { - 1: "You got me. You are magnificent!", - 2: "I never expected another trainer to beat me… I'm surprised." + 1: "날 따라잡았군. 훌륭해!", + 2: "다른 트레이너가 날 이길 거라곤 생각 못했는데… 놀랍군." }, "defeat": { - 1: "That was close. Want to try again?", - 2: "It's not that you are weak. Don't let it bother you." + 1: "근소하군. 다시 해볼까?", + 2: "네가 약해서가 아니다. 신경쓰지 말도록." } }, "karen": { "encounter": { - 1: "I am Karen. Would you care for a showdown with my Dark-type Pokémon?", - 2: "I am unlike those you've already met.", - 3: "You've assembled a charming team. Our battle should be a good one." + 1: "난 카렌! 내 악 타입 포켓몬과의 승부를 원하니?", + 2: "난 네가 이전에 만났던 트레이너들과는 달라.", + 3: "강한 포켓몬, 약한 포켓몬, 그런 건 사람이 멋대로 정하는 것." }, "victory": { - 1: "No! I can't win. How did you become so strong?", - 2: "I will not stray from my chosen path.", - 3: "The Champion is looking forward to meeting you." + 1: "좋아하는 마음이 전해진다면 포켓몬도 답할거야. 그렇게 강해지는 거지", + 2: "난 내가 선택한 길을 걸어갈거야.", + 3: "챔피언이 너를 기다리고 있어." }, "defeat": { - 1: "That's about what I expected.", - 2: "Well, that was relatively entertaining.", - 3: "Come visit me anytime." + 1: "정말 강한 트레이너라면 좋아하는 포켓몬으로 이길 수 있도록 열심히 해야 해.", + 2: "뭐, 비교적 재밌었어.", + 3: "언제라도 다시 찾아와, 상대해줄게." } }, "milo": { @@ -1495,13 +1507,13 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "blue": { "encounter": { - 1: "You must be pretty good to get this far." + 1: "여기까지 왔다니, 실력이 꽤 봐줄만 할 것 같은데." }, "victory": { - 1: "I've only lost to him and now to you… Him? Hee, hee…" + 1: "그 녀석한테만 지는 줄 알았는데… 누구냐고? 하, 하…" }, "defeat": { - 1: "See? My power is what got me here." + 1: "봤지? 여기까지 온 내 실력." } }, "piers": { @@ -1528,24 +1540,24 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "jasmine": { "encounter": { - 1: "Oh… Your Pokémon are impressive. I think I will enjoy this." + 1: "와… 당신의 포켓몬은 인상적이네요. 재미있을 것 같아요." }, "victory": { - 1: "You are truly strong. I'll have to try much harder, too." + 1: "당신은 정말 강하네요. 저도 더 열심히 노력해야겠어요." }, "defeat": { - 1: "I never expected to win." + 1: "이길 줄은 몰랐어요." } }, "lance_champion": { "encounter": { - 1: "I am still the Champion. I won't hold anything back." + 1: "여전히 난 챔피언이다. 더이상 주저할 게 없군." }, "victory": { - 1: "This is the emergence of a new Champion." + 1: "새로운 챔피언의 등장이군." }, "defeat": { - 1: "I successfully defended my Championship." + 1: "성공적으로 챔피언 자리를 지켜냈다." } }, "steven": { @@ -1640,24 +1652,24 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "whitney": { "encounter": { - 1: "Hey! Don't you think Pokémon are, like, super cute?" + 1: "있지! 포켓몬들 말이야, 정말 너무 귀엽지?" }, "victory": { - 1: "Waaah! Waaah! You're so mean!" + 1: "흑! 으아앙! 너무해!" }, "defeat": { - 1: "And that's that!" + 1: "이걸로 끝!" } }, "chuck": { "encounter": { - 1: "Hah! You want to challenge me? Are you brave or just ignorant?" + 1: "하! 나에게 도전하겠다고? 용감한 거냐, 아니면 그냥 무모한 거냐?" }, "victory": { - 1: "You're strong! Would you please make me your apprentice?" + 1: "자네 강하군! 나를 제자로 삼아주겠나?" }, "defeat": { - 1: "There. Do you realize how much more powerful I am than you?" + 1: "자. 내가 자네보다 얼마나 더 강력한지 깨달았겠지?" } }, "katy": { @@ -1673,48 +1685,48 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "pryce": { "encounter": { - 1: "Youth alone does not ensure victory! Experience is what counts." + 1: "젊음만으로는 승리를 보장할 수 없다! 중요한 것은 경험이다." }, "victory": { - 1: "Outstanding! That was perfect. Try not to forget what you feel now." + 1: "특출하군! 완벽해. 지금 이 느낌을 잊지 말도록." }, "defeat": { - 1: "Just as I envisioned." + 1: "내가 예상했던 그대로군." } }, "clair": { "encounter": { - 1: "Do you know who I am? And you still dare to challenge me?" + 1: "내가 누군지 알지? 그런데도 감히 내게 도전해?" }, "victory": { - 1: "I wonder how far you can get with your skill level. This should be fascinating." + 1: "네 실력이 어디까지 올라갈 수 있는지 궁금하네. 아주 흥미진진하겠어." }, "defeat": { - 1: "That's that." + 1: "끝이다." } }, "maylene": { "encounter": { - 1: `I've come to challenge you now, and I won't hold anything back. - $Please prepare yourself for battle!`, + 1: `지금 당신에게 도전하러 왔어요. + $전력을 다할 테니 각오하세요!`, }, "victory": { - 1: "I admit defeat…" + 1: "나의 패배입니다…" }, "defeat": { - 1: "That was awesome." + 1: "멋진 승부였습니다." } }, "fantina": { "encounter": { - 1: `You shall challenge me, yes? But I shall win. - $That is what the Gym Leader of Hearthome does, non?`, + 1: `당신도 도전해 보세요. 전 당신을 이기겠어요. + $그것이 체육관 관장!`, }, "victory": { - 1: "You are so fantastically strong. I know why I have lost." + 1: "당신 최고로 강해요. 나 진 것 알아요." }, "defeat": { - 1: "I am so, so, very happy!" + 1: "너무, 너무 행복해요!" } }, "byron": { diff --git a/src/locales/ko/game-mode.ts b/src/locales/ko/game-mode.ts new file mode 100644 index 00000000000..ad387010a8f --- /dev/null +++ b/src/locales/ko/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "클래식", + "endless": "엔들리스", + "endlessSpliced": "엔들리스(융합체)", + "dailyRun": "데일리 런", + "unknown": "언노운", + "challenge": "챌린지", +} as const; diff --git a/src/locales/ko/menu.ts b/src/locales/ko/menu.ts index b91d674521e..9245d67533a 100644 --- a/src/locales/ko/menu.ts +++ b/src/locales/ko/menu.ts @@ -45,10 +45,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "주간 랭킹", "noRankings": "랭킹 정보 없음", "loading": "로딩 중…", + "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "플레이어 온라인", - "empty":"빈 슬롯", "yes":"예", "no":"아니오", - "disclaimer": "DISCLAIMER", - "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed." + "disclaimer": "면책 조항", + "disclaimerDescription": "이 게임은 완전히 개발되지 않았습니다- (세이브 데이터 소실을 포함) 플레이에 지장을 주는 문제가 생길 수 있으며,\n공지 없이 업데이트가 진행 혹은 중지될 수 있습니다.", } as const; diff --git a/src/locales/ko/modifier-type.ts b/src/locales/ko/modifier-type.ts index fce9d25b629..da8d0cb983a 100644 --- a/src/locales/ko/modifier-type.ts +++ b/src/locales/ko/modifier-type.ts @@ -8,7 +8,7 @@ export const modifierType: ModifierTypeTranslationEntries = { }, "AddVoucherModifierType": { name: "{{voucherTypeName}} {{modifierCount}}장", - description: "{{voucherTypeName}} {{modifierCount}}장을 획득", + description: "{{voucherTypeName}} {{modifierCount}}장을 획득한다.", }, "PokemonHeldItemModifierType": { extra: { @@ -17,63 +17,63 @@ export const modifierType: ModifierTypeTranslationEntries = { } }, "PokemonHpRestoreModifierType": { - description: "포켓몬 1마리의 HP를 {{restorePoints}} 또는 {{restorePercent}}% 중\n높은 수치만큼 회복", + description: "포켓몬 1마리의 HP를 {{restorePoints}} 또는 {{restorePercent}}% 중\n높은 수치만큼 회복한다.", extra: { - "fully": "포켓몬 1마리의 HP를 모두 회복", - "fullyWithStatus": "포켓몬 1마리의 HP와 상태 이상을 모두 회복", + "fully": "포켓몬 1마리의 HP를 모두 회복한다.", + "fullyWithStatus": "포켓몬 1마리의 HP와 상태 이상을 모두 회복한다.", } }, "PokemonReviveModifierType": { - description: "기절해 버린 포켓몬 1마리의 HP를 {{restorePercent}}%까지 회복", + description: "기절해 버린 포켓몬 1마리의 HP를 {{restorePercent}}%까지 회복한다.", }, "PokemonStatusHealModifierType": { - description: "포켓몬 1마리의 상태 이상을 모두 회복", + description: "포켓몬 1마리의 상태 이상을 모두 회복한다.", }, "PokemonPpRestoreModifierType": { - description: "포켓몬이 기억하고 있는 기술 중 1개의 PP를 {{restorePoints}}만큼 회복", + description: "포켓몬이 기억하고 있는 기술 중 1개의 PP를 {{restorePoints}}만큼 회복한다.", extra: { - "fully": "포켓몬이 기억하고 있는 기술 중 1개의 PP를 모두 회복", + "fully": "포켓몬이 기억하고 있는 기술 중 1개의 PP를 모두 회복한다.", } }, "PokemonAllMovePpRestoreModifierType": { - description: "포켓몬이 기억하고 있는 4개의 기술 PP를 {{restorePoints}}씩 회복", + description: "포켓몬이 기억하고 있는 4개의 기술 PP를 {{restorePoints}}씩 회복한다.", extra: { - "fully": "포켓몬이 기억하고 있는 4개의 기술 PP를 모두 회복", + "fully": "포켓몬이 기억하고 있는 4개의 기술 PP를 모두 회복한다.", } }, "PokemonPpUpModifierType": { - description: "포켓몬이 기억하고 있는 기술 중 1개의 PP 최대치를 5마다 {{upPoints}}씩 상승 (최대 3)", + description: "포켓몬이 기억하고 있는 기술 중 1개의 PP 최대치를 5마다 {{upPoints}}씩 상승시킨다 (최대 3).", }, "PokemonNatureChangeModifierType": { name: "{{natureName}}민트", description: "포켓몬의 성격을 {{natureName}}[[로]] 바꾸고 스타팅에도 등록한다.", }, "DoubleBattleChanceBoosterModifierType": { - description: "{{battleCount}}번의 배틀 동안 더블 배틀이 등장할 확률 두 배", + description: "{{battleCount}}번의 배틀 동안 더블 배틀이 등장할 확률이 두 배가 된다.", }, "TempBattleStatBoosterModifierType": { - description: "자신의 모든 포켓몬이 5번의 배틀 동안 {{tempBattleStatName}}[[가]] 한 단계 증가" + description: "자신의 모든 포켓몬이 5번의 배틀 동안 {{tempBattleStatName}}[[가]] 한 단계 증가한다." }, "AttackTypeBoosterModifierType": { - description: "지니게 하면 {{moveType}}타입 기술의 위력이 20% 상승", + description: "지니게 하면 {{moveType}}타입 기술의 위력이 20% 상승한다.", }, "PokemonLevelIncrementModifierType": { - description: "포켓몬 1마리의 레벨이 1만큼 상승", + description: "포켓몬 1마리의 레벨이 1만큼 상승한다.", }, "AllPokemonLevelIncrementModifierType": { - description: "자신의 모든 포켓몬의 레벨이 1씩 상승", + description: "자신의 모든 포켓몬의 레벨이 1씩 상승한다.", }, "PokemonBaseStatBoosterModifierType": { description: "지니게 하면 {{statName}} 종족값을 10% 올려준다. 개체값이 높을수록 더 많이 누적시킬 수 있다.", }, "AllPokemonFullHpRestoreModifierType": { - description: "자신의 포켓몬의 HP를 모두 회복", + description: "자신의 포켓몬의 HP를 모두 회복한다.", }, "AllPokemonFullReviveModifierType": { - description: "자신의 포켓몬의 HP를 기절해 버렸더라도 모두 회복", + description: "자신의 포켓몬의 HP를 기절해 버렸더라도 모두 회복한다.", }, "MoneyRewardModifierType": { - description: "{{moneyMultiplier}} 양의 돈을 획득 (₽{{moneyAmount}})", + description: "{{moneyMultiplier}} 양의 돈을 획득한다 (₽{{moneyAmount}}).", extra: { "small": "적은", "moderate": "적당한", @@ -81,62 +81,62 @@ export const modifierType: ModifierTypeTranslationEntries = { }, }, "ExpBoosterModifierType": { - description: "포켓몬이 받는 경험치가 늘어나는 부적. {{boostPercent}}% 증가", + description: "포켓몬이 받는 경험치가 {{boostPercent}}% 증가한다.", }, "PokemonExpBoosterModifierType": { - description: "지니게 한 포켓몬은 받을 수 있는 경험치가 {{boostPercent}}% 증가", + description: "지니게 한 포켓몬은 받는 경험치가 {{boostPercent}}% 증가한다.", }, "PokemonFriendshipBoosterModifierType": { - description: "배틀 승리로 얻는 친밀도가 50% 증가", + description: "배틀 승리로 얻는 친밀도가 50% 증가한다.", }, "PokemonMoveAccuracyBoosterModifierType": { - description: "기술의 명중률이 {{accuracyAmount}} 증가 (최대 100)", + description: "기술의 명중률이 {{accuracyAmount}} 증가한다 (최대 100).", }, "PokemonMultiHitModifierType": { - description: "공격이 가진 갯수에 따라 60/75/82.5%의 위력으로 한번 더 명중", + description: "지닌 개수(최대 3개)마다 추가 공격을 하는 대신, 공격력이 60%(1개)/75%(2개)/82.5%(3개)만큼 감소합니다.", }, "TmModifierType": { name: "No.{{moveId}} {{moveName}}", - description: "포켓몬에게 {{moveName}}[[를]] 가르침", + description: "포켓몬에게 {{moveName}}[[를]] 가르침.", }, "TmModifierTypeWithInfo": { name: "No.{{moveId}} {{moveName}}", - description: "포켓몬에게 {{moveName}}를(을) 가르침\n(Hold C or Shift for more info)", + description: "포켓몬에게 {{moveName}}를(을) 가르침\n(C 또는 Shift를 꾹 눌러 정보 확인).", }, "EvolutionItemModifierType": { - description: "어느 특정 포켓몬을 진화", + description: "어느 특정 포켓몬을 진화시킨다.", }, "FormChangeItemModifierType": { - description: "어느 특정 포켓몬을 폼 체인지", + description: "어느 특정 포켓몬을 폼 체인지시킨다.", }, "FusePokemonModifierType": { - description: "두 포켓몬을 결합 (특성 변환, 종족값과 타입 분배, 기술폭 공유)", + description: "두 포켓몬을 결합시킨다 (특성 변환, 종족값과 타입 분배, 기술폭 공유).", }, "TerastallizeModifierType": { name: "테라피스 {{teraType}}", - description: "지니게 하면 10번의 배틀 동안 {{teraType}} 테라스탈타입으로 테라스탈", + description: "지니게 하면 10번의 배틀 동안 {{teraType}} 테라스탈타입으로 테라스탈한다.", }, "ContactHeldItemTransferChanceModifierType": { - description: "공격했을 때, {{chancePercent}}%의 확률로 상대의 도구를 도둑질", + description: "공격했을 때, {{chancePercent}}%의 확률로 상대의 도구를 도둑질한다.", }, "TurnHeldItemTransferModifierType": { - description: "매 턴, 지닌 포켓몬은 상대로부터 도구를 하나 획득", + description: "매 턴, 지닌 포켓몬은 상대로부터 도구를 하나 획득한다.", }, "EnemyAttackStatusEffectChanceModifierType": { - description: "공격했을 때 {{statusEffect}} 상태로 만들 확률 {{chancePercent}}% 추가", + description: "공격했을 때 {{statusEffect}} 상태로 만들 확률이 {{chancePercent}}% 추가된다.", }, "EnemyEndureChanceModifierType": { - description: "받은 공격을 버텨낼 확률 {{chancePercent}}% 추가", + description: "받은 공격을 버텨낼 확률이 {{chancePercent}}% 추가된다.", }, "RARE_CANDY": { name: "이상한사탕" }, "RARER_CANDY": { name: "더이상한사탕" }, - "MEGA_BRACELET": { name: "메가링", description: "메가스톤을 사용 가능" }, - "DYNAMAX_BAND": { name: "다이맥스 밴드", description: "다이버섯을 사용 가능" }, - "TERA_ORB": { name: "테라스탈오브", description: "테라피스를 사용 가능" }, + "MEGA_BRACELET": { name: "메가링", description: "메가스톤을 사용할 수 있게 된다." }, + "DYNAMAX_BAND": { name: "다이맥스 밴드", description: "다이버섯을 사용할 수 있게 된다." }, + "TERA_ORB": { name: "테라스탈오브", description: "테라피스를 사용할 수 있게 된다." }, - "MAP": { name: "지도", description: "갈림길에서 목적지 선택 가능" }, + "MAP": { name: "지도", description: "갈림길에서 목적지를 선택할 수 있다." }, "POTION": { name: "상처약" }, "SUPER_POTION": { name: "좋은상처약" }, @@ -151,7 +151,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "SACRED_ASH": { name: "성스러운분말" }, - "REVIVER_SEED": { name: "부활의씨앗", description: "포켓몬이 쓰러지려 할 때 HP를 절반 회복" }, + "REVIVER_SEED": { name: "부활의씨앗", description: "포켓몬이 쓰러지려 할 때 HP를 절반 회복한다." }, "ETHER": { name: "PP에이드" }, "MAX_ETHER": { name: "PP회복" }, @@ -166,12 +166,12 @@ export const modifierType: ModifierTypeTranslationEntries = { "SUPER_LURE": { name: "실버코롱" }, "MAX_LURE": { name: "골드코롱" }, - "MEMORY_MUSHROOM": { name: "기억버섯", description: "포켓몬의 잊어버린 기술을 떠올림" }, + "MEMORY_MUSHROOM": { name: "기억버섯", description: "포켓몬이 잊어버린 기술을 떠올린다." }, - "EXP_SHARE": { name: "학습장치", description: "배틀에 참여하지 않아도 20%의 경험치를 받을 수 있는 장치" }, - "EXP_BALANCE": { name: "균형학습장치", description: "레벨이 낮은 포켓몬이 받는 경험치를 가중" }, + "EXP_SHARE": { name: "학습장치", description: "배틀에 참여하지 않아도 20%의 경험치를 받을 수 있게 된다." }, + "EXP_BALANCE": { name: "균형학습장치", description: "레벨이 낮은 포켓몬이 받는 경험치를 가중시킨다." }, - "OVAL_CHARM": { name: "둥근부적", description: "여러 마리의 포켓몬이 배틀에 참여할 경우, 전체 경험치의 10%씩을 추가로 획득" }, + "OVAL_CHARM": { name: "둥근부적", description: "여러 마리의 포켓몬이 배틀에 참여할 경우, 전체 경험치의 10%씩을 추가로 획득한다." }, "EXP_CHARM": { name: "경험부적" }, "SUPER_EXP_CHARM": { name: "좋은경험부적" }, @@ -182,62 +182,62 @@ export const modifierType: ModifierTypeTranslationEntries = { "SOOTHE_BELL": { name: "평온의방울" }, - "SOUL_DEW": { name: "마음의물방울", description: "지닌 포켓몬의 성격의 효과가 10% 증가 (합연산)" }, + "SOUL_DEW": { name: "마음의물방울", description: "지닌 포켓몬의 성격의 효과가 10% 증가한다 (합연산)." }, "NUGGET": { name: "금구슬" }, "BIG_NUGGET": { name: "큰금구슬" }, "RELIC_GOLD": { name: "고대의금화" }, - "AMULET_COIN": { name: "부적금화", description: "받는 돈이 20% 증가" }, - "GOLDEN_PUNCH": { name: "골든펀치", description: "주는 데미지의 50%만큼 돈을 획득" }, - "COIN_CASE": { name: "동전케이스", description: "매 열 번째 배틀마다, 가진 돈의 10%를 이자로 획득" }, + "AMULET_COIN": { name: "부적금화", description: "받는 돈이 20% 증가한다." }, + "GOLDEN_PUNCH": { name: "골든펀치", description: "주는 데미지의 50%만큼 돈을 획득한다." }, + "COIN_CASE": { name: "동전케이스", description: "매 열 번째 배틀마다, 가진 돈의 10%를 이자로 획득한다." }, - "LOCK_CAPSULE": { name: "록캡슐", description: "받을 아이템을 갱신할 때 희귀도를 고정 가능" }, + "LOCK_CAPSULE": { name: "록캡슐", description: "받을 아이템을 갱신할 때 희귀도를 고정시킬 수 있게 된다." }, "GRIP_CLAW": { name: "끈기갈고리손톱" }, "WIDE_LENS": { name: "광각렌즈" }, "MULTI_LENS": { name: "멀티렌즈" }, - "HEALING_CHARM": { name: "치유의부적", description: "HP를 회복하는 기술을 썼을 때 효율이 10% 증가 (부활 제외)" }, - "CANDY_JAR": { name: "사탕단지", description: "이상한사탕 종류의 아이템이 올려주는 레벨 1 증가" }, + "HEALING_CHARM": { name: "치유의부적", description: "HP를 회복하는 기술을 썼을 때 효율이 10% 증가한다 (부활 제외)." }, + "CANDY_JAR": { name: "사탕단지", description: "이상한사탕 종류의 아이템이 올려주는 레벨이 1 증가한다." }, - "BERRY_POUCH": { name: "열매주머니", description: "사용한 나무열매가 소모되지 않을 확률 33% 추가" }, + "BERRY_POUCH": { name: "열매주머니", description: "사용한 나무열매가 소모되지 않을 확률이 30% 추가된다." }, - "FOCUS_BAND": { name: "기합의머리띠", description: "기절할 듯한 데미지를 받아도 HP를 1 남겨서 견딜 확률 10% 추가" }, + "FOCUS_BAND": { name: "기합의머리띠", description: "기절할 듯한 데미지를 받아도 HP를 1 남겨서 견딜 확률이 10% 추가된다." }, - "QUICK_CLAW": { name: "선제공격손톱", description: "상대보다 먼저 행동할 수 있게 될 확률 10% 추가 (우선도 처리 이후)" }, + "QUICK_CLAW": { name: "선제공격손톱", description: "상대보다 먼저 행동할 수 있게 될 확률이 10% 추가된다 (우선도 처리 이후)." }, - "KINGS_ROCK": { name: "왕의징표석", description: "공격해서 데미지를 줄 때 상대를 풀죽일 확률 10% 추가" }, + "KINGS_ROCK": { name: "왕의징표석", description: "공격해서 데미지를 줄 때 상대를 풀죽일 확률이 10% 추가된다." }, - "LEFTOVERS": { name: "먹다남은음식", description: "포켓몬의 HP가 매 턴 최대 체력의 1/16씩 회복" }, - "SHELL_BELL": { name: "조개껍질방울", description: "포켓몬이 준 데미지의 1/8씩 회복" }, + "LEFTOVERS": { name: "먹다남은음식", description: "포켓몬의 HP가 매 턴 최대 체력의 1/16씩 회복된다." }, + "SHELL_BELL": { name: "조개껍질방울", description: "포켓몬이 준 데미지의 1/8씩을 회복한다." }, "TOXIC_ORB": { name: "맹독구슬", description: "이 도구를 지닌 포켓몬은 턴이 끝나는 시점에 상태이상에 걸리지 않았다면 맹독 상태가 된다." }, "FLAME_ORB": { name: "화염구슬", description: "이 도구를 지닌 포켓몬은 턴이 끝나는 시점에 상태이상에 걸리지 않았다면 화상 상태가 된다." }, "BATON": { name: "바톤", description: "포켓몬을 교체할 때 효과를 넘겨줄 수 있으며, 함정의 영향을 받지 않게 함" }, - "SHINY_CHARM": { name: "빛나는부적", description: "야생 포켓몬이 색이 다른 포켓몬으로 등장할 확률을 급격히 증가" }, - "ABILITY_CHARM": { name: "특성부적", description: "야생 포켓몬이 숨겨진 특성을 가지고 등장할 확률을 급격히 증가" }, + "SHINY_CHARM": { name: "빛나는부적", description: "야생 포켓몬이 색이 다른 포켓몬으로 등장할 확률을 급격히 높인다." }, + "ABILITY_CHARM": { name: "특성부적", description: "야생 포켓몬이 숨겨진 특성을 가지고 등장할 확률을 급격히 높인다." }, - "IV_SCANNER": { name: "개체값탐지기", description: "야생 포켓몬의 개체값을 확인 가능하다. 높은 값이 먼저 표시되며 확인할 수 있는 개체값을 두 종류씩 추가" }, + "IV_SCANNER": { name: "개체값탐지기", description: "야생 포켓몬의 개체값을 확인 가능하다. 높은 값부터, 확인할 수 있는 개체값이 두 종류씩 추가된다." }, "DNA_SPLICERS": { name: "유전자쐐기" }, "MINI_BLACK_HOLE": { name: "미니 블랙홀" }, - "GOLDEN_POKEBALL": { name: "황금몬스터볼", description: "전투 후 획득하는 아이템의 선택지를 하나 더 추가" }, + "GOLDEN_POKEBALL": { name: "황금몬스터볼", description: "전투 후 획득하는 아이템의 선택지가 하나 더 늘어난다." }, - "ENEMY_DAMAGE_BOOSTER": { name: "데미지 토큰", description: "주는 데미지를 5% 증가" }, - "ENEMY_DAMAGE_REDUCTION": { name: "보호 토큰", description: "받는 데미지를 2.5% 감소" }, - "ENEMY_HEAL": { name: "회복 토큰", description: "매 턴 최대 체력의 2%를 회복" }, + "ENEMY_DAMAGE_BOOSTER": { name: "데미지 토큰", description: "주는 데미지를 5% 증가시킨다." }, + "ENEMY_DAMAGE_REDUCTION": { name: "보호 토큰", description: "받는 데미지를 2.5% 감소시킨다." }, + "ENEMY_HEAL": { name: "회복 토큰", description: "매 턴 최대 체력의 2%를 회복한다." }, "ENEMY_ATTACK_POISON_CHANCE": { name: "독 토큰" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "마비 토큰" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "화상 토큰" }, - "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "만병통치 토큰", description: "매 턴 상태이상에서 회복될 확률 2.5% 추가" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "만병통치 토큰", description: "매 턴 상태이상에서 회복될 확률이 2.5% 추가된다." }, "ENEMY_ENDURE_CHANCE": { name: "버티기 토큰" }, - "ENEMY_FUSED_CHANCE": { name: "합체 토큰", description: "야생 포켓몬이 합체할 확률 1% 추가" }, + "ENEMY_FUSED_CHANCE": { name: "합체 토큰", description: "야생 포켓몬이 합체되어 등장할 확률이 1% 추가된다." }, }, TempBattleStatBoosterItem: { "x_attack": "플러스파워", diff --git a/src/locales/ko/move.ts b/src/locales/ko/move.ts index 60a5a5eaafc..700a623c3cc 100644 --- a/src/locales/ko/move.ts +++ b/src/locales/ko/move.ts @@ -3393,7 +3393,7 @@ export const move: MoveTranslationEntries = { effect: "무수히 많은 불덩이로 공격한다. 화상 상태로 만들 때가 있다. 상대가 상태 이상인 경우 위력이 2배가 된다." }, ceaselessEdge: { - name: "비검천충파", + name: "비검천중파", effect: "조개껍질 검으로 공격한다. 조개껍질 파편은 압정이 되어 상대의 발밑에 흩어진다." }, bleakwindStorm: { diff --git a/src/locales/ko/party-ui-handler.ts b/src/locales/ko/party-ui-handler.ts new file mode 100644 index 00000000000..ce731e4915f --- /dev/null +++ b/src/locales/ko/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "교체한다", + "SUMMARY": "능력치를 본다", + "CANCEL": "그만둔다", + "RELEASE": "놓아준다", + "APPLY": "사용한다", + "TEACH": "가르친다" +} as const; diff --git a/src/locales/ko/save-slot-select-ui-handler.ts b/src/locales/ko/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..213da34bda5 --- /dev/null +++ b/src/locales/ko/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "선택한 슬롯에 데이터를 덮어쓰시겠습니까?", + "loading": "로딩 중...", + "wave": "웨이브", + "lv": "Lv", + "empty": "빈 슬롯", +} as const; diff --git a/src/locales/ko/starter-select-ui-handler.ts b/src/locales/ko/starter-select-ui-handler.ts index bb2b4369c92..41001488458 100644 --- a/src/locales/ko/starter-select-ui-handler.ts +++ b/src/locales/ko/starter-select-ui-handler.ts @@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "selectMoveSwapWith": "교체될 기술을 선택해주세요. 대상:", "unlockPassive": "패시브 해금", "reduceCost": "코스트 줄이기", - "cycleShiny": "R: 색상 전환", - "cycleForm": "F: 폼 체인지", - "cycleGender": "G: 암수 전환", - "cycleAbility": "E: 특성 전환", - "cycleNature": "N: 성격 전환", - "cycleVariant": "V: 형태 전환", + "cycleShiny": ": 특별한 색", + "cycleForm": ": 폼 체인지", + "cycleGender": ": 암수 전환", + "cycleAbility": ": 특성 전환", + "cycleNature": ": 성격 전환", + "cycleVariant": ": 색상 전환", "enablePassive": "패시브 활성화", "disablePassive": "패시브 비활성화", "locked": "잠김", diff --git a/src/locales/ko/trainers.ts b/src/locales/ko/trainers.ts index 62e8de560d2..0bc99640333 100644 --- a/src/locales/ko/trainers.ts +++ b/src/locales/ko/trainers.ts @@ -101,6 +101,7 @@ export const trainerClasses: SimpleTranslationEntries = { "smasher": "테니스선수", "snow_worker": "작업원", "snow_worker_female": "작업원", + "sailor": "선원", "striker": "축구선수", "school_kid": "학원끝난 아이", "school_kid_female": "학원끝난 아이", diff --git a/src/locales/pt_BR/ability-trigger.ts b/src/locales/pt_BR/ability-trigger.ts index 19b043094a5..6aee4d542f4 100644 --- a/src/locales/pt_BR/ability-trigger.ts +++ b/src/locales/pt_BR/ability-trigger.ts @@ -4,5 +4,5 @@ export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{abilityName}} de {{pokemonName}}\nprotegeu-o do dano de recuo!", "badDreams": "{{pokemonName}} está tendo pesadelos!", "windPowerCharged": "Ser atingido por {{moveName}} carregou {{pokemonName}} com poder!", - "iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!" + "iceFaceAvoidedDamage": "{{pokemonName}} evitou\ndanos com sua {{abilityName}}!" } as const; diff --git a/src/locales/pt_BR/achv.ts b/src/locales/pt_BR/achv.ts index 5aaccc465ac..a15d59df6c5 100644 --- a/src/locales/pt_BR/achv.ts +++ b/src/locales/pt_BR/achv.ts @@ -1,6 +1,7 @@ import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "Conquistas", }, @@ -168,4 +169,367 @@ export const achv: AchievementTranslationEntries = { name: "Invencível", description: "Vença o jogo no modo clássico", }, + + "MONO_GEN_ONE": { + + name: "O Início de Tudo", + description: "Complete o desafio da geração um.", + }, + "MONO_GEN_TWO": { + name: "Geração 1.5", + description: "Complete o desafio da geração dois.", + }, + "MONO_GEN_THREE": { + name: "Será que tem muita água?", + description: "Complete o desafio da geração três.", + }, + "MONO_GEN_FOUR": { + name: "Essa foi a mais difícil?", + description: "Complete o desafio da geração quatro.", + }, + "MONO_GEN_FIVE": { + name: "Nada original", + description: "Complete o desafio da geração cinco.", + }, + "MONO_GEN_SIX": { + name: "Esse croissant tem recheio?", + description: "Complete o desafio da geração seis.", + }, + "MONO_GEN_SEVEN": { + name: "Z-Move ou Se vira nos 30?", + description: "Complete o desafio da geração sete.", + }, + "MONO_GEN_EIGHT": { + name: "Finalmente ele ganhou!", + description: "Complete o desafio da geração oito.", + }, + "MONO_GEN_NINE": { + name: "Isso aqui tá muito fácil!", + description: "Complete o desafio da geração nove.", + }, + + "MonoType": { + description: "Complete o desafio de monotipo {{type}}.", + }, + "MONO_NORMAL": { + name: "Tenho medo de fantasma", + }, + "MONO_FIGHTING": { + name: "Briga de Rua", + }, + "MONO_FLYING": { + name: "Rinha de Pidgeys", + }, + "MONO_POISON": { + name: "Menina Veneno", + }, + "MONO_GROUND": { + name: "Deixou eles comendo poeira!", + }, + "MONO_ROCK": { + name: "Duro como Pedra", + }, + "MONO_BUG": { + name: "Vida de Inseto", + }, + "MONO_GHOST": { + name: "Posso dormir com você hoje, mamãe?", + }, + "MONO_STEEL": { + name: "Levantando Ferro", + }, + "MONO_FIRE": { + name: "Tá Pegando Fogo, Bicho!", + }, + "MONO_WATER": { + name: "Água mole em pedra dura...", + }, + "MONO_GRASS": { + name: "Jardim Botânico", + }, + "MONO_ELECTRIC": { + name: "Choque de Realidade", + }, + "MONO_PSYCHIC": { + name: "Preciso de Terapia", + }, + "MONO_ICE": { + name: "Era do Gelo", + }, + "MONO_DRAGON": { + name: "Caverna do Dragão", + }, + "MONO_DARK": { + name: "É só uma fase", + }, + "MONO_FAIRY": { + name: "Clube das Winx", + }, +} as const; + +// Achievement translations for the when the player character is female +export const PGFachv: AchievementTranslationEntries = { + "Achievements": { + name: "Conquistas", + }, + "Locked": { + name: "Não conquistado", + }, + + "MoneyAchv": { + description: "Acumule um total de ₽{{moneyAmount}}", + }, + "10K_MONEY": { + name: "Chuva de Dinheiro", + }, + "100K_MONEY": { + name: "Tô Rica!", + }, + "1M_MONEY": { + name: "Quem Quer Ser Um Milionário?", + }, + "10M_MONEY": { + name: "Tio Patinhas", + }, + + "DamageAchv": { + description: "Inflija {{damageAmount}} de dano em um único golpe", + }, + "250_DMG": { + name: "Essa Doeu!", + }, + "1000_DMG": { + name: "Essa Doeu Mais!", + }, + "2500_DMG": { + name: "Essa Doeu Muito!", + }, + "10000_DMG": { + name: "Essa Doeu Pra Caramba!", + }, + + "HealAchv": { + description: "Cure {{healAmount}} {{HP}} de uma vez só com um movimento, habilidade ou item segurado", + }, + "250_HEAL": { + name: "Residente", + }, + "1000_HEAL": { + name: "Enfermeira", + }, + "2500_HEAL": { + name: "Médica", + }, + "10000_HEAL": { + name: "Médica de Plantão", + }, + + "LevelAchv": { + description: "Aumente o nível de um Pokémon para o Nv{{level}}", + }, + "LV_100": { + name: "Calma Que Tem Mais!", + }, + "LV_250": { + name: "Treinadora de Elite", + }, + "LV_1000": { + name: "Ao Infinito e Além!", + }, + + "RibbonAchv": { + description: "Acumule um total de {{ribbonAmount}} Fitas", + }, + "10_RIBBONS": { + name: "Fita de Bronze", + }, + "25_RIBBONS": { + name: "Fita de Prata", + }, + "50_RIBBONS": { + name: "Fita de Ouro", + }, + "75_RIBBONS": { + name: "Fita de Platina", + }, + "100_RIBBONS": { + name: "Fita de Diamante", + }, + + "TRANSFER_MAX_BATTLE_STAT": { + name: "Trabalho em Equipe", + description: "Use Baton Pass com pelo menos um atributo aumentado ao máximo", + }, + "MAX_FRIENDSHIP": { + name: "Melhores Amigos", + description: "Alcance a amizade máxima com um Pokémon", + }, + "MEGA_EVOLVE": { + name: "Megamorfose", + description: "Megaevolua um Pokémon", + }, + "GIGANTAMAX": { + name: "Ficou Gigante!", + description: "Gigantamax um Pokémon", + }, + "TERASTALLIZE": { + name: "Terastalização", + description: "Terastalize um Pokémon", + }, + "STELLAR_TERASTALLIZE": { + name: "Estrela Cadente", + description: "Terastalize um Pokémon para o tipo Estelar", + }, + "SPLICE": { + name: "Fusão!", + description: "Funda dois Pokémon com um Splicer de DNA", + }, + "MINI_BLACK_HOLE": { + name: "Buraco Sem Fundo", + description: "Adquira um Mini Buraco Negro", + }, + "CATCH_MYTHICAL": { + name: "Mítico", + description: "Capture um Pokémon Mítico", + }, + "CATCH_SUB_LEGENDARY": { + name: "Quase Lendário", + description: "Capture um Pokémon Semi-Lendário", + }, + "CATCH_LEGENDARY": { + name: "Lendário", + description: "Capture um Pokémon Lendário", + }, + "SEE_SHINY": { + name: "Ué, Tá Brilhando?", + description: "Encontre um Pokémon Shiny selvagem", + }, + "SHINY_PARTY": { + name: "Tá Todo Mundo Brilhando!", + description: "Tenha uma equipe formada por 6 Pokémon Shiny", + }, + "HATCH_MYTHICAL": { + name: "Ovo Mítico", + description: "Choque um Pokémon Mítico", + }, + "HATCH_SUB_LEGENDARY": { + name: "Ovo Semi-Lendário", + description: "Choque um Pokémon Semi-Lendário", + }, + "HATCH_LEGENDARY": { + name: "Ovo Lendário", + description: "Choque um Pokémon Lendário", + }, + "HATCH_SHINY": { + name: "Ovo Shiny", + description: "Choque um Pokémon Shiny", + }, + "HIDDEN_ABILITY": { + name: "Potencial Oculto", + description: "Capture um Pokémon com uma Habilidade Oculta", + }, + "PERFECT_IVS": { + name: "Perfeição Certificada", + description: "Obtenha IVs perfeitos em um Pokémon", + }, + "CLASSIC_VICTORY": { + name: "Invencível", + description: "Vença o jogo no modo clássico", + }, + + "MONO_GEN_ONE": { + + name: "O Início de Tudo", + description: "Complete o desafio da geração um.", + }, + "MONO_GEN_TWO": { + name: "Geração 1.5", + description: "Complete o desafio da geração dois.", + }, + "MONO_GEN_THREE": { + name: "Será que tem muita água?", + description: "Complete o desafio da geração três.", + }, + "MONO_GEN_FOUR": { + name: "Essa foi a mais difícil?", + description: "Complete o desafio da geração quatro.", + }, + "MONO_GEN_FIVE": { + name: "Nada original", + description: "Complete o desafio da geração cinco.", + }, + "MONO_GEN_SIX": { + name: "Esse croissant tem recheio?", + description: "Complete o desafio da geração seis.", + }, + "MONO_GEN_SEVEN": { + name: "Z-Move ou Se vira nos 30?", + description: "Complete o desafio da geração sete.", + }, + "MONO_GEN_EIGHT": { + name: "Finalmente ele ganhou!", + description: "Complete o desafio da geração oito.", + }, + "MONO_GEN_NINE": { + name: "Isso aqui tá muito fácil!", + description: "Complete o desafio da geração nove.", + }, + + "MonoType": { + description: "Complete o desafio de monotipo {{type}}.", + }, + "MONO_NORMAL": { + name: "Tenho medo de fantasma", + }, + "MONO_FIGHTING": { + name: "Briga de Rua", + }, + "MONO_FLYING": { + name: "Rinha de Pidgeys", + }, + "MONO_POISON": { + name: "Menina Veneno", + }, + "MONO_GROUND": { + name: "Deixou eles comendo poeira!", + }, + "MONO_ROCK": { + name: "Duro como Pedra", + }, + "MONO_BUG": { + name: "Vida de Inseto", + }, + "MONO_GHOST": { + name: "Posso dormir com você hoje, mamãe?", + }, + "MONO_STEEL": { + name: "Levantando Ferro", + }, + "MONO_FIRE": { + name: "Tá Pegando Fogo, Bicho!", + }, + "MONO_WATER": { + name: "Água mole em pedra dura...", + }, + "MONO_GRASS": { + name: "Jardim Botânico", + }, + "MONO_ELECTRIC": { + name: "Choque de Realidade", + }, + "MONO_PSYCHIC": { + name: "Preciso de Terapia", + }, + "MONO_ICE": { + name: "Era do Gelo", + }, + "MONO_DRAGON": { + name: "Caverna do Dragão", + }, + "MONO_DARK": { + name: "É só uma fase", + }, + "MONO_FAIRY": { + name: "Clube das Winx", + }, } as const; diff --git a/src/locales/pt_BR/battle.ts b/src/locales/pt_BR/battle.ts index 47a74fe17b1..ebe0a090473 100644 --- a/src/locales/pt_BR/battle.ts +++ b/src/locales/pt_BR/battle.ts @@ -5,7 +5,7 @@ export const battle: SimpleTranslationEntries = { "trainerAppeared": "{{trainerName}}\nquer batalhar!", "trainerAppearedDouble": "{{trainerName}}\nquerem batalhar!", "singleWildAppeared": "Um {{pokemonName}} selvagem apareceu!", - "trainerSendOut": "{{trainerName}} sent out\n{{pokemonName}}!", + "trainerSendOut": "{{trainerName}} escolheu\n{{pokemonName}}!", "multiWildAppeared": "Um {{pokemonName1}} e um {{pokemonName2}} selvagens\napareceram!", "playerComeBack": "{{pokemonName}}, retorne!", "trainerComeBack": "{{trainerName}} retirou {{pokemonName}} da batalha!", @@ -13,9 +13,9 @@ export const battle: SimpleTranslationEntries = { "trainerGo": "{{trainerName}} escolheu {{pokemonName}}!", "switchQuestion": "Quer trocar\nde {{pokemonName}}?", "trainerDefeated": "Você derrotou\n{{trainerName}}!", - "moneyWon": "You got\n₽{{moneyAmount}} for winning!", + "moneyWon": "Você ganhou\n₽{{moneyAmount}} por ganhar!", "pokemonCaught": "{{pokemonName}} foi capturado!", - "partyFull": "Your party is full.\nRelease a Pokémon to make room for {{pokemonName}}?", + "partyFull": "Sua equipe está cheia.\nSolte um Pokémon para ter espaço para {{pokemonName}}?", "pokemon": "Pokémon", "sendOutPokemon": "{{pokemonName}}, eu escolho você!!", "hitResultCriticalHit": "Um golpe crítico!", diff --git a/src/locales/pt_BR/challenges.ts b/src/locales/pt_BR/challenges.ts new file mode 100644 index 00000000000..9b7bfe1973c --- /dev/null +++ b/src/locales/pt_BR/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "Desafios", + "start": "Iniciar", + "illegalEvolution": "{{pokemon}} não pode ser escolhido\nnesse desafio!", + "singleGeneration.name": "Geração Única", + "singleGeneration.value.0": "Desligado", + "singleGeneration.desc.0": "Você só pode user Pokémon de uma única geração.", + "singleGeneration.value.1": "Geração 1", + "singleGeneration.desc.1": "Você só pode user Pokémon da primeira geração.", + "singleGeneration.value.2": "Geração 2", + "singleGeneration.desc.2": "Você só pode user Pokémon da segunda geração.", + "singleGeneration.value.3": "Geração 3", + "singleGeneration.desc.3": "Você só pode user Pokémon da terceira geração.", + "singleGeneration.value.4": "Geração 4", + "singleGeneration.desc.4": "Você só pode user Pokémon da quarta geração.", + "singleGeneration.value.5": "Geração 5", + "singleGeneration.desc.5": "Você só pode user Pokémon da quinta geração.", + "singleGeneration.value.6": "Geração 6", + "singleGeneration.desc.6": "Você só pode user Pokémon da sexta geração.", + "singleGeneration.value.7": "Geração 7", + "singleGeneration.desc.7": "Você só pode user Pokémon da sétima geração.", + "singleGeneration.value.8": "Geração 8", + "singleGeneration.desc.8": "Você só pode user Pokémon da oitava geração.", + "singleGeneration.value.9": "Geração 9", + "singleGeneration.desc.9": "Você só pode user Pokémon da nona geração.", + "singleType.name": "Tipo Único", + "singleType.value.0": "Desligado", + "singleType.desc.0": "Você só pode user Pokémon de um único tipo.", + "singleType.value.1": "Normal", + "singleType.desc.1": "Você só pode user Pokémon do tipo Normal.", + "singleType.value.2": "Lutador", + "singleType.desc.2": "Você só pode user Pokémon do tipo Lutador.", + "singleType.value.3": "Voador", + "singleType.desc.3": "Você só pode user Pokémon do tipo Voador.", + "singleType.value.4": "Veneno", + "singleType.desc.4": "Você só pode user Pokémon do tipo Veneno.", + "singleType.value.5": "Terra", + "singleType.desc.5": "Você só pode user Pokémon do tipo Terra.", + "singleType.value.6": "Pedra", + "singleType.desc.6": "Você só pode user Pokémon do tipo Pedra.", + "singleType.value.7": "Inseto", + "singleType.desc.7": "Você só pode user Pokémon do tipo Inseto.", + "singleType.value.8": "Fantasma", + "singleType.desc.8": "Você só pode user Pokémon do tipo Fantasma.", + "singleType.value.9": "Aço", + "singleType.desc.9": "Você só pode user Pokémon do tipo Aço.", + "singleType.value.10": "Fogo", + "singleType.desc.10": "Você só pode user Pokémon do tipo Fogo.", + "singleType.value.11": "Água", + "singleType.desc.11": "Você só pode user Pokémon do tipo Água.", + "singleType.value.12": "Grama", + "singleType.desc.12": "Você só pode user Pokémon do tipo Grama.", + "singleType.value.13": "Elétrico", + "singleType.desc.13": "Você só pode user Pokémon do tipo Elétrico.", + "singleType.value.14": "Psíquico", + "singleType.desc.14": "Você só pode user Pokémon do tipo Psíquico.", + "singleType.value.15": "Gelo", + "singleType.desc.15": "Você só pode user Pokémon do tipo Gelo.", + "singleType.value.16": "Dragão", + "singleType.desc.16": "Você só pode user Pokémon do tipo Dragão.", + "singleType.value.17": "Sombrio", + "singleType.desc.17": "Você só pode user Pokémon do tipo Sombrio.", + "singleType.value.18": "Fada", + "singleType.desc.18": "Você só pode user Pokémon do tipo Fada.", +} as const; diff --git a/src/locales/pt_BR/config.ts b/src/locales/pt_BR/config.ts index 1aadb5b20b1..7fa3c483926 100644 --- a/src/locales/pt_BR/config.ts +++ b/src/locales/pt_BR/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -25,10 +27,12 @@ import { menuUiHandler } from "./menu-ui-handler"; import { modifierType } from "./modifier-type"; import { move } from "./move"; import { nature } from "./nature"; +import { partyUiHandler } from "./party-ui-handler"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; @@ -39,12 +43,14 @@ import { weather } from "./weather"; export const ptBrConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const ptBrConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -62,10 +69,12 @@ export const ptBrConfig = { modifierType: modifierType, move: move, nature: nature, + partyUiHandler: partyUiHandler, pokeball: pokeball, pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +82,5 @@ export const ptBrConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, }; diff --git a/src/locales/pt_BR/dialogue.ts b/src/locales/pt_BR/dialogue.ts index cf5ff6ccf4f..dbae36075ec 100644 --- a/src/locales/pt_BR/dialogue.ts +++ b/src/locales/pt_BR/dialogue.ts @@ -371,6 +371,18 @@ export const PGMdialogue: DialogueTranslationEntries = { 3: "Ai! Queimei minha língua!" }, }, + "sailor": { + "encounter": { + 1: "Mano, você vai andar na prancha se perder!", + 2: "Vem com tudo! Sou um marinheiro com orgulho!", + 3: "Ahoy marujo! Tá enjoado, é?!" + }, + "victory": { + 1: "Argh! Perdi pra uma criança!", + 2: "Sua vontade de ganhar me afogou!", + 3: "Estou achando que quem tá enjoado sou eu..." + }, + }, "brock": { "encounter": { 1: "Minha especialidade em Pokémon do tipo Pedra vai te derrubar! Vamos lá!", @@ -753,14 +765,14 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "shauntal": { "encounter": { - 1: "Com licença. Você é um desafiante, certo?\nSou a usuária de Pokémon do tipo Fantasma da Elite Four, Shauntal, e serei sua oponente.", + 1: "Com licença. Você é um desafiante, certo?\nSou a usuária de Pokémon do tipo Fantasma da Elite dos Quatro, Shauntal, e serei sua oponente.", 2: "Adoro escrever sobre Treinadores que vêm aqui e os Pokémon que treinam.\nPosso usar você e seus Pokémon como tema?", 3: "Cada pessoa que trabalha com Pokémon tem uma história para contar.\nQue história está prestes a ser contada?" }, "victory": { 1: "Uau. Estou sem palavras!", 2: "D-desculpe! Primeiro, preciso me desculpar com meus Pokémon...\n\nLamento muito que você tenha tido uma experiência ruim por minha causa!", - 3: "Mesmo com isso, ainda sou uma das Elite Four!" + 3: "Mesmo com isso, ainda sou uma da Elite dos Quatro!" }, "defeat": { 1: "Eheh.", @@ -909,13 +921,13 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "lacey": { "encounter": { - 1: "Vou enfrentar você com meu time usual como membro da Elite Four." + 1: "Vou enfrentar você com meu time usual como membro da Elite dos Quatro." }, "victory": { 1: "Foi uma excelente batalha. Estou ansiosa para o próximo desafio." }, "defeat": { - 1: "Fufufu... Nada mal.\nDesafiantes que derrotam a Elite Four são dignos de notar." + 1: "Fufufu... Nada mal.\nDesafiantes que derrotam a Elite dos Quatro são dignos de notar." } }, "drayton": { @@ -995,7 +1007,7 @@ export const PGMdialogue: DialogueTranslationEntries = { 1: "Batalhar é um assunto profundo e complexo..." }, "defeat": { - 1: "Vencer um membro da Elite Four não é fácil." + 1: "Vencer um membro da Elite dos Quatro não é fácil." } }, "cress": { @@ -1380,7 +1392,7 @@ export const PGMdialogue: DialogueTranslationEntries = { "larry_elite": { "encounter": { 1: `Olá… Sou eu, Larry. - $Eu também sou membro da Elite Four, sim… Infelizmente para mim.`, + $Eu também sou membro da Elite dos Quatro, sim… Infelizmente para mim.`, }, "victory": { 1: "Bem, isso tirou o vento debaixo das nossas asas…" @@ -1464,7 +1476,7 @@ export const PGMdialogue: DialogueTranslationEntries = { 1: "Então, aqui está você… Por que não vemos para quem os ventos favorecem hoje, você… ou eu?" }, "victory": { - 1: "É frustrante para mim como membro da Elite Four, mas parece que sua força é real." + 1: "É frustrante para mim como membro da Elite dos Quatro, mas parece que sua força é real." }, "defeat": { 1: "Essa foi uma jogada de mestre!" diff --git a/src/locales/pt_BR/game-mode.ts b/src/locales/pt_BR/game-mode.ts new file mode 100644 index 00000000000..5f0e930703b --- /dev/null +++ b/src/locales/pt_BR/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "Clássico", + "endless": "Infinito", + "endlessSpliced": "Infinito (Fusões)", + "dailyRun": "Desafio Diário", + "unknown": "Desconhecido", + "challenge": "Desafio", +} as const; diff --git a/src/locales/pt_BR/growth.ts b/src/locales/pt_BR/growth.ts index 50762e5ad94..945520c91d7 100644 --- a/src/locales/pt_BR/growth.ts +++ b/src/locales/pt_BR/growth.ts @@ -1,10 +1,10 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const growth: SimpleTranslationEntries = { - "Erratic": "Instável", + "Erratic": "Muito Rápido", "Fast": "Rápido", "Medium_Fast": "Meio Rápido", "Medium_Slow": "Meio Lento", "Slow": "Lento", - "Fluctuating": "Flutuante" + "Fluctuating": "Muito Lento", } as const; diff --git a/src/locales/pt_BR/menu.ts b/src/locales/pt_BR/menu.ts index 000ffb1e397..f4fc8cc3a72 100644 --- a/src/locales/pt_BR/menu.ts +++ b/src/locales/pt_BR/menu.ts @@ -45,8 +45,8 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Classificação Semanal", "noRankings": "Sem Classificação", "loading": "Carregando…", + "loadingAsset": "Carregando recurso: {{assetName}}", "playersOnline": "Jogadores Ativos", - "empty": "Vazio", "yes": "Sim", "no": "Não", "disclaimer": "AVISO", diff --git a/src/locales/pt_BR/modifier-type.ts b/src/locales/pt_BR/modifier-type.ts index adae36adc26..41e2b84725b 100644 --- a/src/locales/pt_BR/modifier-type.ts +++ b/src/locales/pt_BR/modifier-type.ts @@ -4,11 +4,11 @@ export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { "AddPokeballModifierType": { name: "{{modifierCount}}x {{pokeballName}}", - description: "Ganhe x{{modifierCount}} {{pokeballName}} (Mochila: {{pokeballAmount}}) \nChance de captura: {{catchRate}}", + description: "Ganhe x{{modifierCount}} {{pokeballName}} (Mochila: {{pokeballAmount}}) \nChance de captura: {{catchRate}}.", }, "AddVoucherModifierType": { name: "{{modifierCount}}x {{voucherTypeName}}", - description: "Ganhe x{{modifierCount}} {{voucherTypeName}}", + description: "Ganhe x{{modifierCount}} {{voucherTypeName}}.", }, "PokemonHeldItemModifierType": { extra: { @@ -17,63 +17,63 @@ export const modifierType: ModifierTypeTranslationEntries = { } }, "PokemonHpRestoreModifierType": { - description: "Restaura {{restorePoints}} PS ou {{restorePercent}}% PS de um Pokémon, o que for maior", + description: "Restaura {{restorePoints}} PS ou {{restorePercent}}% PS de um Pokémon, o que for maior.", extra: { - "fully": "Restaura totalmente os PS de um Pokémon", - "fullyWithStatus": "Restaura totalmente os PS de um Pokémon e cura qualquer mudança de estado", + "fully": "Restaura totalmente os PS de um Pokémon.", + "fullyWithStatus": "Restaura totalmente os PS de um Pokémon e cura qualquer mudança de estado.", } }, "PokemonReviveModifierType": { - description: "Reanima um Pokémon e restaura {{restorePercent}}% PS", + description: "Reanima um Pokémon e restaura {{restorePercent}}% PS.", }, "PokemonStatusHealModifierType": { - description: "Cura uma mudança de estado de um Pokémon", + description: "Cura uma mudança de estado de um Pokémon.", }, "PokemonPpRestoreModifierType": { - description: "Restaura {{restorePoints}} PP para um movimento de um Pokémon", + description: "Restaura {{restorePoints}} PP para um movimento de um Pokémon.", extra: { - "fully": "Restaura todos os PP para um movimento de um Pokémon", + "fully": "Restaura todos os PP para um movimento de um Pokémon.", } }, "PokemonAllMovePpRestoreModifierType": { - description: "Restaura {{restorePoints}} PP para todos os movimentos de um Pokémon", + description: "Restaura {{restorePoints}} PP para todos os movimentos de um Pokémon.", extra: { - "fully": "Restaura todos os PP para todos os movimentos de um Pokémon", + "fully": "Restaura todos os PP para todos os movimentos de um Pokémon.", } }, "PokemonPpUpModifierType": { - description: "Aumenta permanentemente os PP para o movimento de um Pokémon em {{upPoints}} para cada 5 PP máximos (máximo 3)", + description: "Aumenta permanentemente os PP para o movimento de um Pokémon em {{upPoints}} para cada 5 PP máximos (máximo 3).", }, "PokemonNatureChangeModifierType": { name: "Hortelã {{natureName}}", - description: "Muda a natureza do Pokémon para {{natureName}} e a desbloqueia permanentemente", + description: "Muda a natureza do Pokémon para {{natureName}} e a desbloqueia permanentemente.", }, "DoubleBattleChanceBoosterModifierType": { - description: "Dobra as chances de encontrar uma batalha em dupla por {{battleCount}} batalhas", + description: "Dobra as chances de encontrar uma batalha em dupla por {{battleCount}} batalhas.", }, "TempBattleStatBoosterModifierType": { - description: "Aumenta o atributo de {{tempBattleStatName}} para todos os membros da equipe por 5 batalhas", + description: "Aumenta o atributo de {{tempBattleStatName}} para todos os membros da equipe por 5 batalhas.", }, "AttackTypeBoosterModifierType": { - description: "Aumenta o poder dos ataques do tipo {{moveType}} de um Pokémon em 20%", + description: "Aumenta o poder dos ataques do tipo {{moveType}} de um Pokémon em 20%.", }, "PokemonLevelIncrementModifierType": { - description: "Aumenta em 1 o nível de um Pokémon", + description: "Aumenta em 1 o nível de um Pokémon.", }, "AllPokemonLevelIncrementModifierType": { - description: "Aumenta em 1 os níveis de todos os Pokémon", + description: "Aumenta em 1 os níveis de todos os Pokémon.", }, "PokemonBaseStatBoosterModifierType": { - description: "Aumenta o atributo base de {{statName}} em 10%. Quanto maior os IVs, maior o limite de aumento", + description: "Aumenta o atributo base de {{statName}} em 10%. Quanto maior os IVs, maior o limite de aumento.", }, "AllPokemonFullHpRestoreModifierType": { - description: "Restaura totalmente os PS de todos os Pokémon", + description: "Restaura totalmente os PS de todos os Pokémon.", }, "AllPokemonFullReviveModifierType": { - description: "Reanima todos os Pokémon, restaurando totalmente seus PS", + description: "Reanima todos os Pokémon, restaurando totalmente seus PS.", }, "MoneyRewardModifierType": { - description: "Garante uma quantidade {{moneyMultiplier}} de dinheiro (₽{{moneyAmount}})", + description: "Garante uma quantidade {{moneyMultiplier}} de dinheiro (₽{{moneyAmount}}).", extra: { "small": "pequena", "moderate": "moderada", @@ -81,62 +81,62 @@ export const modifierType: ModifierTypeTranslationEntries = { }, }, "ExpBoosterModifierType": { - description: "Aumenta o ganho de pontos de experiência em {{boostPercent}}%", + description: "Aumenta o ganho de pontos de experiência em {{boostPercent}}%.", }, "PokemonExpBoosterModifierType": { - description: "Aumenta o ganho de pontos de experiência de quem segura em {{boostPercent}}%", + description: "Aumenta o ganho de pontos de experiência de quem segura em {{boostPercent}}%.", }, "PokemonFriendshipBoosterModifierType": { - description: "Aumenta o ganho de amizade por vitória em 50%", + description: "Aumenta o ganho de amizade por vitória em 50%.", }, "PokemonMoveAccuracyBoosterModifierType": { - description: "Aumenta a precisão dos movimentos em {{accuracyAmount}} (máximo 100)", + description: "Aumenta a precisão dos movimentos em {{accuracyAmount}} (máximo 100).", }, "PokemonMultiHitModifierType": { - description: "Ataques acertam uma vez adicional ao custo de uma redução de poder de 60/75/82.5% por item, respectivamente", + description: "Ataques acertam uma vez adicional ao custo de uma redução de poder de 60/75/82.5% por item, respectivamente.", }, "TmModifierType": { name: "TM{{moveId}} - {{moveName}}", - description: "Ensina {{moveName}} a um Pokémon", + description: "Ensina {{moveName}} a um Pokémon.", }, "TmModifierTypeWithInfo": { name: "TM{{moveId}} - {{moveName}}", - description: "Ensina {{moveName}} a um Pokémon\n(Segure C ou Shift para mais informações)", + description: "Ensina {{moveName}} a um Pokémon\n(Segure C ou Shift para mais informações).", }, "EvolutionItemModifierType": { - description: "Faz certos Pokémon evoluírem", + description: "Faz certos Pokémon evoluírem.", }, "FormChangeItemModifierType": { - description: "Faz certos Pokémon mudarem de forma", + description: "Faz certos Pokémon mudarem de forma.", }, "FusePokemonModifierType": { - description: "Combina dois Pokémon (transfere Habilidade, divide os atributos base e tipos, compartilha os movimentos)", + description: "Combina dois Pokémon (transfere Habilidade, divide os atributos base e tipos, compartilha os movimentos).", }, "TerastallizeModifierType": { - name: "{{teraType}} Fragmento Tera", - description: "{{teraType}} Terastalize um Pokémon por até 10 batalhas", + name: "Fragmento Tera {{teraType}}", + description: "Terastalize um Pokémon para o tipo {{teraType}} por 10 ondas.", }, "ContactHeldItemTransferChanceModifierType": { - description: "Quando atacar, tem {{chancePercent}}% de chance de roubar um item do oponente", + description: "Quando atacar, tem {{chancePercent}}% de chance de roubar um item do oponente.", }, "TurnHeldItemTransferModifierType": { - description: "Todo turno, o Pokémon ganha um item aleatório do oponente", + description: "Todo turno, o Pokémon ganha um item aleatório do oponente.", }, "EnemyAttackStatusEffectChanceModifierType": { - description: "Ganha {{chancePercent}}% de chance de infligir {{statusEffect}} com ataques", + description: "Ganha {{chancePercent}}% de chance de infligir {{statusEffect}} com ataques.", }, "EnemyEndureChanceModifierType": { - description: "Ganha {{chancePercent}}% de chance de sobreviver a um ataque que o faria desmaiar", + description: "Ganha {{chancePercent}}% de chance de sobreviver a um ataque que o faria desmaiar.", }, "RARE_CANDY": { name: "Doce Raro" }, "RARER_CANDY": { name: "Doce Raríssimo" }, - "MEGA_BRACELET": { name: "Mega Bracelete", description: "Mega Pedras ficam disponíveis" }, - "DYNAMAX_BAND": { name: "Bracelete Dynamax", description: "Cogumáximos ficam disponíveis" }, - "TERA_ORB": { name: "Orbe Tera", description: "Fragmentos Tera ficam disponíveis" }, + "MEGA_BRACELET": { name: "Mega Bracelete", description: "Mega Pedras ficam disponíveis." }, + "DYNAMAX_BAND": { name: "Bracelete Dynamax", description: "Cogumáximos ficam disponíveis." }, + "TERA_ORB": { name: "Orbe Tera", description: "Fragmentos Tera ficam disponíveis." }, - "MAP": { name: "Mapa", description: "Permite escolher a próxima rota" }, + "MAP": { name: "Mapa", description: "Permite escolher a próxima rota." }, "POTION": { name: "Poção" }, "SUPER_POTION": { name: "Super Poção" }, @@ -151,7 +151,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "SACRED_ASH": { name: "Cinza Sagrada" }, - "REVIVER_SEED": { name: "Semente Reanimadora", description: "Após desmaiar, reanima com 50% de PS" }, + "REVIVER_SEED": { name: "Semente Reanimadora", description: "Após desmaiar, reanima com 50% de PS." }, "ETHER": { name: "Éter" }, "MAX_ETHER": { name: "Éter Máximo" }, @@ -166,12 +166,12 @@ export const modifierType: ModifierTypeTranslationEntries = { "SUPER_LURE": { name: "Super Incenso" }, "MAX_LURE": { name: "Incenso Máximo" }, - "MEMORY_MUSHROOM": { name: "Cogumemória", description: "Relembra um movimento esquecido" }, + "MEMORY_MUSHROOM": { name: "Cogumemória", description: "Relembra um movimento esquecido." }, - "EXP_SHARE": { name: "Compart. de Exp.", description: "Distribui pontos de experiência para todos os membros da equipe" }, - "EXP_BALANCE": { name: "Balanceador de Exp.", description: "Distribui pontos de experiência principalmente para os Pokémon mais fracos" }, + "EXP_SHARE": { name: "Compart. de Exp.", description: "Distribui pontos de experiência para todos os membros da equipe." }, + "EXP_BALANCE": { name: "Balanceador de Exp.", description: "Distribui pontos de experiência principalmente para os Pokémon mais fracos." }, - "OVAL_CHARM": { name: "Amuleto Oval", description: "Quando vários Pokémon participam de uma batalha, cada um recebe 10% extra de pontos de experiência" }, + "OVAL_CHARM": { name: "Amuleto Oval", description: "Quando vários Pokémon participam de uma batalha, cada um recebe 10% extra de pontos de experiência." }, "EXP_CHARM": { name: "Amuleto de Exp." }, "SUPER_EXP_CHARM": { name: "Super Amuleto de Exp." }, @@ -182,62 +182,62 @@ export const modifierType: ModifierTypeTranslationEntries = { "SOOTHE_BELL": { name: "Guizo" }, - "SOUL_DEW": { name: "Joia da Alma", description: "Aumenta a influência da natureza de um Pokémon em seus atributos em 10% (cumulativo)" }, + "SOUL_DEW": { name: "Joia da Alma", description: "Aumenta a influência da natureza de um Pokémon em seus atributos em 10% (cumulativo)." }, "NUGGET": { name: "Pepita" }, "BIG_NUGGET": { name: "Pepita Grande" }, "RELIC_GOLD": { name: "Relíquia de Ouro" }, - "AMULET_COIN": { name: "Moeda Amuleto", description: "Aumenta a recompensa de dinheiro em 50%" }, - "GOLDEN_PUNCH": { name: "Soco Dourado", description: "Concede 50% do dano causado em dinheiro" }, - "COIN_CASE": { name: "Moedeira", description: "Após cada 10ª batalha, recebe 10% de seu dinheiro em juros" }, + "AMULET_COIN": { name: "Moeda Amuleto", description: "Aumenta a recompensa de dinheiro em 50%." }, + "GOLDEN_PUNCH": { name: "Soco Dourado", description: "Concede 50% do dano causado em dinheiro." }, + "COIN_CASE": { name: "Moedeira", description: "Após cada 10ª batalha, recebe 10% de seu dinheiro em juros." }, - "LOCK_CAPSULE": { name: "Cápsula de Travamento", description: "Permite que você trave raridades de itens ao rolar novamente" }, + "LOCK_CAPSULE": { name: "Cápsula de Travamento", description: "Permite que você trave raridades de itens ao rolar novamente." }, "GRIP_CLAW": { name: "Garra-Aperto" }, "WIDE_LENS": { name: "Lente Ampla" }, "MULTI_LENS": { name: "Multi Lentes" }, - "HEALING_CHARM": { name: "Amuleto de Cura", description: "Aumenta a eficácia dos movimentos e itens que restauram PS em 10% (exceto Reanimador)" }, - "CANDY_JAR": { name: "Pote de Doces", description: "Aumenta o número de níveis adicionados pelo Doce Raro em 1" }, + "HEALING_CHARM": { name: "Amuleto de Cura", description: "Aumenta a eficácia dos movimentos e itens que restauram PS em 10% (exceto Reanimador)." }, + "CANDY_JAR": { name: "Pote de Doces", description: "Aumenta o número de níveis adicionados pelo Doce Raro em 1." }, - "BERRY_POUCH": { name: "Bolsa de Berries", description: "Adiciona uma chance de 30% de que uma berry usada não seja consumida" }, + "BERRY_POUCH": { name: "Bolsa de Berries", description: "Adiciona uma chance de 30% de que uma berry usada não seja consumida." }, - "FOCUS_BAND": { name: "Bandana", description: "Adiciona uma chance de 10% de sobreviver com 1 PS após ser danificado o suficiente para desmaiar" }, + "FOCUS_BAND": { name: "Bandana", description: "Adiciona uma chance de 10% de sobreviver com 1 PS após ser danificado o suficiente para desmaiar." }, - "QUICK_CLAW": { name: "Garra Rápida", description: "Adiciona uma chance de 10% de atacar primeiro, ignorando sua velocidade (após prioridades)" }, + "QUICK_CLAW": { name: "Garra Rápida", description: "Adiciona uma chance de 10% de atacar primeiro, ignorando sua velocidade (após prioridades)." }, - "KINGS_ROCK": { name: "Pedra do Rei", description: "Adiciona uma chance de 10% de movimentos fazerem o oponente hesitar" }, + "KINGS_ROCK": { name: "Pedra do Rei", description: "Adiciona uma chance de 10% de movimentos fazerem o oponente hesitar." }, - "LEFTOVERS": { name: "Sobras", description: "Cura 1/16 dos PS máximos de um Pokémon a cada turno" }, - "SHELL_BELL": { name: "Concha-Sino", description: "Cura 1/8 do dano causado por um Pokémon" }, + "LEFTOVERS": { name: "Sobras", description: "Cura 1/16 dos PS máximos de um Pokémon a cada turno." }, + "SHELL_BELL": { name: "Concha-Sino", description: "Cura 1/8 do dano causado por um Pokémon." }, - "TOXIC_ORB": { name: "Esfera Tóxica", description: "Uma esfera estranha que exala toxinas quando tocada e envenena seriamente quem a segurar" }, - "FLAME_ORB": { name: "Esfera da Chama", description: "Uma esfera estranha que aquece quando tocada e queima quem a segurar" }, + "TOXIC_ORB": { name: "Esfera Tóxica", description: "Uma esfera estranha que exala toxinas quando tocada e envenena seriamente quem a segurar." }, + "FLAME_ORB": { name: "Esfera da Chama", description: "Uma esfera estranha que aquece quando tocada e queima quem a segurar." }, - "BATON": { name: "Bastão", description: "Permite passar mudanças de atributo ao trocar Pokémon, ignorando armadilhas" }, + "BATON": { name: "Bastão", description: "Permite passar mudanças de atributo ao trocar Pokémon, ignorando armadilhas." }, - "SHINY_CHARM": { name: "Amuleto Brilhante", description: "Aumenta drasticamente a chance de um Pokémon selvagem ser Shiny" }, - "ABILITY_CHARM": { name: "Amuleto de Habilidade", description: "Aumenta drasticamente a chance de um Pokémon selvagem ter uma Habilidade Oculta" }, + "SHINY_CHARM": { name: "Amuleto Brilhante", description: "Aumenta drasticamente a chance de um Pokémon selvagem ser Shiny." }, + "ABILITY_CHARM": { name: "Amuleto de Habilidade", description: "Aumenta drasticamente a chance de um Pokémon selvagem ter uma Habilidade Oculta." }, - "IV_SCANNER": { name: "Scanner de IVs", description: "Permite escanear os IVs de Pokémon selvagens. 2 IVs são revelados por item. Os melhores IVs são mostrados primeiro" }, + "IV_SCANNER": { name: "Scanner de IVs", description: "Permite escanear os IVs de Pokémon selvagens. 2 IVs são revelados por item. Os melhores IVs são mostrados primeiro." }, "DNA_SPLICERS": { name: "Splicer de DNA" }, "MINI_BLACK_HOLE": { name: "Mini Buraco Negro" }, - "GOLDEN_POKEBALL": { name: "Poké Bola Dourada", description: "Adiciona 1 opção de item extra ao final de cada batalha" }, + "GOLDEN_POKEBALL": { name: "Poké Bola Dourada", description: "Adiciona 1 opção de item extra ao final de cada batalha." }, - "ENEMY_DAMAGE_BOOSTER": { name: "Token de Dano", description: "Aumenta o dano em 5%" }, - "ENEMY_DAMAGE_REDUCTION": { name: "Token de Proteção", description: "Reduz o dano recebido em 2,5%" }, - "ENEMY_HEAL": { name: "Token de Recuperação", description: "Cura 2% dos PS máximos a cada turno" }, + "ENEMY_DAMAGE_BOOSTER": { name: "Token de Dano", description: "Aumenta o dano em 5%." }, + "ENEMY_DAMAGE_REDUCTION": { name: "Token de Proteção", description: "Reduz o dano recebido em 2,5%." }, + "ENEMY_HEAL": { name: "Token de Recuperação", description: "Cura 2% dos PS máximos a cada turno." }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Token de Veneno" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Token de Paralisia" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Token de Queimadura" }, - "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Token de Cura Total", description: "Adiciona uma chance de 2.5% a cada turno de curar uma condição de status" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Token de Cura Total", description: "Adiciona uma chance de 2.5% a cada turno de curar uma condição de status." }, "ENEMY_ENDURE_CHANCE": { name: "Token de Persistência" }, - "ENEMY_FUSED_CHANCE": { name: "Token de Fusão", description: "Adiciona uma chance de 1% de que um Pokémon selvagem seja uma fusão" }, + "ENEMY_FUSED_CHANCE": { name: "Token de Fusão", description: "Adiciona uma chance de 1% de que um Pokémon selvagem seja uma fusão." }, }, TempBattleStatBoosterItem: { "x_attack": "Ataque X", diff --git a/src/locales/pt_BR/party-ui-handler.ts b/src/locales/pt_BR/party-ui-handler.ts new file mode 100644 index 00000000000..763d733f3e8 --- /dev/null +++ b/src/locales/pt_BR/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "Trocar", + "SUMMARY": "Sumário", + "CANCEL": "Cancelar", + "RELEASE": "Soltar", + "APPLY": "Aplicar", + "TEACH": "Ensinar", +} as const; diff --git a/src/locales/pt_BR/save-slot-select-ui-handler.ts b/src/locales/pt_BR/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..23aeed7c5c7 --- /dev/null +++ b/src/locales/pt_BR/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "Substituir os dados desse slot?", + "loading": "Carregando...", + "wave": "Onda", + "lv": "Nv", + "empty": "Vazio", +} as const; diff --git a/src/locales/pt_BR/starter-select-ui-handler.ts b/src/locales/pt_BR/starter-select-ui-handler.ts index 4d4ee94505b..fc98e72c614 100644 --- a/src/locales/pt_BR/starter-select-ui-handler.ts +++ b/src/locales/pt_BR/starter-select-ui-handler.ts @@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "selectMoveSwapWith": "Escolha o movimento que substituirá", "unlockPassive": "Aprender Passiva", "reduceCost": "Reduzir Custo", - "cycleShiny": "R: » Shiny", - "cycleForm": "F: » Forma", - "cycleGender": "G: » Gênero", - "cycleAbility": "E: » Habilidade", - "cycleNature": "N: » Natureza", - "cycleVariant": "V: » Variante", + "cycleShiny": ": » Shiny", + "cycleForm": ": » Forma", + "cycleGender": ": » Gênero", + "cycleAbility": ": » Habilidade", + "cycleNature": ": » Natureza", + "cycleVariant": ": » Variante", "enablePassive": "Ativar Passiva", "disablePassive": "Desativar Passiva", "locked": "Bloqueada", diff --git a/src/locales/pt_BR/trainers.ts b/src/locales/pt_BR/trainers.ts index 5d624c60ad5..a2c6046e85e 100644 --- a/src/locales/pt_BR/trainers.ts +++ b/src/locales/pt_BR/trainers.ts @@ -6,10 +6,10 @@ export const titles: SimpleTranslationEntries = { "elite_four_female": "Elite dos Quatro", "gym_leader": "Líder de Ginásio", "gym_leader_female": "Líder de Ginásio", - "gym_leader_double": "Gym Leader Duo", + "gym_leader_double": "Líderes de Ginásio", "champion": "Campeão", - "champion_female": "Champion", - "champion_double": "Champion Duo", + "champion_female": "Campeã", + "champion_double": "Dupla Campeã", "rival": "Rival", "professor": "Professor", "frontier_brain": "Cérebro da Fronteira", @@ -18,8 +18,8 @@ export const titles: SimpleTranslationEntries = { // Titles of trainers like "Youngster" or "Lass" export const trainerClasses: SimpleTranslationEntries = { - "ace_trainer": "Trinador Ás", - "ace_trainer_female": "Trinadora Ás", + "ace_trainer": "Treinador Ás", + "ace_trainer_female": "Treinadora Ás", "ace_duo": "Dupla Ás", "artist": "Artista", "artist_female": "Artista", @@ -30,7 +30,7 @@ export const trainerClasses: SimpleTranslationEntries = { "baker": "Padeira", "battle_girl": "Lutadora", "beauty": "Modelo", - "beginners": "Beginners", + "beginners": "Iniciantes", "biker": "Motoqueiro", "black_belt": "Faixa Preta", "breeder": "Criador", @@ -95,6 +95,7 @@ export const trainerClasses: SimpleTranslationEntries = { "rich_kid_female": "Garota Rica", "rich_kids": "Garotos Ricos", "roughneck": "Arruaceiro", + "sailor": "Marinheiro", "scientist": "Cientista", "scientist_female": "Cientista", "scientists": "Cientistas", diff --git a/src/locales/zh_CN/achv.ts b/src/locales/zh_CN/achv.ts index 42b1995bcde..bf1bfc295e8 100644 --- a/src/locales/zh_CN/achv.ts +++ b/src/locales/zh_CN/achv.ts @@ -1,6 +1,7 @@ import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "Achievements", }, @@ -168,4 +169,102 @@ export const achv: AchievementTranslationEntries = { name: "Undefeated", description: "Beat the game in classic mode", }, + + "MONO_GEN_ONE": { + name: "The Original Rival", + description: "Complete the generation one only challenge.", + }, + "MONO_GEN_TWO": { + name: "Generation 1.5", + description: "Complete the generation two only challenge.", + }, + "MONO_GEN_THREE": { + name: "Too much water?", + description: "Complete the generation three only challenge.", + }, + "MONO_GEN_FOUR": { + name: "Is she really the hardest?", + description: "Complete the generation four only challenge.", + }, + "MONO_GEN_FIVE": { + name: "All Original", + description: "Complete the generation five only challenge.", + }, + "MONO_GEN_SIX": { + name: "Almost Royalty", + description: "Complete the generation six only challenge.", + }, + "MONO_GEN_SEVEN": { + name: "Only Technically", + description: "Complete the generation seven only challenge.", + }, + "MONO_GEN_EIGHT": { + name: "A Champion Time!", + description: "Complete the generation eight only challenge.", + }, + "MONO_GEN_NINE": { + name: "She was going easy on you", + description: "Complete the generation nine only challenge.", + }, + + "MonoType": { + description: "Complete the {{type}} monotype challenge.", + }, + "MONO_NORMAL": { + name: "Mono NORMAL", + }, + "MONO_FIGHTING": { + name: "I Know Kung Fu", + }, + "MONO_FLYING": { + name: "Mono FLYING", + }, + "MONO_POISON": { + name: "Kanto's Favourite", + }, + "MONO_GROUND": { + name: "Mono GROUND", + }, + "MONO_ROCK": { + name: "Brock Hard", + }, + "MONO_BUG": { + name: "Sting Like A Beedrill", + }, + "MONO_GHOST": { + name: "Who you gonna call?", + }, + "MONO_STEEL": { + name: "Mono STEEL", + }, + "MONO_FIRE": { + name: "Mono FIRE", + }, + "MONO_WATER": { + name: "When It Rains, It Pours", + }, + "MONO_GRASS": { + name: "Mono GRASS", + }, + "MONO_ELECTRIC": { + name: "Mono ELECTRIC", + }, + "MONO_PSYCHIC": { + name: "Mono PSYCHIC", + }, + "MONO_ICE": { + name: "Mono ICE", + }, + "MONO_DRAGON": { + name: "Mono DRAGON", + }, + "MONO_DARK": { + name: "It's just a phase", + }, + "MONO_FAIRY": { + name: "Mono FAIRY", + }, } as const; + +// Achievement translations for the when the player character is female (it for now uses the same translations as the male version) +export const PGFachv: AchievementTranslationEntries = PGMachv; diff --git a/src/locales/zh_CN/challenges.ts b/src/locales/zh_CN/challenges.ts new file mode 100644 index 00000000000..0810b6f1eeb --- /dev/null +++ b/src/locales/zh_CN/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "适用挑战条件", + "points": "Bad Ideas", + "confirm_start": "要执行这些挑战吗?", + "singleGeneration.name": "单一世代", + "singleGeneration.value.0": "关闭", + "singleGeneration.desc.0": "你只能使用所选世代的宝可梦", + "singleGeneration.value.1": "第一世代", + "singleGeneration.desc.1": "你只能使用第一世代的宝可梦", + "singleGeneration.value.2": "第二世代", + "singleGeneration.desc.2": "你只能使用第二世代的宝可梦", + "singleGeneration.value.3": "第三世代", + "singleGeneration.desc.3": "你只能使用第三世代的宝可梦", + "singleGeneration.value.4": "第四世代", + "singleGeneration.desc.4": "你只能使用第四世代的宝可梦", + "singleGeneration.value.5": "第五世代", + "singleGeneration.desc.5": "你只能使用第五世代的宝可梦", + "singleGeneration.value.6": "第六世代", + "singleGeneration.desc.6": "你只能使用第六世代的宝可梦", + "singleGeneration.value.7": "第七世代", + "singleGeneration.desc.7": "你只能使用第七世代的宝可梦", + "singleGeneration.value.8": "第八世代", + "singleGeneration.desc.8": "你只能使用第八世代的宝可梦", + "singleGeneration.value.9": "第久世代", + "singleGeneration.desc.9": "你只能使用第九世代的宝可梦", + "singleType.name": "单属性", + "singleType.value.0": "关闭", + "singleType.desc.0": "你只能使用所选属性的宝可梦", + "singleType.value.1": "普通", + "singleType.desc.1": "你只能使用普通属性的宝可梦", + "singleType.value.2": "格斗", + "singleType.desc.2": "你只能使用格斗属性的宝可梦", + "singleType.value.3": "飞行", + "singleType.desc.3": "你只能使用飞行属性的宝可梦", + "singleType.value.4": "毒", + "singleType.desc.4": "你只能使用毒属性的宝可梦", + "singleType.value.5": "地面", + "singleType.desc.5": "你只能使用地面属性的宝可梦", + "singleType.value.6": "岩石", + "singleType.desc.6": "你只能使用所选属性的宝可梦", + "singleType.value.7": "虫", + "singleType.desc.7": "你只能使用虫属性的宝可梦", + "singleType.value.8": "幽灵", + "singleType.desc.8": "你只能使用幽灵属性的宝可梦", + "singleType.value.9": "钢", + "singleType.desc.9": "你只能使用钢属性的宝可梦", + "singleType.value.10": "火", + "singleType.desc.10": "你只能使用火属性的宝可梦", + "singleType.value.11": "水", + "singleType.desc.11": "你只能使用水属性的宝可梦", + "singleType.value.12": "草", + "singleType.desc.12": "你只能使用草属性的宝可梦", + "singleType.value.13": "电", + "singleType.desc.13": "你只能使用电属性的宝可梦", + "singleType.value.14": "超能", + "singleType.desc.14": "你只能使用超能属性的宝可梦", + "singleType.value.15": "冰", + "singleType.desc.15": "你只能使用冰属性的宝可梦", + "singleType.value.16": "龙", + "singleType.desc.16": "你只能使用龙属性的宝可梦", + "singleType.value.17": "恶", + "singleType.desc.17": "你只能使用恶属性的宝可梦", + "singleType.value.18": "妖精", + "singleType.desc.18": "你只能使用妖精属性的宝可梦", +} as const; diff --git a/src/locales/zh_CN/config.ts b/src/locales/zh_CN/config.ts index 7a8ab5595f7..3f5504f64ce 100644 --- a/src/locales/zh_CN/config.ts +++ b/src/locales/zh_CN/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -29,22 +31,26 @@ import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; +import { partyUiHandler } from "./party-ui-handler"; export const zhCnConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const zhCnConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -66,6 +73,7 @@ export const zhCnConfig = { pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +81,6 @@ export const zhCnConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, + partyUiHandler: partyUiHandler }; diff --git a/src/locales/zh_CN/dialogue.ts b/src/locales/zh_CN/dialogue.ts index faabab3077d..26602079f65 100644 --- a/src/locales/zh_CN/dialogue.ts +++ b/src/locales/zh_CN/dialogue.ts @@ -371,6 +371,18 @@ export const PGMdialogue: DialogueTranslationEntries = { 3: "Ow! I scorched the tip of my nose!" }, }, + "sailor": { + "encounter": { + 1: "Matey, you're walking the plank if you lose!", + 2: "Come on then! My sailor's pride is at stake!", + 3: "Ahoy there! Are you seasick?" + }, + "victory": { + 1: "Argh! Beaten by a kid!", + 2: "Your spirit sank me!", + 3: "I think it's me that's seasick..." + }, + }, "brock": { "encounter": { 1: "My expertise on Rock-type Pokémon will take you down! Come on!", diff --git a/src/locales/zh_CN/game-mode.ts b/src/locales/zh_CN/game-mode.ts new file mode 100644 index 00000000000..be342b4c390 --- /dev/null +++ b/src/locales/zh_CN/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "Classic", + "endless": "Endless", + "endlessSpliced": "Endless (Spliced)", + "dailyRun": "Daily Run", + "unknown": "Unknown", + "challenge": "Challenge", +} as const; diff --git a/src/locales/zh_CN/menu.ts b/src/locales/zh_CN/menu.ts index d8cad6b05af..39d8e5e3a04 100644 --- a/src/locales/zh_CN/menu.ts +++ b/src/locales/zh_CN/menu.ts @@ -45,8 +45,8 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "每周排名", "noRankings": "无排名", "loading": "加载中...", + "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "在线玩家", - "empty": "空", "yes": "是", "no": "否", "disclaimer": "DISCLAIMER", diff --git a/src/locales/zh_CN/modifier-type.ts b/src/locales/zh_CN/modifier-type.ts index 456cc7bb8fb..597d10c9337 100644 --- a/src/locales/zh_CN/modifier-type.ts +++ b/src/locales/zh_CN/modifier-type.ts @@ -4,11 +4,11 @@ export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { "AddPokeballModifierType": { name: "{{modifierCount}}x {{pokeballName}}", - description: "获得 {{pokeballName}} x{{modifierCount}} (已有:{{pokeballAmount}}) \n捕捉倍率:{{catchRate}}", + description: "获得 {{pokeballName}} x{{modifierCount}} (已有:{{pokeballAmount}}) \n捕捉倍率:{{catchRate}}。", }, "AddVoucherModifierType": { name: "{{modifierCount}}x {{voucherTypeName}}", - description: "获得 {{voucherTypeName}} x{{modifierCount}}", + description: "获得 {{voucherTypeName}} x{{modifierCount}}。", }, "PokemonHeldItemModifierType": { extra: { @@ -17,63 +17,63 @@ export const modifierType: ModifierTypeTranslationEntries = { } }, "PokemonHpRestoreModifierType": { - description: "为一只宝可梦回复 {{restorePoints}} HP 或 {{restorePercent}}% HP,取较大值", + description: "为一只宝可梦回复 {{restorePoints}} HP 或 {{restorePercent}}% HP,取较大值。", extra: { - "fully": "为一只宝可梦回复全部HP", - "fullyWithStatus": "为一只宝可梦回复全部HP并消除所有负面\n状态", + "fully": "为一只宝可梦回复全部HP。", + "fullyWithStatus": "为一只宝可梦回复全部HP并消除所有负面\n状态。", } }, "PokemonReviveModifierType": { - description: "复活一只宝可梦并回复 {{restorePercent}}% HP", + description: "复活一只宝可梦并回复 {{restorePercent}}% HP。", }, "PokemonStatusHealModifierType": { - description: "为一只宝可梦消除所有负面状态", + description: "为一只宝可梦消除所有负面状态。", }, "PokemonPpRestoreModifierType": { - description: "为一只宝可梦的一个招式回复 {{restorePoints}} PP", + description: "为一只宝可梦的一个招式回复 {{restorePoints}} PP。", extra: { - "fully": "完全回复一只宝可梦一个招式的PP", + "fully": "完全回复一只宝可梦一个招式的PP。", } }, "PokemonAllMovePpRestoreModifierType": { - description: "为一只宝可梦的所有招式回复 {{restorePoints}} PP", + description: "为一只宝可梦的所有招式回复 {{restorePoints}} PP。", extra: { - "fully": "为一只宝可梦的所有招式回复所有PP", + "fully": "为一只宝可梦的所有招式回复所有PP。", } }, "PokemonPpUpModifierType": { - description: "为一只宝可梦的一个招式永久增加{{upPoints}}点\nPP每5点当前最大PP (最多3点)", + description: "为一只宝可梦的一个招式永久增加{{upPoints}}点\nPP每5点当前最大PP (最多3点)。", }, "PokemonNatureChangeModifierType": { name: "{{natureName}}薄荷", - description: "将一只宝可梦的性格改为{{natureName}}并为该宝可\n梦永久解锁该性格.", + description: "将一只宝可梦的性格改为{{natureName}}并为该宝可\n梦永久解锁该性格。", }, "DoubleBattleChanceBoosterModifierType": { - description: "接下来的{{battleCount}}场战斗是双打的概率翻倍", + description: "接下来的{{battleCount}}场战斗是双打的概率翻倍。", }, "TempBattleStatBoosterModifierType": { - description: "为所有成员宝可梦提升一级{{tempBattleStatName}},持续5场战斗", + description: "为所有成员宝可梦提升一级{{tempBattleStatName}},持续5场战斗。", }, "AttackTypeBoosterModifierType": { - description: "一只宝可梦的{{moveType}}系招式威力提升20%", + description: "一只宝可梦的{{moveType}}系招式威力提升20%。", }, "PokemonLevelIncrementModifierType": { - description: "一只宝可梦等级提升1级", + description: "一只宝可梦等级提升1级。", }, "AllPokemonLevelIncrementModifierType": { - description: "所有成员宝可梦等级提升1级", + description: "所有成员宝可梦等级提升1级。", }, "PokemonBaseStatBoosterModifierType": { - description: "增加持有者的{{statName}}10%,个体值越高堆叠\n上限越高.", + description: "增加持有者的{{statName}}10%,个体值越高堆叠\n上限越高。", }, "AllPokemonFullHpRestoreModifierType": { - description: "所有宝可梦完全回复HP", + description: "所有宝可梦完全回复HP。", }, "AllPokemonFullReviveModifierType": { - description: "复活所有濒死宝可梦,完全回复HP", + description: "复活所有濒死宝可梦,完全回复HP。", }, "MoneyRewardModifierType": { - description: "获得{{moneyMultiplier}}金钱 (₽{{moneyAmount}})", + description: "获得{{moneyMultiplier}}金钱 (₽{{moneyAmount}})。", extra: { "small": "少量", "moderate": "中等", @@ -81,62 +81,62 @@ export const modifierType: ModifierTypeTranslationEntries = { }, }, "ExpBoosterModifierType": { - description: "经验值获取量增加{{boostPercent}}%", + description: "经验值获取量增加{{boostPercent}}%。", }, "PokemonExpBoosterModifierType": { - description: "持有者经验值获取量增加{{boostPercent}}%", + description: "持有者经验值获取量增加{{boostPercent}}%。", }, "PokemonFriendshipBoosterModifierType": { - description: "每场战斗获得的好感度提升50%", + description: "每场战斗获得的好感度提升50%。", }, "PokemonMoveAccuracyBoosterModifierType": { - description: "招式命中率增加{{accuracyAmount}} (最大100)", + description: "招式命中率增加{{accuracyAmount}} (最大100)。", }, "PokemonMultiHitModifierType": { - description: "攻击造成一次额外伤害,每次堆叠额外伤害\n分别衰减60/75/82.5%", + description: "攻击造成一次额外伤害,每次堆叠额外伤害\n分别衰减60/75/82.5%。", }, "TmModifierType": { name: "招式学习器 {{moveId}} - {{moveName}}", - description: "教会一只宝可梦{{moveName}}", + description: "教会一只宝可梦{{moveName}}。", }, "TmModifierTypeWithInfo": { name: "招式学习器 {{moveId}} - {{moveName}}", - description: "教会一只宝可梦{{moveName}}\n(Hold C or Shift for more info)", + description: "教会一只宝可梦{{moveName}}\n(Hold C or Shift for more info)。", }, "EvolutionItemModifierType": { - description: "使某些宝可梦进化", + description: "使某些宝可梦进化。", }, "FormChangeItemModifierType": { - description: "使某些宝可梦更改形态", + description: "使某些宝可梦更改形态。", }, "FusePokemonModifierType": { - description: "融合两只宝可梦 (改变特性, 平分基础点数\n和属性, 共享招式池)", + description: "融合两只宝可梦 (改变特性, 平分基础点数\n和属性, 共享招式池)。", }, "TerastallizeModifierType": { name: "{{teraType}}太晶碎块", - description: "持有者获得{{teraType}}太晶化10场战斗", + description: "持有者获得{{teraType}}太晶化10场战斗。", }, "ContactHeldItemTransferChanceModifierType": { - description: "攻击时{{chancePercent}}%概率偷取对手物品", + description: "攻击时{{chancePercent}}%概率偷取对手物品。", }, "TurnHeldItemTransferModifierType": { - description: "持有者每回合从对手那里获得一个持有的物品", + description: "持有者每回合从对手那里获得一个持有的物品。", }, "EnemyAttackStatusEffectChanceModifierType": { - description: "攻击时{{chancePercent}}%概率造成{{statusEffect}}", + description: "攻击时{{chancePercent}}%概率造成{{statusEffect}}。", }, "EnemyEndureChanceModifierType": { - description: "增加{{chancePercent}}%遭受攻击的概率", + description: "增加{{chancePercent}}%遭受攻击的概率。", }, "RARE_CANDY": { name: "神奇糖果" }, "RARER_CANDY": { name: "超神奇糖果" }, - "MEGA_BRACELET": { name: "超级手镯", description: "能让携带着超级石战斗的宝可梦进行\n超级进化" }, - "DYNAMAX_BAND": { name: "极巨腕带", description: "能让携带着极巨菇菇战斗的宝可梦进行\n极巨化" }, - "TERA_ORB": { name: "太晶珠", description: "能让携带着太晶碎块战斗的宝可梦进行\n太晶化" }, + "MEGA_BRACELET": { name: "超级手镯", description: "能让携带着超级石战斗的宝可梦进行\n超级进化。" }, + "DYNAMAX_BAND": { name: "极巨腕带", description: "能让携带着极巨菇菇战斗的宝可梦进行\n极巨化。" }, + "TERA_ORB": { name: "太晶珠", description: "能让携带着太晶碎块战斗的宝可梦进行\n太晶化。" }, - "MAP": { name: "地图", description: "允许你在切换宝可梦群落时选择目的地"}, + "MAP": { name: "地图", description: "允许你在切换宝可梦群落时选择目的地。"}, "POTION": { name: "伤药" }, "SUPER_POTION": { name: "好伤药" }, @@ -151,7 +151,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "SACRED_ASH": { name: "圣灰" }, - "REVIVER_SEED": { name: "复活种子", description: "恢复1只濒死宝可梦的HP至1/2" }, + "REVIVER_SEED": { name: "复活种子", description: "恢复1只濒死宝可梦的HP至1/2。" }, "ETHER": { name: "PP单项小补剂" }, "MAX_ETHER": { name: "PP单项全补剂" }, @@ -166,12 +166,12 @@ export const modifierType: ModifierTypeTranslationEntries = { "SUPER_LURE": { name: "白银香水" }, "MAX_LURE": { name: "黄金香水" }, - "MEMORY_MUSHROOM": { name: "回忆蘑菇", description: "回忆一个宝可梦已经遗忘的招式" }, + "MEMORY_MUSHROOM": { name: "回忆蘑菇", description: "回忆一个宝可梦已经遗忘的招式。" }, - "EXP_SHARE": { name: "学习装置", description: "未参加对战的宝可梦获得20%的经验值" }, - "EXP_BALANCE": { name: "均衡型学习装置", description: "队伍中的低级宝可梦获得更多经验值" }, + "EXP_SHARE": { name: "学习装置", description: "未参加对战的宝可梦获得20%的经验值。" }, + "EXP_BALANCE": { name: "均衡型学习装置", description: "队伍中的低级宝可梦获得更多经验值。" }, - "OVAL_CHARM": { name: "圆形护符", description: "当多只宝可梦参与战斗,分别获得总经验值\n10%的额外经验值" }, + "OVAL_CHARM": { name: "圆形护符", description: "当多只宝可梦参与战斗,分别获得总经验值\n10%的额外经验值。" }, "EXP_CHARM": { name: "经验护符" }, "SUPER_EXP_CHARM": { name: "超级经验护符" }, @@ -182,62 +182,62 @@ export const modifierType: ModifierTypeTranslationEntries = { "SOOTHE_BELL": { name: "安抚之铃" }, - "SOUL_DEW": { name: "心之水滴", description: "增加宝可梦性格影响10% (加算)" }, + "SOUL_DEW": { name: "心之水滴", description: "增加宝可梦性格影响10% (加算)。" }, "NUGGET": { name: "金珠" }, "BIG_NUGGET": { name: "巨大金珠" }, "RELIC_GOLD": { name: "古代金币" }, - "AMULET_COIN": { name: "护符金币", description: "金钱奖励增加20%" }, - "GOLDEN_PUNCH": { name: "黄金拳头", description: "将50%造成的伤害转换为金钱" }, - "COIN_CASE": { name: "代币盒", description: "每十场战斗, 获得自己金钱10%的利息" }, + "AMULET_COIN": { name: "护符金币", description: "金钱奖励增加20%。" }, + "GOLDEN_PUNCH": { name: "黄金拳头", description: "将50%造成的伤害转换为金钱。" }, + "COIN_CASE": { name: "代币盒", description: "每十场战斗, 获得自己金钱10%的利息。" }, - "LOCK_CAPSULE": { name: "上锁的容器", description: "允许在刷新物品时锁定物品稀有度" }, + "LOCK_CAPSULE": { name: "上锁的容器", description: "允许在刷新物品时锁定物品稀有度。" }, "GRIP_CLAW": { name: "紧缠钩爪" }, "WIDE_LENS": { name: "广角镜" }, "MULTI_LENS": { name: "多重镜" }, - "HEALING_CHARM": { name: "治愈护符", description: "HP回复量增加10% (含复活)" }, - "CANDY_JAR": { name: "糖果罐", description: "神奇糖果提供的升级额外增加1级" }, + "HEALING_CHARM": { name: "治愈护符", description: "HP回复量增加10% (不含复活)。" }, + "CANDY_JAR": { name: "糖果罐", description: "神奇糖果提供的升级额外增加1级。" }, - "BERRY_POUCH": { name: "树果袋", description: "使用树果时有30%的几率不会消耗树果" }, + "BERRY_POUCH": { name: "树果袋", description: "使用树果时有30%的几率不会消耗树果。" }, - "FOCUS_BAND": { name: "气势头带", description: "携带该道具的宝可梦有10%几率在受到\n攻击而将陷入濒死状态时,保留1点HP不陷入濒死状态" }, + "FOCUS_BAND": { name: "气势头带", description: "携带该道具的宝可梦有10%几率在受到\n攻击而将陷入濒死状态时,保留1点HP不陷入濒死状态。" }, - "QUICK_CLAW": { name: "先制之爪", description: "有10%的几率无视速度优先使出招式\n(先制技能优先)" }, + "QUICK_CLAW": { name: "先制之爪", description: "有10%的几率无视速度优先使出招式\n(先制技能优先)。" }, - "KINGS_ROCK": { name: "王者之证", description: "携带该道具的宝可梦使用任意原本不会造成\n畏缩状态的攻击招式并造成伤害时,有\n10%几率使目标陷入畏缩状态" }, + "KINGS_ROCK": { name: "王者之证", description: "携带该道具的宝可梦使用任意原本不会造成\n畏缩状态的攻击招式并造成伤害时,有\n10%几率使目标陷入畏缩状态。" }, - "LEFTOVERS": { name: "吃剩的东西", description: "携带该道具的宝可梦在每个回合结束时恢复\n最大HP的1/16" }, - "SHELL_BELL": { name: "贝壳之铃", description: "携带该道具的宝可梦在攻击对方成功造成伤\n害时,携带者的HP会恢复其所造成伤害\n的1/8" }, + "LEFTOVERS": { name: "吃剩的东西", description: "携带该道具的宝可梦在每个回合结束时恢复\n最大HP的1/16。" }, + "SHELL_BELL": { name: "贝壳之铃", description: "携带该道具的宝可梦在攻击对方成功造成伤\n害时,携带者的HP会恢复其所造成伤害\n的1/8。" }, - "TOXIC_ORB": { name: "Toxic Orb", description: "It's a bizarre orb that exudes toxins when touched and will badly poison the holder during battle" }, - "FLAME_ORB": { name: "Flame Orb", description: "It's a bizarre orb that gives off heat when touched and will affect the holder with a burn during battle" }, + "TOXIC_ORB": { name: "Toxic Orb", description: "触碰后会放出毒的神奇宝珠。携带后,在战斗时会变成剧毒状态。" }, + "FLAME_ORB": { name: "Flame Orb", description: "触碰后会放出热量的神奇宝珠。携带后,在战斗时会变成灼伤状态。" }, - "BATON": { name: "接力棒", description: "允许在切换宝可梦时保留能力变化, 对陷阱\n同样生效" }, + "BATON": { name: "接力棒", description: "允许在切换宝可梦时保留能力变化, 对陷阱\n同样生效。" }, - "SHINY_CHARM": { name: "闪耀护符", description: "显著增加野生宝可梦的闪光概率" }, - "ABILITY_CHARM": { name: "特性护符", description: "显著增加野生宝可梦有隐藏特性的概率" }, + "SHINY_CHARM": { name: "闪耀护符", description: "显著增加野生宝可梦的闪光概率。" }, + "ABILITY_CHARM": { name: "特性护符", description: "显著增加野生宝可梦有隐藏特性的概率。" }, - "IV_SCANNER": { name: "个体值探测器", description: "允许扫描野生宝可梦的个体值。可叠加,每多拥有一个多显示\n2项个体值. 最好的个体值优先显示" }, + "IV_SCANNER": { name: "个体值探测器", description: "允许扫描野生宝可梦的个体值。可叠加,每多拥有一个多显示\n2项个体值. 最好的个体值优先显示。" }, "DNA_SPLICERS": { name: "基因之楔" }, "MINI_BLACK_HOLE": { name: "迷你黑洞" }, - "GOLDEN_POKEBALL": { name: "黄金精灵球", description: "在每场战斗结束后增加一个额外物品选项" }, + "GOLDEN_POKEBALL": { name: "黄金精灵球", description: "在每场战斗结束后增加一个额外物品选项。" }, - "ENEMY_DAMAGE_BOOSTER": { name: "伤害硬币", description: "增加5%造成伤害" }, - "ENEMY_DAMAGE_REDUCTION": { name: "防御硬币", description: "减少2.5%承受伤害" }, - "ENEMY_HEAL": { name: "回复硬币", description: "每回合回复2%最大HP" }, + "ENEMY_DAMAGE_BOOSTER": { name: "伤害硬币", description: "增加5%造成伤害。" }, + "ENEMY_DAMAGE_REDUCTION": { name: "防御硬币", description: "减少2.5%承受伤害。" }, + "ENEMY_HEAL": { name: "回复硬币", description: "每回合回复2%最大HP。" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "剧毒硬币" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "麻痹硬币" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "灼烧硬币" }, - "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "万灵药硬币", description: "增加2.5%每回合治愈异常状态的概率" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "万灵药硬币", description: "增加2.5%每回合治愈异常状态的概率。" }, "ENEMY_ENDURE_CHANCE": { name: "忍受硬币" }, - "ENEMY_FUSED_CHANCE": { name: "融合硬币", description: "增加1%野生融合宝可梦出现概率" }, + "ENEMY_FUSED_CHANCE": { name: "融合硬币", description: "增加1%野生融合宝可梦出现概率。" }, }, TempBattleStatBoosterItem: { "x_attack": "力量强化", diff --git a/src/locales/zh_CN/party-ui-handler.ts b/src/locales/zh_CN/party-ui-handler.ts new file mode 100644 index 00000000000..9d3c7baa9ae --- /dev/null +++ b/src/locales/zh_CN/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "Send Out", + "SUMMARY": "Summary", + "CANCEL": "Cancel", + "RELEASE": "Release", + "APPLY": "Apply", + "TEACH": "Teach" +} as const; diff --git a/src/locales/zh_CN/save-slot-select-ui-handler.ts b/src/locales/zh_CN/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..98b7764aee2 --- /dev/null +++ b/src/locales/zh_CN/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "Overwrite the data in the selected slot?", + "loading": "Loading...", + "wave": "Wave", + "lv": "Lv", + "empty": "空", +} as const; diff --git a/src/locales/zh_CN/starter-select-ui-handler.ts b/src/locales/zh_CN/starter-select-ui-handler.ts index 9491438bb13..a05c7348ab5 100644 --- a/src/locales/zh_CN/starter-select-ui-handler.ts +++ b/src/locales/zh_CN/starter-select-ui-handler.ts @@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "selectMoveSwapWith": "选择要替换成的招式", "unlockPassive": "解锁被动", "reduceCost": "降低花费", - "cycleShiny": "R: 切换闪光", - "cycleForm": "F: 切换形态", - "cycleGender": "G: 切换性别", - "cycleAbility": "E: 切换特性", - "cycleNature": "N: 切换性格", - "cycleVariant": "V: 切换变种", + "cycleShiny": ": 切换闪光", + "cycleForm": ": 切换形态", + "cycleGender": ": 切换性别", + "cycleAbility": ": 切换特性", + "cycleNature": ": 切换性格", + "cycleVariant": ": 切换变种", "enablePassive": "启用被动", "disablePassive": "禁用被动", "locked": "未解锁", diff --git a/src/locales/zh_CN/trainers.ts b/src/locales/zh_CN/trainers.ts index ae0680a3c75..28b0760cc9b 100644 --- a/src/locales/zh_CN/trainers.ts +++ b/src/locales/zh_CN/trainers.ts @@ -95,6 +95,7 @@ export const trainerClasses: SimpleTranslationEntries = { "rich_kid_female": "Rich Kid", "rich_kids": "富二代组合", "roughneck": "光头男", + "sailor": "水手", "scientist": "研究员", "scientist_female": "研究员", "scientists": "研究员组合", diff --git a/src/locales/zh_CN/tutorial.ts b/src/locales/zh_CN/tutorial.ts index fc737798489..8b0e5aad8fd 100644 --- a/src/locales/zh_CN/tutorial.ts +++ b/src/locales/zh_CN/tutorial.ts @@ -1,7 +1,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const tutorial: SimpleTranslationEntries = { - "intro": `欢迎来到PokéRogue!这是一款以战斗为核心的融合了roguelite元素的宝可梦同人游戏。 + "intro": `欢迎来到PokéRogue!这是一款以战斗为核心的\n融合了roguelite元素的宝可梦同人游戏。 $本游戏未进行商业化,我们没有\nPokémon或Pokémon使用的版 $权资产的所有权。 $游戏仍在开发中,但已可完整游玩。如需报\n告错误,请通过 Discord 社区。 diff --git a/src/locales/zh_TW/achv.ts b/src/locales/zh_TW/achv.ts index 42b1995bcde..bf1bfc295e8 100644 --- a/src/locales/zh_TW/achv.ts +++ b/src/locales/zh_TW/achv.ts @@ -1,6 +1,7 @@ import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; -export const achv: AchievementTranslationEntries = { +// Achievement translations for the when the player character is male +export const PGMachv: AchievementTranslationEntries = { "Achievements": { name: "Achievements", }, @@ -168,4 +169,102 @@ export const achv: AchievementTranslationEntries = { name: "Undefeated", description: "Beat the game in classic mode", }, + + "MONO_GEN_ONE": { + name: "The Original Rival", + description: "Complete the generation one only challenge.", + }, + "MONO_GEN_TWO": { + name: "Generation 1.5", + description: "Complete the generation two only challenge.", + }, + "MONO_GEN_THREE": { + name: "Too much water?", + description: "Complete the generation three only challenge.", + }, + "MONO_GEN_FOUR": { + name: "Is she really the hardest?", + description: "Complete the generation four only challenge.", + }, + "MONO_GEN_FIVE": { + name: "All Original", + description: "Complete the generation five only challenge.", + }, + "MONO_GEN_SIX": { + name: "Almost Royalty", + description: "Complete the generation six only challenge.", + }, + "MONO_GEN_SEVEN": { + name: "Only Technically", + description: "Complete the generation seven only challenge.", + }, + "MONO_GEN_EIGHT": { + name: "A Champion Time!", + description: "Complete the generation eight only challenge.", + }, + "MONO_GEN_NINE": { + name: "She was going easy on you", + description: "Complete the generation nine only challenge.", + }, + + "MonoType": { + description: "Complete the {{type}} monotype challenge.", + }, + "MONO_NORMAL": { + name: "Mono NORMAL", + }, + "MONO_FIGHTING": { + name: "I Know Kung Fu", + }, + "MONO_FLYING": { + name: "Mono FLYING", + }, + "MONO_POISON": { + name: "Kanto's Favourite", + }, + "MONO_GROUND": { + name: "Mono GROUND", + }, + "MONO_ROCK": { + name: "Brock Hard", + }, + "MONO_BUG": { + name: "Sting Like A Beedrill", + }, + "MONO_GHOST": { + name: "Who you gonna call?", + }, + "MONO_STEEL": { + name: "Mono STEEL", + }, + "MONO_FIRE": { + name: "Mono FIRE", + }, + "MONO_WATER": { + name: "When It Rains, It Pours", + }, + "MONO_GRASS": { + name: "Mono GRASS", + }, + "MONO_ELECTRIC": { + name: "Mono ELECTRIC", + }, + "MONO_PSYCHIC": { + name: "Mono PSYCHIC", + }, + "MONO_ICE": { + name: "Mono ICE", + }, + "MONO_DRAGON": { + name: "Mono DRAGON", + }, + "MONO_DARK": { + name: "It's just a phase", + }, + "MONO_FAIRY": { + name: "Mono FAIRY", + }, } as const; + +// Achievement translations for the when the player character is female (it for now uses the same translations as the male version) +export const PGFachv: AchievementTranslationEntries = PGMachv; diff --git a/src/locales/zh_TW/challenges.ts b/src/locales/zh_TW/challenges.ts new file mode 100644 index 00000000000..149037be740 --- /dev/null +++ b/src/locales/zh_TW/challenges.ts @@ -0,0 +1,67 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const challenges: SimpleTranslationEntries = { + "title": "Challenge Modifiers", + "points": "Bad Ideas", + "confirm_start": "Proceed with these challenges?", + "singleGeneration.name": "Mono Gen", + "singleGeneration.value.0": "Off", + "singleGeneration.desc.0": "You can only use pokemon from the chosen generation.", + "singleGeneration.value.1": "Gen 1", + "singleGeneration.desc.1": "You can only use pokemon from generation one.", + "singleGeneration.value.2": "Gen 2", + "singleGeneration.desc.2": "You can only use pokemon from generation two.", + "singleGeneration.value.3": "Gen 3", + "singleGeneration.desc.3": "You can only use pokemon from generation three.", + "singleGeneration.value.4": "Gen 4", + "singleGeneration.desc.4": "You can only use pokemon from generation four.", + "singleGeneration.value.5": "Gen 5", + "singleGeneration.desc.5": "You can only use pokemon from generation five.", + "singleGeneration.value.6": "Gen 6", + "singleGeneration.desc.6": "You can only use pokemon from generation six.", + "singleGeneration.value.7": "Gen 7", + "singleGeneration.desc.7": "You can only use pokemon from generation seven.", + "singleGeneration.value.8": "Gen 8", + "singleGeneration.desc.8": "You can only use pokemon from generation eight.", + "singleGeneration.value.9": "Gen 9", + "singleGeneration.desc.9": "You can only use pokemon from generation nine.", + "singleType.name": "Mono Type", + "singleType.value.0": "Off", + "singleType.desc.0": "You can only use pokemon of the chosen type.", + "singleType.value.1": "Normal", + "singleType.desc.1": "You can only use pokemon with the Normal type.", + "singleType.value.2": "Fighting", + "singleType.desc.2": "You can only use pokemon with the Fighting type.", + "singleType.value.3": "Flying", + "singleType.desc.3": "You can only use pokemon with the Flying type.", + "singleType.value.4": "Poison", + "singleType.desc.4": "You can only use pokemon with the Poison type.", + "singleType.value.5": "Ground", + "singleType.desc.5": "You can only use pokemon with the Ground type.", + "singleType.value.6": "Rock", + "singleType.desc.6": "You can only use pokemon with the Rock type.", + "singleType.value.7": "Bug", + "singleType.desc.7": "You can only use pokemon with the Bug type.", + "singleType.value.8": "Ghost", + "singleType.desc.8": "You can only use pokemon with the Ghost type.", + "singleType.value.9": "Steel", + "singleType.desc.9": "You can only use pokemon with the Steel type.", + "singleType.value.10": "Fire", + "singleType.desc.10": "You can only use pokemon with the Fire type.", + "singleType.value.11": "Water", + "singleType.desc.11": "You can only use pokemon with the Water type.", + "singleType.value.12": "Grass", + "singleType.desc.12": "You can only use pokemon with the Grass type.", + "singleType.value.13": "Electric", + "singleType.desc.13": "You can only use pokemon with the Electric type.", + "singleType.value.14": "Psychic", + "singleType.desc.14": "You can only use pokemon with the Psychic type.", + "singleType.value.15": "Ice", + "singleType.desc.15": "You can only use pokemon with the Ice type.", + "singleType.value.16": "Dragon", + "singleType.desc.16": "You can only use pokemon with the Dragon type.", + "singleType.value.17": "Dark", + "singleType.desc.17": "You can only use pokemon with the Dark type.", + "singleType.value.18": "Fairy", + "singleType.desc.18": "You can only use pokemon with the Fairy type.", +} as const; diff --git a/src/locales/zh_TW/config.ts b/src/locales/zh_TW/config.ts index 1b942e0234f..49e82f3b436 100644 --- a/src/locales/zh_TW/config.ts +++ b/src/locales/zh_TW/config.ts @@ -1,10 +1,11 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; -import { achv } from "./achv"; +import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { berry } from "./berry"; import { biome } from "./biome"; +import { challenges } from "./challenges"; import { commandUiHandler } from "./command-ui-handler"; import { PGFbattleSpecDialogue, @@ -18,6 +19,7 @@ import { } from "./dialogue"; import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { gameMode } from "./game-mode"; import { gameStatsUiHandler } from "./game-stats-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; @@ -29,22 +31,26 @@ import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; +import { saveSlotSelectUiHandler } from "./save-slot-select-ui-handler"; import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; +import { partyUiHandler } from "./party-ui-handler"; export const zhTwConfig = { ability: ability, abilityTriggers: abilityTriggers, - achv: achv, battle: battle, battleMessageUiHandler: battleMessageUiHandler, berry: berry, biome: biome, + challenges: challenges, commandUiHandler: commandUiHandler, + PGMachv: PGMachv, + PGFachv: PGFachv, PGMdialogue: PGMdialogue, PGFdialogue: PGFdialogue, PGMbattleSpecDialogue: PGMbattleSpecDialogue, @@ -55,6 +61,7 @@ export const zhTwConfig = { PGFdoubleBattleDialogue: PGFdoubleBattleDialogue, egg: egg, fightUiHandler: fightUiHandler, + gameMode: gameMode, gameStatsUiHandler: gameStatsUiHandler, growth: growth, menu: menu, @@ -66,6 +73,7 @@ export const zhTwConfig = { pokemon: pokemon, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, + saveSlotSelectUiHandler: saveSlotSelectUiHandler, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, @@ -73,5 +81,6 @@ export const zhTwConfig = { trainerNames: trainerNames, tutorial: tutorial, voucher: voucher, - weather: weather + weather: weather, + partyUiHandler: partyUiHandler }; diff --git a/src/locales/zh_TW/dialogue.ts b/src/locales/zh_TW/dialogue.ts index 7cb29ec8191..5e79471f771 100644 --- a/src/locales/zh_TW/dialogue.ts +++ b/src/locales/zh_TW/dialogue.ts @@ -371,6 +371,18 @@ export const PGMdialogue: DialogueTranslationEntries = { 3: "Ow! I scorched the tip of my nose!" }, }, + "sailor": { + "encounter": { + 1: "Matey, you're walking the plank if you lose!", + 2: "Come on then! My sailor's pride is at stake!", + 3: "Ahoy there! Are you seasick?" + }, + "victory": { + 1: "Argh! Beaten by a kid!", + 2: "Your spirit sank me!", + 3: "I think it's me that's seasick..." + }, + }, "brock": { "encounter": { 1: "My expertise on Rock-type Pokémon will take you down! Come on!", diff --git a/src/locales/zh_TW/game-mode.ts b/src/locales/zh_TW/game-mode.ts new file mode 100644 index 00000000000..be342b4c390 --- /dev/null +++ b/src/locales/zh_TW/game-mode.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const gameMode: SimpleTranslationEntries = { + "classic": "Classic", + "endless": "Endless", + "endlessSpliced": "Endless (Spliced)", + "dailyRun": "Daily Run", + "unknown": "Unknown", + "challenge": "Challenge", +} as const; diff --git a/src/locales/zh_TW/menu.ts b/src/locales/zh_TW/menu.ts index 680db51e8ac..d16052f2ac7 100644 --- a/src/locales/zh_TW/menu.ts +++ b/src/locales/zh_TW/menu.ts @@ -45,8 +45,8 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "每週排名", "noRankings": "無排名", "loading": "加載中…", + "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "在線玩家", - "empty":"空", "yes":"是", "no":"否", "disclaimer": "DISCLAIMER", diff --git a/src/locales/zh_TW/modifier-type.ts b/src/locales/zh_TW/modifier-type.ts index a6e73ebfc28..51e3e6a2bcc 100644 --- a/src/locales/zh_TW/modifier-type.ts +++ b/src/locales/zh_TW/modifier-type.ts @@ -5,11 +5,11 @@ export const modifierType: ModifierTypeTranslationEntries = { AddPokeballModifierType: { name: "{{modifierCount}}x {{pokeballName}}", description: - "獲得 {{pokeballName}} x{{modifierCount}} (已有:{{pokeballAmount}}) \n捕捉倍率:{{catchRate}}", + "獲得 {{pokeballName}} x{{modifierCount}} (已有:{{pokeballAmount}}) \n捕捉倍率:{{catchRate}}。", }, AddVoucherModifierType: { name: "{{modifierCount}}x {{voucherTypeName}}", - description: "獲得 {{voucherTypeName}} x{{modifierCount}}", + description: "獲得 {{voucherTypeName}} x{{modifierCount}}。", }, PokemonHeldItemModifierType: { extra: { @@ -19,25 +19,25 @@ export const modifierType: ModifierTypeTranslationEntries = { }, PokemonHpRestoreModifierType: { description: - "爲一隻寶可夢恢復 {{restorePoints}} HP 或 {{restorePercent}}% HP,取最大值", + "爲一隻寶可夢恢復 {{restorePoints}} HP 或 {{restorePercent}}% HP,取最大值。", extra: { - fully: "爲一隻寶可夢恢復全部HP", - fullyWithStatus: "爲一隻寶可夢恢復全部HP並消除所有負面\n狀態", + fully: "爲一隻寶可夢恢復全部HP。", + fullyWithStatus: "爲一隻寶可夢恢復全部HP並消除所有負面\n狀態。", }, }, PokemonReviveModifierType: { - description: "復活一隻寶可夢並恢復 {{restorePercent}}% HP", + description: "復活一隻寶可夢並恢復 {{restorePercent}}% HP。", }, PokemonStatusHealModifierType: { - description: "爲一隻寶可夢消除所有負面狀態", + description: "爲一隻寶可夢消除所有負面狀態。", }, PokemonPpRestoreModifierType: { - description: "爲一隻寶可夢的一個招式恢復 {{restorePoints}} PP", - extra: { fully: "完全恢復一隻寶可夢一個招式的PP" }, + description: "爲一隻寶可夢的一個招式恢復 {{restorePoints}} PP。", + extra: { fully: "完全恢復一隻寶可夢一個招式的PP。" }, }, PokemonAllMovePpRestoreModifierType: { - description: "爲一隻寶可夢的所有招式恢復 {{restorePoints}} PP", - extra: { fully: "爲一隻寶可夢的所有招式恢復所有PP" }, + description: "爲一隻寶可夢的所有招式恢復 {{restorePoints}} PP。", + extra: { fully: "爲一隻寶可夢的所有招式恢復所有PP。" }, }, PokemonPpUpModifierType: { description: @@ -46,101 +46,101 @@ export const modifierType: ModifierTypeTranslationEntries = { PokemonNatureChangeModifierType: { name: "{{natureName}}薄荷", description: - "將一隻寶可夢的性格改爲{{natureName}}併爲該寶可\n夢永久解鎖該性格.", + "將一隻寶可夢的性格改爲{{natureName}}併爲該寶可\n夢永久解鎖該性格。", }, DoubleBattleChanceBoosterModifierType: { - description: "接下來的{{battleCount}}場戰鬥是雙打的概率翻倍", + description: "接下來的{{battleCount}}場戰鬥是雙打的概率翻倍。", }, TempBattleStatBoosterModifierType: { description: - "爲所有成員寶可夢提升一級{{tempBattleStatName}},持續5場戰鬥", + "爲所有成員寶可夢提升一級{{tempBattleStatName}},持續5場戰鬥。", }, AttackTypeBoosterModifierType: { - description: "一隻寶可夢的{{moveType}}系招式威力提升20%", + description: "一隻寶可夢的{{moveType}}系招式威力提升20%。", }, PokemonLevelIncrementModifierType: { - description: "一隻寶可夢等級提升1級", + description: "一隻寶可夢等級提升1級。", }, AllPokemonLevelIncrementModifierType: { - description: "所有成員寶可夢等級提升1級", + description: "所有成員寶可夢等級提升1級。", }, PokemonBaseStatBoosterModifierType: { description: - "增加持有者的{{statName}}10%,個體值越高堆疊\n上限越高.", + "增加持有者的{{statName}}10%,個體值越高堆疊\n上限越高。", }, AllPokemonFullHpRestoreModifierType: { - description: "所有寶可夢完全恢復HP", + description: "所有寶可夢完全恢復HP。", }, AllPokemonFullReviveModifierType: { - description: "復活所有瀕死寶可夢,完全恢復HP", + description: "復活所有瀕死寶可夢,完全恢復HP。", }, MoneyRewardModifierType: { - description: "獲得{{moneyMultiplier}}金錢 (₽{{moneyAmount}})", + description: "獲得{{moneyMultiplier}}金錢 (₽{{moneyAmount}})。", extra: { small: "少量", moderate: "中等", large: "大量" }, }, ExpBoosterModifierType: { - description: "經驗值獲取量增加{{boostPercent}}%", + description: "經驗值獲取量增加{{boostPercent}}%。", }, PokemonExpBoosterModifierType: { - description: "持有者經驗值獲取量增加{{boostPercent}}%", + description: "持有者經驗值獲取量增加{{boostPercent}}%。", }, PokemonFriendshipBoosterModifierType: { - description: "每場戰鬥獲得的好感度提升50%", + description: "每場戰鬥獲得的好感度提升50%。", }, PokemonMoveAccuracyBoosterModifierType: { - description: "招式命中率增加{{accuracyAmount}} (最大100)", + description: "招式命中率增加{{accuracyAmount}} (最大100)。", }, PokemonMultiHitModifierType: { description: - "攻擊造成一次額外傷害,每次堆疊額外傷害\n分別衰減60/75/82.5%", + "攻擊造成一次額外傷害,每次堆疊額外傷害\n分別衰減60/75/82.5%。", }, TmModifierType: { name: "招式學習器 {{moveId}} - {{moveName}}", - description: "教會一隻寶可夢{{moveName}}", + description: "教會一隻寶可夢{{moveName}}。", }, TmModifierTypeWithInfo: { name: "TM{{moveId}} - {{moveName}}", - description: "教會一隻寶可夢{{moveName}}\n(Hold C or Shift for more info)", + description: "教會一隻寶可夢{{moveName}}\n(Hold C or Shift for more info)。", }, - EvolutionItemModifierType: { description: "使某些寶可夢進化" }, - FormChangeItemModifierType: { description: "使某些寶可夢更改形態" }, + EvolutionItemModifierType: { description: "使某些寶可夢進化。" }, + FormChangeItemModifierType: { description: "使某些寶可夢更改形態。" }, FusePokemonModifierType: { description: - "融合兩隻寶可夢 (改變特性, 平分基礎點數\n和屬性, 共享招式池)", + "融合兩隻寶可夢 (改變特性, 平分基礎點數\n和屬性, 共享招式池)。", }, TerastallizeModifierType: { name: "{{teraType}}太晶碎塊", - description: "持有者獲得{{teraType}}太晶化10場戰鬥", + description: "持有者獲得{{teraType}}太晶化10場戰鬥。", }, ContactHeldItemTransferChanceModifierType: { - description: "攻擊時{{chancePercent}}%概率偷取對手物品", + description: "攻擊時{{chancePercent}}%概率偷取對手物品。", }, TurnHeldItemTransferModifierType: { - description: "持有者每回合從對手那裏獲得一個持有的物品", + description: "持有者每回合從對手那裏獲得一個持有的物品。", }, EnemyAttackStatusEffectChanceModifierType: { - description: "攻擊時{{chancePercent}}%概率造成{{statusEffect}}", + description: "攻擊時{{chancePercent}}%概率造成{{statusEffect}}。", }, EnemyEndureChanceModifierType: { - description: "增加{{chancePercent}}%遭受攻擊的概率", + description: "增加{{chancePercent}}%遭受攻擊的概率。", }, RARE_CANDY: { name: "神奇糖果" }, RARER_CANDY: { name: "超神奇糖果" }, MEGA_BRACELET: { name: "超級手鐲", - description: "能讓攜帶着超級石戰鬥的寶可夢進行\n超級進化", + description: "能讓攜帶着超級石戰鬥的寶可夢進行\n超級進化。", }, DYNAMAX_BAND: { name: "極巨腕帶", - description: "能讓攜帶着極巨菇菇戰鬥的寶可夢進行\n極巨化", + description: "能讓攜帶着極巨菇菇戰鬥的寶可夢進行\n極巨化。", }, TERA_ORB: { name: "太晶珠", - description: "能讓攜帶着太晶碎塊戰鬥的寶可夢進行\n太晶化", + description: "能讓攜帶着太晶碎塊戰鬥的寶可夢進行\n太晶化。", }, MAP: { name: "地圖", - description: "允許你在切換寶可夢羣落時選擇目的地", + description: "允許你在切換寶可夢羣落時選擇目的地。", }, POTION: { name: "傷藥" }, SUPER_POTION: { name: "好傷藥" }, @@ -153,7 +153,7 @@ export const modifierType: ModifierTypeTranslationEntries = { SACRED_ASH: { name: "聖灰" }, REVIVER_SEED: { name: "復活種子", - description: "恢復1只瀕死寶可夢的HP至1/2", + description: "恢復1只瀕死寶可夢的HP至1/2。", }, ETHER: { name: "PP單項小補劑" }, MAX_ETHER: { name: "PP單項全補劑" }, @@ -166,20 +166,20 @@ export const modifierType: ModifierTypeTranslationEntries = { MAX_LURE: { name: "黃金香水" }, MEMORY_MUSHROOM: { name: "回憶蘑菇", - description: "回憶一個寶可夢已經遺忘的招式", + description: "回憶一個寶可夢已經遺忘的招式。", }, EXP_SHARE: { name: "學習裝置", - description: "未參加對戰的寶可夢獲得20%的經驗值", + description: "未參加對戰的寶可夢獲得20%的經驗值。", }, EXP_BALANCE: { name: "均衡型學習裝置", - description: "隊伍中的低級寶可夢獲得更多經驗值", + description: "隊伍中的低級寶可夢獲得更多經驗值。", }, OVAL_CHARM: { name: "圓形護符", description: - "當多隻寶可夢參與戰鬥,分別獲得總經驗值\n10%的額外經驗值", + "當多隻寶可夢參與戰鬥,分別獲得總經驗值\n10%的額外經驗值。", }, EXP_CHARM: { name: "經驗護符" }, SUPER_EXP_CHARM: { name: "超級經驗護符" }, @@ -189,58 +189,58 @@ export const modifierType: ModifierTypeTranslationEntries = { SOOTHE_BELL: { name: "安撫之鈴" }, SOUL_DEW: { name: "心之水滴", - description: "增加寶可夢性格影響10% (加算)", + description: "增加寶可夢性格影響10% (加算)。", }, NUGGET: { name: "金珠" }, BIG_NUGGET: { name: "巨大金珠" }, RELIC_GOLD: { name: "古代金幣" }, - AMULET_COIN: { name: "護符金幣", description: "金錢獎勵增加20%" }, + AMULET_COIN: { name: "護符金幣", description: "金錢獎勵增加20%。" }, GOLDEN_PUNCH: { name: "黃金拳頭", - description: "將50%造成的傷害轉換爲金錢", + description: "將50%造成的傷害轉換爲金錢。", }, COIN_CASE: { name: "代幣盒", - description: "每十場戰鬥, 獲得自己金錢10%的利息", + description: "每十場戰鬥, 獲得自己金錢10%的利息。", }, LOCK_CAPSULE: { name: "上鎖的容器", - description: "允許在刷新物品時鎖定物品稀有度", + description: "允許在刷新物品時鎖定物品稀有度。", }, GRIP_CLAW: { name: "緊纏鉤爪" }, WIDE_LENS: { name: "廣角鏡" }, MULTI_LENS: { name: "多重鏡" }, HEALING_CHARM: { name: "治癒護符", - description: "HP恢復量增加10% (含復活)", + description: "HP恢復量增加10% (不含復活)。", }, - CANDY_JAR: { name: "糖果罐", description: "神奇糖果提供的升級提升1級" }, + CANDY_JAR: { name: "糖果罐", description: "神奇糖果提供的升級提升1級。" }, BERRY_POUCH: { name: "樹果袋", - description: "使用樹果時有30%的幾率不會消耗樹果", + description: "使用樹果時有30%的幾率不會消耗樹果。", }, FOCUS_BAND: { name: "氣勢頭帶", description: - "攜帶該道具的寶可夢有10%幾率在受到\n攻擊而將陷入瀕死狀態時,保留1點HP不陷入瀕死狀態", + "攜帶該道具的寶可夢有10%幾率在受到\n攻擊而將陷入瀕死狀態時,保留1點HP不陷入瀕死狀態。", }, QUICK_CLAW: { name: "先制之爪", - description: "有10%的幾率無視速度優先使出招式\n(先制技能優先)", + description: "有10%的幾率無視速度優先使出招式\n(先制技能優先)。", }, KINGS_ROCK: { name: "王者之證", description: - "攜帶該道具的寶可夢使用任意原本不會造成\n畏縮狀態的攻擊招式並造成傷害時,有\n10%幾率使目標陷入畏縮狀態", + "攜帶該道具的寶可夢使用任意原本不會造成\n畏縮狀態的攻擊招式並造成傷害時,有\n10%幾率使目標陷入畏縮狀態。", }, LEFTOVERS: { name: "喫剩的東西", - description: "攜帶該道具的寶可夢在每個回合結束時恢復\n最大HP的1/16", + description: "攜帶該道具的寶可夢在每個回合結束時恢復\n最大HP的1/16。", }, SHELL_BELL: { name: "貝殼之鈴", description: - "攜帶該道具的寶可夢在攻擊對方成功造成傷\n害時,攜帶者的HP會恢復其所造成傷害\n的1/8", + "攜帶該道具的寶可夢在攻擊對方成功造成傷\n害時,攜帶者的HP會恢復其所造成傷害\n的1/8。", }, TOXIC_ORB: { name: "Toxic Orb", @@ -254,47 +254,47 @@ export const modifierType: ModifierTypeTranslationEntries = { }, BATON: { name: "接力棒", - description: "允許在切換寶可夢時保留能力變化, 對陷阱\n同樣生效", + description: "允許在切換寶可夢時保留能力變化, 對陷阱\n同樣生效。", }, SHINY_CHARM: { name: "閃耀護符", - description: "顯著增加野生寶可夢的閃光概率", + description: "顯著增加野生寶可夢的閃光概率。", }, ABILITY_CHARM: { name: "特性護符", - description: "顯著增加野生寶可夢有隱藏特性的概率", + description: "顯著增加野生寶可夢有隱藏特性的概率。", }, IV_SCANNER: { name: "個體值探測器", description: - "允許掃描野生寶可夢的個體值。 每個次顯示\n2個個體值. 最好的個體值優先顯示", + "允許掃描野生寶可夢的個體值。 每個次顯示\n2個個體值. 最好的個體值優先顯示。", }, DNA_SPLICERS: { name: "基因之楔" }, MINI_BLACK_HOLE: { name: "迷你黑洞" }, GOLDEN_POKEBALL: { name: "黃金精靈球", - description: "在每場戰鬥結束後增加一個額外物品選項", + description: "在每場戰鬥結束後增加一個額外物品選項。", }, ENEMY_DAMAGE_BOOSTER: { name: "傷害硬幣", - description: "增加5%造成傷害", + description: "增加5%造成傷害。", }, ENEMY_DAMAGE_REDUCTION: { name: "防禦硬幣", - description: "減少2.5%承受傷害", + description: "減少2.5%承受傷害。", }, - ENEMY_HEAL: { name: "恢復硬幣", description: "每回合恢復2%最大HP" }, + ENEMY_HEAL: { name: "恢復硬幣", description: "每回合恢復2%最大HP。" }, ENEMY_ATTACK_POISON_CHANCE: { name: "劇毒硬幣" }, ENEMY_ATTACK_PARALYZE_CHANCE: { name: "麻痹硬幣" }, ENEMY_ATTACK_BURN_CHANCE: { name: "灼燒硬幣" }, ENEMY_STATUS_EFFECT_HEAL_CHANCE: { name: "萬靈藥硬幣", - description: "增加2.5%每回合治癒異常狀態的概率", + description: "增加2.5%每回合治癒異常狀態的概率。", }, ENEMY_ENDURE_CHANCE: { name: "忍受硬幣" }, ENEMY_FUSED_CHANCE: { name: "融合硬幣", - description: "增加1%野生融合寶可夢出現概率", + description: "增加1%野生融合寶可夢出現概率。", }, }, TempBattleStatBoosterItem: { diff --git a/src/locales/zh_TW/party-ui-handler.ts b/src/locales/zh_TW/party-ui-handler.ts new file mode 100644 index 00000000000..9d3c7baa9ae --- /dev/null +++ b/src/locales/zh_TW/party-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const partyUiHandler: SimpleTranslationEntries = { + "SEND_OUT": "Send Out", + "SUMMARY": "Summary", + "CANCEL": "Cancel", + "RELEASE": "Release", + "APPLY": "Apply", + "TEACH": "Teach" +} as const; diff --git a/src/locales/zh_TW/save-slot-select-ui-handler.ts b/src/locales/zh_TW/save-slot-select-ui-handler.ts new file mode 100644 index 00000000000..98b7764aee2 --- /dev/null +++ b/src/locales/zh_TW/save-slot-select-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const saveSlotSelectUiHandler: SimpleTranslationEntries = { + "overwriteData": "Overwrite the data in the selected slot?", + "loading": "Loading...", + "wave": "Wave", + "lv": "Lv", + "empty": "空", +} as const; diff --git a/src/locales/zh_TW/starter-select-ui-handler.ts b/src/locales/zh_TW/starter-select-ui-handler.ts index f7139a54189..89642588ee4 100644 --- a/src/locales/zh_TW/starter-select-ui-handler.ts +++ b/src/locales/zh_TW/starter-select-ui-handler.ts @@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "selectMoveSwapWith": "選擇想要替換成的招式", "unlockPassive": "解鎖被動", "reduceCost": "降低花費", - "cycleShiny": "R: 切換閃光", - "cycleForm": "F: 切換形態", - "cycleGender": "G: 切換性別", - "cycleAbility": "E: 切換特性", - "cycleNature": "N: 切換性格", - "cycleVariant": "V: 切換變種", + "cycleShiny": ": 切換閃光", + "cycleForm": ": 切換形態", + "cycleGender": ": 切換性別", + "cycleAbility": ": 切換特性", + "cycleNature": ": 切換性格", + "cycleVariant": ": 切換變種", "enablePassive": "啟用被動", "disablePassive": "禁用被動", "locked": "未解鎖", diff --git a/src/locales/zh_TW/trainers.ts b/src/locales/zh_TW/trainers.ts index f20ee156c3a..07b2949bdd8 100644 --- a/src/locales/zh_TW/trainers.ts +++ b/src/locales/zh_TW/trainers.ts @@ -95,6 +95,7 @@ export const trainerClasses: SimpleTranslationEntries = { "rich_kid_female": "富家孩子", "rich_kids": "富二代組合", "roughneck": "光頭男", + "sailor": "水手", "scientist": "研究員", "scientist_female": "研究員", "scientists": "研究員組合", diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 46019281d4b..6901290a306 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -25,6 +25,7 @@ import i18next from "#app/plugins/i18n"; import { getModifierTierTextTint } from "#app/ui/text"; import { BattlerTagType } from "#app/data/enums/battler-tag-type.js"; import * as Overrides from "../overrides"; +import { MoneyMultiplierModifier } from "./modifier"; const outputModifierData = false; const useMaxWeightForOutput = false; @@ -631,9 +632,13 @@ export class MoneyRewardModifierType extends ModifierType { } getDescription(scene: BattleScene): string { + const moneyAmount = new Utils.IntegerHolder(scene.getWaveMoneyAmount(this.moneyMultiplier)); + scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount); + const formattedMoney = Utils.formatMoney(scene.moneyFormat, moneyAmount.value); + return i18next.t("modifierType:ModifierType.MoneyRewardModifierType.description", { moneyMultiplier: i18next.t(this.moneyMultiplierDescriptorKey as any), - moneyAmount: scene.getWaveMoneyAmount(this.moneyMultiplier).toLocaleString("en-US"), + moneyAmount: formattedMoney, }); } } diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 271cf38cb5c..832c16ee4a9 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -797,7 +797,7 @@ export class BypassSpeedChanceModifier extends PokemonHeldItemModifier { const hasQuickClaw = this.type instanceof ModifierTypes.PokemonHeldItemModifierType && this.type.id === "QUICK_CLAW"; if (isCommandFight && hasQuickClaw) { - pokemon.scene.queueMessage(getPokemonMessage(pokemon, " used its quick claw to move faster!")); + pokemon.scene.queueMessage(getPokemonMessage(pokemon, " used its Quick Claw to move faster!")); } return true; } diff --git a/src/overrides.ts b/src/overrides.ts index 148dc352ae9..f8e3152de98 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -29,6 +29,7 @@ import { modifierTypes } from "./modifier/modifier-type"; export const SEED_OVERRIDE: string = ""; export const WEATHER_OVERRIDE: WeatherType = WeatherType.NONE; export const DOUBLE_BATTLE_OVERRIDE: boolean = false; +export const SINGLE_BATTLE_OVERRIDE: boolean = false; export const STARTING_WAVE_OVERRIDE: integer = 0; export const STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN; export const ARENA_TINT_OVERRIDE: TimeOfDay = null; @@ -110,6 +111,7 @@ export const OPP_MODIFIER_OVERRIDE: Array = []; export const STARTING_HELD_ITEMS_OVERRIDE: Array = []; export const OPP_HELD_ITEMS_OVERRIDE: Array = []; +export const NEVER_CRIT_OVERRIDE: boolean = false; /** * An array of items by keys as defined in the "modifierTypes" object in the "modifier/modifier-type.ts" file. diff --git a/src/phases.ts b/src/phases.ts index c43ab6e1c7f..d5e64ebae2d 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -36,7 +36,7 @@ import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; import { BattleSpec } from "./enums/battle-spec"; import { Species } from "./data/enums/species"; -import { HealAchv, LevelAchv, achvs } from "./system/achv"; +import { ChallengeAchv, HealAchv, LevelAchv, achvs } from "./system/achv"; import { TrainerSlot, trainerConfigs } from "./data/trainer-config"; import { TrainerType } from "./data/enums/trainer-type"; import { EggHatchPhase } from "./egg-hatch-phase"; @@ -55,7 +55,7 @@ import { TerrainType } from "./data/terrain"; import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select-ui-handler"; import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler"; import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run"; -import { GameModes, gameModes } from "./game-mode"; +import { GameMode, GameModes, getGameMode } from "./game-mode"; import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./data/pokemon-species"; import i18next from "./plugins/i18n"; import { Abilities } from "./data/enums/abilities"; @@ -63,6 +63,7 @@ import * as Overrides from "./overrides"; import { TextStyle, addTextObject } from "./ui/text"; import { Type } from "./data/type"; import { BerryUsedEvent, EncounterPhaseEvent, MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events"; +import { ExpNotification } from "./enums/exp-notification"; export class LoginPhase extends Phase { @@ -148,7 +149,7 @@ export class LoginPhase extends Phase { export class TitlePhase extends Phase { private loaded: boolean; private lastSessionData: SessionSaveData; - private gameMode: GameModes; + public gameMode: GameModes; constructor(scene: BattleScene) { super(scene); @@ -201,14 +202,21 @@ export class TitlePhase extends Phase { if (this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]) { const options: OptionSelectItem[] = [ { - label: gameModes[GameModes.CLASSIC].getName(), + label: GameMode.getModeName(GameModes.CLASSIC), handler: () => { setModeAndEnd(GameModes.CLASSIC); return true; } }, { - label: gameModes[GameModes.ENDLESS].getName(), + label: GameMode.getModeName(GameModes.CHALLENGE), + handler: () => { + setModeAndEnd(GameModes.CHALLENGE); + return true; + } + }, + { + label: GameMode.getModeName(GameModes.ENDLESS), handler: () => { setModeAndEnd(GameModes.ENDLESS); return true; @@ -217,7 +225,7 @@ export class TitlePhase extends Phase { ]; if (this.scene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE]) { options.push({ - label: gameModes[GameModes.SPLICED_ENDLESS].getName(), + label: GameMode.getModeName(GameModes.SPLICED_ENDLESS), handler: () => { setModeAndEnd(GameModes.SPLICED_ENDLESS); return true; @@ -306,7 +314,7 @@ export class TitlePhase extends Phase { this.scene.sessionSlotId = slotId; const generateDaily = (seed: string) => { - this.scene.gameMode = gameModes[GameModes.DAILY]; + this.scene.gameMode = getGameMode(GameModes.DAILY); this.scene.setSeed(seed); this.scene.resetSeed(1); @@ -368,7 +376,12 @@ export class TitlePhase extends Phase { end(): void { if (!this.loaded && !this.scene.gameMode.isDaily) { this.scene.arena.preloadBgm(); - this.scene.pushPhase(new SelectStarterPhase(this.scene, this.gameMode)); + this.scene.gameMode = getGameMode(this.gameMode); + if (this.gameMode === GameModes.CHALLENGE) { + this.scene.pushPhase(new SelectChallengePhase(this.scene)); + } else { + this.scene.pushPhase(new SelectStarterPhase(this.scene)); + } this.scene.newArena(this.scene.gameMode.getStartingBiome(this.scene)); } else { this.scene.playBgm(); @@ -377,7 +390,7 @@ export class TitlePhase extends Phase { this.scene.pushPhase(new EncounterPhase(this.scene, this.loaded)); if (this.loaded) { - const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted()).length; + const availablePartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle()).length; this.scene.pushPhase(new SummonPhase(this.scene, 0, true, true)); if (this.scene.currentBattle.double && availablePartyMembers > 1) { @@ -503,13 +516,24 @@ export class SelectGenderPhase extends Phase { } } -export class SelectStarterPhase extends Phase { - private gameMode: GameModes; - - constructor(scene: BattleScene, gameMode: GameModes) { +export class SelectChallengePhase extends Phase { + constructor(scene: BattleScene) { super(scene); + } - this.gameMode = gameMode; + start() { + super.start(); + + this.scene.playBgm("menu"); + + this.scene.ui.setMode(Mode.CHALLENGE_SELECT); + } +} + +export class SelectStarterPhase extends Phase { + + constructor(scene: BattleScene) { + super(scene); } start() { @@ -526,59 +550,62 @@ export class SelectStarterPhase extends Phase { return this.end(); } this.scene.sessionSlotId = slotId; - - const party = this.scene.getParty(); - const loadPokemonAssets: Promise[] = []; - starters.forEach((starter: Starter, i: integer) => { - if (!i && Overrides.STARTER_SPECIES_OVERRIDE) { - starter.species = getPokemonSpecies(Overrides.STARTER_SPECIES_OVERRIDE as Species); - } - const starterProps = this.scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr); - let starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0)); - if (!i && Overrides.STARTER_SPECIES_OVERRIDE) { - starterFormIndex = Overrides.STARTER_FORM_OVERRIDE; - } - let starterGender = starter.species.malePercent !== null - ? !starterProps.female ? Gender.MALE : Gender.FEMALE - : Gender.GENDERLESS; - if (Overrides.GENDER_OVERRIDE !== null) { - starterGender = Overrides.GENDER_OVERRIDE; - } - const starterIvs = this.scene.gameData.dexData[starter.species.speciesId].ivs.slice(0); - const starterPokemon = this.scene.addPlayerPokemon(starter.species, this.scene.gameMode.getStartingLevel(), starter.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterProps.variant, starterIvs, starter.nature); - starterPokemon.tryPopulateMoveset(starter.moveset); - if (starter.passive) { - starterPokemon.passive = true; - } - starterPokemon.luck = this.scene.gameData.getDexAttrLuck(this.scene.gameData.dexData[starter.species.speciesId].caughtAttr); - if (starter.pokerus) { - starterPokemon.pokerus = true; - } - if (this.scene.gameMode.isSplicedOnly) { - starterPokemon.generateFusionSpecies(true); - } - starterPokemon.setVisible(false); - party.push(starterPokemon); - loadPokemonAssets.push(starterPokemon.loadAssets()); - }); - overrideModifiers(this.scene); - overrideHeldItems(this.scene, party[0]); - Promise.all(loadPokemonAssets).then(() => { - SoundFade.fadeOut(this.scene, this.scene.sound.get("menu"), 500, true); - this.scene.time.delayedCall(500, () => this.scene.playBgm()); - if (this.scene.gameMode.isClassic) { - this.scene.gameData.gameStats.classicSessionsPlayed++; - } else { - this.scene.gameData.gameStats.endlessSessionsPlayed++; - } - this.scene.newBattle(); - this.scene.arena.init(); - this.scene.sessionPlayTime = 0; - this.scene.lastSavePlayTime = 0; - this.end(); - }); + this.initBattle(starters); }); - }, this.gameMode); + }); + } + + initBattle(starters: Starter[]) { + const party = this.scene.getParty(); + const loadPokemonAssets: Promise[] = []; + starters.forEach((starter: Starter, i: integer) => { + if (!i && Overrides.STARTER_SPECIES_OVERRIDE) { + starter.species = getPokemonSpecies(Overrides.STARTER_SPECIES_OVERRIDE as Species); + } + const starterProps = this.scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr); + let starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0)); + if (!i && Overrides.STARTER_SPECIES_OVERRIDE) { + starterFormIndex = Overrides.STARTER_FORM_OVERRIDE; + } + let starterGender = starter.species.malePercent !== null + ? !starterProps.female ? Gender.MALE : Gender.FEMALE + : Gender.GENDERLESS; + if (Overrides.GENDER_OVERRIDE !== null) { + starterGender = Overrides.GENDER_OVERRIDE; + } + const starterIvs = this.scene.gameData.dexData[starter.species.speciesId].ivs.slice(0); + const starterPokemon = this.scene.addPlayerPokemon(starter.species, this.scene.gameMode.getStartingLevel(), starter.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterProps.variant, starterIvs, starter.nature); + starterPokemon.tryPopulateMoveset(starter.moveset); + if (starter.passive) { + starterPokemon.passive = true; + } + starterPokemon.luck = this.scene.gameData.getDexAttrLuck(this.scene.gameData.dexData[starter.species.speciesId].caughtAttr); + if (starter.pokerus) { + starterPokemon.pokerus = true; + } + if (this.scene.gameMode.isSplicedOnly) { + starterPokemon.generateFusionSpecies(true); + } + starterPokemon.setVisible(false); + party.push(starterPokemon); + loadPokemonAssets.push(starterPokemon.loadAssets()); + }); + overrideModifiers(this.scene); + overrideHeldItems(this.scene, party[0]); + Promise.all(loadPokemonAssets).then(() => { + SoundFade.fadeOut(this.scene, this.scene.sound.get("menu"), 500, true); + this.scene.time.delayedCall(500, () => this.scene.playBgm()); + if (this.scene.gameMode.isClassic) { + this.scene.gameData.gameStats.classicSessionsPlayed++; + } else { + this.scene.gameData.gameStats.endlessSessionsPlayed++; + } + this.scene.newBattle(); + this.scene.arena.init(); + this.scene.sessionPlayTime = 0; + this.scene.lastSavePlayTime = 0; + this.end(); + }); } } @@ -633,11 +660,12 @@ export abstract class FieldPhase extends BattlePhase { const playerField = this.scene.getPlayerField().filter(p => p.isActive()) as Pokemon[]; const enemyField = this.scene.getEnemyField().filter(p => p.isActive()) as Pokemon[]; - let orderedTargets: Pokemon[] = playerField.concat(enemyField).sort((a: Pokemon, b: Pokemon) => { + // We shuffle the list before sorting so speed ties produce random results + let orderedTargets: Pokemon[] = Utils.randSeedShuffle(playerField.concat(enemyField)).sort((a: Pokemon, b: Pokemon) => { const aSpeed = a?.getBattleStat(Stat.SPD) || 0; const bSpeed = b?.getBattleStat(Stat.SPD) || 0; - return aSpeed < bSpeed ? 1 : aSpeed > bSpeed ? -1 : !this.scene.randBattleSeedInt(2) ? -1 : 1; + return bSpeed - aSpeed; }); const speedReversed = new Utils.BooleanHolder(false); @@ -997,7 +1025,7 @@ export class EncounterPhase extends BattlePhase { } if (!this.loaded) { - const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted()); + const availablePartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle()); if (!availablePartyMembers[0].isOnField()) { this.scene.pushPhase(new SummonPhase(this.scene, 0)); @@ -1290,20 +1318,33 @@ export class SummonPhase extends PartyMemberPokemonPhase { */ preSummon(): void { const partyMember = this.getPokemon(); - // If the Pokemon about to be sent out is fainted, switch to the first non-fainted Pokemon - if (partyMember.isFainted()) { - console.warn("The Pokemon about to be sent out is fainted. Attempting to resolve..."); + // If the Pokemon about to be sent out is fainted or illegal under a challenge, switch to the first non-fainted legal Pokemon + if (!partyMember.isAllowedInBattle()) { + console.warn("The Pokemon about to be sent out is fainted or illegal under a challenge. Attempting to resolve..."); + + // First check if they're somehow still in play, if so remove them. + if (partyMember.isOnField()) { + partyMember.hideInfo(); + partyMember.setVisible(false); + this.scene.field.remove(partyMember); + this.scene.triggerPokemonFormChange(partyMember, SpeciesFormChangeActiveTrigger, true); + } + const party = this.getParty(); // Find the first non-fainted Pokemon index above the current one - const nonFaintedIndex = party.findIndex((p, i) => i > this.partyMemberIndex && !p.isFainted()); - if (nonFaintedIndex === -1) { + const legalIndex = party.findIndex((p, i) => i > this.partyMemberIndex && p.isAllowedInBattle()); + if (legalIndex === -1) { console.error("Party Details:\n", party); - throw new Error("All available Pokemon were fainted!"); + console.error("All available Pokemon were fainted or illegal!"); + this.scene.clearPhaseQueue(); + this.scene.unshiftPhase(new GameOverPhase(this.scene)); + this.end(); + return; } - // Swaps the fainted Pokemon and the first non-fainted Pokemon in the party - [party[this.partyMemberIndex], party[nonFaintedIndex]] = [party[nonFaintedIndex], party[this.partyMemberIndex]]; + // Swaps the fainted Pokemon and the first non-fainted legal Pokemon in the party + [party[this.partyMemberIndex], party[legalIndex]] = [party[legalIndex], party[this.partyMemberIndex]]; console.warn("Swapped %s %O with %s %O", partyMember?.name, partyMember, party[0]?.name, party[0]); } @@ -1347,7 +1388,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { if (this.fieldIndex === 1) { pokemon.setFieldPosition(FieldPosition.RIGHT, 0); } else { - const availablePartyMembers = this.getParty().filter(p => !p.isFainted()).length; + const availablePartyMembers = this.getParty().filter(p => p.isAllowedInBattle()).length; pokemon.setFieldPosition(!this.scene.currentBattle.double || availablePartyMembers === 1 ? FieldPosition.CENTER : FieldPosition.LEFT); } @@ -1637,7 +1678,7 @@ export class ToggleDoublePositionPhase extends BattlePhase { const playerPokemon = this.scene.getPlayerField().find(p => p.isActive(true)); if (playerPokemon) { - playerPokemon.setFieldPosition(this.double && this.scene.getParty().filter(p => !p.isFainted()).length > 1 ? FieldPosition.LEFT : FieldPosition.CENTER, 500).then(() => { + playerPokemon.setFieldPosition(this.double && this.scene.getParty().filter(p => p.isAllowedInBattle()).length > 1 ? FieldPosition.LEFT : FieldPosition.CENTER, 500).then(() => { if (playerPokemon.getFieldIndex() === 1) { const party = this.scene.getParty(); party[1] = party[0]; @@ -1737,6 +1778,34 @@ export class TurnInitPhase extends FieldPhase { start() { super.start(); + this.scene.getPlayerField().forEach(p => { + // If this pokemon is in play and evolved into something illegal under the current challenge, force a switch + if (p.isOnField() && !p.isAllowedInBattle()) { + this.scene.queueMessage(i18next.t("challenges:illegalEvolution", {"pokemon": p.name}), null, true); + + const allowedPokemon = this.scene.getParty().filter(p => p.isAllowedInBattle()); + + if (!allowedPokemon.length) { + // If there are no longer any legal pokemon in the party, game over. + this.scene.clearPhaseQueue(); + this.scene.unshiftPhase(new GameOverPhase(this.scene)); + } else if (allowedPokemon.length >= this.scene.currentBattle.getBattlerCount() || (this.scene.currentBattle.double && !allowedPokemon[0].isActive(true))) { + // If there is at least one pokemon in the back that is legal to switch in, force a switch. + p.switchOut(false, true); + } else { + // If there are no pokemon in the back but we're not game overing, just hide the pokemon. + // This should only happen in double battles. + p.hideInfo(); + p.setVisible(false); + this.scene.field.remove(p); + this.scene.triggerPokemonFormChange(p, SpeciesFormChangeActiveTrigger, true); + } + if (allowedPokemon.length === 1 && this.scene.currentBattle.double) { + this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true)); + } + } + }); + //this.scene.pushPhase(new MoveAnimTestPhase(this.scene)); this.scene.eventTarget.dispatchEvent(new TurnInitEvent()); @@ -1771,9 +1840,15 @@ export class CommandPhase extends FieldPhase { super.start(); if (this.fieldIndex) { - const allyCommand = this.scene.currentBattle.turnCommands[this.fieldIndex - 1]; - if (allyCommand.command === Command.BALL || allyCommand.command === Command.RUN) { - this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: allyCommand.command, skip: true }; + // If we somehow are attempting to check the right pokemon but there's only one pokemon out + // Switch back to the center pokemon. This can happen rarely in double battles with mid turn switching + if (this.scene.getPlayerField().filter(p => p.isActive()).length === 1) { + this.fieldIndex = FieldPosition.CENTER; + } else { + const allyCommand = this.scene.currentBattle.turnCommands[this.fieldIndex - 1]; + if (allyCommand.command === Command.BALL || allyCommand.command === Command.RUN) { + this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: allyCommand.command, skip: true }; + } } } @@ -2348,7 +2423,7 @@ export class BattleEndPhase extends BattlePhase { } } - for (const pokemon of this.scene.getParty().filter(p => !p.isFainted())) { + for (const pokemon of this.scene.getParty().filter(p => p.isAllowedInBattle())) { applyPostBattleAbAttrs(PostBattleAbAttr, pokemon); } @@ -2708,9 +2783,10 @@ export class MoveEffectPhase extends PokemonPhase { } const overridden = new Utils.BooleanHolder(false); + const move = this.move.getMove(); // Assume single target for override - applyMoveAttrs(OverrideMoveEffectAttr, user, this.getTarget(), this.move.getMove(), overridden, this.move.virtual).then(() => { + applyMoveAttrs(OverrideMoveEffectAttr, user, this.getTarget(), move, overridden, this.move.virtual).then(() => { if (overridden.value) { return this.end(); @@ -2721,8 +2797,8 @@ export class MoveEffectPhase extends PokemonPhase { if (user.turnData.hitsLeft === undefined) { const hitCount = new Utils.IntegerHolder(1); // Assume single target for multi hit - applyMoveAttrs(MultiHitAttr, user, this.getTarget(), this.move.getMove(), hitCount); - if (this.move.getMove() instanceof AttackMove && !this.move.getMove().hasAttr(FixedDamageAttr)) { + applyMoveAttrs(MultiHitAttr, user, this.getTarget(), move, hitCount); + if (move instanceof AttackMove && !move.hasAttr(FixedDamageAttr)) { this.scene.applyModifiers(PokemonMultiHitModifier, user.isPlayer(), user, hitCount, new Utils.IntegerHolder(0)); } user.turnData.hitsLeft = user.turnData.hitCount = hitCount.value; @@ -2733,13 +2809,13 @@ export class MoveEffectPhase extends PokemonPhase { const targetHitChecks = Object.fromEntries(targets.map(p => [ p.getBattlerIndex(), this.hitCheck(p) ])); const activeTargets = targets.map(t => t.isActive(true)); - if (!activeTargets.length || (!this.move.getMove().hasAttr(VariableTargetAttr) && !this.move.getMove().isMultiTarget() && !targetHitChecks[this.targets[0]])) { + if (!activeTargets.length || (!move.hasAttr(VariableTargetAttr) && !move.isMultiTarget() && !targetHitChecks[this.targets[0]])) { user.turnData.hitCount = 1; user.turnData.hitsLeft = 1; if (activeTargets.length) { this.scene.queueMessage(getPokemonMessage(user, "'s\nattack missed!")); moveHistoryEntry.result = MoveResult.MISS; - applyMoveAttrs(MissEffectAttr, user, null, this.move.getMove()); + applyMoveAttrs(MissEffectAttr, user, null, move); } else { this.scene.queueMessage(i18next.t("battle:attackFailed")); moveHistoryEntry.result = MoveResult.FAIL; @@ -2750,7 +2826,7 @@ export class MoveEffectPhase extends PokemonPhase { const applyAttrs: Promise[] = []; // Move animation only needs one target - new MoveAnim(this.move.getMove().id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => { + new MoveAnim(move.id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => { for (const target of targets) { if (!targetHitChecks[target.getBattlerIndex()]) { user.turnData.hitCount = 1; @@ -2759,31 +2835,31 @@ export class MoveEffectPhase extends PokemonPhase { if (moveHistoryEntry.result === MoveResult.PENDING) { moveHistoryEntry.result = MoveResult.MISS; } - applyMoveAttrs(MissEffectAttr, user, null, this.move.getMove()); + applyMoveAttrs(MissEffectAttr, user, null, move); continue; } - const isProtected = !this.move.getMove().hasFlag(MoveFlags.IGNORE_PROTECT) && target.findTags(t => t instanceof ProtectedTag).find(t => target.lapseTag(t.tagType)); + const isProtected = !move.hasFlag(MoveFlags.IGNORE_PROTECT) && target.findTags(t => t instanceof ProtectedTag).find(t => target.lapseTag(t.tagType)); const firstHit = moveHistoryEntry.result !== MoveResult.SUCCESS; moveHistoryEntry.result = MoveResult.SUCCESS; - const hitResult = !isProtected ? target.apply(user, this.move) : HitResult.NO_EFFECT; + const hitResult = !isProtected ? target.apply(user, move) : HitResult.NO_EFFECT; this.scene.triggerPokemonFormChange(user, SpeciesFormChangePostMoveTrigger); applyAttrs.push(new Promise(resolve => { - applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.PRE_APPLY && (!attr.firstHitOnly || firstHit), - user, target, this.move.getMove()).then(() => { + applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.PRE_APPLY && (!attr.firstHitOnly || firstHit), + user, target, move).then(() => { if (hitResult !== HitResult.FAIL) { - const chargeEffect = !!this.move.getMove().getAttrs(ChargeAttr).find(ca => ca.usedChargeEffect(user, this.getTarget(), this.move.getMove())); + const chargeEffect = !!move.getAttrs(ChargeAttr).find(ca => ca.usedChargeEffect(user, this.getTarget(), move)); // Charge attribute with charge effect takes all effect attributes and applies them to charge stage, so ignore them if this is present - Utils.executeIf(!chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_APPLY - && (attr as MoveEffectAttr).selfTarget && (!attr.firstHitOnly || firstHit), user, target, this.move.getMove())).then(() => { + Utils.executeIf(!chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.POST_APPLY + && attr.selfTarget && (!attr.firstHitOnly || firstHit), user, target, move)).then(() => { if (hitResult !== HitResult.NO_EFFECT) { - applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_APPLY - && !(attr as MoveEffectAttr).selfTarget && (!attr.firstHitOnly || firstHit), user, target, this.move.getMove()).then(() => { + applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.POST_APPLY + && !attr.selfTarget && (!attr.firstHitOnly || firstHit), user, target, move).then(() => { if (hitResult < HitResult.NO_EFFECT) { const flinched = new Utils.BooleanHolder(false); user.scene.applyModifiers(FlinchChanceModifier, user.isPlayer(), user, flinched); @@ -2791,15 +2867,15 @@ export class MoveEffectPhase extends PokemonPhase { target.addTag(BattlerTagType.FLINCHED, undefined, this.move.moveId, user.id); } } - Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT && (!attr.firstHitOnly || firstHit), - user, target, this.move.getMove()).then(() => { - return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult).then(() => { - if (!user.isPlayer() && this.move.getMove() instanceof AttackMove) { + Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.HIT && (!attr.firstHitOnly || firstHit), + user, target, move).then(() => { + return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, move, hitResult).then(() => { + if (!user.isPlayer() && move instanceof AttackMove) { user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target); } })).then(() => { - applyPostAttackAbAttrs(PostAttackAbAttr, user, target, this.move, hitResult).then(() => { - if (this.move.getMove() instanceof AttackMove) { + applyPostAttackAbAttrs(PostAttackAbAttr, user, target, move, hitResult).then(() => { + if (move instanceof AttackMove) { this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user, target.getFieldIndex()); } resolve(); @@ -2809,7 +2885,7 @@ export class MoveEffectPhase extends PokemonPhase { ).then(() => resolve()); }); } else { - applyMoveAttrs(NoEffectAttr, user, null, this.move.getMove()).then(() => resolve()); + applyMoveAttrs(NoEffectAttr, user, null, move).then(() => resolve()); } }); } else { @@ -2819,8 +2895,8 @@ export class MoveEffectPhase extends PokemonPhase { })); } // Trigger effect which should only apply one time after all targeted effects have already applied - const postTarget = applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_TARGET, - user, null, this.move.getMove()); + const postTarget = applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.POST_TARGET, + user, null, move); if (applyAttrs.length) { // If there is a pending asynchronous move effect, do this after applyAttrs[applyAttrs.length - 1]?.then(() => postTarget); @@ -2834,6 +2910,8 @@ export class MoveEffectPhase extends PokemonPhase { } end() { + const move = this.move.getMove(); + move.type = move.defaultType; const user = this.getUserPokemon(); if (user) { if (--user.turnData.hitsLeft >= 1 && this.getTarget()?.isActive()) { @@ -3478,7 +3556,7 @@ export class DamagePhase extends PokemonPhase { this.scene.setFieldScale(0.75); this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); this.scene.currentBattle.double = true; - const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted()); + const availablePartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle()); if (availablePartyMembers.length > 1) { this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, true)); if (!availablePartyMembers[1].isOnField()) { @@ -3540,7 +3618,7 @@ export class FaintPhase extends PokemonPhase { if (pokemon.turnData?.attacksReceived?.length) { const lastAttack = pokemon.turnData.attacksReceived[0]; - applyPostFaintAbAttrs(PostFaintAbAttr, pokemon, this.scene.getPokemonById(lastAttack.sourceId), new PokemonMove(lastAttack.move), lastAttack.result); + applyPostFaintAbAttrs(PostFaintAbAttr, pokemon, this.scene.getPokemonById(lastAttack.sourceId), new PokemonMove(lastAttack.move).getMove(), lastAttack.result); } const alivePlayField = this.scene.getField(true); @@ -3560,11 +3638,11 @@ export class FaintPhase extends PokemonPhase { } if (this.player) { - const nonFaintedPartyMembers = this.scene.getParty().filter(p => !p.isFainted()); - const nonFaintedPartyMemberCount = nonFaintedPartyMembers.length; + const nonFaintedLegalPartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle()); + const nonFaintedPartyMemberCount = nonFaintedLegalPartyMembers.length; if (!nonFaintedPartyMemberCount) { this.scene.unshiftPhase(new GameOverPhase(this.scene)); - } else if (nonFaintedPartyMemberCount >= this.scene.currentBattle.getBattlerCount() || (this.scene.currentBattle.double && !nonFaintedPartyMembers[0].isActive(true))) { + } else if (nonFaintedPartyMemberCount >= this.scene.currentBattle.getBattlerCount() || (this.scene.currentBattle.double && !nonFaintedLegalPartyMembers[0].isActive(true))) { this.scene.pushPhase(new SwitchPhase(this.scene, this.fieldIndex, true, false)); } if (nonFaintedPartyMemberCount === 1 && this.scene.currentBattle.double) { @@ -3958,7 +4036,7 @@ export class GameOverPhase extends BattlePhase { this.scene.gameData.loadSession(this.scene, this.scene.sessionSlotId).then(() => { this.scene.pushPhase(new EncounterPhase(this.scene, true)); - const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted()).length; + const availablePartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle()).length; this.scene.pushPhase(new SummonPhase(this.scene, 0)); if (this.scene.currentBattle.double && availablePartyMembers > 1) { @@ -4010,6 +4088,10 @@ export class GameOverPhase extends BattlePhase { this.scene.clearPhaseQueue(); this.scene.ui.clearText(); + if (this.victory && this.scene.gameMode.isChallenge) { + this.scene.gameMode.challenges.forEach(c => this.scene.validateAchvs(ChallengeAchv, c)); + } + const clear = (endCardPhase?: EndCardPhase) => { if (newClear) { this.handleUnlocks(); @@ -4213,17 +4295,17 @@ export class SwitchPhase extends BattlePhase { super.start(); // Skip modal switch if impossible - if (this.isModal && !this.scene.getParty().filter(p => !p.isFainted() && !p.isActive(true)).length) { + if (this.isModal && !this.scene.getParty().filter(p => p.isAllowedInBattle() && !p.isActive(true)).length) { return super.end(); } // Check if there is any space still in field - if (this.isModal && this.scene.getPlayerField().filter(p => !p.isFainted() && p.isActive(true)).length >= this.scene.currentBattle.getBattlerCount()) { + if (this.isModal && this.scene.getPlayerField().filter(p => p.isAllowedInBattle() && p.isActive(true)).length >= this.scene.currentBattle.getBattlerCount()) { return super.end(); } - // Override field index to 0 in case of double battle where 2/3 remaining party members fainted at once - const fieldIndex = this.scene.currentBattle.getBattlerCount() === 1 || this.scene.getParty().filter(p => !p.isFainted()).length > 1 ? this.fieldIndex : 0; + // Override field index to 0 in case of double battle where 2/3 remaining legal party members fainted at once + const fieldIndex = this.scene.currentBattle.getBattlerCount() === 1 || this.scene.getParty().filter(p => p.isAllowedInBattle()).length > 1 ? this.fieldIndex : 0; this.scene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.FAINT_SWITCH : PartyUiMode.POST_BATTLE_SWITCH, fieldIndex, (slotIndex: integer, option: PartyOption) => { if (slotIndex >= this.scene.currentBattle.getBattlerCount() && slotIndex < 6) { @@ -4288,20 +4370,20 @@ export class ShowPartyExpBarPhase extends PlayerPartyMemberPokemonPhase { this.scene.unshiftPhase(new HidePartyExpBarPhase(this.scene)); pokemon.updateInfo(); - if (this.scene.expParty === 2) { // 2 - Skip - no level up frame nor message + if (this.scene.expParty === ExpNotification.SKIP) { this.end(); - } else if (this.scene.expParty === 1) { // 1 - Only level up - we display the level up in the small frame instead of a message + } else if (this.scene.expParty === ExpNotification.ONLY_LEVEL_UP) { if (newLevel > lastLevel) { // this means if we level up // instead of displaying the exp gain in the small frame, we display the new level // we use the same method for mode 0 & 1, by giving a parameter saying to display the exp or the level - this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, this.scene.expParty === 1, newLevel).then(() => { + this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, this.scene.expParty === ExpNotification.ONLY_LEVEL_UP, newLevel).then(() => { setTimeout(() => this.end(), 800 / Math.pow(2, this.scene.expGainsSpeed)); }); } else { this.end(); } } else if (this.scene.expGainsSpeed < 3) { - this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, this.scene.expParty === 1, newLevel).then(() => { + this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, false, newLevel).then(() => { setTimeout(() => this.end(), 500 / Math.pow(2, this.scene.expGainsSpeed)); }); } else { @@ -4348,12 +4430,12 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { const prevStats = pokemon.stats.slice(0); pokemon.calculateStats(); pokemon.updateInfo(); - if (this.scene.expParty === 0) { // 0 - default - the normal exp gain display, nothing changed + if (this.scene.expParty === ExpNotification.DEFAULT) { this.scene.playSound("level_up_fanfare"); this.scene.ui.showText(i18next.t("battle:levelUp", { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); - } else if (this.scene.expParty === 2) { // 2 - Skip - no level up frame nor message + } else if (this.scene.expParty === ExpNotification.SKIP) { this.end(); - } else { // 1 - Only level up - we display the level up in the small frame instead of a message + } else { // we still want to display the stats if activated this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()); } @@ -4909,7 +4991,8 @@ export class SelectModifierPhase extends BattlePhase { let cost: integer; switch (rowCursor) { case 0: - if (!cursor) { + switch (cursor) { + case 0: const rerollCost = this.getRerollCost(typeOptions, this.scene.lockModifierTiers); if (this.scene.money < rerollCost) { this.scene.ui.playError(); @@ -4921,20 +5004,28 @@ export class SelectModifierPhase extends BattlePhase { this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); this.scene.money -= rerollCost; this.scene.updateMoneyText(); + this.scene.animateMoneyChanged(false); this.scene.playSound("buy"); } - } else if (cursor === 1) { + break; + case 1: this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => { if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) { const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier - && (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; + && (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; const itemModifier = itemModifiers[itemIndex]; this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity); } else { this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); } }, PartyUiHandler.FilterItemMaxStacks); - } else { + break; + case 2: + this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.CHECK, -1, () => { + this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); + }); + break; + case 3: this.scene.lockModifierTiers = !this.scene.lockModifierTiers; const uiHandler = this.scene.ui.getHandler() as ModifierSelectUiHandler; uiHandler.setRerollCost(this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); @@ -4966,6 +5057,7 @@ export class SelectModifierPhase extends BattlePhase { if (success) { this.scene.money -= cost; this.scene.updateMoneyText(); + this.scene.animateMoneyChanged(false); this.scene.playSound("buy"); (this.scene.ui.getHandler() as ModifierSelectUiHandler).updateCostText(); } else { diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 3f6469904d4..7910a1d1239 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -174,13 +174,13 @@ export function initI18n(): void { de: { ...deConfig }, - pt_BR: { + "pt-BR": { ...ptBrConfig }, - zh_CN: { + "zh-CN": { ...zhCnConfig }, - zh_TW: { + "zh-TW": { ...zhTwConfig }, ko: { @@ -196,35 +196,16 @@ declare module "i18next" { interface CustomTypeOptions { defaultNS: "menu"; // Even if we don't use it, i18next requires a valid default namespace resources: { - menu: SimpleTranslationEntries; - menuUiHandler: SimpleTranslationEntries; - move: MoveTranslationEntries; - battle: SimpleTranslationEntries; - abilityTriggers: SimpleTranslationEntries; ability: AbilityTranslationEntries; - pokeball: SimpleTranslationEntries; - pokemon: SimpleTranslationEntries; - pokemonInfo: PokemonInfoTranslationEntries; - commandUiHandler: SimpleTranslationEntries; - fightUiHandler: SimpleTranslationEntries; - titles: SimpleTranslationEntries; - trainerClasses: SimpleTranslationEntries; - trainerNames: SimpleTranslationEntries; - tutorial: SimpleTranslationEntries; - starterSelectUiHandler: SimpleTranslationEntries; - splashMessages: SimpleTranslationEntries; - nature: SimpleTranslationEntries; - growth: SimpleTranslationEntries; - egg: SimpleTranslationEntries; - weather: SimpleTranslationEntries; - modifierType: ModifierTypeTranslationEntries; + abilityTriggers: SimpleTranslationEntries; + achv: AchievementTranslationEntries; + battle: SimpleTranslationEntries; battleMessageUiHandler: SimpleTranslationEntries; berry: BerryTranslationEntries; - achv: AchievementTranslationEntries; - gameStatsUiHandler: SimpleTranslationEntries; - voucher: SimpleTranslationEntries; biome: SimpleTranslationEntries; - pokemonInfoContainer: SimpleTranslationEntries; + challenges: SimpleTranslationEntries; + commandUiHandler: SimpleTranslationEntries; + PGMachv: AchievementTranslationEntries; PGMdialogue: DialogueTranslationEntries; PGMbattleSpecDialogue: SimpleTranslationEntries; PGMmiscDialogue: SimpleTranslationEntries; @@ -233,6 +214,31 @@ declare module "i18next" { PGFbattleSpecDialogue: SimpleTranslationEntries; PGFmiscDialogue: SimpleTranslationEntries; PGFdoubleBattleDialogue: DialogueTranslationEntries; + PGFachv: AchievementTranslationEntries; + egg: SimpleTranslationEntries; + fightUiHandler: SimpleTranslationEntries; + gameMode: SimpleTranslationEntries; + gameStatsUiHandler: SimpleTranslationEntries; + growth: SimpleTranslationEntries; + menu: SimpleTranslationEntries; + menuUiHandler: SimpleTranslationEntries; + modifierType: ModifierTypeTranslationEntries; + move: MoveTranslationEntries; + nature: SimpleTranslationEntries; + partyUiHandler: SimpleTranslationEntries; + pokeball: SimpleTranslationEntries; + pokemon: SimpleTranslationEntries; + pokemonInfo: PokemonInfoTranslationEntries; + pokemonInfoContainer: SimpleTranslationEntries; + saveSlotSelectUiHandler: SimpleTranslationEntries; + splashMessages: SimpleTranslationEntries; + starterSelectUiHandler: SimpleTranslationEntries; + titles: SimpleTranslationEntries; + trainerClasses: SimpleTranslationEntries; + trainerNames: SimpleTranslationEntries; + tutorial: SimpleTranslationEntries; + voucher: SimpleTranslationEntries; + weather: SimpleTranslationEntries; }; } } @@ -244,3 +250,4 @@ export function getIsInitialized(): boolean { } let isInitialized = false; + diff --git a/src/system/achv.ts b/src/system/achv.ts index f52d547a53f..f44ea2a9301 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -3,6 +3,9 @@ import BattleScene from "../battle-scene"; import { TurnHeldItemTransferModifier } from "../modifier/modifier"; import i18next from "../plugins/i18n"; import * as Utils from "../utils"; +import { PlayerGender } from "#app/data/enums/player-gender"; +import { ParseKeys } from "i18next"; +import { Challenge, SingleGenerationChallenge, SingleTypeChallenge } from "#app/data/challenge.js"; export enum AchvTier { COMMON, @@ -35,9 +38,19 @@ export class Achv { this.localizationKey = localizationKey; } - getName(): string { + /** + * Get the name of the achievement based on the gender of the player + * @param playerGender - the gender of the player + * @returns the name of the achievement localized for the player gender + */ + getName(playerGender: PlayerGender): string { + const prefix = playerGender === PlayerGender.FEMALE ?"PGF" : "PGM"; // Localization key is used to get the name of the achievement - return i18next.t(`achv:${this.localizationKey}.name`); + return i18next.t(`${prefix}achv:${this.localizationKey}.name` as ParseKeys); + } + + getDescription(): string { + return this.description; } getIconImage(): string { @@ -122,6 +135,12 @@ export class ModifierAchv extends Achv { } } +export class ChallengeAchv extends Achv { + constructor(localizationKey: string, name: string, description: string, iconImage: string, score: integer, challengeFunc: (challenge: Challenge) => boolean) { + super(localizationKey, name, description, iconImage, score, (_scene: BattleScene, args: any[]) => challengeFunc((args[0] as Challenge))); + } +} + /** * Get the description of an achievement from the localization file with all the necessary variables filled in @@ -129,87 +148,134 @@ export class ModifierAchv extends Achv { * @returns The description of the achievement */ export function getAchievementDescription(localizationKey: string): string { + // We need to get the player gender from the game data to add the correct prefix to the achievement name + let playerGender = PlayerGender.MALE; + if (this?.scene) { + playerGender = this.scene.gameData.gender; + } + let genderPrefix = "PGM"; + if (playerGender === PlayerGender.FEMALE) { + genderPrefix = "PGF"; + } + switch (localizationKey) { case "10K_MONEY": - return i18next.t("achv:MoneyAchv.description", {"moneyAmount": achvs._10K_MONEY.moneyAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:MoneyAchv.description` as ParseKeys, {"moneyAmount": achvs._10K_MONEY.moneyAmount.toLocaleString("en-US")}); case "100K_MONEY": - return i18next.t("achv:MoneyAchv.description", {"moneyAmount": achvs._100K_MONEY.moneyAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:MoneyAchv.description` as ParseKeys, {"moneyAmount": achvs._100K_MONEY.moneyAmount.toLocaleString("en-US")}); case "1M_MONEY": - return i18next.t("achv:MoneyAchv.description", {"moneyAmount": achvs._1M_MONEY.moneyAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:MoneyAchv.description` as ParseKeys, {"moneyAmount": achvs._1M_MONEY.moneyAmount.toLocaleString("en-US")}); case "10M_MONEY": - return i18next.t("achv:MoneyAchv.description", {"moneyAmount": achvs._10M_MONEY.moneyAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:MoneyAchv.description` as ParseKeys, {"moneyAmount": achvs._10M_MONEY.moneyAmount.toLocaleString("en-US")}); case "250_DMG": - return i18next.t("achv:DamageAchv.description", {"damageAmount": achvs._250_DMG.damageAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:DamageAchv.description` as ParseKeys, {"damageAmount": achvs._250_DMG.damageAmount.toLocaleString("en-US")}); case "1000_DMG": - return i18next.t("achv:DamageAchv.description", {"damageAmount": achvs._1000_DMG.damageAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:DamageAchv.description` as ParseKeys, {"damageAmount": achvs._1000_DMG.damageAmount.toLocaleString("en-US")}); case "2500_DMG": - return i18next.t("achv:DamageAchv.description", {"damageAmount": achvs._2500_DMG.damageAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:DamageAchv.description` as ParseKeys, {"damageAmount": achvs._2500_DMG.damageAmount.toLocaleString("en-US")}); case "10000_DMG": - return i18next.t("achv:DamageAchv.description", {"damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:DamageAchv.description` as ParseKeys, {"damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US")}); case "250_HEAL": - return i18next.t("achv:HealAchv.description", {"healAmount": achvs._250_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")}); + return i18next.t(`${genderPrefix}achv:HealAchv.description` as ParseKeys, {"healAmount": achvs._250_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")}); case "1000_HEAL": - return i18next.t("achv:HealAchv.description", {"healAmount": achvs._1000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")}); + return i18next.t(`${genderPrefix}achv:HealAchv.description` as ParseKeys, {"healAmount": achvs._1000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")}); case "2500_HEAL": - return i18next.t("achv:HealAchv.description", {"healAmount": achvs._2500_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")}); + return i18next.t(`${genderPrefix}achv:HealAchv.description` as ParseKeys, {"healAmount": achvs._2500_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")}); case "10000_HEAL": - return i18next.t("achv:HealAchv.description", {"healAmount": achvs._10000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")}); + return i18next.t(`${genderPrefix}achv:HealAchv.description` as ParseKeys, {"healAmount": achvs._10000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")}); case "LV_100": - return i18next.t("achv:LevelAchv.description", {"level": achvs.LV_100.level}); + return i18next.t(`${genderPrefix}achv:LevelAchv.description` as ParseKeys, {"level": achvs.LV_100.level}); case "LV_250": - return i18next.t("achv:LevelAchv.description", {"level": achvs.LV_250.level}); + return i18next.t(`${genderPrefix}achv:LevelAchv.description` as ParseKeys, {"level": achvs.LV_250.level}); case "LV_1000": - return i18next.t("achv:LevelAchv.description", {"level": achvs.LV_1000.level}); + return i18next.t(`${genderPrefix}achv:LevelAchv.description` as ParseKeys, {"level": achvs.LV_1000.level}); case "10_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {"ribbonAmount": achvs._10_RIBBONS.ribbonAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:RibbonAchv.description` as ParseKeys, {"ribbonAmount": achvs._10_RIBBONS.ribbonAmount.toLocaleString("en-US")}); case "25_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {"ribbonAmount": achvs._25_RIBBONS.ribbonAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:RibbonAchv.description` as ParseKeys, {"ribbonAmount": achvs._25_RIBBONS.ribbonAmount.toLocaleString("en-US")}); case "50_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {"ribbonAmount": achvs._50_RIBBONS.ribbonAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:RibbonAchv.description` as ParseKeys, {"ribbonAmount": achvs._50_RIBBONS.ribbonAmount.toLocaleString("en-US")}); case "75_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {"ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:RibbonAchv.description` as ParseKeys, {"ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US")}); case "100_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {"ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US")}); + return i18next.t(`${genderPrefix}achv:RibbonAchv.description` as ParseKeys, {"ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US")}); case "TRANSFER_MAX_BATTLE_STAT": - return i18next.t("achv:TRANSFER_MAX_BATTLE_STAT.description"); + return i18next.t(`${genderPrefix}achv:TRANSFER_MAX_BATTLE_STAT.description` as ParseKeys); case "MAX_FRIENDSHIP": - return i18next.t("achv:MAX_FRIENDSHIP.description"); + return i18next.t(`${genderPrefix}achv:MAX_FRIENDSHIP.description` as ParseKeys); case "MEGA_EVOLVE": - return i18next.t("achv:MEGA_EVOLVE.description"); + return i18next.t(`${genderPrefix}achv:MEGA_EVOLVE.description` as ParseKeys); case "GIGANTAMAX": - return i18next.t("achv:GIGANTAMAX.description"); + return i18next.t(`${genderPrefix}achv:GIGANTAMAX.description` as ParseKeys); case "TERASTALLIZE": - return i18next.t("achv:TERASTALLIZE.description"); + return i18next.t(`${genderPrefix}achv:TERASTALLIZE.description` as ParseKeys); case "STELLAR_TERASTALLIZE": - return i18next.t("achv:STELLAR_TERASTALLIZE.description"); + return i18next.t(`${genderPrefix}achv:STELLAR_TERASTALLIZE.description` as ParseKeys); case "SPLICE": - return i18next.t("achv:SPLICE.description"); + return i18next.t(`${genderPrefix}achv:SPLICE.description` as ParseKeys); case "MINI_BLACK_HOLE": - return i18next.t("achv:MINI_BLACK_HOLE.description"); + return i18next.t(`${genderPrefix}achv:MINI_BLACK_HOLE.description` as ParseKeys); case "CATCH_MYTHICAL": - return i18next.t("achv:CATCH_MYTHICAL.description"); + return i18next.t(`${genderPrefix}achv:CATCH_MYTHICAL.description` as ParseKeys); case "CATCH_SUB_LEGENDARY": - return i18next.t("achv:CATCH_SUB_LEGENDARY.description"); + return i18next.t(`${genderPrefix}achv:CATCH_SUB_LEGENDARY.description` as ParseKeys); case "CATCH_LEGENDARY": - return i18next.t("achv:CATCH_LEGENDARY.description"); + return i18next.t(`${genderPrefix}achv:CATCH_LEGENDARY.description` as ParseKeys); case "SEE_SHINY": - return i18next.t("achv:SEE_SHINY.description"); + return i18next.t(`${genderPrefix}achv:SEE_SHINY.description` as ParseKeys); case "SHINY_PARTY": - return i18next.t("achv:SHINY_PARTY.description"); + return i18next.t(`${genderPrefix}achv:SHINY_PARTY.description` as ParseKeys); case "HATCH_MYTHICAL": - return i18next.t("achv:HATCH_MYTHICAL.description"); + return i18next.t(`${genderPrefix}achv:HATCH_MYTHICAL.description` as ParseKeys); case "HATCH_SUB_LEGENDARY": - return i18next.t("achv:HATCH_SUB_LEGENDARY.description"); + return i18next.t(`${genderPrefix}achv:HATCH_SUB_LEGENDARY.description` as ParseKeys); case "HATCH_LEGENDARY": - return i18next.t("achv:HATCH_LEGENDARY.description"); + return i18next.t(`${genderPrefix}achv:HATCH_LEGENDARY.description` as ParseKeys); case "HATCH_SHINY": - return i18next.t("achv:HATCH_SHINY.description"); + return i18next.t(`${genderPrefix}achv:HATCH_SHINY.description` as ParseKeys); case "HIDDEN_ABILITY": - return i18next.t("achv:HIDDEN_ABILITY.description"); + return i18next.t(`${genderPrefix}achv:HIDDEN_ABILITY.description` as ParseKeys); case "PERFECT_IVS": - return i18next.t("achv:PERFECT_IVS.description"); + return i18next.t(`${genderPrefix}achv:PERFECT_IVS.description` as ParseKeys); case "CLASSIC_VICTORY": - return i18next.t("achv:CLASSIC_VICTORY.description"); + return i18next.t(`${genderPrefix}achv:CLASSIC_VICTORY.description` as ParseKeys); + case "MONO_GEN_ONE": + return i18next.t(`${genderPrefix}achv:MONO_GEN_ONE.description` as ParseKeys); + case "MONO_GEN_TWO": + return i18next.t(`${genderPrefix}achv:MONO_GEN_TWO.description` as ParseKeys); + case "MONO_GEN_THREE": + return i18next.t(`${genderPrefix}achv:MONO_GEN_THREE.description` as ParseKeys); + case "MONO_GEN_FOUR": + return i18next.t(`${genderPrefix}achv:MONO_GEN_FOUR.description` as ParseKeys); + case "MONO_GEN_FIVE": + return i18next.t(`${genderPrefix}achv:MONO_GEN_FIVE.description` as ParseKeys); + case "MONO_GEN_SIX": + return i18next.t(`${genderPrefix}achv:MONO_GEN_SIX.description` as ParseKeys); + case "MONO_GEN_SEVEN": + return i18next.t(`${genderPrefix}achv:MONO_GEN_SEVEN.description` as ParseKeys); + case "MONO_GEN_EIGHT": + return i18next.t(`${genderPrefix}achv:MONO_GEN_EIGHT.description` as ParseKeys); + case "MONO_GEN_NINE": + return i18next.t(`${genderPrefix}achv:MONO_GEN_NINE.description` as ParseKeys); + case "MONO_NORMAL": + case "MONO_FIGHTING": + case "MONO_FLYING": + case "MONO_POISON": + case "MONO_GROUND": + case "MONO_ROCK": + case "MONO_BUG": + case "MONO_GHOST": + case "MONO_STEEL": + case "MONO_FIRE": + case "MONO_WATER": + case "MONO_GRASS": + case "MONO_ELECTRIC": + case "MONO_PSYCHIC": + case "MONO_ICE": + case "MONO_DRAGON": + case "MONO_DARK": + case "MONO_FAIRY": + return i18next.t(`${genderPrefix}achv:MonoType.description` as ParseKeys, {"type": i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`)}); default: return ""; } @@ -237,36 +303,61 @@ export const achvs = { _50_RIBBONS: new RibbonAchv("50_RIBBONS","", 50, "ultra_ribbon", 50).setSecret(true), _75_RIBBONS: new RibbonAchv("75_RIBBONS","", 75, "rogue_ribbon", 75).setSecret(true), _100_RIBBONS: new RibbonAchv("100_RIBBONS","", 100, "master_ribbon", 100).setSecret(true), - TRANSFER_MAX_BATTLE_STAT: new Achv("TRANSFER_MAX_BATTLE_STAT","", "TRANSFER_MAX_BATTLE_STAT.description", "stick", 20), - MAX_FRIENDSHIP: new Achv("MAX_FRIENDSHIP", "", "MAX_FRIENDSHIP.description", "soothe_bell", 25), - MEGA_EVOLVE: new Achv("MEGA_EVOLVE", "", "MEGA_EVOLVE.description", "mega_bracelet", 50), - GIGANTAMAX: new Achv("GIGANTAMAX", "", "GIGANTAMAX.description", "dynamax_band", 50), - TERASTALLIZE: new Achv("TERASTALLIZE","", "TERASTALLIZE.description", "tera_orb", 25), - STELLAR_TERASTALLIZE: new Achv("STELLAR_TERASTALLIZE", "", "STELLAR_TERASTALLIZE.description", "stellar_tera_shard", 25).setSecret(true), - SPLICE: new Achv("SPLICE","", "SPLICE.description", "dna_splicers", 10), - MINI_BLACK_HOLE: new ModifierAchv("MINI_BLACK_HOLE","", "MINI_BLACK_HOLE.description", "mini_black_hole", 25, modifier => modifier instanceof TurnHeldItemTransferModifier).setSecret(), - CATCH_MYTHICAL: new Achv("CATCH_MYTHICAL","", "CATCH_MYTHICAL.description", "strange_ball", 50).setSecret(), - CATCH_SUB_LEGENDARY: new Achv("CATCH_SUB_LEGENDARY","", "CATCH_SUB_LEGENDARY.description", "rb", 75).setSecret(), - CATCH_LEGENDARY: new Achv("CATCH_LEGENDARY", "", "CATCH_LEGENDARY.description", "mb", 100).setSecret(), - SEE_SHINY: new Achv("SEE_SHINY", "", "SEE_SHINY.description", "pb_gold", 75), - SHINY_PARTY: new Achv("SHINY_PARTY", "", "SHINY_PARTY.description", "shiny_charm", 100).setSecret(true), - HATCH_MYTHICAL: new Achv("HATCH_MYTHICAL", "", "HATCH_MYTHICAL.description", "pair_of_tickets", 75).setSecret(), - HATCH_SUB_LEGENDARY: new Achv("HATCH_SUB_LEGENDARY","", "HATCH_SUB_LEGENDARY.description", "mystic_ticket", 100).setSecret(), - HATCH_LEGENDARY: new Achv("HATCH_LEGENDARY","", "HATCH_LEGENDARY.description", "mystic_ticket", 125).setSecret(), - HATCH_SHINY: new Achv("HATCH_SHINY","", "HATCH_SHINY.description", "golden_mystic_ticket", 100).setSecret(), - HIDDEN_ABILITY: new Achv("HIDDEN_ABILITY","", "HIDDEN_ABILITY.description", "ability_charm", 75), - PERFECT_IVS: new Achv("PERFECT_IVS","", "PERFECT_IVS.description", "blunder_policy", 100), - CLASSIC_VICTORY: new Achv("CLASSIC_VICTORY","", "CLASSIC_VICTORY.description", "relic_crown", 150), + TRANSFER_MAX_BATTLE_STAT: new Achv("TRANSFER_MAX_BATTLE_STAT","", "TRANSFER_MAX_BATTLE_STAT.description","stick", 20), + MAX_FRIENDSHIP: new Achv("MAX_FRIENDSHIP", "", "MAX_FRIENDSHIP.description","soothe_bell", 25), + MEGA_EVOLVE: new Achv("MEGA_EVOLVE", "", "MEGA_EVOLVE.description","mega_bracelet", 50), + GIGANTAMAX: new Achv("GIGANTAMAX", "", "GIGANTAMAX.description","dynamax_band", 50), + TERASTALLIZE: new Achv("TERASTALLIZE","", "TERASTALLIZE.description","tera_orb", 25), + STELLAR_TERASTALLIZE: new Achv("STELLAR_TERASTALLIZE", "", "STELLAR_TERASTALLIZE.description","stellar_tera_shard", 25).setSecret(true), + SPLICE: new Achv("SPLICE","", "SPLICE.description","dna_splicers", 10), + MINI_BLACK_HOLE: new ModifierAchv("MINI_BLACK_HOLE","", "MINI_BLACK_HOLE.description","mini_black_hole", 25, modifier => modifier instanceof TurnHeldItemTransferModifier).setSecret(), + CATCH_MYTHICAL: new Achv("CATCH_MYTHICAL","", "CATCH_MYTHICAL.description","strange_ball", 50).setSecret(), + CATCH_SUB_LEGENDARY: new Achv("CATCH_SUB_LEGENDARY","", "CATCH_SUB_LEGENDARY.description","rb", 75).setSecret(), + CATCH_LEGENDARY: new Achv("CATCH_LEGENDARY", "", "CATCH_LEGENDARY.description","mb", 100).setSecret(), + SEE_SHINY: new Achv("SEE_SHINY", "", "SEE_SHINY.description","pb_gold", 75), + SHINY_PARTY: new Achv("SHINY_PARTY", "", "SHINY_PARTY.description","shiny_charm", 100).setSecret(true), + HATCH_MYTHICAL: new Achv("HATCH_MYTHICAL", "", "HATCH_MYTHICAL.description","pair_of_tickets", 75).setSecret(), + HATCH_SUB_LEGENDARY: new Achv("HATCH_SUB_LEGENDARY","", "HATCH_SUB_LEGENDARY.description","mystic_ticket", 100).setSecret(), + HATCH_LEGENDARY: new Achv("HATCH_LEGENDARY","", "HATCH_LEGENDARY.description","mystic_ticket", 125).setSecret(), + HATCH_SHINY: new Achv("HATCH_SHINY","", "HATCH_SHINY.description","golden_mystic_ticket", 100).setSecret(), + HIDDEN_ABILITY: new Achv("HIDDEN_ABILITY","", "HIDDEN_ABILITY.description","ability_charm", 75), + PERFECT_IVS: new Achv("PERFECT_IVS","", "PERFECT_IVS.description","blunder_policy", 100), + CLASSIC_VICTORY: new Achv("CLASSIC_VICTORY","", "CLASSIC_VICTORY.description","relic_crown", 150), + MONO_GEN_ONE_VICTORY: new ChallengeAchv("MONO_GEN_ONE","", "MONO_GEN_ONE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 1), + MONO_GEN_TWO_VICTORY: new ChallengeAchv("MONO_GEN_TWO","", "MONO_GEN_TWO.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 2), + MONO_GEN_THREE_VICTORY: new ChallengeAchv("MONO_GEN_THREE","", "MONO_GEN_THREE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 3), + MONO_GEN_FOUR_VICTORY: new ChallengeAchv("MONO_GEN_FOUR","", "MONO_GEN_FOUR.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 4), + MONO_GEN_FIVE_VICTORY: new ChallengeAchv("MONO_GEN_FIVE","", "MONO_GEN_FIVE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 5), + MONO_GEN_SIX_VICTORY: new ChallengeAchv("MONO_GEN_SIX","", "MONO_GEN_SIX.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 6), + MONO_GEN_SEVEN_VICTORY: new ChallengeAchv("MONO_GEN_SEVEN","", "MONO_GEN_SEVEN.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 7), + MONO_GEN_EIGHT_VICTORY: new ChallengeAchv("MONO_GEN_EIGHT","", "MONO_GEN_EIGHT.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 8), + MONO_GEN_NINE_VICTORY: new ChallengeAchv("MONO_GEN_NINE","", "MONO_GEN_NINE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 9), + MONO_NORMAL: new ChallengeAchv("MONO_NORMAL","", "MONO_NORMAL.description", "silk_scarf", 100, c => c instanceof SingleTypeChallenge && c.value === 1), + MONO_FIGHTING: new ChallengeAchv("MONO_FIGHTING","", "MONO_FIGHTING.description", "black_belt", 100, c => c instanceof SingleTypeChallenge && c.value === 2), + MONO_FLYING: new ChallengeAchv("MONO_FLYING","", "MONO_FLYING.description", "sharp_beak", 100, c => c instanceof SingleTypeChallenge && c.value === 3), + MONO_POISON: new ChallengeAchv("MONO_POISON","", "MONO_POISON.description", "poison_barb", 100, c => c instanceof SingleTypeChallenge && c.value === 4), + MONO_GROUND: new ChallengeAchv("MONO_GROUND","", "MONO_GROUND.description", "soft_sand", 100, c => c instanceof SingleTypeChallenge && c.value === 5), + MONO_ROCK: new ChallengeAchv("MONO_ROCK","", "MONO_ROCK.description", "hard_stone", 100, c => c instanceof SingleTypeChallenge && c.value === 6), + MONO_BUG: new ChallengeAchv("MONO_BUG","", "MONO_BUG.description", "silver_powder", 100, c => c instanceof SingleTypeChallenge && c.value === 7), + MONO_GHOST: new ChallengeAchv("MONO_GHOST","", "MONO_GHOST.description", "spell_tag", 100, c => c instanceof SingleTypeChallenge && c.value === 8), + MONO_STEEL: new ChallengeAchv("MONO_STEEL","", "MONO_STEEL.description", "metal_coat", 100, c => c instanceof SingleTypeChallenge && c.value === 9), + MONO_FIRE: new ChallengeAchv("MONO_FIRE","", "MONO_FIRE.description", "charcoal", 100, c => c instanceof SingleTypeChallenge && c.value === 10), + MONO_WATER: new ChallengeAchv("MONO_WATER","", "MONO_WATER.description", "mystic_water", 100, c => c instanceof SingleTypeChallenge && c.value === 11), + MONO_GRASS: new ChallengeAchv("MONO_GRASS","", "MONO_GRASS.description", "miracle_seed", 100, c => c instanceof SingleTypeChallenge && c.value === 12), + MONO_ELECTRIC: new ChallengeAchv("MONO_ELECTRIC","", "MONO_ELECTRIC.description", "magnet", 100, c => c instanceof SingleTypeChallenge && c.value === 13), + MONO_PSYCHIC: new ChallengeAchv("MONO_PSYCHIC","", "MONO_PSYCHIC.description", "twisted_spoon", 100, c => c instanceof SingleTypeChallenge && c.value === 14), + MONO_ICE: new ChallengeAchv("MONO_ICE","", "MONO_ICE.description", "never_melt_ice", 100, c => c instanceof SingleTypeChallenge && c.value === 15), + MONO_DRAGON: new ChallengeAchv("MONO_DRAGON","", "MONO_DRAGON.description", "dragon_fang", 100, c => c instanceof SingleTypeChallenge && c.value === 16), + MONO_DARK: new ChallengeAchv("MONO_DARK","", "MONO_DARK.description", "black_glasses", 100, c => c instanceof SingleTypeChallenge && c.value === 17), + MONO_FAIRY: new ChallengeAchv("MONO_FAIRY","", "MONO_FAIRY.description", "fairy_feather", 100, c => c instanceof SingleTypeChallenge && c.value === 18), }; -{ - (function() { - const achvKeys = Object.keys(achvs); - achvKeys.forEach((a: string, i: integer) => { - achvs[a].id = a; - if (achvs[a].hasParent) { - achvs[a].parentId = achvKeys[i - 1]; - } - }); - })(); +export function initAchievements() { + const achvKeys = Object.keys(achvs); + achvKeys.forEach((a: string, i: integer) => { + achvs[a].id = a; + if (achvs[a].hasParent) { + achvs[a].parentId = achvKeys[i - 1]; + } + }); } diff --git a/src/system/challenge-data.ts b/src/system/challenge-data.ts new file mode 100644 index 00000000000..69df11dd395 --- /dev/null +++ b/src/system/challenge-data.ts @@ -0,0 +1,17 @@ +import { Challenge, copyChallenge } from "#app/data/challenge.js"; + +export default class ChallengeData { + public id: integer; + public value: integer; + public severity: integer; + + constructor(source: Challenge | any) { + this.id = source.id; + this.value = source.value; + this.severity = source.severity; + } + + toChallenge(): Challenge { + return copyChallenge(this); + } +} diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 8ed7f521507..a6070c6330f 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -9,7 +9,7 @@ import PokemonData from "./pokemon-data"; import PersistentModifierData from "./modifier-data"; import ArenaData from "./arena-data"; import { Unlockables } from "./unlockables"; -import { GameModes, gameModes } from "../game-mode"; +import { GameModes, getGameMode } from "../game-mode"; import { BattleType } from "../battle"; import TrainerData from "./trainer-data"; import { trainerConfigs } from "../data/trainer-config"; @@ -38,6 +38,7 @@ import { EnemyAttackStatusEffectChanceModifier } from "../modifier/modifier"; import { StatusEffect } from "#app/data/status-effect.js"; import { PlayerGender } from "#app/data/enums/player-gender"; import { GameDataType } from "#app/data/enums/game-data-type"; +import ChallengeData from "./challenge-data"; const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary @@ -60,13 +61,13 @@ export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): str } } -function encrypt(data: string, bypassLogin: boolean): string { +export function encrypt(data: string, bypassLogin: boolean): string { return (bypassLogin ? (data: string) => btoa(data) : (data: string) => AES.encrypt(data, saveKey))(data); } -function decrypt(data: string, bypassLogin: boolean): string { +export function decrypt(data: string, bypassLogin: boolean): string { return (bypassLogin ? (data: string) => atob(data) : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8))(data); @@ -107,6 +108,7 @@ export interface SessionSaveData { trainer: TrainerData; gameVersion: string; timestamp: integer; + challenges: ChallengeData[]; } interface Unlocks { @@ -493,7 +495,7 @@ export class GameData { }); } - private parseSystemData(dataStr: string): SystemSaveData { + parseSystemData(dataStr: string): SystemSaveData { return JSON.parse(dataStr, (k: string, v: any) => { if (k === "gameStats") { return new GameStats(v); @@ -512,7 +514,7 @@ export class GameData { }) as SystemSaveData; } - private convertSystemDataStr(dataStr: string, shorten: boolean = false): string { + convertSystemDataStr(dataStr: string, shorten: boolean = false): string { if (!shorten) { // Account for past key oversight dataStr = dataStr.replace(/\$pAttr/g, "$pa"); @@ -780,7 +782,8 @@ export class GameData { battleType: scene.currentBattle.battleType, trainer: scene.currentBattle.battleType === BattleType.TRAINER ? new TrainerData(scene.currentBattle.trainer) : null, gameVersion: scene.game.config.gameVersion, - timestamp: new Date().getTime() + timestamp: new Date().getTime(), + challenges: scene.gameMode.challenges.map(c => new ChallengeData(c)) } as SessionSaveData; } @@ -829,7 +832,10 @@ export class GameData { const initSessionFromData = async sessionData => { console.debug(sessionData); - scene.gameMode = gameModes[sessionData.gameMode || GameModes.CLASSIC]; + scene.gameMode = getGameMode(sessionData.gameMode || GameModes.CLASSIC); + if (sessionData.challenges) { + scene.gameMode.challenges = sessionData.challenges.map(c => c.toChallenge()); + } scene.setSeed(sessionData.seed || scene.game.config.seed[0]); scene.resetSeed(); @@ -1075,6 +1081,17 @@ export class GameData { return new ArenaData(v); } + if (k === "challenges") { + const ret: ChallengeData[] = []; + if (v === null) { + v = []; + } + for (const c of v) { + ret.push(new ChallengeData(c)); + } + return ret; + } + return v; }) as SessionSaveData; } diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index 75fc8185c89..eb2b016b61e 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -64,9 +64,11 @@ export const SettingKeys = { Sprite_Set: "SPRITE_SET", Fusion_Palette_Swaps: "FUSION_PALETTE_SWAPS", Player_Gender: "PLAYER_GENDER", + Type_Hints: "TYPE_HINTS", Master_Volume: "MASTER_VOLUME", BGM_Volume: "BGM_VOLUME", - SE_Volume: "SE_VOLUME" + SE_Volume: "SE_VOLUME", + Music_Preference: "MUSIC_PREFERENCE" }; /** @@ -267,6 +269,13 @@ export const Setting: Array = [ default: 0, type: SettingType.DISPLAY }, + { + key: SettingKeys.Type_Hints, + label: "Type hints", + options: OFF_ON, + default: 0, + type: SettingType.DISPLAY + }, { key: SettingKeys.Master_Volume, label: "Master Volume", @@ -287,6 +296,14 @@ export const Setting: Array = [ options: VOLUME_OPTIONS, default: 10, type: SettingType.AUDIO + }, + { + key: SettingKeys.Music_Preference, + label: "Music Preference", + options: ["Consistent", "Mixed"], + default: 0, + type: SettingType.AUDIO, + requireReload: true } ]; @@ -335,6 +352,9 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): scene.seVolume = value ? parseInt(Setting[index].options[value]) * 0.01 : 0; scene.updateSoundVolume(); break; + case SettingKeys.Music_Preference: + scene.musicPreference = value; + break; case SettingKeys.Damage_Numbers: scene.damageNumbersMode = value; break; @@ -435,6 +455,9 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): case SettingKeys.Vibration: scene.enableVibration = Setting[index].options[value] !== "Disabled" && hasTouchscreen(); break; + case SettingKeys.Type_Hints: + scene.typeHints = Setting[index].options[value] === "On"; + break; case SettingKeys.Language: if (value) { if (scene.ui) { @@ -480,15 +503,15 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): }, { label: "Português (BR)", - handler: () => changeLocaleHandler("pt_BR") + handler: () => changeLocaleHandler("pt-BR") }, { label: "简体中文", - handler: () => changeLocaleHandler("zh_CN") + handler: () => changeLocaleHandler("zh-CN") }, { label: "繁體中文", - handler: () => changeLocaleHandler("zh_TW") + handler: () => changeLocaleHandler("zh-TW") }, { label: "한국어", diff --git a/src/system/unlockables.ts b/src/system/unlockables.ts index f94e29ff039..d8e7d97edf6 100644 --- a/src/system/unlockables.ts +++ b/src/system/unlockables.ts @@ -1,4 +1,4 @@ -import { GameModes, gameModes } from "../game-mode"; +import { GameMode, GameModes } from "../game-mode"; export enum Unlockables { ENDLESS_MODE, @@ -9,10 +9,10 @@ export enum Unlockables { export function getUnlockableName(unlockable: Unlockables) { switch (unlockable) { case Unlockables.ENDLESS_MODE: - return `${gameModes[GameModes.ENDLESS].getName()} Mode`; + return `${GameMode.getModeName(GameModes.ENDLESS)} Mode`; case Unlockables.MINI_BLACK_HOLE: return "Mini Black Hole"; case Unlockables.SPLICED_ENDLESS_MODE: - return `${gameModes[GameModes.SPLICED_ENDLESS].getName()} Mode`; + return `${GameMode.getModeName(GameModes.SPLICED_ENDLESS)} Mode`; } } diff --git a/src/system/voucher.ts b/src/system/voucher.ts index 9381dd650f8..f5c6a5eeacf 100644 --- a/src/system/voucher.ts +++ b/src/system/voucher.ts @@ -2,6 +2,7 @@ import BattleScene from "../battle-scene"; import { TrainerType } from "../data/enums/trainer-type"; import i18next from "../plugins/i18n"; import { Achv, AchvTier, achvs, getAchievementDescription } from "./achv"; +import { PlayerGender } from "#app/data/enums/player-gender"; export enum VoucherType { REGULAR, @@ -27,7 +28,12 @@ export class Voucher { return !this.conditionFunc || this.conditionFunc(scene, args); } - getName(): string { + /** + * Get the name of the voucher + * @param playerGender - this is ignored here. It's only there to match the signature of the function in the Achv class + * @returns the name of the voucher + */ + getName(playerGender: PlayerGender): string { return getVoucherTypeName(this.voucherType); } @@ -83,41 +89,40 @@ export const vouchers: Vouchers = {}; const voucherAchvs: Achv[] = [ achvs.CLASSIC_VICTORY ]; -{ - (function() { - import("../data/trainer-config").then(tc => { - const trainerConfigs = tc.trainerConfigs; +export function initVouchers() { + import("../data/trainer-config").then(tc => { + const trainerConfigs = tc.trainerConfigs; - for (const achv of voucherAchvs) { - const voucherType = achv.score >= 150 - ? VoucherType.GOLDEN - : achv.score >= 100 - ? VoucherType.PREMIUM - : achv.score >= 75 - ? VoucherType.PLUS - : VoucherType.REGULAR; - vouchers[achv.id] = new Voucher(voucherType, getAchievementDescription(achv.localizationKey)); - } + for (const achv of voucherAchvs) { + const voucherType = achv.score >= 150 + ? VoucherType.GOLDEN + : achv.score >= 100 + ? VoucherType.PREMIUM + : achv.score >= 75 + ? VoucherType.PLUS + : VoucherType.REGULAR; + vouchers[achv.id] = new Voucher(voucherType, getAchievementDescription(achv.localizationKey)); + } - const bossTrainerTypes = Object.keys(trainerConfigs) - .filter(tt => trainerConfigs[tt].isBoss && trainerConfigs[tt].getDerivedType() !== TrainerType.RIVAL); + const bossTrainerTypes = Object.keys(trainerConfigs) + .filter(tt => trainerConfigs[tt].isBoss && trainerConfigs[tt].getDerivedType() !== TrainerType.RIVAL); - for (const trainerType of bossTrainerTypes) { - const voucherType = trainerConfigs[trainerType].moneyMultiplier < 10 - ? VoucherType.PLUS - : VoucherType.PREMIUM; - const key = TrainerType[trainerType]; - const trainerName = trainerConfigs[trainerType].name; - vouchers[key] = new Voucher( - voucherType, - i18next.t("voucher:defeatTrainer", { trainerName }) - ); - } - - const voucherKeys = Object.keys(vouchers); - for (const k of voucherKeys) { - vouchers[k].id = k; - } - }); - })(); + for (const trainerType of bossTrainerTypes) { + const voucherType = trainerConfigs[trainerType].moneyMultiplier < 10 + ? VoucherType.PLUS + : VoucherType.PREMIUM; + const key = TrainerType[trainerType]; + const trainerName = trainerConfigs[trainerType].name; + const trainer = trainerConfigs[trainerType]; + const title = trainer.title ? ` (${trainer.title})` : ""; + vouchers[key] = new Voucher( + voucherType, + `${i18next.t("voucher:defeatTrainer", { trainerName })} ${title}`, + ); + } + const voucherKeys = Object.keys(vouchers); + for (const k of voucherKeys) { + vouchers[k].id = k; + } + }); } diff --git a/src/test/abilities/intimidate.test.ts b/src/test/abilities/intimidate.test.ts new file mode 100644 index 00000000000..b8a1d65088f --- /dev/null +++ b/src/test/abilities/intimidate.test.ts @@ -0,0 +1,83 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#app/data/enums/abilities"; +import {Species} from "#app/data/enums/species"; +import { + CheckSwitchPhase, CommandPhase, MessagePhase, + PostSummonPhase, + ShinySparklePhase, + ShowAbilityPhase, + StatChangePhase, + SummonPhase, + ToggleDoublePositionPhase, TurnInitPhase +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {BattleStat} from "#app/data/battle-stat"; + + +describe("Abilities - Intimidate", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTIMIDATE); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTIMIDATE); + }); + + it("INTIMIDATE", async() => { + await game.runToSummon([ + Species.MIGHTYENA, + Species.MIGHTYENA, + ]); + await game.phaseInterceptor.run(PostSummonPhase); + + + expect(game.scene.getParty()[0].summonData).not.toBeUndefined(); + let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; + expect(battleStatsPokemon[BattleStat.ATK]).toBe(0); + await game.phaseInterceptor.run(ShowAbilityPhase); + await game.phaseInterceptor.run(StatChangePhase); + battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; + expect(battleStatsPokemon[BattleStat.ATK]).toBe(-1); + + + await game.phaseInterceptor.run(SummonPhase); + await game.phaseInterceptor.run(ShinySparklePhase, () => game.isCurrentPhase(ToggleDoublePositionPhase)); + await game.phaseInterceptor.run(ToggleDoublePositionPhase); + game.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => { + game.setMode(Mode.MESSAGE); + game.endPhase(); + }); + await game.phaseInterceptor.run(CheckSwitchPhase); + await game.phaseInterceptor.run(PostSummonPhase); + + + let battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; + expect(battleStatsOpponent[BattleStat.ATK]).toBe(0); + await game.phaseInterceptor.run(ShowAbilityPhase); + game.scene.moveAnimations = null; // Mandatory to avoid crash + await game.phaseInterceptor.run(StatChangePhase); + battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; + expect(battleStatsOpponent[BattleStat.ATK]).toBe(-1); + + + await game.phaseInterceptor.run(MessagePhase); + await game.phaseInterceptor.run(TurnInitPhase); + await game.phaseInterceptor.run(CommandPhase); + }, 20000); +}); diff --git a/src/test/abilities/intrepid_sword.test.ts b/src/test/abilities/intrepid_sword.test.ts new file mode 100644 index 00000000000..da2beb9c029 --- /dev/null +++ b/src/test/abilities/intrepid_sword.test.ts @@ -0,0 +1,65 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#app/data/enums/abilities"; +import {Species} from "#app/data/enums/species"; +import { + MessagePhase, + PostSummonPhase, + ShowAbilityPhase, + StatChangePhase, + ToggleDoublePositionPhase +} from "#app/phases"; +import {BattleStat} from "#app/data/battle-stat"; + + +describe("Abilities - Intrepid Sword", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ZACIAN); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTREPID_SWORD); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTREPID_SWORD); + }); + + it("INTREPID SWORD on player", async() => { + await game.runToSummon([ + Species.ZACIAN, + ]); + await game.phaseInterceptor.runFrom(PostSummonPhase).to(PostSummonPhase); + expect(game.scene.getParty()[0].summonData).not.toBeUndefined(); + let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; + expect(battleStatsPokemon[BattleStat.ATK]).toBe(0); + await game.phaseInterceptor.run(ShowAbilityPhase); + await game.phaseInterceptor.run(StatChangePhase); + battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; + expect(battleStatsPokemon[BattleStat.ATK]).toBe(1); + }, 20000); + + it("INTREPID SWORD on opponent", async() => { + await game.runToSummon([ + Species.ZACIAN, + ]); + let battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; + expect(battleStatsOpponent[BattleStat.ATK]).toBe(0); + await game.phaseInterceptor.runFrom(PostSummonPhase).to(ToggleDoublePositionPhase); + await game.phaseInterceptor.run(StatChangePhase); + await game.phaseInterceptor.run(MessagePhase); + battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; + expect(battleStatsOpponent[BattleStat.ATK]).toBe(1); + }, 20000); +}); diff --git a/src/test/abilities/moxie.test.ts b/src/test/abilities/moxie.test.ts new file mode 100644 index 00000000000..ed27c670c87 --- /dev/null +++ b/src/test/abilities/moxie.test.ts @@ -0,0 +1,67 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#app/data/enums/abilities"; +import {Species} from "#app/data/enums/species"; +import { + CommandPhase, + EnemyCommandPhase, + VictoryPhase +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {Stat} from "#app/data/pokemon-stat"; +import {Moves} from "#app/data/enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Command} from "#app/ui/command-ui-handler"; +import {BattleStat} from "#app/data/battle-stat"; + + +describe("Abilities - Moxie", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const moveToUse = Moves.AERIAL_ACE; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + it("MOXIE", async() => { + const moveToUse = Moves.AERIAL_ACE; + await game.startBattle([ + Species.MIGHTYENA, + Species.MIGHTYENA, + ]); + + let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; + expect(battleStatsPokemon[Stat.ATK]).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(VictoryPhase); + battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; + expect(battleStatsPokemon[BattleStat.ATK]).toBe(1); + }, 20000); +}); diff --git a/src/test/achievement.test.ts b/src/test/achievement.test.ts deleted file mode 100644 index c33707cf5b2..00000000000 --- a/src/test/achievement.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { MoneyAchv } from "#app/system/achv"; -import { describe, expect, it } from "vitest"; - -describe("check some Achievement related stuff", () => { - it ("should check Achievement creation", () => { - const ach = new MoneyAchv("", "Achievement", 1000, null, 100); - expect(ach.name).toBe("Achievement"); - }); -}); diff --git a/src/test/achievements/achievement.test.ts b/src/test/achievements/achievement.test.ts new file mode 100644 index 00000000000..f24529187c6 --- /dev/null +++ b/src/test/achievements/achievement.test.ts @@ -0,0 +1,274 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import {MoneyAchv, Achv, AchvTier, RibbonAchv, DamageAchv, HealAchv, LevelAchv, ModifierAchv, achvs} from "#app/system/achv"; +import BattleScene from "../../battle-scene"; +import { IntegerHolder, NumberHolder } from "#app/utils.js"; +import { TurnHeldItemTransferModifier } from "#app/modifier/modifier.js"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; + +describe("check some Achievement related stuff", () => { + it ("should check Achievement creation", () => { + const ach = new MoneyAchv("", "Achievement", 1000, null, 100); + expect(ach.name).toBe("Achievement"); + }); +}); + + +describe("Achv", () => { + let achv: Achv; + + beforeEach(() => { + achv = new Achv("", "Test Achievement", "This is a test achievement", "test_icon", 10); + }); + + it("should have the correct name", () => { + expect(achv.getDescription()).toBe("This is a test achievement"); + }); + + it("should have the correct icon image", () => { + expect(achv.getIconImage()).toBe("test_icon"); + }); + + it("should set the achievement as secret", () => { + achv.setSecret(); + expect(achv.secret).toBe(true); + expect(achv.hasParent).toBe(false); + + achv.setSecret(true); + expect(achv.secret).toBe(true); + expect(achv.hasParent).toBe(true); + + achv.setSecret(false); + expect(achv.secret).toBe(true); + expect(achv.hasParent).toBe(false); + }); + + it("should return the correct tier based on the score", () => { + const achv1 = new Achv("", "Test Achievement 1", "Test Description", "test_icon", 10); + const achv2 = new Achv("", "Test Achievement 2", "Test Description", "test_icon", 25); + const achv3 = new Achv("", "Test Achievement 3", "Test Description", "test_icon", 50); + const achv4 = new Achv("", "Test Achievement 4", "Test Description", "test_icon", 75); + const achv5 = new Achv("", "Test Achievement 5", "Test Description", "test_icon", 100); + + expect(achv1.getTier()).toBe(AchvTier.COMMON); + expect(achv2.getTier()).toBe(AchvTier.GREAT); + expect(achv3.getTier()).toBe(AchvTier.ULTRA); + expect(achv4.getTier()).toBe(AchvTier.ROGUE); + expect(achv5.getTier()).toBe(AchvTier.MASTER); + }); + + it("should validate the achievement based on the condition function", () => { + const conditionFunc = jest.fn((scene: BattleScene, args: any[]) => args[0] === 10); + const achv = new Achv("", "Test Achievement", "Test Description", "test_icon", 10, conditionFunc); + + expect(achv.validate(new BattleScene(), [5])).toBe(false); + expect(achv.validate(new BattleScene(), [10])).toBe(true); + expect(conditionFunc).toHaveBeenCalledTimes(2); + }); +}); + +describe("MoneyAchv", () => { + it("should create an instance of MoneyAchv", () => { + const moneyAchv = new MoneyAchv("", "Test Money Achievement", 10000, "money_icon", 10); + expect(moneyAchv).toBeInstanceOf(MoneyAchv); + expect(moneyAchv instanceof Achv).toBe(true); + }); + + it("should validate the achievement based on the money amount", () => { + const moneyAchv = new MoneyAchv("", "Test Money Achievement", 10000, "money_icon", 10); + const scene = new BattleScene(); + scene.money = 5000; + + expect(moneyAchv.validate(scene, [])).toBe(false); + + scene.money = 15000; + expect(moneyAchv.validate(scene, [])).toBe(true); + }); +}); + +describe("RibbonAchv", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + let scene: BattleScene; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([]); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([]); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + game = new GameManager(phaserGame); + scene = game.scene; + }); + + it("should create an instance of RibbonAchv", () => { + const ribbonAchv = new RibbonAchv("", "Test Ribbon Achievement", 10, "ribbon_icon", 10); + expect(ribbonAchv).toBeInstanceOf(RibbonAchv); + expect(ribbonAchv instanceof Achv).toBe(true); + }); + + it("should validate the achievement based on the ribbon amount", () => { + const ribbonAchv = new RibbonAchv("", "Test Ribbon Achievement", 10, "ribbon_icon", 10); + scene.gameData.gameStats.ribbonsOwned = 5; + + expect(ribbonAchv.validate(scene, [])).toBe(false); + + scene.gameData.gameStats.ribbonsOwned = 15; + expect(ribbonAchv.validate(scene, [])).toBe(true); + }); +}); + +describe("DamageAchv", () => { + it("should create an instance of DamageAchv", () => { + const damageAchv = new DamageAchv("", "Test Damage Achievement", 250, "damage_icon", 10); + expect(damageAchv).toBeInstanceOf(DamageAchv); + expect(damageAchv instanceof Achv).toBe(true); + }); + + it("should validate the achievement based on the damage amount", () => { + const damageAchv = new DamageAchv("", "Test Damage Achievement", 250, "damage_icon", 10); + const scene = new BattleScene(); + const numberHolder = new NumberHolder(200); + + expect(damageAchv.validate(scene, [numberHolder])).toBe(false); + + numberHolder.value = 300; + expect(damageAchv.validate(scene, [numberHolder])).toBe(true); + }); +}); + +describe("HealAchv", () => { + it("should create an instance of HealAchv", () => { + const healAchv = new HealAchv("", "Test Heal Achievement", 250, "heal_icon", 10); + expect(healAchv).toBeInstanceOf(HealAchv); + expect(healAchv instanceof Achv).toBe(true); + }); + + it("should validate the achievement based on the heal amount", () => { + const healAchv = new HealAchv("", "Test Heal Achievement", 250, "heal_icon", 10); + const scene = new BattleScene(); + const numberHolder = new NumberHolder(200); + + expect(healAchv.validate(scene, [numberHolder])).toBe(false); + + numberHolder.value = 300; + expect(healAchv.validate(scene, [numberHolder])).toBe(true); + }); +}); + +describe("LevelAchv", () => { + it("should create an instance of LevelAchv", () => { + const levelAchv = new LevelAchv("", "Test Level Achievement", 100, "level_icon", 10); + expect(levelAchv).toBeInstanceOf(LevelAchv); + expect(levelAchv instanceof Achv).toBe(true); + }); + + it("should validate the achievement based on the level", () => { + const levelAchv = new LevelAchv("", "Test Level Achievement", 100, "level_icon", 10); + const scene = new BattleScene(); + const integerHolder = new IntegerHolder(50); + + expect(levelAchv.validate(scene, [integerHolder])).toBe(false); + + integerHolder.value = 150; + expect(levelAchv.validate(scene, [integerHolder])).toBe(true); + }); +}); + +describe("ModifierAchv", () => { + it("should create an instance of ModifierAchv", () => { + const modifierAchv = new ModifierAchv("", "Test Modifier Achievement", "Test Description", "modifier_icon", 10, () => true); + expect(modifierAchv).toBeInstanceOf(ModifierAchv); + expect(modifierAchv instanceof Achv).toBe(true); + }); + + it("should validate the achievement based on the modifier function", () => { + const modifierAchv = new ModifierAchv("", "Test Modifier Achievement", "Test Description", "modifier_icon", 10, () => true); + const scene = new BattleScene(); + const modifier = new TurnHeldItemTransferModifier(null, 3, 1); + + expect(modifierAchv.validate(scene, [modifier])).toBe(true); + }); +}); + +describe("achvs", () => { + it("should contain the predefined achievements", () => { + expect(achvs._10K_MONEY).toBeInstanceOf(MoneyAchv); + expect(achvs._100K_MONEY).toBeInstanceOf(MoneyAchv); + expect(achvs._1M_MONEY).toBeInstanceOf(MoneyAchv); + expect(achvs._10M_MONEY).toBeInstanceOf(MoneyAchv); + expect(achvs._250_DMG).toBeInstanceOf(DamageAchv); + expect(achvs._1000_DMG).toBeInstanceOf(DamageAchv); + expect(achvs._2500_DMG).toBeInstanceOf(DamageAchv); + expect(achvs._10000_DMG).toBeInstanceOf(DamageAchv); + expect(achvs._250_HEAL).toBeInstanceOf(HealAchv); + expect(achvs._1000_HEAL).toBeInstanceOf(HealAchv); + expect(achvs._2500_HEAL).toBeInstanceOf(HealAchv); + expect(achvs._10000_HEAL).toBeInstanceOf(HealAchv); + expect(achvs.LV_100).toBeInstanceOf(LevelAchv); + expect(achvs.LV_250).toBeInstanceOf(LevelAchv); + expect(achvs.LV_1000).toBeInstanceOf(LevelAchv); + expect(achvs._10_RIBBONS).toBeInstanceOf(RibbonAchv); + expect(achvs._25_RIBBONS).toBeInstanceOf(RibbonAchv); + expect(achvs._50_RIBBONS).toBeInstanceOf(RibbonAchv); + expect(achvs._75_RIBBONS).toBeInstanceOf(RibbonAchv); + expect(achvs._100_RIBBONS).toBeInstanceOf(RibbonAchv); + expect(achvs.TRANSFER_MAX_BATTLE_STAT).toBeInstanceOf(Achv); + expect(achvs.MAX_FRIENDSHIP).toBeInstanceOf(Achv); + expect(achvs.MEGA_EVOLVE).toBeInstanceOf(Achv); + expect(achvs.GIGANTAMAX).toBeInstanceOf(Achv); + expect(achvs.TERASTALLIZE).toBeInstanceOf(Achv); + expect(achvs.STELLAR_TERASTALLIZE).toBeInstanceOf(Achv); + expect(achvs.SPLICE).toBeInstanceOf(Achv); + expect(achvs.MINI_BLACK_HOLE).toBeInstanceOf(ModifierAchv); + expect(achvs.CATCH_MYTHICAL).toBeInstanceOf(Achv); + expect(achvs.CATCH_SUB_LEGENDARY).toBeInstanceOf(Achv); + expect(achvs.CATCH_LEGENDARY).toBeInstanceOf(Achv); + expect(achvs.SEE_SHINY).toBeInstanceOf(Achv); + expect(achvs.SHINY_PARTY).toBeInstanceOf(Achv); + expect(achvs.HATCH_MYTHICAL).toBeInstanceOf(Achv); + expect(achvs.HATCH_SUB_LEGENDARY).toBeInstanceOf(Achv); + expect(achvs.HATCH_LEGENDARY).toBeInstanceOf(Achv); + expect(achvs.HATCH_SHINY).toBeInstanceOf(Achv); + expect(achvs.HIDDEN_ABILITY).toBeInstanceOf(Achv); + expect(achvs.PERFECT_IVS).toBeInstanceOf(Achv); + expect(achvs.CLASSIC_VICTORY).toBeInstanceOf(Achv); + }); + + it("should initialize the achievements with IDs and parent IDs", () => { + + expect(achvs._10K_MONEY.id).toBe("_10K_MONEY"); + expect(achvs._10K_MONEY.hasParent).toBe(undefined); + expect(achvs._100K_MONEY.id).toBe("_100K_MONEY"); + expect(achvs._100K_MONEY.hasParent).toBe(true); + expect(achvs._100K_MONEY.parentId).toBe("_10K_MONEY"); + expect(achvs._1M_MONEY.id).toBe("_1M_MONEY"); + expect(achvs._1M_MONEY.hasParent).toBe(true); + expect(achvs._1M_MONEY.parentId).toBe("_100K_MONEY"); + expect(achvs._10M_MONEY.id).toBe("_10M_MONEY"); + expect(achvs._10M_MONEY.hasParent).toBe(true); + expect(achvs._10M_MONEY.parentId).toBe("_1M_MONEY"); + expect(achvs.LV_100.id).toBe("LV_100"); + expect(achvs.LV_100.hasParent).toBe(false); + expect(achvs.LV_250.id).toBe("LV_250"); + expect(achvs.LV_250.hasParent).toBe(true); + expect(achvs.LV_250.parentId).toBe("LV_100"); + expect(achvs.LV_1000.id).toBe("LV_1000"); + expect(achvs.LV_1000.hasParent).toBe(true); + expect(achvs.LV_1000.parentId).toBe("LV_250"); + }); +}); diff --git a/src/test/battle/battle-order.test.ts b/src/test/battle/battle-order.test.ts new file mode 100644 index 00000000000..7ace7dae224 --- /dev/null +++ b/src/test/battle/battle-order.test.ts @@ -0,0 +1,212 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#app/data/enums/abilities"; +import {Species} from "#app/data/enums/species"; +import { + CommandPhase, EnemyCommandPhase, SelectTargetPhase, + TurnStartPhase +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Moves} from "#app/data/enums/moves"; +import {Command} from "#app/ui/command-ui-handler"; +import {Stat} from "#app/data/pokemon-stat"; +import TargetSelectUiHandler from "#app/ui/target-select-ui-handler"; +import {Button} from "#app/enums/buttons"; + + +describe("Battle order", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + }); + + it("opponent faster than player 50 vs 150", async() => { + await game.startBattle([ + Species.BULBASAUR, + ]); + game.scene.getParty()[0].stats[Stat.SPD] = 50; + game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 150; + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.run(EnemyCommandPhase); + const phase = game.scene.getCurrentPhase() as TurnStartPhase; + const order = phase.getOrder(); + expect(order[0]).toBe(2); + expect(order[1]).toBe(0); + }, 20000); + + it("Player faster than opponent 150 vs 50", async() => { + await game.startBattle([ + Species.BULBASAUR, + ]); + game.scene.getParty()[0].stats[Stat.SPD] = 150; + game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 50; + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.run(EnemyCommandPhase); + const phase = game.scene.getCurrentPhase() as TurnStartPhase; + const order = phase.getOrder(); + expect(order[0]).toBe(0); + expect(order[1]).toBe(2); + }, 20000); + + it("double - both opponents faster than player 50/50 vs 150/150", async() => { + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + await game.startBattle([ + Species.BULBASAUR, + Species.BLASTOISE, + ]); + game.scene.getParty()[0].stats[Stat.SPD] = 50; + game.scene.getParty()[1].stats[Stat.SPD] = 50; + game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 150; + game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150; + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); + const phase = game.scene.getCurrentPhase() as TurnStartPhase; + const order = phase.getOrder(); + expect(order.indexOf(0)).toBeGreaterThan(order.indexOf(2)); + expect(order.indexOf(0)).toBeGreaterThan(order.indexOf(3)); + expect(order.indexOf(1)).toBeGreaterThan(order.indexOf(2)); + expect(order.indexOf(1)).toBeGreaterThan(order.indexOf(3)); + }, 20000); + + it("double - speed tie except 1 - 100/100 vs 100/150", async() => { + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + await game.startBattle([ + Species.BULBASAUR, + Species.BLASTOISE, + ]); + game.scene.getParty()[0].stats[Stat.SPD] = 100; + game.scene.getParty()[1].stats[Stat.SPD] = 100; + game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 100; + game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150; + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); + const phase = game.scene.getCurrentPhase() as TurnStartPhase; + const order = phase.getOrder(); + expect(order.indexOf(3)).toBeLessThan(order.indexOf(0)); + expect(order.indexOf(3)).toBeLessThan(order.indexOf(1)); + expect(order.indexOf(3)).toBeLessThan(order.indexOf(2)); + }, 20000); + + it("double - speed tie 100/150 vs 100/150", async() => { + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + await game.startBattle([ + Species.BULBASAUR, + Species.BLASTOISE, + ]); + game.scene.getParty()[0].stats[Stat.SPD] = 100; + game.scene.getParty()[1].stats[Stat.SPD] = 150; + game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 100; + game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150; + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); + const phase = game.scene.getCurrentPhase() as TurnStartPhase; + const order = phase.getOrder(); + expect(order.indexOf(1)).toBeLessThan(order.indexOf(0)); + expect(order.indexOf(1)).toBeLessThan(order.indexOf(2)); + expect(order.indexOf(3)).toBeLessThan(order.indexOf(0)); + expect(order.indexOf(3)).toBeLessThan(order.indexOf(2)); + }, 20000); +}); diff --git a/src/test/battle/battle.test.ts b/src/test/battle/battle.test.ts new file mode 100644 index 00000000000..28f98d936ce --- /dev/null +++ b/src/test/battle/battle.test.ts @@ -0,0 +1,263 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import {generateStarter, getMovePosition,} from "#app/test/utils/gameManagerUtils"; +import {Mode} from "#app/ui/ui"; +import {GameModes} from "#app/game-mode"; +import {Species} from "#app/data/enums/species"; +import * as overrides from "../../overrides"; +import {Command} from "#app/ui/command-ui-handler"; +import { + CommandPhase, + EncounterPhase, + EnemyCommandPhase, + LoginPhase, + SelectGenderPhase, + SelectModifierPhase, + SelectStarterPhase, + SummonPhase, + TitlePhase, + TurnInitPhase, +} from "#app/phases"; +import {Moves} from "#app/data/enums/moves"; +import GameManager from "#app/test/utils/gameManager"; +import Phaser from "phaser"; +import {allSpecies} from "#app/data/pokemon-species"; +import {PlayerGender} from "#app/data/enums/player-gender"; +import { getGameMode } from "#app/game-mode.js"; +import {Abilities} from "#app/data/enums/abilities"; + +describe("Test Battle Phase", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + }); + + it("test phase interceptor with prompt", async() => { + await game.phaseInterceptor.run(LoginPhase); + + game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { + game.scene.gameData.gender = PlayerGender.MALE; + game.endPhase(); + }); + + await game.phaseInterceptor.run(SelectGenderPhase); + + await game.phaseInterceptor.run(TitlePhase); + await game.waitMode(Mode.TITLE); + + + expect(game.scene.ui?.getMode()).toBe(Mode.TITLE); + expect(game.scene.gameData.gender).toBe(PlayerGender.MALE); + }, 20000); + + it("test phase interceptor with prompt with preparation for a future prompt", async() => { + await game.phaseInterceptor.run(LoginPhase); + + game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { + game.scene.gameData.gender = PlayerGender.MALE; + game.endPhase(); + }); + + game.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => { + game.setMode(Mode.MESSAGE); + game.endPhase(); + }); + await game.phaseInterceptor.run(SelectGenderPhase); + + await game.phaseInterceptor.run(TitlePhase); + await game.waitMode(Mode.TITLE); + + + expect(game.scene.ui?.getMode()).toBe(Mode.TITLE); + expect(game.scene.gameData.gender).toBe(PlayerGender.MALE); + }, 20000); + + it("newGame one-liner", async() => { + await game.startBattle(); + expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND); + expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name); + }, 20000); + + it("do attack wave 3 - single battle - regular - OHKO", async() => { + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + await game.startBattle(); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase); + expect(game.scene.ui?.getMode()).toBe(Mode.MODIFIER_SELECT); + expect(game.scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name); + }, 20000); + + it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async() => { + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP]); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + await game.startBattle(); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase); + }, 20000); + + it("load 100% data file", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + }, 20000); + + it("start battle with selected team", async() => { + await game.startBattle([ + Species.CHARIZARD, + Species.CHANSEY, + Species.MEW + ]); + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.CHARIZARD); + expect(game.scene.getParty()[1].species.speciesId).toBe(Species.CHANSEY); + expect(game.scene.getParty()[2].species.speciesId).toBe(Species.MEW); + }, 20000); + + it("test remove random battle seed int", async() => { + for (let i=0; i<10; i++) { + const rand = game.scene.randBattleSeedInt(15); + expect(rand).toBe(14); + } + }); + + it("wrong phase", async() => { + await game.phaseInterceptor.run(LoginPhase); + await game.phaseInterceptor.run(LoginPhase).catch((e) => { + expect(e).toBe("Wrong phase: this is SelectGenderPhase and not LoginPhase"); + }); + }, 20000); + + it("wrong phase but skip", async() => { + await game.phaseInterceptor.run(LoginPhase); + await game.phaseInterceptor.run(LoginPhase, () => game.isCurrentPhase(SelectGenderPhase)); + }, 20000); + + it("good run", async() => { + await game.phaseInterceptor.run(LoginPhase); + game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { + game.scene.gameData.gender = PlayerGender.MALE; + game.endPhase(); + }, () => game.isCurrentPhase(TitlePhase)); + await game.phaseInterceptor.run(SelectGenderPhase, () => game.isCurrentPhase(TitlePhase)); + await game.phaseInterceptor.run(TitlePhase); + }, 20000); + + it("good run from select gender to title", async() => { + await game.phaseInterceptor.run(LoginPhase); + game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { + game.scene.gameData.gender = PlayerGender.MALE; + game.endPhase(); + }, () => game.isCurrentPhase(TitlePhase)); + await game.phaseInterceptor.runFrom(SelectGenderPhase).to(TitlePhase); + }, 20000); + + it("good run to SummonPhase phase", async() => { + await game.phaseInterceptor.run(LoginPhase); + game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { + game.scene.gameData.gender = PlayerGender.MALE; + game.endPhase(); + }, () => game.isCurrentPhase(TitlePhase)); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + game.scene.gameMode = getGameMode(GameModes.CLASSIC); + const starters = generateStarter(game.scene); + const selectStarterPhase = new SelectStarterPhase(game.scene); + game.scene.pushPhase(new EncounterPhase(game.scene, false)); + selectStarterPhase.initBattle(starters); + }); + await game.phaseInterceptor.runFrom(SelectGenderPhase).to(SummonPhase); + }, 20000); + + it("2vs1", async() => { + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + await game.startBattle([ + Species.BLASTOISE, + Species.CHARIZARD, + ]); + expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND); + expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name); + }, 20000); + + it("1vs1", async() => { + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + await game.startBattle([ + Species.BLASTOISE, + ]); + expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND); + expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name); + }, 20000); + + it("2vs2", async() => { + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + await game.startBattle([ + Species.BLASTOISE, + Species.CHARIZARD, + ]); + expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND); + expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name); + }, 20000); + + it("4vs2", async() => { + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + await game.startBattle([ + Species.BLASTOISE, + Species.CHARIZARD, + Species.DARKRAI, + Species.GABITE, + ]); + expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND); + expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name); + }, 20000); +}); + diff --git a/src/test/battle/error-handling.test.ts b/src/test/battle/error-handling.test.ts new file mode 100644 index 00000000000..2cb29aab1e7 --- /dev/null +++ b/src/test/battle/error-handling.test.ts @@ -0,0 +1,39 @@ +import {afterEach, beforeAll, beforeEach, describe, it, vi} from "vitest"; +import GameManager from "#app/test/utils/gameManager"; +import Phaser from "phaser"; +import * as overrides from "#app/overrides"; +import {Species} from "#app/data/enums/species"; +import {Moves} from "#app/data/enums/moves"; +import {Abilities} from "#app/data/enums/abilities"; + +describe("Test Battle Phase", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + }); + + it("should start phase", async() => { + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + await game.startBattle(); + }, 100000); +}); + diff --git a/src/test/eggs/egg.test.ts b/src/test/eggs/egg.test.ts new file mode 100644 index 00000000000..7cfe7fda651 --- /dev/null +++ b/src/test/eggs/egg.test.ts @@ -0,0 +1,33 @@ +import {beforeAll, describe, expect, it} from "vitest"; +import BattleScene from "../../battle-scene"; +import { getLegendaryGachaSpeciesForTimestamp } from "#app/data/egg.js"; +import { Species } from "#app/data/enums/species.js"; +import Phaser from "phaser"; + +describe("getLegendaryGachaSpeciesForTimestamp", () => { + + beforeAll(() => { + new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + it("should return Arceus for the 10th of June", () => { + const scene = new BattleScene(); + const timestamp = new Date(2024, 5, 10, 15, 0, 0, 0).getTime(); + const expectedSpecies = Species.ARCEUS; + + const result = getLegendaryGachaSpeciesForTimestamp(scene, timestamp); + + expect(result).toBe(expectedSpecies); + }); + it("should return Arceus for the 10th of July", () => { + const scene = new BattleScene(); + const timestamp = new Date(2024, 6, 10, 15, 0, 0, 0).getTime(); + const expectedSpecies = Species.ARCEUS; + + const result = getLegendaryGachaSpeciesForTimestamp(scene, timestamp); + + expect(result).toBe(expectedSpecies); + }); +}); diff --git a/src/test/debugImports.test.ts b/src/test/imports.test.ts similarity index 100% rename from src/test/debugImports.test.ts rename to src/test/imports.test.ts diff --git a/src/test/inputs/inputs.test.ts b/src/test/inputs/inputs.test.ts new file mode 100644 index 00000000000..4924ade0fc4 --- /dev/null +++ b/src/test/inputs/inputs.test.ts @@ -0,0 +1,105 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import pad_xbox360 from "#app/configs/inputs/pad_xbox360"; +import cfg_keyboard_qwerty from "#app/configs/inputs/cfg_keyboard_qwerty"; +import InputsHandler from "#app/test/utils/inputsHandler"; + + +describe("Inputs", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + let originalDocument: Document; + + beforeAll(() => { + originalDocument = window.document; + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + Object.defineProperty(window, "document", { + value: originalDocument, + configurable: true, + writable: true, + }); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.inputsHandler = new InputsHandler(game.scene); + }); + + it("Mobile - test touch holding for 1ms - 1 input", async () => { + await game.inputsHandler.pressTouch("dpadUp", 1); + expect(game.inputsHandler.log.length).toBe(1); + }); + + it("Mobile - test touch holding for 200ms - 1 input", async () => { + await game.inputsHandler.pressTouch("dpadUp", 200); + expect(game.inputsHandler.log.length).toBe(1); + }); + + it("Mobile - test touch holding for 300ms - 2 input", async () => { + await game.inputsHandler.pressTouch("dpadUp", 300); + expect(game.inputsHandler.log.length).toBe(2); + }); + + it("Mobile - test touch holding for 1000ms - 4 input", async () => { + await game.inputsHandler.pressTouch("dpadUp", 1000); + expect(game.inputsHandler.log.length).toBe(4); + }); + + it("keyboard - test input holding for 1ms - 1 input", async() => { + await game.inputsHandler.pressKeyboardKey(cfg_keyboard_qwerty.deviceMapping.KEY_ARROW_UP, 1); + expect(game.inputsHandler.log.length).toBe(1); + }); + + it("keyboard - test input holding for 200ms - 1 input", async() => { + await game.inputsHandler.pressKeyboardKey(cfg_keyboard_qwerty.deviceMapping.KEY_ARROW_UP, 200); + expect(game.inputsHandler.log.length).toBe(1); + }); + + it("keyboard - test input holding for 300ms - 2 input", async() => { + await game.inputsHandler.pressKeyboardKey(cfg_keyboard_qwerty.deviceMapping.KEY_ARROW_UP, 300); + expect(game.inputsHandler.log.length).toBe(2); + }); + + it("keyboard - test input holding for 1000ms - 4 input", async() => { + await game.inputsHandler.pressKeyboardKey(cfg_keyboard_qwerty.deviceMapping.KEY_ARROW_UP, 1000); + expect(game.inputsHandler.log.length).toBe(4); + }); + + it("keyboard - test input holding for 2000ms - 8 input", async() => { + await game.inputsHandler.pressKeyboardKey(cfg_keyboard_qwerty.deviceMapping.KEY_ARROW_UP, 2000); + expect(game.inputsHandler.log.length).toBe(8); + }); + + it("gamepad - test input holding for 1ms - 1 input", async() => { + await game.inputsHandler.pressGamepadButton(pad_xbox360.deviceMapping.RC_S, 1); + expect(game.inputsHandler.log.length).toBe(1); + }); + + it("gamepad - test input holding for 200ms - 1 input", async() => { + await game.inputsHandler.pressGamepadButton(pad_xbox360.deviceMapping.RC_S, 200); + expect(game.inputsHandler.log.length).toBe(1); + }); + + it("gamepad - test input holding for 300ms - 2 input", async() => { + await game.inputsHandler.pressGamepadButton(pad_xbox360.deviceMapping.RC_S, 300); + expect(game.inputsHandler.log.length).toBe(2); + }); + + it("gamepad - test input holding for 1000ms - 4 input", async() => { + await game.inputsHandler.pressGamepadButton(pad_xbox360.deviceMapping.RC_S, 1000); + expect(game.inputsHandler.log.length).toBe(4); + }); + + it("gamepad - test input holding for 2000ms - 8 input", async() => { + await game.inputsHandler.pressGamepadButton(pad_xbox360.deviceMapping.RC_S, 2000); + expect(game.inputsHandler.log.length).toBe(8); + }); +}); + diff --git a/src/test/items/toxic_orb.test.ts b/src/test/items/toxic_orb.test.ts new file mode 100644 index 00000000000..7064bcd13a1 --- /dev/null +++ b/src/test/items/toxic_orb.test.ts @@ -0,0 +1,80 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#app/data/enums/abilities"; +import {Species} from "#app/data/enums/species"; +import { + CommandPhase, + EnemyCommandPhase, + MessagePhase, + TurnEndPhase, +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {Moves} from "#app/data/enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Command} from "#app/ui/command-ui-handler"; +import {StatusEffect} from "#app/data/status-effect"; + + +describe("Items - Toxic orb", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const moveToUse = Moves.GROWTH; + const oppMoveToUse = Moves.TACKLE; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([oppMoveToUse, oppMoveToUse, oppMoveToUse, oppMoveToUse]); + vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ + name: "TOXIC_ORB", + }]); + }); + + it("TOXIC ORB", async() => { + const moveToUse = Moves.GROWTH; + await game.startBattle([ + Species.MIGHTYENA, + Species.MIGHTYENA, + ]); + expect(game.scene.modifiers[0].type.id).toBe("TOXIC_ORB"); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + // Select Attack + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + // Select Move Growth + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + // will run the 13 phase from enemyCommandPhase to TurnEndPhase + await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); + // Toxic orb should trigger here + await game.phaseInterceptor.run(MessagePhase); + const message = game.textInterceptor.getLatestMessage(); + expect(message).toContain("was badly poisoned by Toxic Orb"); + await game.phaseInterceptor.run(MessagePhase); + const message2 = game.textInterceptor.getLatestMessage(); + expect(message2).toContain("is hurt"); + expect(message2).toContain("by poison"); + expect(game.scene.getParty()[0].status.effect).toBe(StatusEffect.TOXIC); + }, 20000); +}); diff --git a/src/test/lokalisation/french.test.ts b/src/test/lokalisation/french.test.ts new file mode 100644 index 00000000000..25b7d7d9803 --- /dev/null +++ b/src/test/lokalisation/french.test.ts @@ -0,0 +1,42 @@ +import {afterEach, beforeAll, describe, expect, it} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import {Species} from "#app/data/enums/species"; +import i18next from "i18next"; +import {initI18n} from "#app/plugins/i18n"; + +describe("Lokalization - french", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + initI18n(); + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + it("test bulbasaur name english", async () => { + game = new GameManager(phaserGame); + await game.startBattle([ + Species.BULBASAUR, + ]); + expect(game.scene.getParty()[0].name).toBe("Bulbasaur"); + }, 20000); + + it("test bulbasaure name french", async () => { + const locale = "fr"; + i18next.changeLanguage(locale); + localStorage.setItem("prLang", locale); + game = new GameManager(phaserGame); + + await game.startBattle([ + Species.BULBASAUR, + ]); + expect(game.scene.getParty()[0].name).toBe("Bulbizarre"); + }, 20000); +}); diff --git a/src/test/moves/growth.test.ts b/src/test/moves/growth.test.ts new file mode 100644 index 00000000000..9a6e13f06a3 --- /dev/null +++ b/src/test/moves/growth.test.ts @@ -0,0 +1,69 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#app/data/enums/abilities"; +import {Species} from "#app/data/enums/species"; +import { + CommandPhase, + EnemyCommandPhase, + TurnInitPhase, +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {Stat} from "#app/data/pokemon-stat"; +import {Moves} from "#app/data/enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Command} from "#app/ui/command-ui-handler"; +import {BattleStat} from "#app/data/battle-stat"; + + +describe("Moves - Growth", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const moveToUse = Moves.GROWTH; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + it("GROWTH", async() => { + const moveToUse = Moves.GROWTH; + await game.startBattle([ + Species.MIGHTYENA, + Species.MIGHTYENA, + ]); + let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; + expect(battleStatsPokemon[Stat.SPATK]).toBe(0); + + const battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; + expect(battleStatsOpponent[BattleStat.SPATK]).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase); + battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; + expect(battleStatsPokemon[BattleStat.SPATK]).toBe(1); + }, 20000); +}); diff --git a/src/test/moves/tackle.test.ts b/src/test/moves/tackle.test.ts new file mode 100644 index 00000000000..ca3f95731f2 --- /dev/null +++ b/src/test/moves/tackle.test.ts @@ -0,0 +1,85 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Species} from "#app/data/enums/species"; +import { + CommandPhase, + EnemyCommandPhase, TurnEndPhase, +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {Moves} from "#app/data/enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Command} from "#app/ui/command-ui-handler"; +import {Stat} from "#app/data/pokemon-stat"; + + +describe("Moves - Tackle", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const moveToUse = Moves.TACKLE; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(97); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.GROWTH,Moves.GROWTH,Moves.GROWTH,Moves.GROWTH]); + vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + }); + + it("TACKLE against ghost", async() => { + const moveToUse = Moves.TACKLE; + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.GENGAR); + await game.startBattle([ + Species.MIGHTYENA, + ]); + const hpOpponent = game.scene.currentBattle.enemyParty[0].hp; + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); + const hpLost = hpOpponent - game.scene.currentBattle.enemyParty[0].hp; + expect(hpLost).toBe(0); + }, 20000); + + it("TACKLE against not resistant", async() => { + const moveToUse = Moves.TACKLE; + await game.startBattle([ + Species.MIGHTYENA, + ]); + game.scene.currentBattle.enemyParty[0].stats[Stat.DEF] = 50; + game.scene.getParty()[0].stats[Stat.ATK] = 50; + + + const hpOpponent = game.scene.currentBattle.enemyParty[0].hp; + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); + const hpLost = hpOpponent - game.scene.currentBattle.enemyParty[0].hp; + expect(hpLost).toBeGreaterThan(0); + expect(hpLost).toBe(4); + }, 20000); +}); diff --git a/src/test/moves/tail_whip.test.ts b/src/test/moves/tail_whip.test.ts new file mode 100644 index 00000000000..2d6789102d1 --- /dev/null +++ b/src/test/moves/tail_whip.test.ts @@ -0,0 +1,66 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#app/data/enums/abilities"; +import {Species} from "#app/data/enums/species"; +import { + CommandPhase, + EnemyCommandPhase, + TurnInitPhase, +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {Moves} from "#app/data/enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Command} from "#app/ui/command-ui-handler"; +import {BattleStat} from "#app/data/battle-stat"; + + +describe("Moves - Tail whip", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const moveToUse = Moves.TAIL_WHIP; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + it("TAIL_WHIP", async() => { + const moveToUse = Moves.TAIL_WHIP; + await game.startBattle([ + Species.MIGHTYENA, + Species.MIGHTYENA, + ]); + + let battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; + expect(battleStatsOpponent[BattleStat.DEF]).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase); + battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; + expect(battleStatsOpponent[BattleStat.DEF]).toBe(-1); + }, 20000); +}); diff --git a/src/test/phaser.setup.ts b/src/test/phaser.setup.ts deleted file mode 100644 index 1776e8134e2..00000000000 --- a/src/test/phaser.setup.ts +++ /dev/null @@ -1,5 +0,0 @@ -import Phaser from "phaser"; - -export default new Phaser.Game({ - type: Phaser.HEADLESS, -}); diff --git a/src/test/phases/phases.test.ts b/src/test/phases/phases.test.ts new file mode 100644 index 00000000000..009526ebe41 --- /dev/null +++ b/src/test/phases/phases.test.ts @@ -0,0 +1,54 @@ +import BattleScene from "#app/battle-scene.js"; +import { LoginPhase, TitlePhase, UnavailablePhase } from "#app/phases.js"; +import { Mode } from "#app/ui/ui.js"; +import {afterEach, beforeAll, beforeEach, describe, expect, it} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; + +describe("Phases", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + let scene: BattleScene; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + scene = game.scene; + }); + + describe("LoginPhase", () => { + it("should start the login phase", async () => { + const loginPhase = new LoginPhase(scene); + scene.pushPhase(loginPhase); + await game.phaseInterceptor.run(LoginPhase); + expect(scene.ui.getMode()).to.equal(Mode.MESSAGE); + }); + }); + + describe("TitlePhase", () => { + it("should start the title phase", async () => { + const titlePhase = new TitlePhase(scene); + scene.pushPhase(titlePhase); + await game.phaseInterceptor.run(TitlePhase); + expect(scene.ui.getMode()).to.equal(Mode.TITLE); + }); + }); + + describe("UnavailablePhase", () => { + it("should start the unavailable phase", async () => { + const unavailablePhase = new UnavailablePhase(scene); + scene.pushPhase(unavailablePhase); + await game.phaseInterceptor.run(UnavailablePhase); + expect(scene.ui.getMode()).to.equal(Mode.UNAVAILABLE); + }, 20000); + }); +}); diff --git a/src/test/pokemon.test.ts b/src/test/pokemon.test.ts deleted file mode 100644 index d1f7da45256..00000000000 --- a/src/test/pokemon.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import {describe, expect, it} from "vitest"; -import {getPokemonSpecies} from "#app/data/pokemon-species"; -import {PokemonMove} from "#app/field/pokemon"; -import {Species} from "#app/data/enums/species"; -import {Moves} from "#app/data/enums/moves"; -import PokemonData from "#app/system/pokemon-data"; - -describe("some tests related to PokemonData and Species", () => { - it("should create a species", () => { - const species = getPokemonSpecies(Species.MEW); - expect(species).not.toBeNull(); - }); - - it("should create a pokemon", () => { - const pokemon = new PokemonData({ - species: Species.MEW, - level: 1, - }); - expect(pokemon).not.toBeNull(); - expect(pokemon.level).toEqual(1); - expect(pokemon.species).toEqual(Species.MEW); - }); - - it("should generate a moveset", () => { - const pokemon = new PokemonData({ - species: Species.MEW, - level: 1, - }); - expect(pokemon.moveset[0].moveId).toBe(Moves.TACKLE); - expect(pokemon.moveset[1].moveId).toBe(Moves.GROWL); - }); - - it("should create an ennemypokemon", () => { - const ennemyPokemon = new PokemonData({ - species: Species.MEWTWO, - level: 100, - }); - expect(ennemyPokemon).not.toBeNull(); - expect(ennemyPokemon.level).toEqual(100); - expect(ennemyPokemon.species).toEqual(Species.MEWTWO); - }); - - it("should create an ennemypokemon with specified moveset", () => { - const ennemyPokemon = new PokemonData({ - species: Species.MEWTWO, - level: 100, - moveset: [ - new PokemonMove(Moves.ACID), - new PokemonMove(Moves.ACROBATICS), - new PokemonMove(Moves.FOCUS_ENERGY), - ] - }); - expect(ennemyPokemon.moveset[0].moveId).toBe(Moves.ACID); - expect(ennemyPokemon.moveset[1].moveId).toBe(Moves.ACROBATICS); - expect(ennemyPokemon.moveset[2].moveId).toBe(Moves.FOCUS_ENERGY); - }); -}); diff --git a/src/test/helpers/inGameManip.ts b/src/test/settingMenu/helpers/inGameManip.ts similarity index 100% rename from src/test/helpers/inGameManip.ts rename to src/test/settingMenu/helpers/inGameManip.ts diff --git a/src/test/helpers/menuManip.ts b/src/test/settingMenu/helpers/menuManip.ts similarity index 100% rename from src/test/helpers/menuManip.ts rename to src/test/settingMenu/helpers/menuManip.ts diff --git a/src/test/rebinding_setting.test.ts b/src/test/settingMenu/rebinding_setting.test.ts similarity index 99% rename from src/test/rebinding_setting.test.ts rename to src/test/settingMenu/rebinding_setting.test.ts index 03e8cbb51c4..dee29cd42a2 100644 --- a/src/test/rebinding_setting.test.ts +++ b/src/test/settingMenu/rebinding_setting.test.ts @@ -5,8 +5,8 @@ import { getKeyWithKeycode, getKeyWithSettingName, } from "#app/configs/inputs/configHandler"; -import {MenuManip} from "#app/test/helpers/menuManip"; -import {InGameManip} from "#app/test/helpers/inGameManip"; +import {MenuManip} from "#app/test/settingMenu/helpers/menuManip"; +import {InGameManip} from "#app/test/settingMenu/helpers/inGameManip"; import {Device} from "#app/enums/devices"; import {InterfaceConfig} from "#app/inputs-controller"; import cfg_keyboard_qwerty from "#app/configs/inputs/cfg_keyboard_qwerty"; diff --git a/src/test/pokemonSprite.test.ts b/src/test/sprites/pokemonSprite.test.ts similarity index 98% rename from src/test/pokemonSprite.test.ts rename to src/test/sprites/pokemonSprite.test.ts index 07b3cd01cc7..5c1db85fa6f 100644 --- a/src/test/pokemonSprite.test.ts +++ b/src/test/sprites/pokemonSprite.test.ts @@ -1,8 +1,8 @@ import {beforeAll, describe, expect, it} from "vitest"; -import _masterlist from "../../public/images/pokemon/variant/_masterlist.json"; +import _masterlist from "../../../public/images/pokemon/variant/_masterlist.json"; import fs from "fs"; import path from "path"; -import {getAppRootDir} from "#app/test/testUtils"; +import {getAppRootDir} from "#app/test/sprites/spritesUtils"; const deepCopy = (data) => { return JSON.parse(JSON.stringify(data)); diff --git a/src/test/testUtils.ts b/src/test/sprites/spritesUtils.ts similarity index 100% rename from src/test/testUtils.ts rename to src/test/sprites/spritesUtils.ts diff --git a/src/test/ui/starter-select.test.ts b/src/test/ui/starter-select.test.ts new file mode 100644 index 00000000000..9f323a2839c --- /dev/null +++ b/src/test/ui/starter-select.test.ts @@ -0,0 +1,594 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import {Species} from "#app/data/enums/species"; +import { + EncounterPhase, + SelectStarterPhase, + TitlePhase, +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {GameModes} from "#app/game-mode"; +import StarterSelectUiHandler from "#app/ui/starter-select-ui-handler"; +import {Button} from "#app/enums/buttons"; +import OptionSelectUiHandler from "#app/ui/settings/option-select-ui-handler"; +import SaveSlotSelectUiHandler from "#app/ui/save-slot-select-ui-handler"; +import {OptionSelectItem} from "#app/ui/abstact-option-select-ui-handler"; +import {Gender} from "#app/data/gender"; +import {allSpecies} from "#app/data/pokemon-species"; +import {Nature} from "#app/data/nature"; +import {Abilities} from "#app/data/enums/abilities"; + + +describe("UI - Starter select", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + }); + + it("Bulbasaur - shiny - variant 2 male", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.SUBMIT); + }); + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + resolve(); + }); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.BULBASAUR); + expect(game.scene.getParty()[0].shiny).toBe(true); + expect(game.scene.getParty()[0].variant).toBe(2); + expect(game.scene.getParty()[0].gender).toBe(Gender.MALE); + }, 20000); + + it("Bulbasaur - shiny - variant 2 female hardy overgrow", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.CYCLE_GENDER); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.SUBMIT); + }); + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + resolve(); + }); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.BULBASAUR); + expect(game.scene.getParty()[0].shiny).toBe(true); + expect(game.scene.getParty()[0].variant).toBe(2); + expect(game.scene.getParty()[0].nature).toBe(Nature.HARDY); + expect(game.scene.getParty()[0].getAbility().id).toBe(Abilities.OVERGROW); + }, 20000); + + it("Bulbasaur - shiny - variant 2 female lonely chlorophyl", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.CYCLE_GENDER); + handler.processInput(Button.CYCLE_NATURE); + handler.processInput(Button.CYCLE_ABILITY); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.SUBMIT); + }); + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + resolve(); + }); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.BULBASAUR); + expect(game.scene.getParty()[0].shiny).toBe(true); + expect(game.scene.getParty()[0].variant).toBe(2); + expect(game.scene.getParty()[0].nature).toBe(Nature.LONELY); + expect(game.scene.getParty()[0].getAbility().id).toBe(Abilities.CHLOROPHYLL); + }, 20000); + + it("Bulbasaur - shiny - variant 2 female lonely chlorophyl", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.CYCLE_GENDER); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.SUBMIT); + }); + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + resolve(); + }); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.BULBASAUR); + expect(game.scene.getParty()[0].shiny).toBe(true); + expect(game.scene.getParty()[0].variant).toBe(2); + expect(game.scene.getParty()[0].gender).toBe(Gender.FEMALE); + }, 20000); + + it("Bulbasaur - not shiny", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.CYCLE_SHINY); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.SUBMIT); + }); + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + resolve(); + }); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.BULBASAUR); + expect(game.scene.getParty()[0].shiny).toBe(false); + expect(game.scene.getParty()[0].variant).toBe(0); + }, 20000); + + it("Bulbasaur - shiny - variant 1", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.V); + handler.processInput(Button.V); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.SUBMIT); + }); + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + resolve(); + }); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.BULBASAUR); + expect(game.scene.getParty()[0].shiny).toBe(true); + expect(game.scene.getParty()[0].variant).toBe(1); + }, 20000); + + it("Bulbasaur - shiny - variant 2", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.V); + handler.processInput(Button.V); + handler.processInput(Button.V); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.SUBMIT); + }); + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + resolve(); + }); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.BULBASAUR); + expect(game.scene.getParty()[0].shiny).toBe(true); + expect(game.scene.getParty()[0].variant).toBe(2); + }, 20000); + + it("Check if first pokemon in party is caterpie from gen 1 and 1rd row, 3rd column", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.RIGHT); + handler.processInput(Button.RIGHT); + handler.processInput(Button.RIGHT); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + let starterSelectUiHandler: StarterSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + starterSelectUiHandler = game.scene.ui.getHandler() as StarterSelectUiHandler; + starterSelectUiHandler.processInput(Button.SUBMIT); + resolve(); + }); + }); + + expect(starterSelectUiHandler.starterGens[0]).toBe(0); + expect(starterSelectUiHandler.starterCursors[0]).toBe(3); + expect(starterSelectUiHandler.cursorObj.x).toBe(132 + 4 * 18); + expect(starterSelectUiHandler.cursorObj.y).toBe(10); + + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.CATERPIE); + }, 20000); + + it("Check if first pokemon in party is nidoran_m from gen 1 and 2nd row, 4th column (cursor (9+4)-1)", async() => { + await game.importData("src/test/utils/saves/everything.prsv"); + const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { + const species = game.scene.gameData.dexData[key]; + return species.caughtAttr !== 0n; + }).length; + expect(caughtCount).toBe(Object.keys(allSpecies).length); + await game.runToTitle(); + game.onNextPrompt("TitlePhase", Mode.TITLE, () => { + const currentPhase = game.scene.getCurrentPhase() as TitlePhase; + currentPhase.gameMode = GameModes.CLASSIC; + currentPhase.end(); + }); + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.RIGHT); + handler.processInput(Button.RIGHT); + handler.processInput(Button.RIGHT); + handler.processInput(Button.RIGHT); + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + game.phaseInterceptor.unlock(); + }); + await game.phaseInterceptor.run(SelectStarterPhase); + let options: OptionSelectItem[]; + let optionSelectUiHandler: OptionSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.OPTION_SELECT, () => { + optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + options = optionSelectUiHandler.getOptionsWithScroll(); + resolve(); + }); + }); + expect(options.some(option => option.label === "Add to Party")).toBe(true); + expect(options.some(option => option.label === "Toggle IVs")).toBe(true); + expect(options.some(option => option.label === "Manage Moves")).toBe(true); + expect(options.some(option => option.label === "Use Candies")).toBe(true); + expect(options.some(option => option.label === "Cancel")).toBe(true); + optionSelectUiHandler.processInput(Button.ACTION); + + let starterSelectUiHandler: StarterSelectUiHandler; + await new Promise((resolve) => { + game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { + starterSelectUiHandler = game.scene.ui.getHandler() as StarterSelectUiHandler; + starterSelectUiHandler.processInput(Button.SUBMIT); + resolve(); + }); + }); + + expect(starterSelectUiHandler.starterGens[0]).toBe(0); + expect(starterSelectUiHandler.starterCursors[0]).toBe(12); + expect(starterSelectUiHandler.cursorObj.x).toBe(132 + 4 * 18); + expect(starterSelectUiHandler.cursorObj.y).toBe(28); + + game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { + const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("SelectStarterPhase", Mode.SAVE_SLOT, () => { + const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; + saveSlotSelectUiHandler.processInput(Button.ACTION); + }); + await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + expect(game.scene.getParty()[0].species.speciesId).toBe(Species.NIDORAN_M); + }, 20000); +}); diff --git a/src/test/utils/TextInterceptor.ts b/src/test/utils/TextInterceptor.ts new file mode 100644 index 00000000000..d3048f23f74 --- /dev/null +++ b/src/test/utils/TextInterceptor.ts @@ -0,0 +1,16 @@ +export default class TextInterceptor { + private scene; + private logs = []; + constructor(scene) { + this.scene = scene; + scene.messageWrapper = this; + } + + showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer): void { + this.logs.push(text); + } + + getLatestMessage(): string { + return this.logs[this.logs.length - 1]; + } +} diff --git a/src/test/utils/errorInterceptor.ts b/src/test/utils/errorInterceptor.ts new file mode 100644 index 00000000000..7f06c47fd39 --- /dev/null +++ b/src/test/utils/errorInterceptor.ts @@ -0,0 +1,50 @@ +export default class ErrorInterceptor { + private static instance: ErrorInterceptor; + public running; + + constructor() { + this.running = []; + } + + public static getInstance(): ErrorInterceptor { + if (!ErrorInterceptor.instance) { + ErrorInterceptor.instance = new ErrorInterceptor(); + } + return ErrorInterceptor.instance; + } + + clear() { + this.running = []; + } + + add(obj) { + this.running.push(obj); + } + + remove(obj) { + const index = this.running.indexOf(obj); + if (index !== -1) { + this.running.splice(index, 1); + } + } +} + + +process.on("uncaughtException", (error) => { + console.log(error); + const toStop = ErrorInterceptor.getInstance().running; + for (const elm of toStop) { + elm.rejectAll(error); + } + global.testFailed = true; +}); + +// Global error handler for unhandled promise rejections +process.on("unhandledRejection", (reason, promise) => { + console.log(reason); + const toStop = ErrorInterceptor.getInstance().running; + for (const elm of toStop) { + elm.rejectAll(reason); + } + global.testFailed = true; +}); diff --git a/src/test/utils/fakeMobile.html b/src/test/utils/fakeMobile.html new file mode 100644 index 00000000000..6fa0406f361 --- /dev/null +++ b/src/test/utils/fakeMobile.html @@ -0,0 +1,50 @@ + +
+
+ + + + + + + +
+ +
+
+ A +
+
+ B +
+
+
+ R +
+
+ V +
+
+ C +
+
+ Menu +
+
+
+
+ F +
+
+ G +
+
+ E +
+
+ N +
+
+
+
+ \ No newline at end of file diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts new file mode 100644 index 00000000000..dc1991d5659 --- /dev/null +++ b/src/test/utils/gameManager.ts @@ -0,0 +1,216 @@ +import GameWrapper from "#app/test/utils/gameWrapper"; +import {Mode} from "#app/ui/ui"; +import {generateStarter, waitUntil} from "#app/test/utils/gameManagerUtils"; +import { + CommandPhase, + EncounterPhase, + LoginPhase, + PostSummonPhase, + SelectGenderPhase, + SelectStarterPhase, + TitlePhase, +} from "#app/phases"; +import BattleScene from "#app/battle-scene.js"; +import PhaseInterceptor from "#app/test/utils/phaseInterceptor"; +import TextInterceptor from "#app/test/utils/TextInterceptor"; +import {GameModes, getGameMode} from "#app/game-mode"; +import fs from "fs"; +import { AES, enc } from "crypto-js"; +import {updateUserInfo} from "#app/account"; +import {Species} from "#app/data/enums/species"; +import {PlayerGender} from "#app/data/enums/player-gender"; +import {GameDataType} from "#app/data/enums/game-data-type"; +import InputsHandler from "#app/test/utils/inputsHandler"; +import {ExpNotification} from "#app/enums/exp-notification"; +import ErrorInterceptor from "#app/test/utils/errorInterceptor"; + +/** + * Class to manage the game state and transitions between phases. + */ +export default class GameManager { + public gameWrapper: GameWrapper; + public scene: BattleScene; + public phaseInterceptor: PhaseInterceptor; + public textInterceptor: TextInterceptor; + public inputsHandler: InputsHandler; + + /** + * Creates an instance of GameManager. + * @param phaserGame - The Phaser game instance. + * @param bypassLogin - Whether to bypass the login phase. + */ + constructor(phaserGame: Phaser.Game, bypassLogin: boolean = true) { + localStorage.clear(); + ErrorInterceptor.getInstance().clear(); + BattleScene.prototype.randBattleSeedInt = (arg) => arg-1; + this.gameWrapper = new GameWrapper(phaserGame, bypassLogin); + this.scene = new BattleScene(); + this.phaseInterceptor = new PhaseInterceptor(this.scene); + this.textInterceptor = new TextInterceptor(this.scene); + this.gameWrapper.setScene(this.scene); + } + + /** + * Sets the game mode. + * @param mode - The mode to set. + */ + setMode(mode: Mode) { + this.scene.ui?.setMode(mode); + } + + /** + * Waits until the specified mode is set. + * @param mode - The mode to wait for. + * @returns A promise that resolves when the mode is set. + */ + waitMode(mode: Mode): Promise { + return new Promise(async (resolve) => { + await waitUntil(() => this.scene.ui?.getMode() === mode); + return resolve(); + }); + } + + /** + * Ends the current phase. + */ + endPhase() { + this.scene.getCurrentPhase().end(); + } + + /** + * Adds an action to be executed on the next prompt. + * @param phaseTarget - The target phase. + * @param mode - The mode to wait for. + * @param callback - The callback to execute. + * @param expireFn - Optional function to determine if the prompt has expired. + */ + onNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn?: () => void) { + this.phaseInterceptor.addToNextPrompt(phaseTarget, mode, callback, expireFn); + } + + /** + * Runs the game to the title phase. + * @returns A promise that resolves when the title phase is reached. + */ + runToTitle(): Promise { + return new Promise(async(resolve, reject) => { + await this.phaseInterceptor.run(LoginPhase).catch((e) => reject(e)); + this.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { + this.scene.gameData.gender = PlayerGender.MALE; + this.endPhase(); + }, () => this.isCurrentPhase(TitlePhase)); + await this.phaseInterceptor.run(SelectGenderPhase, () => this.isCurrentPhase(TitlePhase)).catch((e) => reject(e)); + await this.phaseInterceptor.run(TitlePhase).catch((e) => reject(e)); + this.scene.gameSpeed = 5; + this.scene.moveAnimations = false; + this.scene.showLevelUpStats = false; + this.scene.expGainsSpeed = 3; + this.scene.expParty = ExpNotification.SKIP; + this.scene.hpBarSpeed = 3; + resolve(); + }); + } + + /** + * Runs the game to the summon phase. + * @param species - Optional array of species to summon. + * @returns A promise that resolves when the summon phase is reached. + */ + runToSummon(species?: Species[]): Promise { + return new Promise(async(resolve, reject) => { + await this.runToTitle().catch((e) => reject(e)); + this.onNextPrompt("TitlePhase", Mode.TITLE, () => { + this.scene.gameMode = getGameMode(GameModes.CLASSIC); + const starters = generateStarter(this.scene, species); + const selectStarterPhase = new SelectStarterPhase(this.scene); + this.scene.pushPhase(new EncounterPhase(this.scene, false)); + selectStarterPhase.initBattle(starters); + }); + await this.phaseInterceptor.run(EncounterPhase).catch((e) => reject(e)); + resolve(); + }); + } + + /** + * Starts a battle. + * @param species - Optional array of species to start the battle with. + * @returns A promise that resolves when the battle is started. + */ + startBattle(species?: Species[]): Promise { + return new Promise(async(resolve, reject) => { + await this.runToSummon(species).catch((e) => reject(e)); + this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => { + this.setMode(Mode.MESSAGE); + this.endPhase(); + }, () => this.isCurrentPhase(CommandPhase)); + this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => { + this.setMode(Mode.MESSAGE); + this.endPhase(); + }, () => this.isCurrentPhase(CommandPhase)); + await this.phaseInterceptor.runFrom(PostSummonPhase).to(CommandPhase).catch((e) => reject(e)); + console.log("==================[New Turn]=================="); + return resolve(); + }); + } + + /** + * Checks if the player has won the battle. + * @returns True if the player has won, otherwise false. + */ + isVictory() { + return this.scene.currentBattle.enemyParty.every(pokemon => pokemon.isFainted()); + } + + /** + * Checks if the current phase matches the target phase. + * @param phaseTarget - The target phase. + * @returns True if the current phase matches the target phase, otherwise false. + */ + isCurrentPhase(phaseTarget) { + const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name; + return this.scene.getCurrentPhase().constructor.name === targetName; + } + + /** + * Checks if the current mode matches the target mode. + * @param mode - The target mode. + * @returns True if the current mode matches the target mode, otherwise false. + */ + isCurrentMode(mode: Mode) { + return this.scene.ui?.getMode() === mode; + } + + /** + * Exports the save data to import it in a test game. + * @returns A promise that resolves with the exported save data. + */ + exportSaveToTest(): Promise { + return new Promise(async (resolve) => { + await this.scene.gameData.saveAll(this.scene, true, true, true, true); + this.scene.reset(true); + await waitUntil(() => this.scene.ui?.getMode() === Mode.TITLE); + await this.scene.gameData.tryExportData(GameDataType.SESSION, 0); + await waitUntil(() => localStorage.hasOwnProperty("toExport")); + return resolve(localStorage.getItem("toExport")); + }); + } + + /** + * Imports game data from a file. + * @param path - The path to the data file. + * @returns A promise that resolves with a tuple containing a boolean indicating success and an integer status code. + */ + async importData(path): Promise<[boolean, integer]> { + const saveKey = "x0i2O7WRiANTqPmZ"; + const dataRaw = fs.readFileSync(path, {encoding: "utf8", flag: "r"}); + let dataStr = AES.decrypt(dataRaw, saveKey).toString(enc.Utf8); + dataStr = this.scene.gameData.convertSystemDataStr(dataStr); + const systemData = this.scene.gameData.parseSystemData(dataStr); + const valid = !!systemData.dexData && !!systemData.timestamp; + if (valid) { + await updateUserInfo(); + await this.scene.gameData.initSystem(dataStr); + } + return updateUserInfo(); + } +} diff --git a/src/test/utils/gameManagerUtils.ts b/src/test/utils/gameManagerUtils.ts new file mode 100644 index 00000000000..1b7bbdabaf0 --- /dev/null +++ b/src/test/utils/gameManagerUtils.ts @@ -0,0 +1,87 @@ +// Function to convert Blob to string +import {getDailyRunStarters} from "#app/data/daily-run"; +import {Gender} from "#app/data/gender"; +import {Species} from "#app/data/enums/species"; +import {Starter} from "#app/ui/starter-select-ui-handler"; +import {GameModes, getGameMode} from "#app/game-mode"; +import {getPokemonSpecies, getPokemonSpeciesForm} from "#app/data/pokemon-species"; +import {PlayerPokemon} from "#app/field/pokemon"; + +export function blobToString(blob) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onloadend = () => { + resolve(reader.result); + }; + + reader.onerror = () => { + reject(new Error("Error reading Blob as string")); + }; + + reader.readAsText(blob); + }); +} + + +export function holdOn(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export function generateStarter(scene, species?: Species[]) { + const seed = "test"; + const starters = getTestRunStarters(scene, seed, species); + const startingLevel = scene.gameMode.getStartingLevel(); + for (const starter of starters) { + const starterProps = scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr); + const starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0)); + const starterGender = starter.species.malePercent !== null + ? !starterProps.female ? Gender.MALE : Gender.FEMALE + : Gender.GENDERLESS; + const starterPokemon = scene.addPlayerPokemon(starter.species, startingLevel, starter.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterProps.variant, undefined, starter.nature); + starter.moveset = starterPokemon.moveset; + } + return starters; +} + +function getTestRunStarters(scene, seed, species) { + if (!species) { + return getDailyRunStarters(scene, seed); + } + const starters: Starter[] = []; + const startingLevel = getGameMode(GameModes.CLASSIC).getStartingLevel(); + + for (const specie of species) { + const starterSpeciesForm = getPokemonSpeciesForm(specie, 0); + const starterSpecies = getPokemonSpecies(starterSpeciesForm.speciesId); + const pokemon = new PlayerPokemon(scene, starterSpecies, startingLevel, undefined, 0, undefined, undefined, undefined, undefined, undefined, undefined); + const starter: Starter = { + species: starterSpecies, + dexAttr: pokemon.getDexAttr(), + abilityIndex: pokemon.abilityIndex, + passive: false, + nature: pokemon.getNature(), + pokerus: pokemon.pokerus + }; + starters.push(starter); + } + return starters; +} + +export function waitUntil(truth) { + return new Promise(resolve => { + const interval = setInterval(() => { + if (truth()) { + clearInterval(interval); + resolve(true); + } + }, 1000); + }); +} + +export function getMovePosition(scene, pokemonIndex, moveIndex) { + const playerPokemon = scene.getPlayerField()[pokemonIndex]; + const moveSet = playerPokemon.getMoveset(); + const index = moveSet.findIndex((move) => move.moveId === moveIndex); + return index; +} diff --git a/src/test/utils/gameWrapper.ts b/src/test/utils/gameWrapper.ts new file mode 100644 index 00000000000..7d0e4110351 --- /dev/null +++ b/src/test/utils/gameWrapper.ts @@ -0,0 +1,251 @@ +/* eslint-disable */ +// @ts-nocheck +import * as main from "#app/main"; +import fs from "fs"; +import InputManager = Phaser.Input.InputManager; +import KeyboardManager = Phaser.Input.Keyboard.KeyboardManager; +import KeyboardPlugin = Phaser.Input.Keyboard.KeyboardPlugin; +import GamepadPlugin = Phaser.Input.Gamepad.GamepadPlugin; +import EventEmitter = Phaser.Events.EventEmitter; +import UpdateList = Phaser.GameObjects.UpdateList; +import MockGraphics from "#app/test/utils/mocks/mocksContainer/mockGraphics"; +import MockTextureManager from "#app/test/utils/mocks/mockTextureManager"; +import Phaser from "phaser"; +import {blobToString} from "#app/test/utils/gameManagerUtils"; +import {vi} from "vitest"; +import mockLocalStorage from "#app/test/utils/mocks/mockLocalStorage"; +import mockConsoleLog from "#app/test/utils/mocks/mockConsoleLog"; +import MockLoader from "#app/test/utils/mocks/mockLoader"; +import {MockFetch} from "#app/test/utils/mocks/mockFetch"; +import * as Utils from "#app/utils"; +import InputText from "phaser3-rex-plugins/plugins/inputtext"; +import {MockClock} from "#app/test/utils/mocks/mockClock"; +import BattleScene from "#app/battle-scene.js"; +import {MoveAnim} from "#app/data/battle-anims"; +import Pokemon from "#app/field/pokemon"; +import * as battleScene from "#app/battle-scene"; + +Object.defineProperty(window, "localStorage", { + value: mockLocalStorage(), +}); +Object.defineProperty(window, "console", { + value: mockConsoleLog(false), +}); + + +InputText.prototype.setElement = () => null; +InputText.prototype.resize = () => null; +window.URL.createObjectURL = (blob: Blob) => { + blobToString(blob).then((data: string) => { + localStorage.setItem("toExport", data); + }) + return null; +}; +navigator.getGamepads = vi.fn().mockReturnValue([]); +global.fetch = vi.fn(MockFetch); +Utils.setCookie(Utils.sessionIdKey, 'fake_token'); + + +window.matchMedia = () => ({ + matches: false, +}); + + +/** + * Sets this object's position relative to another object with a given offset + * @param guideObject {@linkcode Phaser.GameObjects.GameObject} to base the position off of + * @param x The relative x position + * @param y The relative y position + */ +const setPositionRelative = function (guideObject: any, x: number, y: number) { + const offsetX = guideObject.width * (-0.5 + (0.5 - guideObject.originX)); + const offsetY = guideObject.height * (-0.5 + (0.5 - guideObject.originY)); + this.setPosition(guideObject.x + offsetX + x, guideObject.y + offsetY + y); +}; + +Phaser.GameObjects.Container.prototype.setPositionRelative = setPositionRelative; +Phaser.GameObjects.Sprite.prototype.setPositionRelative = setPositionRelative; +Phaser.GameObjects.Image.prototype.setPositionRelative = setPositionRelative; +Phaser.GameObjects.NineSlice.prototype.setPositionRelative = setPositionRelative; +Phaser.GameObjects.Text.prototype.setPositionRelative = setPositionRelative; +Phaser.GameObjects.Rectangle.prototype.setPositionRelative = setPositionRelative; + + +export default class GameWrapper { + public game: Phaser.Game; + public scene: BattleScene; + + constructor(phaserGame: Phaser.Game, bypassLogin: boolean) { + Phaser.Math.RND.sow([ 'test' ]); + vi.spyOn(Utils, "apiFetch", "get").mockReturnValue(fetch); + if (bypassLogin) { + vi.spyOn(battleScene, "bypassLogin", "get").mockReturnValue(true); + } + this.game = phaserGame; + MoveAnim.prototype.getAnim = () => ({ + frames: {}, + }); + Pokemon.prototype.enableMask = () => null; + } + + setScene(scene: BattleScene) { + this.scene = scene; + this.injectMandatory(); + this.scene.preload && this.scene.preload(); + this.scene.create(); + } + + injectMandatory() { + this.game.config = { + seed: ["test"], + } + this.scene.game = this.game; + this.game.renderer = { + maxTextures: -1, + gl: {}, + deleteTexture: () => null, + canvasToTexture: () => ({}), + createCanvasTexture: () => ({}), + pipelines: { + add: () => null, + }, + }; + this.scene.renderer = this.game.renderer; + this.scene.children = { + removeAll: () => null, + }; + + this.scene.sound = { + play: () => null, + pause: () => null, + setRate: () => null, + add: () => this.scene.sound, + get: () => this.scene.sound, + getAllPlaying: () => [], + manager: { + game: this.game, + }, + setVolume: () => null, + stopByKey: () => null, + on: (evt, callback) => callback(), + key: "", + }; + + this.scene.tweens = { + add: (data) => { + if (data.onComplete) { + data.onComplete(); + } + }, + getTweensOf: () => ([]), + killTweensOf: () => ([]), + chain: () => null, + addCounter: (data) => { + if (data.onComplete) { + data.onComplete(); + } + }, + }; + + this.scene.anims = this.game.anims; + this.scene.cache = this.game.cache; + this.scene.plugins = this.game.plugins; + this.scene.registry = this.game.registry; + this.scene.scale = this.game.scale; + this.scene.textures = this.game.textures; + this.scene.events = this.game.events; + this.scene.manager = new InputManager(this.game, {}); + this.scene.manager.keyboard = new KeyboardManager(this.scene); + this.scene.pluginEvents = new EventEmitter(); + this.scene.domContainer = {} as HTMLDivElement; + this.scene.spritePipeline = {}; + this.scene.fieldSpritePipeline = {}; + this.scene.load = new MockLoader(this.scene); + this.scene.sys = { + queueDepthSort: () => null, + anims: this.game.anims, + game: this.game, + textures: { + addCanvas: () => ({ + get: () => ({ // this.frame in Text.js + source: {}, + setSize: () => null, + glTexture: () => ({ + spectorMetadata: {}, + }), + }), + }) + }, + cache: this.scene.load.cacheManager, + scale: this.game.scale, + // _scene.sys.scale = new ScaleManager(_scene); + // events: { + // on: () => null, + // }, + events: new EventEmitter(), + settings: { + loader: { + key: 'battle', + } + }, + input: this.game.input, + }; + const mockTextureManager = new MockTextureManager(this.scene); + this.scene.add = mockTextureManager.add; + this.scene.sys.displayList = this.scene.add.displayList; + this.scene.sys.updateList = new UpdateList(this.scene); + this.scene.systems = this.scene.sys; + this.scene.input = this.game.input; + this.scene.scene = this.scene; + this.scene.input.keyboard = new KeyboardPlugin(this.scene); + this.scene.input.gamepad = new GamepadPlugin(this.scene); + this.scene.cachedFetch = (url, init) => { + return new Promise((resolve) => { + // need to remove that if later we want to test battle-anims + const newUrl = url.includes('./battle-anims/') ? prependPath('./battle-anims/tackle.json') : prependPath(url); + let raw; + try { + raw = fs.readFileSync(newUrl, {encoding: "utf8", flag: "r"}); + } catch(e) { + return resolve(createFetchBadResponse({})); + } + const data = JSON.parse(raw); + const response = createFetchResponse(data); + return resolve(response); + }); + }; + this.scene.make = { + graphics: (config) => new MockGraphics(mockTextureManager, config), + rexTransitionImagePack: () => ({ + transit: () => null, + }), + }; + this.scene.time = new MockClock(this.scene); + } +} + +function prependPath(originalPath) { + const prefix = "public"; + if (originalPath.startsWith("./")) { + return originalPath.replace("./", `${prefix}/`); + } + return originalPath; +} +// Simulate fetch response +function createFetchResponse(data) { + return { + ok: true, + status: 200, + json: () => Promise.resolve(data), + text: () => Promise.resolve(JSON.stringify(data)), + }; +} +// Simulate fetch response +function createFetchBadResponse(data) { + return { + ok: false, + status: 404, + json: () => Promise.resolve(data), + text: () => Promise.resolve(JSON.stringify(data)), + }; +} \ No newline at end of file diff --git a/src/test/utils/inputsHandler.ts b/src/test/utils/inputsHandler.ts new file mode 100644 index 00000000000..fd961ed3ef6 --- /dev/null +++ b/src/test/utils/inputsHandler.ts @@ -0,0 +1,115 @@ +import BattleScene from "#app/battle-scene"; +import Phaser from "phaser"; +import {InputsController} from "#app/inputs-controller"; +import pad_xbox360 from "#app/configs/inputs/pad_xbox360"; +import {holdOn} from "#app/test/utils/gameManagerUtils"; +import {initTouchControls} from "#app/touch-controls"; +import { JSDOM } from "jsdom"; +import fs from "fs"; + + +export default class InputsHandler { + private scene: BattleScene; + private events: Phaser.Events.EventEmitter; + private inputController: InputsController; + public log = []; + public logUp = []; + private fakePad: Fakepad; + private fakeMobile: FakeMobile; + + constructor(scene: BattleScene) { + this.scene = scene; + this.inputController = this.scene.inputController; + this.fakePad = new Fakepad(pad_xbox360); + this.fakeMobile = new FakeMobile(); + this.scene.input.gamepad.gamepads.push(this.fakePad); + this.init(); + } + + pressTouch(button: string, duration: integer): Promise { + return new Promise(async (resolve) => { + this.fakeMobile.touchDown(button); + await holdOn(duration); + this.fakeMobile.touchUp(button); + resolve(); + }); + } + + pressGamepadButton(button: integer, duration: integer): Promise { + return new Promise(async (resolve) => { + this.scene.input.gamepad.emit("down", this.fakePad, {index: button}); + await holdOn(duration); + this.scene.input.gamepad.emit("up", this.fakePad, {index: button}); + resolve(); + }); + } + + pressKeyboardKey(key: integer, duration: integer): Promise { + return new Promise(async (resolve) => { + this.scene.input.keyboard.emit("keydown", {keyCode: key}); + await holdOn(duration); + this.scene.input.keyboard.emit("keyup", {keyCode: key}); + resolve(); + }); + } + + init(): void { + setInterval(() => { + this.inputController.update(); + }); + initTouchControls(this.inputController.events); + this.events = this.inputController.events; + this.scene.input.gamepad.emit("connected", this.fakePad); + this.listenInputs(); + } + + listenInputs(): void { + this.events.on("input_down", (event) => { + this.log.push({type: "input_down", button: event.button}); + }, this); + + this.events.on("input_up", (event) => { + this.logUp.push({type: "input_up", button: event.button}); + }, this); + } +} + +class Fakepad extends Phaser.Input.Gamepad.Gamepad { + public id: string; + public index: number; + + constructor(pad) { + super(undefined, {...pad, buttons: pad.deviceMapping, axes: []}); + this.id = "xbox_360_fakepad"; + this.index = 0; + } +} + +class FakeMobile { + constructor() { + const fakeMobilePage = fs.readFileSync("./src/test/utils/fakeMobile.html", {encoding: "utf8", flag: "r"}); + const dom = new JSDOM(fakeMobilePage); + Object.defineProperty(window, "document", { + value: dom.window.document, + configurable: true, + }); + } + + touchDown(button: string) { + const node = document.querySelector(`[data-key][id='${button}']`); + if (!node) { + return; + } + const event = new Event("touchstart"); + node.dispatchEvent(event); + } + + touchUp(button: string) { + const node = document.querySelector(`[data-key][id='${button}']`); + if (!node) { + return; + } + const event = new Event("touchend"); + node.dispatchEvent(event); + } +} diff --git a/src/test/utils/misc.test.ts b/src/test/utils/misc.test.ts new file mode 100644 index 00000000000..da67fb48192 --- /dev/null +++ b/src/test/utils/misc.test.ts @@ -0,0 +1,79 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import {apiFetch} from "#app/utils"; +import {waitUntil} from "#app/test/utils/gameManagerUtils"; + +describe("Test misc", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + }); + + it("test fetch mock async", async () => { + const spy = vi.fn(); + await fetch("https://localhost:8080/account/info").then(response => { + expect(response.status).toBe(200); + expect(response.ok).toBe(true); + return response.json(); + }).then(data => { + spy(); // Call the spy function + expect(data).toEqual({"username":"greenlamp","lastSessionSlot":0}); + }); + expect(spy).toHaveBeenCalled(); + }); + + it("test apifetch mock async", async () => { + const spy = vi.fn(); + await apiFetch("https://localhost:8080/account/info").then(response => { + expect(response.status).toBe(200); + expect(response.ok).toBe(true); + return response.json(); + }).then(data => { + spy(); // Call the spy function + expect(data).toEqual({"username":"greenlamp","lastSessionSlot":0}); + }); + expect(spy).toHaveBeenCalled(); + }); + + it("test fetch mock sync", async () => { + const response = await fetch("https://localhost:8080/account/info"); + const data = await response.json(); + + expect(response.ok).toBe(true); + expect(response.status).toBe(200); + expect(data).toEqual({"username":"greenlamp","lastSessionSlot":0}); + }); + + it("test apifetch mock sync", async () => { + const data = await game.scene.cachedFetch("./battle-anims/splishy-splash.json"); + expect(data).not.toBeUndefined(); + }); + + it("testing wait phase queue", async () => { + const fakeScene = { + phaseQueue: [1, 2, 3] // Initially not empty + }; + setTimeout(() => { + fakeScene.phaseQueue = []; + }, 500); + const spy = vi.fn(); + await waitUntil(() => fakeScene.phaseQueue.length === 0).then(result => { + expect(result).toBe(true); + spy(); // Call the spy function + }); + expect(spy).toHaveBeenCalled(); + }); +}); diff --git a/src/test/utils/mocks/mockClock.ts b/src/test/utils/mocks/mockClock.ts new file mode 100644 index 00000000000..0d5ea68ed59 --- /dev/null +++ b/src/test/utils/mocks/mockClock.ts @@ -0,0 +1,17 @@ +import Clock = Phaser.Time.Clock; + + +export class MockClock extends Clock { + constructor(scene) { + super(scene); + setInterval(() => { + /* + To simulate frame update + eventEmitter.on(SceneEvents.PRE_UPDATE, this.preUpdate, this); + eventEmitter.on(SceneEvents.UPDATE, this.update, this); + */ + this.preUpdate(this.systems.game.loop.time, 100); + this.update(this.systems.game.loop.time, 100); + }, 100); + } +} diff --git a/src/test/utils/mocks/mockConsoleLog.ts b/src/test/utils/mocks/mockConsoleLog.ts new file mode 100644 index 00000000000..61c6c14b989 --- /dev/null +++ b/src/test/utils/mocks/mockConsoleLog.ts @@ -0,0 +1,82 @@ +const MockConsoleLog = (_logDisabled= false, _phaseText=false) => { + let logs = []; + const logDisabled: boolean = _logDisabled; + const phaseText: boolean = _phaseText; + const originalLog = console.log; + const originalError = console.error; + const originalDebug = console.debug; + const originalWarn = console.warn; + const notified = []; + + const blacklist = ["Phaser", "variant icon does not exist", "Texture \"%s\" not found"]; + const whitelist = ["Phase"]; + + return ({ + log(...args) { + const argsStr = this.getStr(args); + logs.push(argsStr); + if (logDisabled && (!phaseText)) { + return; + } + if ((phaseText && !whitelist.some((b) => argsStr.includes(b))) || blacklist.some((b) => argsStr.includes(b))) { + return; + } + originalLog(args); + }, + error(...args) { + const argsStr = this.getStr(args); + logs.push(argsStr); + originalError(args); // Appelle le console.error originel + }, + debug(...args) { + const argsStr = this.getStr(args); + logs.push(argsStr); + if (logDisabled && (!phaseText)) { + return; + } + if (!whitelist.some((b) => argsStr.includes(b)) || blacklist.some((b) => argsStr.includes(b))) { + return; + } + originalDebug(args); + }, + warn(...args) { + const argsStr = this.getStr(args); + logs.push(args); + if (logDisabled && (!phaseText)) { + return; + } + if (!whitelist.some((b) => argsStr.includes(b)) || blacklist.some((b) => argsStr.includes(b))) { + return; + } + originalWarn(args); + }, + notify(msg) { + originalLog(msg); + notified.push(msg); + }, + getLogs() { + return logs; + }, + clearLogs() { + logs = []; + }, + getStr(...args) { + return args.map(arg => { + if (typeof arg === "object" && arg !== null) { + // Handle objects including arrays + return JSON.stringify(arg, (key, value) => + typeof value === "bigint" ? value.toString() : value + ); + } else if (typeof arg === "bigint") { + // Handle BigInt values + return arg.toString(); + } else { + // Handle all other types + return arg.toString(); + } + }).join(";"); + }, + }); +}; + +export default MockConsoleLog; diff --git a/src/test/utils/mocks/mockFetch.ts b/src/test/utils/mocks/mockFetch.ts new file mode 100644 index 00000000000..ad364a95885 --- /dev/null +++ b/src/test/utils/mocks/mockFetch.ts @@ -0,0 +1,32 @@ +export const MockFetch = (input, init) => { + const url = typeof input === "string" ? input : input.url; + + let responseHandler; + let responseText; + + const handlers = { + "account/info": {"username":"greenlamp","lastSessionSlot":0}, + "savedata/session": {}, + "savedata/system": {}, + "savedata/updateall": "", + "daily/rankingpagecount": { data: 0 }, + "game/titlestats": {"playerCount":0,"battleCount":5}, + "daily/rankings": [], + }; + + + for (const key of Object.keys(handlers)) { + if (url.includes(key)) { + responseHandler = async() => handlers[key]; + responseText = async() => handlers[key] ? JSON.stringify(handlers[key]) : handlers[key]; + break; + } + } + + return Promise.resolve({ + ok: true, + status: 200, + json: responseHandler, + text: responseText, + }); +}; diff --git a/src/test/utils/mocks/mockLoader.ts b/src/test/utils/mocks/mockLoader.ts new file mode 100644 index 00000000000..661eb72f2c2 --- /dev/null +++ b/src/test/utils/mocks/mockLoader.ts @@ -0,0 +1,42 @@ +import CacheManager = Phaser.Cache.CacheManager; + + +export default class MockLoader { + public cacheManager; + constructor(scene) { + this.cacheManager = new CacheManager(scene); + } + + once(event, callback) { + callback(); + } + + setBaseURL(url) { + return null; + } + + video() { + return null; + } + + spritesheet(key, url, frameConfig) { + } + + audio(key, url) { + + } + + isLoading() { + return false; + } + + start() { + } + + image() { + + } + + atlas(key, textureUrl, atlasUrl) { + } +} diff --git a/src/test/utils/mocks/mockLocalStorage.ts b/src/test/utils/mocks/mockLocalStorage.ts new file mode 100644 index 00000000000..bb4ea4e890d --- /dev/null +++ b/src/test/utils/mocks/mockLocalStorage.ts @@ -0,0 +1,27 @@ +const mockLocalStorage = (() => { + let store = {} as Storage; + + return { + getItem(key: string) { + return store[key]; + }, + + setItem(key: string, value: string) { + store[key] = value; + }, + + hasOwnProperty(key: string) { + return store.hasOwnProperty(key); + }, + + removeItem(key: string) { + delete store[key]; + }, + + clear() { + store = {} as Storage; + }, + }; +}); + +export default mockLocalStorage; diff --git a/src/test/utils/mocks/mockTextureManager.ts b/src/test/utils/mocks/mockTextureManager.ts new file mode 100644 index 00000000000..e207f96b722 --- /dev/null +++ b/src/test/utils/mocks/mockTextureManager.ts @@ -0,0 +1,85 @@ +import MockContainer from "#app/test/utils/mocks/mocksContainer/mockContainer"; +import MockSprite from "#app/test/utils/mocks/mocksContainer/mockSprite"; +import MockRectangle from "#app/test/utils/mocks/mocksContainer/mockRectangle"; +import MockNineslice from "#app/test/utils/mocks/mocksContainer/mockNineslice"; +import MockImage from "#app/test/utils/mocks/mocksContainer/mockImage"; +import MockText from "#app/test/utils/mocks/mocksContainer/mockText"; +import MockPolygon from "#app/test/utils/mocks/mocksContainer/mockPolygon"; + + +export default class MockTextureManager { + private textures: Map; + private scene; + public add; + public displayList; + public list = []; + + constructor(scene) { + this.scene = scene; + this.textures = new Map(); + this.displayList = new Phaser.GameObjects.DisplayList(scene); + this.add = { + container: this.container.bind(this), + sprite: this.sprite.bind(this), + tileSprite: this.sprite.bind(this), + existing: this.existing.bind(this), + rectangle: this.rectangle.bind(this), + nineslice: this.nineslice.bind(this), + image: this.image.bind(this), + polygon: this.polygon.bind(this), + text: this.text.bind(this), + bitmapText: this.text.bind(this), + displayList: this.displayList, + }; + } + + container(x, y) { + const container = new MockContainer(this, x, y); + this.list.push(container); + return container; + } + + sprite(x,y, texture) { + const sprite = new MockSprite(this, x, y, texture); + this.list.push(sprite); + return sprite; + } + + existing(obj) { + // const whitelist = ["ArenaBase", "PlayerPokemon", "EnemyPokemon"]; + // const key = obj.constructor.name; + // if (whitelist.includes(key) || obj.texture?.key?.includes("trainer_")) { + // this.containers.push(obj); + // } + } + + rectangle(x, y, width, height, fillColor) { + const rectangle = new MockRectangle(this, x, y, width, height, fillColor); + this.list.push(rectangle); + return rectangle; + } + + nineslice(x, y, texture, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight) { + const nineSlice = new MockNineslice(this, x, y, texture, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight); + this.list.push(nineSlice); + return nineSlice; + } + + image(x, y, texture) { + const image = new MockImage(this, x, y, texture); + this.list.push(image); + return image; + } + + text(x, y, content, styleOptions) { + const text = new MockText(this, x, y, content, styleOptions); + this.list.push(text); + return text; + } + + polygon(x, y, content, fillColor, fillAlpha) { + const polygon = new MockPolygon(this, x, y, content, fillColor, fillAlpha); + this.list.push(polygon); + return polygon; + } +} diff --git a/src/test/utils/mocks/mocksContainer/mockContainer.ts b/src/test/utils/mocks/mocksContainer/mockContainer.ts new file mode 100644 index 00000000000..2e2b9567796 --- /dev/null +++ b/src/test/utils/mocks/mocksContainer/mockContainer.ts @@ -0,0 +1,207 @@ +import MockTextureManager from "#app/test/utils/mocks/mockTextureManager"; + +export default class MockContainer { + protected x; + protected y; + protected scene; + protected width; + protected height; + protected visible; + private alpha; + private style; + public frame; + protected textureManager; + public list = []; + + constructor(textureManager: MockTextureManager, x, y) { + this.x = x; + this.y = y; + this.frame = {}; + this.textureManager = textureManager; + } + setVisible(visible) { + this.visible = visible; + } + + once(event, callback, source) { + } + + off(event, callback, source) { + } + + removeFromDisplayList() { + // same as remove or destroy + } + + addedToScene() { + // This callback is invoked when this Game Object is added to a Scene. + } + + setSize(width, height) { + // Sets the size of this Game Object. + } + + setMask() { + /// Sets the mask that this Game Object will use to render with. + } + + setPositionRelative(source, x, y) { + /// Sets the position of this Game Object to be a relative position from the source Game Object. + } + + setInteractive(hitArea?, callback?, dropZone?) { + /// Sets the InteractiveObject to be a drop zone for a drag and drop operation. + } + setOrigin(x, y) { + this.x = x; + this.y = y; + } + + setAlpha(alpha) { + this.alpha = alpha; + } + + setFrame(frame, updateSize?: boolean, updateOrigin?: boolean) { + // Sets the frame this Game Object will use to render with. + } + + setScale(scale) { + // Sets the scale of this Game Object. + } + + setPosition(x, y) { + this.x = x; + this.y = y; + } + + setX(x) { + this.x = x; + } + + setY(y) { + this.y = y; + } + + destroy() { + this.list = []; + } + + setShadow(shadowXpos, shadowYpos, shadowColor) { + // Sets the shadow settings for this Game Object. + } + + setLineSpacing(lineSpacing) { + // Sets the line spacing value of this Game Object. + } + + setText(text) { + // Sets the text this Game Object will display. + } + + setAngle(angle) { + // Sets the angle of this Game Object. + } + + setShadowOffset(offsetX, offsetY) { + // Sets the shadow offset values. + } + + setWordWrapWidth(width) { + // Sets the width (in pixels) to use for wrapping lines. + } + + setFontSize(fontSize) { + // Sets the font size of this Game Object. + } + getBounds() { + return { width: this.width, height: this.height }; + } + + setColor(color) { + // Sets the tint of this Game Object. + } + + setShadowColor(color) { + // Sets the shadow color. + } + + setTint(color) { + // Sets the tint of this Game Object. + } + + setStrokeStyle(thickness, color) { + // Sets the stroke style for the graphics. + return this; + } + + setDepth(depth) { + // Sets the depth of this Game Object. + } + + setTexture(texture) { + // Sets the texture this Game Object will use to render with. + } + + clearTint() { + // Clears any previously set tint. + } + + sendToBack() { + // Sends this Game Object to the back of its parent's display list. + } + + moveAbove(obj) { + // Moves this Game Object to be above the given Game Object in the display list. + } + + moveBelow(obj) { + // Moves this Game Object to be below the given Game Object in the display list. + } + + setName(name) { + // return this.phaserSprite.setName(name); + } + + bringToTop(obj) { + // Brings this Game Object to the top of its parents display list. + } + + on(event, callback, source) { + } + + add(obj) { + // Adds a child to this Game Object. + this.list.push(obj); + } + + removeAll() { + // Removes all Game Objects from this Container. + this.list = []; + } + + addAt(obj, index) { + // Adds a Game Object to this Container at the given index. + this.list.splice(index, 0, obj); + } + + remove(obj) { + const index = this.list.indexOf(obj); + if (index !== -1) { + this.list.splice(index, 1); + } + } + + getIndex(obj) { + const index = this.list.indexOf(obj); + return index || -1; + } + + getAt(index) { + return this.list[index]; + } + + getAll() { + return this.list; + } + +} diff --git a/src/test/utils/mocks/mocksContainer/mockGraphics.ts b/src/test/utils/mocks/mocksContainer/mockGraphics.ts new file mode 100644 index 00000000000..a08f150fe61 --- /dev/null +++ b/src/test/utils/mocks/mocksContainer/mockGraphics.ts @@ -0,0 +1,96 @@ +export default class MockGraphics { + private scene; + public list = []; + constructor(textureManager, config) { + this.scene = textureManager.scene; + } + + fillStyle(color) { + // Sets the fill style to be used by the fill methods. + } + + beginPath() { + // Starts a new path by emptying the list of sub-paths. Call this method when you want to create a new path. + } + + fillRect(x, y, width, height) { + // Adds a rectangle shape to the path which is filled when you call fill(). + } + + createGeometryMask() { + // Creates a geometry mask. + } + + setOrigin(x, y) { + } + + setAlpha(alpha) { + } + + setVisible(visible) { + } + + setName(name) { + } + + once(event, callback, source) { + } + + removeFromDisplayList() { + // same as remove or destroy + } + + addedToScene() { + // This callback is invoked when this Game Object is added to a Scene. + } + + setPositionRelative(source, x, y) { + /// Sets the position of this Game Object to be a relative position from the source Game Object. + } + + destroy() { + this.list = []; + } + + setScale(scale) { + // Sets the scale of this Game Object. + } + + off(event, callback, source) { + } + + add(obj) { + // Adds a child to this Game Object. + this.list.push(obj); + } + + removeAll() { + // Removes all Game Objects from this Container. + this.list = []; + } + + addAt(obj, index) { + // Adds a Game Object to this Container at the given index. + this.list.splice(index, 0, obj); + } + + remove(obj) { + const index = this.list.indexOf(obj); + if (index !== -1) { + this.list.splice(index, 1); + } + } + + getIndex(obj) { + const index = this.list.indexOf(obj); + return index || -1; + } + + getAt(index) { + return this.list[index]; + } + + getAll() { + return this.list; + } +} diff --git a/src/test/utils/mocks/mocksContainer/mockImage.ts b/src/test/utils/mocks/mocksContainer/mockImage.ts new file mode 100644 index 00000000000..601dfd22811 --- /dev/null +++ b/src/test/utils/mocks/mocksContainer/mockImage.ts @@ -0,0 +1,11 @@ +import MockContainer from "#app/test/utils/mocks/mocksContainer/mockContainer"; + + +export default class MockImage extends MockContainer { + private texture; + + constructor(textureManager, x, y, texture) { + super(textureManager, x, y); + this.texture = texture; + } +} diff --git a/src/test/utils/mocks/mocksContainer/mockNineslice.ts b/src/test/utils/mocks/mocksContainer/mockNineslice.ts new file mode 100644 index 00000000000..3edbbb18c31 --- /dev/null +++ b/src/test/utils/mocks/mocksContainer/mockNineslice.ts @@ -0,0 +1,20 @@ +import MockContainer from "#app/test/utils/mocks/mocksContainer/mockContainer"; + + +export default class MockNineslice extends MockContainer { + private texture; + private leftWidth; + private rightWidth; + private topHeight; + private bottomHeight; + + constructor(textureManager, x, y, texture, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight) { + super(textureManager, x, y); + this.texture = texture; + this.frame = frame; + this.leftWidth = leftWidth; + this.rightWidth = rightWidth; + this.topHeight = topHeight; + this.bottomHeight = bottomHeight; + } +} diff --git a/src/test/utils/mocks/mocksContainer/mockPolygon.ts b/src/test/utils/mocks/mocksContainer/mockPolygon.ts new file mode 100644 index 00000000000..cf448883ce0 --- /dev/null +++ b/src/test/utils/mocks/mocksContainer/mockPolygon.ts @@ -0,0 +1,9 @@ +import MockContainer from "#app/test/utils/mocks/mocksContainer/mockContainer"; + + +export default class MockPolygon extends MockContainer { + constructor(textureManager, x, y, content, fillColor, fillAlpha) { + super(textureManager, x, y); + } +} + diff --git a/src/test/utils/mocks/mocksContainer/mockRectangle.ts b/src/test/utils/mocks/mocksContainer/mockRectangle.ts new file mode 100644 index 00000000000..f4ecd2af9d8 --- /dev/null +++ b/src/test/utils/mocks/mocksContainer/mockRectangle.ts @@ -0,0 +1,74 @@ +export default class MockRectangle { + private fillColor; + private scene; + public list = []; + + constructor(textureManager, x, y, width, height, fillColor) { + this.fillColor = fillColor; + this.scene = textureManager.scene; + } + setOrigin(x, y) { + } + + setAlpha(alpha) { + } + setVisible(visible) { + } + + setName(name) { + } + + once(event, callback, source) { + } + + removeFromDisplayList() { + // same as remove or destroy + } + + addedToScene() { + // This callback is invoked when this Game Object is added to a Scene. + } + + setPositionRelative(source, x, y) { + /// Sets the position of this Game Object to be a relative position from the source Game Object. + } + + destroy() { + this.list = []; + } + + add(obj) { + // Adds a child to this Game Object. + this.list.push(obj); + } + + removeAll() { + // Removes all Game Objects from this Container. + this.list = []; + } + + addAt(obj, index) { + // Adds a Game Object to this Container at the given index. + this.list.splice(index, 0, obj); + } + + remove(obj) { + const index = this.list.indexOf(obj); + if (index !== -1) { + this.list.splice(index, 1); + } + } + + getIndex(obj) { + const index = this.list.indexOf(obj); + return index || -1; + } + + getAt(index) { + return this.list[index]; + } + + getAll() { + return this.list; + } +} diff --git a/src/test/utils/mocks/mocksContainer/mockSprite.ts b/src/test/utils/mocks/mocksContainer/mockSprite.ts new file mode 100644 index 00000000000..30effe185ad --- /dev/null +++ b/src/test/utils/mocks/mocksContainer/mockSprite.ts @@ -0,0 +1,205 @@ +import Sprite = Phaser.GameObjects.Sprite; +import Frame = Phaser.Textures.Frame; +import Phaser from "phaser"; + + +export default class MockSprite { + private phaserSprite; + public pipelineData; + public texture; + public key; + public frame; + public textureManager; + public scene; + public anims; + public list = []; + constructor(textureManager, x, y, texture) { + this.textureManager = textureManager; + this.scene = textureManager.scene; + Phaser.GameObjects.Sprite.prototype.setInteractive = this.setInteractive; + // @ts-ignore + Phaser.GameObjects.Sprite.prototype.setTexture = this.setTexture; + Phaser.GameObjects.Sprite.prototype.setSizeToFrame = this.setSizeToFrame; + Phaser.GameObjects.Sprite.prototype.setFrame = this.setFrame; + // Phaser.GameObjects.Sprite.prototype.disable = this.disable; + + // Phaser.GameObjects.Sprite.prototype.texture = { frameTotal: 1, get: () => null }; + this.phaserSprite = new Phaser.GameObjects.Sprite(textureManager.scene, x, y, texture); + this.pipelineData = {}; + this.texture = { + key: texture || "", + }; + this.anims = { + pause: () => null, + }; + } + + setTexture(key: string, frame?: string | number) { + return this; + } + + setSizeToFrame(frame?: boolean | Frame): Sprite { + return {} as Sprite; + } + + setPipeline(obj) { + // Sets the pipeline of this Game Object. + return this.phaserSprite.setPipeline(obj); + } + + off(event, callback, source) { + } + + setTintFill(color) { + // Sets the tint fill color. + return this.phaserSprite.setTintFill(color); + } + + setScale(scale) { + return this.phaserSprite.setScale(scale); + } + + setOrigin(x, y) { + return this.phaserSprite.setOrigin(x, y); + } + + setSize(width, height) { + // Sets the size of this Game Object. + return this.phaserSprite.setSize(width, height); + } + + once(event, callback, source) { + return this.phaserSprite.once(event, callback, source); + } + + removeFromDisplayList() { + // same as remove or destroy + return this.phaserSprite.removeFromDisplayList(); + } + + addedToScene() { + // This callback is invoked when this Game Object is added to a Scene. + return this.phaserSprite.addedToScene(); + } + + setVisible(visible) { + return this.phaserSprite.setVisible(visible); + } + + setPosition(x, y) { + return this.phaserSprite.setPosition(x, y); + } + + stop() { + return this.phaserSprite.stop(); + } + + setInteractive(hitArea, hitAreaCallback, dropZone) { + return null; + } + + on(event, callback, source) { + return this.phaserSprite.on(event, callback, source); + } + + setAlpha(alpha) { + return this.phaserSprite.setAlpha(alpha); + } + + setTint(color) { + // Sets the tint of this Game Object. + return this.phaserSprite.setTint(color); + } + + setFrame(frame, updateSize?: boolean, updateOrigin?: boolean) { + // Sets the frame this Game Object will use to render with. + this.frame = frame; + return frame; + } + + setPositionRelative(source, x, y) { + /// Sets the position of this Game Object to be a relative position from the source Game Object. + return this.phaserSprite.setPositionRelative(source, x, y); + } + + setCrop(x, y, width, height) { + // Sets the crop size of this Game Object. + return this.phaserSprite.setCrop(x, y, width, height); + } + + clearTint() { + // Clears any previously set tint. + return this.phaserSprite.clearTint(); + } + + disableInteractive() { + // Disables Interactive features of this Game Object. + return null; + } + + apply() { + return this.phaserSprite.apply(); + } + + play() { + // return this.phaserSprite.play(); + } + + setPipelineData(key, value) { + this.pipelineData[key] = value; + } + + destroy() { + return this.phaserSprite.destroy(); + } + + setName(name) { + return this.phaserSprite.setName(name); + } + + setAngle(angle) { + return this.phaserSprite.setAngle(angle); + } + + setMask() { + + } + + add(obj) { + // Adds a child to this Game Object. + this.list.push(obj); + } + + removeAll() { + // Removes all Game Objects from this Container. + this.list = []; + } + + addAt(obj, index) { + // Adds a Game Object to this Container at the given index. + this.list.splice(index, 0, obj); + } + + remove(obj) { + const index = this.list.indexOf(obj); + if (index !== -1) { + this.list.splice(index, 1); + } + } + + getIndex(obj) { + const index = this.list.indexOf(obj); + return index || -1; + } + + getAt(index) { + return this.list[index]; + } + + getAll() { + return this.list; + } + + + +} diff --git a/src/test/utils/mocks/mocksContainer/mockText.ts b/src/test/utils/mocks/mocksContainer/mockText.ts new file mode 100644 index 00000000000..bfff146465e --- /dev/null +++ b/src/test/utils/mocks/mocksContainer/mockText.ts @@ -0,0 +1,267 @@ +import UI from "#app/ui/ui"; + +export default class MockText { + private phaserText; + private wordWrapWidth; + private splitRegExp; + private scene; + private textureManager; + public list = []; + public style; + constructor(textureManager, x, y, content, styleOptions) { + this.scene = textureManager.scene; + this.textureManager = textureManager; + this.style = {}; + // Phaser.GameObjects.TextStyle.prototype.setStyle = () => null; + // Phaser.GameObjects.Text.prototype.updateText = () => null; + // Phaser.Textures.TextureManager.prototype.addCanvas = () => {}; + UI.prototype.showText = this.showText; + // super(scene, x, y); + // this.phaserText = new Phaser.GameObjects.Text(scene, x, y, content, styleOptions); + } + + runWordWrap(text) { + if (!text) { + return ""; + } + let result = ""; + this.splitRegExp = /(?:\r\n|\r|\n)/; + const lines = text.split(this.splitRegExp); + const lastLineIndex = lines.length - 1; + const whiteSpaceWidth = 2; + + for (let i = 0; i <= lastLineIndex; i++) { + let spaceLeft = this.wordWrapWidth; + const words = lines[i].split(" "); + const lastWordIndex = words.length - 1; + + for (let j = 0; j <= lastWordIndex; j++) { + const word = words[j]; + const wordWidth = word.length * 2; + let wordWidthWithSpace = wordWidth; + + if (j < lastWordIndex) { + wordWidthWithSpace += whiteSpaceWidth; + } + + if (wordWidthWithSpace > spaceLeft) { + // Skip printing the newline if it's the first word of the line that is greater + // than the word wrap width. + if (j > 0) { + result += "\n"; + spaceLeft = this.wordWrapWidth; + } + } + + result += word; + + if (j < lastWordIndex) { + result += " "; + spaceLeft -= wordWidthWithSpace; + } else { + spaceLeft -= wordWidth; + } + } + + if (i < lastLineIndex) { + result += "\n"; + } + } + + return result; + } + + showText(text, delay, callback, callbackDelay, prompt, promptDelay) { + this.scene.messageWrapper.showText(text, delay, callback, callbackDelay, prompt, promptDelay); + if (callback) { + callback(); + } + } + + setScale(scale) { + // return this.phaserText.setScale(scale); + } + + setShadow(shadowXpos, shadowYpos, shadowColor) { + // Sets the shadow settings for this Game Object. + // return this.phaserText.setShadow(shadowXpos, shadowYpos, shadowColor); + } + + setLineSpacing(lineSpacing) { + // Sets the line spacing value of this Game Object. + // return this.phaserText.setLineSpacing(lineSpacing); + } + + setOrigin(x, y) { + // return this.phaserText.setOrigin(x, y); + } + + once(event, callback, source) { + // return this.phaserText.once(event, callback, source); + } + + off(event, callback, obj) { + } + + removedFromScene() { + + } + + addToDisplayList() { + + } + + setStroke(color, thickness) { + // Sets the stroke color and thickness. + // return this.phaserText.setStroke(color, thickness); + } + + removeFromDisplayList() { + // same as remove or destroy + // return this.phaserText.removeFromDisplayList(); + } + + addedToScene() { + // This callback is invoked when this Game Object is added to a Scene. + // return this.phaserText.addedToScene(); + } + + setVisible(visible) { + // return this.phaserText.setVisible(visible); + } + + setY(y) { + // return this.phaserText.setY(y); + } + + setX(x) { + // return this.phaserText.setX(x); + } + + setText(text) { + // Sets the text this Game Object will display. + // return this.phaserText.setText(text); + } + + setAngle(angle) { + // Sets the angle of this Game Object. + // return this.phaserText.setAngle(angle); + } + + setPositionRelative(source, x, y) { + /// Sets the position of this Game Object to be a relative position from the source Game Object. + // return this.phaserText.setPositionRelative(source, x, y); + } + + setShadowOffset(offsetX, offsetY) { + // Sets the shadow offset values. + // return this.phaserText.setShadowOffset(offsetX, offsetY); + } + + setWordWrapWidth(width) { + // Sets the width (in pixels) to use for wrapping lines. + this.wordWrapWidth = width; + } + + setFontSize(fontSize) { + // Sets the font size of this Game Object. + // return this.phaserText.setFontSize(fontSize); + } + + getBounds() { + // return this.phaserText.getBounds(); + return { + width: 1, + }; + } + + setColor(color) { + // Sets the tint of this Game Object. + // return this.phaserText.setColor(color); + } + + setShadowColor(color) { + // Sets the shadow color. + // return this.phaserText.setShadowColor(color); + } + + setTint(color) { + // Sets the tint of this Game Object. + // return this.phaserText.setTint(color); + } + + setStrokeStyle(thickness, color) { + // Sets the stroke style for the graphics. + // return this.phaserText.setStrokeStyle(thickness, color); + } + + destroy() { + // return this.phaserText.destroy(); + this.list = []; + } + + setAlpha(alpha) { + // return this.phaserText.setAlpha(alpha); + } + + setName(name) { + // return this.phaserText.setName(name); + } + + setAlign(align) { + // return this.phaserText.setAlign(align); + } + + setMask() { + /// Sets the mask that this Game Object will use to render with. + } + + getBottomLeft() { + return { + x: 0, + y: 0, + }; + } + + getTopLeft() { + return { + x: 0, + y: 0, + }; + } + + add(obj) { + // Adds a child to this Game Object. + this.list.push(obj); + } + + removeAll() { + // Removes all Game Objects from this Container. + this.list = []; + } + + addAt(obj, index) { + // Adds a Game Object to this Container at the given index. + this.list.splice(index, 0, obj); + } + + remove(obj) { + const index = this.list.indexOf(obj); + if (index !== -1) { + this.list.splice(index, 1); + } + } + + getIndex(obj) { + const index = this.list.indexOf(obj); + return index || -1; + } + + getAt(index) { + return this.list[index]; + } + + getAll() { + return this.list; + } +} diff --git a/src/test/utils/phaseInterceptor.ts b/src/test/utils/phaseInterceptor.ts new file mode 100644 index 00000000000..49e67e8448c --- /dev/null +++ b/src/test/utils/phaseInterceptor.ts @@ -0,0 +1,314 @@ +import { + BattleEndPhase, + BerryPhase, + CheckSwitchPhase, CommandPhase, DamagePhase, EggLapsePhase, + EncounterPhase, EnemyCommandPhase, FaintPhase, + LoginPhase, MessagePhase, MoveEffectPhase, MoveEndPhase, MovePhase, NewBattlePhase, NextEncounterPhase, + PostSummonPhase, + SelectGenderPhase, SelectModifierPhase, + SelectStarterPhase, SelectTargetPhase, ShinySparklePhase, ShowAbilityPhase, StatChangePhase, SummonPhase, + TitlePhase, ToggleDoublePositionPhase, TurnEndPhase, TurnInitPhase, TurnStartPhase, UnavailablePhase, VictoryPhase +} from "#app/phases"; +import UI, {Mode} from "#app/ui/ui"; +import {Phase} from "#app/phase"; +import ErrorInterceptor from "#app/test/utils/errorInterceptor"; + +export default class PhaseInterceptor { + public scene; + public phases = {}; + public log; + private onHold; + private interval; + private promptInterval; + private intervalRun; + private prompts; + private phaseFrom; + private inProgress; + private originalSetMode; + private originalSuperEnd; + + /** + * List of phases with their corresponding start methods. + */ + private PHASES = [ + [LoginPhase, this.startPhase], + [TitlePhase, this.startPhase], + [SelectGenderPhase, this.startPhase], + [EncounterPhase, this.startPhase], + [SelectStarterPhase, this.startPhase], + [PostSummonPhase, this.startPhase], + [SummonPhase, this.startPhase], + [ToggleDoublePositionPhase, this.startPhase], + [CheckSwitchPhase, this.startPhase], + [ShowAbilityPhase, this.startPhase], + [MessagePhase, this.startPhase], + [TurnInitPhase, this.startPhase], + [CommandPhase, this.startPhase], + [EnemyCommandPhase, this.startPhase], + [TurnStartPhase, this.startPhase], + [MovePhase, this.startPhase], + [MoveEffectPhase, this.startPhase], + [DamagePhase, this.startPhase], + [FaintPhase, this.startPhase], + [BerryPhase, this.startPhase], + [TurnEndPhase, this.startPhase], + [BattleEndPhase, this.startPhase], + [EggLapsePhase, this.startPhase], + [SelectModifierPhase, this.startPhase], + [NextEncounterPhase, this.startPhase], + [NewBattlePhase, this.startPhase], + [VictoryPhase, this.startPhase], + [MoveEndPhase, this.startPhase], + [StatChangePhase, this.startPhase], + [ShinySparklePhase, this.startPhase], + [SelectTargetPhase, this.startPhase], + [UnavailablePhase, this.startPhase], + ]; + + private endBySetMode = [ + TitlePhase, SelectGenderPhase, CommandPhase, SelectModifierPhase + ]; + + /** + * Constructor to initialize the scene and properties, and to start the phase handling. + * @param scene - The scene to be managed. + */ + constructor(scene) { + this.scene = scene; + this.log = []; + this.onHold = []; + this.prompts = []; + this.initPhases(); + this.startPromptHander(); + } + + rejectAll(error) { + if (this.inProgress) { + clearInterval(this.promptInterval); + clearInterval(this.interval); + clearInterval(this.intervalRun); + this.inProgress.onError(error); + } + } + + /** + * Method to set the starting phase. + * @param phaseFrom - The phase to start from. + * @returns The instance of the PhaseInterceptor. + */ + runFrom(phaseFrom) { + this.phaseFrom = phaseFrom; + return this; + } + + /** + * Method to transition to a target phase. + * @param phaseTo - The phase to transition to. + * @returns A promise that resolves when the transition is complete. + */ + async to(phaseTo, runTarget: boolean = true): Promise { + return new Promise(async (resolve, reject) => { + ErrorInterceptor.getInstance().add(this); + await this.run(this.phaseFrom).catch((e) => reject(e)); + this.phaseFrom = null; + const targetName = typeof phaseTo === "string" ? phaseTo : phaseTo.name; + this.intervalRun = setInterval(async() => { + const currentPhase = this.onHold?.length && this.onHold[0]; + if (currentPhase && currentPhase.name === targetName) { + clearInterval(this.intervalRun); + if (!runTarget) { + return resolve(); + } + await this.run(currentPhase).catch((e) => { + clearInterval(this.intervalRun); + return reject(e); + }); + return resolve(); + } + if (currentPhase && currentPhase.name !== targetName) { + await this.run(currentPhase).catch((e) => { + clearInterval(this.intervalRun); + return reject(e); + }); + } + }); + }); + } + + /** + * Method to run a phase with an optional skip function. + * @param phaseTarget - The phase to run. + * @param skipFn - Optional skip function. + * @returns A promise that resolves when the phase is run. + */ + run(phaseTarget, skipFn?): Promise { + const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name; + this.scene.moveAnimations = null; // Mandatory to avoid crash + return new Promise(async (resolve, reject) => { + ErrorInterceptor.getInstance().add(this); + const interval = setInterval(async () => { + const currentPhase = this.onHold.shift(); + if (currentPhase) { + if (currentPhase.name !== targetName) { + clearInterval(interval); + const skip = skipFn && skipFn(currentPhase.name); + if (skip) { + this.onHold.unshift(currentPhase); + ErrorInterceptor.getInstance().remove(this); + return resolve(); + } + clearInterval(interval); + return reject(`Wrong phase: this is ${currentPhase.name} and not ${targetName}`); + } + clearInterval(interval); + this.inProgress = { + name: currentPhase.name, + callback: () => { + ErrorInterceptor.getInstance().remove(this); + resolve(); + }, + onError: (error) => reject(error), + }; + currentPhase.call(); + } + }); + }); + } + + whenAboutToRun(phaseTarget, skipFn?): Promise { + const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name; + this.scene.moveAnimations = null; // Mandatory to avoid crash + return new Promise(async (resolve, reject) => { + ErrorInterceptor.getInstance().add(this); + const interval = setInterval(async () => { + const currentPhase = this.onHold.shift(); + if (currentPhase) { + if (currentPhase.name !== targetName) { + this.onHold.unshift(currentPhase); + } else { + clearInterval(interval); + resolve(); + } + } + }); + }); + } + + /** + * Method to initialize phases and their corresponding methods. + */ + initPhases() { + this.originalSetMode = UI.prototype.setMode; + this.originalSuperEnd = Phase.prototype.end; + UI.prototype.setMode = (mode, ...args) => this.setMode.call(this, mode, ...args); + Phase.prototype.end = () => this.superEndPhase.call(this); + for (const [phase, methodStart] of this.PHASES) { + const originalStart = phase.prototype.start; + this.phases[phase.name] = { + start: originalStart, + endBySetMode: this.endBySetMode.some((elm) => elm.name === phase.name), + }; + phase.prototype.start = () => methodStart.call(this, phase); + } + } + + /** + * Method to start a phase and log it. + * @param phase - The phase to start. + */ + startPhase(phase) { + this.log.push(phase.name); + const instance = this.scene.getCurrentPhase(); + this.onHold.push({ + name: phase.name, + call: () => { + this.phases[phase.name].start.apply(instance); + } + }); + } + + unlock() { + this.inProgress?.callback(); + this.inProgress = undefined; + } + + /** + * Method to end a phase and log it. + * @param phase - The phase to start. + */ + superEndPhase() { + const instance = this.scene.getCurrentPhase(); + console.log(`%c INTERCEPTED Super End Phase ${instance.constructor.name}`, "color:red;"); + this.originalSuperEnd.apply(instance); + this.inProgress?.callback(); + this.inProgress = undefined; + } + + /** + * m2m to set mode. + * @param phase - The phase to start. + */ + setMode(mode: Mode, ...args: any[]): Promise { + const currentPhase = this.scene.getCurrentPhase(); + const instance = this.scene.ui; + console.log("setMode", mode, args); + const ret = this.originalSetMode.apply(instance, [mode, ...args]); + if (this.phases[currentPhase.constructor.name].endBySetMode) { + this.inProgress?.callback(); + this.inProgress = undefined; + } + return ret; + } + + /** + * Method to start the prompt handler. + */ + startPromptHander() { + this.promptInterval = setInterval(() => { + if (this.prompts.length) { + const actionForNextPrompt = this.prompts[0]; + const expireFn = actionForNextPrompt.expireFn && actionForNextPrompt.expireFn(); + const currentMode = this.scene.ui.getMode(); + const currentPhase = this.scene.getCurrentPhase().constructor.name; + if (expireFn) { + this.prompts.shift(); + } else if (currentMode === actionForNextPrompt.mode && currentPhase === actionForNextPrompt.phaseTarget) { + this.prompts.shift().callback(); + } + } + }); + } + + /** + * Method to add an action to the next prompt. + * @param phaseTarget - The target phase for the prompt. + * @param mode - The mode of the UI. + * @param callback - The callback function to execute. + * @param expireFn - The function to determine if the prompt has expired. + */ + addToNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn: () => void) { + this.prompts.push({ + phaseTarget, + mode, + callback, + expireFn + }); + } + + /** + * Restores the original state of phases and clears intervals. + * + * This function iterates through all phases and resets their `start` method to the original + * function stored in `this.phases`. Additionally, it clears the `promptInterval` and `interval`. + */ + restoreOg() { + for (const [phase] of this.PHASES) { + phase.prototype.start = this.phases[phase.name].start; + } + UI.prototype.setMode = this.originalSetMode; + Phase.prototype.end = this.originalSuperEnd; + clearInterval(this.promptInterval); + clearInterval(this.interval); + clearInterval(this.intervalRun); + } +} diff --git a/src/test/utils/saves/everything.prsv b/src/test/utils/saves/everything.prsv new file mode 100644 index 00000000000..2e4a851eb8f --- /dev/null +++ b/src/test/utils/saves/everything.prsv @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/src/test/vitest.setup.ts b/src/test/vitest.setup.ts index 5777cc00611..8dac707255a 100644 --- a/src/test/vitest.setup.ts +++ b/src/test/vitest.setup.ts @@ -1,5 +1,4 @@ import "vitest-canvas-mock"; -import "#app/test/phaser.setup"; import "#app/test/fontFace.setup"; import {initStatsKeys} from "#app/ui/game-stats-ui-handler"; import {initPokemonPrevolutions} from "#app/data/pokemon-evolutions"; @@ -9,7 +8,11 @@ import {initPokemonForms} from "#app/data/pokemon-forms"; import {initSpecies} from "#app/data/pokemon-species"; import {initMoves} from "#app/data/move"; import {initAbilities} from "#app/data/ability"; +import {initAchievements} from "#app/system/achv.js"; +import { initVouchers } from "#app/system/voucher.js"; +initVouchers(); +initAchievements(); initStatsKeys(); initPokemonPrevolutions(); initBiomes(); @@ -18,3 +21,5 @@ initPokemonForms(); initSpecies(); initMoves(); initAbilities(); + +global.testFailed = false; diff --git a/src/touch-controls.ts b/src/touch-controls.ts index 3b734e01467..401ae7c6b93 100644 --- a/src/touch-controls.ts +++ b/src/touch-controls.ts @@ -70,12 +70,14 @@ function simulateKeyboardEvent(eventType: string, key: string, events: EventEmit events.emit("input_down", { controller_type: "keyboard", button: button, + isTouch: true }); break; case "keyup": events.emit("input_up", { controller_type: "keyboard", button: button, + isTouch: true }); break; } diff --git a/src/ui-inputs.ts b/src/ui-inputs.ts index d068cbebde7..3523cdc9f1e 100644 --- a/src/ui-inputs.ts +++ b/src/ui-inputs.ts @@ -30,8 +30,23 @@ export class UiInputs { this.listenInputs(); } + detectInputMethod(evt): void { + if (evt.controller_type === "keyboard") { + //if the touch property is present and defined, then this is a simulated keyboard event from the touch screen + if (evt.hasOwnProperty("isTouch") && evt.isTouch) { + this.scene.inputMethod = "touch"; + } else { + this.scene.inputMethod = "keyboard"; + } + } else if (evt.controller_type === "gamepad") { + this.scene.inputMethod = "gamepad"; + } + } + listenInputs(): void { this.events.on("input_down", (event) => { + this.detectInputMethod(event); + const actions = this.getActionsKeyDown(); if (!actions.hasOwnProperty(event.button)) { return; diff --git a/src/ui/achv-bar.ts b/src/ui/achv-bar.ts index f24fda0792b..9e9b20795e3 100644 --- a/src/ui/achv-bar.ts +++ b/src/ui/achv-bar.ts @@ -2,6 +2,7 @@ import BattleScene from "../battle-scene"; import { Achv, getAchievementDescription } from "../system/achv"; import { Voucher } from "../system/voucher"; import { TextStyle, addTextObject } from "./text"; +import { PlayerGender } from "#app/data/enums/player-gender"; export default class AchvBar extends Phaser.GameObjects.Container { private defaultWidth: number; @@ -14,11 +15,13 @@ export default class AchvBar extends Phaser.GameObjects.Container { private descriptionText: Phaser.GameObjects.Text; private queue: (Achv | Voucher)[] = []; + private playerGender: PlayerGender; public shown: boolean; constructor(scene: BattleScene) { super(scene, scene.game.canvas.width / 6, 0); + this.playerGender = scene.gameData.gender; } setup(): void { @@ -64,7 +67,7 @@ export default class AchvBar extends Phaser.GameObjects.Container { this.bg.setTexture(`achv_bar${tier ? `_${tier + 1}` : ""}`); this.icon.setFrame(achv.getIconImage()); - this.titleText.setText(achv.getName()); + this.titleText.setText(achv.getName(this.playerGender)); this.scoreText.setVisible(achv instanceof Achv); if (achv instanceof Achv) { this.descriptionText.setText(getAchievementDescription((achv as Achv).localizationKey)); @@ -96,13 +99,13 @@ export default class AchvBar extends Phaser.GameObjects.Container { ease: "Sine.easeOut" }); - this.scene.time.delayedCall(10000, () => this.hide()); + this.scene.time.delayedCall(10000, () => this.hide(this.playerGender)); this.setVisible(true); this.shown = true; } - protected hide(): void { + protected hide(playerGender: PlayerGender): void { if (!this.shown) { return; } diff --git a/src/ui/achvs-ui-handler.ts b/src/ui/achvs-ui-handler.ts index a73f7560282..464a967cbfd 100644 --- a/src/ui/achvs-ui-handler.ts +++ b/src/ui/achvs-ui-handler.ts @@ -3,9 +3,11 @@ import { Button } from "../enums/buttons"; import i18next from "../plugins/i18n"; import { Achv, achvs, getAchievementDescription } from "../system/achv"; import MessageUiHandler from "./message-ui-handler"; -import { TextStyle, addTextObject } from "./text"; +import { addTextObject, TextStyle } from "./text"; import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; +import { PlayerGender } from "#app/data/enums/player-gender"; +import { ParseKeys } from "i18next"; export default class AchvsUiHandler extends MessageUiHandler { private achvsContainer: Phaser.GameObjects.Container; @@ -33,7 +35,14 @@ export default class AchvsUiHandler extends MessageUiHandler { const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24); headerBg.setOrigin(0, 0); - const headerText = addTextObject(this.scene, 0, 0, i18next.t("achv:Achievements.name"), TextStyle.SETTINGS_LABEL); + // We need to get the player gender from the game data to add the correct prefix to the achievement name + const playerGender = this.scene.gameData.gender; + let genderPrefix = "PGM"; + if (playerGender === PlayerGender.FEMALE) { + genderPrefix = "PGF"; + } + + const headerText = addTextObject(this.scene, 0, 0, i18next.t(`${genderPrefix}achv:Achievements.name` as ParseKeys), TextStyle.SETTINGS_LABEL); headerText.setOrigin(0, 0); headerText.setPositionRelative(headerBg, 8, 4); @@ -137,7 +146,14 @@ export default class AchvsUiHandler extends MessageUiHandler { } protected showAchv(achv: Achv) { - achv.name = i18next.t(`achv:${achv.localizationKey}.name`); + // We need to get the player gender from the game data to add the correct prefix to the achievement name + const playerGender = this.scene.gameData.gender; + let genderPrefix = "PGM"; + if (playerGender === PlayerGender.FEMALE) { + genderPrefix = "PGF"; + } + + achv.name = i18next.t(`${genderPrefix}achv:${achv.localizationKey}.name` as ParseKeys); achv.description = getAchievementDescription(achv.localizationKey); const achvUnlocks = this.scene.gameData.achvUnlocks; const unlocked = achvUnlocks.hasOwnProperty(achv.id); @@ -145,7 +161,7 @@ export default class AchvsUiHandler extends MessageUiHandler { this.titleText.setText(unlocked ? achv.name : "???"); this.showText(!hidden ? achv.description : ""); this.scoreText.setText(`${achv.score}pt`); - this.unlockText.setText(unlocked ? new Date(achvUnlocks[achv.id]).toLocaleDateString() : i18next.t("achv:Locked.name")); + this.unlockText.setText(unlocked ? new Date(achvUnlocks[achv.id]).toLocaleDateString() : i18next.t(`${genderPrefix}achv:Locked.name` as ParseKeys)); } processInput(button: Button): boolean { diff --git a/src/ui/battle-flyout.ts b/src/ui/battle-flyout.ts index 9a9e3ef46a9..956ea65fd83 100644 --- a/src/ui/battle-flyout.ts +++ b/src/ui/battle-flyout.ts @@ -55,6 +55,9 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { /** The array of {@linkcode MoveInfo} used to track moves for the {@linkcode Pokemon} linked to the flyout */ private moveInfo: MoveInfo[] = new Array(); + /** Current state of the flyout's visibility */ + public flyoutVisible: boolean = false; + // Stores callbacks in a variable so they can be unsubscribed from when destroyed private readonly onMoveUsedEvent = (event: Event) => this.onMoveUsed(event); private readonly onBerryUsedEvent = (event: Event) => this.onBerryUsed(event); @@ -170,6 +173,8 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { /** Animates the flyout to either show or hide it by applying a fade and translation */ toggleFlyout(visible: boolean): void { + this.flyoutVisible = visible; + this.scene.tweens.add({ targets: this.flyoutParent, x: visible ? this.anchorX : this.anchorX - this.translationX, diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index 9fb81f89698..c246af73d07 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -9,6 +9,7 @@ import { Type, getTypeRgb } from "../data/type"; import { getVariantTint } from "#app/data/variant"; import { BattleStat } from "#app/data/battle-stat"; import BattleFlyout from "./battle-flyout"; +import { WindowVariant, addWindow } from "./ui-theme"; const battleStatOrder = [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.ACC, BattleStat.EVA, BattleStat.SPD ]; @@ -52,6 +53,13 @@ export default class BattleInfo extends Phaser.GameObjects.Container { private type3Icon: Phaser.GameObjects.Sprite; private expBar: Phaser.GameObjects.Image; + // #region Type effectiveness hint objects + private effectivenessContainer: Phaser.GameObjects.Container; + private effectivenessWindow: Phaser.GameObjects.NineSlice; + private effectivenessText: Phaser.GameObjects.Text; + private currentEffectiveness?: string; + // #endregion + public expMaskRect: Phaser.GameObjects.Graphics; private statsContainer: Phaser.GameObjects.Container; @@ -59,7 +67,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { private statValuesContainer: Phaser.GameObjects.Container; private statNumbers: Phaser.GameObjects.Sprite[]; - public flyoutMenu: BattleFlyout; + public flyoutMenu?: BattleFlyout; constructor(scene: Phaser.Scene, x: number, y: number, player: boolean) { super(scene, x, y); @@ -250,6 +258,19 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.type3Icon.setName("icon_type_3"); this.type3Icon.setOrigin(0, 0); this.add(this.type3Icon); + + if (!this.player) { + this.effectivenessContainer = this.scene.add.container(0, 0); + this.effectivenessContainer.setPositionRelative(this.type1Icon, 22, 4); + this.effectivenessContainer.setVisible(false); + this.add(this.effectivenessContainer); + + this.effectivenessText = addTextObject(this.scene, 5, 4.5, "", TextStyle.BATTLE_INFO); + this.effectivenessWindow = addWindow((this.scene as BattleScene), 0, 0, 0, 20, false, false, null, null, WindowVariant.XTHIN); + + this.effectivenessContainer.add(this.effectivenessWindow); + this.effectivenessContainer.add(this.effectivenessText); + } } initInfo(pokemon: Pokemon) { @@ -711,6 +732,39 @@ export default class BattleInfo extends Phaser.GameObjects.Container { }); } + /** + * Request the flyoutMenu to toggle if available and hides or shows the effectiveness window where necessary + */ + toggleFlyout(visible: boolean): void { + this.flyoutMenu?.toggleFlyout(visible); + + if (visible) { + this.effectivenessContainer?.setVisible(false); + } else { + this.updateEffectiveness(this.currentEffectiveness); + } + } + + /** + * Show or hide the type effectiveness multiplier window + * Passing undefined will hide the window + */ + updateEffectiveness(effectiveness?: string) { + if (this.player) { + return; + } + this.currentEffectiveness = effectiveness; + + if (!(this.scene as BattleScene).typeHints || effectiveness === undefined || this.flyoutMenu.flyoutVisible) { + this.effectivenessContainer.setVisible(false); + return; + } + + this.effectivenessText.setText(effectiveness); + this.effectivenessWindow.width = 10 + this.effectivenessText.displayWidth; + this.effectivenessContainer.setVisible(true); + } + getBaseY(): number { return this.baseY; } diff --git a/src/ui/challenges-select-ui-handler.ts b/src/ui/challenges-select-ui-handler.ts new file mode 100644 index 00000000000..092d954eae7 --- /dev/null +++ b/src/ui/challenges-select-ui-handler.ts @@ -0,0 +1,330 @@ +import BattleScene from "../battle-scene"; +import { TextStyle, addTextObject } from "./text"; +import { Mode } from "./ui"; +import UiHandler from "./ui-handler"; +import { addWindow } from "./ui-theme"; +import {Button} from "../enums/buttons"; +import i18next from "#app/plugins/i18n.js"; +import { SelectStarterPhase, TitlePhase } from "#app/phases.js"; +import { Challenge } from "#app/data/challenge.js"; + +/** + * Handles all the UI for choosing optional challenges. + */ +export default class GameChallengesUiHandler extends UiHandler { + private challengesContainer: Phaser.GameObjects.Container; + private valuesContainer: Phaser.GameObjects.Container; + + private scrollCursor: integer; + + private optionsBg: Phaser.GameObjects.NineSlice; + + // private difficultyText: Phaser.GameObjects.Text; + + private descriptionText: Phaser.GameObjects.Text; + + private challengeLabels: Phaser.GameObjects.Text[]; + private challengeValueLabels: Phaser.GameObjects.Text[]; + + private cursorObj: Phaser.GameObjects.NineSlice; + + private startCursor: Phaser.GameObjects.NineSlice; + + constructor(scene: BattleScene, mode?: Mode) { + super(scene, mode); + } + + setup() { + const ui = this.getUi(); + + this.challengesContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1); + + this.challengesContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains); + + // TODO: Change this back to /9 when adding in difficulty + const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6), 24); + headerBg.setOrigin(0, 0); + + const headerText = addTextObject(this.scene, 0, 0, i18next.t("challenges:title"), TextStyle.SETTINGS_LABEL); + headerText.setOrigin(0, 0); + headerText.setPositionRelative(headerBg, 8, 4); + + // const difficultyBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 18) - 2, 24); + // difficultyBg.setOrigin(0, 0); + // difficultyBg.setPositionRelative(headerBg, headerBg.width, 0); + + // this.difficultyText = addTextObject(this.scene, 0, 0, "0", TextStyle.SETTINGS_LABEL); + // this.difficultyText.setOrigin(0, 0); + // this.difficultyText.setPositionRelative(difficultyBg, 8, 4); + + // const difficultyName = addTextObject(this.scene, 0, 0, i18next.t("challenges:points"), TextStyle.SETTINGS_LABEL); + // difficultyName.setOrigin(0, 0); + // difficultyName.setPositionRelative(difficultyBg, difficultyBg.width - difficultyName.displayWidth - 8, 4); + + this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 9), (this.scene.game.canvas.height / 6) - headerBg.height - 2); + this.optionsBg.setOrigin(0, 0); + + const descriptionBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 18) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 26); + descriptionBg.setOrigin(0, 0); + descriptionBg.setPositionRelative(this.optionsBg, this.optionsBg.width, 0); + + this.descriptionText = addTextObject(this.scene, 0, 0, "", TextStyle.SETTINGS_LABEL); + this.descriptionText.setOrigin(0, 0); + this.descriptionText.setWordWrapWidth(500, true); + this.descriptionText.setPositionRelative(descriptionBg, 6, 4); + + const startBg = addWindow(this.scene, 0, 0, descriptionBg.width, 24); + startBg.setOrigin(0, 0); + startBg.setPositionRelative(descriptionBg, 0, descriptionBg.height); + + const startText = addTextObject(this.scene, 0, 0, i18next.t("challenges:start"), TextStyle.SETTINGS_LABEL); + startText.setOrigin(0, 0); + startText.setPositionRelative(startBg, 8, 4); + + this.startCursor = this.scene.add.nineslice(0, 0, "summary_moves_cursor", null, (this.scene.game.canvas.width / 18) - 10, 16, 1, 1, 1, 1); + this.startCursor.setOrigin(0, 0); + this.startCursor.setPositionRelative(startBg, 4, 4); + this.startCursor.setVisible(false); + + this.valuesContainer = this.scene.add.container(0, 0); + + this.challengeLabels = []; + this.challengeValueLabels = []; + + for (let i = 0; i < 9; i++) { + this.challengeLabels[i] = addTextObject(this.scene, 8, 28 + i * 16, "", TextStyle.SETTINGS_LABEL); + this.challengeLabels[i].setOrigin(0, 0); + + this.valuesContainer.add(this.challengeLabels[i]); + + this.challengeValueLabels[i] = addTextObject(this.scene, 0, 28 + i * 16, "", TextStyle.SETTINGS_LABEL); + this.challengeValueLabels[i].setPositionRelative(this.challengeLabels[i], 100, 0); + + this.valuesContainer.add(this.challengeValueLabels[i]); + } + + this.challengesContainer.add(headerBg); + this.challengesContainer.add(headerText); + // this.challengesContainer.add(difficultyBg); + // this.challengesContainer.add(this.difficultyText); + // this.challengesContainer.add(difficultyName); + this.challengesContainer.add(this.optionsBg); + this.challengesContainer.add(descriptionBg); + this.challengesContainer.add(this.descriptionText); + this.challengesContainer.add(startBg); + this.challengesContainer.add(startText); + this.challengesContainer.add(this.startCursor); + this.challengesContainer.add(this.valuesContainer); + + ui.add(this.challengesContainer); + + this.setCursor(0); + this.setScrollCursor(0); + + this.challengesContainer.setVisible(false); + } + + + updateText(): void { + if (this.scene.gameMode.challenges.length > 0) { + this.descriptionText.text = this.getActiveChallenge().getDescription(); + this.descriptionText.updateText(); + } + + // const totalDifficulty = this.scene.gameMode.challenges.reduce((v, c) => v + c.getDifficulty(), 0); + // const totalMinDifficulty = this.scene.gameMode.challenges.reduce((v, c) => v + c.getMinDifficulty(), 0); + // this.difficultyText.text = `${totalDifficulty}` + (totalMinDifficulty ? `/${totalMinDifficulty}` : ""); + // this.difficultyText.updateText(); + + for (let i = 0; i < this.challengeLabels.length; i++) { + if (i + this.scrollCursor < this.scene.gameMode.challenges.length) { + this.challengeLabels[i].setVisible(true); + this.challengeValueLabels[i].setVisible(true); + this.challengeLabels[i].text = this.scene.gameMode.challenges[i + this.scrollCursor].getName(); + this.challengeValueLabels[i].text = this.scene.gameMode.challenges[i + this.scrollCursor].getValue(); + this.challengeLabels[i].updateText(); + this.challengeValueLabels[i].updateText(); + } else { + this.challengeLabels[i].setVisible(false); + this.challengeValueLabels[i].setVisible(false); + } + } + } + + show(args: any[]): boolean { + super.show(args); + + this.startCursor.setVisible(false); + this.challengesContainer.setVisible(true); + this.setCursor(0); + + this.updateText(); + + this.getUi().moveTo(this.challengesContainer, this.getUi().length - 1); + + this.getUi().hideTooltip(); + + return true; + } + + /** + * Processes input from a specified button. + * This method handles navigation through a UI menu, including movement through menu items + * and handling special actions like cancellation. Each button press may adjust the cursor + * position or the menu scroll, and plays a sound effect if the action was successful. + * + * @param button - The button pressed by the user. + * @returns `true` if the action associated with the button was successfully processed, `false` otherwise. + */ + processInput(button: Button): boolean { + const ui = this.getUi(); + // Defines the maximum number of rows that can be displayed on the screen. + const rowsToDisplay = 9; + + let success = false; + + if (button === Button.CANCEL) { + if (this.startCursor.visible) { + this.startCursor.setVisible(false); + this.cursorObj?.setVisible(true); + } else { + this.scene.clearPhaseQueue(); + this.scene.pushPhase(new TitlePhase(this.scene)); + this.scene.getCurrentPhase().end(); + } + success = true; + } else if (button === Button.SUBMIT || button === Button.ACTION) { + if (this.startCursor.visible) { + const totalDifficulty = this.scene.gameMode.challenges.reduce((v, c) => v + c.getDifficulty(), 0); + const totalMinDifficulty = this.scene.gameMode.challenges.reduce((v, c) => v + c.getMinDifficulty(), 0); + if (totalDifficulty >= totalMinDifficulty) { + this.scene.unshiftPhase(new SelectStarterPhase(this.scene)); + this.scene.getCurrentPhase().end(); + success = true; + } else { + success = false; + } + } else { + this.startCursor.setVisible(true); + this.cursorObj?.setVisible(false); + success = true; + } + } else { + switch (button) { + case Button.UP: + if (this.cursor === 0) { + if (this.scrollCursor === 0) { + // When at the top of the menu and pressing UP, move to the bottommost item. + if (this.scene.gameMode.challenges.length > rowsToDisplay) { // If there are more than 9 challenges, scroll to the bottom + // First, set the cursor to the last visible element, preparing for the scroll to the end. + const successA = this.setCursor(rowsToDisplay - 1); + // Then, adjust the scroll to display the bottommost elements of the menu. + const successB = this.setScrollCursor(this.scene.gameMode.challenges.length - rowsToDisplay); + success = successA && successB; // success is just there to play the little validation sound effect + } else { // If there are 9 or less challenges, just move to the bottom one + success = this.setCursor(this.scene.gameMode.challenges.length - 1); + } + } else { + success = this.setScrollCursor(this.scrollCursor - 1); + } + } else { + success = this.setCursor(this.cursor - 1); + } + if (success) { + this.updateText(); + } + break; + case Button.DOWN: + if (this.cursor === rowsToDisplay - 1) { + if (this.scrollCursor < this.scene.gameMode.challenges.length - rowsToDisplay) { + // When at the bottom and pressing DOWN, scroll if possible. + success = this.setScrollCursor(this.scrollCursor + 1); + } else { + // When at the bottom of a scrolling menu and pressing DOWN, move to the topmost item. + // First, set the cursor to the first visible element, preparing for the scroll to the top. + const successA = this.setCursor(0); + // Then, adjust the scroll to display the topmost elements of the menu. + const successB = this.setScrollCursor(0); + success = successA && successB; // success is just there to play the little validation sound effect + } + } else if (this.scene.gameMode.challenges.length < rowsToDisplay && this.cursor === this.scene.gameMode.challenges.length - 1) { + // When at the bottom of a non-scrolling menu and pressing DOWN, move to the topmost item. + success = this.setCursor(0); + } else { + success = this.setCursor(this.cursor + 1); + } + if (success) { + this.updateText(); + } + break; + case Button.LEFT: + // Moves the option cursor left, if possible. + success = this.getActiveChallenge().decreaseValue(); + if (success) { + this.updateText(); + } + break; + case Button.RIGHT: + // Moves the option cursor right, if possible. + success = this.getActiveChallenge().increaseValue(); + if (success) { + this.updateText(); + } + break; + } + } + + // Plays a select sound effect if an action was successfully processed. + if (success) { + ui.playSelect(); + } + + return success; + } + + setCursor(cursor: integer): boolean { + let ret = super.setCursor(cursor); + + if (!this.cursorObj) { + this.cursorObj = this.scene.add.nineslice(0, 0, "summary_moves_cursor", null, (this.scene.game.canvas.width / 9) - 10, 16, 1, 1, 1, 1); + this.cursorObj.setOrigin(0, 0); + this.valuesContainer.add(this.cursorObj); + } + + ret ||= !this.cursorObj.visible; + this.cursorObj.setVisible(true); + + this.cursorObj.setPositionRelative(this.optionsBg, 4, 4 + (this.cursor + this.scrollCursor) * 16); + + return ret; + } + + setScrollCursor(scrollCursor: integer): boolean { + if (scrollCursor === this.scrollCursor) { + return false; + } + + this.scrollCursor = scrollCursor; + + this.setCursor(this.cursor); + + return true; + } + + getActiveChallenge(): Challenge { + return this.scene.gameMode.challenges[this.cursor + this.scrollCursor]; + } + + clear() { + super.clear(); + this.challengesContainer.setVisible(false); + this.eraseCursor(); + } + + eraseCursor() { + if (this.cursorObj) { + this.cursorObj.destroy(); + } + this.cursorObj = null; + } +} diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index acbf66b7075..0ed3671ad18 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -1,6 +1,6 @@ import BattleScene from "../battle-scene"; import { addTextObject, TextStyle } from "./text"; -import { Type } from "../data/type"; +import { getTypeDamageMultiplierColor, Type } from "../data/type"; import { Command } from "./command-ui-handler"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; @@ -9,6 +9,7 @@ import { CommandPhase } from "../phases"; import { MoveCategory } from "#app/data/move.js"; import i18next from "../plugins/i18n"; import {Button} from "../enums/buttons"; +import Pokemon, { PokemonMove } from "#app/field/pokemon.js"; export default class FightUiHandler extends UiHandler { private movesContainer: Phaser.GameObjects.Container; @@ -162,7 +163,8 @@ export default class FightUiHandler extends UiHandler { ui.add(this.cursorObj); } - const moveset = (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getMoveset(); + const pokemon = (this.scene.getCurrentPhase() as CommandPhase).getPokemon(); + const moveset = pokemon.getMoveset(); const hasMove = cursor < moveset.length; @@ -177,8 +179,24 @@ export default class FightUiHandler extends UiHandler { const pp = maxPP - pokemonMove.ppUsed; this.ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`); + const ppPercentLeft = pp / maxPP; + let ppColor = "white"; + if (ppPercentLeft <= 0.5) { + ppColor = "yellow"; + } + if (ppPercentLeft <= 0.25) { + ppColor = "orange"; + } + if (pp === 0) { + ppColor = "red"; + } + this.ppText.setColor(ppColor); this.powerText.setText(`${power >= 0 ? power : "---"}`); this.accuracyText.setText(`${accuracy >= 0 ? accuracy : "---"}`); + + pokemon.getOpponents().forEach((opponent) => { + opponent.updateEffectiveness(this.getEffectivenessText(pokemon, opponent, pokemonMove)); + }); } this.typeIcon.setVisible(hasMove); @@ -195,17 +213,60 @@ export default class FightUiHandler extends UiHandler { return changed; } + /** + * Gets multiplier text for a pokemon's move against a specific opponent + * Returns undefined if it's a status move + */ + private getEffectivenessText(pokemon: Pokemon, opponent: Pokemon, pokemonMove: PokemonMove): string | undefined { + const effectiveness = opponent.getMoveEffectiveness(pokemon, pokemonMove); + if (effectiveness === undefined) { + return undefined; + } + + return `${effectiveness}x`; + } + displayMoves() { - const moveset = (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getMoveset(); - for (let m = 0; m < 4; m++) { - const moveText = addTextObject(this.scene, m % 2 === 0 ? 0 : 100, m < 2 ? 0 : 16, "-", TextStyle.WINDOW); - if (m < moveset.length) { - moveText.setText(moveset[m].getName()); + const pokemon = (this.scene.getCurrentPhase() as CommandPhase).getPokemon(); + const moveset = pokemon.getMoveset(); + + for (let moveIndex = 0; moveIndex < 4; moveIndex++) { + const moveText = addTextObject(this.scene, moveIndex % 2 === 0 ? 0 : 100, moveIndex < 2 ? 0 : 16, "-", TextStyle.WINDOW); + + if (moveIndex < moveset.length) { + const pokemonMove = moveset[moveIndex]; + moveText.setText(pokemonMove.getName()); + moveText.setColor(this.getMoveColor(pokemon, pokemonMove) ?? moveText.style.color); } + this.movesContainer.add(moveText); } } + /** + * Returns a specific move's color based on its type effectiveness against opponents + * If there are multiple opponents, the highest effectiveness' color is returned + * @returns A color or undefined if the default color should be used + */ + private getMoveColor(pokemon: Pokemon, pokemonMove: PokemonMove): string | undefined { + if (!this.scene.typeHints) { + return undefined; + } + + const opponents = pokemon.getOpponents(); + if (opponents.length <= 0) { + return undefined; + } + + const moveColors = opponents.map((opponent) => { + return opponent.getMoveEffectiveness(pokemon, pokemonMove); + }).sort((a, b) => b - a).map((effectiveness) => { + return getTypeDamageMultiplierColor(effectiveness, "offense"); + }); + + return moveColors[0]; + } + clear() { super.clear(); this.clearMoves(); @@ -222,6 +283,11 @@ export default class FightUiHandler extends UiHandler { clearMoves() { this.movesContainer.removeAll(true); + + const opponents = (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getOpponents(); + opponents.forEach((opponent) => { + opponent.updateEffectiveness(undefined); + }); } eraseCursor() { diff --git a/src/ui/game-stats-ui-handler.ts b/src/ui/game-stats-ui-handler.ts index 86b4e71f72d..57a02257810 100644 --- a/src/ui/game-stats-ui-handler.ts +++ b/src/ui/game-stats-ui-handler.ts @@ -1,3 +1,4 @@ +import Phaser from "phaser"; import BattleScene from "../battle-scene"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; @@ -88,7 +89,7 @@ const displayStats: DisplayStats = { }, highestMoney: { label_key: "highestMoney", - sourceFunc: gameData => Utils.formatFancyLargeNumber(gameData.gameStats.highestMoney, 3), + sourceFunc: gameData => Utils.formatFancyLargeNumber(gameData.gameStats.highestMoney), }, highestDamage: { label_key: "highestDamage", diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index f6738a33d98..9a17f6e344d 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -9,6 +9,7 @@ import { handleTutorial, Tutorial } from "../tutorial"; import {Button} from "../enums/buttons"; import MoveInfoOverlay from "./move-info-overlay"; import { allMoves } from "../data/move"; +import * as Utils from "./../utils"; export const SHOP_OPTIONS_ROW_LIMIT = 6; @@ -17,9 +18,11 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { private rerollButtonContainer: Phaser.GameObjects.Container; private lockRarityButtonContainer: Phaser.GameObjects.Container; private transferButtonContainer: Phaser.GameObjects.Container; + private checkButtonContainer: Phaser.GameObjects.Container; private rerollCostText: Phaser.GameObjects.Text; private lockRarityButtonText: Phaser.GameObjects.Text; private moveInfoOverlay : MoveInfoOverlay; + private moveInfoOverlayActive : boolean = false; private rowCursor: integer = 0; private player: boolean; @@ -43,7 +46,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.modifierContainer = this.scene.add.container(0, 0); ui.add(this.modifierContainer); - this.transferButtonContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 1, -64); + this.transferButtonContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 71, -64); this.transferButtonContainer.setName("container-transfer-btn"); this.transferButtonContainer.setVisible(false); ui.add(this.transferButtonContainer); @@ -53,6 +56,16 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { transferButtonText.setOrigin(1, 0); this.transferButtonContainer.add(transferButtonText); + this.checkButtonContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 1, -64); + this.checkButtonContainer.setName("container-use-btn"); + this.checkButtonContainer.setVisible(false); + ui.add(this.checkButtonContainer); + + const checkButtonText = addTextObject(this.scene, -4, -2, "Check Team", TextStyle.PARTY); + checkButtonText.setName("text-use-btn"); + checkButtonText.setOrigin(1, 0); + this.checkButtonContainer.add(checkButtonText); + this.rerollButtonContainer = this.scene.add.container(16, -64); this.rerollButtonContainer.setName("container-reroll-brn"); this.rerollButtonContainer.setVisible(false); @@ -99,6 +112,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.awaitingActionInput = true; this.onActionInput = args[2]; } + this.moveInfoOverlay.active = this.moveInfoOverlayActive; return false; } @@ -118,6 +132,9 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.transferButtonContainer.setVisible(false); this.transferButtonContainer.setAlpha(0); + this.checkButtonContainer.setVisible(false); + this.checkButtonContainer.setAlpha(0); + this.rerollButtonContainer.setVisible(false); this.rerollButtonContainer.setAlpha(0); @@ -201,12 +218,14 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { } this.rerollButtonContainer.setAlpha(0); + this.checkButtonContainer.setAlpha(0); this.lockRarityButtonContainer.setAlpha(0); this.rerollButtonContainer.setVisible(true); + this.checkButtonContainer.setVisible(true); this.lockRarityButtonContainer.setVisible(canLockRarities); this.scene.tweens.add({ - targets: [ this.rerollButtonContainer, this.lockRarityButtonContainer ], + targets: [ this.rerollButtonContainer, this.lockRarityButtonContainer, this.checkButtonContainer ], alpha: 1, duration: 250 }); @@ -242,6 +261,10 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { if (!originalOnActionInput(this.rowCursor, this.cursor)) { this.awaitingActionInput = true; this.onActionInput = originalOnActionInput; + } else { + this.moveInfoOverlayActive = this.moveInfoOverlay.active; + this.moveInfoOverlay.setVisible(false); + this.moveInfoOverlay.active = false; // this is likely unnecessary, but it should help future prove the UI } } } else if (button === Button.CANCEL) { @@ -252,12 +275,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.awaitingActionInput = false; this.onActionInput = null; originalOnActionInput(-1); + this.moveInfoOverlayActive = this.moveInfoOverlay.active; + this.moveInfoOverlay.setVisible(false); + this.moveInfoOverlay.active = false; // don't clear here as we might need to restore the UI in case the user cancels the action } } } else { switch (button) { case Button.UP: - if (!this.rowCursor && this.cursor === 2) { + if (this.rowCursor === 0 && this.cursor === 3) { success = this.setCursor(0); } else if (this.rowCursor < this.shopOptionsRows.length + 1) { success = this.setRowCursor(this.rowCursor + 1); @@ -266,13 +292,29 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { case Button.DOWN: if (this.rowCursor) { success = this.setRowCursor(this.rowCursor - 1); - } else if (this.lockRarityButtonContainer.visible && !this.cursor) { - success = this.setCursor(2); + } else if (this.lockRarityButtonContainer.visible && this.cursor === 0) { + success = this.setCursor(3); } break; case Button.LEFT: if (!this.rowCursor) { - success = this.cursor === 1 && this.rerollButtonContainer.visible && this.setCursor(0); + switch (this.cursor) { + case 0: + success = false; + break; + case 1: + success = this.rerollButtonContainer.visible && this.setCursor(0); + break; + case 2: + if (this.transferButtonContainer.visible) { + success = this.setCursor(1); + } else if (this.rerollButtonContainer.visible) { + success = this.setCursor(0); + } else { + success = false; + } + break; + } } else if (this.cursor) { success = this.setCursor(this.cursor - 1); } else if (this.rowCursor === 1 && this.rerollButtonContainer.visible) { @@ -281,7 +323,21 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { break; case Button.RIGHT: if (!this.rowCursor) { - success = this.cursor !== 1 && this.transferButtonContainer.visible && this.setCursor(1); + switch (this.cursor) { + case 0: + if (this.transferButtonContainer.visible) { + success = this.setCursor(1); + } else { + success = this.setCursor(2); + } + break; + case 1: + success = this.setCursor(2); + break; + case 2: + success = false; + break; + } } else if (this.cursor < this.getRowItems(this.rowCursor) - 1) { success = this.setCursor(this.cursor + 1); } else if (this.rowCursor === 1 && this.transferButtonContainer.visible) { @@ -327,12 +383,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { // prepare the move overlay to be shown with the toggle this.moveInfoOverlay.show(allMoves[type.moveId]); } - } else if (!cursor) { + } else if (cursor === 0) { this.cursorObj.setPosition(6, this.lockRarityButtonContainer.visible ? -72 : -60); ui.showText("Spend money to reroll your item options."); } else if (cursor === 1) { - this.cursorObj.setPosition((this.scene.game.canvas.width / 6) - 50, -60); + this.cursorObj.setPosition((this.scene.game.canvas.width / 6) - 120, -60); ui.showText("Transfer a held item from one Pokémon to another."); + } else if (cursor === 2) { + this.cursorObj.setPosition((this.scene.game.canvas.width / 6) - 60, -60); + ui.showText("Check your team or use a form changing item."); } else { this.cursorObj.setPosition(6, -60); ui.showText("Lock item rarities on reroll (affects reroll cost)."); @@ -344,14 +403,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { setRowCursor(rowCursor: integer): boolean { const lastRowCursor = this.rowCursor; - if (rowCursor !== lastRowCursor && (rowCursor || this.rerollButtonContainer.visible || this.transferButtonContainer.visible)) { + if (rowCursor !== lastRowCursor) { this.rowCursor = rowCursor; let newCursor = Math.round(this.cursor / Math.max(this.getRowItems(lastRowCursor) - 1, 1) * (this.getRowItems(rowCursor) - 1)); - if (!rowCursor) { - if (!newCursor && !this.rerollButtonContainer.visible) { + if (rowCursor === 0) { + if (newCursor === 0 && !this.rerollButtonContainer.visible) { newCursor = 1; - } else if (newCursor && !this.transferButtonContainer.visible) { - newCursor = 0; + } + if (newCursor === 1 && !this.transferButtonContainer.visible) { + newCursor = 2; } } this.cursor = -1; @@ -365,7 +425,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { private getRowItems(rowCursor: integer): integer { switch (rowCursor) { case 0: - return 2; + return 3; case 1: return this.options.length; default: @@ -389,7 +449,9 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { updateRerollCostText(): void { const canReroll = this.scene.money >= this.rerollCost; - this.rerollCostText.setText(`₽${this.rerollCost.toLocaleString("en-US")}`); + const formattedMoney = Utils.formatMoney(this.scene.moneyFormat, this.rerollCost); + + this.rerollCostText.setText(`₽${formattedMoney}`); this.rerollCostText.setColor(this.getTextColor(canReroll ? TextStyle.MONEY : TextStyle.PARTY_RED)); this.rerollCostText.setShadowColor(this.getTextColor(canReroll ? TextStyle.MONEY : TextStyle.PARTY_RED, true)); } @@ -403,6 +465,8 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { clear() { super.clear(); + this.moveInfoOverlay.clear(); + this.moveInfoOverlayActive = false; this.awaitingActionInput = false; this.onActionInput = null; this.getUi().clearText(); @@ -423,7 +487,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { onComplete: () => options.forEach(o => o.destroy()) }); - [ this.rerollButtonContainer, this.transferButtonContainer, this.lockRarityButtonContainer ].forEach(container => { + [ this.rerollButtonContainer, this.checkButtonContainer, this.transferButtonContainer, this.lockRarityButtonContainer ].forEach(container => { if (container.visible) { this.scene.tweens.add({ targets: container, @@ -645,7 +709,9 @@ class ModifierOption extends Phaser.GameObjects.Container { const scene = this.scene as BattleScene; const textStyle = this.modifierTypeOption.cost <= scene.money ? TextStyle.MONEY : TextStyle.PARTY_RED; - this.itemCostText.setText(`₽${this.modifierTypeOption.cost.toLocaleString("en-US")}`); + const formattedMoney = Utils.formatMoney(scene.moneyFormat, this.modifierTypeOption.cost); + + this.itemCostText.setText(`₽${formattedMoney}`); this.itemCostText.setColor(getTextColor(textStyle, false, scene.uiTheme)); this.itemCostText.setShadowColor(getTextColor(textStyle, true, scene.uiTheme)); } diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index c51fea747a9..d965345d3de 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { CommandPhase } from "../phases"; +import { CommandPhase, SelectModifierPhase } from "../phases"; import BattleScene from "../battle-scene"; import { PlayerPokemon, PokemonMove } from "../field/pokemon"; import { addTextObject, TextStyle } from "./text"; @@ -17,7 +17,9 @@ import { addWindow } from "./ui-theme"; import { SpeciesFormChangeItemTrigger } from "../data/pokemon-forms"; import { getVariantTint } from "#app/data/variant"; import {Button} from "../enums/buttons"; +import { applyChallenges, ChallengeType } from "#app/data/challenge.js"; import MoveInfoOverlay from "./move-info-overlay"; +import i18next from "i18next"; const defaultMessage = "Choose a Pokémon."; @@ -32,7 +34,8 @@ export enum PartyUiMode { REMEMBER_MOVE_MODIFIER, MODIFIER_TRANSFER, SPLICE, - RELEASE + RELEASE, + CHECK } export enum PartyOption { @@ -119,6 +122,20 @@ export default class PartyUiHandler extends MessageUiHandler { return null; }; + /** + * For consistency reasons, this looks like the above filters. However this is used only internally and is always enforced for switching. + * @param pokemon The pokemon to check. + * @returns + */ + private FilterChallengeLegal = (pokemon: PlayerPokemon) => { + const challengeAllowed = new Utils.BooleanHolder(true); + applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, pokemon, challengeAllowed); + if (!challengeAllowed.value) { + return `${pokemon.name} can't be used in\nthis challenge!`; + } + return null; + }; + private static FilterAllMoves = (_pokemonMove: PokemonMove) => null; public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => { @@ -131,6 +148,8 @@ export default class PartyUiHandler extends MessageUiHandler { public static NoEffectMessage = "It won't have any effect."; + private localizedOptions = [PartyOption.SEND_OUT, PartyOption.SUMMARY, PartyOption.CANCEL, PartyOption.APPLY, PartyOption.RELEASE, PartyOption.TEACH]; + constructor(scene: BattleScene) { super(scene, Mode.PARTY); } @@ -277,6 +296,9 @@ export default class PartyUiHandler extends MessageUiHandler { let filterResult: string; if (option !== PartyOption.TRANSFER && option !== PartyOption.SPLICE) { filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon); + if (filterResult === null && (option === PartyOption.SEND_OUT || option === PartyOption.PASS_BATON)) { + filterResult = this.FilterChallengeLegal(pokemon); + } if (filterResult === null && this.partyUiMode === PartyUiMode.MOVE_MODIFIER) { filterResult = this.moveSelectFilter(pokemon.moveset[this.optionsCursor]); } @@ -290,7 +312,7 @@ export default class PartyUiHandler extends MessageUiHandler { if (this.partyUiMode !== PartyUiMode.SPLICE) { this.clearOptions(); } - if (this.selectCallback) { + if (this.selectCallback && this.partyUiMode !== PartyUiMode.CHECK) { if (option === PartyOption.TRANSFER) { if (this.transferCursor !== this.cursor) { (this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.transferQuantities[this.transferOptionCursor], this.cursor); @@ -312,11 +334,8 @@ export default class PartyUiHandler extends MessageUiHandler { selectCallback(this.cursor, option); } } else { - if (option >= PartyOption.FORM_CHANGE_ITEM && this.scene.getCurrentPhase() instanceof CommandPhase) { - switch (this.partyUiMode) { - case PartyUiMode.SWITCH: - case PartyUiMode.FAINT_SWITCH: - case PartyUiMode.POST_BATTLE_SWITCH: + if (option >= PartyOption.FORM_CHANGE_ITEM && this.scene.getCurrentPhase() instanceof SelectModifierPhase) { + if (this.partyUiMode === PartyUiMode.CHECK) { let formChangeItemModifiers = this.scene.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[]; if (formChangeItemModifiers.find(m => m.active)) { formChangeItemModifiers = formChangeItemModifiers.filter(m => m.active); @@ -324,7 +343,6 @@ export default class PartyUiHandler extends MessageUiHandler { const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM]; modifier.active = !modifier.active; this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeItemTrigger, false, true); - break; } } else if (this.cursor) { (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor, option === PartyOption.PASS_BATON); @@ -370,7 +388,7 @@ export default class PartyUiHandler extends MessageUiHandler { } else if (option === PartyOption.RELEASE) { this.clearOptions(); ui.playSelect(); - if (this.cursor >= this.scene.currentBattle.getBattlerCount()) { + if (this.cursor >= this.scene.currentBattle.getBattlerCount() || !pokemon.isAllowedInBattle()) { this.showText(`Do you really want to release ${pokemon.name}?`, null, () => { ui.setModeWithoutClear(Mode.CONFIRM, () => { ui.setMode(Mode.PARTY); @@ -687,15 +705,6 @@ export default class PartyUiHandler extends MessageUiHandler { this.options.push(PartyOption.PASS_BATON); } } - if (this.scene.getCurrentPhase() instanceof CommandPhase) { - formChangeItemModifiers = this.scene.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[]; - if (formChangeItemModifiers.find(m => m.active)) { - formChangeItemModifiers = formChangeItemModifiers.filter(m => m.active); - } - for (let i = 0; i < formChangeItemModifiers.length; i++) { - this.options.push(PartyOption.FORM_CHANGE_ITEM + i); - } - } break; case PartyUiMode.REVIVAL_BLESSING: this.options.push(PartyOption.REVIVE); @@ -721,6 +730,17 @@ export default class PartyUiHandler extends MessageUiHandler { case PartyUiMode.RELEASE: this.options.push(PartyOption.RELEASE); break; + case PartyUiMode.CHECK: + if (this.scene.getCurrentPhase() instanceof SelectModifierPhase) { + formChangeItemModifiers = this.scene.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[]; + if (formChangeItemModifiers.find(m => m.active)) { + formChangeItemModifiers = formChangeItemModifiers.filter(m => m.active); + } + for (let i = 0; i < formChangeItemModifiers.length; i++) { + this.options.push(PartyOption.FORM_CHANGE_ITEM + i); + } + } + break; } this.options.push(PartyOption.SUMMARY); @@ -810,7 +830,11 @@ export default class PartyUiHandler extends MessageUiHandler { const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM]; optionName = `${modifier.active ? "Deactivate" : "Activate"} ${modifier.type.name}`; } else { - optionName = Utils.toReadableString(PartyOption[option]); + if (this.localizedOptions.includes(option)) { + optionName = i18next.t(`partyUiHandler:${PartyOption[option]}`); + } else { + optionName = Utils.toReadableString(PartyOption[option]); + } } break; } diff --git a/src/ui/save-slot-select-ui-handler.ts b/src/ui/save-slot-select-ui-handler.ts index d5dda05a519..e5417f83596 100644 --- a/src/ui/save-slot-select-ui-handler.ts +++ b/src/ui/save-slot-select-ui-handler.ts @@ -1,15 +1,15 @@ +import i18next from "i18next"; import BattleScene from "../battle-scene"; -import { gameModes } from "../game-mode"; +import { Button } from "../enums/buttons"; +import { GameMode } from "../game-mode"; +import { PokemonHeldItemModifier } from "../modifier/modifier"; import { SessionSaveData } from "../system/game-data"; +import PokemonData from "../system/pokemon-data"; +import * as Utils from "../utils"; +import MessageUiHandler from "./message-ui-handler"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; -import * as Utils from "../utils"; -import PokemonData from "../system/pokemon-data"; -import { PokemonHeldItemModifier } from "../modifier/modifier"; -import MessageUiHandler from "./message-ui-handler"; -import i18next from "i18next"; -import {Button} from "../enums/buttons"; const sessionSlotCount = 5; @@ -118,7 +118,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { originalCallback(cursor); }; if (this.sessionSlots[cursor].hasData) { - ui.showText("Overwrite the data in the selected slot?", null, () => { + ui.showText(i18next.t("saveSlotSelectUiHandler:overwriteData"), null, () => { ui.setOverlayMode(Mode.CONFIRM, () => saveAndCallback(), () => { ui.revertMode(); ui.showText(null, 0); @@ -258,7 +258,7 @@ class SessionSlot extends Phaser.GameObjects.Container { const slotWindow = addWindow(this.scene, 0, 0, 304, 52); this.add(slotWindow); - this.loadingLabel = addTextObject(this.scene, 152, 26, "Loading…", TextStyle.WINDOW); + this.loadingLabel = addTextObject(this.scene, 152, 26, i18next.t("saveSlotSelectUiHandler:loading"), TextStyle.WINDOW); this.loadingLabel.setOrigin(0.5, 0.5); this.add(this.loadingLabel); } @@ -266,7 +266,7 @@ class SessionSlot extends Phaser.GameObjects.Container { async setupWithData(data: SessionSaveData) { this.remove(this.loadingLabel, true); - const gameModeLabel = addTextObject(this.scene, 8, 5, `${gameModes[data.gameMode]?.getName() || "Unknown"} - Wave ${data.waveIndex}`, TextStyle.WINDOW); + const gameModeLabel = addTextObject(this.scene, 8, 5, `${GameMode.getModeName(data.gameMode) || i18next.t("gameMode:unkown")} - ${i18next.t("saveSlotSelectUiHandler:wave")} ${data.waveIndex}`, TextStyle.WINDOW); this.add(gameModeLabel); const timestampLabel = addTextObject(this.scene, 8, 19, new Date(data.timestamp).toLocaleString(), TextStyle.WINDOW); @@ -283,7 +283,7 @@ class SessionSlot extends Phaser.GameObjects.Container { const pokemon = p.toPokemon(this.scene); const icon = this.scene.addPokemonIcon(pokemon, 0, 0, 0, 0); - const text = addTextObject(this.scene, 32, 20, `Lv${Utils.formatLargeNumber(pokemon.level, 1000)}`, TextStyle.PARTY, { fontSize: "54px", color: "#f8f8f8" }); + const text = addTextObject(this.scene, 32, 20, `${i18next.t("saveSlotSelectUiHandler:lv")}${Utils.formatLargeNumber(pokemon.level, 1000)}`, TextStyle.PARTY, { fontSize: "54px", color: "#f8f8f8" }); text.setShadow(0, 0, null); text.setStroke("#424242", 14); text.setOrigin(1, 0); @@ -324,7 +324,7 @@ class SessionSlot extends Phaser.GameObjects.Container { this.scene.gameData.getSession(this.slotId).then(async sessionData => { if (!sessionData) { this.hasData = false; - this.loadingLabel.setText(i18next.t("menu:empty")); + this.loadingLabel.setText(i18next.t("saveSlotSelectUiHandler:empty")); resolve(false); return; } diff --git a/src/ui/settings/settings-display-ui-handler.ts b/src/ui/settings/settings-display-ui-handler.ts index 9e61c2ba0b2..0aed0689388 100644 --- a/src/ui/settings/settings-display-ui-handler.ts +++ b/src/ui/settings/settings-display-ui-handler.ts @@ -2,7 +2,7 @@ import BattleScene from "../../battle-scene"; import { Mode } from "../ui"; "#app/inputs-controller.js"; import AbstractSettingsUiHandler from "./abstract-settings-ui-handler"; -import { Setting, SettingType } from "#app/system/settings/settings"; +import { Setting, SettingKeys, SettingType } from "#app/system/settings/settings"; export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler { /** @@ -15,6 +15,48 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler super(scene, mode); this.title = "Display"; this.settings = Setting.filter(s => s.type === SettingType.DISPLAY); + + /** + * Update to current language from default value. + * - default value is 'English' + */ + const languageIndex = this.settings.findIndex(s => s.key === SettingKeys.Language); + if (languageIndex >= 0) { + const currentLocale = localStorage.getItem("prLang"); + switch (currentLocale) { + case "en": + this.settings[languageIndex].options[0] = "English"; + break; + case "es": + this.settings[languageIndex].options[0] = "Español"; + break; + case "it": + this.settings[languageIndex].options[0] = "Italiano"; + break; + case "fr": + this.settings[languageIndex].options[0] = "Français"; + break; + case "de": + this.settings[languageIndex].options[0] = "Deutsch"; + break; + case "pt-BR": + this.settings[languageIndex].options[0] = "Português (BR)"; + break; + case "zh-CN": + this.settings[languageIndex].options[0] = "简体中文"; + break; + case "zh-TW": + this.settings[languageIndex].options[0] = "繁體中文"; + break; + case "ko": + this.settings[languageIndex].options[0] = "한국어"; + break; + default: + this.settings[languageIndex].options[0] = "English"; + break; + } + } + this.localStorageKey = "settings"; } } diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 1dbb60915ca..e6be659ce7d 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -18,8 +18,8 @@ import { LevelMoves, pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "../ import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species"; import { Type } from "../data/type"; import { Button } from "../enums/buttons"; -import { GameModes, gameModes } from "../game-mode"; -import { TitlePhase } from "../phases"; +import { GameModes } from "../game-mode"; +import { SelectChallengePhase, TitlePhase } from "../phases"; import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, StarterFormMoveData, StarterMoveset } from "../system/game-data"; import { Passive as PassiveAttr } from "#app/data/enums/passive"; import { Tutorial, handleTutorial } from "../tutorial"; @@ -31,7 +31,11 @@ import { StatsContainer } from "./stats-container"; import { TextStyle, addBBCodeTextObject, addTextObject } from "./text"; import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; +import {SettingKeyboard} from "#app/system/settings/settings-keyboard"; +import {Device} from "#app/enums/devices"; +import * as Challenge from "../data/challenge"; import MoveInfoOverlay from "./move-info-overlay"; +import { getEggTierForSpecies } from "#app/data/egg.js"; export type StarterSelectCallback = (starters: Starter[]) => void; @@ -55,7 +59,7 @@ interface LanguageSetting { const languageSettings: { [key: string]: LanguageSetting } = { "en":{ starterInfoTextSize: "56px", - instructionTextSize: "42px", + instructionTextSize: "38px", }, "de":{ starterInfoTextSize: "56px", @@ -186,8 +190,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private pokemonCandyCountText: Phaser.GameObjects.Text; private pokemonCaughtHatchedContainer: Phaser.GameObjects.Container; private pokemonCaughtCountText: Phaser.GameObjects.Text; + private pokemonHatchedIcon : Phaser.GameObjects.Sprite; private pokemonHatchedCountText: Phaser.GameObjects.Text; private genOptionsText: Phaser.GameObjects.Text; + private instructionsContainer: Phaser.GameObjects.Container; private instructionsText: Phaser.GameObjects.Text; private starterSelectMessageBox: Phaser.GameObjects.NineSlice; private starterSelectMessageBoxContainer: Phaser.GameObjects.Container; @@ -207,8 +213,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private genSpecies: PokemonSpecies[][] = []; private lastSpecies: PokemonSpecies; private speciesLoaded: Map = new Map(); - private starterGens: integer[] = []; - private starterCursors: integer[] = []; + public starterGens: integer[] = []; + public starterCursors: integer[] = []; private pokerusGens: integer[] = []; private pokerusCursors: integer[] = []; private starterAttr: bigint[] = []; @@ -227,7 +233,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private canAddParty: boolean; private assetLoadCancelled: Utils.BooleanHolder; - private cursorObj: Phaser.GameObjects.Image; + public cursorObj: Phaser.GameObjects.Image; private starterCursorObjs: Phaser.GameObjects.Image[]; private pokerusCursorObjs: Phaser.GameObjects.Image[]; private starterIcons: Phaser.GameObjects.Sprite[]; @@ -244,8 +250,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private iconAnimHandler: PokemonIconAnimHandler; + //variables to keep track of the dynamically rendered list of instruction prompts for starter select + private instructionRowX = 0; + private instructionRowY = 0; + private instructionRowTextOffset = 12; + private starterSelectCallback: StarterSelectCallback; - private gameMode: GameModes; protected blockInput: boolean = false; @@ -577,10 +587,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonCaughtCountText.setOrigin(0, 0); this.pokemonCaughtHatchedContainer.add(this.pokemonCaughtCountText); - const pokemonHatchedIcon = this.scene.add.sprite(1, 14, "items", "mystery_egg"); - pokemonHatchedIcon.setOrigin(0, 0); - pokemonHatchedIcon.setScale(0.75); - this.pokemonCaughtHatchedContainer.add(pokemonHatchedIcon); + this.pokemonHatchedIcon = this.scene.add.sprite(1, 14, "egg_icons"); + this.pokemonHatchedIcon.setOrigin(0.15, 0.2); + this.pokemonHatchedIcon.setScale(0.8); + this.pokemonCaughtHatchedContainer.add(this.pokemonHatchedIcon); this.pokemonHatchedCountText = addTextObject(this.scene, 24, 19, "0", TextStyle.SUMMARY_ALT); this.pokemonHatchedCountText.setOrigin(0, 0); @@ -646,10 +656,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.starterSelectContainer.add(this.pokemonEggMovesContainer); // The font size should be set per language - const instructionTextSize = textSettings.instructionTextSize; - - this.instructionsText = addTextObject(this.scene, 4, 156, "", TextStyle.PARTY, { fontSize: instructionTextSize }); - this.starterSelectContainer.add(this.instructionsText); + this.instructionsContainer = this.scene.add.container(4, 156); + this.instructionsContainer.setVisible(true); + this.starterSelectContainer.add(this.instructionsContainer); this.starterSelectMessageBoxContainer = this.scene.add.container(0, this.scene.game.canvas.height / 6); this.starterSelectMessageBoxContainer.setVisible(false); @@ -663,15 +672,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.message.setOrigin(0, 0); this.starterSelectMessageBoxContainer.add(this.message); - const overlayScale = 1; // scale for the move info. "2/3" might be another good option... - this.moveInfoOverlay = new MoveInfoOverlay(this.scene, { - scale: overlayScale, - top: true, - x: 1, - y: this.scene.game.canvas.height / 6 - MoveInfoOverlay.getHeight(overlayScale) - 29, - }); - this.starterSelectContainer.add(this.moveInfoOverlay); - const date = new Date(); date.setUTCHours(0, 0, 0, 0); @@ -716,20 +716,29 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.starterSelectContainer.add(this.statsContainer); + // add the info overlay last to be the top most ui element and prevent the IVs from overlaying this + const overlayScale = 1; + this.moveInfoOverlay = new MoveInfoOverlay(this.scene, { + scale: overlayScale, + top: true, + x: 1, + y: this.scene.game.canvas.height / 6 - MoveInfoOverlay.getHeight(overlayScale) - 29, + }); + this.starterSelectContainer.add(this.moveInfoOverlay); + this.scene.eventTarget.addEventListener(BattleSceneEventType.CANDY_UPGRADE_NOTIFICATION_CHANGED, (e) => this.onCandyUpgradeDisplayChanged(e)); this.updateInstructions(); } show(args: any[]): boolean { - if (args.length >= 2 && args[0] instanceof Function && typeof args[1] === "number") { + this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers + if (args.length >= 1 && args[0] instanceof Function) { super.show(args); this.starterSelectCallback = args[0] as StarterSelectCallback; this.starterSelectContainer.setVisible(true); - this.gameMode = args[1]; - this.setGenMode(false); this.setCursor(0); this.setGenMode(true); @@ -955,7 +964,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } else { this.blockInput = true; this.scene.clearPhaseQueue(); - this.scene.pushPhase(new TitlePhase(this.scene)); + if (this.scene.gameMode.isChallenge) { + this.scene.pushPhase(new SelectChallengePhase(this.scene)); + } else { + this.scene.pushPhase(new TitlePhase(this.scene)); + } this.scene.getCurrentPhase().end(); success = true; } @@ -1027,7 +1040,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } const species = this.genSpecies[this.getGenCursorWithScroll()][this.cursor]; - if (!isDupe && this.tryUpdateValue(this.scene.gameData.getSpeciesStarterValue(species.speciesId))) { + + const isValidForChallenge = new Utils.BooleanHolder(true); + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge); + + if (!isDupe && isValidForChallenge.value && this.tryUpdateValue(this.scene.gameData.getSpeciesStarterValue(species.speciesId))) { const cursorObj = this.starterCursorObjs[this.starterCursors.length]; cursorObj.setVisible(true); cursorObj.setPosition(this.cursorObj.x, this.cursorObj.y); @@ -1477,55 +1494,100 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, undefined, false); } + createButtonFromIconText(iconSetting, gamepadType, translatedText, instructionTextSize): void { + let iconPath; + // touch controls cannot be rebound as is, and are just emulating a keyboard event. + // Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls + if (gamepadType === "touch") { + gamepadType = "keyboard"; + switch (iconSetting) { + case SettingKeyboard.Button_Cycle_Shiny: + iconPath = "R.png"; + break; + case SettingKeyboard.Button_Cycle_Form: + iconPath = "F.png"; + break; + case SettingKeyboard.Button_Cycle_Gender: + iconPath = "G.png"; + break; + case SettingKeyboard.Button_Cycle_Ability: + iconPath = "E.png"; + break; + case SettingKeyboard.Button_Cycle_Nature: + iconPath = "N.png"; + break; + case SettingKeyboard.Button_Cycle_Variant: + iconPath = "V.png"; + break; + default: + break; + } + } else { + iconPath = this.scene.inputController?.getIconForLatestInputRecorded(iconSetting); + } + const iconElement = this.scene.add.sprite(this.instructionRowX, this.instructionRowY, gamepadType, iconPath); + iconElement.setScale(0.675); + iconElement.setOrigin(0.0, 0.0); + const controlLabel = addTextObject(this.scene, this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, translatedText, TextStyle.PARTY, { fontSize: instructionTextSize }); + this.instructionsContainer.add([iconElement, controlLabel]); + this.instructionRowY += 8; + if (this.instructionRowY >= 24) { + this.instructionRowY = 0; + this.instructionRowX += 50; + } + } + updateInstructions(): void { - const instructionLines = [ ]; - const cycleInstructionLines = []; + const currentLanguage = i18next.resolvedLanguage; + const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)); + const textSettings = languageSettings[langSettingKey]; + const instructionTextSize = textSettings.instructionTextSize; + this.instructionRowX = 0; + this.instructionRowY = 0; + this.instructionsContainer.removeAll(); + let gamepadType; + if (this.scene.inputMethod === "gamepad") { + gamepadType = this.scene.inputController.getConfig(this.scene.inputController.selectedDevice[Device.GAMEPAD]).padType; + } else { + gamepadType = this.scene.inputMethod; + } + if (this.speciesStarterDexEntry?.caughtAttr) { if (this.canCycleShiny) { - cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleShiny")); + this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Shiny, gamepadType, i18next.t("starterSelectUiHandler:cycleShiny"), instructionTextSize); } if (this.canCycleForm) { - cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleForm")); + this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Form, gamepadType, i18next.t("starterSelectUiHandler:cycleForm"), instructionTextSize); } if (this.canCycleGender) { - cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleGender")); + this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Gender, gamepadType, i18next.t("starterSelectUiHandler:cycleGender"), instructionTextSize); } if (this.canCycleAbility) { - cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleAbility")); + this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Ability, gamepadType, i18next.t("starterSelectUiHandler:cycleAbility"), instructionTextSize); } if (this.canCycleNature) { - cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleNature")); + this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Nature, gamepadType, i18next.t("starterSelectUiHandler:cycleNature"), instructionTextSize); } if (this.canCycleVariant) { - cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleVariant")); + this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Variant, gamepadType, i18next.t("starterSelectUiHandler:cycleVariant"), instructionTextSize); } } - - if (cycleInstructionLines.length > 2) { - cycleInstructionLines[0] += " | " + cycleInstructionLines.splice(1, 1); - if (cycleInstructionLines.length > 2) { - cycleInstructionLines[1] += " | " + cycleInstructionLines.splice(2, 1); - } - if (cycleInstructionLines.length > 2) { - cycleInstructionLines[2] += " | " + cycleInstructionLines.splice(3, 1); - } - } - - for (const cil of cycleInstructionLines) { - instructionLines.push(cil); - } - - this.instructionsText.setText(instructionLines.join("\n")); } getValueLimit(): integer { - switch (this.gameMode) { + const valueLimit = new Utils.IntegerHolder(0); + switch (this.scene.gameMode.modeId) { case GameModes.ENDLESS: case GameModes.SPLICED_ENDLESS: - return 15; + valueLimit.value = 15; + break; default: - return 10; + valueLimit.value = 10; } + + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_POINTS, valueLimit); + + return valueLimit.value; } setCursor(cursor: integer): boolean { @@ -1716,11 +1778,26 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonPassiveLabelText.setVisible(true); this.pokemonNatureLabelText.setVisible(true); this.pokemonCaughtCountText.setText(`${this.speciesStarterDexEntry.caughtCount}`); + if (species.speciesId === Species.MANAPHY || species.speciesId === Species.PHIONE) { + this.pokemonHatchedIcon.setFrame("manaphy"); + } else { + this.pokemonHatchedIcon.setFrame(getEggTierForSpecies(species)); + } this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry.hatchedCount}`); this.pokemonCaughtHatchedContainer.setVisible(true); if (pokemonPrevolutions.hasOwnProperty(species.speciesId)) { this.pokemonCaughtHatchedContainer.setY(16); - [ this.pokemonCandyIcon, this.pokemonCandyOverlayIcon, this.pokemonCandyDarknessOverlay, this.pokemonCandyCountText ].map(c => c.setVisible(false)); + [ + this.pokemonCandyIcon, + this.pokemonCandyOverlayIcon, + this.pokemonCandyDarknessOverlay, + this.pokemonCandyCountText, + this.pokemonHatchedIcon, + this.pokemonHatchedCountText + ].map(c => c.setVisible(false)); + } else if (species.speciesId === Species.ETERNATUS) { + this.pokemonHatchedIcon.setVisible(false); + this.pokemonHatchedCountText.setVisible(false); } else { this.pokemonCaughtHatchedContainer.setY(25); this.pokemonCandyIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[0]))); @@ -1731,6 +1808,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonCandyCountText.setText(`x${this.scene.gameData.starterData[species.speciesId].candyCount}`); this.pokemonCandyCountText.setVisible(true); this.pokemonFormText.setVisible(true); + this.pokemonHatchedIcon.setVisible(true); + this.pokemonHatchedCountText.setVisible(true); let currentFriendship = this.scene.gameData.starterData[this.lastSpecies.speciesId].friendship; if (!currentFriendship || currentFriendship === undefined) { @@ -2158,20 +2237,25 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const speciesSprite = this.starterSelectGenIconContainers[g].getAt(s) as Phaser.GameObjects.Sprite; /** - * If remainValue greater than or equal pokemon species, the user can select. + * If remainValue greater than or equal pokemon species and the pokemon is legal for this challenge, the user can select. * so that the alpha value of pokemon sprite set 1. * * If speciesStarterDexEntry?.caughtAttr is true, this species registered in stater. * we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too. */ - if (remainValue >= speciesStarterValue) { + const isValidForChallenge = new Utils.BooleanHolder(true); + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.genSpecies[g][s], isValidForChallenge); + + const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value; + + if (canBeChosen) { speciesSprite.setAlpha(1); if (speciesStarterDexEntry?.caughtAttr) { this.canAddParty = true; } } else { /** - * If remainValue less than pokemon, the use can't select. + * If it can't be chosen, the user can't select. * so that the alpha value of pokemon sprite set 0.375. */ speciesSprite.setAlpha(0.375); @@ -2200,8 +2284,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { ui.showText(i18next.t("starterSelectUiHandler:confirmStartTeam"), null, () => { ui.setModeWithoutClear(Mode.CONFIRM, () => { - const startRun = (gameMode: GameModes) => { - this.scene.gameMode = gameModes[gameMode]; + const startRun = () => { this.scene.money = this.scene.gameMode.getStartingMoney(); ui.setMode(Mode.STARTER_SELECT); const thisObj = this; @@ -2220,7 +2303,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { }; })); }; - startRun(this.gameMode); + startRun(); }, cancel, null, null, 19); }); diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 5a1f883d94f..fb788f2c9c0 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -22,6 +22,8 @@ import { Variant, getVariantTint } from "#app/data/variant"; import {Button} from "../enums/buttons"; import { Ability } from "../data/ability.js"; import i18next from "i18next"; +import {modifierSortFunc} from "../modifier/modifier"; + enum Page { PROFILE, @@ -828,8 +830,9 @@ export default class SummaryUiHandler extends UiHandler { statsContainer.add(statValue); }); - const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier - && (m as PokemonHeldItemModifier).pokemonId === this.pokemon.id, true) as PokemonHeldItemModifier[]; + const itemModifiers = (this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier + && (m as PokemonHeldItemModifier).pokemonId === this.pokemon.id, true) as PokemonHeldItemModifier[]) + .sort(modifierSortFunc); itemModifiers.forEach((item, i) => { const icon = item.getIcon(this.scene, true); diff --git a/src/ui/ui-handler.ts b/src/ui/ui-handler.ts index 74015ed7245..e74853276ea 100644 --- a/src/ui/ui-handler.ts +++ b/src/ui/ui-handler.ts @@ -3,12 +3,19 @@ import { TextStyle, getTextColor } from "./text"; import { Mode } from "./ui"; import {Button} from "../enums/buttons"; +/** + * A basic abstract class to act as a holder and processor for UI elements. + */ export default abstract class UiHandler { protected scene: BattleScene; protected mode: integer; protected cursor: integer = 0; public active: boolean = false; + /** + * @param {BattleScene} scene The same scene as everything else. + * @param {Mode} mode The mode of the UI element. These should be unique. + */ constructor(scene: BattleScene, mode: Mode) { this.scene = scene; this.mode = mode; diff --git a/src/ui/ui.ts b/src/ui/ui.ts index aaf764f501f..366be949374 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -14,6 +14,7 @@ import EvolutionSceneHandler from "./evolution-scene-handler"; import TargetSelectUiHandler from "./target-select-ui-handler"; import SettingsUiHandler from "./settings/settings-ui-handler"; import SettingsGamepadUiHandler from "./settings/settings-gamepad-ui-handler"; +import GameChallengesUiHandler from "./challenges-select-ui-handler"; import { TextStyle, addTextObject } from "./text"; import AchvBar from "./achv-bar"; import MenuUiHandler from "./menu-ui-handler"; @@ -80,7 +81,8 @@ export enum Mode { LOADING, SESSION_RELOAD, UNAVAILABLE, - OUTDATED + OUTDATED, + CHALLENGE_SELECT } const transitionModes = [ @@ -91,7 +93,8 @@ const transitionModes = [ Mode.EVOLUTION_SCENE, Mode.EGG_HATCH_SCENE, Mode.EGG_LIST, - Mode.EGG_GACHA + Mode.EGG_GACHA, + Mode.CHALLENGE_SELECT ]; const noTransitionModes = [ @@ -173,7 +176,8 @@ export default class UI extends Phaser.GameObjects.Container { new LoadingModalUiHandler(scene), new SessionReloadModalUiHandler(scene), new UnavailableModalUiHandler(scene), - new OutdatedModalUiHandler(scene) + new OutdatedModalUiHandler(scene), + new GameChallengesUiHandler(scene) ]; } diff --git a/src/utils.test.ts b/src/utils.test.ts index 01bdd5db542..93f2a96ec4c 100644 --- a/src/utils.test.ts +++ b/src/utils.test.ts @@ -1,9 +1,15 @@ -import { expect, describe, it } from "vitest"; +import {expect, describe, it, beforeAll} from "vitest"; import { randomString, padInt } from "./utils"; import Phaser from "phaser"; describe("utils", () => { + + beforeAll(() => { + new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); describe("randomString", () => { it("should return a string of the specified length", () => { const str = randomString(10); diff --git a/src/utils.ts b/src/utils.ts index 3454593b23c..ccffd453dff 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,5 @@ import i18next from "i18next"; +import { MoneyFormat } from "./enums/money-format"; export const MissingTextureKey = "__MISSING"; @@ -127,6 +128,23 @@ export function randSeedEasedWeightedItem(items: T[], easingFunction: string return items[Math.floor(easedValue * items.length)]; } +/** + * Shuffle a list using the seeded rng. Utilises the Fisher-Yates algorithm. + * @param {Array} items An array of items. + * @returns {Array} A new shuffled array of items. + */ +export function randSeedShuffle(items: T[]): T[] { + if (items.length <= 1) { + return items; + } + const newArray = items.slice(0); + for (let i = items.length - 1; i > 0; i--) { + const j = Phaser.Math.RND.integerInRange(0, i); + [newArray[i], newArray[j]] = [newArray[j], newArray[i]]; + } + return newArray; +} + export function getFrameMs(frameCount: integer): integer { return Math.floor((1 / 60) * 1000 * frameCount); } @@ -220,7 +238,7 @@ export function formatLargeNumber(count: integer, threshold: integer): string { // Abbreviations from 10^0 to 10^33 const AbbreviationsLargeNumber: string[] = ["", "K", "M", "B", "t", "q", "Q", "s", "S", "o", "n", "d"]; -export function formatFancyLargeNumber(number: number, rounded: number = 2): string { +export function formatFancyLargeNumber(number: number, rounded: number = 3): string { let exponent: number; if (number < 1000) { @@ -234,7 +252,14 @@ export function formatFancyLargeNumber(number: number, rounded: number = 2): str number /= Math.pow(1000, exponent); } - return `${(exponent === 0) ? number : number.toFixed(rounded)}${AbbreviationsLargeNumber[exponent]}`; + return `${(exponent === 0) || number % 1 === 0 ? number : number.toFixed(rounded)}${AbbreviationsLargeNumber[exponent]}`; +} + +export function formatMoney(format: MoneyFormat, amount: number) { + if (format === MoneyFormat.ABBREVIATED) { + return formatFancyLargeNumber(amount); + } + return amount.toLocaleString(); } export function formatStat(stat: integer, forHp: boolean = false): string { @@ -260,15 +285,19 @@ export const isLocal = ( /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/.test(window.location.hostname)) && window.location.port !== "") || window.location.hostname === ""; +export const localServerUrl = import.meta.env.VITE_SERVER_URL ?? `http://${window.location.hostname}:${window.location.port+1}`; + // Set the server URL based on whether it's local or not -export const apiUrl = "https://api.pokerogue.net"; +export const serverUrl = isLocal ? localServerUrl : ""; +export const apiUrl = isLocal ? serverUrl : "https://api.pokerogue.net"; // used to disable api calls when isLocal is true and a server is not found +export const isLocalServerConnected = true; export function setCookie(cName: string, cValue: string): void { console.log("setCookie: ", cName, cValue); const expiration = new Date(); expiration.setTime(new Date().getTime() + 3600000 * 24 * 30 * 3/*7*/); - document.cookie = `${cName}=${cValue};SameSite=Strict;path=/;expires=${expiration.toUTCString()}`; + document.cookie = `${cName}=${cValue};Secure;SameSite=Strict;Path=/;Expires=${expiration.toUTCString()}`; } export function getCookie(cName: string): string { diff --git a/src/vite.env.d.ts b/src/vite.env.d.ts index 898d7cecc6c..387358d0dfe 100644 --- a/src/vite.env.d.ts +++ b/src/vite.env.d.ts @@ -4,6 +4,7 @@ interface ImportMetaEnv { readonly VITE_BYPASS_LOGIN?: string; readonly VITE_BYPASS_TUTORIAL?: string; readonly VITE_API_BASE_URL?: string; + readonly VITE_SERVER_URL?: string; readonly VITE_MOCK_API?: string; } diff --git a/vitest.config.js b/vitest.config.js index c73476431dd..5dcb326e1ea 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -15,6 +15,7 @@ export default defineConfig(({ mode }) => { }, threads: false, trace: true, + restoreMocks: true, environmentOptions: { jsdom: { resources: 'usable',