diff --git a/eslint.config.js b/eslint.config.js index 1cea5563a78..0da9cc604bf 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -5,6 +5,7 @@ import importX from 'eslint-plugin-import-x'; export default [ { + name: "eslint-config", files: ["src/**/*.{ts,tsx,js,jsx}"], ignores: ["dist/*", "build/*", "coverage/*", "public/*", ".github/*", "node_modules/*", ".vscode/*"], languageOptions: { @@ -48,5 +49,22 @@ export default [ "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }], // Disallows multiple empty lines "@typescript-eslint/consistent-type-imports": "error", // Enforces type-only imports wherever possible } + }, + { + name: "eslint-tests", + files: ["src/test/**/**.test.ts"], + languageOptions: { + parser: parser, + parserOptions: { + "project": ["./tsconfig.json"] + } + }, + plugins: { + "@typescript-eslint": tseslint + }, + rules: { + "@typescript-eslint/no-floating-promises": "error", // Require Promise-like statements to be handled appropriately. - https://typescript-eslint.io/rules/no-floating-promises/ + "@typescript-eslint/no-misused-promises": "error", // Disallow Promises in places not designed to handle them. - https://typescript-eslint.io/rules/no-misused-promises/ + } } ] diff --git a/public/images/events/valentines2025event-de.png b/public/images/events/valentines2025event-de.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-de.png differ diff --git a/public/images/events/valentines2025event-en.png b/public/images/events/valentines2025event-en.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-en.png differ diff --git a/public/images/events/valentines2025event-es-ES.png b/public/images/events/valentines2025event-es-ES.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-es-ES.png differ diff --git a/public/images/events/valentines2025event-fr.png b/public/images/events/valentines2025event-fr.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-fr.png differ diff --git a/public/images/events/valentines2025event-it.png b/public/images/events/valentines2025event-it.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-it.png differ diff --git a/public/images/events/valentines2025event-ja.png b/public/images/events/valentines2025event-ja.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-ja.png differ diff --git a/public/images/events/valentines2025event-ko.png b/public/images/events/valentines2025event-ko.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-ko.png differ diff --git a/public/images/events/valentines2025event-pt-BR.png b/public/images/events/valentines2025event-pt-BR.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-pt-BR.png differ diff --git a/public/images/events/valentines2025event-zh-CN.png b/public/images/events/valentines2025event-zh-CN.png new file mode 100644 index 00000000000..0ec3bfe704b Binary files /dev/null and b/public/images/events/valentines2025event-zh-CN.png differ diff --git a/public/images/pokemon/335.json b/public/images/pokemon/335.json index 0279e0fba5a..a9313fcec5d 100644 --- a/public/images/pokemon/335.json +++ b/public/images/pokemon/335.json @@ -1,1910 +1,547 @@ -{ - "textures": [ - { - "image": "335.png", - "format": "RGBA8888", - "size": { - "w": 366, - "h": 366 - }, - "scale": 1, - "frames": [ - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 68, - "h": 63 - }, - "frame": { - "x": 0, - "y": 0, - "w": 68, - "h": 63 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 68, - "h": 63 - }, - "frame": { - "x": 0, - "y": 0, - "w": 68, - "h": 63 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 68, - "h": 63 - }, - "frame": { - "x": 0, - "y": 0, - "w": 68, - "h": 63 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 68, - "h": 63 - }, - "frame": { - "x": 0, - "y": 0, - "w": 68, - "h": 63 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 65, - "h": 66 - }, - "frame": { - "x": 0, - "y": 63, - "w": 65, - "h": 66 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 67, - "h": 63 - }, - "frame": { - "x": 68, - "y": 0, - "w": 67, - "h": 63 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 67, - "h": 63 - }, - "frame": { - "x": 68, - "y": 0, - "w": 67, - "h": 63 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 68, - "h": 61 - }, - "frame": { - "x": 65, - "y": 63, - "w": 68, - "h": 61 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 68, - "h": 61 - }, - "frame": { - "x": 65, - "y": 63, - "w": 68, - "h": 61 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 68, - "h": 61 - }, - "frame": { - "x": 65, - "y": 63, - "w": 68, - "h": 61 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 68, - "h": 61 - }, - "frame": { - "x": 65, - "y": 63, - "w": 68, - "h": 61 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 64, - "h": 63 - }, - "frame": { - "x": 0, - "y": 129, - "w": 64, - "h": 63 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 64, - "h": 63 - }, - "frame": { - "x": 0, - "y": 129, - "w": 64, - "h": 63 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 64, - "h": 63 - }, - "frame": { - "x": 0, - "y": 129, - "w": 64, - "h": 63 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 64, - "h": 63 - }, - "frame": { - "x": 0, - "y": 129, - "w": 64, - "h": 63 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 61, - "h": 66 - }, - "frame": { - "x": 0, - "y": 192, - "w": 61, - "h": 66 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 61, - "h": 66 - }, - "frame": { - "x": 0, - "y": 258, - "w": 61, - "h": 66 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 61, - "h": 66 - }, - "frame": { - "x": 0, - "y": 258, - "w": 61, - "h": 66 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 64, - "h": 62 - }, - "frame": { - "x": 135, - "y": 0, - "w": 64, - "h": 62 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 64, - "h": 62 - }, - "frame": { - "x": 135, - "y": 0, - "w": 64, - "h": 62 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 65, - "h": 61 - }, - "frame": { - "x": 199, - "y": 0, - "w": 65, - "h": 61 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 67, - "h": 58 - }, - "frame": { - "x": 264, - "y": 0, - "w": 67, - "h": 58 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 67, - "h": 58 - }, - "frame": { - "x": 264, - "y": 0, - "w": 67, - "h": 58 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 67, - "h": 58 - }, - "frame": { - "x": 264, - "y": 0, - "w": 67, - "h": 58 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 67, - "h": 58 - }, - "frame": { - "x": 264, - "y": 0, - "w": 67, - "h": 58 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 64, - "h": 59 - }, - "frame": { - "x": 65, - "y": 124, - "w": 64, - "h": 59 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 64, - "h": 59 - }, - "frame": { - "x": 65, - "y": 124, - "w": 64, - "h": 59 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 64, - "h": 59 - }, - "frame": { - "x": 65, - "y": 124, - "w": 64, - "h": 59 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 64, - "h": 59 - }, - "frame": { - "x": 65, - "y": 124, - "w": 64, - "h": 59 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 64, - "h": 61 - }, - "frame": { - "x": 64, - "y": 183, - "w": 64, - "h": 61 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 1, - "w": 62, - "h": 65 - }, - "frame": { - "x": 61, - "y": 244, - "w": 62, - "h": 65 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 6, - "y": 9, - "w": 63, - "h": 57 - }, - "frame": { - "x": 61, - "y": 309, - "w": 63, - "h": 57 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 61, - "h": 64 - }, - "frame": { - "x": 123, - "y": 244, - "w": 61, - "h": 64 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 63, - "h": 58 - }, - "frame": { - "x": 124, - "y": 308, - "w": 63, - "h": 58 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 5, - "w": 61, - "h": 61 - }, - "frame": { - "x": 128, - "y": 183, - "w": 61, - "h": 61 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 5, - "w": 61, - "h": 61 - }, - "frame": { - "x": 128, - "y": 183, - "w": 61, - "h": 61 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 5, - "w": 61, - "h": 61 - }, - "frame": { - "x": 128, - "y": 183, - "w": 61, - "h": 61 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 5, - "w": 61, - "h": 61 - }, - "frame": { - "x": 128, - "y": 183, - "w": 61, - "h": 61 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 9, - "w": 62, - "h": 57 - }, - "frame": { - "x": 187, - "y": 307, - "w": 62, - "h": 57 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 9, - "w": 62, - "h": 57 - }, - "frame": { - "x": 187, - "y": 307, - "w": 62, - "h": 57 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 62, - "h": 63 - }, - "frame": { - "x": 264, - "y": 58, - "w": 62, - "h": 63 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 55, - "h": 63 - }, - "frame": { - "x": 133, - "y": 63, - "w": 55, - "h": 63 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 55, - "h": 63 - }, - "frame": { - "x": 133, - "y": 63, - "w": 55, - "h": 63 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 55, - "h": 63 - }, - "frame": { - "x": 133, - "y": 63, - "w": 55, - "h": 63 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 55, - "h": 63 - }, - "frame": { - "x": 133, - "y": 63, - "w": 55, - "h": 63 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 55, - "h": 66 - }, - "frame": { - "x": 188, - "y": 62, - "w": 55, - "h": 66 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 55, - "h": 66 - }, - "frame": { - "x": 188, - "y": 62, - "w": 55, - "h": 66 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 58, - "h": 66 - }, - "frame": { - "x": 189, - "y": 128, - "w": 58, - "h": 66 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 60, - "h": 66 - }, - "frame": { - "x": 247, - "y": 121, - "w": 60, - "h": 66 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 59, - "h": 63 - }, - "frame": { - "x": 307, - "y": 121, - "w": 59, - "h": 63 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 59, - "h": 63 - }, - "frame": { - "x": 307, - "y": 121, - "w": 59, - "h": 63 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 59, - "h": 63 - }, - "frame": { - "x": 307, - "y": 121, - "w": 59, - "h": 63 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 59, - "h": 63 - }, - "frame": { - "x": 307, - "y": 121, - "w": 59, - "h": 63 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 247, - "y": 187, - "w": 60, - "h": 63 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 247, - "y": 187, - "w": 60, - "h": 63 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 247, - "y": 187, - "w": 60, - "h": 63 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 247, - "y": 187, - "w": 60, - "h": 63 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 58, - "h": 63 - }, - "frame": { - "x": 307, - "y": 184, - "w": 58, - "h": 63 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 58, - "h": 63 - }, - "frame": { - "x": 307, - "y": 184, - "w": 58, - "h": 63 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 58, - "h": 63 - }, - "frame": { - "x": 307, - "y": 184, - "w": 58, - "h": 63 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 58, - "h": 63 - }, - "frame": { - "x": 307, - "y": 184, - "w": 58, - "h": 63 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 249, - "y": 250, - "w": 60, - "h": 63 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:9c4e9647cd30b406386dcfa45795951c:b817a280fcd689ce74ea32e378a31e74:40bb9f4809624b12bf79bbfe664bea73$" - } +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0002.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0003.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0004.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0005.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0006.png", + "frame": { "x": 0, "y": 185, "w": 59, "h": 59 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 7, "w": 59, "h": 59 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0007.png", + "frame": { "x": 119, "y": 182, "w": 62, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 9, "w": 62, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0008.png", + "frame": { "x": 119, "y": 125, "w": 64, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 10, "w": 64, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0009.png", + "frame": { "x": 195, "y": 0, "w": 66, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 7, "w": 66, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0010.png", + "frame": { "x": 129, "y": 0, "w": 66, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 66, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0011.png", + "frame": { "x": 320, "y": 0, "w": 62, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 62, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0012.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0013.png", + "frame": { "x": 0, "y": 244, "w": 53, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 53, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0014.png", + "frame": { "x": 59, "y": 188, "w": 56, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 56, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0015.png", + "frame": { "x": 306, "y": 187, "w": 57, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 57, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0016.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0017.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0018.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0019.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0020.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0021.png", + "frame": { "x": 0, "y": 185, "w": 59, "h": 59 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 7, "w": 59, "h": 59 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0022.png", + "frame": { "x": 119, "y": 182, "w": 62, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 9, "w": 62, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0023.png", + "frame": { "x": 119, "y": 125, "w": 64, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 10, "w": 64, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0024.png", + "frame": { "x": 195, "y": 0, "w": 66, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 7, "w": 66, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0025.png", + "frame": { "x": 129, "y": 0, "w": 66, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 66, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0026.png", + "frame": { "x": 320, "y": 0, "w": 62, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 62, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0027.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0028.png", + "frame": { "x": 0, "y": 244, "w": 53, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 53, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0029.png", + "frame": { "x": 59, "y": 188, "w": 56, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 56, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0030.png", + "frame": { "x": 306, "y": 187, "w": 57, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 57, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0031.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0032.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0033.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0034.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0035.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0036.png", + "frame": { "x": 0, "y": 185, "w": 59, "h": 59 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 7, "w": 59, "h": 59 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0037.png", + "frame": { "x": 119, "y": 182, "w": 62, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 9, "w": 62, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0038.png", + "frame": { "x": 119, "y": 125, "w": 64, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 10, "w": 64, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0039.png", + "frame": { "x": 195, "y": 0, "w": 66, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 7, "w": 66, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0040.png", + "frame": { "x": 129, "y": 0, "w": 66, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 66, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0041.png", + "frame": { "x": 320, "y": 0, "w": 62, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 62, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0042.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0043.png", + "frame": { "x": 0, "y": 244, "w": 53, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 53, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0044.png", + "frame": { "x": 59, "y": 188, "w": 56, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 56, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0045.png", + "frame": { "x": 306, "y": 187, "w": 57, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 57, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0046.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0047.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0048.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0049.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0050.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0051.png", + "frame": { "x": 248, "y": 129, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0052.png", + "frame": { "x": 188, "y": 123, "w": 60, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 5, "w": 60, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0053.png", + "frame": { "x": 0, "y": 125, "w": 61, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 6, "w": 61, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0054.png", + "frame": { "x": 0, "y": 66, "w": 63, "h": 59 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 7, "w": 63, "h": 59 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0055.png", + "frame": { "x": 234, "y": 190, "w": 61, "h": 56 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 10, "w": 61, "h": 56 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0056.png", + "frame": { "x": 234, "y": 246, "w": 60, "h": 55 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 60, "h": 55 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0057.png", + "frame": { "x": 115, "y": 239, "w": 61, "h": 56 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 11, "w": 61, "h": 56 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0058.png", + "frame": { "x": 63, "y": 62, "w": 62, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 62, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0059.png", + "frame": { "x": 63, "y": 0, "w": 66, "h": 62 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 4, "w": 66, "h": 62 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0060.png", + "frame": { "x": 0, "y": 0, "w": 63, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 0, "w": 63, "h": 66 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0061.png", + "frame": { "x": 261, "y": 0, "w": 59, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 0, "w": 59, "h": 66 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0062.png", + "frame": { "x": 181, "y": 184, "w": 53, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 0, "w": 53, "h": 66 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0063.png", + "frame": { "x": 63, "y": 122, "w": 56, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 0, "w": 56, "h": 66 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0064.png", + "frame": { "x": 320, "y": 61, "w": 58, "h": 65 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 1, "w": 58, "h": 65 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0065.png", + "frame": { "x": 129, "y": 61, "w": 59, "h": 64 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 2, "w": 59, "h": 64 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0066.png", + "frame": { "x": 195, "y": 60, "w": 60, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 3, "w": 60, "h": 63 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0067.png", + "frame": { "x": 255, "y": 66, "w": 59, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 63 }, + "sourceSize": { "w": 74, "h": 67 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.9.2-x64", + "image": "335.png", + "format": "I8", + "size": { "w": 382, "h": 305 }, + "scale": "1" + } } diff --git a/public/images/pokemon/335.png b/public/images/pokemon/335.png index e5d051dd850..65b56582339 100644 Binary files a/public/images/pokemon/335.png and b/public/images/pokemon/335.png differ diff --git a/public/images/pokemon/back/658.json b/public/images/pokemon/back/658.json index 050b63e3592..1d8893e2d5d 100644 --- a/public/images/pokemon/back/658.json +++ b/public/images/pokemon/back/658.json @@ -1,19 +1,19 @@ { "frames": [ { "filename": "0001.png", - "frame": { "x": 0, "y": 0, "w": 77, "h": 77 }, + "frame": { "x": 0, "y": 0, "w": 77, "h": 65 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 77, "h": 77 }, - "sourceSize": { "w": 77, "h": 77 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 77, "h": 65 }, + "sourceSize": { "w": 77, "h": 65 }, "duration": 100 } ], "meta": { "app": "https://www.aseprite.org/", - "version": "1.3.7-x64", + "version": "1.3.9.2-x64", "format": "I8", - "size": { "w": 77, "h": 77 }, + "size": { "w": 77, "h": 65 }, "scale": "1" } } diff --git a/public/images/pokemon/back/658.png b/public/images/pokemon/back/658.png index ea24d9a6336..be286b88666 100644 Binary files a/public/images/pokemon/back/658.png and b/public/images/pokemon/back/658.png differ diff --git a/public/images/pokemon/back/shiny/658.json b/public/images/pokemon/back/shiny/658.json index 050b63e3592..867e1d2d3d2 100644 --- a/public/images/pokemon/back/shiny/658.json +++ b/public/images/pokemon/back/shiny/658.json @@ -1,11 +1,11 @@ { "frames": [ { "filename": "0001.png", - "frame": { "x": 0, "y": 0, "w": 77, "h": 77 }, + "frame": { "x": 0, "y": 0, "w": 77, "h": 65 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 77, "h": 77 }, - "sourceSize": { "w": 77, "h": 77 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 77, "h": 65 }, + "sourceSize": { "w": 77, "h": 65 }, "duration": 100 } ], @@ -13,7 +13,7 @@ "app": "https://www.aseprite.org/", "version": "1.3.7-x64", "format": "I8", - "size": { "w": 77, "h": 77 }, + "size": { "w": 77, "h": 65 }, "scale": "1" } } diff --git a/public/images/pokemon/back/shiny/658.png b/public/images/pokemon/back/shiny/658.png index 21519b6a145..239aaafb6ce 100644 Binary files a/public/images/pokemon/back/shiny/658.png and b/public/images/pokemon/back/shiny/658.png differ diff --git a/public/images/pokemon/shiny/335.json b/public/images/pokemon/shiny/335.json index ca797f1d7a4..80c43b41c12 100644 --- a/public/images/pokemon/shiny/335.json +++ b/public/images/pokemon/shiny/335.json @@ -1,1910 +1,523 @@ -{ - "textures": [ - { - "image": "335.png", - "format": "RGBA8888", - "size": { - "w": 366, - "h": 366 - }, - "scale": 1, - "frames": [ - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 68, - "h": 63 - }, - "frame": { - "x": 0, - "y": 0, - "w": 68, - "h": 63 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 68, - "h": 63 - }, - "frame": { - "x": 0, - "y": 0, - "w": 68, - "h": 63 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 68, - "h": 63 - }, - "frame": { - "x": 0, - "y": 0, - "w": 68, - "h": 63 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 68, - "h": 63 - }, - "frame": { - "x": 0, - "y": 0, - "w": 68, - "h": 63 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 65, - "h": 66 - }, - "frame": { - "x": 0, - "y": 63, - "w": 65, - "h": 66 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 67, - "h": 63 - }, - "frame": { - "x": 68, - "y": 0, - "w": 67, - "h": 63 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 67, - "h": 63 - }, - "frame": { - "x": 68, - "y": 0, - "w": 67, - "h": 63 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 68, - "h": 61 - }, - "frame": { - "x": 65, - "y": 63, - "w": 68, - "h": 61 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 68, - "h": 61 - }, - "frame": { - "x": 65, - "y": 63, - "w": 68, - "h": 61 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 68, - "h": 61 - }, - "frame": { - "x": 65, - "y": 63, - "w": 68, - "h": 61 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 68, - "h": 61 - }, - "frame": { - "x": 65, - "y": 63, - "w": 68, - "h": 61 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 64, - "h": 63 - }, - "frame": { - "x": 0, - "y": 129, - "w": 64, - "h": 63 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 64, - "h": 63 - }, - "frame": { - "x": 0, - "y": 129, - "w": 64, - "h": 63 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 64, - "h": 63 - }, - "frame": { - "x": 0, - "y": 129, - "w": 64, - "h": 63 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 64, - "h": 63 - }, - "frame": { - "x": 0, - "y": 129, - "w": 64, - "h": 63 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 61, - "h": 66 - }, - "frame": { - "x": 0, - "y": 192, - "w": 61, - "h": 66 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 61, - "h": 66 - }, - "frame": { - "x": 0, - "y": 258, - "w": 61, - "h": 66 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 61, - "h": 66 - }, - "frame": { - "x": 0, - "y": 258, - "w": 61, - "h": 66 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 64, - "h": 62 - }, - "frame": { - "x": 135, - "y": 0, - "w": 64, - "h": 62 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 64, - "h": 62 - }, - "frame": { - "x": 135, - "y": 0, - "w": 64, - "h": 62 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 65, - "h": 61 - }, - "frame": { - "x": 199, - "y": 0, - "w": 65, - "h": 61 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 67, - "h": 58 - }, - "frame": { - "x": 264, - "y": 0, - "w": 67, - "h": 58 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 67, - "h": 58 - }, - "frame": { - "x": 264, - "y": 0, - "w": 67, - "h": 58 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 67, - "h": 58 - }, - "frame": { - "x": 264, - "y": 0, - "w": 67, - "h": 58 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 67, - "h": 58 - }, - "frame": { - "x": 264, - "y": 0, - "w": 67, - "h": 58 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 64, - "h": 59 - }, - "frame": { - "x": 65, - "y": 124, - "w": 64, - "h": 59 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 64, - "h": 59 - }, - "frame": { - "x": 65, - "y": 124, - "w": 64, - "h": 59 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 64, - "h": 59 - }, - "frame": { - "x": 65, - "y": 124, - "w": 64, - "h": 59 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 64, - "h": 59 - }, - "frame": { - "x": 65, - "y": 124, - "w": 64, - "h": 59 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 64, - "h": 61 - }, - "frame": { - "x": 64, - "y": 183, - "w": 64, - "h": 61 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 1, - "w": 62, - "h": 65 - }, - "frame": { - "x": 61, - "y": 244, - "w": 62, - "h": 65 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 6, - "y": 9, - "w": 63, - "h": 57 - }, - "frame": { - "x": 61, - "y": 309, - "w": 63, - "h": 57 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 61, - "h": 64 - }, - "frame": { - "x": 123, - "y": 244, - "w": 61, - "h": 64 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 63, - "h": 58 - }, - "frame": { - "x": 124, - "y": 308, - "w": 63, - "h": 58 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 5, - "w": 61, - "h": 61 - }, - "frame": { - "x": 128, - "y": 183, - "w": 61, - "h": 61 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 5, - "w": 61, - "h": 61 - }, - "frame": { - "x": 128, - "y": 183, - "w": 61, - "h": 61 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 5, - "w": 61, - "h": 61 - }, - "frame": { - "x": 128, - "y": 183, - "w": 61, - "h": 61 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 3, - "y": 5, - "w": 61, - "h": 61 - }, - "frame": { - "x": 128, - "y": 183, - "w": 61, - "h": 61 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 184, - "y": 244, - "w": 60, - "h": 63 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 9, - "w": 62, - "h": 57 - }, - "frame": { - "x": 187, - "y": 307, - "w": 62, - "h": 57 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 9, - "w": 62, - "h": 57 - }, - "frame": { - "x": 187, - "y": 307, - "w": 62, - "h": 57 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 62, - "h": 63 - }, - "frame": { - "x": 264, - "y": 58, - "w": 62, - "h": 63 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 55, - "h": 63 - }, - "frame": { - "x": 133, - "y": 63, - "w": 55, - "h": 63 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 55, - "h": 63 - }, - "frame": { - "x": 133, - "y": 63, - "w": 55, - "h": 63 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 55, - "h": 63 - }, - "frame": { - "x": 133, - "y": 63, - "w": 55, - "h": 63 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 55, - "h": 63 - }, - "frame": { - "x": 133, - "y": 63, - "w": 55, - "h": 63 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 55, - "h": 66 - }, - "frame": { - "x": 188, - "y": 62, - "w": 55, - "h": 66 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 55, - "h": 66 - }, - "frame": { - "x": 188, - "y": 62, - "w": 55, - "h": 66 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 58, - "h": 66 - }, - "frame": { - "x": 189, - "y": 128, - "w": 58, - "h": 66 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 60, - "h": 66 - }, - "frame": { - "x": 247, - "y": 121, - "w": 60, - "h": 66 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 59, - "h": 63 - }, - "frame": { - "x": 307, - "y": 121, - "w": 59, - "h": 63 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 59, - "h": 63 - }, - "frame": { - "x": 307, - "y": 121, - "w": 59, - "h": 63 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 59, - "h": 63 - }, - "frame": { - "x": 307, - "y": 121, - "w": 59, - "h": 63 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 59, - "h": 63 - }, - "frame": { - "x": 307, - "y": 121, - "w": 59, - "h": 63 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 247, - "y": 187, - "w": 60, - "h": 63 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 247, - "y": 187, - "w": 60, - "h": 63 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 247, - "y": 187, - "w": 60, - "h": 63 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 247, - "y": 187, - "w": 60, - "h": 63 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 58, - "h": 63 - }, - "frame": { - "x": 307, - "y": 184, - "w": 58, - "h": 63 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 58, - "h": 63 - }, - "frame": { - "x": 307, - "y": 184, - "w": 58, - "h": 63 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 58, - "h": 63 - }, - "frame": { - "x": 307, - "y": 184, - "w": 58, - "h": 63 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 58, - "h": 63 - }, - "frame": { - "x": 307, - "y": 184, - "w": 58, - "h": 63 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 74, - "h": 66 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 60, - "h": 63 - }, - "frame": { - "x": 249, - "y": 250, - "w": 60, - "h": 63 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:0df67af080306e793f3e63687a642a63:bd66cef8682173381b002070c3411214:40bb9f4809624b12bf79bbfe664bea73$" - } +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0002.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0003.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0004.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0005.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0006.png", + "frame": { "x": 0, "y": 185, "w": 59, "h": 59 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 7, "w": 59, "h": 59 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0007.png", + "frame": { "x": 119, "y": 182, "w": 62, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 9, "w": 62, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0008.png", + "frame": { "x": 119, "y": 125, "w": 64, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 10, "w": 64, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0009.png", + "frame": { "x": 195, "y": 0, "w": 66, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 7, "w": 66, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0010.png", + "frame": { "x": 129, "y": 0, "w": 66, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 66, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0011.png", + "frame": { "x": 320, "y": 0, "w": 62, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 62, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0012.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0013.png", + "frame": { "x": 0, "y": 244, "w": 53, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 53, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0014.png", + "frame": { "x": 59, "y": 188, "w": 56, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 56, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0015.png", + "frame": { "x": 306, "y": 187, "w": 57, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 57, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0016.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0017.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0018.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0019.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0020.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0021.png", + "frame": { "x": 0, "y": 185, "w": 59, "h": 59 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 7, "w": 59, "h": 59 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0022.png", + "frame": { "x": 119, "y": 182, "w": 62, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 9, "w": 62, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0023.png", + "frame": { "x": 119, "y": 125, "w": 64, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 10, "w": 64, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0024.png", + "frame": { "x": 195, "y": 0, "w": 66, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 7, "w": 66, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0025.png", + "frame": { "x": 129, "y": 0, "w": 66, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 66, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0026.png", + "frame": { "x": 320, "y": 0, "w": 62, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 62, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0027.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0028.png", + "frame": { "x": 0, "y": 244, "w": 53, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 53, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0029.png", + "frame": { "x": 59, "y": 188, "w": 56, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 56, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0030.png", + "frame": { "x": 306, "y": 187, "w": 57, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 57, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0031.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0032.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0033.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0034.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0035.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0036.png", + "frame": { "x": 0, "y": 185, "w": 59, "h": 59 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 7, "w": 59, "h": 59 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0037.png", + "frame": { "x": 119, "y": 182, "w": 62, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 9, "w": 62, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0038.png", + "frame": { "x": 119, "y": 125, "w": 64, "h": 57 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 10, "w": 64, "h": 57 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0039.png", + "frame": { "x": 195, "y": 0, "w": 66, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 7, "w": 66, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0040.png", + "frame": { "x": 129, "y": 0, "w": 66, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 66, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0041.png", + "frame": { "x": 320, "y": 0, "w": 62, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 62, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0042.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0043.png", + "frame": { "x": 0, "y": 244, "w": 53, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 53, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0044.png", + "frame": { "x": 59, "y": 188, "w": 56, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 56, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0045.png", + "frame": { "x": 306, "y": 187, "w": 57, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 57, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0046.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0047.png", + "frame": { "x": 314, "y": 126, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0048.png", + "frame": { "x": 248, "y": 129, "w": 58, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 5, "w": 58, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0049.png", + "frame": { "x": 188, "y": 123, "w": 60, "h": 61 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 5, "w": 60, "h": 61 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0050.png", + "frame": { "x": 0, "y": 125, "w": 61, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 6, "w": 61, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0051.png", + "frame": { "x": 0, "y": 66, "w": 63, "h": 59 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 7, "w": 63, "h": 59 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0052.png", + "frame": { "x": 234, "y": 190, "w": 61, "h": 56 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 10, "w": 61, "h": 56 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0053.png", + "frame": { "x": 234, "y": 246, "w": 60, "h": 55 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 60, "h": 55 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0054.png", + "frame": { "x": 115, "y": 239, "w": 61, "h": 56 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 11, "w": 61, "h": 56 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0055.png", + "frame": { "x": 63, "y": 62, "w": 62, "h": 60 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 62, "h": 60 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0056.png", + "frame": { "x": 63, "y": 0, "w": 66, "h": 62 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 4, "w": 66, "h": 62 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0057.png", + "frame": { "x": 0, "y": 0, "w": 63, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 0, "w": 63, "h": 66 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0058.png", + "frame": { "x": 261, "y": 0, "w": 59, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 0, "w": 59, "h": 66 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0059.png", + "frame": { "x": 181, "y": 184, "w": 53, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 0, "w": 53, "h": 66 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0060.png", + "frame": { "x": 63, "y": 122, "w": 56, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 0, "w": 56, "h": 66 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0061.png", + "frame": { "x": 320, "y": 61, "w": 58, "h": 65 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 1, "w": 58, "h": 65 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0062.png", + "frame": { "x": 129, "y": 61, "w": 59, "h": 64 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 2, "w": 59, "h": 64 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0063.png", + "frame": { "x": 195, "y": 60, "w": 60, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 3, "w": 60, "h": 63 }, + "sourceSize": { "w": 74, "h": 67 } + }, + { + "filename": "0064.png", + "frame": { "x": 255, "y": 66, "w": 59, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 63 }, + "sourceSize": { "w": 74, "h": 67 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.9.2-x64", + "image": "335.png", + "format": "I8", + "size": { "w": 382, "h": 305 }, + "scale": "1" + } } diff --git a/public/images/pokemon/shiny/335.png b/public/images/pokemon/shiny/335.png index 765344af6fd..fc7c325a469 100644 Binary files a/public/images/pokemon/shiny/335.png and b/public/images/pokemon/shiny/335.png differ diff --git a/src/battle.ts b/src/battle.ts index fa333040c22..3f36865c74b 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -101,6 +101,9 @@ export default class Battle { public battleSeed: string = Utils.randomString(16, true); private battleSeedState: string | null = null; public moneyScattered: number = 0; + /** Primarily for double battles, keeps track of last enemy and player pokemon that triggered its ability or used a move */ + public lastEnemyInvolved: number; + public lastPlayerInvolved: number; public lastUsedPokeball: PokeballType | null = null; /** The number of times a Pokemon on the player's side has fainted this battle */ public playerFaints: number = 0; diff --git a/src/data/ability.ts b/src/data/ability.ts index c19b6fe9ba4..21ec5667426 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2756,6 +2756,44 @@ export class PreStatStageChangeAbAttr extends AbAttr { } } +/** + * Reflect all {@linkcode BattleStat} reductions caused by other Pokémon's moves and Abilities. + * Currently only applies to Mirror Armor. + */ +export class ReflectStatStageChangeAbAttr extends PreStatStageChangeAbAttr { + /** {@linkcode BattleStat} to reflect */ + private reflectedStat? : BattleStat; + + /** + * Apply the {@linkcode ReflectStatStageChangeAbAttr} to an interaction + * @param _pokemon The user pokemon + * @param _passive N/A + * @param simulated `true` if the ability is being simulated by the AI + * @param stat the {@linkcode BattleStat} being affected + * @param cancelled The {@linkcode Utils.BooleanHolder} that will be set to true due to reflection + * @param args + * @returns true because it reflects any stat being lowered + */ + applyPreStatStageChange(_pokemon: Pokemon, _passive: boolean, simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const attacker: Pokemon = args[0]; + const stages = args[1]; + this.reflectedStat = stat; + if (!simulated) { + globalScene.unshiftPhase(new StatStageChangePhase(attacker.getBattlerIndex(), false, [ stat ], stages, true, false, true, null, true)); + } + cancelled.value = true; + return true; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { + return i18next.t("abilityTriggers:protectStat", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + abilityName, + statName: this.reflectedStat ? i18next.t(getStatKey(this.reflectedStat)) : i18next.t("battle:stats") + }); + } +} + /** * Protect one or all {@linkcode BattleStat} from reductions caused by other Pokémon's moves and Abilities */ @@ -6065,8 +6103,8 @@ export function initAbilities() { new Ability(Abilities.PROPELLER_TAIL, 8) .attr(BlockRedirectAbAttr), new Ability(Abilities.MIRROR_ARMOR, 8) - .ignorable() - .unimplemented(), + .attr(ReflectStatStageChangeAbAttr) + .ignorable(), /** * Right now, the logic is attached to Surf and Dive moves. Ideally, the post-defend/hit should be an * ability attribute but the current implementation of move effects for BattlerTag does not support this- in the case diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 816de3e824c..2fa4593fd6c 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -910,7 +910,7 @@ class StickyWebTag extends ArenaTrapTag { if (!cancelled.value) { globalScene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() })); const stages = new NumberHolder(-1); - globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value)); + globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value, true, false, true, null, false, true)); return true; } } diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index c399a9bb595..43168ea5c0c 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -1752,7 +1752,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag { super.onAdd(pokemon); let highestStat: EffectiveStat; - EFFECTIVE_STATS.map(s => pokemon.getEffectiveStat(s)).reduce((highestValue: number, value: number, i: number) => { + EFFECTIVE_STATS.map(s => pokemon.getEffectiveStat(s, undefined, undefined, undefined, undefined, undefined, undefined, true)).reduce((highestValue: number, value: number, i: number) => { if (value > highestValue) { highestStat = EFFECTIVE_STATS[i]; return value; @@ -1763,15 +1763,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag { highestStat = highestStat!; // tell TS compiler it's defined! this.stat = highestStat; - switch (this.stat) { - case Stat.SPD: - this.multiplier = 1.5; - break; - default: - this.multiplier = 1.3; - break; - } - + this.multiplier = this.stat === Stat.SPD ? 1.5 : 1.3; globalScene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: i18next.t(getStatKey(highestStat)) }), null, false, null, true); } diff --git a/src/data/move.ts b/src/data/move.ts index 48f90297115..967d2ee0cc2 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4559,7 +4559,8 @@ export class TeraMoveCategoryAttr extends VariableMoveCategoryAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const category = (args[0] as Utils.NumberHolder); - if (user.isTerastallized() && user.getEffectiveStat(Stat.ATK, target, move) > user.getEffectiveStat(Stat.SPATK, target, move)) { + if (user.isTerastallized() && user.getEffectiveStat(Stat.ATK, target, move, true, true, false, false, true) > + user.getEffectiveStat(Stat.SPATK, target, move, true, true, false, false, true)) { category.value = MoveCategory.PHYSICAL; return true; } @@ -10905,8 +10906,7 @@ export function initMoves() { .attr(TeraMoveCategoryAttr) .attr(TeraBlastTypeAttr) .attr(TeraBlastPowerAttr) - .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, { condition: (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR) }) - .partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */ + .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, { condition: (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR) }), new SelfStatusMove(Moves.SILK_TRAP, Type.BUG, -1, 10, -1, 4, 9) .attr(ProtectAttr, BattlerTagType.SILK_TRAP) .condition(failIfLastCondition), diff --git a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts index 53f89069491..287376f8bd0 100644 --- a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts +++ b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts @@ -41,8 +41,6 @@ export const FunAndGamesEncounter: MysteryEncounter = .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) .withSceneRequirement(new MoneyRequirement(0, 1.5)) // Cost equal to 1 Max Potion to play .withAutoHideIntroVisuals(false) - // Allows using move without a visible enemy pokemon - .withBattleAnimationsWithoutTargets(true) // The Wobbuffet won't use moves .withSkipEnemyBattleTurns(true) // Will skip COMMAND selection menu and go straight to FIGHT (move select) menu diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index ead0443908b..351b969b1a8 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -887,16 +887,21 @@ export function getRandomEncounterSpecies(level: number, isBoss: boolean = false let bossSpecies: PokemonSpecies; let isEventEncounter = false; const eventEncounters = globalScene.eventManager.getEventEncounters(); + let formIndex; if (eventEncounters.length > 0 && randSeedInt(2) === 1) { const eventEncounter = randSeedItem(eventEncounters); const levelSpecies = getPokemonSpecies(eventEncounter.species).getWildSpeciesForLevel(level, !eventEncounter.blockEvolution, isBoss, globalScene.gameMode); isEventEncounter = true; bossSpecies = getPokemonSpecies(levelSpecies); + formIndex = eventEncounter.formIndex; } else { bossSpecies = globalScene.arena.randomSpecies(globalScene.currentBattle.waveIndex, level, 0, getPartyLuckValue(globalScene.getPlayerParty()), isBoss); } const ret = new EnemyPokemon(bossSpecies, level, TrainerSlot.NONE, isBoss); + if (formIndex) { + ret.formIndex = formIndex; + } //Reroll shiny for event encounters if (isEventEncounter && !ret.shiny) { diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 16af8364502..79d7192b4db 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -947,11 +947,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param ignoreOppAbility during an attack, determines whether the opposing Pokemon's abilities should be ignored during the stat calculation. * @param isCritical determines whether a critical hit has occurred or not (`false` by default) * @param simulated if `true`, nullifies any effects that produce any changes to game state from triggering + * @param ignoreHeldItems determines whether this Pokemon's held items should be ignored during the stat calculation, default `false` * @returns the final in-battle value of a stat */ - getEffectiveStat(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreAbility: boolean = false, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): number { + getEffectiveStat(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreAbility: boolean = false, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true, ignoreHeldItems: boolean = false): number { const statValue = new Utils.NumberHolder(this.getStat(stat, false)); - globalScene.applyModifiers(StatBoosterModifier, this.isPlayer(), this, stat, statValue); + if (!ignoreHeldItems) { + globalScene.applyModifiers(StatBoosterModifier, this.isPlayer(), this, stat, statValue); + } // The Ruin abilities here are never ignored, but they reveal themselves on summon anyway const fieldApplied = new Utils.BooleanHolder(false); @@ -965,7 +968,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { applyStatMultiplierAbAttrs(StatMultiplierAbAttr, this, stat, statValue, simulated); } - let ret = statValue.value * this.getStatStageMultiplier(stat, opponent, move, ignoreOppAbility, isCritical, simulated); + let ret = statValue.value * this.getStatStageMultiplier(stat, opponent, move, ignoreOppAbility, isCritical, simulated, ignoreHeldItems); switch (stat) { case Stat.ATK: @@ -1063,6 +1066,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { globalScene.applyModifiers(PokemonBaseStatFlatModifier, this.isPlayer(), this, baseStats); if (this.isFusion()) { const fusionBaseStats = this.getFusionSpeciesForm(true).baseStats; + applyChallenges(globalScene.gameMode, ChallengeType.FLIP_STAT, this, fusionBaseStats); + for (const s of PERMANENT_STATS) { baseStats[s] = Math.ceil((baseStats[s] + fusionBaseStats[s]) / 2); } @@ -2487,9 +2492,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param ignoreOppAbility determines whether the effects of the opponent's abilities (i.e. Unaware) should be ignored (`false` by default) * @param isCritical determines whether a critical hit has occurred or not (`false` by default) * @param simulated determines whether effects are applied without altering game state (`true` by default) + * @param ignoreHeldItems determines whether this Pokemon's held items should be ignored during the stat calculation, default `false` * @return the stat stage multiplier to be used for effective stat calculation */ - getStatStageMultiplier(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): number { + getStatStageMultiplier(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true, ignoreHeldItems: boolean = false): number { const statStage = new Utils.IntegerHolder(this.getStatStage(stat)); const ignoreStatStage = new Utils.BooleanHolder(false); @@ -2516,7 +2522,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!ignoreStatStage.value) { const statStageMultiplier = new Utils.NumberHolder(Math.max(2, 2 + statStage.value) / Math.max(2, 2 - statStage.value)); - globalScene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), stat, statStageMultiplier); + if (!ignoreHeldItems) { + globalScene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), stat, statStageMultiplier); + } return Math.min(statStageMultiplier.value, 4); } return 1; @@ -4356,8 +4364,12 @@ export class PlayerPokemon extends Pokemon { ].filter(d => !!d); const amount = new Utils.NumberHolder(friendship); globalScene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); - const candyFriendshipMultiplier = globalScene.eventManager.getClassicFriendshipMultiplier(); - const starterAmount = new Utils.NumberHolder(Math.floor(amount.value * (globalScene.gameMode.isClassic ? candyFriendshipMultiplier : 1) / (fusionStarterSpeciesId ? 2 : 1))); + const candyFriendshipMultiplier = globalScene.gameMode.isClassic ? globalScene.eventManager.getClassicFriendshipMultiplier() : 1; + const fusionReduction = fusionStarterSpeciesId + ? globalScene.eventManager.areFusionsBoosted() ? 1.5 // Divide candy gain for fusions by 1.5 during events + : 2 // 2 for fusions outside events + : 1; // 1 for non-fused mons + const starterAmount = new Utils.NumberHolder(Math.floor(amount.value * candyFriendshipMultiplier / fusionReduction)); // Add friendship to this PlayerPokemon this.friendship = Math.min(this.friendship + amount.value, 255); diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 60a0513f608..e8f817c1c39 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -249,9 +249,9 @@ export class LoadingScene extends SceneBase { } const availableLangs = [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ]; if (lang && availableLangs.includes(lang)) { - this.loadImage("yearofthesnakeevent-" + lang, "events"); + this.loadImage("valentines2025event-" + lang, "events"); } else { - this.loadImage("yearofthesnakeevent-en", "events"); + this.loadImage("valentines2025event-en", "events"); } this.loadAtlas("statuses", ""); diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 526286ff402..b959c354adf 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1720,7 +1720,16 @@ const modifierPool: ModifierPool = { }, 4), new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3), new WeightedModifierType(modifierTypes.TERA_SHARD, 1), - new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => globalScene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 4 : 0), + new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => { + if (party.filter(p => !p.fusionSpecies).length > 1) { + if (globalScene.gameMode.isSplicedOnly) { + return 4; + } else if (globalScene.gameMode.isClassic && globalScene.eventManager.areFusionsBoosted()) { + return 1; + } + } + return 0; + }, 4), new WeightedModifierType(modifierTypes.VOUCHER, (_party: Pokemon[], rerollCount: number) => !globalScene.gameMode.isDaily ? Math.max(1 - rerollCount, 0) : 0, 1), ].map(m => { m.setTier(ModifierTier.GREAT); return m; @@ -1879,7 +1888,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.MULTI_LENS, 18), new WeightedModifierType(modifierTypes.VOUCHER_PREMIUM, (_party: Pokemon[], rerollCount: number) => !globalScene.gameMode.isDaily && !globalScene.gameMode.isEndless && !globalScene.gameMode.isSplicedOnly ? Math.max(5 - rerollCount * 2, 0) : 0, 5), - new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => !globalScene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 24 : 0, 24), + new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => !(globalScene.gameMode.isClassic && globalScene.eventManager.areFusionsBoosted()) && !globalScene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 24 : 0, 24), new WeightedModifierType(modifierTypes.MINI_BLACK_HOLE, () => (globalScene.gameMode.isDaily || (!globalScene.gameMode.isFreshStartChallenge() && globalScene.gameData.isUnlocked(Unlockables.MINI_BLACK_HOLE))) ? 1 : 0, 1), ].map(m => { m.setTier(ModifierTier.MASTER); return m; @@ -2538,7 +2547,7 @@ export function getPartyLuckValue(party: Pokemon[]): number { return DailyLuck.value; } const eventSpecies = globalScene.eventManager.getEventLuckBoostedSpecies(); - const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() + (eventSpecies.includes(p.species.speciesId) ? 1 : 0) : 0) + const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() + (eventSpecies.includes(p.species.speciesId) ? 3 : 0) : 0) .reduce((total: number, value: number) => total += value, 0), 0, 14); return Math.min(globalScene.eventManager.getEventLuckBoost() + (luck ?? 0), 14); } diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index fff8caf38b5..be9a36940ea 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -95,6 +95,13 @@ export class MoveEffectPhase extends PokemonPhase { return super.end(); } + /** If an enemy used this move, set this as last enemy that used move or ability */ + if (!user.isPlayer()) { + globalScene.currentBattle.lastEnemyInvolved = this.fieldIndex; + } else { + globalScene.currentBattle.lastPlayerInvolved = this.fieldIndex; + } + const isDelayedAttack = this.move.getMove().hasAttr(DelayedAttackAttr); /** If the user was somehow removed from the field and it's not a delayed attack, end this phase */ if (!user.isOnField()) { diff --git a/src/phases/show-ability-phase.ts b/src/phases/show-ability-phase.ts index a0db660ded5..d759ad833a1 100644 --- a/src/phases/show-ability-phase.ts +++ b/src/phases/show-ability-phase.ts @@ -17,6 +17,14 @@ export class ShowAbilityPhase extends PokemonPhase { const pokemon = this.getPokemon(); if (pokemon) { + + if (!pokemon.isPlayer()) { + /** If its an enemy pokemon, list it as last enemy to use ability or move */ + globalScene.currentBattle.lastEnemyInvolved = pokemon.getBattlerIndex() % 2; + } else { + globalScene.currentBattle.lastPlayerInvolved = pokemon.getBattlerIndex() % 2; + } + globalScene.abilityBar.showAbility(pokemon, this.passive); if (pokemon?.battleData) { diff --git a/src/phases/stat-stage-change-phase.ts b/src/phases/stat-stage-change-phase.ts index 359610b320c..753d1f7cede 100644 --- a/src/phases/stat-stage-change-phase.ts +++ b/src/phases/stat-stage-change-phase.ts @@ -1,7 +1,8 @@ import { globalScene } from "#app/global-scene"; import type { BattlerIndex } from "#app/battle"; -import { applyAbAttrs, applyPostStatStageChangeAbAttrs, applyPreStatStageChangeAbAttrs, PostStatStageChangeAbAttr, ProtectStatAbAttr, StatStageChangeCopyAbAttr, StatStageChangeMultiplierAbAttr } from "#app/data/ability"; +import { applyAbAttrs, applyPostStatStageChangeAbAttrs, applyPreStatStageChangeAbAttrs, PostStatStageChangeAbAttr, ProtectStatAbAttr, ReflectStatStageChangeAbAttr, StatStageChangeCopyAbAttr, StatStageChangeMultiplierAbAttr } from "#app/data/ability"; import { ArenaTagSide, MistTag } from "#app/data/arena-tag"; +import type { ArenaTag } from "#app/data/arena-tag"; import type Pokemon from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { ResetNegativeStatStageModifier } from "#app/modifier/modifier"; @@ -10,6 +11,8 @@ import { NumberHolder, BooleanHolder } from "#app/utils"; import i18next from "i18next"; import { PokemonPhase } from "./pokemon-phase"; import { Stat, type BattleStat, getStatKey, getStatStageChangeDescriptionKey } from "#enums/stat"; +import { OctolockTag } from "#app/data/battler-tags"; +import { ArenaTagType } from "#app/enums/arena-tag-type"; export type StatStageChangeCallback = (target: Pokemon | null, changed: BattleStat[], relativeChanges: number[]) => void; @@ -21,9 +24,11 @@ export class StatStageChangePhase extends PokemonPhase { private ignoreAbilities: boolean; private canBeCopied: boolean; private onChange: StatStageChangeCallback | null; + private comingFromMirrorArmorUser: boolean; + private comingFromStickyWeb: boolean; - constructor(battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], stages: number, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true, onChange: StatStageChangeCallback | null = null) { + constructor(battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], stages: number, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true, onChange: StatStageChangeCallback | null = null, comingFromMirrorArmorUser: boolean = false, comingFromStickyWeb: boolean = false) { super(battlerIndex); this.selfTarget = selfTarget; @@ -33,6 +38,8 @@ export class StatStageChangePhase extends PokemonPhase { this.ignoreAbilities = ignoreAbilities; this.canBeCopied = canBeCopied; this.onChange = onChange; + this.comingFromMirrorArmorUser = comingFromMirrorArmorUser; + this.comingFromStickyWeb = comingFromStickyWeb; } start() { @@ -41,12 +48,44 @@ export class StatStageChangePhase extends PokemonPhase { if (this.stats.length > 1) { for (let i = 0; i < this.stats.length; i++) { const stat = [ this.stats[i] ]; - globalScene.unshiftPhase(new StatStageChangePhase(this.battlerIndex, this.selfTarget, stat, this.stages, this.showMessage, this.ignoreAbilities, this.canBeCopied, this.onChange)); + globalScene.unshiftPhase(new StatStageChangePhase(this.battlerIndex, this.selfTarget, stat, this.stages, this.showMessage, this.ignoreAbilities, this.canBeCopied, this.onChange, this.comingFromMirrorArmorUser)); } return this.end(); } const pokemon = this.getPokemon(); + let opponentPokemon: Pokemon | undefined; + + /** Gets the position of last enemy or player pokemon that used ability or move, primarily for double battles involving Mirror Armor */ + if (pokemon.isPlayer()) { + /** If this SSCP is not from sticky web, then we find the opponent pokemon that last did something */ + if (!this.comingFromStickyWeb) { + opponentPokemon = globalScene.getEnemyField()[globalScene.currentBattle.lastEnemyInvolved]; + } else { + /** If this SSCP is from sticky web, then check if pokemon that last sucessfully used sticky web is on field */ + const stickyTagID = globalScene.arena.findTagsOnSide( + (t: ArenaTag) => t.tagType === ArenaTagType.STICKY_WEB, + ArenaTagSide.PLAYER)[0].sourceId; + globalScene.getEnemyField().forEach((e) => { + if (e.id === stickyTagID) { + opponentPokemon = e; + } + }); + } + } else { + if (!this.comingFromStickyWeb) { + opponentPokemon = globalScene.getPlayerField()[globalScene.currentBattle.lastPlayerInvolved]; + } else { + const stickyTagID = globalScene.arena.findTagsOnSide( + (t: ArenaTag) => t.tagType === ArenaTagType.STICKY_WEB, + ArenaTagSide.ENEMY)[0].sourceId; + globalScene.getPlayerField().forEach((e) => { + if (e.id === stickyTagID) { + opponentPokemon = e; + } + }); + } + } if (!pokemon.isActive(true)) { return this.end(); @@ -70,6 +109,11 @@ export class StatStageChangePhase extends PokemonPhase { if (!cancelled.value && !this.selfTarget && stages.value < 0) { applyPreStatStageChangeAbAttrs(ProtectStatAbAttr, pokemon, stat, cancelled, simulate); + + /** Potential stat reflection due to Mirror Armor, does not apply to Octolock end of turn effect */ + if (opponentPokemon !== undefined && !pokemon.findTag(t => t instanceof OctolockTag) && !this.comingFromMirrorArmorUser) { + applyPreStatStageChangeAbAttrs(ReflectStatStageChangeAbAttr, pokemon, stat, cancelled, simulate, opponentPokemon, this.stages); + } } // If one stat stage decrease is cancelled, simulate the rest of the applications diff --git a/src/test/abilities/mirror_armor.test.ts b/src/test/abilities/mirror_armor.test.ts new file mode 100644 index 00000000000..070428a8ee7 --- /dev/null +++ b/src/test/abilities/mirror_armor.test.ts @@ -0,0 +1,315 @@ +import { Stat } from "#enums/stat"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { BattlerIndex } from "#app/battle"; + +// TODO: When Magic Bounce is implemented, make a test for its interaction with mirror guard, use screech + +describe("Ability - Mirror Armor", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + game.override.battleType("single") + .enemySpecies(Species.RATTATA) + .enemyMoveset([ Moves.SPLASH, Moves.STICKY_WEB, Moves.TICKLE, Moves.OCTOLOCK ]) + .enemyAbility(Abilities.BALL_FETCH) + .startingLevel(2000) + .moveset([ Moves.SPLASH, Moves.STICKY_WEB, Moves.TICKLE, Moves.OCTOLOCK ]) + .ability(Abilities.BALL_FETCH); + }); + + it("Player side + single battle Intimidate - opponent loses stats", async () => { + game.override.ability(Abilities.MIRROR_ARMOR); + game.override.enemyAbility(Abilities.INTIMIDATE); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + // Enemy has intimidate, enemy should lose -1 atk + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1); + expect(userPokemon.getStatStage(Stat.ATK)).toBe(0); + }); + + it("Enemy side + single battle Intimidate - player loses stats", async () => { + game.override.enemyAbility(Abilities.MIRROR_ARMOR); + game.override.ability(Abilities.INTIMIDATE); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + // Enemy has intimidate, enemy should lose -1 atk + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(userPokemon.getStatStage(Stat.ATK)).toBe(-1); + expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); + }); + + it("Player side + double battle Intimidate - opponents each lose -2 atk", async () => { + game.override.battleType("double"); + game.override.ability(Abilities.MIRROR_ARMOR); + game.override.enemyAbility(Abilities.INTIMIDATE); + await game.classicMode.startBattle([ Species.BULBASAUR, Species.CHARMANDER ]); + + const [ enemy1, enemy2 ] = game.scene.getEnemyField(); + const [ player1, player2 ] = game.scene.getPlayerField(); + + // Enemy has intimidate, enemy should lose -2 atk each + game.move.select(Moves.SPLASH); + game.move.select(Moves.SPLASH, 1); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2); + await game.toNextTurn(); + + expect(enemy1.getStatStage(Stat.ATK)).toBe(-2); + expect(enemy2.getStatStage(Stat.ATK)).toBe(-2); + expect(player1.getStatStage(Stat.ATK)).toBe(0); + expect(player2.getStatStage(Stat.ATK)).toBe(0); + }); + + it("Enemy side + double battle Intimidate - players each lose -2 atk", async () => { + game.override.battleType("double"); + game.override.enemyAbility(Abilities.MIRROR_ARMOR); + game.override.ability(Abilities.INTIMIDATE); + await game.classicMode.startBattle([ Species.BULBASAUR, Species.CHARMANDER ]); + + const [ enemy1, enemy2 ] = game.scene.getEnemyField(); + const [ player1, player2 ] = game.scene.getPlayerField(); + + // Enemy has intimidate, enemy should lose -1 atk + game.move.select(Moves.SPLASH); + game.move.select(Moves.SPLASH, 1); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2); + await game.toNextTurn(); + + expect(enemy1.getStatStage(Stat.ATK)).toBe(0); + expect(enemy2.getStatStage(Stat.ATK)).toBe(0); + expect(player1.getStatStage(Stat.ATK)).toBe(-2); + expect(player2.getStatStage(Stat.ATK)).toBe(-2); + }); + + it("Player side + single battle Intimidate + Tickle - opponent loses stats", async () => { + game.override.ability(Abilities.MIRROR_ARMOR); + game.override.enemyAbility(Abilities.INTIMIDATE); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + // Enemy has intimidate and uses tickle, enemy receives -2 atk and -1 defense + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(-1); + expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-2); + expect(userPokemon.getStatStage(Stat.ATK)).toBe(0); + expect(userPokemon.getStatStage(Stat.DEF)).toBe(0); + }); + + it("Player side + double battle Intimidate + Tickle - opponents each lose -3 atk, -1 def", async () => { + game.override.battleType("double"); + game.override.ability(Abilities.MIRROR_ARMOR); + game.override.enemyAbility(Abilities.INTIMIDATE); + await game.classicMode.startBattle([ Species.BULBASAUR, Species.CHARMANDER ]); + + const [ enemy1, enemy2 ] = game.scene.getEnemyField(); + const [ player1, player2 ] = game.scene.getPlayerField(); + + game.move.select(Moves.SPLASH); + game.move.select(Moves.SPLASH, 1); + await game.forceEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER); + await game.forceEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER_2); + await game.toNextTurn(); + + expect(player1.getStatStage(Stat.ATK)).toBe(0); + expect(player1.getStatStage(Stat.DEF)).toBe(0); + expect(player2.getStatStage(Stat.ATK)).toBe(0); + expect(player2.getStatStage(Stat.DEF)).toBe(0); + expect(enemy1.getStatStage(Stat.ATK)).toBe(-3); + expect(enemy1.getStatStage(Stat.DEF)).toBe(-1); + expect(enemy2.getStatStage(Stat.ATK)).toBe(-3); + expect(enemy2.getStatStage(Stat.DEF)).toBe(-1); + + }); + + it("Enemy side + single battle Intimidate + Tickle - player loses stats", async () => { + game.override.enemyAbility(Abilities.MIRROR_ARMOR); + game.override.ability(Abilities.INTIMIDATE); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + // Enemy has intimidate and uses tickle, enemy receives -2 atk and -1 defense + game.move.select(Moves.TICKLE); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(userPokemon.getStatStage(Stat.DEF)).toBe(-1); + expect(userPokemon.getStatStage(Stat.ATK)).toBe(-2); + expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); + expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0); + }); + + it("Player side + single battle Intimidate + oppoenent has white smoke - no one loses stats", async () => { + game.override.enemyAbility(Abilities.WHITE_SMOKE); + game.override.ability(Abilities.MIRROR_ARMOR); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + // Enemy has intimidate and uses tickle, enemy has white smoke, no one loses stats + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0); + expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); + expect(userPokemon.getStatStage(Stat.ATK)).toBe(0); + expect(userPokemon.getStatStage(Stat.DEF)).toBe(0); + }); + + it("Enemy side + single battle Intimidate + player has white smoke - no one loses stats", async () => { + game.override.ability(Abilities.WHITE_SMOKE); + game.override.enemyAbility(Abilities.MIRROR_ARMOR); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + // Enemy has intimidate and uses tickle, enemy has white smoke, no one loses stats + game.move.select(Moves.TICKLE); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0); + expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); + expect(userPokemon.getStatStage(Stat.ATK)).toBe(0); + expect(userPokemon.getStatStage(Stat.DEF)).toBe(0); + }); + + it("Player side + single battle + opponent uses octolock - does not interact with mirror armor, player loses stats", async () => { + game.override.ability(Abilities.MIRROR_ARMOR); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + // Enemy uses octolock, player loses stats at end of turn + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.OCTOLOCK, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0); + expect(enemyPokemon.getStatStage(Stat.SPDEF)).toBe(0); + expect(userPokemon.getStatStage(Stat.DEF)).toBe(-1); + expect(userPokemon.getStatStage(Stat.SPDEF)).toBe(-1); + }); + + it("Enemy side + single battle + player uses octolock - does not interact with mirror armor, opponent loses stats", async () => { + game.override.enemyAbility(Abilities.MIRROR_ARMOR); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + // Player uses octolock, enemy loses stats at end of turn + game.move.select(Moves.OCTOLOCK); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(userPokemon.getStatStage(Stat.DEF)).toBe(0); + expect(userPokemon.getStatStage(Stat.SPDEF)).toBe(0); + expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(-1); + expect(enemyPokemon.getStatStage(Stat.SPDEF)).toBe(-1); + }); + + it("Both sides have mirror armor - does not loop, player loses attack", async () => { + game.override.enemyAbility(Abilities.MIRROR_ARMOR); + game.override.ability(Abilities.MIRROR_ARMOR); + game.override.ability(Abilities.INTIMIDATE); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(userPokemon.getStatStage(Stat.ATK)).toBe(-1); + expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); + }); + + it("Single battle + sticky web applied player side - player switches out and enemy should lose -1 speed", async () => { + game.override.ability(Abilities.MIRROR_ARMOR); + await game.classicMode.startBattle([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const userPokemon = game.scene.getPlayerPokemon()!; + + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.STICKY_WEB, BattlerIndex.PLAYER); + await game.toNextTurn(); + + game.doSwitchPokemon(1); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.toNextTurn(); + + expect(userPokemon.getStatStage(Stat.SPD)).toBe(0); + expect(enemyPokemon.getStatStage(Stat.SPD)).toBe(-1); + }); + + it("Double battle + sticky web applied player side - player switches out and enemy 1 should lose -1 speed", async () => { + game.override.battleType("double"); + game.override.ability(Abilities.MIRROR_ARMOR); + await game.classicMode.startBattle([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE ]); + + const [ enemy1, enemy2 ] = game.scene.getEnemyField(); + const [ player1, player2 ] = game.scene.getPlayerField(); + + game.move.select(Moves.SPLASH); + game.move.select(Moves.SPLASH, 1); + await game.forceEnemyMove(Moves.STICKY_WEB, BattlerIndex.PLAYER); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2); + await game.toNextTurn(); + + game.doSwitchPokemon(2); + game.move.select(Moves.SPLASH, 1); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); + await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2); + await game.toNextTurn(); + + expect(enemy1.getStatStage(Stat.SPD)).toBe(-1); + expect(enemy2.getStatStage(Stat.SPD)).toBe(0); + expect(player1.getStatStage(Stat.SPD)).toBe(0); + expect(player2.getStatStage(Stat.SPD)).toBe(0); + }); +}); diff --git a/src/test/abilities/protosynthesis.test.ts b/src/test/abilities/protosynthesis.test.ts new file mode 100644 index 00000000000..67786c3ae9e --- /dev/null +++ b/src/test/abilities/protosynthesis.test.ts @@ -0,0 +1,66 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Nature } from "#enums/nature"; +import { Species } from "#enums/species"; +import { Stat } from "#enums/stat"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { BattlerIndex } from "#app/battle"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Protosynthesis", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([ Moves.SPLASH, Moves.TACKLE ]) + .ability(Abilities.PROTOSYNTHESIS) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should not consider temporary items when determining which stat to boost", async() => { + // Mew has uniform base stats + game.override.startingModifier([{ name: "TEMP_STAT_STAGE_BOOSTER", type: Stat.DEF }]) + .enemyMoveset(Moves.SUNNY_DAY) + .startingLevel(100) + .enemyLevel(100); + await game.classicMode.startBattle([ Species.MEW ]); + const mew = game.scene.getPlayerPokemon()!; + // Nature of starting mon is randomized. We need to fix it to a neutral nature for the automated test. + mew.setNature(Nature.HARDY); + const enemy = game.scene.getEnemyPokemon()!; + const def_before_boost = mew.getEffectiveStat(Stat.DEF, undefined, undefined, false, undefined, false, false, true); + const atk_before_boost = mew.getEffectiveStat(Stat.ATK, undefined, undefined, false, undefined, false, false, true); + const initialHp = enemy.hp; + game.move.select(Moves.TACKLE); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.toNextTurn(); + const unboosted_dmg = initialHp - enemy.hp; + enemy.hp = initialHp; + const def_after_boost = mew.getEffectiveStat(Stat.DEF, undefined, undefined, false, undefined, false, false, true); + const atk_after_boost = mew.getEffectiveStat(Stat.ATK, undefined, undefined, false, undefined, false, false, true); + game.move.select(Moves.TACKLE); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.toNextTurn(); + const boosted_dmg = initialHp - enemy.hp; + expect(boosted_dmg).toBeGreaterThan(unboosted_dmg); + expect(def_after_boost).toEqual(def_before_boost); + expect(atk_after_boost).toBeGreaterThan(atk_before_boost); + }); +}); diff --git a/src/test/abilities/shield_dust.test.ts b/src/test/abilities/shield_dust.test.ts index 9f1e6aeb11d..329f52cc4c6 100644 --- a/src/test/abilities/shield_dust.test.ts +++ b/src/test/abilities/shield_dust.test.ts @@ -53,11 +53,11 @@ describe("Abilities - Shield Dust", () => { expect(move.id).toBe(Moves.AIR_SLASH); const chance = new NumberHolder(move.chance); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getFirstTarget(), false); - applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, phase.getFirstTarget()!, phase.getUserPokemon()!, null, null, false, chance); + await applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getFirstTarget(), false); + await applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, phase.getFirstTarget()!, phase.getUserPokemon()!, null, null, false, chance); expect(chance.value).toBe(0); - }, 20000); + }); //TODO King's Rock Interaction Unit Test }); diff --git a/src/test/abilities/unseen_fist.test.ts b/src/test/abilities/unseen_fist.test.ts index f8fa8a723fe..584f997aa55 100644 --- a/src/test/abilities/unseen_fist.test.ts +++ b/src/test/abilities/unseen_fist.test.ts @@ -45,9 +45,9 @@ describe("Abilities - Unseen Fist", () => { it( "should not apply if the source has Long Reach", - () => { + async () => { game.override.passiveAbility(Abilities.LONG_REACH); - testUnseenFistHitResult(game, Moves.QUICK_ATTACK, Moves.PROTECT, false); + await testUnseenFistHitResult(game, Moves.QUICK_ATTACK, Moves.PROTECT, false); } ); @@ -67,7 +67,7 @@ describe("Abilities - Unseen Fist", () => { game.override.enemyLevel(1); game.override.moveset([ Moves.TACKLE ]); - await game.startBattle(); + await game.classicMode.startBattle(); const enemyPokemon = game.scene.getEnemyPokemon()!; enemyPokemon.addTag(BattlerTagType.SUBSTITUTE, 0, Moves.NONE, enemyPokemon.id); @@ -86,7 +86,7 @@ async function testUnseenFistHitResult(game: GameManager, attackMove: Moves, pro game.override.moveset([ attackMove ]); game.override.enemyMoveset([ protectMove, protectMove, protectMove, protectMove ]); - await game.startBattle(); + await game.classicMode.startBattle(); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); diff --git a/src/test/data/status_effect.test.ts b/src/test/data/status_effect.test.ts index 7948549b8e8..071dea989a9 100644 --- a/src/test/data/status_effect.test.ts +++ b/src/test/data/status_effect.test.ts @@ -20,8 +20,8 @@ const pokemonName = "PKM"; const sourceText = "SOURCE"; describe("Status Effect Messages", () => { - beforeAll(() => { - i18next.init(); + beforeAll(async () => { + await i18next.init(); }); describe("NONE", () => { diff --git a/src/test/evolution.test.ts b/src/test/evolution.test.ts index d198049801c..8dc19a548ca 100644 --- a/src/test/evolution.test.ts +++ b/src/test/evolution.test.ts @@ -40,10 +40,10 @@ describe("Evolution", () => { eevee.abilityIndex = 2; trapinch.abilityIndex = 2; - eevee.evolve(pokemonEvolutions[Species.EEVEE][6], eevee.getSpeciesForm()); + await eevee.evolve(pokemonEvolutions[Species.EEVEE][6], eevee.getSpeciesForm()); expect(eevee.abilityIndex).toBe(2); - trapinch.evolve(pokemonEvolutions[Species.TRAPINCH][0], trapinch.getSpeciesForm()); + await trapinch.evolve(pokemonEvolutions[Species.TRAPINCH][0], trapinch.getSpeciesForm()); expect(trapinch.abilityIndex).toBe(1); }); @@ -55,10 +55,10 @@ describe("Evolution", () => { bulbasaur.abilityIndex = 0; charmander.abilityIndex = 1; - bulbasaur.evolve(pokemonEvolutions[Species.BULBASAUR][0], bulbasaur.getSpeciesForm()); + await bulbasaur.evolve(pokemonEvolutions[Species.BULBASAUR][0], bulbasaur.getSpeciesForm()); expect(bulbasaur.abilityIndex).toBe(0); - charmander.evolve(pokemonEvolutions[Species.CHARMANDER][0], charmander.getSpeciesForm()); + await charmander.evolve(pokemonEvolutions[Species.CHARMANDER][0], charmander.getSpeciesForm()); expect(charmander.abilityIndex).toBe(1); }); @@ -68,7 +68,7 @@ describe("Evolution", () => { const squirtle = game.scene.getPlayerPokemon()!; squirtle.abilityIndex = 5; - squirtle.evolve(pokemonEvolutions[Species.SQUIRTLE][0], squirtle.getSpeciesForm()); + await squirtle.evolve(pokemonEvolutions[Species.SQUIRTLE][0], squirtle.getSpeciesForm()); expect(squirtle.abilityIndex).toBe(0); }); @@ -80,7 +80,7 @@ describe("Evolution", () => { nincada.metBiome = -1; nincada.gender = 1; - nincada.evolve(pokemonEvolutions[Species.NINCADA][0], nincada.getSpeciesForm()); + await nincada.evolve(pokemonEvolutions[Species.NINCADA][0], nincada.getSpeciesForm()); const ninjask = game.scene.getPlayerParty()[0]; const shedinja = game.scene.getPlayerParty()[1]; expect(ninjask.abilityIndex).toBe(2); diff --git a/src/test/items/light_ball.test.ts b/src/test/items/light_ball.test.ts index 987a5ab8b0c..aae1d806a28 100644 --- a/src/test/items/light_ball.test.ts +++ b/src/test/items/light_ball.test.ts @@ -31,7 +31,7 @@ describe("Items - Light Ball", () => { it("LIGHT_BALL activates in battle correctly", async() => { game.override.startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "LIGHT_BALL" }]); const consoleSpy = vi.spyOn(console, "log"); - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU ]); @@ -64,7 +64,7 @@ describe("Items - Light Ball", () => { }); it("LIGHT_BALL held by PIKACHU", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU ]); @@ -83,7 +83,7 @@ describe("Items - Light Ball", () => { expect(spAtkValue.value / spAtkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue); @@ -92,7 +92,7 @@ describe("Items - Light Ball", () => { }, 20000); it("LIGHT_BALL held by fused PIKACHU (base)", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU, Species.MAROWAK ]); @@ -122,7 +122,7 @@ describe("Items - Light Ball", () => { expect(spAtkValue.value / spAtkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue); @@ -161,7 +161,7 @@ describe("Items - Light Ball", () => { expect(spAtkValue.value / spAtkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue); @@ -189,7 +189,7 @@ describe("Items - Light Ball", () => { expect(spAtkValue.value / spAtkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue); diff --git a/src/test/items/metal_powder.test.ts b/src/test/items/metal_powder.test.ts index 42ef9c1bb16..68c3107af08 100644 --- a/src/test/items/metal_powder.test.ts +++ b/src/test/items/metal_powder.test.ts @@ -31,7 +31,7 @@ describe("Items - Metal Powder", () => { it("METAL_POWDER activates in battle correctly", async() => { game.override.startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "METAL_POWDER" }]); const consoleSpy = vi.spyOn(console, "log"); - await game.startBattle([ + await game.classicMode.startBattle([ Species.DITTO ]); @@ -79,7 +79,7 @@ describe("Items - Metal Powder", () => { expect(defValue.value / defStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue); expect(defValue.value / defStat).toBe(2); @@ -112,7 +112,7 @@ describe("Items - Metal Powder", () => { expect(defValue.value / defStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue); expect(defValue.value / defStat).toBe(2); @@ -145,7 +145,7 @@ describe("Items - Metal Powder", () => { expect(defValue.value / defStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue); expect(defValue.value / defStat).toBe(2); @@ -167,7 +167,7 @@ describe("Items - Metal Powder", () => { expect(defValue.value / defStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue); expect(defValue.value / defStat).toBe(1); diff --git a/src/test/items/quick_powder.test.ts b/src/test/items/quick_powder.test.ts index d30111cbd6a..ae16daf17ff 100644 --- a/src/test/items/quick_powder.test.ts +++ b/src/test/items/quick_powder.test.ts @@ -31,7 +31,7 @@ describe("Items - Quick Powder", () => { it("QUICK_POWDER activates in battle correctly", async() => { game.override.startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "QUICK_POWDER" }]); const consoleSpy = vi.spyOn(console, "log"); - await game.startBattle([ + await game.classicMode.startBattle([ Species.DITTO ]); @@ -64,7 +64,7 @@ describe("Items - Quick Powder", () => { }); it("QUICK_POWDER held by DITTO", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.DITTO ]); @@ -79,14 +79,14 @@ describe("Items - Quick Powder", () => { expect(spdValue.value / spdStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue); expect(spdValue.value / spdStat).toBe(2); - }, 20000); + }); it("QUICK_POWDER held by fused DITTO (base)", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.DITTO, Species.MAROWAK ]); @@ -112,14 +112,14 @@ describe("Items - Quick Powder", () => { expect(spdValue.value / spdStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue); expect(spdValue.value / spdStat).toBe(2); - }, 20000); + }); it("QUICK_POWDER held by fused DITTO (part)", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.MAROWAK, Species.DITTO ]); @@ -145,14 +145,14 @@ describe("Items - Quick Powder", () => { expect(spdValue.value / spdStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue); expect(spdValue.value / spdStat).toBe(2); - }, 20000); + }); it("QUICK_POWDER not held by DITTO", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.MAROWAK ]); @@ -167,9 +167,9 @@ describe("Items - Quick Powder", () => { expect(spdValue.value / spdStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue); expect(spdValue.value / spdStat).toBe(1); - }, 20000); + }); }); diff --git a/src/test/items/thick_club.test.ts b/src/test/items/thick_club.test.ts index 08b19250ea7..d32c213e506 100644 --- a/src/test/items/thick_club.test.ts +++ b/src/test/items/thick_club.test.ts @@ -31,7 +31,7 @@ describe("Items - Thick Club", () => { it("THICK_CLUB activates in battle correctly", async() => { game.override.startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "THICK_CLUB" }]); const consoleSpy = vi.spyOn(console, "log"); - await game.startBattle([ + await game.classicMode.startBattle([ Species.CUBONE ]); @@ -64,7 +64,7 @@ describe("Items - Thick Club", () => { }); it("THICK_CLUB held by CUBONE", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.CUBONE ]); @@ -79,14 +79,14 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); - }, 20000); + }); it("THICK_CLUB held by MAROWAK", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.MAROWAK ]); @@ -101,14 +101,14 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); - }, 20000); + }); it("THICK_CLUB held by ALOLA_MAROWAK", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.ALOLA_MAROWAK ]); @@ -123,18 +123,18 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); - }, 20000); + }); it("THICK_CLUB held by fused CUBONE line (base)", async() => { // Randomly choose from the Cubone line const species = [ Species.CUBONE, Species.MAROWAK, Species.ALOLA_MAROWAK ]; const randSpecies = Utils.randInt(species.length); - await game.startBattle([ + await game.classicMode.startBattle([ species[randSpecies], Species.PIKACHU ]); @@ -160,18 +160,18 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); - }, 20000); + }); it("THICK_CLUB held by fused CUBONE line (part)", async() => { // Randomly choose from the Cubone line const species = [ Species.CUBONE, Species.MAROWAK, Species.ALOLA_MAROWAK ]; const randSpecies = Utils.randInt(species.length); - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU, species[randSpecies] ]); @@ -197,14 +197,14 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); - }, 20000); + }); it("THICK_CLUB not held by CUBONE", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU ]); @@ -219,9 +219,9 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); + await game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(1); - }, 20000); + }); }); diff --git a/src/test/moves/dragon_rage.test.ts b/src/test/moves/dragon_rage.test.ts index a2350960546..61630ede326 100644 --- a/src/test/moves/dragon_rage.test.ts +++ b/src/test/moves/dragon_rage.test.ts @@ -45,14 +45,10 @@ describe("Moves - Dragon Rage", () => { game.override.enemyPassiveAbility(Abilities.BALL_FETCH); game.override.enemyLevel(100); - await game.startBattle(); + await game.classicMode.startBattle(); partyPokemon = game.scene.getPlayerParty()[0]; enemyPokemon = game.scene.getEnemyPokemon()!; - - // remove berries - game.scene.removePartyMemberModifiers(0); - game.scene.clearEnemyHeldItemModifiers(); }); it("ignores weaknesses", async () => { diff --git a/src/test/moves/fissure.test.ts b/src/test/moves/fissure.test.ts index 0975a87b2b1..65719df0205 100644 --- a/src/test/moves/fissure.test.ts +++ b/src/test/moves/fissure.test.ts @@ -41,14 +41,10 @@ describe("Moves - Fissure", () => { game.override.enemyPassiveAbility(Abilities.BALL_FETCH); game.override.enemyLevel(100); - await game.startBattle(); + await game.classicMode.startBattle(); partyPokemon = game.scene.getPlayerParty()[0]; enemyPokemon = game.scene.getEnemyPokemon()!; - - // remove berries - game.scene.removePartyMemberModifiers(0); - game.scene.clearEnemyHeldItemModifiers(); }); it("ignores damage modification from abilities, for example FUR_COAT", async () => { diff --git a/src/test/moves/tera_blast.test.ts b/src/test/moves/tera_blast.test.ts index 44dc29f68b5..21cbf4c1463 100644 --- a/src/test/moves/tera_blast.test.ts +++ b/src/test/moves/tera_blast.test.ts @@ -1,6 +1,6 @@ import { BattlerIndex } from "#app/battle"; import { Stat } from "#enums/stat"; -import { allMoves } from "#app/data/move"; +import { allMoves, TeraMoveCategoryAttr } from "#app/data/move"; import { Type } from "#enums/type"; import { Abilities } from "#app/enums/abilities"; import { HitResult } from "#app/field/pokemon"; @@ -14,6 +14,7 @@ describe("Moves - Tera Blast", () => { let phaserGame: Phaser.Game; let game: GameManager; const moveToCheck = allMoves[Moves.TERA_BLAST]; + const teraBlastAttr = moveToCheck.getAttrs(TeraMoveCategoryAttr)[0]; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -86,19 +87,86 @@ describe("Moves - Tera Blast", () => { expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.SUPER_EFFECTIVE); }); - // Currently abilities are bugged and can't see when a move's category is changed - it.todo("uses the higher stat of the user's Atk and SpAtk for damage calculation", async () => { - game.override.enemyAbility(Abilities.TOXIC_DEBRIS); + it("uses the higher ATK for damage calculation", async () => { await game.startBattle(); const playerPokemon = game.scene.getPlayerPokemon()!; playerPokemon.stats[Stat.ATK] = 100; playerPokemon.stats[Stat.SPATK] = 1; + vi.spyOn(teraBlastAttr, "apply"); + game.move.select(Moves.TERA_BLAST); - await game.phaseInterceptor.to("TurnEndPhase"); - expect(game.scene.getEnemyPokemon()!.battleData.abilityRevealed).toBe(true); - }, 20000); + await game.toNextTurn(); + expect(teraBlastAttr.apply).toHaveLastReturnedWith(true); + }); + + it("uses the higher SPATK for damage calculation", async () => { + await game.startBattle(); + + const playerPokemon = game.scene.getPlayerPokemon()!; + playerPokemon.stats[Stat.ATK] = 1; + playerPokemon.stats[Stat.SPATK] = 100; + + vi.spyOn(teraBlastAttr, "apply"); + + game.move.select(Moves.TERA_BLAST); + await game.toNextTurn(); + expect(teraBlastAttr.apply).toHaveLastReturnedWith(false); + }); + + it("should stay as a special move if ATK turns lower than SPATK mid-turn", async () => { + game.override.enemyMoveset([ Moves.CHARM ]); + await game.startBattle(); + + const playerPokemon = game.scene.getPlayerPokemon()!; + playerPokemon.stats[Stat.ATK] = 51; + playerPokemon.stats[Stat.SPATK] = 50; + + vi.spyOn(teraBlastAttr, "apply"); + + game.move.select(Moves.TERA_BLAST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextTurn(); + expect(teraBlastAttr.apply).toHaveLastReturnedWith(false); + }); + + it("does not change its move category from stat changes due to held items", async () => { + game.override + .startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "THICK_CLUB" }]) + .starterSpecies(Species.CUBONE); + await game.startBattle(); + + const playerPokemon = game.scene.getPlayerPokemon()!; + + playerPokemon.stats[Stat.ATK] = 50; + playerPokemon.stats[Stat.SPATK] = 51; + + vi.spyOn(teraBlastAttr, "apply"); + + game.move.select(Moves.TERA_BLAST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextTurn(); + + expect(teraBlastAttr.apply).toHaveLastReturnedWith(false); + }); + + it("does not change its move category from stat changes due to abilities", async () => { + game.override.ability(Abilities.HUGE_POWER); + await game.startBattle(); + + const playerPokemon = game.scene.getPlayerPokemon()!; + playerPokemon.stats[Stat.ATK] = 50; + playerPokemon.stats[Stat.SPATK] = 51; + + vi.spyOn(teraBlastAttr, "apply"); + + game.move.select(Moves.TERA_BLAST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextTurn(); + expect(teraBlastAttr.apply).toHaveLastReturnedWith(false); + }); + it("causes stat drops if user is Stellar tera type", async () => { game.override.startingHeldItems([{ name: "TERA_SHARD", type: Type.STELLAR }]); diff --git a/src/test/moves/toxic_spikes.test.ts b/src/test/moves/toxic_spikes.test.ts index c2d1c5aaee8..8969289c2f2 100644 --- a/src/test/moves/toxic_spikes.test.ts +++ b/src/test/moves/toxic_spikes.test.ts @@ -132,7 +132,7 @@ describe("Moves - Toxic Spikes", () => { const sessionData : SessionSaveData = gameData["getSessionSaveData"](); localStorage.setItem("sessionTestData", encrypt(JSON.stringify(sessionData), true)); const recoveredData : SessionSaveData = gameData.parseSessionData(decrypt(localStorage.getItem("sessionTestData")!, true)); - gameData.loadSession(0, recoveredData); + await gameData.loadSession(0, recoveredData); expect(sessionData.arena.tags).toEqual(recoveredData.arena.tags); localStorage.removeItem("sessionTestData"); diff --git a/src/test/mystery-encounter/mystery-encounter-utils.test.ts b/src/test/mystery-encounter/mystery-encounter-utils.test.ts index f0057fea7f0..7c924b86e0d 100644 --- a/src/test/mystery-encounter/mystery-encounter-utils.test.ts +++ b/src/test/mystery-encounter/mystery-encounter-utils.test.ts @@ -48,12 +48,12 @@ describe("Mystery Encounter Utils", () => { expect(result.species.speciesId).toBe(Species.ARCEUS); }); - it("gets a fainted pokemon from player party if isAllowedInBattle is false", () => { + it("gets a fainted pokemon from player party if isAllowedInBattle is false", async () => { // Both pokemon fainted scene.getPlayerParty().forEach(p => { p.hp = 0; p.trySetStatus(StatusEffect.FAINT); - p.updateInfo(); + void p.updateInfo(); }); // Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal) @@ -68,12 +68,12 @@ describe("Mystery Encounter Utils", () => { expect(result.species.speciesId).toBe(Species.ARCEUS); }); - it("gets an unfainted legal pokemon from player party if isAllowed is true and isFainted is false", () => { + it("gets an unfainted legal pokemon from player party if isAllowed is true and isFainted is false", async () => { // Only faint 1st pokemon const party = scene.getPlayerParty(); party[0].hp = 0; party[0].trySetStatus(StatusEffect.FAINT); - party[0].updateInfo(); + await party[0].updateInfo(); // Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal) game.override.seed("random"); @@ -87,12 +87,12 @@ describe("Mystery Encounter Utils", () => { expect(result.species.speciesId).toBe(Species.MANAPHY); }); - it("returns last unfainted pokemon if doNotReturnLastAbleMon is false", () => { + it("returns last unfainted pokemon if doNotReturnLastAbleMon is false", async () => { // Only faint 1st pokemon const party = scene.getPlayerParty(); party[0].hp = 0; party[0].trySetStatus(StatusEffect.FAINT); - party[0].updateInfo(); + await party[0].updateInfo(); // Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal) game.override.seed("random"); @@ -106,12 +106,12 @@ describe("Mystery Encounter Utils", () => { expect(result.species.speciesId).toBe(Species.MANAPHY); }); - it("never returns last unfainted pokemon if doNotReturnLastAbleMon is true", () => { + it("never returns last unfainted pokemon if doNotReturnLastAbleMon is true", async () => { // Only faint 1st pokemon const party = scene.getPlayerParty(); party[0].hp = 0; party[0].trySetStatus(StatusEffect.FAINT); - party[0].updateInfo(); + await party[0].updateInfo(); // Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal) game.override.seed("random"); @@ -152,12 +152,12 @@ describe("Mystery Encounter Utils", () => { expect(result.species.speciesId).toBe(Species.ARCEUS); }); - it("returns highest level unfainted if unfainted is true", () => { + it("returns highest level unfainted if unfainted is true", async () => { const party = scene.getPlayerParty(); party[0].level = 100; party[0].hp = 0; party[0].trySetStatus(StatusEffect.FAINT); - party[0].updateInfo(); + await party[0].updateInfo(); party[1].level = 10; const result = getHighestLevelPlayerPokemon(true); @@ -191,12 +191,12 @@ describe("Mystery Encounter Utils", () => { expect(result.species.speciesId).toBe(Species.ARCEUS); }); - it("returns lowest level unfainted if unfainted is true", () => { + it("returns lowest level unfainted if unfainted is true", async () => { const party = scene.getPlayerParty(); party[0].level = 10; party[0].hp = 0; party[0].trySetStatus(StatusEffect.FAINT); - party[0].updateInfo(); + await party[0].updateInfo(); party[1].level = 100; const result = getLowestLevelPlayerPokemon(true); diff --git a/src/test/ui/transfer-item.test.ts b/src/test/ui/transfer-item.test.ts index 762db7fc7ce..b08b056f60e 100644 --- a/src/test/ui/transfer-item.test.ts +++ b/src/test/ui/transfer-item.test.ts @@ -2,8 +2,6 @@ import { BerryType } from "#app/enums/berry-type"; import { Button } from "#app/enums/buttons"; import { Moves } from "#app/enums/moves"; import { Species } from "#app/enums/species"; -import { BattleEndPhase } from "#app/phases/battle-end-phase"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import PartyUiHandler, { PartyUiMode } from "#app/ui/party-ui-handler"; import { Mode } from "#app/ui/ui"; @@ -12,7 +10,6 @@ import Phaser from "phaser"; import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("UI - Transfer Items", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -41,7 +38,7 @@ describe("UI - Transfer Items", () => { game.override.enemySpecies(Species.MAGIKARP); game.override.enemyMoveset([ Moves.SPLASH ]); - await game.startBattle([ Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA ]); + await game.classicMode.startBattle([ Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA ]); game.move.select(Moves.DRAGON_CLAW); @@ -52,10 +49,10 @@ describe("UI - Transfer Items", () => { handler.setCursor(1); handler.processInput(Button.ACTION); - game.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER); + void game.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER); }); - await game.phaseInterceptor.to(BattleEndPhase); + await game.phaseInterceptor.to("BattleEndPhase"); }); it("check red tint for held item limit in transfer menu", async () => { @@ -72,7 +69,7 @@ describe("UI - Transfer Items", () => { game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.to(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); }, 20000); it("check transfer option for pokemon to transfer to", async () => { @@ -91,6 +88,6 @@ describe("UI - Transfer Items", () => { game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.to(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); }, 20000); }); diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 7a9f0e59993..bebacf87ebc 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -27,6 +27,7 @@ interface EventBanner { interface EventEncounter { species: Species; blockEvolution?: boolean; + formIndex?: number; } interface EventMysteryEncounterTier { @@ -49,6 +50,7 @@ interface TimedEvent extends EventBanner { weather?: WeatherPoolEntry[]; mysteryEncounterTierChanges?: EventMysteryEncounterTier[]; luckBoostedSpecies?: Species[]; + boostFusions?: boolean; //MODIFIER REWORK PLEASE } const timedEvents: TimedEvent[] = [ @@ -144,6 +146,40 @@ const timedEvents: TimedEvent[] = [ Species.ROARING_MOON, Species.BLOODMOON_URSALUNA ] + }, + { + name: "Valentine", + eventType: EventType.SHINY, + startDate: new Date(Date.UTC(2025, 1, 10)), + endDate: new Date(Date.UTC(2025, 1, 21)), + boostFusions: true, + shinyMultiplier: 2, + bannerKey: "valentines2025event-", + scale: 0.21, + availableLangs: [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ], + eventEncounters: [ + { species: Species.NIDORAN_F }, + { species: Species.NIDORAN_M }, + { species: Species.IGGLYBUFF }, + { species: Species.SMOOCHUM }, + { species: Species.VOLBEAT }, + { species: Species.ILLUMISE }, + { species: Species.ROSELIA }, + { species: Species.LUVDISC }, + { species: Species.WOOBAT }, + { species: Species.FRILLISH }, + { species: Species.ALOMOMOLA }, + { species: Species.FURFROU, formIndex: 1 }, // Heart trim + { species: Species.ESPURR }, + { species: Species.SPRITZEE }, + { species: Species.SWIRLIX }, + { species: Species.APPLIN }, + { species: Species.MILCERY }, + { species: Species.INDEEDEE }, + { species: Species.TANDEMAUS }, + { species: Species.ENAMORUS } + ], + luckBoostedSpecies: [ Species.LUVDISC ] } ]; @@ -297,6 +333,10 @@ export class TimedEventManager { }); return ret; } + + areFusionsBoosted(): boolean { + return timedEvents.some((te) => this.isActive(te) && te.boostFusions); + } } export class TimedEventDisplay extends Phaser.GameObjects.Container { diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 3305b3f7aa2..cf5d40bc006 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -96,6 +96,9 @@ export default class SummaryUiHandler extends UiHandler { private friendshipText: Phaser.GameObjects.Text; private friendshipIcon: Phaser.GameObjects.Sprite; private friendshipOverlay: Phaser.GameObjects.Sprite; + private permStatsContainer: Phaser.GameObjects.Container; + private ivContainer: Phaser.GameObjects.Container; + private statsContainer: Phaser.GameObjects.Container; private descriptionScrollTween: Phaser.Tweens.Tween | null; private moveCursorBlinkTimer: Phaser.Time.TimerEvent | null; @@ -534,6 +537,10 @@ export default class SummaryUiHandler extends UiHandler { this.passiveContainer.nameText?.setVisible(!this.passiveContainer.descriptionText?.visible); this.passiveContainer.descriptionText?.setVisible(!this.passiveContainer.descriptionText.visible); this.passiveContainer.labelImage.setVisible(!this.passiveContainer.labelImage.visible); + } else if (this.cursor === Page.STATS) { + //Show IVs + this.permStatsContainer.setVisible(!this.permStatsContainer.visible); + this.ivContainer.setVisible(!this.ivContainer.visible); } } else if (button === Button.CANCEL) { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { @@ -877,8 +884,13 @@ export default class SummaryUiHandler extends UiHandler { profileContainer.add(memoText); break; case Page.STATS: - const statsContainer = globalScene.add.container(0, -pageBg.height); - pageContainer.add(statsContainer); + this.statsContainer = globalScene.add.container(0, -pageBg.height); + pageContainer.add(this.statsContainer); + this.permStatsContainer = globalScene.add.container(27, 56); + this.statsContainer.add(this.permStatsContainer); + this.ivContainer = globalScene.add.container(27, 56); + this.statsContainer.add(this.ivContainer); + this.statsContainer.setVisible(true); PERMANENT_STATS.forEach((stat, s) => { const statName = i18next.t(getStatKey(stat)); @@ -887,18 +899,27 @@ export default class SummaryUiHandler extends UiHandler { const natureStatMultiplier = getNatureStatMultiplier(this.pokemon?.getNature()!, s); // TODO: is this bang correct? - const statLabel = addTextObject(27 + 115 * colIndex + (colIndex === 1 ? 5 : 0), 56 + 16 * rowIndex, statName, natureStatMultiplier === 1 ? TextStyle.SUMMARY : natureStatMultiplier > 1 ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE); + const statLabel = addTextObject(115 * colIndex + (colIndex === 1 ? 5 : 0), 16 * rowIndex, statName, natureStatMultiplier === 1 ? TextStyle.SUMMARY : natureStatMultiplier > 1 ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE); + const ivLabel = addTextObject(115 * colIndex + (colIndex === 1 ? 5 : 0), 16 * rowIndex, statName, this.pokemon?.ivs[stat] === 31 ? TextStyle.SUMMARY_GOLD : TextStyle.SUMMARY); + statLabel.setOrigin(0.5, 0); - statsContainer.add(statLabel); + ivLabel.setOrigin(0.5, 0); + this.permStatsContainer.add(statLabel); + this.ivContainer.add(ivLabel); const statValueText = stat !== Stat.HP ? Utils.formatStat(this.pokemon?.getStat(stat)!) // TODO: is this bang correct? : `${Utils.formatStat(this.pokemon?.hp!, true)}/${Utils.formatStat(this.pokemon?.getMaxHp()!, true)}`; // TODO: are those bangs correct? + const ivText = `${this.pokemon?.ivs[stat]}/31`; - const statValue = addTextObject(120 + 88 * colIndex, 56 + 16 * rowIndex, statValueText, TextStyle.WINDOW_ALT); + const statValue = addTextObject(93 + 88 * colIndex, 16 * rowIndex, statValueText, TextStyle.WINDOW_ALT); statValue.setOrigin(1, 0); - statsContainer.add(statValue); + this.permStatsContainer.add(statValue); + const ivValue = addTextObject(93 + 88 * colIndex, 16 * rowIndex, ivText, TextStyle.WINDOW_ALT); + ivValue.setOrigin(1, 0); + this.ivContainer.add(ivValue); }); + this.ivContainer.setVisible(false); const itemModifiers = (globalScene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.pokemonId === this.pokemon?.id, this.playerParty) as PokemonHeldItemModifier[]) @@ -908,7 +929,7 @@ export default class SummaryUiHandler extends UiHandler { const icon = item.getIcon(true); icon.setPosition((i % 17) * 12 + 3, 14 * Math.floor(i / 17) + 15); - statsContainer.add(icon); + this.statsContainer.add(icon); icon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 32, 32), Phaser.Geom.Rectangle.Contains); icon.on("pointerover", () => globalScene.ui.showTooltip(item.type.name, item.type.getDescription(), true)); @@ -924,26 +945,26 @@ export default class SummaryUiHandler extends UiHandler { const expLabel = addTextObject(6, 112, i18next.t("pokemonSummary:expPoints"), TextStyle.SUMMARY); expLabel.setOrigin(0, 0); - statsContainer.add(expLabel); + this.statsContainer.add(expLabel); const nextLvExpLabel = addTextObject(6, 128, i18next.t("pokemonSummary:nextLv"), TextStyle.SUMMARY); nextLvExpLabel.setOrigin(0, 0); - statsContainer.add(nextLvExpLabel); + this.statsContainer.add(nextLvExpLabel); const expText = addTextObject(208, 112, pkmExp.toString(), TextStyle.WINDOW_ALT); expText.setOrigin(1, 0); - statsContainer.add(expText); + this.statsContainer.add(expText); const nextLvExp = pkmLvl < globalScene.getMaxExpLevel() ? getLevelTotalExp(pkmLvl + 1, pkmSpeciesGrowthRate) - pkmExp : 0; const nextLvExpText = addTextObject(208, 128, nextLvExp.toString(), TextStyle.WINDOW_ALT); nextLvExpText.setOrigin(1, 0); - statsContainer.add(nextLvExpText); + this.statsContainer.add(nextLvExpText); const expOverlay = globalScene.add.image(140, 145, "summary_stats_overlay_exp"); expOverlay.setOrigin(0, 0); - statsContainer.add(expOverlay); + this.statsContainer.add(expOverlay); const expMaskRect = globalScene.make.graphics({}); expMaskRect.setScale(6); @@ -954,6 +975,11 @@ export default class SummaryUiHandler extends UiHandler { const expMask = expMaskRect.createGeometryMask(); expOverlay.setMask(expMask); + this.abilityPrompt = globalScene.add.image(0, 0, !globalScene.inputController?.gamepadSupport ? "summary_profile_prompt_z" : "summary_profile_prompt_a"); + this.abilityPrompt.setPosition(8, 47); + this.abilityPrompt.setVisible(true); + this.abilityPrompt.setOrigin(0, 0); + this.statsContainer.add(this.abilityPrompt); break; case Page.MOVES: this.movesContainer = globalScene.add.container(5, -pageBg.height + 26);