Merging with beta
16
.github/workflows/deploy.yml
vendored
@ -1,8 +1,12 @@
|
||||
name: Deploy
|
||||
name: Deploy Main
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
@ -22,7 +26,7 @@ jobs:
|
||||
env:
|
||||
NODE_ENV: production
|
||||
- name: Set up SSH
|
||||
if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
|
||||
if: github.event_name == 'push' && github.ref_name == 'main'
|
||||
run: |
|
||||
mkdir ~/.ssh
|
||||
echo "${{ secrets.SSH_PUBLIC_KEY }}" > ~/.ssh/id_ed25519.pub
|
||||
@ -30,12 +34,12 @@ jobs:
|
||||
chmod 600 ~/.ssh/*
|
||||
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
|
||||
- name: Deploy build on server
|
||||
if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
|
||||
if: github.event_name == 'push' && github.ref_name == 'main'
|
||||
run: |
|
||||
rsync --del --no-times --checksum -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }}
|
||||
ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json"
|
||||
- name: Purge Cloudflare Cache
|
||||
if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
|
||||
if: github.event_name == 'push' && github.ref_name == 'main'
|
||||
id: purge-cache
|
||||
uses: NathanVaughn/actions-cloudflare-purge@v3.1.0
|
||||
with:
|
||||
|
@ -17,7 +17,12 @@ If you have the motivation and experience with Typescript/Javascript (or are wil
|
||||
2. Run `npm run start:dev` to locally run the project in `localhost:8000`
|
||||
|
||||
#### Linting
|
||||
We're using ESLint as our common linter and formatter. It will run automatically during the pre-commit hook but if you would like to manually run it, use the `npm run eslint` script.
|
||||
We're using ESLint as our common linter and formatter. It will run automatically during the pre-commit hook but if you would like to manually run it, use the `npm run eslint` script. To view the complete rules, check out the [eslint.config.js](./eslint.config.js) file.
|
||||
|
||||
### 📚 Documentation
|
||||
You can find the auto-generated documentation [here](https://pagefaultgames.github.io/pokerogue/main/index.html).
|
||||
For information on enemy AI, check out the [enemy-ai.md](./docs/enemy-ai.md) file.
|
||||
For detailed guidelines on documenting your code, refer to the [comments.md](./docs/comments.md) file.
|
||||
|
||||
### ❔ FAQ
|
||||
|
||||
|
@ -49,7 +49,7 @@ async function promptFileName(selectedType) {
|
||||
{
|
||||
type: "input",
|
||||
name: "userInput",
|
||||
message: `Please provide a file name for the ${selectedType} test:`,
|
||||
message: `Please provide the name of the ${selectedType}:`,
|
||||
},
|
||||
]);
|
||||
|
||||
@ -110,7 +110,7 @@ import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
describe("${description}", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
@ -129,15 +129,22 @@ describe("${description}", () => {
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.moveset([Moves.SPLASH])
|
||||
.moveset([ Moves.SPLASH ])
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.battleType("single")
|
||||
.disableCrits()
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.SPLASH);
|
||||
});
|
||||
|
||||
it("test case", async () => {
|
||||
// await game.classicMode.startBattle([Species.MAGIKARP]);
|
||||
// game.move.select(Moves.SPLASH);
|
||||
it("should do X", async () => {
|
||||
await game.classicMode.startBattle([ Species.FEEBAS ]);
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
`;
|
||||
|
@ -41,6 +41,11 @@ export default [
|
||||
"keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords
|
||||
"comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after comma
|
||||
"import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json
|
||||
"array-bracket-spacing": ["error", "always", { "objectsInArrays": false, "arraysInArrays": false }], // Enforces consistent spacing inside array brackets
|
||||
"object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }], // Enforces consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers
|
||||
"computed-property-spacing": ["error", "never" ], // Enforces consistent spacing inside computed property brackets
|
||||
"space-infix-ops": ["error", { "int32Hint": false }], // Enforces spacing around infix operators
|
||||
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }], // Disallows multiple empty lines
|
||||
}
|
||||
}
|
||||
]
|
||||
|
14
global.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import type { SetupServerApi } from "msw/node";
|
||||
|
||||
export {};
|
||||
|
||||
declare global {
|
||||
/**
|
||||
* Only used in testing.
|
||||
* Can technically be undefined/null but for ease of use we are going to assume it is always defined.
|
||||
* Used to load i18n files exclusively.
|
||||
*
|
||||
* To set up your own server in a test see `game_data.test.ts`
|
||||
*/
|
||||
var i18nServer: SetupServerApi;
|
||||
}
|
1
package-lock.json
generated
@ -7,6 +7,7 @@
|
||||
"": {
|
||||
"name": "pokemon-rogue-battle",
|
||||
"version": "1.0.4",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@material/material-color-utilities": "^0.2.7",
|
||||
"crypto-js": "^4.2.0",
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
@ -399,13 +399,13 @@
|
||||
"x": 0,
|
||||
"y": 6,
|
||||
"w": 36,
|
||||
"h": 55
|
||||
"h": 54
|
||||
},
|
||||
"frame": {
|
||||
"x": 72,
|
||||
"y": 55,
|
||||
"w": 36,
|
||||
"h": 55
|
||||
"h": 54
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -420,13 +420,13 @@
|
||||
"x": 0,
|
||||
"y": 6,
|
||||
"w": 36,
|
||||
"h": 55
|
||||
"h": 54
|
||||
},
|
||||
"frame": {
|
||||
"x": 72,
|
||||
"y": 55,
|
||||
"w": 36,
|
||||
"h": 55
|
||||
"h": 54
|
||||
}
|
||||
},
|
||||
{
|
||||
|
Before Width: | Height: | Size: 769 B After Width: | Height: | Size: 411 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 637 B After Width: | Height: | Size: 399 B |
Before Width: | Height: | Size: 879 B After Width: | Height: | Size: 942 B |
Before Width: | Height: | Size: 637 B After Width: | Height: | Size: 399 B |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
@ -399,13 +399,13 @@
|
||||
"x": 0,
|
||||
"y": 6,
|
||||
"w": 36,
|
||||
"h": 55
|
||||
"h": 54
|
||||
},
|
||||
"frame": {
|
||||
"x": 72,
|
||||
"y": 55,
|
||||
"w": 36,
|
||||
"h": 55
|
||||
"h": 54
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -420,13 +420,13 @@
|
||||
"x": 0,
|
||||
"y": 6,
|
||||
"w": 36,
|
||||
"h": 55
|
||||
"h": 54
|
||||
},
|
||||
"frame": {
|
||||
"x": 72,
|
||||
"y": 55,
|
||||
"w": 36,
|
||||
"h": 55
|
||||
"h": 54
|
||||
}
|
||||
},
|
||||
{
|
||||
|
Before Width: | Height: | Size: 769 B After Width: | Height: | Size: 411 B |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
40
public/images/pokemon/variant/6706.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"1": {
|
||||
"566678": "0e6296",
|
||||
"e0e4f4": "513981",
|
||||
"625287": "4e4094",
|
||||
"536273": "1f1233",
|
||||
"988b98": "b24c86",
|
||||
"9170b9": "8b69c3",
|
||||
"c4cce1": "3b235c",
|
||||
"e6d3e9": "f1a4c5",
|
||||
"bfacc1": "da75a5",
|
||||
"515f70": "197497",
|
||||
"c5cee3": "63cee1",
|
||||
"8e96aa": "301848",
|
||||
"8b93a6": "3aa8c4",
|
||||
"80737f": "8a2166",
|
||||
"4b454f": "6f1357",
|
||||
"36404c": "0c5474",
|
||||
"b791f2": "c7a1e5"
|
||||
},
|
||||
"2": {
|
||||
"566678": "8e480b",
|
||||
"e0e4f4": "176463",
|
||||
"625287": "274159",
|
||||
"536273": "02262c",
|
||||
"988b98": "2a6563",
|
||||
"9170b9": "2f667c",
|
||||
"c4cce1": "0d484a",
|
||||
"e6d3e9": "9cead8",
|
||||
"bfacc1": "5db6a9",
|
||||
"515f70": "a34205",
|
||||
"c5cee3": "f7af58",
|
||||
"8e96aa": "073338",
|
||||
"8b93a6": "d27e26",
|
||||
"80737f": "2b736f",
|
||||
"4b454f": "194f51",
|
||||
"36404c": "842401",
|
||||
"b791f2": "4a9699"
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "6706_2.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 82,
|
||||
"h": 82
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:02eb46aa66ac70df612e129b7801a85c:a77cca14b23f4f3aece64d1a82449a0f:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 5.0 KiB |
@ -1,41 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "6706_3.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 82,
|
||||
"h": 82
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:02eb46aa66ac70df612e129b7801a85c:a77cca14b23f4f3aece64d1a82449a0f:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 5.1 KiB |
@ -3721,8 +3721,8 @@
|
||||
],
|
||||
"6706": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"6713": [
|
||||
0,
|
||||
@ -7754,8 +7754,8 @@
|
||||
],
|
||||
"6706": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"6713": [
|
||||
0,
|
||||
@ -8493,8 +8493,8 @@
|
||||
],
|
||||
"705": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"706": [
|
||||
0,
|
||||
@ -9568,8 +9568,8 @@
|
||||
],
|
||||
"6706": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"female": {},
|
||||
"back": {
|
||||
@ -11095,8 +11095,8 @@
|
||||
],
|
||||
"6706": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"6713": [
|
||||
0,
|
||||
|
38
public/images/pokemon/variant/back/6706.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"1": {
|
||||
"566678": "197497",
|
||||
"8e96aa": "3b235c",
|
||||
"929aad": "3aa8c4",
|
||||
"625287": "4e4094",
|
||||
"536273": "301848",
|
||||
"988b98": "b24c86",
|
||||
"36404c": "0c5474",
|
||||
"c4cce1": "513981",
|
||||
"e6d3e9": "f1a4c5",
|
||||
"bfacc1": "d074a0",
|
||||
"546475": "0e6296",
|
||||
"c5cee3": "63cee1",
|
||||
"80737f": "8a2166",
|
||||
"4b454f": "6f1357",
|
||||
"9170b9": "8b69c3",
|
||||
"b791f2": "c7a1e5"
|
||||
},
|
||||
"2": {
|
||||
"566678": "a34205",
|
||||
"8e96aa": "073338",
|
||||
"929aad": "d27e26",
|
||||
"625287": "0e3f47",
|
||||
"536273": "042329",
|
||||
"988b98": "2b736f",
|
||||
"36404c": "842401",
|
||||
"c4cce1": "0d484a",
|
||||
"e6d3e9": "9cead8",
|
||||
"bfacc1": "5db6a9",
|
||||
"546475": "8e480b",
|
||||
"c5cee3": "f7af58",
|
||||
"80737f": "194f51",
|
||||
"4b454f": "274159",
|
||||
"9170b9": "2f667c",
|
||||
"b791f2": "4a9699"
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "6706_2.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 79,
|
||||
"h": 79
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 79,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 79,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 79,
|
||||
"h": 73
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:64f7e6dfa489012922487e45ba53d557:4d24652b372939abe499497c4b6647b0:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 4.7 KiB |
@ -1,41 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "6706_3.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 79,
|
||||
"h": 79
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 79,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 79,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 79,
|
||||
"h": 73
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:64f7e6dfa489012922487e45ba53d557:4d24652b372939abe499497c4b6647b0:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 4.7 KiB |
40
public/images/pokemon/variant/exp/6706.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"1": {
|
||||
"566678": "0e6296",
|
||||
"e0e4f4": "513981",
|
||||
"625287": "4e4094",
|
||||
"536273": "1f1233",
|
||||
"988b98": "b24c86",
|
||||
"36404c": "0c5474",
|
||||
"c4cce1": "3b235c",
|
||||
"e6d3e9": "f1a4c5",
|
||||
"bfacc1": "da75a5",
|
||||
"515f70": "197497",
|
||||
"c5cee3": "63cee1",
|
||||
"b791f2": "c7a1e5",
|
||||
"8b93a6": "3aa8c4",
|
||||
"80737f": "8a2166",
|
||||
"4b454f": "6f1357",
|
||||
"9170b9": "8b69c3",
|
||||
"8e96aa": "301848"
|
||||
},
|
||||
"2": {
|
||||
"566678": "8e480b",
|
||||
"e0e4f4": "176463",
|
||||
"625287": "274159",
|
||||
"536273": "02262c",
|
||||
"988b98": "2a6563",
|
||||
"36404c": "842401",
|
||||
"c4cce1": "0d484a",
|
||||
"e6d3e9": "9cead8",
|
||||
"bfacc1": "5db6a9",
|
||||
"515f70": "a34205",
|
||||
"c5cee3": "f7af58",
|
||||
"b791f2": "4a9699",
|
||||
"8b93a6": "d27e26",
|
||||
"80737f": "2b736f",
|
||||
"4b454f": "194f51",
|
||||
"9170b9": "2f667c",
|
||||
"8e96aa": "073338"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 55 KiB |
33
public/images/pokemon/variant/exp/705.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"1": {
|
||||
"101010":"101010",
|
||||
"4d454d":"8a2166",
|
||||
"807380":"b93f84",
|
||||
"bfacbf":"e56ca6",
|
||||
"f2daf2":"fbb3d2",
|
||||
"665980":"4e4094",
|
||||
"8f7db3":"8b69c3",
|
||||
"b8a1e5":"c7a1e5",
|
||||
"4d993d":"aa6a00",
|
||||
"66cc52":"ffd047",
|
||||
"4e9c3e":"0c5474",
|
||||
"67cf53":"3aa8c4",
|
||||
"b6f2aa":"63cee1"
|
||||
},
|
||||
"2": {
|
||||
"101010":"101010",
|
||||
"4d454d":"194f51",
|
||||
"807380":"2b736f",
|
||||
"bfacbf":"5db6a9",
|
||||
"f2daf2":"9cead8",
|
||||
"665980":"274159",
|
||||
"8f7db3":"2f667c",
|
||||
"b8a1e5":"4a9699",
|
||||
"4d993d":"007d61",
|
||||
"66cc52":"49ffbf",
|
||||
"4e9c3e":"842401",
|
||||
"67cf53":"a34205",
|
||||
"b6f2aa":"d27e26"
|
||||
}
|
||||
}
|
||||
|
@ -1,272 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "705_2.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 154,
|
||||
"h": 154
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 46,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 46,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 91,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
"w": 42,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 58,
|
||||
"w": 42,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
"w": 42,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 58,
|
||||
"w": 42,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 42,
|
||||
"y": 58,
|
||||
"w": 41,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 42,
|
||||
"y": 58,
|
||||
"w": 41,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 36,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 83,
|
||||
"y": 58,
|
||||
"w": 36,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 36,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 83,
|
||||
"y": 58,
|
||||
"w": 36,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 35,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 119,
|
||||
"y": 58,
|
||||
"w": 35,
|
||||
"h": 58
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:4bf155254b23c88780e7eee282256589:82bb727988054c3064e203b6908ff464:6b57e983626c7fc9144ab67f30c66814$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 4.0 KiB |
@ -1,272 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "705_3.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 154,
|
||||
"h": 154
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 46,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 46,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 91,
|
||||
"y": 0,
|
||||
"w": 45,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
"w": 42,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 58,
|
||||
"w": 42,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
"w": 42,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 58,
|
||||
"w": 42,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 42,
|
||||
"y": 58,
|
||||
"w": 41,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 41,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 42,
|
||||
"y": 58,
|
||||
"w": 41,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 36,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 83,
|
||||
"y": 58,
|
||||
"w": 36,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 36,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 83,
|
||||
"y": 58,
|
||||
"w": 36,
|
||||
"h": 58
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 49,
|
||||
"h": 58
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 35,
|
||||
"h": 58
|
||||
},
|
||||
"frame": {
|
||||
"x": 119,
|
||||
"y": 58,
|
||||
"w": 35,
|
||||
"h": 58
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:4bf155254b23c88780e7eee282256589:82bb727988054c3064e203b6908ff464:6b57e983626c7fc9144ab67f30c66814$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 4.0 KiB |
38
public/images/pokemon/variant/exp/back/6706.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"1": {
|
||||
"566678": "197497",
|
||||
"8e96aa": "3b235c",
|
||||
"929aad": "3aa8c4",
|
||||
"625287": "4e4094",
|
||||
"536273": "301848",
|
||||
"988b98": "b24c86",
|
||||
"36404c": "0c5474",
|
||||
"c4cce1": "513981",
|
||||
"e6d3e9": "f1a4c5",
|
||||
"bfacc1": "d074a0",
|
||||
"546475": "0e6296",
|
||||
"c5cee3": "63cee1",
|
||||
"80737f": "8a2166",
|
||||
"4b454f": "6f1357",
|
||||
"9170b9": "8b69c3",
|
||||
"b791f2": "c7a1e5"
|
||||
},
|
||||
"2": {
|
||||
"566678": "a34205",
|
||||
"8e96aa": "073338",
|
||||
"929aad": "d27e26",
|
||||
"625287": "0e3f47",
|
||||
"536273": "042329",
|
||||
"988b98": "2b736f",
|
||||
"36404c": "842401",
|
||||
"c4cce1": "0d484a",
|
||||
"e6d3e9": "9cead8",
|
||||
"bfacc1": "5db6a9",
|
||||
"546475": "8e480b",
|
||||
"c5cee3": "f7af58",
|
||||
"80737f": "194f51",
|
||||
"4b454f": "274159",
|
||||
"9170b9": "2f667c",
|
||||
"b791f2": "4a9699"
|
||||
}
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "6706_2.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 358,
|
||||
"h": 358
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 4,
|
||||
"w": 84,
|
||||
"h": 69
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 84,
|
||||
"h": 69
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 4,
|
||||
"w": 84,
|
||||
"h": 69
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 84,
|
||||
"h": 69
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 1,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 1,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0034.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 1,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 69,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 167,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 167,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0035.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 250,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0036.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 250,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 4,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 167,
|
||||
"y": 70,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 4,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 167,
|
||||
"y": 70,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0013.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 83,
|
||||
"y": 72,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0014.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 83,
|
||||
"y": 72,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0025.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 141,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0026.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 141,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0027.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 141,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0032.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 4,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 249,
|
||||
"y": 70,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0033.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 4,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 249,
|
||||
"y": 70,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 0,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 214,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 0,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 214,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0017.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 287,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0018.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 287,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0028.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 0,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 81,
|
||||
"y": 214,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0029.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 0,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 81,
|
||||
"y": 214,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0021.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 81,
|
||||
"y": 287,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0022.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 81,
|
||||
"y": 287,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0015.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 165,
|
||||
"y": 143,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0016.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 165,
|
||||
"y": 143,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0023.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 247,
|
||||
"y": 143,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0024.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 247,
|
||||
"y": 143,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 6,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 162,
|
||||
"y": 215,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 6,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 162,
|
||||
"y": 215,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0019.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 3,
|
||||
"w": 81,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 162,
|
||||
"y": 288,
|
||||
"w": 81,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0020.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 3,
|
||||
"w": 81,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 162,
|
||||
"y": 288,
|
||||
"w": 81,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0030.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 6,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 242,
|
||||
"y": 215,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0031.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 6,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 242,
|
||||
"y": 215,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:5d65e2c5a6a97b7c7014a175ce3592af:3255e87f637a475d82734fc7d93baf71:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 22 KiB |
@ -1,776 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "6706_3.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 358,
|
||||
"h": 358
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 4,
|
||||
"w": 84,
|
||||
"h": 69
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 84,
|
||||
"h": 69
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0002.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 4,
|
||||
"w": 84,
|
||||
"h": 69
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 84,
|
||||
"h": 69
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0005.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 1,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0006.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 1,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 84,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0034.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 1,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 69,
|
||||
"w": 83,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0003.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 167,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0004.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 167,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0035.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 250,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0036.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 250,
|
||||
"y": 0,
|
||||
"w": 83,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0007.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 4,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 167,
|
||||
"y": 70,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0008.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 4,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 167,
|
||||
"y": 70,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0013.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 83,
|
||||
"y": 72,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0014.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 83,
|
||||
"y": 72,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0025.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 141,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0026.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 141,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0027.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 3,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 141,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0032.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 4,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 249,
|
||||
"y": 70,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0033.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 4,
|
||||
"y": 0,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 249,
|
||||
"y": 70,
|
||||
"w": 82,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0011.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 0,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 214,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0012.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 0,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 214,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0017.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 287,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0018.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 287,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0028.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 0,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 81,
|
||||
"y": 214,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0029.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"y": 0,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 81,
|
||||
"y": 214,
|
||||
"w": 81,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0021.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 81,
|
||||
"y": 287,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0022.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 81,
|
||||
"y": 287,
|
||||
"w": 81,
|
||||
"h": 71
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0015.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 165,
|
||||
"y": 143,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0016.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 165,
|
||||
"y": 143,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0023.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 247,
|
||||
"y": 143,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0024.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 247,
|
||||
"y": 143,
|
||||
"w": 82,
|
||||
"h": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0009.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 6,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 162,
|
||||
"y": 215,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0010.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 6,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 162,
|
||||
"y": 215,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0019.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 3,
|
||||
"w": 81,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 162,
|
||||
"y": 288,
|
||||
"w": 81,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0020.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 3,
|
||||
"w": 81,
|
||||
"h": 70
|
||||
},
|
||||
"frame": {
|
||||
"x": 162,
|
||||
"y": 288,
|
||||
"w": 81,
|
||||
"h": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0030.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 6,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 242,
|
||||
"y": 215,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "0031.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 86,
|
||||
"h": 73
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 6,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 242,
|
||||
"y": 215,
|
||||
"w": 80,
|
||||
"h": 73
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:5d65e2c5a6a97b7c7014a175ce3592af:3255e87f637a475d82734fc7d93baf71:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 22 KiB |
@ -853,14 +853,14 @@
|
||||
"spriteSourceSize": { "x": 7, "y": 2, "w": 27, "h": 26 },
|
||||
"sourceSize": { "w": 40, "h": 30 }
|
||||
},
|
||||
"981_2.png": {
|
||||
"981_2": {
|
||||
"frame": { "x": 108, "y": 87, "w": 23, "h": 30 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 9, "y": 0, "w": 23, "h": 30 },
|
||||
"sourceSize": { "w": 40, "h": 30 }
|
||||
},
|
||||
"981_3.png": {
|
||||
"981_3": {
|
||||
"frame": { "x": 246, "y": 86, "w": 23, "h": 30 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
|
@ -20,7 +20,7 @@ export function initLoggedInUser(): void {
|
||||
export function updateUserInfo(): Promise<[boolean, integer]> {
|
||||
return new Promise<[boolean, integer]>(resolve => {
|
||||
if (bypassLogin) {
|
||||
loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false};
|
||||
loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false };
|
||||
let lastSessionSlot = -1;
|
||||
for (let s = 0; s < 5; s++) {
|
||||
if (localStorage.getItem(`sessionData${s ? s : ""}_${loggedInUser.username}`)) {
|
||||
|
@ -1,57 +1,57 @@
|
||||
import Phaser from "phaser";
|
||||
import UI from "./ui/ui";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon } from "./field/pokemon";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "./data/pokemon-species";
|
||||
import UI from "#app/ui/ui";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species";
|
||||
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||
import * as Utils from "./utils";
|
||||
import * as Utils from "#app/utils";
|
||||
import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, Modifier, ModifierBar, ModifierPredicate, MultipleParticipantExpBonusModifier, overrideHeldItems, overrideModifiers, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, TerastallizeModifier, TurnHeldItemTransferModifier } from "./modifier/modifier";
|
||||
import { PokeballType } from "./data/pokeball";
|
||||
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "./data/battle-anims";
|
||||
import { Phase } from "./phase";
|
||||
import { initGameSpeed } from "./system/game-speed";
|
||||
import { Arena, ArenaBase } from "./field/arena";
|
||||
import { GameData } from "./system/game-data";
|
||||
import { addTextObject, getTextColor, TextStyle } from "./ui/text";
|
||||
import { allMoves } from "./data/move";
|
||||
import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, ModifierPoolType, modifierTypes, PokemonHeldItemModifierType } from "./modifier/modifier-type";
|
||||
import AbilityBar from "./ui/ability-bar";
|
||||
import { allAbilities, applyAbAttrs, applyPostBattleInitAbAttrs, BlockItemTheftAbAttr, ChangeMovePriorityAbAttr, DoubleBattleChanceAbAttr, PostBattleInitAbAttr } from "./data/ability";
|
||||
import Battle, { BattleType, FixedBattleConfig } from "./battle";
|
||||
import { GameMode, GameModes, getGameMode } from "./game-mode";
|
||||
import FieldSpritePipeline from "./pipelines/field-sprite";
|
||||
import SpritePipeline from "./pipelines/sprite";
|
||||
import PartyExpBar from "./ui/party-exp-bar";
|
||||
import { trainerConfigs, TrainerSlot } from "./data/trainer-config";
|
||||
import Trainer, { TrainerVariant } from "./field/trainer";
|
||||
import TrainerData from "./system/trainer-data";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "#app/data/battle-anims";
|
||||
import { Phase } from "#app/phase";
|
||||
import { initGameSpeed } from "#app/system/game-speed";
|
||||
import { Arena, ArenaBase } from "#app/field/arena";
|
||||
import { GameData } from "#app/system/game-data";
|
||||
import { addTextObject, getTextColor, TextStyle } from "#app/ui/text";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, ModifierPoolType, modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import AbilityBar from "#app/ui/ability-bar";
|
||||
import { allAbilities, applyAbAttrs, applyPostBattleInitAbAttrs, BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, PostBattleInitAbAttr } from "#app/data/ability";
|
||||
import Battle, { BattleType, FixedBattleConfig } from "#app/battle";
|
||||
import { GameMode, GameModes, getGameMode } from "#app/game-mode";
|
||||
import FieldSpritePipeline from "#app/pipelines/field-sprite";
|
||||
import SpritePipeline from "#app/pipelines/sprite";
|
||||
import PartyExpBar from "#app/ui/party-exp-bar";
|
||||
import { trainerConfigs, TrainerSlot } from "#app/data/trainer-config";
|
||||
import Trainer, { TrainerVariant } from "#app/field/trainer";
|
||||
import TrainerData from "#app/system/trainer-data";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { pokemonPrevolutions } from "./data/balance/pokemon-evolutions";
|
||||
import PokeballTray from "./ui/pokeball-tray";
|
||||
import InvertPostFX from "./pipelines/invert";
|
||||
import { Achv, achvs, ModifierAchv, MoneyAchv } from "./system/achv";
|
||||
import { Voucher, vouchers } from "./system/voucher";
|
||||
import { Gender } from "./data/gender";
|
||||
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import PokeballTray from "#app/ui/pokeball-tray";
|
||||
import InvertPostFX from "#app/pipelines/invert";
|
||||
import { Achv, achvs, ModifierAchv, MoneyAchv } from "#app/system/achv";
|
||||
import { Voucher, vouchers } from "#app/system/voucher";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin";
|
||||
import { addUiThemeOverrides } from "./ui/ui-theme";
|
||||
import PokemonData from "./system/pokemon-data";
|
||||
import { Nature } from "./data/nature";
|
||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChange, SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger } from "./data/pokemon-forms";
|
||||
import { FormChangePhase } from "./phases/form-change-phase";
|
||||
import { getTypeRgb } from "./data/type";
|
||||
import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler";
|
||||
import CharSprite from "./ui/char-sprite";
|
||||
import DamageNumberHandler from "./field/damage-number-handler";
|
||||
import PokemonInfoContainer from "./ui/pokemon-info-container";
|
||||
import { biomeDepths, getBiomeName } from "./data/balance/biomes";
|
||||
import { SceneBase } from "./scene-base";
|
||||
import CandyBar from "./ui/candy-bar";
|
||||
import { Variant, variantData } from "./data/variant";
|
||||
import { addUiThemeOverrides } from "#app/ui/ui-theme";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChange, SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger } from "#app/data/pokemon-forms";
|
||||
import { FormChangePhase } from "#app/phases/form-change-phase";
|
||||
import { getTypeRgb } from "#app/data/type";
|
||||
import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler";
|
||||
import CharSprite from "#app/ui/char-sprite";
|
||||
import DamageNumberHandler from "#app/field/damage-number-handler";
|
||||
import PokemonInfoContainer from "#app/ui/pokemon-info-container";
|
||||
import { biomeDepths, getBiomeName } from "#app/data/balance/biomes";
|
||||
import { SceneBase } from "#app/scene-base";
|
||||
import CandyBar from "#app/ui/candy-bar";
|
||||
import { Variant, variantData } from "#app/data/variant";
|
||||
import { Localizable } from "#app/interfaces/locales";
|
||||
import Overrides from "#app/overrides";
|
||||
import { InputsController } from "./inputs-controller";
|
||||
import { UiInputs } from "./ui-inputs";
|
||||
import { NewArenaEvent } from "./events/battle-scene";
|
||||
import { ArenaFlyout } from "./ui/arena-flyout";
|
||||
import { InputsController } from "#app/inputs-controller";
|
||||
import { UiInputs } from "#app/ui-inputs";
|
||||
import { NewArenaEvent } from "#app/events/battle-scene";
|
||||
import { ArenaFlyout } from "#app/ui/arena-flyout";
|
||||
import { EaseType } from "#enums/ease-type";
|
||||
import { BattleSpec } from "#enums/battle-spec";
|
||||
import { BattleStyle } from "#enums/battle-style";
|
||||
@ -66,27 +66,27 @@ import { TimedEventManager } from "#app/timed-event-manager";
|
||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||
import i18next from "i18next";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { battleSpecDialogue } from "./data/dialogue";
|
||||
import { LoadingScene } from "./loading-scene";
|
||||
import { LevelCapPhase } from "./phases/level-cap-phase";
|
||||
import { LoginPhase } from "./phases/login-phase";
|
||||
import { MessagePhase } from "./phases/message-phase";
|
||||
import { MovePhase } from "./phases/move-phase";
|
||||
import { NewBiomeEncounterPhase } from "./phases/new-biome-encounter-phase";
|
||||
import { NextEncounterPhase } from "./phases/next-encounter-phase";
|
||||
import { PokemonAnimPhase } from "./phases/pokemon-anim-phase";
|
||||
import { QuietFormChangePhase } from "./phases/quiet-form-change-phase";
|
||||
import { ReturnPhase } from "./phases/return-phase";
|
||||
import { SelectBiomePhase } from "./phases/select-biome-phase";
|
||||
import { ShowTrainerPhase } from "./phases/show-trainer-phase";
|
||||
import { SummonPhase } from "./phases/summon-phase";
|
||||
import { SwitchPhase } from "./phases/switch-phase";
|
||||
import { TitlePhase } from "./phases/title-phase";
|
||||
import { ToggleDoublePositionPhase } from "./phases/toggle-double-position-phase";
|
||||
import { TurnInitPhase } from "./phases/turn-init-phase";
|
||||
import { ShopCursorTarget } from "./enums/shop-cursor-target";
|
||||
import MysteryEncounter from "./data/mystery-encounters/mystery-encounter";
|
||||
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters";
|
||||
import { battleSpecDialogue } from "#app/data/dialogue";
|
||||
import { LoadingScene } from "#app/loading-scene";
|
||||
import { LevelCapPhase } from "#app/phases/level-cap-phase";
|
||||
import { LoginPhase } from "#app/phases/login-phase";
|
||||
import { MessagePhase } from "#app/phases/message-phase";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase";
|
||||
import { NextEncounterPhase } from "#app/phases/next-encounter-phase";
|
||||
import { PokemonAnimPhase } from "#app/phases/pokemon-anim-phase";
|
||||
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
|
||||
import { ReturnPhase } from "#app/phases/return-phase";
|
||||
import { SelectBiomePhase } from "#app/phases/select-biome-phase";
|
||||
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
|
||||
import { SummonPhase } from "#app/phases/summon-phase";
|
||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
||||
import { TitlePhase } from "#app/phases/title-phase";
|
||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
||||
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
@ -94,7 +94,7 @@ import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import { ExpPhase } from "#app/phases/exp-phase";
|
||||
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
import { ExpGainsSpeed } from "./enums/exp-gains-speed";
|
||||
import { ExpGainsSpeed } from "#enums/exp-gains-speed";
|
||||
|
||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||
|
||||
@ -889,6 +889,9 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
const pokemon = new EnemyPokemon(this, species, level, trainerSlot, boss, dataSource);
|
||||
if (Overrides.OPP_FUSION_OVERRIDE) {
|
||||
pokemon.generateFusionSpecies();
|
||||
}
|
||||
|
||||
overrideModifiers(this, false);
|
||||
overrideHeldItems(this, pokemon, false);
|
||||
@ -1261,7 +1264,7 @@ export default class BattleScene extends SceneBase {
|
||||
const isEndlessFifthWave = this.gameMode.hasShortBiomes && (lastBattle.waveIndex % 5) === 0;
|
||||
const isWaveIndexMultipleOfFiftyMinusOne = (lastBattle.waveIndex % 50) === 49;
|
||||
const isNewBiome = isWaveIndexMultipleOfTen || isEndlessFifthWave || (isEndlessOrDaily && isWaveIndexMultipleOfFiftyMinusOne);
|
||||
const resetArenaState = isNewBiome || [BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.currentBattle.battleType) || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
||||
const resetArenaState = isNewBiome || [ BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER ].includes(this.currentBattle.battleType) || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
||||
this.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy());
|
||||
this.trySpreadPokerus();
|
||||
if (!isNewBiome && (newWaveIndex % 10) === 5) {
|
||||
@ -1758,14 +1761,14 @@ export default class BattleScene extends SceneBase {
|
||||
if (fromArenaPool) {
|
||||
return this.arena.randomSpecies(waveIndex, level, undefined, getPartyLuckValue(this.party));
|
||||
}
|
||||
const filteredSpecies = speciesFilter ? [...new Set(allSpecies.filter(s => s.isCatchable()).filter(speciesFilter).map(s => {
|
||||
const filteredSpecies = speciesFilter ? [ ...new Set(allSpecies.filter(s => s.isCatchable()).filter(speciesFilter).map(s => {
|
||||
if (!filterAllEvolutions) {
|
||||
while (pokemonPrevolutions.hasOwnProperty(s.speciesId)) {
|
||||
s = getPokemonSpecies(pokemonPrevolutions[s.speciesId]);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}))] : allSpecies.filter(s => s.isCatchable());
|
||||
})) ] : allSpecies.filter(s => s.isCatchable());
|
||||
return filteredSpecies[Utils.randSeedInt(filteredSpecies.length)];
|
||||
}
|
||||
|
||||
@ -1885,14 +1888,14 @@ export default class BattleScene extends SceneBase {
|
||||
case "battle_anims":
|
||||
case "cry":
|
||||
if (soundDetails[1].startsWith("PRSFX- ")) {
|
||||
sound.setVolume(this.masterVolume*this.fieldVolume*0.5);
|
||||
sound.setVolume(this.masterVolume * this.fieldVolume * 0.5);
|
||||
} else {
|
||||
sound.setVolume(this.masterVolume*this.fieldVolume);
|
||||
sound.setVolume(this.masterVolume * this.fieldVolume);
|
||||
}
|
||||
break;
|
||||
case "se":
|
||||
case "ui":
|
||||
sound.setVolume(this.masterVolume*this.seVolume);
|
||||
sound.setVolume(this.masterVolume * this.seVolume);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2221,7 +2224,7 @@ export default class BattleScene extends SceneBase {
|
||||
*
|
||||
*/
|
||||
pushConditionalPhase(phase: Phase, condition: () => boolean): void {
|
||||
this.conditionalQueue.push([condition, phase]);
|
||||
this.conditionalQueue.push([ condition, phase ]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2313,7 +2316,10 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
}
|
||||
|
||||
this.currentPhase?.start();
|
||||
if (this.currentPhase) {
|
||||
console.log(`%cStart Phase ${this.currentPhase.constructor.name}`, "color:green;");
|
||||
this.currentPhase.start();
|
||||
}
|
||||
}
|
||||
|
||||
overridePhase(phase: Phase): boolean {
|
||||
@ -2323,6 +2329,7 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
this.standbyPhase = this.currentPhase;
|
||||
this.currentPhase = phase;
|
||||
console.log(`%cStart Phase ${phase.constructor.name}`, "color:green;");
|
||||
phase.start();
|
||||
|
||||
return true;
|
||||
@ -2356,17 +2363,6 @@ export default class BattleScene extends SceneBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
pushMovePhase(movePhase: MovePhase, priorityOverride?: integer): void {
|
||||
const movePriority = new Utils.IntegerHolder(priorityOverride !== undefined ? priorityOverride : movePhase.move.getMove().priority);
|
||||
applyAbAttrs(ChangeMovePriorityAbAttr, movePhase.pokemon, null, false, movePhase.move.getMove(), movePriority);
|
||||
const lowerPriorityPhase = this.phaseQueue.find(p => p instanceof MovePhase && p.move.getMove().priority < movePriority.value);
|
||||
if (lowerPriorityPhase) {
|
||||
this.phaseQueue.splice(this.phaseQueue.indexOf(lowerPriorityPhase), 0, movePhase);
|
||||
} else {
|
||||
this.pushPhase(movePhase);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to add the input phase to index before target phase in the phaseQueue, else simply calls unshiftPhase()
|
||||
* @param phase {@linkcode Phase} the phase to be added
|
||||
@ -2498,7 +2494,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success));
|
||||
return Promise.allSettled([ this.party.map(p => p.updateInfo(instant)), ...modifierPromises ]).then(() => resolve(success));
|
||||
} else {
|
||||
const args = [ this ];
|
||||
if (modifier.shouldApply(...args)) {
|
||||
@ -2684,7 +2680,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all modifiers from enemy of PersistentModifier type
|
||||
* Removes all modifiers from enemy pokemon of {@linkcode PersistentModifier} type
|
||||
*/
|
||||
clearEnemyModifiers(): void {
|
||||
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PersistentModifier);
|
||||
@ -2695,10 +2691,11 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all modifiers from enemy of PokemonHeldItemModifier type
|
||||
* Removes all modifiers from enemy pokemon of {@linkcode PokemonHeldItemModifier} type
|
||||
* @param pokemon - If specified, only removes held items from that {@linkcode Pokemon}
|
||||
*/
|
||||
clearEnemyHeldItemModifiers(): void {
|
||||
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier);
|
||||
clearEnemyHeldItemModifiers(pokemon?: Pokemon): void {
|
||||
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier && (!pokemon || m.getPokemon(this) === pokemon));
|
||||
for (const m of modifiersToRemove) {
|
||||
this.enemyModifiers.splice(this.enemyModifiers.indexOf(m), 1);
|
||||
}
|
||||
@ -2818,7 +2815,7 @@ export default class BattleScene extends SceneBase {
|
||||
return mods;
|
||||
}
|
||||
const rand = Utils.randSeedInt(mods.length);
|
||||
return [mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand))];
|
||||
return [ mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand)) ];
|
||||
};
|
||||
modifiers = shuffleModifiers(modifiers);
|
||||
}, scene.currentBattle.turn << 4, scene.waveSeed);
|
||||
@ -2978,7 +2975,7 @@ export default class BattleScene extends SceneBase {
|
||||
keys.push(p.getBattleSpriteKey(true, true));
|
||||
keys.push("cry/" + p.species.getCryKey(p.formIndex));
|
||||
if (p.fusionSpecies) {
|
||||
keys.push("cry/"+p.fusionSpecies.getCryKey(p.fusionFormIndex));
|
||||
keys.push("cry/" + p.fusionSpecies.getCryKey(p.fusionFormIndex));
|
||||
}
|
||||
});
|
||||
// enemyParty has to be operated on separately from playerParty because playerPokemon =/= enemyPokemon
|
||||
@ -2987,7 +2984,7 @@ export default class BattleScene extends SceneBase {
|
||||
keys.push(p.getSpriteKey(true));
|
||||
keys.push("cry/" + p.species.getCryKey(p.formIndex));
|
||||
if (p.fusionSpecies) {
|
||||
keys.push("cry/"+p.fusionSpecies.getCryKey(p.fusionFormIndex));
|
||||
keys.push("cry/" + p.fusionSpecies.getCryKey(p.fusionFormIndex));
|
||||
}
|
||||
});
|
||||
return keys;
|
||||
@ -3135,7 +3132,7 @@ export default class BattleScene extends SceneBase {
|
||||
* @param sessionDataEncounterType
|
||||
*/
|
||||
private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number, sessionDataEncounterType?: MysteryEncounterType): boolean {
|
||||
const [lowestMysteryEncounterWave, highestMysteryEncounterWave] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave) {
|
||||
// Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor
|
||||
const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
|
||||
@ -3169,13 +3166,17 @@ export default class BattleScene extends SceneBase {
|
||||
/**
|
||||
* Loads or generates a mystery encounter
|
||||
* @param encounterType used to load session encounter when restarting game, etc.
|
||||
* @param canBypass optional boolean to indicate that the request is coming from a function that needs to access a Mystery Encounter outside of gameplay requirements
|
||||
* @returns
|
||||
*/
|
||||
getMysteryEncounter(encounterType?: MysteryEncounterType): MysteryEncounter {
|
||||
getMysteryEncounter(encounterType?: MysteryEncounterType, canBypass?: boolean): MysteryEncounter {
|
||||
// Loading override or session encounter
|
||||
let encounter: MysteryEncounter | null;
|
||||
if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_OVERRIDE) && allMysteryEncounters.hasOwnProperty(Overrides.MYSTERY_ENCOUNTER_OVERRIDE)) {
|
||||
encounter = allMysteryEncounters[Overrides.MYSTERY_ENCOUNTER_OVERRIDE];
|
||||
} else if (canBypass) {
|
||||
encounter = allMysteryEncounters[encounterType ?? -1];
|
||||
return encounter;
|
||||
} else {
|
||||
encounter = !isNullOrUndefined(encounterType) ? allMysteryEncounters[encounterType] : null;
|
||||
}
|
||||
@ -3201,7 +3202,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
// See Enum values for base tier weights
|
||||
const tierWeights = [MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE];
|
||||
const tierWeights = [ MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE ];
|
||||
|
||||
// Adjust tier weights by previously encountered events to lower odds of only Common/Great in run
|
||||
this.mysteryEncounterSaveData.encounteredEvents.forEach(seenEncounterData => {
|
||||
|
@ -497,7 +497,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand
|
||||
}
|
||||
|
||||
/* 1/3 chance for evil team grunts to be double battles */
|
||||
const evilTeamGrunts = [TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT];
|
||||
const evilTeamGrunts = [ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ];
|
||||
const isEvilTeamGrunt = evilTeamGrunts.includes(trainerTypes[rand]);
|
||||
|
||||
if (trainerConfigs[trainerTypes[rand]].hasDouble && isEvilTeamGrunt) {
|
||||
@ -527,34 +527,34 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }),
|
||||
[35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)),
|
||||
[55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }),
|
||||
[62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)),
|
||||
[64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)),
|
||||
[66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ] ], true)),
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true)),
|
||||
[95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }),
|
||||
[112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)),
|
||||
[114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ] ], true, 1)),
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true, 1)),
|
||||
[ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE, TrainerType.PENNY ]))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }),
|
||||
[145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }),
|
||||
[ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2, TrainerType.PENNY_2 ]))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }),
|
||||
[182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])),
|
||||
[184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)
|
||||
@ -567,5 +567,5 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])),
|
||||
[195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false })
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false })
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {Button} from "#enums/buttons";
|
||||
import {SettingKeyboard} from "#app/system/settings/settings-keyboard";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { SettingKeyboard } from "#app/system/settings/settings-keyboard";
|
||||
|
||||
const cfg_keyboard_qwerty = {
|
||||
padID: "default",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Device} from "#enums/devices";
|
||||
import { Device } from "#enums/devices";
|
||||
|
||||
/**
|
||||
* Retrieves the key associated with the specified keycode from the mapping.
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "../../system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "../../system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* Dualshock mapping
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "../../system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "../../system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* Generic pad mapping
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "#app/system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "#app/system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* Nintendo Pro Controller mapping
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "../../system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "../../system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* 081f-e401 - UnlicensedSNES
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "../../system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "../../system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* Generic pad mapping
|
||||
|
@ -118,6 +118,14 @@ export class Ability implements Localizable {
|
||||
this.nameAppend += " (N)";
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal flag used for developers to document edge cases. When using this, please be sure to document the edge case.
|
||||
* @returns the ability
|
||||
*/
|
||||
edgeCase(): this {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
type AbAttrApplyFunc<TAttr extends AbAttr> = (attr: TAttr, passive: boolean) => boolean | Promise<boolean>;
|
||||
@ -162,7 +170,7 @@ export class BlockRecoilDamageAttr extends AbAttr {
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) {
|
||||
return i18next.t("abilityTriggers:blockRecoilDamage", {pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName});
|
||||
return i18next.t("abilityTriggers:blockRecoilDamage", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName });
|
||||
}
|
||||
}
|
||||
|
||||
@ -634,15 +642,15 @@ export class ReverseDrainAbAttr extends PostDefendAbAttr {
|
||||
* Examples include: Absorb, Draining Kiss, Bitter Blade, etc.
|
||||
* Also displays a message to show this ability was activated.
|
||||
* @param pokemon {@linkcode Pokemon} with this ability
|
||||
* @param passive N/A
|
||||
* @param _passive N/A
|
||||
* @param attacker {@linkcode Pokemon} that is attacking this Pokemon
|
||||
* @param move {@linkcode PokemonMove} that is being used
|
||||
* @param hitResult N/A
|
||||
* @args N/A
|
||||
* @param _hitResult N/A
|
||||
* @param _args N/A
|
||||
* @returns true if healing should be reversed on a healing move, false otherwise.
|
||||
*/
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.hasAttr(HitHealAttr)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (move.hasAttr(HitHealAttr) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (!simulated) {
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:reverseDrain", { pokemonNameWithAffix: getPokemonNameWithAffix(attacker) }));
|
||||
}
|
||||
@ -669,8 +677,8 @@ export class PostDefendStatStageChangeAbAttr extends PostDefendAbAttr {
|
||||
this.allOthers = allOthers;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (simulated) {
|
||||
return true;
|
||||
}
|
||||
@ -707,13 +715,13 @@ export class PostDefendHpGatedStatStageChangeAbAttr extends PostDefendAbAttr {
|
||||
this.selfTarget = selfTarget;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
const hpGateFlat: integer = Math.ceil(pokemon.getMaxHp() * this.hpGate);
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
const hpGateFlat: number = Math.ceil(pokemon.getMaxHp() * this.hpGate);
|
||||
const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1];
|
||||
const damageReceived = lastAttackReceived?.damage || 0;
|
||||
|
||||
if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat)) {
|
||||
if (!simulated ) {
|
||||
if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (!simulated) {
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.stages));
|
||||
}
|
||||
return true;
|
||||
@ -734,8 +742,8 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr {
|
||||
this.tagType = tagType;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
const tag = pokemon.scene.arena.getTag(this.tagType) as ArenaTrapTag;
|
||||
if (!pokemon.scene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers) {
|
||||
if (!simulated) {
|
||||
@ -758,8 +766,8 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
|
||||
this.tagType = tagType;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (!pokemon.getTag(this.tagType) && !simulated) {
|
||||
pokemon.addTag(this.tagType, undefined, undefined, pokemon.id);
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }));
|
||||
@ -771,8 +779,8 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (hitResult < HitResult.NO_EFFECT) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean {
|
||||
if (hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (simulated) {
|
||||
return true;
|
||||
}
|
||||
@ -787,7 +795,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
||||
return i18next.t("abilityTriggers:postDefendTypeChange", {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||
abilityName,
|
||||
@ -805,8 +813,8 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr {
|
||||
this.terrainType = terrainType;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (hitResult < HitResult.NO_EFFECT) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean {
|
||||
if (hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (simulated) {
|
||||
return pokemon.scene.arena.terrain?.terrainType !== (this.terrainType || undefined);
|
||||
} else {
|
||||
@ -829,8 +837,9 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr {
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status
|
||||
&& (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)];
|
||||
if (simulated) {
|
||||
return attacker.canSetStatus(effect, true, false, pokemon);
|
||||
@ -869,8 +878,8 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr {
|
||||
this.turnCount = turnCount;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (simulated) {
|
||||
return attacker.canAddTag(this.tagType);
|
||||
} else {
|
||||
@ -893,7 +902,11 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr {
|
||||
this.stages = stages;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (move.hitsSubstitute(attacker, pokemon)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!simulated) {
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.stages));
|
||||
}
|
||||
@ -901,7 +914,7 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr {
|
||||
return true;
|
||||
}
|
||||
|
||||
getCondition(): AbAttrCondition {
|
||||
override getCondition(): AbAttrCondition {
|
||||
return (pokemon: Pokemon) => pokemon.turnData.attacksReceived.length !== 0 && pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1].critical;
|
||||
}
|
||||
}
|
||||
@ -915,8 +928,9 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr {
|
||||
this.damageRatio = damageRatio;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (!simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (!simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)
|
||||
&& !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER);
|
||||
attacker.turnData.damageTaken += Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio));
|
||||
return true;
|
||||
@ -925,7 +939,7 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
||||
return i18next.t("abilityTriggers:postDefendContactDamage", {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||
abilityName
|
||||
@ -948,8 +962,8 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr {
|
||||
this.turns = turns;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (pokemon.getTag(BattlerTagType.PERISH_SONG) || attacker.getTag(BattlerTagType.PERISH_SONG)) {
|
||||
return false;
|
||||
} else {
|
||||
@ -963,24 +977,24 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return i18next.t("abilityTriggers:perishBody", {pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName});
|
||||
override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
||||
return i18next.t("abilityTriggers:perishBody", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName });
|
||||
}
|
||||
}
|
||||
|
||||
export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr {
|
||||
private weatherType: WeatherType;
|
||||
protected condition: PokemonDefendCondition | null;
|
||||
protected condition?: PokemonDefendCondition;
|
||||
|
||||
constructor(weatherType: WeatherType, condition?: PokemonDefendCondition) {
|
||||
super();
|
||||
|
||||
this.weatherType = weatherType;
|
||||
this.condition = condition ?? null;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition !== null && !this.condition(pokemon, attacker, move)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (this.condition && !this.condition(pokemon, attacker, move) || move.hitsSubstitute(attacker, pokemon)) {
|
||||
return false;
|
||||
}
|
||||
if (!pokemon.scene.arena.weather?.isImmutable()) {
|
||||
@ -999,8 +1013,9 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr {
|
||||
super();
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)
|
||||
&& !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (!simulated) {
|
||||
const tempAbilityId = attacker.getAbility().id;
|
||||
attacker.summonData.ability = pokemon.getAbility().id;
|
||||
@ -1012,7 +1027,7 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
override getTriggerMessage(pokemon: Pokemon, _abilityName: string, ..._args: any[]): string {
|
||||
return i18next.t("abilityTriggers:postDefendAbilitySwap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
}
|
||||
}
|
||||
@ -1025,8 +1040,9 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr {
|
||||
this.ability = ability;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr)
|
||||
&& !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (!simulated) {
|
||||
attacker.summonData.ability = this.ability;
|
||||
}
|
||||
@ -1037,7 +1053,7 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
||||
return i18next.t("abilityTriggers:postDefendAbilityGive", {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||
abilityName
|
||||
@ -1056,8 +1072,8 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr {
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (attacker.getTag(BattlerTagType.DISABLED) === null) {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
if (attacker.getTag(BattlerTagType.DISABLED) === null && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) {
|
||||
if (simulated) {
|
||||
return true;
|
||||
@ -1268,7 +1284,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
|
||||
if (pokemon.getTypes().some((t) => t !== moveType)) {
|
||||
if (!simulated) {
|
||||
this.moveType = moveType;
|
||||
pokemon.summonData.types = [moveType];
|
||||
pokemon.summonData.types = [ moveType ];
|
||||
pokemon.updateInfo();
|
||||
}
|
||||
|
||||
@ -1724,17 +1740,17 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr {
|
||||
}
|
||||
|
||||
export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
||||
private condition: PokemonDefendCondition | null;
|
||||
private condition?: PokemonDefendCondition;
|
||||
|
||||
constructor(condition?: PokemonDefendCondition) {
|
||||
super();
|
||||
|
||||
this.condition = condition ?? null;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) {
|
||||
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move)) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
const heldItems = this.getTargetHeldItems(attacker).filter(i => i.isTransferable);
|
||||
if (heldItems.length) {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
@ -2814,7 +2830,7 @@ export class PreApplyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr {
|
||||
constructor(immuneTagTypes: BattlerTagType | BattlerTagType[]) {
|
||||
super();
|
||||
|
||||
this.immuneTagTypes = Array.isArray(immuneTagTypes) ? immuneTagTypes : [immuneTagTypes];
|
||||
this.immuneTagTypes = Array.isArray(immuneTagTypes) ? immuneTagTypes : [ immuneTagTypes ];
|
||||
}
|
||||
|
||||
applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, simulated: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
@ -3099,17 +3115,17 @@ function getAnticipationCondition(): AbAttrCondition {
|
||||
// edge case for hidden power, type is computed
|
||||
if (move.getMove().id === Moves.HIDDEN_POWER) {
|
||||
const iv_val = Math.floor(((opponent.ivs[Stat.HP] & 1)
|
||||
+(opponent.ivs[Stat.ATK] & 1) * 2
|
||||
+(opponent.ivs[Stat.DEF] & 1) * 4
|
||||
+(opponent.ivs[Stat.SPD] & 1) * 8
|
||||
+(opponent.ivs[Stat.SPATK] & 1) * 16
|
||||
+(opponent.ivs[Stat.SPDEF] & 1) * 32) * 15/63);
|
||||
+ (opponent.ivs[Stat.ATK] & 1) * 2
|
||||
+ (opponent.ivs[Stat.DEF] & 1) * 4
|
||||
+ (opponent.ivs[Stat.SPD] & 1) * 8
|
||||
+ (opponent.ivs[Stat.SPATK] & 1) * 16
|
||||
+ (opponent.ivs[Stat.SPDEF] & 1) * 32) * 15 / 63);
|
||||
|
||||
const type = [
|
||||
Type.FIGHTING, Type.FLYING, Type.POISON, Type.GROUND,
|
||||
Type.ROCK, Type.BUG, Type.GHOST, Type.STEEL,
|
||||
Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC,
|
||||
Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK][iv_val];
|
||||
Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK ][iv_val];
|
||||
|
||||
if (pokemon.getAttackTypeEffectiveness(type, opponent) >= 2) {
|
||||
return true;
|
||||
@ -3644,7 +3660,7 @@ export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr {
|
||||
if ((opp.status?.effect === StatusEffect.SLEEP || opp.hasAbility(Abilities.COMATOSE)) && !opp.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) {
|
||||
if (!simulated) {
|
||||
opp.damageAndUpdate(Utils.toDmgValue(opp.getMaxHp() / 8), HitResult.OTHER);
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:badDreams", {pokemonName: getPokemonNameWithAffix(opp)}));
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:badDreams", { pokemonName: getPokemonNameWithAffix(opp) }));
|
||||
}
|
||||
hadEffect = true;
|
||||
}
|
||||
@ -3755,8 +3771,8 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
*/
|
||||
applyPostMoveUsed(dancer: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], simulated: boolean, args: any[]): boolean | Promise<boolean> {
|
||||
// List of tags that prevent the Dancer from replicating the move
|
||||
const forbiddenTags = [BattlerTagType.FLYING, BattlerTagType.UNDERWATER,
|
||||
BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN];
|
||||
const forbiddenTags = [ BattlerTagType.FLYING, BattlerTagType.UNDERWATER,
|
||||
BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN ];
|
||||
// The move to replicate cannot come from the Dancer
|
||||
if (source.getBattlerIndex() !== dancer.getBattlerIndex()
|
||||
&& !dancer.summonData.tags.some(tag => forbiddenTags.includes(tag.tagType))) {
|
||||
@ -3767,7 +3783,7 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, target, move, true, true));
|
||||
} else if (move.getMove() instanceof SelfStatusMove) {
|
||||
// If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself
|
||||
dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, [dancer.getBattlerIndex()], move, true, true));
|
||||
dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, [ dancer.getBattlerIndex() ], move, true, true));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -3784,9 +3800,9 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
*/
|
||||
getTarget(dancer: Pokemon, source: Pokemon, targets: BattlerIndex[]) : BattlerIndex[] {
|
||||
if (dancer.isPlayer()) {
|
||||
return source.isPlayer() ? targets : [source.getBattlerIndex()];
|
||||
return source.isPlayer() ? targets : [ source.getBattlerIndex() ];
|
||||
}
|
||||
return source.isPlayer() ? [source.getBattlerIndex()] : targets;
|
||||
return source.isPlayer() ? [ source.getBattlerIndex() ] : targets;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4476,7 +4492,7 @@ export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageC
|
||||
export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
||||
private multiplier: number;
|
||||
private tagType: BattlerTagType;
|
||||
private recoilDamageFunc: ((pokemon: Pokemon) => number) | undefined;
|
||||
private recoilDamageFunc?: ((pokemon: Pokemon) => number);
|
||||
private triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string;
|
||||
|
||||
constructor(condition: PokemonDefendCondition, multiplier: number, tagType: BattlerTagType, triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string, recoilDamageFunc?: (pokemon: Pokemon) => number) {
|
||||
@ -4492,16 +4508,16 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
||||
* Applies the pre-defense ability to the Pokémon.
|
||||
* Removes the appropriate `BattlerTagType` when hit by an attack and is in its defense form.
|
||||
*
|
||||
* @param {Pokemon} pokemon The Pokémon with the ability.
|
||||
* @param {boolean} passive n/a
|
||||
* @param {Pokemon} attacker The attacking Pokémon.
|
||||
* @param {PokemonMove} move The move being used.
|
||||
* @param {Utils.BooleanHolder} cancelled n/a
|
||||
* @param {any[]} args Additional arguments.
|
||||
* @returns {boolean} Whether the immunity was applied.
|
||||
* @param pokemon The Pokémon with the ability.
|
||||
* @param _passive n/a
|
||||
* @param attacker The attacking Pokémon.
|
||||
* @param move The move being used.
|
||||
* @param _cancelled n/a
|
||||
* @param args Additional arguments.
|
||||
* @returns `true` if the immunity was applied.
|
||||
*/
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
override applyPreDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
if (!simulated) {
|
||||
(args[0] as Utils.NumberHolder).value = this.multiplier;
|
||||
pokemon.removeTag(this.tagType);
|
||||
@ -4517,12 +4533,12 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
||||
|
||||
/**
|
||||
* Gets the message triggered when the Pokémon avoids damage using the form-changing ability.
|
||||
* @param {Pokemon} pokemon The Pokémon with the ability.
|
||||
* @param {string} abilityName The name of the ability.
|
||||
* @param {...any} args n/a
|
||||
* @returns {string} The trigger message.
|
||||
* @param pokemon The Pokémon with the ability.
|
||||
* @param abilityName The name of the ability.
|
||||
* @param _args n/a
|
||||
* @returns The trigger message.
|
||||
*/
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
||||
return this.triggerMessageFunc(pokemon, abilityName);
|
||||
}
|
||||
}
|
||||
@ -4561,7 +4577,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr {
|
||||
const turnCommand =
|
||||
pokemon.scene.currentBattle.turnCommands[pokemon.getBattlerIndex()];
|
||||
const isCommandFight = turnCommand?.command === Command.FIGHT;
|
||||
const move = turnCommand?.move?.move ?allMoves[turnCommand.move.move] : null;
|
||||
const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null;
|
||||
const isDamageMove = move?.category === MoveCategory.PHYSICAL || move?.category === MoveCategory.SPECIAL;
|
||||
|
||||
if (isCommandFight && isDamageMove) {
|
||||
@ -4574,7 +4590,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr {
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return i18next.t("abilityTriggers:quickDraw", {pokemonName: getPokemonNameWithAffix(pokemon)});
|
||||
return i18next.t("abilityTriggers:quickDraw", { pokemonName: getPokemonNameWithAffix(pokemon) });
|
||||
}
|
||||
}
|
||||
|
||||
@ -4622,8 +4638,8 @@ async function applyAbAttrsInternal<TAttr extends AbAttr>(
|
||||
simulated: boolean = false,
|
||||
messages: string[] = [],
|
||||
) {
|
||||
for (const passive of [false, true]) {
|
||||
if (!pokemon?.canApplyAbility(passive)) {
|
||||
for (const passive of [ false, true ]) {
|
||||
if (!pokemon?.canApplyAbility(passive) || (passive && pokemon.getPassiveAbility().id === pokemon.getAbility().id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -4872,7 +4888,7 @@ export function initAbilities() {
|
||||
.attr(TypeImmunityHealAbAttr, Type.WATER)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.OBLIVIOUS, 3)
|
||||
.attr(BattlerTagImmunityAbAttr, [BattlerTagType.INFATUATED, BattlerTagType.TAUNT])
|
||||
.attr(BattlerTagImmunityAbAttr, [ BattlerTagType.INFATUATED, BattlerTagType.TAUNT ])
|
||||
.attr(IntimidateImmunityAbAttr)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.CLOUD_NINE, 3)
|
||||
@ -4898,7 +4914,7 @@ export function initAbilities() {
|
||||
.ignorable(),
|
||||
new Ability(Abilities.SHIELD_DUST, 3)
|
||||
.attr(IgnoreMoveEffectsAbAttr)
|
||||
.partial(),
|
||||
.edgeCase(), // Does not work with secret power (unimplemented)
|
||||
new Ability(Abilities.OWN_TEMPO, 3)
|
||||
.attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED)
|
||||
.attr(IntimidateImmunityAbAttr)
|
||||
@ -4943,7 +4959,7 @@ export function initAbilities() {
|
||||
.ignorable(),
|
||||
new Ability(Abilities.SERENE_GRACE, 3)
|
||||
.attr(MoveEffectChanceMultiplierAbAttr, 2)
|
||||
.partial(),
|
||||
.edgeCase(), // does not work with secret power (unimplemented)
|
||||
new Ability(Abilities.SWIFT_SWIM, 3)
|
||||
.attr(StatMultiplierAbAttr, Stat.SPD, 2)
|
||||
.condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)),
|
||||
@ -5017,10 +5033,10 @@ export function initAbilities() {
|
||||
new Ability(Abilities.CUTE_CHARM, 3)
|
||||
.attr(PostDefendContactApplyTagChanceAbAttr, 30, BattlerTagType.INFATUATED),
|
||||
new Ability(Abilities.PLUS, 3)
|
||||
.conditionalAttr(p => p.scene.currentBattle.double && [Abilities.PLUS, Abilities.MINUS].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5)
|
||||
.conditionalAttr(p => p.scene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.MINUS, 3)
|
||||
.conditionalAttr(p => p.scene.currentBattle.double && [Abilities.PLUS, Abilities.MINUS].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5)
|
||||
.conditionalAttr(p => p.scene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.FORECAST, 3)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
@ -5138,7 +5154,7 @@ export function initAbilities() {
|
||||
.conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(Abilities.COMATOSE), StatMultiplierAbAttr, Stat.SPD, 1.5),
|
||||
new Ability(Abilities.NORMALIZE, 4)
|
||||
.attr(MoveTypeChangeAbAttr, Type.NORMAL, 1.2, (user, target, move) => {
|
||||
return ![Moves.HIDDEN_POWER, Moves.WEATHER_BALL, Moves.NATURAL_GIFT, Moves.JUDGMENT, Moves.TECHNO_BLAST].includes(move.id);
|
||||
return ![ Moves.HIDDEN_POWER, Moves.WEATHER_BALL, Moves.NATURAL_GIFT, Moves.JUDGMENT, Moves.TECHNO_BLAST ].includes(move.id);
|
||||
}),
|
||||
new Ability(Abilities.SNIPER, 4)
|
||||
.attr(MultCritAbAttr, 1.5),
|
||||
@ -5184,7 +5200,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.SLOW_START, 4)
|
||||
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5),
|
||||
new Ability(Abilities.SCRAPPY, 4)
|
||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
|
||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ])
|
||||
.attr(IntimidateImmunityAbAttr),
|
||||
new Ability(Abilities.STORM_DRAIN, 4)
|
||||
.attr(RedirectTypeMoveAbAttr, Type.WATER)
|
||||
@ -5225,16 +5241,17 @@ export function initAbilities() {
|
||||
.attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT))
|
||||
.condition(getSheerForceHitDisableAbCondition()),
|
||||
new Ability(Abilities.SHEER_FORCE, 5)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461/4096)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461 / 4096)
|
||||
.attr(MoveEffectChanceMultiplierAbAttr, 0)
|
||||
.partial(),
|
||||
.edgeCase() // Should disable shell bell and Meloetta's relic song transformation
|
||||
.edgeCase(), // Should disable life orb, eject button, red card, kee/maranga berry if they get implemented
|
||||
new Ability(Abilities.CONTRARY, 5)
|
||||
.attr(StatStageChangeMultiplierAbAttr, -1)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.UNNERVE, 5)
|
||||
.attr(PreventBerryUseAbAttr),
|
||||
new Ability(Abilities.DEFIANT, 5)
|
||||
.attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [Stat.ATK], 2),
|
||||
.attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [ Stat.ATK ], 2),
|
||||
new Ability(Abilities.DEFEATIST, 5)
|
||||
.attr(StatMultiplierAbAttr, Stat.ATK, 0.5)
|
||||
.attr(StatMultiplierAbAttr, Stat.SPATK, 0.5)
|
||||
@ -5270,7 +5287,7 @@ export function initAbilities() {
|
||||
/** Rate is doubled when under sun {@link https://dex.pokemonshowdown.com/abilities/harvest} */
|
||||
(pokemon) => 0.5 * (getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)(pokemon) ? 2 : 1)
|
||||
)
|
||||
.partial(),
|
||||
.edgeCase(), // Cannot recover berries used up by fling or natural gift (unimplemented)
|
||||
new Ability(Abilities.TELEPATHY, 5)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move instanceof AttackMove)
|
||||
.ignorable(),
|
||||
@ -5320,7 +5337,7 @@ export function initAbilities() {
|
||||
return move.category !== MoveCategory.STATUS
|
||||
&& (moveType === Type.DARK || moveType === Type.BUG || moveType === Type.GHOST);
|
||||
}, Stat.SPD, 1)
|
||||
.attr(PostIntimidateStatStageChangeAbAttr, [Stat.SPD], 1),
|
||||
.attr(PostIntimidateStatStageChangeAbAttr, [ Stat.SPD ], 1),
|
||||
new Ability(Abilities.MAGIC_BOUNCE, 5)
|
||||
.ignorable()
|
||||
.unimplemented(),
|
||||
@ -5349,7 +5366,7 @@ export function initAbilities() {
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.VICTORY_STAR, 5)
|
||||
.attr(StatMultiplierAbAttr, Stat.ACC, 1.1)
|
||||
.partial(),
|
||||
.partial(), // Does not boost ally's accuracy
|
||||
new Ability(Abilities.TURBOBLAZE, 5)
|
||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonTurboblaze", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||
.attr(MoveAbilityBypassAbAttr),
|
||||
@ -5357,12 +5374,12 @@ export function initAbilities() {
|
||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonTeravolt", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||
.attr(MoveAbilityBypassAbAttr),
|
||||
new Ability(Abilities.AROMA_VEIL, 6)
|
||||
.attr(UserFieldBattlerTagImmunityAbAttr, [BattlerTagType.INFATUATED, BattlerTagType.TAUNT, BattlerTagType.DISABLED, BattlerTagType.TORMENT, BattlerTagType.HEAL_BLOCK]),
|
||||
.attr(UserFieldBattlerTagImmunityAbAttr, [ BattlerTagType.INFATUATED, BattlerTagType.TAUNT, BattlerTagType.DISABLED, BattlerTagType.TORMENT, BattlerTagType.HEAL_BLOCK ]),
|
||||
new Ability(Abilities.FLOWER_VEIL, 6)
|
||||
.ignorable()
|
||||
.unimplemented(),
|
||||
new Ability(Abilities.CHEEK_POUCH, 6)
|
||||
.attr(HealFromBerryUseAbAttr, 1/3),
|
||||
.attr(HealFromBerryUseAbAttr, 1 / 3),
|
||||
new Ability(Abilities.PROTEAN, 6)
|
||||
.attr(PokemonTypeChangeAbAttr),
|
||||
//.condition((p) => !p.summonData?.abilitiesApplied.includes(Abilities.PROTEAN)), //Gen 9 Implementation
|
||||
@ -5375,7 +5392,7 @@ export function initAbilities() {
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.BALLBOMB_MOVE))
|
||||
.ignorable(),
|
||||
new Ability(Abilities.COMPETITIVE, 6)
|
||||
.attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [Stat.SPATK], 2),
|
||||
.attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [ Stat.SPATK ], 2),
|
||||
new Ability(Abilities.STRONG_JAW, 6)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.BITING_MOVE), 1.5),
|
||||
new Ability(Abilities.REFRIGERATE, 6)
|
||||
@ -5460,7 +5477,7 @@ export function initAbilities() {
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
.partial(), // Meteor form should protect against status effects and yawn
|
||||
new Ability(Abilities.STAKEOUT, 7)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => user?.scene.currentBattle.turnCommands[target?.getBattlerIndex() ?? BattlerIndex.ATTACKER]?.command === Command.POKEMON, 2),
|
||||
new Ability(Abilities.WATER_BUBBLE, 7)
|
||||
@ -5471,7 +5488,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.STEELWORKER, 7)
|
||||
.attr(MoveTypePowerBoostAbAttr, Type.STEEL),
|
||||
new Ability(Abilities.BERSERK, 7)
|
||||
.attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [Stat.SPATK], 1)
|
||||
.attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ Stat.SPATK ], 1)
|
||||
.condition(getSheerForceHitDisableAbCondition()),
|
||||
new Ability(Abilities.SLUSH_RUSH, 7)
|
||||
.attr(StatMultiplierAbAttr, Stat.SPD, 2)
|
||||
@ -5503,7 +5520,8 @@ export function initAbilities() {
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
// Add BattlerTagType.DISGUISE if the pokemon is in its disguised form
|
||||
.conditionalAttr(pokemon => pokemon.formIndex === 0, PostSummonAddBattlerTagAbAttr, BattlerTagType.DISGUISE, 0, false)
|
||||
.attr(FormBlockDamageAbAttr, (target, user, move) => !!target.getTag(BattlerTagType.DISGUISE) && target.getMoveEffectiveness(user, move) > 0, 0, BattlerTagType.DISGUISE,
|
||||
.attr(FormBlockDamageAbAttr,
|
||||
(target, user, move) => !!target.getTag(BattlerTagType.DISGUISE) && target.getMoveEffectiveness(user, move) > 0, 0, BattlerTagType.DISGUISE,
|
||||
(pokemon, abilityName) => i18next.t("abilityTriggers:disguiseAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }),
|
||||
(pokemon) => Utils.toDmgValue(pokemon.getMaxHp() / 8))
|
||||
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
||||
@ -5527,9 +5545,9 @@ export function initAbilities() {
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
new Ability(Abilities.CORROSION, 7) // TODO: Test Corrosion against Magic Bounce once it is implemented
|
||||
.attr(IgnoreTypeStatusEffectImmunityAbAttr, [StatusEffect.POISON, StatusEffect.TOXIC], [Type.STEEL, Type.POISON])
|
||||
.partial(),
|
||||
new Ability(Abilities.CORROSION, 7)
|
||||
.attr(IgnoreTypeStatusEffectImmunityAbAttr, [ StatusEffect.POISON, StatusEffect.TOXIC ], [ Type.STEEL, Type.POISON ])
|
||||
.edgeCase(), // Should interact correctly with magic coat/bounce (not yet implemented), fling with toxic orb (not implemented yet), and synchronize (not fully implemented yet)
|
||||
new Ability(Abilities.COMATOSE, 7)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
@ -5545,7 +5563,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.DANCER, 7)
|
||||
.attr(PostDancingMoveAbAttr),
|
||||
new Ability(Abilities.BATTERY, 7)
|
||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL], 1.3),
|
||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [ MoveCategory.SPECIAL ], 1.3),
|
||||
new Ability(Abilities.FLUFFY, 7)
|
||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5)
|
||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => user.getMoveType(move) === Type.FIRE, 2)
|
||||
@ -5665,17 +5683,18 @@ export function initAbilities() {
|
||||
.conditionalAttr(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW), PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0)
|
||||
// When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE
|
||||
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW)
|
||||
.attr(FormBlockDamageAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE,
|
||||
.attr(FormBlockDamageAbAttr,
|
||||
(target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE,
|
||||
(pokemon, abilityName) => i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }))
|
||||
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
||||
.bypassFaint()
|
||||
.ignorable(),
|
||||
new Ability(Abilities.POWER_SPOT, 8)
|
||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3),
|
||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [ MoveCategory.SPECIAL, MoveCategory.PHYSICAL ], 1.3),
|
||||
new Ability(Abilities.MIMICRY, 8)
|
||||
.unimplemented(),
|
||||
new Ability(Abilities.SCREEN_CLEANER, 8)
|
||||
.attr(PostSummonRemoveArenaTagAbAttr, [ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.REFLECT]),
|
||||
.attr(PostSummonRemoveArenaTagAbAttr, [ ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.REFLECT ]),
|
||||
new Ability(Abilities.STEELY_SPIRIT, 8)
|
||||
.attr(UserFieldMoveTypePowerBoostAbAttr, Type.STEEL),
|
||||
new Ability(Abilities.PERISH_BODY, 8)
|
||||
@ -5683,7 +5702,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.WANDERING_SPIRIT, 8)
|
||||
.attr(PostDefendAbilitySwapAbAttr)
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
.edgeCase(), // interacts incorrectly with rock head. It's meant to switch abilities before recoil would apply so that a pokemon with rock head would lose rock head first and still take the recoil
|
||||
new Ability(Abilities.GORILLA_TACTICS, 8)
|
||||
.attr(GorillaTacticsAbAttr),
|
||||
new Ability(Abilities.NEUTRALIZING_GAS, 8)
|
||||
@ -5692,7 +5711,7 @@ export function initAbilities() {
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonNeutralizingGas", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||
.partial(),
|
||||
.partial(), // A bunch of weird interactions with other abilities being suppressed then unsuppressed
|
||||
new Ability(Abilities.PASTEL_VEIL, 8)
|
||||
.attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||
@ -5758,7 +5777,7 @@ export function initAbilities() {
|
||||
.attr(PostSummonStatStageChangeOnArenaAbAttr, ArenaTagType.TAILWIND)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.GUARD_DOG, 9)
|
||||
.attr(PostIntimidateStatStageChangeAbAttr, [Stat.ATK], 1, true)
|
||||
.attr(PostIntimidateStatStageChangeAbAttr, [ Stat.ATK ], 1, true)
|
||||
.attr(ForceSwitchOutImmunityAbAttr)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.ROCKY_PAYLOAD, 9)
|
||||
@ -5797,7 +5816,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.GOOD_AS_GOLD, 9)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS)
|
||||
.ignorable()
|
||||
.partial(),
|
||||
.partial(), // Lots of weird interactions with moves and abilities such as negating status moves that target the field
|
||||
new Ability(Abilities.VESSEL_OF_RUIN, 9)
|
||||
.attr(FieldMultiplyStatAbAttr, Stat.SPATK, 0.75)
|
||||
.attr(PostSummonMessageAbAttr, (user) => i18next.t("abilityTriggers:postSummonVesselOfRuin", { pokemonNameWithAffix: getPokemonNameWithAffix(user), statName: i18next.t(getStatKey(Stat.SPATK)) }))
|
||||
@ -5830,7 +5849,7 @@ export function initAbilities() {
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.SLICING_MOVE), 1.5),
|
||||
new Ability(Abilities.SUPREME_OVERLORD, 9)
|
||||
.attr(VariableMovePowerBoostAbAttr, (user, target, move) => 1 + 0.1 * Math.min(user.isPlayer() ? user.scene.currentBattle.playerFaints : user.scene.currentBattle.enemyFaints, 5))
|
||||
.partial(),
|
||||
.partial(), // Counter resets every wave
|
||||
new Ability(Abilities.COSTAR, 9)
|
||||
.attr(PostSummonCopyAllyStatsAbAttr),
|
||||
new Ability(Abilities.TOXIC_DEBRIS, 9)
|
||||
@ -5847,7 +5866,7 @@ export function initAbilities() {
|
||||
.attr(PreventBypassSpeedChanceAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS)
|
||||
.attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS),
|
||||
new Ability(Abilities.MINDS_EYE, 9)
|
||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
|
||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ])
|
||||
.attr(ProtectStatAbAttr, Stat.ACC)
|
||||
.attr(IgnoreOpponentStatStagesAbAttr, [ Stat.EVA ])
|
||||
.ignorable(),
|
||||
@ -5863,25 +5882,25 @@ export function initAbilities() {
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(),
|
||||
.partial(), // Ogerpon tera interactions
|
||||
new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.SPDEF ], 1, true)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(),
|
||||
.partial(), // Ogerpon tera interactions
|
||||
new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.ATK ], 1, true)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(),
|
||||
.partial(), // Ogerpon tera interactions
|
||||
new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.DEF ], 1, true)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(),
|
||||
.partial(), // Ogerpon tera interactions
|
||||
new Ability(Abilities.TERA_SHIFT, 9)
|
||||
.attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
|
@ -4,7 +4,7 @@ import { Type } from "#app/data/type";
|
||||
import * as Utils from "#app/utils";
|
||||
import { MoveCategory, allMoves, MoveTarget, IncrementMovePriorityAttr, applyMoveAttrs } from "#app/data/move";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import Pokemon, { HitResult, PlayerPokemon, PokemonMove, EnemyPokemon } from "#app/field/pokemon";
|
||||
import Pokemon, { HitResult, PokemonMove } from "#app/field/pokemon";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { BlockNonDirectDamageAbAttr, ChangeMovePriorityAbAttr, ProtectStatAbAttr, applyAbAttrs } from "#app/data/ability";
|
||||
@ -19,6 +19,7 @@ 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";
|
||||
|
||||
export enum ArenaTagSide {
|
||||
BOTH,
|
||||
@ -27,20 +28,13 @@ export enum ArenaTagSide {
|
||||
}
|
||||
|
||||
export abstract class ArenaTag {
|
||||
public tagType: ArenaTagType;
|
||||
public turnCount: integer;
|
||||
public sourceMove?: Moves;
|
||||
public sourceId?: integer;
|
||||
public side: ArenaTagSide;
|
||||
|
||||
|
||||
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId?: integer, side: ArenaTagSide = ArenaTagSide.BOTH) {
|
||||
this.tagType = tagType;
|
||||
this.turnCount = turnCount;
|
||||
this.sourceMove = sourceMove;
|
||||
this.sourceId = sourceId;
|
||||
this.side = side;
|
||||
}
|
||||
constructor(
|
||||
public tagType: ArenaTagType,
|
||||
public turnCount: number,
|
||||
public sourceMove?: Moves,
|
||||
public sourceId?: number,
|
||||
public side: ArenaTagSide = ArenaTagSide.BOTH
|
||||
) {}
|
||||
|
||||
apply(arena: Arena, args: any[]): boolean {
|
||||
return true;
|
||||
@ -65,6 +59,44 @@ export abstract class ArenaTag {
|
||||
? allMoves[this.sourceMove].name
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* When given a arena tag or json representing one, load the data for it.
|
||||
* This is meant to be inherited from by any arena tag with custom attributes
|
||||
* @param {ArenaTag | any} source An arena tag
|
||||
*/
|
||||
loadTag(source : ArenaTag | any) : void {
|
||||
this.turnCount = source.turnCount;
|
||||
this.sourceMove = source.sourceMove;
|
||||
this.sourceId = source.sourceId;
|
||||
this.side = source.side;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that retrieves the source Pokemon
|
||||
* @param scene medium to retrieve the source Pokemon
|
||||
* @returns The source {@linkcode Pokemon} or `null` if none is found
|
||||
*/
|
||||
public getSourcePokemon(scene: BattleScene): Pokemon | null {
|
||||
return this.sourceId ? scene.getPokemonById(this.sourceId) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that retrieves the Pokemon affected
|
||||
* @param scene - medium to retrieve the involved Pokemon
|
||||
* @returns list of PlayerPokemon or EnemyPokemon on the field
|
||||
*/
|
||||
public getAffectedPokemon(scene: BattleScene): Pokemon[] {
|
||||
switch (this.side) {
|
||||
case ArenaTagSide.PLAYER:
|
||||
return scene.getPlayerField() ?? [];
|
||||
case ArenaTagSide.ENEMY:
|
||||
return scene.getEnemyField() ?? [];
|
||||
case ArenaTagSide.BOTH:
|
||||
default:
|
||||
return scene.getField(true) ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,7 +104,7 @@ export abstract class ArenaTag {
|
||||
* Prevents Pokémon on the opposing side from lowering the stats of the Pokémon in the Mist.
|
||||
*/
|
||||
export class MistTag extends ArenaTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side);
|
||||
}
|
||||
|
||||
@ -116,7 +148,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||
* @param side - The side (player or enemy) the tag affects.
|
||||
* @param weakenedCategories - The categories of moves that are weakened by this tag.
|
||||
*/
|
||||
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, weakenedCategories: MoveCategory[]) {
|
||||
constructor(tagType: ArenaTagType, turnCount: number, sourceMove: Moves, sourceId: number, side: ArenaTagSide, weakenedCategories: MoveCategory[]) {
|
||||
super(tagType, turnCount, sourceMove, sourceId, side);
|
||||
|
||||
this.weakenedCategories = weakenedCategories;
|
||||
@ -135,7 +167,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||
*/
|
||||
apply(arena: Arena, args: any[]): boolean {
|
||||
if (this.weakenedCategories.includes((args[0] as MoveCategory))) {
|
||||
(args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732/4096 : 0.5;
|
||||
(args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732 / 4096 : 0.5;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -147,8 +179,8 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||
* Used by {@linkcode Moves.REFLECT}
|
||||
*/
|
||||
class ReflectTag extends WeakenMoveScreenTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [MoveCategory.PHYSICAL]);
|
||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [ MoveCategory.PHYSICAL ]);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
@ -163,8 +195,8 @@ class ReflectTag extends WeakenMoveScreenTag {
|
||||
* Used by {@linkcode Moves.LIGHT_SCREEN}
|
||||
*/
|
||||
class LightScreenTag extends WeakenMoveScreenTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [MoveCategory.SPECIAL]);
|
||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [ MoveCategory.SPECIAL ]);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
@ -179,8 +211,8 @@ class LightScreenTag extends WeakenMoveScreenTag {
|
||||
* Used by {@linkcode Moves.AURORA_VEIL}
|
||||
*/
|
||||
class AuroraVeilTag extends WeakenMoveScreenTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL]);
|
||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [ MoveCategory.SPECIAL, MoveCategory.PHYSICAL ]);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
@ -202,7 +234,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
||||
/** Does this apply to all moves, including those that ignore other forms of protection? */
|
||||
protected ignoresBypass: boolean;
|
||||
|
||||
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, condition: ProtectConditionFunc, ignoresBypass: boolean = false) {
|
||||
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: number, side: ArenaTagSide, condition: ProtectConditionFunc, ignoresBypass: boolean = false) {
|
||||
super(tagType, 1, sourceMove, sourceId, side);
|
||||
|
||||
this.protectConditionFunc = condition;
|
||||
@ -264,7 +296,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
||||
*/
|
||||
const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||
const move = allMoves[moveId];
|
||||
const priority = new Utils.IntegerHolder(move.priority);
|
||||
const priority = new Utils.NumberHolder(move.priority);
|
||||
const effectPhase = arena.scene.getCurrentPhase();
|
||||
|
||||
if (effectPhase instanceof MoveEffectPhase) {
|
||||
@ -280,7 +312,7 @@ const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||
* Condition: The incoming move has increased priority.
|
||||
*/
|
||||
class QuickGuardTag extends ConditionalProtectTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.QUICK_GUARD, Moves.QUICK_GUARD, sourceId, side, QuickGuardConditionFunc);
|
||||
}
|
||||
}
|
||||
@ -311,7 +343,7 @@ const WideGuardConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean =
|
||||
* can be an ally or enemy.
|
||||
*/
|
||||
class WideGuardTag extends ConditionalProtectTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.WIDE_GUARD, Moves.WIDE_GUARD, sourceId, side, WideGuardConditionFunc);
|
||||
}
|
||||
}
|
||||
@ -333,7 +365,7 @@ const MatBlockConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean =>
|
||||
* Condition: The incoming move is a Physical or Special attack move.
|
||||
*/
|
||||
class MatBlockTag extends ConditionalProtectTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.MAT_BLOCK, Moves.MAT_BLOCK, sourceId, side, MatBlockConditionFunc);
|
||||
}
|
||||
|
||||
@ -371,7 +403,7 @@ const CraftyShieldConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||
* not target all Pokemon or sides of the field.
|
||||
*/
|
||||
class CraftyShieldTag extends ConditionalProtectTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.CRAFTY_SHIELD, Moves.CRAFTY_SHIELD, sourceId, side, CraftyShieldConditionFunc, true);
|
||||
}
|
||||
}
|
||||
@ -383,12 +415,12 @@ class CraftyShieldTag extends ConditionalProtectTag {
|
||||
export class NoCritTag extends ArenaTag {
|
||||
/**
|
||||
* Constructor method for the NoCritTag class
|
||||
* @param turnCount `integer` the number of turns this effect lasts
|
||||
* @param turnCount `number` the number of turns this effect lasts
|
||||
* @param sourceMove {@linkcode Moves} the move that created this effect
|
||||
* @param sourceId `integer` the ID of the {@linkcode Pokemon} that created this effect
|
||||
* @param sourceId `number` the ID of the {@linkcode Pokemon} that created this effect
|
||||
* @param side {@linkcode ArenaTagSide} the side to which this effect belongs
|
||||
*/
|
||||
constructor(turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(turnCount: number, sourceMove: Moves, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.NO_CRIT, turnCount, sourceMove, sourceId, side);
|
||||
}
|
||||
|
||||
@ -418,7 +450,7 @@ class WishTag extends ArenaTag {
|
||||
private triggerMessage: string;
|
||||
private healHp: number;
|
||||
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.WISH, turnCount, Moves.WISH, sourceId, side);
|
||||
}
|
||||
|
||||
@ -459,7 +491,7 @@ export class WeakenMoveTypeTag extends ArenaTag {
|
||||
* @param sourceMove - The move that created the tag.
|
||||
* @param sourceId - The ID of the source of the tag.
|
||||
*/
|
||||
constructor(tagType: ArenaTagType, turnCount: integer, type: Type, sourceMove: Moves, sourceId: integer) {
|
||||
constructor(tagType: ArenaTagType, turnCount: number, type: Type, sourceMove: Moves, sourceId: number) {
|
||||
super(tagType, turnCount, sourceMove, sourceId);
|
||||
|
||||
this.weakenedType = type;
|
||||
@ -480,7 +512,7 @@ export class WeakenMoveTypeTag extends ArenaTag {
|
||||
* Weakens Electric type moves for a set amount of turns, usually 5.
|
||||
*/
|
||||
class MudSportTag extends WeakenMoveTypeTag {
|
||||
constructor(turnCount: integer, sourceId: integer) {
|
||||
constructor(turnCount: number, sourceId: number) {
|
||||
super(ArenaTagType.MUD_SPORT, turnCount, Type.ELECTRIC, Moves.MUD_SPORT, sourceId);
|
||||
}
|
||||
|
||||
@ -498,7 +530,7 @@ class MudSportTag extends WeakenMoveTypeTag {
|
||||
* Weakens Fire type moves for a set amount of turns, usually 5.
|
||||
*/
|
||||
class WaterSportTag extends WeakenMoveTypeTag {
|
||||
constructor(turnCount: integer, sourceId: integer) {
|
||||
constructor(turnCount: number, sourceId: number) {
|
||||
super(ArenaTagType.WATER_SPORT, turnCount, Type.FIRE, Moves.WATER_SPORT, sourceId);
|
||||
}
|
||||
|
||||
@ -512,15 +544,16 @@ class WaterSportTag extends WeakenMoveTypeTag {
|
||||
}
|
||||
|
||||
/**
|
||||
* Arena Tag class for the secondary effect of {@link https://bulbapedia.bulbagarden.net/wiki/Plasma_Fists_(move) | Plasma Fists}.
|
||||
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Ion_Deluge_(move) | Ion Deluge}
|
||||
* and the secondary effect of {@link https://bulbapedia.bulbagarden.net/wiki/Plasma_Fists_(move) | Plasma Fists}.
|
||||
* Converts Normal-type moves to Electric type for the rest of the turn.
|
||||
*/
|
||||
export class PlasmaFistsTag extends ArenaTag {
|
||||
constructor() {
|
||||
super(ArenaTagType.PLASMA_FISTS, 1, Moves.PLASMA_FISTS);
|
||||
export class IonDelugeTag extends ArenaTag {
|
||||
constructor(sourceMove?: Moves) {
|
||||
super(ArenaTagType.ION_DELUGE, 1, sourceMove);
|
||||
}
|
||||
|
||||
/** Queues Plasma Fists' on-add message */
|
||||
/** Queues an on-add message */
|
||||
onAdd(arena: Arena): void {
|
||||
arena.scene.queueMessage(i18next.t("arenaTag:plasmaFistsOnAdd"));
|
||||
}
|
||||
@ -548,8 +581,8 @@ export class PlasmaFistsTag extends ArenaTag {
|
||||
* Abstract class to implement arena traps.
|
||||
*/
|
||||
export class ArenaTrapTag extends ArenaTag {
|
||||
public layers: integer;
|
||||
public maxLayers: integer;
|
||||
public layers: number;
|
||||
public maxLayers: number;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the ArenaTrapTag class.
|
||||
@ -560,7 +593,7 @@ export class ArenaTrapTag extends ArenaTag {
|
||||
* @param side - The side (player or enemy) the tag affects.
|
||||
* @param maxLayers - The maximum amount of layers this tag can have.
|
||||
*/
|
||||
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, maxLayers: integer) {
|
||||
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: number, side: ArenaTagSide, maxLayers: number) {
|
||||
super(tagType, 0, sourceMove, sourceId, side);
|
||||
|
||||
this.layers = 1;
|
||||
@ -591,6 +624,12 @@ export class ArenaTrapTag extends ArenaTag {
|
||||
getMatchupScoreMultiplier(pokemon: Pokemon): number {
|
||||
return pokemon.isGrounded() ? 1 : Phaser.Math.Linear(0, 1 / Math.pow(2, this.layers), Math.min(pokemon.getHpRatio(), 0.5) * 2);
|
||||
}
|
||||
|
||||
loadTag(source: any): void {
|
||||
super.loadTag(source);
|
||||
this.layers = source.layers;
|
||||
this.maxLayers = source.maxLayers;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -599,7 +638,7 @@ export class ArenaTrapTag extends ArenaTag {
|
||||
* in damage for 1, 2, or 3 layers of Spikes respectively if they are summoned into this trap.
|
||||
*/
|
||||
class SpikesTag extends ArenaTrapTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3);
|
||||
}
|
||||
|
||||
@ -643,7 +682,7 @@ class SpikesTag extends ArenaTrapTag {
|
||||
class ToxicSpikesTag extends ArenaTrapTag {
|
||||
private neutralized: boolean;
|
||||
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.TOXIC_SPIKES, Moves.TOXIC_SPIKES, sourceId, side, 2);
|
||||
this.neutralized = false;
|
||||
}
|
||||
@ -701,7 +740,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
||||
class DelayedAttackTag extends ArenaTag {
|
||||
public targetIndex: BattlerIndex;
|
||||
|
||||
constructor(tagType: ArenaTagType, sourceMove: Moves | undefined, sourceId: integer, targetIndex: BattlerIndex) {
|
||||
constructor(tagType: ArenaTagType, sourceMove: Moves | undefined, sourceId: number, targetIndex: BattlerIndex) {
|
||||
super(tagType, 3, sourceMove, sourceId);
|
||||
|
||||
this.targetIndex = targetIndex;
|
||||
@ -726,7 +765,7 @@ class DelayedAttackTag extends ArenaTag {
|
||||
* who is summoned into the trap, based on the Rock type's type effectiveness.
|
||||
*/
|
||||
class StealthRockTag extends ArenaTrapTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1);
|
||||
}
|
||||
|
||||
@ -802,7 +841,7 @@ class StealthRockTag extends ArenaTrapTag {
|
||||
* to any Pokémon who is summoned into this trap.
|
||||
*/
|
||||
class StickyWebTag extends ArenaTrapTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1);
|
||||
}
|
||||
|
||||
@ -836,7 +875,7 @@ class StickyWebTag extends ArenaTrapTag {
|
||||
* also reversing the turn order for all Pokémon on the field as well.
|
||||
*/
|
||||
export class TrickRoomTag extends ArenaTag {
|
||||
constructor(turnCount: integer, sourceId: integer) {
|
||||
constructor(turnCount: number, sourceId: number) {
|
||||
super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId);
|
||||
}
|
||||
|
||||
@ -864,7 +903,7 @@ export class TrickRoomTag extends ArenaTag {
|
||||
* {@linkcode Abilities.LEVITATE} for the duration of the arena tag, usually 5 turns.
|
||||
*/
|
||||
export class GravityTag extends ArenaTag {
|
||||
constructor(turnCount: integer) {
|
||||
constructor(turnCount: number) {
|
||||
super(ArenaTagType.GRAVITY, turnCount, Moves.GRAVITY);
|
||||
}
|
||||
|
||||
@ -872,7 +911,8 @@ export class GravityTag extends ArenaTag {
|
||||
arena.scene.queueMessage(i18next.t("arenaTag:gravityOnAdd"));
|
||||
arena.scene.getField(true).forEach((pokemon) => {
|
||||
if (pokemon !== null) {
|
||||
pokemon.removeTag(BattlerTagType.MAGNET_RISEN);
|
||||
pokemon.removeTag(BattlerTagType.FLOATING);
|
||||
pokemon.removeTag(BattlerTagType.TELEKINESIS);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -888,7 +928,7 @@ export class GravityTag extends ArenaTag {
|
||||
* Applies this arena tag for 4 turns (including the turn the move was used).
|
||||
*/
|
||||
class TailwindTag extends ArenaTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side);
|
||||
}
|
||||
|
||||
@ -926,7 +966,7 @@ class TailwindTag extends ArenaTag {
|
||||
* Doubles the prize money from trainers and money moves like {@linkcode Moves.PAY_DAY} and {@linkcode Moves.MAKE_IT_RAIN}.
|
||||
*/
|
||||
class HappyHourTag extends ArenaTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.HAPPY_HOUR, turnCount, Moves.HAPPY_HOUR, sourceId, side);
|
||||
}
|
||||
|
||||
@ -940,7 +980,7 @@ class HappyHourTag extends ArenaTag {
|
||||
}
|
||||
|
||||
class SafeguardTag extends ArenaTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.SAFEGUARD, turnCount, Moves.SAFEGUARD, sourceId, side);
|
||||
}
|
||||
|
||||
@ -953,42 +993,35 @@ class SafeguardTag extends ArenaTag {
|
||||
}
|
||||
}
|
||||
|
||||
class NoneTag extends ArenaTag {
|
||||
constructor() {
|
||||
super(ArenaTagType.NONE, 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This arena tag facilitates the application of the move Imprison
|
||||
* Imprison remains in effect as long as the source Pokemon is active and present on the field.
|
||||
* Imprison will apply to any opposing Pokemon that switch onto the field as well.
|
||||
*/
|
||||
class ImprisonTag extends ArenaTrapTag {
|
||||
private source: Pokemon;
|
||||
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.IMPRISON, Moves.IMPRISON, sourceId, side, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that retrieves the Pokemon affected
|
||||
* @param {BattleScene} scene medium to retrieve the involved Pokemon
|
||||
* @returns list of PlayerPokemon or EnemyPokemon on the field
|
||||
*/
|
||||
private retrieveField(scene: BattleScene): PlayerPokemon[] | EnemyPokemon[] {
|
||||
if (!this.source.isPlayer()) {
|
||||
return scene.getPlayerField() ?? [];
|
||||
}
|
||||
return scene.getEnemyField() ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* This function applies the effects of Imprison to the opposing Pokemon already present on the field.
|
||||
* @param arena
|
||||
*/
|
||||
override onAdd({ scene }: Arena) {
|
||||
this.source = scene.getPokemonById(this.sourceId!)!;
|
||||
if (this.source) {
|
||||
const party = this.retrieveField(scene);
|
||||
party?.forEach((p: PlayerPokemon | EnemyPokemon ) => {
|
||||
p.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
||||
const source = this.getSourcePokemon(scene);
|
||||
if (source) {
|
||||
const party = this.getAffectedPokemon(scene);
|
||||
party?.forEach((p: Pokemon ) => {
|
||||
if (p.isAllowedInBattle()) {
|
||||
p.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
||||
}
|
||||
});
|
||||
scene.queueMessage(i18next.t("battlerTags:imprisonOnAdd", {pokemonNameWithAffix: getPokemonNameWithAffix(this.source)}));
|
||||
scene.queueMessage(i18next.t("battlerTags:imprisonOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(source) }));
|
||||
}
|
||||
}
|
||||
|
||||
@ -997,8 +1030,9 @@ class ImprisonTag extends ArenaTrapTag {
|
||||
* @param _arena
|
||||
* @returns `true` if the source of the tag is still active on the field | `false` if not
|
||||
*/
|
||||
override lapse(_arena: Arena): boolean {
|
||||
return this.source.isActive(true);
|
||||
override lapse({ scene }: Arena): boolean {
|
||||
const source = this.getSourcePokemon(scene);
|
||||
return source ? source.isActive(true) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1007,7 +1041,8 @@ class ImprisonTag extends ArenaTrapTag {
|
||||
* @returns `true`
|
||||
*/
|
||||
override activateTrap(pokemon: Pokemon): boolean {
|
||||
if (this.source.isActive(true)) {
|
||||
const source = this.getSourcePokemon(pokemon.scene);
|
||||
if (source && source.isActive(true) && pokemon.isAllowedInBattle()) {
|
||||
pokemon.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
||||
}
|
||||
return true;
|
||||
@ -1018,14 +1053,90 @@ class ImprisonTag extends ArenaTrapTag {
|
||||
* @param arena
|
||||
*/
|
||||
override onRemove({ scene }: Arena): void {
|
||||
const party = this.retrieveField(scene);
|
||||
party?.forEach((p: PlayerPokemon | EnemyPokemon) => {
|
||||
const party = this.getAffectedPokemon(scene);
|
||||
party?.forEach((p: Pokemon) => {
|
||||
p.removeTag(BattlerTagType.IMPRISON);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag | null {
|
||||
/**
|
||||
* Arena Tag implementing the "sea of fire" effect from the combination
|
||||
* of {@link https://bulbapedia.bulbagarden.net/wiki/Fire_Pledge_(move) | Fire Pledge}
|
||||
* and {@link https://bulbapedia.bulbagarden.net/wiki/Grass_Pledge_(move) | Grass Pledge}.
|
||||
* Damages all non-Fire-type Pokemon on the given side of the field at the end
|
||||
* of each turn for 4 turns.
|
||||
*/
|
||||
class FireGrassPledgeTag extends ArenaTag {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.FIRE_GRASS_PLEDGE, 4, Moves.FIRE_PLEDGE, sourceId, side);
|
||||
}
|
||||
|
||||
override onAdd(arena: Arena): void {
|
||||
// "A sea of fire enveloped your/the opposing team!"
|
||||
arena.scene.queueMessage(i18next.t(`arenaTag:fireGrassPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`));
|
||||
}
|
||||
|
||||
override lapse(arena: Arena): boolean {
|
||||
const field: Pokemon[] = (this.side === ArenaTagSide.PLAYER)
|
||||
? arena.scene.getPlayerField()
|
||||
: arena.scene.getEnemyField();
|
||||
|
||||
field.filter(pokemon => !pokemon.isOfType(Type.FIRE)).forEach(pokemon => {
|
||||
// "{pokemonNameWithAffix} was hurt by the sea of fire!"
|
||||
pokemon.scene.queueMessage(i18next.t("arenaTag:fireGrassPledgeLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
// TODO: Replace this with a proper animation
|
||||
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.MAGMA_STORM));
|
||||
pokemon.damageAndUpdate(Utils.toDmgValue(pokemon.getMaxHp() / 8));
|
||||
});
|
||||
|
||||
return super.lapse(arena);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Arena Tag implementing the "rainbow" effect from the combination
|
||||
* of {@link https://bulbapedia.bulbagarden.net/wiki/Water_Pledge_(move) | Water Pledge}
|
||||
* and {@link https://bulbapedia.bulbagarden.net/wiki/Fire_Pledge_(move) | Fire Pledge}.
|
||||
* Doubles the secondary effect chance of moves from Pokemon on the
|
||||
* given side of the field for 4 turns.
|
||||
*/
|
||||
class WaterFirePledgeTag extends ArenaTag {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.WATER_FIRE_PLEDGE, 4, Moves.WATER_PLEDGE, sourceId, side);
|
||||
}
|
||||
|
||||
override onAdd(arena: Arena): void {
|
||||
// "A rainbow appeared in the sky on your/the opposing team's side!"
|
||||
arena.scene.queueMessage(i18next.t(`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`));
|
||||
}
|
||||
|
||||
override apply(arena: Arena, args: any[]): boolean {
|
||||
const moveChance = args[0] as Utils.NumberHolder;
|
||||
moveChance.value *= 2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Arena Tag implementing the "swamp" effect from the combination
|
||||
* of {@link https://bulbapedia.bulbagarden.net/wiki/Grass_Pledge_(move) | Grass Pledge}
|
||||
* and {@link https://bulbapedia.bulbagarden.net/wiki/Water_Pledge_(move) | Water Pledge}.
|
||||
* Quarters the Speed of Pokemon on the given side of the field for 4 turns.
|
||||
*/
|
||||
class GrassWaterPledgeTag extends ArenaTag {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.GRASS_WATER_PLEDGE, 4, Moves.GRASS_PLEDGE, sourceId, side);
|
||||
}
|
||||
|
||||
override onAdd(arena: Arena): void {
|
||||
// "A swamp enveloped your/the opposing team!"
|
||||
arena.scene.queueMessage(i18next.t(`arenaTag:grassWaterPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: swap `sourceMove` and `sourceId` and make `sourceMove` an optional parameter
|
||||
export function getArenaTag(tagType: ArenaTagType, turnCount: number, sourceMove: Moves | undefined, sourceId: number, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag | null {
|
||||
switch (tagType) {
|
||||
case ArenaTagType.MIST:
|
||||
return new MistTag(turnCount, sourceId, side);
|
||||
@ -1043,8 +1154,8 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
|
||||
return new MudSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.WATER_SPORT:
|
||||
return new WaterSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.PLASMA_FISTS:
|
||||
return new PlasmaFistsTag();
|
||||
case ArenaTagType.ION_DELUGE:
|
||||
return new IonDelugeTag(sourceMove);
|
||||
case ArenaTagType.SPIKES:
|
||||
return new SpikesTag(sourceId, side);
|
||||
case ArenaTagType.TOXIC_SPIKES:
|
||||
@ -1076,7 +1187,26 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
|
||||
return new SafeguardTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.IMPRISON:
|
||||
return new ImprisonTag(sourceId, side);
|
||||
case ArenaTagType.FIRE_GRASS_PLEDGE:
|
||||
return new FireGrassPledgeTag(sourceId, side);
|
||||
case ArenaTagType.WATER_FIRE_PLEDGE:
|
||||
return new WaterFirePledgeTag(sourceId, side);
|
||||
case ArenaTagType.GRASS_WATER_PLEDGE:
|
||||
return new GrassWaterPledgeTag(sourceId, side);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When given a battler tag or json representing one, creates an actual ArenaTag object with the same data.
|
||||
* @param {ArenaTag | any} source An arena tag
|
||||
* @return {ArenaTag} The valid arena tag
|
||||
*/
|
||||
export function loadArenaTag(source: ArenaTag | any): ArenaTag {
|
||||
const tag = getArenaTag(source.tagType, source.turnCount, source.sourceMove, source.sourceId, source.targetIndex, source.side)
|
||||
?? new NoneTag();
|
||||
tag.loadTag(source);
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
603
src/data/balance/species-egg-tiers.ts
Normal file
@ -0,0 +1,603 @@
|
||||
import { Species } from "#enums/species";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
|
||||
/**
|
||||
* Map of all starters and their respective {@linkcode EggTier}, which determines the type of egg the starter hatches from.
|
||||
*/
|
||||
export const speciesEggTiers = {
|
||||
[Species.BULBASAUR]: EggTier.COMMON,
|
||||
[Species.CHARMANDER]: EggTier.COMMON,
|
||||
[Species.SQUIRTLE]: EggTier.COMMON,
|
||||
[Species.CATERPIE]: EggTier.COMMON,
|
||||
[Species.WEEDLE]: EggTier.COMMON,
|
||||
[Species.PIDGEY]: EggTier.COMMON,
|
||||
[Species.RATTATA]: EggTier.COMMON,
|
||||
[Species.SPEAROW]: EggTier.COMMON,
|
||||
[Species.EKANS]: EggTier.COMMON,
|
||||
[Species.PIKACHU]: EggTier.COMMON,
|
||||
[Species.SANDSHREW]: EggTier.COMMON,
|
||||
[Species.NIDORAN_F]: EggTier.COMMON,
|
||||
[Species.NIDORAN_M]: EggTier.COMMON,
|
||||
[Species.CLEFAIRY]: EggTier.COMMON,
|
||||
[Species.VULPIX]: EggTier.COMMON,
|
||||
[Species.JIGGLYPUFF]: EggTier.COMMON,
|
||||
[Species.ZUBAT]: EggTier.COMMON,
|
||||
[Species.ODDISH]: EggTier.COMMON,
|
||||
[Species.PARAS]: EggTier.COMMON,
|
||||
[Species.VENONAT]: EggTier.COMMON,
|
||||
[Species.DIGLETT]: EggTier.COMMON,
|
||||
[Species.MEOWTH]: EggTier.COMMON,
|
||||
[Species.PSYDUCK]: EggTier.COMMON,
|
||||
[Species.MANKEY]: EggTier.RARE,
|
||||
[Species.GROWLITHE]: EggTier.RARE,
|
||||
[Species.POLIWAG]: EggTier.COMMON,
|
||||
[Species.ABRA]: EggTier.RARE,
|
||||
[Species.MACHOP]: EggTier.COMMON,
|
||||
[Species.BELLSPROUT]: EggTier.COMMON,
|
||||
[Species.TENTACOOL]: EggTier.COMMON,
|
||||
[Species.GEODUDE]: EggTier.COMMON,
|
||||
[Species.PONYTA]: EggTier.COMMON,
|
||||
[Species.SLOWPOKE]: EggTier.COMMON,
|
||||
[Species.MAGNEMITE]: EggTier.RARE,
|
||||
[Species.FARFETCHD]: EggTier.COMMON,
|
||||
[Species.DODUO]: EggTier.COMMON,
|
||||
[Species.SEEL]: EggTier.COMMON,
|
||||
[Species.GRIMER]: EggTier.COMMON,
|
||||
[Species.SHELLDER]: EggTier.RARE,
|
||||
[Species.GASTLY]: EggTier.RARE,
|
||||
[Species.ONIX]: EggTier.COMMON,
|
||||
[Species.DROWZEE]: EggTier.COMMON,
|
||||
[Species.KRABBY]: EggTier.COMMON,
|
||||
[Species.VOLTORB]: EggTier.COMMON,
|
||||
[Species.EXEGGCUTE]: EggTier.COMMON,
|
||||
[Species.CUBONE]: EggTier.COMMON,
|
||||
[Species.HITMONLEE]: EggTier.RARE,
|
||||
[Species.HITMONCHAN]: EggTier.RARE,
|
||||
[Species.LICKITUNG]: EggTier.COMMON,
|
||||
[Species.KOFFING]: EggTier.COMMON,
|
||||
[Species.RHYHORN]: EggTier.COMMON,
|
||||
[Species.CHANSEY]: EggTier.COMMON,
|
||||
[Species.TANGELA]: EggTier.COMMON,
|
||||
[Species.KANGASKHAN]: EggTier.RARE,
|
||||
[Species.HORSEA]: EggTier.COMMON,
|
||||
[Species.GOLDEEN]: EggTier.COMMON,
|
||||
[Species.STARYU]: EggTier.COMMON,
|
||||
[Species.MR_MIME]: EggTier.COMMON,
|
||||
[Species.SCYTHER]: EggTier.RARE,
|
||||
[Species.JYNX]: EggTier.RARE,
|
||||
[Species.ELECTABUZZ]: EggTier.RARE,
|
||||
[Species.MAGMAR]: EggTier.RARE,
|
||||
[Species.PINSIR]: EggTier.RARE,
|
||||
[Species.TAUROS]: EggTier.RARE,
|
||||
[Species.MAGIKARP]: EggTier.RARE,
|
||||
[Species.LAPRAS]: EggTier.RARE,
|
||||
[Species.DITTO]: EggTier.COMMON,
|
||||
[Species.EEVEE]: EggTier.COMMON,
|
||||
[Species.PORYGON]: EggTier.RARE,
|
||||
[Species.OMANYTE]: EggTier.COMMON,
|
||||
[Species.KABUTO]: EggTier.COMMON,
|
||||
[Species.AERODACTYL]: EggTier.RARE,
|
||||
[Species.SNORLAX]: EggTier.RARE,
|
||||
[Species.ARTICUNO]: EggTier.EPIC,
|
||||
[Species.ZAPDOS]: EggTier.EPIC,
|
||||
[Species.MOLTRES]: EggTier.EPIC,
|
||||
[Species.DRATINI]: EggTier.RARE,
|
||||
[Species.MEWTWO]: EggTier.LEGENDARY,
|
||||
[Species.MEW]: EggTier.EPIC,
|
||||
|
||||
[Species.CHIKORITA]: EggTier.COMMON,
|
||||
[Species.CYNDAQUIL]: EggTier.COMMON,
|
||||
[Species.TOTODILE]: EggTier.COMMON,
|
||||
[Species.SENTRET]: EggTier.COMMON,
|
||||
[Species.HOOTHOOT]: EggTier.COMMON,
|
||||
[Species.LEDYBA]: EggTier.COMMON,
|
||||
[Species.SPINARAK]: EggTier.COMMON,
|
||||
[Species.CHINCHOU]: EggTier.COMMON,
|
||||
[Species.PICHU]: EggTier.COMMON,
|
||||
[Species.CLEFFA]: EggTier.COMMON,
|
||||
[Species.IGGLYBUFF]: EggTier.COMMON,
|
||||
[Species.TOGEPI]: EggTier.COMMON,
|
||||
[Species.NATU]: EggTier.COMMON,
|
||||
[Species.MAREEP]: EggTier.COMMON,
|
||||
[Species.MARILL]: EggTier.RARE,
|
||||
[Species.SUDOWOODO]: EggTier.COMMON,
|
||||
[Species.HOPPIP]: EggTier.COMMON,
|
||||
[Species.AIPOM]: EggTier.COMMON,
|
||||
[Species.SUNKERN]: EggTier.COMMON,
|
||||
[Species.YANMA]: EggTier.COMMON,
|
||||
[Species.WOOPER]: EggTier.COMMON,
|
||||
[Species.MURKROW]: EggTier.COMMON,
|
||||
[Species.MISDREAVUS]: EggTier.COMMON,
|
||||
[Species.UNOWN]: EggTier.COMMON,
|
||||
[Species.WOBBUFFET]: EggTier.COMMON,
|
||||
[Species.GIRAFARIG]: EggTier.COMMON,
|
||||
[Species.PINECO]: EggTier.COMMON,
|
||||
[Species.DUNSPARCE]: EggTier.COMMON,
|
||||
[Species.GLIGAR]: EggTier.COMMON,
|
||||
[Species.SNUBBULL]: EggTier.COMMON,
|
||||
[Species.QWILFISH]: EggTier.COMMON,
|
||||
[Species.SHUCKLE]: EggTier.COMMON,
|
||||
[Species.HERACROSS]: EggTier.RARE,
|
||||
[Species.SNEASEL]: EggTier.RARE,
|
||||
[Species.TEDDIURSA]: EggTier.RARE,
|
||||
[Species.SLUGMA]: EggTier.COMMON,
|
||||
[Species.SWINUB]: EggTier.COMMON,
|
||||
[Species.CORSOLA]: EggTier.COMMON,
|
||||
[Species.REMORAID]: EggTier.COMMON,
|
||||
[Species.DELIBIRD]: EggTier.COMMON,
|
||||
[Species.MANTINE]: EggTier.COMMON,
|
||||
[Species.SKARMORY]: EggTier.RARE,
|
||||
[Species.HOUNDOUR]: EggTier.COMMON,
|
||||
[Species.PHANPY]: EggTier.COMMON,
|
||||
[Species.STANTLER]: EggTier.COMMON,
|
||||
[Species.SMEARGLE]: EggTier.COMMON,
|
||||
[Species.TYROGUE]: EggTier.COMMON,
|
||||
[Species.SMOOCHUM]: EggTier.COMMON,
|
||||
[Species.ELEKID]: EggTier.COMMON,
|
||||
[Species.MAGBY]: EggTier.COMMON,
|
||||
[Species.MILTANK]: EggTier.RARE,
|
||||
[Species.RAIKOU]: EggTier.EPIC,
|
||||
[Species.ENTEI]: EggTier.EPIC,
|
||||
[Species.SUICUNE]: EggTier.EPIC,
|
||||
[Species.LARVITAR]: EggTier.RARE,
|
||||
[Species.LUGIA]: EggTier.LEGENDARY,
|
||||
[Species.HO_OH]: EggTier.LEGENDARY,
|
||||
[Species.CELEBI]: EggTier.EPIC,
|
||||
|
||||
[Species.TREECKO]: EggTier.COMMON,
|
||||
[Species.TORCHIC]: EggTier.RARE,
|
||||
[Species.MUDKIP]: EggTier.COMMON,
|
||||
[Species.POOCHYENA]: EggTier.COMMON,
|
||||
[Species.ZIGZAGOON]: EggTier.COMMON,
|
||||
[Species.WURMPLE]: EggTier.COMMON,
|
||||
[Species.LOTAD]: EggTier.COMMON,
|
||||
[Species.SEEDOT]: EggTier.COMMON,
|
||||
[Species.TAILLOW]: EggTier.COMMON,
|
||||
[Species.WINGULL]: EggTier.COMMON,
|
||||
[Species.RALTS]: EggTier.COMMON,
|
||||
[Species.SURSKIT]: EggTier.COMMON,
|
||||
[Species.SHROOMISH]: EggTier.COMMON,
|
||||
[Species.SLAKOTH]: EggTier.RARE,
|
||||
[Species.NINCADA]: EggTier.RARE,
|
||||
[Species.WHISMUR]: EggTier.COMMON,
|
||||
[Species.MAKUHITA]: EggTier.COMMON,
|
||||
[Species.AZURILL]: EggTier.RARE,
|
||||
[Species.NOSEPASS]: EggTier.COMMON,
|
||||
[Species.SKITTY]: EggTier.COMMON,
|
||||
[Species.SABLEYE]: EggTier.COMMON,
|
||||
[Species.MAWILE]: EggTier.COMMON,
|
||||
[Species.ARON]: EggTier.COMMON,
|
||||
[Species.MEDITITE]: EggTier.COMMON,
|
||||
[Species.ELECTRIKE]: EggTier.COMMON,
|
||||
[Species.PLUSLE]: EggTier.COMMON,
|
||||
[Species.MINUN]: EggTier.COMMON,
|
||||
[Species.VOLBEAT]: EggTier.COMMON,
|
||||
[Species.ILLUMISE]: EggTier.COMMON,
|
||||
[Species.ROSELIA]: EggTier.COMMON,
|
||||
[Species.GULPIN]: EggTier.COMMON,
|
||||
[Species.CARVANHA]: EggTier.COMMON,
|
||||
[Species.WAILMER]: EggTier.COMMON,
|
||||
[Species.NUMEL]: EggTier.COMMON,
|
||||
[Species.TORKOAL]: EggTier.COMMON,
|
||||
[Species.SPOINK]: EggTier.COMMON,
|
||||
[Species.SPINDA]: EggTier.COMMON,
|
||||
[Species.TRAPINCH]: EggTier.COMMON,
|
||||
[Species.CACNEA]: EggTier.COMMON,
|
||||
[Species.SWABLU]: EggTier.COMMON,
|
||||
[Species.ZANGOOSE]: EggTier.RARE,
|
||||
[Species.SEVIPER]: EggTier.COMMON,
|
||||
[Species.LUNATONE]: EggTier.COMMON,
|
||||
[Species.SOLROCK]: EggTier.COMMON,
|
||||
[Species.BARBOACH]: EggTier.COMMON,
|
||||
[Species.CORPHISH]: EggTier.COMMON,
|
||||
[Species.BALTOY]: EggTier.COMMON,
|
||||
[Species.LILEEP]: EggTier.COMMON,
|
||||
[Species.ANORITH]: EggTier.COMMON,
|
||||
[Species.FEEBAS]: EggTier.RARE,
|
||||
[Species.CASTFORM]: EggTier.COMMON,
|
||||
[Species.KECLEON]: EggTier.COMMON,
|
||||
[Species.SHUPPET]: EggTier.COMMON,
|
||||
[Species.DUSKULL]: EggTier.COMMON,
|
||||
[Species.TROPIUS]: EggTier.COMMON,
|
||||
[Species.CHIMECHO]: EggTier.COMMON,
|
||||
[Species.ABSOL]: EggTier.RARE,
|
||||
[Species.WYNAUT]: EggTier.COMMON,
|
||||
[Species.SNORUNT]: EggTier.COMMON,
|
||||
[Species.SPHEAL]: EggTier.COMMON,
|
||||
[Species.CLAMPERL]: EggTier.COMMON,
|
||||
[Species.RELICANTH]: EggTier.COMMON,
|
||||
[Species.LUVDISC]: EggTier.COMMON,
|
||||
[Species.BAGON]: EggTier.RARE,
|
||||
[Species.BELDUM]: EggTier.RARE,
|
||||
[Species.REGIROCK]: EggTier.EPIC,
|
||||
[Species.REGICE]: EggTier.EPIC,
|
||||
[Species.REGISTEEL]: EggTier.EPIC,
|
||||
[Species.LATIAS]: EggTier.EPIC,
|
||||
[Species.LATIOS]: EggTier.EPIC,
|
||||
[Species.KYOGRE]: EggTier.LEGENDARY,
|
||||
[Species.GROUDON]: EggTier.LEGENDARY,
|
||||
[Species.RAYQUAZA]: EggTier.LEGENDARY,
|
||||
[Species.JIRACHI]: EggTier.EPIC,
|
||||
[Species.DEOXYS]: EggTier.EPIC,
|
||||
|
||||
[Species.TURTWIG]: EggTier.COMMON,
|
||||
[Species.CHIMCHAR]: EggTier.COMMON,
|
||||
[Species.PIPLUP]: EggTier.COMMON,
|
||||
[Species.STARLY]: EggTier.COMMON,
|
||||
[Species.BIDOOF]: EggTier.COMMON,
|
||||
[Species.KRICKETOT]: EggTier.COMMON,
|
||||
[Species.SHINX]: EggTier.COMMON,
|
||||
[Species.BUDEW]: EggTier.COMMON,
|
||||
[Species.CRANIDOS]: EggTier.COMMON,
|
||||
[Species.SHIELDON]: EggTier.COMMON,
|
||||
[Species.BURMY]: EggTier.COMMON,
|
||||
[Species.COMBEE]: EggTier.COMMON,
|
||||
[Species.PACHIRISU]: EggTier.COMMON,
|
||||
[Species.BUIZEL]: EggTier.COMMON,
|
||||
[Species.CHERUBI]: EggTier.COMMON,
|
||||
[Species.SHELLOS]: EggTier.COMMON,
|
||||
[Species.DRIFLOON]: EggTier.COMMON,
|
||||
[Species.BUNEARY]: EggTier.COMMON,
|
||||
[Species.GLAMEOW]: EggTier.COMMON,
|
||||
[Species.CHINGLING]: EggTier.COMMON,
|
||||
[Species.STUNKY]: EggTier.COMMON,
|
||||
[Species.BRONZOR]: EggTier.COMMON,
|
||||
[Species.BONSLY]: EggTier.COMMON,
|
||||
[Species.MIME_JR]: EggTier.COMMON,
|
||||
[Species.HAPPINY]: EggTier.COMMON,
|
||||
[Species.CHATOT]: EggTier.COMMON,
|
||||
[Species.SPIRITOMB]: EggTier.RARE,
|
||||
[Species.GIBLE]: EggTier.RARE,
|
||||
[Species.MUNCHLAX]: EggTier.RARE,
|
||||
[Species.RIOLU]: EggTier.COMMON,
|
||||
[Species.HIPPOPOTAS]: EggTier.COMMON,
|
||||
[Species.SKORUPI]: EggTier.COMMON,
|
||||
[Species.CROAGUNK]: EggTier.COMMON,
|
||||
[Species.CARNIVINE]: EggTier.COMMON,
|
||||
[Species.FINNEON]: EggTier.COMMON,
|
||||
[Species.MANTYKE]: EggTier.COMMON,
|
||||
[Species.SNOVER]: EggTier.COMMON,
|
||||
[Species.ROTOM]: EggTier.RARE,
|
||||
[Species.UXIE]: EggTier.EPIC,
|
||||
[Species.MESPRIT]: EggTier.EPIC,
|
||||
[Species.AZELF]: EggTier.EPIC,
|
||||
[Species.DIALGA]: EggTier.LEGENDARY,
|
||||
[Species.PALKIA]: EggTier.LEGENDARY,
|
||||
[Species.HEATRAN]: EggTier.EPIC,
|
||||
[Species.REGIGIGAS]: EggTier.EPIC,
|
||||
[Species.GIRATINA]: EggTier.LEGENDARY,
|
||||
[Species.CRESSELIA]: EggTier.EPIC,
|
||||
[Species.PHIONE]: EggTier.RARE,
|
||||
[Species.MANAPHY]: EggTier.EPIC,
|
||||
[Species.DARKRAI]: EggTier.EPIC,
|
||||
[Species.SHAYMIN]: EggTier.EPIC,
|
||||
[Species.ARCEUS]: EggTier.LEGENDARY,
|
||||
|
||||
[Species.VICTINI]: EggTier.EPIC,
|
||||
[Species.SNIVY]: EggTier.COMMON,
|
||||
[Species.TEPIG]: EggTier.COMMON,
|
||||
[Species.OSHAWOTT]: EggTier.COMMON,
|
||||
[Species.PATRAT]: EggTier.COMMON,
|
||||
[Species.LILLIPUP]: EggTier.COMMON,
|
||||
[Species.PURRLOIN]: EggTier.COMMON,
|
||||
[Species.PANSAGE]: EggTier.COMMON,
|
||||
[Species.PANSEAR]: EggTier.COMMON,
|
||||
[Species.PANPOUR]: EggTier.COMMON,
|
||||
[Species.MUNNA]: EggTier.COMMON,
|
||||
[Species.PIDOVE]: EggTier.COMMON,
|
||||
[Species.BLITZLE]: EggTier.COMMON,
|
||||
[Species.ROGGENROLA]: EggTier.COMMON,
|
||||
[Species.WOOBAT]: EggTier.COMMON,
|
||||
[Species.DRILBUR]: EggTier.RARE,
|
||||
[Species.AUDINO]: EggTier.COMMON,
|
||||
[Species.TIMBURR]: EggTier.RARE,
|
||||
[Species.TYMPOLE]: EggTier.COMMON,
|
||||
[Species.THROH]: EggTier.RARE,
|
||||
[Species.SAWK]: EggTier.RARE,
|
||||
[Species.SEWADDLE]: EggTier.COMMON,
|
||||
[Species.VENIPEDE]: EggTier.COMMON,
|
||||
[Species.COTTONEE]: EggTier.COMMON,
|
||||
[Species.PETILIL]: EggTier.COMMON,
|
||||
[Species.BASCULIN]: EggTier.RARE,
|
||||
[Species.SANDILE]: EggTier.RARE,
|
||||
[Species.DARUMAKA]: EggTier.RARE,
|
||||
[Species.MARACTUS]: EggTier.COMMON,
|
||||
[Species.DWEBBLE]: EggTier.COMMON,
|
||||
[Species.SCRAGGY]: EggTier.COMMON,
|
||||
[Species.SIGILYPH]: EggTier.RARE,
|
||||
[Species.YAMASK]: EggTier.COMMON,
|
||||
[Species.TIRTOUGA]: EggTier.COMMON,
|
||||
[Species.ARCHEN]: EggTier.COMMON,
|
||||
[Species.TRUBBISH]: EggTier.COMMON,
|
||||
[Species.ZORUA]: EggTier.COMMON,
|
||||
[Species.MINCCINO]: EggTier.COMMON,
|
||||
[Species.GOTHITA]: EggTier.COMMON,
|
||||
[Species.SOLOSIS]: EggTier.COMMON,
|
||||
[Species.DUCKLETT]: EggTier.COMMON,
|
||||
[Species.VANILLITE]: EggTier.COMMON,
|
||||
[Species.DEERLING]: EggTier.COMMON,
|
||||
[Species.EMOLGA]: EggTier.COMMON,
|
||||
[Species.KARRABLAST]: EggTier.COMMON,
|
||||
[Species.FOONGUS]: EggTier.COMMON,
|
||||
[Species.FRILLISH]: EggTier.COMMON,
|
||||
[Species.ALOMOMOLA]: EggTier.RARE,
|
||||
[Species.JOLTIK]: EggTier.COMMON,
|
||||
[Species.FERROSEED]: EggTier.COMMON,
|
||||
[Species.KLINK]: EggTier.COMMON,
|
||||
[Species.TYNAMO]: EggTier.COMMON,
|
||||
[Species.ELGYEM]: EggTier.COMMON,
|
||||
[Species.LITWICK]: EggTier.COMMON,
|
||||
[Species.AXEW]: EggTier.RARE,
|
||||
[Species.CUBCHOO]: EggTier.COMMON,
|
||||
[Species.CRYOGONAL]: EggTier.RARE,
|
||||
[Species.SHELMET]: EggTier.COMMON,
|
||||
[Species.STUNFISK]: EggTier.COMMON,
|
||||
[Species.MIENFOO]: EggTier.COMMON,
|
||||
[Species.DRUDDIGON]: EggTier.RARE,
|
||||
[Species.GOLETT]: EggTier.COMMON,
|
||||
[Species.PAWNIARD]: EggTier.RARE,
|
||||
[Species.BOUFFALANT]: EggTier.RARE,
|
||||
[Species.RUFFLET]: EggTier.COMMON,
|
||||
[Species.VULLABY]: EggTier.COMMON,
|
||||
[Species.HEATMOR]: EggTier.COMMON,
|
||||
[Species.DURANT]: EggTier.RARE,
|
||||
[Species.DEINO]: EggTier.RARE,
|
||||
[Species.LARVESTA]: EggTier.RARE,
|
||||
[Species.COBALION]: EggTier.EPIC,
|
||||
[Species.TERRAKION]: EggTier.EPIC,
|
||||
[Species.VIRIZION]: EggTier.EPIC,
|
||||
[Species.TORNADUS]: EggTier.EPIC,
|
||||
[Species.THUNDURUS]: EggTier.EPIC,
|
||||
[Species.RESHIRAM]: EggTier.LEGENDARY,
|
||||
[Species.ZEKROM]: EggTier.LEGENDARY,
|
||||
[Species.LANDORUS]: EggTier.EPIC,
|
||||
[Species.KYUREM]: EggTier.LEGENDARY,
|
||||
[Species.KELDEO]: EggTier.EPIC,
|
||||
[Species.MELOETTA]: EggTier.EPIC,
|
||||
[Species.GENESECT]: EggTier.EPIC,
|
||||
|
||||
[Species.CHESPIN]: EggTier.COMMON,
|
||||
[Species.FENNEKIN]: EggTier.COMMON,
|
||||
[Species.FROAKIE]: EggTier.RARE,
|
||||
[Species.BUNNELBY]: EggTier.COMMON,
|
||||
[Species.FLETCHLING]: EggTier.COMMON,
|
||||
[Species.SCATTERBUG]: EggTier.COMMON,
|
||||
[Species.LITLEO]: EggTier.COMMON,
|
||||
[Species.FLABEBE]: EggTier.COMMON,
|
||||
[Species.SKIDDO]: EggTier.COMMON,
|
||||
[Species.PANCHAM]: EggTier.COMMON,
|
||||
[Species.FURFROU]: EggTier.COMMON,
|
||||
[Species.ESPURR]: EggTier.COMMON,
|
||||
[Species.HONEDGE]: EggTier.RARE,
|
||||
[Species.SPRITZEE]: EggTier.COMMON,
|
||||
[Species.SWIRLIX]: EggTier.COMMON,
|
||||
[Species.INKAY]: EggTier.COMMON,
|
||||
[Species.BINACLE]: EggTier.COMMON,
|
||||
[Species.SKRELP]: EggTier.COMMON,
|
||||
[Species.CLAUNCHER]: EggTier.COMMON,
|
||||
[Species.HELIOPTILE]: EggTier.COMMON,
|
||||
[Species.TYRUNT]: EggTier.COMMON,
|
||||
[Species.AMAURA]: EggTier.COMMON,
|
||||
[Species.HAWLUCHA]: EggTier.RARE,
|
||||
[Species.DEDENNE]: EggTier.COMMON,
|
||||
[Species.CARBINK]: EggTier.COMMON,
|
||||
[Species.GOOMY]: EggTier.RARE,
|
||||
[Species.KLEFKI]: EggTier.COMMON,
|
||||
[Species.PHANTUMP]: EggTier.COMMON,
|
||||
[Species.PUMPKABOO]: EggTier.COMMON,
|
||||
[Species.BERGMITE]: EggTier.COMMON,
|
||||
[Species.NOIBAT]: EggTier.COMMON,
|
||||
[Species.XERNEAS]: EggTier.LEGENDARY,
|
||||
[Species.YVELTAL]: EggTier.LEGENDARY,
|
||||
[Species.ZYGARDE]: EggTier.LEGENDARY,
|
||||
[Species.DIANCIE]: EggTier.EPIC,
|
||||
[Species.HOOPA]: EggTier.EPIC,
|
||||
[Species.VOLCANION]: EggTier.EPIC,
|
||||
[Species.ETERNAL_FLOETTE]: EggTier.RARE,
|
||||
|
||||
[Species.ROWLET]: EggTier.COMMON,
|
||||
[Species.LITTEN]: EggTier.COMMON,
|
||||
[Species.POPPLIO]: EggTier.RARE,
|
||||
[Species.PIKIPEK]: EggTier.COMMON,
|
||||
[Species.YUNGOOS]: EggTier.COMMON,
|
||||
[Species.GRUBBIN]: EggTier.COMMON,
|
||||
[Species.CRABRAWLER]: EggTier.COMMON,
|
||||
[Species.ORICORIO]: EggTier.COMMON,
|
||||
[Species.CUTIEFLY]: EggTier.COMMON,
|
||||
[Species.ROCKRUFF]: EggTier.COMMON,
|
||||
[Species.WISHIWASHI]: EggTier.COMMON,
|
||||
[Species.MAREANIE]: EggTier.COMMON,
|
||||
[Species.MUDBRAY]: EggTier.COMMON,
|
||||
[Species.DEWPIDER]: EggTier.COMMON,
|
||||
[Species.FOMANTIS]: EggTier.COMMON,
|
||||
[Species.MORELULL]: EggTier.COMMON,
|
||||
[Species.SALANDIT]: EggTier.COMMON,
|
||||
[Species.STUFFUL]: EggTier.COMMON,
|
||||
[Species.BOUNSWEET]: EggTier.COMMON,
|
||||
[Species.COMFEY]: EggTier.RARE,
|
||||
[Species.ORANGURU]: EggTier.RARE,
|
||||
[Species.PASSIMIAN]: EggTier.RARE,
|
||||
[Species.WIMPOD]: EggTier.COMMON,
|
||||
[Species.SANDYGAST]: EggTier.COMMON,
|
||||
[Species.PYUKUMUKU]: EggTier.COMMON,
|
||||
[Species.TYPE_NULL]: EggTier.RARE,
|
||||
[Species.MINIOR]: EggTier.RARE,
|
||||
[Species.KOMALA]: EggTier.COMMON,
|
||||
[Species.TURTONATOR]: EggTier.RARE,
|
||||
[Species.TOGEDEMARU]: EggTier.COMMON,
|
||||
[Species.MIMIKYU]: EggTier.RARE,
|
||||
[Species.BRUXISH]: EggTier.RARE,
|
||||
[Species.DRAMPA]: EggTier.RARE,
|
||||
[Species.DHELMISE]: EggTier.RARE,
|
||||
[Species.JANGMO_O]: EggTier.RARE,
|
||||
[Species.TAPU_KOKO]: EggTier.EPIC,
|
||||
[Species.TAPU_LELE]: EggTier.EPIC,
|
||||
[Species.TAPU_BULU]: EggTier.EPIC,
|
||||
[Species.TAPU_FINI]: EggTier.EPIC,
|
||||
[Species.COSMOG]: EggTier.EPIC,
|
||||
[Species.NIHILEGO]: EggTier.EPIC,
|
||||
[Species.BUZZWOLE]: EggTier.EPIC,
|
||||
[Species.PHEROMOSA]: EggTier.EPIC,
|
||||
[Species.XURKITREE]: EggTier.EPIC,
|
||||
[Species.CELESTEELA]: EggTier.EPIC,
|
||||
[Species.KARTANA]: EggTier.EPIC,
|
||||
[Species.GUZZLORD]: EggTier.EPIC,
|
||||
[Species.NECROZMA]: EggTier.LEGENDARY,
|
||||
[Species.MAGEARNA]: EggTier.EPIC,
|
||||
[Species.MARSHADOW]: EggTier.EPIC,
|
||||
[Species.POIPOLE]: EggTier.EPIC,
|
||||
[Species.STAKATAKA]: EggTier.EPIC,
|
||||
[Species.BLACEPHALON]: EggTier.EPIC,
|
||||
[Species.ZERAORA]: EggTier.EPIC,
|
||||
[Species.MELTAN]: EggTier.EPIC,
|
||||
[Species.ALOLA_RATTATA]: EggTier.COMMON,
|
||||
[Species.ALOLA_SANDSHREW]: EggTier.COMMON,
|
||||
[Species.ALOLA_VULPIX]: EggTier.COMMON,
|
||||
[Species.ALOLA_DIGLETT]: EggTier.COMMON,
|
||||
[Species.ALOLA_MEOWTH]: EggTier.COMMON,
|
||||
[Species.ALOLA_GEODUDE]: EggTier.COMMON,
|
||||
[Species.ALOLA_GRIMER]: EggTier.COMMON,
|
||||
|
||||
[Species.GROOKEY]: EggTier.COMMON,
|
||||
[Species.SCORBUNNY]: EggTier.RARE,
|
||||
[Species.SOBBLE]: EggTier.COMMON,
|
||||
[Species.SKWOVET]: EggTier.COMMON,
|
||||
[Species.ROOKIDEE]: EggTier.COMMON,
|
||||
[Species.BLIPBUG]: EggTier.COMMON,
|
||||
[Species.NICKIT]: EggTier.COMMON,
|
||||
[Species.GOSSIFLEUR]: EggTier.COMMON,
|
||||
[Species.WOOLOO]: EggTier.COMMON,
|
||||
[Species.CHEWTLE]: EggTier.COMMON,
|
||||
[Species.YAMPER]: EggTier.COMMON,
|
||||
[Species.ROLYCOLY]: EggTier.COMMON,
|
||||
[Species.APPLIN]: EggTier.COMMON,
|
||||
[Species.SILICOBRA]: EggTier.COMMON,
|
||||
[Species.CRAMORANT]: EggTier.COMMON,
|
||||
[Species.ARROKUDA]: EggTier.COMMON,
|
||||
[Species.TOXEL]: EggTier.COMMON,
|
||||
[Species.SIZZLIPEDE]: EggTier.COMMON,
|
||||
[Species.CLOBBOPUS]: EggTier.COMMON,
|
||||
[Species.SINISTEA]: EggTier.COMMON,
|
||||
[Species.HATENNA]: EggTier.COMMON,
|
||||
[Species.IMPIDIMP]: EggTier.COMMON,
|
||||
[Species.MILCERY]: EggTier.COMMON,
|
||||
[Species.FALINKS]: EggTier.RARE,
|
||||
[Species.PINCURCHIN]: EggTier.COMMON,
|
||||
[Species.SNOM]: EggTier.COMMON,
|
||||
[Species.STONJOURNER]: EggTier.COMMON,
|
||||
[Species.EISCUE]: EggTier.COMMON,
|
||||
[Species.INDEEDEE]: EggTier.RARE,
|
||||
[Species.MORPEKO]: EggTier.COMMON,
|
||||
[Species.CUFANT]: EggTier.COMMON,
|
||||
[Species.DRACOZOLT]: EggTier.RARE,
|
||||
[Species.ARCTOZOLT]: EggTier.RARE,
|
||||
[Species.DRACOVISH]: EggTier.RARE,
|
||||
[Species.ARCTOVISH]: EggTier.RARE,
|
||||
[Species.DURALUDON]: EggTier.RARE,
|
||||
[Species.DREEPY]: EggTier.RARE,
|
||||
[Species.ZACIAN]: EggTier.LEGENDARY,
|
||||
[Species.ZAMAZENTA]: EggTier.LEGENDARY,
|
||||
[Species.ETERNATUS]: EggTier.COMMON,
|
||||
[Species.KUBFU]: EggTier.EPIC,
|
||||
[Species.ZARUDE]: EggTier.EPIC,
|
||||
[Species.REGIELEKI]: EggTier.EPIC,
|
||||
[Species.REGIDRAGO]: EggTier.EPIC,
|
||||
[Species.GLASTRIER]: EggTier.EPIC,
|
||||
[Species.SPECTRIER]: EggTier.EPIC,
|
||||
[Species.CALYREX]: EggTier.LEGENDARY,
|
||||
[Species.GALAR_MEOWTH]: EggTier.COMMON,
|
||||
[Species.GALAR_PONYTA]: EggTier.COMMON,
|
||||
[Species.GALAR_SLOWPOKE]: EggTier.COMMON,
|
||||
[Species.GALAR_FARFETCHD]: EggTier.COMMON,
|
||||
[Species.GALAR_CORSOLA]: EggTier.COMMON,
|
||||
[Species.GALAR_ZIGZAGOON]: EggTier.COMMON,
|
||||
[Species.GALAR_DARUMAKA]: EggTier.RARE,
|
||||
[Species.GALAR_YAMASK]: EggTier.COMMON,
|
||||
[Species.GALAR_STUNFISK]: EggTier.COMMON,
|
||||
[Species.GALAR_MR_MIME]: EggTier.COMMON,
|
||||
[Species.GALAR_ARTICUNO]: EggTier.EPIC,
|
||||
[Species.GALAR_ZAPDOS]: EggTier.EPIC,
|
||||
[Species.GALAR_MOLTRES]: EggTier.EPIC,
|
||||
[Species.HISUI_GROWLITHE]: EggTier.RARE,
|
||||
[Species.HISUI_VOLTORB]: EggTier.COMMON,
|
||||
[Species.HISUI_QWILFISH]: EggTier.RARE,
|
||||
[Species.HISUI_SNEASEL]: EggTier.RARE,
|
||||
[Species.HISUI_ZORUA]: EggTier.COMMON,
|
||||
[Species.ENAMORUS]: EggTier.EPIC,
|
||||
|
||||
[Species.SPRIGATITO]: EggTier.RARE,
|
||||
[Species.FUECOCO]: EggTier.RARE,
|
||||
[Species.QUAXLY]: EggTier.RARE,
|
||||
[Species.LECHONK]: EggTier.COMMON,
|
||||
[Species.TAROUNTULA]: EggTier.COMMON,
|
||||
[Species.NYMBLE]: EggTier.COMMON,
|
||||
[Species.PAWMI]: EggTier.COMMON,
|
||||
[Species.TANDEMAUS]: EggTier.RARE,
|
||||
[Species.FIDOUGH]: EggTier.COMMON,
|
||||
[Species.SMOLIV]: EggTier.COMMON,
|
||||
[Species.SQUAWKABILLY]: EggTier.COMMON,
|
||||
[Species.NACLI]: EggTier.RARE,
|
||||
[Species.CHARCADET]: EggTier.RARE,
|
||||
[Species.TADBULB]: EggTier.COMMON,
|
||||
[Species.WATTREL]: EggTier.COMMON,
|
||||
[Species.MASCHIFF]: EggTier.COMMON,
|
||||
[Species.SHROODLE]: EggTier.COMMON,
|
||||
[Species.BRAMBLIN]: EggTier.COMMON,
|
||||
[Species.TOEDSCOOL]: EggTier.COMMON,
|
||||
[Species.KLAWF]: EggTier.COMMON,
|
||||
[Species.CAPSAKID]: EggTier.COMMON,
|
||||
[Species.RELLOR]: EggTier.COMMON,
|
||||
[Species.FLITTLE]: EggTier.COMMON,
|
||||
[Species.TINKATINK]: EggTier.RARE,
|
||||
[Species.WIGLETT]: EggTier.COMMON,
|
||||
[Species.BOMBIRDIER]: EggTier.COMMON,
|
||||
[Species.FINIZEN]: EggTier.COMMON,
|
||||
[Species.VAROOM]: EggTier.RARE,
|
||||
[Species.CYCLIZAR]: EggTier.RARE,
|
||||
[Species.ORTHWORM]: EggTier.RARE,
|
||||
[Species.GLIMMET]: EggTier.RARE,
|
||||
[Species.GREAVARD]: EggTier.COMMON,
|
||||
[Species.FLAMIGO]: EggTier.RARE,
|
||||
[Species.CETODDLE]: EggTier.COMMON,
|
||||
[Species.VELUZA]: EggTier.RARE,
|
||||
[Species.DONDOZO]: EggTier.RARE,
|
||||
[Species.TATSUGIRI]: EggTier.RARE,
|
||||
[Species.GREAT_TUSK]: EggTier.EPIC,
|
||||
[Species.SCREAM_TAIL]: EggTier.EPIC,
|
||||
[Species.BRUTE_BONNET]: EggTier.EPIC,
|
||||
[Species.FLUTTER_MANE]: EggTier.EPIC,
|
||||
[Species.SLITHER_WING]: EggTier.EPIC,
|
||||
[Species.SANDY_SHOCKS]: EggTier.EPIC,
|
||||
[Species.IRON_TREADS]: EggTier.EPIC,
|
||||
[Species.IRON_BUNDLE]: EggTier.EPIC,
|
||||
[Species.IRON_HANDS]: EggTier.EPIC,
|
||||
[Species.IRON_JUGULIS]: EggTier.EPIC,
|
||||
[Species.IRON_MOTH]: EggTier.EPIC,
|
||||
[Species.IRON_THORNS]: EggTier.EPIC,
|
||||
[Species.FRIGIBAX]: EggTier.RARE,
|
||||
[Species.GIMMIGHOUL]: EggTier.RARE,
|
||||
[Species.WO_CHIEN]: EggTier.EPIC,
|
||||
[Species.CHIEN_PAO]: EggTier.EPIC,
|
||||
[Species.TING_LU]: EggTier.EPIC,
|
||||
[Species.CHI_YU]: EggTier.EPIC,
|
||||
[Species.ROARING_MOON]: EggTier.EPIC,
|
||||
[Species.IRON_VALIANT]: EggTier.EPIC,
|
||||
[Species.KORAIDON]: EggTier.LEGENDARY,
|
||||
[Species.MIRAIDON]: EggTier.LEGENDARY,
|
||||
[Species.WALKING_WAKE]: EggTier.EPIC,
|
||||
[Species.IRON_LEAVES]: EggTier.EPIC,
|
||||
[Species.POLTCHAGEIST]: EggTier.RARE,
|
||||
[Species.OKIDOGI]: EggTier.EPIC,
|
||||
[Species.MUNKIDORI]: EggTier.EPIC,
|
||||
[Species.FEZANDIPITI]: EggTier.EPIC,
|
||||
[Species.OGERPON]: EggTier.EPIC,
|
||||
[Species.GOUGING_FIRE]: EggTier.EPIC,
|
||||
[Species.RAGING_BOLT]: EggTier.EPIC,
|
||||
[Species.IRON_BOULDER]: EggTier.EPIC,
|
||||
[Species.IRON_CROWN]: EggTier.EPIC,
|
||||
[Species.TERAPAGOS]: EggTier.LEGENDARY,
|
||||
[Species.PECHARUNT]: EggTier.EPIC,
|
||||
[Species.PALDEA_TAUROS]: EggTier.RARE,
|
||||
[Species.PALDEA_WOOPER]: EggTier.COMMON,
|
||||
[Species.BLOODMOON_URSALUNA]: EggTier.EPIC,
|
||||
};
|
@ -630,16 +630,16 @@ export const speciesStarterCosts = {
|
||||
};
|
||||
|
||||
const starterCandyCosts: { passive: number; costReduction: [number, number]; egg: number; }[] = [
|
||||
{ passive: 40, costReduction: [25, 60], egg: 30 }, // 1 Cost
|
||||
{ passive: 40, costReduction: [25, 60], egg: 30 }, // 2 Cost
|
||||
{ passive: 35, costReduction: [20, 50], egg: 25 }, // 3 Cost
|
||||
{ passive: 30, costReduction: [15, 40], egg: 20 }, // 4 Cost
|
||||
{ passive: 25, costReduction: [12, 35], egg: 18 }, // 5 Cost
|
||||
{ passive: 20, costReduction: [10, 30], egg: 15 }, // 6 Cost
|
||||
{ passive: 15, costReduction: [8, 20], egg: 12 }, // 7 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 8 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 9 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 10 Cost
|
||||
{ passive: 40, costReduction: [ 25, 60 ], egg: 30 }, // 1 Cost
|
||||
{ passive: 40, costReduction: [ 25, 60 ], egg: 30 }, // 2 Cost
|
||||
{ passive: 35, costReduction: [ 20, 50 ], egg: 25 }, // 3 Cost
|
||||
{ passive: 30, costReduction: [ 15, 40 ], egg: 20 }, // 4 Cost
|
||||
{ passive: 25, costReduction: [ 12, 35 ], egg: 18 }, // 5 Cost
|
||||
{ passive: 20, costReduction: [ 10, 30 ], egg: 15 }, // 6 Cost
|
||||
{ passive: 15, costReduction: [ 8, 20 ], egg: 12 }, // 7 Cost
|
||||
{ passive: 10, costReduction: [ 5, 15 ], egg: 10 }, // 8 Cost
|
||||
{ passive: 10, costReduction: [ 5, 15 ], egg: 10 }, // 9 Cost
|
||||
{ passive: 10, costReduction: [ 5, 15 ], egg: 10 }, // 10 Cost
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -556,7 +556,7 @@ function logMissingMoveAnim(move: Moves, ...optionalParams: any[]) {
|
||||
* @param encounterAnim one or more animations to fetch
|
||||
*/
|
||||
export async function initEncounterAnims(scene: BattleScene, encounterAnim: EncounterAnim | EncounterAnim[]): Promise<void> {
|
||||
const anims = Array.isArray(encounterAnim) ? encounterAnim : [encounterAnim];
|
||||
const anims = Array.isArray(encounterAnim) ? encounterAnim : [ encounterAnim ];
|
||||
const encounterAnimNames = Utils.getEnumKeys(EncounterAnim);
|
||||
const encounterAnimFetches: Promise<Map<EncounterAnim, AnimConfig>>[] = [];
|
||||
for (const anim of anims) {
|
||||
@ -774,9 +774,9 @@ export abstract class BattleAnim {
|
||||
|
||||
private getGraphicFrameData(scene: BattleScene, frames: AnimFrame[], onSubstitute?: boolean): Map<integer, Map<AnimFrameTarget, GraphicFrameData>> {
|
||||
const ret: Map<integer, Map<AnimFrameTarget, GraphicFrameData>> = new Map([
|
||||
[AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
[ AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[ AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[ AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
]);
|
||||
|
||||
const isOppAnim = this.isOppAnim();
|
||||
@ -1093,9 +1093,9 @@ export abstract class BattleAnim {
|
||||
|
||||
private getGraphicFrameDataWithoutTarget(frames: AnimFrame[], targetInitialX: number, targetInitialY: number): Map<integer, Map<AnimFrameTarget, GraphicFrameData>> {
|
||||
const ret: Map<integer, Map<AnimFrameTarget, GraphicFrameData>> = new Map([
|
||||
[AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
[ AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[ AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[ AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
]);
|
||||
|
||||
let g = 0;
|
||||
|
@ -23,6 +23,7 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||
import { StatStageChangePhase, StatStageChangeCallback } from "#app/phases/stat-stage-change-phase";
|
||||
import { PokemonAnimType } from "#app/enums/pokemon-anim-type";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
|
||||
export enum BattlerTagLapseType {
|
||||
FAINT,
|
||||
@ -90,6 +91,15 @@ export class BattlerTag {
|
||||
this.sourceMove = source.sourceMove;
|
||||
this.sourceId = source.sourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that retrieves the source Pokemon object
|
||||
* @param scene medium to retrieve the source Pokemon
|
||||
* @returns The source {@linkcode Pokemon} or `null` if none is found
|
||||
*/
|
||||
public getSourcePokemon(scene: BattleScene): Pokemon | null {
|
||||
return this.sourceId ? scene.getPokemonById(this.sourceId) : null;
|
||||
}
|
||||
}
|
||||
|
||||
export interface WeatherBattlerTag {
|
||||
@ -120,7 +130,7 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag {
|
||||
const phase = pokemon.scene.getCurrentPhase() as MovePhase;
|
||||
const move = phase.move;
|
||||
|
||||
if (this.isMoveRestricted(move.moveId)) {
|
||||
if (this.isMoveRestricted(move.moveId, pokemon)) {
|
||||
if (this.interruptedText(pokemon, move.moveId)) {
|
||||
pokemon.scene.queueMessage(this.interruptedText(pokemon, move.moveId));
|
||||
}
|
||||
@ -136,10 +146,11 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag {
|
||||
/**
|
||||
* Gets whether this tag is restricting a move.
|
||||
*
|
||||
* @param {Moves} move {@linkcode Moves} ID to check restriction for.
|
||||
* @returns {boolean} `true` if the move is restricted by this tag, otherwise `false`.
|
||||
* @param move - {@linkcode Moves} ID to check restriction for.
|
||||
* @param user - The {@linkcode Pokemon} involved
|
||||
* @returns `true` if the move is restricted by this tag, otherwise `false`.
|
||||
*/
|
||||
abstract isMoveRestricted(move: Moves): boolean;
|
||||
public abstract isMoveRestricted(move: Moves, user?: Pokemon): boolean;
|
||||
|
||||
/**
|
||||
* Checks if this tag is restricting a move based on a user's decisions during the target selection phase
|
||||
@ -327,6 +338,16 @@ export class GorillaTacticsTag extends MoveRestrictionBattlerTag {
|
||||
pokemon.setStat(Stat.ATK, pokemon.getStat(Stat.ATK, false) * 1.5, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the Gorilla Tactics Battler Tag along with its unique class variable moveId
|
||||
* @override
|
||||
* @param source Gorilla Tactics' {@linkcode BattlerTag} information
|
||||
*/
|
||||
public override loadTag(source: BattlerTag | any): void {
|
||||
super.loadTag(source);
|
||||
this.moveId = source.moveId;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @override
|
||||
@ -363,7 +384,7 @@ export class RechargingTag extends BattlerTag {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
// Queue a placeholder move for the Pokemon to "use" next turn
|
||||
pokemon.getMoveQueue().push({ move: Moves.NONE, targets: [] });
|
||||
pokemon.getMoveQueue().push({ move: Moves.NONE, targets: []});
|
||||
}
|
||||
|
||||
/** Cancels the source's move this turn and queues a "__ must recharge!" message */
|
||||
@ -569,7 +590,7 @@ export class InterruptedTag extends BattlerTag {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.getMoveQueue().shift();
|
||||
pokemon.pushMoveHistory({move: Moves.NONE, result: MoveResult.OTHER});
|
||||
pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.OTHER });
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
@ -1376,7 +1397,7 @@ export class ContactStatStageChangeProtectedTag extends DamageProtectedTag {
|
||||
const effectPhase = pokemon.scene.getCurrentPhase();
|
||||
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) {
|
||||
const attacker = effectPhase.getPokemon();
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), true, [ this.stat ], this.levels));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), false, [ this.stat ], this.levels));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1713,7 +1734,12 @@ export class TypeImmuneTag extends BattlerTag {
|
||||
}
|
||||
}
|
||||
|
||||
export class MagnetRisenTag extends TypeImmuneTag {
|
||||
/**
|
||||
* Battler Tag that lifts the affected Pokemon into the air and provides immunity to Ground type moves.
|
||||
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Magnet_Rise_(move) | Moves.MAGNET_RISE}
|
||||
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Telekinesis_(move) | Moves.TELEKINESIS}
|
||||
*/
|
||||
export class FloatingTag extends TypeImmuneTag {
|
||||
constructor(tagType: BattlerTagType, sourceMove: Moves) {
|
||||
super(tagType, sourceMove, Type.GROUND, 5);
|
||||
}
|
||||
@ -1721,13 +1747,17 @@ export class MagnetRisenTag extends TypeImmuneTag {
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
if (this.sourceMove === Moves.MAGNET_RISE) {
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
super.onRemove(pokemon);
|
||||
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
if (this.sourceMove === Moves.MAGNET_RISE) {
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1935,10 +1965,10 @@ export class RoostedTag extends BattlerTag {
|
||||
modifiedTypes = currentTypes.filter(type => type !== Type.NORMAL);
|
||||
modifiedTypes.push(Type.FLYING);
|
||||
} else {
|
||||
modifiedTypes = [Type.FLYING];
|
||||
modifiedTypes = [ Type.FLYING ];
|
||||
}
|
||||
} else {
|
||||
modifiedTypes = [...currentTypes];
|
||||
modifiedTypes = [ ...currentTypes ];
|
||||
modifiedTypes.push(Type.FLYING);
|
||||
}
|
||||
pokemon.summonData.types = modifiedTypes;
|
||||
@ -1958,10 +1988,10 @@ export class RoostedTag extends BattlerTag {
|
||||
if (this.isBaseFlying) {
|
||||
let modifiedTypes: Type[];
|
||||
if (this.isBasePureFlying && !isCurrentlyDualType) {
|
||||
modifiedTypes = [Type.NORMAL];
|
||||
modifiedTypes = [ Type.NORMAL ];
|
||||
} else {
|
||||
if (!!pokemon.getTag(RemovedTypeTag) && isOriginallyDualType && !isCurrentlyDualType) {
|
||||
modifiedTypes = [Type.UNKNOWN];
|
||||
modifiedTypes = [ Type.UNKNOWN ];
|
||||
} else {
|
||||
modifiedTypes = currentTypes.filter(type => type !== Type.FLYING);
|
||||
}
|
||||
@ -2067,8 +2097,8 @@ export class StockpilingTag extends BattlerTag {
|
||||
super.loadTag(source);
|
||||
this.stockpiledCount = source.stockpiledCount || 0;
|
||||
this.statChangeCounts = {
|
||||
[ Stat.DEF ]: source.statChangeCounts?.[ Stat.DEF ] ?? 0,
|
||||
[ Stat.SPDEF ]: source.statChangeCounts?.[ Stat.SPDEF ] ?? 0,
|
||||
[Stat.DEF]: source.statChangeCounts?.[Stat.DEF] ?? 0,
|
||||
[Stat.SPDEF]: source.statChangeCounts?.[Stat.SPDEF] ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -2090,7 +2120,7 @@ export class StockpilingTag extends BattlerTag {
|
||||
// Attempt to increase DEF and SPDEF by one stage, keeping track of successful changes.
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(
|
||||
pokemon.scene, pokemon.getBattlerIndex(), true,
|
||||
[Stat.SPDEF, Stat.DEF], 1, true, false, true, this.onStatStagesChanged
|
||||
[ Stat.SPDEF, Stat.DEF ], 1, true, false, true, this.onStatStagesChanged
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -2139,6 +2169,10 @@ export class GulpMissileTag extends BattlerTag {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (moveEffectPhase.move.getMove().hitsSubstitute(attacker, pokemon)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
applyAbAttrs(BlockNonDirectDamageAbAttr, attacker, cancelled);
|
||||
|
||||
@ -2310,6 +2344,21 @@ export class TarShotTag extends BattlerTag {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Battler Tag implementing the type-changing effect of {@link https://bulbapedia.bulbagarden.net/wiki/Electrify_(move) | Electrify}.
|
||||
* While this tag is in effect, the afflicted Pokemon's moves are changed to Electric type.
|
||||
*/
|
||||
export class ElectrifiedTag extends BattlerTag {
|
||||
constructor() {
|
||||
super(BattlerTagType.ELECTRIFIED, BattlerTagLapseType.TURN_END, 1, Moves.ELECTRIFY);
|
||||
}
|
||||
|
||||
override onAdd(pokemon: Pokemon): void {
|
||||
// "{pokemonNameWithAffix}'s moves have been electrified!"
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:electrifiedOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Battler Tag that keeps track of how many times the user has Autotomized
|
||||
* Each count of Autotomization reduces the weight by 100kg
|
||||
@ -2354,7 +2403,7 @@ export class SubstituteTag extends BattlerTag {
|
||||
public sourceInFocus: boolean;
|
||||
|
||||
constructor(sourceMove: Moves, sourceId: integer) {
|
||||
super(BattlerTagType.SUBSTITUTE, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE, BattlerTagLapseType.HIT], 0, sourceMove, sourceId, true);
|
||||
super(BattlerTagType.SUBSTITUTE, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE, BattlerTagLapseType.HIT ], 0, sourceMove, sourceId, true);
|
||||
}
|
||||
|
||||
/** Sets the Substitute's HP and queues an on-add battle animation that initializes the Substitute's sprite. */
|
||||
@ -2378,7 +2427,7 @@ export class SubstituteTag extends BattlerTag {
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
// Only play the animation if the cause of removal isn't from the source's own move
|
||||
if (!this.sourceInFocus) {
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_REMOVE, [this.sprite]);
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_REMOVE, [ this.sprite ]);
|
||||
} else {
|
||||
this.sprite.destroy();
|
||||
}
|
||||
@ -2402,13 +2451,13 @@ export class SubstituteTag extends BattlerTag {
|
||||
|
||||
/** Triggers an animation that brings the Pokemon into focus before it uses a move */
|
||||
onPreMove(pokemon: Pokemon): void {
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_PRE_MOVE, [this.sprite]);
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_PRE_MOVE, [ this.sprite ]);
|
||||
this.sourceInFocus = true;
|
||||
}
|
||||
|
||||
/** Triggers an animation that brings the Pokemon out of focus after it uses a move */
|
||||
onAfterMove(pokemon: Pokemon): void {
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_POST_MOVE, [this.sprite]);
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_POST_MOVE, [ this.sprite ]);
|
||||
this.sourceInFocus = false;
|
||||
}
|
||||
|
||||
@ -2482,8 +2531,6 @@ export class MysteryEncounterPostSummonTag extends BattlerTag {
|
||||
* Torment does not interrupt the move if the move is performed consecutively in the same turn and right after Torment is applied
|
||||
*/
|
||||
export class TormentTag extends MoveRestrictionBattlerTag {
|
||||
private target: Pokemon;
|
||||
|
||||
constructor(sourceId: number) {
|
||||
super(BattlerTagType.TORMENT, BattlerTagLapseType.AFTER_MOVE, 1, Moves.TORMENT, sourceId);
|
||||
}
|
||||
@ -2495,7 +2542,6 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||
*/
|
||||
override onAdd(pokemon: Pokemon) {
|
||||
super.onAdd(pokemon);
|
||||
this.target = pokemon;
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:tormentOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), 1500);
|
||||
}
|
||||
|
||||
@ -2514,15 +2560,18 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||
* @param {Moves} move the move under investigation
|
||||
* @returns `true` if there is valid consecutive usage | `false` if the moves are different from each other
|
||||
*/
|
||||
override isMoveRestricted(move: Moves): boolean {
|
||||
const lastMove = this.target.getLastXMoves(1)[0];
|
||||
public override isMoveRestricted(move: Moves, user: Pokemon): boolean {
|
||||
if (!user) {
|
||||
return false;
|
||||
}
|
||||
const lastMove = user.getLastXMoves(1)[0];
|
||||
if ( !lastMove ) {
|
||||
return false;
|
||||
}
|
||||
// This checks for locking / momentum moves like Rollout and Hydro Cannon + if the user is under the influence of BattlerTagType.FRENZY
|
||||
// Because Uproar's unique behavior is not implemented, it does not check for Uproar. Torment has been marked as partial in moves.ts
|
||||
const moveObj = allMoves[lastMove.move];
|
||||
const isUnaffected = moveObj.hasAttr(ConsecutiveUseDoublePowerAttr) || this.target.getTag(BattlerTagType.FRENZY) || moveObj.hasAttr(ChargeAttr);
|
||||
const isUnaffected = moveObj.hasAttr(ConsecutiveUseDoublePowerAttr) || user.getTag(BattlerTagType.FRENZY) || moveObj.hasAttr(ChargeAttr);
|
||||
const validLastMoveResult = (lastMove.result === MoveResult.SUCCESS) || (lastMove.result === MoveResult.MISS);
|
||||
if (lastMove.move === move && validLastMoveResult && lastMove.move !== Moves.STRUGGLE && !isUnaffected) {
|
||||
return true;
|
||||
@ -2542,7 +2591,7 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||
*/
|
||||
export class TauntTag extends MoveRestrictionBattlerTag {
|
||||
constructor() {
|
||||
super(BattlerTagType.TAUNT, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE], 4, Moves.TAUNT);
|
||||
super(BattlerTagType.TAUNT, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 4, Moves.TAUNT);
|
||||
}
|
||||
|
||||
override onAdd(pokemon: Pokemon) {
|
||||
@ -2574,37 +2623,39 @@ export class TauntTag extends MoveRestrictionBattlerTag {
|
||||
* The tag is only removed when the source-user is removed from the field.
|
||||
*/
|
||||
export class ImprisonTag extends MoveRestrictionBattlerTag {
|
||||
private source: Pokemon | null;
|
||||
|
||||
constructor(sourceId: number) {
|
||||
super(BattlerTagType.IMPRISON, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE], 1, Moves.IMPRISON, sourceId);
|
||||
}
|
||||
|
||||
override onAdd(pokemon: Pokemon) {
|
||||
if (this.sourceId) {
|
||||
this.source = pokemon.scene.getPokemonById(this.sourceId);
|
||||
}
|
||||
super(BattlerTagType.IMPRISON, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 1, Moves.IMPRISON, sourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the source of Imprison is still active
|
||||
* @param _pokemon
|
||||
* @param _lapseType
|
||||
* @override
|
||||
* @param pokemon The pokemon this tag is attached to
|
||||
* @returns `true` if the source is still active
|
||||
*/
|
||||
override lapse(_pokemon: Pokemon, _lapseType: BattlerTagLapseType): boolean {
|
||||
return this.source?.isActive(true) ?? false;
|
||||
public override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
const source = this.getSourcePokemon(pokemon.scene);
|
||||
if (source) {
|
||||
if (lapseType === BattlerTagLapseType.PRE_MOVE) {
|
||||
return super.lapse(pokemon, lapseType) && source.isActive(true);
|
||||
} else {
|
||||
return source.isActive(true);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the source of the tag has the parameter move in its moveset and that the source is still active
|
||||
* @override
|
||||
* @param {Moves} move the move under investigation
|
||||
* @returns `false` if either condition is not met
|
||||
*/
|
||||
override isMoveRestricted(move: Moves): boolean {
|
||||
if (this.source) {
|
||||
const sourceMoveset = this.source.getMoveset().map(m => m!.moveId);
|
||||
return sourceMoveset?.includes(move) && this.source.isActive(true);
|
||||
public override isMoveRestricted(move: Moves, user: Pokemon): boolean {
|
||||
const source = this.getSourcePokemon(user.scene);
|
||||
if (source) {
|
||||
const sourceMoveset = source.getMoveset().map(m => m!.moveId);
|
||||
return sourceMoveset?.includes(move) && source.isActive(true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -2621,16 +2672,16 @@ export class ImprisonTag extends MoveRestrictionBattlerTag {
|
||||
/**
|
||||
* Battler Tag that applies the effects of Syrup Bomb to the target Pokemon.
|
||||
* For three turns, starting from the turn of hit, at the end of each turn, the target Pokemon's speed will decrease by 1.
|
||||
* The tag can also expire by taking the target Pokemon off the field.
|
||||
* The tag can also expire by taking the target Pokemon off the field, or the Pokemon that originally used the move.
|
||||
*/
|
||||
export class SyrupBombTag extends BattlerTag {
|
||||
constructor() {
|
||||
super(BattlerTagType.SYRUP_BOMB, BattlerTagLapseType.TURN_END, 3, Moves.SYRUP_BOMB);
|
||||
constructor(sourceId: number) {
|
||||
super(BattlerTagType.SYRUP_BOMB, BattlerTagLapseType.TURN_END, 3, Moves.SYRUP_BOMB, sourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Syrup Bomb battler tag to the target Pokemon.
|
||||
* @param {Pokemon} pokemon the target Pokemon
|
||||
* @param pokemon - The target {@linkcode Pokemon}
|
||||
*/
|
||||
override onAdd(pokemon: Pokemon) {
|
||||
super.onAdd(pokemon);
|
||||
@ -2639,31 +2690,44 @@ export class SyrupBombTag extends BattlerTag {
|
||||
|
||||
/**
|
||||
* Applies the single-stage speed down to the target Pokemon and decrements the tag's turn count
|
||||
* @param {Pokemon} pokemon the target Pokemon
|
||||
* @param {BattlerTagLapseType} _lapseType
|
||||
* @returns `true` if the turnCount is still greater than 0 | `false` if the turnCount is 0 or the target Pokemon has been removed from the field
|
||||
* @param pokemon - The target {@linkcode Pokemon}
|
||||
* @param _lapseType - N/A
|
||||
* @returns `true` if the `turnCount` is still greater than `0`; `false` if the `turnCount` is `0` or the target or source Pokemon has been removed from the field
|
||||
*/
|
||||
override lapse(pokemon: Pokemon, _lapseType: BattlerTagLapseType): boolean {
|
||||
if (!pokemon.isActive(true)) {
|
||||
if (this.sourceId && !pokemon.scene.getPokemonById(this.sourceId)?.isActive(true)) {
|
||||
return false;
|
||||
}
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:syrupBombLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); // Custom message in lieu of an animation in mainline
|
||||
// Custom message in lieu of an animation in mainline
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:syrupBombLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(
|
||||
pokemon.scene, pokemon.getBattlerIndex(), true,
|
||||
[Stat.SPD], -1, true, false, true
|
||||
[ Stat.SPD ], -1, true, false, true
|
||||
));
|
||||
return --this.turnCount > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Telekinesis raises the target into the air for three turns and causes all moves used against the target (aside from OHKO moves) to hit the target unless the target is in a semi-invulnerable state from Fly/Dig.
|
||||
* The first effect is provided by {@linkcode FloatingTag}, the accuracy-bypass effect is provided by TelekinesisTag
|
||||
* The effects of Telekinesis can be baton passed to a teammate. Unlike the mainline games, Telekinesis can be baton-passed to Mega Gengar.
|
||||
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Telekinesis_(move) | Moves.TELEKINESIS}
|
||||
*/
|
||||
export class TelekinesisTag extends BattlerTag {
|
||||
constructor(sourceMove: Moves) {
|
||||
super(BattlerTagType.TELEKINESIS, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 3, sourceMove, undefined, true);
|
||||
}
|
||||
|
||||
override onAdd(pokemon: Pokemon) {
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:telekinesisOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@linkcode BattlerTag} based on the provided tag type, turn count, source move, and source ID.
|
||||
*
|
||||
* @param {BattlerTagType} tagType the type of the {@linkcode BattlerTagType}.
|
||||
* @param turnCount the turn count.
|
||||
* @param {Moves} sourceMove the source {@linkcode Moves}.
|
||||
* @param sourceId the source ID.
|
||||
* @returns {BattlerTag} the corresponding {@linkcode BattlerTag} object.
|
||||
* @param sourceId - The ID of the pokemon adding the tag
|
||||
* @returns The corresponding {@linkcode BattlerTag} object.
|
||||
*/
|
||||
export function getBattlerTag(tagType: BattlerTagType, turnCount: number, sourceMove: Moves, sourceId: number): BattlerTag {
|
||||
switch (tagType) {
|
||||
@ -2786,8 +2850,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
return new CursedTag(sourceId);
|
||||
case BattlerTagType.CHARGED:
|
||||
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
|
||||
case BattlerTagType.MAGNET_RISEN:
|
||||
return new MagnetRisenTag(tagType, sourceMove);
|
||||
case BattlerTagType.FLOATING:
|
||||
return new FloatingTag(tagType, sourceMove);
|
||||
case BattlerTagType.MINIMIZED:
|
||||
return new MinimizeTag();
|
||||
case BattlerTagType.DESTINY_BOND:
|
||||
@ -2803,14 +2867,16 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
case BattlerTagType.DISABLED:
|
||||
return new DisabledTag(sourceId);
|
||||
case BattlerTagType.IGNORE_GHOST:
|
||||
return new ExposedTag(tagType, sourceMove, Type.GHOST, [Type.NORMAL, Type.FIGHTING]);
|
||||
return new ExposedTag(tagType, sourceMove, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]);
|
||||
case BattlerTagType.IGNORE_DARK:
|
||||
return new ExposedTag(tagType, sourceMove, Type.DARK, [Type.PSYCHIC]);
|
||||
return new ExposedTag(tagType, sourceMove, Type.DARK, [ Type.PSYCHIC ]);
|
||||
case BattlerTagType.GULP_MISSILE_ARROKUDA:
|
||||
case BattlerTagType.GULP_MISSILE_PIKACHU:
|
||||
return new GulpMissileTag(tagType, sourceMove);
|
||||
case BattlerTagType.TAR_SHOT:
|
||||
return new TarShotTag();
|
||||
case BattlerTagType.ELECTRIFIED:
|
||||
return new ElectrifiedTag();
|
||||
case BattlerTagType.THROAT_CHOPPED:
|
||||
return new ThroatChoppedTag();
|
||||
case BattlerTagType.GORILLA_TACTICS:
|
||||
@ -2830,7 +2896,9 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
case BattlerTagType.IMPRISON:
|
||||
return new ImprisonTag(sourceId);
|
||||
case BattlerTagType.SYRUP_BOMB:
|
||||
return new SyrupBombTag();
|
||||
return new SyrupBombTag(sourceId);
|
||||
case BattlerTagType.TELEKINESIS:
|
||||
return new TelekinesisTag(sourceMove);
|
||||
case BattlerTagType.NONE:
|
||||
default:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
|
@ -185,7 +185,7 @@ export abstract class Challenge {
|
||||
*/
|
||||
getDescription(overrideValue?: number): string {
|
||||
const value = overrideValue ?? this.value;
|
||||
return `${i18next.t([`challenges:${this.geti18nKey()}.desc.${value}`, `challenges:${this.geti18nKey()}.desc`])}`;
|
||||
return `${i18next.t([ `challenges:${this.geti18nKey()}.desc.${value}`, `challenges:${this.geti18nKey()}.desc` ])}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -414,9 +414,9 @@ export class SingleGenerationChallenge extends Challenge {
|
||||
}
|
||||
|
||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||
const generations = [pokemon.generation];
|
||||
const generations = [ pokemon.generation ];
|
||||
if (soft) {
|
||||
const speciesToCheck = [pokemon.speciesId];
|
||||
const speciesToCheck = [ pokemon.speciesId ];
|
||||
while (speciesToCheck.length) {
|
||||
const checking = speciesToCheck.pop();
|
||||
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
|
||||
@ -455,7 +455,7 @@ export class SingleGenerationChallenge extends Challenge {
|
||||
trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ];
|
||||
break;
|
||||
case 186:
|
||||
trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE]), TrainerType.LARRY_ELITE ];
|
||||
trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ]), TrainerType.LARRY_ELITE ];
|
||||
break;
|
||||
case 188:
|
||||
trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ];
|
||||
@ -528,10 +528,10 @@ interface monotypeOverride {
|
||||
*/
|
||||
export class SingleTypeChallenge extends Challenge {
|
||||
private static TYPE_OVERRIDES: monotypeOverride[] = [
|
||||
{species: Species.CASTFORM, type: Type.NORMAL, fusion: false},
|
||||
{ species: Species.CASTFORM, type: Type.NORMAL, fusion: false },
|
||||
];
|
||||
// TODO: Find a solution for all Pokemon with this ssui issue, including Basculin and Burmy
|
||||
private static SPECIES_OVERRIDES: Species[] = [Species.MELOETTA];
|
||||
private static SPECIES_OVERRIDES: Species[] = [ Species.MELOETTA ];
|
||||
|
||||
constructor() {
|
||||
super(Challenges.SINGLE_TYPE, 18);
|
||||
@ -539,9 +539,9 @@ export class SingleTypeChallenge extends Challenge {
|
||||
|
||||
override applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||
const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex);
|
||||
const types = [speciesForm.type1, speciesForm.type2];
|
||||
const types = [ speciesForm.type1, speciesForm.type2 ];
|
||||
if (soft && !SingleTypeChallenge.SPECIES_OVERRIDES.includes(pokemon.speciesId)) {
|
||||
const speciesToCheck = [pokemon.speciesId];
|
||||
const speciesToCheck = [ pokemon.speciesId ];
|
||||
while (speciesToCheck.length) {
|
||||
const checking = speciesToCheck.pop();
|
||||
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
|
||||
@ -606,9 +606,9 @@ export class SingleTypeChallenge extends Challenge {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
const type = i18next.t(`pokemonInfo:Type.${Type[this.value - 1]}`);
|
||||
const typeColor = `[color=${TypeColor[Type[this.value-1]]}][shadow=${TypeShadow[Type[this.value-1]]}]${type}[/shadow][/color]`;
|
||||
const typeColor = `[color=${TypeColor[Type[this.value - 1]]}][shadow=${TypeShadow[Type[this.value - 1]]}]${type}[/shadow][/color]`;
|
||||
const defaultDesc = i18next.t("challenges:singleType.desc_default");
|
||||
const typeDesc = i18next.t("challenges:singleType.desc", {type: typeColor});
|
||||
const typeDesc = i18next.t("challenges:singleType.desc", { type: typeColor });
|
||||
return this.value === 0 ? defaultDesc : typeDesc;
|
||||
}
|
||||
|
||||
@ -653,7 +653,7 @@ export class FreshStartChallenge extends Challenge {
|
||||
pokemon.shiny = false; // Not shiny
|
||||
pokemon.variant = 0; // Not shiny
|
||||
pokemon.formIndex = 0; // Froakie should be base form
|
||||
pokemon.ivs = [10, 10, 10, 10, 10, 10]; // Default IVs of 10 for all stats
|
||||
pokemon.ivs = [ 10, 10, 10, 10, 10, 10 ]; // Default IVs of 10 for all stats
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3123,44 +3123,44 @@ export const trainerTypeDialogue: TrainerTypeDialogue = {
|
||||
|
||||
export const doubleBattleDialogue = {
|
||||
"blue_red_double": {
|
||||
encounter: ["doubleBattleDialogue:blue_red_double.encounter.1"],
|
||||
victory: ["doubleBattleDialogue:blue_red_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:blue_red_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:blue_red_double.victory.1" ]
|
||||
},
|
||||
"red_blue_double": {
|
||||
encounter: ["doubleBattleDialogue:red_blue_double.encounter.1"],
|
||||
victory: ["doubleBattleDialogue:red_blue_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:red_blue_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:red_blue_double.victory.1" ]
|
||||
},
|
||||
"tate_liza_double": {
|
||||
encounter: ["doubleBattleDialogue:tate_liza_double.encounter.1"],
|
||||
victory: ["doubleBattleDialogue:tate_liza_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:tate_liza_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:tate_liza_double.victory.1" ]
|
||||
},
|
||||
"liza_tate_double": {
|
||||
encounter: ["doubleBattleDialogue:liza_tate_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:liza_tate_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:liza_tate_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:liza_tate_double.victory.1" ]
|
||||
},
|
||||
"wallace_steven_double": {
|
||||
encounter: [ "doubleBattleDialogue:wallace_steven_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:wallace_steven_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:wallace_steven_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:wallace_steven_double.victory.1" ]
|
||||
},
|
||||
"steven_wallace_double": {
|
||||
encounter: [ "doubleBattleDialogue:steven_wallace_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:steven_wallace_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:steven_wallace_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:steven_wallace_double.victory.1" ]
|
||||
},
|
||||
"alder_iris_double": {
|
||||
encounter: [ "doubleBattleDialogue:alder_iris_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:alder_iris_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:alder_iris_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:alder_iris_double.victory.1" ]
|
||||
},
|
||||
"iris_alder_double": {
|
||||
encounter: [ "doubleBattleDialogue:iris_alder_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:iris_alder_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:iris_alder_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:iris_alder_double.victory.1" ]
|
||||
},
|
||||
"marnie_piers_double": {
|
||||
encounter: [ "doubleBattleDialogue:marnie_piers_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:marnie_piers_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:marnie_piers_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:marnie_piers_double.victory.1" ]
|
||||
},
|
||||
"piers_marnie_double": {
|
||||
encounter: [ "doubleBattleDialogue:piers_marnie_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:piers_marnie_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:piers_marnie_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:piers_marnie_double.victory.1" ]
|
||||
},
|
||||
|
||||
|
||||
@ -3193,7 +3193,7 @@ export function initTrainerTypeDialogue(): void {
|
||||
const trainerTypes = Object.keys(trainerTypeDialogue).map(t => parseInt(t) as TrainerType);
|
||||
for (const trainerType of trainerTypes) {
|
||||
const messages = trainerTypeDialogue[trainerType];
|
||||
const messageTypes = ["encounter", "victory", "defeat"];
|
||||
const messageTypes = [ "encounter", "victory", "defeat" ];
|
||||
for (const messageType of messageTypes) {
|
||||
if (Array.isArray(messages)) {
|
||||
if (messages[0][messageType]) {
|
||||
|
@ -48,7 +48,7 @@ export class EggHatchData {
|
||||
seenCount: currDexEntry.seenCount,
|
||||
caughtCount: currDexEntry.caughtCount,
|
||||
hatchedCount: currDexEntry.hatchedCount,
|
||||
ivs: [...currDexEntry.ivs]
|
||||
ivs: [ ...currDexEntry.ivs ]
|
||||
};
|
||||
this.starterDataEntryBeforeUpdate = {
|
||||
moveset: currStarterDataEntry.moveset,
|
||||
|
@ -11,6 +11,7 @@ import { EggTier } from "#enums/egg-type";
|
||||
import { Species } from "#enums/species";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { MANAPHY_EGG_MANAPHY_RATE, SAME_SPECIES_EGG_HA_RATE, GACHA_EGG_HA_RATE, GACHA_DEFAULT_RARE_EGGMOVE_RATE, SAME_SPECIES_EGG_RARE_EGGMOVE_RATE, GACHA_MOVE_UP_RARE_EGGMOVE_RATE, GACHA_DEFAULT_SHINY_RATE, GACHA_SHINY_UP_SHINY_RATE, SAME_SPECIES_EGG_SHINY_RATE, EGG_PITY_LEGENDARY_THRESHOLD, EGG_PITY_EPIC_THRESHOLD, EGG_PITY_RARE_THRESHOLD, SHINY_VARIANT_CHANCE, SHINY_EPIC_CHANCE, GACHA_DEFAULT_COMMON_EGG_THRESHOLD, GACHA_DEFAULT_RARE_EGG_THRESHOLD, GACHA_DEFAULT_EPIC_EGG_THRESHOLD, GACHA_LEGENDARY_UP_THRESHOLD_OFFSET, HATCH_WAVES_MANAPHY_EGG, HATCH_WAVES_COMMON_EGG, HATCH_WAVES_RARE_EGG, HATCH_WAVES_EPIC_EGG, HATCH_WAVES_LEGENDARY_EGG } from "#app/data/balance/rates";
|
||||
import { speciesEggTiers } from "#app/data/balance/species-egg-tiers";
|
||||
|
||||
export const EGG_SEED = 1073741824;
|
||||
|
||||
@ -160,7 +161,7 @@ export class Egg {
|
||||
|
||||
// Override egg tier and hatchwaves if species was given
|
||||
if (eggOptions?.species) {
|
||||
this._tier = this.getEggTierFromSpeciesStarterValue();
|
||||
this._tier = this.getEggTier();
|
||||
this._hatchWaves = eggOptions.hatchWaves ?? this.getEggTierDefaultHatchWaves();
|
||||
}
|
||||
// If species has no variant, set variantTier to common. This needs to
|
||||
@ -261,11 +262,11 @@ export class Egg {
|
||||
return "Manaphy";
|
||||
}
|
||||
switch (this.tier) {
|
||||
case EggTier.GREAT:
|
||||
case EggTier.RARE:
|
||||
return i18next.t("egg:greatTier");
|
||||
case EggTier.ULTRA:
|
||||
case EggTier.EPIC:
|
||||
return i18next.t("egg:ultraTier");
|
||||
case EggTier.MASTER:
|
||||
case EggTier.LEGENDARY:
|
||||
return i18next.t("egg:masterTier");
|
||||
default:
|
||||
return i18next.t("egg:defaultTier");
|
||||
@ -288,7 +289,7 @@ export class Egg {
|
||||
public getEggTypeDescriptor(scene: BattleScene): string {
|
||||
switch (this.sourceType) {
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName()});
|
||||
return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName() });
|
||||
case EggSourceType.GACHA_LEGENDARY:
|
||||
return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`;
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
@ -336,9 +337,9 @@ export class Egg {
|
||||
switch (eggTier ?? this._tier) {
|
||||
case EggTier.COMMON:
|
||||
return HATCH_WAVES_COMMON_EGG;
|
||||
case EggTier.GREAT:
|
||||
case EggTier.RARE:
|
||||
return HATCH_WAVES_RARE_EGG;
|
||||
case EggTier.ULTRA:
|
||||
case EggTier.EPIC:
|
||||
return HATCH_WAVES_EPIC_EGG;
|
||||
}
|
||||
return HATCH_WAVES_LEGENDARY_EGG;
|
||||
@ -347,7 +348,7 @@ export class Egg {
|
||||
private rollEggTier(): EggTier {
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0;
|
||||
const tierValue = Utils.randInt(256);
|
||||
return tierValue >= GACHA_DEFAULT_COMMON_EGG_THRESHOLD + tierValueOffset ? EggTier.COMMON : tierValue >= GACHA_DEFAULT_RARE_EGG_THRESHOLD + tierValueOffset ? EggTier.GREAT : tierValue >= GACHA_DEFAULT_EPIC_EGG_THRESHOLD + tierValueOffset ? EggTier.ULTRA : EggTier.MASTER;
|
||||
return tierValue >= GACHA_DEFAULT_COMMON_EGG_THRESHOLD + tierValueOffset ? EggTier.COMMON : tierValue >= GACHA_DEFAULT_RARE_EGG_THRESHOLD + tierValueOffset ? EggTier.RARE : tierValue >= GACHA_DEFAULT_EPIC_EGG_THRESHOLD + tierValueOffset ? EggTier.EPIC : EggTier.LEGENDARY;
|
||||
}
|
||||
|
||||
private rollSpecies(scene: BattleScene): Species | null {
|
||||
@ -367,7 +368,7 @@ export class Egg {
|
||||
*/
|
||||
const rand = (Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) !== 1);
|
||||
return rand ? Species.PHIONE : Species.MANAPHY;
|
||||
} else if (this.tier === EggTier.MASTER
|
||||
} else if (this.tier === EggTier.LEGENDARY
|
||||
&& this._sourceType === EggSourceType.GACHA_LEGENDARY) {
|
||||
if (!Utils.randSeedInt(2)) {
|
||||
return getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp);
|
||||
@ -378,15 +379,15 @@ export class Egg {
|
||||
let maxStarterValue: integer;
|
||||
|
||||
switch (this.tier) {
|
||||
case EggTier.GREAT:
|
||||
case EggTier.RARE:
|
||||
minStarterValue = 4;
|
||||
maxStarterValue = 5;
|
||||
break;
|
||||
case EggTier.ULTRA:
|
||||
case EggTier.EPIC:
|
||||
minStarterValue = 6;
|
||||
maxStarterValue = 7;
|
||||
break;
|
||||
case EggTier.MASTER:
|
||||
case EggTier.LEGENDARY:
|
||||
minStarterValue = 8;
|
||||
maxStarterValue = 9;
|
||||
break;
|
||||
@ -396,10 +397,10 @@ export class Egg {
|
||||
break;
|
||||
}
|
||||
|
||||
const ignoredSpecies = [Species.PHIONE, Species.MANAPHY, Species.ETERNATUS];
|
||||
const ignoredSpecies = [ Species.PHIONE, Species.MANAPHY, Species.ETERNATUS ];
|
||||
|
||||
let speciesPool = Object.keys(speciesStarterCosts)
|
||||
.filter(s => speciesStarterCosts[s] >= minStarterValue && speciesStarterCosts[s] <= maxStarterValue)
|
||||
let speciesPool = Object.keys(speciesEggTiers)
|
||||
.filter(s => speciesEggTiers[s] === this.tier)
|
||||
.map(s => parseInt(s) as Species)
|
||||
.filter(s => !pokemonPrevolutions.hasOwnProperty(s) && getPokemonSpecies(s).isObtainable() && ignoredSpecies.indexOf(s) === -1);
|
||||
|
||||
@ -430,7 +431,9 @@ export class Egg {
|
||||
let totalWeight = 0;
|
||||
const speciesWeights : number[] = [];
|
||||
for (const speciesId of speciesPool) {
|
||||
let weight = Math.floor((((maxStarterValue - speciesStarterCosts[speciesId]) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100);
|
||||
// Accounts for species that have starter costs outside of the normal range for their EggTier
|
||||
const speciesCostClamped = Phaser.Math.Clamp(speciesStarterCosts[speciesId], minStarterValue, maxStarterValue);
|
||||
let weight = Math.floor((((maxStarterValue - speciesCostClamped) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100);
|
||||
const species = getPokemonSpecies(speciesId);
|
||||
if (species.isRegional()) {
|
||||
weight = Math.floor(weight / 2);
|
||||
@ -498,16 +501,16 @@ export class Egg {
|
||||
|
||||
private checkForPityTierOverrides(scene: BattleScene): void {
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0;
|
||||
scene.gameData.eggPity[EggTier.GREAT] += 1;
|
||||
scene.gameData.eggPity[EggTier.ULTRA] += 1;
|
||||
scene.gameData.eggPity[EggTier.MASTER] += 1 + tierValueOffset;
|
||||
scene.gameData.eggPity[EggTier.RARE] += 1;
|
||||
scene.gameData.eggPity[EggTier.EPIC] += 1;
|
||||
scene.gameData.eggPity[EggTier.LEGENDARY] += 1 + tierValueOffset;
|
||||
// These numbers are roughly the 80% mark. That is, 80% of the time you'll get an egg before this gets triggered.
|
||||
if (scene.gameData.eggPity[EggTier.MASTER] >= EGG_PITY_LEGENDARY_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.MASTER;
|
||||
} else if (scene.gameData.eggPity[EggTier.ULTRA] >= EGG_PITY_EPIC_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.ULTRA;
|
||||
} else if (scene.gameData.eggPity[EggTier.GREAT] >= EGG_PITY_RARE_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.GREAT;
|
||||
if (scene.gameData.eggPity[EggTier.LEGENDARY] >= EGG_PITY_LEGENDARY_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.LEGENDARY;
|
||||
} else if (scene.gameData.eggPity[EggTier.EPIC] >= EGG_PITY_EPIC_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.EPIC;
|
||||
} else if (scene.gameData.eggPity[EggTier.RARE] >= EGG_PITY_RARE_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.RARE;
|
||||
}
|
||||
scene.gameData.eggPity[this._tier] = 0;
|
||||
}
|
||||
@ -516,38 +519,24 @@ export class Egg {
|
||||
scene.gameData.gameStats.eggsPulled++;
|
||||
if (this.isManaphyEgg()) {
|
||||
scene.gameData.gameStats.manaphyEggsPulled++;
|
||||
this._hatchWaves = this.getEggTierDefaultHatchWaves(EggTier.ULTRA);
|
||||
this._hatchWaves = this.getEggTierDefaultHatchWaves(EggTier.EPIC);
|
||||
return;
|
||||
}
|
||||
switch (this.tier) {
|
||||
case EggTier.GREAT:
|
||||
case EggTier.RARE:
|
||||
scene.gameData.gameStats.rareEggsPulled++;
|
||||
break;
|
||||
case EggTier.ULTRA:
|
||||
case EggTier.EPIC:
|
||||
scene.gameData.gameStats.epicEggsPulled++;
|
||||
break;
|
||||
case EggTier.MASTER:
|
||||
case EggTier.LEGENDARY:
|
||||
scene.gameData.gameStats.legendaryEggsPulled++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private getEggTierFromSpeciesStarterValue(): EggTier {
|
||||
const speciesStartValue = speciesStarterCosts[this.species];
|
||||
if (speciesStartValue >= 1 && speciesStartValue <= 3) {
|
||||
return EggTier.COMMON;
|
||||
}
|
||||
if (speciesStartValue >= 4 && speciesStartValue <= 5) {
|
||||
return EggTier.GREAT;
|
||||
}
|
||||
if (speciesStartValue >= 6 && speciesStartValue <= 7) {
|
||||
return EggTier.ULTRA;
|
||||
}
|
||||
if (speciesStartValue >= 8) {
|
||||
return EggTier.MASTER;
|
||||
}
|
||||
|
||||
return EggTier.COMMON;
|
||||
private getEggTier(): EggTier {
|
||||
return speciesEggTiers[this.species];
|
||||
}
|
||||
|
||||
////
|
||||
@ -556,8 +545,8 @@ export class Egg {
|
||||
}
|
||||
|
||||
export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timestamp: number): Species {
|
||||
const legendarySpecies = Object.entries(speciesStarterCosts)
|
||||
.filter(s => s[1] >= 8 && s[1] <= 9)
|
||||
const legendarySpecies = Object.entries(speciesEggTiers)
|
||||
.filter(s => s[1] === EggTier.LEGENDARY)
|
||||
.map(s => parseInt(s[0]))
|
||||
.filter(s => getPokemonSpecies(s).isObtainable());
|
||||
|
||||
@ -579,17 +568,9 @@ export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timesta
|
||||
|
||||
/**
|
||||
* Check for a given species EggTier Value
|
||||
* @param species - Species for wich we will check the egg tier it belongs to
|
||||
* @param pokemonSpecies - Species for wich we will check the egg tier it belongs to
|
||||
* @returns The egg tier of a given pokemon species
|
||||
*/
|
||||
export function getEggTierForSpecies(pokemonSpecies :PokemonSpecies): EggTier {
|
||||
const speciesBaseValue = speciesStarterCosts[pokemonSpecies.getRootSpeciesId()];
|
||||
if (speciesBaseValue <= 3) {
|
||||
return EggTier.COMMON;
|
||||
} else if (speciesBaseValue <= 5) {
|
||||
return EggTier.GREAT;
|
||||
} else if (speciesBaseValue <= 7) {
|
||||
return EggTier.ULTRA;
|
||||
}
|
||||
return EggTier.MASTER;
|
||||
return speciesEggTiers[pokemonSpecies.getRootSpeciesId()];
|
||||
}
|
||||
|
659
src/data/move.ts
@ -128,6 +128,7 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -149,10 +150,10 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
||||
pulled: false,
|
||||
sourceType: EggSourceType.EVENT,
|
||||
eggDescriptor: encounter.misc.trainerEggDescription,
|
||||
tier: EggTier.ULTRA
|
||||
tier: EggTier.EPIC
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.epic`));
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SACRED_ASH ], guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ULTRA ], fillRemaining: true }, [ eggOptions ]);
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
)
|
||||
@ -171,10 +172,10 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
||||
pulled: false,
|
||||
sourceType: EggSourceType.EVENT,
|
||||
eggDescriptor: encounter.misc.trainerEggDescription,
|
||||
tier: EggTier.GREAT
|
||||
tier: EggTier.RARE
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.rare`));
|
||||
setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [eggOptions]);
|
||||
setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [ eggOptions ]);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
|
@ -166,6 +166,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -195,7 +196,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
// Can't define stack count on a ModifierType, have to just create separate instances for each stack
|
||||
// Overflow berries will be "lost" on the boss, but it's un-catchable anyway
|
||||
for (let i = 0; i < berryMod.stackCount; i++) {
|
||||
const modifierType = generateModifierType(scene, modifierTypes.BERRY, [berryMod.berryType]) as PokemonHeldItemModifierType;
|
||||
const modifierType = generateModifierType(scene, modifierTypes.BERRY, [ berryMod.berryType ]) as PokemonHeldItemModifierType;
|
||||
bossModifierConfigs.push({ modifier: modifierType });
|
||||
}
|
||||
});
|
||||
@ -204,8 +205,8 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
|
||||
// SpDef buff below wave 50, +1 to all stats otherwise
|
||||
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
|
||||
[Stat.SPDEF] :
|
||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
|
||||
[ Stat.SPDEF ] :
|
||||
[ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ];
|
||||
|
||||
// Calculate boss mon
|
||||
const config: EnemyPartyConfig = {
|
||||
@ -215,9 +216,9 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
species: getPokemonSpecies(Species.GREEDENT),
|
||||
isBoss: true,
|
||||
bossSegments: 3,
|
||||
moveSet: [Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH],
|
||||
moveSet: [ Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH ],
|
||||
modifierConfigs: bossModifierConfigs,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.1.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
||||
@ -226,7 +227,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
],
|
||||
};
|
||||
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
encounter.setDialogueToken("greedentName", getPokemonSpecies(Species.GREEDENT).getName());
|
||||
|
||||
return true;
|
||||
@ -280,7 +281,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, givePartyPokemonReviverSeeds);
|
||||
encounter.startOfBattleEffects.push({
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
targets: [ BattlerIndex.ENEMY ],
|
||||
move: new PokemonMove(Moves.STUFF_CHEEKS),
|
||||
ignorePp: true
|
||||
});
|
||||
@ -320,7 +321,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
Phaser.Math.RND.shuffle(berryTypesAsArray);
|
||||
const randBerryType = berryTypesAsArray.pop();
|
||||
|
||||
const berryModType = generateModifierType(scene, modifierTypes.BERRY, [randBerryType]) as BerryModifierType;
|
||||
const berryModType = generateModifierType(scene, modifierTypes.BERRY, [ randBerryType ]) as BerryModifierType;
|
||||
applyModifierTypeToPlayerPokemon(scene, pokemon, berryModType);
|
||||
}
|
||||
}
|
||||
@ -355,7 +356,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
// Greedent joins the team, level equal to 2 below highest party member
|
||||
const level = getHighestLevelPlayerPokemon(scene, false, true).level - 2;
|
||||
const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false);
|
||||
greedent.moveset = [new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF)];
|
||||
greedent.moveset = [ new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF) ];
|
||||
greedent.passive = true;
|
||||
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
@ -472,7 +473,7 @@ function doGreedentEatBerries(scene: BattleScene) {
|
||||
*/
|
||||
function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) {
|
||||
const berryAddDelay = 150;
|
||||
let animationOrder = ["starf", "sitrus", "lansat", "salac", "apicot", "enigma", "liechi", "ganlon", "lum", "petaya", "leppa"];
|
||||
let animationOrder = [ "starf", "sitrus", "lansat", "salac", "apicot", "enigma", "liechi", "ganlon", "lum", "petaya", "leppa" ];
|
||||
if (isEat) {
|
||||
animationOrder = animationOrder.reverse();
|
||||
}
|
||||
@ -496,7 +497,7 @@ function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) {
|
||||
// Animate Petaya berry falling off the pile
|
||||
if (berry === "petaya" && sprite && tintSprite && !isEat) {
|
||||
scene.time.delayedCall(200, () => {
|
||||
doBerryBounce(scene, [sprite, tintSprite], 30, 500);
|
||||
doBerryBounce(scene, [ sprite, tintSprite ], 30, 500);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -64,6 +64,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
|
@ -69,7 +69,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
isBoss: true
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Calculate the number of extra berries that player receives
|
||||
// 10-40: 2, 40-120: 4, 120-160: 5, 160-180: 7
|
||||
@ -110,6 +110,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -193,11 +194,11 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
|
||||
// Defense/Spd buffs below wave 50, +1 to all stats otherwise
|
||||
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
|
||||
[Stat.DEF, Stat.SPDEF, Stat.SPD] :
|
||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
|
||||
[ Stat.DEF, Stat.SPDEF, Stat.SPD ] :
|
||||
[ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ];
|
||||
|
||||
const config = scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
|
||||
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||
config.pokemonConfigs![0].tags = [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ];
|
||||
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.2.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
||||
@ -208,7 +209,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
return;
|
||||
} else {
|
||||
// Gains 1 berry for every 10% faster the player's pokemon is than the enemy, up to a max of numBerries, minimum of 2
|
||||
const numBerriesGrabbed = Math.max(Math.min(Math.round((speedDiff - 1)/0.08), numBerries), 2);
|
||||
const numBerriesGrabbed = Math.max(Math.min(Math.round((speedDiff - 1) / 0.08), numBerries), 2);
|
||||
encounter.setDialogueToken("numBerries", String(numBerriesGrabbed));
|
||||
const doFasterBerryRewards = () => {
|
||||
const berryText = i18next.t(`${namespace}:berries`);
|
||||
@ -250,7 +251,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
|
||||
function tryGiveBerry(scene: BattleScene, prioritizedPokemon?: PlayerPokemon) {
|
||||
const berryType = randSeedInt(Object.keys(BerryType).filter(s => !isNaN(Number(s))).length) as BerryType;
|
||||
const berry = generateModifierType(scene, modifierTypes.BERRY, [berryType]) as BerryModifierType;
|
||||
const berry = generateModifierType(scene, modifierTypes.BERRY, [ berryType ]) as BerryModifierType;
|
||||
|
||||
const party = scene.getParty();
|
||||
|
||||
|
@ -181,7 +181,7 @@ const MISC_TUTOR_MOVES = [
|
||||
/**
|
||||
* Wave breakpoints that determine how strong to make the Bug-Type Superfan's team
|
||||
*/
|
||||
const WAVE_LEVEL_BREAKPOINTS = [30, 50, 70, 100, 120, 140, 160];
|
||||
const WAVE_LEVEL_BREAKPOINTS = [ 30, 50, 70, 100, 120, 140, 160 ];
|
||||
|
||||
/**
|
||||
* Bug Type Superfan encounter.
|
||||
@ -193,7 +193,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||
// Must have at least 1 Bug type on team, OR have a bug item somewhere on the team
|
||||
new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1),
|
||||
new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1),
|
||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1),
|
||||
new TypeRequirement(Type.BUG, false, 1)
|
||||
))
|
||||
@ -268,7 +268,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
const requiredItems = [
|
||||
generateModifierType(scene, modifierTypes.QUICK_CLAW),
|
||||
generateModifierType(scene, modifierTypes.GRIP_CLAW),
|
||||
generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.BUG]),
|
||||
generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.BUG ]),
|
||||
];
|
||||
|
||||
const requiredItemString = requiredItems.map(m => m?.name ?? "unknown").join("/");
|
||||
@ -276,6 +276,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -331,7 +332,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
encounter.setDialogueToken("numBugTypes", numBugTypesText);
|
||||
|
||||
if (numBugTypes < 2) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL ], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}:speaker`,
|
||||
@ -339,7 +340,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
},
|
||||
];
|
||||
} else if (numBugTypes < 4) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.QUICK_CLAW, modifierTypes.MAX_LURE, modifierTypes.ULTRA_BALL], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.QUICK_CLAW, modifierTypes.MAX_LURE, modifierTypes.ULTRA_BALL ], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}:speaker`,
|
||||
@ -347,7 +348,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
},
|
||||
];
|
||||
} else if (numBugTypes < 6) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.GRIP_CLAW, modifierTypes.MAX_LURE, modifierTypes.ROGUE_BALL], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.GRIP_CLAW, modifierTypes.MAX_LURE, modifierTypes.ROGUE_BALL ], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}:speaker`,
|
||||
@ -356,7 +357,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
];
|
||||
} else {
|
||||
// If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to a Master Ball
|
||||
const modifierOptions: ModifierTypeOption[] = [generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)!];
|
||||
const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)! ];
|
||||
const specialOptions: ModifierTypeOption[] = [];
|
||||
|
||||
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
|
||||
@ -397,7 +398,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||
// Meets one or both of the below reqs
|
||||
new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1),
|
||||
new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1),
|
||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1)
|
||||
))
|
||||
.withDialogue({
|
||||
@ -474,7 +475,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
const bugNet = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!;
|
||||
bugNet.type.tier = ModifierTier.ROGUE;
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [bugNet], guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ bugNet ], guaranteedModifierTypeFuncs: [ modifierTypes.REVIVER_SEED ], fillRemaining: false });
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build())
|
||||
@ -535,7 +536,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -558,14 +559,14 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon2.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ pool3Mon2.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon2.formIndex)) {
|
||||
p.formIndex = pool3Mon2.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -586,7 +587,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -611,14 +612,14 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon2.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon2.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon2.formIndex)) {
|
||||
p.formIndex = pool3Mon2.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
|
@ -129,25 +129,26 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
{
|
||||
species: getPokemonSpecies(Species.MR_MIME),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC]
|
||||
moveSet: [ Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC ]
|
||||
},
|
||||
{ // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
|
||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ ability: ability, types: [randSeedInt(18), randSeedInt(18)] }),
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ]}),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN]
|
||||
moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ]
|
||||
},
|
||||
],
|
||||
doubleBattle: true
|
||||
});
|
||||
|
||||
// Load animations/sfx for start of fight moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.ROLE_PLAY, Moves.TAUNT]);
|
||||
loadCustomMovesForEncounter(scene, [ Moves.ROLE_PLAY, Moves.TAUNT ]);
|
||||
|
||||
encounter.setDialogueToken("blacephalonName", getPokemonSpecies(Species.BLACEPHALON).getName());
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -175,19 +176,19 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
encounter.startOfBattleEffects.push(
|
||||
{ // Mr. Mime copies the Blacephalon's random ability
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY_2],
|
||||
targets: [ BattlerIndex.ENEMY_2 ],
|
||||
move: new PokemonMove(Moves.ROLE_PLAY),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.TAUNT),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER_2],
|
||||
targets: [ BattlerIndex.PLAYER_2 ],
|
||||
move: new PokemonMove(Moves.TAUNT),
|
||||
ignorePp: true
|
||||
});
|
||||
@ -336,11 +337,11 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
.filter(move => move && !originalTypes.includes(move.getMove().type) && move.getMove().category !== MoveCategory.STATUS)
|
||||
.map(move => move!.getMove().type);
|
||||
if (priorityTypes?.length > 0) {
|
||||
priorityTypes = [...new Set(priorityTypes)].sort();
|
||||
priorityTypes = [ ...new Set(priorityTypes) ].sort();
|
||||
priorityTypes = randSeedShuffle(priorityTypes);
|
||||
}
|
||||
|
||||
const newTypes = [originalTypes[0]];
|
||||
const newTypes = [ originalTypes[0] ];
|
||||
let secondType: Type | null = null;
|
||||
while (secondType === null || secondType === newTypes[0] || originalTypes.includes(secondType)) {
|
||||
if (priorityTypes.length > 0) {
|
||||
@ -453,37 +454,37 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem
|
||||
// Pools have instances of the modifier type equal to the max stacks that modifier can be applied to any one pokemon
|
||||
// This is to prevent "over-generating" a random item of a certain type during item swaps
|
||||
const ultraPool = [
|
||||
[modifierTypes.REVIVER_SEED, 1],
|
||||
[modifierTypes.GOLDEN_PUNCH, 5],
|
||||
[modifierTypes.ATTACK_TYPE_BOOSTER, 99],
|
||||
[modifierTypes.QUICK_CLAW, 3],
|
||||
[modifierTypes.WIDE_LENS, 3]
|
||||
[ modifierTypes.REVIVER_SEED, 1 ],
|
||||
[ modifierTypes.GOLDEN_PUNCH, 5 ],
|
||||
[ modifierTypes.ATTACK_TYPE_BOOSTER, 99 ],
|
||||
[ modifierTypes.QUICK_CLAW, 3 ],
|
||||
[ modifierTypes.WIDE_LENS, 3 ]
|
||||
];
|
||||
|
||||
const roguePool = [
|
||||
[modifierTypes.LEFTOVERS, 4],
|
||||
[modifierTypes.SHELL_BELL, 4],
|
||||
[modifierTypes.SOUL_DEW, 10],
|
||||
[modifierTypes.SOOTHE_BELL, 3],
|
||||
[modifierTypes.SCOPE_LENS, 1],
|
||||
[modifierTypes.BATON, 1],
|
||||
[modifierTypes.FOCUS_BAND, 5],
|
||||
[modifierTypes.KINGS_ROCK, 3],
|
||||
[modifierTypes.GRIP_CLAW, 5]
|
||||
[ modifierTypes.LEFTOVERS, 4 ],
|
||||
[ modifierTypes.SHELL_BELL, 4 ],
|
||||
[ modifierTypes.SOUL_DEW, 10 ],
|
||||
[ modifierTypes.SOOTHE_BELL, 3 ],
|
||||
[ modifierTypes.SCOPE_LENS, 1 ],
|
||||
[ modifierTypes.BATON, 1 ],
|
||||
[ modifierTypes.FOCUS_BAND, 5 ],
|
||||
[ modifierTypes.KINGS_ROCK, 3 ],
|
||||
[ modifierTypes.GRIP_CLAW, 5 ]
|
||||
];
|
||||
|
||||
const berryPool = [
|
||||
[BerryType.APICOT, 3],
|
||||
[BerryType.ENIGMA, 2],
|
||||
[BerryType.GANLON, 3],
|
||||
[BerryType.LANSAT, 3],
|
||||
[BerryType.LEPPA, 2],
|
||||
[BerryType.LIECHI, 3],
|
||||
[BerryType.LUM, 2],
|
||||
[BerryType.PETAYA, 3],
|
||||
[BerryType.SALAC, 2],
|
||||
[BerryType.SITRUS, 2],
|
||||
[BerryType.STARF, 3]
|
||||
[ BerryType.APICOT, 3 ],
|
||||
[ BerryType.ENIGMA, 2 ],
|
||||
[ BerryType.GANLON, 3 ],
|
||||
[ BerryType.LANSAT, 3 ],
|
||||
[ BerryType.LEPPA, 2 ],
|
||||
[ BerryType.LIECHI, 3 ],
|
||||
[ BerryType.LUM, 2 ],
|
||||
[ BerryType.PETAYA, 3 ],
|
||||
[ BerryType.SALAC, 2 ],
|
||||
[ BerryType.SITRUS, 2 ],
|
||||
[ BerryType.STARF, 3 ]
|
||||
];
|
||||
|
||||
let pool: any[];
|
||||
@ -502,7 +503,7 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem
|
||||
const newItemType = pool[randIndex];
|
||||
let newMod: PokemonHeldItemModifierType;
|
||||
if (tier === "Berries") {
|
||||
newMod = generateModifierType(scene, modifierTypes.BERRY, [newItemType[0]]) as PokemonHeldItemModifierType;
|
||||
newMod = generateModifierType(scene, modifierTypes.BERRY, [ newItemType[0] ]) as PokemonHeldItemModifierType;
|
||||
} else {
|
||||
newMod = generateModifierType(scene, newItemType[0]) as PokemonHeldItemModifierType;
|
||||
}
|
||||
|
@ -102,6 +102,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -141,7 +142,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
scene.getEnemyParty().forEach(enemyPokemon => {
|
||||
scene.field.remove(enemyPokemon, true);
|
||||
});
|
||||
scene.currentBattle.enemyParty = [oricorio];
|
||||
scene.currentBattle.enemyParty = [ oricorio ];
|
||||
scene.field.add(oricorio);
|
||||
// Spawns on offscreen field
|
||||
oricorio.x -= 300;
|
||||
@ -153,14 +154,14 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
dataSource: oricorioData,
|
||||
isBoss: true,
|
||||
// Gets +1 to all stats except SPD on battle start
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.1.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF], 1));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF ], 1));
|
||||
}
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
encounter.misc = {
|
||||
oricorioData
|
||||
};
|
||||
@ -187,13 +188,13 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
|
||||
encounter.startOfBattleEffects.push({
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.REVELATION_DANCE),
|
||||
ignorePp: true
|
||||
});
|
||||
|
||||
await hideOricorioPokemon(scene);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.BATON], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.BATON ], fillRemaining: true });
|
||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||
})
|
||||
.build()
|
||||
|
@ -117,6 +117,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||
.withSceneWaveRangeRequirement(30, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1])
|
||||
.withScenePartySizeRequirement(2, 6, true) // Must have at least 2 pokemon in party
|
||||
.withCatchAllowed(true)
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -164,7 +165,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||
// Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+
|
||||
const roll = randSeedInt(100);
|
||||
const starterTier: number | [number, number] =
|
||||
roll >= 65 ? 6 : roll >= 15 ? 7 : roll >= 5 ? 8 : [9, 10];
|
||||
roll >= 65 ? 6 : roll >= 15 ? 7 : roll >= 5 ? 8 : [ 9, 10 ];
|
||||
const bossSpecies = getPokemonSpecies(getRandomSpeciesByStarterTier(starterTier, excludedBosses, bossTypes));
|
||||
const pokemonConfig: EnemyPokemonConfig = {
|
||||
species: bossSpecies,
|
||||
@ -179,7 +180,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||
pokemonConfig.formIndex = 0;
|
||||
}
|
||||
const config: EnemyPartyConfig = {
|
||||
pokemonConfigs: [pokemonConfig],
|
||||
pokemonConfigs: [ pokemonConfig ],
|
||||
};
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
|
@ -22,7 +22,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
const namespace = "mysteryEncounters/delibirdy";
|
||||
|
||||
/** Berries only */
|
||||
const OPTION_2_ALLOWED_MODIFIERS = ["BerryModifier", "PokemonInstantReviveModifier"];
|
||||
const OPTION_2_ALLOWED_MODIFIERS = [ "BerryModifier", "PokemonInstantReviveModifier" ];
|
||||
|
||||
/** Disallowed items are berries, Reviver Seeds, and Vitamins (form change items and fusion items are not PokemonHeldItemModifiers) */
|
||||
const OPTION_3_DISALLOWED_MODIFIERS = [
|
||||
@ -84,6 +84,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
|
@ -51,6 +51,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
|
@ -52,6 +52,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -87,9 +88,9 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ATK])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.DEF])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.ATK ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.DEF ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
];
|
||||
@ -133,9 +134,9 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPATK])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPDEF])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPATK ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPDEF ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
];
|
||||
@ -179,8 +180,8 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ACC])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.ACC ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.GREAT_BALL)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.IV_SCANNER)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
@ -227,7 +228,7 @@ function pokemonAndMoveChosen(scene: BattleScene, pokemon: PlayerPokemon, move:
|
||||
text: `${namespace}:correct_exp`,
|
||||
},
|
||||
];
|
||||
setEncounterExp(scene, [pokemon.id], 100);
|
||||
setEncounterExp(scene, [ pokemon.id ], 100);
|
||||
}
|
||||
encounter.misc = {
|
||||
correctMove: correctMove,
|
||||
|
@ -73,7 +73,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
doubleBattle: true,
|
||||
disableSwitch: true
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Load hidden Volcarona sprites
|
||||
encounter.spriteConfigs = [
|
||||
@ -99,7 +99,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
];
|
||||
|
||||
// Load animations/sfx for Volcarona moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.FIRE_SPIN, Moves.QUIVER_DANCE]);
|
||||
loadCustomMovesForEncounter(scene, [ Moves.FIRE_SPIN, Moves.QUIVER_DANCE ]);
|
||||
|
||||
scene.arena.trySetWeather(WeatherType.SUNNY, true);
|
||||
|
||||
@ -122,6 +122,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -143,25 +144,25 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER_2],
|
||||
targets: [ BattlerIndex.PLAYER_2 ],
|
||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
targets: [ BattlerIndex.ENEMY ],
|
||||
move: new PokemonMove(Moves.QUIVER_DANCE),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.ENEMY_2],
|
||||
targets: [ BattlerIndex.ENEMY_2 ],
|
||||
move: new PokemonMove(Moves.QUIVER_DANCE),
|
||||
ignorePp: true
|
||||
});
|
||||
@ -237,7 +238,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
const primary = encounter.options[2].primaryPokemon!;
|
||||
const secondary = encounter.options[2].secondaryPokemon![0];
|
||||
|
||||
setEncounterExp(scene, [primary.id, secondary.id], getPokemonSpecies(Species.VOLCARONA).baseExp * 2);
|
||||
setEncounterExp(scene, [ primary.id, secondary.id ], getPokemonSpecies(Species.VOLCARONA).baseExp * 2);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.build()
|
||||
@ -248,7 +249,7 @@ function giveLeadPokemonCharcoal(scene: BattleScene) {
|
||||
// Give first party pokemon Charcoal for free at end of battle
|
||||
const leadPokemon = scene.getParty()?.[0];
|
||||
if (leadPokemon) {
|
||||
const charcoal = generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]) as AttackTypeBoosterModifierType;
|
||||
const charcoal = generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.FIRE ]) as AttackTypeBoosterModifierType;
|
||||
applyModifierTypeToPlayerPokemon(scene, leadPokemon, charcoal);
|
||||
scene.currentBattle.mysteryEncounter!.setDialogueToken("leadPokemon", leadPokemon.getNameToRender());
|
||||
queueEncounterMessage(scene, `${namespace}:found_charcoal`);
|
||||
|
@ -65,16 +65,16 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
species: bossSpecies,
|
||||
dataSource: new PokemonData(bossPokemon),
|
||||
isBoss: true,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.1.stat_boost`);
|
||||
// Randomly boost 1 stat 2 stages
|
||||
// Cannot boost Spd, Acc, or Evasion
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [randSeedInt(4, 1)], 2));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randSeedInt(4, 1) ], 2));
|
||||
}
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Calculate item
|
||||
// Waves 10-40 GREAT, 60-120 ULTRA, 120-160 ROGUE, 160-180 MASTER
|
||||
@ -90,7 +90,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
let item: ModifierTypeOption | null = null;
|
||||
// TMs and Candy Jar excluded from possible rewards as they're too swingy in value for a singular item reward
|
||||
while (!item || item.type.id.includes("TM_") || item.type.id === "CANDY_JAR") {
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier], allowLuckUpgrades: false })[0];
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [ tier ], allowLuckUpgrades: false })[0];
|
||||
}
|
||||
encounter.setDialogueToken("itemName", item.type.name);
|
||||
encounter.misc = item;
|
||||
@ -120,6 +120,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -137,7 +138,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
// Pick battle
|
||||
// Pokemon will randomly boost 1 stat by 2 stages
|
||||
const item = scene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false });
|
||||
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]);
|
||||
}
|
||||
)
|
||||
@ -159,7 +160,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
// Pick steal
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const item = scene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false });
|
||||
|
||||
// Use primaryPokemon to execute the thievery
|
||||
const primaryPokemon = encounter.options[1].primaryPokemon!;
|
||||
|
@ -76,6 +76,7 @@ export const FunAndGamesEncounter: MysteryEncounter =
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -197,7 +198,7 @@ async function summonPlayerPokemon(scene: BattleScene) {
|
||||
const enemySpecies = getPokemonSpecies(Species.WOBBUFFET);
|
||||
scene.currentBattle.enemyParty = [];
|
||||
const wobbuffet = scene.addEnemyPokemon(enemySpecies, encounter.misc.playerPokemon.level, TrainerSlot.NONE, false);
|
||||
wobbuffet.ivs = [0, 0, 0, 0, 0, 0];
|
||||
wobbuffet.ivs = [ 0, 0, 0, 0, 0, 0 ];
|
||||
wobbuffet.setNature(Nature.MILD);
|
||||
wobbuffet.setAlpha(0);
|
||||
wobbuffet.setVisible(false);
|
||||
@ -256,15 +257,15 @@ function handleNextTurn(scene: BattleScene) {
|
||||
let isHealPhase = false;
|
||||
if (healthRatio < 0.03) {
|
||||
// Grand prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MULTI_LENS], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.MULTI_LENS ], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}:best_result`;
|
||||
} else if (healthRatio < 0.15) {
|
||||
// 2nd prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SCOPE_LENS], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SCOPE_LENS ], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}:great_result`;
|
||||
} else if (healthRatio < 0.33) {
|
||||
// 3rd prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.WIDE_LENS], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.WIDE_LENS ], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}:good_result`;
|
||||
} else {
|
||||
// No prize
|
||||
@ -411,7 +412,7 @@ function hideShowmanIntroSprite(scene: BattleScene) {
|
||||
|
||||
// Slide the Wobbuffet and Game over slightly
|
||||
scene.tweens.add({
|
||||
targets: [wobbuffet, carnivalGame],
|
||||
targets: [ wobbuffet, carnivalGame ],
|
||||
x: "+=16",
|
||||
ease: "Sine.easeInOut",
|
||||
duration: 750
|
||||
|
@ -35,15 +35,15 @@ const WONDER_TRADE_SHINY_CHANCE = 512;
|
||||
const MAX_WONDER_TRADE_SHINY_CHANCE = 4096;
|
||||
|
||||
const LEGENDARY_TRADE_POOLS = {
|
||||
1: [Species.RATTATA, Species.PIDGEY, Species.WEEDLE],
|
||||
2: [Species.SENTRET, Species.HOOTHOOT, Species.LEDYBA],
|
||||
3: [Species.POOCHYENA, Species.ZIGZAGOON, Species.TAILLOW],
|
||||
4: [Species.BIDOOF, Species.STARLY, Species.KRICKETOT],
|
||||
5: [Species.PATRAT, Species.PURRLOIN, Species.PIDOVE],
|
||||
6: [Species.BUNNELBY, Species.LITLEO, Species.SCATTERBUG],
|
||||
7: [Species.PIKIPEK, Species.YUNGOOS, Species.ROCKRUFF],
|
||||
8: [Species.SKWOVET, Species.WOOLOO, Species.ROOKIDEE],
|
||||
9: [Species.LECHONK, Species.FIDOUGH, Species.TAROUNTULA]
|
||||
1: [ Species.RATTATA, Species.PIDGEY, Species.WEEDLE ],
|
||||
2: [ Species.SENTRET, Species.HOOTHOOT, Species.LEDYBA ],
|
||||
3: [ Species.POOCHYENA, Species.ZIGZAGOON, Species.TAILLOW ],
|
||||
4: [ Species.BIDOOF, Species.STARLY, Species.KRICKETOT ],
|
||||
5: [ Species.PATRAT, Species.PURRLOIN, Species.PIDOVE ],
|
||||
6: [ Species.BUNNELBY, Species.LITLEO, Species.SCATTERBUG ],
|
||||
7: [ Species.PIKIPEK, Species.YUNGOOS, Species.ROCKRUFF ],
|
||||
8: [ Species.SKWOVET, Species.WOOLOO, Species.ROOKIDEE ],
|
||||
9: [ Species.LECHONK, Species.FIDOUGH, Species.TAROUNTULA ]
|
||||
};
|
||||
|
||||
/** Exclude Paradox mons as they aren't considered legendary/mythical */
|
||||
@ -96,6 +96,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -387,11 +388,11 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
let item: ModifierTypeOption | null = null;
|
||||
// TMs excluded from possible rewards
|
||||
while (!item || item.type.id.includes("TM_")) {
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier], allowLuckUpgrades: false })[0];
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [ tier ], allowLuckUpgrades: false })[0];
|
||||
}
|
||||
|
||||
encounter.setDialogueToken("itemName", item.type.name);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false });
|
||||
|
||||
// Remove the chosen modifier if its stacks go to 0
|
||||
modifier.stackCount -= 1;
|
||||
@ -650,7 +651,7 @@ function doPokemonTradeSequence(scene: BattleScene, tradedPokemon: PlayerPokemon
|
||||
// addPokeballOpenParticles(scene, tradedPokemon.x, tradedPokemon.y, tradedPokemon.pokeball);
|
||||
|
||||
scene.tweens.add({
|
||||
targets: [tradedPokemonTintSprite, tradedPokemonSprite],
|
||||
targets: [ tradedPokemonTintSprite, tradedPokemonSprite ],
|
||||
duration: 500,
|
||||
ease: "Sine.easeIn",
|
||||
scale: 0.25,
|
||||
@ -726,7 +727,7 @@ function doPokemonTradeFlyBySequence(scene: BattleScene, tradedPokemonSprite: Ph
|
||||
duration: FADE_DELAY,
|
||||
onComplete: () => {
|
||||
scene.tweens.add({
|
||||
targets: [receivedPokemonSprite, tradedPokemonSprite],
|
||||
targets: [ receivedPokemonSprite, tradedPokemonSprite ],
|
||||
y: tradeBaseBg.displayWidth / 2 - 100,
|
||||
ease: "Cubic.easeInOut",
|
||||
duration: BASE_ANIM_DURATION * 3,
|
||||
|
@ -10,7 +10,7 @@ import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encount
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import {PokemonMove} from "#app/field/pokemon";
|
||||
import { PokemonMove } from "#app/field/pokemon";
|
||||
|
||||
const OPTION_1_REQUIRED_MOVE = Moves.SURF;
|
||||
const OPTION_2_REQUIRED_MOVE = Moves.FLY;
|
||||
@ -50,6 +50,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
|
@ -125,6 +125,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -143,7 +144,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
// Spawn standard trainer battle with memory mushroom reward
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
@ -168,7 +169,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
// Spawn hard fight
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[1];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
@ -196,7 +197,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
// To avoid player level snowballing from picking this option
|
||||
encounter.expMultiplier = 0.9;
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
|
@ -61,6 +61,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -76,12 +77,12 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
species: getPokemonSpecies(Species.GIMMIGHOUL),
|
||||
formIndex: 0,
|
||||
isBoss: true,
|
||||
moveSet: [Moves.NASTY_PLOT, Moves.SHADOW_BALL, Moves.POWER_GEM, Moves.THIEF]
|
||||
moveSet: [ Moves.NASTY_PLOT, Moves.SHADOW_BALL, Moves.POWER_GEM, Moves.THIEF ]
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
encounter.setDialogueToken("gimmighoulName", getPokemonSpecies(Species.GIMMIGHOUL).getName());
|
||||
encounter.setDialogueToken("trapPercent", TRAP_PERCENT.toString());
|
||||
@ -157,13 +158,13 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
} else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT - ROGUE_REWARDS_PERCENT) {
|
||||
// Choose between 2 ROGUE tier items (10%)
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE] });
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE ]});
|
||||
// Display result message then proceed to rewards
|
||||
queueEncounterMessage(scene, `${namespace}:option.1.great`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
} else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT - ROGUE_REWARDS_PERCENT - MASTER_REWARDS_PERCENT) {
|
||||
// Choose 1 MASTER tier item (5%)
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.MASTER] });
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.MASTER ]});
|
||||
// Display result message then proceed to rewards
|
||||
queueEncounterMessage(scene, `${namespace}:option.1.amazing`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
|
@ -69,6 +69,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -94,7 +95,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
// Calculation from Pokemon.calculateStats
|
||||
const baselineValue = Math.floor(((2 * 90 + 16) * pokemon.level) * 0.01) + 5;
|
||||
const percentDiff = (pokemon.getStat(Stat.SPD) - baselineValue) / baselineValue;
|
||||
const moneyMultiplier = Math.min(Math.max(2.5 * (1+ percentDiff), 1), 4);
|
||||
const moneyMultiplier = Math.min(Math.max(2.5 * (1 + percentDiff), 1), 4);
|
||||
|
||||
encounter.misc = {
|
||||
moneyMultiplier
|
||||
|
@ -23,7 +23,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounters/safariZone";
|
||||
|
||||
const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768];
|
||||
const TRAINER_THROW_ANIMATION_TIMES = [ 512, 184, 768 ];
|
||||
|
||||
const SAFARI_MONEY_MULTIPLIER = 2;
|
||||
|
||||
@ -54,6 +54,7 @@ export const SafariZoneEncounter: MysteryEncounter =
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -260,7 +261,7 @@ async function summonSafariPokemon(scene: BattleScene) {
|
||||
let enemySpecies;
|
||||
let pokemon;
|
||||
scene.executeWithSeedOffset(() => {
|
||||
enemySpecies = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false));
|
||||
enemySpecies = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false));
|
||||
const level = scene.currentBattle.getLevelForWave();
|
||||
enemySpecies = getPokemonSpecies(enemySpecies.getWildSpeciesForLevel(level, true, false, scene.gameMode));
|
||||
pokemon = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, false);
|
||||
|
@ -33,7 +33,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withSceneRequirement(new MoneyRequirement(0, VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER)) // Must have the money for at least the cheap deal
|
||||
.withPrimaryPokemonHealthRatioRequirement([0.51, 1]) // At least 1 Pokemon must have above half HP
|
||||
.withPrimaryPokemonHealthRatioRequirement([ 0.51, 1 ]) // At least 1 Pokemon must have above half HP
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: Species.KROOKODILE.toString(),
|
||||
@ -62,6 +62,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -140,7 +141,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
chosenPokemon.nature = newNature;
|
||||
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
||||
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
||||
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||
chosenPokemon.updateInfo();
|
||||
})
|
||||
.build()
|
||||
@ -201,7 +202,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||
|
||||
queueEncounterMessage(scene, `${namespace}:no_bad_effects`);
|
||||
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||
|
||||
chosenPokemon.updateInfo();
|
||||
})
|
||||
|
@ -60,15 +60,15 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
const pokemonConfig: EnemyPokemonConfig = {
|
||||
species: bossSpecies,
|
||||
isBoss: true,
|
||||
status: [StatusEffect.SLEEP, 5], // Extra turns on timer for Snorlax's start of fight moves
|
||||
moveSet: [Moves.REST, Moves.SLEEP_TALK, Moves.CRUNCH, Moves.GIGA_IMPACT],
|
||||
status: [ StatusEffect.SLEEP, 5 ], // Extra turns on timer for Snorlax's start of fight moves
|
||||
moveSet: [ Moves.REST, Moves.SLEEP_TALK, Moves.CRUNCH, Moves.GIGA_IMPACT ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.ENIGMA ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2
|
||||
},
|
||||
],
|
||||
@ -77,17 +77,18 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
};
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveModifier: 0.5,
|
||||
pokemonConfigs: [pokemonConfig],
|
||||
pokemonConfigs: [ pokemonConfig ],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Load animations/sfx for Snorlax fight start moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.SNORE]);
|
||||
loadCustomMovesForEncounter(scene, [ Moves.SNORE ]);
|
||||
|
||||
encounter.setDialogueToken("snorlaxName", getPokemonSpecies(Species.SNORLAX).getName());
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -104,17 +105,17 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: true});
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.LEFTOVERS ], fillRemaining: true });
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.SNORE),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.SNORE),
|
||||
ignorePp: true
|
||||
});
|
||||
@ -156,7 +157,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Steal the Snorlax's Leftovers
|
||||
const instance = scene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.LEFTOVERS ], fillRemaining: false });
|
||||
// Snorlax exp to Pokemon that did the stealing
|
||||
setEncounterExp(scene, instance.primaryPokemon!.id, getPokemonSpecies(Species.SNORLAX).baseExp);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
|
@ -26,8 +26,8 @@ import { getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIF
|
||||
const namespace = "mysteryEncounters/teleportingHijinks";
|
||||
|
||||
const MONEY_COST_MULTIPLIER = 1.75;
|
||||
const BIOME_CANDIDATES = [Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO];
|
||||
const MACHINE_INTERFACING_TYPES = [Type.ELECTRIC, Type.STEEL];
|
||||
const BIOME_CANDIDATES = [ Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO ];
|
||||
const MACHINE_INTERFACING_TYPES = [ Type.ELECTRIC, Type.STEEL ];
|
||||
|
||||
/**
|
||||
* Teleporting Hijinks encounter.
|
||||
@ -38,7 +38,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.TELEPORTING_HIJINKS)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withSceneRequirement(new WaveModulusRequirement([1, 2, 3], 10)) // Must be in first 3 waves after boss wave
|
||||
.withSceneRequirement(new WaveModulusRequirement([ 1, 2, 3 ], 10)) // Must be in first 3 waves after boss wave
|
||||
.withSceneRequirement(new MoneyRequirement(0, MONEY_COST_MULTIPLIER)) // Must be able to pay teleport cost
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withCatchAllowed(true)
|
||||
@ -58,6 +58,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -145,9 +146,9 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
}],
|
||||
};
|
||||
|
||||
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.STEEL])!;
|
||||
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.ELECTRIC])!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [magnet, metalCoat], fillRemaining: true });
|
||||
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.STEEL ])!;
|
||||
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.ELECTRIC ])!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ magnet, metalCoat ], fillRemaining: true });
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
@ -163,7 +164,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
|
||||
// Show dialogue and transition biome
|
||||
await showEncounterText(scene, `${namespace}:transport`);
|
||||
await Promise.all([animateBiomeChange(scene, newBiome), transitionMysteryEncounterIntroVisuals(scene)]);
|
||||
await Promise.all([ animateBiomeChange(scene, newBiome), transitionMysteryEncounterIntroVisuals(scene) ]);
|
||||
scene.playBgm();
|
||||
await showEncounterText(scene, `${namespace}:attacked`);
|
||||
|
||||
@ -175,8 +176,8 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
|
||||
// Defense/Spd buffs below wave 50, +1 to all stats otherwise
|
||||
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
|
||||
[Stat.DEF, Stat.SPDEF, Stat.SPD] :
|
||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
|
||||
[ Stat.DEF, Stat.SPDEF, Stat.SPD ] :
|
||||
[ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ];
|
||||
|
||||
const config: EnemyPartyConfig = {
|
||||
pokemonConfigs: [{
|
||||
@ -184,7 +185,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
species: bossSpecies,
|
||||
dataSource: new PokemonData(bossPokemon),
|
||||
isBoss: true,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
||||
@ -198,7 +199,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
async function animateBiomeChange(scene: BattleScene, nextBiome: Biome) {
|
||||
return new Promise<void>(resolve => {
|
||||
scene.tweens.add({
|
||||
targets: [scene.arenaEnemy, scene.lastEnemyTrainer],
|
||||
targets: [ scene.arenaEnemy, scene.lastEnemyTrainer ],
|
||||
x: "+=300",
|
||||
duration: 2000,
|
||||
onComplete: () => {
|
||||
@ -214,7 +215,7 @@ async function animateBiomeChange(scene: BattleScene, nextBiome: Biome) {
|
||||
scene.arenaPlayerTransition.setVisible(true);
|
||||
|
||||
scene.tweens.add({
|
||||
targets: [scene.arenaPlayer, scene.arenaBgTransition, scene.arenaPlayerTransition],
|
||||
targets: [ scene.arenaPlayer, scene.arenaBgTransition, scene.arenaPlayerTransition ],
|
||||
duration: 1000,
|
||||
ease: "Sine.easeInOut",
|
||||
alpha: (target: any) => target === scene.arenaPlayer ? 0 : 1,
|
||||
|
@ -48,29 +48,29 @@ class BreederSpeciesEvolution {
|
||||
}
|
||||
|
||||
const POOL_1_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
||||
[Species.MUNCHLAX, new BreederSpeciesEvolution(Species.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.HAPPINY, new BreederSpeciesEvolution(Species.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.MAGBY, new BreederSpeciesEvolution(Species.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.ELEKID, new BreederSpeciesEvolution(Species.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.RIOLU, new BreederSpeciesEvolution(Species.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.BUDEW, new BreederSpeciesEvolution(Species.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.TOXEL, new BreederSpeciesEvolution(Species.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.MIME_JR, new BreederSpeciesEvolution(Species.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE)]
|
||||
[ Species.MUNCHLAX, new BreederSpeciesEvolution(Species.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.HAPPINY, new BreederSpeciesEvolution(Species.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.MAGBY, new BreederSpeciesEvolution(Species.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.ELEKID, new BreederSpeciesEvolution(Species.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.RIOLU, new BreederSpeciesEvolution(Species.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.BUDEW, new BreederSpeciesEvolution(Species.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.TOXEL, new BreederSpeciesEvolution(Species.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.MIME_JR, new BreederSpeciesEvolution(Species.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE) ]
|
||||
];
|
||||
|
||||
const POOL_2_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
||||
[Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.RAICHU, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.JYNX],
|
||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.IGGLYBUFF, new BreederSpeciesEvolution(Species.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.AZURILL, new BreederSpeciesEvolution(Species.MARILL, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.WYNAUT, new BreederSpeciesEvolution(Species.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.CHINGLING, new BreederSpeciesEvolution(Species.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.BONSLY, new BreederSpeciesEvolution(Species.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.MANTYKE, new BreederSpeciesEvolution(Species.MANTINE, SECOND_STAGE_EVOLUTION_WAVE)]
|
||||
[ Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.RAICHU, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.JYNX ],
|
||||
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.IGGLYBUFF, new BreederSpeciesEvolution(Species.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.AZURILL, new BreederSpeciesEvolution(Species.MARILL, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.WYNAUT, new BreederSpeciesEvolution(Species.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.CHINGLING, new BreederSpeciesEvolution(Species.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.BONSLY, new BreederSpeciesEvolution(Species.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.MANTYKE, new BreederSpeciesEvolution(Species.MANTINE, SECOND_STAGE_EVOLUTION_WAVE) ]
|
||||
];
|
||||
|
||||
/**
|
||||
@ -138,7 +138,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
encounter.setDialogueToken("pokemon3Name", pokemon3.getNameToRender());
|
||||
|
||||
// Dialogue and egg calcs for Pokemon 1
|
||||
const [pokemon1CommonEggs, pokemon1RareEggs] = calculateEggRewardsForPokemon(pokemon1);
|
||||
const [ pokemon1CommonEggs, pokemon1RareEggs ] = calculateEggRewardsForPokemon(pokemon1);
|
||||
let pokemon1Tooltip = getEncounterText(scene, `${namespace}:option.1.tooltip_base`)!;
|
||||
if (pokemon1RareEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon1RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
@ -153,7 +153,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
encounter.options[0].dialogue!.buttonTooltip = pokemon1Tooltip;
|
||||
|
||||
// Dialogue and egg calcs for Pokemon 2
|
||||
const [pokemon2CommonEggs, pokemon2RareEggs] = calculateEggRewardsForPokemon(pokemon2);
|
||||
const [ pokemon2CommonEggs, pokemon2RareEggs ] = calculateEggRewardsForPokemon(pokemon2);
|
||||
let pokemon2Tooltip = getEncounterText(scene, `${namespace}:option.2.tooltip_base`)!;
|
||||
if (pokemon2RareEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
@ -168,7 +168,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip;
|
||||
|
||||
// Dialogue and egg calcs for Pokemon 3
|
||||
const [pokemon3CommonEggs, pokemon3RareEggs] = calculateEggRewardsForPokemon(pokemon3);
|
||||
const [ pokemon3CommonEggs, pokemon3RareEggs ] = calculateEggRewardsForPokemon(pokemon3);
|
||||
let pokemon3Tooltip = getEncounterText(scene, `${namespace}:option.3.tooltip_base`)!;
|
||||
if (pokemon3RareEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon3RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
@ -196,6 +196,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
@ -381,11 +382,11 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
abilityIndex: 1, // Magic Guard
|
||||
shiny: false,
|
||||
nature: Nature.ADAMANT,
|
||||
moveSet: [Moves.METEOR_MASH, Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH],
|
||||
ivs: [31, 31, 31, 31, 31, 31],
|
||||
moveSet: [ Moves.METEOR_MASH, Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH ],
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.TERA_SHARD, [Type.STEEL]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.TERA_SHARD, [ Type.STEEL ]) as PokemonHeldItemModifierType,
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -402,8 +403,8 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
shiny: true,
|
||||
variant: 1,
|
||||
nature: Nature.MODEST,
|
||||
moveSet: [Moves.MOONBLAST, Moves.MYSTICAL_FIRE, Moves.ICE_BEAM, Moves.THUNDERBOLT],
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
moveSet: [ Moves.MOONBLAST, Moves.MYSTICAL_FIRE, Moves.ICE_BEAM, Moves.THUNDERBOLT ],
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ]
|
||||
},
|
||||
{
|
||||
nickname: i18next.t(`${namespace}:cleffa_3_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }),
|
||||
@ -413,8 +414,8 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
shiny: true,
|
||||
variant: 2,
|
||||
nature: Nature.BOLD,
|
||||
moveSet: [Moves.TRI_ATTACK, Moves.STORED_POWER, Moves.TAKE_HEART, Moves.MOONLIGHT],
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
moveSet: [ Moves.TRI_ATTACK, Moves.STORED_POWER, Moves.TAKE_HEART, Moves.MOONLIGHT ],
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ]
|
||||
});
|
||||
} else {
|
||||
// Second member from pool 1
|
||||
@ -425,12 +426,12 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
baseConfig.pokemonConfigs!.push({
|
||||
species: getPokemonSpecies(pool1Species),
|
||||
isBoss: false,
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ]
|
||||
},
|
||||
{
|
||||
species: getPokemonSpecies(pool2Species),
|
||||
isBoss: false,
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ]
|
||||
});
|
||||
}
|
||||
|
||||
@ -468,7 +469,7 @@ function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number]
|
||||
// 1 Common egg for every point leftover
|
||||
const numCommons = totalPoints % 6;
|
||||
|
||||
return [numCommons, numRares];
|
||||
return [ numCommons, numRares ];
|
||||
}
|
||||
|
||||
function getEggOptions(scene: BattleScene, commonEggs: number, rareEggs: number) {
|
||||
@ -493,7 +494,7 @@ function getEggOptions(scene: BattleScene, commonEggs: number, rareEggs: number)
|
||||
pulled: false,
|
||||
sourceType: EggSourceType.EVENT,
|
||||
eggDescriptor: eggDescription,
|
||||
tier: EggTier.GREAT
|
||||
tier: EggTier.RARE
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -53,18 +53,19 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.setLocalizationKey(`${namespace}`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
let species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false));
|
||||
let species = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false));
|
||||
let tries = 0;
|
||||
|
||||
// Reroll any species that don't have HAs
|
||||
while ((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE) && tries < 5) {
|
||||
species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false));
|
||||
species = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false));
|
||||
tries++;
|
||||
}
|
||||
|
||||
|