Merge branch 'main' into fix-releasing-read-pokemon

This commit is contained in:
cadi 2024-06-25 19:08:58 +09:00
commit e26cdaca3f
245 changed files with 16677 additions and 13027 deletions

View File

@ -31,11 +31,6 @@
font-family: 'emerald'; font-family: 'emerald';
src: url('./fonts/pokemon-emerald-pro.ttf') format('truetype'); src: url('./fonts/pokemon-emerald-pro.ttf') format('truetype');
} }
@font-face {
font-family: 'unifont';
src: url('./fonts/unifont-15.1.05.otf') format('opentype');
size-adjust: 70%;
}
@font-face { @font-face {
font-family: 'pkmnems'; font-family: 'pkmnems';

6
package-lock.json generated
View File

@ -8365,9 +8365,9 @@
"dev": true "dev": true
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.16.0", "version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -29,8 +29,8 @@
"15-mega", "15-mega",
"150-mega", "150-mega",
"150-mega", "150-mega",
"150-mega", "150-mega-x",
"150-mega", "150-mega-y",
"18-mega", "18-mega",
"18-mega", "18-mega",
"181-mega", "181-mega",
@ -185,8 +185,8 @@
"531-mega", "531-mega",
"6-mega", "6-mega",
"6-mega", "6-mega",
"6-mega", "6-mega-x",
"6-mega", "6-mega-y",
"6058", "6058",
"6058", "6058",
"6059", "6059",
@ -1161,8 +1161,8 @@
"15b-mega", "15b-mega",
"150b-mega", "150b-mega",
"150b-mega", "150b-mega",
"150b-mega", "150b-mega-x",
"150b-mega", "150b-mega-y",
"18b-mega", "18b-mega",
"18b-mega", "18b-mega",
"181b-mega", "181b-mega",
@ -1317,8 +1317,8 @@
"531b-mega", "531b-mega",
"6b-mega", "6b-mega",
"6b-mega", "6b-mega",
"6b-mega", "6b-mega-x",
"6b-mega", "6b-mega-y",
"6058b", "6058b",
"6058b", "6058b",
"6059b", "6059b",
@ -2295,8 +2295,8 @@
"15sb-mega", "15sb-mega",
"150sb-mega", "150sb-mega",
"150sb-mega", "150sb-mega",
"150sb-mega", "150sb-mega-x",
"150sb-mega", "150sb-mega-y",
"18sb-mega", "18sb-mega",
"18sb-mega", "18sb-mega",
"181sb-mega", "181sb-mega",
@ -2451,8 +2451,8 @@
"531sb-mega", "531sb-mega",
"6sb-mega", "6sb-mega",
"6sb-mega", "6sb-mega",
"6sb-mega", "6sb-mega-x",
"6sb-mega", "6sb-mega-y",
"6058sb", "6058sb",
"6058sb", "6058sb",
"6059sb", "6059sb",
@ -3432,8 +3432,8 @@
"15s-mega", "15s-mega",
"150s-mega", "150s-mega",
"150s-mega", "150s-mega",
"150s-mega", "150s-mega-x",
"150s-mega", "150s-mega-y",
"18s-mega", "18s-mega",
"18s-mega", "18s-mega",
"181s-mega", "181s-mega",
@ -3588,8 +3588,8 @@
"531s-mega", "531s-mega",
"6s-mega", "6s-mega",
"6s-mega", "6s-mega",
"6s-mega", "6s-mega-x",
"6s-mega", "6s-mega-y",
"6058s", "6058s",
"6058s", "6058s",
"6059s", "6059s",

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,41 +0,0 @@
{
"textures": [
{
"image": "678ms.png",
"format": "RGBA8888",
"size": {
"w": 56,
"h": 56
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 45,
"h": 56
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 45,
"h": 56
},
"frame": {
"x": 0,
"y": 0,
"w": 45,
"h": 56
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:935ddcd2ff1f413e94967151e2f4cc6d:bdb048fb547d7ebb9a83d391e8f1c9ba:81f219fee9493a3658266d8c5e858b9e$"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 713 B

View File

@ -1,41 +0,0 @@
{
"textures": [
{
"image": "678msb.png",
"format": "RGBA8888",
"size": {
"w": 55,
"h": 55
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 46,
"h": 55
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 46,
"h": 55
},
"frame": {
"x": 0,
"y": 0,
"w": 46,
"h": 55
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:979291307687f1a4af47bc4d29542ccf:f61247ececc23f282bb95c5bfe49e179:bbcc2663448733722c64bc1ebafbf9c6$"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,7 +1,7 @@
{ {
"textures": [ "textures": [
{ {
"image": "types_pt_BR.png", "image": "types_pt-BR.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": { "size": {
"w": 32, "w": 32,

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,7 +1,7 @@
{ {
"textures": [ "textures": [
{ {
"image": "types_zh_CN.png", "image": "types_zh-CN.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": { "size": {
"w": 32, "w": 32,

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -1,7 +1,7 @@
{ {
"textures": [ "textures": [
{ {
"image": "types_zh_TW.png", "image": "types_zh-TW.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": { "size": {
"w": 32, "w": 32,

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

View File

Before

Width:  |  Height:  |  Size: 800 B

After

Width:  |  Height:  |  Size: 800 B

View File

Before

Width:  |  Height:  |  Size: 799 B

After

Width:  |  Height:  |  Size: 799 B

View File

@ -1,55 +1,9 @@
import { AbilityTranslationEntries, SimpleTranslationEntries, AchievementTranslationEntries, BerryTranslationEntries, DialogueTranslationEntries, ModifierTypeTranslationEntries, MoveTranslationEntries, PokemonInfoTranslationEntries, TranslationEntries } from "#app/interfaces/locales"; import { enConfig } from "#app/locales/en/config.js";
// Module declared to make referencing keys in the localization files type-safe. // Module declared to make referencing keys in the localization files type-safe.
declare module "i18next" { declare module "i18next" {
interface CustomTypeOptions { interface CustomTypeOptions {
defaultNS: "menu", // needed here as well for typedoc defaultNS: "menu", // needed here as well for typedoc
resources: { resources: typeof enConfig
ability: AbilityTranslationEntries;
abilityTriggers: SimpleTranslationEntries;
achv: AchievementTranslationEntries;
battle: SimpleTranslationEntries;
battleMessageUiHandler: SimpleTranslationEntries;
berry: BerryTranslationEntries;
biome: SimpleTranslationEntries;
challenges: SimpleTranslationEntries;
commandUiHandler: SimpleTranslationEntries;
common: TranslationEntries;
PGMachv: AchievementTranslationEntries;
PGFachv: AchievementTranslationEntries;
PGMdialogue: DialogueTranslationEntries;
PGFdialogue: DialogueTranslationEntries;
PGMbattleSpecDialogue: SimpleTranslationEntries;
PGFbattleSpecDialogue: SimpleTranslationEntries;
PGMmiscDialogue: SimpleTranslationEntries;
PGFmiscDialogue: SimpleTranslationEntries;
PGMdoubleBattleDialogue: DialogueTranslationEntries;
PGFdoubleBattleDialogue: DialogueTranslationEntries;
egg: SimpleTranslationEntries;
fightUiHandler: SimpleTranslationEntries;
gameMode: SimpleTranslationEntries;
gameStatsUiHandler: SimpleTranslationEntries;
growth: SimpleTranslationEntries;
menu: SimpleTranslationEntries;
menuUiHandler: SimpleTranslationEntries;
modifierType: ModifierTypeTranslationEntries;
move: MoveTranslationEntries;
nature: SimpleTranslationEntries;
partyUiHandler: SimpleTranslationEntries;
pokeball: SimpleTranslationEntries;
pokemon: SimpleTranslationEntries;
pokemonInfo: PokemonInfoTranslationEntries;
pokemonInfoContainer: SimpleTranslationEntries;
saveSlotSelectUiHandler: SimpleTranslationEntries;
settings: SimpleTranslationEntries;
splashMessages: SimpleTranslationEntries;
starterSelectUiHandler: SimpleTranslationEntries;
titles: SimpleTranslationEntries;
trainerClasses: SimpleTranslationEntries;
trainerNames: SimpleTranslationEntries;
tutorial: SimpleTranslationEntries;
voucher: SimpleTranslationEntries;
weather: SimpleTranslationEntries;
};
} }
} }

View File

@ -37,7 +37,7 @@ import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin";
import { addUiThemeOverrides } from "./ui/ui-theme"; import { addUiThemeOverrides } from "./ui/ui-theme";
import PokemonData from "./system/pokemon-data"; import PokemonData from "./system/pokemon-data";
import { Nature } from "./data/nature"; import { Nature } from "./data/nature";
import { SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger, pokemonFormChanges } from "./data/pokemon-forms"; import { SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger, pokemonFormChanges } from "./data/pokemon-forms";
import { FormChangePhase, QuietFormChangePhase } from "./form-change-phase"; import { FormChangePhase, QuietFormChangePhase } from "./form-change-phase";
import { getTypeRgb } from "./data/type"; import { getTypeRgb } from "./data/type";
import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler"; import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler";
@ -157,6 +157,8 @@ export default class BattleScene extends SceneBase {
public fusionPaletteSwaps: boolean = true; public fusionPaletteSwaps: boolean = true;
public enableTouchControls: boolean = false; public enableTouchControls: boolean = false;
public enableVibration: boolean = false; public enableVibration: boolean = false;
public showBgmBar: boolean = true;
/** /**
* Determines the selected battle style. * Determines the selected battle style.
* - 0 = 'Switch' * - 0 = 'Switch'
@ -219,6 +221,7 @@ export default class BattleScene extends SceneBase {
public arenaFlyout: ArenaFlyout; public arenaFlyout: ArenaFlyout;
private fieldOverlay: Phaser.GameObjects.Rectangle; private fieldOverlay: Phaser.GameObjects.Rectangle;
private shopOverlay: Phaser.GameObjects.Rectangle;
public modifiers: PersistentModifier[]; public modifiers: PersistentModifier[];
private enemyModifiers: PersistentModifier[]; private enemyModifiers: PersistentModifier[];
public uiContainer: Phaser.GameObjects.Container; public uiContainer: Phaser.GameObjects.Container;
@ -332,7 +335,9 @@ export default class BattleScene extends SceneBase {
launchBattle() { launchBattle() {
this.arenaBg = this.add.sprite(0, 0, "plains_bg"); this.arenaBg = this.add.sprite(0, 0, "plains_bg");
this.arenaBg.setName("sprite-arena-bg");
this.arenaBgTransition = this.add.sprite(0, 0, "plains_bg"); this.arenaBgTransition = this.add.sprite(0, 0, "plains_bg");
this.arenaBgTransition.setName("sprite-arena-bg-transition");
[ this.arenaBgTransition, this.arenaBg ].forEach(a => { [ this.arenaBgTransition, this.arenaBg ].forEach(a => {
a.setPipeline(this.fieldSpritePipeline); a.setPipeline(this.fieldSpritePipeline);
@ -342,13 +347,13 @@ export default class BattleScene extends SceneBase {
}); });
const field = this.add.container(0, 0); const field = this.add.container(0, 0);
field.setName("field");
field.setScale(6); field.setScale(6);
field.setName("container-field");
this.field = field; this.field = field;
const fieldUI = this.add.container(0, this.game.canvas.height); const fieldUI = this.add.container(0, this.game.canvas.height);
fieldUI.setName("container-field-ui"); fieldUI.setName("field-ui");
fieldUI.setDepth(1); fieldUI.setDepth(1);
fieldUI.setScale(6); fieldUI.setScale(6);
@ -372,7 +377,7 @@ export default class BattleScene extends SceneBase {
this.add.existing(transition); this.add.existing(transition);
const uiContainer = this.add.container(0, 0); const uiContainer = this.add.container(0, 0);
uiContainer.setName("container-ui"); uiContainer.setName("ui");
uiContainer.setDepth(2); uiContainer.setDepth(2);
uiContainer.setScale(6); uiContainer.setScale(6);
@ -386,16 +391,22 @@ export default class BattleScene extends SceneBase {
this.fieldOverlay.setAlpha(0); this.fieldOverlay.setAlpha(0);
this.fieldUI.add(this.fieldOverlay); this.fieldUI.add(this.fieldOverlay);
this.shopOverlay = this.add.rectangle(0, overlayHeight * -1 - 48, overlayWidth, overlayHeight, 0x070707);
this.shopOverlay.setName("rect-shop-overlay");
this.shopOverlay.setOrigin(0, 0);
this.shopOverlay.setAlpha(0);
this.fieldUI.add(this.shopOverlay);
this.modifiers = []; this.modifiers = [];
this.enemyModifiers = []; this.enemyModifiers = [];
this.modifierBar = new ModifierBar(this); this.modifierBar = new ModifierBar(this);
this.modifierBar.setName("container-modifier-bar"); this.modifierBar.setName("modifier-bar");
this.add.existing(this.modifierBar); this.add.existing(this.modifierBar);
uiContainer.add(this.modifierBar); uiContainer.add(this.modifierBar);
this.enemyModifierBar = new ModifierBar(this, true); this.enemyModifierBar = new ModifierBar(this, true);
this.enemyModifierBar.setName("container-enemy-modifier-bar"); this.enemyModifierBar.setName("enemy-modifier-bar");
this.add.existing(this.enemyModifierBar); this.add.existing(this.enemyModifierBar);
uiContainer.add(this.enemyModifierBar); uiContainer.add(this.enemyModifierBar);
@ -406,28 +417,28 @@ export default class BattleScene extends SceneBase {
this.fieldUI.add(this.charSprite); this.fieldUI.add(this.charSprite);
this.pbTray = new PokeballTray(this, true); this.pbTray = new PokeballTray(this, true);
this.pbTray.setName("container-pb-tray"); this.pbTray.setName("pb-tray");
this.pbTray.setup(); this.pbTray.setup();
this.pbTrayEnemy = new PokeballTray(this, false); this.pbTrayEnemy = new PokeballTray(this, false);
this.pbTrayEnemy.setName("container-enemy-pb-tray"); this.pbTrayEnemy.setName("enemy-pb-tray");
this.pbTrayEnemy.setup(); this.pbTrayEnemy.setup();
this.fieldUI.add(this.pbTray); this.fieldUI.add(this.pbTray);
this.fieldUI.add(this.pbTrayEnemy); this.fieldUI.add(this.pbTrayEnemy);
this.abilityBar = new AbilityBar(this); this.abilityBar = new AbilityBar(this);
this.abilityBar.setName("container-ability-bar"); this.abilityBar.setName("ability-bar");
this.abilityBar.setup(); this.abilityBar.setup();
this.fieldUI.add(this.abilityBar); this.fieldUI.add(this.abilityBar);
this.partyExpBar = new PartyExpBar(this); this.partyExpBar = new PartyExpBar(this);
this.partyExpBar.setName("container-party-exp-bar"); this.partyExpBar.setName("party-exp-bar");
this.partyExpBar.setup(); this.partyExpBar.setup();
this.fieldUI.add(this.partyExpBar); this.fieldUI.add(this.partyExpBar);
this.candyBar = new CandyBar(this); this.candyBar = new CandyBar(this);
this.candyBar.setName("container-candy-bar"); this.candyBar.setName("candy-bar");
this.candyBar.setup(); this.candyBar.setup();
this.fieldUI.add(this.candyBar); this.fieldUI.add(this.candyBar);
@ -479,13 +490,13 @@ export default class BattleScene extends SceneBase {
const loadPokemonAssets = []; const loadPokemonAssets = [];
this.arenaPlayer = new ArenaBase(this, true); this.arenaPlayer = new ArenaBase(this, true);
this.arenaPlayer.setName("container-arena-player"); this.arenaPlayer.setName("arena-player");
this.arenaPlayerTransition = new ArenaBase(this, true); this.arenaPlayerTransition = new ArenaBase(this, true);
this.arenaPlayerTransition.setName("container-arena-player-transition"); this.arenaPlayerTransition.setName("arena-player-transition");
this.arenaEnemy = new ArenaBase(this, false); this.arenaEnemy = new ArenaBase(this, false);
this.arenaEnemy.setName("container-arena-enemy"); this.arenaEnemy.setName("arena-enemy");
this.arenaNextEnemy = new ArenaBase(this, false); this.arenaNextEnemy = new ArenaBase(this, false);
this.arenaNextEnemy.setName("container-arena-next-enemy"); this.arenaNextEnemy.setName("arena-next-enemy");
this.arenaBgTransition.setVisible(false); this.arenaBgTransition.setVisible(false);
this.arenaPlayerTransition.setVisible(false); this.arenaPlayerTransition.setVisible(false);
@ -737,6 +748,14 @@ export default class BattleScene extends SceneBase {
: ret; : ret;
} }
/**
* Returns the ModifierBar of this scene, which is declared private and therefore not accessible elsewhere
* @returns {ModifierBar}
*/
getModifierBar(): ModifierBar {
return this.modifierBar;
}
// store info toggles to be accessible by the ui // store info toggles to be accessible by the ui
addInfoToggle(infoToggle: InfoToggle): void { addInfoToggle(infoToggle: InfoToggle): void {
this.infoToggles.push(infoToggle); this.infoToggles.push(infoToggle);
@ -798,8 +817,10 @@ export default class BattleScene extends SceneBase {
addPokemonIcon(pokemon: Pokemon, x: number, y: number, originX: number = 0.5, originY: number = 0.5, ignoreOverride: boolean = false): Phaser.GameObjects.Container { addPokemonIcon(pokemon: Pokemon, x: number, y: number, originX: number = 0.5, originY: number = 0.5, ignoreOverride: boolean = false): Phaser.GameObjects.Container {
const container = this.add.container(x, y); const container = this.add.container(x, y);
container.setName(`${pokemon.name}-icon`);
const icon = this.add.sprite(0, 0, pokemon.getIconAtlasKey(ignoreOverride)); const icon = this.add.sprite(0, 0, pokemon.getIconAtlasKey(ignoreOverride));
icon.setName(`sprite-${pokemon.name}-icon`);
icon.setFrame(pokemon.getIconId(true)); icon.setFrame(pokemon.getIconId(true));
// Temporary fix to show pokemon's default icon if variant icon doesn't exist // Temporary fix to show pokemon's default icon if variant icon doesn't exist
if (icon.frame.name !== pokemon.getIconId(true)) { if (icon.frame.name !== pokemon.getIconId(true)) {
@ -816,6 +837,7 @@ export default class BattleScene extends SceneBase {
if (pokemon.isFusion()) { if (pokemon.isFusion()) {
const fusionIcon = this.add.sprite(0, 0, pokemon.getFusionIconAtlasKey(ignoreOverride)); const fusionIcon = this.add.sprite(0, 0, pokemon.getFusionIconAtlasKey(ignoreOverride));
fusionIcon.setName("sprite-fusion-icon");
fusionIcon.setOrigin(0.5, 0); fusionIcon.setOrigin(0.5, 0);
fusionIcon.setFrame(pokemon.getFusionIconId(true)); fusionIcon.setFrame(pokemon.getFusionIconId(true));
@ -1100,8 +1122,10 @@ export default class BattleScene extends SceneBase {
playerField.forEach((_, p) => this.unshiftPhase(new ReturnPhase(this, p))); playerField.forEach((_, p) => this.unshiftPhase(new ReturnPhase(this, p)));
for (const pokemon of this.getParty()) { for (const pokemon of this.getParty()) {
if (pokemon.hasAbility(Abilities.ICE_FACE)) { // Only trigger form change when Eiscue is in Noice form
pokemon.formIndex = 0; // Hardcoded Eiscue for now in case it is fused with another pokemon
if (pokemon.species.speciesId === Species.EISCUE && pokemon.hasAbility(Abilities.ICE_FACE) && pokemon.formIndex === 1) {
this.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger);
} }
pokemon.resetBattleData(); pokemon.resetBattleData();
@ -1397,6 +1421,30 @@ export default class BattleScene extends SceneBase {
}); });
} }
showShopOverlay(duration: integer): Promise<void> {
return new Promise(resolve => {
this.tweens.add({
targets: this.shopOverlay,
alpha: 0.8,
ease: "Sine.easeOut",
duration: duration,
onComplete: () => resolve()
});
});
}
hideShopOverlay(duration: integer): Promise<void> {
return new Promise(resolve => {
this.tweens.add({
targets: this.shopOverlay,
alpha: 0,
duration: duration,
ease: "Cubic.easeIn",
onComplete: () => resolve()
});
});
}
showEnemyModifierBar(): void { showEnemyModifierBar(): void {
this.enemyModifierBar.setVisible(true); this.enemyModifierBar.setVisible(true);
} }
@ -1408,6 +1456,7 @@ export default class BattleScene extends SceneBase {
updateBiomeWaveText(): void { updateBiomeWaveText(): void {
const isBoss = !(this.currentBattle.waveIndex % 10); const isBoss = !(this.currentBattle.waveIndex % 10);
const biomeString: string = getBiomeName(this.arena.biomeType); const biomeString: string = getBiomeName(this.arena.biomeType);
this.fieldUI.moveAbove(this.biomeWaveText, this.luckText);
this.biomeWaveText.setText( biomeString + " - " + this.currentBattle.waveIndex.toString()); this.biomeWaveText.setText( biomeString + " - " + this.currentBattle.waveIndex.toString());
this.biomeWaveText.setColor(!isBoss ? "#ffffff" : "#f89890"); this.biomeWaveText.setColor(!isBoss ? "#ffffff" : "#f89890");
this.biomeWaveText.setShadowColor(!isBoss ? "#636363" : "#984038"); this.biomeWaveText.setShadowColor(!isBoss ? "#636363" : "#984038");
@ -1592,6 +1641,7 @@ export default class BattleScene extends SceneBase {
: this.getBgmLoopPoint(bgmName); : this.getBgmLoopPoint(bgmName);
let loaded = false; let loaded = false;
const playNewBgm = () => { const playNewBgm = () => {
this.ui.bgmBar.setBgmToBgmBar(bgmName);
if (bgmName === null && this.bgm && !this.bgm.pendingRemove) { if (bgmName === null && this.bgm && !this.bgm.pendingRemove) {
this.bgm.play({ this.bgm.play({
volume: this.masterVolume * this.bgmVolume volume: this.masterVolume * this.bgmVolume
@ -1847,8 +1897,26 @@ export default class BattleScene extends SceneBase {
return 13.940; return 13.940;
case "end_summit": //PMD RTDX Sky Tower Summit case "end_summit": //PMD RTDX Sky Tower Summit
return 30.025; return 30.025;
case "battle_rocket_grunt": //HGSS Team Rocket Battle
return 12.707;
case "battle_aqua_magma_grunt": //ORAS Team Aqua & Magma Battle
return 12.062;
case "battle_galactic_grunt": //BDSP Team Galactic Battle
return 13.043;
case "battle_plasma_grunt": //BW Team Plasma Battle case "battle_plasma_grunt": //BW Team Plasma Battle
return 12.974; return 12.974;
case "battle_flare_grunt": //XY Team Flare Battle
return 4.228;
case "battle_rocket_boss": //USUM Giovanni Battle
return 9.115;
case "battle_aqua_magma_boss": //ORAS Archie & Maxie Battle
return 14.847;
case "battle_galactic_boss": //BDSP Cyrus Battle
return 106.962;
case "battle_plasma_boss": //B2W2 Ghetsis Battle
return 25.624;
case "battle_flare_boss": //XY Lysandre Battle
return 8.085;
} }
return 0; return 0;

View File

@ -7,6 +7,7 @@ import { GameMode } from "./game-mode";
import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier"; import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier";
import { PokeballType } from "./data/pokeball"; import { PokeballType } from "./data/pokeball";
import {trainerConfigs} from "#app/data/trainer-config"; import {trainerConfigs} from "#app/data/trainer-config";
import { ArenaTagType } from "#enums/arena-tag-type";
import { BattleSpec } from "#enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
@ -166,6 +167,10 @@ export default class Battle {
const moneyAmount = new Utils.IntegerHolder(scene.currentBattle.moneyScattered); const moneyAmount = new Utils.IntegerHolder(scene.currentBattle.moneyScattered);
scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount); scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
if (scene.arena.getTag(ArenaTagType.HAPPY_HOUR)) {
moneyAmount.value *= 2;
}
scene.addMoney(moneyAmount.value); scene.addMoney(moneyAmount.value);
scene.queueMessage(`You picked up ₽${moneyAmount.value.toLocaleString("en-US")}!`, null, true); scene.queueMessage(`You picked up ₽${moneyAmount.value.toLocaleString("en-US")}!`, null, true);
@ -426,8 +431,8 @@ export interface FixedBattleConfigs {
/** /**
* Youngster/Lass on 5 * Youngster/Lass on 5
* Rival on 8, 55, 95, 145, 195 * Rival on 8, 55, 95, 145, 195
* Evil team grunts on 35, 62, 64, 65, 112, 114 (Not currently spawning) * Evil team grunts on 35, 62, 64, 66, 112, 114
* Evil leader on 115, 165 (Not currently spawning) * Evil leader on 115, 165
* E4 on 182, 184, 186, 188 * E4 on 182, 184, 186, 188
* Champion on 190 * Champion on 190
*/ */
@ -438,28 +443,28 @@ export const classicFixedBattles: FixedBattleConfigs = {
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
// [35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
[55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
// [62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) [62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
// [64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) [64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
// [65]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) [66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
[95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
// [112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) [112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
// [114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) [114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
// [115]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) [115]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE ])),
[145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
// [165]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) [165]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2 ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2 ])),
[182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])), .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])),
[184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) [184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)

View File

@ -6,7 +6,7 @@ import { BattleStat, getBattleStatName } from "./battle-stat";
import { MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases"; import { MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases";
import { getPokemonMessage, getPokemonNameWithAffix } from "../messages"; import { getPokemonMessage, getPokemonNameWithAffix } from "../messages";
import { Weather, WeatherType } from "./weather"; import { Weather, WeatherType } from "./weather";
import { BattlerTag } from "./battler-tags"; import { BattlerTag, GroundedTag } from "./battler-tags";
import { StatusEffect, getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "./status-effect"; import { StatusEffect, getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "./status-effect";
import { Gender } from "./gender"; import { Gender } from "./gender";
import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, FlinchAttr, OneHitKOAttr, HitHealAttr, allMoves, StatusMove, SelfStatusMove, VariablePowerAttr, applyMoveAttrs, IncrementMovePriorityAttr, VariableMoveTypeAttr, RandomMovesetMoveAttr, RandomMoveAttr, NaturePowerAttr, CopyMoveAttr } from "./move"; import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, FlinchAttr, OneHitKOAttr, HitHealAttr, allMoves, StatusMove, SelfStatusMove, VariablePowerAttr, applyMoveAttrs, IncrementMovePriorityAttr, VariableMoveTypeAttr, RandomMovesetMoveAttr, RandomMoveAttr, NaturePowerAttr, CopyMoveAttr } from "./move";
@ -1702,7 +1702,18 @@ export class PostIntimidateStatChangeAbAttr extends AbAttr {
} }
} }
/**
* Base class for defining all {@linkcode Ability} Attributes post summon
* @see {@linkcode applyPostSummon()}
*/
export class PostSummonAbAttr extends AbAttr { export class PostSummonAbAttr extends AbAttr {
/**
* Applies ability post summon (after switching in)
* @param pokemon {@linkcode Pokemon} with this ability
* @param passive Whether this ability is a passive
* @param args Set of unique arguments needed by this attribute
* @returns true if application of the ability succeeds
*/
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> { applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
return false; return false;
} }
@ -1974,7 +1985,11 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr {
} }
} }
export class TraceAbAttr extends PostSummonAbAttr { /** Attempts to copy a pokemon's ability */
export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr {
private target: Pokemon;
private targetAbilityName: string;
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
const targets = pokemon.getOpponents(); const targets = pokemon.getOpponents();
if (!targets.length) { if (!targets.length) {
@ -1988,18 +2003,57 @@ export class TraceAbAttr extends PostSummonAbAttr {
target = targets[0]; target = targets[0];
} }
// Wonder Guard is normally uncopiable so has the attribute, but trace specifically can copy it if (
if (target.getAbility().hasAttr(UncopiableAbilityAbAttr) && target.getAbility().id !== Abilities.WONDER_GUARD) { target.getAbility().hasAttr(UncopiableAbilityAbAttr) &&
// Wonder Guard is normally uncopiable so has the attribute, but Trace specifically can copy it
!(pokemon.hasAbility(Abilities.TRACE) && target.getAbility().id === Abilities.WONDER_GUARD)
) {
return false; return false;
} }
this.target = target;
this.targetAbilityName = allAbilities[target.getAbility().id].name;
pokemon.summonData.ability = target.getAbility().id; pokemon.summonData.ability = target.getAbility().id;
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` traced ${target.name}'s\n${allAbilities[target.getAbility().id].name}!`));
setAbilityRevealed(target); setAbilityRevealed(target);
pokemon.updateInfo();
return true; return true;
} }
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
return i18next.t("abilityTriggers:trace", {
pokemonName: getPokemonNameWithAffix(pokemon),
targetName: getPokemonNameWithAffix(this.target),
abilityName: this.targetAbilityName,
});
}
}
/** Attempt to copy the stat changes on an ally pokemon */
export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr {
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
if (!pokemon.scene.currentBattle.double) {
return false;
}
const ally = pokemon.getAlly();
if (!ally || ally.summonData.battleStats.every((change) => change === 0)) {
return false;
}
pokemon.summonData.battleStats = ally.summonData.battleStats;
pokemon.updateInfo();
return true;
}
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
return i18next.t("abilityTriggers:costar", {
pokemonName: getPokemonNameWithAffix(pokemon),
allyName: getPokemonNameWithAffix(pokemon.getAlly()),
});
}
} }
export class PostSummonTransformAbAttr extends PostSummonAbAttr { export class PostSummonTransformAbAttr extends PostSummonAbAttr {
@ -2350,7 +2404,7 @@ export class BlockNonDirectDamageAbAttr extends AbAttr {
/** /**
* This attribute will block any status damage that you put in the parameter. * This attribute will block any status damage that you put in the parameter.
*/ */
export class BlockStatusDamageAbAttr extends BlockNonDirectDamageAbAttr { export class BlockStatusDamageAbAttr extends AbAttr {
private effects: StatusEffect[]; private effects: StatusEffect[];
/** /**
@ -2370,7 +2424,7 @@ export class BlockStatusDamageAbAttr extends BlockNonDirectDamageAbAttr {
* @returns Returns true if status damage is blocked * @returns Returns true if status damage is blocked
*/ */
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (this.effects.includes(pokemon.status.effect)) { if (this.effects.includes(pokemon.status?.effect)) {
cancelled.value = true; cancelled.value = true;
return true; return true;
} }
@ -3732,6 +3786,54 @@ export class IceFaceBlockPhysicalAbAttr extends ReceivedMoveDamageMultiplierAbAt
} }
} }
/**
* If a Pokémon with this Ability selects a damaging move, it has a 30% chance of going first in its priority bracket. If the Ability activates, this is announced at the start of the turn (after move selection).
*
* @extends AbAttr
*/
export class BypassSpeedChanceAbAttr extends AbAttr {
public chance: integer;
/**
* @param {integer} chance probability of ability being active.
*/
constructor(chance: integer) {
super(true);
this.chance = chance;
}
/**
* bypass move order in their priority bracket when pokemon choose damaging move
* @param {Pokemon} pokemon {@linkcode Pokemon} the Pokemon applying this ability
* @param {boolean} passive N/A
* @param {Utils.BooleanHolder} cancelled N/A
* @param {any[]} args [0] {@linkcode Utils.BooleanHolder} set to true when the ability activated
* @returns {boolean} - whether the ability was activated.
*/
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
const bypassSpeed = args[0] as Utils.BooleanHolder;
if (!bypassSpeed.value && pokemon.randSeedInt(100) < this.chance) {
const turnCommand =
pokemon.scene.currentBattle.turnCommands[pokemon.getBattlerIndex()];
const isCommandFight = turnCommand?.command === Command.FIGHT;
const move = allMoves[turnCommand.move?.move];
const isDamageMove = move?.category === MoveCategory.PHYSICAL || move?.category === MoveCategory.SPECIAL;
if (isCommandFight && isDamageMove) {
bypassSpeed.value = true;
return true;
}
}
return false;
}
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
return i18next.t("abilityTriggers:quickDraw", {pokemonName: getPokemonNameWithAffix(pokemon)});
}
}
function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: Constructor<TAttr>, function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: Constructor<TAttr>,
pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> { pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
@ -4056,7 +4158,7 @@ export function initAbilities() {
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.LEVITATE, 3) new Ability(Abilities.LEVITATE, 3)
.attr(TypeImmunityAbAttr, Type.GROUND, (pokemon: Pokemon) => !pokemon.getTag(BattlerTagType.IGNORE_FLYING) && !pokemon.scene.arena.getTag(ArenaTagType.GRAVITY) && !pokemon.getTag(BattlerTagType.GROUNDED)) .attr(TypeImmunityAbAttr, Type.GROUND, (pokemon: Pokemon) => !pokemon.getTag(GroundedTag) && !pokemon.scene.arena.getTag(ArenaTagType.GRAVITY))
.ignorable(), .ignorable(),
new Ability(Abilities.EFFECT_SPORE, 3) new Ability(Abilities.EFFECT_SPORE, 3)
.attr(EffectSporeAbAttr), .attr(EffectSporeAbAttr),
@ -4086,7 +4188,7 @@ export function initAbilities() {
.attr(DoubleBattleChanceAbAttr) .attr(DoubleBattleChanceAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.TRACE, 3) new Ability(Abilities.TRACE, 3)
.attr(TraceAbAttr) .attr(PostSummonCopyAbilityAbAttr)
.attr(UncopiableAbilityAbAttr), .attr(UncopiableAbilityAbAttr),
new Ability(Abilities.HUGE_POWER, 3) new Ability(Abilities.HUGE_POWER, 3)
.attr(BattleStatMultiplierAbAttr, BattleStat.ATK, 2), .attr(BattleStatMultiplierAbAttr, BattleStat.ATK, 2),
@ -4489,8 +4591,8 @@ export function initAbilities() {
.attr(HealFromBerryUseAbAttr, 1/3) .attr(HealFromBerryUseAbAttr, 1/3)
.partial(), // Healing not blocked by Heal Block .partial(), // Healing not blocked by Heal Block
new Ability(Abilities.PROTEAN, 6) new Ability(Abilities.PROTEAN, 6)
.attr(PokemonTypeChangeAbAttr) .attr(PokemonTypeChangeAbAttr),
.condition((p) => !p.summonData?.abilitiesApplied.includes(Abilities.PROTEAN)), //.condition((p) => !p.summonData?.abilitiesApplied.includes(Abilities.PROTEAN)), //Gen 9 Implementation
new Ability(Abilities.FUR_COAT, 6) new Ability(Abilities.FUR_COAT, 6)
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, 0.5) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, 0.5)
.ignorable(), .ignorable(),
@ -4542,7 +4644,8 @@ export function initAbilities() {
.attr(FieldMoveTypePowerBoostAbAttr, Type.FAIRY, 4 / 3), .attr(FieldMoveTypePowerBoostAbAttr, Type.FAIRY, 4 / 3),
new Ability(Abilities.AURA_BREAK, 6) new Ability(Abilities.AURA_BREAK, 6)
.ignorable() .ignorable()
.unimplemented(), .conditionalAttr(target => target.hasAbility(Abilities.DARK_AURA), FieldMoveTypePowerBoostAbAttr, Type.DARK, 9 / 16)
.conditionalAttr(target => target.hasAbility(Abilities.FAIRY_AURA), FieldMoveTypePowerBoostAbAttr, Type.FAIRY, 9 / 16),
new Ability(Abilities.PRIMORDIAL_SEA, 6) new Ability(Abilities.PRIMORDIAL_SEA, 6)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.HEAVY_RAIN) .attr(PostSummonWeatherChangeAbAttr, WeatherType.HEAVY_RAIN)
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HEAVY_RAIN) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HEAVY_RAIN)
@ -4732,8 +4835,8 @@ export function initAbilities() {
.attr(PostSummonStatChangeAbAttr, BattleStat.DEF, 1, true) .attr(PostSummonStatChangeAbAttr, BattleStat.DEF, 1, true)
.condition(getOncePerBattleCondition(Abilities.DAUNTLESS_SHIELD)), .condition(getOncePerBattleCondition(Abilities.DAUNTLESS_SHIELD)),
new Ability(Abilities.LIBERO, 8) new Ability(Abilities.LIBERO, 8)
.attr(PokemonTypeChangeAbAttr) .attr(PokemonTypeChangeAbAttr),
.condition((p) => !p.summonData?.abilitiesApplied.includes(Abilities.LIBERO)), //.condition((p) => !p.summonData?.abilitiesApplied.includes(Abilities.LIBERO)), //Gen 9 Implementation
new Ability(Abilities.BALL_FETCH, 8) new Ability(Abilities.BALL_FETCH, 8)
.attr(FetchBallAbAttr) .attr(FetchBallAbAttr)
.condition(getOncePerBattleCondition(Abilities.BALL_FETCH)), .condition(getOncePerBattleCondition(Abilities.BALL_FETCH)),
@ -4815,7 +4918,7 @@ export function initAbilities() {
.attr(NoFusionAbilityAbAttr) .attr(NoFusionAbilityAbAttr)
.condition((pokemon) => !pokemon.isTerastallized()), .condition((pokemon) => !pokemon.isTerastallized()),
new Ability(Abilities.QUICK_DRAW, 8) new Ability(Abilities.QUICK_DRAW, 8)
.unimplemented(), .attr(BypassSpeedChanceAbAttr, 30),
new Ability(Abilities.UNSEEN_FIST, 8) new Ability(Abilities.UNSEEN_FIST, 8)
.attr(IgnoreProtectOnContactAbAttr), .attr(IgnoreProtectOnContactAbAttr),
new Ability(Abilities.CURIOUS_MEDICINE, 8) new Ability(Abilities.CURIOUS_MEDICINE, 8)
@ -4941,7 +5044,7 @@ export function initAbilities() {
.attr(VariableMovePowerBoostAbAttr, (user, target, move) => 1 + 0.1 * Math.min(user.isPlayer() ? user.scene.currentBattle.playerFaints : user.scene.currentBattle.enemyFaints, 5)) .attr(VariableMovePowerBoostAbAttr, (user, target, move) => 1 + 0.1 * Math.min(user.isPlayer() ? user.scene.currentBattle.playerFaints : user.scene.currentBattle.enemyFaints, 5))
.partial(), .partial(),
new Ability(Abilities.COSTAR, 9) new Ability(Abilities.COSTAR, 9)
.unimplemented(), .attr(PostSummonCopyAllyStatsAbAttr),
new Ability(Abilities.TOXIC_DEBRIS, 9) new Ability(Abilities.TOXIC_DEBRIS, 9)
.attr(PostDefendApplyArenaTrapTagAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, ArenaTagType.TOXIC_SPIKES) .attr(PostDefendApplyArenaTrapTagAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, ArenaTagType.TOXIC_SPIKES)
.bypassFaint(), .bypassFaint(),

View File

@ -4,7 +4,7 @@ import * as Utils from "../utils";
import { MoveCategory, allMoves, MoveTarget } from "./move"; import { MoveCategory, allMoves, MoveTarget } from "./move";
import { getPokemonMessage } from "../messages"; import { getPokemonMessage } from "../messages";
import Pokemon, { HitResult, PokemonMove } from "../field/pokemon"; import Pokemon, { HitResult, PokemonMove } from "../field/pokemon";
import { MoveEffectPhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase} from "../phases"; import { MoveEffectPhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases";
import { StatusEffect } from "./status-effect"; import { StatusEffect } from "./status-effect";
import { BattlerIndex } from "../battle"; import { BattlerIndex } from "../battle";
import { BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability"; import { BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability";
@ -63,6 +63,10 @@ export abstract class ArenaTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Mist_(move) Mist}.
* Prevents Pokémon on the opposing side from lowering the stats of the Pokémon in the Mist.
*/
export class MistTag extends ArenaTag { export class MistTag extends ArenaTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side); super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side);
@ -86,37 +90,57 @@ export class MistTag extends ArenaTag {
} }
} }
/**
* Reduces the damage of specific move categories in the arena.
* @extends ArenaTag
*/
export class WeakenMoveScreenTag extends ArenaTag { export class WeakenMoveScreenTag extends ArenaTag {
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide) { protected weakenedCategories: MoveCategory[];
/**
* Creates a new instance of the WeakenMoveScreenTag class.
*
* @param tagType - The type of the arena tag.
* @param turnCount - The number of turns the tag is active.
* @param sourceMove - The move that created the tag.
* @param sourceId - The ID of the source of the tag.
* @param side - The side (player or enemy) the tag affects.
* @param weakenedCategories - The categories of moves that are weakened by this tag.
*/
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, weakenedCategories: MoveCategory[]) {
super(tagType, turnCount, sourceMove, sourceId, side); super(tagType, turnCount, sourceMove, sourceId, side);
this.weakenedCategories = weakenedCategories;
} }
/**
* Applies the weakening effect to the move.
*
* @param arena - The arena where the move is applied.
* @param args - The arguments for the move application.
* @param args[0] - The category of the move.
* @param args[1] - A boolean indicating whether it is a double battle.
* @param args[2] - An object of type `Utils.NumberHolder` that holds the damage multiplier
*
* @returns True if the move was weakened, otherwise false.
*/
apply(arena: Arena, args: any[]): boolean { apply(arena: Arena, args: any[]): boolean {
if ((args[1] as boolean)) { if (this.weakenedCategories.includes((args[0] as MoveCategory))) {
(args[2] as Utils.NumberHolder).value = 2732/4096; (args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732/4096 : 0.5;
} else {
(args[2] as Utils.NumberHolder).value = 0.5;
}
return true;
}
}
class ReflectTag extends WeakenMoveScreenTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side);
}
apply(arena: Arena, args: any[]): boolean {
if ((args[0] as MoveCategory) === MoveCategory.PHYSICAL) {
if ((args[1] as boolean)) {
(args[2] as Utils.NumberHolder).value = 2732/4096;
} else {
(args[2] as Utils.NumberHolder).value = 0.5;
}
return true; return true;
} }
return false; return false;
} }
}
/**
* Reduces the damage of physical moves.
* Used by {@linkcode Moves.REFLECT}
*/
class ReflectTag extends WeakenMoveScreenTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [MoveCategory.PHYSICAL]);
}
onAdd(arena: Arena, quiet: boolean = false): void { onAdd(arena: Arena, quiet: boolean = false): void {
if (!quiet) { if (!quiet) {
@ -125,21 +149,13 @@ class ReflectTag extends WeakenMoveScreenTag {
} }
} }
/**
* Reduces the damage of special moves.
* Used by {@linkcode Moves.LIGHT_SCREEN}
*/
class LightScreenTag extends WeakenMoveScreenTag { class LightScreenTag extends WeakenMoveScreenTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side); super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [MoveCategory.SPECIAL]);
}
apply(arena: Arena, args: any[]): boolean {
if ((args[0] as MoveCategory) === MoveCategory.SPECIAL) {
if ((args[1] as boolean)) {
(args[2] as Utils.NumberHolder).value = 2732/4096;
} else {
(args[2] as Utils.NumberHolder).value = 0.5;
}
return true;
}
return false;
} }
onAdd(arena: Arena, quiet: boolean = false): void { onAdd(arena: Arena, quiet: boolean = false): void {
@ -149,9 +165,13 @@ class LightScreenTag extends WeakenMoveScreenTag {
} }
} }
/**
* Reduces the damage of physical and special moves.
* Used by {@linkcode Moves.AURORA_VEIL}
*/
class AuroraVeilTag extends WeakenMoveScreenTag { class AuroraVeilTag extends WeakenMoveScreenTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side); super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL]);
} }
onAdd(arena: Arena, quiet: boolean = false): void { onAdd(arena: Arena, quiet: boolean = false): void {
@ -283,6 +303,10 @@ class CraftyShieldTag extends ConditionalProtectTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Wish_(move) Wish}.
* Heals the Pokémon in the user's position the turn after Wish is used.
*/
class WishTag extends ArenaTag { class WishTag extends ArenaTag {
private battlerIndex: BattlerIndex; private battlerIndex: BattlerIndex;
private triggerMessage: string; private triggerMessage: string;
@ -308,9 +332,21 @@ class WishTag extends ArenaTag {
} }
} }
/**
* Abstract class to implement weakened moves of a specific type.
*/
export class WeakenMoveTypeTag extends ArenaTag { export class WeakenMoveTypeTag extends ArenaTag {
private weakenedType: Type; private weakenedType: Type;
/**
* Creates a new instance of the WeakenMoveTypeTag class.
*
* @param tagType - The type of the arena tag.
* @param turnCount - The number of turns the tag is active.
* @param type - The type being weakened from this tag.
* @param sourceMove - The move that created the tag.
* @param sourceId - The ID of the source of the tag.
*/
constructor(tagType: ArenaTagType, turnCount: integer, type: Type, sourceMove: Moves, sourceId: integer) { constructor(tagType: ArenaTagType, turnCount: integer, type: Type, sourceMove: Moves, sourceId: integer) {
super(tagType, turnCount, sourceMove, sourceId); super(tagType, turnCount, sourceMove, sourceId);
@ -327,6 +363,10 @@ export class WeakenMoveTypeTag extends ArenaTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Mud_Sport_(move) Mud Sport}.
* Weakens Electric type moves for a set amount of turns, usually 5.
*/
class MudSportTag extends WeakenMoveTypeTag { class MudSportTag extends WeakenMoveTypeTag {
constructor(turnCount: integer, sourceId: integer) { constructor(turnCount: integer, sourceId: integer) {
super(ArenaTagType.MUD_SPORT, turnCount, Type.ELECTRIC, Moves.MUD_SPORT, sourceId); super(ArenaTagType.MUD_SPORT, turnCount, Type.ELECTRIC, Moves.MUD_SPORT, sourceId);
@ -341,6 +381,10 @@ class MudSportTag extends WeakenMoveTypeTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Water_Sport_(move) Water Sport}.
* Weakens Fire type moves for a set amount of turns, usually 5.
*/
class WaterSportTag extends WeakenMoveTypeTag { class WaterSportTag extends WeakenMoveTypeTag {
constructor(turnCount: integer, sourceId: integer) { constructor(turnCount: integer, sourceId: integer) {
super(ArenaTagType.WATER_SPORT, turnCount, Type.FIRE, Moves.WATER_SPORT, sourceId); super(ArenaTagType.WATER_SPORT, turnCount, Type.FIRE, Moves.WATER_SPORT, sourceId);
@ -355,10 +399,22 @@ class WaterSportTag extends WeakenMoveTypeTag {
} }
} }
/**
* Abstract class to implement arena traps.
*/
export class ArenaTrapTag extends ArenaTag { export class ArenaTrapTag extends ArenaTag {
public layers: integer; public layers: integer;
public maxLayers: integer; public maxLayers: integer;
/**
* Creates a new instance of the ArenaTrapTag class.
*
* @param tagType - The type of the arena tag.
* @param sourceMove - The move that created the tag.
* @param sourceId - The ID of the source of the tag.
* @param side - The side (player or enemy) the tag affects.
* @param maxLayers - The maximum amount of layers this tag can have.
*/
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, maxLayers: integer) { constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, maxLayers: integer) {
super(tagType, 0, sourceMove, sourceId, side); super(tagType, 0, sourceMove, sourceId, side);
@ -392,6 +448,11 @@ export class ArenaTrapTag extends ArenaTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Spikes_(move) Spikes}.
* Applies up to 3 layers of Spikes, dealing 1/8th, 1/6th, or 1/4th of the the Pokémon's HP
* in damage for 1, 2, or 3 layers of Spikes respectively if they are summoned into this trap.
*/
class SpikesTag extends ArenaTrapTag { class SpikesTag extends ArenaTrapTag {
constructor(sourceId: integer, side: ArenaTagSide) { constructor(sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3); super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3);
@ -428,6 +489,12 @@ class SpikesTag extends ArenaTrapTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Spikes_(move) Toxic Spikes}.
* Applies up to 2 layers of Toxic Spikes, poisoning or badly poisoning any Pokémon who is
* summoned into this trap if 1 or 2 layers of Toxic Spikes respectively are up. Poison-type
* Pokémon summoned into this trap remove it entirely.
*/
class ToxicSpikesTag extends ArenaTrapTag { class ToxicSpikesTag extends ArenaTrapTag {
private neutralized: boolean; private neutralized: boolean;
@ -481,6 +548,11 @@ class ToxicSpikesTag extends ArenaTrapTag {
} }
} }
/**
* Arena Tag class for delayed attacks, such as {@linkcode Moves.FUTURE_SIGHT} or {@linkcode Moves.DOOM_DESIRE}.
* Delays the attack's effect by a set amount of turns, usually 3 (including the turn the move is used),
* and deals damage after the turn count is reached.
*/
class DelayedAttackTag extends ArenaTag { class DelayedAttackTag extends ArenaTag {
public targetIndex: BattlerIndex; public targetIndex: BattlerIndex;
@ -503,6 +575,11 @@ class DelayedAttackTag extends ArenaTag {
onRemove(arena: Arena): void { } onRemove(arena: Arena): void { }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Stealth_Rock_(move) Stealth Rock}.
* Applies up to 1 layer of Stealth Rocks, dealing percentage-based damage to any Pokémon
* who is summoned into the trap, based on the Rock type's type effectiveness.
*/
class StealthRockTag extends ArenaTrapTag { class StealthRockTag extends ArenaTrapTag {
constructor(sourceId: integer, side: ArenaTagSide) { constructor(sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1); super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1);
@ -574,6 +651,11 @@ class StealthRockTag extends ArenaTrapTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Sticky_Web_(move) Sticky Web}.
* Applies up to 1 layer of Sticky Web, which lowers the Speed by one stage
* to any Pokémon who is summoned into this trap.
*/
class StickyWebTag extends ArenaTrapTag { class StickyWebTag extends ArenaTrapTag {
constructor(sourceId: integer, side: ArenaTagSide) { constructor(sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1); super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1);
@ -606,6 +688,11 @@ class StickyWebTag extends ArenaTrapTag {
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Trick_Room_(move) Trick Room}.
* Reverses the Speed stats for all Pokémon on the field as long as this arena tag is up,
* also reversing the turn order for all Pokémon on the field as well.
*/
export class TrickRoomTag extends ArenaTag { export class TrickRoomTag extends ArenaTag {
constructor(turnCount: integer, sourceId: integer) { constructor(turnCount: integer, sourceId: integer) {
super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId); super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId);
@ -626,6 +713,11 @@ export class TrickRoomTag extends ArenaTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Gravity_(move) Gravity}.
* Grounds all Pokémon on the field, including Flying-types and those with
* {@linkcode Abilities.LEVITATE} for the duration of the arena tag, usually 5 turns.
*/
export class GravityTag extends ArenaTag { export class GravityTag extends ArenaTag {
constructor(turnCount: integer) { constructor(turnCount: integer) {
super(ArenaTagType.GRAVITY, turnCount, Moves.GRAVITY); super(ArenaTagType.GRAVITY, turnCount, Moves.GRAVITY);
@ -645,6 +737,11 @@ export class GravityTag extends ArenaTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Tailwind_(move) Tailwind}.
* Doubles the Speed of the Pokémon who created this arena tag, as well as all allied Pokémon.
* Applies this arena tag for 4 turns (including the turn the move was used).
*/
class TailwindTag extends ArenaTag { class TailwindTag extends ArenaTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side); super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side);
@ -679,6 +776,24 @@ class TailwindTag extends ArenaTag {
} }
} }
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Happy_Hour_(move) Happy Hour}.
* Doubles the prize money from trainers and money moves like {@linkcode Moves.PAY_DAY} and {@linkcode Moves.MAKE_IT_RAIN}.
*/
class HappyHourTag extends ArenaTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.HAPPY_HOUR, turnCount, Moves.HAPPY_HOUR, sourceId, side);
}
onAdd(arena: Arena): void {
arena.scene.queueMessage("Everyone is caught up in the happy atmosphere!");
}
onRemove(arena: Arena): void {
arena.scene.queueMessage("The atmosphere returned to normal.");
}
}
export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag { export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag {
switch (tagType) { switch (tagType) {
case ArenaTagType.MIST: case ArenaTagType.MIST:
@ -720,5 +835,7 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
return new AuroraVeilTag(turnCount, sourceId, side); return new AuroraVeilTag(turnCount, sourceId, side);
case ArenaTagType.TAILWIND: case ArenaTagType.TAILWIND:
return new TailwindTag(turnCount, sourceId, side); return new TailwindTag(turnCount, sourceId, side);
case ArenaTagType.HAPPY_HOUR:
return new HappyHourTag(turnCount, sourceId, side);
} }
} }

View File

@ -32,34 +32,38 @@ export function getBattleStatName(stat: BattleStat) {
} }
} }
export function getBattleStatLevelChangeDescription(levels: integer, up: boolean) { export function getBattleStatLevelChangeDescription(pokemonNameWithAffix: string, stats: string, levels: integer, up: boolean) {
if (up) { const stringKey = (() => {
switch (levels) { if (up) {
case 1: switch (levels) {
return i18next.t("battle:statRose"); case 1:
case 2: return "battle:statRose";
return i18next.t("battle:statSharplyRose"); case 2:
case 3: return "battle:statSharplyRose";
case 4: case 3:
case 5: case 4:
case 6: case 5:
return i18next.t("battle:statRoseDrastically"); case 6:
default: return "battle:statRoseDrastically";
return i18next.t("battle:statWontGoAnyHigher"); 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";
}
} }
} else { })();
switch (levels) {
case 1: return i18next.t(stringKey, { pokemonNameWithAffix, stats });
return i18next.t("battle:statFell");
case 2:
return i18next.t("battle:statHarshlyFell");
case 3:
case 4:
case 5:
case 6:
return i18next.t("battle:statSeverelyFell");
default:
return i18next.t("battle:statWontGoAnyLower");
}
}
} }

View File

@ -1258,7 +1258,7 @@ export class TerrainHighestStatBoostTag extends HighestStatBoostTag implements T
} }
} }
export class HideSpriteTag extends BattlerTag { export class SemiInvulnerableTag extends BattlerTag {
constructor(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves) { constructor(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves) {
super(tagType, BattlerTagLapseType.MOVE_EFFECT, turnCount, sourceMove); super(tagType, BattlerTagLapseType.MOVE_EFFECT, turnCount, sourceMove);
} }
@ -1467,6 +1467,17 @@ export class CursedTag extends BattlerTag {
} }
} }
/**
* Battler tag for effects that ground the source, allowing Ground-type moves to hit them. Encompasses two tag types:
* @item IGNORE_FLYING: Persistent grounding effects (i.e. from Smack Down and Thousand Waves)
* @item ROOSTED: One-turn grounding effects (i.e. from Roost)
*/
export class GroundedTag extends BattlerTag {
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, sourceMove: Moves) {
super(tagType, lapseType, 1, sourceMove);
}
}
/** /**
* Provides the Ice Face ability's effects. * Provides the Ice Face ability's effects.
*/ */
@ -1604,7 +1615,7 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
case BattlerTagType.UNDERGROUND: case BattlerTagType.UNDERGROUND:
case BattlerTagType.UNDERWATER: case BattlerTagType.UNDERWATER:
case BattlerTagType.HIDDEN: case BattlerTagType.HIDDEN:
return new HideSpriteTag(tagType, turnCount, sourceMove); return new SemiInvulnerableTag(tagType, turnCount, sourceMove);
case BattlerTagType.FIRE_BOOST: case BattlerTagType.FIRE_BOOST:
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:
@ -1618,9 +1629,9 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
case BattlerTagType.BYPASS_SLEEP: case BattlerTagType.BYPASS_SLEEP:
return new BattlerTag(BattlerTagType.BYPASS_SLEEP, BattlerTagLapseType.TURN_END, turnCount, sourceMove); return new BattlerTag(BattlerTagType.BYPASS_SLEEP, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
case BattlerTagType.IGNORE_FLYING: case BattlerTagType.IGNORE_FLYING:
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove); return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
case BattlerTagType.GROUNDED: case BattlerTagType.ROOSTED:
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount - 1, sourceMove); return new GroundedTag(tagType, BattlerTagLapseType.TURN_END, sourceMove);
case BattlerTagType.SALT_CURED: case BattlerTagType.SALT_CURED:
return new SaltCuredTag(sourceId); return new SaltCuredTag(sourceId);
case BattlerTagType.CURSED: case BattlerTagType.CURSED:

View File

@ -1,97 +1,525 @@
import BattleScene from "../battle-scene"; import BattleScene from "../battle-scene";
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species"; import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species";
import { VariantTier } from "../enums/variant-tiers";
import * as Utils from "../utils";
import * as Overrides from "../overrides";
import { pokemonPrevolutions } from "./pokemon-evolutions";
import { PlayerPokemon } from "#app/field/pokemon";
import i18next from "i18next"; import i18next from "i18next";
import { EggTier } from "#enums/egg-type"; import { EggTier } from "#enums/egg-type";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { EggSourceType } from "#app/enums/egg-source-types.js";
export const EGG_SEED = 1073741824; export const EGG_SEED = 1073741824;
export enum GachaType { // Rates for specific random properties in 1/x
MOVE, const DEFAULT_SHINY_RATE = 128;
LEGENDARY, const GACHA_SHINY_UP_SHINY_RATE = 64;
SHINY const SAME_SPECIES_EGG_SHINY_RATE = 32;
const SAME_SPECIES_EGG_HA_RATE = 16;
const MANAPHY_EGG_MANAPHY_RATE = 8;
// 1/x for legendary eggs, 1/x*2 for epic eggs, 1/x*4 for rare eggs, and 1/x*8 for common eggs
const DEFAULT_RARE_EGGMOVE_RATE = 6;
const SAME_SPECIES_EGG_RARE_EGGMOVE_RATE = 3;
const GACHA_MOVE_UP_RARE_EGGMOVE_RATE = 3;
/** Egg options to override egg properties */
export interface IEggOptions {
/** Id. Used to check if egg type will be manaphy (id % 204 === 0) */
id?: number;
/** Timestamp when this egg got created */
timestamp?: number;
/** Defines if the egg got pulled from a gacha or not. If true, egg pity and pull statistics will be applyed.
* Egg will be automaticly added to the game data.
* NEEDS scene eggOption to work.
*/
pulled?: boolean;
/** Defines where the egg comes from. Applies specific modifiers.
* Will also define the text displayed in the egg list.
*/
sourceType?: EggSourceType;
/** Needs to be defined if eggOption pulled is defined or if no species or isShiny is degined since this will be needed to generate them. */
scene?: BattleScene;
/** Sets the tier of the egg. Only species of this tier can be hatched from this egg.
* Tier will be overriden if species eggOption is set.
*/
tier?: EggTier;
/** Sets how many waves it will take till this egg hatches. */
hatchWaves?: number;
/** Sets the exact species that will hatch from this egg.
* Needs scene eggOption if not provided.
*/
species?: Species;
/** Defines if the hatched pokemon will be a shiny. */
isShiny?: boolean;
/** Defines the variant of the pokemon that will hatch from this egg. If no variantTier is given the normal variant rates will apply. */
variantTier?: VariantTier;
/** Defines which egg move will be unlocked. 3 = rare egg move. */
eggMoveIndex?: number;
/** Defines if the egg will hatch with the hidden ability of this species.
* If no hidden ability exist, a random one will get choosen.
*/
overrideHiddenAbility?: boolean
} }
export class Egg { export class Egg {
public id: integer;
public tier: EggTier;
public gachaType: GachaType;
public hatchWaves: integer;
public timestamp: integer;
constructor(id: integer, gachaType: GachaType, hatchWaves: integer, timestamp: integer) { ////
this.id = id; // #region Privat properties
this.tier = Math.floor(id / EGG_SEED); ////
this.gachaType = gachaType;
this.hatchWaves = hatchWaves; private _id: number;
this.timestamp = timestamp; private _tier: EggTier;
private _sourceType: EggSourceType | undefined;
private _hatchWaves: number;
private _timestamp: number;
private _species: Species;
private _isShiny: boolean;
private _variantTier: VariantTier;
private _eggMoveIndex: number;
private _overrideHiddenAbility: boolean;
////
// #endregion
////
////
// #region Public facing properties
////
get id(): number {
return this._id;
} }
isManaphyEgg(): boolean { get tier(): EggTier {
return this.tier === EggTier.COMMON && !(this.id % 204); return this._tier;
} }
getKey(): string { get sourceType(): EggSourceType | undefined {
return this._sourceType;
}
get hatchWaves(): number {
return this._hatchWaves;
}
set hatchWaves(value: number) {
this._hatchWaves = value;
}
get timestamp(): number {
return this._timestamp;
}
get species(): Species {
return this._species;
}
get isShiny(): boolean {
return this._isShiny;
}
get variantTier(): VariantTier {
return this._variantTier;
}
get eggMoveIndex(): number {
return this._eggMoveIndex;
}
get overrideHiddenAbility(): boolean {
return this._overrideHiddenAbility;
}
////
// #endregion
////
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.")
this._tier = eggOptions.tier ?? (Overrides.EGG_TIER_OVERRIDE ?? this.rollEggTier());
this._sourceType = eggOptions.sourceType ?? undefined;
// If egg was pulled, check if egg pity needs to override the egg tier
if (eggOptions.pulled) {
// Needs this._tier and this._sourceType to work
this.checkForPityTierOverrides(eggOptions.scene);
}
this._id = eggOptions.id ?? Utils.randInt(EGG_SEED, EGG_SEED * this._tier);
this._sourceType = eggOptions.sourceType ?? undefined;
this._hatchWaves = eggOptions.hatchWaves ?? this.getEggTierDefaultHatchWaves();
this._timestamp = eggOptions.timestamp ?? new Date().getTime();
// 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._variantTier = eggOptions.variantTier ?? (Overrides.EGG_VARIANT_OVERRIDE ?? this.rollVariant());
this._species = eggOptions.species ?? this.rollSpecies(eggOptions.scene);
this._overrideHiddenAbility = eggOptions.overrideHiddenAbility ?? false;
// Override egg tier and hatchwaves if species was given
if (eggOptions.species) {
this._tier = this.getEggTierFromSpeciesStarterValue();
this._hatchWaves = eggOptions.hatchWaves ?? this.getEggTierDefaultHatchWaves();
// If species has no variant, set variantTier to common. This needs to
// be done because species with no variants get filtered at rollSpecies but since the
// species is set the check never happens
if (!getPokemonSpecies(this.species).hasVariants()) {
this._variantTier = VariantTier.COMMON;
}
}
// Needs this._tier so it needs to be generated afer the tier override if bought from same species
this._eggMoveIndex = eggOptions.eggMoveIndex ?? this.rollEggMoveIndex();
if (eggOptions.pulled) {
this.increasePullStatistic(eggOptions.scene);
this.addEggToGameData(eggOptions.scene);
}
}
////
// #region Public methodes
////
public isManaphyEgg(): boolean {
return (this._species === Species.PHIONE || this._species === Species.MANAPHY) ||
this._tier === EggTier.COMMON && !(this._id % 204) && !this._species;
}
public getKey(): string {
if (this.isManaphyEgg()) { if (this.isManaphyEgg()) {
return "manaphy"; return "manaphy";
} }
return this.tier.toString(); return this._tier.toString();
} }
// Generates a PlayerPokemon from an egg
public generatePlayerPokemon(scene: BattleScene): PlayerPokemon {
// Legacy egg wants to hatch. Generate missing properties
if (!this._species) {
this._isShiny = this.rollShiny();
this._species = this.rollSpecies(scene);
}
const pokemonSpecies = getPokemonSpecies(this._species);
// Sets the hidden ability if a hidden ability exists and the override is set
// or if the same species egg hits the chance
let abilityIndex = undefined;
if (pokemonSpecies.abilityHidden && (this._overrideHiddenAbility
|| (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !Utils.randSeedInt(SAME_SPECIES_EGG_HA_RATE)))) {
abilityIndex = pokemonSpecies.ability2 ? 2 : 1;
}
// This function has way to many optional parameters
const ret: PlayerPokemon = scene.addPlayerPokemon(pokemonSpecies, 1, abilityIndex, undefined, undefined, false);
ret.shiny = this._isShiny;
ret.variant = this._variantTier;
const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295));
for (let s = 0; s < ret.ivs.length; s++) {
ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]);
}
return ret;
}
// Doesn't need to be called if the egg got pulled by a gacha machiene
public addEggToGameData(scene: BattleScene): void {
scene.gameData.eggs.push(this);
}
public getEggDescriptor(): string {
if (this.isManaphyEgg()) {
return "Manaphy";
}
switch (this.tier) {
case EggTier.GREAT:
return i18next.t("egg:greatTier");
case EggTier.ULTRA:
return i18next.t("egg:ultraTier");
case EggTier.MASTER:
return i18next.t("egg:masterTier");
default:
return i18next.t("egg:defaultTier");
}
}
public getEggHatchWavesMessage(): string {
if (this.hatchWaves <= 5) {
return i18next.t("egg:hatchWavesMessageSoon");
}
if (this.hatchWaves <= 15) {
return i18next.t("egg:hatchWavesMessageClose");
}
if (this.hatchWaves <= 50) {
return i18next.t("egg:hatchWavesMessageNotClose");
}
return i18next.t("egg:hatchWavesMessageLongTime");
}
public getEggTypeDescriptor(scene: BattleScene): string {
switch (this.sourceType) {
case EggSourceType.SAME_SPECIES_EGG:
return i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName()});
case EggSourceType.GACHA_LEGENDARY:
return `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`;
case EggSourceType.GACHA_SHINY:
return i18next.t("egg:gachaTypeShiny");
case EggSourceType.GACHA_MOVE:
return i18next.t("egg:gachaTypeMove");
}
}
////
// #endregion
////
////
// #region Private methodes
////
private rollEggMoveIndex() {
let baseChance = DEFAULT_RARE_EGGMOVE_RATE;
switch (this._sourceType) {
case EggSourceType.SAME_SPECIES_EGG:
baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE;
break;
case EggSourceType.GACHA_MOVE:
baseChance = GACHA_MOVE_UP_RARE_EGGMOVE_RATE;
break;
default:
break;
}
return Utils.randSeedInt(baseChance * Math.pow(2, 3 - this.tier)) ? Utils.randSeedInt(3) : 3;
}
private getEggTierDefaultHatchWaves(eggTier?: EggTier): number {
if (this._species === Species.PHIONE || this._species === Species.MANAPHY) {
return 50;
}
switch (eggTier ?? this._tier) {
case EggTier.COMMON:
return 10;
case EggTier.GREAT:
return 25;
case EggTier.ULTRA:
return 50;
}
return 100;
}
private rollEggTier(): EggTier {
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? 1 : 0;
const tierValue = Utils.randInt(256);
return tierValue >= 52 + tierValueOffset ? EggTier.COMMON : tierValue >= 8 + tierValueOffset ? EggTier.GREAT : tierValue >= 1 + tierValueOffset ? EggTier.ULTRA : EggTier.MASTER;
}
private rollSpecies(scene: BattleScene): Species {
if (!scene) {
return undefined;
}
/**
* Manaphy eggs have a 1/8 chance of being Manaphy and 7/8 chance of being Phione
* Legendary eggs pulled from the legendary gacha have a 50% of being converted into
* the species that was the legendary focus at the time
*/
if (this.isManaphyEgg()) {
const rand = Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE);
return rand ? Species.PHIONE : Species.MANAPHY;
} else if (this.tier === EggTier.MASTER
&& this._sourceType === EggSourceType.GACHA_LEGENDARY) {
if (!Utils.randSeedInt(2)) {
return getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp);
}
}
let minStarterValue: integer;
let maxStarterValue: integer;
switch (this.tier) {
case EggTier.GREAT:
minStarterValue = 4;
maxStarterValue = 5;
break;
case EggTier.ULTRA:
minStarterValue = 6;
maxStarterValue = 7;
break;
case EggTier.MASTER:
minStarterValue = 8;
maxStarterValue = 9;
break;
default:
minStarterValue = 1;
maxStarterValue = 3;
break;
}
const ignoredSpecies = [Species.PHIONE, Species.MANAPHY, Species.ETERNATUS];
let speciesPool = Object.keys(speciesStarters)
.filter(s => speciesStarters[s] >= minStarterValue && speciesStarters[s] <= maxStarterValue)
.map(s => parseInt(s) as Species)
.filter(s => !pokemonPrevolutions.hasOwnProperty(s) && getPokemonSpecies(s).isObtainable() && ignoredSpecies.indexOf(s) === -1);
// If this is the 10th egg without unlocking something new, attempt to force it.
if (scene.gameData.unlockPity[this.tier] >= 9) {
const lockedPool = speciesPool.filter(s => !scene.gameData.dexData[s].caughtAttr);
if (lockedPool.length) { // Skip this if everything is unlocked
speciesPool = lockedPool;
}
}
// If egg variant is set to RARE or EPIC, filter species pool to only include ones with variants.
if (this.variantTier && (this.variantTier === VariantTier.RARE || this.variantTier === VariantTier.EPIC)) {
speciesPool = speciesPool.filter(s => getPokemonSpecies(s).hasVariants());
}
/**
* Pokemon that are cheaper in their tier get a weight boost. Regionals get a weight penalty
* 1 cost mons get 2x
* 2 cost mons get 1.5x
* 4, 6, 8 cost mons get 1.75x
* 3, 5, 7, 9 cost mons get 1x
* Alolan, Galarian, and Paldean mons get 0.5x
* Hisui mons get 0.125x
*
* The total weight is also being calculated EACH time there is an egg hatch instead of being generated once
* and being the same each time
*/
let totalWeight = 0;
const speciesWeights = [];
for (const speciesId of speciesPool) {
let weight = Math.floor((((maxStarterValue - speciesStarters[speciesId]) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100);
const species = getPokemonSpecies(speciesId);
if (species.isRegional()) {
weight = Math.floor(weight / (species.isRareRegional() ? 8 : 2));
}
speciesWeights.push(totalWeight + weight);
totalWeight += weight;
}
let species: Species;
const rand = Utils.randSeedInt(totalWeight);
for (let s = 0; s < speciesWeights.length; s++) {
if (rand < speciesWeights[s]) {
species = speciesPool[s];
break;
}
}
if (!!scene.gameData.dexData[species].caughtAttr) {
scene.gameData.unlockPity[this.tier] = Math.min(scene.gameData.unlockPity[this.tier] + 1, 10);
} else {
scene.gameData.unlockPity[this.tier] = 0;
}
return species;
}
/**
* Rolls whether the egg is shiny or not.
* @returns True if the egg is shiny
**/
private rollShiny(): boolean {
let shinyChance = DEFAULT_SHINY_RATE;
switch (this._sourceType) {
case EggSourceType.GACHA_SHINY:
shinyChance = GACHA_SHINY_UP_SHINY_RATE;
break;
case EggSourceType.SAME_SPECIES_EGG:
shinyChance = SAME_SPECIES_EGG_SHINY_RATE;
break;
default:
break;
}
return !Utils.randSeedInt(shinyChance);
}
// Uses the same logic as pokemon.generateVariant(). I would like to only have this logic in one
// place but I don't want to touch the pokemon class.
private rollVariant(): VariantTier {
if (!this.isShiny) {
return VariantTier.COMMON;
}
const rand = Utils.randSeedInt(10);
if (rand >= 4) {
return VariantTier.COMMON; // 6/10
} else if (rand >= 1) {
return VariantTier.RARE; // 3/10
} else {
return VariantTier.EPIC; // 1/10
}
}
private checkForPityTierOverrides(scene: BattleScene): void {
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? 1 : 0;
scene.gameData.eggPity[EggTier.GREAT] += 1;
scene.gameData.eggPity[EggTier.ULTRA] += 1;
scene.gameData.eggPity[EggTier.MASTER] += 1 + tierValueOffset;
// These numbers are roughly the 80% mark. That is, 80% of the time you'll get an egg before this gets triggered.
if (scene.gameData.eggPity[EggTier.MASTER] >= 412 && this._tier === EggTier.COMMON) {
this._tier = EggTier.MASTER;
} else if (scene.gameData.eggPity[EggTier.ULTRA] >= 59 && this._tier === EggTier.COMMON) {
this._tier = EggTier.ULTRA;
} else if (scene.gameData.eggPity[EggTier.GREAT] >= 9 && this._tier === EggTier.COMMON) {
this._tier = EggTier.GREAT;
}
scene.gameData.eggPity[this._tier] = 0;
}
private increasePullStatistic(scene: BattleScene): void {
scene.gameData.gameStats.eggsPulled++;
if (this.isManaphyEgg()) {
scene.gameData.gameStats.manaphyEggsPulled++;
this._hatchWaves = this.getEggTierDefaultHatchWaves(EggTier.ULTRA);
return;
}
switch (this.tier) {
case EggTier.GREAT:
scene.gameData.gameStats.rareEggsPulled++;
break;
case EggTier.ULTRA:
scene.gameData.gameStats.epicEggsPulled++;
break;
case EggTier.MASTER:
scene.gameData.gameStats.legendaryEggsPulled++;
break;
}
}
private getEggTierFromSpeciesStarterValue(): EggTier {
const speciesStartValue = speciesStarters[this.species];
if (speciesStartValue >= 1 && speciesStartValue <= 3) {
return EggTier.COMMON;
}
if (speciesStartValue >= 4 && speciesStartValue <= 5) {
return EggTier.GREAT;
}
if (speciesStartValue >= 6 && speciesStartValue <= 7) {
return EggTier.ULTRA;
}
if (speciesStartValue >= 8) {
return EggTier.MASTER;
}
}
////
// #endregion
////
} }
export function getEggTierDefaultHatchWaves(tier: EggTier): integer { export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timestamp: number): Species {
switch (tier) {
case EggTier.COMMON:
return 10;
case EggTier.GREAT:
return 25;
case EggTier.ULTRA:
return 50;
}
return 100;
}
export function getEggDescriptor(egg: Egg): string {
if (egg.isManaphyEgg()) {
return "Manaphy";
}
switch (egg.tier) {
case EggTier.GREAT:
return i18next.t("egg:greatTier");
case EggTier.ULTRA:
return i18next.t("egg:ultraTier");
case EggTier.MASTER:
return i18next.t("egg:masterTier");
default:
return i18next.t("egg:defaultTier");
}
}
export function getEggHatchWavesMessage(hatchWaves: integer): string {
if (hatchWaves <= 5) {
return i18next.t("egg:hatchWavesMessageSoon");
}
if (hatchWaves <= 15) {
return i18next.t("egg:hatchWavesMessageClose");
}
if (hatchWaves <= 50) {
return i18next.t("egg:hatchWavesMessageNotClose");
}
return i18next.t("egg:hatchWavesMessageLongTime");
}
export function getEggGachaTypeDescriptor(scene: BattleScene, egg: Egg): string {
switch (egg.gachaType) {
case GachaType.LEGENDARY:
return `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, egg.timestamp)).getName()})`;
case GachaType.MOVE:
return i18next.t("egg:gachaTypeMove");
case GachaType.SHINY:
return i18next.t("egg:gachaTypeShiny");
}
}
export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timestamp: integer): Species {
const legendarySpecies = Object.entries(speciesStarters) const legendarySpecies = Object.entries(speciesStarters)
.filter(s => s[1] >= 8 && s[1] <= 9) .filter(s => s[1] >= 8 && s[1] <= 9)
.map(s => parseInt(s[0])) .map(s => parseInt(s[0]))

View File

@ -1,7 +1,7 @@
import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims"; import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
import { BattleEndPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../phases"; import { BattleEndPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../phases";
import { BattleStat, getBattleStatName } from "./battle-stat"; import { BattleStat, getBattleStatName } from "./battle-stat";
import { EncoreTag } from "./battler-tags"; import { EncoreTag, SemiInvulnerableTag } from "./battler-tags";
import { getPokemonMessage, getPokemonNameWithAffix } from "../messages"; import { getPokemonMessage, getPokemonNameWithAffix } from "../messages";
import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon"; import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon";
import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects} from "./status-effect"; import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects} from "./status-effect";
@ -3662,10 +3662,9 @@ export class NeutralDamageAgainstFlyingTypeMultiplierAttr extends VariableMoveTy
if (!target.getTag(BattlerTagType.IGNORE_FLYING)) { if (!target.getTag(BattlerTagType.IGNORE_FLYING)) {
const multiplier = args[0] as Utils.NumberHolder; const multiplier = args[0] as Utils.NumberHolder;
//When a flying type is hit, the first hit is always 1x multiplier. Levitating pokemon are instantly affected by typing //When a flying type is hit, the first hit is always 1x multiplier. Levitating pokemon are instantly affected by typing
if (target.isOfType(Type.FLYING)) { if (target.isOfType(Type.FLYING) || target.hasAbility(Abilities.LEVITATE)) {
multiplier.value = 1; multiplier.value = 1;
} }
target.addTag(BattlerTagType.IGNORE_FLYING, 20, move.id, user.id); //TODO: Grounded effect should not have turn limit
return true; return true;
} }
@ -3964,6 +3963,8 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
return -3; return -3;
case BattlerTagType.ENCORE: case BattlerTagType.ENCORE:
return -2; return -2;
case BattlerTagType.MINIMIZED:
return 0;
case BattlerTagType.INGRAIN: case BattlerTagType.INGRAIN:
case BattlerTagType.IGNORE_ACCURACY: case BattlerTagType.IGNORE_ACCURACY:
case BattlerTagType.AQUA_RING: case BattlerTagType.AQUA_RING:
@ -3990,7 +3991,7 @@ export class CurseAttr extends MoveEffectAttr {
apply(user: Pokemon, target: Pokemon, move:Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move:Move, args: any[]): boolean {
if (user.getTypes(true).includes(Type.GHOST)) { if (user.getTypes(true).includes(Type.GHOST)) {
if (target.getTag(BattlerTagType.CURSED)) { if (target.getTag(BattlerTagType.CURSED)) {
user.scene.queueMessage("But it failed!"); user.scene.queueMessage(i18next.t("battle:attackFailed"));
return false; return false;
} }
const curseRecoilDamage = Math.max(1, Math.floor(user.getMaxHp() / 2)); const curseRecoilDamage = Math.max(1, Math.floor(user.getMaxHp() / 2));
@ -4447,7 +4448,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
} }
resolve(true); resolve(true);
} else { } else {
user.scene.queueMessage("But it failed!"); user.scene.queueMessage(i18next.t("battle:attackFailed"));
resolve(false); resolve(false);
} }
}); });
@ -5290,7 +5291,16 @@ export class SwitchAbilitiesAttr extends MoveEffectAttr {
} }
} }
/**
* Attribute used for moves that suppress abilities like {@linkcode Moves.GASTRO_ACID}.
* A suppressed ability cannot be activated.
*
* @extends MoveEffectAttr
* @see {@linkcode apply}
* @see {@linkcode getCondition}
*/
export class SuppressAbilitiesAttr extends MoveEffectAttr { export class SuppressAbilitiesAttr extends MoveEffectAttr {
/** Sets ability suppression for the target pokemon and displays a message. */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args)) { if (!super.apply(user, target, move, args)) {
return false; return false;
@ -5303,8 +5313,9 @@ export class SuppressAbilitiesAttr extends MoveEffectAttr {
return true; return true;
} }
/** Causes the effect to fail when the target's ability is unsupressable or already suppressed. */
getCondition(): MoveConditionFunc { getCondition(): MoveConditionFunc {
return (user, target, move) => !target.getAbility().hasAttr(UnsuppressableAbilityAbAttr); return (user, target, move) => !target.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !target.summonData.abilitySuppressed;
} }
} }
@ -5319,7 +5330,7 @@ export class SuppressAbilitiesIfActedAttr extends MoveEffectAttr {
* abillity cannot be suppressed. This is a secondary effect and has no bearing on the success or failure of the move. * abillity cannot be suppressed. This is a secondary effect and has no bearing on the success or failure of the move.
* *
* @returns True if the move occurred, otherwise false. Note that true will be returned even if the target has not * @returns True if the move occurred, otherwise false. Note that true will be returned even if the target has not
* yet moved or if the target's abiilty is un-suppressable. * yet moved or if the suppression failed to apply.
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args)) { if (!super.apply(user, target, move, args)) {
@ -6595,7 +6606,7 @@ export function initMoves() {
.attr(StatChangeAttr, BattleStat.SPATK, -2, true), .attr(StatChangeAttr, BattleStat.SPATK, -2, true),
new SelfStatusMove(Moves.ROOST, Type.FLYING, -1, 5, -1, 0, 4) new SelfStatusMove(Moves.ROOST, Type.FLYING, -1, 5, -1, 0, 4)
.attr(HealAttr, 0.5) .attr(HealAttr, 0.5)
.attr(AddBattlerTagAttr, BattlerTagType.GROUNDED, true, false, 1) .attr(AddBattlerTagAttr, BattlerTagType.ROOSTED, true, false)
.triageMove(), .triageMove(),
new StatusMove(Moves.GRAVITY, Type.PSYCHIC, -1, 5, -1, 0, 4) new StatusMove(Moves.GRAVITY, Type.PSYCHIC, -1, 5, -1, 0, 4)
.attr(AddArenaTagAttr, ArenaTagType.GRAVITY, 5) .attr(AddArenaTagAttr, ArenaTagType.GRAVITY, 5)
@ -6936,7 +6947,7 @@ export function initMoves() {
.target(MoveTarget.BOTH_SIDES) .target(MoveTarget.BOTH_SIDES)
.unimplemented(), .unimplemented(),
new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5) new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5)
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 5) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false)
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
.attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN]) .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN])
.attr(HitsTagAttr, BattlerTagType.FLYING, false) .attr(HitsTagAttr, BattlerTagType.FLYING, false)
@ -7227,7 +7238,7 @@ export function initMoves() {
.attr(AddArenaTagAttr, ArenaTagType.CRAFTY_SHIELD, 1, true, true), .attr(AddArenaTagAttr, ArenaTagType.CRAFTY_SHIELD, 1, true, true),
new StatusMove(Moves.FLOWER_SHIELD, Type.FAIRY, -1, 10, -1, 0, 6) new StatusMove(Moves.FLOWER_SHIELD, Type.FAIRY, -1, 10, -1, 0, 6)
.target(MoveTarget.ALL) .target(MoveTarget.ALL)
.unimplemented(), .attr(StatChangeAttr, BattleStat.DEF, 1, false, (user, target, move) => target.getTypes().includes(Type.GRASS) && !target.getTag(SemiInvulnerableTag)),
new StatusMove(Moves.GRASSY_TERRAIN, Type.GRASS, -1, 10, -1, 0, 6) new StatusMove(Moves.GRASSY_TERRAIN, Type.GRASS, -1, 10, -1, 0, 6)
.attr(TerrainChangeAttr, TerrainType.GRASSY) .attr(TerrainChangeAttr, TerrainType.GRASSY)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),
@ -7293,8 +7304,8 @@ export function initMoves() {
.target(MoveTarget.USER_AND_ALLIES) .target(MoveTarget.USER_AND_ALLIES)
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => p.hasAbility(a, false)))), .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => p.hasAbility(a, false)))),
new StatusMove(Moves.HAPPY_HOUR, Type.NORMAL, -1, 30, -1, 0, 6) // No animation new StatusMove(Moves.HAPPY_HOUR, Type.NORMAL, -1, 30, -1, 0, 6) // No animation
.target(MoveTarget.USER_SIDE) .attr(AddArenaTagAttr, ArenaTagType.HAPPY_HOUR, null, true)
.unimplemented(), .target(MoveTarget.USER_SIDE),
new StatusMove(Moves.ELECTRIC_TERRAIN, Type.ELECTRIC, -1, 10, -1, 0, 6) new StatusMove(Moves.ELECTRIC_TERRAIN, Type.ELECTRIC, -1, 10, -1, 0, 6)
.attr(TerrainChangeAttr, TerrainType.ELECTRIC) .attr(TerrainChangeAttr, TerrainType.ELECTRIC)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),
@ -7320,6 +7331,7 @@ export function initMoves() {
.triageMove(), .triageMove(),
new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr) .attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false)
.attr(HitsTagAttr, BattlerTagType.FLYING, false) .attr(HitsTagAttr, BattlerTagType.FLYING, false)
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
.attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN]) .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN])
@ -8003,6 +8015,7 @@ export function initMoves() {
new AttackMove(Moves.CHLOROBLAST, Type.GRASS, MoveCategory.SPECIAL, 150, 95, 5, -1, 0, 8) new AttackMove(Moves.CHLOROBLAST, Type.GRASS, MoveCategory.SPECIAL, 150, 95, 5, -1, 0, 8)
.attr(RecoilAttr, true, 0.5), .attr(RecoilAttr, true, 0.5),
new AttackMove(Moves.MOUNTAIN_GALE, Type.ICE, MoveCategory.PHYSICAL, 100, 85, 10, 30, 0, 8) new AttackMove(Moves.MOUNTAIN_GALE, Type.ICE, MoveCategory.PHYSICAL, 100, 85, 10, 30, 0, 8)
.makesContact(false)
.attr(FlinchAttr), .attr(FlinchAttr),
new SelfStatusMove(Moves.VICTORY_DANCE, Type.FIGHTING, -1, 10, -1, 0, 8) new SelfStatusMove(Moves.VICTORY_DANCE, Type.FIGHTING, -1, 10, -1, 0, 8)
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPD ], 1, true) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPD ], 1, true)

View File

@ -819,6 +819,10 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
return super.isObtainable(); return super.isObtainable();
} }
hasVariants() {
return variantData.hasOwnProperty(this.speciesId);
}
getFormSpriteKey(formIndex?: integer) { getFormSpriteKey(formIndex?: integer) {
if (this.forms.length && formIndex >= this.forms.length) { if (this.forms.length && formIndex >= this.forms.length) {
console.warn(`Attempted accessing form with index ${formIndex} of species ${this.getName()} with only ${this.forms.length || 0} forms`); console.warn(`Attempted accessing form with index ${formIndex} of species ${this.getName()} with only ${this.forms.length || 0} forms`);

File diff suppressed because it is too large Load Diff

View File

@ -531,13 +531,18 @@ export class TrainerConfig {
* Initializes the trainer configuration for an evil team leader. Temporarily hardcoding evil leader teams though. * Initializes the trainer configuration for an evil team leader. Temporarily hardcoding evil leader teams though.
* @param {Species | Species[]} signatureSpecies - The signature species for the evil team leader. * @param {Species | Species[]} signatureSpecies - The signature species for the evil team leader.
* @param {Type[]} specialtyTypes - The specialty types for the evil team Leader. * @param {Type[]} specialtyTypes - The specialty types for the evil team Leader.
* @param boolean whether or not this is the rematch fight
* @returns {TrainerConfig} - The updated TrainerConfig instance. * @returns {TrainerConfig} - The updated TrainerConfig instance.
* **/ * **/
initForEvilTeamLeader(title: string, signatureSpecies: (Species | Species[])[], ...specialtyTypes: Type[]): TrainerConfig { initForEvilTeamLeader(title: string, signatureSpecies: (Species | Species[])[], rematch: boolean = false, ...specialtyTypes: Type[]): TrainerConfig {
if (!getIsInitialized()) { if (!getIsInitialized()) {
initI18n(); initI18n();
} }
this.setPartyTemplates(trainerPartyTemplates.RIVAL_5); if (rematch) {
this.setPartyTemplates(trainerPartyTemplates.ELITE_FOUR);
} else {
this.setPartyTemplates(trainerPartyTemplates.RIVAL_5);
}
signatureSpecies.forEach((speciesPool, s) => { signatureSpecies.forEach((speciesPool, s) => {
if (!Array.isArray(speciesPool)) { if (!Array.isArray(speciesPool)) {
speciesPool = [speciesPool]; speciesPool = [speciesPool];
@ -551,11 +556,11 @@ export class TrainerConfig {
const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); const nameForCall = this.name.toLowerCase().replace(/\s/g, "_");
this.name = i18next.t(`trainerNames:${nameForCall}`); this.name = i18next.t(`trainerNames:${nameForCall}`);
this.setTitle(title); this.setTitle(title);
this.setMoneyMultiplier(2.5); this.setMoneyMultiplier(2.25);
this.setBoss(); this.setBoss();
this.setStaticParty(); this.setStaticParty();
this.setBattleBgm("battle_unova_gym"); // TODO: change this.setBattleBgm("battle_plasma_boss");
this.setVictoryBgm("victory_gym"); // TODO: change this.setVictoryBgm("victory_team_plasma");
return this; return this;
} }
@ -814,7 +819,7 @@ interface TrainerConfigs {
} }
/** /**
* The function to get variable strength grutns * The function to get variable strength grunts
* @param scene the singleton scene being passed in * @param scene the singleton scene being passed in
* @returns the correct TrainerPartyTemplate * @returns the correct TrainerPartyTemplate
*/ */
@ -822,22 +827,14 @@ function getEvilGruntPartyTemplate(scene: BattleScene): TrainerPartyTemplate {
const waveIndex = scene.currentBattle?.waveIndex; const waveIndex = scene.currentBattle?.waveIndex;
if (waveIndex < 40) { if (waveIndex < 40) {
return trainerPartyTemplates.TWO_AVG; return trainerPartyTemplates.TWO_AVG;
} else if (waveIndex < 80) { } else if (waveIndex < 63) {
switch (waveIndex) { return trainerPartyTemplates.THREE_AVG;
case 62: } else if (waveIndex < 65) {
return trainerPartyTemplates.THREE_AVG; return trainerPartyTemplates.TWO_AVG_ONE_STRONG;
case 64: } else if (waveIndex < 112) {
return trainerPartyTemplates.TWO_AVG_ONE_STRONG; return trainerPartyTemplates.GYM_LEADER_4; // 3avg 1 strong 1 stronger
case 65:
return trainerPartyTemplates.GYM_LEADER_4; // 3avg 1 strong 1 stronger
}
} else { } else {
switch (waveIndex) { return trainerPartyTemplates.GYM_LEADER_5; // 3 avg 2 strong 1 stronger
case 112:
return trainerPartyTemplates.GYM_LEADER_4; // 3avg 1 strong 1 stronger
case 114:
return trainerPartyTemplates.GYM_LEADER_5; // 3 avg 2 strong 1 stronger
}
} }
} }
@ -1183,53 +1180,47 @@ export const trainerConfigs: TrainerConfigs = {
.setSpeciesPools( .setSpeciesPools(
[Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP] [Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP]
), ),
[TrainerType.ROCKET_GRUNT]: new TrainerConfig(++t).setHasGenders("Rocket Grunt Female").setHasDouble("Rocket Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) [TrainerType.ROCKET_GRUNT]: new TrainerConfig(++t).setHasGenders("Rocket Grunt Female").setHasDouble("Rocket Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
.setSpeciesPools({ .setSpeciesPools({
[TrainerPoolTier.COMMON]: [ Species.WEEDLE, Species.RATTATA, Species.EKANS, Species.SANDSHREW, Species.ZUBAT, Species.GEODUDE, Species.KOFFING], [TrainerPoolTier.COMMON]: [ Species.WEEDLE, Species.RATTATA, Species.EKANS, Species.SANDSHREW, Species.ZUBAT, Species.GEODUDE, Species.KOFFING, Species.GRIMER, Species.ODDISH],
[TrainerPoolTier.UNCOMMON]: [Species.GRIMER, Species.CUBONE, Species.ODDISH, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB], [TrainerPoolTier.UNCOMMON]: [ Species.GYARADOS, Species.TAUROS, Species.SCYTHER, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB],
[TrainerPoolTier.RARE]: [Species.GYARADOS, Species.TAUROS, Species.SCYTHER], [TrainerPoolTier.RARE]: [Species.PORYGON, Species.ALOLA_RATTATA, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE],
[TrainerPoolTier.SUPER_RARE]: [Species.PORYGON, Species.ALOLA_RATTATA, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE], [TrainerPoolTier.SUPER_RARE]: [Species.DRATINI, Species.LARVITAR]
[TrainerPoolTier.ULTRA_RARE]: [Species.DRATINI, Species.LARVITAR]
}), }),
[TrainerType.MAGMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Magma Grunt Female").setHasDouble("Magma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) [TrainerType.MAGMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Magma Grunt Female").setHasDouble("Magma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
.setSpeciesPools({ .setSpeciesPools({
[TrainerPoolTier.COMMON]: [Species.SLUGMA, Species.POOCHYENA, Species.NUMEL, Species.ZIGZAGOON, Species.DIGLETT, Species.MAGBY], [TrainerPoolTier.COMMON]: [Species.SLUGMA, Species.POOCHYENA, Species.NUMEL, Species.ZIGZAGOON, Species.DIGLETT, Species.MAGBY, Species.TORKOAL, Species.BALTOY, Species.BARBOACH],
[TrainerPoolTier.UNCOMMON]: [Species.PHANPY, Species.SWINUB, Species.GLIGAR, Species.TORKOAL, Species.BALTOY, Species.BARBOACH], [TrainerPoolTier.UNCOMMON]: [Species.SOLROCK, Species.HIPPOPOTAS, Species.SANDACONDA, Species.PHANPY, Species.SWINUB, Species.GLIGAR],
[TrainerPoolTier.RARE]: [Species.SOLROCK, Species.HIPPOPOTAS, Species.SANDACONDA], [TrainerPoolTier.RARE]: [Species.TRAPINCH, Species.HEATMOR],
[TrainerPoolTier.SUPER_RARE]: [Species.TRAPINCH, Species.HEATMOR], [TrainerPoolTier.SUPER_RARE]: [Species.TURTONATOR, Species.CHARCADET]
[TrainerPoolTier.ULTRA_RARE]: [Species.TURTONATOR, Species.CHARCADET]
}), }),
[TrainerType.AQUA_GRUNT]: new TrainerConfig(++t).setHasGenders("Aqua Grunt Female").setHasDouble("Aqua Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) [TrainerType.AQUA_GRUNT]: new TrainerConfig(++t).setHasGenders("Aqua Grunt Female").setHasDouble("Aqua Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
.setSpeciesPools({ .setSpeciesPools({
[TrainerPoolTier.COMMON]: [ Species.CARVANHA, Species.WAILMER, Species.ZIGZAGOON, Species.LOTAD, Species.CORPHISH], [TrainerPoolTier.COMMON]: [ Species.CARVANHA, Species.WAILMER, Species.ZIGZAGOON, Species.LOTAD, Species.CORPHISH, Species.SPHEAL ],
[TrainerPoolTier.UNCOMMON]: [Species.SPHEAL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL ], [TrainerPoolTier.UNCOMMON]: [Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.QWILFISH ],
[TrainerPoolTier.RARE]: [Species.CLAMPERL, Species.REMORAID, Species.ARROKUDA], [TrainerPoolTier.RARE]: [Species.MANTINE, Species.BASCULEGION, Species.REMORAID, Species.ARROKUDA],
[TrainerPoolTier.SUPER_RARE]: [Species.MANTINE, Species.BASCULEGION], [TrainerPoolTier.SUPER_RARE]: [Species.DONDOZO]
[TrainerPoolTier.ULTRA_RARE]: [Species.DONDOZO]
}), }),
[TrainerType.GALACTIC_GRUNT]: new TrainerConfig(++t).setHasGenders("Galactic Grunt Female").setHasDouble("Galactic Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) [TrainerType.GALACTIC_GRUNT]: new TrainerConfig(++t).setHasGenders("Galactic Grunt Female").setHasDouble("Galactic Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
.setSpeciesPools({ .setSpeciesPools({
[TrainerPoolTier.COMMON]: [ Species.GLAMEOW, Species.STUNKY, Species.CROAGUNK, Species.SHINX, Species.WURMPLE], [TrainerPoolTier.COMMON]: [ Species.GLAMEOW, Species.STUNKY, Species.CROAGUNK, Species.SHINX, Species.WURMPLE, Species.BRONZOR, Species.DRIFLOON, Species.BURMY],
[TrainerPoolTier.UNCOMMON]: [Species.BRONZOR, Species.DRIFLOON, Species.BURMY], [TrainerPoolTier.UNCOMMON]: [ Species.CARNIVINE, Species.GROWLITHE, Species.QWILFISH, Species.SNEASEL ],
[TrainerPoolTier.RARE]: [Species.CARNIVINE], [TrainerPoolTier.RARE]: [Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.HISUI_SNEASEL],
[TrainerPoolTier.SUPER_RARE]: [Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.HISUI_SNEASEL], [TrainerPoolTier.SUPER_RARE]: [Species.HISUI_ZORUA, Species.HISUI_SLIGGOO]
[TrainerPoolTier.ULTRA_RARE]: [Species.HISUI_ZORUA, Species.HISUI_SLIGGOO]
}), }),
[TrainerType.PLASMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Plasma Grunt Female").setHasDouble("Plasma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) [TrainerType.PLASMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Plasma Grunt Female").setHasDouble("Plasma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
.setSpeciesPools({ .setSpeciesPools({
[TrainerPoolTier.COMMON]: [ Species.PATRAT, Species.LILLIPUP, Species.PURRLOIN, Species.SCRAFTY, Species.WOOBAT, Species.VANILLITE], [TrainerPoolTier.COMMON]: [ Species.PATRAT, Species.LILLIPUP, Species.PURRLOIN, Species.SCRAFTY, Species.WOOBAT, Species.VANILLITE, Species.SANDILE, Species.TRUBBISH],
[TrainerPoolTier.UNCOMMON]: [ Species.FRILLISH, Species.VENIPEDE, Species.SANDILE, Species.TRUBBISH, Species.GOLETT], [TrainerPoolTier.UNCOMMON]: [ Species.FRILLISH, Species.VENIPEDE, Species.GOLETT, Species.TIMBURR, Species.DARUMAKA, Species.AMOONGUSS],
[TrainerPoolTier.RARE]: [Species.TIMBURR, Species.DARUMAKA, Species.AMOONGUSS, Species.DRILBUR, Species.KLINK, Species.VULLABY], [TrainerPoolTier.RARE]: [Species.PAWNIARD, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.KLINK],
[TrainerPoolTier.SUPER_RARE]: [Species.PAWNIARD, Species.VULLABY, Species.DRUDDIGON, Species.BOUFFALANT, Species.ZORUA], [TrainerPoolTier.SUPER_RARE]: [Species.DRUDDIGON, Species.BOUFFALANT, Species.AXEW, Species.DEINO, Species.DURANT]
[TrainerPoolTier.ULTRA_RARE]: [Species.AXEW, Species.DEINO, Species.DURANT]
}), }),
[TrainerType.FLARE_GRUNT]: new TrainerConfig(++t).setHasGenders("Flare Grunt Female").setHasDouble("Flare Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) [TrainerType.FLARE_GRUNT]: new TrainerConfig(++t).setHasGenders("Flare Grunt Female").setHasDouble("Flare Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
.setSpeciesPools({ .setSpeciesPools({
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI], [TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI, Species.SCRAFTY, Species.CROAGUNK],
[TrainerPoolTier.UNCOMMON]: [Species.HELIOPTILE, Species.ELECTRIKE, Species.SKRELP, Species.GULPIN], [TrainerPoolTier.UNCOMMON]: [Species.HELIOPTILE, Species.ELECTRIKE, Species.SKRELP, Species.GULPIN, Species.PURRLOIN, Species.POOCHYENA, Species.SCATTERBUG],
[TrainerPoolTier.RARE]: [Species.LITWICK, Species.SNEASEL], [TrainerPoolTier.RARE]: [Species.LITWICK, Species.SNEASEL, Species.PANCHAM, Species.PAWNIARD],
[TrainerPoolTier.SUPER_RARE]: [Species.NOIVERN], [TrainerPoolTier.SUPER_RARE]: [Species.NOIVERN, Species.DRUDDIGON]
[TrainerPoolTier.ULTRA_RARE]: []
}), }),
[TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(signatureSpecies["BROCK"],true, Type.ROCK).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), [TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(signatureSpecies["BROCK"],true, Type.ROCK).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MISTY"],false, Type.WATER).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), [TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MISTY"],false, Type.WATER).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
@ -1509,7 +1500,7 @@ export const trainerConfigs: TrainerConfigs = {
return [modifierTypes.TERA_SHARD().generateType(null, [starter.species.type1]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier]; return [modifierTypes.TERA_SHARD().generateType(null, [starter.species.type1]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier];
}), }),
[TrainerType.ROCKET_BOSS_GIOVANNI_1]: new TrainerConfig(t = TrainerType.ROCKET_BOSS_GIOVANNI_1).setName("Giovanni").initForEvilTeamLeader("Rocket Boss",[]) [TrainerType.ROCKET_BOSS_GIOVANNI_1]: new TrainerConfig(t = TrainerType.ROCKET_BOSS_GIOVANNI_1).setName("Giovanni").initForEvilTeamLeader("Rocket Boss",[]).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN , Species.ALOLA_PERSIAN])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN , Species.ALOLA_PERSIAN]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.NIDOKING , Species.NIDOQUEEN ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.NIDOKING , Species.NIDOQUEEN ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.RHYPERIOR ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.RHYPERIOR ]))
@ -1521,14 +1512,14 @@ export const trainerConfigs: TrainerConfigs = {
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = 1; p.formIndex = 1;
})), })),
[TrainerType.ROCKET_BOSS_GIOVANNI_2]: new TrainerConfig(++t).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", []) [TrainerType.ROCKET_BOSS_GIOVANNI_2]: new TrainerConfig(++t).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", [], true).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.TYRANITAR , Species.IRON_THORNS], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.TYRANITAR , Species.IRON_THORNS], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
})) }))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.EXCADRILL ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HIPPOWDON ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HIPPOWDON ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.EXCADRILL ]))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
@ -1541,7 +1532,7 @@ export const trainerConfigs: TrainerConfigs = {
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL; p.pokeball = PokeballType.MASTER_BALL;
})), })),
[TrainerType.MAXIE]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss",[]) [TrainerType.MAXIE]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss",[]).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.MIGHTYENA ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.MIGHTYENA ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.GLISCOR ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.GLISCOR ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WEEZING, Species.GALAR_WEEZING ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WEEZING, Species.GALAR_WEEZING ]))
@ -1553,33 +1544,33 @@ export const trainerConfigs: TrainerConfigs = {
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = 1; p.formIndex = 1;
})), })),
[TrainerType.MAXIE_2]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss",[]) [TrainerType.MAXIE_2]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss",[], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SOLROCK, Species.HOUNDOOM ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SOLROCK, Species.TYPHLOSION ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
})) }))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GREAT_TUSK ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.TORKOAL, Species.NINETALES ], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
p.abilityIndex = 2; // DROUGHT
}))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SHIFTRY, Species.SCOVILLAIN ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SHIFTRY, Species.SCOVILLAIN ], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.abilityIndex = 0; // Chlorophyll p.abilityIndex = 0; // Chlorophyll
})) }))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TORKOAL, Species.NINETALES ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GREAT_TUSK ]))
p.generateAndPopulateMoveset(); .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.CAMERUPT ], TrainerSlot.TRAINER, true, p => {
p.abilityIndex = 2; // DROUGHT
}))
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GROUDON ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL;
}))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.CAMERUPT ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = 1; p.formIndex = 1;
}))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GROUDON ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL;
})), })),
[TrainerType.ARCHIE]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss",[]) [TrainerType.ARCHIE]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss",[]).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LINOONE ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LINOONE ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.PELIPPER ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.PELIPPER ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MUK, Species.ALOLA_MUK ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MUK, Species.ALOLA_MUK ]))
@ -1591,36 +1582,36 @@ export const trainerConfigs: TrainerConfigs = {
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = 1; p.formIndex = 1;
})), })),
[TrainerType.ARCHIE_2]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss",[]) [TrainerType.ARCHIE_2]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss",[], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.KINGDRA, Species.LUDICOLO ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.KINGDRA, Species.LUDICOLO ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
})) }))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BEARTIC, Species.ARMALDO ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.POLITOED, Species.PELIPPER ], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
p.abilityIndex = 2; // Swift Swim
}))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HUNTAIL, Species.GOREBYSS ], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
p.abilityIndex = 0; // Swift Swim
}))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.POLITOED, Species.PELIPPER ], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.abilityIndex = 2; // Drizzle p.abilityIndex = 2; // Drizzle
})) }))
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KYOGRE ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.BEARTIC, Species.ARMALDO ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL; p.abilityIndex = 2; // Swift Swim
})) }))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.SHARPEDO ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.HUNTAIL, Species.GOREBYSS ], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
p.abilityIndex = 0; // Swift Swim
}))
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SHARPEDO ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = 1; p.formIndex = 1;
}))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KYOGRE ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL;
})), })),
[TrainerType.CYRUS]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss",[]) [TrainerType.CYRUS]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss",[]).setMixedBattleBgm("battle_galactic_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GYARADOS, Species.BASCULEGION ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GYARADOS, Species.BASCULEGION ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HONCHKROW, Species.HISUI_BRAVIARY ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HONCHKROW, Species.HISUI_BRAVIARY ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CROBAT, Species.OVERQWIL ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CROBAT, Species.OVERQWIL ]))
@ -1635,25 +1626,29 @@ export const trainerConfigs: TrainerConfigs = {
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
})), })),
[TrainerType.CYRUS_2]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss",[]) [TrainerType.CYRUS_2]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss",[], true).setMixedBattleBgm("battle_galactic_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
})) }))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ELECTRODE, Species.HISUI_ELECTRODE ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ELECTRODE, Species.HISUI_ELECTRODE ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SALAMENCE, Species.ROARING_MOON ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SALAMENCE, Species.ROARING_MOON ]))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.HISUI_ZOROARK ])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.HOUNDOOM ], TrainerSlot.TRAINER, true, p => {
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.DARKRAI ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = 1;
})) }))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.WEAVILE ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.WEAVILE ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
}))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DARKRAI ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL;
})), })),
[TrainerType.GHETSIS]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss",[]) [TrainerType.GHETSIS]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss",[]).setMixedBattleBgm("battle_plasma_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.COFAGRIGUS, Species.RUNERIGUS ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.COFAGRIGUS, Species.RUNERIGUS ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BOUFFALANT ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BOUFFALANT ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SEISMITOAD, Species.CARRACOSTA ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SEISMITOAD, Species.CARRACOSTA ]))
@ -1664,7 +1659,7 @@ export const trainerConfigs: TrainerConfigs = {
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
})), })),
[TrainerType.GHETSIS_2]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss",[]) [TrainerType.GHETSIS_2]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss",[], true).setMixedBattleBgm("battle_plasma_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SLITHER_WING, Species.IRON_MOTH ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SLITHER_WING, Species.IRON_MOTH ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
@ -1673,17 +1668,17 @@ export const trainerConfigs: TrainerConfigs = {
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DURANT ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DURANT ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.DARMANITAN, Species.GALAR_DARMANITAN ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.DARMANITAN, Species.GALAR_DARMANITAN ]))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KINGAMBIT ])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KINGAMBIT ]))
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KYUREM ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.HYDREIGON, Species.IRON_JUGULIS ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL;
}))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.HYDREIGON, Species.IRON_JUGULIS ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
}))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KYUREM ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL;
})), })),
[TrainerType.LYSANDRE]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss",[]) [TrainerType.LYSANDRE]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss",[]).setMixedBattleBgm("battle_flare_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.MIENSHAO ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.MIENSHAO ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HONCHKROW, Species.TALONFLAME ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HONCHKROW, Species.TALONFLAME ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.PYROAR ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.PYROAR ]))
@ -1695,7 +1690,7 @@ export const trainerConfigs: TrainerConfigs = {
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = 1; p.formIndex = 1;
})), })),
[TrainerType.LYSANDRE_2]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss",[]) [TrainerType.LYSANDRE_2]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss",[], true).setMixedBattleBgm("battle_flare_boss").setVictoryBgm("victory_team_plasma")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SCREAM_TAIL, Species.FLUTTER_MANE ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SCREAM_TAIL, Species.FLUTTER_MANE ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
@ -1704,15 +1699,15 @@ export const trainerConfigs: TrainerConfigs = {
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GHOLDENGO, Species.AEGISLASH ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GHOLDENGO, Species.AEGISLASH ]))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.PYROAR ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.PYROAR ]))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GOODRA, Species.HISUI_GOODRA ])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GOODRA, Species.HISUI_GOODRA ]))
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.YVELTAL ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GYARADOS ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL;
}))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GYARADOS ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = 1; p.formIndex = 1;
}))
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.YVELTAL ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.generateAndPopulateMoveset();
p.pokeball = PokeballType.MASTER_BALL;
})), })),
}; };

View File

@ -1,19 +1,16 @@
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import i18next from "i18next";
import { Phase } from "./phase"; import { Phase } from "./phase";
import BattleScene, { AnySound } from "./battle-scene"; import BattleScene, { AnySound } from "./battle-scene";
import * as Utils from "./utils"; import * as Utils from "./utils";
import { Mode } from "./ui/ui"; import { Mode } from "./ui/ui";
import { EGG_SEED, Egg, GachaType, getLegendaryGachaSpeciesForTimestamp } from "./data/egg"; import { EGG_SEED, Egg } from "./data/egg";
import EggHatchSceneHandler from "./ui/egg-hatch-scene-handler"; import EggHatchSceneHandler from "./ui/egg-hatch-scene-handler";
import { PlayerPokemon } from "./field/pokemon"; import { PlayerPokemon } from "./field/pokemon";
import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species";
import { achvs } from "./system/achv"; import { achvs } from "./system/achv";
import { pokemonPrevolutions } from "./data/pokemon-evolutions";
import PokemonInfoContainer from "./ui/pokemon-info-container"; import PokemonInfoContainer from "./ui/pokemon-info-container";
import EggCounterContainer from "./ui/egg-counter-container"; import EggCounterContainer from "./ui/egg-counter-container";
import { EggCountChangedEvent } from "./events/egg"; import { EggCountChangedEvent } from "./events/egg";
import { EggTier } from "#enums/egg-type";
import { Species } from "#enums/species";
/** /**
* Class that represents egg hatching * Class that represents egg hatching
@ -345,7 +342,7 @@ export class EggHatchPhase extends Phase {
this.scene.playSoundWithoutBgm("evolution_fanfare"); this.scene.playSoundWithoutBgm("evolution_fanfare");
this.scene.ui.showText(`${this.pokemon.name} hatched from the egg!`, null, () => { this.scene.ui.showText(i18next.t("egg:hatchFromTheEgg", { pokemonName: this.pokemon.name }), null, () => {
this.scene.gameData.updateSpeciesDexIvs(this.pokemon.species.speciesId, this.pokemon.ivs); this.scene.gameData.updateSpeciesDexIvs(this.pokemon.species.speciesId, this.pokemon.ivs);
this.scene.gameData.setPokemonCaught(this.pokemon, true, true).then(() => { this.scene.gameData.setPokemonCaught(this.pokemon, true, true).then(() => {
this.scene.gameData.setEggMoveUnlocked(this.pokemon.species, this.eggMoveIndex).then(() => { this.scene.gameData.setEggMoveUnlocked(this.pokemon.species, this.eggMoveIndex).then(() => {
@ -442,135 +439,10 @@ export class EggHatchPhase extends Phase {
*/ */
generatePokemon(): PlayerPokemon { generatePokemon(): PlayerPokemon {
let ret: PlayerPokemon; let ret: PlayerPokemon;
let speciesOverride: Species; // SpeciesOverride should probably be a passed in parameter for future species-eggs
this.scene.executeWithSeedOffset(() => { this.scene.executeWithSeedOffset(() => {
ret = this.egg.generatePlayerPokemon(this.scene);
/** this.eggMoveIndex = this.egg.eggMoveIndex;
* Manaphy eggs have a 1/8 chance of being Manaphy and 7/8 chance of being Phione
* Legendary eggs pulled from the legendary gacha have a 50% of being converted into
* the species that was the legendary focus at the time
*/
if (this.egg.isManaphyEgg()) {
const rand = Utils.randSeedInt(8);
speciesOverride = rand ? Species.PHIONE : Species.MANAPHY;
} else if (this.egg.tier === EggTier.MASTER
&& this.egg.gachaType === GachaType.LEGENDARY) {
if (!Utils.randSeedInt(2)) {
speciesOverride = getLegendaryGachaSpeciesForTimestamp(this.scene, this.egg.timestamp);
}
}
if (speciesOverride) {
const pokemonSpecies = getPokemonSpecies(speciesOverride);
ret = this.scene.addPlayerPokemon(pokemonSpecies, 1, undefined, undefined, undefined, false);
} else {
let minStarterValue: integer;
let maxStarterValue: integer;
switch (this.egg.tier) {
case EggTier.GREAT:
minStarterValue = 4;
maxStarterValue = 5;
break;
case EggTier.ULTRA:
minStarterValue = 6;
maxStarterValue = 7;
break;
case EggTier.MASTER:
minStarterValue = 8;
maxStarterValue = 9;
break;
default:
minStarterValue = 1;
maxStarterValue = 3;
break;
}
const ignoredSpecies = [ Species.PHIONE, Species.MANAPHY, Species.ETERNATUS ];
let speciesPool = Object.keys(speciesStarters)
.filter(s => speciesStarters[s] >= minStarterValue && speciesStarters[s] <= maxStarterValue)
.map(s => parseInt(s) as Species)
.filter(s => !pokemonPrevolutions.hasOwnProperty(s) && getPokemonSpecies(s).isObtainable() && ignoredSpecies.indexOf(s) === -1);
// If this is the 10th egg without unlocking something new, attempt to force it.
if (this.scene.gameData.unlockPity[this.egg.tier] >= 9) {
const lockedPool = speciesPool.filter(s => !this.scene.gameData.dexData[s].caughtAttr);
if (lockedPool.length) { // Skip this if everything is unlocked
speciesPool = lockedPool;
}
}
/**
* Pokemon that are cheaper in their tier get a weight boost. Regionals get a weight penalty
* 1 cost mons get 2x
* 2 cost mons get 1.5x
* 4, 6, 8 cost mons get 1.75x
* 3, 5, 7, 9 cost mons get 1x
* Alolan, Galarian, and Paldean mons get 0.5x
* Hisui mons get 0.125x
*
* The total weight is also being calculated EACH time there is an egg hatch instead of being generated once
* and being the same each time
*/
let totalWeight = 0;
const speciesWeights = [];
for (const speciesId of speciesPool) {
let weight = Math.floor((((maxStarterValue - speciesStarters[speciesId]) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100);
const species = getPokemonSpecies(speciesId);
if (species.isRegional()) {
weight = Math.floor(weight / (species.isRareRegional() ? 8 : 2));
}
speciesWeights.push(totalWeight + weight);
totalWeight += weight;
}
let species: Species;
const rand = Utils.randSeedInt(totalWeight);
for (let s = 0; s < speciesWeights.length; s++) {
if (rand < speciesWeights[s]) {
species = speciesPool[s];
break;
}
}
if (!!this.scene.gameData.dexData[species].caughtAttr) {
this.scene.gameData.unlockPity[this.egg.tier] = Math.min(this.scene.gameData.unlockPity[this.egg.tier] + 1, 10);
} else {
this.scene.gameData.unlockPity[this.egg.tier] = 0;
}
const pokemonSpecies = getPokemonSpecies(species);
ret = this.scene.addPlayerPokemon(pokemonSpecies, 1, undefined, undefined, undefined, false);
}
/**
* Non Shiny gacha Pokemon have a 1/128 chance of being shiny
* Shiny gacha Pokemon have a 1/64 chance of being shiny
* IVs are rolled twice and the higher of each stat's IV is taken
* The egg move gacha doubles the rate of rare egg moves but the base rates are
* Common: 1/48
* Rare: 1/24
* Epic: 1/12
* Legendary: 1/6
*/
ret.trySetShiny(this.egg.gachaType === GachaType.SHINY ? 1024 : 512);
ret.variant = ret.shiny ? ret.generateVariant() : 0;
const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295));
for (let s = 0; s < ret.ivs.length; s++) {
ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]);
}
const baseChance = this.egg.gachaType === GachaType.MOVE ? 3 : 6;
this.eggMoveIndex = Utils.randSeedInt(baseChance * Math.pow(2, 3 - this.egg.tier))
? Utils.randSeedInt(3)
: 3;
}, this.egg.id, EGG_SEED.toString()); }, this.egg.id, EGG_SEED.toString());

View File

@ -20,5 +20,6 @@ export enum ArenaTagType {
WIDE_GUARD = "WIDE_GUARD", WIDE_GUARD = "WIDE_GUARD",
MAT_BLOCK = "MAT_BLOCK", MAT_BLOCK = "MAT_BLOCK",
CRAFTY_SHIELD = "CRAFTY_SHIELD", CRAFTY_SHIELD = "CRAFTY_SHIELD",
TAILWIND = "TAILWIND" TAILWIND = "TAILWIND",
HAPPY_HOUR = "HAPPY_HOUR"
} }

View File

@ -54,7 +54,7 @@ export enum BattlerTagType {
SALT_CURED = "SALT_CURED", SALT_CURED = "SALT_CURED",
CURSED = "CURSED", CURSED = "CURSED",
CHARGED = "CHARGED", CHARGED = "CHARGED",
GROUNDED = "GROUNDED", ROOSTED = "ROOSTED",
MAGNET_RISEN = "MAGNET_RISEN", MAGNET_RISEN = "MAGNET_RISEN",
MINIMIZED = "MINIMIZED", MINIMIZED = "MINIMIZED",
DESTINY_BOND = "DESTINY_BOND", DESTINY_BOND = "DESTINY_BOND",

View File

@ -0,0 +1,7 @@
export enum EggSourceType {
GACHA_MOVE,
GACHA_LEGENDARY,
GACHA_SHINY,
SAME_SPECIES_EGG,
EVENT
}

5
src/enums/gacha-types.ts Normal file
View File

@ -0,0 +1,5 @@
export enum GachaType {
MOVE,
LEGENDARY,
SHINY
}

View File

@ -0,0 +1,5 @@
export enum VariantTier {
COMMON,
RARE,
EPIC
}

View File

@ -20,6 +20,7 @@ export default class DamageNumberHandler {
const battlerIndex = target.getBattlerIndex(); const battlerIndex = target.getBattlerIndex();
const baseScale = target.getSpriteScale() / 6; const baseScale = target.getSpriteScale() / 6;
const damageNumber = addTextObject(scene, target.x, -(scene.game.canvas.height / 6) + target.y - target.getSprite().height / 2, Utils.formatStat(amount, true), TextStyle.SUMMARY); const damageNumber = addTextObject(scene, target.x, -(scene.game.canvas.height / 6) + target.y - target.getSprite().height / 2, Utils.formatStat(amount, true), TextStyle.SUMMARY);
damageNumber.setName("text-damage-number");
damageNumber.setOrigin(0.5, 1); damageNumber.setOrigin(0.5, 1);
damageNumber.setScale(baseScale); damageNumber.setScale(baseScale);

View File

@ -39,6 +39,7 @@ export default class PokemonSpriteSparkleHandler {
const [ xOffset, yOffset ] = [ -s.originX * s.width, -s.originY * s.height]; const [ xOffset, yOffset ] = [ -s.originX * s.width, -s.originY * s.height];
const sparkle = (s.scene as BattleScene).addFieldSprite(((pokemon?.x || 0) + s.x + pixelX * ratioX + xOffset), ((pokemon?.y || 0) + s.y + pixelY * ratioY + yOffset), "tera_sparkle"); const sparkle = (s.scene as BattleScene).addFieldSprite(((pokemon?.x || 0) + s.x + pixelX * ratioX + xOffset), ((pokemon?.y || 0) + s.y + pixelY * ratioY + yOffset), "tera_sparkle");
sparkle.pipelineData["ignoreTimeTint"] = s.pipelineData["ignoreTimeTint"]; sparkle.pipelineData["ignoreTimeTint"] = s.pipelineData["ignoreTimeTint"];
sparkle.setName("sprite-tera-sparkle");
sparkle.play("tera_sparkle"); sparkle.play("tera_sparkle");
parent.add(sparkle); parent.add(sparkle);
s.scene.time.delayedCall(Utils.fixedInt(Math.floor((1000 / 12) * 13)), () => sparkle.destroy()); s.scene.time.delayedCall(Utils.fixedInt(Math.floor((1000 / 12) * 13)), () => sparkle.destroy());

View File

@ -3,14 +3,14 @@ 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, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, VariableMoveTypeAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, MoveFlags } from "../data/move"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, VariableMoveTypeAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, MoveFlags, NeutralDamageAgainstFlyingTypeMultiplierAttr } 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 } from "../data/pokemon-stat";
import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from "../modifier/modifier"; import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, EvolutionStatBoosterModifier, 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";
@ -19,7 +19,7 @@ import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEv
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms"; import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms";
import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase, ToggleDoublePositionPhase } from "../phases"; import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase, ToggleDoublePositionPhase } from "../phases";
import { BattleStat } from "../data/battle-stat"; import { BattleStat } from "../data/battle-stat";
import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, TypeImmuneTag, getBattlerTag } from "../data/battler-tags"; import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, TypeImmuneTag, getBattlerTag } from "../data/battler-tags";
import { WeatherType } from "../data/weather"; import { WeatherType } from "../data/weather";
import { TempBattleStat } from "../data/temp-battle-stat"; import { TempBattleStat } from "../data/temp-battle-stat";
import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from "../data/arena-tag"; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from "../data/arena-tag";
@ -657,6 +657,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), battleStat as integer as TempBattleStat, statLevel); this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), battleStat as integer as TempBattleStat, statLevel);
} }
const statValue = new Utils.NumberHolder(this.getStat(stat)); const statValue = new Utils.NumberHolder(this.getStat(stat));
this.scene.applyModifiers(EvolutionStatBoosterModifier, 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); applyFieldBattleStatMultiplierAbAttrs(FieldMultiplyBattleStatAbAttr, pokemon, stat, statValue, this, fieldApplied);
@ -851,6 +853,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this.getLevelMoves(1, true).map(lm => lm[1]).filter(lm => !this.moveset.filter(m => m.moveId === lm).length).filter((move: Moves, i: integer, array: Moves[]) => array.indexOf(move) === i); return this.getLevelMoves(1, true).map(lm => lm[1]).filter(lm => !this.moveset.filter(m => m.moveId === lm).length).filter((move: Moves, i: integer, array: Moves[]) => array.indexOf(move) === i);
} }
/**
* Gets the types of a pokemon
* @param includeTeraType boolean to include tera-formed type, default false
* @param forDefend boolean if the pokemon is defending from an attack
* @param ignoreOverride boolean if true, ignore ability changing effects
* @returns array of {@linkcode Type}
*/
getTypes(includeTeraType = false, forDefend: boolean = false, ignoreOverride?: boolean): Type[] { getTypes(includeTeraType = false, forDefend: boolean = false, ignoreOverride?: boolean): Type[] {
const types = []; const types = [];
@ -884,7 +893,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
} }
if (forDefend && (this.getTag(BattlerTagType.IGNORE_FLYING) || this.scene.arena.getTag(ArenaTagType.GRAVITY) || this.getTag(BattlerTagType.GROUNDED))) { // this.scene potentially can be undefined for a fainted pokemon in doubles
// use optional chaining to avoid runtime errors
if (forDefend && (this.getTag(GroundedTag) || this.scene?.arena.getTag(ArenaTagType.GRAVITY))) {
const flyingIndex = types.indexOf(Type.FLYING); const flyingIndex = types.indexOf(Type.FLYING);
if (flyingIndex > -1) { if (flyingIndex > -1) {
types.splice(flyingIndex, 1); types.splice(flyingIndex, 1);
@ -1061,7 +1072,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* in effect, and both passive and non-passive. This is one of the two primary ways to check * in effect, and both passive and non-passive. This is one of the two primary ways to check
* whether a pokemon has a particular ability. * whether a pokemon has a particular ability.
* @param {AbAttr} attrType The ability attribute to check for * @param {AbAttr} attrType The ability attribute to check for
* @param {boolean} canApply If false, it doesn't check whether the abiltiy is currently active * @param {boolean} canApply If false, it doesn't check whether the ability is currently active
* @param {boolean} ignoreOverride If true, it ignores ability changing effects * @param {boolean} ignoreOverride If true, it ignores ability changing effects
* @returns {boolean} Whether an ability with that attribute is present and active * @returns {boolean} Whether an ability with that attribute is present and active
*/ */
@ -1082,13 +1093,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return weight.value; return weight.value;
} }
/**
* Gets the tera-formed type of the pokemon, or UNKNOWN if not present
* @returns the {@linkcode Type}
*/
getTeraType(): Type { getTeraType(): Type {
const teraModifier = this.scene.findModifier(m => m instanceof TerastallizeModifier // this.scene can be undefined for a fainted mon in doubles
&& m.pokemonId === this.id && !!m.getBattlesLeft(), this.isPlayer()) as TerastallizeModifier; if (this.scene !== undefined) {
if (teraModifier) { const teraModifier = this.scene.findModifier(m => m instanceof TerastallizeModifier
return teraModifier.teraType; && m.pokemonId === this.id && !!m.getBattlesLeft(), this.isPlayer()) as TerastallizeModifier;
// return teraType
if (teraModifier) {
return teraModifier.teraType;
}
} }
// if scene is undefined, or if teraModifier is considered false, then return unknown type
return Type.UNKNOWN; return Type.UNKNOWN;
} }
@ -1097,7 +1116,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
isGrounded(): boolean { isGrounded(): boolean {
return !this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.MAGNET_RISEN); return !!this.getTag(GroundedTag) || (!this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.MAGNET_RISEN));
} }
/** /**
@ -1769,12 +1788,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
aura.applyPreAttack(null, null, null, move, [power]); aura.applyPreAttack(null, null, null, move, [power]);
} }
applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, move, cancelled, power);
power.value *= typeChangeMovePowerMultiplier.value; power.value *= typeChangeMovePowerMultiplier.value;
if (!typeless) { if (!typeless) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier); applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier);
applyMoveAttrs(NeutralDamageAgainstFlyingTypeMultiplierAttr, source, this, move, typeMultiplier);
} }
if (!cancelled.value) { if (!cancelled.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier); applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier);
@ -1796,7 +1814,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (this.scene.arena.getTerrainType() === TerrainType.GRASSY && this.isGrounded() && move.type === Type.GROUND && move.moveTarget === MoveTarget.ALL_NEAR_OTHERS) { if (this.scene.arena.getTerrainType() === TerrainType.GRASSY && this.isGrounded() && move.type === Type.GROUND && move.moveTarget === MoveTarget.ALL_NEAR_OTHERS) {
power.value /= 2; power.value /= 2;
} }
applyMoveAttrs(VariablePowerAttr, source, this, move, power); applyMoveAttrs(VariablePowerAttr, source, this, move, power);
this.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, new Utils.IntegerHolder(0), power); this.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, new Utils.IntegerHolder(0), power);
if (!typeless) { if (!typeless) {
this.scene.arena.applyTags(WeakenMoveTypeTag, move.type, power); this.scene.arena.applyTags(WeakenMoveTypeTag, move.type, power);
@ -1934,6 +1954,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage); applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage);
applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, move, cancelled, power);
if (power.value === 0) { if (power.value === 0) {
damage.value = 0; damage.value = 0;
@ -3505,6 +3526,10 @@ export class EnemyPokemon extends Pokemon {
const target = this.scene.getField()[mt]; const target = this.scene.getField()[mt];
let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1); let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1);
if (Number.isNaN(targetScore)) {
console.error(`Move ${move.name} returned score of NaN`);
targetScore = 0;
}
if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id)) { if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id)) {
targetScore = -20; targetScore = -20;
} else if (move instanceof AttackMove) { } else if (move instanceof AttackMove) {

View File

@ -432,20 +432,24 @@ export default class Trainer extends Phaser.GameObjects.Container {
} }
const party = this.scene.getEnemyParty(); const party = this.scene.getEnemyParty();
const nonFaintedPartyMembers = party.slice(this.scene.currentBattle.getBattlerCount()).filter(p => !p.isFainted()).filter(p => !trainerSlot || p.trainerSlot === trainerSlot); const nonFaintedLegalPartyMembers = party.slice(this.scene.currentBattle.getBattlerCount()).filter(p => p.isAllowedInBattle()).filter(p => !trainerSlot || p.trainerSlot === trainerSlot);
const partyMemberScores = nonFaintedPartyMembers.map(p => { const partyMemberScores = nonFaintedLegalPartyMembers.map(p => {
const playerField = this.scene.getPlayerField(); const playerField = this.scene.getPlayerField().filter(p => p.isAllowedInBattle());
let score = 0; let score = 0;
for (const playerPokemon of playerField) {
score += p.getMatchupScore(playerPokemon); if (playerField.length > 0) {
if (playerPokemon.species.legendary) { for (const playerPokemon of playerField) {
score /= 2; score += p.getMatchupScore(playerPokemon);
if (playerPokemon.species.legendary) {
score /= 2;
}
}
score /= playerField.length;
if (forSwitch && !p.isOnField()) {
this.scene.arena.findTagsOnSide(t => t instanceof ArenaTrapTag, ArenaTagSide.ENEMY).map(t => score *= (t as ArenaTrapTag).getMatchupScoreMultiplier(p));
} }
} }
score /= playerField.length;
if (forSwitch && !p.isOnField()) {
this.scene.arena.findTagsOnSide(t => t instanceof ArenaTrapTag, ArenaTagSide.ENEMY).map(t => score *= (t as ArenaTrapTag).getMatchupScoreMultiplier(p));
}
return [party.indexOf(p), score]; return [party.indexOf(p), score];
}) as [integer, integer][]; }) as [integer, integer][];

View File

@ -1,4 +1,4 @@
import { GachaType } from "./data/egg"; import { GachaType } from "./enums/gacha-types";
import { trainerConfigs } from "./data/trainer-config"; import { trainerConfigs } from "./data/trainer-config";
import { getBiomeHasProps } from "./field/arena"; import { getBiomeHasProps } from "./field/arena";
import CacheBustedLoaderPlugin from "./plugins/cache-busted-loader-plugin"; import CacheBustedLoaderPlugin from "./plugins/cache-busted-loader-plugin";
@ -43,7 +43,6 @@ export class LoadingScene extends SceneBase {
// Load menu images // Load menu images
this.loadAtlas("bg", "ui"); this.loadAtlas("bg", "ui");
this.loadImage("command_fight_labels", "ui");
this.loadAtlas("prompt", "ui"); this.loadAtlas("prompt", "ui");
this.loadImage("candy", "ui"); this.loadImage("candy", "ui");
this.loadImage("candy_overlay", "ui"); this.loadImage("candy_overlay", "ui");
@ -321,6 +320,7 @@ export class LoadingScene extends SceneBase {
this.loadBgm("minor_fanfare", "bw/minor_fanfare.mp3"); this.loadBgm("minor_fanfare", "bw/minor_fanfare.mp3");
this.loadBgm("heal", "bw/heal.mp3"); this.loadBgm("heal", "bw/heal.mp3");
this.loadBgm("victory_trainer", "bw/victory_trainer.mp3"); this.loadBgm("victory_trainer", "bw/victory_trainer.mp3");
this.loadBgm("victory_team_plasma", "bw/victory_team_plasma.mp3");
this.loadBgm("victory_gym", "bw/victory_gym.mp3"); this.loadBgm("victory_gym", "bw/victory_gym.mp3");
this.loadBgm("victory_champion", "bw/victory_champion.mp3"); this.loadBgm("victory_champion", "bw/victory_champion.mp3");
this.loadBgm("evolution", "bw/evolution.mp3"); this.loadBgm("evolution", "bw/evolution.mp3");

View File

@ -1,8 +1,11 @@
import { SimpleTranslationEntries } from "#app/interfaces/locales"; import { SimpleTranslationEntries } from "#app/interfaces/locales";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!", "blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}} vor Rückstoß geschützt!",
"badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!", "badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!",
"costar": "{{pokemonName}} kopiert die Statusveränderungen von {{allyName}}!",
"iceFaceAvoidedDamage": "{{pokemonName}} wehrt Schaden mit {{abilityName}} ab!",
"trace": "{{pokemonName}} kopiert {{abilityName}} von {{targetName}}!",
"windPowerCharged": "Der Treffer durch {{moveName}} läd die Stärke von {{pokemonName}} auf!", "windPowerCharged": "Der Treffer durch {{moveName}} läd die Stärke von {{pokemonName}} auf!",
"iceFaceAvoidedDamage": "{{pokemonName}} wehrt Schaden\nmit {{abilityName}} ab!", "quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
} as const; } as const;

View File

@ -15,6 +15,7 @@ export const battle: SimpleTranslationEntries = {
"trainerDefeated": "{{trainerName}}\nwurde besiegt!", "trainerDefeated": "{{trainerName}}\nwurde besiegt!",
"moneyWon": "Du gewinnst\n{{moneyAmount}} ₽!", "moneyWon": "Du gewinnst\n{{moneyAmount}} ₽!",
"pokemonCaught": "{{pokemonName}} wurde gefangen!", "pokemonCaught": "{{pokemonName}} wurde gefangen!",
"addedAsAStarter": "{{pokemonName}} wurde als Starterpokémon hinzugefügt!",
"partyFull": "Dein Team ist voll.\nMöchtest du ein Pokémon durch {{pokemonName}} ersetzen?", "partyFull": "Dein Team ist voll.\nMöchtest du ein Pokémon durch {{pokemonName}} ersetzen?",
"pokemon": "Pokémon", "pokemon": "Pokémon",
"sendOutPokemon": "Los, {{pokemonName}}!", "sendOutPokemon": "Los, {{pokemonName}}!",
@ -54,6 +55,8 @@ export const battle: SimpleTranslationEntries = {
"escapeVerbFlee": "flucht", "escapeVerbFlee": "flucht",
"skipItemQuestion": "Bist du sicher, dass du kein Item nehmen willst?", "skipItemQuestion": "Bist du sicher, dass du kein Item nehmen willst?",
"notDisabled": "{{pokemonName}}'s {{moveName}} ist\nnicht mehr deaktiviert!", "notDisabled": "{{pokemonName}}'s {{moveName}} ist\nnicht mehr deaktiviert!",
"turnEndHpRestore": "{{pokemonName}}'s HP was restored.",
"hpIsFull": "{{pokemonName}}'s\nHP is full!",
"eggHatching": "Oh?", "eggHatching": "Oh?",
"ivScannerUseQuestion": "IV-Scanner auf {{pokemonName}} benutzen?", "ivScannerUseQuestion": "IV-Scanner auf {{pokemonName}} benutzen?",
"wildPokemonWithAffix": "{{pokemonName}} (wild)", "wildPokemonWithAffix": "{{pokemonName}} (wild)",
@ -62,14 +65,14 @@ export const battle: SimpleTranslationEntries = {
"drainMessage": "{{pokemonName}} wurde Energie abgesaugt", "drainMessage": "{{pokemonName}} wurde Energie abgesaugt",
"regainHealth": "KP von {{pokemonName}} wurden wieder aufgefrischt!", "regainHealth": "KP von {{pokemonName}} wurden wieder aufgefrischt!",
"fainted": "{{pokemonNameWithAffix}} wurde besiegt!", "fainted": "{{pokemonNameWithAffix}} wurde besiegt!",
"statRose": "steigt", "statRose": "{{stats}} von {{pokemonNameWithAffix}} steigt!",
"statSharplyRose": "steigt stark", "statSharplyRose": "{{stats}} von {{pokemonNameWithAffix}} steigt stark!",
"statRoseDrastically": "steigt drastisch", "statRoseDrastically": "{{stats}} von {{pokemonNameWithAffix}} steigt drastisch!",
"statWontGoAnyHigher": "kann nicht weiter erhöht werden", "statWontGoAnyHigher": "{{stats}} von {{pokemonNameWithAffix}} kann nicht weiter erhöht werden!",
"statFell": "sinkt", "statFell": "{{stats}} von {{pokemonNameWithAffix}} sinkt!",
"statHarshlyFell": "sinkt stark", "statHarshlyFell": "{{stats}} von {{pokemonNameWithAffix}} sinkt stark!",
"statSeverelyFell": "sinkt drastisch", "statSeverelyFell": "{{stats}} von {{pokemonNameWithAffix}} sinkt drastisch!",
"statWontGoAnyLower": "kann nicht weiter sinken", "statWontGoAnyLower": "{{stats}} von {{pokemonNameWithAffix}} kann nicht weiter sinken!",
"ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!",
"battlerTagsRechargingLapse": "{{pokemonNameWithAffix}} kann sich wegen des Rückstoßes durch den Angriff nicht bewegen!", "battlerTagsRechargingLapse": "{{pokemonNameWithAffix}} kann sich wegen des Rückstoßes durch den Angriff nicht bewegen!",
"battlerTagsTrappedOnAdd": "{{pokemonNameWithAffix}} kann nicht mehr fliehen!", "battlerTagsTrappedOnAdd": "{{pokemonNameWithAffix}} kann nicht mehr fliehen!",

144
src/locales/de/bgm-name.ts Normal file
View File

@ -0,0 +1,144 @@
import { SimpleTranslationEntries } from "#app/interfaces/locales";
export const bgmName: SimpleTranslationEntries = {
"music": "Musik",
"missing_entries" : "{{name}}",
"battle_kanto_champion": "S2W2 Vs. Kanto Champion",
"battle_johto_champion": "S2W2 Vs. Johto Champion",
"battle_hoenn_champion": "S2W2 Vs. Hoenn Champion",
"battle_sinnoh_champion": "S2W2 Vs. Champion Cynthia",
"battle_champion_alder": "SW Vs. Champion Lauro",
"battle_champion_iris": "S2W2 Vs. Champion Lilia",
"battle_kalos_champion": "XY Vs. Champion Diantha",
"battle_alola_champion": "USUM Vs. Alola Champion",
"battle_galar_champion": "SWSH Vs. Champion Delion",
"battle_champion_geeta": "KAPU Vs. Champion Sagaria",
"battle_champion_nemona": "KAPU Vs. Champion Nemila",
"battle_champion_kieran": "KAPU Vs. Jo",
"battle_hoenn_elite": "ORAS Vs. Hoenn Top Vier",
"battle_unova_elite": "SW Vs. Einall Top Vier",
"battle_kalos_elite": "XY Vs. Kalos Top Vier",
"battle_alola_elite": "SM Vs. Alola Top Vier",
"battle_galar_elite": "SWSH Galar Champ-Cup",
"battle_paldea_elite": "KAPU Vs. Paldea Top Vier",
"battle_bb_elite": "KAPU Vs. Blaubeer-Top-Vier",
"battle_final_encounter": "PMDDX Rayquazas Domäne",
"battle_final": "SW Vs. G-Cis",
"battle_kanto_gym": "S2W2 Vs. Kanto Arenaleiter",
"battle_johto_gym": "S2W2 Vs. Johto Arenaleiter",
"battle_hoenn_gym": "S2W2 Vs. Hoenn Arenaleiter",
"battle_sinnoh_gym": "S2W2 Vs. Sinnoh Arenaleiter",
"battle_unova_gym": "SW Vs. Einall Arenaleiter",
"battle_kalos_gym": "XY Vs. Kalos Arenaleiter",
"battle_galar_gym": "SWSH Vs. Galar Arenaleiter",
"battle_paldea_gym": "KAPU Vs. Paldea Arenaleiter",
"battle_legendary_kanto": "XY Vs. Legendäres Kanto Pokémon",
"battle_legendary_raikou": "HGSS Vs. Raikou",
"battle_legendary_entei": "HGSS Vs. Entei",
"battle_legendary_suicune": "HGSS Vs. Suicune",
"battle_legendary_lugia": "HGSS Vs. Lugia",
"battle_legendary_ho_oh": "HGSS Vs. Ho-oh",
"battle_legendary_regis_g5": "S2W2 Vs. Legendäre Giganten",
"battle_legendary_regis_g6": "ORAS Vs. Legendäre Giganten",
"battle_legendary_gro_kyo": "ORAS Vs. Groudon & Kyogre",
"battle_legendary_rayquaza": "ORAS Vs. Rayquaza",
"battle_legendary_deoxys": "ORAS Vs. Deoxys",
"battle_legendary_lake_trio": "ORAS Vs. Seen-Trio",
"battle_legendary_sinnoh": "ORAS Vs. Legendäres Sinnoh Pokémon",
"battle_legendary_dia_pal": "ORAS Vs. Dialga & Palkia",
"battle_legendary_giratina": "ORAS Vs. Giratina",
"battle_legendary_arceus": "HGSS Vs. Arceus",
"battle_legendary_unova": "SW Vs. Legendäres Einall Pokémon",
"battle_legendary_kyurem": "SW Vs. Kyurem",
"battle_legendary_res_zek": "SW Vs. Reshiram & Zekrom",
"battle_legendary_xern_yvel": "XY Vs. Xerneas & Yveltal",
"battle_legendary_tapu": "SM Vs. Kapu",
"battle_legendary_sol_lun": "SM Vs. Solgaleo & Lunala",
"battle_legendary_ub": "SM Vs. Ultrabestie",
"battle_legendary_dusk_dawn": "USUM Vs. Abendmähne- & Morgenschwingen-Necrozma",
"battle_legendary_ultra_nec": "USUM Vs. Ultra-Necrozma",
"battle_legendary_zac_zam": "SWSH Vs. Zacian & Zamazenta",
"battle_legendary_glas_spec": "SWSH Vs. Polaross & Phantoross",
"battle_legendary_calyrex": "SWSH Vs. Coronospa",
"battle_legendary_birds_galar": "SWSH Vs. Legendäre Galar-Vögel",
"battle_legendary_ruinous": "KAPU Vs. Schätze des Unheils",
"battle_legendary_loyal_three": "KAPU Drei Gefährten",
"battle_legendary_ogerpon": "KAPU Vs. Ogerpon",
"battle_legendary_terapagos": "KAPU Vs. Terapagos",
"battle_legendary_pecharunt": "KAPU Vs. Infamomo",
"battle_rival": "SW Vs. Rivale",
"battle_rival_2": "SW Vs. N",
"battle_rival_3": "SW Vs. N (Finale)",
"battle_trainer": "SW Vs. Trainer",
"battle_wild": "SW Vs. Wilde Pokémon",
"battle_wild_strong": "SW Vs. Starke Wilde Pokémon",
"end_summit": "PMDDX Gipfel des Himmelturms",
"battle_rocket_grunt": "HGSS Team Rocket Battle",
"battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle",
"battle_galactic_grunt": "BDSP Team Galactic Battle",
"battle_plasma_grunt": "SW Vs. Team Plasma Rüpel",
"battle_flare_grunt": "XY Team Flare Battle",
"battle_rocket_boss": "USUM Giovanni Battle",
"battle_aqua_magma_boss": "ORAS Archie & Maxie Battle",
"battle_galactic_boss": "BDSP Cyrus Battle",
"battle_plasma_boss": "B2W2 Ghetsis Battle",
"battle_flare_boss": "XY Lysandre Battle",
// Biome Music
"abyss": "PMD Erkundungsteam Himmel Dunkelkrater",
"badlands": "PMD Erkundungsteam Himmel Kargtal",
"beach": "PMD Erkundungsteam Himmel Feuchtklippe",
"cave": "PMD Erkundungsteam Himmel Himmelsgipfel-Höhle",
"construction_site": "PMD Erkundungsteam Himmel Geröllbruch",
"desert": "PMD Erkundungsteam Himmel Nordwüste",
"dojo": "PMD Erkundungsteam Himmel Knogga-Dojo",
"end": "PMD Retterteam DX Himmelsturm",
"factory": "PMD Erkundungsteam Himmel Verborgene Ruinen",
"fairy_cave": "PMD Erkundungsteam Himmel Sternenhöhle",
"forest": "PMD Erkundungsteam Himmel Düsterwald",
"grass": "PMD Erkundungsteam Himmel Apfelwald",
"graveyard": "PMD Erkundungsteam Himmel Verwirrwald",
"ice_cave": "PMD Erkundungsteam Himmel Rieseneisberg",
"island": "PMD Erkundungsteam Himmel Schroffküste",
//"jungle": "jungle", // The composer thinks about a more creative name
//"labratory": "labratory", // The composer thinks about a more creative name
"lake": "PMD Erkundungsteam Himmel Kristallhöhle",
"meadow": "PMD Erkundungsteam Himmel Himmelsgipfel-Wald",
//"metropolis": "metropolis", // The composer thinks about a more creative name
"mountain": "PMD Erkundungsteam Himmel Hornberg",
"plains": "PMD Erkundungsteam Himmel Himmelsgipfel-Prärie",
"power_plant": "PMD Erkundungsteam Himmel Weite Ampere-Ebene",
"ruins": "PMD Erkundungsteam Himmel Tiefes Ruinenverlies",
"sea": "PMD Erkundungsteam Himmel Salzwasserhöhle",
"seabed": "PMD Erkundungsteam Himmel Untere Salzwasserhöhle",
"slum": "PMD Erkundungsteam Himmel Himmelsgipfel-Küste",
"snowy_forest": "PMD Erkundungsteam Himmel Himmelsgipfel-Schneefeld",
"space": "PMD Erkundungsteam Himmel Schicksalsschlucht",
"swamp": "PMD Erkundungsteam Himmel Ringmeer",
"tall_grass": "PMD Erkundungsteam Himmel Nebelwald",
"temple": "PMD Erkundungsteam Himmel Ägishöhle",
"town": "PMD Erkundungsteam Himmel Zufälliges Dungeon-Theme 3",
"volcano": "PMD Erkundungsteam Himmel Dunsthöhle",
"wasteland": "PMD Erkundungsteam Himmel Verborgenes Hochland",
// Encounter
"encounter_ace_trainer": "SW Trainerblicke treffen sich (Ass-Trainer)",
"encounter_backpacker": "SW Trainerblicke treffen sich (Backpacker)",
"encounter_clerk": "SW Trainerblicke treffen sich (Angestellter)",
"encounter_cyclist": "SW Trainerblicke treffen sich (Biker)",
"encounter_lass": "SW Trainerblicke treffen sich (Göre)",
"encounter_parasol_lady": "SW Trainerblicke treffen sich (Schirmdame)",
"encounter_pokefan": "SW Trainerblicke treffen sich (Pokéfan)",
"encounter_psychic": "SW Trainerblicke treffen sich (Seher)",
"encounter_rich": "SW Trainerblicke treffen sich (Gentleman)",
"encounter_rival": "SW Vs. Cheren",
"encounter_roughneck": "SW Trainerblicke treffen sich (Raufbold)",
"encounter_scientist": "SW Trainerblicke treffen sich (Forscher)",
"encounter_twins": "SW Trainerblicke treffen sich (Zwillinge)",
"encounter_youngster": "SW Trainerblicke treffen sich (Knirps)",
// Other
"heal": "SW Pokémon-Heilung",
"menu": "PMD Erkundungsteam Himmel Willkommen in der Welt der Pokémon!",
"title": "PMD Erkundungsteam Himmel Top-Menü-Thema",
} as const;

View File

@ -4,6 +4,7 @@ import { PGFachv, PGMachv } from "./achv";
import { battle } from "./battle"; import { battle } from "./battle";
import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battleMessageUiHandler } from "./battle-message-ui-handler";
import { berry } from "./berry"; import { berry } from "./berry";
import { bgmName } from "./bgm-name";
import { biome } from "./biome"; import { biome } from "./biome";
import { challenges } from "./challenges"; import { challenges } from "./challenges";
import { commandUiHandler } from "./command-ui-handler"; import { commandUiHandler } from "./command-ui-handler";
@ -48,6 +49,7 @@ export const deConfig = {
battle: battle, battle: battle,
battleMessageUiHandler: battleMessageUiHandler, battleMessageUiHandler: battleMessageUiHandler,
berry: berry, berry: berry,
bgmName: bgmName,
biome: biome, biome: biome,
challenges: challenges, challenges: challenges,
commandUiHandler: commandUiHandler, commandUiHandler: commandUiHandler,

View File

@ -17,5 +17,9 @@ export const egg: SimpleTranslationEntries = {
"notEnoughVouchers": "Du hast nicht genug Ei-Gutscheine!", "notEnoughVouchers": "Du hast nicht genug Ei-Gutscheine!",
"tooManyEggs": "Du hast schon zu viele Eier!", "tooManyEggs": "Du hast schon zu viele Eier!",
"pull": "Pull", "pull": "Pull",
"pulls": "Pulls" "pulls": "Pulls",
"sameSpeciesEgg": "{{species}} wird aus dem Ei schlüpfen!",
"hatchFromTheEgg": "Ein {{pokemonName}} ist aus dem Ei geschlüpft!",
"eggMoveUnlock": "Ei-Attacke freigeschaltet: {{moveName}}",
"rareEggMoveUnlock": "Seltene Ei-Attacke freigeschaltet: {{moveName}}",
} as const; } as const;

View File

@ -19,5 +19,6 @@ export const menuUiHandler: SimpleTranslationEntries = {
"importData": "Daten importieren", "importData": "Daten importieren",
"exportData": "Daten exportieren", "exportData": "Daten exportieren",
"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": "You are not hatching\nany eggs at the moment!"
} as const; } as const;

View File

@ -47,10 +47,11 @@ export const menu: SimpleTranslationEntries = {
"score": "Punkte", "score": "Punkte",
"wave": "Welle", "wave": "Welle",
"loading": "Lade…", "loading": "Lade…",
"loadingAsset": "Loading asset: {{assetName}}", "loadingAsset": "Lade Asset: {{assetName}}",
"playersOnline": "Spieler Online", "playersOnline": "Spieler Online",
"yes":"Ja", "yes":"Ja",
"no":"Nein", "no":"Nein",
"disclaimer": "DISCLAIMER", "disclaimer": "HAFTUNGSAUSSCHLUSS",
"disclaimerDescription": "Dieses Spiel ist ein unfertiges Produkt. Es kann spielbeinträchtigende Fehler (bis hin zum Verlust des Speicherstandes)\n aufweisen, sich ohne Vorankündigung ändern und es gibt keine Garantie dass es weiterentwickelt oder fertiggestellt wird.", "disclaimerDescription": "Dieses Spiel ist ein unfertiges Produkt. Es kann spielbeinträchtigende Fehler (bis hin zum Verlust des Speicherstandes)\n aufweisen, sich ohne Vorankündigung ändern und es gibt keine Garantie dass es weiterentwickelt oder fertiggestellt wird.",
"choosePokemon": "Choose a Pokémon.",
} as const; } as const;

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "Sanftglocke" }, "SOOTHE_BELL": { name: "Sanftglocke" },
"EVIOLITE": { name: "Evolith", description: "Ein mysteriöser Klumpen, der die Vert. u. Spez.-Vert. von Pokémon erhöht, die sich noch entwickeln können." },
"SOUL_DEW": { name: "Seelentau", description: "Erhöht den Einfluss des Wesens eines Pokemon auf seine Werte um 10% (additiv)." }, "SOUL_DEW": { name: "Seelentau", description: "Erhöht den Einfluss des Wesens eines Pokemon auf seine Werte um 10% (additiv)." },
"NUGGET": { name: "Nugget" }, "NUGGET": { name: "Nugget" },

View File

@ -95,4 +95,5 @@ export const settings: SimpleTranslationEntries = {
"mute": "Stumm", "mute": "Stumm",
"controller": "Controller", "controller": "Controller",
"gamepadSupport": "Controllerunterstützung", "gamepadSupport": "Controllerunterstützung",
"showBgmBar": "Musiknamen anzeigen",
} as const; } as const;

View File

@ -31,6 +31,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"selectMoveSwapWith": "Wähle die gewünschte Attacke.", "selectMoveSwapWith": "Wähle die gewünschte Attacke.",
"unlockPassive": "Passiv-Skill freischalten", "unlockPassive": "Passiv-Skill freischalten",
"reduceCost": "Preis reduzieren", "reduceCost": "Preis reduzieren",
"sameSpeciesEgg": "Ein Ei kaufen",
"cycleShiny": ": Schillernd", "cycleShiny": ": Schillernd",
"cycleForm": ": Form", "cycleForm": ": Form",
"cycleGender": ": Geschlecht", "cycleGender": ": Geschlecht",

View File

@ -93,12 +93,12 @@ export const trainerClasses: SimpleTranslationEntries = {
"pokémon_rangers": "Pokémon-Ranger", "pokémon_rangers": "Pokémon-Ranger",
"ranger": "Ranger", "ranger": "Ranger",
"restaurant_staff": "Restaurant Angestellte", "restaurant_staff": "Restaurant Angestellte",
"rich": "Rich", "rich": "Gentleman",
"rich_female": "Rich", "rich_female": "Reiche Dame",
"rich_boy": "Schnösel", "rich_boy": "Schnösel",
"rich_couple": "Reiches Paar", "rich_couple": "Reiches Paar",
"rich_kid": "Rich Kid", "rich_kid": "Schnösel",
"rich_kid_female": "Rich Kid", "rich_kid_female": "Schnöselin",
"rich_kids": "Schnösel", "rich_kids": "Schnösel",
"roughneck": "Raufbold", "roughneck": "Raufbold",
"sailor": "Matrose", "sailor": "Matrose",

View File

@ -1,10 +1,13 @@
import { SimpleTranslationEntries } from "#app/interfaces/locales"; import { SimpleTranslationEntries } from "#app/interfaces/locales";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!", "blockRecoilDamage": "{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!",
"badDreams": "{{pokemonName}} is tormented!", "badDreams": "{{pokemonName}} is tormented!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!", "costar": "{{pokemonName}} copied {{allyName}}'s stat changes!",
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!",
"perishBody": "{{pokemonName}}'s {{abilityName}}\nwill faint both pokemon in 3 turns!", "perishBody": "{{pokemonName}}'s {{abilityName}}\nwill faint both pokemon in 3 turns!",
"poisonHeal": "{{pokemonName}}'s {{abilityName}}\nrestored its HP a little!", "poisonHeal": "{{pokemonName}}'s {{abilityName}}\nrestored its HP a little!",
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!" "trace": "{{pokemonName}} copied {{targetName}}'s\n{{abilityName}}!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
"quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
} as const; } as const;

View File

@ -15,6 +15,7 @@ export const battle: SimpleTranslationEntries = {
"trainerDefeated": "You defeated\n{{trainerName}}!", "trainerDefeated": "You defeated\n{{trainerName}}!",
"moneyWon": "You got\n₽{{moneyAmount}} for winning!", "moneyWon": "You got\n₽{{moneyAmount}} for winning!",
"pokemonCaught": "{{pokemonName}} was caught!", "pokemonCaught": "{{pokemonName}} was caught!",
"addedAsAStarter": "{{pokemonName}} has been\nadded as a starter!",
"partyFull": "Your party is full.\nRelease a Pokémon to make room for {{pokemonName}}?", "partyFull": "Your party is full.\nRelease a Pokémon to make room for {{pokemonName}}?",
"pokemon": "Pokémon", "pokemon": "Pokémon",
"sendOutPokemon": "Go! {{pokemonName}}!", "sendOutPokemon": "Go! {{pokemonName}}!",
@ -53,6 +54,8 @@ export const battle: SimpleTranslationEntries = {
"escapeVerbSwitch": "switching", "escapeVerbSwitch": "switching",
"escapeVerbFlee": "fleeing", "escapeVerbFlee": "fleeing",
"notDisabled": "{{pokemonName}}'s {{moveName}} is disabled\nno more!", "notDisabled": "{{pokemonName}}'s {{moveName}} is disabled\nno more!",
"turnEndHpRestore": "{{pokemonName}}'s HP was restored.",
"hpIsFull": "{{pokemonName}}'s\nHP is full!",
"skipItemQuestion": "Are you sure you want to skip taking an item?", "skipItemQuestion": "Are you sure you want to skip taking an item?",
"eggHatching": "Oh?", "eggHatching": "Oh?",
"ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?", "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?",
@ -62,18 +65,18 @@ export const battle: SimpleTranslationEntries = {
"drainMessage": "{{pokemonName}} had its\nenergy drained!", "drainMessage": "{{pokemonName}} had its\nenergy drained!",
"regainHealth": "{{pokemonName}} regained\nhealth!", "regainHealth": "{{pokemonName}} regained\nhealth!",
"fainted": "{{pokemonNameWithAffix}} fainted!", "fainted": "{{pokemonNameWithAffix}} fainted!",
"statRose": "rose", "statRose": "{{pokemonNameWithAffix}}'s {{stats}} rose!",
"statSharplyRose": "sharply rose", "statSharplyRose": "{{pokemonNameWithAffix}}'s {{stats}} sharply rose!",
"statRoseDrastically": "rose drastically", "statRoseDrastically": "{{pokemonNameWithAffix}}'s {{stats}} rose drastically!",
"statWontGoAnyHigher": "won't go any higher", "statWontGoAnyHigher": "{{pokemonNameWithAffix}}'s {{stats}} won't go any higher!",
"statFell": "fell", "statFell": "{{pokemonNameWithAffix}}'s {{stats}} fell!",
"statHarshlyFell": "harshly fell", "statHarshlyFell": "{{pokemonNameWithAffix}}'s {{stats}} harshly fell!",
"statSeverelyFell": "severely fell", "statSeverelyFell": "{{pokemonNameWithAffix}}'s {{stats}} severely fell!",
"statWontGoAnyLower": "won't go any lower", "statWontGoAnyLower": "{{pokemonNameWithAffix}}'s {{stats}} won't go any lower!",
"ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!",
"battlerTagsRechargingLapse": "{{pokemonNameWithAffix}} must\nrecharge!", "battlerTagsRechargingLapse": "{{pokemonNameWithAffix}} must\nrecharge!",
"battlerTagsTrappedOnAdd": "{{pokemonNameWithAffix}} can no\nlonger escape!", "battlerTagsTrappedOnAdd": "{{pokemonNameWithAffix}} can no\nlonger escape!",
"battlerTagsTrappedOnRemove": "{{pokemonNameWithAffix}} was freed\nfrom {{moveName}}", "battlerTagsTrappedOnRemove": "{{pokemonNameWithAffix}} was freed\nfrom {{moveName}}!",
"battlerTagsFlinchedLapse": "{{pokemonNameWithAffix}} flinched!", "battlerTagsFlinchedLapse": "{{pokemonNameWithAffix}} flinched!",
"battlerTagsConfusedOnAdd": "{{pokemonNameWithAffix}} became\nconfused!", "battlerTagsConfusedOnAdd": "{{pokemonNameWithAffix}} became\nconfused!",
"battlerTagsConfusedOnRemove": "{{pokemonNameWithAffix}} snapped\nout of confusion!", "battlerTagsConfusedOnRemove": "{{pokemonNameWithAffix}} snapped\nout of confusion!",

144
src/locales/en/bgm-name.ts Normal file
View File

@ -0,0 +1,144 @@
import { SimpleTranslationEntries } from "#app/interfaces/locales";
export const bgmName: SimpleTranslationEntries = {
"music": "Music",
"missing_entries" : "{{name}}",
"battle_kanto_champion": "B2W2 Kanto Champion Battle",
"battle_johto_champion": "B2W2 Johto Champion Battle",
"battle_hoenn_champion": "B2W2 Hoenn Champion Battle",
"battle_sinnoh_champion": "B2W2 Sinnoh Champion Battle",
"battle_champion_alder": "BW Unova Champion Battle",
"battle_champion_iris": "B2W2 Unova Champion Battle",
"battle_kalos_champion": "XY Kalos Champion Battle",
"battle_alola_champion": "USUM Alola Champion Battle",
"battle_galar_champion": "SWSH Galar Champion Battle",
"battle_champion_geeta": "SV Champion Geeta Battle",
"battle_champion_nemona": "SV Champion Nemona Battle",
"battle_champion_kieran": "SV Champion Kieran Battle",
"battle_hoenn_elite": "ORAS Elite Four Battle",
"battle_unova_elite": "BW Elite Four Battle",
"battle_kalos_elite": "XY Elite Four Battle",
"battle_alola_elite": "SM Elite Four Battle",
"battle_galar_elite": "SWSH League Tournament Battle",
"battle_paldea_elite": "SV Elite Four Battle",
"battle_bb_elite": "SV BB League Elite Four Battle",
"battle_final_encounter": "PMD RTDX Rayquaza's Domain",
"battle_final": "BW Ghetsis Battle",
"battle_kanto_gym": "B2W2 Kanto Gym Battle",
"battle_johto_gym": "B2W2 Johto Gym Battle",
"battle_hoenn_gym": "B2W2 Hoenn Gym Battle",
"battle_sinnoh_gym": "B2W2 Sinnoh Gym Battle",
"battle_unova_gym": "BW Unova Gym Battle",
"battle_kalos_gym": "XY Kalos Gym Battle",
"battle_galar_gym": "SWSH Galar Gym Battle",
"battle_paldea_gym": "SV Paldea Gym Battle",
"battle_legendary_kanto": "XY Kanto Legendary Battle",
"battle_legendary_raikou": "HGSS Raikou Battle",
"battle_legendary_entei": "HGSS Entei Battle",
"battle_legendary_suicune": "HGSS Suicune Battle",
"battle_legendary_lugia": "HGSS Lugia Battle",
"battle_legendary_ho_oh": "HGSS Ho-oh Battle",
"battle_legendary_regis_g5": "B2W2 Legendary Titan Battle",
"battle_legendary_regis_g6": "ORAS Legendary Titan Battle",
"battle_legendary_gro_kyo": "ORAS Groudon & Kyogre Battle",
"battle_legendary_rayquaza": "ORAS Rayquaza Battle",
"battle_legendary_deoxys": "ORAS Deoxys Battle",
"battle_legendary_lake_trio": "ORAS Lake Guardians Battle",
"battle_legendary_sinnoh": "ORAS Sinnoh Legendary Battle",
"battle_legendary_dia_pal": "ORAS Dialga & Palkia Battle",
"battle_legendary_giratina": "ORAS Giratina Battle",
"battle_legendary_arceus": "HGSS Arceus Battle",
"battle_legendary_unova": "BW Unova Legendary Battle",
"battle_legendary_kyurem": "BW Kyurem Battle",
"battle_legendary_res_zek": "BW Reshiram & Zekrom Battle",
"battle_legendary_xern_yvel": "XY Xerneas & Yveltal Battle",
"battle_legendary_tapu": "SM Tapu Battle",
"battle_legendary_sol_lun": "SM Solgaleo & Lunala Battle",
"battle_legendary_ub": "SM Ultra Beast Battle",
"battle_legendary_dusk_dawn": "USUM Dusk Mane & Dawn Wings Necrozma Battle",
"battle_legendary_ultra_nec": "USUM Ultra Necrozma Battle",
"battle_legendary_zac_zam": "SWSH Zacian & Zamazenta Battle",
"battle_legendary_glas_spec": "SWSH Glastrier & Spectrier Battle",
"battle_legendary_calyrex": "SWSH Calyrex Battle",
"battle_legendary_birds_galar": "SWSH Galarian Legendary Birds Battle",
"battle_legendary_ruinous": "SV Treasures of Ruin Battle",
"battle_legendary_loyal_three": "SV Loyal Three Battle",
"battle_legendary_ogerpon": "SV Ogerpon Battle",
"battle_legendary_terapagos": "SV Terapagos Battle",
"battle_legendary_pecharunt": "SV Pecharunt Battle",
"battle_rival": "BW Rival Battle",
"battle_rival_2": "BW N Battle",
"battle_rival_3": "BW Final N Battle",
"battle_trainer": "BW Trainer Battle",
"battle_wild": "BW Wild Battle",
"battle_wild_strong": "BW Strong Wild Battle",
"end_summit": "PMD RTDX Sky Tower Summit",
"battle_rocket_grunt": "HGSS Team Rocket Battle",
"battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle",
"battle_galactic_grunt": "BDSP Team Galactic Battle",
"battle_plasma_grunt": "BW Team Plasma Battle",
"battle_flare_grunt": "XY Team Flare Battle",
"battle_rocket_boss": "USUM Giovanni Battle",
"battle_aqua_magma_boss": "ORAS Archie & Maxie Battle",
"battle_galactic_boss": "BDSP Cyrus Battle",
"battle_plasma_boss": "B2W2 Ghetsis Battle",
"battle_flare_boss": "XY Lysandre Battle",
// Biome Music
"abyss": "PMD EoS Dark Crater",
"badlands": "PMD EoS Barren Valley",
"beach": "PMD EoS Drenched Bluff",
"cave": "PMD EoS Sky Peak Cave",
"construction_site": "PMD EoS Boulder Quarry",
"desert": "PMD EoS Northern Desert",
"dojo": "PMD EoS Marowa Dojo",
"end": "PMD RTDX Sky Tower",
"factory": "PMD EoS Concealed Ruins",
"fairy_cave": "PMD EoS Star Cave",
"forest": "PMD EoS Dusk Forest",
"grass": "PMD EoS Apple Woods",
"graveyard": "PMD EoS Mystifying Forest",
"ice_cave": "PMD EoS Vast Ice Mountain",
"island": "PMD EoS Craggy Coast",
//"jungle": "jungle", // The composer thinks about a more creative name
//"labratory": "labratory", // The composer thinks about a more creative name
"lake": "PMD EoS Crystal Cave",
"meadow": "PMD EoS Sky Peak Forest",
//"metropolis": "metropolis", // The composer thinks about a more creative name
"mountain": "PMD EoS Mt. Horn",
"plains": "PMD EoS Sky Peak Prairie",
"power_plant": "PMD EoS Far Amp Plains",
"ruins": "PMD EoS Deep Sealed Ruin",
"sea": "PMD EoS Brine Cave",
"seabed": "PMD EoS Lower Brine Cave",
"slum": "PMD EoS Sky Peak Coast",
"snowy_forest": "PMD EoS Sky Peak Snowfield",
"space": "PMD EoS Fortune Ravine",
"swamp": "PMD EoS Surrounded Sea",
"tall_grass": "PMD EoS Foggy Forest",
"temple": "PMD EoS Aegis Cave",
"town": "PMD EoS Random Dungeon Theme 3",
"volcano": "PMD EoS Steam Cave",
"wasteland": "PMD EoS Hidden Highland",
// Encounter
"encounter_ace_trainer": "BW Trainers' Eyes Meet (Ace Trainer)",
"encounter_backpacker": "BW Trainers' Eyes Meet (Backpacker)",
"encounter_clerk": "BW Trainers' Eyes Meet (Clerk)",
"encounter_cyclist": "BW Trainers' Eyes Meet (Cyclist)",
"encounter_lass": "BW Trainers' Eyes Meet (Lass)",
"encounter_parasol_lady": "BW Trainers' Eyes Meet (Parasol Lady)",
"encounter_pokefan": "BW Trainers' Eyes Meet (Poke Fan)",
"encounter_psychic": "BW Trainers' Eyes Meet (Psychic)",
"encounter_rich": "BW Trainers' Eyes Meet (Gentleman)",
"encounter_rival": "BW Cheren",
"encounter_roughneck": "BW Trainers' Eyes Meet (Roughneck)",
"encounter_scientist": "BW Trainers' Eyes Meet (Scientist)",
"encounter_twins": "BW Trainers' Eyes Meet (Twins)",
"encounter_youngster": "BW Trainers' Eyes Meet (Youngster)",
// Other
"heal": "BW Pokémon Heal",
"menu": "PMD EoS Welcome to the World of Pokémon!",
"title": "PMD EoS Top Menu Theme",
} as const;

View File

@ -6,6 +6,7 @@ import { PGFachv, PGMachv } from "./achv";
import { battle } from "./battle"; import { battle } from "./battle";
import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battleMessageUiHandler } from "./battle-message-ui-handler";
import { berry } from "./berry"; import { berry } from "./berry";
import { bgmName } from "./bgm-name";
import { biome } from "./biome"; import { biome } from "./biome";
import { challenges } from "./challenges"; import { challenges } from "./challenges";
import { commandUiHandler } from "./command-ui-handler"; import { commandUiHandler } from "./command-ui-handler";
@ -48,6 +49,7 @@ export const enConfig = {
battle: battle, battle: battle,
battleMessageUiHandler: battleMessageUiHandler, battleMessageUiHandler: battleMessageUiHandler,
berry: berry, berry: berry,
bgmName: bgmName,
biome: biome, biome: biome,
challenges: challenges, challenges: challenges,
commandUiHandler: commandUiHandler, commandUiHandler: commandUiHandler,

View File

@ -477,7 +477,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
}, },
"aqua_boss_archie_1": { "aqua_boss_archie_1": {
"encounter": { "encounter": {
1: "I'm leader of Team Aqua, so I'm afraid it's the rope's end for you." 1: "I'm the leader of Team Aqua, so I'm afraid it's the rope's end for you."
}, },
"victory": { "victory": {
1: "Let's meet again somewhere. I'll be sure to remember that face." 1: "Let's meet again somewhere. I'll be sure to remember that face."

View File

@ -17,5 +17,9 @@ export const egg: SimpleTranslationEntries = {
"notEnoughVouchers": "You don't have enough vouchers!", "notEnoughVouchers": "You don't have enough vouchers!",
"tooManyEggs": "You have too many eggs!", "tooManyEggs": "You have too many eggs!",
"pull": "Pull", "pull": "Pull",
"pulls": "Pulls" "pulls": "Pulls",
"sameSpeciesEgg": "{{species}} will hatch from this egg!",
"hatchFromTheEgg": "{{pokemonName}} hatched from the egg!",
"eggMoveUnlock": "Egg Move unlocked: {{moveName}}",
"rareEggMoveUnlock": "Rare Egg Move unlocked: {{moveName}}",
} as const; } as const;

View File

@ -19,5 +19,6 @@ export const menuUiHandler: SimpleTranslationEntries = {
"importData": "Import Data", "importData": "Import Data",
"exportData": "Export Data", "exportData": "Export Data",
"cancel": "Cancel", "cancel": "Cancel",
"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!"
} as const; } as const;

View File

@ -53,4 +53,5 @@ export const menu: SimpleTranslationEntries = {
"no":"No", "no":"No",
"disclaimer": "DISCLAIMER", "disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed.", "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed.",
"choosePokemon": "Choose a Pokémon.",
} as const; } as const;

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "Soothe Bell" }, "SOOTHE_BELL": { name: "Soothe Bell" },
"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." },
"SOUL_DEW": { name: "Soul Dew", description: "Increases the influence of a Pokémon's nature on its stats by 10% (additive)." }, "SOUL_DEW": { name: "Soul Dew", description: "Increases the influence of a Pokémon's nature on its stats by 10% (additive)." },
"NUGGET": { name: "Nugget" }, "NUGGET": { name: "Nugget" },

View File

@ -94,5 +94,6 @@ export const settings: SimpleTranslationEntries = {
"alt": " (Alt)", "alt": " (Alt)",
"mute": "Mute", "mute": "Mute",
"controller": "Controller", "controller": "Controller",
"gamepadSupport": "Gamepad Support" "gamepadSupport": "Gamepad Support",
"showBgmBar": "Show Music Names",
} as const; } as const;

View File

@ -31,6 +31,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"selectMoveSwapWith": "Select a move to swap with", "selectMoveSwapWith": "Select a move to swap with",
"unlockPassive": "Unlock Passive", "unlockPassive": "Unlock Passive",
"reduceCost": "Reduce Cost", "reduceCost": "Reduce Cost",
"sameSpeciesEgg": "Buy an Egg",
"cycleShiny": ": Shiny", "cycleShiny": ": Shiny",
"cycleForm": ": Form", "cycleForm": ": Form",
"cycleGender": ": Gender", "cycleGender": ": Gender",

View File

@ -3,6 +3,9 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "¡{{abilityName}} de {{pokemonName}}\nlo protegió del daño de retroceso!", "blockRecoilDamage" : "¡{{abilityName}} de {{pokemonName}}\nlo protegió del daño de retroceso!",
"badDreams": "¡{{pokemonName}} está atormentado!", "badDreams": "¡{{pokemonName}} está atormentado!",
"costar": "{{pokemonName}} copied {{allyName}}'s stat changes!",
"iceFaceAvoidedDamage": "¡{{pokemonNameWithAffix}} evitó\ndaño con {{abilityName}}!",
"trace": "{{pokemonName}} copied {{targetName}}'s\n{{abilityName}}!",
"windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!", "windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!",
"iceFaceAvoidedDamage": "¡{{pokemonNameWithAffix}} evitó\ndaño con {{abilityName}}!" "quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
} as const; } as const;

View File

@ -15,6 +15,7 @@ export const battle: SimpleTranslationEntries = {
"trainerDefeated": "¡Has derrotado a\n{{trainerName}}!", "trainerDefeated": "¡Has derrotado a\n{{trainerName}}!",
"moneyWon": "¡Has ganado\n₽{{moneyAmount}} por vencer!", "moneyWon": "¡Has ganado\n₽{{moneyAmount}} por vencer!",
"pokemonCaught": "¡{{pokemonName}} atrapado!", "pokemonCaught": "¡{{pokemonName}} atrapado!",
"addedAsAStarter": "{{pokemonName}} ha sido añadido\na tus iniciales!",
"partyFull": "Tu equipo esta completo.\n¿Quieres liberar un Pokémon para meter a {{pokemonName}}?", "partyFull": "Tu equipo esta completo.\n¿Quieres liberar un Pokémon para meter a {{pokemonName}}?",
"pokemon": "Pokémon", "pokemon": "Pokémon",
"sendOutPokemon": "¡Adelante, {{pokemonName}}!", "sendOutPokemon": "¡Adelante, {{pokemonName}}!",
@ -53,6 +54,8 @@ export const battle: SimpleTranslationEntries = {
"escapeVerbSwitch": "cambiar", "escapeVerbSwitch": "cambiar",
"escapeVerbFlee": "huir", "escapeVerbFlee": "huir",
"notDisabled": "¡El movimiento {{moveName}} de {{pokemonName}}\nya no está anulado!", "notDisabled": "¡El movimiento {{moveName}} de {{pokemonName}}\nya no está anulado!",
"turnEndHpRestore": "{{pokemonName}}'s HP was restored.",
"hpIsFull": "{{pokemonName}}'s\nHP is full!",
"skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?", "skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?",
"eggHatching": "¿Y esto?", "eggHatching": "¿Y esto?",
"ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?", "ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?",
@ -62,18 +65,18 @@ export const battle: SimpleTranslationEntries = {
"drainMessage": "¡{{pokemonName}} tuvo su\nenergía absorbida!", "drainMessage": "¡{{pokemonName}} tuvo su\nenergía absorbida!",
"regainHealth": "¡{{pokemonName}} recuperó\nPS!", "regainHealth": "¡{{pokemonName}} recuperó\nPS!",
"fainted": "¡{{pokemonNameWithAffix}} se debilitó!", "fainted": "¡{{pokemonNameWithAffix}} se debilitó!",
"statRose": "rose", "statRose": "¡El {{stats}} de {{pokemonNameWithAffix}} ha subido!",
"statSharplyRose": "sharply rose", "statSharplyRose": "¡El {{stats}} de {{pokemonNameWithAffix}} ha subido mucho!",
"statRoseDrastically": "rose drastically", "statRoseDrastically": "¡El {{stats}} de {{pokemonNameWithAffix}} ha subido muchísimo!",
"statWontGoAnyHigher": "won't go any higher", "statWontGoAnyHigher": "¡El {{stats}} de {{pokemonNameWithAffix}} no puede subir más!",
"statFell": "fell", "statFell": "¡El {{stats}} de {{pokemonNameWithAffix}} ha bajado!",
"statHarshlyFell": "harshly fell", "statHarshlyFell": "¡El {{stats}} de {{pokemonNameWithAffix}}} ha bajado mucho!",
"statSeverelyFell": "severely fell", "statSeverelyFell": "¡El {{stats}} de {{pokemonNameWithAffix}} ha bajado muchísimo!",
"statWontGoAnyLower": "won't go any lower", "statWontGoAnyLower": "¡El {{stats}} de {{pokemonNameWithAffix}} no puede bajar más!",
"ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!",
"battlerTagsRechargingLapse": "{{pokemonNameWithAffix}} must\nrecharge!", "battlerTagsRechargingLapse": "{{pokemonNameWithAffix}} must\nrecharge!",
"battlerTagsTrappedOnAdd": "{{pokemonNameWithAffix}} can no\nlonger escape!", "battlerTagsTrappedOnAdd": "{{pokemonNameWithAffix}} can no\nlonger escape!",
"battlerTagsTrappedOnRemove": "{{pokemonNameWithAffix}} was freed\nfrom {{moveName}}", "battlerTagsTrappedOnRemove": "{{pokemonNameWithAffix}} was freed\nfrom {{moveName}}!",
"battlerTagsFlinchedLapse": "{{pokemonNameWithAffix}} flinched!", "battlerTagsFlinchedLapse": "{{pokemonNameWithAffix}} flinched!",
"battlerTagsConfusedOnAdd": "{{pokemonNameWithAffix}} became\nconfused!", "battlerTagsConfusedOnAdd": "{{pokemonNameWithAffix}} became\nconfused!",
"battlerTagsConfusedOnRemove": "{{pokemonNameWithAffix}} snapped\nout of confusion!", "battlerTagsConfusedOnRemove": "{{pokemonNameWithAffix}} snapped\nout of confusion!",

144
src/locales/es/bgm-name.ts Normal file
View File

@ -0,0 +1,144 @@
import { SimpleTranslationEntries } from "#app/interfaces/locales";
export const bgmName: SimpleTranslationEntries = {
"music": "Música",
"missing_entries" : "{{name}}",
"battle_kanto_champion": "B2W2 - ¡Vs Campeón de Kanto!",
"battle_johto_champion": "B2W2 - ¡Vs Campeón de Johto!",
"battle_hoenn_champion": "B2W2 - ¡Vs Campeón de Hoenn!",
"battle_sinnoh_champion": "B2W2 - ¡Vs Campeón de Sinnoh!",
"battle_champion_alder": "BW - ¡Vs Campeón de Teselia!",
"battle_champion_iris": "B2W2 - ¡Vs Campeón de Teselia!",
"battle_kalos_champion": "XY - ¡Vs Campeón de Kalos!",
"battle_alola_champion": "USUM - ¡Vs Campeón de Alola!",
"battle_galar_champion": "SWSH - ¡Vs Campeón de Galar!",
"battle_champion_geeta": "SV - ¡Vs Campeona Ságita!",
"battle_champion_nemona": "SV - ¡Vs Campeona Mencía!",
"battle_champion_kieran": "SV - ¡Vs Campeón Cass!",
"battle_hoenn_elite": "ORAS - ¡Vs Alto Mando!",
"battle_unova_elite": "BW - ¡Vs Alto Mando!",
"battle_kalos_elite": "XY - ¡Vs Alto Mando!",
"battle_alola_elite": "SM - ¡Vs Alto Mando!",
"battle_galar_elite": "SWSH - Torneo de Finalistas",
"battle_paldea_elite": "SV - ¡Vs Alto Mando!",
"battle_bb_elite": "SV - ¡Vs Alto Mando de la Academia Arándano!",
"battle_final_encounter": "PMD RTDX - Dominio de Rayquaza",
"battle_final": "BW - ¡Vs Ghechis!",
"battle_kanto_gym": "B2W2 - ¡Vs Líder de Kanto!",
"battle_johto_gym": "B2W2 - ¡Vs Líder de Johto!",
"battle_hoenn_gym": "B2W2 - ¡Vs Líder de Hoenn!",
"battle_sinnoh_gym": "B2W2 - ¡Vs Líder de Sinnoh!",
"battle_unova_gym": "BW - ¡Vs Líder de Teselia!",
"battle_kalos_gym": "XY - ¡Vs Líder de Kalos!",
"battle_galar_gym": "SWSH - ¡Vs Líder de Galar!",
"battle_paldea_gym": "SV - ¡Vs Líder de Paldea!",
"battle_legendary_kanto": "XY - ¡Vs Legendarios de Kanto!",
"battle_legendary_raikou": "HGSS - ¡Vs Raikou!",
"battle_legendary_entei": "HGSS - ¡Vs Entei!",
"battle_legendary_suicune": "HGSS - ¡Vs Suicune!",
"battle_legendary_lugia": "HGSS - ¡Vs Lugia!",
"battle_legendary_ho_oh": "HGSS - ¡Vs Ho-oh!",
"battle_legendary_regis_g5": "B2W2 - ¡Vs Regis!",
"battle_legendary_regis_g6": "ORAS - ¡Vs Regis!",
"battle_legendary_gro_kyo": "ORAS - ¡Vs Groudon/Kyogre!",
"battle_legendary_rayquaza": "ORAS - ¡Vs Rayquaza!",
"battle_legendary_deoxys": "ORAS - ¡Vs Deoxys!",
"battle_legendary_lake_trio": "ORAS - ¡Vs Trío del Lago!",
"battle_legendary_sinnoh": "ORAS - ¡Vs Legendarios de Sinnoh!",
"battle_legendary_dia_pal": "ORAS - ¡Vs Dialga/Palkia!",
"battle_legendary_giratina": "ORAS - ¡Vs Giratina!",
"battle_legendary_arceus": "HGSS - ¡Vs Arceus!",
"battle_legendary_unova": "BW - ¡Vs Legendarios de Teselia!",
"battle_legendary_kyurem": "BW - ¡Vs Kyurem!",
"battle_legendary_res_zek": "BW - ¡Vs Reshiram/Zekrom!",
"battle_legendary_xern_yvel": "XY - ¡Vs Xerneas/Yveltal!",
"battle_legendary_tapu": "SM - ¡Vs Tapus!",
"battle_legendary_sol_lun": "SM - ¡Vs Solgaleo/Lunala!",
"battle_legendary_ub": "SM - ¡Vs Ultraentes!",
"battle_legendary_dusk_dawn": "USUM - ¡Vs Necrozma Melena Crepuscular/Alas del Alba!",
"battle_legendary_ultra_nec": "USUM - ¡Vs Ultra-Necrozma!",
"battle_legendary_zac_zam": "SWSH - ¡Vs Zacian/Zamazenta!",
"battle_legendary_glas_spec": "SWSH - ¡Vs Glastrier/Spectrier!",
"battle_legendary_calyrex": "SWSH - ¡Vs Calyrex!",
"battle_legendary_birds_galar": "SWSH - ¡Vs Aves Legendarias de Galar!",
"battle_legendary_ruinous": "SV - ¡Vs Tesoros Funestos!",
"battle_legendary_loyal_three": "SV - ¡Vs Compatrones!",
"battle_legendary_ogerpon": "SV - ¡Vs Ogerpon!",
"battle_legendary_terapagos": "SV - ¡Vs Terapagos!",
"battle_legendary_pecharunt": "SV - ¡Vs Pecharunt!",
"battle_rival": "BW - ¡Vs Rival!",
"battle_rival_2": "BW - ¡Vs N!",
"battle_rival_3": "BW - ¡Vs N (Liga Pokémon)!",
"battle_trainer": "BW - ¡Vs Entrenador!",
"battle_wild": "BW - ¡Vs Pokémon Salvaje!",
"battle_wild_strong": "BW - ¡Vs Pokémon Salvaje Raro!",
"end_summit": "PMD RTDX - Techo del Cielo",
"battle_rocket_grunt": "HGSS Team Rocket Battle",
"battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle",
"battle_galactic_grunt": "BDSP Team Galactic Battle",
"battle_plasma_grunt": "BW - ¡Vs Equipo Plasma!",
"battle_flare_grunt": "XY Team Flare Battle",
"battle_rocket_boss": "USUM Giovanni Battle",
"battle_aqua_magma_boss": "ORAS Archie & Maxie Battle",
"battle_galactic_boss": "BDSP Cyrus Battle",
"battle_plasma_boss": "B2W2 Ghetsis Battle",
"battle_flare_boss": "XY Lysandre Battle",
// Biome Music
"abyss": "PMD EoS - Cráter Oscuro",
"badlands": "PMD EoS - Valle Desolado",
"beach": "PMD EoS - Risco Calado",
"cave": "PMD EoS - Cueva de la Cumbre del Cielo",
"construction_site": "PMD EoS - Roquedal",
"desert": "PMD EoS - Desierto Norte",
"dojo": "PMD EoS - Dojo Marowak",
"end": "PMD RTDX - Torre del Cielo",
"factory": "PMD EoS - Ruinas Camufladas",
"fairy_cave": "PMD EoS - Cueva Estrella",
"forest": "PMD EoS - Bosque Sombrío",
"grass": "PMD EoS - Manzanar",
"graveyard": "PMD EoS - Bosque Misterio",
"ice_cave": "PMD EoS - Gran Iceberg",
"island": "PMD EoS - Costa Escarpada",
//"jungle": "jungle", // The composer thinks about a more creative name
//"labratory": "labratory", // The composer thinks about a more creative name
"lake": "PMD EoS - Cueva Cristal",
"meadow": "PMD EoS - Bosque de la Cumbre del Cielo",
//"metropolis": "metropolis", // The composer thinks about a more creative name
"mountain": "PMD EoS - Monte Cuerno",
"plains": "PMD EoS - Pradera de la Cumbre del Cielo",
"power_plant": "PMD EoS - Pradera Destello",
"ruins": "PMD EoS - Sima Hermética",
"sea": "PMD EoS - Cueva Aguamar",
"seabed": "PMD EoS - Fosa Aguamar",
"slum": "PMD EoS - Costa de la Cumbre del Cielo",
"snowy_forest": "PMD EoS - Campo nevado de la Cumbre del Cielo",
"space": "PMD EoS - Risco Fortuna",
"swamp": "PMD EoS - Mar Circundante",
"tall_grass": "PMD EoS - Bosque Niebla",
"temple": "PMD EoS - Cueva Regia",
"town": "PMD EoS - Tema del territorio aleatorio 3",
"volcano": "PMD EoS - Cueva Vapor",
"wasteland": "PMD EoS - Corazón Tierra Oculta",
// Encounter
"encounter_ace_trainer": "BW - Desafío Combate (Entrenador Guay)",
"encounter_backpacker": "BW - Desafío Combate (Mochilero)",
"encounter_clerk": "BW - Desafío Combate (Empresario)",
"encounter_cyclist": "BW - Desafío Combate (Ciclista)",
"encounter_lass": "BW - Desafío Combate (Chica)",
"encounter_parasol_lady": "BW - Desafío Combate (Dama parasol)",
"encounter_pokefan": "BW - Desafío Combate (Pokéfan)",
"encounter_psychic": "BW - Desafío Combate (Médium)",
"encounter_rich": "BW - Desafío Combate (Aristócrata)",
"encounter_rival": "BW - Desafío Combate (Cheren)",
"encounter_roughneck": "BW - Desafío Combate (Calvo)",
"encounter_scientist": "BW - Desafío Combate (Científico)",
"encounter_twins": "BW - Desafío Combate (Gemelas)",
"encounter_youngster": "BW - Desafío Combate (Joven)",
// Other
"heal": "BW - Cura Pokémon",
"menu": "PMD EoS - ¡Bienvenidos al mundo de los Pokémon!",
"title": "PMD EoS - Tema del menú principal",
} as const;

View File

@ -4,6 +4,7 @@ import { PGFachv, PGMachv } from "./achv";
import { battle } from "./battle"; import { battle } from "./battle";
import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battleMessageUiHandler } from "./battle-message-ui-handler";
import { berry } from "./berry"; import { berry } from "./berry";
import { bgmName } from "./bgm-name";
import { biome } from "./biome"; import { biome } from "./biome";
import { challenges } from "./challenges"; import { challenges } from "./challenges";
import { commandUiHandler } from "./command-ui-handler"; import { commandUiHandler } from "./command-ui-handler";
@ -48,6 +49,7 @@ export const esConfig = {
battle: battle, battle: battle,
battleMessageUiHandler: battleMessageUiHandler, battleMessageUiHandler: battleMessageUiHandler,
berry: berry, berry: berry,
bgmName: bgmName,
biome: biome, biome: biome,
challenges: challenges, challenges: challenges,
commandUiHandler: commandUiHandler, commandUiHandler: commandUiHandler,

View File

@ -383,6 +383,186 @@ export const PGMdialogue: DialogueTranslationEntries = {
3: "Creo que soy yo quien está mareado..." 3: "Creo que soy yo quien está mareado..."
}, },
}, },
"rocket_grunt": {
"encounter": {
1: "¡Ríndete ahora, o prepárate para luchar!"
},
"victory": {
1: "¡El Team Rocket despega de nuevo!"
},
},
"magma_grunt": {
"encounter": {
1: "¡No esperes piedad si te interpones al Team Magma!"
},
"victory": {
1: "¿Eh? ¿He perdido?"
},
},
"aqua_grunt": {
"encounter": {
1: "El Team Aqua no muestra piedad, ¡ni siquiera a los niños!"
},
"victory": {
1: "¡Bromeas! ¡No me lo creo!"
},
},
"galactic_grunt": {
"encounter": {
1: "¡No desafíes al Equipo Galaxia, te arrepentirás!"
},
"victory": {
1: "Me callaste la boca..."
},
},
"plasma_grunt": {
"encounter": {
1: "¡El Equipo Plasma no tolerará otros ideales!"
},
"victory": {
1: "Plasmaaaaaaaaa!"
},
},
"flare_grunt": {
"encounter": {
1: "¡La moda es lo más importante para nosotros!"
},
"victory": {
1: "Me temo que se me avecina un futuro oscuro..."
},
},
"rocket_boss_giovanni_1": {
"encounter": {
1: "He de decir... estoy impresionado de que hayas llegado tan lejos."
},
"victory": {
1: "¿¡QUÉ?! ¡No puede ser!"
},
"defeat": {
1: "Recuerda mis palabras: Que no seas capaz de medir\n tu propia fuerza demuestra que todavía eres un niño"
}
},
"rocket_boss_giovanni_2": {
"encounter": {
1: "Mis antiguos socios me necesitan... ¿te atreves a imponerte en mi camino?"
},
"victory": {
1: "¿Cómo es esto posible?\nEl sueño del Team Rocket, ahora tan solo una mera ilusión..."
},
"defeat": {
1: "El Team Rocket renacerá... ¡y gobernaré el mundo!"
}
},
"magma_boss_maxie_1": {
"encounter": {
1: "Está bien, tendré que cavar yo mismo tu propia tumba. Siéntete orgulloso."
},
"victory": {
1: "Ugh! Eres... muy capaz...\nFue por poco, estuve a esto de ganarte..."
},
"defeat": {
1: "¡El Equipo Magma prevalecerá!"
}
},
"magma_boss_maxie_2": {
"encounter": {
1: "Eres el obstáculo final entre mi y mis propósitos.\n¡Aquí va mi mejor golpe! ¡MUAJAJAJA!"
},
"victory": {
1: "No... no es posib... nnngh..."
},
"defeat": {
1: "Y ahora... transformaré este planeta en una tierra ideal para la humanidad."
}
},
"aqua_boss_archie_1": {
"encounter": {
1: "Soy el líder del Equipo Aqua, así que me temo que aquí se acaba tu bromita."
},
"victory": {
1: "Volvamos a vernos más tarde. Recordaré tu cara."
},
"defeat": {
1: "¡Excelente! ¡Nadie se puede oponer a mi equipo!"
}
},
"aqua_boss_archie_2": {
"encounter": {
1: "Llevo esperando mucho que llegara este día.\n¡Contempla el poder de mi equipo!"
},
"victory": {
1: "Quién me lo iba a decir..."
},
"defeat": {
1: "Devolveré todo en este planeta a su estado original.\nSe avecina un nuevo mundo, ¡más puro!"
}
},
"galactic_boss_cyrus_1": {
"encounter": {
1: "Tu fútil sentimentalidad te hizo interferir.\n¡Haré que te arrepientas de escuchar a tu corazón!"
},
"victory": {
1: "Interesante. Muy... curioso."
},
"defeat": {
1: "Crearé un nuevo mundo..."
}
},
"galactic_boss_cyrus_2": {
"encounter": {
1: "Nos vemos de nuevo... se ve que nuestros destinos están entrelazados.\nPero, aquí y ahora, ¡sesgaré ese vínculo!"
},
"victory": {
1: "¿Cómo? ¿¡Cómo!? ¿¡¡CÓMO!!?"
},
"defeat": {
1: "Hasta nunca."
}
},
"plasma_boss_ghetsis_1": {
"encounter": {
1: "¡No permitiré que nadie me detenga!"
},
"victory": {
1: "¿Cómo puede ser esto? ¡yo creé al Equipo Plasma!\n¡Soy PERFECTO!"
},
"defeat": {
1: "Soy el perfecto gobernante para un perfecto nuevo mundo. ¡Muajajajaja!"
}
},
"plasma_boss_ghetsis_2": {
"encounter": {
1: "¡Adelante! ¡Quiero ver tu cara cuando la desesperación se apoderede de ti!"
},
"victory": {
1: "Mis planes... ¡no! ¡El mundo debería pertenecerme!"
},
"defeat": {
1: "¡Kyurem, Absorfusión... ahora!"
}
},
"flare_boss_lysandre_1": {
"encounter": {
1: "¿Acaso quieres detenerme? Demuéstramelo."
},
"victory": {
1: "Estás aquí para detenerme. Pero tendrás que esperar. "
},
"defeat": {
1: "Los Pokémon... su fin ha llegado."
}
},
"flare_boss_lysandre_2": {
"encounter": {
1: "El futuro que quieres tú, o el futuro que quiero yo.\nVeamos cuál de los dos se merece existir..."
},
"victory": {
1: "¡AARGH!"
},
"defeat": {
1: "Los idiotas sin ningún tipo de visión continuarán asediando este mundo."
}
},
"brock": { "brock": {
"encounter": { "encounter": {
1: "My expertise on Rock-type Pokémon will take you down! Come on!", 1: "My expertise on Rock-type Pokémon will take you down! Come on!",

View File

@ -17,5 +17,9 @@ export const egg: SimpleTranslationEntries = {
"notEnoughVouchers": "¡No tienes suficientes vales!", "notEnoughVouchers": "¡No tienes suficientes vales!",
"tooManyEggs": "¡No tienes suficiente espacio!", "tooManyEggs": "¡No tienes suficiente espacio!",
"pull": "Tirada", "pull": "Tirada",
"pulls": "Tiradas" "pulls": "Tiradas",
"sameSpeciesEgg": "{{species}} will hatch from this egg!",
"hatchFromTheEgg": "¡Ha salido un {{pokemonName}} del Huevo!",
"eggMoveUnlock": "Mov. Huevo desbloqueado:\n{{moveName}}",
"rareEggMoveUnlock": "Mov. Huevo Raro desbloqueado:\n{{moveName}}",
} as const; } as const;

View File

@ -19,5 +19,6 @@ export const menuUiHandler: SimpleTranslationEntries = {
"importData": "Importar Datos", "importData": "Importar Datos",
"exportData": "Exportar Datos", "exportData": "Exportar Datos",
"cancel": "Cancelar", "cancel": "Cancelar",
"losingProgressionWarning": "Perderás cualquier progreso desde el inicio de la batalla. ¿Continuar?" "losingProgressionWarning": "Perderás cualquier progreso desde el inicio de la batalla. ¿Continuar?",
"noEggs": "You are not hatching\nany eggs at the moment!"
} as const; } as const;

View File

@ -53,4 +53,5 @@ export const menu: SimpleTranslationEntries = {
"no":"No", "no":"No",
"disclaimer": "AVISO", "disclaimer": "AVISO",
"disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida\n de datos de guardado),cambiar sin avisar, y puede o no puede ser actualizado hasta ser completado.", "disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida\n de datos de guardado),cambiar sin avisar, y puede o no puede ser actualizado hasta ser completado.",
"choosePokemon": "Choose a Pokémon.",
} as const; } as const;

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "Camp. Alivio" }, "SOOTHE_BELL": { name: "Camp. Alivio" },
"EVIOLITE": { name: "Mineral Evolutivo", description: "Roca misteriosa. El Pokémon portador aumentará su Defensa y su Defensa Especial si aún puede evolucionar." },
"SOUL_DEW": { name: "Rocío bondad", description: "Aumenta la influencia de la naturaleza de un Pokémon en sus estadísticas en un 10% (aditivo)." }, "SOUL_DEW": { name: "Rocío bondad", description: "Aumenta la influencia de la naturaleza de un Pokémon en sus estadísticas en un 10% (aditivo)." },
"NUGGET": { name: "Pepita" }, "NUGGET": { name: "Pepita" },

View File

@ -94,5 +94,6 @@ export const settings: SimpleTranslationEntries = {
"alt": " (Alt)", "alt": " (Alt)",
"mute": "Mute", "mute": "Mute",
"controller": "Controller", "controller": "Controller",
"gamepadSupport": "Gamepad Support" "gamepadSupport": "Gamepad Support",
"showBgmBar": "Show Music Names",
} as const; } as const;

View File

@ -31,6 +31,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"selectMoveSwapWith": "Elige el movimiento que sustituirá a", "selectMoveSwapWith": "Elige el movimiento que sustituirá a",
"unlockPassive": "Añadir Pasiva", "unlockPassive": "Añadir Pasiva",
"reduceCost": "Reducir Coste", "reduceCost": "Reducir Coste",
"sameSpeciesEgg": "Buy an Egg",
"cycleShiny": ": Shiny", "cycleShiny": ": Shiny",
"cycleForm": ": Forma", "cycleForm": ": Forma",
"cycleGender": ": Género", "cycleGender": ": Género",

View File

@ -3,8 +3,11 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !", "blockRecoilDamage" : "{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !",
"badDreams": "{{pokemonName}} a le sommeil agité !", "badDreams": "{{pokemonName}} a le sommeil agité !",
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !", "costar": "{{pokemonName}} copie les changements de stats\nde {{allyName}} !",
"iceFaceAvoidedDamage": "{{pokemonName}} évite les dégâts\navec {{abilityName}} !",
"perishBody": "{{abilityName}} de {{pokemonName}}\nmettra les deux Pokémon K.O. dans trois tours !", "perishBody": "{{abilityName}} de {{pokemonName}}\nmettra les deux Pokémon K.O. dans trois tours !",
"poisonHeal": "{{abilityName}} de {{pokemonName}}\nrestaure un peu ses PV !", "poisonHeal": "{{abilityName}} de {{pokemonName}}\nrestaure un peu ses PV !",
"iceFaceAvoidedDamage": "{{pokemonName}} évite les dégâts\navec {{abilityName}} !" "trace": "{{pokemonName}} copie le talent {{abilityName}}\nde {{targetName}} !",
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !",
"quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
} as const; } as const;

View File

@ -15,6 +15,7 @@ export const battle: SimpleTranslationEntries = {
"trainerDefeated": "Vous avez battu\n{{trainerName}} !", "trainerDefeated": "Vous avez battu\n{{trainerName}} !",
"moneyWon": "Vous remportez\n{{moneyAmount}} ₽ !", "moneyWon": "Vous remportez\n{{moneyAmount}} ₽ !",
"pokemonCaught": "Vous avez attrapé {{pokemonName}} !", "pokemonCaught": "Vous avez attrapé {{pokemonName}} !",
"addedAsAStarter": "{{pokemonName}} est ajouté\ncomme starter !",
"partyFull": "Votre équipe est pleine.\nRelâcher un Pokémon pour {{pokemonName}} ?", "partyFull": "Votre équipe est pleine.\nRelâcher un Pokémon pour {{pokemonName}} ?",
"pokemon": "Pokémon", "pokemon": "Pokémon",
"sendOutPokemon": "{{pokemonName}} ! Go !", "sendOutPokemon": "{{pokemonName}} ! Go !",
@ -53,6 +54,8 @@ export const battle: SimpleTranslationEntries = {
"escapeVerbSwitch": "le changement", "escapeVerbSwitch": "le changement",
"escapeVerbFlee": "la fuite", "escapeVerbFlee": "la fuite",
"notDisabled": "La capacité {{moveName}}\nde {{pokemonName}} nest plus sous entrave !", "notDisabled": "La capacité {{moveName}}\nde {{pokemonName}} nest plus sous entrave !",
"turnEndHpRestore": "{{pokemonName}} récupère des PV !",
"hpIsFull": "Les PV de {{pokemonName}}\nsont au maximum !",
"skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre dobjet ?", "skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre dobjet ?",
"eggHatching": "Hein ?", "eggHatching": "Hein ?",
"ivScannerUseQuestion": "Utiliser le Scanner dIV sur {{pokemonName}} ?", "ivScannerUseQuestion": "Utiliser le Scanner dIV sur {{pokemonName}} ?",
@ -62,15 +65,15 @@ export const battle: SimpleTranslationEntries = {
"drainMessage": "Lénergie de {{pokemonName}}\nest drainée !", "drainMessage": "Lénergie de {{pokemonName}}\nest drainée !",
"regainHealth": "{{pokemonName}} récupère\ndes PV !", "regainHealth": "{{pokemonName}} récupère\ndes PV !",
"fainted": "{{pokemonNameWithAffix}}\nest K.O. !", "fainted": "{{pokemonNameWithAffix}}\nest K.O. !",
"statRose": "augmente", "statRose": "{{stats}} de {{pokemonNameWithAffix}}\naugmente !",
"statSharplyRose": "augmente beaucoup", "statSharplyRose": "{{stats}} de {{pokemonNameWithAffix}}\naugmente beaucoup !",
"statRoseDrastically": "augmente énormément", "statRoseDrastically": "{{stats}} de {{pokemonNameWithAffix}}\naugmente énormément !",
"statWontGoAnyHigher": "ne peut plus augmenter", "statWontGoAnyHigher": "{{stats}} de {{pokemonNameWithAffix}}\nne peut plus augmenter !",
"statFell": "baisse", "statFell": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse !",
"statHarshlyFell": "baisse beaucoup", "statHarshlyFell": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse beaucoup !",
"statSeverelyFell": "baisse énormément", "statSeverelyFell": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse énormément !",
"statWontGoAnyLower": "ne peut plus baisser", "statWontGoAnyLower": "{{stats}} de {{pokemonNameWithAffix}}\nne peut plus baisser !",
"ppReduced": "Les PP de la capacité {{moveName}}\nde {{targetName}} sont réduits de {{reduction}} !", "ppReduced": "Les PP de la capacité {{moveName}}\nde {{targetName}} baissent de {{reduction}} !",
"battlerTagsRechargingLapse": "Le contrecoup empêche {{pokemonNameWithAffix}}\n de bouger !", "battlerTagsRechargingLapse": "Le contrecoup empêche {{pokemonNameWithAffix}}\n de bouger !",
"battlerTagsTrappedOnAdd": "{{pokemonNameWithAffix}}\nne peut plus séchapper !", "battlerTagsTrappedOnAdd": "{{pokemonNameWithAffix}}\nne peut plus séchapper !",
"battlerTagsTrappedOnRemove": "{{pokemonNameWithAffix}} est libéré\nde la capacité {{moveName}} !", "battlerTagsTrappedOnRemove": "{{pokemonNameWithAffix}} est libéré\nde la capacité {{moveName}} !",

144
src/locales/fr/bgm-name.ts Normal file
View File

@ -0,0 +1,144 @@
import { SimpleTranslationEntries } from "#app/interfaces/locales";
export const bgmName: SimpleTranslationEntries = {
"music": "Musique ",
"missing_entries" : "{{name}}",
"battle_kanto_champion": "N2B2 - Vs. Maitre de Kanto",
"battle_johto_champion": "N2B2 - Vs. Maitre de Johto",
"battle_hoenn_champion": "N2B2 - Vs. Maitre de Hoenn",
"battle_sinnoh_champion": "N2B2 - Vs. Maitresse de Sinnoh",
"battle_champion_alder": "NB - Vs. Maitre dUnys",
"battle_champion_iris": "N2B2 - Vs. Maitresse dUnys",
"battle_kalos_champion": "XY - Maitresse de Kalos",
"battle_alola_champion": "USUL - Maitre dAlola",
"battle_galar_champion": "ÉB - Maitre de Galar",
"battle_champion_geeta": "ÉV - Vs. Alisma la Maitresse",
"battle_champion_nemona": "ÉV - Vs. Menzi la Maitresse",
"battle_champion_kieran": "ÉV - Vs. Kassis le Maitre",
"battle_hoenn_elite": "ROSA - Vs. Conseil 4",
"battle_unova_elite": "NB - Vs. Conseil 4",
"battle_kalos_elite": "XY - Vs. Conseil 4",
"battle_alola_elite": "SL - Vs. Conseil 4",
"battle_galar_elite": "ÉB - Vs. Tournoi des Champions",
"battle_paldea_elite": "ÉV - Vs. Conseil 4",
"battle_bb_elite": "ÉV - Vs. Conseil 4 de lInstitut Myrtille",
"battle_final_encounter": "PDM ÉSDX - Vs. Rayquaza",
"battle_final": "NB - Vs. Ghetis",
"battle_kanto_gym": "N2B2 - Vs. Champion·ne dArène de Kanto",
"battle_johto_gym": "N2B2 - Vs. Champion·ne dArène de Johto",
"battle_hoenn_gym": "N2B2 - Vs. Champion·ne dArène de Hoenn",
"battle_sinnoh_gym": "N2B2 - Vs. Champion·ne dArène de Sinnoh",
"battle_unova_gym": "NB - Vs. Champion·ne dArène dUnys",
"battle_kalos_gym": "XY - Vs. Champion·ne dArène de Kalos",
"battle_galar_gym": "ÉB - Vs. Champion·ne dArène de Galar",
"battle_paldea_gym": "ÉV - Vs. Champion·ne dArène de Paldea",
"battle_legendary_kanto": "XY - Vs. Légendaire de Kanto",
"battle_legendary_raikou": "HGSS - Vs. Raikou",
"battle_legendary_entei": "HGSS - Vs. Entei",
"battle_legendary_suicune": "HGSS - Vs. Suicune",
"battle_legendary_lugia": "HGSS - Vs. Lugia",
"battle_legendary_ho_oh": "HGSS - Vs. Ho-oh",
"battle_legendary_regis_g5": "N2B2 - Vs. Colosses Légendaires",
"battle_legendary_regis_g6": "ROSA - Vs. Colosses Légendaires",
"battle_legendary_gro_kyo": "ROSA - Vs. Groudon/Kyogre",
"battle_legendary_rayquaza": "ROSA - Vs. Rayquaza",
"battle_legendary_deoxys": "ROSA - Vs. Deoxys",
"battle_legendary_lake_trio": "ROSA - Vs. Gardiens des Lacs",
"battle_legendary_sinnoh": "ROSA - Vs. Légendaire de Sinnoh",
"battle_legendary_dia_pal": "ROSA - Vs. Dialga/Palkia",
"battle_legendary_giratina": "ROSA - Vs. Giratina",
"battle_legendary_arceus": "HGSS - Vs. Arceus",
"battle_legendary_unova": "NB - Vs. Légendaire dUnys",
"battle_legendary_kyurem": "NB - Vs. Kyurem",
"battle_legendary_res_zek": "NB - Vs. Reshiram/Zekrom",
"battle_legendary_xern_yvel": "XY - Vs. Xerneas/Yveltal",
"battle_legendary_tapu": "SL - Vs. Divinités gardiennes dAlola",
"battle_legendary_sol_lun": "SL - Vs. Solgaleo/Lunala",
"battle_legendary_ub": "SL - Vs. Ultra-Chimère",
"battle_legendary_dusk_dawn": "USUL - Vs. Necrozma Crinière du Couchant/Ailes de lAurore",
"battle_legendary_ultra_nec": "USUL - Vs. Ultra-Necrozma",
"battle_legendary_zac_zam": "ÉB - Vs. Zacian/Zamazenta",
"battle_legendary_glas_spec": "ÉB - Vs. Blizzeval/Spectreval",
"battle_legendary_calyrex": "ÉB - Vs. Sylveroy",
"battle_legendary_birds_galar": "ÉB - Vs. Oiseaux Légendaires de Galar",
"battle_legendary_ruinous": "ÉV - Vs. Trésors du fléau",
"battle_legendary_loyal_three": "ÉV - Vs. Adoramis",
"battle_legendary_ogerpon": "ÉV - Vs. Ogerpon",
"battle_legendary_terapagos": "ÉV - Vs. Terapagos",
"battle_legendary_pecharunt": "ÉV - Vs. Pêchaminus",
"battle_rival": "NB - Vs. Rival",
"battle_rival_2": "NB - Vs. N",
"battle_rival_3": "NB - Combat final Vs. N",
"battle_trainer": "NB - Vs. Dresseur·euse",
"battle_wild": "NB - Vs. Pokémon sauvage",
"battle_wild_strong": "NB - Vs. Pokémon puissant sauvage",
"end_summit": "PDM ÉSDX - Tour Céleste",
"battle_rocket_grunt": "HGSS Team Rocket Battle",
"battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle",
"battle_galactic_grunt": "BDSP Team Galactic Battle",
"battle_plasma_grunt": "NB - Vs. Team Plasma",
"battle_flare_grunt": "XY Team Flare Battle",
"battle_rocket_boss": "USUM Giovanni Battle",
"battle_aqua_magma_boss": "ORAS Archie & Maxie Battle",
"battle_galactic_boss": "BDSP Cyrus Battle",
"battle_plasma_boss": "B2W2 Ghetsis Battle",
"battle_flare_boss": "XY Lysandre Battle",
// Biome Music
"abyss": "PDM EdS - Cratère Obscur",
"badlands": "PDM EdS - Vallée Stérile",
"beach": "PDM EdS - Falaise Trempée",
"cave": "PDM EdS - Pic Céleste (grotte)",
"construction_site": "PDM EdS - Carrière Rocher",
"desert": "PDM EdS - Désert du Nord",
"dojo": "PDM EdS - Dojo Ossatueur",
"end": "PDM EdS - Tour Céleste",
"factory": "PDM EdS - Ruines Cachées",
"fairy_cave": "PDM EdS - Caverne Étoile",
"forest": "PDM EdS - Forêt Crépuscule",
"grass": "PDM EdS - Bois aux Pommes",
"graveyard": "PDM EdS - Forêt Trompeuse",
"ice_cave": "PDM EdS - Montagne Glacier",
"island": "PDM EdS - Côte Escarpée",
//"jungle": "jungle", // The composer thinks about a more creative name
//"labratory": "labratory", // The composer thinks about a more creative name
"lake": "PDM EdS - Caverne Cristal",
"meadow": "PDM EdS - Pic Céleste (forêt)",
//"metropolis": "metropolis", // The composer thinks about a more creative name
"mountain": "PDM EdS - Mt Corne",
"plains": "PDM EdS - Pic Céleste (prairie)",
"power_plant": "PDM EdS - Plaines Élek",
"ruins": "PDM EdS - Ruine Scellée",
"sea": "PDM EdS - Caverne Saline",
"seabed": "PDM EdS - Caverne Saline profondeurs",
"slum": "PDM EdS - Pic Céleste (côte)",
"snowy_forest": "PDM EdS - Pic Céleste (plaine enneigée)",
"space": "PDM EdS - Ravin Aubaine",
"swamp": "PDM EdS - Mer Fermée",
"tall_grass": "PDM EdS - Forêt Brumeuse",
"temple": "PDM EdS - Grotte Égide",
"town": "PDM EdS - Donjon aléatoire - Thème 3",
"volcano": "PDM EdS - Grotte Étuve",
"wasteland": "PDM EdS - Terres Illusoires",
// Encounter
"encounter_ace_trainer": "NB - Regards croisés (Topdresseur·euse)",
"encounter_backpacker": "NB - Regards croisés (Randonneur·euse)",
"encounter_clerk": "NB - Regards croisés (Employé·e)",
"encounter_cyclist": "NB - Regards croisés (Cycliste)",
"encounter_lass": "NB - Regards croisés (Fillette)",
"encounter_parasol_lady": "NB - Regards croisés (Sœur Parasol)",
"encounter_pokefan": "NB - Regards croisés (Pokéfan)",
"encounter_psychic": "NB - Regards croisés (Kinésiste)",
"encounter_rich": "NB - Regards croisés (Gentleman)",
"encounter_rival": "NB - Tcheren",
"encounter_roughneck": "NB - Regards croisés (Loubard)",
"encounter_scientist": "NB - Regards croisés (Scientifique)",
"encounter_twins": "NB - Regards croisés (Jumelles)",
"encounter_youngster": "NB - Regards croisés (Gamin)",
// Other
"heal": "NB - Soin de Pokémon",
"menu": "PDM EdS - Bienvenue dans le monde de Pokémon !",
"title": "PDM EdS - Menu Principal",
} as const;

View File

@ -4,6 +4,7 @@ import { PGFachv, PGMachv } from "./achv";
import { battle } from "./battle"; import { battle } from "./battle";
import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battleMessageUiHandler } from "./battle-message-ui-handler";
import { berry } from "./berry"; import { berry } from "./berry";
import { bgmName } from "./bgm-name";
import { biome } from "./biome"; import { biome } from "./biome";
import { challenges } from "./challenges"; import { challenges } from "./challenges";
import { commandUiHandler } from "./command-ui-handler"; import { commandUiHandler } from "./command-ui-handler";
@ -48,6 +49,7 @@ export const frConfig = {
battle: battle, battle: battle,
battleMessageUiHandler: battleMessageUiHandler, battleMessageUiHandler: battleMessageUiHandler,
berry: berry, berry: berry,
bgmName: bgmName,
biome: biome, biome: biome,
challenges: challenges, challenges: challenges,
commandUiHandler: commandUiHandler, commandUiHandler: commandUiHandler,

View File

@ -383,6 +383,186 @@ export const PGMdialogue: DialogueTranslationEntries = {
3: "I think it's me that's seasick..." 3: "I think it's me that's seasick..."
}, },
}, },
"rocket_grunt": {
"encounter": {
1: "Nous sommes de retour !"
},
"victory": {
1: "Une fois de plus la Team Rocket senvole vers dautres cieux !"
},
},
"magma_grunt": {
"encounter": {
1: "Nespère pas recevoir de la pitié si tu te mets sur le chemin de la Team Magma !"
},
"victory": {
1: "Je…?\nJai perdu ?!"
},
},
"aqua_grunt": {
"encounter": {
1: "Aucune pitié si tu te mets sur le chemin de la Team Aqua, même pour un gamin !"
},
"victory": {
1: "Comment ça ?"
},
},
"galactic_grunt": {
"encounter": {
1: "Ne te mets pas en travers de la Team Galaxie !"
},
"victory": {
1: "Désactivation…"
},
},
"plasma_grunt": {
"encounter": {
1: "Pas de quatiers à ceux qui ne suivent pas notre idéal !"
},
"victory": {
1: "Plasmaaaaaaaaa !"
},
},
"flare_grunt": {
"encounter": {
1: "Le style et le bon gout, il ny a que ça qui compte !"
},
"victory": {
1: "Mon futur me semble guère radieux."
},
},
"rocket_boss_giovanni_1": {
"encounter": {
1: "Bien. Je dois admettre que je suis impressionné de te voir ici !"
},
"victory": {
1: "QUOI ? IMPOSSIBLE !"
},
"defeat": {
1: "Retiens bien. Ton incapacité à évaluer ta propre force est\nla démonstration claire que tu n'es encore quun gamin."
}
},
"rocket_boss_giovanni_2": {
"encounter": {
1: "Mes anciens collaborateurs mattendent.\nComptes-tu men empêcher ?"
},
"victory": {
1: "Comment c'est possible… ?\nLe grand dessein de la Team Rocket nest plus quune illusion…"
},
"defeat": {
1: "La Team Rocket renaitra, et je dominerai le monde !"
}
},
"magma_boss_maxie_1": {
"encounter": {
1: "Je vais tenterrer de mes propres mains.\nJespère que tapprécieras cet honneur !"
},
"victory": {
1: "Gnn… ! Tu… Tas du répondant…\nCe sentiment dêtre à la traine, de si peu…"
},
"defeat": {
1: "La Team Magma vaincra !"
}
},
"magma_boss_maxie_2": {
"encounter": {
1: "Tes le dernier rempart entravant mes objectifs.\nPrépare-toi à mon ultime riposte ! Hahahaha !"
},
"victory": {
1: "Ce… Ce n'est pas… Gnn…"
},
"defeat": {
1: "L'heure est venue…\nJe vais transformer cette planète en paradis pour lhumanité."
}
},
"aqua_boss_archie_1": {
"encounter": {
1: "Je suis le Leader de la Team Aqua.\nJai bien peur que pour toi, ce soit fin de parcours."
},
"victory": {
1: "Retrouvons-nous.\nJe me souviendrai de ton visage."
},
"defeat": {
1: "Magnifique !\nPlus rien ne peut nous retenir !"
}
},
"aqua_boss_archie_2": {
"encounter": {
1: "Jai attendu ce moment depuis si longtemps.\nVoici la vraie puissance de la Team Aqua !"
},
"victory": {
1: "Comme si jy avait cru…"
},
"defeat": {
1: "Je rendrai à ce monde sa pureté originelle !"
}
},
"galactic_boss_cyrus_1": {
"encounter": {
1: "Tu tes senti obligé de venir ici dans un acte vide de sens.\nJe vais te le faire regretter."
},
"victory": {
1: "Intéressant. Et plutôt curieux."
},
"defeat": {
1: "Je le créerai, mon nouveau monde…"
}
},
"galactic_boss_cyrus_2": {
"encounter": {
1: "Nous y revoilà. Il semblerait que nos destinées soient entremêlées.\nIl est lheure dy mettre un terme."
},
"victory": {
1: "Comment. Comment ?\nCOMMENT ?!"
},
"defeat": {
1: "Adieu."
}
},
"plasma_boss_ghetsis_1": {
"encounter": {
1: "Je naccepterai pas quon me barre la route !\nPeu importe qui fait quoi !"
},
"victory": {
1: "Comment ? Je suis le leader de la Team Plasma !\nJe suis parfait !"
},
"defeat": {
1: "Je suis le parfait monarque dun monde parfait !\nHahaha !"
}
},
"plasma_boss_ghetsis_2": {
"encounter": {
1: "Viens ! Je veux voir ton visage à linstant même où lespoir quittera ton corps !"
},
"victory": {
1: "Mes calculs… Non ! Mes plans étaient parfaits !\nCe monde devrait être mien !"
},
"defeat": {
1: "Kyurem ! Fusiorption !!!"
}
},
"flare_boss_lysandre_1": {
"encounter": {
1: "Comptes-tu marrêter ? Prouve-le."
},
"victory": {
1: "Tes venu marrêter. Mais je te demande dattendre."
},
"defeat": {
1: "Les Pokémon… Ne devraient plus exister."
}
},
"flare_boss_lysandre_2": {
"encounter": {
1: "Ton future ou le mien… Voyons lequel mérite plus."
},
"victory": {
1: "Ohhhh… !"
},
"defeat": {
1: "Les ignorants sans aucune vision nauront donc de cesse de souiller ce monde."
}
},
"brock": { "brock": {
"encounter": { "encounter": {
1: "My expertise on Rock-type Pokémon will take you down! Come on!", 1: "My expertise on Rock-type Pokémon will take you down! Come on!",
@ -2288,7 +2468,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
$@c{neutral}Cet endroit est terrifiant Et pourtant il ma lair familier, comme si jy avais déjà mis les pieds. $@c{neutral}Cet endroit est terrifiant Et pourtant il ma lair familier, comme si jy avais déjà mis les pieds.
$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ? $@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?
$@c{serious}et cest comme si quelque chose ici me parlait. $@c{serious}et cest comme si quelque chose ici me parlait.
$Comme si cétait tout ce que ce monde avait toujours connu. $Comme si cétait tout ce que ce monde avait toujours connu.
$Ces précieux moments ensemble semblent si proches ne sont rien de plus quun lointain souvenir. $Ces précieux moments ensemble semblent si proches ne sont rien de plus quun lointain souvenir.
$@c{neutral_eclosed}Dailleurs, qui peut dire aujourdhui quils ont pu être réels ? $@c{neutral_eclosed}Dailleurs, qui peut dire aujourdhui quils ont pu être réels ?
$@c{serious_mopen_fists}Il faut que tu persévères. Si tu tarrêtes, ça n'aura jamais de fin et tes la seule à en être capable. $@c{serious_mopen_fists}Il faut que tu persévères. Si tu tarrêtes, ça n'aura jamais de fin et tes la seule à en être capable.
@ -2686,6 +2866,210 @@ export const PGFdialogue: DialogueTranslationEntries = {
1: "I'll tune up for the next race." 1: "I'll tune up for the next race."
}, },
}, },
"firebreather": {
"encounter": {
1: "My flames shall devour you!",
2: "My soul is on fire. I'll show you how hot it burns!",
3: "Step right up and take a look!"
},
"victory": {
1: "I burned down to ashes...",
2: "Yow! That's hot!",
3: "Ow! I scorched the tip of my nose!"
},
},
"sailor": {
"encounter": {
1: "Matey, you're walking the plank if you lose!",
2: "Come on then! My sailor's pride is at stake!",
3: "Ahoy there! Are you seasick?"
},
"victory": {
1: "Argh! Beaten by a kid!",
2: "Your spirit sank me!",
3: "I think it's me that's seasick..."
},
},
"rocket_grunt": {
"encounter": {
1: "Nous sommes de retour !"
},
"victory": {
1: "Une fois de plus la Team Rocket senvole vers dautres cieux !"
},
},
"magma_grunt": {
"encounter": {
1: "Nespère pas recevoir de la pitié si tu te mets sur le chemin de la Team Magma !"
},
"victory": {
1: "Je…?\nJai perdu ?!"
},
},
"aqua_grunt": {
"encounter": {
1: "Aucune pitié si tu te mets sur le chemin de la Team Aqua, même pour une gamine !"
},
"victory": {
1: "Comment ça ?"
},
},
"galactic_grunt": {
"encounter": {
1: "Ne te mets pas en travers de la Team Galaxie !"
},
"victory": {
1: "Désactivation…"
},
},
"plasma_grunt": {
"encounter": {
1: "Pas de quatiers à ceux qui ne suivent pas notre idéal !"
},
"victory": {
1: "Plasmaaaaaaaaa !"
},
},
"flare_grunt": {
"encounter": {
1: "Le style et le bon gout, il ny a que ça qui compte !"
},
"victory": {
1: "Mon futur me semble guère radieux."
},
},
"rocket_boss_giovanni_1": {
"encounter": {
1: "Bien. Je dois admettre que je suis impressionné de te voir ici !"
},
"victory": {
1: "QUOI ? IMPOSSIBLE !"
},
"defeat": {
1: "Retiens bien. Ton incapacité à évaluer ta propre force est\nla démonstration claire que tu n'es encore quune gamine."
}
},
"rocket_boss_giovanni_2": {
"encounter": {
1: "Mes anciens collaborateurs mattendent.\nComptes-tu men empêcher ?"
},
"victory": {
1: "Comment c'est possible… ?\nLe grand dessein de la Team Rocket nest plus quune illusion…"
},
"defeat": {
1: "La Team Rocket renaitra, et je dominerai le monde !"
}
},
"magma_boss_maxie_1": {
"encounter": {
1: "Je vais tenterrer de mes propres mains.\nJespère que tapprécieras cet honneur !"
},
"victory": {
1: "Gnn… ! Tu… Tas du répondant…\nCe sentiment dêtre à la traine, de si peu…"
},
"defeat": {
1: "La Team Magma vaincra !"
}
},
"magma_boss_maxie_2": {
"encounter": {
1: "Tes le dernier rempart entravant mes objectifs.\nPrépare-toi à mon ultime riposte ! Hahahaha !"
},
"victory": {
1: "Ce… Ce n'est pas… Gnn…"
},
"defeat": {
1: "L'heure est venue…\nJe vais transformer cette planète en paradis pour lhumanité."
}
},
"aqua_boss_archie_1": {
"encounter": {
1: "Je suis le Leader de la Team Aqua.\nJai bien peur que pour toi, ce soit fin de parcours."
},
"victory": {
1: "Retrouvons-nous.\nJe me souviendrai de ton visage."
},
"defeat": {
1: "Magnifique !\nPlus rien ne peut nous retenir !"
}
},
"aqua_boss_archie_2": {
"encounter": {
1: "Jai attendu ce moment depuis si longtemps.\nVoici la vraie puissance de la Team Aqua !"
},
"victory": {
1: "Comme si jy avait cru…"
},
"defeat": {
1: "Je rendrai à ce monde sa pureté originelle !"
}
},
"galactic_boss_cyrus_1": {
"encounter": {
1: "Tu tes sentie obligée de venir ici dans un acte vide de sens.\nJe vais te le faire regretter."
},
"victory": {
1: "Intéressant. Et plutôt curieux."
},
"defeat": {
1: "Je le créerai, mon nouveau monde…"
}
},
"galactic_boss_cyrus_2": {
"encounter": {
1: "Nous y revoilà. Il semblerait que nos destinées soient entremêlées.\nIl est lheure dy mettre un terme."
},
"victory": {
1: "Comment. Comment ?\nCOMMENT ?!"
},
"defeat": {
1: "Adieu."
}
},
"plasma_boss_ghetsis_1": {
"encounter": {
1: "Je naccepterai pas quon me barre la route !\nPeu importe qui fait quoi !"
},
"victory": {
1: "Comment ? Je suis le leader de la Team Plasma !\nJe suis parfait !"
},
"defeat": {
1: "Je suis le parfait monarque dun monde parfait !\nHahaha !"
}
},
"plasma_boss_ghetsis_2": {
"encounter": {
1: "Viens ! Je veux voir ton visage à linstant même où lespoir quittera ton corps !"
},
"victory": {
1: "Mes calculs… Non ! Mes plans étaient parfaits !\nCe monde devrait être mien !"
},
"defeat": {
1: "Kyurem ! Fusiorption !!!"
}
},
"flare_boss_lysandre_1": {
"encounter": {
1: "Comptes-tu marrêter ? Prouve-le."
},
"victory": {
1: "Tes venu marrêter. Mais je te demande dattendre."
},
"defeat": {
1: "Les Pokémon… Ne devraient plus exister."
}
},
"flare_boss_lysandre_2": {
"encounter": {
1: "Ton future ou le mien… Voyons lequel mérite plus."
},
"victory": {
1: "Ohhhh… !"
},
"defeat": {
1: "Les ignorants sans aucune vision nauront donc de cesse de souiller ce monde."
}
},
"brock": { "brock": {
"encounter": { "encounter": {
1: "My expertise on Rock-type Pokémon will take you down! Come on!", 1: "My expertise on Rock-type Pokémon will take you down! Come on!",
@ -4565,7 +4949,8 @@ export const PGFdialogue: DialogueTranslationEntries = {
$@c{neutral_eclosed}Jignore si je serai capable de laccomplir, mais je ferai tout ce qui est en mon pouvoir. $@c{neutral_eclosed}Jignore si je serai capable de laccomplir, mais je ferai tout ce qui est en mon pouvoir.
$@c{neutral}Cet endroit est terrifiant Et pourtant il ma lair familier, comme si jy avais déjà mis les pieds. $@c{neutral}Cet endroit est terrifiant Et pourtant il ma lair familier, comme si jy avais déjà mis les pieds.
$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ? $@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?
$@c{serious}et cest comme si quelque chose ici me parlait.\nComme si cétait tout ce que ce monde avait toujours connu. $@c{serious}et cest comme si quelque chose ici me parlait.
$Comme si cétait tout ce que ce monde avait toujours connu.
$Ces précieux moments ensemble semblent si proches ne sont rien de plus quun lointain souvenir. $Ces précieux moments ensemble semblent si proches ne sont rien de plus quun lointain souvenir.
$@c{neutral_eclosed}Dailleurs, qui peut dire aujourdhui quils ont pu être réels ? $@c{neutral_eclosed}Dailleurs, qui peut dire aujourdhui quils ont pu être réels ?
$@c{serious_mopen_fists}Il faut que tu persévères. Si tu tarrêtes, ça n'aura jamais de fin et tes la seule à en être capable. $@c{serious_mopen_fists}Il faut que tu persévères. Si tu tarrêtes, ça n'aura jamais de fin et tes la seule à en être capable.
@ -4592,7 +4977,7 @@ export const PGFdialogue: DialogueTranslationEntries = {
$@c{smile_ehalf}Ont-ils au moins é réels ? Tout semble si loin maintenant $@c{smile_ehalf}Ont-ils au moins é réels ? Tout semble si loin maintenant
$@c{angry_mopen}Il faut que tu persévères. Si tu tarrêtes, ça n'aura jamais de fin et tes le seul à en être capable. $@c{angry_mopen}Il faut que tu persévères. Si tu tarrêtes, ça n'aura jamais de fin et tes le seul à en être capable.
$@c{smile_ehalf}Je jignore le sens de tout ça Mais je sais que cest la réalité. $@c{smile_ehalf}Je jignore le sens de tout ça Mais je sais que cest la réalité.
$@c{neutral}Si tu ne parviens à pas me battre ici et maintenant, tu nas aucune chance.` $@c{neutral}Si tu ne parviens pas à me battre ici et maintenant, tu nas aucune chance.`
}, },
"victory": { "victory": {
1: `@c{smile_ehalf}Je… Je crois que j'ai rempli ma mission… 1: `@c{smile_ehalf}Je… Je crois que j'ai rempli ma mission…

View File

@ -17,5 +17,9 @@ export const egg: SimpleTranslationEntries = {
"notEnoughVouchers": "Vous navez pas assez de coupons !", "notEnoughVouchers": "Vous navez pas assez de coupons !",
"tooManyEggs": "Vous avez trop dŒufs !", "tooManyEggs": "Vous avez trop dŒufs !",
"pull": "Tirage", "pull": "Tirage",
"pulls": "Tirages" "pulls": "Tirages",
"sameSpeciesEgg": "{{species}} sortira de cet Œuf !",
"hatchFromTheEgg": "{{pokemonName}} sort de lŒuf !",
"eggMoveUnlock": "Capacité Œuf débloquée :\n{{moveName}}",
"rareEggMoveUnlock": "Capacité Œuf Rare débloquée :\n{{moveName}}",
} as const; } as const;

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