diff --git a/package-lock.json b/package-lock.json index a1f40f1b885..33e9dd08104 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pokemon-rogue-battle", - "version": "1.7.7", + "version": "1.8.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pokemon-rogue-battle", - "version": "1.7.7", + "version": "1.8.4", "hasInstallScript": true, "dependencies": { "@material/material-color-utilities": "^0.2.7", @@ -17,7 +17,7 @@ "i18next-korean-postposition-processor": "^1.0.0", "json-stable-stringify": "^1.2.0", "jszip": "^3.10.1", - "phaser": "^3.88.2", + "phaser": "^3.70.0", "phaser3-rex-plugins": "^1.80.14" }, "devDependencies": { @@ -86,14 +86,13 @@ "license": "ISC" }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", + "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" }, "engines": { @@ -322,27 +321,120 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", + "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.8" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz", + "integrity": "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -364,15 +456,15 @@ } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -410,9 +502,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.8.tgz", + "integrity": "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==", "dev": true, "license": "MIT", "dependencies": { @@ -768,9 +860,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", - "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", + "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", "cpu": [ "ppc64" ], @@ -785,9 +877,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", - "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", + "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", "cpu": [ "arm" ], @@ -802,9 +894,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", - "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", + "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", "cpu": [ "arm64" ], @@ -819,9 +911,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", - "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", + "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", "cpu": [ "x64" ], @@ -836,9 +928,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", - "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", + "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", "cpu": [ "arm64" ], @@ -853,9 +945,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", - "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", + "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", "cpu": [ "x64" ], @@ -870,9 +962,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", - "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", + "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", "cpu": [ "arm64" ], @@ -887,9 +979,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", - "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", + "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", "cpu": [ "x64" ], @@ -904,9 +996,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", - "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", + "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", "cpu": [ "arm" ], @@ -921,9 +1013,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", - "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", + "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", "cpu": [ "arm64" ], @@ -938,9 +1030,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", - "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", + "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", "cpu": [ "ia32" ], @@ -955,9 +1047,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", - "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", + "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", "cpu": [ "loong64" ], @@ -972,9 +1064,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", - "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", + "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", "cpu": [ "mips64el" ], @@ -989,9 +1081,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", - "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", + "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", "cpu": [ "ppc64" ], @@ -1006,9 +1098,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", - "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", + "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", "cpu": [ "riscv64" ], @@ -1023,9 +1115,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", - "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", + "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", "cpu": [ "s390x" ], @@ -1040,9 +1132,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", - "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", + "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", "cpu": [ "x64" ], @@ -1057,9 +1149,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", - "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", + "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", "cpu": [ "arm64" ], @@ -1074,9 +1166,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", - "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", + "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", "cpu": [ "x64" ], @@ -1091,9 +1183,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", - "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", + "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", "cpu": [ "arm64" ], @@ -1108,9 +1200,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", - "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", + "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", "cpu": [ "x64" ], @@ -1125,9 +1217,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", - "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", + "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", "cpu": [ "x64" ], @@ -1142,9 +1234,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", - "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", + "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", "cpu": [ "arm64" ], @@ -1159,9 +1251,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", - "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", + "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", "cpu": [ "ia32" ], @@ -1176,9 +1268,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", - "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", + "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", "cpu": [ "x64" ], @@ -1387,13 +1479,15 @@ } }, "node_modules/@gerrit0/mini-shiki": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.2.1.tgz", - "integrity": "sha512-HbzRC6MKB6U8kQhczz0APKPIzFHTrcqhaC7es2EXInq1SpjPVnpVSIsBe6hNoLWqqCx1n5VKiPXq6PfXnHZKOQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.2.2.tgz", + "integrity": "sha512-vaZNGhGLKMY14HbF53xxHNgFO9Wz+t5lTlGNpl2N9xFiKQ0I5oIe0vKjU9dh7Nb3Dw6lZ7wqUE0ri+zcdpnK+Q==", "dev": true, "license": "MIT", "dependencies": { "@shikijs/engine-oniguruma": "^3.2.1", + "@shikijs/langs": "^3.2.1", + "@shikijs/themes": "^3.2.1", "@shikijs/types": "^3.2.1", "@shikijs/vscode-textmate": "^10.0.2" } @@ -1502,99 +1596,6 @@ } } }, - "node_modules/@inquirer/checkbox/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/checkbox/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/checkbox/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/checkbox/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/checkbox/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/checkbox/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/confirm": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.8.tgz", @@ -1617,7 +1618,7 @@ } } }, - "node_modules/@inquirer/confirm/node_modules/@inquirer/core": { + "node_modules/@inquirer/core": { "version": "10.1.9", "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", @@ -1645,42 +1646,14 @@ } } }, - "node_modules/@inquirer/confirm/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/confirm/node_modules/emoji-regex": { + "node_modules/@inquirer/core/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, - "node_modules/@inquirer/confirm/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/confirm/node_modules/string-width": { + "node_modules/@inquirer/core/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -1695,7 +1668,7 @@ "node": ">=8" } }, - "node_modules/@inquirer/confirm/node_modules/wrap-ansi": { + "node_modules/@inquirer/core/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", @@ -1733,99 +1706,6 @@ } } }, - "node_modules/@inquirer/editor/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/editor/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/editor/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/editor/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/editor/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/editor/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/expand": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.11.tgz", @@ -1849,99 +1729,6 @@ } } }, - "node_modules/@inquirer/expand/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/expand/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/expand/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/expand/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/figures": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.11.tgz", @@ -1974,99 +1761,6 @@ } } }, - "node_modules/@inquirer/input/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/input/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/input/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/input/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/input/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/input/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/number": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.11.tgz", @@ -2089,99 +1783,6 @@ } } }, - "node_modules/@inquirer/number/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/number/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/number/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/number/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/password": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.11.tgz", @@ -2205,99 +1806,6 @@ } } }, - "node_modules/@inquirer/password/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/password/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/password/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/password/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/password/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/password/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/prompts": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.4.0.tgz", @@ -2351,99 +1859,6 @@ } } }, - "node_modules/@inquirer/rawlist/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/rawlist/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/rawlist/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/rawlist/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/rawlist/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/rawlist/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/search": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.11.tgz", @@ -2468,99 +1883,6 @@ } } }, - "node_modules/@inquirer/search/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/search/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/search/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/search/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/search/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/search/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/select": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.1.0.tgz", @@ -2586,35 +1908,7 @@ } } }, - "node_modules/@inquirer/select/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/select/node_modules/@inquirer/type": { + "node_modules/@inquirer/type": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", @@ -2632,53 +1926,6 @@ } } }, - "node_modules/@inquirer/select/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/select/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/select/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/select/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2899,6 +2146,19 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.0.tgz", + "integrity": "sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.38.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.38.0.tgz", @@ -3190,6 +2450,26 @@ "@shikijs/vscode-textmate": "^10.0.2" } }, + "node_modules/@shikijs/langs": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.2.1.tgz", + "integrity": "sha512-If0iDHYRSGbihiA8+7uRsgb1er1Yj11pwpX1c6HLYnizDsKAw5iaT3JXj5ZpaimXSWky/IhxTm7C6nkiYVym+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.2.1" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.2.1.tgz", + "integrity": "sha512-k5DKJUT8IldBvAm8WcrDT5+7GA7se6lLksR+2E3SvyqGTyFMzU2F9Gb7rmD+t+Pga1MKrYFxDIeyWjMZWM6uBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.2.1" + } + }, "node_modules/@shikijs/types": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.2.1.tgz", @@ -3331,17 +2611,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz", - "integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.0.tgz", + "integrity": "sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/type-utils": "8.28.0", - "@typescript-eslint/utils": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/type-utils": "8.29.0", + "@typescript-eslint/utils": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -3361,16 +2641,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz", - "integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.0.tgz", + "integrity": "sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/typescript-estree": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/typescript-estree": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", "debug": "^4.3.4" }, "engines": { @@ -3386,14 +2666,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz", - "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.0.tgz", + "integrity": "sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0" + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3404,14 +2684,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz", - "integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.0.tgz", + "integrity": "sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.28.0", - "@typescript-eslint/utils": "8.28.0", + "@typescript-eslint/typescript-estree": "8.29.0", + "@typescript-eslint/utils": "8.29.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -3428,9 +2708,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz", - "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", + "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", "dev": true, "license": "MIT", "engines": { @@ -3442,14 +2722,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz", - "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.0.tgz", + "integrity": "sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3469,16 +2749,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz", - "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.0.tgz", + "integrity": "sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/typescript-estree": "8.28.0" + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/typescript-estree": "8.29.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3493,13 +2773,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz", - "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.0.tgz", + "integrity": "sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/types": "8.29.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -4668,9 +3948,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", - "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", + "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4681,31 +3961,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.1", - "@esbuild/android-arm": "0.25.1", - "@esbuild/android-arm64": "0.25.1", - "@esbuild/android-x64": "0.25.1", - "@esbuild/darwin-arm64": "0.25.1", - "@esbuild/darwin-x64": "0.25.1", - "@esbuild/freebsd-arm64": "0.25.1", - "@esbuild/freebsd-x64": "0.25.1", - "@esbuild/linux-arm": "0.25.1", - "@esbuild/linux-arm64": "0.25.1", - "@esbuild/linux-ia32": "0.25.1", - "@esbuild/linux-loong64": "0.25.1", - "@esbuild/linux-mips64el": "0.25.1", - "@esbuild/linux-ppc64": "0.25.1", - "@esbuild/linux-riscv64": "0.25.1", - "@esbuild/linux-s390x": "0.25.1", - "@esbuild/linux-x64": "0.25.1", - "@esbuild/netbsd-arm64": "0.25.1", - "@esbuild/netbsd-x64": "0.25.1", - "@esbuild/openbsd-arm64": "0.25.1", - "@esbuild/openbsd-x64": "0.25.1", - "@esbuild/sunos-x64": "0.25.1", - "@esbuild/win32-arm64": "0.25.1", - "@esbuild/win32-ia32": "0.25.1", - "@esbuild/win32-x64": "0.25.1" + "@esbuild/aix-ppc64": "0.25.2", + "@esbuild/android-arm": "0.25.2", + "@esbuild/android-arm64": "0.25.2", + "@esbuild/android-x64": "0.25.2", + "@esbuild/darwin-arm64": "0.25.2", + "@esbuild/darwin-x64": "0.25.2", + "@esbuild/freebsd-arm64": "0.25.2", + "@esbuild/freebsd-x64": "0.25.2", + "@esbuild/linux-arm": "0.25.2", + "@esbuild/linux-arm64": "0.25.2", + "@esbuild/linux-ia32": "0.25.2", + "@esbuild/linux-loong64": "0.25.2", + "@esbuild/linux-mips64el": "0.25.2", + "@esbuild/linux-ppc64": "0.25.2", + "@esbuild/linux-riscv64": "0.25.2", + "@esbuild/linux-s390x": "0.25.2", + "@esbuild/linux-x64": "0.25.2", + "@esbuild/netbsd-arm64": "0.25.2", + "@esbuild/netbsd-x64": "0.25.2", + "@esbuild/openbsd-arm64": "0.25.2", + "@esbuild/openbsd-x64": "0.25.2", + "@esbuild/sunos-x64": "0.25.2", + "@esbuild/win32-arm64": "0.25.2", + "@esbuild/win32-ia32": "0.25.2", + "@esbuild/win32-x64": "0.25.2" } }, "node_modules/escalade": { @@ -4815,12 +4095,13 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.9.4.tgz", - "integrity": "sha512-IPWbN0KBgBCpAiSlUcS17zc1eqMzRlYz15AzsFrw2Qfqt+e0IupxYbvYD96bGLKVlNdkNwa4ggv1skztpaZR/g==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.10.0.tgz", + "integrity": "sha512-5ej+0WILhX3D6wkcdsyYmPp10SUIK6fmuZ6KS8nf9MD8CJ6/S/3Dl7m21g+MLeaTMsvcEXo3JunNAbgHwXxs/g==", "dev": true, "license": "MIT", "dependencies": { + "@pkgr/core": "^0.2.0", "@types/doctrine": "^0.0.9", "@typescript-eslint/utils": "^8.28.0", "debug": "^4.4.0", @@ -4828,7 +4109,7 @@ "eslint-import-resolver-node": "^0.3.9", "get-tsconfig": "^4.10.0", "is-glob": "^4.0.3", - "minimatch": "^10.0.1", + "minimatch": "^9.0.3 || ^10.0.1", "semver": "^7.7.1", "stable-hash": "^0.0.5", "tslib": "^2.8.1", @@ -4841,22 +4122,6 @@ "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/eslint-plugin-import-x/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/eslint-scope": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", @@ -5095,9 +4360,9 @@ "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { @@ -5105,7 +4370,7 @@ "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -5145,9 +4410,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { @@ -5730,99 +4995,6 @@ } } }, - "node_modules/inquirer/node_modules/@inquirer/core": { - "version": "10.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", - "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/inquirer/node_modules/@inquirer/type": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", - "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/inquirer/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/inquirer/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/inquirer/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/interpret": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", @@ -6225,9 +5397,9 @@ } }, "node_modules/lefthook": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-1.11.5.tgz", - "integrity": "sha512-iv3pJsfg0zDVqRa+sUsfZ4AsAk2W5KOpouNptLQxFncU5hZa60HfDHIp9pne/E7LoAyzGbwMCGYnBdGpQZc5Pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-1.11.6.tgz", + "integrity": "sha512-j0VmMM50WlPDassmgvapRum9po29Tv1BXzBNFpzGkk9E91CEG9jKik/OHyH/r/na+q8qNIUUyPL6QQuTN/UhQQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -6235,22 +5407,22 @@ "lefthook": "bin/index.js" }, "optionalDependencies": { - "lefthook-darwin-arm64": "1.11.5", - "lefthook-darwin-x64": "1.11.5", - "lefthook-freebsd-arm64": "1.11.5", - "lefthook-freebsd-x64": "1.11.5", - "lefthook-linux-arm64": "1.11.5", - "lefthook-linux-x64": "1.11.5", - "lefthook-openbsd-arm64": "1.11.5", - "lefthook-openbsd-x64": "1.11.5", - "lefthook-windows-arm64": "1.11.5", - "lefthook-windows-x64": "1.11.5" + "lefthook-darwin-arm64": "1.11.6", + "lefthook-darwin-x64": "1.11.6", + "lefthook-freebsd-arm64": "1.11.6", + "lefthook-freebsd-x64": "1.11.6", + "lefthook-linux-arm64": "1.11.6", + "lefthook-linux-x64": "1.11.6", + "lefthook-openbsd-arm64": "1.11.6", + "lefthook-openbsd-x64": "1.11.6", + "lefthook-windows-arm64": "1.11.6", + "lefthook-windows-x64": "1.11.6" } }, "node_modules/lefthook-darwin-arm64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-1.11.5.tgz", - "integrity": "sha512-58VgfpwVZou3OcELAo673gwT1Y2iE0W/zdh9sI7/ZJHjjPNGuxHqroI/woB/SzhRjndwKsa2YUaYntb2ZqgyMw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-1.11.6.tgz", + "integrity": "sha512-gWgdWrKgZgX+bKc6Vs/x7JkO+58lLOpRzpteLx//82D0MKVPlNZwjd4zz4AbIBXtM4Hcj+6gSsOzQ7QDXxjVvQ==", "cpu": [ "arm64" ], @@ -6262,9 +5434,9 @@ ] }, "node_modules/lefthook-darwin-x64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-1.11.5.tgz", - "integrity": "sha512-wZBYZWK0CcsHYQJwLHxaitG1LKIPE0s4E4MjB0oGd4DrFGWSmJUSv1q888Rc1515U2L3VS8CH91f1PvOusTURA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-1.11.6.tgz", + "integrity": "sha512-Ia0TjTKuYcSaDTuoCnbWtpPZ2VEoKzgn33OB90VjNaSVs4ooE0PIdpO+w00x1elqIaf1pbrpq6HgeB26Du8KbQ==", "cpu": [ "x64" ], @@ -6276,9 +5448,9 @@ ] }, "node_modules/lefthook-freebsd-arm64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-1.11.5.tgz", - "integrity": "sha512-fyTZffoe3XaKquQ1gqEybwpSv4z1XRTLkgqYoz3uuY0s/4vcRu1N13egDu5Lqbdm57ps9VWEqYD7wTiHw3ldGA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-1.11.6.tgz", + "integrity": "sha512-PxIwj+hmjLahyzEmcIfalIBDhgklAQCavwM4sGCgbzDi4/+VQX+4aEs4pQqtd7v3aohmjtO/4n2emzTI8donww==", "cpu": [ "arm64" ], @@ -6290,9 +5462,9 @@ ] }, "node_modules/lefthook-freebsd-x64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-1.11.5.tgz", - "integrity": "sha512-sumvthx/U2R36YfNH/Uhwi77ZC5g1s41xBBjAE9VM6xlQarcw/A/DGPu9OaH8AM0Td089jUStT/8zN85GQfg6Q==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-1.11.6.tgz", + "integrity": "sha512-3o1lMKxz1VtWaP/o117wgUn3ZOpefMoSf+8LuiTzI3/PDprIuzgyw2nXKlBZAMDpNPHMNnJeQNts9XLMRmkldg==", "cpu": [ "x64" ], @@ -6304,9 +5476,9 @@ ] }, "node_modules/lefthook-linux-arm64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-1.11.5.tgz", - "integrity": "sha512-DclKoRxDc6NqhPyjuwbA+oOGSkhCZXmHzUdpo/p6Yf4owoJZtcM6yEvWN+77L8N4kUiW2pNoFj61fEZkYCc4pA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-1.11.6.tgz", + "integrity": "sha512-nKPFZ5cA9f5tVn0ybDVqcXXlpTHZqo05N4KQRhWTj5Nem+JoD2YzJIlvZhdJhUrldERqj6deDMXChH5T3z4Rrw==", "cpu": [ "arm64" ], @@ -6318,9 +5490,9 @@ ] }, "node_modules/lefthook-linux-x64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-1.11.5.tgz", - "integrity": "sha512-5omR/uX0TOYJy94uWAeQIO+4HkoQjW425VQ48HtR3aqmODqj1ELYbR8YKtEcYUK+RqIzREG1kBODXmtIsINTdA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-1.11.6.tgz", + "integrity": "sha512-naN8dllLCOEeP+wznLnq+oXrs1dvt/iMLkcl+pOPWLqFccPfDiHzr8V8GslaTa+rSFsAnvjR7SJIOi5C29xedA==", "cpu": [ "x64" ], @@ -6332,9 +5504,9 @@ ] }, "node_modules/lefthook-openbsd-arm64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-1.11.5.tgz", - "integrity": "sha512-i1Ji2+KBQPeqCFaSmoBkGhcREQ+0zocuo24fxj2I5jkEIZFM0+UvwPTSsg6ZwOgftV2IcqRKGE2DbIQN1M+U2A==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-1.11.6.tgz", + "integrity": "sha512-dPxhJfYQ667T+U3pz1+O3mTRNHzXH/BvPlXSH+oy8uiSry4AtVNRXkVvXPUcpLlrAy6HuFYodsrpCIlWFeYwiQ==", "cpu": [ "arm64" ], @@ -6346,9 +5518,9 @@ ] }, "node_modules/lefthook-openbsd-x64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-1.11.5.tgz", - "integrity": "sha512-60XJUYgk4DEoMX1af8b8R3DosneawiHeJR6A3Pa62rfElVL9puqHEdscA9qW5hW9lm/bH6gFs8KB55yqjMmf1g==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-1.11.6.tgz", + "integrity": "sha512-9D26kcSsjiW4D0AuVDdi+0ZqrsOzRWOpMS/kcUbLfrU99yCvma0rMTqKbbDMkVur/znS7qL53oGahXCXDNA+IQ==", "cpu": [ "x64" ], @@ -6360,9 +5532,9 @@ ] }, "node_modules/lefthook-windows-arm64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-1.11.5.tgz", - "integrity": "sha512-Ttfwdk9QeoDwvgjS71PocpvwuNnB39+8Az6OuXteWaSn5UA3g+wtD28Bu/BRHseym3RhqXfkYWthii7Vwu7iTQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-1.11.6.tgz", + "integrity": "sha512-xdCenr4+BFnfBEhiXj6GJp02EPmcwTAGa7NYm6hVTfDwGXw24tuLv7lpnGjgK3kovN6EukgLH1FYkeyDOBEMnA==", "cpu": [ "arm64" ], @@ -6374,9 +5546,9 @@ ] }, "node_modules/lefthook-windows-x64": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-1.11.5.tgz", - "integrity": "sha512-r5MWvJbnCElXeMzKZ4RTyffqzeIWK1xq526hB/Qt55PfbF8is/caEVoutjhzzhyks2vfXZUwVE7oDYif/co5iA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-1.11.6.tgz", + "integrity": "sha512-Fg2GzLhzeDV/GX8+ydrI0wBOytQWpPkNdngx+a8B/feCDbwjAiFklDG5oV4ytuWrtg1JPEEWLJd6nHefj4wtHA==", "cpu": [ "x64" ], @@ -6757,6 +5929,16 @@ "mustache": "bin/mustache" } }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -7037,9 +6219,9 @@ } }, "node_modules/phaser": { - "version": "3.88.2", - "resolved": "https://registry.npmjs.org/phaser/-/phaser-3.88.2.tgz", - "integrity": "sha512-UBgd2sAFuRJbF2xKaQ5jpMWB8oETncChLnymLGHcrnT53vaqiGrQWbUKUDBawKLm24sghjKo4Bf+/xfv8espZQ==", + "version": "3.80.1", + "resolved": "https://registry.npmjs.org/phaser/-/phaser-3.80.1.tgz", + "integrity": "sha512-VQGAWoDOkEpAWYkI+PUADv5Ql+SM0xpLuAMBJHz9tBcOLqjJ2wd8bUhxJgOqclQlLTg97NmMd9MhS75w16x1Cw==", "license": "MIT", "dependencies": { "eventemitter3": "^5.0.1" @@ -7241,7 +6423,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/readable-stream": { "version": "2.3.8", @@ -7357,9 +6540,9 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -8093,15 +7276,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.28.0.tgz", - "integrity": "sha512-jfZtxJoHm59bvoCMYCe2BM0/baMswRhMmYhy+w6VfcyHrjxZ0OJe0tGasydCpIpA+A/WIJhTyZfb3EtwNC/kHQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.29.0.tgz", + "integrity": "sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.28.0", - "@typescript-eslint/parser": "8.28.0", - "@typescript-eslint/utils": "8.28.0" + "@typescript-eslint/eslint-plugin": "8.29.0", + "@typescript-eslint/parser": "8.29.0", + "@typescript-eslint/utils": "8.29.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8222,9 +7405,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/vite": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", - "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", + "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index f0b7a9a525f..6b1c73db158 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.7.7", + "version": "1.8.4", "type": "module", "scripts": { "start": "vite", @@ -62,7 +62,7 @@ "i18next-korean-postposition-processor": "^1.0.0", "json-stable-stringify": "^1.2.0", "jszip": "^3.10.1", - "phaser": "^3.88.2", + "phaser": "^3.70.0", "phaser3-rex-plugins": "^1.80.14" }, "engines": { diff --git a/public/audio/bgm/battle_rival_3_afd.mp3 b/public/audio/bgm/battle_rival_3_afd.mp3 new file mode 100644 index 00000000000..6dec5c861c6 Binary files /dev/null and b/public/audio/bgm/battle_rival_3_afd.mp3 differ diff --git a/public/audio/bgm/title_afd.mp3 b/public/audio/bgm/title_afd.mp3 new file mode 100644 index 00000000000..c427d86b397 Binary files /dev/null and b/public/audio/bgm/title_afd.mp3 differ diff --git a/public/images/events/aprf25-de.png b/public/images/events/aprf25-de.png new file mode 100644 index 00000000000..d4bb7ebdc50 Binary files /dev/null and b/public/images/events/aprf25-de.png differ diff --git a/public/images/events/aprf25-en.png b/public/images/events/aprf25-en.png new file mode 100644 index 00000000000..8f7268b01b6 Binary files /dev/null and b/public/images/events/aprf25-en.png differ diff --git a/public/images/events/aprf25-es-ES.png b/public/images/events/aprf25-es-ES.png new file mode 100644 index 00000000000..a6136a2c8de Binary files /dev/null and b/public/images/events/aprf25-es-ES.png differ diff --git a/public/images/events/aprf25-es-MX.png b/public/images/events/aprf25-es-MX.png new file mode 100644 index 00000000000..a6136a2c8de Binary files /dev/null and b/public/images/events/aprf25-es-MX.png differ diff --git a/public/images/events/aprf25-fr.png b/public/images/events/aprf25-fr.png new file mode 100644 index 00000000000..c68264c75dd Binary files /dev/null and b/public/images/events/aprf25-fr.png differ diff --git a/public/images/events/aprf25-it.png b/public/images/events/aprf25-it.png new file mode 100644 index 00000000000..01bc0d2a1f0 Binary files /dev/null and b/public/images/events/aprf25-it.png differ diff --git a/public/images/events/aprf25-ja.png b/public/images/events/aprf25-ja.png new file mode 100644 index 00000000000..c6b62a3672e Binary files /dev/null and b/public/images/events/aprf25-ja.png differ diff --git a/public/images/events/aprf25-ko.png b/public/images/events/aprf25-ko.png new file mode 100644 index 00000000000..bcc87e33ac1 Binary files /dev/null and b/public/images/events/aprf25-ko.png differ diff --git a/public/images/events/aprf25-pt-BR.png b/public/images/events/aprf25-pt-BR.png new file mode 100644 index 00000000000..f56f5b5c1e9 Binary files /dev/null and b/public/images/events/aprf25-pt-BR.png differ diff --git a/public/images/events/aprf25-zh-CN.png b/public/images/events/aprf25-zh-CN.png new file mode 100644 index 00000000000..57b2c3ec5be Binary files /dev/null and b/public/images/events/aprf25-zh-CN.png differ diff --git a/public/locales b/public/locales index e599780a369..e98f0eb9c20 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit e599780a369f87a96ab0469a8908cea86628145f +Subproject commit e98f0eb9c2022bc78b53f0444424c636498e725a diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 5797fda5611..a759cbb84c2 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -170,6 +170,7 @@ import { StatusEffect } from "#enums/status-effect"; import { initGlobalScene } from "#app/global-scene"; import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { HideAbilityPhase } from "#app/phases/hide-ability-phase"; +import { timedEventManager } from "./global-event-manager"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -2268,6 +2269,9 @@ export default class BattleScene extends SceneBase { if (bgmName === undefined) { bgmName = this.currentBattle?.getBgmOverride() || this.arena?.bgm; } + + bgmName = timedEventManager.getEventBgmReplacement(bgmName); + if (this.bgm && bgmName === this.bgm.key) { if (!this.bgm.isPlaying) { this.bgm.play({ @@ -2660,6 +2664,10 @@ export default class BattleScene extends SceneBase { return 41.42; case "mystery_encounter_delibirdy": // Firel Delibirdy return 82.28; + case "title_afd": // Andr06 - PokéRogue Title Remix (AFD) + return 47.66; + case "battle_rival_3_afd": // Andr06 - Final N Battle Remix (AFD) + return 49.147; } return 0; @@ -2929,14 +2937,19 @@ export default class BattleScene extends SceneBase { * @param show Whether to show or hide the bar */ public queueAbilityDisplay(pokemon: Pokemon, passive: boolean, show: boolean): void { - this.unshiftPhase( - show - ? new ShowAbilityPhase(pokemon.getBattlerIndex(), passive) - : new HideAbilityPhase(pokemon.getBattlerIndex(), passive), - ); + this.unshiftPhase(show ? new ShowAbilityPhase(pokemon.getBattlerIndex(), passive) : new HideAbilityPhase()); this.clearPhaseQueueSplice(); } + /** + * Hides the ability bar if it is currently visible + */ + public hideAbilityBar(): void { + if (this.abilityBar.isVisible()) { + this.unshiftPhase(new HideAbilityPhase()); + } + } + /** * Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order) */ diff --git a/src/constants.ts b/src/constants.ts index 63f00b9f33f..927575c0a28 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,7 +2,7 @@ export const PLAYER_PARTY_MAX_SIZE: number = 6; /** Whether to use seasonal splash messages in general */ -export const USE_SEASONAL_SPLASH_MESSAGES: boolean = false; +export const USE_SEASONAL_SPLASH_MESSAGES: boolean = true; /** Name of the session ID cookie */ export const SESSION_ID_COOKIE_NAME: string = "pokerogue_sessionId"; diff --git a/src/data/ability.ts b/src/data/ability.ts index e12dbf1e0e3..eea24c791b0 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -854,7 +854,8 @@ export class PostDefendStatStageChangeAbAttr extends PostDefendAbAttr { } if (this.allOthers) { - const otherPokemon = pokemon.getAlly() ? pokemon.getOpponents().concat([ pokemon.getAlly() ]) : pokemon.getOpponents(); + const ally = pokemon.getAlly(); + const otherPokemon = !Utils.isNullOrUndefined(ally) ? pokemon.getOpponents().concat([ ally ]) : pokemon.getOpponents(); for (const other of otherPokemon) { globalScene.unshiftPhase(new StatStageChangePhase((other).getBattlerIndex(), false, [ this.stat ], this.stages)); } @@ -2460,12 +2461,12 @@ export class PostSummonAllyHealAbAttr extends PostSummonAbAttr { } override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return pokemon.getAlly()?.isActive(true); + return pokemon.getAlly()?.isActive(true) ?? false; } override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { const target = pokemon.getAlly(); - if (!simulated) { + if (!simulated && !Utils.isNullOrUndefined(target)) { globalScene.unshiftPhase(new PokemonHealPhase(target.getBattlerIndex(), Utils.toDmgValue(pokemon.getMaxHp() / this.healRatio), i18next.t("abilityTriggers:postSummonAllyHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(target), pokemonName: pokemon.name }), true, !this.showAnim)); } @@ -2486,12 +2487,12 @@ export class PostSummonClearAllyStatStagesAbAttr extends PostSummonAbAttr { } override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return pokemon.getAlly()?.isActive(true); + return pokemon.getAlly()?.isActive(true) ?? false; } override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { const target = pokemon.getAlly(); - if (!simulated) { + if (!simulated && !Utils.isNullOrUndefined(target)) { for (const s of BATTLE_STATS) { target.setStatStage(s, 0); } @@ -2712,7 +2713,7 @@ export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr { } const ally = pokemon.getAlly(); - if (!ally || ally.getStatStages().every(s => s === 0)) { + if (Utils.isNullOrUndefined(ally) || ally.getStatStages().every(s => s === 0)) { return false; } @@ -2721,7 +2722,7 @@ export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr { override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { const ally = pokemon.getAlly(); - if (!simulated) { + if (!simulated && !Utils.isNullOrUndefined(ally)) { for (const s of BATTLE_STATS) { pokemon.setStatStage(s, ally.getStatStage(s)); } @@ -2822,7 +2823,7 @@ export class PostSummonFormChangeByWeatherAbAttr extends PostSummonAbAttr { private ability: Abilities; constructor(ability: Abilities) { - super(false); + super(true); this.ability = ability; } @@ -2846,7 +2847,6 @@ export class PostSummonFormChangeByWeatherAbAttr extends PostSummonAbAttr { if (!simulated) { globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeWeatherTrigger); globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeRevertWeatherFormTrigger); - globalScene.queueAbilityDisplay(pokemon, passive, true); } } } @@ -2867,8 +2867,9 @@ export class CommanderAbAttr extends AbAttr { // another Pokemon, this effect cannot apply. // TODO: Should this work with X + Dondozo fusions? - return globalScene.currentBattle?.double && pokemon.getAlly()?.species.speciesId === Species.DONDOZO - && !(pokemon.getAlly().isFainted() || pokemon.getAlly().getTag(BattlerTagType.COMMANDED)); + const ally = pokemon.getAlly(); + return globalScene.currentBattle?.double && !Utils.isNullOrUndefined(ally) && ally.species.speciesId === Species.DONDOZO + && !(ally.isFainted() || ally.getTag(BattlerTagType.COMMANDED)); } override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: null, args: any[]): void { @@ -2878,7 +2879,7 @@ export class CommanderAbAttr extends AbAttr { // Play an animation of the source jumping into the ally Dondozo's mouth globalScene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.COMMANDER_APPLY); // Apply boosts from this effect to the ally Dondozo - pokemon.getAlly().addTag(BattlerTagType.COMMANDED, 0, Moves.NONE, pokemon.id); + pokemon.getAlly()?.addTag(BattlerTagType.COMMANDED, 0, Moves.NONE, pokemon.id); // Cancel the source Pokemon's next move (if a move is queued) globalScene.tryRemovePhase((phase) => phase instanceof MovePhase && phase.pokemon === pokemon); } @@ -4078,7 +4079,7 @@ export class PostTurnStatusHealAbAttr extends PostTurnAbAttr { */ export class PostTurnResetStatusAbAttr extends PostTurnAbAttr { private allyTarget: boolean; - private target: Pokemon; + private target: Pokemon | undefined; constructor(allyTarget = false) { super(true); @@ -4091,11 +4092,11 @@ export class PostTurnResetStatusAbAttr extends PostTurnAbAttr { } else { this.target = pokemon; } - return !Utils.isNullOrUndefined(this.target.status); + return !Utils.isNullOrUndefined(this.target?.status); } override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { - if (!simulated && this.target.status) { + if (!simulated && this.target?.status) { globalScene.queueMessage(getStatusEffectHealText(this.target.status?.effect, getPokemonNameWithAffix(this.target))); this.target.resetStatus(false); this.target.updateInfo(); @@ -5441,6 +5442,8 @@ class ForceSwitchOutHelper { * It will not flee if it is a Mystery Encounter with fleeing disabled (checked in `getSwitchOutCondition()`) or if it is a wave 10x wild boss */ } else { + const allyPokemon = switchOutTarget.getAlly(); + if (!globalScene.currentBattle.waveIndex || globalScene.currentBattle.waveIndex % 10 === 0) { return false; } @@ -5448,14 +5451,12 @@ class ForceSwitchOutHelper { if (switchOutTarget.hp > 0) { switchOutTarget.leaveField(false); globalScene.queueMessage(i18next.t("moveTriggers:fled", { pokemonName: getPokemonNameWithAffix(switchOutTarget) }), null, true, 500); - - if (globalScene.currentBattle.double) { - const allyPokemon = switchOutTarget.getAlly(); + if (globalScene.currentBattle.double && !Utils.isNullOrUndefined(allyPokemon)) { globalScene.redirectPokemonMoves(switchOutTarget, allyPokemon); } } - if (!switchOutTarget.getAlly()?.isActive(true)) { + if (!allyPokemon?.isActive(true)) { globalScene.clearEnemyHeldItemModifiers(); if (switchOutTarget.hp) { @@ -6441,9 +6442,9 @@ export function initAbilities() { new Ability(Abilities.CUTE_CHARM, 3) .attr(PostDefendContactApplyTagChanceAbAttr, 30, BattlerTagType.INFATUATED), new Ability(Abilities.PLUS, 3) - .conditionalAttr(p => globalScene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5), + .conditionalAttr(p => globalScene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => (p.getAlly()?.hasAbility(a) ?? false)), StatMultiplierAbAttr, Stat.SPATK, 1.5), new Ability(Abilities.MINUS, 3) - .conditionalAttr(p => globalScene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5), + .conditionalAttr(p => globalScene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => (p.getAlly()?.hasAbility(a) ?? false)), StatMultiplierAbAttr, Stat.SPATK, 1.5), new Ability(Abilities.FORECAST, 3) .uncopiable() .unreplaceable() @@ -6670,7 +6671,7 @@ export function initAbilities() { .attr(PostDefendMoveDisableAbAttr, 30) .bypassFaint(), new Ability(Abilities.HEALER, 5) - .conditionalAttr(pokemon => pokemon.getAlly() && Utils.randSeedInt(10) < 3, PostTurnResetStatusAbAttr, true), + .conditionalAttr(pokemon => !Utils.isNullOrUndefined(pokemon.getAlly()) && Utils.randSeedInt(10) < 3, PostTurnResetStatusAbAttr, true), new Ability(Abilities.FRIEND_GUARD, 5) .attr(AlliedFieldDamageReductionAbAttr, 0.75) .ignorable(), diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 8f1d6b09a73..871f622f70a 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -28,7 +28,6 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { Moves } from "#enums/moves"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; -import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { CommonAnimPhase } from "#app/phases/common-anim-phase"; @@ -1160,9 +1159,11 @@ class TailwindTag extends ArenaTag { ); } // Raise attack by one stage if party member has WIND_RIDER ability + // TODO: Ability displays should be handled by the ability if (pokemon.hasAbility(Abilities.WIND_RIDER)) { - globalScene.unshiftPhase(new ShowAbilityPhase(pokemon.getBattlerIndex())); + globalScene.queueAbilityDisplay(pokemon, false, true); globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.ATK], 1, true)); + globalScene.queueAbilityDisplay(pokemon, false, false); } } } diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index e39c86ee4b3..624e242944b 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -15,7 +15,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [Species.VENUSAUR]: { 0: Abilities.GRASSY_SURGE, 1: Abilities.SEED_SOWER, 2: Abilities.FLOWER_VEIL }, [Species.CHARMANDER]: { 0: Abilities.SHEER_FORCE }, [Species.CHARMELEON]: { 0: Abilities.BEAST_BOOST }, - [Species.CHARIZARD]: { 0: Abilities.BEAST_BOOST, 1: Abilities.LEVITATE, 2: Abilities.INTIMIDATE, 3: Abilities.UNNERVE }, + [Species.CHARIZARD]: { 0: Abilities.BEAST_BOOST, 1: Abilities.LEVITATE, 2: Abilities.TURBOBLAZE, 3: Abilities.UNNERVE }, [Species.SQUIRTLE]: { 0: Abilities.DAUNTLESS_SHIELD }, [Species.WARTORTLE]: { 0: Abilities.DAUNTLESS_SHIELD }, [Species.BLASTOISE]: { 0: Abilities.DAUNTLESS_SHIELD, 1: Abilities.BULLETPROOF, 2: Abilities.BULLETPROOF }, @@ -154,14 +154,14 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [Species.LEAFEON]: { 0: Abilities.GRASSY_SURGE }, [Species.GLACEON]: { 0: Abilities.SNOW_WARNING }, [Species.SYLVEON]: { 0: Abilities.COMPETITIVE }, - [Species.PORYGON]: { 0: Abilities.LEVITATE }, - [Species.PORYGON2]: { 0: Abilities.LEVITATE }, + [Species.PORYGON]: { 0: Abilities.TRANSISTOR }, + [Species.PORYGON2]: { 0: Abilities.TRANSISTOR }, [Species.PORYGON_Z]: { 0: Abilities.PROTEAN }, [Species.OMANYTE]: { 0: Abilities.STURDY }, [Species.OMASTAR]: { 0: Abilities.STURDY }, [Species.KABUTO]: { 0: Abilities.TOUGH_CLAWS }, [Species.KABUTOPS]: { 0: Abilities.TOUGH_CLAWS }, - [Species.AERODACTYL]: { 0: Abilities.INTIMIDATE, 1: Abilities.DELTA_STREAM }, + [Species.AERODACTYL]: { 0: Abilities.INTIMIDATE, 1: Abilities.INTIMIDATE }, [Species.ARTICUNO]: { 0: Abilities.SNOW_WARNING }, [Species.ZAPDOS]: { 0: Abilities.DRIZZLE }, [Species.MOLTRES]: { 0: Abilities.DROUGHT }, @@ -309,7 +309,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [Species.SHIFTRY]: { 0: Abilities.SHARPNESS }, [Species.TAILLOW]: { 0: Abilities.AERILATE }, [Species.SWELLOW]: { 0: Abilities.AERILATE }, - [Species.WINGULL]: { 0: Abilities.DRIZZLE }, + [Species.WINGULL]: { 0: Abilities.WATER_ABSORB }, [Species.PELIPPER]: { 0: Abilities.SWIFT_SWIM }, [Species.RALTS]: { 0: Abilities.NEUROFORCE }, [Species.KIRLIA]: { 0: Abilities.NEUROFORCE }, @@ -612,8 +612,8 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [Species.REUNICLUS]: { 0: Abilities.PSYCHIC_SURGE }, [Species.DUCKLETT]: { 0: Abilities.DRIZZLE }, [Species.SWANNA]: { 0: Abilities.DRIZZLE }, - [Species.VANILLITE]: { 0: Abilities.SNOW_WARNING }, - [Species.VANILLISH]: { 0: Abilities.SNOW_WARNING }, + [Species.VANILLITE]: { 0: Abilities.REFRIGERATE }, + [Species.VANILLISH]: { 0: Abilities.REFRIGERATE }, [Species.VANILLUXE]: { 0: Abilities.SLUSH_RUSH }, [Species.DEERLING]: { 0: Abilities.FLOWER_VEIL, 1: Abilities.CUD_CHEW, 2: Abilities.HARVEST, 3: Abilities.FUR_COAT }, [Species.SAWSBUCK]: { 0: Abilities.FLOWER_VEIL, 1: Abilities.CUD_CHEW, 2: Abilities.HARVEST, 3: Abilities.FUR_COAT }, @@ -838,7 +838,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [Species.CELESTEELA]: { 0: Abilities.HEATPROOF }, [Species.KARTANA]: { 0: Abilities.TECHNICIAN }, [Species.GUZZLORD]: { 0: Abilities.POISON_HEAL }, - [Species.NECROZMA]: { 0: Abilities.BEAST_BOOST, 1: Abilities.FULL_METAL_BODY, 2: Abilities.SHADOW_SHIELD, 3: Abilities.PRISM_ARMOR }, + [Species.NECROZMA]: { 0: Abilities.BEAST_BOOST, 1: Abilities.FULL_METAL_BODY, 2: Abilities.SHADOW_SHIELD, 3: Abilities.UNNERVE }, [Species.MAGEARNA]: { 0: Abilities.STEELY_SPIRIT, 1: Abilities.STEELY_SPIRIT }, [Species.MARSHADOW]: { 0: Abilities.IRON_FIST }, [Species.POIPOLE]: { 0: Abilities.LEVITATE }, diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index c391c4010b8..546dbb4a3db 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -30,7 +30,6 @@ import { CommonAnimPhase } from "#app/phases/common-anim-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MovePhase } from "#app/phases/move-phase"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; -import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import type { StatStageChangeCallback } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import i18next from "#app/plugins/i18n"; @@ -1901,12 +1900,14 @@ export class TruantTag extends AbilityBattlerTag { if (lastMove && lastMove.move !== Moves.NONE) { (globalScene.getCurrentPhase() as MovePhase).cancel(); - globalScene.unshiftPhase(new ShowAbilityPhase(pokemon.id, passive)); + // TODO: Ability displays should be handled by the ability + globalScene.queueAbilityDisplay(pokemon, passive, true); globalScene.queueMessage( i18next.t("battlerTags:truantLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), }), ); + globalScene.queueAbilityDisplay(pokemon, passive, false); } return true; diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 455421ffefd..868fc7d2e60 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -1272,23 +1272,22 @@ function checkSpeciesValidForChallenge(species: PokemonSpecies, props: DexAttrPr if (soft && isValidForChallenge.value) { return true; } - pokemonFormChanges[species.speciesId].forEach(f1 => { - // Exclude form changes that require the mon to be on the field to begin with, - // such as Castform - if (!("item" in f1)) { - return; + + const result = pokemonFormChanges[species.speciesId].some(f1 => { + // Exclude form changes that require the mon to be on the field to begin with + if (!("item" in f1.trigger)) { + return false; } - species.forms.forEach((f2, formIndex) => { + + return species.forms.some((f2, formIndex) => { if (f1.formKey === f2.formKey) { - const formProps = { ...props }; - formProps.formIndex = formIndex; + const formProps = { ...props, formIndex }; const isFormValidForChallenge = new Utils.BooleanHolder(true); applyChallenges(ChallengeType.STARTER_CHOICE, species, isFormValidForChallenge, formProps); - if (isFormValidForChallenge.value) { - return true; - } + return isFormValidForChallenge.value; } + return false; }); }); - return false; + return result; } diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index a05d63b3d3d..2624fe6cda9 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -106,7 +106,6 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { SwitchPhase } from "#app/phases/switch-phase"; import { SwitchSummonPhase } from "#app/phases/switch-summon-phase"; -import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { SpeciesFormChangeRevertWeatherFormTrigger } from "../pokemon-forms"; import type { GameMode } from "#app/game-mode"; import { applyChallenges, ChallengeType } from "../challenge"; @@ -789,9 +788,9 @@ export default class Move implements Localizable { } applyPreAttackAbAttrs(VariableMovePowerAbAttr, source, target, this, simulated, power); - - if (source.getAlly()) { - applyPreAttackAbAttrs(AllyMoveCategoryPowerBoostAbAttr, source.getAlly(), target, this, simulated, power); + const ally = source.getAlly(); + if (!Utils.isNullOrUndefined(ally)) { + applyPreAttackAbAttrs(AllyMoveCategoryPowerBoostAbAttr, ally, target, this, simulated, power); } const fieldAuras = new Set( @@ -912,7 +911,8 @@ export default class Move implements Localizable { ]; // ...and cannot enhance Pollen Puff when targeting an ally. - const exceptPollenPuffAlly: boolean = this.id === Moves.POLLEN_PUFF && targets.includes(user.getAlly().getBattlerIndex()) + const ally = user.getAlly(); + const exceptPollenPuffAlly: boolean = this.id === Moves.POLLEN_PUFF && !Utils.isNullOrUndefined(ally) && targets.includes(ally.getBattlerIndex()) return (!restrictSpread || !isMultiTarget) && !this.isChargingMove() @@ -1924,7 +1924,9 @@ export class PartyStatusCureAttr extends MoveEffectAttr { pokemon.resetStatus(); pokemon.updateInfo(); } else { - globalScene.unshiftPhase(new ShowAbilityPhase(pokemon.id, pokemon.getPassiveAbility()?.id === this.abilityCondition)); + // TODO: Ability displays should be handled by the ability + globalScene.queueAbilityDisplay(pokemon, pokemon.getPassiveAbility()?.id === this.abilityCondition, true); + globalScene.queueAbilityDisplay(pokemon, pokemon.getPassiveAbility()?.id === this.abilityCondition, false); } } } @@ -1945,7 +1947,7 @@ export class FlameBurstAttr extends MoveEffectAttr { const targetAlly = target.getAlly(); const cancelled = new Utils.BooleanHolder(false); - if (targetAlly) { + if (!Utils.isNullOrUndefined(targetAlly)) { applyAbAttrs(BlockNonDirectDamageAbAttr, targetAlly, cancelled); } @@ -1958,7 +1960,7 @@ export class FlameBurstAttr extends MoveEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { - return target.getAlly() ? -5 : 0; + return !Utils.isNullOrUndefined(target.getAlly()) ? -5 : 0; } } @@ -4356,10 +4358,10 @@ export class LastMoveDoublePowerAttr extends VariablePowerAttr { const userAlly = user.getAlly(); const enemyAlly = enemy?.getAlly(); - if (userAlly && userAlly.turnData.acted) { + if (!Utils.isNullOrUndefined(userAlly) && userAlly.turnData.acted) { pokemonActed.push(userAlly); } - if (enemyAlly && enemyAlly.turnData.acted) { + if (!Utils.isNullOrUndefined(enemyAlly) && enemyAlly.turnData.acted) { pokemonActed.push(enemyAlly); } } @@ -6161,9 +6163,8 @@ export class RevivalBlessingAttr extends MoveEffectAttr { pokemon.resetStatus(); pokemon.heal(Math.min(Utils.toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); globalScene.queueMessage(i18next.t("moveTriggers:revivalBlessing", { pokemonName: getPokemonNameWithAffix(pokemon) }), 0, true); - - if (globalScene.currentBattle.double && globalScene.getEnemyParty().length > 1) { - const allyPokemon = user.getAlly(); + const allyPokemon = user.getAlly(); + if (globalScene.currentBattle.double && globalScene.getEnemyParty().length > 1 && !Utils.isNullOrUndefined(allyPokemon)) { // Handle cases where revived pokemon needs to get switched in on same turn if (allyPokemon.isFainted() || allyPokemon === pokemon) { // Enemy switch phase should be removed and replaced with the revived pkmn switching in @@ -6342,18 +6343,19 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { return false; } + const allyPokemon = switchOutTarget.getAlly(); + if (switchOutTarget.hp > 0) { switchOutTarget.leaveField(false); globalScene.queueMessage(i18next.t("moveTriggers:fled", { pokemonName: getPokemonNameWithAffix(switchOutTarget) }), null, true, 500); // in double battles redirect potential moves off fled pokemon - if (globalScene.currentBattle.double) { - const allyPokemon = switchOutTarget.getAlly(); + if (globalScene.currentBattle.double && !Utils.isNullOrUndefined(allyPokemon)) { globalScene.redirectPokemonMoves(switchOutTarget, allyPokemon); } } - if (!switchOutTarget.getAlly()?.isActive(true)) { + if (!allyPokemon?.isActive(true)) { globalScene.clearEnemyHeldItemModifiers(); if (switchOutTarget.hp) { @@ -7029,7 +7031,7 @@ export class RepeatMoveAttr extends MoveEffectAttr { const firstTarget = globalScene.getField()[moveTargets[0]]; if (globalScene.currentBattle.double && moveTargets.length === 1 && firstTarget.isFainted() && firstTarget !== target.getAlly()) { const ally = firstTarget.getAlly(); - if (ally.isActive()) { // ally exists, is not dead and can sponge the blast + if (!Utils.isNullOrUndefined(ally) && ally.isActive()) { // ally exists, is not dead and can sponge the blast moveTargets = [ ally.getBattlerIndex() ]; } } @@ -7403,10 +7405,11 @@ export class AbilityCopyAttr extends MoveEffectAttr { globalScene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name })); user.setTempAbility(target.getAbility()); + const ally = user.getAlly(); - if (this.copyToPartner && globalScene.currentBattle?.double && user.getAlly().hp) { - globalScene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(user.getAlly()), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name })); - user.getAlly().setTempAbility(target.getAbility()); + if (this.copyToPartner && globalScene.currentBattle?.double && !Utils.isNullOrUndefined(ally) && ally.hp) { // TODO is this the best way to check that the ally is active? + globalScene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(ally), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name })); + ally.setTempAbility(target.getAbility()); } return true; @@ -7414,9 +7417,10 @@ export class AbilityCopyAttr extends MoveEffectAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { + const ally = user.getAlly(); let ret = target.getAbility().isCopiable && user.getAbility().isReplaceable; if (this.copyToPartner && globalScene.currentBattle?.double) { - ret = ret && (!user.getAlly().hp || user.getAlly().getAbility().isReplaceable); + ret = ret && (!ally?.hp || ally?.getAbility().isReplaceable); } else { ret = ret && user.getAbility().id !== target.getAbility().id; } @@ -8187,6 +8191,7 @@ export function getMoveTargets(user: Pokemon, move: Moves, replaceTarget?: MoveT let set: Pokemon[] = []; let multiple = false; + const ally: Pokemon | undefined = user.getAlly(); switch (moveTarget) { case MoveTarget.USER: @@ -8197,7 +8202,7 @@ export function getMoveTargets(user: Pokemon, move: Moves, replaceTarget?: MoveT case MoveTarget.OTHER: case MoveTarget.ALL_NEAR_OTHERS: case MoveTarget.ALL_OTHERS: - set = (opponents.concat([ user.getAlly() ])); + set = !Utils.isNullOrUndefined(ally) ? (opponents.concat([ ally ])) : opponents; multiple = moveTarget === MoveTarget.ALL_NEAR_OTHERS || moveTarget === MoveTarget.ALL_OTHERS; break; case MoveTarget.NEAR_ENEMY: @@ -8214,21 +8219,22 @@ export function getMoveTargets(user: Pokemon, move: Moves, replaceTarget?: MoveT return { targets: [ -1 as BattlerIndex ], multiple: false }; case MoveTarget.NEAR_ALLY: case MoveTarget.ALLY: - set = [ user.getAlly() ]; + set = !Utils.isNullOrUndefined(ally) ? [ ally ] : []; break; case MoveTarget.USER_OR_NEAR_ALLY: case MoveTarget.USER_AND_ALLIES: case MoveTarget.USER_SIDE: - set = [ user, user.getAlly() ]; + set = !Utils.isNullOrUndefined(ally) ? [ user, ally ] : [ user ]; multiple = moveTarget !== MoveTarget.USER_OR_NEAR_ALLY; break; case MoveTarget.ALL: case MoveTarget.BOTH_SIDES: - set = [ user, user.getAlly() ].concat(opponents); + set = (!Utils.isNullOrUndefined(ally) ? [ user, ally ] : [ user ]).concat(opponents); multiple = true; break; case MoveTarget.CURSE: - set = user.getTypes(true).includes(PokemonType.GHOST) ? (opponents.concat([ user.getAlly() ])) : [ user ]; + const extraTargets = !Utils.isNullOrUndefined(ally) ? [ ally ] : []; + set = user.getTypes(true).includes(PokemonType.GHOST) ? (opponents.concat(extraTargets)) : [ user ]; break; } @@ -10122,7 +10128,7 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.DEF, Stat.SPDEF ], 1, false, { condition: (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS ].find(a => target.hasAbility(a, false)) }) .ignoresSubstitute() .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p.hasAbility(a, false)))), + .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p?.hasAbility(a, false)))), new StatusMove(Moves.HAPPY_HOUR, PokemonType.NORMAL, -1, 30, -1, 0, 6) // No animation .attr(AddArenaTagAttr, ArenaTagType.HAPPY_HOUR, null, true) .target(MoveTarget.USER_SIDE), @@ -10312,7 +10318,7 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, false, { condition: (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS ].find(a => target.hasAbility(a, false)) }) .ignoresSubstitute() .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p.hasAbility(a, false)))), + .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p?.hasAbility(a, false)))), new AttackMove(Moves.THROAT_CHOP, PokemonType.DARK, MoveCategory.PHYSICAL, 80, 100, 15, 100, 0, 7) .attr(AddBattlerTagAttr, BattlerTagType.THROAT_CHOPPED), new AttackMove(Moves.POLLEN_PUFF, PokemonType.BUG, MoveCategory.SPECIAL, 90, 100, 15, -1, 0, 7) diff --git a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts index c1486ff100b..364484cb511 100644 --- a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts +++ b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts @@ -37,6 +37,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { Species } from "#enums/species"; +import { timedEventManager } from "#app/global-event-manager"; /** the i18n namespace for this encounter */ const namespace = "mysteryEncounters/delibirdy"; @@ -56,7 +57,7 @@ const OPTION_3_DISALLOWED_MODIFIERS = [ const DELIBIRDY_MONEY_PRICE_MULTIPLIER = 2; const doEventReward = () => { - const event_buff = globalScene.eventManager.getDelibirdyBuff(); + const event_buff = timedEventManager.getDelibirdyBuff(); if (event_buff.length > 0) { const candidates = event_buff.filter(c => { const mtype = generateModifierType(modifierTypes[c]); diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index c13501c4511..f80620647b0 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -46,6 +46,7 @@ import { addPokemonDataToDexAndValidateAchievements } from "#app/data/mystery-en import type { PokeballType } from "#enums/pokeball"; import { doShinySparkleAnim } from "#app/field/anims"; import { TrainerType } from "#enums/trainer-type"; +import { timedEventManager } from "#app/global-event-manager"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/globalTradeSystem"; @@ -273,8 +274,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil // Extra shiny roll at 1/128 odds (boosted by events and charms) if (!tradePokemon.shiny) { const shinyThreshold = new NumberHolder(WONDER_TRADE_SHINY_CHANCE); - if (globalScene.eventManager.isEventActive()) { - shinyThreshold.value *= globalScene.eventManager.getShinyMultiplier(); + if (timedEventManager.isEventActive()) { + shinyThreshold.value *= timedEventManager.getShinyMultiplier(); } globalScene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold); @@ -984,12 +985,11 @@ function doTradeReceivedSequence( function generateRandomTraderName() { const length = TrainerType.YOUNGSTER - TrainerType.ACE_TRAINER + 1; // +1 avoids TrainerType.UNKNOWN - const trainerTypePool = i18next.t("trainersCommon:" + TrainerType[randInt(length) + 1], { returnObjects: true }); + const classKey = `trainersCommon:${TrainerType[randInt(length) + 1]}`; // Some trainers have 2 gendered pools, some do not - const gender = randInt(2) === 0 ? "MALE" : "FEMALE"; - const trainerNameString = randSeedItem( - Object.values(trainerTypePool.hasOwnProperty(gender) ? trainerTypePool[gender] : trainerTypePool), - ) as string; + const genderKey = i18next.exists(`${classKey}.MALE`) ? (randInt(2) === 0 ? ".MALE" : ".FEMALE") : ""; + const trainerNameKey = randSeedItem(Object.keys(i18next.t(`${classKey}${genderKey}`, { returnObjects: true }))); + const trainerNameString = i18next.t(`${classKey}${genderKey}.${trainerNameKey}`); // Some names have an '&' symbol and need to be trimmed to a single name instead of a double name const trainerNames = trainerNameString.split(" & "); return trainerNames[randInt(trainerNames.length)]; diff --git a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts index e54df048430..c994c6e993f 100644 --- a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -93,7 +93,7 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder bossSegments: 5, shiny: false, // Shiny lock because shiny is rolled only if the battle option is picked customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }), - nature: Nature.BOLD, + nature: Nature.HARDY, moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER], modifierConfigs: [ { @@ -117,7 +117,7 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(`${namespace}:option.2.stat_boost`); globalScene.unshiftPhase( - new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.DEF, Stat.SPDEF], 2), + new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.DEF, Stat.SPDEF], 1), ); }, }, diff --git a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts index 1c617aa2c7f..e60fe0ddc18 100644 --- a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts +++ b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts @@ -27,6 +27,7 @@ import { Moves } from "#enums/moves"; import { BattlerIndex } from "#app/battle"; import { PokemonMove } from "#app/field/pokemon"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import { randSeedInt } from "#app/utils"; /** the i18n namespace for this encounter */ const namespace = "mysteryEncounters/trashToTreasure"; @@ -80,7 +81,43 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde shiny: false, // Shiny lock because of custom intro sprite formIndex: 1, // Gmax bossSegmentModifier: 1, // +1 Segment from normal - moveSet: [Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH], + moveSet: [Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.HAMMER_ARM, Moves.PAYBACK], + modifierConfigs: [ + { + modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BASE_STAT_BOOSTER) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BASE_STAT_BOOSTER) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.TOXIC_ORB) as PokemonHeldItemModifierType, + stackCount: randSeedInt(2, 0), + }, + { + modifier: generateModifierType(modifierTypes.SOOTHE_BELL) as PokemonHeldItemModifierType, + stackCount: randSeedInt(2, 1), + }, + { + modifier: generateModifierType(modifierTypes.LUCKY_EGG) as PokemonHeldItemModifierType, + stackCount: randSeedInt(3, 1), + }, + { + modifier: generateModifierType(modifierTypes.GOLDEN_EGG) as PokemonHeldItemModifierType, + stackCount: randSeedInt(2, 0), + }, + ], }; const config: EnemyPartyConfig = { levelAdditiveModifier: 0.5, @@ -90,7 +127,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde encounter.enemyPartyConfigs = [config]; // Load animations/sfx for Garbodor fight start moves - loadCustomMovesForEncounter([Moves.TOXIC, Moves.AMNESIA]); + loadCustomMovesForEncounter([Moves.TOXIC, Moves.STOCKPILE]); globalScene.loadSe("PRSFX- Dig2", "battle_anims", "PRSFX- Dig2.wav"); globalScene.loadSe("PRSFX- Venom Drench", "battle_anims", "PRSFX- Venom Drench.wav"); @@ -115,7 +152,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde doGarbageDig(); }) .withOptionPhase(async () => { - // Gain 2 Leftovers and 2 Shell Bell + // Gain 2 Leftovers and 1 Shell Bell await transitionMysteryEncounterIntroVisuals(); await tryApplyDigRewardItems(); @@ -175,7 +212,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde { sourceBattlerIndex: BattlerIndex.ENEMY, targets: [BattlerIndex.ENEMY], - move: new PokemonMove(Moves.AMNESIA), + move: new PokemonMove(Moves.STOCKPILE), ignorePp: true, }, ); @@ -231,21 +268,7 @@ async function tryApplyDigRewardItems() { true, ); - // First Shell bell - for (const pokemon of party) { - const heldItems = globalScene.findModifiers( - m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id, - true, - ) as PokemonHeldItemModifier[]; - const existingShellBell = heldItems.find(m => m instanceof HitHealModifier) as HitHealModifier; - - if (!existingShellBell || existingShellBell.getStackCount() < existingShellBell.getMaxStackCount()) { - await applyModifierTypeToPlayerPokemon(pokemon, shellBell); - break; - } - } - - // Second Shell bell + // Only Shell bell for (const pokemon of party) { const heldItems = globalScene.findModifiers( m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id, @@ -263,7 +286,7 @@ async function tryApplyDigRewardItems() { await showEncounterText( i18next.t("battle:rewardGainCount", { modifierName: shellBell.name, - count: 2, + count: 1, }), null, undefined, diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index 5c6acf43e26..76d07bf01ba 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -65,6 +65,7 @@ import { getPokemonSpecies } from "#app/data/pokemon-species"; import { PokemonType } from "#enums/pokemon-type"; import { getNatureName } from "#app/data/nature"; import { getPokemonNameWithAffix } from "#app/messages"; +import { timedEventManager } from "#app/global-event-manager"; /** * Animates exclamation sprite over trainer's head at start of encounter @@ -1046,7 +1047,7 @@ export function handleMysteryEncounterTurnStartEffects(): boolean { export function getRandomEncounterSpecies(level: number, isBoss = false, rerollHidden = false): EnemyPokemon { let bossSpecies: PokemonSpecies; let isEventEncounter = false; - const eventEncounters = globalScene.eventManager.getEventEncounters(); + const eventEncounters = timedEventManager.getEventEncounters(); let formIndex: number | undefined; if (eventEncounters.length > 0 && randSeedInt(2) === 1) { diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 8ba72e8041f..929d632eb0b 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -3054,11 +3054,11 @@ export function initSpecies() { new PokemonSpecies(Species.DIPPLIN, 9, false, false, false, "Candy Apple Pokémon", PokemonType.GRASS, PokemonType.DRAGON, 0.4, 9.7, Abilities.SUPERSWEET_SYRUP, Abilities.GLUTTONY, Abilities.STICKY_HOLD, 485, 80, 80, 110, 95, 80, 40, 45, 50, 170, GrowthRate.ERRATIC, 50, false), new PokemonSpecies(Species.POLTCHAGEIST, 9, false, false, false, "Matcha Pokémon", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, GrowthRate.SLOW, null, false, false, new PokemonForm("Counterfeit Form", "counterfeit", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, true), - new PokemonForm("Artisan Form", "artisan", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, true), + new PokemonForm("Artisan Form", "artisan", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, false, true), ), new PokemonSpecies(Species.SINISTCHA, 9, false, false, false, "Matcha Pokémon", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178, GrowthRate.SLOW, null, false, false, new PokemonForm("Unremarkable Form", "unremarkable", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178), - new PokemonForm("Masterpiece Form", "masterpiece", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178), + new PokemonForm("Masterpiece Form", "masterpiece", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178, false, null, false, true), ), new PokemonSpecies(Species.OKIDOGI, 9, true, false, false, "Retainer Pokémon", PokemonType.POISON, PokemonType.FIGHTING, 1.8, 92.2, Abilities.TOXIC_CHAIN, Abilities.NONE, Abilities.GUARD_DOG, 555, 88, 128, 115, 58, 86, 80, 3, 0, 276, GrowthRate.SLOW, 100, false), new PokemonSpecies(Species.MUNKIDORI, 9, true, false, false, "Retainer Pokémon", PokemonType.POISON, PokemonType.PSYCHIC, 1, 12.2, Abilities.TOXIC_CHAIN, Abilities.NONE, Abilities.FRISK, 555, 88, 75, 66, 130, 90, 106, 3, 0, 276, GrowthRate.SLOW, 100, false), diff --git a/src/data/trainers/trainer-config.ts b/src/data/trainers/trainer-config.ts index 0e53cd71add..a5ba19290fe 100644 --- a/src/data/trainers/trainer-config.ts +++ b/src/data/trainers/trainer-config.ts @@ -32,6 +32,7 @@ import { TeraAIMode } from "#enums/tera-ai-mode"; import { TrainerPoolTier } from "#enums/trainer-pool-tier"; import { TrainerSlot } from "#enums/trainer-slot"; import { TrainerType } from "#enums/trainer-type"; +import { timedEventManager } from "#app/global-event-manager"; // Type imports import type { PokemonSpeciesFilter } from "#app/data/pokemon-species"; @@ -516,13 +517,13 @@ export class TrainerConfig { // return ret; // } - setEventModifierRewardFuncs(...modifierTypeFuncs: (() => ModifierTypeFunc)[]): TrainerConfig { - this.eventRewardFuncs = modifierTypeFuncs.map(func => () => { - const modifierTypeFunc = func(); - const modifierType = modifierTypeFunc(); - modifierType.withIdFromFunc(modifierTypeFunc); - return modifierType; - }); + /** + * Sets eventRewardFuncs to the active event rewards for the specified wave + * @param wave Associated with {@linkcode getFixedBattleEventRewards} + * @returns this + */ + setEventModifierRewardFuncs(wave: number): TrainerConfig { + this.eventRewardFuncs = timedEventManager.getFixedBattleEventRewards(wave).map(r => modifierTypes[r]); return this; } @@ -3696,11 +3697,7 @@ export const trainerConfigs: TrainerConfigs = { () => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE, ) - .setEventModifierRewardFuncs( - () => modifierTypes.SHINY_CHARM, - () => modifierTypes.ABILITY_CHARM, - () => modifierTypes.CATCHING_CHARM, - ) + .setEventModifierRewardFuncs(8) .setPartyMemberFunc( 0, getRandomPartyMemberFunc( @@ -3768,7 +3765,7 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_rival") .setPartyTemplates(trainerPartyTemplates.RIVAL_2) .setModifierRewardFuncs(() => modifierTypes.EXP_SHARE) - .setEventModifierRewardFuncs(() => modifierTypes.SHINY_CHARM) + .setEventModifierRewardFuncs(25) .setPartyMemberFunc( 0, getRandomPartyMemberFunc( @@ -4077,7 +4074,7 @@ export const trainerConfigs: TrainerConfigs = { getRandomPartyMemberFunc([Species.RAYQUAZA], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 3); p.pokeball = PokeballType.MASTER_BALL; - p.shiny = true; + p.shiny = timedEventManager.getClassicTrainerShinyChance() === 0; p.variant = 1; }), ) @@ -4174,7 +4171,7 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; - p.shiny = true; + p.shiny = timedEventManager.getClassicTrainerShinyChance() === 0; p.variant = 1; p.formIndex = 1; // Mega Rayquaza p.generateName(); diff --git a/src/data/weather.ts b/src/data/weather.ts index c2b0263c9f6..34978232377 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -11,6 +11,7 @@ import { TerrainType, getTerrainName } from "./terrain"; import i18next from "i18next"; import { globalScene } from "#app/global-scene"; import type { Arena } from "#app/field/arena"; +import { timedEventManager } from "#app/global-event-manager"; export class Weather { public weatherType: WeatherType; @@ -405,8 +406,8 @@ export function getRandomWeatherType(arena: Arena): WeatherType { break; } - if (arena.biomeType === Biome.TOWN && globalScene.eventManager.isEventActive()) { - globalScene.eventManager.getWeather()?.map(w => weatherPool.push(w)); + if (arena.biomeType === Biome.TOWN && timedEventManager.isEventActive()) { + timedEventManager.getWeather()?.map(w => weatherPool.push(w)); } if (weatherPool.length > 1) { diff --git a/src/field/arena.ts b/src/field/arena.ts index 4f243789567..cf48647e45e 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -40,7 +40,6 @@ import { TrainerType } from "#enums/trainer-type"; import { Abilities } from "#enums/abilities"; import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#app/data/pokemon-forms"; import { CommonAnimPhase } from "#app/phases/common-anim-phase"; -import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { WeatherType } from "#enums/weather-type"; import { FieldEffectModifier } from "#app/modifier/modifier"; @@ -378,7 +377,6 @@ export class Arena { const isCherrimWithFlowerGift = p.hasAbility(Abilities.FLOWER_GIFT) && p.species.speciesId === Species.CHERRIM; if (isCastformWithForecast || isCherrimWithFlowerGift) { - new ShowAbilityPhase(p.getBattlerIndex()); globalScene.triggerPokemonFormChange(p, SpeciesFormChangeWeatherTrigger); } }); @@ -395,7 +393,6 @@ export class Arena { p.hasAbility(Abilities.FLOWER_GIFT, false, true) && p.species.speciesId === Species.CHERRIM; if (isCastformWithForecast || isCherrimWithFlowerGift) { - new ShowAbilityPhase(p.getBattlerIndex()); return globalScene.triggerPokemonFormChange(p, SpeciesFormChangeRevertWeatherFormTrigger); } }); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index b595d516f53..f89319a6e30 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -263,6 +263,7 @@ import { Nature } from "#enums/nature"; import { StatusEffect } from "#enums/status-effect"; import { doShinySparkleAnim } from "#app/field/anims"; import { MoveFlags } from "#enums/MoveFlags"; +import { timedEventManager } from "#app/global-event-manager"; export enum LearnMoveSituation { MISC, @@ -1446,7 +1447,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } const ally = this.getAlly(); - if (ally) { + if (!Utils.isNullOrUndefined(ally)) { applyAllyStatMultiplierAbAttrs(AllyStatMultiplierAbAttr, ally, stat, statValue, simulated, this, move?.hasFlag(MoveFlags.IGNORE_ABILITIES) || ignoreAllyAbility); } @@ -2983,8 +2984,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const shinyThreshold = new Utils.NumberHolder(BASE_SHINY_CHANCE); if (thresholdOverride === undefined) { - if (globalScene.eventManager.isEventActive()) { - shinyThreshold.value *= globalScene.eventManager.getShinyMultiplier(); + if (timedEventManager.isEventActive()) { + const tchance = timedEventManager.getClassicTrainerShinyChance(); + shinyThreshold.value *= timedEventManager.getShinyMultiplier(); + if (this.hasTrainer() && tchance > 0) { + shinyThreshold.value = Math.max(tchance, shinyThreshold.value); // Choose the higher boost + } } if (!this.hasTrainer()) { globalScene.applyModifiers( @@ -3025,8 +3030,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (thresholdOverride !== undefined && applyModifiersToOverride) { shinyThreshold.value = thresholdOverride; } - if (globalScene.eventManager.isEventActive()) { - shinyThreshold.value *= globalScene.eventManager.getShinyMultiplier(); + if (timedEventManager.isEventActive()) { + shinyThreshold.value *= timedEventManager.getShinyMultiplier(); } if (!this.hasTrainer()) { globalScene.applyModifiers( @@ -3709,7 +3714,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { : i18next.t("arenaTag:yourTeam"); } - getAlly(): Pokemon { + getAlly(): Pokemon | undefined { return ( this.isPlayer() ? globalScene.getPlayerField() @@ -3895,7 +3900,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ); const ally = this.getAlly(); - if (ally) { + if (!isNullOrUndefined(ally)) { const ignore = this.hasAbilityWithAttr(MoveAbilityBypassAbAttr) || sourceMove.hasFlag(MoveFlags.IGNORE_ABILITIES); applyAllyStatMultiplierAbAttrs(AllyStatMultiplierAbAttr, ally, Stat.ACC, accuracyMultiplier, false, this, ignore); applyAllyStatMultiplierAbAttrs(AllyStatMultiplierAbAttr, ally, Stat.EVA, evasionMultiplier, false, this, ignore); @@ -4331,11 +4336,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { damage, ); + const ally = this.getAlly(); /** Additionally apply friend guard damage reduction if ally has it. */ - if (globalScene.currentBattle.double && this.getAlly()?.isActive(true)) { + if (globalScene.currentBattle.double && !isNullOrUndefined(ally) && ally.isActive(true)) { applyPreDefendAbAttrs( AlliedFieldDamageReductionAbAttr, - this.getAlly(), + ally, source, move, cancelled, @@ -6469,10 +6475,10 @@ export class PlayerPokemon extends Pokemon { amount, ); const candyFriendshipMultiplier = globalScene.gameMode.isClassic - ? globalScene.eventManager.getClassicFriendshipMultiplier() + ? timedEventManager.getClassicFriendshipMultiplier() : 1; const fusionReduction = fusionStarterSpeciesId - ? globalScene.eventManager.areFusionsBoosted() + ? timedEventManager.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 diff --git a/src/field/trainer.ts b/src/field/trainer.ts index c52957eef75..ccd8c83e684 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -33,14 +33,16 @@ export default class Trainer extends Phaser.GameObjects.Container { public partyTemplateIndex: number; public name: string; public partnerName: string; + public nameKey: string; + public partnerNameKey: string | undefined; public originalIndexes: { [key: number]: number } = {}; constructor( trainerType: TrainerType, variant: TrainerVariant, partyTemplateIndex?: number, - name?: string, - partnerName?: string, + nameKey?: string, + partnerNameKey?: string, trainerConfigOverride?: TrainerConfig, ) { super(globalScene, -72, 80); @@ -59,28 +61,41 @@ export default class Trainer extends Phaser.GameObjects.Container { : Utils.randSeedWeightedItem(this.config.partyTemplates.map((_, i) => i)), this.config.partyTemplates.length - 1, ); - if (i18next.exists("trainersCommon:" + TrainerType[trainerType], { returnObjects: true })) { - const namePool = i18next.t("trainersCommon:" + TrainerType[trainerType], { returnObjects: true }); - this.name = - name || - Utils.randSeedItem( - Object.values( - namePool.hasOwnProperty("MALE") - ? namePool[variant === TrainerVariant.FEMALE ? "FEMALE" : "MALE"] - : namePool, - ), + const classKey = `trainersCommon:${TrainerType[trainerType]}`; + if (i18next.exists(classKey, { returnObjects: true })) { + if (nameKey) { + this.nameKey = nameKey; + } else { + const genderKey = i18next.exists(`${classKey}.MALE`) + ? variant === TrainerVariant.FEMALE + ? ".FEMALE" + : ".MALE" + : ""; + const trainerKey = Utils.randSeedItem( + Object.keys(i18next.t(`${classKey}${genderKey}`, { returnObjects: true })), ); + this.nameKey = `${classKey}${genderKey}.${trainerKey}`; + } + this.name = i18next.t(this.nameKey); if (variant === TrainerVariant.DOUBLE) { if (this.config.doubleOnly) { - if (partnerName) { - this.partnerName = partnerName; + if (partnerNameKey) { + this.partnerNameKey = partnerNameKey; + this.partnerName = i18next.t(this.partnerNameKey); } else { [this.name, this.partnerName] = this.name.split(" & "); } } else { - this.partnerName = - partnerName || - Utils.randSeedItem(Object.values(namePool.hasOwnProperty("FEMALE") ? namePool["FEMALE"] : namePool)); + const partnerGenderKey = i18next.exists(`${classKey}.FEMALE`) ? ".FEMALE" : ""; + const partnerTrainerKey = Utils.randSeedItem( + Object.keys( + i18next.t(`${classKey}${partnerGenderKey}`, { + returnObjects: true, + }), + ), + ); + this.partnerNameKey = `${classKey}${partnerGenderKey}.${partnerTrainerKey}`; + this.partnerName = i18next.t(this.partnerNameKey); } } } diff --git a/src/game-mode.ts b/src/game-mode.ts index 5e27c32f015..c340768ef77 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -68,6 +68,19 @@ export class GameMode implements GameModeConfig { this.battleConfig = battleConfig || {}; } + /** + * Enables challenges if they are disabled and sets the specified challenge's value + * @param challenge The challenge to set + * @param value The value to give the challenge. Impact depends on the specific challenge + */ + setChallengeValue(challenge: Challenges, value: number) { + if (!this.isChallenge) { + this.isChallenge = true; + this.challenges = allChallenges.map(c => copyChallenge(c)); + } + this.challenges.filter((chal: Challenge) => chal.id === challenge).map((chal: Challenge) => (chal.value = value)); + } + /** * Helper function to see if a GameMode has a specific challenge type * @param challenge the Challenges it looks for diff --git a/src/global-event-manager.ts b/src/global-event-manager.ts new file mode 100644 index 00000000000..3df3d17b5e9 --- /dev/null +++ b/src/global-event-manager.ts @@ -0,0 +1,3 @@ +import { TimedEventManager } from "./timed-event-manager"; + +export const timedEventManager = new TimedEventManager(); diff --git a/src/loading-scene.ts b/src/loading-scene.ts index d1f0b0ca242..f99831c53bc 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -20,6 +20,7 @@ import { initStatsKeys } from "#app/ui/game-stats-ui-handler"; import { initVouchers } from "#app/system/voucher"; import { Biome } from "#enums/biome"; import { initMysteryEncounters } from "#app/data/mystery-encounters/mystery-encounters"; +import { timedEventManager } from "./global-event-manager"; export class LoadingScene extends SceneBase { public static readonly KEY = "loading"; @@ -250,11 +251,13 @@ export class LoadingScene extends SceneBase { this.loadAtlas("statuses", ""); this.loadAtlas("types", ""); } - const availableLangs = ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-MX", "pt-BR", "zh-CN", "zh-TW", "ca-ES"]; - if (lang && availableLangs.includes(lang)) { - this.loadImage(`pkmnday2025event-${lang}`, "events"); - } else { - this.loadImage("pkmnday2025event-en", "events"); + if (timedEventManager.activeEventHasBanner()) { + const availableLangs = timedEventManager.getEventBannerLangs(); + if (lang && availableLangs.includes(lang)) { + this.loadImage(`${timedEventManager.getEventBannerFilename()}-${lang}`, "events"); + } else { + this.loadImage(`${timedEventManager.getEventBannerFilename()}-en`, "events"); + } } this.loadAtlas("statuses", ""); diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index f9770e9c6cc..8feb60c7778 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -127,6 +127,7 @@ import type { PermanentStat, TempBattleStat } from "#enums/stat"; import { getStatKey, Stat, TEMP_BATTLE_STATS } from "#enums/stat"; import { StatusEffect } from "#enums/status-effect"; import i18next from "i18next"; +import { timedEventManager } from "#app/global-event-manager"; const outputModifierData = false; const useMaxWeightForOutput = false; @@ -2655,7 +2656,7 @@ const modifierPool: ModifierPool = { if (globalScene.gameMode.isSplicedOnly) { return 4; } - if (globalScene.gameMode.isClassic && globalScene.eventManager.areFusionsBoosted()) { + if (globalScene.gameMode.isClassic && timedEventManager.areFusionsBoosted()) { return 2; } } @@ -2822,37 +2823,48 @@ const modifierPool: ModifierPool = { modifierTypes.MYSTICAL_ROCK, (party: Pokemon[]) => { return party.some(p => { - const moveset = p.getMoveset(true).map(m => m.moveId); + let isHoldingMax = false; + for (const i of p.getHeldItems()) { + if (i.type.id === "MYSTICAL_ROCK") { + isHoldingMax = i.getStackCount() === i.getMaxStackCount(); + break; + } + } - const hasAbility = [ - Abilities.DRIZZLE, - Abilities.ORICHALCUM_PULSE, - Abilities.DRIZZLE, - Abilities.SAND_STREAM, - Abilities.SAND_SPIT, - Abilities.SNOW_WARNING, - Abilities.ELECTRIC_SURGE, - Abilities.HADRON_ENGINE, - Abilities.PSYCHIC_SURGE, - Abilities.GRASSY_SURGE, - Abilities.SEED_SOWER, - Abilities.MISTY_SURGE, - ].some(a => p.hasAbility(a, false, true)); + if (!isHoldingMax) { + const moveset = p.getMoveset(true).map(m => m.moveId); - const hasMoves = [ - Moves.SUNNY_DAY, - Moves.RAIN_DANCE, - Moves.SANDSTORM, - Moves.SNOWSCAPE, - Moves.HAIL, - Moves.CHILLY_RECEPTION, - Moves.ELECTRIC_TERRAIN, - Moves.PSYCHIC_TERRAIN, - Moves.GRASSY_TERRAIN, - Moves.MISTY_TERRAIN, - ].some(m => moveset.includes(m)); + const hasAbility = [ + Abilities.DROUGHT, + Abilities.ORICHALCUM_PULSE, + Abilities.DRIZZLE, + Abilities.SAND_STREAM, + Abilities.SAND_SPIT, + Abilities.SNOW_WARNING, + Abilities.ELECTRIC_SURGE, + Abilities.HADRON_ENGINE, + Abilities.PSYCHIC_SURGE, + Abilities.GRASSY_SURGE, + Abilities.SEED_SOWER, + Abilities.MISTY_SURGE, + ].some(a => p.hasAbility(a, false, true)); - return hasAbility || hasMoves; + const hasMoves = [ + Moves.SUNNY_DAY, + Moves.RAIN_DANCE, + Moves.SANDSTORM, + Moves.SNOWSCAPE, + Moves.HAIL, + Moves.CHILLY_RECEPTION, + Moves.ELECTRIC_TERRAIN, + Moves.PSYCHIC_TERRAIN, + Moves.GRASSY_TERRAIN, + Moves.MISTY_TERRAIN, + ].some(m => moveset.includes(m)); + + return hasAbility || hasMoves; + } + return false; }) ? 10 : 0; @@ -2939,7 +2951,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType( modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => - !(globalScene.gameMode.isClassic && globalScene.eventManager.areFusionsBoosted()) && + !(globalScene.gameMode.isClassic && timedEventManager.areFusionsBoosted()) && !globalScene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 24 @@ -3703,7 +3715,7 @@ export function getPartyLuckValue(party: Pokemon[]): number { ); return DailyLuck.value; } - const eventSpecies = globalScene.eventManager.getEventLuckBoostedSpecies(); + const eventSpecies = timedEventManager.getEventLuckBoostedSpecies(); const luck = Phaser.Math.Clamp( party .map(p => (p.isAllowedInBattle() ? p.getLuck() + (eventSpecies.includes(p.species.speciesId) ? 1 : 0) : 0)) @@ -3711,7 +3723,7 @@ export function getPartyLuckValue(party: Pokemon[]): number { 0, 14, ); - return Math.min(globalScene.eventManager.getEventLuckBoost() + (luck ?? 0), 14); + return Math.min(timedEventManager.getEventLuckBoost() + (luck ?? 0), 14); } export function getLuckString(luckValue: number): string { diff --git a/src/phases/enemy-command-phase.ts b/src/phases/enemy-command-phase.ts index 2e4861aacfc..166b8c1ae2d 100644 --- a/src/phases/enemy-command-phase.ts +++ b/src/phases/enemy-command-phase.ts @@ -39,7 +39,7 @@ export class EnemyCommandPhase extends FieldPhase { if ( battle.double && enemyPokemon.hasAbility(Abilities.COMMANDER) && - enemyPokemon.getAlly().getTag(BattlerTagType.COMMANDED) + enemyPokemon.getAlly()?.getTag(BattlerTagType.COMMANDED) ) { this.skipTurn = true; } diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index dfc0e0653a5..7e1ae4ec07b 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -209,8 +209,8 @@ export class FaintPhase extends PokemonPhase { } // in double battles redirect potential moves off fainted pokemon - if (globalScene.currentBattle.double) { - const allyPokemon = pokemon.getAlly(); + const allyPokemon = pokemon.getAlly(); + if (globalScene.currentBattle.double && !isNullOrUndefined(allyPokemon)) { globalScene.redirectPokemonMoves(pokemon, allyPokemon); } diff --git a/src/phases/game-over-phase.ts b/src/phases/game-over-phase.ts index 2090592367d..f105b625cc8 100644 --- a/src/phases/game-over-phase.ts +++ b/src/phases/game-over-phase.ts @@ -45,6 +45,8 @@ export class GameOverPhase extends BattlePhase { start() { super.start(); + globalScene.hideAbilityBar(); + // Failsafe if players somehow skip floor 200 in classic mode if (globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex > 200) { this.isVictory = true; diff --git a/src/phases/hide-ability-phase.ts b/src/phases/hide-ability-phase.ts index 0745b3f832a..142bb4b251d 100644 --- a/src/phases/hide-ability-phase.ts +++ b/src/phases/hide-ability-phase.ts @@ -1,27 +1,12 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; -import { PokemonPhase } from "./pokemon-phase"; - -export class HideAbilityPhase extends PokemonPhase { - private passive: boolean; - - constructor(battlerIndex: BattlerIndex, passive = false) { - super(battlerIndex); - - this.passive = passive; - } +import { Phase } from "#app/phase"; +export class HideAbilityPhase extends Phase { start() { super.start(); - const pokemon = this.getPokemon(); - - if (pokemon) { - globalScene.abilityBar.hide().then(() => { - this.end(); - }); - } else { + globalScene.abilityBar.hide().then(() => { this.end(); - } + }); } } diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 995684f8c03..bd1c9caad96 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -69,6 +69,7 @@ import type { Phase } from "#app/phase"; import { ShowAbilityPhase } from "./show-ability-phase"; import { MovePhase } from "./move-phase"; import { MoveEndPhase } from "./move-end-phase"; +import { HideAbilityPhase } from "#app/phases/hide-ability-phase"; export class MoveEffectPhase extends PokemonPhase { public move: PokemonMove; @@ -326,12 +327,14 @@ export class MoveEffectPhase extends PokemonPhase { ? getMoveTargets(target, move.id).targets : [user.getBattlerIndex()]; if (!isReflecting) { + // TODO: Ability displays should be handled by the ability queuedPhases.push( new ShowAbilityPhase( target.getBattlerIndex(), target.getPassiveAbility().hasAttr(ReflectStatusMoveAbAttr), ), ); + queuedPhases.push(new HideAbilityPhase()); } queuedPhases.push( diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index f8edaa56981..e04f48c2880 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -42,7 +42,6 @@ import { CommonAnimPhase } from "#app/phases/common-anim-phase"; import { MoveChargePhase } from "#app/phases/move-charge-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { NumberHolder } from "#app/utils"; import { Abilities } from "#enums/abilities"; import { ArenaTagType } from "#enums/arena-tag-type"; @@ -535,11 +534,16 @@ export class MovePhase extends BattlePhase { if (this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr)) { redirectTarget.value = currentTarget; - globalScene.unshiftPhase( - new ShowAbilityPhase( - this.pokemon.getBattlerIndex(), - this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr), - ), + // TODO: Ability displays should be handled by the ability + globalScene.queueAbilityDisplay( + this.pokemon, + this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr), + true, + ); + globalScene.queueAbilityDisplay( + this.pokemon, + this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr), + false, ); } diff --git a/src/phases/revival-blessing-phase.ts b/src/phases/revival-blessing-phase.ts index 1ed63f76b64..e650d714abc 100644 --- a/src/phases/revival-blessing-phase.ts +++ b/src/phases/revival-blessing-phase.ts @@ -42,8 +42,12 @@ export class RevivalBlessingPhase extends BattlePhase { true, ); - if (globalScene.currentBattle.double && globalScene.getPlayerParty().length > 1) { - const allyPokemon = this.user.getAlly(); + const allyPokemon = this.user.getAlly(); + if ( + globalScene.currentBattle.double && + globalScene.getPlayerParty().length > 1 && + !Utils.isNullOrUndefined(allyPokemon) + ) { if (slotIndex <= 1) { // Revived ally pokemon globalScene.unshiftPhase( diff --git a/src/phases/show-ability-phase.ts b/src/phases/show-ability-phase.ts index 1b3c6dde568..8097af33fe0 100644 --- a/src/phases/show-ability-phase.ts +++ b/src/phases/show-ability-phase.ts @@ -35,7 +35,7 @@ export class ShowAbilityPhase extends PokemonPhase { // If the bar is already out, hide it before showing the new one if (globalScene.abilityBar.isVisible()) { - globalScene.unshiftPhase(new HideAbilityPhase(this.battlerIndex, this.passive)); + globalScene.unshiftPhase(new HideAbilityPhase()); globalScene.unshiftPhase(new ShowAbilityPhase(this.battlerIndex, this.passive)); return this.end(); } diff --git a/src/phases/stat-stage-change-phase.ts b/src/phases/stat-stage-change-phase.ts index f58744ef5ce..4c82661a3bb 100644 --- a/src/phases/stat-stage-change-phase.ts +++ b/src/phases/stat-stage-change-phase.ts @@ -17,7 +17,7 @@ import type Pokemon from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { ResetNegativeStatStageModifier } from "#app/modifier/modifier"; import { handleTutorial, Tutorial } from "#app/tutorial"; -import { NumberHolder, BooleanHolder } from "#app/utils"; +import { NumberHolder, BooleanHolder, isNullOrUndefined } from "#app/utils"; import i18next from "i18next"; import { PokemonPhase } from "./pokemon-phase"; import { Stat, type BattleStat, getStatKey, getStatStageChangeDescriptionKey } from "#enums/stat"; @@ -161,7 +161,7 @@ export class StatStageChangePhase extends PokemonPhase { pokemon, ); const ally = pokemon.getAlly(); - if (ally) { + if (!isNullOrUndefined(ally)) { applyPreStatStageChangeAbAttrs( ConditionalUserFieldProtectStatAbAttr, ally, diff --git a/src/phases/title-phase.ts b/src/phases/title-phase.ts index 5b69f8db45c..dc455a0a62a 100644 --- a/src/phases/title-phase.ts +++ b/src/phases/title-phase.ts @@ -212,6 +212,8 @@ export class TitlePhase extends Phase { const generateDaily = (seed: string) => { globalScene.gameMode = getGameMode(GameModes.DAILY); + // Daily runs don't support all challenges yet (starter select restrictions aren't considered) + globalScene.eventManager.startEventChallenges(); globalScene.setSeed(seed); globalScene.resetSeed(0); diff --git a/src/phases/trainer-victory-phase.ts b/src/phases/trainer-victory-phase.ts index f7b2eb2bb66..a024885121f 100644 --- a/src/phases/trainer-victory-phase.ts +++ b/src/phases/trainer-victory-phase.ts @@ -11,6 +11,7 @@ import { TrainerSlot } from "#enums/trainer-slot"; import { globalScene } from "#app/global-scene"; import { Biome } from "#app/enums/biome"; import { achvs } from "#app/system/achv"; +import { timedEventManager } from "#app/global-event-manager"; export class TrainerVictoryPhase extends BattlePhase { constructor() { @@ -29,7 +30,7 @@ export class TrainerVictoryPhase extends BattlePhase { globalScene.unshiftPhase(new ModifierRewardPhase(modifierRewardFunc)); } - if (globalScene.eventManager.isEventActive()) { + if (timedEventManager.isEventActive()) { for (const rewardFunc of globalScene.currentBattle.trainer?.config.eventRewardFuncs!) { globalScene.unshiftPhase(new ModifierRewardPhase(rewardFunc)); } @@ -42,7 +43,7 @@ export class TrainerVictoryPhase extends BattlePhase { !globalScene.validateVoucher(vouchers[TrainerType[trainerType]]) && globalScene.currentBattle.trainer?.config.isBoss ) { - if (globalScene.eventManager.getUpgradeUnlockedVouchers()) { + if (timedEventManager.getUpgradeUnlockedVouchers()) { globalScene.unshiftPhase( new ModifierRewardPhase( [ diff --git a/src/phases/turn-end-phase.ts b/src/phases/turn-end-phase.ts index 836647fbfb4..ddfc0955508 100644 --- a/src/phases/turn-end-phase.ts +++ b/src/phases/turn-end-phase.ts @@ -28,6 +28,8 @@ export class TurnEndPhase extends FieldPhase { globalScene.currentBattle.incrementTurn(); globalScene.eventTarget.dispatchEvent(new TurnEndEvent(globalScene.currentBattle.turn)); + globalScene.hideAbilityBar(); + const handlePokemon = (pokemon: Pokemon) => { if (!pokemon.switchOutStatus) { pokemon.lapseTags(BattlerTagLapseType.TURN_END); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 2388918dca2..391ceec503d 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -1793,7 +1793,9 @@ export class GameData { const dexEntry = this.dexData[species.speciesId]; const caughtAttr = dexEntry.caughtAttr; const formIndex = pokemon.formIndex; - const dexAttr = pokemon.getDexAttr(); + + // This makes sure that we do not try to unlock data which cannot be unlocked + const dexAttr = pokemon.getDexAttr() & species.getFullUnlocksData(); // Mark as caught dexEntry.caughtAttr |= dexAttr; @@ -1803,6 +1805,10 @@ export class GameData { // always true except for the case of Urshifu. const formKey = pokemon.getFormKey(); if (formIndex > 0) { + // In case a Pikachu with formIndex > 0 was unlocked, base form Pichu is also unlocked + if (pokemon.species.speciesId === Species.PIKACHU && species.speciesId === Species.PICHU) { + dexEntry.caughtAttr |= globalScene.gameData.getFormAttr(0); + } if (pokemon.species.speciesId === Species.URSHIFU) { if (formIndex === 2) { dexEntry.caughtAttr |= globalScene.gameData.getFormAttr(0); diff --git a/src/system/trainer-data.ts b/src/system/trainer-data.ts index 48ab8d8d42a..0e6298309bc 100644 --- a/src/system/trainer-data.ts +++ b/src/system/trainer-data.ts @@ -5,8 +5,8 @@ export default class TrainerData { public trainerType: TrainerType; public variant: TrainerVariant; public partyTemplateIndex: number; - public name: string; - public partnerName: string; + public nameKey: string; + public partnerNameKey: string | undefined; constructor(source: Trainer | any) { const sourceTrainer = source instanceof Trainer ? (source as Trainer) : null; @@ -17,11 +17,11 @@ export default class TrainerData { ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT; this.partyTemplateIndex = source.partyMemberTemplateIndex; - this.name = source.name; - this.partnerName = source.partnerName; + this.nameKey = source.nameKey; + this.partnerNameKey = source.partnerNameKey; } toTrainer(): Trainer { - return new Trainer(this.trainerType, this.variant, this.partyTemplateIndex, this.name, this.partnerName); + return new Trainer(this.trainerType, this.variant, this.partyTemplateIndex, this.nameKey, this.partnerNameKey); } } diff --git a/src/system/version_migration/version_converter.ts b/src/system/version_migration/version_converter.ts index 3c5abc2cc18..074f60c2c5d 100644 --- a/src/system/version_migration/version_converter.ts +++ b/src/system/version_migration/version_converter.ts @@ -10,6 +10,9 @@ import * as v1_1_0 from "./versions/v1_1_0"; // --- v1.7.0 PATCHES --- // import * as v1_7_0 from "./versions/v1_7_0"; +// --- v1.8.3 PATCHES --- // +import * as v1_8_3 from "./versions/v1_8_3"; + const LATEST_VERSION = version.split(".").map(value => Number.parseInt(value)); /** @@ -174,6 +177,12 @@ class SystemVersionConverter extends VersionConverter { console.log("Applying v1.7.0 system data migration!"); this.callMigrators(data, v1_7_0.systemMigrators); } + if (curMinor === 8) { + if (curPatch <= 2) { + console.log("Applying v1.8.3 system data migration!"); + this.callMigrators(data, v1_8_3.systemMigrators); + } + } } console.log(`System data successfully migrated to v${version}!`); diff --git a/src/system/version_migration/versions/v1_8_3.ts b/src/system/version_migration/versions/v1_8_3.ts new file mode 100644 index 00000000000..d35530c28e9 --- /dev/null +++ b/src/system/version_migration/versions/v1_8_3.ts @@ -0,0 +1,30 @@ +import { getPokemonSpecies } from "#app/data/pokemon-species"; +import { DexAttr, type SystemSaveData } from "#app/system/game-data"; +import { Species } from "#enums/species"; + +export const systemMigrators = [ + /** + * If a starter is caught, but the only forms registered as caught are not starterSelectable, + * unlock the default form. + * @param data {@linkcode SystemSaveData} + */ + function migratePichuForms(data: SystemSaveData) { + if (data.starterData && data.dexData) { + // This is Pichu's Pokédex number + const sd = 172; + const caughtAttr = data.dexData[sd]?.caughtAttr; + const species = getPokemonSpecies(sd); + // An extra check because you never know + if (species.speciesId === Species.PICHU && caughtAttr) { + // Ensuring that only existing forms are unlocked + data.dexData[sd].caughtAttr &= species.getFullUnlocksData(); + // If no forms are unlocked now, since Pichu is caught, we unlock form 0 + data.dexData[sd].caughtAttr |= DexAttr.DEFAULT_FORM; + } + } + }, +] as const; + +export const settingsMigrators = [] as const; + +export const sessionMigrators = [] as const; diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 80667b033ad..7bbd157948b 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -9,6 +9,7 @@ import { WeatherType } from "#enums/weather-type"; import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER } from "./data/balance/starters"; import { MysteryEncounterType } from "./enums/mystery-encounter-type"; import { MysteryEncounterTier } from "./enums/mystery-encounter-tier"; +import { Challenges } from "#enums/challenges"; export enum EventType { SHINY, @@ -36,6 +37,18 @@ interface EventMysteryEncounterTier { disable?: boolean; } +interface EventWaveReward { + wave: number; + type: string; +} + +type EventMusicReplacement = [string, string]; + +interface EventChallenge { + challenge: Challenges; + value: number; +} + interface TimedEvent extends EventBanner { name: string; eventType: EventType; @@ -51,6 +64,10 @@ interface TimedEvent extends EventBanner { mysteryEncounterTierChanges?: EventMysteryEncounterTier[]; luckBoostedSpecies?: Species[]; boostFusions?: boolean; //MODIFIER REWORK PLEASE + classicWaveRewards?: EventWaveReward[]; // Rival battle rewards + trainerShinyChance?: number; // Odds over 65536 of trainer mon generating as shiny + music?: EventMusicReplacement[]; + dailyRunChallenges?: EventChallenge[]; } const timedEvents: TimedEvent[] = [ @@ -61,7 +78,7 @@ const timedEvents: TimedEvent[] = [ upgradeUnlockedVouchers: true, startDate: new Date(Date.UTC(2024, 11, 21, 0)), endDate: new Date(Date.UTC(2025, 0, 4, 0)), - bannerKey: "winter_holidays2024-event-", + bannerKey: "winter_holidays2024-event", scale: 0.21, availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN"], eventEncounters: [ @@ -104,6 +121,12 @@ const timedEvents: TimedEvent[] = [ disable: true, }, ], + classicWaveRewards: [ + { wave: 8, type: "SHINY_CHARM" }, + { wave: 8, type: "ABILITY_CHARM" }, + { wave: 8, type: "CATCHING_CHARM" }, + { wave: 25, type: "SHINY_CHARM" }, + ], }, { name: "Year of the Snake", @@ -111,7 +134,7 @@ const timedEvents: TimedEvent[] = [ luckBoost: 1, startDate: new Date(Date.UTC(2025, 0, 29, 0)), endDate: new Date(Date.UTC(2025, 1, 3, 0)), - bannerKey: "yearofthesnakeevent-", + bannerKey: "yearofthesnakeevent", scale: 0.21, availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN"], eventEncounters: [ @@ -169,6 +192,12 @@ const timedEvents: TimedEvent[] = [ Species.ROARING_MOON, Species.BLOODMOON_URSALUNA, ], + classicWaveRewards: [ + { wave: 8, type: "SHINY_CHARM" }, + { wave: 8, type: "ABILITY_CHARM" }, + { wave: 8, type: "CATCHING_CHARM" }, + { wave: 25, type: "SHINY_CHARM" }, + ], }, { name: "Valentine", @@ -177,7 +206,7 @@ const timedEvents: TimedEvent[] = [ endDate: new Date(Date.UTC(2025, 1, 21)), boostFusions: true, shinyMultiplier: 2, - bannerKey: "valentines2025event-", + bannerKey: "valentines2025event", scale: 0.21, availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN"], eventEncounters: [ @@ -203,6 +232,12 @@ const timedEvents: TimedEvent[] = [ { species: Species.ENAMORUS }, ], luckBoostedSpecies: [Species.LUVDISC], + classicWaveRewards: [ + { wave: 8, type: "SHINY_CHARM" }, + { wave: 8, type: "ABILITY_CHARM" }, + { wave: 8, type: "CATCHING_CHARM" }, + { wave: 25, type: "SHINY_CHARM" }, + ], }, { name: "PKMNDAY2025", @@ -210,7 +245,7 @@ const timedEvents: TimedEvent[] = [ startDate: new Date(Date.UTC(2025, 1, 27)), endDate: new Date(Date.UTC(2025, 2, 4)), classicFriendshipMultiplier: 4, - bannerKey: "pkmnday2025event-", + bannerKey: "pkmnday2025event", scale: 0.21, availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN"], eventEncounters: [ @@ -248,6 +283,32 @@ const timedEvents: TimedEvent[] = [ Species.ZYGARDE, Species.ETERNAL_FLOETTE, ], + classicWaveRewards: [ + { wave: 8, type: "SHINY_CHARM" }, + { wave: 8, type: "ABILITY_CHARM" }, + { wave: 8, type: "CATCHING_CHARM" }, + { wave: 25, type: "SHINY_CHARM" }, + ], + }, + { + name: "April Fools 2025", + eventType: EventType.LUCK, + startDate: new Date(Date.UTC(2025, 2, 31)), + endDate: new Date(Date.UTC(2025, 3, 3)), + bannerKey: "aprf25", + scale: 0.21, + availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-MX", "pt-BR", "zh-CN"], + trainerShinyChance: 13107, // 13107/65536 = 1/5 + music: [ + ["title", "title_afd"], + ["battle_rival_3", "battle_rival_3_afd"], + ], + dailyRunChallenges: [ + { + challenge: Challenges.INVERSE_BATTLE, + value: 1, + }, + ], }, ]; @@ -265,7 +326,7 @@ export class TimedEventManager { } activeEventHasBanner(): boolean { - const activeEvents = timedEvents.filter(te => this.isActive(te) && te.hasOwnProperty("bannerFilename")); + const activeEvents = timedEvents.filter(te => this.isActive(te) && te.hasOwnProperty("bannerKey")); return activeEvents.length > 0; } @@ -283,6 +344,12 @@ export class TimedEventManager { return timedEvents.find((te: TimedEvent) => this.isActive(te))?.bannerKey ?? ""; } + getEventBannerLangs(): string[] { + const ret: string[] = []; + ret.push(...timedEvents.find(te => this.isActive(te) && !isNullOrUndefined(te.availableLangs))?.availableLangs!); + return ret; + } + getEventEncounters(): EventEncounter[] { const ret: EventEncounter[] = []; timedEvents @@ -417,6 +484,55 @@ export class TimedEventManager { areFusionsBoosted(): boolean { return timedEvents.some(te => this.isActive(te) && te.boostFusions); } + + /** + * Gets all the modifier types associated with a certain wave during an event + * @see EventWaveReward + * @param wave the wave to check for associated rewards + * @returns array of strings of the event modifier reward types + */ + getFixedBattleEventRewards(wave: number): string[] { + const ret: string[] = []; + timedEvents + .filter(te => this.isActive(te) && !isNullOrUndefined(te.classicWaveRewards)) + .map(te => { + ret.push(...te.classicWaveRewards!.filter(cwr => cwr.wave === wave).map(cwr => cwr.type)); + }); + return ret; + } + + // Gets the extra shiny chance for trainers due to event (odds/65536) + getClassicTrainerShinyChance(): number { + let ret = 0; + const tsEvents = timedEvents.filter(te => this.isActive(te) && !isNullOrUndefined(te.trainerShinyChance)); + tsEvents.map(t => (ret += t.trainerShinyChance!)); + return ret; + } + + getEventBgmReplacement(bgm: string): string { + let ret = bgm; + timedEvents.map(te => { + if (this.isActive(te) && !isNullOrUndefined(te.music)) { + te.music.map(mr => { + if (mr[0] === bgm) { + console.log(`it is ${te.name} so instead of ${mr[0]} we play ${mr[1]}`); + ret = mr[1]; + } + }); + } + }); + return ret; + } + + /** + * Activates any challenges on {@linkcode globalScene.gameMode} for the currently active event + */ + startEventChallenges(): void { + const challenges = this.activeEvent()?.dailyRunChallenges; + challenges?.forEach((eventChal: EventChallenge) => + globalScene.gameMode.setChallengeValue(eventChal.challenge, eventChal.value), + ); + } } export class TimedEventDisplay extends Phaser.GameObjects.Container { @@ -456,11 +572,12 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container { let key = this.event.bannerKey; if (lang && this.event.availableLangs && this.event.availableLangs.length > 0) { if (this.event.availableLangs.includes(lang)) { - key += lang; + key += "-" + lang; } else { - key += "en"; + key += "-en"; } } + console.log(key); console.log(this.event.bannerKey); const padding = 5; const showTimer = this.event.eventType !== EventType.NO_TIMER_DISPLAY; diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index a9fdf22ec57..d87d4e5ca79 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -11,6 +11,7 @@ import { globalScene } from "#app/global-scene"; import type { Species } from "#enums/species"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { PlayerGender } from "#enums/player-gender"; +import { timedEventManager } from "#app/global-event-manager"; export default class TitleUiHandler extends OptionSelectUiHandler { /** If the stats can not be retrieved, use this fallback value */ @@ -43,8 +44,8 @@ export default class TitleUiHandler extends OptionSelectUiHandler { logo.setOrigin(0.5, 0); this.titleContainer.add(logo); - if (globalScene.eventManager.isEventActive()) { - this.eventDisplay = new TimedEventDisplay(0, 0, globalScene.eventManager.activeEvent()); + if (timedEventManager.isEventActive()) { + this.eventDisplay = new TimedEventDisplay(0, 0, timedEventManager.activeEvent()); this.eventDisplay.setup(); this.titleContainer.add(this.eventDisplay); } @@ -142,7 +143,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler { const ui = this.getUi(); - if (globalScene.eventManager.isEventActive()) { + if (timedEventManager.isEventActive()) { this.eventDisplay.setWidth(globalScene.scaledCanvas.width - this.optionSelectBg.width - this.optionSelectBg.x); this.eventDisplay.show(); } diff --git a/test/abilities/parental_bond.test.ts b/test/abilities/parental_bond.test.ts index d4bf544e8c7..2aa24e78d6e 100644 --- a/test/abilities/parental_bond.test.ts +++ b/test/abilities/parental_bond.test.ts @@ -9,7 +9,6 @@ import { StatusEffect } from "#enums/status-effect"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { BattlerIndex } from "#app/battle"; describe("Abilities - Parental Bond", () => { let phaserGame: Phaser.Game; @@ -427,21 +426,4 @@ describe("Abilities - Parental Bond", () => { // TODO: Update hit count to 1 once Future Sight is fixed to not activate abilities if user is off the field expect(enemyPokemon.damageAndUpdate).toHaveBeenCalledTimes(2); }); - - it("should not allow Pollen Puff to heal ally more than once", async () => { - game.override.battleType("double").moveset([Moves.POLLEN_PUFF, Moves.ENDURE]); - await game.classicMode.startBattle([Species.BULBASAUR, Species.OMANYTE]); - - const [, rightPokemon] = game.scene.getPlayerField(); - - rightPokemon.damageAndUpdate(rightPokemon.hp - 1); - - game.move.select(Moves.POLLEN_PUFF, 0, BattlerIndex.PLAYER_2); - game.move.select(Moves.ENDURE, 1); - - await game.toNextTurn(); - - // Pollen Puff heals with a ratio of 0.5, as long as Pollen Puff triggers only once the pokemon will always be <= (0.5 * Max HP) + 1 - expect(rightPokemon.hp).toBeLessThanOrEqual(0.5 * rightPokemon.getMaxHp() + 1); - }); }); diff --git a/test/moves/pollen_puff.test.ts b/test/moves/pollen_puff.test.ts new file mode 100644 index 00000000000..3af3ea1f41d --- /dev/null +++ b/test/moves/pollen_puff.test.ts @@ -0,0 +1,64 @@ +import { BattlerIndex } from "#app/battle"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Pollen Puff", () => { + 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.POLLEN_PUFF]) + .ability(Abilities.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should not heal more than once when the user has a source of multi-hit", async () => { + game.override.battleType("double").moveset([Moves.POLLEN_PUFF, Moves.ENDURE]).ability(Abilities.PARENTAL_BOND); + await game.classicMode.startBattle([Species.BULBASAUR, Species.OMANYTE]); + + const [_, rightPokemon] = game.scene.getPlayerField(); + + rightPokemon.damageAndUpdate(rightPokemon.hp - 1); + + game.move.select(Moves.POLLEN_PUFF, 0, BattlerIndex.PLAYER_2); + game.move.select(Moves.ENDURE, 1); + + await game.phaseInterceptor.to("BerryPhase"); + + // Pollen Puff heals with a ratio of 0.5, as long as Pollen Puff triggers only once the pokemon will always be <= (0.5 * Max HP) + 1 + expect(rightPokemon.hp).toBeLessThanOrEqual(0.5 * rightPokemon.getMaxHp() + 1); + }); + + it("should damage an enemy multiple times when the user has a source of multi-hit", async () => { + game.override.moveset([Moves.POLLEN_PUFF]).ability(Abilities.PARENTAL_BOND).enemyLevel(100); + await game.classicMode.startBattle([Species.MAGIKARP]); + + const target = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.POLLEN_PUFF); + + await game.phaseInterceptor.to("BerryPhase"); + + expect(target.battleData.hitCount).toBe(2); + }); +}); diff --git a/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts b/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts index 57d55af5dac..a9e6a339d36 100644 --- a/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts @@ -114,7 +114,7 @@ describe("The Strong Stuff - Mystery Encounter", () => { bossSegments: 5, shiny: false, customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }), - nature: Nature.BOLD, + nature: Nature.HARDY, moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER], modifierConfigs: expect.any(Array), tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], @@ -198,7 +198,7 @@ describe("The Strong Stuff - Mystery Encounter", () => { expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(Species.SHUCKLE); - expect(enemyField[0].summonData.statStages).toEqual([0, 2, 0, 2, 0, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 0, 0, 0]); const shuckleItems = enemyField[0].getHeldItems(); expect(shuckleItems.length).toBe(5); expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.SITRUS)?.stackCount).toBe( diff --git a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts index 90e2312e624..df7bbb9f424 100644 --- a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts +++ b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts @@ -1,30 +1,37 @@ +import type BattleScene from "#app/battle-scene"; +import * as BattleAnims from "#app/data/battle-anims"; +import { TrashToTreasureEncounter } from "#app/data/mystery-encounters/encounters/trash-to-treasure-encounter"; import * as MysteryEncounters from "#app/data/mystery-encounters/mystery-encounters"; +import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { + type EnemyPartyConfig, + type EnemyPokemonConfig, + generateModifierType, +} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { getPokemonSpecies } from "#app/data/pokemon-species"; import { Biome } from "#app/enums/biome"; import { MysteryEncounterType } from "#app/enums/mystery-encounter-type"; import { Species } from "#app/enums/species"; -import GameManager from "#test/testUtils/gameManager"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { getPokemonSpecies } from "#app/data/pokemon-species"; -import * as BattleAnims from "#app/data/battle-anims"; -import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { PokemonMove } from "#app/field/pokemon"; +import { HealShopCostModifier, HitHealModifier, TurnHealModifier } from "#app/modifier/modifier"; +import { ModifierTier } from "#app/modifier/modifier-tier"; +import { modifierTypes, type PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; +import { CommandPhase } from "#app/phases/command-phase"; +import { MovePhase } from "#app/phases/move-phase"; +import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; +import { Mode } from "#app/ui/ui"; +import * as Utils from "#app/utils"; +import { Moves } from "#enums/moves"; +import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; +import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase, } from "#test/mystery-encounter/encounter-test-utils"; -import { Moves } from "#enums/moves"; -import type BattleScene from "#app/battle-scene"; -import { PokemonMove } from "#app/field/pokemon"; -import { Mode } from "#app/ui/ui"; -import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; -import { HitHealModifier, HealShopCostModifier, TurnHealModifier } from "#app/modifier/modifier"; -import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; -import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; +import GameManager from "#test/testUtils/gameManager"; import { initSceneWithoutEncounterPhase } from "#test/testUtils/gameManagerUtils"; -import { TrashToTreasureEncounter } from "#app/data/mystery-encounters/encounters/trash-to-treasure-encounter"; -import { ModifierTier } from "#app/modifier/modifier-tier"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -import { MovePhase } from "#app/phases/move-phase"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; const namespace = "mysteryEncounters/trashToTreasure"; const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; @@ -73,6 +80,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { }); it("should initialize fully", async () => { + vi.spyOn(Utils, "randSeedInt").mockImplementation((range, min = 0) => min + range - 1); initSceneWithoutEncounterPhase(scene, defaultParty); scene.currentBattle.mysteryEncounter = TrashToTreasureEncounter; const moveInitSpy = vi.spyOn(BattleAnims, "initMoveAnim"); @@ -85,22 +93,61 @@ describe("Trash to Treasure - Mystery Encounter", () => { TrashToTreasureEncounter.populateDialogueTokensFromRequirements(); const onInitResult = onInit!(); - expect(TrashToTreasureEncounter.enemyPartyConfigs).toEqual([ - { - levelAdditiveModifier: 0.5, - disableSwitch: true, - pokemonConfigs: [ - { - species: getPokemonSpecies(Species.GARBODOR), - isBoss: true, - shiny: false, - formIndex: 1, - bossSegmentModifier: 1, - moveSet: [Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH], - }, - ], - }, - ]); + const bossSpecies = getPokemonSpecies(Species.GARBODOR); + const pokemonConfig: EnemyPokemonConfig = { + species: bossSpecies, + isBoss: true, + shiny: false, // Shiny lock because of custom intro sprite + formIndex: 1, // Gmax + bossSegmentModifier: 1, // +1 Segment from normal + moveSet: [Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.HAMMER_ARM, Moves.PAYBACK], + modifierConfigs: [ + { + modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BASE_STAT_BOOSTER) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.BASE_STAT_BOOSTER) as PokemonHeldItemModifierType, + }, + { + modifier: generateModifierType(modifierTypes.TOXIC_ORB) as PokemonHeldItemModifierType, + stackCount: Utils.randSeedInt(2, 0), + }, + { + modifier: generateModifierType(modifierTypes.SOOTHE_BELL) as PokemonHeldItemModifierType, + stackCount: Utils.randSeedInt(2, 1), + }, + { + modifier: generateModifierType(modifierTypes.LUCKY_EGG) as PokemonHeldItemModifierType, + stackCount: Utils.randSeedInt(3, 1), + }, + { + modifier: generateModifierType(modifierTypes.GOLDEN_EGG) as PokemonHeldItemModifierType, + stackCount: Utils.randSeedInt(2, 0), + }, + ], + }; + const config: EnemyPartyConfig = { + levelAdditiveModifier: 0.5, + pokemonConfigs: [pokemonConfig], + disableSwitch: true, + }; + const enemyPartyConfigs = [config]; + + expect(JSON.stringify(TrashToTreasureEncounter.enemyPartyConfigs, undefined, 2)).toEqual( + JSON.stringify(enemyPartyConfigs, undefined, 2), + ); await vi.waitFor(() => expect(moveInitSpy).toHaveBeenCalled()); await vi.waitFor(() => expect(moveLoadSpy).toHaveBeenCalled()); expect(onInitResult).toBe(true); @@ -122,7 +169,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { }); }); - it("should give 2 Leftovers, 2 Shell Bell, and Black Sludge", async () => { + it("should give 2 Leftovers, 1 Shell Bell, and Black Sludge", async () => { await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); await runMysteryEncounterToEnd(game, 1); await game.phaseInterceptor.to(SelectModifierPhase, false); @@ -134,7 +181,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { const shellBell = scene.findModifier(m => m instanceof HitHealModifier) as HitHealModifier; expect(shellBell).toBeDefined(); - expect(shellBell?.stackCount).toBe(2); + expect(shellBell?.stackCount).toBe(1); const blackSludge = scene.findModifier(m => m instanceof HealShopCostModifier) as HealShopCostModifier; expect(blackSludge).toBeDefined(); @@ -178,17 +225,17 @@ describe("Trash to Treasure - Mystery Encounter", () => { expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(Species.GARBODOR); expect(enemyField[0].moveset).toEqual([ - new PokemonMove(Moves.PAYBACK), new PokemonMove(Moves.GUNK_SHOT), new PokemonMove(Moves.STOMPING_TANTRUM), - new PokemonMove(Moves.DRAIN_PUNCH), + new PokemonMove(Moves.HAMMER_ARM), + new PokemonMove(Moves.PAYBACK), ]); // Should have used moves pre-battle const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); expect(movePhases.length).toBe(2); expect(movePhases.filter(p => (p as MovePhase).move.moveId === Moves.TOXIC).length).toBe(1); - expect(movePhases.filter(p => (p as MovePhase).move.moveId === Moves.AMNESIA).length).toBe(1); + expect(movePhases.filter(p => (p as MovePhase).move.moveId === Moves.STOCKPILE).length).toBe(1); }); it("should have 2 Rogue, 1 Ultra, 1 Great in rewards", async () => {