Merge branch 'beta' into toxic_spikes

This commit is contained in:
NightKev 2024-09-04 18:41:40 -07:00
commit 63d55abcc9
343 changed files with 11930 additions and 18621 deletions

View File

@ -30,7 +30,7 @@
- [ ] The PR is self-contained and cannot be split into smaller PRs? - [ ] The PR is self-contained and cannot be split into smaller PRs?
- [ ] Have I provided a clear explanation of the changes? - [ ] Have I provided a clear explanation of the changes?
- [ ] Have I considered writing automated tests for the issue? - [ ] Have I considered writing automated tests for the issue?
- [ ] If I have text, did I add make it translatable and added a key in the English language? - [ ] If I have text, did I make it translatable and add a key in the English locale file(s)?
- [ ] Have I tested the changes (manually)? - [ ] Have I tested the changes (manually)?
- [ ] Are all unit tests still passing? (`npm run test`) - [ ] Are all unit tests still passing? (`npm run test`)
- [ ] Are the changes visual? - [ ] Are the changes visual?

View File

@ -11,6 +11,8 @@ on:
branches: branches:
- main # Trigger on pull request events targeting the main branch - main # Trigger on pull request events targeting the main branch
- beta # Trigger on pull request events targeting the beta branch - beta # Trigger on pull request events targeting the beta branch
merge_group:
types: [checks_requested]
jobs: jobs:
run-linters: # Define a job named "run-linters" run-linters: # Define a job named "run-linters"

View File

@ -8,6 +8,8 @@ on:
branches: branches:
- main - main
- beta - beta
merge_group:
types: [checks_requested]
jobs: jobs:
pages: pages:

View File

@ -11,6 +11,8 @@ on:
branches: branches:
- main # Trigger on pull request events targeting the main branch - main # Trigger on pull request events targeting the main branch
- beta # Trigger on pull request events targeting the beta branch - beta # Trigger on pull request events targeting the beta branch
merge_group:
types: [checks_requested]
jobs: jobs:
run-tests: # Define a job named "run-tests" run-tests: # Define a job named "run-tests"

101
create-test-boilerplate.js Normal file
View File

@ -0,0 +1,101 @@
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
/**
* This script creates a test boilerplate file for a move or ability.
* @param {string} type - The type of test to create. Either "move" or "ability".
* @param {string} fileName - The name of the file to create.
* @example npm run create-test move tackle
*/
// Get the directory name of the current module file
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Get the arguments from the command line
const args = process.argv.slice(2);
const type = args[0]; // "move" or "ability"
let fileName = args[1]; // The file name
if (!type || !fileName) {
console.error('Please provide both a type ("move" or "ability") and a file name.');
process.exit(1);
}
// Convert fileName from to snake_case if camelCase is given
fileName = fileName.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();
// Format the description for the test case
const formattedName = fileName
.replace(/_/g, ' ')
.replace(/\b\w/g, char => char.toUpperCase());
// Determine the directory based on the type
let dir;
let description;
if (type === 'move') {
dir = path.join(__dirname, 'src', 'test', 'moves');
description = `Moves - ${formattedName}`;
} else if (type === 'ability') {
dir = path.join(__dirname, 'src', 'test', 'abilities');
description = `Abilities - ${formattedName}`;
} else {
console.error('Invalid type. Please use "move" or "ability".');
process.exit(1);
}
// Ensure the directory exists
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
// Create the file with the given name
const filePath = path.join(dir, `${fileName}.test.ts`);
if (fs.existsSync(filePath)) {
console.error(`File "${fileName}.test.ts" already exists.`);
process.exit(1);
}
// Define the content template
const content = `import { Abilities } from "#enums/abilities";
import GameManager from "#test/utils/gameManager";
import { SPLASH_ONLY } from "#test/utils/testUtils";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, it } from "vitest";
describe("${description}", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
const TIMEOUT = 20 * 1000;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.battleType("single")
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(SPLASH_ONLY);
});
it("test case", async () => {
// await game.classicMode.startBattle();
// game.move.select();
}, TIMEOUT);
});
`;
// Write the template content to the file
fs.writeFileSync(filePath, content, 'utf8');
console.log(`File created at: ${filePath}`);

View File

@ -191,15 +191,15 @@ Now that the enemy Pokémon with the best matchup score is on the field (assumin
We then need to apply a 2x multiplier for the move's type effectiveness and a 1.5x multiplier since STAB applies. After applying these multipliers, the final score for this move is **75**. We then need to apply a 2x multiplier for the move's type effectiveness and a 1.5x multiplier since STAB applies. After applying these multipliers, the final score for this move is **75**.
- **Swords Dance**: As a non-attacking move, this move's benefit score is derived entirely from the sum of its attributes' benefit scores. Swords Dance's `StatChangeAttr` has a user benefit score of 0 and a target benefit score that, in this case, simplifies to - **Swords Dance**: As a non-attacking move, this move's benefit score is derived entirely from the sum of its attributes' benefit scores. Swords Dance's `StatStageChangeAttr` has a user benefit score of 0 and a target benefit score that, in this case, simplifies to
$\text{TBS}=4\times \text{levels} + (-2\times \text{sign(levels)})$ $\text{TBS}=4\times \text{levels} + (-2\times \text{sign(levels)})$
where `levels` is the number of stat stages added by the attribute (in this case, +2). The final score for this move is **6** (Note: because this move is self-targeted, we don't flip the sign of TBS when computing the target score). where `levels` is the number of stat stages added by the attribute (in this case, +2). The final score for this move is **6** (Note: because this move is self-targeted, we don't flip the sign of TBS when computing the target score).
- **Crush Claw**: This move is a 75-power Normal-type physical attack with a 50 percent chance to lower the target's Defense by one stage. The additional effect is implemented by the same `StatChangeAttr` as Swords Dance, so we can use the same formulas from before to compute the total TBS and base target score. - **Crush Claw**: This move is a 75-power Normal-type physical attack with a 50 percent chance to lower the target's Defense by one stage. The additional effect is implemented by the same `StatStageChangeAttr` as Swords Dance, so we can use the same formulas from before to compute the total TBS and base target score.
$\text{TBS}=\text{getTargetBenefitScore(StatChangeAttr)}-\text{attackScore}$ $\text{TBS}=\text{getTargetBenefitScore(StatStageChangeAttr)}-\text{attackScore}$
$\text{TBS}=(-4 + 2)-(-2\times 2 + \lfloor \frac{75}{5} \rfloor)=-2-11=-13$ $\text{TBS}=(-4 + 2)-(-2\times 2 + \lfloor \frac{75}{5} \rfloor)=-2-11=-13$
@ -221,4 +221,4 @@ When implementing a new move attribute, it's important to override `MoveAttr`'s
- A move's **user benefit score (UBS)** incentivizes (or discourages) the move's usage in general. A positive UBS gives the move more incentive to be used, while a negative UBS gives the move less incentive. - A move's **user benefit score (UBS)** incentivizes (or discourages) the move's usage in general. A positive UBS gives the move more incentive to be used, while a negative UBS gives the move less incentive.
- A move's **target benefit score (TBS)** incentivizes (or discourages) the move's usage on a specific target. A positive TBS indicates the move is better used on the user or its allies, while a negative TBS indicates the move is better used on enemies. - A move's **target benefit score (TBS)** incentivizes (or discourages) the move's usage on a specific target. A positive TBS indicates the move is better used on the user or its allies, while a negative TBS indicates the move is better used on enemies.
- **The total benefit score (UBS + TBS) of a move should never be 0.** The move selection algorithm assumes the move's benefit score is unimplemented if the total score is 0 and penalizes the move's usage as a result. With status moves especially, it's important to have some form of implementation among the move's attributes to avoid this scenario. - **The total benefit score (UBS + TBS) of a move should never be 0.** The move selection algorithm assumes the move's benefit score is unimplemented if the total score is 0 and penalizes the move's usage as a result. With status moves especially, it's important to have some form of implementation among the move's attributes to avoid this scenario.
- **Score functions that use formulas should include comments.** If your attribute requires complex logic or formulas to calculate benefit scores, please add comments to explain how the logic works and its intended effect on the enemy's decision making. - **Score functions that use formulas should include comments.** If your attribute requires complex logic or formulas to calculate benefit scores, please add comments to explain how the logic works and its intended effect on the enemy's decision making.

View File

@ -23,15 +23,6 @@ body {
} }
} }
#links {
width: 90%;
text-align: center;
position: fixed;
bottom: 0;
display: flex;
justify-content: space-around;
}
#app { #app {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -93,7 +84,7 @@ input:-internal-autofill-selected {
@media (orientation: landscape) { @media (orientation: landscape) {
#touchControls { #touchControls {
--controls-size: 20vh; --controls-size: 20vh;
--text-shadow-size: 1.3vh; --text-shadow-size: 1.3vh;
--small-button-offset: 4vh; --small-button-offset: 4vh;
} }

View File

@ -39,7 +39,6 @@
</style> </style>
<link rel="stylesheet" type="text/css" href="./index.css" /> <link rel="stylesheet" type="text/css" href="./index.css" />
<link rel="manifest" href="./manifest.webmanifest"> <link rel="manifest" href="./manifest.webmanifest">
<script type="text/javascript" src="https://app.termly.io/resource-blocker/c5dbfa2f-9723-4c0f-a84b-2895124e851f?autoBlock=on"></script>
<script> <script>
if ("serviceWorker" in navigator) { if ("serviceWorker" in navigator) {
window.addEventListener("load", function () { window.addEventListener("load", function () {
@ -144,13 +143,6 @@
</div> </div>
</div> </div>
<div id="tnc-links">
<a href="#" class="termly-display-preferences" style="display: none;" target="_blank" rel="noreferrer noopener">Consent Preferences</a>
<a href="https://app.termly.io/policy-viewer/policy.html?policyUUID=bc96778b-3f04-4d25-bafc-0deba53e8bec" target="_blank" rel="noreferrer noopener">Privacy Policy</a>
<a href="https://app.termly.io/policy-viewer/policy.html?policyUUID=8b523c05-7ec2-4646-9534-5bd61b386e2a" target="_blank" rel="noreferrer noopener">Cookie Disclaimer</a>
<a href="https://app.termly.io/policy-viewer/policy.html?policyUUID=b01e092a-9721-477f-8356-45576702ff9e" target="_blank" rel="noreferrer noopener">Terms & Conditions</a>
<a href="https://app.termly.io/policy-viewer/policy.html?policyUUID=3b5d1928-3f5b-4ee1-b8df-2d6c276b0bcc" target="_blank" rel="noreferrer noopener">Acceptable Use Policy</a>
</div>
<script type="module" src="./src/main.ts"></script> <script type="module" src="./src/main.ts"></script>
<script src="./src/touch-controls.ts" type="module"></script> <script src="./src/touch-controls.ts" type="module"></script>
<script src="./src/debug.js" type="module"></script> <script src="./src/debug.js" type="module"></script>

View File

@ -18,7 +18,8 @@
"eslint-ci": "eslint .", "eslint-ci": "eslint .",
"docs": "typedoc", "docs": "typedoc",
"depcruise": "depcruise src", "depcruise": "depcruise src",
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg" "depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
"create-test": "node ./create-test-boilerplate.js"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.3.0", "@eslint/js": "^9.3.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Before

Width:  |  Height:  |  Size: 405 B

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,38 +1,49 @@
{ {
"0": { "0": {
"bc4524": "af5457",
"31638c": "324a26", "31638c": "324a26",
"101010": "101010",
"5aa5ce": "40683c", "5aa5ce": "40683c",
"a5e6ff": "b6d9ac", "ce4252": "af2c4f",
"7bceef": "789c6e",
"ced6ef": "c09e99",
"737384": "774644",
"ffffff": "f1dcd8", "ffffff": "f1dcd8",
"8c4231": "420b0c", "8c4231": "420b0c",
"ffde4a": "c66f68",
"c57b31": "551917",
"ffffad": "f4bfb6", "ffffad": "f4bfb6",
"ffde4a": "c66f68",
"7bceef": "789c6e",
"a5e6ff": "b6d9ac",
"737384": "774644",
"f7b531": "af5457", "f7b531": "af5457",
"ce4252": "af2c4f", "c57b31": "551917",
"bc4524": "af5457", "ced6ef": "c09e99"
"00e5e7": "00e5e7"
}, },
"1": { "1": {
"bc4524": "3d325e",
"31638c": "143a72", "31638c": "143a72",
"101010": "101010",
"5aa5ce": "4060bc", "5aa5ce": "4060bc",
"a5e6ff": "b4b3ff", "ce4252": "b75558",
"7bceef": "657ddf",
"ced6ef": "a8b5dd",
"737384": "737384",
"ffffff": "e5ecff", "ffffff": "e5ecff",
"8c4231": "17103f", "8c4231": "17103f",
"ffde4a": "534e72",
"c57b31": "2a1f50",
"ffffad": "87879b", "ffffad": "87879b",
"ffde4a": "534e72",
"7bceef": "657ddf",
"a5e6ff": "b4b3ff",
"f7b531": "3d325e", "f7b531": "3d325e",
"ce4252": "b75558", "c57b31": "2a1f50",
"bc4524": "3d325e", "ced6ef": "a8b5dd"
"00e5e7": "00e5e7" },
"2": {
"ce4252": "215991",
"ffde4a": "f16f40",
"ffffad": "ffb274",
"737384": "884c43",
"c57b31": "761c03",
"7bceef": "be3d2f",
"8c4231": "5a0700",
"5aa5ce": "892722",
"8c4232": "761c03",
"ffffff": "f5e1d1",
"a5e6ff": "dd533a",
"f7b531": "bc4524",
"ced6ef": "d19e92",
"31638c": "610f0e"
} }
} }

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1017,7 +1017,7 @@
"279": [ "279": [
1, 1,
1, 1,
2 1
], ],
"280": [ "280": [
0, 0,

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

View File

@ -130,7 +130,7 @@ export default class BattleScene extends SceneBase {
public gameSpeed: integer = 1; public gameSpeed: integer = 1;
public damageNumbersMode: integer = 0; public damageNumbersMode: integer = 0;
public reroll: boolean = false; public reroll: boolean = false;
public shopCursorTarget: number = ShopCursorTarget.CHECK_TEAM; public shopCursorTarget: number = ShopCursorTarget.REWARDS;
public showMovesetFlyout: boolean = true; public showMovesetFlyout: boolean = true;
public showArenaFlyout: boolean = true; public showArenaFlyout: boolean = true;
public showTimeOfDayWidget: boolean = true; public showTimeOfDayWidget: boolean = true;
@ -841,12 +841,13 @@ export default class BattleScene extends SceneBase {
} }
addEnemyPokemon(species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean = false, dataSource?: PokemonData, postProcess?: (enemyPokemon: EnemyPokemon) => void): EnemyPokemon { addEnemyPokemon(species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean = false, dataSource?: PokemonData, postProcess?: (enemyPokemon: EnemyPokemon) => void): EnemyPokemon {
if (Overrides.OPP_LEVEL_OVERRIDE > 0) {
level = Overrides.OPP_LEVEL_OVERRIDE;
}
if (Overrides.OPP_SPECIES_OVERRIDE) { if (Overrides.OPP_SPECIES_OVERRIDE) {
species = getPokemonSpecies(Overrides.OPP_SPECIES_OVERRIDE); species = getPokemonSpecies(Overrides.OPP_SPECIES_OVERRIDE);
} // The fact that a Pokemon is a boss or not can change based on its Species and level
boss = this.getEncounterBossSegments(this.currentBattle.waveIndex, level, species) > 1;
if (Overrides.OPP_LEVEL_OVERRIDE !== 0) {
level = Overrides.OPP_LEVEL_OVERRIDE;
} }
const pokemon = new EnemyPokemon(this, species, level, trainerSlot, boss, dataSource); const pokemon = new EnemyPokemon(this, species, level, trainerSlot, boss, dataSource);
@ -973,6 +974,7 @@ export default class BattleScene extends SceneBase {
this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24)); this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24));
console.log("Seed:", this.seed); console.log("Seed:", this.seed);
this.resetSeed(); // Properly resets RNG after saving and quitting a session
this.disableMenu = false; this.disableMenu = false;
@ -1327,6 +1329,13 @@ export default class BattleScene extends SceneBase {
} }
getEncounterBossSegments(waveIndex: integer, level: integer, species?: PokemonSpecies, forceBoss: boolean = false): integer { getEncounterBossSegments(waveIndex: integer, level: integer, species?: PokemonSpecies, forceBoss: boolean = false): integer {
if (Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE > 1) {
return Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE;
} else if (Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE === 1) {
// The rest of the code expects to be returned 0 and not 1 if the enemy is not a boss
return 0;
}
if (this.gameMode.isDaily && this.gameMode.isWaveFinal(waveIndex)) { if (this.gameMode.isDaily && this.gameMode.isWaveFinal(waveIndex)) {
return 5; return 5;
} }
@ -1791,6 +1800,7 @@ export default class BattleScene extends SceneBase {
config = config ?? {}; config = config ?? {};
try { try {
const keyDetails = key.split("/"); const keyDetails = key.split("/");
config["volume"] = config["volume"] ?? 1;
switch (keyDetails[0]) { switch (keyDetails[0]) {
case "level_up_fanfare": case "level_up_fanfare":
case "item_fanfare": case "item_fanfare":
@ -1800,11 +1810,11 @@ export default class BattleScene extends SceneBase {
case "evolution_fanfare": case "evolution_fanfare":
// These sounds are loaded in as BGM, but played as sound effects // These sounds are loaded in as BGM, but played as sound effects
// When these sounds are updated in updateVolume(), they are treated as BGM however because they are placed in the BGM Cache through being called by playSoundWithoutBGM() // When these sounds are updated in updateVolume(), they are treated as BGM however because they are placed in the BGM Cache through being called by playSoundWithoutBGM()
config["volume"] = this.masterVolume * this.bgmVolume; config["volume"] *= (this.masterVolume * this.bgmVolume);
break; break;
case "battle_anims": case "battle_anims":
case "cry": case "cry":
config["volume"] = this.masterVolume * this.fieldVolume; config["volume"] *= (this.masterVolume * this.fieldVolume);
//PRSFX sound files are unusually loud //PRSFX sound files are unusually loud
if (keyDetails[1].startsWith("PRSFX- ")) { if (keyDetails[1].startsWith("PRSFX- ")) {
config["volume"] *= 0.5; config["volume"] *= 0.5;
@ -1812,10 +1822,10 @@ export default class BattleScene extends SceneBase {
break; break;
case "ui": case "ui":
//As of, right now this applies to the "select", "menu_open", "error" sound effects //As of, right now this applies to the "select", "menu_open", "error" sound effects
config["volume"] = this.masterVolume * this.uiVolume; config["volume"] *= (this.masterVolume * this.uiVolume);
break; break;
case "se": case "se":
config["volume"] = this.masterVolume * this.seVolume; config["volume"] *= (this.masterVolume * this.seVolume);
break; break;
} }
this.sound.play(key, config); this.sound.play(key, config);
@ -2732,6 +2742,35 @@ export default class BattleScene extends SceneBase {
(window as any).gameInfo = gameInfo; (window as any).gameInfo = gameInfo;
} }
/**
* This function retrieves the sprite and audio keys for active Pokemon.
* Active Pokemon include both enemy and player Pokemon of the current wave.
* Note: Questions on garbage collection go to @frutescens
* @returns a string array of active sprite and audio keys that should not be deleted
*/
getActiveKeys(): string[] {
const keys: string[] = [];
const playerParty = this.getParty();
playerParty.forEach(p => {
keys.push("pkmn__" + p.species.getSpriteId(p.gender === Gender.FEMALE, p.species.formIndex, p.shiny, p.variant));
keys.push("pkmn__" + p.species.getSpriteId(p.gender === Gender.FEMALE, p.species.formIndex, p.shiny, p.variant, true));
keys.push("cry/" + p.species.getCryKey(p.species.formIndex));
if (p.fusionSpecies && p.getSpeciesForm() !== p.getFusionSpeciesForm()) {
keys.push("cry/"+p.getFusionSpeciesForm().getCryKey(p.fusionSpecies.formIndex));
}
});
// enemyParty has to be operated on separately from playerParty because playerPokemon =/= enemyPokemon
const enemyParty = this.getEnemyParty();
enemyParty.forEach(p => {
keys.push(p.species.getSpriteKey(p.gender === Gender.FEMALE, p.species.formIndex, p.shiny, p.variant));
keys.push("cry/" + p.species.getCryKey(p.species.formIndex));
if (p.fusionSpecies && p.getSpeciesForm() !== p.getFusionSpeciesForm()) {
keys.push("cry/"+p.getFusionSpeciesForm().getCryKey(p.fusionSpecies.formIndex));
}
});
return keys;
}
/** /**
* Initialized the 2nd phase of the final boss (e.g. form-change for Eternatus) * Initialized the 2nd phase of the final boss (e.g. form-change for Eternatus)
* @param pokemon The (enemy) pokemon * @param pokemon The (enemy) pokemon

File diff suppressed because it is too large Load Diff

View File

@ -7,17 +7,17 @@ import Pokemon, { HitResult, PokemonMove } from "../field/pokemon";
import { StatusEffect } from "./status-effect"; import { StatusEffect } from "./status-effect";
import { BattlerIndex } from "../battle"; import { BattlerIndex } from "../battle";
import { BlockNonDirectDamageAbAttr, ChangeMovePriorityAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability"; import { BlockNonDirectDamageAbAttr, ChangeMovePriorityAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability";
import { BattleStat } from "./battle-stat"; import { Stat } from "#enums/stat";
import { CommonAnim, CommonBattleAnim } from "./battle-anims"; import { CommonAnim, CommonBattleAnim } from "./battle-anims";
import i18next from "i18next"; import i18next from "i18next";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { ArenaTagType } from "#enums/arena-tag-type"; import { ArenaTagType } from "#enums/arena-tag-type";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase.js"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
import { ShowAbilityPhase } from "#app/phases/show-ability-phase.js"; import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
import { StatChangePhase } from "#app/phases/stat-change-phase.js"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
export enum ArenaTagSide { export enum ArenaTagSide {
BOTH, BOTH,
@ -804,8 +804,8 @@ class StickyWebTag extends ArenaTrapTag {
applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled);
if (!cancelled.value) { if (!cancelled.value) {
pokemon.scene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() })); pokemon.scene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() }));
const statLevels = new Utils.NumberHolder(-1); const stages = new Utils.NumberHolder(-1);
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [BattleStat.SPD], statLevels.value)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value));
} }
} }
@ -893,7 +893,7 @@ class TailwindTag extends ArenaTag {
// Raise attack by one stage if party member has WIND_RIDER ability // Raise attack by one stage if party member has WIND_RIDER ability
if (pokemon.hasAbility(Abilities.WIND_RIDER)) { if (pokemon.hasAbility(Abilities.WIND_RIDER)) {
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.getBattlerIndex())); pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.getBattlerIndex()));
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK], 1, true)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.ATK ], 1, true));
} }
} }
} }
@ -923,6 +923,21 @@ class HappyHourTag extends ArenaTag {
} }
} }
class SafeguardTag extends ArenaTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.SAFEGUARD, turnCount, Moves.SAFEGUARD, sourceId, side);
}
onAdd(arena: Arena): void {
arena.scene.queueMessage(i18next.t(`arenaTag:safeguardOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`));
}
onRemove(arena: Arena): void {
arena.scene.queueMessage(i18next.t(`arenaTag:safeguardOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`));
}
}
class NoneTag extends ArenaTag { class NoneTag extends ArenaTag {
constructor() { constructor() {
super(ArenaTagType.NONE, 0, undefined, undefined); super(ArenaTagType.NONE, 0, undefined, undefined);
@ -974,6 +989,8 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
return new TailwindTag(turnCount, sourceId, side); return new TailwindTag(turnCount, sourceId, side);
case ArenaTagType.HAPPY_HOUR: case ArenaTagType.HAPPY_HOUR:
return new HappyHourTag(turnCount, sourceId, side); return new HappyHourTag(turnCount, sourceId, side);
case ArenaTagType.SAFEGUARD:
return new SafeguardTag(turnCount, sourceId, side);
default: default:
return null; return null;
} }

View File

@ -788,10 +788,10 @@ export abstract class BattleAnim {
targetSprite.pipelineData["tone"] = [ 0.0, 0.0, 0.0, 0.0 ]; targetSprite.pipelineData["tone"] = [ 0.0, 0.0, 0.0, 0.0 ];
targetSprite.setAngle(0); targetSprite.setAngle(0);
if (!this.isHideUser() && userSprite) { if (!this.isHideUser() && userSprite) {
userSprite.setVisible(true); this.user?.getSprite().setVisible(true); // using this.user to fix context loss due to isOppAnim swap (#481)
} }
if (!this.isHideTarget() && (targetSprite !== userSprite || !this.isHideUser())) { if (!this.isHideTarget() && (targetSprite !== userSprite || !this.isHideUser())) {
targetSprite.setVisible(true); this.target?.getSprite().setVisible(true); // using this.target to fix context loss due to isOppAnim swap (#481)
} }
for (const ms of Object.values(spriteCache).flat()) { for (const ms of Object.values(spriteCache).flat()) {
if (ms) { if (ms) {

View File

@ -1,71 +0,0 @@
import i18next, { ParseKeys } from "i18next";
export enum BattleStat {
ATK,
DEF,
SPATK,
SPDEF,
SPD,
ACC,
EVA,
RAND,
HP
}
export function getBattleStatName(stat: BattleStat) {
switch (stat) {
case BattleStat.ATK:
return i18next.t("pokemonInfo:Stat.ATK");
case BattleStat.DEF:
return i18next.t("pokemonInfo:Stat.DEF");
case BattleStat.SPATK:
return i18next.t("pokemonInfo:Stat.SPATK");
case BattleStat.SPDEF:
return i18next.t("pokemonInfo:Stat.SPDEF");
case BattleStat.SPD:
return i18next.t("pokemonInfo:Stat.SPD");
case BattleStat.ACC:
return i18next.t("pokemonInfo:Stat.ACC");
case BattleStat.EVA:
return i18next.t("pokemonInfo:Stat.EVA");
case BattleStat.HP:
return i18next.t("pokemonInfo:Stat.HPStat");
default:
return "???";
}
}
export function getBattleStatLevelChangeDescription(pokemonNameWithAffix: string, stats: string, levels: integer, up: boolean, count: number = 1) {
const stringKey = (() => {
if (up) {
switch (levels) {
case 1:
return "battle:statRose";
case 2:
return "battle:statSharplyRose";
case 3:
case 4:
case 5:
case 6:
return "battle:statRoseDrastically";
default:
return "battle:statWontGoAnyHigher";
}
} else {
switch (levels) {
case 1:
return "battle:statFell";
case 2:
return "battle:statHarshlyFell";
case 3:
case 4:
case 5:
case 6:
return "battle:statSeverelyFell";
default:
return "battle:statWontGoAnyLower";
}
}
})();
return i18next.t(stringKey as ParseKeys, { pokemonNameWithAffix, stats, count });
}

View File

@ -1,7 +1,6 @@
import { ChargeAnim, CommonAnim, CommonBattleAnim, MoveChargeAnim } from "./battle-anims"; import { ChargeAnim, CommonAnim, CommonBattleAnim, MoveChargeAnim } from "./battle-anims";
import { getPokemonNameWithAffix } from "../messages"; import { getPokemonNameWithAffix } from "../messages";
import Pokemon, { MoveResult, HitResult } from "../field/pokemon"; import Pokemon, { MoveResult, HitResult } from "../field/pokemon";
import { Stat, getStatName } from "./pokemon-stat";
import { StatusEffect } from "./status-effect"; import { StatusEffect } from "./status-effect";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { ChargeAttr, MoveFlags, allMoves } from "./move"; import { ChargeAttr, MoveFlags, allMoves } from "./move";
@ -9,20 +8,20 @@ import { Type } from "./type";
import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs } from "./ability"; import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs } from "./ability";
import { TerrainType } from "./terrain"; import { TerrainType } from "./terrain";
import { WeatherType } from "./weather"; import { WeatherType } from "./weather";
import { BattleStat } from "./battle-stat";
import { allAbilities } from "./ability"; import { allAbilities } from "./ability";
import { SpeciesFormChangeManualTrigger } from "./pokemon-forms"; import { SpeciesFormChangeManualTrigger } from "./pokemon-forms";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import i18next from "#app/plugins/i18n.js"; import i18next from "#app/plugins/i18n";
import { CommonAnimPhase } from "#app/phases/common-anim-phase.js"; import { Stat, type BattleStat, type EffectiveStat, EFFECTIVE_STATS, getStatKey } from "#app/enums/stat";
import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; import { CommonAnimPhase } from "#app/phases/common-anim-phase";
import { MovePhase } from "#app/phases/move-phase.js"; import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase.js"; import { MovePhase } from "#app/phases/move-phase";
import { ShowAbilityPhase } from "#app/phases/show-ability-phase.js"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
import { StatChangePhase, StatChangeCallback } from "#app/phases/stat-change-phase.js"; import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
import { StatStageChangePhase, StatStageChangeCallback } from "#app/phases/stat-stage-change-phase";
export enum BattlerTagLapseType { export enum BattlerTagLapseType {
FAINT, FAINT,
@ -40,13 +39,15 @@ export class BattlerTag {
public turnCount: number; public turnCount: number;
public sourceMove: Moves; public sourceMove: Moves;
public sourceId?: number; public sourceId?: number;
public isBatonPassable: boolean;
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: number, sourceMove?: Moves, sourceId?: number) { constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: number, sourceMove?: Moves, sourceId?: number, isBatonPassable: boolean = false) {
this.tagType = tagType; this.tagType = tagType;
this.lapseTypes = Array.isArray(lapseType) ? lapseType : [ lapseType ]; this.lapseTypes = Array.isArray(lapseType) ? lapseType : [ lapseType ];
this.turnCount = turnCount; this.turnCount = turnCount;
this.sourceMove = sourceMove!; // TODO: is this bang correct? this.sourceMove = sourceMove!; // TODO: is this bang correct?
this.sourceId = sourceId; this.sourceId = sourceId;
this.isBatonPassable = isBatonPassable;
} }
canAdd(pokemon: Pokemon): boolean { canAdd(pokemon: Pokemon): boolean {
@ -207,12 +208,12 @@ export class ShellTrapTag extends BattlerTag {
export class TrappedTag extends BattlerTag { export class TrappedTag extends BattlerTag {
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: number, sourceMove: Moves, sourceId: number) { constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: number, sourceMove: Moves, sourceId: number) {
super(tagType, lapseType, turnCount, sourceMove, sourceId); super(tagType, lapseType, turnCount, sourceMove, sourceId, true);
} }
canAdd(pokemon: Pokemon): boolean { canAdd(pokemon: Pokemon): boolean {
const isGhost = pokemon.isOfType(Type.GHOST); const isGhost = pokemon.isOfType(Type.GHOST);
const isTrapped = pokemon.getTag(BattlerTagType.TRAPPED); const isTrapped = pokemon.getTag(TrappedTag);
return !isTrapped && !isGhost; return !isTrapped && !isGhost;
} }
@ -245,6 +246,23 @@ export class TrappedTag extends BattlerTag {
} }
} }
/**
* BattlerTag implementing No Retreat's trapping effect.
* This is treated separately from other trapping effects to prevent
* Ghost-type Pokemon from being able to reuse the move.
* @extends TrappedTag
*/
class NoRetreatTag extends TrappedTag {
constructor(sourceId: number) {
super(BattlerTagType.NO_RETREAT, BattlerTagLapseType.CUSTOM, 0, Moves.NO_RETREAT, sourceId);
}
/** overrides {@linkcode TrappedTag.apply}, removing the Ghost-type condition */
canAdd(pokemon: Pokemon): boolean {
return !pokemon.getTag(TrappedTag);
}
}
/** /**
* BattlerTag that represents the {@link https://bulbapedia.bulbagarden.net/wiki/Flinch Flinch} status condition * BattlerTag that represents the {@link https://bulbapedia.bulbagarden.net/wiki/Flinch Flinch} status condition
*/ */
@ -310,7 +328,7 @@ export class InterruptedTag extends BattlerTag {
*/ */
export class ConfusedTag extends BattlerTag { export class ConfusedTag extends BattlerTag {
constructor(turnCount: number, sourceMove: Moves) { constructor(turnCount: number, sourceMove: Moves) {
super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove); super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove, undefined, true);
} }
canAdd(pokemon: Pokemon): boolean { canAdd(pokemon: Pokemon): boolean {
@ -345,8 +363,8 @@ export class ConfusedTag extends BattlerTag {
// 1/3 chance of hitting self with a 40 base power move // 1/3 chance of hitting self with a 40 base power move
if (pokemon.randSeedInt(3) === 0) { if (pokemon.randSeedInt(3) === 0) {
const atk = pokemon.getBattleStat(Stat.ATK); const atk = pokemon.getEffectiveStat(Stat.ATK);
const def = pokemon.getBattleStat(Stat.DEF); const def = pokemon.getEffectiveStat(Stat.DEF);
const damage = Utils.toDmgValue(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedInt(15, 85) / 100)); const damage = Utils.toDmgValue(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedInt(15, 85) / 100));
pokemon.scene.queueMessage(i18next.t("battlerTags:confusedLapseHurtItself")); pokemon.scene.queueMessage(i18next.t("battlerTags:confusedLapseHurtItself"));
pokemon.damageAndUpdate(damage); pokemon.damageAndUpdate(damage);
@ -370,7 +388,7 @@ export class ConfusedTag extends BattlerTag {
*/ */
export class DestinyBondTag extends BattlerTag { export class DestinyBondTag extends BattlerTag {
constructor(sourceMove: Moves, sourceId: number) { constructor(sourceMove: Moves, sourceId: number) {
super(BattlerTagType.DESTINY_BOND, BattlerTagLapseType.PRE_MOVE, 1, sourceMove, sourceId); super(BattlerTagType.DESTINY_BOND, BattlerTagLapseType.PRE_MOVE, 1, sourceMove, sourceId, true);
} }
/** /**
@ -489,7 +507,7 @@ export class SeedTag extends BattlerTag {
private sourceIndex: number; private sourceIndex: number;
constructor(sourceId: number) { constructor(sourceId: number) {
super(BattlerTagType.SEEDED, BattlerTagLapseType.TURN_END, 1, Moves.LEECH_SEED, sourceId); super(BattlerTagType.SEEDED, BattlerTagLapseType.TURN_END, 1, Moves.LEECH_SEED, sourceId, true);
} }
/** /**
@ -750,7 +768,7 @@ export class OctolockTag extends TrappedTag {
const shouldLapse = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType); const shouldLapse = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
if (shouldLapse) { if (shouldLapse) {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.DEF, BattleStat.SPDEF], -1)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.DEF, Stat.SPDEF ], -1));
return true; return true;
} }
@ -760,7 +778,7 @@ export class OctolockTag extends TrappedTag {
export class AquaRingTag extends BattlerTag { export class AquaRingTag extends BattlerTag {
constructor() { constructor() {
super(BattlerTagType.AQUA_RING, BattlerTagLapseType.TURN_END, 1, Moves.AQUA_RING, undefined); super(BattlerTagType.AQUA_RING, BattlerTagLapseType.TURN_END, 1, Moves.AQUA_RING, undefined, true);
} }
onAdd(pokemon: Pokemon): void { onAdd(pokemon: Pokemon): void {
@ -792,7 +810,7 @@ export class AquaRingTag extends BattlerTag {
/** Tag used to allow moves that interact with {@link Moves.MINIMIZE} to function */ /** Tag used to allow moves that interact with {@link Moves.MINIMIZE} to function */
export class MinimizeTag extends BattlerTag { export class MinimizeTag extends BattlerTag {
constructor() { constructor() {
super(BattlerTagType.MINIMIZED, BattlerTagLapseType.TURN_END, 1, Moves.MINIMIZE, undefined); super(BattlerTagType.MINIMIZED, BattlerTagLapseType.TURN_END, 1, Moves.MINIMIZE);
} }
canAdd(pokemon: Pokemon): boolean { canAdd(pokemon: Pokemon): boolean {
@ -864,7 +882,7 @@ export abstract class DamagingTrapTag extends TrappedTag {
} }
canAdd(pokemon: Pokemon): boolean { canAdd(pokemon: Pokemon): boolean {
return !pokemon.isOfType(Type.GHOST) && !pokemon.findTag(t => t instanceof DamagingTrapTag); return !pokemon.getTag(TrappedTag);
} }
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
@ -1076,7 +1094,7 @@ export class ContactDamageProtectedTag extends ProtectedTag {
} }
} }
export class ContactStatChangeProtectedTag extends ProtectedTag { export class ContactStatStageChangeProtectedTag extends ProtectedTag {
private stat: BattleStat; private stat: BattleStat;
private levels: number; private levels: number;
@ -1093,7 +1111,7 @@ export class ContactStatChangeProtectedTag extends ProtectedTag {
*/ */
loadTag(source: BattlerTag | any): void { loadTag(source: BattlerTag | any): void {
super.loadTag(source); super.loadTag(source);
this.stat = source.stat as BattleStat; this.stat = source.stat;
this.levels = source.levels; this.levels = source.levels;
} }
@ -1104,7 +1122,7 @@ export class ContactStatChangeProtectedTag extends ProtectedTag {
const effectPhase = pokemon.scene.getCurrentPhase(); const effectPhase = pokemon.scene.getCurrentPhase();
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) { if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) {
const attacker = effectPhase.getPokemon(); const attacker = effectPhase.getPokemon();
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, attacker.getBattlerIndex(), true, [ this.stat ], this.levels)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), true, [ this.stat ], this.levels));
} }
} }
@ -1190,7 +1208,7 @@ export class SturdyTag extends BattlerTag {
export class PerishSongTag extends BattlerTag { export class PerishSongTag extends BattlerTag {
constructor(turnCount: number) { constructor(turnCount: number) {
super(BattlerTagType.PERISH_SONG, BattlerTagLapseType.TURN_END, turnCount, Moves.PERISH_SONG); super(BattlerTagType.PERISH_SONG, BattlerTagLapseType.TURN_END, turnCount, Moves.PERISH_SONG, undefined, true);
} }
canAdd(pokemon: Pokemon): boolean { canAdd(pokemon: Pokemon): boolean {
@ -1246,7 +1264,7 @@ export class AbilityBattlerTag extends BattlerTag {
public ability: Abilities; public ability: Abilities;
constructor(tagType: BattlerTagType, ability: Abilities, lapseType: BattlerTagLapseType, turnCount: number) { constructor(tagType: BattlerTagType, ability: Abilities, lapseType: BattlerTagLapseType, turnCount: number) {
super(tagType, lapseType, turnCount, undefined); super(tagType, lapseType, turnCount);
this.ability = ability; this.ability = ability;
} }
@ -1331,11 +1349,10 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
onAdd(pokemon: Pokemon): void { onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon); super.onAdd(pokemon);
const stats = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ]; let highestStat: EffectiveStat;
let highestStat: Stat; EFFECTIVE_STATS.map(s => pokemon.getEffectiveStat(s)).reduce((highestValue: number, value: number, i: number) => {
stats.map(s => pokemon.getBattleStat(s)).reduce((highestValue: number, value: number, i: number) => {
if (value > highestValue) { if (value > highestValue) {
highestStat = stats[i]; highestStat = EFFECTIVE_STATS[i];
return value; return value;
} }
return highestValue; return highestValue;
@ -1353,7 +1370,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
break; break;
} }
pokemon.scene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: getStatName(highestStat) }), null, false, null, true); pokemon.scene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: i18next.t(getStatKey(highestStat)) }), null, false, null, true);
} }
onRemove(pokemon: Pokemon): void { onRemove(pokemon: Pokemon): void {
@ -1423,7 +1440,7 @@ export class TypeImmuneTag extends BattlerTag {
public immuneType: Type; public immuneType: Type;
constructor(tagType: BattlerTagType, sourceMove: Moves, immuneType: Type, length: number = 1) { constructor(tagType: BattlerTagType, sourceMove: Moves, immuneType: Type, length: number = 1) {
super(tagType, BattlerTagLapseType.TURN_END, length, sourceMove); super(tagType, BattlerTagLapseType.TURN_END, length, sourceMove, undefined, true);
this.immuneType = immuneType; this.immuneType = immuneType;
} }
@ -1487,7 +1504,7 @@ export class TypeBoostTag extends BattlerTag {
export class CritBoostTag extends BattlerTag { export class CritBoostTag extends BattlerTag {
constructor(tagType: BattlerTagType, sourceMove: Moves) { constructor(tagType: BattlerTagType, sourceMove: Moves) {
super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove); super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove, undefined, true);
} }
onAdd(pokemon: Pokemon): void { onAdd(pokemon: Pokemon): void {
@ -1507,6 +1524,25 @@ export class CritBoostTag extends BattlerTag {
} }
} }
/**
* Tag for the effects of Dragon Cheer, which boosts the critical hit ratio of the user's allies.
* @extends {CritBoostTag}
*/
export class DragonCheerTag extends CritBoostTag {
/** The types of the user's ally when the tag is added */
public typesOnAdd: Type[];
constructor() {
super(BattlerTagType.CRIT_BOOST, Moves.DRAGON_CHEER);
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
this.typesOnAdd = pokemon.getTypes(true);
}
}
export class SaltCuredTag extends BattlerTag { export class SaltCuredTag extends BattlerTag {
private sourceIndex: number; private sourceIndex: number;
@ -1560,7 +1596,7 @@ export class CursedTag extends BattlerTag {
private sourceIndex: number; private sourceIndex: number;
constructor(sourceId: number) { constructor(sourceId: number) {
super(BattlerTagType.CURSED, BattlerTagLapseType.TURN_END, 1, Moves.CURSE, sourceId); super(BattlerTagType.CURSED, BattlerTagLapseType.TURN_END, 1, Moves.CURSE, sourceId, true);
} }
/** /**
@ -1678,25 +1714,25 @@ export class IceFaceBlockDamageTag extends FormBlockDamageTag {
*/ */
export class StockpilingTag extends BattlerTag { export class StockpilingTag extends BattlerTag {
public stockpiledCount: number = 0; public stockpiledCount: number = 0;
public statChangeCounts: { [BattleStat.DEF]: number; [BattleStat.SPDEF]: number } = { public statChangeCounts: { [Stat.DEF]: number; [Stat.SPDEF]: number } = {
[BattleStat.DEF]: 0, [Stat.DEF]: 0,
[BattleStat.SPDEF]: 0 [Stat.SPDEF]: 0
}; };
constructor(sourceMove: Moves = Moves.NONE) { constructor(sourceMove: Moves = Moves.NONE) {
super(BattlerTagType.STOCKPILING, BattlerTagLapseType.CUSTOM, 1, sourceMove); super(BattlerTagType.STOCKPILING, BattlerTagLapseType.CUSTOM, 1, sourceMove);
} }
private onStatsChanged: StatChangeCallback = (_, statsChanged, statChanges) => { private onStatStagesChanged: StatStageChangeCallback = (_, statsChanged, statChanges) => {
const defChange = statChanges[statsChanged.indexOf(BattleStat.DEF)] ?? 0; const defChange = statChanges[statsChanged.indexOf(Stat.DEF)] ?? 0;
const spDefChange = statChanges[statsChanged.indexOf(BattleStat.SPDEF)] ?? 0; const spDefChange = statChanges[statsChanged.indexOf(Stat.SPDEF)] ?? 0;
if (defChange) { if (defChange) {
this.statChangeCounts[BattleStat.DEF]++; this.statChangeCounts[Stat.DEF]++;
} }
if (spDefChange) { if (spDefChange) {
this.statChangeCounts[BattleStat.SPDEF]++; this.statChangeCounts[Stat.SPDEF]++;
} }
}; };
@ -1704,8 +1740,8 @@ export class StockpilingTag extends BattlerTag {
super.loadTag(source); super.loadTag(source);
this.stockpiledCount = source.stockpiledCount || 0; this.stockpiledCount = source.stockpiledCount || 0;
this.statChangeCounts = { this.statChangeCounts = {
[ BattleStat.DEF ]: source.statChangeCounts?.[ BattleStat.DEF ] ?? 0, [ Stat.DEF ]: source.statChangeCounts?.[ Stat.DEF ] ?? 0,
[ BattleStat.SPDEF ]: source.statChangeCounts?.[ BattleStat.SPDEF ] ?? 0, [ Stat.SPDEF ]: source.statChangeCounts?.[ Stat.SPDEF ] ?? 0,
}; };
} }
@ -1725,9 +1761,9 @@ export class StockpilingTag extends BattlerTag {
})); }));
// Attempt to increase DEF and SPDEF by one stage, keeping track of successful changes. // Attempt to increase DEF and SPDEF by one stage, keeping track of successful changes.
pokemon.scene.unshiftPhase(new StatChangePhase( pokemon.scene.unshiftPhase(new StatStageChangePhase(
pokemon.scene, pokemon.getBattlerIndex(), true, pokemon.scene, pokemon.getBattlerIndex(), true,
[BattleStat.SPDEF, BattleStat.DEF], 1, true, false, true, this.onStatsChanged [Stat.SPDEF, Stat.DEF], 1, true, false, true, this.onStatStagesChanged
)); ));
} }
} }
@ -1741,15 +1777,15 @@ export class StockpilingTag extends BattlerTag {
* one stage for each stack which had successfully changed that particular stat during onAdd. * one stage for each stack which had successfully changed that particular stat during onAdd.
*/ */
onRemove(pokemon: Pokemon): void { onRemove(pokemon: Pokemon): void {
const defChange = this.statChangeCounts[BattleStat.DEF]; const defChange = this.statChangeCounts[Stat.DEF];
const spDefChange = this.statChangeCounts[BattleStat.SPDEF]; const spDefChange = this.statChangeCounts[Stat.SPDEF];
if (defChange) { if (defChange) {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.DEF], -defChange, true, false, true)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.DEF ], -defChange, true, false, true));
} }
if (spDefChange) { if (spDefChange) {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.SPDEF], -spDefChange, true, false, true)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.SPDEF ], -spDefChange, true, false, true));
} }
} }
} }
@ -1864,6 +1900,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
return new DrowsyTag(); return new DrowsyTag();
case BattlerTagType.TRAPPED: case BattlerTagType.TRAPPED:
return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
case BattlerTagType.NO_RETREAT:
return new NoRetreatTag(sourceId);
case BattlerTagType.BIND: case BattlerTagType.BIND:
return new BindTag(turnCount, sourceId); return new BindTag(turnCount, sourceId);
case BattlerTagType.WRAP: case BattlerTagType.WRAP:
@ -1889,11 +1927,11 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
case BattlerTagType.SPIKY_SHIELD: case BattlerTagType.SPIKY_SHIELD:
return new ContactDamageProtectedTag(sourceMove, 8); return new ContactDamageProtectedTag(sourceMove, 8);
case BattlerTagType.KINGS_SHIELD: case BattlerTagType.KINGS_SHIELD:
return new ContactStatChangeProtectedTag(sourceMove, tagType, BattleStat.ATK, -1); return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.ATK, -1);
case BattlerTagType.OBSTRUCT: case BattlerTagType.OBSTRUCT:
return new ContactStatChangeProtectedTag(sourceMove, tagType, BattleStat.DEF, -2); return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.DEF, -2);
case BattlerTagType.SILK_TRAP: case BattlerTagType.SILK_TRAP:
return new ContactStatChangeProtectedTag(sourceMove, tagType, BattleStat.SPD, -1); return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1);
case BattlerTagType.BANEFUL_BUNKER: case BattlerTagType.BANEFUL_BUNKER:
return new ContactPoisonProtectedTag(sourceMove); return new ContactPoisonProtectedTag(sourceMove);
case BattlerTagType.BURNING_BULWARK: case BattlerTagType.BURNING_BULWARK:
@ -1923,6 +1961,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
return new TypeBoostTag(tagType, sourceMove, Type.FIRE, 1.5, false); return new TypeBoostTag(tagType, sourceMove, Type.FIRE, 1.5, false);
case BattlerTagType.CRIT_BOOST: case BattlerTagType.CRIT_BOOST:
return new CritBoostTag(tagType, sourceMove); return new CritBoostTag(tagType, sourceMove);
case BattlerTagType.DRAGON_CHEER:
return new DragonCheerTag();
case BattlerTagType.ALWAYS_CRIT: case BattlerTagType.ALWAYS_CRIT:
case BattlerTagType.IGNORE_ACCURACY: case BattlerTagType.IGNORE_ACCURACY:
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, 2, sourceMove); return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, 2, sourceMove);

View File

@ -1,14 +1,14 @@
import { getPokemonNameWithAffix } from "../messages"; import { getPokemonNameWithAffix } from "../messages";
import Pokemon, { HitResult } from "../field/pokemon"; import Pokemon, { HitResult } from "../field/pokemon";
import { BattleStat } from "./battle-stat";
import { getStatusEffectHealText } from "./status-effect"; import { getStatusEffectHealText } from "./status-effect";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./ability"; import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./ability";
import i18next from "i18next"; import i18next from "i18next";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase.js"; import { Stat, type BattleStat } from "#app/enums/stat";
import { StatChangePhase } from "#app/phases/stat-change-phase.js"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
export function getBerryName(berryType: BerryType): string { export function getBerryName(berryType: BerryType): string {
return i18next.t(`berry:${BerryType[berryType]}.name`); return i18next.t(`berry:${BerryType[berryType]}.name`);
@ -35,9 +35,10 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate {
case BerryType.SALAC: case BerryType.SALAC:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new Utils.NumberHolder(0.25);
const battleStat = (berryType - BerryType.LIECHI) as BattleStat; // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
const stat: BattleStat = berryType - BerryType.ENIGMA;
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < threshold.value && pokemon.summonData.battleStats[battleStat] < 6; return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6;
}; };
case BerryType.LANSAT: case BerryType.LANSAT:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
@ -95,10 +96,11 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
const battleStat = (berryType - BerryType.LIECHI) as BattleStat; // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
const statLevels = new Utils.NumberHolder(1); const stat: BattleStat = berryType - BerryType.ENIGMA;
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statLevels); const statStages = new Utils.NumberHolder(1);
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ battleStat ], statLevels.value)); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value));
}; };
case BerryType.LANSAT: case BerryType.LANSAT:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
@ -112,9 +114,10 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
const statLevels = new Utils.NumberHolder(2); const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statLevels); const stages = new Utils.NumberHolder(2);
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ BattleStat.RAND ], statLevels.value)); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value));
}; };
case BerryType.LEPPA: case BerryType.LEPPA:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {

View File

@ -1,6 +1,6 @@
import { Type } from "./type"; import { Type } from "./type";
import * as Utils from "../utils"; import * as Utils from "../utils";
import {pokemonEvolutions, SpeciesFormEvolution} from "./pokemon-evolutions"; import { pokemonEvolutions, SpeciesFormEvolution } from "./pokemon-evolutions";
import i18next from "i18next"; import i18next from "i18next";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
@ -46,7 +46,7 @@ export const biomeLinks: BiomeLinks = {
[Biome.SEABED]: [ Biome.CAVE, [ Biome.VOLCANO, 3 ] ], [Biome.SEABED]: [ Biome.CAVE, [ Biome.VOLCANO, 3 ] ],
[Biome.MOUNTAIN]: [ Biome.VOLCANO, [ Biome.WASTELAND, 2 ], [ Biome.SPACE, 3 ] ], [Biome.MOUNTAIN]: [ Biome.VOLCANO, [ Biome.WASTELAND, 2 ], [ Biome.SPACE, 3 ] ],
[Biome.BADLANDS]: [ Biome.DESERT, Biome.MOUNTAIN ], [Biome.BADLANDS]: [ Biome.DESERT, Biome.MOUNTAIN ],
[Biome.CAVE]: [ Biome.BADLANDS, Biome.LAKE [ Biome.LABORATORY, 2 ] ], [Biome.CAVE]: [ Biome.BADLANDS, Biome.LAKE, [ Biome.LABORATORY, 2 ] ],
[Biome.DESERT]: [ Biome.RUINS, [ Biome.CONSTRUCTION_SITE, 2 ] ], [Biome.DESERT]: [ Biome.RUINS, [ Biome.CONSTRUCTION_SITE, 2 ] ],
[Biome.ICE_CAVE]: Biome.SNOWY_FOREST, [Biome.ICE_CAVE]: Biome.SNOWY_FOREST,
[Biome.MEADOW]: [ Biome.PLAINS, Biome.FAIRY_CAVE ], [Biome.MEADOW]: [ Biome.PLAINS, Biome.FAIRY_CAVE ],
@ -7666,7 +7666,7 @@ export function initBiomes() {
if (biome === Biome.END) { if (biome === Biome.END) {
const biomeList = Object.keys(Biome).filter(key => !isNaN(Number(key))); const biomeList = Object.keys(Biome).filter(key => !isNaN(Number(key)));
biomeList.pop(); // Removes Biome.END from the list biomeList.pop(); // Removes Biome.END from the list
const randIndex = Utils.randInt(biomeList.length, 2); // Will never be Biome.TOWN or Biome.PLAINS const randIndex = Utils.randInt(biomeList.length, 1); // Will never be Biome.TOWN
biome = Biome[biomeList[randIndex]]; biome = Biome[biomeList[randIndex]];
} }
const linkedBiomes: (Biome | [ Biome, integer ])[] = Array.isArray(biomeLinks[biome]) const linkedBiomes: (Biome | [ Biome, integer ])[] = Array.isArray(biomeLinks[biome])

View File

@ -13,7 +13,6 @@ import { TrainerType } from "#enums/trainer-type";
import { Nature } from "./nature"; import { Nature } from "./nature";
import { Moves } from "#app/enums/moves.js"; import { Moves } from "#app/enums/moves.js";
import { TypeColor, TypeShadow } from "#app/enums/color.js"; import { TypeColor, TypeShadow } from "#app/enums/color.js";
import { Gender } from "./gender";
import { pokemonEvolutions } from "./pokemon-evolutions"; import { pokemonEvolutions } from "./pokemon-evolutions";
import { pokemonFormChanges } from "./pokemon-forms"; import { pokemonFormChanges } from "./pokemon-forms";
@ -659,7 +658,6 @@ export class FreshStartChallenge extends Challenge {
pokemon.luck = 0; // No luck pokemon.luck = 0; // No luck
pokemon.shiny = false; // Not shiny pokemon.shiny = false; // Not shiny
pokemon.variant = 0; // Not shiny pokemon.variant = 0; // Not shiny
pokemon.gender = Gender.MALE; // Starters default to male
pokemon.formIndex = 0; // Froakie should be base form 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; return true;

View File

@ -1,6 +1,6 @@
import { BattleSpec } from "#enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import {trainerConfigs} from "./trainer-config"; import { trainerConfigs } from "./trainer-config";
export interface TrainerTypeMessages { export interface TrainerTypeMessages {
encounter?: string | string[], encounter?: string | string[],
@ -707,6 +707,20 @@ export const trainerTypeDialogue: TrainerTypeDialogue = {
] ]
} }
], ],
[TrainerType.ROOD]: [
{
encounter: [
"dialogue:rood.encounter.1",
"dialogue:rood.encounter.2",
"dialogue:rood.encounter.3",
],
victory: [
"dialogue:rood.victory.1",
"dialogue:rood.victory.2",
"dialogue:rood.victory.3",
]
}
],
[TrainerType.FLARE_GRUNT]: [ [TrainerType.FLARE_GRUNT]: [
{ {
encounter: [ encounter: [

View File

@ -0,0 +1,98 @@
import BattleScene from "#app/battle-scene";
import { PlayerPokemon } from "#app/field/pokemon";
import { DexEntry, StarterDataEntry } from "#app/system/game-data";
/**
* Stores data associated with a specific egg and the hatched pokemon
* Allows hatch info to be stored at hatch then retrieved for display during egg summary
*/
export class EggHatchData {
/** the pokemon that hatched from the file (including shiny, IVs, ability) */
public pokemon: PlayerPokemon;
/** index of the egg move from the hatched pokemon (not stored in PlayerPokemon) */
public eggMoveIndex: number;
/** boolean indicating if the egg move for the hatch is new */
public eggMoveUnlocked: boolean;
/** stored copy of the hatched pokemon's dex entry before it was updated due to hatch */
public dexEntryBeforeUpdate: DexEntry;
/** stored copy of the hatched pokemon's starter entry before it was updated due to hatch */
public starterDataEntryBeforeUpdate: StarterDataEntry;
/** reference to the battle scene to get gamedata and update dex */
private scene: BattleScene;
constructor(scene: BattleScene, pokemon: PlayerPokemon, eggMoveIndex: number) {
this.scene = scene;
this.pokemon = pokemon;
this.eggMoveIndex = eggMoveIndex;
}
/**
* Sets the boolean for if the egg move for the hatch is a new unlock
* @param unlocked True if the EM is new
*/
setEggMoveUnlocked(unlocked: boolean) {
this.eggMoveUnlocked = unlocked;
}
/**
* Stores a copy of the current DexEntry of the pokemon and StarterDataEntry of its starter
* Used before updating the dex, so comparing the pokemon to these entries will show the new attributes
*/
setDex() {
const currDexEntry = this.scene.gameData.dexData[this.pokemon.species.speciesId];
const currStarterDataEntry = this.scene.gameData.starterData[this.pokemon.species.getRootSpeciesId()];
this.dexEntryBeforeUpdate = {
seenAttr: currDexEntry.seenAttr,
caughtAttr: currDexEntry.caughtAttr,
natureAttr: currDexEntry.natureAttr,
seenCount: currDexEntry.seenCount,
caughtCount: currDexEntry.caughtCount,
hatchedCount: currDexEntry.hatchedCount,
ivs: [...currDexEntry.ivs]
};
this.starterDataEntryBeforeUpdate = {
moveset: currStarterDataEntry.moveset,
eggMoves: currStarterDataEntry.eggMoves,
candyCount: currStarterDataEntry.candyCount,
friendship: currStarterDataEntry.friendship,
abilityAttr: currStarterDataEntry.abilityAttr,
passiveAttr: currStarterDataEntry.passiveAttr,
valueReduction: currStarterDataEntry.valueReduction,
classicWinCount: currStarterDataEntry.classicWinCount
};
}
/**
* Gets the dex entry before update
* @returns Dex Entry corresponding to this pokemon before the pokemon was added / updated to dex
*/
getDex(): DexEntry {
return this.dexEntryBeforeUpdate;
}
/**
* Gets the starter dex entry before update
* @returns Starter Dex Entry corresponding to this pokemon before the pokemon was added / updated to dex
*/
getStarterEntry(): StarterDataEntry {
return this.starterDataEntryBeforeUpdate;
}
/**
* Update the pokedex data corresponding with the new hatch's pokemon data
* Also sets whether the egg move is a new unlock or not
* @param showMessage boolean to show messages for the new catches and egg moves (false by default)
* @returns
*/
updatePokemon(showMessage : boolean = false) {
return new Promise<void>(resolve => {
this.scene.gameData.setPokemonCaught(this.pokemon, true, true, showMessage).then(() => {
this.scene.gameData.updateSpeciesDexIvs(this.pokemon.species.speciesId, this.pokemon.ivs);
this.scene.gameData.setEggMoveUnlocked(this.pokemon.species, this.eggMoveIndex, showMessage).then((value) => {
this.setEggMoveUnlocked(value);
resolve();
});
});
});
}
}

View File

@ -139,46 +139,57 @@ export class Egg {
//// ////
constructor(eggOptions?: IEggOptions) { constructor(eggOptions?: IEggOptions) {
//if (eggOptions.tier && eggOptions.species) throw Error("Error egg can't have species and tier as option. only choose one of them.") const generateEggProperties = (eggOptions?: IEggOptions) => {
//if (eggOptions.tier && eggOptions.species) throw Error("Error egg can't have species and tier as option. only choose one of them.")
this._sourceType = eggOptions?.sourceType!; // TODO: is this bang correct? this._sourceType = eggOptions?.sourceType!; // TODO: is this bang correct?
// Ensure _sourceType is defined before invoking rollEggTier(), as it is referenced // Ensure _sourceType is defined before invoking rollEggTier(), as it is referenced
this._tier = eggOptions?.tier ?? (Overrides.EGG_TIER_OVERRIDE ?? this.rollEggTier()); this._tier = eggOptions?.tier ?? (Overrides.EGG_TIER_OVERRIDE ?? this.rollEggTier());
// If egg was pulled, check if egg pity needs to override the egg tier // If egg was pulled, check if egg pity needs to override the egg tier
if (eggOptions?.pulled) { if (eggOptions?.pulled) {
// Needs this._tier and this._sourceType to work // Needs this._tier and this._sourceType to work
this.checkForPityTierOverrides(eggOptions.scene!); // TODO: is this bang correct? this.checkForPityTierOverrides(eggOptions.scene!); // TODO: is this bang correct?
} }
this._id = eggOptions?.id ?? Utils.randInt(EGG_SEED, EGG_SEED * this._tier); this._id = eggOptions?.id ?? Utils.randInt(EGG_SEED, EGG_SEED * this._tier);
this._sourceType = eggOptions?.sourceType ?? undefined; this._sourceType = eggOptions?.sourceType ?? undefined;
this._hatchWaves = eggOptions?.hatchWaves ?? this.getEggTierDefaultHatchWaves(); this._hatchWaves = eggOptions?.hatchWaves ?? this.getEggTierDefaultHatchWaves();
this._timestamp = eggOptions?.timestamp ?? new Date().getTime(); this._timestamp = eggOptions?.timestamp ?? new Date().getTime();
// First roll shiny and variant so we can filter if species with an variant exist // First roll shiny and variant so we can filter if species with an variant exist
this._isShiny = eggOptions?.isShiny ?? (Overrides.EGG_SHINY_OVERRIDE || this.rollShiny()); this._isShiny = eggOptions?.isShiny ?? (Overrides.EGG_SHINY_OVERRIDE || this.rollShiny());
this._variantTier = eggOptions?.variantTier ?? (Overrides.EGG_VARIANT_OVERRIDE ?? this.rollVariant()); this._variantTier = eggOptions?.variantTier ?? (Overrides.EGG_VARIANT_OVERRIDE ?? this.rollVariant());
this._species = eggOptions?.species ?? this.rollSpecies(eggOptions!.scene!)!; // TODO: Are those bangs correct? this._species = eggOptions?.species ?? this.rollSpecies(eggOptions!.scene!)!; // TODO: Are those bangs correct?
this._overrideHiddenAbility = eggOptions?.overrideHiddenAbility ?? false; this._overrideHiddenAbility = eggOptions?.overrideHiddenAbility ?? false;
// Override egg tier and hatchwaves if species was given // Override egg tier and hatchwaves if species was given
if (eggOptions?.species) { if (eggOptions?.species) {
this._tier = this.getEggTierFromSpeciesStarterValue(); this._tier = this.getEggTierFromSpeciesStarterValue();
this._hatchWaves = eggOptions.hatchWaves ?? this.getEggTierDefaultHatchWaves(); this._hatchWaves = eggOptions.hatchWaves ?? this.getEggTierDefaultHatchWaves();
} }
// If species has no variant, set variantTier to common. This needs to // If species has no variant, set variantTier to common. This needs to
// be done because species with no variants get filtered at rollSpecies but if the // be done because species with no variants get filtered at rollSpecies but if the
// species is set via options or the legendary gacha pokemon gets choosen the check never happens // species is set via options or the legendary gacha pokemon gets choosen the check never happens
if (this._species && !getPokemonSpecies(this._species).hasVariants()) { if (this._species && !getPokemonSpecies(this._species).hasVariants()) {
this._variantTier = VariantTier.COMMON; this._variantTier = VariantTier.COMMON;
} }
// Needs this._tier so it needs to be generated afer the tier override if bought from same species // Needs this._tier so it needs to be generated afer the tier override if bought from same species
this._eggMoveIndex = eggOptions?.eggMoveIndex ?? this.rollEggMoveIndex(); this._eggMoveIndex = eggOptions?.eggMoveIndex ?? this.rollEggMoveIndex();
if (eggOptions?.pulled) { if (eggOptions?.pulled) {
this.increasePullStatistic(eggOptions.scene!); // TODO: is this bang correct? this.increasePullStatistic(eggOptions.scene!); // TODO: is this bang correct?
this.addEggToGameData(eggOptions.scene!); // TODO: is this bang correct? this.addEggToGameData(eggOptions.scene!); // TODO: is this bang correct?
}
};
if (eggOptions?.scene) {
const seedOverride = Utils.randomString(24);
eggOptions?.scene.executeWithSeedOffset(() => {
generateEggProperties(eggOptions);
}, 0, seedOverride);
} else { // For legacy eggs without scene
generateEggProperties(eggOptions);
} }
} }
@ -200,37 +211,46 @@ export class Egg {
// Generates a PlayerPokemon from an egg // Generates a PlayerPokemon from an egg
public generatePlayerPokemon(scene: BattleScene): PlayerPokemon { public generatePlayerPokemon(scene: BattleScene): PlayerPokemon {
// Legacy egg wants to hatch. Generate missing properties let ret: PlayerPokemon;
if (!this._species) {
this._isShiny = this.rollShiny();
this._species = this.rollSpecies(scene!)!; // TODO: are these bangs correct?
}
let pokemonSpecies = getPokemonSpecies(this._species); const generatePlayerPokemonHelper = (scene: BattleScene) => {
// Special condition to have Phione eggs also have a chance of generating Manaphy // Legacy egg wants to hatch. Generate missing properties
if (this._species === Species.PHIONE) { if (!this._species) {
pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY); this._isShiny = this.rollShiny();
} this._species = this.rollSpecies(scene!)!; // TODO: are these bangs correct?
}
// Sets the hidden ability if a hidden ability exists and let pokemonSpecies = getPokemonSpecies(this._species);
// the override is set or the egg hits the chance // Special condition to have Phione eggs also have a chance of generating Manaphy
let abilityIndex: number | undefined = undefined; if (this._species === Species.PHIONE) {
const sameSpeciesEggHACheck = (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !Utils.randSeedInt(SAME_SPECIES_EGG_HA_RATE)); pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY);
const gachaEggHACheck = (!(this._sourceType === EggSourceType.SAME_SPECIES_EGG) && !Utils.randSeedInt(GACHA_EGG_HA_RATE)); }
if (pokemonSpecies.abilityHidden && (this._overrideHiddenAbility || sameSpeciesEggHACheck || gachaEggHACheck)) {
abilityIndex = 2;
}
// This function has way to many optional parameters // Sets the hidden ability if a hidden ability exists and
const ret: PlayerPokemon = scene.addPlayerPokemon(pokemonSpecies, 1, abilityIndex, undefined, undefined, false); // the override is set or the egg hits the chance
ret.shiny = this._isShiny; let abilityIndex: number | undefined = undefined;
ret.variant = this._variantTier; const sameSpeciesEggHACheck = (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !Utils.randSeedInt(SAME_SPECIES_EGG_HA_RATE));
const gachaEggHACheck = (!(this._sourceType === EggSourceType.SAME_SPECIES_EGG) && !Utils.randSeedInt(GACHA_EGG_HA_RATE));
if (pokemonSpecies.abilityHidden && (this._overrideHiddenAbility || sameSpeciesEggHACheck || gachaEggHACheck)) {
abilityIndex = 2;
}
const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295)); // This function has way to many optional parameters
ret = scene.addPlayerPokemon(pokemonSpecies, 1, abilityIndex, undefined, undefined, false);
ret.shiny = this._isShiny;
ret.variant = this._variantTier;
for (let s = 0; s < ret.ivs.length; s++) { const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295));
ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]);
} for (let s = 0; s < ret.ivs.length; s++) {
ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]);
}
};
ret = ret!; // Tell TS compiler it's defined now
scene.executeWithSeedOffset(() => {
generatePlayerPokemonHelper(scene);
}, this._id, EGG_SEED.toString());
return ret; return ret;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
import { Stat, getStatName } from "./pokemon-stat";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { TextStyle, getBBCodeFrag } from "../ui/text"; import { TextStyle, getBBCodeFrag } from "../ui/text";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { UiTheme } from "#enums/ui-theme"; import { UiTheme } from "#enums/ui-theme";
import i18next from "i18next"; import i18next from "i18next";
import { Stat, EFFECTIVE_STATS, getShortenedStatKey } from "#app/enums/stat";
export { Nature }; export { Nature };
@ -14,10 +14,9 @@ export function getNatureName(nature: Nature, includeStatEffects: boolean = fals
ret = i18next.t("nature:" + ret as any); ret = i18next.t("nature:" + ret as any);
} }
if (includeStatEffects) { if (includeStatEffects) {
const stats = Utils.getEnumValues(Stat).slice(1);
let increasedStat: Stat | null = null; let increasedStat: Stat | null = null;
let decreasedStat: Stat | null = null; let decreasedStat: Stat | null = null;
for (const stat of stats) { for (const stat of EFFECTIVE_STATS) {
const multiplier = getNatureStatMultiplier(nature, stat); const multiplier = getNatureStatMultiplier(nature, stat);
if (multiplier > 1) { if (multiplier > 1) {
increasedStat = stat; increasedStat = stat;
@ -28,7 +27,7 @@ export function getNatureName(nature: Nature, includeStatEffects: boolean = fals
const textStyle = forStarterSelect ? TextStyle.SUMMARY_ALT : TextStyle.WINDOW; const textStyle = forStarterSelect ? TextStyle.SUMMARY_ALT : TextStyle.WINDOW;
const getTextFrag = !ignoreBBCode ? (text: string, style: TextStyle) => getBBCodeFrag(text, style, uiTheme) : (text: string, style: TextStyle) => text; const getTextFrag = !ignoreBBCode ? (text: string, style: TextStyle) => getBBCodeFrag(text, style, uiTheme) : (text: string, style: TextStyle) => text;
if (increasedStat && decreasedStat) { if (increasedStat && decreasedStat) {
ret = `${getTextFrag(`${ret}${!forStarterSelect ? "\n" : " "}(`, textStyle)}${getTextFrag(`+${getStatName(increasedStat, true)}`, TextStyle.SUMMARY_PINK)}${getTextFrag("/", textStyle)}${getTextFrag(`-${getStatName(decreasedStat, true)}`, TextStyle.SUMMARY_BLUE)}${getTextFrag(")", textStyle)}`; ret = `${getTextFrag(`${ret}${!forStarterSelect ? "\n" : " "}(`, textStyle)}${getTextFrag(`+${i18next.t(getShortenedStatKey(increasedStat))}`, TextStyle.SUMMARY_PINK)}${getTextFrag("/", textStyle)}${getTextFrag(`-${i18next.t(getShortenedStatKey(decreasedStat))}`, TextStyle.SUMMARY_BLUE)}${getTextFrag(")", textStyle)}`;
} else { } else {
ret = getTextFrag(`${ret}${!forStarterSelect ? "\n" : " "}(-)`, textStyle); ret = getTextFrag(`${ret}${!forStarterSelect ? "\n" : " "}(-)`, textStyle);
} }

View File

@ -1,7 +1,7 @@
import { Gender } from "./gender"; import { Gender } from "./gender";
import { PokeballType } from "./pokeball"; import { PokeballType } from "./pokeball";
import Pokemon from "../field/pokemon"; import Pokemon from "../field/pokemon";
import { Stat } from "./pokemon-stat"; import { Stat } from "#enums/stat";
import { Type } from "./type"; import { Type } from "./type";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { SpeciesFormKey } from "./pokemon-species"; import { SpeciesFormKey } from "./pokemon-species";

View File

@ -66,34 +66,34 @@ export enum FormChangeItem {
BLUE_ORB = 50, BLUE_ORB = 50,
RED_ORB, RED_ORB,
SHARP_METEORITE,
HARD_METEORITE,
SMOOTH_METEORITE,
ADAMANT_CRYSTAL, ADAMANT_CRYSTAL,
LUSTROUS_GLOBE, LUSTROUS_GLOBE,
GRISEOUS_CORE, GRISEOUS_CORE,
REVEAL_GLASS, REVEAL_GLASS,
GRACIDEA,
MAX_MUSHROOMS, MAX_MUSHROOMS,
DARK_STONE, DARK_STONE,
LIGHT_STONE, LIGHT_STONE,
PRISON_BOTTLE, PRISON_BOTTLE,
N_LUNARIZER,
N_SOLARIZER,
RUSTED_SWORD, RUSTED_SWORD,
RUSTED_SHIELD, RUSTED_SHIELD,
ICY_REINS_OF_UNITY, ICY_REINS_OF_UNITY,
SHADOW_REINS_OF_UNITY, SHADOW_REINS_OF_UNITY,
WELLSPRING_MASK, ULTRANECROZIUM_Z,
HEARTHFLAME_MASK,
CORNERSTONE_MASK, SHARP_METEORITE = 100,
HARD_METEORITE,
SMOOTH_METEORITE,
GRACIDEA,
SHOCK_DRIVE, SHOCK_DRIVE,
BURN_DRIVE, BURN_DRIVE,
CHILL_DRIVE, CHILL_DRIVE,
DOUSE_DRIVE, DOUSE_DRIVE,
ULTRANECROZIUM_Z, N_SOLARIZER,
N_LUNARIZER,
FIST_PLATE = 100, WELLSPRING_MASK,
HEARTHFLAME_MASK,
CORNERSTONE_MASK,
FIST_PLATE,
SKY_PLATE, SKY_PLATE,
TOXIC_PLATE, TOXIC_PLATE,
EARTH_PLATE, EARTH_PLATE,
@ -129,7 +129,7 @@ export enum FormChangeItem {
DRAGON_MEMORY, DRAGON_MEMORY,
DARK_MEMORY, DARK_MEMORY,
FAIRY_MEMORY, FAIRY_MEMORY,
BLANK_MEMORY // TODO: Find a potential use for this NORMAL_MEMORY // TODO: Find a potential use for this
} }
export type SpeciesFormChangeConditionPredicate = (p: Pokemon) => boolean; export type SpeciesFormChangeConditionPredicate = (p: Pokemon) => boolean;
@ -359,7 +359,7 @@ export class SpeciesDefaultFormMatchTrigger extends SpeciesFormChangeTrigger {
/** /**
* Class used for triggering form changes based on weather. * Class used for triggering form changes based on weather.
* Used by Castform. * Used by Castform and Cherrim.
* @extends SpeciesFormChangeTrigger * @extends SpeciesFormChangeTrigger
*/ */
export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger { export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger {
@ -392,7 +392,7 @@ export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger {
/** /**
* Class used for reverting to the original form when the weather runs out * Class used for reverting to the original form when the weather runs out
* or when the user loses the ability/is suppressed. * or when the user loses the ability/is suppressed.
* Used by Castform. * Used by Castform and Cherrim.
* @extends SpeciesFormChangeTrigger * @extends SpeciesFormChangeTrigger
*/ */
export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChangeTrigger { export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChangeTrigger {
@ -930,6 +930,11 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeActiveTrigger(), true), new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeActiveTrigger(), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeActiveTrigger(), true), new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeActiveTrigger(), true),
], ],
[Species.CHERRIM]: [
new SpeciesFormChange(Species.CHERRIM, "overcast", "sunshine", new SpeciesFormChangeWeatherTrigger(Abilities.FLOWER_GIFT, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true),
new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FLOWER_GIFT, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG, WeatherType.HAIL, WeatherType.HEAVY_RAIN, WeatherType.SNOW, WeatherType.RAIN ]), true),
new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeActiveTrigger(), true),
],
}; };
export function initPokemonForms() { export function initPokemonForms() {

View File

@ -14,7 +14,7 @@ import { GrowthRate } from "./exp";
import { EvolutionLevel, SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions"; import { EvolutionLevel, SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions";
import { Type } from "./type"; import { Type } from "./type";
import { LevelMoves, pokemonFormLevelMoves, pokemonFormLevelMoves as pokemonSpeciesFormLevelMoves, pokemonSpeciesLevelMoves } from "./pokemon-level-moves"; import { LevelMoves, pokemonFormLevelMoves, pokemonFormLevelMoves as pokemonSpeciesFormLevelMoves, pokemonSpeciesLevelMoves } from "./pokemon-level-moves";
import { Stat } from "./pokemon-stat"; import { Stat } from "#enums/stat";
import { Variant, VariantSet, variantColorCache, variantData } from "./variant"; import { Variant, VariantSet, variantColorCache, variantData } from "./variant";
export enum Region { export enum Region {
@ -944,7 +944,7 @@ export function initSpecies() {
new PokemonSpecies(Species.METAPOD, 1, false, false, false, "Cocoon Pokémon", Type.BUG, null, 0.7, 9.9, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 50, 20, 55, 25, 25, 30, 120, 50, 72, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.METAPOD, 1, false, false, false, "Cocoon Pokémon", Type.BUG, null, 0.7, 9.9, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 50, 20, 55, 25, 25, 30, 120, 50, 72, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.BUTTERFREE, 1, false, false, false, "Butterfly Pokémon", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, GrowthRate.MEDIUM_FAST, 50, true, true, new PokemonSpecies(Species.BUTTERFREE, 1, false, false, false, "Butterfly Pokémon", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, GrowthRate.MEDIUM_FAST, 50, true, true,
new PokemonForm("Normal", "", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, true, null, true), new PokemonForm("Normal", "", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, true, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.FLYING, 17, 32, Abilities.TINTED_LENS, Abilities.TINTED_LENS, Abilities.TINTED_LENS, 495, 85, 35, 80, 120, 90, 85, 45, 50, 198, true), new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.FLYING, 17, 32, Abilities.COMPOUND_EYES, Abilities.COMPOUND_EYES, Abilities.COMPOUND_EYES, 495, 85, 35, 80, 120, 90, 85, 45, 50, 198, true),
), ),
new PokemonSpecies(Species.WEEDLE, 1, false, false, false, "Hairy Bug Pokémon", Type.BUG, Type.POISON, 0.3, 3.2, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 40, 35, 30, 20, 20, 50, 255, 70, 39, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.WEEDLE, 1, false, false, false, "Hairy Bug Pokémon", Type.BUG, Type.POISON, 0.3, 3.2, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 40, 35, 30, 20, 20, 50, 255, 70, 39, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.KAKUNA, 1, false, false, false, "Cocoon Pokémon", Type.BUG, Type.POISON, 0.6, 10, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 45, 25, 50, 25, 25, 35, 120, 70, 72, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.KAKUNA, 1, false, false, false, "Cocoon Pokémon", Type.BUG, Type.POISON, 0.6, 10, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 45, 25, 50, 25, 25, 35, 120, 70, 72, GrowthRate.MEDIUM_FAST, 50, false),

View File

@ -1,29 +0,0 @@
import { Stat } from "#enums/stat";
import i18next from "i18next";
export { Stat };
export function getStatName(stat: Stat, shorten: boolean = false) {
let ret: string = "";
switch (stat) {
case Stat.HP:
ret = !shorten ? i18next.t("pokemonInfo:Stat.HP") : i18next.t("pokemonInfo:Stat.HPshortened");
break;
case Stat.ATK:
ret = !shorten ? i18next.t("pokemonInfo:Stat.ATK") : i18next.t("pokemonInfo:Stat.ATKshortened");
break;
case Stat.DEF:
ret = !shorten ? i18next.t("pokemonInfo:Stat.DEF") : i18next.t("pokemonInfo:Stat.DEFshortened");
break;
case Stat.SPATK:
ret = !shorten ? i18next.t("pokemonInfo:Stat.SPATK") : i18next.t("pokemonInfo:Stat.SPATKshortened");
break;
case Stat.SPDEF:
ret = !shorten ? i18next.t("pokemonInfo:Stat.SPDEF") : i18next.t("pokemonInfo:Stat.SPDEFshortened");
break;
case Stat.SPD:
ret = !shorten ? i18next.t("pokemonInfo:Stat.SPD") : i18next.t("pokemonInfo:Stat.SPDshortened");
break;
}
return ret;
}

View File

@ -1,38 +0,0 @@
import { BattleStat, getBattleStatName } from "./battle-stat";
import i18next from "i18next";
export enum TempBattleStat {
ATK,
DEF,
SPATK,
SPDEF,
SPD,
ACC,
CRIT
}
export function getTempBattleStatName(tempBattleStat: TempBattleStat) {
if (tempBattleStat === TempBattleStat.CRIT) {
return i18next.t("modifierType:TempBattleStatBoosterStatName.CRIT");
}
return getBattleStatName(tempBattleStat as integer as BattleStat);
}
export function getTempBattleStatBoosterItemName(tempBattleStat: TempBattleStat) {
switch (tempBattleStat) {
case TempBattleStat.ATK:
return "X Attack";
case TempBattleStat.DEF:
return "X Defense";
case TempBattleStat.SPATK:
return "X Sp. Atk";
case TempBattleStat.SPDEF:
return "X Sp. Def";
case TempBattleStat.SPD:
return "X Speed";
case TempBattleStat.ACC:
return "X Accuracy";
case TempBattleStat.CRIT:
return "Dire Hit";
}
}

View File

@ -22,5 +22,6 @@ export enum ArenaTagType {
CRAFTY_SHIELD = "CRAFTY_SHIELD", CRAFTY_SHIELD = "CRAFTY_SHIELD",
TAILWIND = "TAILWIND", TAILWIND = "TAILWIND",
HAPPY_HOUR = "HAPPY_HOUR", HAPPY_HOUR = "HAPPY_HOUR",
SAFEGUARD = "SAFEGUARD",
NO_CRIT = "NO_CRIT" NO_CRIT = "NO_CRIT"
} }

View File

@ -69,5 +69,7 @@ export enum BattlerTagType {
GULP_MISSILE_ARROKUDA = "GULP_MISSILE_ARROKUDA", GULP_MISSILE_ARROKUDA = "GULP_MISSILE_ARROKUDA",
GULP_MISSILE_PIKACHU = "GULP_MISSILE_PIKACHU", GULP_MISSILE_PIKACHU = "GULP_MISSILE_PIKACHU",
BEAK_BLAST_CHARGING = "BEAK_BLAST_CHARGING", BEAK_BLAST_CHARGING = "BEAK_BLAST_CHARGING",
SHELL_TRAP = "SHELL_TRAP" SHELL_TRAP = "SHELL_TRAP",
DRAGON_CHEER = "DRAGON_CHEER",
NO_RETREAT = "NO_RETREAT",
} }

View File

@ -1,13 +1,13 @@
/** /**
* Determines the cursor target when entering the shop phase. * Determines the row cursor target when entering the shop phase.
*/ */
export enum ShopCursorTarget { export enum ShopCursorTarget {
/** Cursor points to Reroll */ /** Cursor points to Reroll row */
REROLL, REROLL,
/** Cursor points to Items */ /** Cursor points to Rewards row */
ITEMS, REWARDS,
/** Cursor points to Shop */ /** Cursor points to Shop row */
SHOP, SHOP,
/** Cursor points to Check Team */ /** Cursor points to Check Team row */
CHECK_TEAM CHECK_TEAM
} }

View File

@ -1,8 +1,75 @@
/** Enum that comprises all possible stat-related attributes, in-battle and permanent, of a Pokemon. */
export enum Stat { export enum Stat {
/** Hit Points */
HP = 0, HP = 0,
/** Attack */
ATK, ATK,
/** Defense */
DEF, DEF,
/** Special Attack */
SPATK, SPATK,
/** Special Defense */
SPDEF, SPDEF,
/** Speed */
SPD, SPD,
/** Accuracy */
ACC,
/** Evasiveness */
EVA
}
/** A constant array comprised of the {@linkcode Stat} values that make up {@linkcode PermanentStat}. */
export const PERMANENT_STATS = [ Stat.HP, Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ] as const;
/** Type used to describe the core, permanent stats of a Pokemon. */
export type PermanentStat = typeof PERMANENT_STATS[number];
/** A constant array comprised of the {@linkcode Stat} values that make up {@linkcode EFfectiveStat}. */
export const EFFECTIVE_STATS = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ] as const;
/** Type used to describe the intersection of core stats and stats that have stages in battle. */
export type EffectiveStat = typeof EFFECTIVE_STATS[number];
/** A constant array comprised of {@linkcode Stat} the values that make up {@linkcode BattleStat}. */
export const BATTLE_STATS = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD, Stat.ACC, Stat.EVA ] as const;
/** Type used to describe the stats that have stages which can be incremented and decremented in battle. */
export type BattleStat = typeof BATTLE_STATS[number];
/** A constant array comprised of {@linkcode Stat} the values that make up {@linkcode TempBattleStat}. */
export const TEMP_BATTLE_STATS = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD, Stat.ACC ] as const;
/** Type used to describe the stats that have X item (`TEMP_STAT_STAGE_BOOSTER`) equivalents. */
export type TempBattleStat = typeof TEMP_BATTLE_STATS[number];
/**
* Provides the translation key corresponding to the amount of stat stages and whether those stat stages
* are positive or negative.
* @param stages the amount of stages
* @param isIncrease dictates a negative (`false`) or a positive (`true`) stat stage change
* @returns the translation key fitting the conditions described by {@linkcode stages} and {@linkcode isIncrease}
*/
export function getStatStageChangeDescriptionKey(stages: number, isIncrease: boolean) {
if (stages === 1) {
return isIncrease ? "battle:statRose" : "battle:statFell";
} else if (stages === 2) {
return isIncrease ? "battle:statSharplyRose" : "battle:statHarshlyFell";
} else if (stages <= 6) {
return isIncrease ? "battle:statRoseDrastically" : "battle:statSeverelyFell";
}
return isIncrease ? "battle:statWontGoAnyHigher" : "battle:statWontGoAnyLower";
}
/**
* Provides the translation key corresponding to a given stat which can be translated into its full name.
* @param stat the {@linkcode Stat} to be translated
* @returns the translation key corresponding to the given {@linkcode Stat}
*/
export function getStatKey(stat: Stat) {
return `pokemonInfo:Stat.${Stat[stat]}`;
}
/**
* Provides the translation key corresponding to a given stat which can be translated into its shortened name.
* @param stat the {@linkcode Stat} to be translated
* @returns the translation key corresponding to the given {@linkcode Stat}
*/
export function getShortenedStatKey(stat: PermanentStat) {
return `pokemonInfo:Stat.${Stat[stat]}shortened`;
} }

View File

@ -339,7 +339,10 @@ export class Arena {
*/ */
triggerWeatherBasedFormChanges(): void { triggerWeatherBasedFormChanges(): void {
this.scene.getField(true).forEach( p => { this.scene.getField(true).forEach( p => {
if (p.hasAbility(Abilities.FORECAST) && p.species.speciesId === Species.CASTFORM) { const isCastformWithForecast = (p.hasAbility(Abilities.FORECAST) && p.species.speciesId === Species.CASTFORM);
const isCherrimWithFlowerGift = (p.hasAbility(Abilities.FLOWER_GIFT) && p.species.speciesId === Species.CHERRIM);
if (isCastformWithForecast || isCherrimWithFlowerGift) {
new ShowAbilityPhase(this.scene, p.getBattlerIndex()); new ShowAbilityPhase(this.scene, p.getBattlerIndex());
this.scene.triggerPokemonFormChange(p, SpeciesFormChangeWeatherTrigger); this.scene.triggerPokemonFormChange(p, SpeciesFormChangeWeatherTrigger);
} }
@ -351,7 +354,10 @@ export class Arena {
*/ */
triggerWeatherBasedFormChangesToNormal(): void { triggerWeatherBasedFormChangesToNormal(): void {
this.scene.getField(true).forEach( p => { this.scene.getField(true).forEach( p => {
if (p.hasAbility(Abilities.FORECAST, false, true) && p.species.speciesId === Species.CASTFORM) { const isCastformWithForecast = (p.hasAbility(Abilities.FORECAST, false, true) && p.species.speciesId === Species.CASTFORM);
const isCherrimWithFlowerGift = (p.hasAbility(Abilities.FLOWER_GIFT, false, true) && p.species.speciesId === Species.CHERRIM);
if (isCastformWithForecast || isCherrimWithFlowerGift) {
new ShowAbilityPhase(this.scene, p.getBattlerIndex()); new ShowAbilityPhase(this.scene, p.getBattlerIndex());
return this.scene.triggerPokemonFormChange(p, SpeciesFormChangeRevertWeatherFormTrigger); return this.scene.triggerPokemonFormChange(p, SpeciesFormChangeRevertWeatherFormTrigger);
} }

View File

@ -3,26 +3,24 @@ import BattleScene, { AnySound } from "../battle-scene";
import { Variant, VariantSet, variantColorCache } from "#app/data/variant"; import { Variant, VariantSet, variantColorCache } from "#app/data/variant";
import { variantData } from "#app/data/variant"; import { variantData } from "#app/data/variant";
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "../ui/battle-info"; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "../ui/battle-info";
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr } from "../data/move"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr } from "../data/move";
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species"; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species";
import { Constructor } from "#app/utils"; import { Constructor } from "#app/utils";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type"; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type";
import { getLevelTotalExp } from "../data/exp"; import { getLevelTotalExp } from "../data/exp";
import { Stat } from "../data/pokemon-stat"; import { Stat, type PermanentStat, type BattleStat, type EffectiveStat, PERMANENT_STATS, BATTLE_STATS, EFFECTIVE_STATS } from "#enums/stat";
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier } from "../modifier/modifier"; import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier } from "../modifier/modifier";
import { PokeballType } from "../data/pokeball"; import { PokeballType } from "../data/pokeball";
import { Gender } from "../data/gender"; import { Gender } from "../data/gender";
import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims"; import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
import { Status, StatusEffect, getRandomStatus } from "../data/status-effect"; import { Status, StatusEffect, getRandomStatus } from "../data/status-effect";
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "../data/pokemon-evolutions"; import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "../data/pokemon-evolutions";
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms"; import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms";
import { BattleStat } from "../data/battle-stat"; import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag } from "../data/battler-tags";
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, ExposedTag } from "../data/battler-tags";
import { WeatherType } from "../data/weather"; import { WeatherType } from "../data/weather";
import { TempBattleStat } from "../data/temp-battle-stat";
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag"; import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag";
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AddSecondStrikeAbAttr, IgnoreOpponentEvasionAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr } from "../data/ability"; import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr } from "../data/ability";
import PokemonData from "../system/pokemon-data"; import PokemonData from "../system/pokemon-data";
import { BattlerIndex } from "../battle"; import { BattlerIndex } from "../battle";
import { Mode } from "../ui/ui"; import { Mode } from "../ui/ui";
@ -40,7 +38,7 @@ import Overrides from "#app/overrides";
import i18next from "i18next"; import i18next from "i18next";
import { speciesEggMoves } from "../data/egg-moves"; import { speciesEggMoves } from "../data/egg-moves";
import { ModifierTier } from "../modifier/modifier-tier"; import { ModifierTier } from "../modifier/modifier-tier";
import { applyChallenges, ChallengeType } from "#app/data/challenge.js"; import { applyChallenges, ChallengeType } from "#app/data/challenge";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { ArenaTagType } from "#enums/arena-tag-type"; import { ArenaTagType } from "#enums/arena-tag-type";
import { BattleSpec } from "#enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
@ -49,17 +47,17 @@ import { BerryType } from "#enums/berry-type";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { getPokemonNameWithAffix } from "#app/messages";
import { DamagePhase } from "#app/phases/damage-phase";
import { FaintPhase } from "#app/phases/faint-phase";
import { LearnMovePhase } from "#app/phases/learn-move-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { MoveEndPhase } from "#app/phases/move-end-phase";
import { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
import { Challenges } from "#enums/challenges"; import { Challenges } from "#enums/challenges";
import { getPokemonNameWithAffix } from "#app/messages.js";
import { DamagePhase } from "#app/phases/damage-phase.js";
import { FaintPhase } from "#app/phases/faint-phase.js";
import { LearnMovePhase } from "#app/phases/learn-move-phase.js";
import { MoveEffectPhase } from "#app/phases/move-effect-phase.js";
import { MoveEndPhase } from "#app/phases/move-end-phase.js";
import { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase.js";
import { StatChangePhase } from "#app/phases/stat-change-phase.js";
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase.js";
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase.js";
export enum FieldPosition { export enum FieldPosition {
CENTER, CENTER,
@ -119,6 +117,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
public maskEnabled: boolean; public maskEnabled: boolean;
public maskSprite: Phaser.GameObjects.Sprite | null; public maskSprite: Phaser.GameObjects.Sprite | null;
public usedTMs: Moves[];
private shinySparkle: Phaser.GameObjects.Sprite; private shinySparkle: Phaser.GameObjects.Sprite;
constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) { constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) {
@ -133,9 +133,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); this.scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
} }
const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value);
const randAbilityIndex = Utils.randSeedInt(2);
this.species = species; this.species = species;
this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL; this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL;
this.level = level; this.level = level;
@ -146,6 +143,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.abilityIndex = abilityIndex; // Use the provided ability index if it is defined this.abilityIndex = abilityIndex; // Use the provided ability index if it is defined
} else { } else {
// If abilityIndex is not provided, determine it based on species and hidden ability // If abilityIndex is not provided, determine it based on species and hidden ability
const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value);
const randAbilityIndex = Utils.randSeedInt(2);
if (species.abilityHidden && hasHiddenAbility) { if (species.abilityHidden && hasHiddenAbility) {
// If the species has a hidden ability and the hidden ability is present // If the species has a hidden ability and the hidden ability is present
this.abilityIndex = 2; this.abilityIndex = 2;
@ -196,6 +195,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.fusionVariant = dataSource.fusionVariant || 0; this.fusionVariant = dataSource.fusionVariant || 0;
this.fusionGender = dataSource.fusionGender; this.fusionGender = dataSource.fusionGender;
this.fusionLuck = dataSource.fusionLuck; this.fusionLuck = dataSource.fusionLuck;
this.usedTMs = dataSource.usedTMs ?? [];
} else { } else {
this.id = Utils.randSeedInt(4294967296); this.id = Utils.randSeedInt(4294967296);
this.ivs = ivs || Utils.getIvsFromId(this.id); this.ivs = ivs || Utils.getIvsFromId(this.id);
@ -674,49 +674,139 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}); });
} }
getStat(stat: Stat): integer { /**
* Retrieves the entire set of stats of the {@linkcode Pokemon}.
* @param bypassSummonData prefer actual stats (`true` by default) or in-battle overriden stats (`false`)
* @returns the numeric values of the {@linkcode Pokemon}'s stats
*/
getStats(bypassSummonData: boolean = true): number[] {
if (!bypassSummonData && this.summonData?.stats) {
return this.summonData.stats;
}
return this.stats;
}
/**
* Retrieves the corresponding {@linkcode PermanentStat} of the {@linkcode Pokemon}.
* @param stat the desired {@linkcode PermanentStat}
* @param bypassSummonData prefer actual stats (`true` by default) or in-battle overridden stats (`false`)
* @returns the numeric value of the desired {@linkcode Stat}
*/
getStat(stat: PermanentStat, bypassSummonData: boolean = true): number {
if (!bypassSummonData && this.summonData && (this.summonData.stats[stat] !== 0)) {
return this.summonData.stats[stat];
}
return this.stats[stat]; return this.stats[stat];
} }
getBattleStat(stat: Stat, opponent?: Pokemon, move?: Move, isCritical: boolean = false): integer { /**
if (stat === Stat.HP) { * Writes the value to the corrseponding {@linkcode PermanentStat} of the {@linkcode Pokemon}.
return this.getStat(Stat.HP); *
} * Note that this does nothing if {@linkcode value} is less than 0.
const battleStat = (stat - 1) as BattleStat; * @param stat the desired {@linkcode PermanentStat} to be overwritten
const statLevel = new Utils.IntegerHolder(this.summonData.battleStats[battleStat]); * @param value the desired numeric value
if (opponent) { * @param bypassSummonData write to actual stats (`true` by default) or in-battle overridden stats (`false`)
if (isCritical) { */
switch (stat) { setStat(stat: PermanentStat, value: number, bypassSummonData: boolean = true): void {
case Stat.ATK: if (value >= 0) {
case Stat.SPATK: if (!bypassSummonData && this.summonData) {
statLevel.value = Math.max(statLevel.value, 0); this.summonData.stats[stat] = value;
break; } else {
case Stat.DEF: this.stats[stat] = value;
case Stat.SPDEF:
statLevel.value = Math.min(statLevel.value, 0);
break;
}
}
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, opponent, null, false, statLevel);
if (move) {
applyMoveAttrs(IgnoreOpponentStatChangesAttr, this, opponent, move, statLevel);
} }
} }
if (this.isPlayer()) { }
this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), battleStat as integer as TempBattleStat, statLevel);
/**
* Retrieves the entire set of in-battle stat stages of the {@linkcode Pokemon}.
* @returns the numeric values of the {@linkcode Pokemon}'s in-battle stat stages if available, a fresh stat stage array otherwise
*/
getStatStages(): number[] {
return this.summonData ? this.summonData.statStages : [ 0, 0, 0, 0, 0, 0, 0 ];
}
/**
* Retrieves the in-battle stage of the specified {@linkcode BattleStat}.
* @param stat the {@linkcode BattleStat} whose stage is desired
* @returns the stage of the desired {@linkcode BattleStat} if available, 0 otherwise
*/
getStatStage(stat: BattleStat): number {
return this.summonData ? this.summonData.statStages[stat - 1] : 0;
}
/**
* Writes the value to the in-battle stage of the corresponding {@linkcode BattleStat} of the {@linkcode Pokemon}.
*
* Note that, if the value is not within a range of [-6, 6], it will be forced to the closest range bound.
* @param stat the {@linkcode BattleStat} whose stage is to be overwritten
* @param value the desired numeric value
*/
setStatStage(stat: BattleStat, value: number): void {
if (this.summonData) {
if (value >= -6) {
this.summonData.statStages[stat - 1] = Math.min(value, 6);
} else {
this.summonData.statStages[stat - 1] = Math.max(value, -6);
}
} }
const statValue = new Utils.NumberHolder(this.getStat(stat)); }
/**
* Retrieves the critical-hit stage considering the move used and the Pokemon
* who used it.
* @param source the {@linkcode Pokemon} who using the move
* @param move the {@linkcode Move} being used
* @returns the final critical-hit stage value
*/
getCritStage(source: Pokemon, move: Move): number {
const critStage = new Utils.IntegerHolder(0);
applyMoveAttrs(HighCritAttr, source, this, move, critStage);
this.scene.applyModifiers(CritBoosterModifier, source.isPlayer(), source, critStage);
this.scene.applyModifiers(TempCritBoosterModifier, source.isPlayer(), critStage);
const bonusCrit = new Utils.BooleanHolder(false);
//@ts-ignore
if (applyAbAttrs(BonusCritAbAttr, source, null, false, bonusCrit)) { // TODO: resolve ts-ignore. This is a promise. Checking a promise is bogus.
if (bonusCrit.value) {
critStage.value += 1;
}
}
const critBoostTag = source.getTag(CritBoostTag);
if (critBoostTag) {
if (critBoostTag instanceof DragonCheerTag) {
critStage.value += critBoostTag.typesOnAdd.includes(Type.DRAGON) ? 2 : 1;
} else {
critStage.value += 2;
}
}
console.log(`crit stage: +${critStage.value}`);
return critStage.value;
}
/**
* Calculates and retrieves the final value of a stat considering any held
* items, move effects, opponent abilities, and whether there was a critical
* hit.
* @param stat the desired {@linkcode EffectiveStat}
* @param opponent the target {@linkcode Pokemon}
* @param move the {@linkcode Move} being used
* @param isCritical determines whether a critical hit has occurred or not (`false` by default)
* @returns the final in-battle value of a stat
*/
getEffectiveStat(stat: EffectiveStat, opponent?: Pokemon, move?: Move, isCritical: boolean = false): integer {
const statValue = new Utils.NumberHolder(this.getStat(stat, false));
this.scene.applyModifiers(StatBoosterModifier, this.isPlayer(), this, stat, statValue); this.scene.applyModifiers(StatBoosterModifier, this.isPlayer(), this, stat, statValue);
const fieldApplied = new Utils.BooleanHolder(false); const fieldApplied = new Utils.BooleanHolder(false);
for (const pokemon of this.scene.getField(true)) { for (const pokemon of this.scene.getField(true)) {
applyFieldBattleStatMultiplierAbAttrs(FieldMultiplyBattleStatAbAttr, pokemon, stat, statValue, this, fieldApplied); applyFieldStatMultiplierAbAttrs(FieldMultiplyStatAbAttr, pokemon, stat, statValue, this, fieldApplied);
if (fieldApplied.value) { if (fieldApplied.value) {
break; break;
} }
} }
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, this, battleStat, statValue); applyStatMultiplierAbAttrs(StatMultiplierAbAttr, this, stat, statValue);
let ret = statValue.value * (Math.max(2, 2 + statLevel.value) / Math.max(2, 2 - statLevel.value)); let ret = statValue.value * this.getStatStageMultiplier(stat, opponent, move, isCritical);
switch (stat) { switch (stat) {
case Stat.ATK: case Stat.ATK:
if (this.getTag(BattlerTagType.SLOW_START)) { if (this.getTag(BattlerTagType.SLOW_START)) {
@ -763,24 +853,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (!this.stats) { if (!this.stats) {
this.stats = [ 0, 0, 0, 0, 0, 0 ]; this.stats = [ 0, 0, 0, 0, 0, 0 ];
} }
const baseStats = this.getSpeciesForm().baseStats.slice(0);
if (this.fusionSpecies) { // Get and manipulate base stats
const fusionBaseStats = this.getFusionSpeciesForm().baseStats; const baseStats = this.getSpeciesForm(true).baseStats.slice();
for (let s = 0; s < this.stats.length; s++) { if (this.isFusion()) {
const fusionBaseStats = this.getFusionSpeciesForm(true).baseStats;
for (const s of PERMANENT_STATS) {
baseStats[s] = Math.ceil((baseStats[s] + fusionBaseStats[s]) / 2); baseStats[s] = Math.ceil((baseStats[s] + fusionBaseStats[s]) / 2);
} }
} else if (this.scene.gameMode.isSplicedOnly) { } else if (this.scene.gameMode.isSplicedOnly) {
for (let s = 0; s < this.stats.length; s++) { for (const s of PERMANENT_STATS) {
baseStats[s] = Math.ceil(baseStats[s] / 2); baseStats[s] = Math.ceil(baseStats[s] / 2);
} }
} }
this.scene.applyModifiers(PokemonBaseStatModifier, this.isPlayer(), this, baseStats); this.scene.applyModifiers(BaseStatModifier, this.isPlayer(), this, baseStats);
const stats = Utils.getEnumValues(Stat);
for (const s of stats) { // Using base stats, calculate and store stats one by one
const isHp = s === Stat.HP; for (const s of PERMANENT_STATS) {
const baseStat = baseStats[s]; let value = Math.floor(((2 * baseStats[s] + this.ivs[s]) * this.level) * 0.01);
let value = Math.floor(((2 * baseStat + this.ivs[s]) * this.level) * 0.01); if (s === Stat.HP) {
if (isHp) {
value = value + this.level + 10; value = value + this.level + 10;
if (this.hasAbility(Abilities.WONDER_GUARD, false, true)) { if (this.hasAbility(Abilities.WONDER_GUARD, false, true)) {
value = 1; value = 1;
@ -801,7 +892,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
value = Math.max(Math[natureStatMultiplier.value > 1 ? "ceil" : "floor"](value * natureStatMultiplier.value), 1); value = Math.max(Math[natureStatMultiplier.value > 1 ? "ceil" : "floor"](value * natureStatMultiplier.value), 1);
} }
} }
this.stats[s] = value;
this.setStat(s, value);
} }
} }
@ -936,7 +1028,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (this.metBiome === -1 && !this.scene.gameMode.isFreshStartChallenge() && !this.scene.gameMode.isDaily) { if (this.metBiome === -1 && !this.scene.gameMode.isFreshStartChallenge() && !this.scene.gameMode.isDaily) {
levelMoves = this.getUnlockedEggMoves().concat(levelMoves); levelMoves = this.getUnlockedEggMoves().concat(levelMoves);
} }
return levelMoves.filter(lm => !this.moveset.some(m => m?.moveId === lm)); if (Array.isArray(this.usedTMs) && this.usedTMs.length > 0) {
levelMoves = this.usedTMs.filter(m => !levelMoves.includes(m)).concat(levelMoves);
}
levelMoves = levelMoves.filter(lm => !this.moveset.some(m => m?.moveId === lm));
return levelMoves;
} }
/** /**
@ -1210,6 +1306,28 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return !!this.getTag(GroundedTag) || (!this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.MAGNET_RISEN) && !this.getTag(SemiInvulnerableTag)); return !!this.getTag(GroundedTag) || (!this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.MAGNET_RISEN) && !this.getTag(SemiInvulnerableTag));
} }
/**
* Determines whether this Pokemon is prevented from running or switching due
* to effects from moves and/or abilities.
* @param trappedAbMessages `string[]` If defined, ability trigger messages
* (e.g. from Shadow Tag) are forwarded through this array.
* @param simulated `boolean` if `true`, applies abilities via simulated calls.
* @returns
*/
isTrapped(trappedAbMessages: string[] = [], simulated: boolean = true): boolean {
if (this.isOfType(Type.GHOST)) {
return false;
}
const trappedByAbility = new Utils.BooleanHolder(false);
this.scene.getEnemyField()!.forEach(enemyPokemon =>
applyCheckTrappedAbAttrs(CheckTrappedAbAttr, enemyPokemon, trappedByAbility, this, trappedAbMessages, simulated)
);
return (trappedByAbility.value || !!this.getTag(TrappedTag));
}
/** /**
* Calculates the type of a move when used by this Pokemon after * Calculates the type of a move when used by this Pokemon after
* type-changing move and ability attributes have applied. * type-changing move and ability attributes have applied.
@ -1276,6 +1394,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
} }
// Apply Tera Shell's effect to attacks after all immunities are accounted for
if (!ignoreAbility && move.category !== MoveCategory.STATUS) {
applyPreDefendAbAttrs(FullHpResistTypeAbAttr, this, source, move, cancelledHolder, simulated, typeMultiplier);
}
return (!cancelledHolder.value ? typeMultiplier.value : 0) as TypeDamageMultiplier; return (!cancelledHolder.value ? typeMultiplier.value : 0) as TypeDamageMultiplier;
} }
@ -1345,7 +1468,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const types = this.getTypes(true); const types = this.getTypes(true);
const enemyTypes = opponent.getTypes(true, true); const enemyTypes = opponent.getTypes(true, true);
/** Is this Pokemon faster than the opponent? */ /** Is this Pokemon faster than the opponent? */
const outspeed = (this.isActive(true) ? this.getBattleStat(Stat.SPD, opponent) : this.getStat(Stat.SPD)) >= opponent.getBattleStat(Stat.SPD, this); const outspeed = (this.isActive(true) ? this.getEffectiveStat(Stat.SPD, opponent) : this.getStat(Stat.SPD, false)) >= opponent.getEffectiveStat(Stat.SPD, this);
/** /**
* Based on how effective this Pokemon's types are offensively against the opponent's types. * Based on how effective this Pokemon's types are offensively against the opponent's types.
* This score is increased by 25 percent if this Pokemon is faster than the opponent. * This score is increased by 25 percent if this Pokemon is faster than the opponent.
@ -1501,13 +1624,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
/** /**
* Function that tries to set a Pokemon shiny based on the trainer's trainer ID and secret ID * Function that tries to set a Pokemon shiny based on the trainer's trainer ID and secret ID.
* Endless Pokemon in the end biome are unable to be set to shiny * Endless Pokemon in the end biome are unable to be set to shiny
* *
* The exact mechanic is that it calculates E as the XOR of the player's trainer ID and secret ID * The exact mechanic is that it calculates E as the XOR of the player's trainer ID and secret ID.
* F is calculated as the XOR of the first 16 bits of the Pokemon's ID with the last 16 bits * F is calculated as the XOR of the first 16 bits of the Pokemon's ID with the last 16 bits.
* The XOR of E and F are then compared to the thresholdOverride (default case 32) to see whether or not to generate a shiny * The XOR of E and F are then compared to the {@linkcode shinyThreshold} (or {@linkcode thresholdOverride} if set) to see whether or not to generate a shiny.
* @param thresholdOverride number that is divided by 2^16 (65536) to get the shiny chance * The base shiny odds are {@linkcode baseShinyChance} / 65536
* @param thresholdOverride number that is divided by 2^16 (65536) to get the shiny chance, overrides {@linkcode shinyThreshold} if set (bypassing shiny rate modifiers such as Shiny Charm)
* @returns true if the Pokemon has been set as a shiny, false otherwise * @returns true if the Pokemon has been set as a shiny, false otherwise
*/ */
trySetShiny(thresholdOverride?: integer): boolean { trySetShiny(thresholdOverride?: integer): boolean {
@ -1522,7 +1646,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const E = this.scene.gameData.trainerId ^ this.scene.gameData.secretId; const E = this.scene.gameData.trainerId ^ this.scene.gameData.secretId;
const F = rand1 ^ rand2; const F = rand1 ^ rand2;
const shinyThreshold = new Utils.IntegerHolder(32); /** `64/65536 -> 1/1024` */
const baseShinyChance = 64;
const shinyThreshold = new Utils.IntegerHolder(baseShinyChance);
if (thresholdOverride === undefined) { if (thresholdOverride === undefined) {
if (this.scene.eventManager.isEventActive()) { if (this.scene.eventManager.isEventActive()) {
shinyThreshold.value *= this.scene.eventManager.getShinyMultiplier(); shinyThreshold.value *= this.scene.eventManager.getShinyMultiplier();
@ -1535,9 +1661,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
this.shiny = (E ^ F) < shinyThreshold.value; this.shiny = (E ^ F) < shinyThreshold.value;
if ((E ^ F) < 32) {
console.log("REAL SHINY!!");
}
if (this.shiny) { if (this.shiny) {
this.initShinySparkle(); this.initShinySparkle();
@ -1724,7 +1847,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1)]); movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1)]);
movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttrOnHit) ? 0.5 : 1)]); movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttrOnHit) ? 0.5 : 1)]);
// Trainers get a weight bump to stat buffing moves // Trainers get a weight bump to stat buffing moves
movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].getAttrs(StatChangeAttr).some(a => a.levels > 1 && a.selfTarget) ? 1.25 : 1)]); movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].getAttrs(StatStageChangeAttr).some(a => a.stages > 1 && a.selfTarget) ? 1.25 : 1)]);
// Trainers get a weight decrease to multiturn moves // Trainers get a weight decrease to multiturn moves
movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(ChargeAttr) || !!allMoves[m[0]].hasAttr(RechargeAttr) ? 0.7 : 1)]); movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(ChargeAttr) || !!allMoves[m[0]].hasAttr(RechargeAttr) ? 0.7 : 1)]);
} }
@ -1736,8 +1859,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].category === MoveCategory.STATUS ? 1 : Math.max(Math.min(allMoves[m[0]].power/maxPower, 1), 0.5))]); movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].category === MoveCategory.STATUS ? 1 : Math.max(Math.min(allMoves[m[0]].power/maxPower, 1), 0.5))]);
// Weight damaging moves against the lower stat // Weight damaging moves against the lower stat
const worseCategory: MoveCategory = this.stats[Stat.ATK] > this.stats[Stat.SPATK] ? MoveCategory.SPECIAL : MoveCategory.PHYSICAL; const atk = this.getStat(Stat.ATK);
const statRatio = worseCategory === MoveCategory.PHYSICAL ? this.stats[Stat.ATK]/this.stats[Stat.SPATK] : this.stats[Stat.SPATK]/this.stats[Stat.ATK]; const spAtk = this.getStat(Stat.SPATK);
const worseCategory: MoveCategory = atk > spAtk ? MoveCategory.SPECIAL : MoveCategory.PHYSICAL;
const statRatio = worseCategory === MoveCategory.PHYSICAL ? atk / spAtk : spAtk / atk;
movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].category === worseCategory ? statRatio : 1)]); movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].category === worseCategory ? statRatio : 1)]);
let weightMultiplier = 0.9; // The higher this is the more the game weights towards higher level moves. At 0 all moves are equal weight. let weightMultiplier = 0.9; // The higher this is the more the game weights towards higher level moves. At 0 all moves are equal weight.
@ -1923,6 +2048,48 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this instanceof PlayerPokemon ? this.scene.getPlayerField() : this.scene.getEnemyField(); return this instanceof PlayerPokemon ? this.scene.getPlayerField() : this.scene.getEnemyField();
} }
/**
* Calculates the stat stage multiplier of the user against an opponent.
*
* Note that this does not apply to evasion or accuracy
* @see {@linkcode getAccuracyMultiplier}
* @param stat the desired {@linkcode EffectiveStat}
* @param opponent the target {@linkcode Pokemon}
* @param move the {@linkcode Move} being used
* @param isCritical determines whether a critical hit has occurred or not (`false` by default)
* @return the stat stage multiplier to be used for effective stat calculation
*/
getStatStageMultiplier(stat: EffectiveStat, opponent?: Pokemon, move?: Move, isCritical: boolean = false): number {
const statStage = new Utils.IntegerHolder(this.getStatStage(stat));
const ignoreStatStage = new Utils.BooleanHolder(false);
if (opponent) {
if (isCritical) {
switch (stat) {
case Stat.ATK:
case Stat.SPATK:
statStage.value = Math.max(statStage.value, 0);
break;
case Stat.DEF:
case Stat.SPDEF:
statStage.value = Math.min(statStage.value, 0);
break;
}
}
applyAbAttrs(IgnoreOpponentStatStagesAbAttr, opponent, null, false, stat, ignoreStatStage);
if (move) {
applyMoveAttrs(IgnoreOpponentStatStagesAttr, this, opponent, move, ignoreStatStage);
}
}
if (!ignoreStatStage.value) {
const statStageMultiplier = new Utils.NumberHolder(Math.max(2, 2 + statStage.value) / Math.max(2, 2 - statStage.value));
this.scene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), stat, statStageMultiplier);
return Math.min(statStageMultiplier.value, 4);
}
return 1;
}
/** /**
* Calculates the accuracy multiplier of the user against a target. * Calculates the accuracy multiplier of the user against a target.
* *
@ -1939,34 +2106,38 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return 1; return 1;
} }
const userAccuracyLevel = new Utils.IntegerHolder(this.summonData.battleStats[BattleStat.ACC]); const userAccStage = new Utils.IntegerHolder(this.getStatStage(Stat.ACC));
const targetEvasionLevel = new Utils.IntegerHolder(target.summonData.battleStats[BattleStat.EVA]); const targetEvaStage = new Utils.IntegerHolder(target.getStatStage(Stat.EVA));
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, false, userAccuracyLevel); const ignoreAccStatStage = new Utils.BooleanHolder(false);
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, this, null, false, targetEvasionLevel); const ignoreEvaStatStage = new Utils.BooleanHolder(false);
applyAbAttrs(IgnoreOpponentEvasionAbAttr, this, null, false, targetEvasionLevel);
applyMoveAttrs(IgnoreOpponentStatChangesAttr, this, target, sourceMove, targetEvasionLevel); applyAbAttrs(IgnoreOpponentStatStagesAbAttr, target, null, false, Stat.ACC, ignoreAccStatStage);
this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), TempBattleStat.ACC, userAccuracyLevel); applyAbAttrs(IgnoreOpponentStatStagesAbAttr, this, null, false, Stat.EVA, ignoreEvaStatStage);
applyMoveAttrs(IgnoreOpponentStatStagesAttr, this, target, sourceMove, ignoreEvaStatStage);
this.scene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), Stat.ACC, userAccStage);
userAccStage.value = ignoreAccStatStage.value ? 0 : Math.min(userAccStage.value, 6);
targetEvaStage.value = ignoreEvaStatStage.value ? 0 : targetEvaStage.value;
if (target.findTag(t => t instanceof ExposedTag)) { if (target.findTag(t => t instanceof ExposedTag)) {
targetEvasionLevel.value = Math.min(0, targetEvasionLevel.value); targetEvaStage.value = Math.min(0, targetEvaStage.value);
} }
const accuracyMultiplier = new Utils.NumberHolder(1); const accuracyMultiplier = new Utils.NumberHolder(1);
if (userAccuracyLevel.value !== targetEvasionLevel.value) { if (userAccStage.value !== targetEvaStage.value) {
accuracyMultiplier.value = userAccuracyLevel.value > targetEvasionLevel.value accuracyMultiplier.value = userAccStage.value > targetEvaStage.value
? (3 + Math.min(userAccuracyLevel.value - targetEvasionLevel.value, 6)) / 3 ? (3 + Math.min(userAccStage.value - targetEvaStage.value, 6)) / 3
: 3 / (3 + Math.min(targetEvasionLevel.value - userAccuracyLevel.value, 6)); : 3 / (3 + Math.min(targetEvaStage.value - userAccStage.value, 6));
} }
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, this, BattleStat.ACC, accuracyMultiplier, false, sourceMove); applyStatMultiplierAbAttrs(StatMultiplierAbAttr, this, Stat.ACC, accuracyMultiplier, false, sourceMove);
const evasionMultiplier = new Utils.NumberHolder(1); const evasionMultiplier = new Utils.NumberHolder(1);
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, target, BattleStat.EVA, evasionMultiplier); applyStatMultiplierAbAttrs(StatMultiplierAbAttr, target, Stat.EVA, evasionMultiplier);
accuracyMultiplier.value /= evasionMultiplier.value; return accuracyMultiplier.value / evasionMultiplier.value;
return accuracyMultiplier.value;
} }
/** /**
@ -2053,22 +2224,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (critOnly.value || critAlways) { if (critOnly.value || critAlways) {
isCritical = true; isCritical = true;
} else { } else {
const critLevel = new Utils.IntegerHolder(0); const critChance = [24, 8, 2, 1][Math.max(0, Math.min(this.getCritStage(source, move), 3))];
applyMoveAttrs(HighCritAttr, source, this, move, critLevel);
this.scene.applyModifiers(CritBoosterModifier, source.isPlayer(), source, critLevel);
this.scene.applyModifiers(TempBattleStatBoosterModifier, source.isPlayer(), TempBattleStat.CRIT, critLevel);
const bonusCrit = new Utils.BooleanHolder(false);
//@ts-ignore
if (applyAbAttrs(BonusCritAbAttr, source, null, false, bonusCrit)) { // TODO: resolve ts-ignore. This is a promise. Checking a promise is bogus.
if (bonusCrit.value) {
critLevel.value += 1;
}
}
if (source.getTag(BattlerTagType.CRIT_BOOST)) {
critLevel.value += 2;
}
console.log(`crit stage: +${critLevel.value}`);
const critChance = [24, 8, 2, 1][Math.max(0, Math.min(critLevel.value, 3))];
isCritical = critChance === 1 || !this.scene.randBattleSeedInt(critChance); isCritical = critChance === 1 || !this.scene.randBattleSeedInt(critChance);
if (Overrides.NEVER_CRIT_OVERRIDE) { if (Overrides.NEVER_CRIT_OVERRIDE) {
isCritical = false; isCritical = false;
@ -2082,8 +2238,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
isCritical = false; isCritical = false;
} }
} }
const sourceAtk = new Utils.IntegerHolder(source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK, this, undefined, isCritical)); const sourceAtk = new Utils.IntegerHolder(source.getEffectiveStat(isPhysical ? Stat.ATK : Stat.SPATK, this, undefined, isCritical));
const targetDef = new Utils.IntegerHolder(this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, isCritical)); const targetDef = new Utils.IntegerHolder(this.getEffectiveStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, isCritical));
const criticalMultiplier = new Utils.NumberHolder(isCritical ? 1.5 : 1); const criticalMultiplier = new Utils.NumberHolder(isCritical ? 1.5 : 1);
applyAbAttrs(MultCritAbAttr, source, null, false, criticalMultiplier); applyAbAttrs(MultCritAbAttr, source, null, false, criticalMultiplier);
const screenMultiplier = new Utils.NumberHolder(1); const screenMultiplier = new Utils.NumberHolder(1);
@ -2494,24 +2650,23 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @param source {@linkcode Pokemon} the pokemon whose stats/Tags are to be passed on from, ie: the Pokemon using Baton Pass * @param source {@linkcode Pokemon} the pokemon whose stats/Tags are to be passed on from, ie: the Pokemon using Baton Pass
*/ */
transferSummon(source: Pokemon): void { transferSummon(source: Pokemon): void {
const battleStats = Utils.getEnumValues(BattleStat); // Copy all stat stages
for (const stat of battleStats) { for (const s of BATTLE_STATS) {
this.summonData.battleStats[stat] = source.summonData.battleStats[stat]; const sourceStage = source.getStatStage(s);
if ((this instanceof PlayerPokemon) && (sourceStage === 6)) {
this.scene.validateAchv(achvs.TRANSFER_MAX_STAT_STAGE);
}
this.setStatStage(s, sourceStage);
} }
for (const tag of source.summonData.tags) { for (const tag of source.summonData.tags) {
if (!tag.isBatonPassable) {
// bypass those can not be passed via Baton Pass
const excludeTagTypes = new Set([BattlerTagType.DROWSY, BattlerTagType.INFATUATED, BattlerTagType.FIRE_BOOST]);
if (excludeTagTypes.has(tag.tagType)) {
continue; continue;
} }
this.summonData.tags.push(tag); this.summonData.tags.push(tag);
} }
if (this instanceof PlayerPokemon && source.summonData.battleStats.find(bs => bs === 6)) {
this.scene.validateAchv(achvs.TRANSFER_MAX_BATTLE_STAT);
}
this.updateInfo(); this.updateInfo();
} }
@ -2754,6 +2909,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const types = this.getTypes(true, true); const types = this.getTypes(true, true);
const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
if (sourcePokemon && sourcePokemon !== this && this.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, defendingSide)) {
return false;
}
switch (effect) { switch (effect) {
case StatusEffect.POISON: case StatusEffect.POISON:
case StatusEffect.TOXIC: case StatusEffect.TOXIC:
@ -3319,6 +3479,7 @@ export default interface Pokemon {
export class PlayerPokemon extends Pokemon { export class PlayerPokemon extends Pokemon {
public compatibleTms: Moves[]; public compatibleTms: Moves[];
public usedTms: Moves[];
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) { constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) {
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource); super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource);
@ -3342,6 +3503,7 @@ export class PlayerPokemon extends Pokemon {
} }
} }
this.generateCompatibleTms(); this.generateCompatibleTms();
this.usedTms = [];
} }
initBattleInfo(): void { initBattleInfo(): void {
@ -3600,6 +3762,9 @@ export class PlayerPokemon extends Pokemon {
newPokemon.moveset = this.moveset.slice(); newPokemon.moveset = this.moveset.slice();
newPokemon.moveset = this.copyMoveset(); newPokemon.moveset = this.copyMoveset();
newPokemon.luck = this.luck; newPokemon.luck = this.luck;
newPokemon.metLevel = this.metLevel;
newPokemon.metBiome = this.metBiome;
newPokemon.metSpecies = this.metSpecies;
newPokemon.fusionSpecies = this.fusionSpecies; newPokemon.fusionSpecies = this.fusionSpecies;
newPokemon.fusionFormIndex = this.fusionFormIndex; newPokemon.fusionFormIndex = this.fusionFormIndex;
newPokemon.fusionAbilityIndex = this.fusionAbilityIndex; newPokemon.fusionAbilityIndex = this.fusionAbilityIndex;
@ -3679,16 +3844,17 @@ export class PlayerPokemon extends Pokemon {
this.scene.gameData.gameStats.pokemonFused++; this.scene.gameData.gameStats.pokemonFused++;
// Store the average HP% that each Pokemon has // Store the average HP% that each Pokemon has
const newHpPercent = ((pokemon.hp / pokemon.stats[Stat.HP]) + (this.hp / this.stats[Stat.HP])) / 2; const maxHp = this.getMaxHp();
const newHpPercent = ((pokemon.hp / pokemon.getMaxHp()) + (this.hp / maxHp)) / 2;
this.generateName(); this.generateName();
this.calculateStats(); this.calculateStats();
// Set this Pokemon's HP to the average % of both fusion components // Set this Pokemon's HP to the average % of both fusion components
this.hp = Math.round(this.stats[Stat.HP] * newHpPercent); this.hp = Math.round(maxHp * newHpPercent);
if (!this.isFainted()) { if (!this.isFainted()) {
// If this Pokemon hasn't fainted, make sure the HP wasn't set over the new maximum // If this Pokemon hasn't fainted, make sure the HP wasn't set over the new maximum
this.hp = Math.min(this.hp, this.stats[Stat.HP]); this.hp = Math.min(this.hp, maxHp);
this.status = getRandomStatus(this.status, pokemon.status); // Get a random valid status between the two this.status = getRandomStatus(this.status, pokemon.status); // Get a random valid status between the two
} else if (!pokemon.isFainted()) { } else if (!pokemon.isFainted()) {
// If this Pokemon fainted but the other hasn't, make sure the HP wasn't set to zero // If this Pokemon fainted but the other hasn't, make sure the HP wasn't set to zero
@ -4138,7 +4304,7 @@ export class EnemyPokemon extends Pokemon {
//console.log('damage', damage, 'segment', segmentsBypassed + 1, 'segment size', segmentSize, 'damage needed', Math.round(segmentSize * Math.pow(2, segmentsBypassed + 1))); //console.log('damage', damage, 'segment', segmentsBypassed + 1, 'segment size', segmentSize, 'damage needed', Math.round(segmentSize * Math.pow(2, segmentsBypassed + 1)));
} }
damage = hpRemainder + Math.round(segmentSize * segmentsBypassed); damage = Utils.toDmgValue(this.hp - hpThreshold + segmentSize * segmentsBypassed);
clearedBossSegmentIndex = s - segmentsBypassed; clearedBossSegmentIndex = s - segmentsBypassed;
} }
break; break;
@ -4181,43 +4347,40 @@ export class EnemyPokemon extends Pokemon {
handleBossSegmentCleared(segmentIndex: integer): void { handleBossSegmentCleared(segmentIndex: integer): void {
while (segmentIndex - 1 < this.bossSegmentIndex) { while (segmentIndex - 1 < this.bossSegmentIndex) {
let boostedStat = BattleStat.RAND; // Filter out already maxed out stat stages and weigh the rest based on existing stats
const leftoverStats = EFFECTIVE_STATS.filter((s: EffectiveStat) => this.getStatStage(s) < 6);
const statWeights = leftoverStats.map((s: EffectiveStat) => this.getStat(s, false));
const battleStats = Utils.getEnumValues(BattleStat).slice(0, -3); let boostedStat: EffectiveStat;
const statWeights = new Array().fill(battleStats.length).filter((bs: BattleStat) => this.summonData.battleStats[bs] < 6).map((bs: BattleStat) => this.getStat(bs + 1)); const statThresholds: number[] = [];
const statThresholds: integer[] = [];
let totalWeight = 0; let totalWeight = 0;
for (const bs of battleStats) {
totalWeight += statWeights[bs]; for (const i in statWeights) {
totalWeight += statWeights[i];
statThresholds.push(totalWeight); statThresholds.push(totalWeight);
} }
// Pick a random stat from the leftover stats to increase its stages
const randInt = Utils.randSeedInt(totalWeight); const randInt = Utils.randSeedInt(totalWeight);
for (const i in statThresholds) {
for (const bs of battleStats) { if (randInt < statThresholds[i]) {
if (randInt < statThresholds[bs]) { boostedStat = leftoverStats[i];
boostedStat = bs;
break; break;
} }
} }
let statLevels = 1; let stages = 1;
switch (segmentIndex) { // increase the boost if the boss has at least 3 segments and we passed last shield
case 1: if (this.bossSegments >= 3 && this.bossSegmentIndex === 1) {
if (this.bossSegments >= 3) { stages++;
statLevels++; }
} // increase the boost if the boss has at least 5 segments and we passed the second to last shield
break; if (this.bossSegments >= 5 && this.bossSegmentIndex === 2) {
case 2: stages++;
if (this.bossSegments >= 5) {
statLevels++;
}
break;
} }
this.scene.unshiftPhase(new StatChangePhase(this.scene, this.getBattlerIndex(), true, [ boostedStat ], statLevels, true, true)); this.scene.unshiftPhase(new StatStageChangePhase(this.scene, this.getBattlerIndex(), true, [ boostedStat! ], stages, true, true));
this.bossSegmentIndex--; this.bossSegmentIndex--;
} }
} }
@ -4274,7 +4437,7 @@ export interface TurnMove {
targets?: BattlerIndex[]; targets?: BattlerIndex[];
result: MoveResult; result: MoveResult;
virtual?: boolean; virtual?: boolean;
turn?: integer; turn?: number;
} }
export interface QueuedMove { export interface QueuedMove {
@ -4286,17 +4449,17 @@ export interface QueuedMove {
export interface AttackMoveResult { export interface AttackMoveResult {
move: Moves; move: Moves;
result: DamageResult; result: DamageResult;
damage: integer; damage: number;
critical: boolean; critical: boolean;
sourceId: integer; sourceId: number;
sourceBattlerIndex: BattlerIndex; sourceBattlerIndex: BattlerIndex;
} }
export class PokemonSummonData { export class PokemonSummonData {
public battleStats: integer[] = [ 0, 0, 0, 0, 0, 0, 0 ]; public statStages: number[] = [ 0, 0, 0, 0, 0, 0, 0 ];
public moveQueue: QueuedMove[] = []; public moveQueue: QueuedMove[] = [];
public disabledMove: Moves = Moves.NONE; public disabledMove: Moves = Moves.NONE;
public disabledTurns: integer = 0; public disabledTurns: number = 0;
public tags: BattlerTag[] = []; public tags: BattlerTag[] = [];
public abilitySuppressed: boolean = false; public abilitySuppressed: boolean = false;
public abilitiesApplied: Abilities[] = []; public abilitiesApplied: Abilities[] = [];
@ -4306,14 +4469,14 @@ export class PokemonSummonData {
public ability: Abilities = Abilities.NONE; public ability: Abilities = Abilities.NONE;
public gender: Gender; public gender: Gender;
public fusionGender: Gender; public fusionGender: Gender;
public stats: integer[]; public stats: number[] = [ 0, 0, 0, 0, 0, 0 ];
public moveset: (PokemonMove | null)[]; public moveset: (PokemonMove | null)[];
// If not initialized this value will not be populated from save data. // If not initialized this value will not be populated from save data.
public types: Type[] = []; public types: Type[] = [];
} }
export class PokemonBattleData { export class PokemonBattleData {
public hitCount: integer = 0; public hitCount: number = 0;
public endured: boolean = false; public endured: boolean = false;
public berriesEaten: BerryType[] = []; public berriesEaten: BerryType[] = [];
public abilitiesApplied: Abilities[] = []; public abilitiesApplied: Abilities[] = [];
@ -4322,21 +4485,23 @@ export class PokemonBattleData {
export class PokemonBattleSummonData { export class PokemonBattleSummonData {
/** The number of turns the pokemon has passed since entering the battle */ /** The number of turns the pokemon has passed since entering the battle */
public turnCount: integer = 1; public turnCount: number = 1;
/** The list of moves the pokemon has used since entering the battle */ /** The list of moves the pokemon has used since entering the battle */
public moveHistory: TurnMove[] = []; public moveHistory: TurnMove[] = [];
} }
export class PokemonTurnData { export class PokemonTurnData {
public flinched: boolean; public flinched: boolean = false;
public acted: boolean; public acted: boolean = false;
public hitCount: integer; public hitCount: number;
public hitsLeft: integer; public hitsLeft: number;
public damageDealt: integer = 0; public damageDealt: number = 0;
public currDamageDealt: integer = 0; public currDamageDealt: number = 0;
public damageTaken: integer = 0; public damageTaken: number = 0;
public attacksReceived: AttackMoveResult[] = []; public attacksReceived: AttackMoveResult[] = [];
public order: number; public order: number;
public statStagesIncreased: boolean = false;
public statStagesDecreased: boolean = false;
} }
export enum AiType { export enum AiType {

View File

@ -37,8 +37,7 @@ export interface ModifierTypeTranslationEntries {
ModifierType: { [key: string]: ModifierTypeTranslationEntry }, ModifierType: { [key: string]: ModifierTypeTranslationEntry },
SpeciesBoosterItem: { [key: string]: ModifierTypeTranslationEntry }, SpeciesBoosterItem: { [key: string]: ModifierTypeTranslationEntry },
AttackTypeBoosterItem: SimpleTranslationEntries, AttackTypeBoosterItem: SimpleTranslationEntries,
TempBattleStatBoosterItem: SimpleTranslationEntries, TempStatStageBoosterItem: SimpleTranslationEntries,
TempBattleStatBoosterStatName: SimpleTranslationEntries,
BaseStatBoosterItem: SimpleTranslationEntries, BaseStatBoosterItem: SimpleTranslationEntries,
EvolutionItem: SimpleTranslationEntries, EvolutionItem: SimpleTranslationEntries,
FormChangeItem: SimpleTranslationEntries, FormChangeItem: SimpleTranslationEntries,

View File

@ -41,8 +41,6 @@ export class LoadingScene extends SceneBase {
this.loadImage("loading_bg", "arenas"); this.loadImage("loading_bg", "arenas");
this.loadImage("logo", ""); this.loadImage("logo", "");
// this.loadImage("pride-update", "events");
this.loadImage("august-variant-update", "events");
// Load menu images // Load menu images
this.loadAtlas("bg", "ui"); this.loadAtlas("bg", "ui");
@ -80,6 +78,7 @@ export class LoadingScene extends SceneBase {
this.loadAtlas("overlay_hp_boss", "ui"); this.loadAtlas("overlay_hp_boss", "ui");
this.loadImage("overlay_exp", "ui"); this.loadImage("overlay_exp", "ui");
this.loadImage("icon_owned", "ui"); this.loadImage("icon_owned", "ui");
this.loadImage("icon_egg_move", "ui");
this.loadImage("ability_bar_left", "ui"); this.loadImage("ability_bar_left", "ui");
this.loadImage("bgm_bar", "ui"); this.loadImage("bgm_bar", "ui");
this.loadImage("party_exp_bar", "ui"); this.loadImage("party_exp_bar", "ui");
@ -100,6 +99,8 @@ export class LoadingScene extends SceneBase {
this.loadImage("ha_capsule", "ui", "ha_capsule.png"); this.loadImage("ha_capsule", "ui", "ha_capsule.png");
this.loadImage("champion_ribbon", "ui", "champion_ribbon.png"); this.loadImage("champion_ribbon", "ui", "champion_ribbon.png");
this.loadImage("icon_spliced", "ui"); this.loadImage("icon_spliced", "ui");
this.loadImage("icon_lock", "ui", "icon_lock.png");
this.loadImage("icon_stop", "ui", "icon_stop.png");
this.loadImage("icon_tera", "ui"); this.loadImage("icon_tera", "ui");
this.loadImage("type_tera", "ui"); this.loadImage("type_tera", "ui");
this.loadAtlas("type_bgs", "ui"); this.loadAtlas("type_bgs", "ui");
@ -246,7 +247,12 @@ export class LoadingScene extends SceneBase {
} else { } else {
this.loadAtlas("types", ""); this.loadAtlas("types", "");
} }
const availableLangs = ["en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN"];
if (lang && availableLangs.includes(lang)) {
this.loadImage("september-update-"+lang, "events");
} else {
this.loadImage("september-update-en", "events");
}
this.loadAtlas("statuses", ""); this.loadAtlas("statuses", "");
this.loadAtlas("categories", ""); this.loadAtlas("categories", "");
@ -267,6 +273,7 @@ export class LoadingScene extends SceneBase {
this.loadImage("gacha_knob", "egg"); this.loadImage("gacha_knob", "egg");
this.loadImage("egg_list_bg", "ui"); this.loadImage("egg_list_bg", "ui");
this.loadImage("egg_summary_bg", "ui");
this.loadImage("end_m", "cg"); this.loadImage("end_m", "cg");
this.loadImage("end_f", "cg"); this.loadImage("end_f", "cg");

View File

@ -89,7 +89,7 @@
"name": "Bänder-Meister", "name": "Bänder-Meister",
"name_female": "Bänder-Meisterin" "name_female": "Bänder-Meisterin"
}, },
"TRANSFER_MAX_BATTLE_STAT": { "TRANSFER_MAX_STAT_STAGE": {
"name": "Teamwork", "name": "Teamwork",
"description": "Nutze Staffette, während der Anwender mindestens eines Statuswertes maximiert hat." "description": "Nutze Staffette, während der Anwender mindestens eines Statuswertes maximiert hat."
}, },
@ -274,4 +274,4 @@
"name": "Spieglein, Spieglein an der Wand", "name": "Spieglein, Spieglein an der Wand",
"description": "Schließe die 'Umkehrkampf' Herausforderung ab" "description": "Schließe die 'Umkehrkampf' Herausforderung ab"
} }
} }

View File

@ -47,5 +47,11 @@
"tailwindOnRemovePlayer": "Der Rückenwind auf deiner Seite hat sich gelegt!", "tailwindOnRemovePlayer": "Der Rückenwind auf deiner Seite hat sich gelegt!",
"tailwindOnRemoveEnemy": "Der Rückenwind auf gegnerischer Seite hat sich gelegt!", "tailwindOnRemoveEnemy": "Der Rückenwind auf gegnerischer Seite hat sich gelegt!",
"happyHourOnAdd": "Goldene Zeiten sind angebrochen!", "happyHourOnAdd": "Goldene Zeiten sind angebrochen!",
"happyHourOnRemove": "Die goldenen Zeiten sind vorbei!" "happyHourOnRemove": "Die goldenen Zeiten sind vorbei!",
"safeguardOnAdd": "Das ganze Feld wird von einem Schleier umhüllt!",
"safeguardOnAddPlayer": "Das Team des Anwenders wird von einem Schleier umhüllt!",
"safeguardOnAddEnemy": "Das gegnerische Team wird von einem Schleier umhüllt!",
"safeguardOnRemove": "Der mystische Schleier, der das ganze Feld umgab, hat sich gelüftet!",
"safeguardOnRemovePlayer": "Der mystische Schleier, der dein Team umgab, hat sich gelüftet!",
"safeguardOnRemoveEnemy": "Der mystische Schleier, der das gegnerische Team umgab, hat sich gelüftet!"
} }

View File

@ -94,5 +94,6 @@
"retryBattle": "Möchtest du vom Beginn des Kampfes neustarten?", "retryBattle": "Möchtest du vom Beginn des Kampfes neustarten?",
"unlockedSomething": "{{unlockedThing}} wurde freigeschaltet.", "unlockedSomething": "{{unlockedThing}} wurde freigeschaltet.",
"congratulations": "Glückwunsch!", "congratulations": "Glückwunsch!",
"beatModeFirstTime": "{{speciesName}} hat den {{gameMode}} Modus zum ersten Mal beendet! Du erhältst {{newModifier}}!" "beatModeFirstTime": "{{speciesName}} hat den {{gameMode}} Modus zum ersten Mal beendet! Du erhältst {{newModifier}}!",
"eggSkipPrompt": "Zur Ei-Zusammenfassung springen?"
} }

View File

@ -1,10 +1,11 @@
{ {
"noneSelected": "Keine ausgewählt",
"title": "Herausforderungsmodifikatoren", "title": "Herausforderungsmodifikatoren",
"illegalEvolution": "{{pokemon}} hat sich in ein Pokémon verwandelt, dass für diese Herausforderung nicht zulässig ist!", "illegalEvolution": "{{pokemon}} hat sich in ein Pokémon verwandelt, dass für diese Herausforderung nicht zulässig ist!",
"singleGeneration": { "singleGeneration": {
"name": "Mono-Generation", "name": "Mono-Generation",
"desc": "Du kannst nur Pokémon aus der {{gen}} Generation verwenden.", "desc": "Du kannst nur Pokémon aus der {{gen}} Generation verwenden.",
"desc_default": "Du kannst nur Pokémon gewählten Generation verwenden.", "desc_default": "Du kannst nur Pokémon aus der gewählten Generation verwenden.",
"gen_1": "ersten", "gen_1": "ersten",
"gen_2": "zweiten", "gen_2": "zweiten",
"gen_3": "dritten", "gen_3": "dritten",

View File

@ -1,6 +1,6 @@
{ {
"ending": "@c{smile}Oh? Du hast gewonnen?@d{96} @c{smile_eclosed}Ich schätze, das hätte ich wissen sollen.\n$Aber, du bist jetzt zurück.\n$@c{smile}Es ist vorbei.@d{64} Du hast die Schleife beendet.\n$@c{serious_smile_fists}Du hast auch deinen Traum erfüllt, nicht wahr?\nDu hast nicht einmal verloren.\n$@c{neutral}Ich bin der Einzige, der sich daran erinnern wird, was du getan hast.@d{96}\n$Ich schätze, das ist in Ordnung, oder?\n$@c{serious_smile_fists}Deine Legende wird immer in unseren Herzen weiterleben.\n$@c{smile_eclosed}Wie auch immer, ich habe genug von diesem Ort, oder nicht? Lass uns nach Hause gehen.\n$@c{serious_smile_fists}Vielleicht können wir, wenn wir zurück sind, noch einen Kampf haben?\n$Wenn du dazu bereit bist.", "ending": "@c{shock}Du bist zurück?@d{32} Bedeutet das…@d{96} du hast gewonnen?!\n$@c{smile_ehalf}Ich hätte wissen sollen, dass du es in dir hast.\n$@c{smile_eclosed}Natürlich… ich hatte immer dieses Gefühl.\n$@c{smile}Es ist jetzt vorbei, richtig? Du hast die Schleife beendet.\n$@c{smile_ehalf}Du hast auch deinen Traum erfüllt, nicht wahr?\n$Du hast nicht einmal verloren.\n$Ich werde die Einzige sein, die sich daran erinnert, was du getan hast.\n$@c{angry_mopen}Ich werde versuchen, es nicht zu vergessen!\n$@c{smile_wave_wink}Nur ein Scherz!@d{64} @c{smile}Ich würde es nie vergessen.@d{32}\n$Deine Legende wird in unseren Herzen weiterleben.\n$@c{smile_wave}Wie auch immer,@d{64} es wird spät…@d{96} denke ich?\nEs ist schwer zu sagen an diesem Ort.\n$Lass uns nach Hause gehen. \n$@c{smile_wave_wink}Vielleicht können wir morgen noch einen Kampf haben, der alten Zeiten willen?",
"ending_female": "@c{shock}Du bist zurück?@d{32} Bedeutet das…@d{96} du hast gewonnen?!\n$@c{smile_ehalf}Ich hätte wissen sollen, dass du es in dir hast.\n$@c{smile_eclosed}Natürlich… ich hatte immer dieses Gefühl.\n$@c{smile}Es ist jetzt vorbei, richtig? Du hast die Schleife beendet.\n$@c{smile_ehalf}Du hast auch deinen Traum erfüllt, nicht wahr?\n$Du hast nicht einmal verloren.\n$Ich werde die Einzige sein, die sich daran erinnert, was du getan hast.\n$@c{angry_mopen}Ich werde versuchen, es nicht zu vergessen!\n$@c{smile_wave_wink}Nur ein Scherz!@d{64} @c{smile}Ich würde es nie vergessen.@d{32}\n$Deine Legende wird in unseren Herzen weiterleben.\n$@c{smile_wave}Wie auch immer,@d{64} es wird spät…@d{96} denke ich?\nEs ist schwer zu sagen an diesem Ort.\n$Lass uns nach Hause gehen. \n$@c{smile_wave_wink}Vielleicht können wir morgen noch einen Kampf haben, der alten Zeiten willen?", "ending_female": "@c{smile}Oh? Du hast gewonnen?@d{96} @c{smile_eclosed}Ich schätze, das hätte ich wissen sollen.\n$Aber, du bist jetzt zurück.\n$@c{smile}Es ist vorbei.@d{64} Du hast die Schleife beendet.\n$@c{serious_smile_fists}Du hast auch deinen Traum erfüllt, nicht wahr?\nDu hast nicht einmal verloren.\n$@c{neutral}Ich bin der Einzige, der sich daran erinnern wird, was du getan hast.@d{96}\n$Ich schätze, das ist in Ordnung, oder?\n$@c{serious_smile_fists}Deine Legende wird immer in unseren Herzen weiterleben.\n$@c{smile_eclosed}Wie auch immer, ich habe genug von diesem Ort, oder nicht? Lass uns nach Hause gehen.\n$@c{serious_smile_fists}Vielleicht können wir, wenn wir zurück sind, noch einen Kampf haben?\n$Wenn du dazu bereit bist.",
"ending_endless": "Glückwunsch! Du hast das aktuelle Ende erreicht!\nWir arbeiten an mehr Spielinhalten.", "ending_endless": "Glückwunsch! Du hast das aktuelle Ende erreicht!\nWir arbeiten an mehr Spielinhalten.",
"ending_name": "Entwickler" "ending_name": "Entwickler"
} }

View File

@ -1403,19 +1403,19 @@
"1": "Ich muss dein Potenzial als Trainer und die Stärke der Pokémon sehen, die mit dir kämpfen!", "1": "Ich muss dein Potenzial als Trainer und die Stärke der Pokémon sehen, die mit dir kämpfen!",
"2": "Los geht's! Dies sind meine Gesteins-Pokémon, mein ganzer Stolz!", "2": "Los geht's! Dies sind meine Gesteins-Pokémon, mein ganzer Stolz!",
"3": "Gesteins-Pokémon sind einfach die besten!", "3": "Gesteins-Pokémon sind einfach die besten!",
"4": "Ich muss dein Potenzial als Trainer und die Stärke der Pokémon sehen, die mit dir kämpfen!" "4": "Tag für Tag grabe ich hier nach Fossilien.\n$Die viele Arbeit hat meine Pokémon felsenfest gemacht\nund das wirst du jetzt im Kampf zu spüren bekommen!"
}, },
"victory": { "victory": {
"1": "W-was? Das kann nicht sein! Meine total tranierten Pokémon!", "1": "W-was? Das kann nicht sein! Meine total tranierten Pokémon!",
"2": "…Wir haben die Kontrolle verloren. Beim nächsten Mal fordere ich dich\n$zu einem Fossilien-Ausgrabungswettbewerb heraus.", "2": "…Wir haben die Kontrolle verloren. Beim nächsten Mal fordere ich dich\n$zu einem Fossilien-Ausgrabungswettbewerb heraus.",
"3": "Mit deinem Können ist es nur natürlich, dass du gewinnst.", "3": "Mit deinem Können ist es nur natürlich, dass du gewinnst.",
"4": "W-was?! Das kann nicht sein! Selbst das war nicht genug?", "4": "W-was?! Das kann nicht sein! Selbst das war nicht genug?"
"5": "Ich habe es vermasselt."
}, },
"defeat": { "defeat": {
"1": "Siehst du? Ich bin stolz auf meinen steinigen Kampfstil!", "1": "Siehst du? Ich bin stolz auf meinen steinigen Kampfstil!",
"2": "Danke! Der Kampf hat mir Vertrauen gegeben, dass ich vielleicht meinen Vater besiegen kann!", "2": "Danke! Der Kampf hat mir Vertrauen gegeben, dass ich vielleicht meinen Vater besiegen kann!",
"3": "Ich fühle mich, als hätte ich gerade einen wirklich hartnäckigen Felsen durchbrochen!" "3": "Na, was sagst du jetzt? Meine felsenfesten Pokémon waren hart genug für dich, was?",
"4": "Ich wusste, dass ich gewinnen würde!"
} }
}, },
"morty": { "morty": {

View File

@ -25,5 +25,6 @@
"unlinkGoogle": "Google trennen", "unlinkGoogle": "Google trennen",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"losingProgressionWarning": "Du wirst jeglichen Fortschritt seit Anfang dieses Kampfes verlieren. Fortfahren?", "losingProgressionWarning": "Du wirst jeglichen Fortschritt seit Anfang dieses Kampfes verlieren. Fortfahren?",
"noEggs": "Du brütest aktuell keine Eier aus!" "noEggs": "Du brütest aktuell keine Eier aus!",
"donate": "Spenden"
} }

View File

@ -49,8 +49,8 @@
"DoubleBattleChanceBoosterModifierType": { "DoubleBattleChanceBoosterModifierType": {
"description": "Verdoppelt die Wahrscheinlichkeit, dass die nächsten {{battleCount}} Begegnungen mit wilden Pokémon ein Doppelkampf sind." "description": "Verdoppelt die Wahrscheinlichkeit, dass die nächsten {{battleCount}} Begegnungen mit wilden Pokémon ein Doppelkampf sind."
}, },
"TempBattleStatBoosterModifierType": { "TempStatStageBoosterModifierType": {
"description": "Erhöht die {{tempBattleStatName}} aller Teammitglieder für 5 Kämpfe um eine Stufe." "description": "Erhöht die {{stat}} aller Teammitglieder für 5 Kämpfe um eine Stufe."
}, },
"AttackTypeBoosterModifierType": { "AttackTypeBoosterModifierType": {
"description": "Erhöht die Stärke aller {{moveType}}-Attacken eines Pokémon um 20%." "description": "Erhöht die Stärke aller {{moveType}}-Attacken eines Pokémon um 20%."
@ -61,8 +61,8 @@
"AllPokemonLevelIncrementModifierType": { "AllPokemonLevelIncrementModifierType": {
"description": "Erhöht das Level aller Teammitglieder um {{levels}}." "description": "Erhöht das Level aller Teammitglieder um {{levels}}."
}, },
"PokemonBaseStatBoosterModifierType": { "BaseStatBoosterModifierType": {
"description": "Erhöht den {{statName}} Basiswert des Trägers um 10%. Das Stapellimit erhöht sich, je höher dein IS-Wert ist." "description": "Erhöht den {{stat}} Basiswert des Trägers um 10%. Das Stapellimit erhöht sich, je höher dein IS-Wert ist."
}, },
"AllPokemonFullHpRestoreModifierType": { "AllPokemonFullHpRestoreModifierType": {
"description": "Stellt 100% der KP aller Pokémon her." "description": "Stellt 100% der KP aller Pokémon her."
@ -248,6 +248,12 @@
"name": "Scope-Linse", "name": "Scope-Linse",
"description": "Ein Item zum Tragen. Es erhöht die Volltrefferquote." "description": "Ein Item zum Tragen. Es erhöht die Volltrefferquote."
}, },
"DIRE_HIT": {
"name": "X-Volltreffer",
"extra": {
"raises": "Volltrefferquote"
}
},
"LEEK": { "LEEK": {
"name": "Lauchstange", "name": "Lauchstange",
"description": "Ein Item, das von Porenta getragen werden kann. Diese lange Lauchstange erhöht die Volltrefferquote stark." "description": "Ein Item, das von Porenta getragen werden kann. Diese lange Lauchstange erhöht die Volltrefferquote stark."
@ -411,25 +417,13 @@
"description": "Ein Item, das Ditto zum Tragen gegeben werden kann. Fein und doch hart, erhöht dieses sonderbare Pulver die Initiative." "description": "Ein Item, das Ditto zum Tragen gegeben werden kann. Fein und doch hart, erhöht dieses sonderbare Pulver die Initiative."
} }
}, },
"TempBattleStatBoosterItem": { "TempStatStageBoosterItem": {
"x_attack": "X-Angriff", "x_attack": "X-Angriff",
"x_defense": "X-Verteidigung", "x_defense": "X-Verteidigung",
"x_sp_atk": "X-Sp.-Ang.", "x_sp_atk": "X-Sp.-Ang.",
"x_sp_def": "X-Sp.-Vert.", "x_sp_def": "X-Sp.-Vert.",
"x_speed": "X-Tempo", "x_speed": "X-Tempo",
"x_accuracy": "X-Treffer", "x_accuracy": "X-Treffer"
"dire_hit": "X-Volltreffer"
},
"TempBattleStatBoosterStatName": {
"ATK": "Angriff",
"DEF": "Verteidigung",
"SPATK": "Sp. Ang",
"SPDEF": "Sp. Vert",
"SPD": "Initiative",
"ACC": "Genauigkeit",
"CRIT": "Volltrefferquote",
"EVA": "Fluchtwert",
"DEFAULT": "???"
}, },
"AttackTypeBoosterItem": { "AttackTypeBoosterItem": {
"silk_scarf": "Seidenschal", "silk_scarf": "Seidenschal",
@ -604,6 +598,6 @@
"DRAGON_MEMORY": "Drachen-Disc", "DRAGON_MEMORY": "Drachen-Disc",
"DARK_MEMORY": "Unlicht-Disc", "DARK_MEMORY": "Unlicht-Disc",
"FAIRY_MEMORY": "Feen-Disc", "FAIRY_MEMORY": "Feen-Disc",
"BLANK_MEMORY": "Leere-Disc" "NORMAL_MEMORY": "Normal-Disc"
} }
} }

View File

@ -3,7 +3,7 @@
"turnHealApply": "{{typeName}} von {{pokemonNameWithAffix}} füllt einige KP auf!", "turnHealApply": "{{typeName}} von {{pokemonNameWithAffix}} füllt einige KP auf!",
"hitHealApply": "{{typeName}} von {{pokemonNameWithAffix}} füllt einige KP auf!", "hitHealApply": "{{typeName}} von {{pokemonNameWithAffix}} füllt einige KP auf!",
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} wurde durch {{typeName}} wiederbelebt!", "pokemonInstantReviveApply": "{{pokemonNameWithAffix}} wurde durch {{typeName}} wiederbelebt!",
"pokemonResetNegativeStatStageApply": "Die negative Statuswertveränderung von {{pokemonNameWithAffix}} wurde durch {{typeName}} aufgehoben!", "resetNegativeStatStageApply": "Die negative Statuswertveränderung von {{pokemonNameWithAffix}} wurde durch {{typeName}} aufgehoben!",
"moneyInterestApply": "Du erhählst {{moneyAmount}} ₽ durch das Item {{typeName}}!", "moneyInterestApply": "Du erhählst {{moneyAmount}} ₽ durch das Item {{typeName}}!",
"turnHeldItemTransferApply": "{{itemName}} von {{pokemonNameWithAffix}} wurde durch {{typeName}} von {{pokemonName}} absorbiert!", "turnHeldItemTransferApply": "{{itemName}} von {{pokemonNameWithAffix}} wurde durch {{typeName}} von {{pokemonName}} absorbiert!",
"contactHeldItemTransferApply": "{{itemName}} von {{pokemonNameWithAffix}} wurde durch {{typeName}} von {{pokemonName}} geklaut!", "contactHeldItemTransferApply": "{{itemName}} von {{pokemonNameWithAffix}} wurde durch {{typeName}} von {{pokemonName}} geklaut!",

View File

@ -3,6 +3,10 @@
"cutHpPowerUpMove": "{{pokemonName}} nutzt seine KP um seine Attacke zu verstärken!", "cutHpPowerUpMove": "{{pokemonName}} nutzt seine KP um seine Attacke zu verstärken!",
"absorbedElectricity": "{{pokemonName}} absorbiert elektrische Energie!", "absorbedElectricity": "{{pokemonName}} absorbiert elektrische Energie!",
"switchedStatChanges": "{{pokemonName}} tauschte die Statuswerteveränderungen mit dem Ziel!", "switchedStatChanges": "{{pokemonName}} tauschte die Statuswerteveränderungen mit dem Ziel!",
"switchedTwoStatChanges": "{{pokemonName}} tauscht Veränderungen an {{firstStat}} und {{secondStat}} mit dem Ziel!",
"switchedStat": "{{pokemonName}} tauscht seinen {{stat}}-Wert mit dem des Zieles!",
"sharedGuard": "{{pokemonName}} addiert seine Schutzkräfte mit jenen des Zieles und teilt sie gerecht auf!",
"sharedPower": "{{pokemonName}} addiert seine Kräfte mit jenen des Zieles und teilt sie gerecht auf!",
"goingAllOutForAttack": "{{pokemonName}} legt sich ins Zeug!", "goingAllOutForAttack": "{{pokemonName}} legt sich ins Zeug!",
"regainedHealth": "{{pokemonName}} erholt sich!", "regainedHealth": "{{pokemonName}} erholt sich!",
"keptGoingAndCrashed": "{{pokemonName}} springt daneben und verletzt sich!", "keptGoingAndCrashed": "{{pokemonName}} springt daneben und verletzt sich!",
@ -61,5 +65,6 @@
"suppressAbilities": "Die Fähigkeit von {{pokemonName}} wirkt nicht mehr!", "suppressAbilities": "Die Fähigkeit von {{pokemonName}} wirkt nicht mehr!",
"revivalBlessing": "{{pokemonName}} ist wieder fit und kampfbereit!", "revivalBlessing": "{{pokemonName}} ist wieder fit und kampfbereit!",
"swapArenaTags": "{{pokemonName}} hat die Effekte, die auf den beiden Seiten des Kampffeldes wirken, miteinander getauscht!", "swapArenaTags": "{{pokemonName}} hat die Effekte, die auf den beiden Seiten des Kampffeldes wirken, miteinander getauscht!",
"exposedMove": "{{pokemonName}} erkennt {{targetPokemonName}}!" "exposedMove": "{{pokemonName}} erkennt {{targetPokemonName}}!",
} "safeguard": "{{targetName}} wird durch Bodyguard geschützt!"
}

View File

@ -10,5 +10,5 @@
"eternamaxChange": "{{preName}} hat sich zu {{pokemonName}} unendynamaximiert!", "eternamaxChange": "{{preName}} hat sich zu {{pokemonName}} unendynamaximiert!",
"revertChange": "{{pokemonName}} hat seine ursprüngliche Form zurückerlangt!", "revertChange": "{{pokemonName}} hat seine ursprüngliche Form zurückerlangt!",
"formChange": "{{preName}} hat seine Form geändert!", "formChange": "{{preName}} hat seine Form geändert!",
"disguiseChange": "Its disguise served it as a decoy!" "disguiseChange": "Sein Kostüm hat die Attacke absorbiert!"
} }

View File

@ -1,7 +1,6 @@
{ {
"Stat": { "Stat": {
"HP": "KP", "HP": "KP",
"HPStat": "KP",
"HPshortened": "KP", "HPshortened": "KP",
"ATK": "Angriff", "ATK": "Angriff",
"ATKshortened": "Ang", "ATKshortened": "Ang",

View File

@ -100,7 +100,7 @@
"moveTouchControls": "Bewegung Touch Steuerung", "moveTouchControls": "Bewegung Touch Steuerung",
"shopOverlayOpacity": "Shop Overlay Deckkraft", "shopOverlayOpacity": "Shop Overlay Deckkraft",
"shopCursorTarget": "Shop-Cursor Ziel", "shopCursorTarget": "Shop-Cursor Ziel",
"items": "Items", "rewards": "Items",
"reroll": "Neu rollen", "reroll": "Neu rollen",
"shop": "Shop", "shop": "Shop",
"checkTeam": "Team überprüfen" "checkTeam": "Team überprüfen"

View File

@ -12,6 +12,7 @@
"blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!", "blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!",
"typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!", "typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!", "nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!",
"fullHpResistType": "{{pokemonNameWithAffix}} made its shell gleam!\nIt's distorting type matchups!",
"moveImmunity": "It doesn't affect {{pokemonNameWithAffix}}!", "moveImmunity": "It doesn't affect {{pokemonNameWithAffix}}!",
"reverseDrain": "{{pokemonNameWithAffix}} sucked up the liquid ooze!", "reverseDrain": "{{pokemonNameWithAffix}} sucked up the liquid ooze!",
"postDefendTypeChange": "{{pokemonNameWithAffix}}'s {{abilityName}}\nmade it the {{typeName}} type!", "postDefendTypeChange": "{{pokemonNameWithAffix}}'s {{abilityName}}\nmade it the {{typeName}} type!",

View File

@ -1,268 +0,0 @@
{
"Achievements": {
"name": "Achievements"
},
"Locked": {
"name": "Locked"
},
"MoneyAchv": {
"description": "Accumulate a total of ₽{{moneyAmount}}"
},
"10K_MONEY": {
"name": "Money Haver"
},
"100K_MONEY": {
"name": "Rich"
},
"1M_MONEY": {
"name": "Millionaire"
},
"10M_MONEY": {
"name": "One Percenter"
},
"DamageAchv": {
"description": "Inflict {{damageAmount}} damage in one hit"
},
"250_DMG": {
"name": "Hard Hitter"
},
"1000_DMG": {
"name": "Harder Hitter"
},
"2500_DMG": {
"name": "That's a Lotta Damage!"
},
"10000_DMG": {
"name": "One Punch Man"
},
"HealAchv": {
"description": "Heal {{healAmount}} {{HP}} at once with a move, ability, or held item"
},
"250_HEAL": {
"name": "Novice Healer"
},
"1000_HEAL": {
"name": "Big Healer"
},
"2500_HEAL": {
"name": "Cleric"
},
"10000_HEAL": {
"name": "Recovery Master"
},
"LevelAchv": {
"description": "Level up a Pokémon to Lv{{level}}"
},
"LV_100": {
"name": "But Wait, There's More!"
},
"LV_250": {
"name": "Elite"
},
"LV_1000": {
"name": "To Go Even Further Beyond"
},
"RibbonAchv": {
"description": "Accumulate a total of {{ribbonAmount}} Ribbons"
},
"10_RIBBONS": {
"name": "Pokémon League Champion"
},
"25_RIBBONS": {
"name": "Great League Champion"
},
"50_RIBBONS": {
"name": "Ultra League Champion"
},
"75_RIBBONS": {
"name": "Rogue League Champion"
},
"100_RIBBONS": {
"name": "Master League Champion"
},
"TRANSFER_MAX_BATTLE_STAT": {
"name": "Teamwork",
"description": "Baton pass to another party member with at least one stat maxed out"
},
"MAX_FRIENDSHIP": {
"name": "Friendmaxxing",
"description": "Reach max friendship on a Pokémon"
},
"MEGA_EVOLVE": {
"name": "Megamorph",
"description": "Mega evolve a Pokémon"
},
"GIGANTAMAX": {
"name": "Absolute Unit",
"description": "Gigantamax a Pokémon"
},
"TERASTALLIZE": {
"name": "STAB Enthusiast",
"description": "Terastallize a Pokémon"
},
"STELLAR_TERASTALLIZE": {
"name": "The Hidden Type",
"description": "Stellar Terastallize a Pokémon"
},
"SPLICE": {
"name": "Infinite Fusion",
"description": "Splice two Pokémon together with DNA Splicers"
},
"MINI_BLACK_HOLE": {
"name": "A Hole Lot of Items",
"description": "Acquire a Mini Black Hole"
},
"CATCH_MYTHICAL": {
"name": "Mythical",
"description": "Catch a mythical Pokémon"
},
"CATCH_SUB_LEGENDARY": {
"name": "(Sub-)Legendary",
"description": "Catch a sub-legendary Pokémon"
},
"CATCH_LEGENDARY": {
"name": "Legendary",
"description": "Catch a legendary Pokémon"
},
"SEE_SHINY": {
"name": "Shiny",
"description": "Find a shiny Pokémon in the wild"
},
"SHINY_PARTY": {
"name": "That's Dedication",
"description": "Have a full party of shiny Pokémon"
},
"HATCH_MYTHICAL": {
"name": "Mythical Egg",
"description": "Hatch a mythical Pokémon from an egg"
},
"HATCH_SUB_LEGENDARY": {
"name": "Sub-Legendary Egg",
"description": "Hatch a sub-legendary Pokémon from an egg"
},
"HATCH_LEGENDARY": {
"name": "Legendary Egg",
"description": "Hatch a legendary Pokémon from an egg"
},
"HATCH_SHINY": {
"name": "Shiny Egg",
"description": "Hatch a shiny Pokémon from an egg"
},
"HIDDEN_ABILITY": {
"name": "Hidden Potential",
"description": "Catch a Pokémon with a hidden ability"
},
"PERFECT_IVS": {
"name": "Certificate of Authenticity",
"description": "Get perfect IVs on a Pokémon"
},
"CLASSIC_VICTORY": {
"name": "Undefeated",
"description": "Beat the game in classic mode"
},
"UNEVOLVED_CLASSIC_VICTORY": {
"name": "Bring Your Child To Work Day",
"description": "Beat the game in Classic Mode with at least one unevolved party member."
},
"MONO_GEN_ONE": {
"name": "The Original Rival",
"description": "Complete the generation one only challenge."
},
"MONO_GEN_TWO": {
"name": "Generation 1.5",
"description": "Complete the generation two only challenge."
},
"MONO_GEN_THREE": {
"name": "Too much water?",
"description": "Complete the generation three only challenge."
},
"MONO_GEN_FOUR": {
"name": "Is she really the hardest?",
"description": "Complete the generation four only challenge."
},
"MONO_GEN_FIVE": {
"name": "All Original",
"description": "Complete the generation five only challenge."
},
"MONO_GEN_SIX": {
"name": "Almost Royalty",
"description": "Complete the generation six only challenge."
},
"MONO_GEN_SEVEN": {
"name": "Only Technically",
"description": "Complete the generation seven only challenge."
},
"MONO_GEN_EIGHT": {
"name": "A Champion Time!",
"description": "Complete the generation eight only challenge."
},
"MONO_GEN_NINE": {
"name": "She was going easy on you",
"description": "Complete the generation nine only challenge."
},
"MonoType": {
"description": "Complete the {{type}} monotype challenge."
},
"MONO_NORMAL": {
"name": "Extra Ordinary"
},
"MONO_FIGHTING": {
"name": "I Know Kung Fu"
},
"MONO_FLYING": {
"name": "Angry Birds"
},
"MONO_POISON": {
"name": "Kanto's Favourite"
},
"MONO_GROUND": {
"name": "Forecast: Earthquakes"
},
"MONO_ROCK": {
"name": "Brock Hard"
},
"MONO_BUG": {
"name": "You Like Jazz?"
},
"MONO_GHOST": {
"name": "Who You Gonna Call?"
},
"MONO_STEEL": {
"name": "Iron Giant"
},
"MONO_FIRE": {
"name": "I Cast Fireball!"
},
"MONO_WATER": {
"name": "When It Rains, It Pours"
},
"MONO_GRASS": {
"name": "Can't Touch This"
},
"MONO_ELECTRIC": {
"name": "Aim For The Horn!"
},
"MONO_PSYCHIC": {
"name": "Big Brain Energy"
},
"MONO_ICE": {
"name": "Walking On Thin Ice"
},
"MONO_DRAGON": {
"name": "Pseudo-Legend Club"
},
"MONO_DARK": {
"name": "It's Just A Phase"
},
"MONO_FAIRY": {
"name": "Hey! Listen!"
},
"FRESH_START": {
"name": "First Try!",
"description": "Complete the Fresh Start challenge."
},
"INVERSE_BATTLE": {
"name": "Mirror rorriM",
"description": "Complete the Inverse Battle challenge.\n.egnellahc elttaB esrevnI eht etelpmoC"
}
}

View File

@ -10,19 +10,19 @@
}, },
"10K_MONEY": { "10K_MONEY": {
"name": "Money Haver", "name": "Money Haver",
"name_female": null "name_female": "Money Haver"
}, },
"100K_MONEY": { "100K_MONEY": {
"name": "Rich", "name": "Rich",
"name_female": null "name_female": "Rich"
}, },
"1M_MONEY": { "1M_MONEY": {
"name": "Millionaire", "name": "Millionaire",
"name_female": null "name_female": "Millionaire"
}, },
"10M_MONEY": { "10M_MONEY": {
"name": "One Percenter", "name": "One Percenter",
"name_female": null "name_female": "One Percenter"
}, },
"DamageAchv": { "DamageAchv": {
"description": "Inflict {{damageAmount}} damage in one hit" "description": "Inflict {{damageAmount}} damage in one hit"
@ -32,11 +32,11 @@
}, },
"1000_DMG": { "1000_DMG": {
"name": "Harder Hitter", "name": "Harder Hitter",
"name_female": null "name_female": "Harder Hitter"
}, },
"2500_DMG": { "2500_DMG": {
"name": "That's a Lotta Damage!", "name": "That's a Lotta Damage!",
"name_female": null "name_female": "That's a Lotta Damage!"
}, },
"10000_DMG": { "10000_DMG": {
"name": "One Punch Man", "name": "One Punch Man",
@ -47,19 +47,19 @@
}, },
"250_HEAL": { "250_HEAL": {
"name": "Novice Healer", "name": "Novice Healer",
"name_female": null "name_female": "Novice Healer"
}, },
"1000_HEAL": { "1000_HEAL": {
"name": "Big Healer", "name": "Big Healer",
"name_female": null "name_female": "Big Healer"
}, },
"2500_HEAL": { "2500_HEAL": {
"name": "Cleric", "name": "Cleric",
"name_female": null "name_female": "Cleric"
}, },
"10000_HEAL": { "10000_HEAL": {
"name": "Recovery Master", "name": "Recovery Master",
"name_female": null "name_female": "Recovery Master"
}, },
"LevelAchv": { "LevelAchv": {
"description": "Level up a Pokémon to Lv{{level}}" "description": "Level up a Pokémon to Lv{{level}}"
@ -69,7 +69,7 @@
}, },
"LV_250": { "LV_250": {
"name": "Elite", "name": "Elite",
"name_female": null "name_female": "Elite"
}, },
"LV_1000": { "LV_1000": {
"name": "To Go Even Further Beyond" "name": "To Go Even Further Beyond"
@ -79,27 +79,27 @@
}, },
"10_RIBBONS": { "10_RIBBONS": {
"name": "Pokémon League Champion", "name": "Pokémon League Champion",
"name_female": null "name_female": "Pokémon League Champion"
}, },
"25_RIBBONS": { "25_RIBBONS": {
"name": "Great League Champion", "name": "Great League Champion",
"name_female": null "name_female": "Great League Champion"
}, },
"50_RIBBONS": { "50_RIBBONS": {
"name": "Ultra League Champion", "name": "Ultra League Champion",
"name_female": null "name_female": "Ultra League Champion"
}, },
"75_RIBBONS": { "75_RIBBONS": {
"name": "Rogue League Champion", "name": "Rogue League Champion",
"name_female": null "name_female": "Rogue League Champion"
}, },
"100_RIBBONS": { "100_RIBBONS": {
"name": "Master League Champion", "name": "Master League Champion",
"name_female": null "name_female": "Master League Champion"
}, },
"TRANSFER_MAX_BATTLE_STAT": { "TRANSFER_MAX_STAT_STAGE": {
"name": "Teamwork", "name": "Teamwork",
"description": "Baton pass to another party member with at least one stat maxed out" "description": "Baton pass to another party member with at least one stat stage maxed out"
}, },
"MAX_FRIENDSHIP": { "MAX_FRIENDSHIP": {
"name": "Friendmaxxing", "name": "Friendmaxxing",
@ -147,7 +147,7 @@
}, },
"SHINY_PARTY": { "SHINY_PARTY": {
"name": "That's Dedication", "name": "That's Dedication",
"name_female": null, "name_female": "That's Dedication",
"description": "Have a full party of shiny Pokémon" "description": "Have a full party of shiny Pokémon"
}, },
"HATCH_MYTHICAL": { "HATCH_MYTHICAL": {
@ -176,7 +176,7 @@
}, },
"CLASSIC_VICTORY": { "CLASSIC_VICTORY": {
"name": "Undefeated", "name": "Undefeated",
"name_female": null, "name_female": "Undefeated",
"description": "Beat the game in classic mode" "description": "Beat the game in classic mode"
}, },
"UNEVOLVED_CLASSIC_VICTORY": { "UNEVOLVED_CLASSIC_VICTORY": {
@ -284,4 +284,4 @@
"name": "Mirror rorriM", "name": "Mirror rorriM",
"description": "Complete the Inverse Battle challenge.\n.egnellahc elttaB esrevnI eht etelpmoC" "description": "Complete the Inverse Battle challenge.\n.egnellahc elttaB esrevnI eht etelpmoC"
} }
} }

View File

@ -39,5 +39,6 @@
"matBlock": "Mat Block", "matBlock": "Mat Block",
"craftyShield": "Crafty Shield", "craftyShield": "Crafty Shield",
"tailwind": "Tailwind", "tailwind": "Tailwind",
"happyHour": "Happy Hour" "happyHour": "Happy Hour",
} "safeguard": "Safeguard"
}

View File

@ -47,5 +47,11 @@
"tailwindOnRemovePlayer": "Your team's Tailwind petered out!", "tailwindOnRemovePlayer": "Your team's Tailwind petered out!",
"tailwindOnRemoveEnemy": "The opposing team's Tailwind petered out!", "tailwindOnRemoveEnemy": "The opposing team's Tailwind petered out!",
"happyHourOnAdd": "Everyone is caught up in the happy atmosphere!", "happyHourOnAdd": "Everyone is caught up in the happy atmosphere!",
"happyHourOnRemove": "The atmosphere returned to normal." "happyHourOnRemove": "The atmosphere returned to normal.",
"safeguardOnAdd": "The whole field is cloaked in a mystical veil!",
"safeguardOnAddPlayer": "Your team cloaked itself in a mystical veil!",
"safeguardOnAddEnemy": "The opposing team cloaked itself in a mystical veil!",
"safeguardOnRemove": "The field is no longer protected by Safeguard!",
"safeguardOnRemovePlayer": "Your team is no longer protected by Safeguard!",
"safeguardOnRemoveEnemy": "The opposing team is no longer protected by Safeguard!"
} }

View File

@ -61,6 +61,7 @@
"skipItemQuestion": "Are you sure you want to skip taking an item?", "skipItemQuestion": "Are you sure you want to skip taking an item?",
"itemStackFull": "The stack for {{fullItemName}} is full.\nYou will receive {{itemName}} instead.", "itemStackFull": "The stack for {{fullItemName}} is full.\nYou will receive {{itemName}} instead.",
"eggHatching": "Oh?", "eggHatching": "Oh?",
"eggSkipPrompt": "Skip to egg summary?",
"ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?", "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?",
"wildPokemonWithAffix": "Wild {{pokemonName}}", "wildPokemonWithAffix": "Wild {{pokemonName}}",
"foePokemonWithAffix": "Foe {{pokemonName}}", "foePokemonWithAffix": "Foe {{pokemonName}}",

View File

@ -1,6 +1,7 @@
{ {
"title": "Challenge Modifiers", "title": "Challenge Modifiers",
"illegalEvolution": "{{pokemon}} changed into an ineligble pokémon\nfor this challenge!", "illegalEvolution": "{{pokemon}} changed into an ineligble pokémon\nfor this challenge!",
"noneSelected": "None Selected",
"singleGeneration": { "singleGeneration": {
"name": "Mono Gen", "name": "Mono Gen",
"desc": "You can only use Pokémon from Generation {{gen}}.", "desc": "You can only use Pokémon from Generation {{gen}}.",

View File

@ -58,7 +58,7 @@
"iris_alder_double": { "iris_alder_double": {
"encounter": { "encounter": {
"1": "Iris: Welcome Challenger! I am THE Unova Champion!\n$Alder: Iris, aren't you a bit too excited?", "1": "Iris: Welcome Challenger! I am THE Unova Champion!\n$Alder: Iris, aren't you a bit too excited?",
"1_female": null "1_female": "Iris: Welcome Challenger! I am THE Unova Champion!\n$Alder: Iris, aren't you a bit too excited?"
}, },
"victory": { "victory": {
"1": "Iris: A loss like this is not easy to take...\n$Alder: But we will only get stronger with every loss!" "1": "Iris: A loss like this is not easy to take...\n$Alder: But we will only get stronger with every loss!"
@ -75,7 +75,7 @@
"marnie_piers_double": { "marnie_piers_double": {
"encounter": { "encounter": {
"1": "Piers: Ready for a concert?\n$Marnie: Brother... They are here to fight, not to sing...", "1": "Piers: Ready for a concert?\n$Marnie: Brother... They are here to fight, not to sing...",
"1_female": null "1_female": "Piers: Ready for a concert?\n$Marnie: Brother... They are here to fight, not to sing..."
}, },
"victory": { "victory": {
"1": "Piers: Now that was a great concert!\n$Marnie: Brother..." "1": "Piers: Now that was a great concert!\n$Marnie: Brother..."

View File

@ -1,6 +1,6 @@
{ {
"encounter": "It appears the time has finally come once again.\nYou know why you have come here, do you not?\n$You were drawn here, because you have been here before.\nCountless times.\n$Though, perhaps it can be counted.\nTo be precise, this is in fact your {{cycleCount}} cycle.\n$Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain.\n$Until now you have yet to succeed, but I sense a different presence in you this time.\n\n$You are the only one here, though it is as if there is… another.\n$Will you finally prove a formidable challenge to me?\nThe challenge I have longed after for millennia?\n$We begin.", "encounter": "It appears the time has finally come once again.\nYou know why you have come here, do you not?\n$You were drawn here, because you have been here before.\nCountless times.\n$Though, perhaps it can be counted.\nTo be precise, this is in fact your {{cycleCount}} cycle.\n$Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain.\n$Until now you have yet to succeed, but I sense a different presence in you this time.\n\n$You are the only one here, though it is as if there is… another.\n$Will you finally prove a formidable challenge to me?\nThe challenge I have longed after for millennia?\n$We begin.",
"encounter_female": null, "encounter_female": "It appears the time has finally come once again.\nYou know why you have come here, do you not?\n$You were drawn here, because you have been here before.\nCountless times.\n$Though, perhaps it can be counted.\nTo be precise, this is in fact your {{cycleCount}} cycle.\n$Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain.\n$Until now you have yet to succeed, but I sense a different presence in you this time.\n\n$You are the only one here, though it is as if there is… another.\n$Will you finally prove a formidable challenge to me?\nThe challenge I have longed after for millennia?\n$We begin.",
"firstStageWin": "I see. The presence I felt was indeed real.\nIt appears I no longer need to hold back.\n$Do not disappoint me.", "firstStageWin": "I see. The presence I felt was indeed real.\nIt appears I no longer need to hold back.\n$Do not disappoint me.",
"secondStageWin": "…Magnificent.", "secondStageWin": "…Magnificent.",
"key_ordinal_one": "st", "key_ordinal_one": "st",

View File

@ -1,6 +1,6 @@
{ {
"ending": "@c{smile}Oh? You won?@d{96} @c{smile_eclosed}I guess I should've known.\nBut, you're back now.\n$@c{smile}It's over.@d{64} You ended the loop.\n$@c{serious_smile_fists}You fulfilled your dream too, didn't you?\nYou didn't lose even once.\n$@c{neutral}I'm the only one who'll remember what you did.@d{96}\nI guess that's okay, isn't it?\n$@c{serious_smile_fists}Your legend will always live on in our hearts.\n$@c{smile_eclosed}Anyway, I've had about enough of this place, haven't you? Let's head home.\n$@c{serious_smile_fists}Maybe when we get back, we can have another battle?\nIf you're up to it.", "ending": "@c{shock}You're back?@d{32} Does that mean…@d{96} you won?!\n@c{smile_ehalf}I should have known you had it in you.\n$@c{smile_eclosed}Of course… I always had that feeling.\n@c{smile}It's over now, right? You ended the loop.\n$@c{smile_ehalf}You fulfilled your dream too, didn't you?\nYou didn't lose even once.\n$I'll be the only one to remember what you did.\n@c{angry_mopen}I'll try not to forget!\n$@c{smile_wave_wink}Just kidding!@d{64} @c{smile}I'd never forget.@d{32}\nYour legend will live on in our hearts.\n$@c{smile_wave}Anyway,@d{64} it's getting late…@d{96} I think?\nIt's hard to tell in this place.\n$Let's go home. @c{smile_wave_wink}Maybe tomorrow, we can have another battle, for old time's sake?",
"ending_female": "@c{shock}You're back?@d{32} Does that mean…@d{96} you won?!\n@c{smile_ehalf}I should have known you had it in you.\n$@c{smile_eclosed}Of course… I always had that feeling.\n@c{smile}It's over now, right? You ended the loop.\n$@c{smile_ehalf}You fulfilled your dream too, didn't you?\nYou didn't lose even once.\n$I'll be the only one to remember what you did.\n@c{angry_mopen}I'll try not to forget!\n$@c{smile_wave_wink}Just kidding!@d{64} @c{smile}I'd never forget.@d{32}\nYour legend will live on in our hearts.\n$@c{smile_wave}Anyway,@d{64} it's getting late…@d{96} I think?\nIt's hard to tell in this place.\n$Let's go home. @c{smile_wave_wink}Maybe tomorrow, we can have another battle, for old time's sake?", "ending_female": "@c{smile}Oh? You won?@d{96} @c{smile_eclosed}I guess I should've known.\nBut, you're back now.\n$@c{smile}It's over.@d{64} You ended the loop.\n$@c{serious_smile_fists}You fulfilled your dream too, didn't you?\nYou didn't lose even once.\n$@c{neutral}I'm the only one who'll remember what you did.@d{96}\nI guess that's okay, isn't it?\n$@c{serious_smile_fists}Your legend will always live on in our hearts.\n$@c{smile_eclosed}Anyway, I've had about enough of this place, haven't you? Let's head home.\n$@c{serious_smile_fists}Maybe when we get back, we can have another battle?\nIf you're up to it.",
"ending_endless": "Congratulations on reaching the current end!\nMore content is coming soon.", "ending_endless": "Congratulations on reaching the current end!\nMore content is coming soon.",
"ending_name": "Devs" "ending_name": "Devs"
} }

View File

@ -3,31 +3,31 @@
"encounter": { "encounter": {
"1": "Hey, wanna battle?", "1": "Hey, wanna battle?",
"2": "Are you a new trainer too?", "2": "Are you a new trainer too?",
"2_female": null, "2_female": "Are you a new trainer too?",
"3": "Hey, I haven't seen you before. Let's battle!", "3": "Hey, I haven't seen you before. Let's battle!",
"4": "I just lost, so I'm trying to find more Pokémon.\nWait! You look weak! Come on, let's battle!", "4": "I just lost, so I'm trying to find more Pokémon.\nWait! You look weak! Come on, let's battle!",
"4_female": null, "4_female": "I just lost, so I'm trying to find more Pokémon.\nWait! You look weak! Come on, let's battle!",
"5": "Have we met or not? I don't really remember. Well, I guess it's nice to meet you anyway!", "5": "Have we met or not? I don't really remember. Well, I guess it's nice to meet you anyway!",
"6": "All right! Let's go!", "6": "All right! Let's go!",
"7": "All right! Here I come! I'll show you my power!", "7": "All right! Here I come! I'll show you my power!",
"8": "Haw haw haw... I'll show you how hawesome my Pokémon are!", "8": "Haw haw haw... I'll show you how hawesome my Pokémon are!",
"9": "No need to waste time saying hello. Bring it on whenever you're ready!", "9": "No need to waste time saying hello. Bring it on whenever you're ready!",
"9_female": null, "9_female": "No need to waste time saying hello. Bring it on whenever you're ready!",
"10": "Don't let your guard down, or you may be crying when a kid beats you.", "10": "Don't let your guard down, or you may be crying when a kid beats you.",
"11": "I've raised my Pokémon with great care. You're not allowed to hurt them!", "11": "I've raised my Pokémon with great care. You're not allowed to hurt them!",
"12": "Glad you made it! It won't be an easy job from here.", "12": "Glad you made it! It won't be an easy job from here.",
"12_female": null, "12_female": "Glad you made it! It won't be an easy job from here.",
"13": "The battles continue forever! Welcome to the world with no end!", "13": "The battles continue forever! Welcome to the world with no end!",
"13_female": null "13_female": "The battles continue forever! Welcome to the world with no end!"
}, },
"victory": { "victory": {
"1": "Wow! You're strong!", "1": "Wow! You're strong!",
"1_female": null, "1_female": "Wow! You're strong!",
"2": "I didn't stand a chance, huh?", "2": "I didn't stand a chance, huh?",
"3": "I'll find you again when I'm older and beat you!", "3": "I'll find you again when I'm older and beat you!",
"4": "Ugh. I don't have any more Pokémon.", "4": "Ugh. I don't have any more Pokémon.",
"5": "No way… NO WAY! How could I lose again…", "5": "No way… NO WAY! How could I lose again…",
"5_female": null, "5_female": "No way… NO WAY! How could I lose again…",
"6": "No! I lost!", "6": "No! I lost!",
"7": "Whoa! You are incredible! I'm amazed and surprised!", "7": "Whoa! You are incredible! I'm amazed and surprised!",
"8": "Could it be… How… My Pokémon and I are the strongest, though…", "8": "Could it be… How… My Pokémon and I are the strongest, though…",
@ -42,12 +42,12 @@
"encounter": { "encounter": {
"1": "Let's have a battle, shall we?", "1": "Let's have a battle, shall we?",
"2": "You look like a new trainer. Let's have a battle!", "2": "You look like a new trainer. Let's have a battle!",
"2_female": null, "2_female": "You look like a new trainer. Let's have a battle!",
"3": "I don't recognize you. How about a battle?", "3": "I don't recognize you. How about a battle?",
"4": "Let's have a fun Pokémon battle!", "4": "Let's have a fun Pokémon battle!",
"5": "I'll show you the ropes of how to really use Pokémon!", "5": "I'll show you the ropes of how to really use Pokémon!",
"6": "A serious battle starts from a serious beginning! Are you sure you're ready?", "6": "A serious battle starts from a serious beginning! Are you sure you're ready?",
"6_female": null, "6_female": "A serious battle starts from a serious beginning! Are you sure you're ready?",
"7": "You're only young once. And you only get one shot at a given battle. Soon, you'll be nothing but a memory.", "7": "You're only young once. And you only get one shot at a given battle. Soon, you'll be nothing but a memory.",
"8": "You'd better go easy on me, OK? Though I'll be seriously fighting!", "8": "You'd better go easy on me, OK? Though I'll be seriously fighting!",
"9": "School is boring. I've got nothing to do. Yawn. I'm only battling to kill the time." "9": "School is boring. I've got nothing to do. Yawn. I'm only battling to kill the time."
@ -55,15 +55,15 @@
"victory": { "victory": {
"1": "That was impressive! I've got a lot to learn.", "1": "That was impressive! I've got a lot to learn.",
"2": "I didn't think you'd beat me that bad…", "2": "I didn't think you'd beat me that bad…",
"2_female": null, "2_female": "I didn't think you'd beat me that bad…",
"3": "I hope we get to have a rematch some day.", "3": "I hope we get to have a rematch some day.",
"4": "That was pretty amazingly fun! You've totally exhausted me…", "4": "That was pretty amazingly fun! You've totally exhausted me…",
"5": "You actually taught me a lesson! You're pretty amazing!", "5": "You actually taught me a lesson! You're pretty amazing!",
"6": "Seriously, I lost. That is, like, seriously depressing, but you were seriously cool.", "6": "Seriously, I lost. That is, like, seriously depressing, but you were seriously cool.",
"6_female": null, "6_female": "Seriously, I lost. That is, like, seriously depressing, but you were seriously cool.",
"7": "I don't need memories like this. Deleting memory…", "7": "I don't need memories like this. Deleting memory…",
"8": "Hey! I told you to go easy on me! Still, you're pretty cool when you're serious.", "8": "Hey! I told you to go easy on me! Still, you're pretty cool when you're serious.",
"8_female": null, "8_female": "Hey! I told you to go easy on me! Still, you're pretty cool when you're serious.",
"9": "I'm actually getting tired of battling… There's gotta be something new to do…" "9": "I'm actually getting tired of battling… There's gotta be something new to do…"
} }
}, },
@ -154,7 +154,7 @@
"ace_trainer": { "ace_trainer": {
"encounter": { "encounter": {
"1": "You seem quite confident.", "1": "You seem quite confident.",
"1_female": null, "1_female": "You seem quite confident.",
"2": "Your Pokémon… Show them to me…", "2": "Your Pokémon… Show them to me…",
"3": "Because I'm an Ace Trainer, people think I'm strong.", "3": "Because I'm an Ace Trainer, people think I'm strong.",
"4": "Are you aware of what it takes to be an Ace Trainer?" "4": "Are you aware of what it takes to be an Ace Trainer?"
@ -163,9 +163,9 @@
"1": "Yes… You have good Pokémon…", "1": "Yes… You have good Pokémon…",
"2": "What?! But I'm a battling genius!", "2": "What?! But I'm a battling genius!",
"3": "Of course, you are the main character!", "3": "Of course, you are the main character!",
"3_female": null, "3_female": "Of course, you are the main character!",
"4": "OK! OK! You could be an Ace Trainer!", "4": "OK! OK! You could be an Ace Trainer!",
"4_female": null "4_female": "OK! OK! You could be an Ace Trainer!"
}, },
"defeat": { "defeat": {
"1": "I am devoting my body and soul to Pokémon battles!", "1": "I am devoting my body and soul to Pokémon battles!",
@ -187,7 +187,7 @@
"1": "Get ready, because when we team up, it's double the trouble!", "1": "Get ready, because when we team up, it's double the trouble!",
"2": "Two hearts, one strategy let's see if you can keep up with our twin power!", "2": "Two hearts, one strategy let's see if you can keep up with our twin power!",
"3": "Hope you're ready for double trouble, because we're about to bring the heat!", "3": "Hope you're ready for double trouble, because we're about to bring the heat!",
"3_female": null "3_female": "Hope you're ready for double trouble, because we're about to bring the heat!"
}, },
"victory": { "victory": {
"1": "We may have lost this round, but our bond remains unbreakable!", "1": "We may have lost this round, but our bond remains unbreakable!",
@ -216,7 +216,7 @@
"encounter": { "encounter": {
"1": "I praise your courage in challenging me! For I am the one with the strongest kick!", "1": "I praise your courage in challenging me! For I am the one with the strongest kick!",
"2": "Oh, I see. Would you like to be cut to pieces? Or do you prefer the role of punching bag?", "2": "Oh, I see. Would you like to be cut to pieces? Or do you prefer the role of punching bag?",
"2_female": null "2_female": "Oh, I see. Would you like to be cut to pieces? Or do you prefer the role of punching bag?"
}, },
"victory": { "victory": {
"1": "Oh. The Pokémon did the fighting. My strong kick didn't help a bit.", "1": "Oh. The Pokémon did the fighting. My strong kick didn't help a bit.",
@ -328,7 +328,7 @@
"defeat": { "defeat": {
"1": "New age simply refers to twentieth century classical composers, right?", "1": "New age simply refers to twentieth century classical composers, right?",
"2": "Don't get hung up on sadness or frustration. You can use your grudges to motivate yourself.", "2": "Don't get hung up on sadness or frustration. You can use your grudges to motivate yourself.",
"2_female": null "2_female": "Don't get hung up on sadness or frustration. You can use your grudges to motivate yourself."
} }
}, },
"psychic": { "psychic": {
@ -360,7 +360,7 @@
"baker": { "baker": {
"encounter": { "encounter": {
"1": "Hope you're ready to taste defeat!", "1": "Hope you're ready to taste defeat!",
"1_female": null "1_female": "Hope you're ready to taste defeat!"
}, },
"victory": { "victory": {
"1": "I'll bake a comeback." "1": "I'll bake a comeback."
@ -391,7 +391,7 @@
"1": "Matey, you're walking the plank if you lose!", "1": "Matey, you're walking the plank if you lose!",
"2": "Come on then! My sailor's pride is at stake!", "2": "Come on then! My sailor's pride is at stake!",
"3": "Ahoy there! Are you seasick?", "3": "Ahoy there! Are you seasick?",
"3_female": null "3_female": "Ahoy there! Are you seasick?"
}, },
"victory": { "victory": {
"1": "Argh! Beaten by a kid!", "1": "Argh! Beaten by a kid!",
@ -413,13 +413,13 @@
}, },
"ariana": { "ariana": {
"encounter": { "encounter": {
"1": "Hold it right there! We can't someone on the loose.\n$It's harmful to Team Rocket's pride, you see.", "1": "Hold it right there!\nWe can't have someone on the loose.\n$It's harmful to Team Rocket's pride, you see.",
"2": "I don't know or care if what I'm doing is right or wrong...\n$I just put my faith in Giovanni and do as I am told", "2": "I don't know or care if what I'm doing is right or wrong...\n$I just put my faith in Giovanni and do as I am told",
"3": "Your trip ends here. I'm going to take you down!" "3": "Your trip ends here. I'm going to take you down!"
}, },
"victory": { "victory": {
"1": "Tch, you really are strong. It's too bad.\n$If you were to join Team Rocket, you could become an Executive.", "1": "Tch, you really are strong. It's too bad.\n$If you were to join Team Rocket, you could become an Executive.",
"1_female": null, "1_female": "Tch, you really are strong. It's too bad.\n$If you were to join Team Rocket, you could become an Executive.",
"2": "I... I'm shattered...", "2": "I... I'm shattered...",
"3": "Aaaieeeee! This can't be happening! I fought hard, but I still lost…" "3": "Aaaieeeee! This can't be happening! I fought hard, but I still lost…"
} }
@ -458,7 +458,7 @@
"1": "Hehehe! You might have beaten me, but you don't stand a chance against the boss!\n$If you get lost now, you won't have to face a sound whipping!", "1": "Hehehe! You might have beaten me, but you don't stand a chance against the boss!\n$If you get lost now, you won't have to face a sound whipping!",
"2": "Hehehe... So, I lost, too...", "2": "Hehehe... So, I lost, too...",
"3": "Ahya! How could this be? For an Admin like me to lose to some random trainer...", "3": "Ahya! How could this be? For an Admin like me to lose to some random trainer...",
"3_female": null "3_female": "Ahya! How could this be? For an Admin like me to lose to some random trainer..."
} }
}, },
"courtney": { "courtney": {
@ -478,13 +478,13 @@
"1": "Ahahahaha! You're going to meddle in Team Aqua's affairs?\n$You're either absolutely fearless, simply ignorant, or both!\n$You're so cute, you're disgusting! I'll put you down", "1": "Ahahahaha! You're going to meddle in Team Aqua's affairs?\n$You're either absolutely fearless, simply ignorant, or both!\n$You're so cute, you're disgusting! I'll put you down",
"2": "What's this? Who's this spoiled brat?", "2": "What's this? Who's this spoiled brat?",
"3": "Cool your jets. Be patient. I'll crush you shortly.", "3": "Cool your jets. Be patient. I'll crush you shortly.",
"3_female": null "3_female": "Cool your jets. Be patient. I'll crush you shortly."
}, },
"victory": { "victory": {
"1": "Ahahahaha! We got meddled with unexpectedly! We're out of options.\n$We'll have to pull out. But this isn't the last you'll see of Team Aqua!\n$We have other plans! Don't you forget it!", "1": "Ahahahaha! We got meddled with unexpectedly! We're out of options.\n$We'll have to pull out. But this isn't the last you'll see of Team Aqua!\n$We have other plans! Don't you forget it!",
"2": "Ahhh?! Did I go too easy on you?!", "2": "Ahhh?! Did I go too easy on you?!",
"3": "Uh. Are you telling me you've upped your game even more during the fight?\n$You're a brat with a bright future… My Pokémon and I don't have any strength left to fight…\n$Go on… Go and be destroyed by Archie.", "3": "Uh. Are you telling me you've upped your game even more during the fight?\n$You're a brat with a bright future… My Pokémon and I don't have any strength left to fight…\n$Go on… Go and be destroyed by Archie.",
"3_female": null "3_female": "Uh. Are you telling me you've upped your game even more during the fight?\n$You're a brat with a bright future… My Pokémon and I don't have any strength left to fight…\n$Go on… Go and be destroyed by Archie."
} }
}, },
"matt": { "matt": {
@ -497,7 +497,7 @@
"1": "Muwuhahaha! That battle was fun even though I lost!", "1": "Muwuhahaha! That battle was fun even though I lost!",
"2": "I can feel it! I can feel it, all right! The strength coming offa you!\n$More! I still want more! But looks like we're outta time...", "2": "I can feel it! I can feel it, all right! The strength coming offa you!\n$More! I still want more! But looks like we're outta time...",
"3": "Oho! That's a loss I can be proud of!", "3": "Oho! That's a loss I can be proud of!",
"3_female": null "3_female": "Oho! That's a loss I can be proud of!"
} }
}, },
"mars": { "mars": {
@ -505,7 +505,7 @@
"1": "I'm Mars, one of Team Galactic's top Commanders.", "1": "I'm Mars, one of Team Galactic's top Commanders.",
"2": "Team Galactic's vision for the future is unwavering. Opposition will be crushed without mercy!", "2": "Team Galactic's vision for the future is unwavering. Opposition will be crushed without mercy!",
"3": "Feeling nervous? You should be!", "3": "Feeling nervous? You should be!",
"3_female": null "3_female": "Feeling nervous? You should be!"
}, },
"victory": { "victory": {
"1": "This can't be happening! How did I lose?!", "1": "This can't be happening! How did I lose?!",
@ -540,25 +540,25 @@
"zinzolin": { "zinzolin": {
"encounter": { "encounter": {
"1": "You could become a threat to Team Plasma, so we will eliminate you here and now!", "1": "You could become a threat to Team Plasma, so we will eliminate you here and now!",
"1_female": null, "1_female": "You could become a threat to Team Plasma, so we will eliminate you here and now!",
"2": "You don't have the sense to know when to quit, it seems. It's an act of mercy on my part to bring an end to this now!", "2": "You don't have the sense to know when to quit, it seems. It's an act of mercy on my part to bring an end to this now!",
"3": "You're an impressive Trainer to have made it this far. But it ends here.", "3": "You're an impressive Trainer to have made it this far. But it ends here.",
"3_female": null "3_female": "You're an impressive Trainer to have made it this far. But it ends here."
}, },
"victory": { "victory": {
"1": "Ghetsis... I have failed you...", "1": "Ghetsis... I have failed you...",
"2": "It's bitter cold. I'm shivering. I'm suffering. Yet, we will stand victorious.", "2": "It's bitter cold. I'm shivering. I'm suffering. Yet, we will stand victorious.",
"3": "Hmph. You're a smarter Trainer than I expected, but not smart enough.", "3": "Hmph. You're a smarter Trainer than I expected, but not smart enough.",
"3_female": null "3_female": "Hmph. You're a smarter Trainer than I expected, but not smart enough."
} }
}, },
"rood": { "rood": {
"encounter": { "encounter": {
"1": "You are a threat to Team Plasma. We cannot let you walk away from here and now!", "1": "You are a threat to Team Plasma. We cannot let you walk away from here and now!",
"1_female": null, "1_female": "You are a threat to Team Plasma. We cannot let you walk away from here and now!",
"2": "It seems you don't know when to give up. I'll make sure no one interferes with our plans!", "2": "It seems you don't know when to give up. I'll make sure no one interferes with our plans!",
"3": "You are a remarkable Trainer to have made it this far. But this is where it ends.", "3": "You are a remarkable Trainer to have made it this far. But this is where it ends.",
"3_female": null "3_female": "You are a remarkable Trainer to have made it this far. But this is where it ends."
}, },
"victory": { "victory": {
"1": "Ghetsis... I have failed my mission...", "1": "Ghetsis... I have failed my mission...",
@ -569,15 +569,15 @@
"xerosic": { "xerosic": {
"encounter": { "encounter": {
"1": "Ah ha ha! It would be my pleasure. Come on, little Trainer! Let's see what you've got!", "1": "Ah ha ha! It would be my pleasure. Come on, little Trainer! Let's see what you've got!",
"1_female": null, "1_female": "Ah ha ha! It would be my pleasure. Come on, little Trainer! Let's see what you've got!",
"2": "Hmm... You're more powerful than you look. I wonder how much energy there is inside you.", "2": "Hmm... You're more powerful than you look. I wonder how much energy there is inside you.",
"2_female": null, "2_female": "Hmm... You're more powerful than you look. I wonder how much energy there is inside you.",
"3": "I've been waiting for you! I need to do a little research on you! Come, let us begin!" "3": "I've been waiting for you! I need to do a little research on you! Come, let us begin!"
}, },
"victory": { "victory": {
"1": "Ah, you're quite strong. Oh yes—very strong, indeed.", "1": "Ah, you're quite strong. Oh yes—very strong, indeed.",
"2": "Ding-ding-ding! You did it! To the victor go the spoils!", "2": "Ding-ding-ding! You did it! To the victor go the spoils!",
"2_female": null, "2_female": "Ding-ding-ding! You did it! To the victor go the spoils!",
"3": "Wonderful! Amazing! You have tremendous skill and bravery!" "3": "Wonderful! Amazing! You have tremendous skill and bravery!"
} }
}, },
@ -585,7 +585,7 @@
"encounter": { "encounter": {
"1": "I am Bryony, and it would be my pleasure to battle you. Show me what you've got.", "1": "I am Bryony, and it would be my pleasure to battle you. Show me what you've got.",
"2": "Impressive... You're more powerful than you appear. Let's see the true extent of your energy.", "2": "Impressive... You're more powerful than you appear. Let's see the true extent of your energy.",
"2_female": null, "2_female": "Impressive... You're more powerful than you appear. Let's see the true extent of your energy.",
"3": "I've anticipated your arrival. It's time for a little test. Shall we begin?" "3": "I've anticipated your arrival. It's time for a little test. Shall we begin?"
}, },
"victory": { "victory": {
@ -598,11 +598,11 @@
"encounter": { "encounter": {
"1": "Prepare for trouble!", "1": "Prepare for trouble!",
"2": "We're pulling a big job here! Get lost, kid!", "2": "We're pulling a big job here! Get lost, kid!",
"2_female": null, "2_female": "We're pulling a big job here! Get lost, kid!",
"3": "Hand over your Pokémon, or face the wrath of Team Rocket!", "3": "Hand over your Pokémon, or face the wrath of Team Rocket!",
"4": "You're about to experience the true terror of Team Rocket!", "4": "You're about to experience the true terror of Team Rocket!",
"5": "Hey, kid! Me am a Team Rocket member kind of guy!", "5": "Hey, kid! Me am a Team Rocket member kind of guy!",
"5_female": null "5_female": "Hey, kid! Me am a Team Rocket member kind of guy!"
}, },
"victory": { "victory": {
"1": "Team Rocket blasting off again!", "1": "Team Rocket blasting off again!",
@ -624,7 +624,7 @@
"1": "Huh? I lost?!", "1": "Huh? I lost?!",
"2": "I can't believe I lost! I even skipped lunch for this", "2": "I can't believe I lost! I even skipped lunch for this",
"3": "No way! You're just a kid!", "3": "No way! You're just a kid!",
"3_female": null, "3_female": "No way! You're just a kid!",
"4": "Urrrgh... I should've ducked into our hideout right away...", "4": "Urrrgh... I should've ducked into our hideout right away...",
"5": "You beat me... Do you think the boss will dock my pay for this?" "5": "You beat me... Do you think the boss will dock my pay for this?"
} }
@ -652,7 +652,7 @@
"3": "In the name of Team Galactic, I'll eliminate anyone who stands in our way!", "3": "In the name of Team Galactic, I'll eliminate anyone who stands in our way!",
"4": "Get ready to lose!", "4": "Get ready to lose!",
"5": "Hope you're ready for a cosmic beatdown!", "5": "Hope you're ready for a cosmic beatdown!",
"5_female": null "5_female": "Hope you're ready for a cosmic beatdown!"
}, },
"victory": { "victory": {
"1": "Shut down...", "1": "Shut down...",
@ -682,7 +682,7 @@
"encounter": { "encounter": {
"1": "Your Pokémon are no match for the elegance of Team Flare.", "1": "Your Pokémon are no match for the elegance of Team Flare.",
"2": "Hope you brought your sunglasses, because things are about to get bright!", "2": "Hope you brought your sunglasses, because things are about to get bright!",
"2_female": null, "2_female": "Hope you brought your sunglasses, because things are about to get bright!",
"3": "Team Flare will cleanse the world of imperfection!", "3": "Team Flare will cleanse the world of imperfection!",
"4": "Prepare to face the brilliance of Team Flare!", "4": "Prepare to face the brilliance of Team Flare!",
"5": "Fashion is most important to us!" "5": "Fashion is most important to us!"
@ -699,6 +699,7 @@
"encounter": { "encounter": {
"1": "I'll fight you with all I have to wipe you out!", "1": "I'll fight you with all I have to wipe you out!",
"2": "I don't care if you're a kid or what. I'll send you flying if you threaten us!", "2": "I don't care if you're a kid or what. I'll send you flying if you threaten us!",
"2_female": "I don't care if you're a kid or what. I'll send you flying if you threaten us!",
"3": "I was told to turn away Trainers, whomever they might be!", "3": "I was told to turn away Trainers, whomever they might be!",
"4": "I'll show you the power of Aether Paradise!", "4": "I'll show you the power of Aether Paradise!",
"5": "Now that you've learned of the darkness at the heart of Aether Paradise, we'll need you to conveniently disappear!" "5": "Now that you've learned of the darkness at the heart of Aether Paradise, we'll need you to conveniently disappear!"
@ -715,11 +716,13 @@
"encounter": { "encounter": {
"1": "I, Branch Chief Faba, shall show you the harshness of the real world!", "1": "I, Branch Chief Faba, shall show you the harshness of the real world!",
"2": "The man who is called Aether Paradise's last line of defense is to battle a mere child?", "2": "The man who is called Aether Paradise's last line of defense is to battle a mere child?",
"2_female": "The man who is called Aether Paradise's last line of defense is to battle a mere child?",
"3": "I, Faba, am the Aether Branch Chief. The only one in the world, I'm irreplaceable." "3": "I, Faba, am the Aether Branch Chief. The only one in the world, I'm irreplaceable."
}, },
"victory": { "victory": {
"1": "Aiyee!", "1": "Aiyee!",
"2": "H-h-how can this be?! How could this child...", "2": "H-h-how can this be?! How could this child...",
"2_female": "H-h-how can this be?! How could this child...",
"3": "This is why... This is why I can't bring myself to like children." "3": "This is why... This is why I can't bring myself to like children."
} }
}, },
@ -727,9 +730,12 @@
"encounter": { "encounter": {
"1": "We're not bad-we're just hard!", "1": "We're not bad-we're just hard!",
"2": "You want some? That's how we say hello! Nice knowing you, punks!", "2": "You want some? That's how we say hello! Nice knowing you, punks!",
"2_female": "You want some? That's how we say hello! Nice knowing you, punks!",
"3": "We're just a bunch of guys and gals with a great interest in other people's Pokémon!", "3": "We're just a bunch of guys and gals with a great interest in other people's Pokémon!",
"4": "Why you trying to act hard when we're already hard as bones out here, homie?", "4": "Why you trying to act hard when we're already hard as bones out here, homie?",
"5": "Team Skull represent! We can't pay the rent! Had a lot of fun, but our youth was misspent!" "4_female": "Why you trying to act hard when we're already hard as bones out here, homie?",
"5": "Team Skull represent! We can't pay the rent! Had a lot of fun, but our youth was misspent!",
"5_female": "Team Skull represent! We can't pay the rent! Had a lot of fun, but our youth was misspent!"
}, },
"victory": { "victory": {
"1": "Huh? Is it over already?", "1": "Huh? Is it over already?",
@ -742,11 +748,13 @@
"plumeria": { "plumeria": {
"encounter": { "encounter": {
"1": " ...Hmph. You don't look like anything special to me.", "1": " ...Hmph. You don't look like anything special to me.",
"2": "It takes these dumb Grunts way too long to deal with you kids..", "1_female": " ...Hmph. You don't look like anything special to me.",
"2": "It takes these dumb Grunts way too long to deal with you kids...",
"3": "Mess with anyone in Team Skull, and I'll show you how serious I can get." "3": "Mess with anyone in Team Skull, and I'll show you how serious I can get."
}, },
"victory": { "victory": {
"1": "Hmmph! You're pretty strong. I'll give you that.", "1": "Hmmph! You're pretty strong. I'll give you that.",
"1_female": "Hmmph! You're pretty strong. I'll give you that.",
"2": "Hmmph. Guess you are pretty tough. Now I understand why my Grunts waste so much time battling kids.", "2": "Hmmph. Guess you are pretty tough. Now I understand why my Grunts waste so much time battling kids.",
"3": "Hmmph! I guess I just have to hold that loss." "3": "Hmmph! I guess I just have to hold that loss."
} }
@ -755,6 +763,7 @@
"encounter": { "encounter": {
"1": "It looks like this is the end of the line for you!", "1": "It looks like this is the end of the line for you!",
"2": "You are a trainer aren't you? I'm afraid that doesn't give you the right to interfere in our work.", "2": "You are a trainer aren't you? I'm afraid that doesn't give you the right to interfere in our work.",
"2_female": "You are a trainer aren't you? I'm afraid that doesn't give you the right to interfere in our work.",
"3": "I'm from Macro Cosmos Insurance! Do you have a life insurance policy?" "3": "I'm from Macro Cosmos Insurance! Do you have a life insurance policy?"
}, },
"victory": { "victory": {
@ -772,6 +781,7 @@
"victory": { "victory": {
"1": "*sigh* I wasn't able to win... Oleana...you really are a hopeless woman.", "1": "*sigh* I wasn't able to win... Oleana...you really are a hopeless woman.",
"2": "Arghhh! This is inexcusable... What was I thinking... Any trainer who's made it this far would be no pushover..", "2": "Arghhh! This is inexcusable... What was I thinking... Any trainer who's made it this far would be no pushover..",
"2_female": "Arghhh! This is inexcusable... What was I thinking... Any trainer who's made it this far would be no pushover..",
"3": "*sigh* I am one tired Oleana..." "3": "*sigh* I am one tired Oleana..."
} }
}, },
@ -784,7 +794,7 @@
}, },
"defeat": { "defeat": {
"1": "Mark my words. Not being able to measure your own strength shows that you are still a child.", "1": "Mark my words. Not being able to measure your own strength shows that you are still a child.",
"1_female": null "1_female": "Mark my words. Not being able to measure your own strength shows that you are still a child."
} }
}, },
"rocket_boss_giovanni_2": { "rocket_boss_giovanni_2": {
@ -845,7 +855,7 @@
"galactic_boss_cyrus_1": { "galactic_boss_cyrus_1": {
"encounter": { "encounter": {
"1": "You were compelled to come here by such vacuous sentimentality.\n$I will make you regret paying heed to your heart!", "1": "You were compelled to come here by such vacuous sentimentality.\n$I will make you regret paying heed to your heart!",
"1_female": null "1_female": "You were compelled to come here by such vacuous sentimentality.\n$I will make you regret paying heed to your heart!"
}, },
"victory": { "victory": {
"1": "Interesting. And quite curious." "1": "Interesting. And quite curious."
@ -995,7 +1005,7 @@
"misty": { "misty": {
"encounter": { "encounter": {
"1": "My policy is an all out offensive with Water-type Pokémon!", "1": "My policy is an all out offensive with Water-type Pokémon!",
"1_female": null, "1_female": "My policy is an all out offensive with Water-type Pokémon!",
"2": "Hiya, I'll show you the strength of my aquatic Pokémon!", "2": "Hiya, I'll show you the strength of my aquatic Pokémon!",
"3": "My dream was to go on a journey and battle powerful trainers…\nWill you be a sufficient challenge?" "3": "My dream was to go on a journey and battle powerful trainers…\nWill you be a sufficient challenge?"
}, },
@ -1013,14 +1023,14 @@
"lt_surge": { "lt_surge": {
"encounter": { "encounter": {
"1": "My Electric Pokémon saved me during the war! I'll show you how!", "1": "My Electric Pokémon saved me during the war! I'll show you how!",
"1_female": null, "1_female": "My Electric Pokémon saved me during the war! I'll show you how!",
"2": "Ten-hut! I'll shock you into surrender!", "2": "Ten-hut! I'll shock you into surrender!",
"3": "I'll zap you just like I do to all my enemies in battle!" "3": "I'll zap you just like I do to all my enemies in battle!"
}, },
"victory": { "victory": {
"1": "Whoa! Your team's the real deal, kid!", "1": "Whoa! Your team's the real deal, kid!",
"2": "Aaargh, you're strong! Even my electric tricks lost against you.", "2": "Aaargh, you're strong! Even my electric tricks lost against you.",
"2_female": null, "2_female": "Aaargh, you're strong! Even my electric tricks lost against you.",
"3": "That was an absolutely shocking loss!" "3": "That was an absolutely shocking loss!"
}, },
"defeat": { "defeat": {
@ -1045,7 +1055,7 @@
"defeat": { "defeat": {
"1": "I was afraid I would doze off…", "1": "I was afraid I would doze off…",
"2": "Oh my, it seems my Grass Pokémon overwhelmed you.", "2": "Oh my, it seems my Grass Pokémon overwhelmed you.",
"2_female": null, "2_female": "Oh my, it seems my Grass Pokémon overwhelmed you.",
"3": "That battle was such a soothing experience.", "3": "That battle was such a soothing experience.",
"4": "Oh… Is that all?" "4": "Oh… Is that all?"
} }
@ -1106,7 +1116,7 @@
"1": "I, the leader of Team Rocket, will make you feel a world of pain!", "1": "I, the leader of Team Rocket, will make you feel a world of pain!",
"2": "My training here will be vital before I am to face my old associates again.", "2": "My training here will be vital before I am to face my old associates again.",
"3": "I do not think you are prepared for the level of failure you are about to experience!", "3": "I do not think you are prepared for the level of failure you are about to experience!",
"3_female": null "3_female": "I do not think you are prepared for the level of failure you are about to experience!"
}, },
"victory": { "victory": {
"1": "WHAT! Me, lose?! There is nothing I wish to say to you!", "1": "WHAT! Me, lose?! There is nothing I wish to say to you!",
@ -1139,7 +1149,7 @@
"brawly": { "brawly": {
"encounter": { "encounter": {
"1": "Oh man, a challenger!\nLet's see what you can do!", "1": "Oh man, a challenger!\nLet's see what you can do!",
"1_female": null, "1_female": "Oh man, a challenger!\nLet's see what you can do!",
"2": "You seem like a big splash.\nLet's battle!", "2": "You seem like a big splash.\nLet's battle!",
"3": "Time to create a storm!\nLet's go!" "3": "Time to create a storm!\nLet's go!"
}, },
@ -1167,7 +1177,7 @@
}, },
"defeat": { "defeat": {
"1": "Recharge your batteries and challenge me again sometime!\nWahahahaha!", "1": "Recharge your batteries and challenge me again sometime!\nWahahahaha!",
"1_female": null, "1_female": "Recharge your batteries and challenge me again sometime!\nWahahahaha!",
"2": "I hope you found our battle electrifying!\nWahahahaha!", "2": "I hope you found our battle electrifying!\nWahahahaha!",
"3": "Aren't you shocked I won?\nWahahahaha!" "3": "Aren't you shocked I won?\nWahahahaha!"
} }
@ -1214,7 +1224,7 @@
}, },
"victory": { "victory": {
"1": "You're the first Trainer I've seen with more grace than I.\nExcellently played.", "1": "You're the first Trainer I've seen with more grace than I.\nExcellently played.",
"1_female": null, "1_female": "You're the first Trainer I've seen with more grace than I.\nExcellently played.",
"2": "Oh, my Flying Pokémon have plummeted!\nVery well.", "2": "Oh, my Flying Pokémon have plummeted!\nVery well.",
"3": "Though I may have fallen, my Pokémon will continue to fly!" "3": "Though I may have fallen, my Pokémon will continue to fly!"
}, },
@ -1227,7 +1237,7 @@
"tate": { "tate": {
"encounter": { "encounter": {
"1": "Hehehe…\nWere you surprised to see me without my sister?", "1": "Hehehe…\nWere you surprised to see me without my sister?",
"1_female": null, "1_female": "Hehehe…\nWere you surprised to see me without my sister?",
"2": "I can see what you're thinking…\nYou want to battle!", "2": "I can see what you're thinking…\nYou want to battle!",
"3": "How can you defeat someone…\nWho knows your every move?" "3": "How can you defeat someone…\nWho knows your every move?"
}, },
@ -1245,7 +1255,7 @@
"liza": { "liza": {
"encounter": { "encounter": {
"1": "Fufufu…\nWere you surprised to see me without my brother?", "1": "Fufufu…\nWere you surprised to see me without my brother?",
"1_female": null, "1_female": "Fufufu…\nWere you surprised to see me without my brother?",
"2": "I can determine what you desire…\nYou want to battle, don't you?", "2": "I can determine what you desire…\nYou want to battle, don't you?",
"3": "How can you defeat someone…\nWho's one with their Pokémon?" "3": "How can you defeat someone…\nWho's one with their Pokémon?"
}, },
@ -1317,10 +1327,10 @@
"nessa": { "nessa": {
"encounter": { "encounter": {
"1": "No matter what kind of plan your refined mind may be plotting, my partner and I will be sure to sink it.", "1": "No matter what kind of plan your refined mind may be plotting, my partner and I will be sure to sink it.",
"1_female": null, "1_female": "No matter what kind of plan your refined mind may be plotting, my partner and I will be sure to sink it.",
"2": "I'm not here to chat. I'm here to win!", "2": "I'm not here to chat. I'm here to win!",
"3": "This is a little gift from my Pokémon… I hope you can take it!", "3": "This is a little gift from my Pokémon… I hope you can take it!",
"3_female": null "3_female": "This is a little gift from my Pokémon… I hope you can take it!"
}, },
"victory": { "victory": {
"1": "You and your Pokémon are just too much…", "1": "You and your Pokémon are just too much…",
@ -1341,7 +1351,7 @@
}, },
"victory": { "victory": {
"1": "You… You're pretty good, huh?", "1": "You… You're pretty good, huh?",
"1_female": null, "1_female": "You… You're pretty good, huh?",
"2": "If you find Gordie around, be sure to give him a right trashing, would you?", "2": "If you find Gordie around, be sure to give him a right trashing, would you?",
"3": "I think you took breaking the ice a little too literally…" "3": "I think you took breaking the ice a little too literally…"
}, },
@ -1355,12 +1365,12 @@
"encounter": { "encounter": {
"1": "You look strong! Shoots! Let's start!", "1": "You look strong! Shoots! Let's start!",
"2": "I'm strong like the ocean's wide. You're gonna get swept away, fo' sho'.", "2": "I'm strong like the ocean's wide. You're gonna get swept away, fo' sho'.",
"2_female": null, "2_female": "I'm strong like the ocean's wide. You're gonna get swept away, fo' sho'.",
"3": "Oh ho, so I'm facing you! That's off the wall." "3": "Oh ho, so I'm facing you! That's off the wall."
}, },
"victory": { "victory": {
"1": "You totally rocked that! You're raising some wicked Pokémon. You got this Trainer thing down!", "1": "You totally rocked that! You're raising some wicked Pokémon. You got this Trainer thing down!",
"1_female": null, "1_female": "You totally rocked that! You're raising some wicked Pokémon. You got this Trainer thing down!",
"2": "You don't just look strong, you're strong fo' reals! Eh, I was swept away, too!", "2": "You don't just look strong, you're strong fo' reals! Eh, I was swept away, too!",
"3": "You're strong as a gnarly wave!" "3": "You're strong as a gnarly wave!"
}, },
@ -1373,7 +1383,7 @@
"shauntal": { "shauntal": {
"encounter": { "encounter": {
"1": "Excuse me. You're a challenger, right?\nI'm the Elite Four's Ghost-type Pokémon user, Shauntal, and I shall be your opponent.", "1": "Excuse me. You're a challenger, right?\nI'm the Elite Four's Ghost-type Pokémon user, Shauntal, and I shall be your opponent.",
"1_female": null, "1_female": "Excuse me. You're a challenger, right?\nI'm the Elite Four's Ghost-type Pokémon user, Shauntal, and I shall be your opponent.",
"2": "I absolutely love writing about Trainers who come here and the Pokémon they train.\nCould I use you and your Pokémon as a subject?", "2": "I absolutely love writing about Trainers who come here and the Pokémon they train.\nCould I use you and your Pokémon as a subject?",
"3": "Every person who works with Pokémon has a story to tell.\nWhat story is about to be told?" "3": "Every person who works with Pokémon has a story to tell.\nWhat story is about to be told?"
}, },
@ -1391,7 +1401,7 @@
"marshal": { "marshal": {
"encounter": { "encounter": {
"1": "My mentor, Alder, sees your potential as a Trainer and is taking an interest in you.\nIt is my intention to test you--to take you to the limits of your strength. Kiai!", "1": "My mentor, Alder, sees your potential as a Trainer and is taking an interest in you.\nIt is my intention to test you--to take you to the limits of your strength. Kiai!",
"1_female": null, "1_female": "My mentor, Alder, sees your potential as a Trainer and is taking an interest in you.\nIt is my intention to test you--to take you to the limits of your strength. Kiai!",
"2": "Victory, decisive victory, is my intention! Challenger, here I come!", "2": "Victory, decisive victory, is my intention! Challenger, here I come!",
"3": "In myself, I seek to develop the strength of a fighter and shatter any weakness in myself!\nPrevailing with the force of my convictions!" "3": "In myself, I seek to develop the strength of a fighter and shatter any weakness in myself!\nPrevailing with the force of my convictions!"
}, },
@ -1411,7 +1421,7 @@
"1": "You remind me of an old friend. That makes me excited about this Pokémon battle!", "1": "You remind me of an old friend. That makes me excited about this Pokémon battle!",
"2": "Pokémon battles have no meaning if you don't think why you battle.\n$Or better said, it makes battling together with Pokémon meaningless.", "2": "Pokémon battles have no meaning if you don't think why you battle.\n$Or better said, it makes battling together with Pokémon meaningless.",
"3": "My name's Cheren! I'm a Gym Leader and a teacher! Pleasure to meet you.", "3": "My name's Cheren! I'm a Gym Leader and a teacher! Pleasure to meet you.",
"3_female": null "3_female": "My name's Cheren! I'm a Gym Leader and a teacher! Pleasure to meet you."
}, },
"victory": { "victory": {
"1": "Thank you! I saw what was missing in me.", "1": "Thank you! I saw what was missing in me.",
@ -1427,73 +1437,73 @@
"chili": { "chili": {
"encounter": { "encounter": {
"1": "Yeeeeooow! Time to play with FIRE!! I'm the strongest of us brothers!", "1": "Yeeeeooow! Time to play with FIRE!! I'm the strongest of us brothers!",
"1_female": null, "1_female": "Yeeeeooow! Time to play with FIRE!! I'm the strongest of us brothers!",
"2": "Ta-da! The Fire-type scorcher Chili--that's me--will be your opponent!", "2": "Ta-da! The Fire-type scorcher Chili--that's me--will be your opponent!",
"2_female": null, "2_female": "Ta-da! The Fire-type scorcher Chili--that's me--will be your opponent!",
"3": "I'm going to show you what me and my blazing Fire types can do!", "3": "I'm going to show you what me and my blazing Fire types can do!",
"3_female": null "3_female": "I'm going to show you what me and my blazing Fire types can do!"
}, },
"victory": { "victory": {
"1": "You got me. I am… burned… out…", "1": "You got me. I am… burned… out…",
"1_female": null, "1_female": "You got me. I am… burned… out…",
"2": "Whoa ho! You're on fire!", "2": "Whoa ho! You're on fire!",
"2_female": null, "2_female": "Whoa ho! You're on fire!",
"3": "Augh! You got me!" "3": "Augh! You got me!"
}, },
"defeat": { "defeat": {
"1": "I'm on fire! Play with me, and you'll get burned!", "1": "I'm on fire! Play with me, and you'll get burned!",
"1_female": null, "1_female": "I'm on fire! Play with me, and you'll get burned!",
"2": "When you play with fire, you get burned!", "2": "When you play with fire, you get burned!",
"3": "I mean, c'mon, your opponent was me! You didn't have a chance!", "3": "I mean, c'mon, your opponent was me! You didn't have a chance!",
"3_female": null "3_female": "I mean, c'mon, your opponent was me! You didn't have a chance!"
} }
}, },
"cilan": { "cilan": {
"encounter": { "encounter": {
"1": "Nothing personal... No hard feelings... Me and my Grass-type Pokémon will...\n$Um... We're gonna battle come what may.", "1": "Nothing personal... No hard feelings... Me and my Grass-type Pokémon will...\n$Um... We're gonna battle come what may.",
"1_female": null, "1_female": "Nothing personal... No hard feelings... Me and my Grass-type Pokémon will...\n$Um... We're gonna battle come what may.",
"2": "So, um, if you're OK with me, I'll, um, put everything I've got into being, er, you know, your opponent.", "2": "So, um, if you're OK with me, I'll, um, put everything I've got into being, er, you know, your opponent.",
"2_female": null, "2_female": "So, um, if you're OK with me, I'll, um, put everything I've got into being, er, you know, your opponent.",
"3": "OK… So, um, I'm Cilan, I like Grass-type Pokémon.", "3": "OK… So, um, I'm Cilan, I like Grass-type Pokémon.",
"3_female": null "3_female": "OK… So, um, I'm Cilan, I like Grass-type Pokémon."
}, },
"victory": { "victory": {
"1": "Er… Is it over now?", "1": "Er… Is it over now?",
"1_female": null, "1_female": "Er… Is it over now?",
"2": "…What a surprise. You are very strong, aren't you? \n$I guess my brothers wouldn't have been able to defeat you either…", "2": "…What a surprise. You are very strong, aren't you? \n$I guess my brothers wouldn't have been able to defeat you either…",
"2_female": null, "2_female": "…What a surprise. You are very strong, aren't you? \n$I guess my brothers wouldn't have been able to defeat you either…",
"3": "…Huh. Looks like my timing was, um, off?" "3": "…Huh. Looks like my timing was, um, off?"
}, },
"defeat": { "defeat": {
"1": "Huh? Did I win?", "1": "Huh? Did I win?",
"1_female": null, "1_female": "Huh? Did I win?",
"2": "I guess… \n$I suppose I won, because I've been competing with my brothers Chili and Cress, and we all were able to get tougher.", "2": "I guess… \n$I suppose I won, because I've been competing with my brothers Chili and Cress, and we all were able to get tougher.",
"2_female": null, "2_female": "I guess… \n$I suppose I won, because I've been competing with my brothers Chili and Cress, and we all were able to get tougher.",
"3": "It…it was quite a thrilling experience…", "3": "It…it was quite a thrilling experience…",
"3_female": null "3_female": "It…it was quite a thrilling experience…"
} }
}, },
"roark": { "roark": {
"encounter": { "encounter": {
"1": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!", "1": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!",
"1_female": null, "1_female": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!",
"2": "Here goes! These are my rocking Pokémon, my pride and joy!", "2": "Here goes! These are my rocking Pokémon, my pride and joy!",
"3": "Rock-type Pokémon are simply the best!", "3": "Rock-type Pokémon are simply the best!",
"4": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!", "4": "Every day, I toughened up my Pokémon by digging up Fossils nonstop.\n$Could I show you how tough I made them in a battle?",
"4_female": null "4_female": "Every day, I toughened up my Pokémon by digging up Fossils nonstop.\n$Could I show you how tough I made them in a battle?"
}, },
"victory": { "victory": {
"1": "W-what? That can't be! My buffed-up Pokémon!", "1": "W-what? That can't be! My buffed-up Pokémon!",
"2": "…We lost control there. Next time I'd like to challenge you to a Fossil-digging race underground.", "2": "…We lost control there. Next time I'd like to challenge you to a Fossil-digging race underground.",
"2_female": null, "2_female": "…We lost control there. Next time I'd like to challenge you to a Fossil-digging race underground.",
"3": "With skill like yours, it's natural for you to win.", "3": "With skill like yours, it's natural for you to win.",
"4": "Wh-what?! It can't be! Even that wasn't enough?", "4": "Wh-what?! It can't be! Even that wasn't enough?"
"5": "I blew it."
}, },
"defeat": { "defeat": {
"1": "See? I'm proud of my rocking battle style!", "1": "See? I'm proud of my rocking battle style!",
"2": "Thanks! The battle gave me confidence that I may be able to beat my dad!", "2": "Thanks! The battle gave me confidence that I may be able to beat my dad!",
"3": "I feel like I just smashed through a really stubborn boulder!" "3": "See? These are my rocking Pokémon, my pride and joy!",
"4": "I knew I would win!"
} }
}, },
"morty": { "morty": {
@ -1508,7 +1518,7 @@
"victory": { "victory": {
"1": "I'm not good enough yet…", "1": "I'm not good enough yet…",
"2": "I see… Your journey has taken you to far-away places and you have witnessed much more than I.\n$I envy you for that…", "2": "I see… Your journey has taken you to far-away places and you have witnessed much more than I.\n$I envy you for that…",
"2_female": null, "2_female": "I see… Your journey has taken you to far-away places and you have witnessed much more than I.\n$I envy you for that…",
"3": "How is this possible…", "3": "How is this possible…",
"4": "I don't think our potentials are so different.\n$But you seem to have something more than that… So be it.", "4": "I don't think our potentials are so different.\n$But you seem to have something more than that… So be it.",
"5": "Guess I need more training.", "5": "Guess I need more training.",
@ -1568,13 +1578,13 @@
}, },
"defeat": { "defeat": {
"1": "Heh heh! Don't mind me, just scooping up a W over here. I get it if you're upset, but don't go full Kieran on me, OK?", "1": "Heh heh! Don't mind me, just scooping up a W over here. I get it if you're upset, but don't go full Kieran on me, OK?",
"1_female": null "1_female": "Heh heh! Don't mind me, just scooping up a W over here. I get it if you're upset, but don't go full Kieran on me, OK?"
} }
}, },
"ramos": { "ramos": {
"encounter": { "encounter": {
"1": "Did yeh enjoy the garden playground I made with all these sturdy plants o' mine?\n$Their strength is a sign o' my strength as a gardener and a Gym Leader! Yeh sure yer up to facing all that?", "1": "Did yeh enjoy the garden playground I made with all these sturdy plants o' mine?\n$Their strength is a sign o' my strength as a gardener and a Gym Leader! Yeh sure yer up to facing all that?",
"1_female": null "1_female": "Did yeh enjoy the garden playground I made with all these sturdy plants o' mine?\n$Their strength is a sign o' my strength as a gardener and a Gym Leader! Yeh sure yer up to facing all that?"
}, },
"victory": { "victory": {
"1": "Yeh believe in yer Pokémon… And they believe in yeh, too… It was a fine battle, sprout." "1": "Yeh believe in yer Pokémon… And they believe in yeh, too… It was a fine battle, sprout."
@ -1605,7 +1615,7 @@
"victory": { "victory": {
"1": "I must say, I'm warmed up to you! I might even admire you a little.", "1": "I must say, I'm warmed up to you! I might even admire you a little.",
"2": "Wow! You're great! You've earned my respect! \n$I think your focus and will bowled us over totally. ", "2": "Wow! You're great! You've earned my respect! \n$I think your focus and will bowled us over totally. ",
"2_female": null "2_female": "Wow! You're great! You've earned my respect! \n$I think your focus and will bowled us over totally. "
}, },
"defeat": { "defeat": {
"1": "I sensed your will to win, but I don't lose!", "1": "I sensed your will to win, but I don't lose!",
@ -1618,7 +1628,7 @@
}, },
"victory": { "victory": {
"1": "Amazing! You're very good, aren't you?", "1": "Amazing! You're very good, aren't you?",
"1_female": null "1_female": "Amazing! You're very good, aren't you?"
}, },
"defeat": { "defeat": {
"1": "Yes! My Pokémon and I are perfectly good!" "1": "Yes! My Pokémon and I are perfectly good!"
@ -1660,7 +1670,7 @@
"clay": { "clay": {
"encounter": { "encounter": {
"1": "Harrumph! Kept me waitin', didn't ya, kid? All right, time to see what ya can do!", "1": "Harrumph! Kept me waitin', didn't ya, kid? All right, time to see what ya can do!",
"1_female": null "1_female": "Harrumph! Kept me waitin', didn't ya, kid? All right, time to see what ya can do!"
}, },
"victory": { "victory": {
"1": "Man oh man… It feels good to go all out and still be defeated!" "1": "Man oh man… It feels good to go all out and still be defeated!"
@ -1675,7 +1685,7 @@
}, },
"victory": { "victory": {
"1": "Vaultin' Veluza! Yer a lively one, aren't ya! A little TOO lively, if I do say so myself!", "1": "Vaultin' Veluza! Yer a lively one, aren't ya! A little TOO lively, if I do say so myself!",
"1_female": null "1_female": "Vaultin' Veluza! Yer a lively one, aren't ya! A little TOO lively, if I do say so myself!"
}, },
"defeat": { "defeat": {
"1": "You come back to see me again now, ya hear?" "1": "You come back to see me again now, ya hear?"
@ -1742,7 +1752,7 @@
}, },
"victory": { "victory": {
"1": "Bravo. I realize now your authenticity and magnificence as a Pokémon Trainer. \n$I find much joy in having met you and your Pokémon. You have proven yourself worthy.", "1": "Bravo. I realize now your authenticity and magnificence as a Pokémon Trainer. \n$I find much joy in having met you and your Pokémon. You have proven yourself worthy.",
"1_female": null "1_female": "Bravo. I realize now your authenticity and magnificence as a Pokémon Trainer. \n$I find much joy in having met you and your Pokémon. You have proven yourself worthy."
}, },
"defeat": { "defeat": {
"1": "A grand illusion!" "1": "A grand illusion!"
@ -1751,14 +1761,14 @@
"lorelei": { "lorelei": {
"encounter": { "encounter": {
"1": "No one can best me when it comes to icy Pokémon! Freezing moves are powerful!\n$Your Pokémon will be at my mercy when they are frozen solid! Hahaha! Are you ready?", "1": "No one can best me when it comes to icy Pokémon! Freezing moves are powerful!\n$Your Pokémon will be at my mercy when they are frozen solid! Hahaha! Are you ready?",
"1_female": null "1_female": "No one can best me when it comes to icy Pokémon! Freezing moves are powerful!\n$Your Pokémon will be at my mercy when they are frozen solid! Hahaha! Are you ready?"
}, },
"victory": { "victory": {
"1": "How dare you!" "1": "How dare you!"
}, },
"defeat": { "defeat": {
"1": "There's nothing you can do once you're frozen.", "1": "There's nothing you can do once you're frozen.",
"1_female": null "1_female": "There's nothing you can do once you're frozen."
} }
}, },
"will": { "will": {
@ -1775,11 +1785,11 @@
"malva": { "malva": {
"encounter": { "encounter": {
"1": "I feel like my heart might just burst into flames. \n$I'm burning up with my hatred for you, runt!", "1": "I feel like my heart might just burst into flames. \n$I'm burning up with my hatred for you, runt!",
"1_female": null "1_female": "I feel like my heart might just burst into flames. \n$I'm burning up with my hatred for you, runt!"
}, },
"victory": { "victory": {
"1": "What news… So a new challenger has defeated Malva!", "1": "What news… So a new challenger has defeated Malva!",
"1_female": null "1_female": "What news… So a new challenger has defeated Malva!"
}, },
"defeat": { "defeat": {
"1": "I am delighted! Yes, delighted that I could squash you beneath my heel." "1": "I am delighted! Yes, delighted that I could squash you beneath my heel."
@ -1802,7 +1812,7 @@
}, },
"victory": { "victory": {
"1": "I certainly found an interesting Trainer to face!", "1": "I certainly found an interesting Trainer to face!",
"1_female": null "1_female": "I certainly found an interesting Trainer to face!"
}, },
"defeat": { "defeat": {
"1": "Ahaha. What an interesting battle." "1": "Ahaha. What an interesting battle."
@ -1814,11 +1824,11 @@
}, },
"victory": { "victory": {
"1": "Not bad, kiddo.", "1": "Not bad, kiddo.",
"1_female": null "1_female": "Not bad, kiddo."
}, },
"defeat": { "defeat": {
"1": "Nahahaha! You really are something else, kiddo!", "1": "Nahahaha! You really are something else, kiddo!",
"1_female": null "1_female": "Nahahaha! You really are something else, kiddo!"
} }
}, },
"bruno": { "bruno": {
@ -1838,7 +1848,7 @@
}, },
"victory": { "victory": {
"1": "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win.", "1": "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win.",
"1_female": null "1_female": "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
}, },
"defeat": { "defeat": {
"1": "Thanks! Thanks to our battle, I was also able to make progress in my research!" "1": "Thanks! Thanks to our battle, I was also able to make progress in my research!"
@ -1869,11 +1879,11 @@
"lenora": { "lenora": {
"encounter": { "encounter": {
"1": "Well then, challenger, I'm going to research how you battle with the Pokémon you've so lovingly raised!", "1": "Well then, challenger, I'm going to research how you battle with the Pokémon you've so lovingly raised!",
"1_female": null "1_female": "Well then, challenger, I'm going to research how you battle with the Pokémon you've so lovingly raised!"
}, },
"victory": { "victory": {
"1": "My theory about you was correct. You're more than just talented… You're motivated! I salute you!", "1": "My theory about you was correct. You're more than just talented… You're motivated! I salute you!",
"1_female": null "1_female": "My theory about you was correct. You're more than just talented… You're motivated! I salute you!"
}, },
"defeat": { "defeat": {
"1": "Ah ha ha! If you lose, make sure to analyze why, and use that knowledge in your next battle!" "1": "Ah ha ha! If you lose, make sure to analyze why, and use that knowledge in your next battle!"
@ -1899,7 +1909,7 @@
}, },
"defeat": { "defeat": {
"1": "Hey, c'mon! Get serious! You gotta put more out there!", "1": "Hey, c'mon! Get serious! You gotta put more out there!",
"1_female": null "1_female": "Hey, c'mon! Get serious! You gotta put more out there!"
} }
}, },
"olivia": { "olivia": {
@ -1938,7 +1948,7 @@
"flint": { "flint": {
"encounter": { "encounter": {
"1": "Hope you're warmed up, cause here comes the Big Bang!", "1": "Hope you're warmed up, cause here comes the Big Bang!",
"1_female": null "1_female": "Hope you're warmed up, cause here comes the Big Bang!"
}, },
"victory": { "victory": {
"1": "Incredible! Your moves are so hot, they make mine look lukewarm!" "1": "Incredible! Your moves are so hot, they make mine look lukewarm!"
@ -1961,7 +1971,7 @@
"caitlin": { "caitlin": {
"encounter": { "encounter": {
"1": "It's me who appeared when the flower opened up. You who have been waiting…\n$You look like a Pokémon Trainer with refined strength and deepened kindness. \n$What I look for in my opponent is superb strength… \n$Please unleash your power to the fullest!", "1": "It's me who appeared when the flower opened up. You who have been waiting…\n$You look like a Pokémon Trainer with refined strength and deepened kindness. \n$What I look for in my opponent is superb strength… \n$Please unleash your power to the fullest!",
"1_female": null "1_female": "It's me who appeared when the flower opened up. You who have been waiting…\n$You look like a Pokémon Trainer with refined strength and deepened kindness. \n$What I look for in my opponent is superb strength… \n$Please unleash your power to the fullest!"
}, },
"victory": { "victory": {
"1": "My Pokémon and I learned so much! I offer you my thanks." "1": "My Pokémon and I learned so much! I offer you my thanks."
@ -1984,15 +1994,15 @@
"wikstrom": { "wikstrom": {
"encounter": { "encounter": {
"1": "Well met, young challenger! Verily am I the famed blade of hardened steel, Duke Wikstrom! \n$Let the battle begin! En garde!", "1": "Well met, young challenger! Verily am I the famed blade of hardened steel, Duke Wikstrom! \n$Let the battle begin! En garde!",
"1_female": null "1_female": "Well met, young challenger! Verily am I the famed blade of hardened steel, Duke Wikstrom! \n$Let the battle begin! En garde!"
}, },
"victory": { "victory": {
"1": "Glorious! The trust that you share with your honorable Pokémon surpasses even mine!", "1": "Glorious! The trust that you share with your honorable Pokémon surpasses even mine!",
"1_female": null "1_female": "Glorious! The trust that you share with your honorable Pokémon surpasses even mine!"
}, },
"defeat": { "defeat": {
"1": "What manner of magic is this? My heart, it doth hammer ceaselessly in my breast! \n$Winning against such a worthy opponent doth give my soul wings--thus do I soar!", "1": "What manner of magic is this? My heart, it doth hammer ceaselessly in my breast! \n$Winning against such a worthy opponent doth give my soul wings--thus do I soar!",
"1_female": null "1_female": "What manner of magic is this? My heart, it doth hammer ceaselessly in my breast! \n$Winning against such a worthy opponent doth give my soul wings--thus do I soar!"
} }
}, },
"acerola": { "acerola": {
@ -2024,14 +2034,14 @@
}, },
"victory": { "victory": {
"1": "You got me. You are magnificent!", "1": "You got me. You are magnificent!",
"1_female": null, "1_female": "You got me. You are magnificent!",
"2": "I never expected another trainer to beat me… I'm surprised.", "2": "I never expected another trainer to beat me… I'm surprised.",
"2_female": null "2_female": "I never expected another trainer to beat me… I'm surprised."
}, },
"defeat": { "defeat": {
"1": "That was close. Want to try again?", "1": "That was close. Want to try again?",
"2": "It's not that you are weak. Don't let it bother you.", "2": "It's not that you are weak. Don't let it bother you.",
"2_female": null "2_female": "It's not that you are weak. Don't let it bother you."
} }
}, },
"karen": { "karen": {
@ -2057,7 +2067,7 @@
}, },
"victory": { "victory": {
"1": "The power of Grass has wilted… What an incredible Challenger!", "1": "The power of Grass has wilted… What an incredible Challenger!",
"1_female": null "1_female": "The power of Grass has wilted… What an incredible Challenger!"
}, },
"defeat": { "defeat": {
"1": "This'll really leave you in shock and awe." "1": "This'll really leave you in shock and awe."
@ -2077,7 +2087,7 @@
"drasna": { "drasna": {
"encounter": { "encounter": {
"1": "You must be a strong Trainer. Yes, quite strong indeed…\n$That's just wonderful news! Facing opponents like you and your team will make my Pokémon grow like weeds!", "1": "You must be a strong Trainer. Yes, quite strong indeed…\n$That's just wonderful news! Facing opponents like you and your team will make my Pokémon grow like weeds!",
"1_female": null "1_female": "You must be a strong Trainer. Yes, quite strong indeed…\n$That's just wonderful news! Facing opponents like you and your team will make my Pokémon grow like weeds!"
}, },
"victory": { "victory": {
"1": "Oh, dear me. That sure was a quick battle… I do hope you'll come back again sometime!" "1": "Oh, dear me. That sure was a quick battle… I do hope you'll come back again sometime!"
@ -2111,7 +2121,7 @@
"blue": { "blue": {
"encounter": { "encounter": {
"1": "You must be pretty good to get this far.", "1": "You must be pretty good to get this far.",
"1_female": null "1_female": "You must be pretty good to get this far."
}, },
"victory": { "victory": {
"1": "I've only lost to him and now to you… Him? Hee, hee…" "1": "I've only lost to him and now to you… Him? Hee, hee…"
@ -2159,7 +2169,7 @@
}, },
"victory": { "victory": {
"1": "This is the emergence of a new Champion.", "1": "This is the emergence of a new Champion.",
"1_female": null "1_female": "This is the emergence of a new Champion."
}, },
"defeat": { "defeat": {
"1": "I successfully defended my Championship." "1": "I successfully defended my Championship."
@ -2248,7 +2258,7 @@
}, },
"victory": { "victory": {
"1": "Waaah! Waaah! You're so mean!", "1": "Waaah! Waaah! You're so mean!",
"1_female": null "1_female": "Waaah! Waaah! You're so mean!"
}, },
"defeat": { "defeat": {
"1": "And that's that!" "1": "And that's that!"
@ -2257,7 +2267,7 @@
"chuck": { "chuck": {
"encounter": { "encounter": {
"1": "Hah! You want to challenge me? Are you brave or just ignorant?", "1": "Hah! You want to challenge me? Are you brave or just ignorant?",
"1_female": null "1_female": "Hah! You want to challenge me? Are you brave or just ignorant?"
}, },
"victory": { "victory": {
"1": "You're strong! Would you please make me your apprentice?" "1": "You're strong! Would you please make me your apprentice?"
@ -2269,7 +2279,7 @@
"katy": { "katy": {
"encounter": { "encounter": {
"1": "Don't let your guard down unless you would like to find yourself knocked off your feet!", "1": "Don't let your guard down unless you would like to find yourself knocked off your feet!",
"1_female": null "1_female": "Don't let your guard down unless you would like to find yourself knocked off your feet!"
}, },
"victory": { "victory": {
"1": "All of my sweet little Pokémon dropped like flies!" "1": "All of my sweet little Pokémon dropped like flies!"
@ -2303,7 +2313,7 @@
"maylene": { "maylene": {
"encounter": { "encounter": {
"1": "I've come to challenge you now, and I won't hold anything back. \n$Please prepare yourself for battle!", "1": "I've come to challenge you now, and I won't hold anything back. \n$Please prepare yourself for battle!",
"1_female": null "1_female": "I've come to challenge you now, and I won't hold anything back. \n$Please prepare yourself for battle!"
}, },
"victory": { "victory": {
"1": "I admit defeat…" "1": "I admit defeat…"
@ -2326,7 +2336,7 @@
"byron": { "byron": {
"encounter": { "encounter": {
"1": "Trainer! You're young, just like my son, Roark. \n$With more young Trainers taking charge, the future of Pokémon is bright! \n$So, as a wall for young people, I'll take your challenge!", "1": "Trainer! You're young, just like my son, Roark. \n$With more young Trainers taking charge, the future of Pokémon is bright! \n$So, as a wall for young people, I'll take your challenge!",
"1_female": null "1_female": "Trainer! You're young, just like my son, Roark. \n$With more young Trainers taking charge, the future of Pokémon is bright! \n$So, as a wall for young people, I'll take your challenge!"
}, },
"victory": { "victory": {
"1": "Hmm! My sturdy Pokémon--defeated!" "1": "Hmm! My sturdy Pokémon--defeated!"
@ -2349,7 +2359,7 @@
"volkner": { "volkner": {
"encounter": { "encounter": {
"1": "Since you've come this far, you must be quite strong…\n$I hope you're the Trainer who'll make me remember how fun it is to battle!", "1": "Since you've come this far, you must be quite strong…\n$I hope you're the Trainer who'll make me remember how fun it is to battle!",
"1_female": null "1_female": "Since you've come this far, you must be quite strong…\n$I hope you're the Trainer who'll make me remember how fun it is to battle!"
}, },
"victory": { "victory": {
"1": "You've got me beat…\n$Your desire and the noble way your Pokémon battled for you… \n$I even felt thrilled during our match. That was a very good battle." "1": "You've got me beat…\n$Your desire and the noble way your Pokémon battled for you… \n$I even felt thrilled during our match. That was a very good battle."
@ -2452,7 +2462,7 @@
"valerie": { "valerie": {
"encounter": { "encounter": {
"1": "Oh, if it isn't a young Trainer… It is lovely to get to meet you like this. \n$Then I suppose you have earned yourself the right to a battle, as a reward for your efforts. \n$The elusive Fairy may appear frail as the breeze and delicate as a bloom, but it is strong.", "1": "Oh, if it isn't a young Trainer… It is lovely to get to meet you like this. \n$Then I suppose you have earned yourself the right to a battle, as a reward for your efforts. \n$The elusive Fairy may appear frail as the breeze and delicate as a bloom, but it is strong.",
"1_female": null "1_female": "Oh, if it isn't a young Trainer… It is lovely to get to meet you like this. \n$Then I suppose you have earned yourself the right to a battle, as a reward for your efforts. \n$The elusive Fairy may appear frail as the breeze and delicate as a bloom, but it is strong."
}, },
"victory": { "victory": {
"1": "I hope that you will find things worth smiling about tomorrow…" "1": "I hope that you will find things worth smiling about tomorrow…"
@ -2500,7 +2510,7 @@
}, },
"victory": { "victory": {
"1": "Your pink is still lacking, but you're an excellent Trainer with excellent Pokémon.", "1": "Your pink is still lacking, but you're an excellent Trainer with excellent Pokémon.",
"1_female": null "1_female": "Your pink is still lacking, but you're an excellent Trainer with excellent Pokémon."
}, },
"defeat": { "defeat": {
"1": "Too bad for you, I guess." "1": "Too bad for you, I guess."
@ -2509,7 +2519,7 @@
"bede": { "bede": {
"encounter": { "encounter": {
"1": "I suppose I should prove beyond doubt just how pathetic you are and how strong I am.", "1": "I suppose I should prove beyond doubt just how pathetic you are and how strong I am.",
"1_female": null "1_female": "I suppose I should prove beyond doubt just how pathetic you are and how strong I am."
}, },
"victory": { "victory": {
"1": "I see… Well, that's fine. I wasn't really trying all that hard anyway." "1": "I see… Well, that's fine. I wasn't really trying all that hard anyway."
@ -2554,7 +2564,7 @@
"brassius": { "brassius": {
"encounter": { "encounter": {
"1": "I assume you are ready? Let our collaborative work of art begin!", "1": "I assume you are ready? Let our collaborative work of art begin!",
"1_female": null "1_female": "I assume you are ready? Let our collaborative work of art begin!"
}, },
"victory": { "victory": {
"1": "Ahhh…vant-garde!" "1": "Ahhh…vant-garde!"
@ -2566,11 +2576,11 @@
"iono": { "iono": {
"encounter": { "encounter": {
"1": "How're ya feelin' about this battle?\n$...\n$Let's get this show on the road! How strong is our challenger? \n$I 'unno! Let's find out together!", "1": "How're ya feelin' about this battle?\n$...\n$Let's get this show on the road! How strong is our challenger? \n$I 'unno! Let's find out together!",
"1_female": null "1_female": "How're ya feelin' about this battle?\n$...\n$Let's get this show on the road! How strong is our challenger? \n$I 'unno! Let's find out together!"
}, },
"victory": { "victory": {
"1": "You're as flashy and bright as a 10,000,000-volt Thunderbolt, friendo!", "1": "You're as flashy and bright as a 10,000,000-volt Thunderbolt, friendo!",
"1_female": null "1_female": "You're as flashy and bright as a 10,000,000-volt Thunderbolt, friendo!"
}, },
"defeat": { "defeat": {
"1": "Your eyeballs are MINE!" "1": "Your eyeballs are MINE!"
@ -2593,7 +2603,7 @@
}, },
"victory": { "victory": {
"1": "You're cool, my friend—you move my SOUL!", "1": "You're cool, my friend—you move my SOUL!",
"1_female": null "1_female": "You're cool, my friend—you move my SOUL!"
}, },
"defeat": { "defeat": {
"1": "Later, baby!" "1": "Later, baby!"
@ -2627,9 +2637,9 @@
"nessa_elite": { "nessa_elite": {
"encounter": { "encounter": {
"1": "The tides are turning in my favor. Ready to get swept away?", "1": "The tides are turning in my favor. Ready to get swept away?",
"1_female": null, "1_female": "The tides are turning in my favor. Ready to get swept away?",
"2": "Let's make some waves with this battle! I hope you're prepared!", "2": "Let's make some waves with this battle! I hope you're prepared!",
"2_female": null "2_female": "Let's make some waves with this battle! I hope you're prepared!"
}, },
"victory": { "victory": {
"1": "You navigated those waters perfectly... Well done!", "1": "You navigated those waters perfectly... Well done!",
@ -2657,7 +2667,7 @@
"allister_elite": { "allister_elite": {
"encounter": { "encounter": {
"1": "Shadows fall... Are you ready to face your fears?", "1": "Shadows fall... Are you ready to face your fears?",
"1_female": null, "1_female": "Shadows fall... Are you ready to face your fears?",
"2": "Let's see if you can handle the darkness that I command." "2": "Let's see if you can handle the darkness that I command."
}, },
"victory": { "victory": {
@ -2681,7 +2691,7 @@
"defeat": { "defeat": {
"1": "Another storm weathered, another victory claimed! Well fought!", "1": "Another storm weathered, another victory claimed! Well fought!",
"2": "You got caught in my storm! Better luck next time!", "2": "You got caught in my storm! Better luck next time!",
"2_female": null "2_female": "You got caught in my storm! Better luck next time!"
} }
}, },
"alder": { "alder": {

View File

@ -24,6 +24,7 @@
"linkGoogle": "Link Google", "linkGoogle": "Link Google",
"unlinkGoogle": "Unlink Google", "unlinkGoogle": "Unlink Google",
"cancel": "Cancel", "cancel": "Cancel",
"donate": "Donate",
"losingProgressionWarning": "You will lose any progress since the beginning of the battle. Proceed?", "losingProgressionWarning": "You will lose any progress since the beginning of the battle. Proceed?",
"noEggs": "You are not hatching\nany eggs at the moment!" "noEggs": "You are not hatching\nany eggs at the moment!"
} }

View File

@ -49,8 +49,8 @@
"DoubleBattleChanceBoosterModifierType": { "DoubleBattleChanceBoosterModifierType": {
"description": "Doubles the chance of an encounter being a double battle for {{battleCount}} battles." "description": "Doubles the chance of an encounter being a double battle for {{battleCount}} battles."
}, },
"TempBattleStatBoosterModifierType": { "TempStatStageBoosterModifierType": {
"description": "Increases the {{tempBattleStatName}} of all party members by 1 stage for 5 battles." "description": "Increases the {{stat}} of all party members by 1 stage for 5 battles."
}, },
"AttackTypeBoosterModifierType": { "AttackTypeBoosterModifierType": {
"description": "Increases the power of a Pokémon's {{moveType}}-type moves by 20%." "description": "Increases the power of a Pokémon's {{moveType}}-type moves by 20%."
@ -61,8 +61,8 @@
"AllPokemonLevelIncrementModifierType": { "AllPokemonLevelIncrementModifierType": {
"description": "Increases all party members' level by {{levels}}." "description": "Increases all party members' level by {{levels}}."
}, },
"PokemonBaseStatBoosterModifierType": { "BaseStatBoosterModifierType": {
"description": "Increases the holder's base {{statName}} by 10%. The higher your IVs, the higher the stack limit." "description": "Increases the holder's base {{stat}} by 10%. The higher your IVs, the higher the stack limit."
}, },
"AllPokemonFullHpRestoreModifierType": { "AllPokemonFullHpRestoreModifierType": {
"description": "Restores 100% HP for all Pokémon." "description": "Restores 100% HP for all Pokémon."
@ -183,6 +183,7 @@
"SOOTHE_BELL": { "name": "Soothe Bell" }, "SOOTHE_BELL": { "name": "Soothe Bell" },
"SCOPE_LENS": { "name": "Scope Lens", "description": "It's a lens for scoping out weak points. It boosts the holder's critical-hit ratio."}, "SCOPE_LENS": { "name": "Scope Lens", "description": "It's a lens for scoping out weak points. It boosts the holder's critical-hit ratio."},
"DIRE_HIT": { "name": "Dire Hit", "extra": { "raises": "Critical Hit Ratio" } },
"LEEK": { "name": "Leek", "description": "This very long and stiff stalk of leek boosts the critical-hit ratio of Farfetch'd's moves."}, "LEEK": { "name": "Leek", "description": "This very long and stiff stalk of leek boosts the critical-hit ratio of Farfetch'd's moves."},
"EVIOLITE": { "name": "Eviolite", "description": "This mysterious evolutionary lump boosts the Defense and Sp. Def stats when held by a Pokémon that can still evolve." }, "EVIOLITE": { "name": "Eviolite", "description": "This mysterious evolutionary lump boosts the Defense and Sp. Def stats when held by a Pokémon that can still evolve." },
@ -250,28 +251,14 @@
"METAL_POWDER": { "name": "Metal Powder", "description": "Extremely fine yet hard, this odd powder boosts Ditto's Defense stat." }, "METAL_POWDER": { "name": "Metal Powder", "description": "Extremely fine yet hard, this odd powder boosts Ditto's Defense stat." },
"QUICK_POWDER": { "name": "Quick Powder", "description": "Extremely fine yet hard, this odd powder boosts Ditto's Speed stat." } "QUICK_POWDER": { "name": "Quick Powder", "description": "Extremely fine yet hard, this odd powder boosts Ditto's Speed stat." }
}, },
"TempBattleStatBoosterItem": { "TempStatStageBoosterItem": {
"x_attack": "X Attack", "x_attack": "X Attack",
"x_defense": "X Defense", "x_defense": "X Defense",
"x_sp_atk": "X Sp. Atk", "x_sp_atk": "X Sp. Atk",
"x_sp_def": "X Sp. Def", "x_sp_def": "X Sp. Def",
"x_speed": "X Speed", "x_speed": "X Speed",
"x_accuracy": "X Accuracy", "x_accuracy": "X Accuracy"
"dire_hit": "Dire Hit"
}, },
"TempBattleStatBoosterStatName": {
"ATK": "Attack",
"DEF": "Defense",
"SPATK": "Sp. Atk",
"SPDEF": "Sp. Def",
"SPD": "Speed",
"ACC": "Accuracy",
"CRIT": "Critical Hit Ratio",
"EVA": "Evasiveness",
"DEFAULT": "???"
},
"AttackTypeBoosterItem": { "AttackTypeBoosterItem": {
"silk_scarf": "Silk Scarf", "silk_scarf": "Silk Scarf",
"black_belt": "Black Belt", "black_belt": "Black Belt",
@ -450,6 +437,6 @@
"DRAGON_MEMORY": "Dragon Memory", "DRAGON_MEMORY": "Dragon Memory",
"DARK_MEMORY": "Dark Memory", "DARK_MEMORY": "Dark Memory",
"FAIRY_MEMORY": "Fairy Memory", "FAIRY_MEMORY": "Fairy Memory",
"BLANK_MEMORY": "Blank Memory" "NORMAL_MEMORY": "Normal Memory"
} }
} }

View File

@ -3,7 +3,7 @@
"turnHealApply": "{{pokemonNameWithAffix}} restored a little HP using\nits {{typeName}}!", "turnHealApply": "{{pokemonNameWithAffix}} restored a little HP using\nits {{typeName}}!",
"hitHealApply": "{{pokemonNameWithAffix}} restored a little HP using\nits {{typeName}}!", "hitHealApply": "{{pokemonNameWithAffix}} restored a little HP using\nits {{typeName}}!",
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} was revived\nby its {{typeName}}!", "pokemonInstantReviveApply": "{{pokemonNameWithAffix}} was revived\nby its {{typeName}}!",
"pokemonResetNegativeStatStageApply": "{{pokemonNameWithAffix}}'s lowered stats were restored\nby its {{typeName}}!", "resetNegativeStatStageApply": "{{pokemonNameWithAffix}}'s lowered stats were restored\nby its {{typeName}}!",
"moneyInterestApply": "You received interest of ₽{{moneyAmount}}\nfrom the {{typeName}}!", "moneyInterestApply": "You received interest of ₽{{moneyAmount}}\nfrom the {{typeName}}!",
"turnHeldItemTransferApply": "{{pokemonNameWithAffix}}'s {{itemName}} was absorbed\nby {{pokemonName}}'s {{typeName}}!", "turnHeldItemTransferApply": "{{pokemonNameWithAffix}}'s {{itemName}} was absorbed\nby {{pokemonName}}'s {{typeName}}!",
"contactHeldItemTransferApply": "{{pokemonNameWithAffix}}'s {{itemName}} was snatched\nby {{pokemonName}}'s {{typeName}}!", "contactHeldItemTransferApply": "{{pokemonNameWithAffix}}'s {{itemName}} was snatched\nby {{pokemonName}}'s {{typeName}}!",

View File

@ -3,6 +3,10 @@
"cutHpPowerUpMove": "{{pokemonName}} cut its own HP to power up its move!", "cutHpPowerUpMove": "{{pokemonName}} cut its own HP to power up its move!",
"absorbedElectricity": "{{pokemonName}} absorbed electricity!", "absorbedElectricity": "{{pokemonName}} absorbed electricity!",
"switchedStatChanges": "{{pokemonName}} switched stat changes with the target!", "switchedStatChanges": "{{pokemonName}} switched stat changes with the target!",
"switchedTwoStatChanges": "{{pokemonName}} switched all changes to its {{firstStat}}\nand {{secondStat}} with its target!",
"switchedStat": "{{pokemonName}} switched {{stat}} with its target!",
"sharedGuard": "{{pokemonName}} shared its guard with the target!",
"sharedPower": "{{pokemonName}} shared its power with the target!",
"goingAllOutForAttack": "{{pokemonName}} is going all out for this attack!", "goingAllOutForAttack": "{{pokemonName}} is going all out for this attack!",
"regainedHealth": "{{pokemonName}} regained\nhealth!", "regainedHealth": "{{pokemonName}} regained\nhealth!",
"keptGoingAndCrashed": "{{pokemonName}} kept going\nand crashed!", "keptGoingAndCrashed": "{{pokemonName}} kept going\nand crashed!",
@ -61,5 +65,6 @@
"suppressAbilities": "{{pokemonName}}'s ability\nwas suppressed!", "suppressAbilities": "{{pokemonName}}'s ability\nwas suppressed!",
"revivalBlessing": "{{pokemonName}} was revived!", "revivalBlessing": "{{pokemonName}} was revived!",
"swapArenaTags": "{{pokemonName}} swapped the battle effects affecting each side of the field!", "swapArenaTags": "{{pokemonName}} swapped the battle effects affecting each side of the field!",
"exposedMove": "{{pokemonName}} identified\n{{targetPokemonName}}!" "exposedMove": "{{pokemonName}} identified\n{{targetPokemonName}}!",
} "safeguard": "{{targetName}} is protected by Safeguard!"
}

Some files were not shown because too many files have changed in this diff Show More