Merge branch 'main' into more_music

This commit is contained in:
Madmadness65 2024-06-04 17:46:31 -05:00
commit 36910fa4f4
59 changed files with 971 additions and 336 deletions

View File

@ -146,8 +146,8 @@ body {
margin-left: 10%; margin-left: 10%;
} }
#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadRectBtnContainer > .apadSqBtn, #touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_ACCESSIBILITY']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadRectBtnContainer > .apadSqBtn,
#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadSqBtnContainer #touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_ACCESSIBILITY']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadSqBtnContainer
{ {
display: none; display: none;
} }

9
package-lock.json generated
View File

@ -12,6 +12,7 @@
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"i18next": "^23.11.1", "i18next": "^23.11.1",
"i18next-browser-languagedetector": "^7.2.1", "i18next-browser-languagedetector": "^7.2.1",
"i18next-korean-postposition-processor": "^1.0.0",
"json-stable-stringify": "^1.1.0", "json-stable-stringify": "^1.1.0",
"phaser": "^3.70.0", "phaser": "^3.70.0",
"phaser3-rex-plugins": "^1.1.84" "phaser3-rex-plugins": "^1.1.84"
@ -3615,6 +3616,14 @@
"cross-fetch": "4.0.0" "cross-fetch": "4.0.0"
} }
}, },
"node_modules/i18next-korean-postposition-processor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/i18next-korean-postposition-processor/-/i18next-korean-postposition-processor-1.0.0.tgz",
"integrity": "sha512-ruNXjI9awsFK6Ie+F9gYaMW8ciLMuCkeRjH9QkSv2Wb8xI0mnm773v3M9eua8dtvAXudIUk4p6Ho7hNkEASXDg==",
"peerDependencies": {
"i18next": ">=8.4.0"
}
},
"node_modules/iconv-lite": { "node_modules/iconv-lite": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",

View File

@ -43,6 +43,7 @@
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"i18next": "^23.11.1", "i18next": "^23.11.1",
"i18next-browser-languagedetector": "^7.2.1", "i18next-browser-languagedetector": "^7.2.1",
"i18next-korean-postposition-processor": "^1.0.0",
"json-stable-stringify": "^1.1.0", "json-stable-stringify": "^1.1.0",
"phaser": "^3.70.0", "phaser": "^3.70.0",
"phaser3-rex-plugins": "^1.1.84" "phaser3-rex-plugins": "^1.1.84"

Binary file not shown.

View File

@ -4065,7 +4065,7 @@
"426": [ "426": [
0, 0,
1, 1,
2 1
], ],
"427": [ "427": [
0, 0,

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

View File

@ -1,4 +1,5 @@
import Move from "./data/move"; import Move from "./data/move";
import { BerryModifier } from "./modifier/modifier";
/** Alias for all {@linkcode BattleScene} events */ /** Alias for all {@linkcode BattleScene} events */
export enum BattleSceneEventType { export enum BattleSceneEventType {
@ -13,6 +14,12 @@ export enum BattleSceneEventType {
* @see {@linkcode MoveUsedEvent} * @see {@linkcode MoveUsedEvent}
*/ */
MOVE_USED = "onMoveUsed", MOVE_USED = "onMoveUsed",
/**
* Triggers when a berry gets successfully used
* @see {@linkcode BerryUsedEvent}
*/
BERRY_USED = "onBerryUsed",
/** /**
* Triggers on the first turn of a new battle * Triggers on the first turn of a new battle
* @see {@linkcode TurnInitEvent} * @see {@linkcode TurnInitEvent}
@ -23,6 +30,7 @@ export enum BattleSceneEventType {
* @see {@linkcode TurnEndEvent} * @see {@linkcode TurnEndEvent}
*/ */
TURN_END = "onTurnEnd", TURN_END = "onTurnEnd",
/** /**
* Triggers when a new {@linkcode Arena} is created during initialization * Triggers when a new {@linkcode Arena} is created during initialization
* @see {@linkcode NewArenaEvent} * @see {@linkcode NewArenaEvent}
@ -50,7 +58,7 @@ export class CandyUpgradeNotificationChangedEvent extends Event {
*/ */
export class MoveUsedEvent extends Event { export class MoveUsedEvent extends Event {
/** The ID of the {@linkcode Pokemon} that used the {@linkcode Move} */ /** The ID of the {@linkcode Pokemon} that used the {@linkcode Move} */
public userId: number; public pokemonId: number;
/** The {@linkcode Move} used */ /** The {@linkcode Move} used */
public move: Move; public move: Move;
/** The amount of PP used on the {@linkcode Move} this turn */ /** The amount of PP used on the {@linkcode Move} this turn */
@ -58,11 +66,25 @@ export class MoveUsedEvent extends Event {
constructor(userId: number, move: Move, ppUsed: number) { constructor(userId: number, move: Move, ppUsed: number) {
super(BattleSceneEventType.MOVE_USED); super(BattleSceneEventType.MOVE_USED);
this.userId = userId; this.pokemonId = userId;
this.move = move; this.move = move;
this.ppUsed = ppUsed; this.ppUsed = ppUsed;
} }
} }
/**
* Container class for {@linkcode BattleSceneEventType.BERRY_USED} events
* @extends Event
*/
export class BerryUsedEvent extends Event {
/** The {@linkcode BerryModifier} being used */
public berryModifier: BerryModifier;
constructor(berry: BerryModifier) {
super(BattleSceneEventType.BERRY_USED);
this.berryModifier = berry;
}
}
/** /**
* Container class for {@linkcode BattleSceneEventType.TURN_INIT} events * Container class for {@linkcode BattleSceneEventType.TURN_INIT} events
* @extends Event * @extends Event

View File

@ -58,6 +58,7 @@ import {InputsController} from "./inputs-controller";
import {UiInputs} from "./ui-inputs"; import {UiInputs} from "./ui-inputs";
import { MoneyFormat } from "./enums/money-format"; import { MoneyFormat } from "./enums/money-format";
import { NewArenaEvent } from "./battle-scene-events"; import { NewArenaEvent } from "./battle-scene-events";
import ArenaFlyout from "./ui/arena-flyout";
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
@ -92,6 +93,7 @@ export default class BattleScene extends SceneBase {
public damageNumbersMode: integer = 0; public damageNumbersMode: integer = 0;
public reroll: boolean = false; public reroll: boolean = false;
public showMovesetFlyout: boolean = true; public showMovesetFlyout: boolean = true;
public showArenaFlyout: boolean = true;
public showLevelUpStats: boolean = true; public showLevelUpStats: boolean = true;
public enableTutorials: boolean = import.meta.env.VITE_BYPASS_TUTORIAL === "1"; public enableTutorials: boolean = import.meta.env.VITE_BYPASS_TUTORIAL === "1";
public enableRetries: boolean = false; public enableRetries: boolean = false;
@ -179,6 +181,8 @@ export default class BattleScene extends SceneBase {
private luckText: Phaser.GameObjects.Text; private luckText: Phaser.GameObjects.Text;
private modifierBar: ModifierBar; private modifierBar: ModifierBar;
private enemyModifierBar: ModifierBar; private enemyModifierBar: ModifierBar;
public arenaFlyout: ArenaFlyout;
private fieldOverlay: Phaser.GameObjects.Rectangle; private fieldOverlay: Phaser.GameObjects.Rectangle;
private modifiers: PersistentModifier[]; private modifiers: PersistentModifier[];
private enemyModifiers: PersistentModifier[]; private enemyModifiers: PersistentModifier[];
@ -412,6 +416,10 @@ export default class BattleScene extends SceneBase {
this.luckLabelText.setVisible(false); this.luckLabelText.setVisible(false);
this.fieldUI.add(this.luckLabelText); this.fieldUI.add(this.luckLabelText);
this.arenaFlyout = new ArenaFlyout(this);
this.fieldUI.add(this.arenaFlyout);
this.fieldUI.moveBelow<Phaser.GameObjects.GameObject>(this.arenaFlyout, this.fieldOverlay);
this.updateUIPositions(); this.updateUIPositions();
this.damageNumberHandler = new DamageNumberHandler(); this.damageNumberHandler = new DamageNumberHandler();
@ -1104,6 +1112,8 @@ export default class BattleScene extends SceneBase {
case Species.FLOETTE: case Species.FLOETTE:
case Species.FLORGES: case Species.FLORGES:
case Species.FURFROU: case Species.FURFROU:
case Species.PUMPKABOO:
case Species.GOURGEIST:
case Species.ORICORIO: case Species.ORICORIO:
case Species.MAGEARNA: case Species.MAGEARNA:
case Species.ZARUDE: case Species.ZARUDE:
@ -1273,6 +1283,13 @@ export default class BattleScene extends SceneBase {
return sprite; return sprite;
} }
moveBelowOverlay<T extends Phaser.GameObjects.GameObject>(gameObject: T) {
this.fieldUI.moveBelow<any>(gameObject, this.fieldOverlay);
}
processInfoButton(pressed: boolean): void {
this.arenaFlyout.toggleFlyout(pressed);
}
showFieldOverlay(duration: integer): Promise<void> { showFieldOverlay(duration: integer): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
this.tweens.add({ this.tweens.add({

View File

@ -1341,7 +1341,7 @@ export class CursedTag extends BattlerTag {
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
if (!cancelled.value) { if (!cancelled.value) {
pokemon.damageAndUpdate(Math.floor(pokemon.getMaxHp() / 4)); pokemon.damageAndUpdate(Math.max(Math.floor(pokemon.getMaxHp() / 4), 1));
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is hurt by the ${this.getMoveName()}!`)); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is hurt by the ${this.getMoveName()}!`));
} }
} }

View File

@ -7,20 +7,7 @@ import { getStatusEffectHealText } from "./status-effect";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./ability"; import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./ability";
import i18next from "../plugins/i18n"; import i18next from "../plugins/i18n";
import { BerryType } from "./enums/berry-type";
export enum BerryType {
SITRUS,
LUM,
ENIGMA,
LIECHI,
GANLON,
PETAYA,
APICOT,
SALAC,
LANSAT,
STARF,
LEPPA
}
export function getBerryName(berryType: BerryType): string { export function getBerryName(berryType: BerryType): string {
return i18next.t(`berry:${BerryType[berryType]}.name`); return i18next.t(`berry:${BerryType[berryType]}.name`);

View File

@ -0,0 +1,14 @@
export enum BerryType {
SITRUS,
LUM,
ENIGMA,
LIECHI,
GANLON,
PETAYA,
APICOT,
SALAC,
LANSAT,
STARF,
LEPPA
}

View File

@ -66,7 +66,7 @@ export enum FormChangeItem {
HARD_METEORITE, HARD_METEORITE,
SMOOTH_METEORITE, SMOOTH_METEORITE,
ADAMANT_CRYSTAL, ADAMANT_CRYSTAL,
LUSTROUS_ORB, LUSTROUS_GLOBE,
GRISEOUS_CORE, GRISEOUS_CORE,
REVEAL_GLASS, REVEAL_GLASS,
GRACIDEA, GRACIDEA,
@ -520,7 +520,7 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.DIALGA, "", SpeciesFormKey.ORIGIN, new SpeciesFormChangeItemTrigger(FormChangeItem.ADAMANT_CRYSTAL)) new SpeciesFormChange(Species.DIALGA, "", SpeciesFormKey.ORIGIN, new SpeciesFormChangeItemTrigger(FormChangeItem.ADAMANT_CRYSTAL))
], ],
[Species.PALKIA]: [ [Species.PALKIA]: [
new SpeciesFormChange(Species.PALKIA, "", SpeciesFormKey.ORIGIN, new SpeciesFormChangeItemTrigger(FormChangeItem.LUSTROUS_ORB)) new SpeciesFormChange(Species.PALKIA, "", SpeciesFormKey.ORIGIN, new SpeciesFormChangeItemTrigger(FormChangeItem.LUSTROUS_GLOBE))
], ],
[Species.GIRATINA]: [ [Species.GIRATINA]: [
new SpeciesFormChange(Species.GIRATINA, "altered", SpeciesFormKey.ORIGIN, new SpeciesFormChangeItemTrigger(FormChangeItem.GRISEOUS_CORE)) new SpeciesFormChange(Species.GIRATINA, "altered", SpeciesFormKey.ORIGIN, new SpeciesFormChangeItemTrigger(FormChangeItem.GRISEOUS_CORE))

View File

@ -2010,15 +2010,15 @@ export function initSpecies() {
new PokemonSpecies(Species.TREVENANT, 6, false, false, false, "Elder Tree Pokémon", Type.GHOST, Type.GRASS, 1.5, 71, Abilities.NATURAL_CURE, Abilities.FRISK, Abilities.HARVEST, 474, 85, 110, 76, 65, 82, 56, 60, 50, 166, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.TREVENANT, 6, false, false, false, "Elder Tree Pokémon", Type.GHOST, Type.GRASS, 1.5, 71, Abilities.NATURAL_CURE, Abilities.FRISK, Abilities.HARVEST, 474, 85, 110, 76, 65, 82, 56, 60, 50, 166, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.PUMPKABOO, 6, false, false, false, "Pumpkin Pokémon", Type.GHOST, Type.GRASS, 0.4, 5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 49, 66, 70, 44, 55, 51, 120, 50, 67, GrowthRate.MEDIUM_FAST, 50, false, false, new PokemonSpecies(Species.PUMPKABOO, 6, false, false, false, "Pumpkin Pokémon", Type.GHOST, Type.GRASS, 0.4, 5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 49, 66, 70, 44, 55, 51, 120, 50, 67, GrowthRate.MEDIUM_FAST, 50, false, false,
new PokemonForm("Average Size", "", Type.GHOST, Type.GRASS, 0.4, 5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 49, 66, 70, 44, 55, 51, 120, 50, 67, false, null, true), new PokemonForm("Average Size", "", Type.GHOST, Type.GRASS, 0.4, 5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 49, 66, 70, 44, 55, 51, 120, 50, 67, false, null, true),
new PokemonForm("Small Size", "small", Type.GHOST, Type.GRASS, 0.3, 3.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 44, 66, 70, 44, 55, 56, 120, 50, 67, false, null, true), new PokemonForm("Small Size", "small", Type.GHOST, Type.GRASS, 0.3, 3.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 44, 66, 70, 44, 55, 56, 120, 50, 67, false, "", true),
new PokemonForm("Large Size", "large", Type.GHOST, Type.GRASS, 0.5, 7.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 54, 66, 70, 44, 55, 46, 120, 50, 67, false, null, true), new PokemonForm("Large Size", "large", Type.GHOST, Type.GRASS, 0.5, 7.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 54, 66, 70, 44, 55, 46, 120, 50, 67, false, "", true),
new PokemonForm("Super Size", "super", Type.GHOST, Type.GRASS, 0.8, 15, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 59, 66, 70, 44, 55, 41, 120, 50, 67, false, null, true), new PokemonForm("Super Size", "super", Type.GHOST, Type.GRASS, 0.8, 15, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 335, 59, 66, 70, 44, 55, 41, 120, 50, 67, false, "", true),
), ),
new PokemonSpecies(Species.GOURGEIST, 6, false, false, false, "Pumpkin Pokémon", Type.GHOST, Type.GRASS, 0.9, 12.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 65, 90, 122, 58, 75, 84, 60, 50, 173, GrowthRate.MEDIUM_FAST, 50, false, false, new PokemonSpecies(Species.GOURGEIST, 6, false, false, false, "Pumpkin Pokémon", Type.GHOST, Type.GRASS, 0.9, 12.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 65, 90, 122, 58, 75, 84, 60, 50, 173, GrowthRate.MEDIUM_FAST, 50, false, false,
new PokemonForm("Average Size", "", Type.GHOST, Type.GRASS, 0.9, 12.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 65, 90, 122, 58, 75, 84, 60, 50, 173, false, null, true), new PokemonForm("Average Size", "", Type.GHOST, Type.GRASS, 0.9, 12.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 65, 90, 122, 58, 75, 84, 60, 50, 173, false, null, true),
new PokemonForm("Small Size", "small", Type.GHOST, Type.GRASS, 0.7, 9.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 55, 85, 122, 58, 75, 99, 60, 50, 173, false, null, true), new PokemonForm("Small Size", "small", Type.GHOST, Type.GRASS, 0.7, 9.5, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 55, 85, 122, 58, 75, 99, 60, 50, 173, false, "", true),
new PokemonForm("Large Size", "large", Type.GHOST, Type.GRASS, 1.1, 14, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 75, 95, 122, 58, 75, 69, 60, 50, 173, false, null, true), new PokemonForm("Large Size", "large", Type.GHOST, Type.GRASS, 1.1, 14, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 75, 95, 122, 58, 75, 69, 60, 50, 173, false, "", true),
new PokemonForm("Super Size", "super", Type.GHOST, Type.GRASS, 1.7, 39, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 85, 100, 122, 58, 75, 54, 60, 50, 173, false, null, true), new PokemonForm("Super Size", "super", Type.GHOST, Type.GRASS, 1.7, 39, Abilities.PICKUP, Abilities.FRISK, Abilities.INSOMNIA, 494, 85, 100, 122, 58, 75, 54, 60, 50, 173, false, "", true),
), ),
new PokemonSpecies(Species.BERGMITE, 6, false, false, false, "Ice Chunk Pokémon", Type.ICE, null, 1, 99.5, Abilities.OWN_TEMPO, Abilities.ICE_BODY, Abilities.STURDY, 304, 55, 69, 85, 32, 35, 28, 190, 50, 61, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.BERGMITE, 6, false, false, false, "Ice Chunk Pokémon", Type.ICE, null, 1, 99.5, Abilities.OWN_TEMPO, Abilities.ICE_BODY, Abilities.STURDY, 304, 55, 69, 85, 32, 35, 28, 190, 50, 61, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.AVALUGG, 6, false, false, false, "Iceberg Pokémon", Type.ICE, null, 2, 505, Abilities.OWN_TEMPO, Abilities.ICE_BODY, Abilities.STURDY, 514, 95, 117, 184, 44, 46, 28, 55, 50, 180, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.AVALUGG, 6, false, false, false, "Iceberg Pokémon", Type.ICE, null, 2, 505, Abilities.OWN_TEMPO, Abilities.ICE_BODY, Abilities.STURDY, 514, 95, 117, 184, 44, 46, 28, 55, 50, 180, GrowthRate.MEDIUM_FAST, 50, false),

View File

@ -63123,9 +63123,12 @@ export const tmSpecies: TmSpecies = {
[Moves.SNOWSCAPE]: [ [Moves.SNOWSCAPE]: [
Species.SLOWPOKE, Species.SLOWPOKE,
Species.SLOWBRO, Species.SLOWBRO,
Species.SEEL,
Species.DEWGONG,
Species.SHELLDER, Species.SHELLDER,
Species.CLOYSTER, Species.CLOYSTER,
Species.CHANSEY, Species.CHANSEY,
Species.LAPRAS,
Species.ARTICUNO, Species.ARTICUNO,
Species.DRAGONITE, Species.DRAGONITE,
Species.MEW, Species.MEW,
@ -63140,6 +63143,7 @@ export const tmSpecies: TmSpecies = {
Species.PILOSWINE, Species.PILOSWINE,
Species.DELIBIRD, Species.DELIBIRD,
Species.BLISSEY, Species.BLISSEY,
Species.SUICUNE,
Species.WINGULL, Species.WINGULL,
Species.PELIPPER, Species.PELIPPER,
Species.SPOINK, Species.SPOINK,
@ -63148,11 +63152,20 @@ export const tmSpecies: TmSpecies = {
Species.SNORUNT, Species.SNORUNT,
Species.GLALIE, Species.GLALIE,
Species.LUVDISC, Species.LUVDISC,
Species.REGICE,
Species.PIPLUP, Species.PIPLUP,
Species.PRINPLUP, Species.PRINPLUP,
Species.EMPOLEON, Species.EMPOLEON,
[
Species.SHELLOS, Species.SHELLOS,
"east",
"west",
],
[
Species.GASTRODON, Species.GASTRODON,
"east",
"west",
],
Species.MISMAGIUS, Species.MISMAGIUS,
Species.HAPPINY, Species.HAPPINY,
Species.SNOVER, Species.SNOVER,
@ -63170,7 +63183,17 @@ export const tmSpecies: TmSpecies = {
Species.CUBCHOO, Species.CUBCHOO,
Species.BEARTIC, Species.BEARTIC,
Species.CRYOGONAL, Species.CRYOGONAL,
[
Species.TORNADUS, Species.TORNADUS,
"incarnate",
"therian",
],
[
Species.KYUREM,
"",
"black",
"white",
],
Species.FROAKIE, Species.FROAKIE,
Species.FROGADIER, Species.FROGADIER,
[ [
@ -63184,8 +63207,13 @@ export const tmSpecies: TmSpecies = {
Species.BERGMITE, Species.BERGMITE,
Species.AVALUGG, Species.AVALUGG,
Species.DIANCIE, Species.DIANCIE,
Species.PRIMARINA,
Species.CRABOMINABLE, Species.CRABOMINABLE,
[
Species.MAGEARNA, Species.MAGEARNA,
"",
"original",
],
Species.INTELEON, Species.INTELEON,
Species.FROSMOTH, Species.FROSMOTH,
Species.EISCUE, Species.EISCUE,
@ -63633,12 +63661,21 @@ export const tmSpecies: TmSpecies = {
Species.WEAVILE, Species.WEAVILE,
Species.GLACEON, Species.GLACEON,
Species.FROSLASS, Species.FROSLASS,
[
Species.PALKIA, Species.PALKIA,
"",
"origin",
],
Species.ARCEUS, Species.ARCEUS,
Species.OSHAWOTT, Species.OSHAWOTT,
Species.DEWOTT, Species.DEWOTT,
Species.SAMUROTT, Species.SAMUROTT,
[
Species.BASCULIN, Species.BASCULIN,
"red-striped",
"blue-striped",
"white-striped",
],
Species.DUCKLETT, Species.DUCKLETT,
Species.SWANNA, Species.SWANNA,
Species.ALOMOMOLA, Species.ALOMOMOLA,

View File

@ -618,7 +618,7 @@ export class TrainerConfig {
* @param isMale - Whether the Champion is Male or Female (for localization of the title). * @param isMale - Whether the Champion is Male or Female (for localization of the title).
* @returns {TrainerConfig} - The updated TrainerConfig instance. * @returns {TrainerConfig} - The updated TrainerConfig instance.
**/ **/
initForChampion(signatureSpecies: (Species | Species[])[],isMale: boolean): TrainerConfig { initForChampion(signatureSpecies: (Species | Species[])[], isMale: boolean): TrainerConfig {
// Check if the internationalization (i18n) system is initialized. // Check if the internationalization (i18n) system is initialized.
if (!getIsInitialized()) { if (!getIsInitialized()) {
initI18n(); initI18n();
@ -917,20 +917,20 @@ export const signatureSpecies: SignatureSpecies = {
AMARYS: [Species.SKARMORY, Species.EMPOLEON, Species.SCIZOR, Species.METAGROSS], AMARYS: [Species.SKARMORY, Species.EMPOLEON, Species.SCIZOR, Species.METAGROSS],
LACEY: [Species.EXCADRILL, Species.PRIMARINA, Species.ALCREMIE, Species.GALAR_SLOWBRO], LACEY: [Species.EXCADRILL, Species.PRIMARINA, Species.ALCREMIE, Species.GALAR_SLOWBRO],
DRAYTON: [Species.DRAGONITE, Species.ARCHALUDON, Species.FLYGON, Species.SCEPTILE], DRAYTON: [Species.DRAGONITE, Species.ARCHALUDON, Species.FLYGON, Species.SCEPTILE],
BLUE: [Species.GYARADOS, Species.MEWTWO, Species.ARCANINE, Species.ALAKAZAM, Species.PIDGEOT], BLUE: [[Species.GYARADOS, Species.EXEGGUTOR, Species.ARCANINE], Species.HO_OH, [Species.RHYPERIOR, Species.MAGNEZONE]], // Alakazam lead, Mega Pidgeot
RED: [Species.CHARIZARD, [Species.LUGIA, Species.HO_OH], Species.SNORLAX, Species.RAICHU, Species.ESPEON], RED: [Species.LUGIA, Species.SNORLAX, [Species.ESPEON, Species.UMBREON, Species.SYLVEON]], // GMax Pikachu lead, Mega gen 1 starter
LANCE_CHAMPION: [Species.DRAGONITE, Species.ZYGARDE, Species.AERODACTYL, Species.KINGDRA, Species.ALOLA_EXEGGUTOR], LANCE_CHAMPION: [Species.DRAGONITE, Species.KINGDRA, Species.ALOLA_EXEGGUTOR], // Aerodactyl lead, Mega Lati@s
STEVEN: [Species.METAGROSS, [Species.DIALGA, Species.PALKIA], Species.SKARMORY, Species.AGGRON, Species.CARBINK], STEVEN: [Species.AGGRON, [Species.ARMALDO, Species.CRADILY], Species.DIALGA], // Skarmorly lead, Mega Metagross
WALLACE: [Species.MILOTIC, Species.KYOGRE, Species.WHISCASH, Species.WALREIN, Species.LUDICOLO], WALLACE: [Species.MILOTIC, Species.PALKIA, Species.LUDICOLO], // Pelipper lead, Mega Swampert
CYNTHIA: [Species.SPIRITOMB, Species.GIRATINA, Species.GARCHOMP, Species.MILOTIC, Species.LUCARIO, Species.TOGEKISS], CYNTHIA: [Species.GIRATINA, Species.LUCARIO, Species.TOGEKISS], // Spiritomb lead, Mega Garchomp
ALDER: [Species.VOLCARONA, Species.GROUDON, Species.BOUFFALANT, Species.ACCELGOR, Species.CONKELDURR], ALDER: [Species.VOLCARONA, Species.ZEKROM, [Species.ACCELGOR, Species.ESCAVALIER], Species.KELDEO], // Bouffalant/Braviary lead
IRIS: [Species.HAXORUS, Species.YVELTAL, Species.DRUDDIGON, Species.AGGRON, Species.LAPRAS], IRIS: [Species.HAXORUS, Species.RESHIRAM, Species.ARCHEOPS], // Druddigon lead, Gmax Lapras
DIANTHA: [Species.HAWLUCHA, Species.XERNEAS, Species.GOURGEIST, Species.GOODRA, Species.GARDEVOIR], DIANTHA: [Species.HAWLUCHA, Species.XERNEAS, Species.GOODRA], // Gourgeist lead, Mega Gardevoir
HAU: [Species.ALOLA_RAICHU, [Species.SOLGALEO, Species.LUNALA], Species.NOIVERN, [Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA], Species.CRABOMINABLE], HAU: [[Species.SOLGALEO, Species.LUNALA], Species.NOIVERN, [Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA], [Species.TAPU_BULU, Species.TAPU_FINI, Species.TAPU_KOKO, Species.TAPU_LELE]], // Alola Raichu lead
LEON: [Species.DRAGAPULT, [Species.ZACIAN, Species.ZAMAZENTA], Species.SEISMITOAD, Species.AEGISLASH, Species.CHARIZARD], LEON: [Species.DRAGAPULT, [Species.ZACIAN, Species.ZAMAZENTA], Species.AEGISLASH], // Rillaboom/Cinderace/Inteleon lead
GEETA: [Species.GLIMMORA, Species.MIRAIDON, Species.ESPATHRA, Species.VELUZA, Species.KINGAMBIT], GEETA: [Species.MIRAIDON, [Species.ESPATHRA, Species.VELUZA], [Species.AVALUGG, Species.HISUI_AVALUGG], Species.KINGAMBIT], // Glimmora lead
NEMONA: [Species.LYCANROC, Species.KORAIDON, Species.KOMMO_O, Species.PAWMOT, Species.DUSKNOIR], NEMONA: [Species.KORAIDON, Species.PAWMOT, [Species.DUDUNSPARCE, Species.ORTHWORM], [Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL]], // Lycanroc lead
KIERAN: [Species.POLITOED, [Species.OGERPON, Species.TERAPAGOS], Species.HYDRAPPLE, Species.PORYGON_Z, Species.GRIMMSNARL], KIERAN: [[Species.GRIMMSNARL, Species.INCINEROAR, Species.PORYGON_Z], Species.OGERPON, Species.TERAPAGOS, Species.HYDRAPPLE], // Poliwrath/Politoed lead
}; };
export const trainerConfigs: TrainerConfigs = { export const trainerConfigs: TrainerConfigs = {
@ -1212,20 +1212,100 @@ export const trainerConfigs: TrainerConfigs = {
[TrainerType.LACEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LACEY"],false, Type.FAIRY), [TrainerType.LACEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LACEY"],false, Type.FAIRY),
[TrainerType.DRAYTON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAYTON"],true, Type.DRAGON), [TrainerType.DRAYTON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAYTON"],true, Type.DRAGON),
[TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(signatureSpecies["BLUE"],true).setBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double"), [TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(signatureSpecies["BLUE"],true).setBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double")
[TrainerType.RED]: new TrainerConfig(++t).initForChampion(signatureSpecies["RED"],true).setBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double"), .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALAKAZAM], TrainerSlot.TRAINER, true, p => {
[TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(signatureSpecies["LANCE_CHAMPION"],true).setBattleBgm("battle_johto_champion"), p.generateAndPopulateMoveset();
[TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(signatureSpecies["STEVEN"],true).setBattleBgm("battle_hoenn_champion").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double"), }))
[TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(signatureSpecies["WALLACE"],true).setBattleBgm("battle_hoenn_champion").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double"), .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT], TrainerSlot.TRAINER, true, p => {
[TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(signatureSpecies["CYNTHIA"],false).setBattleBgm("battle_sinnoh_champion"), p.formIndex = 1;
[TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(signatureSpecies["ALDER"],true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder"), p.generateAndPopulateMoveset();
[TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(signatureSpecies["IRIS"],false).setBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double"), })),
[TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(signatureSpecies["DIANTHA"],false), [TrainerType.RED]: new TrainerConfig(++t).initForChampion(signatureSpecies["RED"],true).setBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double")
[TrainerType.HAU]: new TrainerConfig(++t).initForChampion(signatureSpecies["HAU"],true), .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PIKACHU], TrainerSlot.TRAINER, true, p => {
[TrainerType.LEON]: new TrainerConfig(++t).initForChampion(signatureSpecies["LEON"],true), p.formIndex = 8;
[TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(signatureSpecies["GEETA"],false), p.generateAndPopulateMoveset();
[TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(signatureSpecies["NEMONA"],false), }))
[TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(signatureSpecies["KIERAN"],true), .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
})),
[TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(signatureSpecies["LANCE_CHAMPION"],true).setBattleBgm("battle_johto_champion")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.AERODACTYL], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.LATIAS, Species.LATIOS], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
})),
[TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(signatureSpecies["STEVEN"],true).setBattleBgm("battle_hoenn_champion").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SKARMORY], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
})),
[TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(signatureSpecies["WALLACE"],true).setBattleBgm("battle_hoenn_champion").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => {
p.abilityIndex = 1; // Drizzle
p.generateAndPopulateMoveset();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.SWAMPERT], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
})),
[TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(signatureSpecies["CYNTHIA"],false).setBattleBgm("battle_sinnoh_champion")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SPIRITOMB], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.GARCHOMP], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
})),
[TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(signatureSpecies["ALDER"],true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BOUFFALANT, Species.BRAVIARY], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
})),
[TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(signatureSpecies["IRIS"],false).setBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double")
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DRUDDIGON], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
})),
[TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(signatureSpecies["DIANTHA"],false)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GOURGEIST], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.GARDEVOIR], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
})),
[TrainerType.HAU]: new TrainerConfig(++t).initForChampion(signatureSpecies["HAU"],true)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALOLA_RAICHU], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
})),
[TrainerType.LEON]: new TrainerConfig(++t).initForChampion(signatureSpecies["LEON"],true)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.RILLABOOM, Species.CINDERACE, Species.INTELEON], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.CHARIZARD], TrainerSlot.TRAINER, true, p => {
p.formIndex = 3;
p.generateAndPopulateMoveset();
})),
[TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(signatureSpecies["GEETA"],false)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GLIMMORA], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
})),
[TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(signatureSpecies["NEMONA"],false)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
})),
[TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(signatureSpecies["KIERAN"],true)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.POLIWRATH, Species.POLITOED], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset();
})),
[TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL) [TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL)

View File

@ -10,8 +10,10 @@ export enum ArenaEventType {
/** Triggers when a {@linkcode TerrainType} is added, overlapped, or removed */ /** Triggers when a {@linkcode TerrainType} is added, overlapped, or removed */
TERRAIN_CHANGED = "onTerrainChanged", TERRAIN_CHANGED = "onTerrainChanged",
/** Triggers when a {@linkcode ArenaTagType} is added or removed */ /** Triggers when a {@linkcode ArenaTagType} is added */
TAG_CHANGED = "onTagChanged", TAG_ADDED = "onTagAdded",
/** Triggers when a {@linkcode ArenaTagType} is removed */
TAG_REMOVED = "onTagRemoved",
} }
/** /**
@ -59,17 +61,34 @@ export class TerrainChangedEvent extends ArenaEvent {
this.newTerrainType = newTerrainType; this.newTerrainType = newTerrainType;
} }
} }
/** /**
* Container class for {@linkcode ArenaEventType.TAG_CHANGED} events * Container class for {@linkcode ArenaEventType.TAG_ADDED} events
* @extends ArenaEvent * @extends ArenaEvent
*/ */
export class TagChangedEvent extends ArenaEvent { export class TagAddedEvent extends ArenaEvent {
/** The {@linkcode ArenaTagType} being set */ /** The {@linkcode ArenaTagType} being added */
public arenaTagType: ArenaTagType; public arenaTagType: ArenaTagType;
/** The {@linkcode ArenaTagSide} the tag is being placed on */ /** The {@linkcode ArenaTagSide} the tag is being placed on */
public arenaTagSide: ArenaTagSide; public arenaTagSide: ArenaTagSide;
constructor(arenaTagType: ArenaTagType, arenaTagSide: ArenaTagSide, duration: number) { constructor(arenaTagType: ArenaTagType, arenaTagSide: ArenaTagSide, duration: number) {
super(ArenaEventType.TAG_CHANGED, duration); super(ArenaEventType.TAG_ADDED, duration);
this.arenaTagType = arenaTagType;
this.arenaTagSide = arenaTagSide;
}
}
/**
* Container class for {@linkcode ArenaEventType.TAG_REMOVED} events
* @extends ArenaEvent
*/
export class TagRemovedEvent extends ArenaEvent {
/** The {@linkcode ArenaTagType} being removed */
public arenaTagType: ArenaTagType;
/** The {@linkcode ArenaTagSide} the tag was being placed on */
public arenaTagSide: ArenaTagSide;
constructor(arenaTagType: ArenaTagType, arenaTagSide: ArenaTagSide, duration: number) {
super(ArenaEventType.TAG_REMOVED, duration);
this.arenaTagType = arenaTagType; this.arenaTagType = arenaTagType;
this.arenaTagSide = arenaTagSide; this.arenaTagSide = arenaTagSide;

View File

@ -19,7 +19,7 @@ import { Terrain, TerrainType } from "../data/terrain";
import { PostTerrainChangeAbAttr, PostWeatherChangeAbAttr, applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs } from "../data/ability"; import { PostTerrainChangeAbAttr, PostWeatherChangeAbAttr, applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs } from "../data/ability";
import Pokemon from "./pokemon"; import Pokemon from "./pokemon";
import * as Overrides from "../overrides"; import * as Overrides from "../overrides";
import { WeatherChangedEvent, TerrainChangedEvent, TagChangedEvent } from "./arena-events"; import { WeatherChangedEvent, TerrainChangedEvent, TagAddedEvent, TagRemovedEvent } from "./arena-events";
export class Arena { export class Arena {
public scene: BattleScene; public scene: BattleScene;
@ -550,7 +550,7 @@ export class Arena {
this.tags.push(newTag); this.tags.push(newTag);
newTag.onAdd(this); newTag.onAdd(this);
this.eventTarget.dispatchEvent(new TagChangedEvent(newTag.tagType, newTag.side, newTag.turnCount)); this.eventTarget.dispatchEvent(new TagAddedEvent(newTag.tagType, newTag.side, newTag.turnCount));
return true; return true;
} }
@ -577,6 +577,8 @@ export class Arena {
this.tags.filter(t => !(t.lapse(this))).forEach(t => { this.tags.filter(t => !(t.lapse(this))).forEach(t => {
t.onRemove(this); t.onRemove(this);
this.tags.splice(this.tags.indexOf(t), 1); this.tags.splice(this.tags.indexOf(t), 1);
this.eventTarget.dispatchEvent(new TagRemovedEvent(t.tagType, t.side, t.turnCount));
}); });
} }
@ -586,6 +588,8 @@ export class Arena {
if (tag) { if (tag) {
tag.onRemove(this); tag.onRemove(this);
tags.splice(tags.indexOf(tag), 1); tags.splice(tags.indexOf(tag), 1);
this.eventTarget.dispatchEvent(new TagRemovedEvent(tag.tagType, tag.side, tag.turnCount));
} }
return !!tag; return !!tag;
} }
@ -595,6 +599,8 @@ export class Arena {
if (tag) { if (tag) {
tag.onRemove(this); tag.onRemove(this);
this.tags.splice(this.tags.indexOf(tag), 1); this.tags.splice(this.tags.indexOf(tag), 1);
this.eventTarget.dispatchEvent(new TagRemovedEvent(tag.tagType, tag.side, tag.turnCount));
} }
return !!tag; return !!tag;
} }
@ -603,6 +609,8 @@ export class Arena {
removeAllTags(): void { removeAllTags(): void {
while (this.tags.length) { while (this.tags.length) {
this.tags[0].onRemove(this); this.tags[0].onRemove(this);
this.eventTarget.dispatchEvent(new TagRemovedEvent(this.tags[0].tagType, this.tags[0].side, this.tags[0].turnCount));
this.tags.splice(0, 1); this.tags.splice(0, 1);
} }
} }

View File

@ -44,7 +44,7 @@ import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMov
import { TerrainType } from "../data/terrain"; import { TerrainType } from "../data/terrain";
import { TrainerSlot } from "../data/trainer-config"; import { TrainerSlot } from "../data/trainer-config";
import * as Overrides from "../overrides"; import * as Overrides from "../overrides";
import { BerryType } from "../data/berry"; import { BerryType } from "../data/enums/berry-type";
import i18next from "../plugins/i18n"; import i18next from "../plugins/i18n";
import { speciesEggMoves } from "../data/egg-moves"; import { speciesEggMoves } from "../data/egg-moves";
import { ModifierTier } from "../modifier/modifier-tier"; import { ModifierTier } from "../modifier/modifier-tier";

View File

@ -95,6 +95,11 @@ export class LoadingScene extends SceneBase {
this.loadImage("type_tera", "ui"); this.loadImage("type_tera", "ui");
this.loadAtlas("type_bgs", "ui"); this.loadAtlas("type_bgs", "ui");
this.loadImage("dawn_icon", "ui");
this.loadImage("day_icon", "ui");
this.loadImage("dusk_icon", "ui");
this.loadImage("night_icon", "ui");
this.loadImage("pb_tray_overlay_player", "ui"); this.loadImage("pb_tray_overlay_player", "ui");
this.loadImage("pb_tray_overlay_enemy", "ui"); this.loadImage("pb_tray_overlay_enemy", "ui");
this.loadAtlas("pb_tray_ball", "ui"); this.loadAtlas("pb_tray_ball", "ui");
@ -208,7 +213,7 @@ export class LoadingScene extends SceneBase {
this.loadAtlas("types", ""); this.loadAtlas("types", "");
// Get current lang and load the types atlas for it. English will only load types while all other languages will load types and types_<lang> // Get current lang and load the types atlas for it. English will only load types while all other languages will load types and types_<lang>
const lang = i18next.language; const lang = i18next.resolvedLanguage;
if (lang !== "en") { if (lang !== "en") {
if (Utils.verifyLang(lang)) { if (Utils.verifyLang(lang)) {
this.loadAtlas(`types_${lang}`, ""); this.loadAtlas(`types_${lang}`, "");

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Wiederherstellungsmarke", description: "Heilt 2% der maximalen KP pro Runde" }, "ENEMY_HEAL": { name: "Wiederherstellungsmarke", description: "Heilt 2% der maximalen KP pro Runde" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Giftmarke" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Giftmarke" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { "name": "Lähmungsmarke" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { "name": "Lähmungsmarke" },
"ENEMY_ATTACK_SLEEP_CHANCE": { "name": "Schlafmarke" },
"ENEMY_ATTACK_FREEZE_CHANCE": { "name": "Gefriermarke" },
"ENEMY_ATTACK_BURN_CHANCE": { "name": "Brandmarke" }, "ENEMY_ATTACK_BURN_CHANCE": { "name": "Brandmarke" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { "name": "Vollheilungsmarke", "description": "Fügt eine 10%ige Chance hinzu, jede Runde einen Statuszustand zu heilen" }, "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { "name": "Vollheilungsmarke", "description": "Fügt eine 2,5%ige Chance hinzu, jede Runde einen Statuszustand zu heilen" },
"ENEMY_ENDURE_CHANCE": { "name": "Ausdauer-Marke" }, "ENEMY_ENDURE_CHANCE": { "name": "Ausdauer-Marke" },
"ENEMY_FUSED_CHANCE": { "name": "Fusionsmarke", "description": "Fügt eine 1%ige Chance hinzu, dass ein wildes Pokémon eine Fusion ist" }, "ENEMY_FUSED_CHANCE": { "name": "Fusionsmarke", "description": "Fügt eine 1%ige Chance hinzu, dass ein wildes Pokémon eine Fusion ist" },
@ -366,7 +364,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"HARD_METEORITE": "Harter Meteorit", "HARD_METEORITE": "Harter Meteorit",
"SMOOTH_METEORITE": "Glatter Meteorit", "SMOOTH_METEORITE": "Glatter Meteorit",
"ADAMANT_CRYSTAL": "Adamantkristall", "ADAMANT_CRYSTAL": "Adamantkristall",
"LUSTROUS_ORB": "Weiß-Orb", "LUSTROUS_GLOBE": "Weißkristall",
"GRISEOUS_CORE": "Platinumkristall", "GRISEOUS_CORE": "Platinumkristall",
"REVEAL_GLASS": "Wahrspiegel", "REVEAL_GLASS": "Wahrspiegel",
"GRACIDEA": "Gracidea", "GRACIDEA": "Gracidea",

View File

@ -1578,7 +1578,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
"encounter": { "encounter": {
1: `Know what? I really look forward to having serious battles with strong Trainers! 1: `Know what? I really look forward to having serious battles with strong Trainers!
$I mean, come on! The Trainers who make it here are Trainers who desire victory with every fiber of their being! $I mean, come on! The Trainers who make it here are Trainers who desire victory with every fiber of their being!
#And they are battling alongside Pokémon that have been through countless difficult battles! $And they are battling alongside Pokémon that have been through countless difficult battles!
$If I battle with people like that, not only will I get stronger, my Pokémon will, too! $If I battle with people like that, not only will I get stronger, my Pokémon will, too!
$And we'll get to know each other even better! OK! Brace yourself! $And we'll get to know each other even better! OK! Brace yourself!
$I'm Iris, the Pokémon League Champion, and I'm going to defeat you!`, $I'm Iris, the Pokémon League Champion, and I'm going to defeat you!`,

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Recovery Token", description: "Heals 2% of max HP every turn" }, "ENEMY_HEAL": { name: "Recovery Token", description: "Heals 2% of max HP every turn" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Sleep Token" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Freeze Token" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 10% chance every turn to heal a status condition" }, "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 2.5% chance every turn to heal a status condition" },
"ENEMY_ENDURE_CHANCE": { name: "Endure Token" }, "ENEMY_ENDURE_CHANCE": { name: "Endure Token" },
"ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion" }, "ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion" },
}, },
@ -365,7 +363,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"HARD_METEORITE": "Hard Meteorite", "HARD_METEORITE": "Hard Meteorite",
"SMOOTH_METEORITE": "Smooth Meteorite", "SMOOTH_METEORITE": "Smooth Meteorite",
"ADAMANT_CRYSTAL": "Adamant Crystal", "ADAMANT_CRYSTAL": "Adamant Crystal",
"LUSTROUS_ORB": "Lustrous Orb", "LUSTROUS_GLOBE": "Lustrous Globe",
"GRISEOUS_CORE": "Griseous Core", "GRISEOUS_CORE": "Griseous Core",
"REVEAL_GLASS": "Reveal Glass", "REVEAL_GLASS": "Reveal Glass",
"GRACIDEA": "Gracidea", "GRACIDEA": "Gracidea",

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Recovery Token", description: "Cura el 2% de los PS máximo en cada turno" }, "ENEMY_HEAL": { name: "Recovery Token", description: "Cura el 2% de los PS máximo en cada turno" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Sleep Token" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Freeze Token" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Agrega un 10% de probabilidad cada turno de curar un problema de estado" }, "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Agrega un 2.5% de probabilidad cada turno de curar un problema de estado" },
"ENEMY_ENDURE_CHANCE": { name: "Endure Token" }, "ENEMY_ENDURE_CHANCE": { name: "Endure Token" },
"ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Agrega un 1% de probabilidad de que un Pokémon salvaje sea una fusión" }, "ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Agrega un 1% de probabilidad de que un Pokémon salvaje sea una fusión" },
}, },
@ -365,7 +363,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"HARD_METEORITE": "Meteorito Duro", "HARD_METEORITE": "Meteorito Duro",
"SMOOTH_METEORITE": "Meteorito Suave", "SMOOTH_METEORITE": "Meteorito Suave",
"ADAMANT_CRYSTAL": "Gran Diamansfera", "ADAMANT_CRYSTAL": "Gran Diamansfera",
"LUSTROUS_ORB": "Gran Lustresfera", "LUSTROUS_GLOBE": "Gran Lustresfera",
"GRISEOUS_CORE": "Gran Griseosfera", "GRISEOUS_CORE": "Gran Griseosfera",
"REVEAL_GLASS": "Espejo Veraz", "REVEAL_GLASS": "Espejo Veraz",
"GRACIDEA": "Gracídea", "GRACIDEA": "Gracídea",

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Jeton Soin", description: "Soigne 2% des PV max à chaque tour" }, "ENEMY_HEAL": { name: "Jeton Soin", description: "Soigne 2% des PV max à chaque tour" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Jeton Poison" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Jeton Poison" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Jeton Paralysie" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Jeton Paralysie" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Jeton Sommeil" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Jeton Gel" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Jeton Brulure" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Jeton Brulure" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Jeton Total Soin", description: "Ajoute 10% de chances à chaque tour de se soigner dun problème de statut." }, "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Jeton Total Soin", description: "Ajoute 2.5% de chances à chaque tour de se soigner dun problème de statut." },
"ENEMY_ENDURE_CHANCE": { name: "Jeton Ténacité" }, "ENEMY_ENDURE_CHANCE": { name: "Jeton Ténacité" },
"ENEMY_FUSED_CHANCE": { name: "Jeton Fusion", description: "Ajoute 1% de chances quun Pokémon sauvage soit une fusion." }, "ENEMY_FUSED_CHANCE": { name: "Jeton Fusion", description: "Ajoute 1% de chances quun Pokémon sauvage soit une fusion." },
}, },
@ -365,7 +363,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"HARD_METEORITE": "Méteorite Solide", "HARD_METEORITE": "Méteorite Solide",
"SMOOTH_METEORITE": "Méteorite Lisse", "SMOOTH_METEORITE": "Méteorite Lisse",
"ADAMANT_CRYSTAL": "Globe Adamant", "ADAMANT_CRYSTAL": "Globe Adamant",
"LUSTROUS_ORB": "Orbe Perlé", "LUSTROUS_GLOBE": "Globe Perlé",
"GRISEOUS_CORE": "Globe Platiné", "GRISEOUS_CORE": "Globe Platiné",
"REVEAL_GLASS": "Miroir Sacré", "REVEAL_GLASS": "Miroir Sacré",
"GRACIDEA": "Gracidée", "GRACIDEA": "Gracidée",

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Gettone del Recupero", description: "Cura il 2% dei PS massimi ogni turno" }, "ENEMY_HEAL": { name: "Gettone del Recupero", description: "Cura il 2% dei PS massimi ogni turno" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Gettone del Veleno" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Gettone del Veleno" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Gettone della Paralisi" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Gettone della Paralisi" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Gettone del Sonno" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Gettone del Congelamento" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Gettone della Bruciatura" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Gettone della Bruciatura" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone Guarigione Completa", description: "Aggiunge una probabilità del 10% a ogni turno di curare una condizione di stato" }, "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone Guarigione Completa", description: "Aggiunge una probabilità del 2.5% a ogni turno di curare una condizione di stato" },
"ENEMY_ENDURE_CHANCE": { name: "Gettone di Resistenza" }, "ENEMY_ENDURE_CHANCE": { name: "Gettone di Resistenza" },
"ENEMY_FUSED_CHANCE": { name: "Gettone della fusione", description: "Aggiunge l'1% di possibilità che un Pokémon selvatico sia una fusione" }, "ENEMY_FUSED_CHANCE": { name: "Gettone della fusione", description: "Aggiunge l'1% di possibilità che un Pokémon selvatico sia una fusione" },
}, },
@ -365,7 +363,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"HARD_METEORITE": "Meteorite Dura", "HARD_METEORITE": "Meteorite Dura",
"SMOOTH_METEORITE": "Meteorite Liscia", "SMOOTH_METEORITE": "Meteorite Liscia",
"ADAMANT_CRYSTAL": "Adamasferoide", "ADAMANT_CRYSTAL": "Adamasferoide",
"LUSTROUS_ORB": "Splendisfera", "LUSTROUS_GLOBE": "Splendisferoide",
"GRISEOUS_CORE": "Grigiosferoide", "GRISEOUS_CORE": "Grigiosferoide",
"REVEAL_GLASS": "Verispecchio", "REVEAL_GLASS": "Verispecchio",
"GRACIDEA": "Gracidea", "GRACIDEA": "Gracidea",

View File

@ -1,6 +1,6 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n"; import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}}(는)은 {{abilityName}} 때문에\n반동 데미지를 받지 않는다!", "blockRecoilDamage" : "{{pokemonName}}[[는]] {{abilityName}} 때문에\n반동 데미지를 받지 않는다!",
"badDreams": "{{pokemonName}}(는)은\n나이트메어 때문에 시달리고 있다!", "badDreams": "{{pokemonName}}[[는]]\n나이트메어 때문에 시달리고 있다!",
} as const; } as const;

View File

@ -1,21 +1,21 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n"; import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const battle: SimpleTranslationEntries = { export const battle: SimpleTranslationEntries = {
"bossAppeared": "{{bossName}}(이)가 나타났다.", "bossAppeared": "{{bossName}}[[가]] 나타났다.",
"trainerAppeared": "{{trainerName}}(이)가\n승부를 걸어왔다!", "trainerAppeared": "{{trainerName}}[[가]]\n승부를 걸어왔다!",
"trainerAppearedDouble": "{{trainerName}}(이)가\n승부를 걸어왔다!", "trainerAppearedDouble": "{{trainerName}}[[가]]\n승부를 걸어왔다!",
"trainerSendOut": "{{trainerName}}(는)은\n{{pokemonName}}(를)을 내보냈다!", "trainerSendOut": "{{trainerName}}[[는]]\n{{pokemonName}}[[를]] 내보냈다!",
"singleWildAppeared": "앗! 야생 {{pokemonName}}(이)가\n튀어나왔다!", "singleWildAppeared": "앗! 야생 {{pokemonName}}[[가]]\n튀어나왔다!",
"multiWildAppeared": "야생 {{pokemonName1}}(과)와\n{{pokemonName2}}(이)가 튀어나왔다!", "multiWildAppeared": "야생 {{pokemonName1}}[[와]]\n{{pokemonName2}}[[가]] 튀어나왔다!",
"playerComeBack": "돌아와, {{pokemonName}}!", "playerComeBack": "돌아와, {{pokemonName}}!",
"trainerComeBack": "{{trainerName}}(는)은 {{pokemonName}}를(을) 넣어버렸다!", "trainerComeBack": "{{trainerName}}[[는]] {{pokemonName}}[[를]] 넣어버렸다!",
"playerGo": "가랏! {{pokemonName}}!", "playerGo": "가랏! {{pokemonName}}!",
"trainerGo": "{{trainerName}}(는)은 {{pokemonName}}를(을) 내보냈다!", "trainerGo": "{{trainerName}}[[는]] {{pokemonName}}[[를]] 내보냈다!",
"switchQuestion": "{{pokemonName}}를(을)\n교체하시겠습니까?", "switchQuestion": "{{pokemonName}}[[를]]\n교체하시겠습니까?",
"trainerDefeated": "{{trainerName}}과(와)의\n승부에서 이겼다!", "trainerDefeated": "{{trainerName}}[[와]]의\n승부에서 이겼다!",
"moneyWon": "상금으로\n₽{{moneyAmount}}을 손에 넣었다!", "moneyWon": "상금으로\n₽{{moneyAmount}}을 손에 넣었다!",
"pokemonCaught": "신난다-!\n{{pokemonName}}(를)을 잡았다!", "pokemonCaught": "신난다-!\n{{pokemonName}}[[를]] 잡았다!",
"partyFull": "지닌 포켓몬이 가득 찼습니다. {{pokemonName}}를(을)\n대신해 포켓몬을 놓아주시겠습니까?", "partyFull": "지닌 포켓몬이 가득 찼습니다. {{pokemonName}}[[를]]\n대신해 포켓몬을 놓아주시겠습니까?",
"pokemon": "포켓몬", "pokemon": "포켓몬",
"sendOutPokemon": "가랏! {{pokemonName}}!", "sendOutPokemon": "가랏! {{pokemonName}}!",
"hitResultCriticalHit": "급소에 맞았다!", "hitResultCriticalHit": "급소에 맞았다!",
@ -25,22 +25,22 @@ export const battle: SimpleTranslationEntries = {
"hitResultOneHitKO": "일격필살!", "hitResultOneHitKO": "일격필살!",
"attackFailed": "하지만 실패했다!", "attackFailed": "하지만 실패했다!",
"attackHitsCount": "{{count}}번 맞았다!", "attackHitsCount": "{{count}}번 맞았다!",
"expGain": "{{pokemonName}}(는)은\n{{exp}} 경험치를 얻었다!", "expGain": "{{pokemonName}}[[는]]\n{{exp}} 경험치를 얻었다!",
"levelUp": "{{pokemonName}}(는)은\n레벨 {{level}}(으)로 올랐다!", "levelUp": "{{pokemonName}}[[는]]\n레벨 {{level}}[[로]] 올랐다!",
"learnMove": "{{pokemonName}}(는)은 새로\n{{moveName}}를(을) 배웠다!", "learnMove": "{{pokemonName}}[[는]] 새로\n{{moveName}}[[를]] 배웠다!",
"learnMovePrompt": "{{pokemonName}}(는)은 새로\n{{moveName}}를(을) 배우고 싶다!…", "learnMovePrompt": "{{pokemonName}}[[는]] 새로\n{{moveName}}[[를]] 배우고 싶다!…",
"learnMoveLimitReached": "그러나 {{pokemonName}}(는)은 기술을 4개\n알고 있으므로 더 이상 배울 수 없다!", "learnMoveLimitReached": "그러나 {{pokemonName}}[[는]] 기술을 4개\n알고 있으므로 더 이상 배울 수 없다!",
"learnMoveReplaceQuestion": "{{moveName}} 대신 다른 기술을 잊게 하겠습니까?", "learnMoveReplaceQuestion": "{{moveName}} 대신 다른 기술을 잊게 하겠습니까?",
"learnMoveStopTeaching": "그럼… {{moveName}}를(을)\n배우는 것을 포기하겠습니까?", "learnMoveStopTeaching": "그럼… {{moveName}}[[를]]\n배우는 것을 포기하겠습니까?",
"learnMoveNotLearned": "{{pokemonName}}(는)은 {{moveName}}를(을)\n결국 배우지 않았다!", "learnMoveNotLearned": "{{pokemonName}}[[는]] {{moveName}}[[를]]\n결국 배우지 않았다!",
"learnMoveForgetQuestion": "어느 기술을 잊게 하고싶은가?", "learnMoveForgetQuestion": "어느 기술을 잊게 하고싶은가?",
"learnMoveForgetSuccess": "{{pokemonName}}(는)은 {{moveName}}를(을) 깨끗이 잊었다!", "learnMoveForgetSuccess": "{{pokemonName}}[[는]] {{moveName}}[[를]] 깨끗이 잊었다!",
"countdownPoof": "@d{32}1, @d{15}2, @d{15}… @d{15}… @d{30}@s{pb_bounce_1}짠!", "countdownPoof": "@d{32}1, @d{15}2, @d{15}… @d{15}… @d{30}@s{pb_bounce_1}짠!",
"learnMoveAnd": "그리고…", "learnMoveAnd": "그리고…",
"levelCapUp": "레벨의 최대치가\n{{levelCap}}까지 상승했다!", "levelCapUp": "레벨의 최대치가\n{{levelCap}}까지 상승했다!",
"moveNotImplemented": "{{moveName}}(는)은 아직 구현되지 않아 사용할 수 없다…", "moveNotImplemented": "{{moveName}}[[는]] 아직 구현되지 않아 사용할 수 없다…",
"moveNoPP": "기술의 남은 포인트가 없다!", "moveNoPP": "기술의 남은 포인트가 없다!",
"moveDisabled": "{{moveName}}를(을) 쓸 수 없다!", "moveDisabled": "{{moveName}}[[를]] 쓸 수 없다!",
"noPokeballForce": "본 적 없는 힘이\n볼을 사용하지 못하게 한다.", "noPokeballForce": "본 적 없는 힘이\n볼을 사용하지 못하게 한다.",
"noPokeballTrainer": "다른 트레이너의 포켓몬은 잡을 수 없다!", "noPokeballTrainer": "다른 트레이너의 포켓몬은 잡을 수 없다!",
"noPokeballMulti": "안돼! 2마리 있어서\n목표를 정할 수가 없어…!", "noPokeballMulti": "안돼! 2마리 있어서\n목표를 정할 수가 없어…!",

View File

@ -5,5 +5,5 @@ export const commandUiHandler: SimpleTranslationEntries = {
"ball": "볼", "ball": "볼",
"pokemon": "포켓몬", "pokemon": "포켓몬",
"run": "도망간다", "run": "도망간다",
"actionMessage": "{{pokemonName}}(는)은 무엇을 할까?", "actionMessage": "{{pokemonName}}[[는]] 무엇을 할까?",
} as const; } as const;

View File

@ -1,4 +1,4 @@
import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/plugins/i18n"; import { DialogueTranslationEntries, SimpleTranslationEntries } from "#app/plugins/i18n";
// Dialogue of the NPCs in the game when the player character is male (or unset) // Dialogue of the NPCs in the game when the player character is male (or unset)
export const PGMdialogue: DialogueTranslationEntries = { export const PGMdialogue: DialogueTranslationEntries = {
@ -2335,113 +2335,113 @@ export const PGFmiscDialogue: SimpleTranslationEntries = PGMmiscDialogue;
export const PGMdoubleBattleDialogue: DialogueTranslationEntries = { export const PGMdoubleBattleDialogue: DialogueTranslationEntries = {
"blue_red_double": { "blue_red_double": {
"encounter": { "encounter": {
1: `Blue: Hey Red, let's show them what we're made of! 1: `그린: 어이 레드! 우리가 누군지 보여주자고!
$Red: ... $레드: ...
$Blue: This is Pallet Town Power!`, $그린: 태초마을의 !`,
}, },
"victory": { "victory": {
1: `Blue: That was a great battle! 1: `그린: 훌륭한 승부였어!
$Red: ...`, $레드: ...`,
}, },
}, },
"red_blue_double": { "red_blue_double": {
"encounter": { "encounter": {
1: `Red: ...! 1: `레드: ...!
$Blue: He never talks much. $그린: .
$Blue: But dont let that fool you! He is a champ after all!`, $그린: 그렇지만 ! !`,
}, },
"victory": { "victory": {
1: `Red: ...! 1: `레드: ...!
$Blue: Next time we will beat you!`, $그린: 다음에는 !`,
}, },
}, },
"tate_liza_double": { "tate_liza_double": {
"encounter": { "encounter": {
1: `Tate: Are you suprised? 1: `풍: 에헤헤... 체육관 관장이
$Liza: We are two gym leaders at once! $란: ?
$Tate: We are twins! $풍: 우리는 !
$Liza: We dont need to talk to understand each other! $란: 굳이
$Tate: Twice the power... $풍: 자동으로 릿
$Liza: Can you handle it?`, $란: 호흡을 !`,
}, },
"victory": { "victory": {
1: `Tate: What? Our combination was perfect! 1: `풍: 우, 우리들의
$Liza: Looks like we need to train more...`, $란: 팀워크가...!`,
}, },
}, },
"liza_tate_double": { "liza_tate_double": {
"encounter": { "encounter": {
1: `Liza: Hihihi... Are you suprised? 1: `란: 우후후... 체육관 관장이
$Tate: Yes, we are really two gym leaders at once! $풍: ?
$Liza: This is my twin brother Tate! $란: 우리는 !
$Tate: And this is my twin sister Liza! $풍: 완벽한
$Liza: Don't you think we are a perfect combination?` $란: 과연 ?`
}, },
"victory": { "victory": {
1: `Liza: Are we... 1: `란: 우리들이 생각한 만큼
$Tate: ...not as strong as we thought?`, $풍: 우리가 ?`,
}, },
}, },
"wallace_steven_double": { "wallace_steven_double": {
"encounter": { "encounter": {
1: `Steven: Wallace, let's show them the power of the champions! 1: `성호: 윤진! 우리 챔피언의 힘을 보여주자!
$Wallace: We will show you the power of Hoenn! $윤진: 호연의 !
$Steven: Let's go!`, $성호: 간다!`,
}, },
"victory": { "victory": {
1: `Steven: That was a great battle! 1: `성호: 훌륭한 승부였어!
$Wallace: We will win next time!`, $윤진: 다음엔 !`,
}, },
}, },
"steven_wallace_double": { "steven_wallace_double": {
"encounter": { "encounter": {
1: `Steven: Do you have any rare pokémon? 1: `성호: 너 혹시 희귀한 포켓몬 가지고 있니?
$Wallace: Steven... We are here for a battle, not to show off our pokémon. $윤진: 성호야... .
$Steven: Oh... I see... Let's go then!`, $성호: 오... ... !`,
}, },
"victory": { "victory": {
1: `Steven: Now that we are done with the battle, let's show off our pokémon! 1: `성호: 이제 승부는 끝났으니 포켓몬을 자랑해 볼까!
$Wallace: Steven...`, $윤진: 성호야...`,
}, },
}, },
"alder_iris_double": { "alder_iris_double": {
"encounter": { "encounter": {
1: `Alder: We are the strongest trainers in Unova! 1: `노간주: 우리는 하나 지방 최강의 트레이너들이란다!
$Iris: Fights against strong trainers are the best!`, $아이리스: 이렇게 ~!!`,
}, },
"victory": { "victory": {
1: `Alder: Wow! You are super strong! 1: `노간주: 장하구나! 실로 견줄 자가 천하에 없도다!
$Iris: We will win next time!`, $아이리스: 다음 ~!`,
}, },
}, },
"iris_alder_double": { "iris_alder_double": {
"encounter": { "encounter": {
1: `Iris: Welcome Challenger! I am THE Unova Champion! 1: `아이리스: 어서 와, 도전자! 내가 바로 하나 지방 챔피언이야~!
$Alder: Iris, aren't you a bit too excited?`, $노간주: 아이리스야, ?`,
}, },
"victory": { "victory": {
1: `Iris: A loss like this is not easy to take... 1: `아이리스: 후와아아아아... 최선을 다했는데도... 우리가 져버렸네!
$Alder: But we will only get stronger with every loss!`, $노간주: 하지만 !`,
}, },
}, },
"piers_marnie_double": { "piers_marnie_double": {
"encounter": { "encounter": {
1: `Marnie: Brother, let's show them the power of Spikemuth! 1: `마리: 오빠, 스파이크마을의 힘을 보여주자!
$Piers: We bring darkness!`, $두송: 우리가 !`,
}, },
"victory": { "victory": {
1: `Marnie: You brought light to our darkness! 1: `마리: 네가 우리의 어둠에 빛을 불러왔구나!
$Piers: Its too bright...`, $두송: 여긴 ...`,
}, },
}, },
"marnie_piers_double": { "marnie_piers_double": {
"encounter": { "encounter": {
1: `Piers: Ready for a concert? 1: `두송: 큰서트 즐길 준비 됐어?
$Marnie: Brother... They are here to fight, not to sing...`, $마리: 오빠... ...`,
}, },
"victory": { "victory": {
1: `Piers: Now that was a great concert! 1: `두송: 훌륭한 콘서트였다!
$Marnie: Brother...`, $마리: 오빠...`,
}, },
}, },
}; };

View File

@ -38,9 +38,9 @@ export const menu: SimpleTranslationEntries = {
"girl": "여자", "girl": "여자",
"evolving": "…오잉!?\n{{pokemonName}}의 모습이…!", "evolving": "…오잉!?\n{{pokemonName}}의 모습이…!",
"stoppedEvolving": "얼라리…?\n{{pokemonName}}의 변화가 멈췄다!", "stoppedEvolving": "얼라리…?\n{{pokemonName}}의 변화가 멈췄다!",
"pauseEvolutionsQuestion": "{{pokemonName}}를(을) 진화하지 않게 만드시겠습니까?\n포켓몬 화면에서 다시 활성화시킬 수 있습니다.", "pauseEvolutionsQuestion": "{{pokemonName}}[[를]] 진화하지 않게 만드시겠습니까?\n포켓몬 화면에서 다시 활성화시킬 수 있습니다.",
"evolutionsPaused": "{{pokemonName}}의 진화가 비활성화되었다.", "evolutionsPaused": "{{pokemonName}}의 진화가 비활성화되었다.",
"evolutionDone": "축하합니다! {{pokemonName}}(는)은\n{{evolvedPokemonName}}(으)로 진화했습니다!", "evolutionDone": "축하합니다! {{pokemonName}}[[는]]\n{{evolvedPokemonName}}[[로]] 진화했습니다!",
"dailyRankings": "일간 랭킹", "dailyRankings": "일간 랭킹",
"weeklyRankings": "주간 랭킹", "weeklyRankings": "주간 랭킹",
"noRankings": "랭킹 정보 없음", "noRankings": "랭킹 정보 없음",

View File

@ -12,8 +12,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
}, },
"PokemonHeldItemModifierType": { "PokemonHeldItemModifierType": {
extra: { extra: {
"inoperable": "{{pokemonName}}(는)은\n이 아이템을 얻을 수 없다!", "inoperable": "{{pokemonName}}[[는]]\n이 아이템을 얻을 수 없다!",
"tooMany": "{{pokemonName}}(는)은\n이 아이템을 너무 많이 갖고 있다!", "tooMany": "{{pokemonName}}[[는]]\n이 아이템을 너무 많이 갖고 있다!",
} }
}, },
"PokemonHpRestoreModifierType": { "PokemonHpRestoreModifierType": {
@ -46,13 +46,13 @@ export const modifierType: ModifierTypeTranslationEntries = {
}, },
"PokemonNatureChangeModifierType": { "PokemonNatureChangeModifierType": {
name: "{{natureName}}민트", name: "{{natureName}}민트",
description: "포켓몬의 성격을 {{natureName}}(으)로 바꾸고 스타팅에도 등록한다.", description: "포켓몬의 성격을 {{natureName}}[[로]] 바꾸고 스타팅에도 등록한다.",
}, },
"DoubleBattleChanceBoosterModifierType": { "DoubleBattleChanceBoosterModifierType": {
description: "{{battleCount}}번의 배틀 동안 더블 배틀이 등장할 확률 두 배", description: "{{battleCount}}번의 배틀 동안 더블 배틀이 등장할 확률 두 배",
}, },
"TempBattleStatBoosterModifierType": { "TempBattleStatBoosterModifierType": {
description: "자신의 모든 포켓몬이 5번의 배틀 동안 {{tempBattleStatName}}(이)가 한 단계 증가" description: "자신의 모든 포켓몬이 5번의 배틀 동안 {{tempBattleStatName}}[[가]] 한 단계 증가"
}, },
"AttackTypeBoosterModifierType": { "AttackTypeBoosterModifierType": {
description: "지니게 하면 {{moveType}}타입 기술의 위력이 20% 상승", description: "지니게 하면 {{moveType}}타입 기술의 위력이 20% 상승",
@ -97,7 +97,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
}, },
"TmModifierType": { "TmModifierType": {
name: "No.{{moveId}} {{moveName}}", name: "No.{{moveId}} {{moveName}}",
description: "포켓몬에게 {{moveName}}를(을) 가르침", description: "포켓몬에게 {{moveName}}[[를]] 가르침",
}, },
"EvolutionItemModifierType": { "EvolutionItemModifierType": {
description: "어느 특정 포켓몬을 진화", description: "어느 특정 포켓몬을 진화",
@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "회복 토큰", description: "매 턴 최대 체력의 2%를 회복" }, "ENEMY_HEAL": { name: "회복 토큰", description: "매 턴 최대 체력의 2%를 회복" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "독 토큰" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "독 토큰" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "마비 토큰" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "마비 토큰" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "잠듦 토큰" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "얼음 토큰" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "화상 토큰" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "화상 토큰" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "만병통치 토큰", description: "매 턴 상태이상에서 회복될 확률 10% 추가" }, "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "만병통치 토큰", description: "매 턴 상태이상에서 회복될 확률 2.5% 추가" },
"ENEMY_ENDURE_CHANCE": { name: "버티기 토큰" }, "ENEMY_ENDURE_CHANCE": { name: "버티기 토큰" },
"ENEMY_FUSED_CHANCE": { name: "합체 토큰", description: "야생 포켓몬이 합체할 확률 1% 추가" }, "ENEMY_FUSED_CHANCE": { name: "합체 토큰", description: "야생 포켓몬이 합체할 확률 1% 추가" },
}, },
@ -365,7 +363,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"HARD_METEORITE": "단단한운석", "HARD_METEORITE": "단단한운석",
"SMOOTH_METEORITE": "부드러운운석", "SMOOTH_METEORITE": "부드러운운석",
"ADAMANT_CRYSTAL": "큰금강옥", "ADAMANT_CRYSTAL": "큰금강옥",
"LUSTROUS_ORB": "큰백옥", "LUSTROUS_GLOBE": "큰백옥",
"GRISEOUS_CORE": "큰백금옥", "GRISEOUS_CORE": "큰백금옥",
"REVEAL_GLASS": "비추는거울", "REVEAL_GLASS": "비추는거울",
"GRACIDEA": "그라시데아꽃", "GRACIDEA": "그라시데아꽃",

View File

@ -15,12 +15,12 @@ export const weather: SimpleTranslationEntries = {
"sandstormStartMessage": "모래바람이 불기 시작했다!", "sandstormStartMessage": "모래바람이 불기 시작했다!",
"sandstormLapseMessage": "모래바람이 세차게 분다", "sandstormLapseMessage": "모래바람이 세차게 분다",
"sandstormClearMessage": "모래바람이 가라앉았다!", "sandstormClearMessage": "모래바람이 가라앉았다!",
"sandstormDamageMessage": "모래바람이\n{{pokemonPrefix}}{{pokemonName}}를(을) 덮쳤다!", "sandstormDamageMessage": "모래바람이\n{{pokemonPrefix}}{{pokemonName}}[[를]] 덮쳤다!",
"hailStartMessage": "싸라기눈이 내리기 시작했다!", "hailStartMessage": "싸라기눈이 내리기 시작했다!",
"hailLapseMessage": "싸라기눈이 계속 내리고 있다", "hailLapseMessage": "싸라기눈이 계속 내리고 있다",
"hailClearMessage": "싸라기눈이 그쳤다!", "hailClearMessage": "싸라기눈이 그쳤다!",
"hailDamageMessage": "싸라기눈이\n{{pokemonPrefix}}{{pokemonName}}를(을) 덮쳤다!", "hailDamageMessage": "싸라기눈이\n{{pokemonPrefix}}{{pokemonName}}[[를]] 덮쳤다!",
"snowStartMessage": "눈이 내리기 시작했다!", "snowStartMessage": "눈이 내리기 시작했다!",
"snowLapseMessage": "눈이 계속 내리고 있다", "snowLapseMessage": "눈이 계속 내리고 있다",

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Token de Recuperação", description: "Cura 2% dos PS máximos a cada turno" }, "ENEMY_HEAL": { name: "Token de Recuperação", description: "Cura 2% dos PS máximos a cada turno" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Token de Veneno" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "Token de Veneno" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Token de Paralisia" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Token de Paralisia" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Token de Sono" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Token de Congelamento" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Token de Queimadura" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "Token de Queimadura" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Token de Cura Total", description: "Adiciona uma chance de 10% a cada turno de curar uma condição de status" }, "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Token de Cura Total", description: "Adiciona uma chance de 2.5% a cada turno de curar uma condição de status" },
"ENEMY_ENDURE_CHANCE": { name: "Token de Persistência" }, "ENEMY_ENDURE_CHANCE": { name: "Token de Persistência" },
"ENEMY_FUSED_CHANCE": { name: "Token de Fusão", description: "Adiciona uma chance de 1% de que um Pokémon selvagem seja uma fusão" }, "ENEMY_FUSED_CHANCE": { name: "Token de Fusão", description: "Adiciona uma chance de 1% de que um Pokémon selvagem seja uma fusão" },
}, },
@ -365,7 +363,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"HARD_METEORITE": "Meteorito Duro", "HARD_METEORITE": "Meteorito Duro",
"SMOOTH_METEORITE": " Meteorito Liso", "SMOOTH_METEORITE": " Meteorito Liso",
"ADAMANT_CRYSTAL": "Cristal Adamante", "ADAMANT_CRYSTAL": "Cristal Adamante",
"LUSTROUS_ORB": "Orbe Pérola", "LUSTROUS_GLOBE": "Globo Brilhante",
"GRISEOUS_CORE": "Núcleo Platinado", "GRISEOUS_CORE": "Núcleo Platinado",
"REVEAL_GLASS": "Espelho da Verdade", "REVEAL_GLASS": "Espelho da Verdade",
"GRACIDEA": "Gracídea", "GRACIDEA": "Gracídea",

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "回复硬币", description: "每回合回复2%最大HP" }, "ENEMY_HEAL": { name: "回复硬币", description: "每回合回复2%最大HP" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "剧毒硬币" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "剧毒硬币" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "麻痹硬币" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "麻痹硬币" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "睡眠硬币" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "冰冻硬币" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "灼烧硬币" }, "ENEMY_ATTACK_BURN_CHANCE": { name: "灼烧硬币" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "万灵药硬币", description: "增加10%每回合治愈异常状态的概率" }, "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "万灵药硬币", description: "增加2.5%每回合治愈异常状态的概率" },
"ENEMY_ENDURE_CHANCE": { name: "忍受硬币" }, "ENEMY_ENDURE_CHANCE": { name: "忍受硬币" },
"ENEMY_FUSED_CHANCE": { name: "融合硬币", description: "增加1%野生融合宝可梦出现概率" }, "ENEMY_FUSED_CHANCE": { name: "融合硬币", description: "增加1%野生融合宝可梦出现概率" },
}, },
@ -365,7 +363,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"HARD_METEORITE": "坚硬陨石", "HARD_METEORITE": "坚硬陨石",
"SMOOTH_METEORITE": "光滑陨石", "SMOOTH_METEORITE": "光滑陨石",
"ADAMANT_CRYSTAL": "大金刚宝玉", "ADAMANT_CRYSTAL": "大金刚宝玉",
"LUSTROUS_ORB": "白玉宝珠", "LUSTROUS_GLOBE": "大白宝玉",
"GRISEOUS_CORE": "大白金宝玉", "GRISEOUS_CORE": "大白金宝玉",
"REVEAL_GLASS": "现形镜", "REVEAL_GLASS": "现形镜",
"GRACIDEA": "葛拉西蒂亚花", "GRACIDEA": "葛拉西蒂亚花",

View File

@ -282,12 +282,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
ENEMY_HEAL: { name: "恢復硬幣", description: "每回合恢復2%最大HP" }, ENEMY_HEAL: { name: "恢復硬幣", description: "每回合恢復2%最大HP" },
ENEMY_ATTACK_POISON_CHANCE: { name: "劇毒硬幣" }, ENEMY_ATTACK_POISON_CHANCE: { name: "劇毒硬幣" },
ENEMY_ATTACK_PARALYZE_CHANCE: { name: "麻痹硬幣" }, ENEMY_ATTACK_PARALYZE_CHANCE: { name: "麻痹硬幣" },
ENEMY_ATTACK_SLEEP_CHANCE: { name: "睡眠硬幣" },
ENEMY_ATTACK_FREEZE_CHANCE: { name: "冰凍硬幣" },
ENEMY_ATTACK_BURN_CHANCE: { name: "灼燒硬幣" }, ENEMY_ATTACK_BURN_CHANCE: { name: "灼燒硬幣" },
ENEMY_STATUS_EFFECT_HEAL_CHANCE: { ENEMY_STATUS_EFFECT_HEAL_CHANCE: {
name: "萬靈藥硬幣", name: "萬靈藥硬幣",
description: "增加10%每回合治癒異常狀態的概率", description: "增加2.5%每回合治癒異常狀態的概率",
}, },
ENEMY_ENDURE_CHANCE: { name: "忍受硬幣" }, ENEMY_ENDURE_CHANCE: { name: "忍受硬幣" },
ENEMY_FUSED_CHANCE: { ENEMY_FUSED_CHANCE: {
@ -419,7 +417,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
HARD_METEORITE: "堅硬隕石", HARD_METEORITE: "堅硬隕石",
SMOOTH_METEORITE: "光滑隕石", SMOOTH_METEORITE: "光滑隕石",
ADAMANT_CRYSTAL: "大金剛寶玉", ADAMANT_CRYSTAL: "大金剛寶玉",
LUSTROUS_ORB: "白玉寶珠", LUSTROUS_GLOBE: "大白寶玉",
GRISEOUS_CORE: "大白金寶玉", GRISEOUS_CORE: "大白金寶玉",
REVEAL_GLASS: "現形鏡", REVEAL_GLASS: "現形鏡",
GRACIDEA: "葛拉西蒂亞花", GRACIDEA: "葛拉西蒂亞花",

View File

@ -11,7 +11,8 @@ import { Type } from "../data/type";
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "../ui/party-ui-handler"; import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "../ui/party-ui-handler";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from "../data/temp-battle-stat"; import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from "../data/temp-battle-stat";
import { BerryType, getBerryEffectDescription, getBerryName } from "../data/berry"; import { getBerryEffectDescription, getBerryName } from "../data/berry";
import { BerryType } from "../data/enums/berry-type";
import { Unlockables } from "../system/unlockables"; import { Unlockables } from "../system/unlockables";
import { StatusEffect, getStatusEffectDescriptor } from "../data/status-effect"; import { StatusEffect, getStatusEffectDescriptor } from "../data/status-effect";
import { SpeciesFormKey } from "../data/pokemon-species"; import { SpeciesFormKey } from "../data/pokemon-species";
@ -977,8 +978,8 @@ export class EnemyAttackStatusEffectChanceModifierType extends ModifierType {
private chancePercent: integer; private chancePercent: integer;
private effect: StatusEffect; private effect: StatusEffect;
constructor(localeKey: string, iconImage: string, chancePercent: integer, effect: StatusEffect) { constructor(localeKey: string, iconImage: string, chancePercent: integer, effect: StatusEffect, stackCount?: integer) {
super(localeKey, iconImage, (type, args) => new Modifiers.EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent), "enemy_status_chance"); super(localeKey, iconImage, (type, args) => new Modifiers.EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent, stackCount), "enemy_status_chance");
this.chancePercent = chancePercent; this.chancePercent = chancePercent;
this.effect = effect; this.effect = effect;
@ -1215,14 +1216,12 @@ export const modifierTypes = {
ENEMY_DAMAGE_BOOSTER: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_BOOSTER", "wl_item_drop", (type, _args) => new Modifiers.EnemyDamageBoosterModifier(type, 5)), ENEMY_DAMAGE_BOOSTER: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_BOOSTER", "wl_item_drop", (type, _args) => new Modifiers.EnemyDamageBoosterModifier(type, 5)),
ENEMY_DAMAGE_REDUCTION: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_REDUCTION", "wl_guard_spec", (type, _args) => new Modifiers.EnemyDamageReducerModifier(type, 2.5)), ENEMY_DAMAGE_REDUCTION: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_REDUCTION", "wl_guard_spec", (type, _args) => new Modifiers.EnemyDamageReducerModifier(type, 2.5)),
//ENEMY_SUPER_EFFECT_BOOSTER: () => new ModifierType('Type Advantage Token', 'Increases damage of super effective attacks by 30%', (type, _args) => new Modifiers.EnemySuperEffectiveDamageBoosterModifier(type, 30), 'wl_custom_super_effective'), //ENEMY_SUPER_EFFECT_BOOSTER: () => new ModifierType('Type Advantage Token', 'Increases damage of super effective attacks by 30%', (type, _args) => new Modifiers.EnemySuperEffectiveDamageBoosterModifier(type, 30), 'wl_custom_super_effective'),
ENEMY_HEAL: () => new ModifierType("modifierType:ModifierType.ENEMY_HEAL", "wl_potion", (type, _args) => new Modifiers.EnemyTurnHealModifier(type, 2)), ENEMY_HEAL: () => new ModifierType("modifierType:ModifierType.ENEMY_HEAL", "wl_potion", (type, _args) => new Modifiers.EnemyTurnHealModifier(type, 2, 10)),
ENEMY_ATTACK_POISON_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_POISON_CHANCE", "wl_antidote", 10, StatusEffect.POISON), ENEMY_ATTACK_POISON_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_POISON_CHANCE", "wl_antidote", 5, StatusEffect.POISON, 10),
ENEMY_ATTACK_PARALYZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_PARALYZE_CHANCE", "wl_paralyze_heal", 10, StatusEffect.PARALYSIS), ENEMY_ATTACK_PARALYZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_PARALYZE_CHANCE", "wl_paralyze_heal", 2.5, StatusEffect.PARALYSIS, 10),
ENEMY_ATTACK_SLEEP_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_SLEEP_CHANCE", "wl_awakening", 10, StatusEffect.SLEEP), ENEMY_ATTACK_BURN_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_BURN_CHANCE", "wl_burn_heal", 5, StatusEffect.BURN, 10),
ENEMY_ATTACK_FREEZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_FREEZE_CHANCE", "wl_ice_heal", 10, StatusEffect.FREEZE), ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_STATUS_EFFECT_HEAL_CHANCE", "wl_full_heal", (type, _args) => new Modifiers.EnemyStatusEffectHealChanceModifier(type, 2.5, 10)),
ENEMY_ATTACK_BURN_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_BURN_CHANCE", "wl_burn_heal", 10, StatusEffect.BURN), ENEMY_ENDURE_CHANCE: () => new EnemyEndureChanceModifierType("modifierType:ModifierType.ENEMY_ENDURE_CHANCE", "wl_reset_urge", 2),
ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_STATUS_EFFECT_HEAL_CHANCE", "wl_full_heal", (type, _args) => new Modifiers.EnemyStatusEffectHealChanceModifier(type, 10)),
ENEMY_ENDURE_CHANCE: () => new EnemyEndureChanceModifierType("modifierType:ModifierType.ENEMY_ENDURE_CHANCE", "wl_reset_urge", 2.5),
ENEMY_FUSED_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_FUSED_CHANCE", "wl_custom_spliced", (type, _args) => new Modifiers.EnemyFusionChanceModifier(type, 1)), ENEMY_FUSED_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_FUSED_CHANCE", "wl_custom_spliced", (type, _args) => new Modifiers.EnemyFusionChanceModifier(type, 1)),
}; };
@ -1465,15 +1464,13 @@ const trainerModifierPool: ModifierPool = {
const enemyBuffModifierPool: ModifierPool = { const enemyBuffModifierPool: ModifierPool = {
[ModifierTier.COMMON]: [ [ModifierTier.COMMON]: [
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 10), new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 9),
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 10), new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 9),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_POISON_CHANCE, 2), new WeightedModifierType(modifierTypes.ENEMY_ATTACK_POISON_CHANCE, 3),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_PARALYZE_CHANCE, 2), new WeightedModifierType(modifierTypes.ENEMY_ATTACK_PARALYZE_CHANCE, 3),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_SLEEP_CHANCE, 2), new WeightedModifierType(modifierTypes.ENEMY_ATTACK_BURN_CHANCE, 3),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_FREEZE_CHANCE, 2), new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 9),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_BURN_CHANCE, 2), new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 4),
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 10),
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 5),
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 1) new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 1)
].map(m => { ].map(m => {
m.setTier(ModifierTier.COMMON); return m; m.setTier(ModifierTier.COMMON); return m;

View File

@ -12,7 +12,8 @@ import { FusionSpeciesFormEvolution, pokemonEvolutions, pokemonPrevolutions } fr
import { getPokemonMessage } from "../messages"; import { getPokemonMessage } from "../messages";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { TempBattleStat } from "../data/temp-battle-stat"; import { TempBattleStat } from "../data/temp-battle-stat";
import { BerryType, getBerryEffectFunc, getBerryPredicate } from "../data/berry"; import { getBerryEffectFunc, getBerryPredicate } from "../data/berry";
import { BerryType } from "../data/enums/berry-type";
import { StatusEffect, getStatusEffectHealText } from "../data/status-effect"; import { StatusEffect, getStatusEffectHealText } from "../data/status-effect";
import { achvs } from "../system/achv"; import { achvs } from "../system/achv";
import { VoucherType } from "../system/voucher"; import { VoucherType } from "../system/voucher";
@ -775,6 +776,9 @@ export class BypassSpeedChanceModifier extends PokemonHeldItemModifier {
if (!bypassSpeed.value && pokemon.randSeedInt(10) < this.getStackCount()) { if (!bypassSpeed.value && pokemon.randSeedInt(10) < this.getStackCount()) {
bypassSpeed.value = true; bypassSpeed.value = true;
if (this.type instanceof ModifierTypes.PokemonHeldItemModifierType && this.type.id === "QUICK_CLAW") {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, " used its quick claw to move faster!"));
}
return true; return true;
} }
@ -2140,7 +2144,7 @@ export class EnemyDamageReducerModifier extends EnemyDamageMultiplierModifier {
} }
export class EnemyTurnHealModifier extends EnemyPersistentModifier { export class EnemyTurnHealModifier extends EnemyPersistentModifier {
private healPercent: number; public healPercent: number;
constructor(type: ModifierType, healPercent: number, stackCount?: integer) { constructor(type: ModifierType, healPercent: number, stackCount?: integer) {
super(type, stackCount); super(type, stackCount);
@ -2175,23 +2179,23 @@ export class EnemyTurnHealModifier extends EnemyPersistentModifier {
} }
getMaxStackCount(scene: BattleScene): integer { getMaxStackCount(scene: BattleScene): integer {
return 15; return 10;
} }
} }
export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifier { export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifier {
public effect: StatusEffect; public effect: StatusEffect;
private chance: number; public chance: number;
constructor(type: ModifierType, effect: StatusEffect, chancePercent: number, stackCount?: integer) { constructor(type: ModifierType, effect: StatusEffect, chancePercent: number, stackCount?: integer) {
super(type, stackCount); super(type, stackCount);
this.effect = effect; this.effect = effect;
this.chance = (chancePercent || 10) / 100; this.chance = (chancePercent || 5) / 100;
} }
match(modifier: Modifier): boolean { match(modifier: Modifier): boolean {
return modifier instanceof EnemyAttackStatusEffectChanceModifier && modifier.effect === this.effect && modifier.chance === this.chance; return modifier instanceof EnemyAttackStatusEffectChanceModifier && modifier.effect === this.effect;
} }
clone(): EnemyAttackStatusEffectChanceModifier { clone(): EnemyAttackStatusEffectChanceModifier {
@ -2210,19 +2214,23 @@ export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifi
return false; return false;
} }
getMaxStackCount(scene: BattleScene): integer {
return 10;
}
} }
export class EnemyStatusEffectHealChanceModifier extends EnemyPersistentModifier { export class EnemyStatusEffectHealChanceModifier extends EnemyPersistentModifier {
private chance: number; public chance: number;
constructor(type: ModifierType, chancePercent: number, stackCount?: integer) { constructor(type: ModifierType, chancePercent: number, stackCount?: integer) {
super(type, stackCount); super(type, stackCount);
this.chance = (chancePercent || 10) / 100; this.chance = (chancePercent || 2.5) / 100;
} }
match(modifier: Modifier): boolean { match(modifier: Modifier): boolean {
return modifier instanceof EnemyStatusEffectHealChanceModifier && modifier.chance === this.chance; return modifier instanceof EnemyStatusEffectHealChanceModifier;
} }
clone(): EnemyStatusEffectHealChanceModifier { clone(): EnemyStatusEffectHealChanceModifier {
@ -2244,19 +2252,23 @@ export class EnemyStatusEffectHealChanceModifier extends EnemyPersistentModifier
return false; return false;
} }
getMaxStackCount(scene: BattleScene): integer {
return 10;
}
} }
export class EnemyEndureChanceModifier extends EnemyPersistentModifier { export class EnemyEndureChanceModifier extends EnemyPersistentModifier {
private chance: number; public chance: number;
constructor(type: ModifierType, chancePercent: number, stackCount?: integer) { constructor(type: ModifierType, chancePercent?: number, stackCount?: integer) {
super(type, stackCount); super(type, stackCount || 10);
this.chance = (chancePercent || 2.5) / 100; this.chance = (chancePercent || 2) / 100;
} }
match(modifier: Modifier) { match(modifier: Modifier) {
return modifier instanceof EnemyEndureChanceModifier && modifier.chance === this.chance; return modifier instanceof EnemyEndureChanceModifier;
} }
clone() { clone() {

View File

@ -4,7 +4,7 @@ import { Biome } from "./data/enums/biome";
import { Moves } from "./data/enums/moves"; import { Moves } from "./data/enums/moves";
import { WeatherType } from "./data/weather"; import { WeatherType } from "./data/weather";
import { Variant } from "./data/variant"; import { Variant } from "./data/variant";
import { BerryType } from "./data/berry"; import { BerryType } from "./data/enums/berry-type";
import { TempBattleStat } from "./data/temp-battle-stat"; import { TempBattleStat } from "./data/temp-battle-stat";
import { Nature } from "./data/nature"; import { Nature } from "./data/nature";
import { Type } from "./data/type"; import { Type } from "./data/type";

View File

@ -61,7 +61,7 @@ import { Abilities } from "./data/enums/abilities";
import * as Overrides from "./overrides"; import * as Overrides from "./overrides";
import { TextStyle, addTextObject } from "./ui/text"; import { TextStyle, addTextObject } from "./ui/text";
import { Type } from "./data/type"; import { Type } from "./data/type";
import { MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events"; import { BerryUsedEvent, MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events";
export class LoginPhase extends Phase { export class LoginPhase extends Phase {
@ -2244,6 +2244,7 @@ export class BerryPhase extends FieldPhase {
berryModifier.consumed = false; berryModifier.consumed = false;
} }
} }
this.scene.eventTarget.dispatchEvent(new BerryUsedEvent(berryModifier)); // Announce a berry was used
} }
this.scene.updateModifiers(pokemon.isPlayer()); this.scene.updateModifiers(pokemon.isPlayer());

View File

@ -1,5 +1,6 @@
import i18next from "i18next"; import i18next from "i18next";
import LanguageDetector from "i18next-browser-languagedetector"; import LanguageDetector from "i18next-browser-languagedetector";
import processor, { KoreanPostpositionProcessor } from "i18next-korean-postposition-processor";
import { deConfig } from "#app/locales/de/config.js"; import { deConfig } from "#app/locales/de/config.js";
import { enConfig } from "#app/locales/en/config.js"; import { enConfig } from "#app/locales/en/config.js";
@ -148,7 +149,7 @@ export function initI18n(): void {
* A: In src/system/settings.ts, add a new case to the Setting.Language switch statement. * A: In src/system/settings.ts, add a new case to the Setting.Language switch statement.
*/ */
i18next.use(LanguageDetector).init({ i18next.use(LanguageDetector).use(processor).use(new KoreanPostpositionProcessor()).init({
lng: lang, lng: lang,
nonExplicitSupportedLngs: true, nonExplicitSupportedLngs: true,
fallbackLng: "en", fallbackLng: "en",
@ -186,6 +187,7 @@ export function initI18n(): void {
...koConfig ...koConfig
}, },
}, },
postProcess: ["korean-postposition"],
}); });
} }

View File

@ -34,6 +34,8 @@ import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./setti
import {setSettingKeyboard, SettingKeyboard} from "#app/system/settings/settings-keyboard"; import {setSettingKeyboard, SettingKeyboard} from "#app/system/settings/settings-keyboard";
import { TerrainChangedEvent, WeatherChangedEvent } from "#app/field/arena-events.js"; import { TerrainChangedEvent, WeatherChangedEvent } from "#app/field/arena-events.js";
import { Device } from "#app/enums/devices.js"; import { Device } from "#app/enums/devices.js";
import { EnemyAttackStatusEffectChanceModifier } from "../modifier/modifier";
import { StatusEffect } from "#app/data/status-effect.js";
const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary
@ -1078,6 +1080,9 @@ export class GameData {
if (md?.className === "ExpBalanceModifier") { // Temporarily limit EXP Balance until it gets reworked if (md?.className === "ExpBalanceModifier") { // Temporarily limit EXP Balance until it gets reworked
md.stackCount = Math.min(md.stackCount, 4); md.stackCount = Math.min(md.stackCount, 4);
} }
if (md instanceof EnemyAttackStatusEffectChanceModifier && md.effect === StatusEffect.FREEZE || md.effect === StatusEffect.SLEEP) {
continue;
}
ret.push(new PersistentModifierData(md, player)); ret.push(new PersistentModifierData(md, player));
} }
return ret; return ret;

View File

@ -53,6 +53,7 @@ export const SettingKeys = {
Music_Preference: "MUSIC_PREFERENCE", Music_Preference: "MUSIC_PREFERENCE",
Move_Animations: "MOVE_ANIMATIONS", Move_Animations: "MOVE_ANIMATIONS",
Show_Moveset_Flyout: "SHOW_MOVESET_FLYOUT", Show_Moveset_Flyout: "SHOW_MOVESET_FLYOUT",
Show_Arena_Flyout: "SHOW_ARENA_FLYOUT",
Show_Stats_on_Level_Up: "SHOW_LEVEL_UP_STATS", Show_Stats_on_Level_Up: "SHOW_LEVEL_UP_STATS",
EXP_Gains_Speed: "EXP_GAINS_SPEED", EXP_Gains_Speed: "EXP_GAINS_SPEED",
EXP_Party_Display: "EXP_PARTY_DISPLAY", EXP_Party_Display: "EXP_PARTY_DISPLAY",
@ -198,6 +199,13 @@ export const Setting: Array<Setting> = [
default: 1, default: 1,
type: SettingType.ACCESSIBILITY type: SettingType.ACCESSIBILITY
}, },
{
key: SettingKeys.Show_Arena_Flyout,
label: "Show Battle Effects Flyout",
options: OFF_ON,
default: 1,
type: SettingType.ACCESSIBILITY
},
{ {
key: SettingKeys.Show_Stats_on_Level_Up, key: SettingKeys.Show_Stats_on_Level_Up,
label: "Show Stats on Level Up", label: "Show Stats on Level Up",
@ -355,6 +363,9 @@ export function setSetting(scene: BattleScene, setting: string, value: integer):
case SettingKeys.Show_Moveset_Flyout: case SettingKeys.Show_Moveset_Flyout:
scene.showMovesetFlyout = Setting[index].options[value] === "On"; scene.showMovesetFlyout = Setting[index].options[value] === "On";
break; break;
case SettingKeys.Show_Arena_Flyout:
scene.showArenaFlyout = Setting[index].options[value] === "On";
break;
case SettingKeys.Show_Stats_on_Level_Up: case SettingKeys.Show_Stats_on_Level_Up:
scene.showLevelUpStats = Setting[index].options[value] === "On"; scene.showLevelUpStats = Setting[index].options[value] === "On";
break; break;

View File

@ -119,15 +119,17 @@ export class UiInputs {
} }
} }
buttonInfo(pressed: boolean = true): void { buttonInfo(pressed: boolean = true): void {
if (!this.scene.showMovesetFlyout) { if (this.scene.showMovesetFlyout ) {
return;
}
for (const p of this.scene.getField().filter(p => p?.isActive(true))) { for (const p of this.scene.getField().filter(p => p?.isActive(true))) {
p.toggleFlyout(pressed); p.toggleFlyout(pressed);
} }
} }
if (this.scene.showArenaFlyout) {
this.scene.ui.processInfoButton(pressed);
}
}
buttonMenu(): void { buttonMenu(): void {
if (this.scene.disableMenu) { if (this.scene.disableMenu) {
return; return;

384
src/ui/arena-flyout.ts Normal file
View File

@ -0,0 +1,384 @@
import * as Utils from "../utils";
import { addTextObject, TextStyle } from "./text";
import BattleScene from "#app/battle-scene.js";
import { ArenaTagSide } from "#app/data/arena-tag.js";
import { WeatherType } from "#app/data/weather.js";
import { TerrainType } from "#app/data/terrain.js";
import { addWindow, WindowVariant } from "./ui-theme";
import { ArenaEvent, ArenaEventType, TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/field/arena-events.js";
import { BattleSceneEventType, TurnEndEvent } from "#app/battle-scene-events.js";
import { ArenaTagType } from "#app/data/enums/arena-tag-type.js";
import { TimeOfDay } from "#app/data/enums/time-of-day.js";
/** Enum used to differentiate {@linkcode Arena} effects */
enum ArenaEffectType {
PLAYER,
WEATHER,
TERRAIN,
FIELD,
ENEMY,
}
/** Container for info about an {@linkcode Arena}'s effects */
interface ArenaEffectInfo {
/** The enum string representation of the effect */
name: string;
/** {@linkcode ArenaEffectType} type of effect */
type: ArenaEffectType,
/** The maximum duration set by the effect */
maxDuration: number;
/** The current duration left on the effect */
duration: number;
}
export default class ArenaFlyout extends Phaser.GameObjects.Container {
/** An alias for the scene typecast to a {@linkcode BattleScene} */
private battleScene: BattleScene;
/** The restricted width of the flyout which should be drawn to */
private flyoutWidth = 170;
/** The restricted height of the flyout which should be drawn to */
private flyoutHeight = 51;
/** The amount of translation animation on the x-axis */
private translationX: number;
/** The x-axis point where the flyout should sit when activated */
private anchorX: number;
/** The y-axis point where the flyout should sit when activated */
private anchorY: number;
/** The initial container which defines where the flyout should be attached */
private flyoutParent: Phaser.GameObjects.Container;
/** The container which defines the drawable dimensions of the flyout */
private flyoutContainer: Phaser.GameObjects.Container;
/** The background {@linkcode Phaser.GameObjects.NineSlice} window for the flyout */
private flyoutWindow: Phaser.GameObjects.NineSlice;
/** The header {@linkcode Phaser.GameObjects.NineSlice} window for the flyout */
private flyoutWindowHeader: Phaser.GameObjects.NineSlice;
/** The {@linkcode Phaser.GameObjects.Text} that goes inside of the header */
private flyoutTextHeader: Phaser.GameObjects.Text;
/** The {@linkcode Phaser.GameObjects.Sprite} that represents the current time of day */
private timeOfDayIcon: Phaser.GameObjects.Sprite;
/** The {@linkcode Phaser.GameObjects.Text} header used to indicate the player's effects */
private flyoutTextHeaderPlayer: Phaser.GameObjects.Text;
/** The {@linkcode Phaser.GameObjects.Text} header used to indicate the enemy's effects */
private flyoutTextHeaderEnemy: Phaser.GameObjects.Text;
/** The {@linkcode Phaser.GameObjects.Text} header used to indicate neutral effects */
private flyoutTextHeaderField: Phaser.GameObjects.Text;
/** The {@linkcode Phaser.GameObjects.Text} used to indicate the player's effects */
private flyoutTextPlayer: Phaser.GameObjects.Text;
/** The {@linkcode Phaser.GameObjects.Text} used to indicate the enemy's effects */
private flyoutTextEnemy: Phaser.GameObjects.Text;
/** The {@linkcode Phaser.GameObjects.Text} used to indicate neutral effects */
private flyoutTextField: Phaser.GameObjects.Text;
/** Container for all field effects observed by this object */
private readonly fieldEffectInfo: ArenaEffectInfo[] = [];
// Stores callbacks in a variable so they can be unsubscribed from when destroyed
private readonly onNewArenaEvent = (event: Event) => this.onNewArena(event);
private readonly onTurnInitEvent = (event: Event) => this.onTurnInit(event);
private readonly onTurnEndEvent = (event: Event) => this.onTurnEnd(event);
private readonly onFieldEffectChangedEvent = (event: Event) => this.onFieldEffectChanged(event);
constructor(scene: Phaser.Scene) {
super(scene, 0, 0);
this.battleScene = this.scene as BattleScene;
this.translationX = this.flyoutWidth;
this.anchorX = 0;
this.anchorY = -98;
this.flyoutParent = this.scene.add.container(this.anchorX - this.translationX, this.anchorY);
this.flyoutParent.setAlpha(0);
this.add(this.flyoutParent);
this.flyoutContainer = this.scene.add.container(0, 0);
this.flyoutParent.add(this.flyoutContainer);
this.flyoutWindow = addWindow(this.scene as BattleScene, 0, 0, this.flyoutWidth, this.flyoutHeight, false, false, 0, 0, WindowVariant.THIN);
this.flyoutContainer.add(this.flyoutWindow);
this.flyoutWindowHeader = addWindow(this.scene as BattleScene, this.flyoutWidth / 2, 0, this.flyoutWidth / 2, 14, false, false, 0, 0, WindowVariant.XTHIN);
this.flyoutWindowHeader.setOrigin();
this.flyoutContainer.add(this.flyoutWindowHeader);
this.flyoutTextHeader = addTextObject(this.scene, this.flyoutWidth / 2, 0, "Active Battle Effects", TextStyle.BATTLE_INFO);
this.flyoutTextHeader.setFontSize(54);
this.flyoutTextHeader.setAlign("center");
this.flyoutTextHeader.setOrigin();
this.flyoutContainer.add(this.flyoutTextHeader);
this.timeOfDayIcon = this.scene.add.sprite((this.flyoutWidth / 2) + (this.flyoutWindowHeader.displayWidth / 2), 0, "dawn_icon").setOrigin();
this.timeOfDayIcon.setVisible(false);
this.flyoutContainer.add(this.timeOfDayIcon);
this.flyoutTextHeaderPlayer = addTextObject(this.scene, 6, 5, "Player", TextStyle.SUMMARY_BLUE);
this.flyoutTextHeaderPlayer.setFontSize(54);
this.flyoutTextHeaderPlayer.setAlign("left");
this.flyoutTextHeaderPlayer.setOrigin(0, 0);
this.flyoutContainer.add(this.flyoutTextHeaderPlayer);
this.flyoutTextHeaderField = addTextObject(this.scene, this.flyoutWidth / 2, 5, "Neutral", TextStyle.SUMMARY_GREEN);
this.flyoutTextHeaderField.setFontSize(54);
this.flyoutTextHeaderField.setAlign("center");
this.flyoutTextHeaderField.setOrigin(0.5, 0);
this.flyoutContainer.add(this.flyoutTextHeaderField);
this.flyoutTextHeaderEnemy = addTextObject(this.scene, this.flyoutWidth - 6, 5, "Enemy", TextStyle.SUMMARY_RED);
this.flyoutTextHeaderEnemy.setFontSize(54);
this.flyoutTextHeaderEnemy.setAlign("right");
this.flyoutTextHeaderEnemy.setOrigin(1, 0);
this.flyoutContainer.add(this.flyoutTextHeaderEnemy);
this.flyoutTextPlayer = addTextObject(this.scene, 6, 13, "", TextStyle.BATTLE_INFO);
this.flyoutTextPlayer.setLineSpacing(-1);
this.flyoutTextPlayer.setFontSize(48);
this.flyoutTextPlayer.setAlign("left");
this.flyoutTextPlayer.setOrigin(0, 0);
this.flyoutContainer.add(this.flyoutTextPlayer);
this.flyoutTextField = addTextObject(this.scene, this.flyoutWidth / 2, 13, "", TextStyle.BATTLE_INFO);
this.flyoutTextField.setLineSpacing(-1);
this.flyoutTextField.setFontSize(48);
this.flyoutTextField.setAlign("center");
this.flyoutTextField.setOrigin(0.5, 0);
this.flyoutContainer.add(this.flyoutTextField);
this.flyoutTextEnemy = addTextObject(this.scene, this.flyoutWidth - 6, 13, "", TextStyle.BATTLE_INFO);
this.flyoutTextEnemy.setLineSpacing(-1);
this.flyoutTextEnemy.setFontSize(48);
this.flyoutTextEnemy.setAlign("right");
this.flyoutTextEnemy.setOrigin(1, 0);
this.flyoutContainer.add(this.flyoutTextEnemy);
this.name = "Fight Flyout";
this.flyoutParent.name = "Fight Flyout Parent";
// Subscribes to required events available on game start
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.NEW_ARENA, this.onNewArenaEvent);
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.TURN_INIT, this.onTurnInitEvent);
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.TURN_END, this.onTurnEndEvent);
}
private setTimeOfDayIcon() {
this.timeOfDayIcon.setTexture(TimeOfDay[this.battleScene.arena.getTimeOfDay()].toLowerCase() + "_icon");
}
private onTurnInit(event: Event) {
this.setTimeOfDayIcon();
}
private onNewArena(event: Event) {
this.fieldEffectInfo.length = 0;
// Subscribes to required events available on battle start
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.WEATHER_CHANGED, this.onFieldEffectChangedEvent);
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TERRAIN_CHANGED, this.onFieldEffectChangedEvent);
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TAG_ADDED, this.onFieldEffectChangedEvent);
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TAG_REMOVED, this.onFieldEffectChangedEvent);
this.setTimeOfDayIcon();
}
/**
* Formats a string to title case
* @param unformattedText Text to be formatted
* @returns the formatted string
*/
private formatText(unformattedText: string): string {
const text = unformattedText.split("_");
for (let i = 0; i < text.length; i++) {
text[i] = text[i].charAt(0).toUpperCase() + text[i].substring(1).toLowerCase();
}
return text.join(" ");
}
/** Clears out the current string stored in all arena effect texts */
private clearText() {
this.flyoutTextPlayer.text = "";
this.flyoutTextField.text = "";
this.flyoutTextEnemy.text = "";
}
/** Parses through all set Arena Effects and puts them into the proper {@linkcode Phaser.GameObjects.Text} object */
private updateFieldText() {
this.clearText();
this.fieldEffectInfo.sort((infoA, infoB) => infoA.duration - infoB.duration);
for (let i = 0; i < this.fieldEffectInfo.length; i++) {
const fieldEffectInfo = this.fieldEffectInfo[i];
// Creates a proxy object to decide which text object needs to be updated
let textObject: Phaser.GameObjects.Text;
switch (fieldEffectInfo.type) {
case ArenaEffectType.PLAYER:
textObject = this.flyoutTextPlayer;
break;
case ArenaEffectType.WEATHER:
case ArenaEffectType.TERRAIN:
case ArenaEffectType.FIELD:
textObject = this.flyoutTextField;
break;
case ArenaEffectType.ENEMY:
textObject = this.flyoutTextEnemy;
break;
}
textObject.text += this.formatText(fieldEffectInfo.name);
if (fieldEffectInfo.type === ArenaEffectType.TERRAIN) {
textObject.text += " Terrain"; // Adds 'Terrain' since the enum does not contain it
}
if (fieldEffectInfo.maxDuration !== 0) {
textObject.text += " " + fieldEffectInfo.duration + "/" + fieldEffectInfo.maxDuration;
}
textObject.text += "\n";
}
}
/**
* Parses the {@linkcode Event} being passed and updates the state of the fieldEffectInfo array
* @param event {@linkcode Event} being sent
*/
private onFieldEffectChanged(event: Event) {
const arenaEffectChangedEvent = event as ArenaEvent;
if (!arenaEffectChangedEvent) {
return;
}
let foundIndex: number;
switch (arenaEffectChangedEvent.constructor) {
case TagAddedEvent:
const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent;
this.fieldEffectInfo.push({
name: ArenaTagType[tagAddedEvent.arenaTagType],
type: tagAddedEvent.arenaTagSide === ArenaTagSide.BOTH
? ArenaEffectType.FIELD
: tagAddedEvent.arenaTagSide === ArenaTagSide.PLAYER
? ArenaEffectType.PLAYER
: ArenaEffectType.ENEMY,
maxDuration: tagAddedEvent.duration,
duration: tagAddedEvent.duration});
break;
case TagRemovedEvent:
const tagRemovedEvent = arenaEffectChangedEvent as TagRemovedEvent;
foundIndex = this.fieldEffectInfo.findIndex(info => info.name === ArenaTagType[tagRemovedEvent.arenaTagType]);
if (foundIndex !== -1) { // If the tag was being tracked, remove it
this.fieldEffectInfo.splice(foundIndex, 1);
}
break;
case WeatherChangedEvent:
case TerrainChangedEvent:
const fieldEffectChangedEvent = arenaEffectChangedEvent as WeatherChangedEvent | TerrainChangedEvent;
// Stores the old Weather/Terrain name in case it's in the array already
const oldName =
fieldEffectChangedEvent instanceof WeatherChangedEvent
? WeatherType[fieldEffectChangedEvent.oldWeatherType]
: TerrainType[fieldEffectChangedEvent.oldTerrainType];
// Stores the new Weather/Terrain info
const newInfo = {
name:
fieldEffectChangedEvent instanceof WeatherChangedEvent
? WeatherType[fieldEffectChangedEvent.newWeatherType]
: TerrainType[fieldEffectChangedEvent.newTerrainType],
type: fieldEffectChangedEvent instanceof WeatherChangedEvent
? ArenaEffectType.WEATHER
: ArenaEffectType.TERRAIN,
maxDuration: fieldEffectChangedEvent.duration,
duration: fieldEffectChangedEvent.duration};
foundIndex = this.fieldEffectInfo.findIndex(info => [newInfo.name, oldName].includes(info.name));
if (foundIndex === -1) {
if (newInfo.name !== undefined) {
this.fieldEffectInfo.push(newInfo); // Adds the info to the array if it doesn't already exist and is defined
}
} else if (!newInfo.name) {
this.fieldEffectInfo.splice(foundIndex, 1); // Removes the old info if the new one is undefined
} else {
this.fieldEffectInfo[foundIndex] = newInfo; // Otherwise, replace the old info
}
break;
}
this.updateFieldText();
}
/**
* Iterates through the fieldEffectInfo array and decrements the duration of each item
* @param event {@linkcode Event} being sent
*/
private onTurnEnd(event: Event) {
const turnEndEvent = event as TurnEndEvent;
if (!turnEndEvent) {
return;
}
const fieldEffectInfo: ArenaEffectInfo[] = [];
this.fieldEffectInfo.forEach(i => fieldEffectInfo.push(i));
for (let i = 0; i < fieldEffectInfo.length; i++) {
const info = fieldEffectInfo[i];
if (info.maxDuration === 0) {
continue;
}
--info.duration;
if (info.duration <= 0) { // Removes the item if the duration has expired
this.fieldEffectInfo.splice(this.fieldEffectInfo.indexOf(info), 1);
}
}
this.updateFieldText();
}
/**
* Animates the flyout to either show or hide it by applying a fade and translation
* @param visible Should the flyout be shown?
*/
toggleFlyout(visible: boolean): void {
this.scene.tweens.add({
targets: this.flyoutParent,
x: visible ? this.anchorX : this.anchorX - this.translationX,
duration: Utils.fixedInt(125),
ease: "Sine.easeInOut",
alpha: visible ? 1 : 0,
});
}
destroy(fromScene?: boolean): void {
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.NEW_ARENA, this.onNewArenaEvent);
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.TURN_END, this.onTurnEndEvent);
this.battleScene.arena.eventTarget.removeEventListener(ArenaEventType.WEATHER_CHANGED, this.onFieldEffectChangedEvent);
this.battleScene.arena.eventTarget.removeEventListener(ArenaEventType.TERRAIN_CHANGED, this.onFieldEffectChangedEvent);
this.battleScene.arena.eventTarget.removeEventListener(ArenaEventType.TAG_ADDED, this.onFieldEffectChangedEvent);
this.battleScene.arena.eventTarget.removeEventListener(ArenaEventType.TAG_REMOVED, this.onFieldEffectChangedEvent);
super.destroy(fromScene);
}
}

View File

@ -4,7 +4,9 @@ import * as Utils from "../utils";
import BattleScene from "#app/battle-scene.js"; import BattleScene from "#app/battle-scene.js";
import { UiTheme } from "#app/enums/ui-theme.js"; import { UiTheme } from "#app/enums/ui-theme.js";
import Move from "#app/data/move.js"; import Move from "#app/data/move.js";
import { BattleSceneEventType, MoveUsedEvent } from "#app/battle-scene-events.js"; import { BattleSceneEventType, BerryUsedEvent, MoveUsedEvent } from "#app/battle-scene-events.js";
import { BerryType } from "#app/data/enums/berry-type.js";
import { Moves } from "#app/data/enums/moves.js";
/** Container for info about a {@linkcode Move} */ /** Container for info about a {@linkcode Move} */
interface MoveInfo { interface MoveInfo {
@ -53,7 +55,9 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
/** The array of {@linkcode MoveInfo} used to track moves for the {@linkcode Pokemon} linked to the flyout */ /** The array of {@linkcode MoveInfo} used to track moves for the {@linkcode Pokemon} linked to the flyout */
private moveInfo: MoveInfo[] = new Array(); private moveInfo: MoveInfo[] = new Array();
private readonly onMoveUsed = (event) => this.updateInfo(event); // Stores callbacks in a variable so they can be unsubscribed from when destroyed
private readonly onMoveUsedEvent = (event: Event) => this.onMoveUsed(event);
private readonly onBerryUsedEvent = (event: Event) => this.onBerryUsed(event);
constructor(scene: Phaser.Scene, player: boolean) { constructor(scene: Phaser.Scene, player: boolean) {
super(scene, 0, 0); super(scene, 0, 0);
@ -109,11 +113,12 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
this.name = `Flyout ${this.pokemon.name}`; this.name = `Flyout ${this.pokemon.name}`;
this.flyoutParent.name = `Flyout Parent ${this.pokemon.name}`; this.flyoutParent.name = `Flyout Parent ${this.pokemon.name}`;
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsed); this.battleScene.eventTarget.addEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsedEvent);
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.BERRY_USED, this.onBerryUsedEvent);
} }
/** Sets and formats the text property for all {@linkcode Phaser.GameObjects.Text} in the flyoutText array */ /** Sets and formats the text property for all {@linkcode Phaser.GameObjects.Text} in the flyoutText array */
setText() { private setText() {
for (let i = 0; i < this.flyoutText.length; i++) { for (let i = 0; i < this.flyoutText.length; i++) {
const flyoutText = this.flyoutText[i]; const flyoutText = this.flyoutText[i];
const moveInfo = this.moveInfo[i]; const moveInfo = this.moveInfo[i];
@ -122,21 +127,23 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
continue; continue;
} }
const currentPp = Math.max(moveInfo.maxPp - moveInfo.ppUsed, 0); const currentPp = moveInfo.maxPp - moveInfo.ppUsed;
flyoutText.text = `${moveInfo.move.name} ${currentPp}/${moveInfo.maxPp}`; flyoutText.text = `${moveInfo.move.name} ${currentPp}/${moveInfo.maxPp}`;
} }
} }
/** Updates all of the {@linkcode MoveInfo} objects in the moveInfo array */ /** Updates all of the {@linkcode MoveInfo} objects in the moveInfo array */
updateInfo(event: Event) { private onMoveUsed(event: Event) {
const moveUsedEvent = event as MoveUsedEvent; const moveUsedEvent = event as MoveUsedEvent;
if (!moveUsedEvent || moveUsedEvent.userId !== this.pokemon?.id) { if (!moveUsedEvent
|| moveUsedEvent.pokemonId !== this.pokemon?.id
|| moveUsedEvent.move.id === Moves.STRUGGLE) { // Ignore Struggle
return; return;
} }
const foundInfo = this.moveInfo.find(x => x?.move.id === moveUsedEvent.move.id); const foundInfo = this.moveInfo.find(x => x?.move.id === moveUsedEvent.move.id);
if (foundInfo) { if (foundInfo) {
foundInfo.ppUsed += moveUsedEvent.ppUsed; foundInfo.ppUsed = Math.min(foundInfo.ppUsed + moveUsedEvent.ppUsed, foundInfo.maxPp);
} else { } else {
this.moveInfo.push({move: moveUsedEvent.move, maxPp: moveUsedEvent.move.pp, ppUsed: moveUsedEvent.ppUsed}); this.moveInfo.push({move: moveUsedEvent.move, maxPp: moveUsedEvent.move.pp, ppUsed: moveUsedEvent.ppUsed});
} }
@ -144,6 +151,23 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
this.setText(); this.setText();
} }
private onBerryUsed(event: Event) {
const berryUsedEvent = event as BerryUsedEvent;
if (!berryUsedEvent
|| berryUsedEvent.berryModifier.pokemonId !== this.pokemon?.id
|| berryUsedEvent.berryModifier.berryType !== BerryType.LEPPA) { // We only care about Leppa berries
return;
}
const foundInfo = this.moveInfo.find(info => info.ppUsed === info.maxPp);
if (!foundInfo) { // This will only happen on a de-sync of PP tracking
return;
}
foundInfo.ppUsed = Math.max(foundInfo.ppUsed - 10, 0);
this.setText();
}
/** Animates the flyout to either show or hide it by applying a fade and translation */ /** Animates the flyout to either show or hide it by applying a fade and translation */
toggleFlyout(visible: boolean): void { toggleFlyout(visible: boolean): void {
this.scene.tweens.add({ this.scene.tweens.add({
@ -156,8 +180,9 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
} }
destroy(fromScene?: boolean): void { destroy(fromScene?: boolean): void {
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsed); this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsedEvent);
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.BERRY_USED, this.onBerryUsedEvent);
super.destroy(); super.destroy(fromScene);
} }
} }

View File

@ -35,7 +35,7 @@ export default class FightUiHandler extends UiHandler {
this.movesContainer = this.scene.add.container(18, -38.7); this.movesContainer = this.scene.add.container(18, -38.7);
ui.add(this.movesContainer); ui.add(this.movesContainer);
this.typeIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 57, -36,`types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}` , "unknown"); this.typeIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 57, -36,`types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}` , "unknown");
this.typeIcon.setVisible(false); this.typeIcon.setVisible(false);
ui.add(this.typeIcon); ui.add(this.typeIcon);
@ -168,7 +168,7 @@ export default class FightUiHandler extends UiHandler {
if (hasMove) { if (hasMove) {
const pokemonMove = moveset[cursor]; const pokemonMove = moveset[cursor];
this.typeIcon.setTexture(`types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[pokemonMove.getMove().type].toLowerCase()).setScale(0.8); this.typeIcon.setTexture(`types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[pokemonMove.getMove().type].toLowerCase()).setScale(0.8);
this.moveCategoryIcon.setTexture("categories", MoveCategory[pokemonMove.getMove().category].toLowerCase()).setScale(1.0); this.moveCategoryIcon.setTexture("categories", MoveCategory[pokemonMove.getMove().category].toLowerCase()).setScale(1.0);
const power = pokemonMove.getMove().power; const power = pokemonMove.getMove().power;

View File

@ -73,7 +73,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
} }
setup(): void { setup(): void {
const currentLanguage = i18next.language; const currentLanguage = i18next.resolvedLanguage;
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)); const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang));
const textSettings = languageSettings[langSettingKey]; const textSettings = languageSettings[langSettingKey];
const infoBg = addWindow(this.scene, 0, 0, this.infoWindowWidth, 132); const infoBg = addWindow(this.scene, 0, 0, this.infoWindowWidth, 132);

View File

@ -251,7 +251,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
setup() { setup() {
const ui = this.getUi(); const ui = this.getUi();
const currentLanguage = i18next.language; const currentLanguage = i18next.resolvedLanguage;
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)); const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang));
const textSettings = languageSettings[langSettingKey]; const textSettings = languageSettings[langSettingKey];
@ -518,11 +518,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonSprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true }); this.pokemonSprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true });
this.starterSelectContainer.add(this.pokemonSprite); this.starterSelectContainer.add(this.pokemonSprite);
this.type1Icon = this.scene.add.sprite(8, 98, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`); this.type1Icon.setScale(0.5); this.type1Icon = this.scene.add.sprite(8, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`); this.type1Icon.setScale(0.5);
this.type1Icon.setOrigin(0, 0); this.type1Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type1Icon); this.starterSelectContainer.add(this.type1Icon);
this.type2Icon = this.scene.add.sprite(26, 98, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`); this.type2Icon.setScale(0.5); this.type2Icon = this.scene.add.sprite(26, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`); this.type2Icon.setScale(0.5);
this.type2Icon.setOrigin(0, 0); this.type2Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type2Icon); this.starterSelectContainer.add(this.type2Icon);

View File

@ -695,7 +695,7 @@ export default class SummaryUiHandler extends UiHandler {
const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => { const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => {
const xCoord = 39 + 34 * index; const xCoord = 39 + 34 * index;
const typeIcon = !tera const typeIcon = !tera
? this.scene.add.sprite(xCoord, 42, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[type].toLowerCase()) : this.scene.add.sprite(xCoord, 42, "type_tera"); ? this.scene.add.sprite(xCoord, 42, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[type].toLowerCase()) : this.scene.add.sprite(xCoord, 42, "type_tera");
if (tera) { if (tera) {
typeIcon.setScale(0.5); typeIcon.setScale(0.5);
const typeRgb = getTypeRgb(type); const typeRgb = getTypeRgb(type);
@ -897,7 +897,7 @@ export default class SummaryUiHandler extends UiHandler {
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
this.extraMoveRowContainer.setVisible(true); this.extraMoveRowContainer.setVisible(true);
const newMoveTypeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[this.newMove.type].toLowerCase()); const newMoveTypeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[this.newMove.type].toLowerCase());
newMoveTypeIcon.setOrigin(0, 1); newMoveTypeIcon.setOrigin(0, 1);
this.extraMoveRowContainer.add(newMoveTypeIcon); this.extraMoveRowContainer.add(newMoveTypeIcon);
@ -920,7 +920,7 @@ export default class SummaryUiHandler extends UiHandler {
this.moveRowsContainer.add(moveRowContainer); this.moveRowsContainer.add(moveRowContainer);
if (move) { if (move) {
const typeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[move.getMove().type].toLowerCase()); typeIcon.setOrigin(0, 1); const typeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[move.getMove().type].toLowerCase()); typeIcon.setOrigin(0, 1);
moveRowContainer.add(typeIcon); moveRowContainer.add(typeIcon);
} }

View File

@ -98,7 +98,7 @@ export function addTextInputObject(scene: Phaser.Scene, x: number, y: number, wi
} }
function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle): [ Phaser.Types.GameObjects.Text.TextStyle | InputText.IConfig, string, number, number ] { function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle): [ Phaser.Types.GameObjects.Text.TextStyle | InputText.IConfig, string, number, number ] {
const lang = i18next.language; const lang = i18next.resolvedLanguage;
let shadowXpos = 4; let shadowXpos = 4;
let shadowYpos = 5; let shadowYpos = 5;

View File

@ -222,6 +222,21 @@ export default class UI extends Phaser.GameObjects.Container {
return this.handlers[Mode.MESSAGE] as BattleMessageUiHandler; return this.handlers[Mode.MESSAGE] as BattleMessageUiHandler;
} }
processInfoButton(pressed: boolean) {
if (this.overlayActive) {
return false;
}
const battleScene = this.scene as BattleScene;
if ([Mode.CONFIRM, Mode.COMMAND, Mode.FIGHT, Mode.MESSAGE].includes(this.mode)) {
battleScene?.processInfoButton(pressed);
return true;
}
battleScene?.processInfoButton(false);
return true;
}
processInput(button: Button): boolean { processInput(button: Button): boolean {
if (this.overlayActive) { if (this.overlayActive) {
return false; return false;

View File

@ -396,7 +396,7 @@ English itself counts as not available
export function verifyLang(lang?: string): boolean { export function verifyLang(lang?: string): boolean {
//IMPORTANT - ONLY ADD YOUR LANG HERE IF YOU'VE ALREADY ADDED ALL THE NECESSARY IMAGES //IMPORTANT - ONLY ADD YOUR LANG HERE IF YOU'VE ALREADY ADDED ALL THE NECESSARY IMAGES
if (!lang) { if (!lang) {
lang = i18next.language; lang = i18next.resolvedLanguage;
} }
switch (lang) { switch (lang) {